mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-31 14:28:54 -04:00
Compare commits
308
Commits
pokesnap_test
...
v1.4.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
765e9f2cc3 | ||
|
|
ffda34742c | ||
|
|
c2385edbe7 | ||
|
|
961ad0f4bd | ||
|
|
8851594347 | ||
|
|
3c1ad2bea6 | ||
|
|
e1960792d7 | ||
|
|
23b9f933c7 | ||
|
|
9662699bcb | ||
|
|
32b2d2023b | ||
|
|
c64612859c | ||
|
|
6c97c4c238 | ||
|
|
6535d43964 | ||
|
|
234d1dad44 | ||
|
|
da247e9902 | ||
|
|
0655d63dc5 | ||
|
|
81ba5ef615 | ||
|
|
8354c3838a | ||
|
|
80db305aba | ||
|
|
60e0314f29 | ||
|
|
5f868630e0 | ||
|
|
b93adae945 | ||
|
|
9f1ed344d8 | ||
|
|
2c256eefde | ||
|
|
b075fce83f | ||
|
|
f2ed332c4c | ||
|
|
e8f083d8bf | ||
|
|
1684a341a1 | ||
|
|
b4e1bf794d | ||
|
|
c85ad7d60c | ||
|
|
e61e92a5d4 | ||
|
|
a245e9661c | ||
|
|
059152b34c | ||
|
|
0d35157fcf | ||
|
|
302388d0a6 | ||
|
|
ab957f82e1 | ||
|
|
fef82ae6bf | ||
|
|
8b979c1944 | ||
|
|
4bbbaacacf | ||
|
|
eda8e15509 | ||
|
|
d53a71c188 | ||
|
|
d2f02b0d06 | ||
|
|
5c0bb194b6 | ||
|
|
e41562f5ad | ||
|
|
69ea1ac3bf | ||
|
|
7c15f0f924 | ||
|
|
6165e5e871 | ||
|
|
dd8f59e0d0 | ||
|
|
87611795e9 | ||
|
|
d2fe9b1132 | ||
|
|
e95759a710 | ||
|
|
7284f8d35d | ||
|
|
334dd1206e | ||
|
|
e7caab0ae0 | ||
|
|
47f02f6e50 | ||
|
|
3367b0c39c | ||
|
|
0e43d7730c | ||
|
|
b5604686f2 | ||
|
|
e030dbfbf5 | ||
|
|
96647a9398 | ||
|
|
9e2c0ab0db | ||
|
|
1bc953f3f3 | ||
|
|
d089eab60f | ||
|
|
d18cab39a9 | ||
|
|
4492666f5a | ||
|
|
6a0985958b | ||
|
|
308c5e6d32 | ||
|
|
bd83cc143b | ||
|
|
c9e6cb1022 | ||
|
|
74c75b7faa | ||
|
|
45819a17f6 | ||
|
|
e3f84248b8 | ||
|
|
0ff518194f | ||
|
|
634a1ad6fc | ||
|
|
41217ebdcc | ||
|
|
a021ec1337 | ||
|
|
b03f95b7da | ||
|
|
d8cee44661 | ||
|
|
5dd2287441 | ||
|
|
1eb6af14c2 | ||
|
|
61b73972d4 | ||
|
|
f8bcf8c291 | ||
|
|
543d408e63 | ||
|
|
2cdc781e93 | ||
|
|
8dc0a7f72d | ||
|
|
8b5231d6f0 | ||
|
|
665c4cc26c | ||
|
|
7c860d8f91 | ||
|
|
006e86f3c3 | ||
|
|
91dec859e8 | ||
|
|
85f08c9d28 | ||
|
|
d465f465c8 | ||
|
|
a87bd35fd6 | ||
|
|
0c32da0ce1 | ||
|
|
2bdb110c92 | ||
|
|
d21f3747fc | ||
|
|
fb303fcd97 | ||
|
|
31b185b96c | ||
|
|
034a51b904 | ||
|
|
9e1c491d9c | ||
|
|
f695a99705 | ||
|
|
a8567f9190 | ||
|
|
7d455b2dac | ||
|
|
1dffbd1b37 | ||
|
|
332e25fa76 | ||
|
|
f080fb5639 | ||
|
|
769a1862e4 | ||
|
|
127c5e7a8b | ||
|
|
d1a71373c0 | ||
|
|
77def6de43 | ||
|
|
973c6bb05f | ||
|
|
5b83e49669 | ||
|
|
e01bc2eeab | ||
|
|
f6f3070b8e | ||
|
|
0f2301e668 | ||
|
|
80ce5bab58 | ||
|
|
8fb678b0f8 | ||
|
|
c0a77aca23 | ||
|
|
e4c0eab8e2 | ||
|
|
b9ff46e1b2 | ||
|
|
45a998d3d7 | ||
|
|
a108d85531 | ||
|
|
0fae45f811 | ||
|
|
88717d598d | ||
|
|
33123b4a33 | ||
|
|
74e0915ec8 | ||
|
|
39cd5e9726 | ||
|
|
876be2afcf | ||
|
|
d693f452bc | ||
|
|
a1e94b8200 | ||
|
|
8b4552a532 | ||
|
|
41673ba90f | ||
|
|
18f9942dc6 | ||
|
|
875fe46d21 | ||
|
|
66c6f9bdd1 | ||
|
|
b72af84c8c | ||
|
|
a5ee270b8b | ||
|
|
c08ef4247d | ||
|
|
9424bafabb | ||
|
|
a96ecfcdf2 | ||
|
|
b1d11e8c22 | ||
|
|
c1fb1379a9 | ||
|
|
5a220e0ef0 | ||
|
|
b379fc62b1 | ||
|
|
d442e4e956 | ||
|
|
bb22c22db9 | ||
|
|
09bc174401 | ||
|
|
e109a1d59f | ||
|
|
3b97a0c847 | ||
|
|
87e8fcd7f7 | ||
|
|
b34f8a045d | ||
|
|
4f79b9f8a7 | ||
|
|
d1b651a876 | ||
|
|
b30a67651e | ||
|
|
a1398e9495 | ||
|
|
ca319764f0 | ||
|
|
ac03c68f41 | ||
|
|
0eb4b43b49 | ||
|
|
b49376dba5 | ||
|
|
81f6e7b786 | ||
|
|
574ee1ae4a | ||
|
|
07a83f54a2 | ||
|
|
6f3b530d7b | ||
|
|
4b86dc1e58 | ||
|
|
bb141aee50 | ||
|
|
acb473c01f | ||
|
|
a8dc3f40a4 | ||
|
|
b55f11628d | ||
|
|
150c03d4f5 | ||
|
|
1c092588f4 | ||
|
|
683473c34c | ||
|
|
c7dee1bd53 | ||
|
|
d83a1086d3 | ||
|
|
b34ca3d42b | ||
|
|
3a1389d719 | ||
|
|
e608dc84ae | ||
|
|
c987a5ba19 | ||
|
|
d65090ce10 | ||
|
|
206ec25a99 | ||
|
|
ccd376c055 | ||
|
|
6214fb1b97 | ||
|
|
a65cee3e24 | ||
|
|
9999a04692 | ||
|
|
6901f3e43d | ||
|
|
1a0135c1fd | ||
|
|
23dab6546f | ||
|
|
3b94b6660c | ||
|
|
dc46c96ecf | ||
|
|
55861a249e | ||
|
|
f00a569d9d | ||
|
|
aaa5484752 | ||
|
|
c6e82ebfb9 | ||
|
|
365844ae2e | ||
|
|
c18c1f39fb | ||
|
|
1fd2aa06ae | ||
|
|
931852bd36 | ||
|
|
272f429f59 | ||
|
|
b4787b8db8 | ||
|
|
6a5c6d2b17 | ||
|
|
618453caaa | ||
|
|
e1d048ec9d | ||
|
|
26ebd23d14 | ||
|
|
b446415200 | ||
|
|
ed8fe19dc1 | ||
|
|
cdcc071ce0 | ||
|
|
e674b042d0 | ||
|
|
53abb58ae6 | ||
|
|
17fed9662c | ||
|
|
74dd2a6c0d | ||
|
|
7505ce15e3 | ||
|
|
30ba97ea69 | ||
|
|
5fee2df9f7 | ||
|
|
238c7474b3 | ||
|
|
5da5c72b4f | ||
|
|
0604b45b9d | ||
|
|
132a43c5c7 | ||
|
|
b1e8f9cfb6 | ||
|
|
a166a38c4b | ||
|
|
57fa6a58d5 | ||
|
|
95006ae327 | ||
|
|
ad6fc97eef | ||
|
|
fc39baaa30 | ||
|
|
887ff8ccdb | ||
|
|
4d6117f5bf | ||
|
|
3dc26639a5 | ||
|
|
252f9d5dbd | ||
|
|
599b8c5eec | ||
|
|
974f839d61 | ||
|
|
b4ea13ab20 | ||
|
|
06afb04050 | ||
|
|
92c3d9464b | ||
|
|
03ed8f3edd | ||
|
|
b475b02fff | ||
|
|
8c462f1567 | ||
|
|
1c25ae69a5 | ||
|
|
e668735dd8 | ||
|
|
f0e65fe4de | ||
|
|
084a7bfb3c | ||
|
|
3c11a673dc | ||
|
|
deb2cff477 | ||
|
|
79d89852d4 | ||
|
|
8d38144551 | ||
|
|
a21a172be3 | ||
|
|
b44e5c797e | ||
|
|
ae9337c84a | ||
|
|
5db2c4c955 | ||
|
|
8af1225c90 | ||
|
|
4b181d75c8 | ||
|
|
9e28dce3d7 | ||
|
|
39f084bd56 | ||
|
|
c82bba7872 | ||
|
|
3f557d9ae6 | ||
|
|
c15976a936 | ||
|
|
c8652b519a | ||
|
|
67c828dd0c | ||
|
|
10a1bc6bc6 | ||
|
|
e4db065a85 | ||
|
|
171cd45e32 | ||
|
|
d638315fb1 | ||
|
|
980fa6a13d | ||
|
|
267faf9397 | ||
|
|
7549d77ad7 | ||
|
|
0f6929dd5e | ||
|
|
79597a81fe | ||
|
|
e54e822c3a | ||
|
|
5e60bb525c | ||
|
|
c49cb45892 | ||
|
|
e0a896377e | ||
|
|
b96638226c | ||
|
|
7c025582e0 | ||
|
|
623dfbb78b | ||
|
|
942bf8247e | ||
|
|
d6a991e81e | ||
|
|
5d5de4f2f3 | ||
|
|
7e952295a5 | ||
|
|
d299cad9db | ||
|
|
261408d542 | ||
|
|
cde163c1d1 | ||
|
|
dbc478fc89 | ||
|
|
dde6c1dc97 | ||
|
|
41d7740374 | ||
|
|
29f0c6f7bc | ||
|
|
d128d3e025 | ||
|
|
422bd5a0de | ||
|
|
65271dc1b1 | ||
|
|
8a604fdefe | ||
|
|
a525df98cd | ||
|
|
6a5c52ca0e | ||
|
|
57509b6bba | ||
|
|
0a4b7fe5c8 | ||
|
|
45f72e0e9e | ||
|
|
029e152d95 | ||
|
|
08d6fa00eb | ||
|
|
35bb803fb0 | ||
|
|
ec028c89e4 | ||
|
|
1de8a40bae | ||
|
|
8c682356bb | ||
|
|
f7adaa6100 | ||
|
|
7381ef6a02 | ||
|
|
a54acc48e7 | ||
|
|
5478db4e32 | ||
|
|
5f55cbb5d3 | ||
|
|
dfa104d8cf | ||
|
|
6ff53c0be3 | ||
|
|
088159bab2 | ||
|
|
6682049be1 | ||
|
|
fa2bbdbb10 | ||
|
|
2798f73397 |
No files matched your search
@@ -0,0 +1,30 @@
|
||||
<!-- 1. START HERE: (Before filling all this out, please quickly go to the list of all issues: (https://gitlab.com/cable-mc/cobblemon/-/issues/?sort=created_date&state=all) and do a quick search to see if your issue has already been reported. If it has, please add a comment to the existing issue instead of creating a new one.)-->
|
||||
<!-- 2. If the issue was not already reported, please fill out the following template. -->
|
||||
<!-- 3. If you do not know something, don't worry! Just fill out as much as you can to make sure the issue can get fixed asap. -->
|
||||
|
||||
## Summary
|
||||
(Please summarize the bug encountered concisely)
|
||||
|
||||
## Steps to reproduce
|
||||
(How one can reproduce the issue - this is very important)
|
||||
|
||||
## What is the current bug behavior?
|
||||
(What actually happens)
|
||||
|
||||
## What is the expected correct behavior?
|
||||
(What you should see instead)
|
||||
|
||||
## Cobblemon Version and Mod Loader
|
||||
(Are you using Forge or Fabric? And what version of Cobblemon are you using?)
|
||||
|
||||
## Mods used besides Cobblemon
|
||||
(Did you have any other mods installed besides Cobblemon? If so, please list them here)
|
||||
|
||||
## Relevant logs, screenshots and/or videos
|
||||
(Paste any relevant logs - use code blocks (```) at the start and end to format console output, logs, and code, as
|
||||
it's very hard to read otherwise. Or just put a link here)
|
||||
|
||||
## Additional Information
|
||||
(If you can, link to the line of code that might be responsible for the problem, or any other info that might be useful)
|
||||
|
||||
/label ~bug
|
||||
@@ -0,0 +1,31 @@
|
||||
<!-- 1. START HERE: (Before filling all this out, please quickly go to the list of all issues: (https://gitlab.com/cable-mc/cobblemon/-/issues/?sort=created_date&state=all) and do a quick search to see if your feature was already requested. If it is, please add a comment to the existing issue instead of creating a new one.)-->
|
||||
<!-- 2. If the feature request was not already reported, please fill out the following template. -->
|
||||
<!-- 3. If you do not know something, don't worry! Just fill out as much as you can. -->
|
||||
<!-- 4. The more info you provide here, the greater the chance of it being considered by the Design team. -->
|
||||
|
||||
## Summary
|
||||
(Please summarize your feature request concisely)
|
||||
|
||||
## What are the projected benefits of this feature?
|
||||
- (List)
|
||||
- (benefits)
|
||||
- (here)
|
||||
|
||||
## What could speak against this feature?
|
||||
- (List)
|
||||
- (possible)
|
||||
- (cons)
|
||||
|
||||
## Why do you think the benefits outweigh the cons?
|
||||
(Explain why you think the benefits outweigh the cons)
|
||||
|
||||
## Mods involved besides Cobblemon
|
||||
(Does your suggestion require any other mods besides Cobblemon? If so, please list them here)
|
||||
|
||||
## Sketches, screenshots and/or videos
|
||||
(Feel free to add any sketches, screenshots or videos that might help the Design team understand your suggestion)
|
||||
|
||||
## Additional Information
|
||||
(Is there anything else you would like to add?)
|
||||
|
||||
/label ~feature ~suggestion ~needs-design
|
||||
+117
-23
@@ -1,38 +1,132 @@
|
||||
# Changelog
|
||||
## [1.4.1](#1-4-1)
|
||||
|
||||
### Changes
|
||||
- Slightly lowered the volume of all cries
|
||||
- Pasture blocks will now also connect their bottom left and right sides to walls, iron bars, glass panes and any other modded block that follows the same connection rules.
|
||||
## [1.4.1 (December 23rd, 2023)](#1-4-1)
|
||||
|
||||
### Additions
|
||||
- Cobblemon now has compatibility with [Adorn](https://modrinth.com/mod/adorn) allowing you to craft Apricorn wood furniture.
|
||||
- Added battle spectating. Press R on a player in a battle and you can spectate and bully them for their tactics.
|
||||
- Added the Litwick and Drifloon lines.
|
||||
- Cobblemon now has compatibility with [Adorn](https://modrinth.com/mod/adorn), allowing you to craft Apricorn wood furniture.
|
||||
- Berries can now be used in recipes from [Farmer's Delight](https://modrinth.com/mod/farmers-delight) and [Farmer's Delight (Fabric)](https://modrinth.com/mod/farmers-delight-fabric), as well as any other mods using the same berry tags.
|
||||
- The nature of cobblemon will now be displayed italicized when a mint has been applied. Hovering over the nature will display the mint that was applied. This is the intended behaviour, because the original nature and taste of the Cobblemon does not change when a mint is applied.
|
||||
- Boats, signs and hanging signs are now craftable with Apricorn wood.
|
||||
- Added the Fairy Feather, Iron Ball, Cleanse Tag, Flame Orb, Life Orb, Smoke Ball, and Toxic Orb held items.
|
||||
- Added the Inferno, Void, and Forsaken patterns for Vivillon. These can be obtained by evolving a Spewpa in the Nether, End, or Deep Dark respectively.
|
||||
- Bees can now be fed using Pep-Up Flowers.
|
||||
- Mooshtank can now be milked with a bowl for Mushroom Stew.
|
||||
- Updated Showdown version to use generation 9 battle data.
|
||||
- Added cries to Beldum, Metang and Metagross.
|
||||
- Added a /bedrockparticle command to run Snowstorm-format particle effects.
|
||||
- Added data for Dipplin, Fezandipiti, Munkidori, Ogerpon, Okidogi, Poltchageist and Sinistcha.
|
||||
|
||||
### Changes
|
||||
- Using Potions, Status Heals, Ethers, and Antidotes will now return a glass bottle
|
||||
- Using a Remedy, Fine Remedy, or Superb Remedy will no longer lower friendship with a Pokémon.
|
||||
- The Healing Machine now has a [much more difficult recipe](https://wiki.cobblemon.com/index.php/Healing_Machine), placing it later game.
|
||||
- Made the EXP. Share recipe cheaper.
|
||||
- Turtwig can now be put on your shoulder.
|
||||
- Updated Zubat line model, texture, and animations.
|
||||
- Updated Geodude line models and textures.
|
||||
- Added animations for Hitmontop, Tyrogue, and Mightyena.
|
||||
- Tweaked animations for Dusknoir, Ratatta, Bewear, Exeggutor, and Alolan Exeggutor.
|
||||
- Sized Kantonian Exeggutor down. Still big, but not TOO big.
|
||||
- Tweaked cries for Pikachu, Raichu and Alolan Raichu.
|
||||
- Fixed Swimming behaviors for Wimpod line, Oshawott line, Quaxly line, and Clodsire
|
||||
- Changed the way level scaling works in spawning. By default, anything with a spawn range of up to 5 either side of the party highest level and everything else will spawn per its specified ranges.
|
||||
- The nature of Pokémon will now be displayed italicized when a mint has been applied. Hovering over the nature will display the mint that was applied.
|
||||
- Slightly lowered the volume of all cries.
|
||||
- Giving Pokémon items now plays a sound
|
||||
- Updated the Poké Ball model and animations.
|
||||
- Pasture blocks will now also connect their bottom left and right sides to walls, iron bars, glass panes, and any other modded block that follows the same connection rules.
|
||||
- The config option `consumeHeldItems` has been removed, please see the Datapack & Resourcepack Creators section for instructions on the updated method.
|
||||
- Heal Powder can now be composted with a 75% chance of adding a layer
|
||||
- Mental, Power, White, and Mirror Herbs can now be composted with a 100% chance of adding a layer.
|
||||
- Added glowing eyes to Hoothoot and Noctowl.
|
||||
- Mining Evolution Stone Ores with a Fortune pickaxe will now increase the amount of items received.
|
||||
- Black Augurite can now be used to craft stone axes and obsidian.
|
||||
- Using Experience Candies brings up the Party Pokémon Select screen when not targeting a Pokémon.
|
||||
- Added tab completion for statuses to commands.
|
||||
- Remedies can now be cooked in a Smoker and on a Campfire.
|
||||
- Vertically flipped the Destiny Knot recipe.
|
||||
|
||||
### Fixes
|
||||
- Fixed various stone related blocks not being valid for Big Roots to spread on the Fabric version.
|
||||
- Fixed Raticate, Onix, Unfezant, Bergmite, Avalugg, Boltund and Revavroom cries not playing.
|
||||
- Fixed Alolan Ratticate animations causing a crash.
|
||||
- Fixed Quaxwell not doing its cry.
|
||||
- Fixed Shroomish not using its idle.
|
||||
- Fixed how Weight and Height is calculated for Pokémon, fixing the damage from moves like Low Kick.
|
||||
- Fixed a staggering number of battle messages.
|
||||
- Fixed various stone related blocks not being valid for Big Roots to spread onto on the Fabric version.
|
||||
- Updated the registration of compostable items to improve compatibility with Fabric forks such as Quilt. Please note this does not mean we officially support Quilt, this change was only done since it was possible by correcting the registration to use the new intended way in the Fabric API.
|
||||
- Fixed Dispensers being unable to shear grown Apricorns.
|
||||
- Fixed Bowl not being given back to player after using Berry Juice
|
||||
- Fixed missing text for attempting to catch an uncatchable Pokémon
|
||||
- Fixed Moonphases for Clefairy line
|
||||
- Fixed issue where Potions, Super Potions, and Hyper Potions did not work during battle
|
||||
- Fixed the compatibility patch with the Forge version of [Carry On](https://modrinth.com/mod/carry-on) due to a bug on the mod, the Fabric version was unchanged and is still compatible.
|
||||
- Added the ability to place Berries on modded Farmland blocks.
|
||||
- Shouldered Pokémon now hop off when selected in team and r is pressed. This also is in effect in battles leading to shouldered Pokémon jumping of the shoulder of the trainer when it is their turn.
|
||||
- Shouldered Pokémon now hop off when selected in team and R is pressed. This also is in effect in battles leading to shouldered Pokémon jumping of the shoulder of the trainer when it is their turn.
|
||||
- Made more items compostable and changed the process for making items compostable.
|
||||
- Added the ability for Hoppers to fill Brewing Stands with Medicinal Brews and Potions.
|
||||
- Apricorn blocks are now flammable.
|
||||
- Apricorn blocks are now flammable. Probably should have started that way, but we got there.
|
||||
- The default pose for Pokémon being passengers is now "standing".
|
||||
- Fixed issue where some IVs were changing every player relog.
|
||||
- Fixed cursed battle message
|
||||
- Fixed mistakes in pokemon spawning JSONs
|
||||
- Fixed issue where some IVs were changing every time a player logged back in.
|
||||
- Fixed advancement crash from bad datapack evolution data.
|
||||
- Fixed global influences being applied to TickingSpawners twice.
|
||||
- Reverted the default SpawningSelector back to FlatContextWeightedSelector. This fixes multiple weight related issues, including weights with SpawningInfluences.
|
||||
- Apricorn Planting advancement should work again.
|
||||
- Advancement "Vivillonaire" should now allow High Plains and Icy Snow Vivillon to register.
|
||||
- Fixed the last battle critical hits evolution requirement not working.
|
||||
- Fixed the damage taken evolution requirement not saving progress.
|
||||
- Fixed the defeated Pokémon evolution requirement not saving progress.
|
||||
- Fixed potion brewing recipes not showing up JEI and similar mods on the Forge version.
|
||||
- Fixed an exploit that could convert a single piece of Blaze Powder into an extra Medicinal Brew on the Forge version.
|
||||
- Fixed an issue where health percentages would show incorrectly after healing
|
||||
- Fixed the move Revival Blessing not allowing you to select from fainted party members.
|
||||
- Fixed villagers not being able to pick up and plant mint seeds, vivichoke seeds, and revival herbs.
|
||||
- Fixed Exeggcute faint.
|
||||
- Fixed various spawn configuration issues across the board.
|
||||
- Fixed a possible visual duplication of sent out Pokémon.
|
||||
- Fixed battle text for Trace, Receiver, and Power of Alchemy.
|
||||
- Fixed tooltips being appended too late in items.
|
||||
- Fixed battles ending background music when battle music is not present.
|
||||
- Fixed battles ending background music, instead of pausing, when battle music is played.
|
||||
- Fixed a bunch of regionals to actually be obtainable, namely the unmodelled ones
|
||||
- Fixed battle text for moves that were missing.
|
||||
- Fixed a formatting error that affected Pokémon nicknames when the storage type is JSON.
|
||||
- Fixed a crash that could occur on some servers relating to chunk loading and teleporting.
|
||||
- Fixed an issue with Inkay's evolution requirement.
|
||||
- Fixed conflicting evolution requirements that would cause the Ocean, River, Sun, and Tundra variants of Vivillon to be unobtainable through evolution.
|
||||
- Fixed the Modern variant of Vivillon not being obtainable through evolution.
|
||||
- Fixed Pokémon pathing through berry bushes, harming themselves in the process.
|
||||
|
||||
### Developer
|
||||
- Fixed the `SpawnEvent` not respecting usage of `Cancelable#cancel`.
|
||||
- Added the `EvolutionTestedEvent`, this allows listening and overriding the final result of evolution requirement tests.
|
||||
- Added utility script that can be used to generate all Spawn JSONS for all pokemon from the spawning spreadsheet in 1 click ([cobblemon_spawn_csv_to_json.py](utilityscripts%2Fcobblemon_spawn_csv_to_json.py)).
|
||||
- The `HeldItemManager` has a new method `shouldConsumeItem`, this will return false by default to prevent breaking changes, see the documentation and update your implementations as needed.
|
||||
- Added and implemented minSkyLight and maxSkyLight as config options for SpawnConditions
|
||||
- Player specific battle themes can now be assigned to `PlayerData#battleTheme`.
|
||||
- Changed design of `BattleStartedPreEvent`. Will now expose the `PokemonBattle`.
|
||||
|
||||
### Datapack & Resourcepack Creators
|
||||
- Added 3 new item tags: `cobblemon:held/consumed_in_npc_battle`, `cobblemon:held/consumed_in_pvp_battle` & `cobblemon:held/consumed_in_wild_battle` these will determine which items get consumed in the implied battle types by Cobblemon, keep in mind the controller for this behaviour can be overriden by 3rd party.
|
||||
- Unique wild encounter themes can now be associated with a specific species (or form) by assigning a SoundEvent identifier to the `battleTheme` field in the species' data configuration.
|
||||
- Added a `structure` evolution condition, used to check if a Pokémon is in a given structure.
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
- French and Canadian French
|
||||
- Simplified and Traditional Chinese
|
||||
- Spanish and Mexican Spanish
|
||||
- Pirate English
|
||||
- German
|
||||
- Thai
|
||||
- Portuguese and Brazilian Portuguese
|
||||
- Polish
|
||||
- Italian
|
||||
- Dutch
|
||||
- Ukrainian
|
||||
- Russian
|
||||
|
||||
Thank you so much to all of our community translators that bring the mod to the rest of the world!
|
||||
|
||||
## [1.4.0 - The Friends and Farms Update (October 13th, 2023)](#1-4-0)
|
||||
### Additions
|
||||
@@ -821,17 +915,17 @@
|
||||
- Fixed spawning in several biome tag categories.
|
||||
- Fixed resource pack support for Pokémon models and textures.
|
||||
- **Model Fixes**
|
||||
- Fixed Paras and Nidoqueen looking very weird.
|
||||
- Fixed Hitmonchan asserting dominance with a T-pose as well as Grimer and Muk pointing their hands to the sky.
|
||||
- Fixed specific Pokémon suddenly pausing their animation after staying still for a long time.
|
||||
- Fixed Mankey's feet being buried in the ground.
|
||||
- Updated the Substitute model and updated its shiny texture to be better for the red-green colorblind.
|
||||
- Improved Horsea, Seadra, and Kingdra animations, especially on land.
|
||||
- Fixed Paras and Nidoqueen looking very weird.
|
||||
- Fixed Hitmonchan asserting dominance with a T-pose as well as Grimer and Muk pointing their hands to the sky.
|
||||
- Fixed specific Pokémon suddenly pausing their animation after staying still for a long time.
|
||||
- Fixed Mankey's feet being buried in the ground.
|
||||
- Updated the Substitute model and updated its shiny texture to be better for the red-green colorblind.
|
||||
- Improved Horsea, Seadra, and Kingdra animations, especially on land.
|
||||
- **Battle Fixes**
|
||||
- Fixed an issue with battles where Pokémon had a different max HP causing some desync issues with the health bars.
|
||||
- Fixed Magnitude battle messages.
|
||||
- Moves that are disabled or out of PP now show transparently in the battle GUI instead of being hidden completely.
|
||||
- Statuses like sleep and frozen no longer last forever if it was carried over from a previous battle.
|
||||
- Fixed an issue with battles where Pokémon had a different max HP causing some desync issues with the health bars.
|
||||
- Fixed Magnitude battle messages.
|
||||
- Moves that are disabled or out of PP now show transparently in the battle GUI instead of being hidden completely.
|
||||
- Statuses like sleep and frozen no longer last forever if it was carried over from a previous battle.
|
||||
|
||||
### Localization
|
||||
- Added species, ability, and move translations for `ko_ko`, `jp_jp`, `fr_fr`, `es_es`, `it_it`, and `zh_cn`.
|
||||
|
||||
+7
-2
@@ -6,10 +6,15 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.access;
|
||||
package com.cobblemon.mod.common.duck;
|
||||
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface SoundManagerDuck {
|
||||
void toggleCategories(SoundCategory... categories);
|
||||
|
||||
void pauseSounds(@Nullable Identifier id, @Nullable SoundCategory category);
|
||||
|
||||
void resumeSounds(@Nullable Identifier id, @Nullable SoundCategory category);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.duck;
|
||||
|
||||
import net.minecraft.client.sound.SoundInstance;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface SoundSystemDuck {
|
||||
|
||||
void pauseSounds(@Nullable Identifier id, @Nullable SoundCategory category);
|
||||
|
||||
void resumeSounds(@Nullable Identifier id, @Nullable SoundCategory category);
|
||||
|
||||
Collection<SoundInstance> getSounds(@Nullable SoundCategory category);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import net.minecraft.entity.passive.VillagerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.village.VillagerProfession;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import com.cobblemon.mod.common.villager.VillagerGatherableItems;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Mixin(VillagerEntity.class)
|
||||
public abstract class EntityVillagerMixin {
|
||||
|
||||
@Inject(method = "canGather", at = @At(value = "RETURN"), cancellable = true)
|
||||
private void cobblemon$canGather(ItemStack stack, CallbackInfoReturnable<Boolean> ci) {
|
||||
final VillagerEntity villager = (VillagerEntity) (Object) this;
|
||||
if(ci.getReturnValue() == false && Objects.equals(villager.getVillagerData().getProfession(), VillagerProfession.FARMER) && villager.getInventory().canInsert(stack)) {
|
||||
if(VillagerGatherableItems.INSTANCE.getVillagerGatherableItems().contains(stack.getItem()))
|
||||
ci.setReturnValue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.sound.battle.BattleMusicController;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.sound.MusicTracker;
|
||||
import net.minecraft.client.sound.SoundInstance;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(MusicTracker.class)
|
||||
public class MusicTrackerMixin {
|
||||
|
||||
@Shadow @Final
|
||||
private MinecraftClient client;
|
||||
|
||||
@Shadow @Nullable
|
||||
private SoundInstance current;
|
||||
|
||||
/** Freezes the tracker while a BattleMusicInstance is in progress. Current SoundInstance being tracked will be paused by BattleMusicHandler. */
|
||||
@Inject(method = "tick()V", at = @At("HEAD"), cancellable = true)
|
||||
public void tick(CallbackInfo cb) {
|
||||
if (this.client.getSoundManager().isPlaying(BattleMusicController.INSTANCE.getMusic())) cb.cancel();
|
||||
}
|
||||
}
|
||||
@@ -8,36 +8,77 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.access.SoundManagerDuck;
|
||||
import net.minecraft.client.sound.SoundInstance;
|
||||
import net.minecraft.client.sound.SoundManager;
|
||||
import com.cobblemon.mod.common.client.sound.battle.BattleMusicController;
|
||||
import com.cobblemon.mod.common.duck.SoundManagerDuck;
|
||||
import com.cobblemon.mod.common.duck.SoundSystemDuck;
|
||||
import net.minecraft.client.sound.*;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(SoundManager.class)
|
||||
public class SoundManagerMixin implements SoundManagerDuck {
|
||||
public abstract class SoundManagerMixin implements SoundManagerDuck {
|
||||
|
||||
private boolean[] blockedCategories = new boolean[SoundCategory.values().length];
|
||||
@Shadow
|
||||
public abstract boolean isPlaying(SoundInstance sound);
|
||||
|
||||
@Override
|
||||
public void toggleCategories(SoundCategory... categories) {
|
||||
for (SoundCategory category : categories) {
|
||||
int index = category.ordinal();
|
||||
boolean blocked = blockedCategories[index];
|
||||
blockedCategories[index] = !blocked;
|
||||
}
|
||||
@Shadow @Final
|
||||
private SoundSystem soundSystem;
|
||||
|
||||
// Never-ending ambient loops are a special exception (they are only initiated once) and should always be paused if filtered.
|
||||
private boolean isAmbientLoop(SoundInstance sound) {
|
||||
return sound instanceof BiomeEffectSoundPlayer.MusicLoop || sound instanceof AmbientSoundLoops.Underwater;
|
||||
}
|
||||
|
||||
private boolean filterCondition(SoundInstance sound) {
|
||||
return !isAmbientLoop(sound) &&
|
||||
this.isPlaying(BattleMusicController.INSTANCE.getMusic()) &&
|
||||
BattleMusicController.INSTANCE.getFilteredCategories().contains(sound.getCategory());
|
||||
}
|
||||
|
||||
private boolean ambientLoopCondition(SoundInstance sound) {
|
||||
return isAmbientLoop(sound) &&
|
||||
this.isPlaying(BattleMusicController.INSTANCE.getMusic()) &&
|
||||
BattleMusicController.INSTANCE.getFilteredCategories().contains(sound.getCategory());
|
||||
}
|
||||
|
||||
/** Pauses the queried SoundInstance(s). If id is null, will pause all sounds belonging to the SoundCategory. */
|
||||
@Override
|
||||
public void pauseSounds(@Nullable Identifier id, @Nullable SoundCategory category) {
|
||||
((SoundSystemDuck)soundSystem).pauseSounds(id, category);
|
||||
}
|
||||
|
||||
/** Resumes the queried SoundInstance(s). If id is null, will resume all sounds belonging to the SoundCategory. */
|
||||
@Override
|
||||
public void resumeSounds(@Nullable Identifier id, @Nullable SoundCategory category) {
|
||||
((SoundSystemDuck)soundSystem).resumeSounds(id, category);
|
||||
}
|
||||
|
||||
/** Blocks filtered sounds from being played while a BattleMusicInstance is in progress. */
|
||||
@Inject(method = "play(Lnet/minecraft/client/sound/SoundInstance;)V", at = @At("HEAD"), cancellable = true)
|
||||
public void play(SoundInstance sound, CallbackInfo cb) {
|
||||
if (blockedCategories[sound.getCategory().ordinal()]) cb.cancel();
|
||||
public void playStart(SoundInstance sound, CallbackInfo cb) {
|
||||
if (filterCondition(sound)) cb.cancel();
|
||||
}
|
||||
|
||||
@Inject(method = "play(Lnet/minecraft/client/sound/SoundInstance;I)V", at = @At("HEAD"), cancellable = true)
|
||||
public void play(SoundInstance sound, int delay, CallbackInfo cb) {
|
||||
if (blockedCategories[sound.getCategory().ordinal()]) cb.cancel();
|
||||
public void playStart(SoundInstance sound, int delay, CallbackInfo cb) {
|
||||
if (filterCondition(sound)) cb.cancel();
|
||||
}
|
||||
|
||||
/** Pauses ambient loops while a BattleMusicInstance is in progress. */
|
||||
@Inject(method = "play(Lnet/minecraft/client/sound/SoundInstance;)V", at = @At("TAIL"))
|
||||
public void playEnd(SoundInstance sound, CallbackInfo cb) {
|
||||
if (ambientLoopCondition(sound)) this.pauseSounds(sound.getId(), SoundCategory.AMBIENT);
|
||||
}
|
||||
|
||||
@Inject(method = "play(Lnet/minecraft/client/sound/SoundInstance;I)V", at = @At("TAIL"))
|
||||
public void playEnd(SoundInstance sound, int delay, CallbackInfo cb) {
|
||||
if (ambientLoopCondition(sound)) this.pauseSounds(sound.getId(), SoundCategory.AMBIENT);
|
||||
}
|
||||
}
|
||||
@@ -8,31 +8,102 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.sound.battle.BattleMusicController;
|
||||
import com.cobblemon.mod.common.duck.SoundSystemDuck;
|
||||
import com.google.common.collect.Multimap;
|
||||
import net.minecraft.client.sound.SoundInstance;
|
||||
import net.minecraft.client.sound.SoundSystem;
|
||||
import net.minecraft.client.sound.*;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Mixin(SoundSystem.class)
|
||||
public abstract class SoundSystemMixin {
|
||||
public abstract class SoundSystemMixin implements SoundSystemDuck {
|
||||
|
||||
@Shadow
|
||||
private boolean started;
|
||||
|
||||
@Shadow
|
||||
private Multimap<SoundCategory, SoundInstance> sounds;
|
||||
|
||||
@Shadow @Final
|
||||
private Map<SoundInstance, Channel.SourceManager> sources;
|
||||
|
||||
@Shadow
|
||||
protected abstract void stop(SoundInstance sound);
|
||||
|
||||
@Shadow
|
||||
public abstract boolean isPlaying(SoundInstance sound);
|
||||
|
||||
/** Resumes the Source belonging to the queried SoundInstance. */
|
||||
private void resume(SoundInstance sound) {
|
||||
Channel.SourceManager sourceManager = this.sources.get(sound);
|
||||
if (this.started && sourceManager != null) sourceManager.run(Source::resume);
|
||||
}
|
||||
|
||||
/** Pauses the Source belonging to the queried SoundInstance. */
|
||||
private void pause(SoundInstance sound) {
|
||||
Channel.SourceManager sourceManager = this.sources.get(sound);
|
||||
if (this.started && sourceManager != null) sourceManager.run(Source::pause);
|
||||
}
|
||||
|
||||
/** Resumes the SoundInstance(s) queried by id and/or category. */
|
||||
@Override
|
||||
public void resumeSounds(@Nullable Identifier id, @Nullable SoundCategory category) {
|
||||
if (category != null) {
|
||||
this.sounds.get(category).forEach((sound) -> {
|
||||
if (id == null || sound.getId().equals(id)) resume(sound);
|
||||
});
|
||||
} else if (id == null) {
|
||||
this.sources.keySet().forEach(this::resume);
|
||||
} else {
|
||||
this.sources.keySet().forEach(sound -> {
|
||||
if (sound.getId().equals(id)) resume(sound);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** Pauses the SoundInstances queried by id and/or category. */
|
||||
@Override
|
||||
public void pauseSounds(@Nullable Identifier id, @Nullable SoundCategory category) {
|
||||
if (category != null) {
|
||||
this.sounds.get(category).forEach((sound) -> {
|
||||
if (id == null || sound.getId().equals(id)) pause(sound);
|
||||
});
|
||||
} else if (id == null) {
|
||||
this.sources.keySet().forEach(this::pause);
|
||||
} else {
|
||||
this.sources.keySet().forEach(sound -> {
|
||||
if (sound.getId().equals(id)) pause(sound);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** Allows stopping all SoundInstances that belong to a queried category. */
|
||||
@Inject(method = "stopSounds(Lnet/minecraft/util/Identifier;Lnet/minecraft/sound/SoundCategory;)V", at = @At("HEAD"), cancellable = true)
|
||||
public void stopSounds(@Nullable Identifier id, @Nullable SoundCategory category, CallbackInfo cb) {
|
||||
if (id == null && category != null) {
|
||||
sounds.get(category).forEach(this::stop);
|
||||
this.sounds.get(category).forEach(this::stop);
|
||||
cb.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
/** Different behavior for resuming SoundInstances while a BattleMusicInstance is being played. We do not want to resume filtered sounds. */
|
||||
@Inject(method = "resumeAll()V", at = @At("HEAD"), cancellable = true)
|
||||
public void resumeAll(CallbackInfo cb) {
|
||||
if (this.isPlaying(BattleMusicController.INSTANCE.getMusic())) {
|
||||
this.sounds.values().forEach(sound -> {
|
||||
if (sound == BattleMusicController.INSTANCE.getMusic() || !BattleMusicController.INSTANCE.getFilteredCategories().contains(sound.getCategory())) {
|
||||
resume(sound);
|
||||
}
|
||||
});
|
||||
cb.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
+8
-7
@@ -8,15 +8,16 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin.accessor;
|
||||
|
||||
import net.minecraft.client.sound.MusicTracker;
|
||||
import net.minecraft.entity.vehicle.BoatEntity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(MusicTracker.class)
|
||||
public interface MusicTrackerAccessor {
|
||||
@Accessor("timeUntilNextSong")
|
||||
int timeUntilNextSong();
|
||||
@Mixin(BoatEntity.class)
|
||||
public interface BoatEntityAccessor {
|
||||
|
||||
@Accessor("timeUntilNextSong")
|
||||
void setTimeUntilNextSong(int timeUntilNextSong);
|
||||
@Accessor
|
||||
void setFallVelocity(double fallVelocity);
|
||||
|
||||
@Accessor
|
||||
BoatEntity.Location getLocation();
|
||||
}
|
||||
@@ -371,8 +371,9 @@ object Cobblemon {
|
||||
battleRegistry.startBattle(
|
||||
BattleFormat.GEN_9_SINGLES,
|
||||
BattleSide(PokemonBattleActor(UUID.randomUUID(), BattlePokemon(Pokemon().initialize()), -1F)),
|
||||
BattleSide(PokemonBattleActor(UUID.randomUUID(), BattlePokemon(Pokemon().initialize()), -1F))
|
||||
).apply { mute = true }
|
||||
BattleSide(PokemonBattleActor(UUID.randomUUID(), BattlePokemon(Pokemon().initialize()), -1F)),
|
||||
true
|
||||
).ifSuccessful { it.mute = true }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.block.entity.BerryBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.HealingMachineBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.PCBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.PokemonPastureBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.*
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import net.minecraft.block.entity.BlockEntityType
|
||||
import net.minecraft.registry.Registries
|
||||
@@ -31,5 +28,9 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
|
||||
val BERRY = this.create("berry", BlockEntityType.Builder.create(::BerryBlockEntity, *CobblemonBlocks.berries().values.toTypedArray()).build(null))
|
||||
@JvmField
|
||||
val PASTURE: BlockEntityType<PokemonPastureBlockEntity> = this.create("pasture", BlockEntityType.Builder.create(::PokemonPastureBlockEntity, CobblemonBlocks.PASTURE).build(null))
|
||||
@JvmField
|
||||
val SIGN: BlockEntityType<CobblemonSignBlockEntity> = this.create("sign", BlockEntityType.Builder.create(::CobblemonSignBlockEntity, CobblemonBlocks.APRICORN_SIGN, CobblemonBlocks.APRICORN_WALL_SIGN).build(null))
|
||||
@JvmField
|
||||
val HANGING_SIGN: BlockEntityType<CobblemonHangingSignBlockEntity> = this.create("hanging_sign", BlockEntityType.Builder.create(::CobblemonHangingSignBlockEntity, CobblemonBlocks.APRICORN_HANGING_SIGN, CobblemonBlocks.APRICORN_WALL_HANGING_SIGN).build(null))
|
||||
|
||||
}
|
||||
@@ -19,6 +19,10 @@ import com.cobblemon.mod.common.mixin.invoker.*
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.block.BerryBlock
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonHangingSignBlock
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonSignBlock
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonWallHangingSignBlock
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonWallSignBlock
|
||||
import net.minecraft.block.*
|
||||
import net.minecraft.block.piston.PistonBehavior
|
||||
import net.minecraft.entity.effect.StatusEffects
|
||||
@@ -107,9 +111,14 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
val APRICORN_BUTTON = this.create("apricorn_button", BlocksInvoker.createWoodenButtonBlock(BlockSetType.OAK))
|
||||
@JvmField
|
||||
val APRICORN_PRESSURE_PLATE = this.create("apricorn_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(PressurePlateBlock.ActivationRule.EVERYTHING, AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).noCollision().strength(0.5f).sounds(BlockSoundGroup.WOOD), APRICORN_BLOCK_SET_TYPE))
|
||||
// Tag was removed be sure to add it back when implemented
|
||||
//val APRICORN_SIGN = queue("apricorn_sign") { StandingSignBlock(AbstractBlock.Settings.of(Material.WOOD).noCollission().strength(1.0f).sounds(BlockSoundGroup.WOOD), APRICORN_WOOD_TYPE) }
|
||||
//val APRICORN_WALL_SIGN = queue("apricorn_wall_sign") { WallSignBlock(AbstractBlock.Settings.of(Material.WOOD).noCollission().strength(1.0f).sounds(BlockSoundGroup.WOOD).dropsLike(APRICORN_SIGN), APRICORN_WOOD_TYPE) }
|
||||
@JvmField
|
||||
val APRICORN_SIGN = this.create("apricorn_sign", CobblemonSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_SIGN), APRICORN_WOOD_TYPE))
|
||||
@JvmField
|
||||
val APRICORN_WALL_SIGN = this.create("apricorn_wall_sign", CobblemonWallSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_WALL_SIGN), APRICORN_WOOD_TYPE))
|
||||
@JvmField
|
||||
val APRICORN_HANGING_SIGN = this.create("apricorn_hanging_sign", CobblemonHangingSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_WALL_HANGING_SIGN), APRICORN_WOOD_TYPE))
|
||||
@JvmField
|
||||
val APRICORN_WALL_HANGING_SIGN = this.create("apricorn_wall_hanging_sign", CobblemonWallHangingSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_HANGING_SIGN), APRICORN_WOOD_TYPE))
|
||||
@JvmField
|
||||
val APRICORN_SLAB = this.create("apricorn_slab", SlabBlock(AbstractBlock.Settings.create().mapColor(MapColor.OAK_TAN).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
|
||||
@JvmField
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import java.util.function.Supplier
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.entity.BlockEntity
|
||||
import net.minecraft.block.entity.BlockEntityType
|
||||
@@ -19,11 +18,14 @@ import net.minecraft.client.particle.ParticleFactory
|
||||
import net.minecraft.client.particle.SpriteProvider
|
||||
import net.minecraft.client.render.RenderLayer
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory
|
||||
import net.minecraft.client.render.entity.EntityRendererFactory
|
||||
import net.minecraft.client.render.entity.model.EntityModelLayer
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.entity.EntityType
|
||||
import net.minecraft.item.Item
|
||||
import net.minecraft.particle.ParticleEffect
|
||||
import net.minecraft.particle.ParticleType
|
||||
import net.minecraft.resource.SynchronousResourceReloader
|
||||
import java.util.function.Supplier
|
||||
|
||||
interface CobblemonClientImplementation {
|
||||
fun registerLayer(modelLayer: EntityModelLayer, supplier: Supplier<TexturedModelData>)
|
||||
@@ -38,5 +40,7 @@ interface CobblemonClientImplementation {
|
||||
|
||||
fun registerBlockColors(provider: BlockColorProvider, vararg blocks: Block)
|
||||
|
||||
fun <T : BlockEntity> registerBlockEntityRenderer(type: BlockEntityType<T>, factory: BlockEntityRendererFactory<T>)
|
||||
fun <T : BlockEntity> registerBlockEntityRenderer(type: BlockEntityType<out T>, factory: BlockEntityRendererFactory<T>)
|
||||
|
||||
fun <T : Entity> registerEntityRenderer(type: EntityType<out T>, factory: EntityRendererFactory<T>)
|
||||
}
|
||||
@@ -46,5 +46,6 @@ object CobblemonCommands {
|
||||
ClearPartyCommand.register(dispatcher)
|
||||
ClearPCCommand.register(dispatcher)
|
||||
PokemonRestartCommand.register(dispatcher)
|
||||
BedrockParticleCommand.register(dispatcher)
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatEntity
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonChestBoatEntity
|
||||
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
@@ -45,6 +47,24 @@ object CobblemonEntities : PlatformRegistry<Registry<EntityType<*>>, RegistryKey
|
||||
.build(EMPTY_POKEBALL_KEY.toString())
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val BOAT_KEY = cobblemonResource("boat")
|
||||
@JvmField
|
||||
val BOAT: EntityType<CobblemonBoatEntity> = this.create(
|
||||
BOAT_KEY.path,
|
||||
EntityType.Builder.create(::CobblemonBoatEntity, SpawnGroup.MISC).setDimensions(1.375F, 0.5625F).maxTrackingRange(10)
|
||||
.build(BOAT_KEY.toString())
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val CHEST_BOAT_KEY = cobblemonResource("chest_boat")
|
||||
@JvmField
|
||||
val CHEST_BOAT: EntityType<CobblemonChestBoatEntity> = this.create(
|
||||
CHEST_BOAT_KEY.path,
|
||||
EntityType.Builder.create(::CobblemonChestBoatEntity, SpawnGroup.MISC).setDimensions(1.375F, 0.5625F).maxTrackingRange(10)
|
||||
.build(CHEST_BOAT_KEY.toString())
|
||||
)
|
||||
|
||||
fun registerAttributes(consumer: (EntityType<out LivingEntity>, DefaultAttributeContainer.Builder) -> Unit) {
|
||||
consumer(POKEMON, PokemonEntity.createAttributes())
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
import com.cobblemon.mod.common.block.BerryBlock
|
||||
import com.cobblemon.mod.common.block.MintBlock
|
||||
import com.cobblemon.mod.common.block.MintBlock.MintType
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
|
||||
import com.cobblemon.mod.common.item.*
|
||||
import com.cobblemon.mod.common.item.battle.DireHitItem
|
||||
import com.cobblemon.mod.common.item.battle.GuardSpecItem
|
||||
@@ -27,7 +28,6 @@ import com.cobblemon.mod.common.item.berry.PortionHealingBerryItem
|
||||
import com.cobblemon.mod.common.item.berry.StatusCuringBerryItem
|
||||
import com.cobblemon.mod.common.item.berry.VolatileCuringBerryItem
|
||||
import com.cobblemon.mod.common.item.interactive.*
|
||||
import com.cobblemon.mod.common.item.interactive.PotionItem
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import com.cobblemon.mod.common.pokeball.PokeBall
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
@@ -36,7 +36,13 @@ import net.minecraft.block.Block
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.entity.effect.StatusEffectInstance
|
||||
import net.minecraft.entity.effect.StatusEffects
|
||||
import net.minecraft.item.*
|
||||
import net.minecraft.item.BlockItem
|
||||
import net.minecraft.item.FoodComponent
|
||||
import net.minecraft.item.HangingSignItem
|
||||
import net.minecraft.item.Item
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.item.SignItem
|
||||
import net.minecraft.item.StewItem
|
||||
import net.minecraft.registry.Registries
|
||||
import net.minecraft.registry.Registry
|
||||
import net.minecraft.registry.RegistryKey
|
||||
@@ -123,34 +129,34 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
val VIVICHOKE_SEEDS = compostableItem("vivichoke_seeds", VivichokeItem(CobblemonBlocks.VIVICHOKE_SEEDS))
|
||||
|
||||
@JvmField
|
||||
val RED_APRICORN = apricronItem("red", ApricornItem(CobblemonBlocks.RED_APRICORN))
|
||||
val RED_APRICORN = apricornItem("red", ApricornItem(CobblemonBlocks.RED_APRICORN))
|
||||
@JvmField
|
||||
val YELLOW_APRICORN = apricronItem("yellow", ApricornItem(CobblemonBlocks.YELLOW_APRICORN))
|
||||
val YELLOW_APRICORN = apricornItem("yellow", ApricornItem(CobblemonBlocks.YELLOW_APRICORN))
|
||||
@JvmField
|
||||
val GREEN_APRICORN = apricronItem("green", ApricornItem(CobblemonBlocks.GREEN_APRICORN))
|
||||
val GREEN_APRICORN = apricornItem("green", ApricornItem(CobblemonBlocks.GREEN_APRICORN))
|
||||
@JvmField
|
||||
val BLUE_APRICORN = apricronItem("blue", ApricornItem(CobblemonBlocks.BLUE_APRICORN))
|
||||
val BLUE_APRICORN = apricornItem("blue", ApricornItem(CobblemonBlocks.BLUE_APRICORN))
|
||||
@JvmField
|
||||
val PINK_APRICORN = apricronItem("pink", ApricornItem(CobblemonBlocks.PINK_APRICORN))
|
||||
val PINK_APRICORN = apricornItem("pink", ApricornItem(CobblemonBlocks.PINK_APRICORN))
|
||||
@JvmField
|
||||
val BLACK_APRICORN = apricronItem("black", ApricornItem(CobblemonBlocks.BLACK_APRICORN))
|
||||
val BLACK_APRICORN = apricornItem("black", ApricornItem(CobblemonBlocks.BLACK_APRICORN))
|
||||
@JvmField
|
||||
val WHITE_APRICORN = apricronItem("white", ApricornItem(CobblemonBlocks.WHITE_APRICORN))
|
||||
val WHITE_APRICORN = apricornItem("white", ApricornItem(CobblemonBlocks.WHITE_APRICORN))
|
||||
|
||||
@JvmField
|
||||
val RED_APRICORN_SEED = apricronSeedItem("red", ApricornSeedItem(CobblemonBlocks.RED_APRICORN_SAPLING))
|
||||
val RED_APRICORN_SEED = apricornSeedItem("red", ApricornSeedItem(CobblemonBlocks.RED_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val YELLOW_APRICORN_SEED = apricronSeedItem("yellow", ApricornSeedItem(CobblemonBlocks.YELLOW_APRICORN_SAPLING))
|
||||
val YELLOW_APRICORN_SEED = apricornSeedItem("yellow", ApricornSeedItem(CobblemonBlocks.YELLOW_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val GREEN_APRICORN_SEED = apricronSeedItem("green", ApricornSeedItem(CobblemonBlocks.GREEN_APRICORN_SAPLING))
|
||||
val GREEN_APRICORN_SEED = apricornSeedItem("green", ApricornSeedItem(CobblemonBlocks.GREEN_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val BLUE_APRICORN_SEED = apricronSeedItem("blue", ApricornSeedItem(CobblemonBlocks.BLUE_APRICORN_SAPLING))
|
||||
val BLUE_APRICORN_SEED = apricornSeedItem("blue", ApricornSeedItem(CobblemonBlocks.BLUE_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val PINK_APRICORN_SEED = apricronSeedItem("pink", ApricornSeedItem(CobblemonBlocks.PINK_APRICORN_SAPLING))
|
||||
val PINK_APRICORN_SEED = apricornSeedItem("pink", ApricornSeedItem(CobblemonBlocks.PINK_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val BLACK_APRICORN_SEED = apricronSeedItem("black", ApricornSeedItem(CobblemonBlocks.BLACK_APRICORN_SAPLING))
|
||||
val BLACK_APRICORN_SEED = apricornSeedItem("black", ApricornSeedItem(CobblemonBlocks.BLACK_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val WHITE_APRICORN_SEED = apricronSeedItem("white", ApricornSeedItem(CobblemonBlocks.WHITE_APRICORN_SAPLING))
|
||||
val WHITE_APRICORN_SEED = apricornSeedItem("white", ApricornSeedItem(CobblemonBlocks.WHITE_APRICORN_SAPLING))
|
||||
|
||||
@JvmField
|
||||
val APRICORN_LOG = blockItem("apricorn_log", CobblemonBlocks.APRICORN_LOG)
|
||||
@@ -164,6 +170,10 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
val APRICORN_PLANKS = blockItem("apricorn_planks", CobblemonBlocks.APRICORN_PLANKS)
|
||||
@JvmField
|
||||
val APRICORN_LEAVES = compostableBlockItem("apricorn_leaves", CobblemonBlocks.APRICORN_LEAVES)
|
||||
@JvmField
|
||||
val APRICORN_BOAT = create("apricorn_boat", CobblemonBoatItem(CobblemonBoatType.APRICORN, false, Item.Settings().maxCount(1)))
|
||||
@JvmField
|
||||
val APRICORN_CHEST_BOAT = create("apricorn_chest_boat", CobblemonBoatItem(CobblemonBoatType.APRICORN, true, Item.Settings().maxCount(1)))
|
||||
|
||||
@JvmField
|
||||
val APRICORN_DOOR = blockItem("apricorn_door", CobblemonBlocks.APRICORN_DOOR)
|
||||
@@ -177,12 +187,14 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
val APRICORN_BUTTON = blockItem("apricorn_button", CobblemonBlocks.APRICORN_BUTTON)
|
||||
@JvmField
|
||||
val APRICORN_PRESSURE_PLATE = blockItem("apricorn_pressure_plate", CobblemonBlocks.APRICORN_PRESSURE_PLATE)
|
||||
//@JvmField
|
||||
// val APRICORN_SIGN = create("apricorn_sign", SignItem(Item.Properties().stacksTo(16).tab(CreativeModeTab.TAB_DECORATIONS), CobblemonBlocks.APRICORN_SIGN, CobblemonBlocks.APRICORN_WALL_SIGN))
|
||||
@JvmField
|
||||
val APRICORN_SLAB = blockItem("apricorn_slab", CobblemonBlocks.APRICORN_SLAB)
|
||||
@JvmField
|
||||
val APRICORN_STAIRS = blockItem("apricorn_stairs", CobblemonBlocks.APRICORN_STAIRS)
|
||||
@JvmField
|
||||
val APRICORN_SIGN = this.create("apricorn_sign", SignItem(Item.Settings().maxCount(16), CobblemonBlocks.APRICORN_SIGN, CobblemonBlocks.APRICORN_WALL_SIGN))
|
||||
@JvmField
|
||||
val APRICORN_HANGING_SIGN = this.create("apricorn_hanging_sign", HangingSignItem(CobblemonBlocks.APRICORN_HANGING_SIGN, CobblemonBlocks.APRICORN_WALL_HANGING_SIGN, Item.Settings().maxCount(16)))
|
||||
|
||||
@JvmField
|
||||
val HEALING_MACHINE = blockItem("healing_machine", CobblemonBlocks.HEALING_MACHINE)
|
||||
@@ -564,10 +576,14 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
@JvmField
|
||||
val CHOICE_SPECS = heldItem("choice_specs")
|
||||
@JvmField
|
||||
val CLEANSE_TAG = heldItem("cleanse_tag")
|
||||
@JvmField
|
||||
val DRAGON_FANG = heldItem("dragon_fang")
|
||||
@JvmField
|
||||
val EXP_SHARE = heldItem("exp_share")
|
||||
@JvmField
|
||||
val FAIRY_FEATHER = heldItem("fairy_feather")
|
||||
@JvmField
|
||||
val FOCUS_BAND = heldItem("focus_band")
|
||||
@JvmField
|
||||
val HARD_STONE = heldItem("hard_stone")
|
||||
@@ -612,13 +628,13 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
@JvmField
|
||||
val WISE_GLASSES = heldItem("wise_glasses")
|
||||
@JvmField
|
||||
val MENTAL_HERB = compostableHeldItem("mental_herb")
|
||||
val MENTAL_HERB = compostableHeldItem("mental_herb", null, 1F)
|
||||
@JvmField
|
||||
val MIRROR_HERB = compostableHeldItem("mirror_herb")
|
||||
val MIRROR_HERB = compostableHeldItem("mirror_herb", null, 1F)
|
||||
@JvmField
|
||||
val POWER_HERB = compostableHeldItem("power_herb")
|
||||
val POWER_HERB = compostableHeldItem("power_herb", null, 1F)
|
||||
@JvmField
|
||||
val WHITE_HERB = heldItem("white_herb")
|
||||
val WHITE_HERB = compostableHeldItem("white_herb", null, 1F)
|
||||
@JvmField
|
||||
val BRIGHT_POWDER = heldItem("bright_powder")
|
||||
@JvmField
|
||||
@@ -641,6 +657,14 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
val POWER_LENS = heldItem("power_lens")
|
||||
@JvmField
|
||||
val POWER_WEIGHT = heldItem("power_weight")
|
||||
@JvmField
|
||||
val FLAME_ORB = heldItem("flame_orb")
|
||||
@JvmField
|
||||
val LIFE_ORB = heldItem("life_orb")
|
||||
@JvmField
|
||||
val TOXIC_ORB = heldItem("toxic_orb")
|
||||
@JvmField
|
||||
val SMOKE_BALL = heldItem("smoke_ball")
|
||||
|
||||
// Mulch
|
||||
@JvmField
|
||||
@@ -717,16 +741,16 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
return item
|
||||
}
|
||||
|
||||
private fun apricronItem(name: String, apricornItem: ApricornItem): ApricornItem {
|
||||
private fun apricornItem(name: String, apricornItem: ApricornItem): ApricornItem {
|
||||
val finalName = "${name}_apricorn"
|
||||
val item = this.create(finalName, apricornItem)
|
||||
compostable(item, .65f)
|
||||
return item
|
||||
}
|
||||
|
||||
private fun apricronSeedItem(name: String, apricronSeedItem: ApricornSeedItem): ApricornSeedItem {
|
||||
private fun apricornSeedItem(name: String, apricornSeedItem: ApricornSeedItem): ApricornSeedItem {
|
||||
val finalName = "${name}_apricorn_seed"
|
||||
val item = this.create(finalName, apricronSeedItem)
|
||||
val item = this.create(finalName, apricornSeedItem)
|
||||
compostable(item, .65f)
|
||||
return item
|
||||
}
|
||||
|
||||
@@ -11,8 +11,27 @@ package com.cobblemon.mod.common
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.PlayerInteractOptionsHandler
|
||||
import com.cobblemon.mod.common.client.net.SetClientPlayerDataHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.*
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleApplyPassResponseHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleCaptureEndHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleCaptureShakeHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleCaptureStartHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleChallengeExpiredHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleChallengeNotificationHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleEndHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleFaintHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleHealthChangeHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleInitializeHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleMadeInvalidChoiceHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleMakeChoiceHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleMessageHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleMusicHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattlePersistentStatusHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleQueueRequestHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleSetTeamPokemonHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleSwitchPokemonHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleUpdateTeamPokemonHandler
|
||||
import com.cobblemon.mod.common.client.net.callback.move.OpenMoveCallbackHandler
|
||||
import com.cobblemon.mod.common.client.net.callback.party.OpenPartyCallbackHandler
|
||||
import com.cobblemon.mod.common.client.net.callback.partymove.OpenPartyMoveCallbackHandler
|
||||
@@ -51,6 +70,7 @@ import com.cobblemon.mod.common.client.net.trade.TradeOfferExpiredHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeOfferNotificationHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeStartedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeUpdatedHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.*
|
||||
import com.cobblemon.mod.common.net.messages.client.callback.OpenMoveCallbackPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyCallbackPacket
|
||||
@@ -99,12 +119,10 @@ import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BenchMovePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.RequestMoveSwapPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.*
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectedPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.party.PartyPokemonSelectedPacket
|
||||
@@ -134,7 +152,10 @@ import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptanceP
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.RequestInteractionsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.RemoveSpectatorHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectCancelledHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectedHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.party.PartyPokemonSelectedHandler
|
||||
@@ -168,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.
|
||||
@@ -238,6 +259,7 @@ object CobblemonNetwork : NetworkManager {
|
||||
// UI Packets
|
||||
this.createClientBound(SummaryUIPacket.ID, SummaryUIPacket::decode, SummaryUIPacketHandler)
|
||||
this.createClientBound(InteractPokemonUIPacket.ID, InteractPokemonUIPacket::decode, InteractPokemonUIPacketHandler)
|
||||
this.createClientBound(PlayerInteractOptionsPacket.ID, PlayerInteractOptionsPacket::decode, PlayerInteractOptionsHandler)
|
||||
|
||||
// Starter packets
|
||||
this.createClientBound(OpenStarterUIPacket.ID, OpenStarterUIPacket::decode, StarterUIPacketHandler)
|
||||
@@ -323,6 +345,7 @@ object CobblemonNetwork : NetworkManager {
|
||||
|
||||
// Interaction Packets
|
||||
this.createServerBound(InteractPokemonPacket.ID, InteractPokemonPacket::decode, InteractPokemonHandler)
|
||||
this.createServerBound(RequestPlayerInteractionsPacket.ID, RequestPlayerInteractionsPacket::decode, RequestInteractionsHandler)
|
||||
|
||||
// Storage Packets
|
||||
this.createServerBound(SendOutPokemonPacket.ID, SendOutPokemonPacket::decode, SendOutPokemonHandler)
|
||||
@@ -350,6 +373,8 @@ object CobblemonNetwork : NetworkManager {
|
||||
|
||||
// Battle packets
|
||||
this.createServerBound(BattleSelectActionsPacket.ID, BattleSelectActionsPacket::decode, BattleSelectActionsHandler)
|
||||
this.createServerBound(SpectateBattlePacket.ID, SpectateBattlePacket::decode, SpectateBattleHandler)
|
||||
this.createServerBound(RemoveSpectatorPacket.ID, RemoveSpectatorPacket::decode, RemoveSpectatorHandler)
|
||||
|
||||
// Trade
|
||||
this.createServerBound(AcceptTradeRequestPacket.ID, AcceptTradeRequestPacket::decode, AcceptTradeRequestHandler)
|
||||
|
||||
+22
-10
@@ -40,14 +40,15 @@ import com.cobblemon.mod.common.net.messages.client.battle.BattleEndPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMusicPacket
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.DefeatEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.LastBattleCriticalHitsEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.evolution.requirements.DefeatRequirement
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
import java.io.File
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.text.Text
|
||||
import java.util.concurrent.ConcurrentLinkedDeque
|
||||
|
||||
/**
|
||||
* Individual battle instance
|
||||
@@ -55,6 +56,7 @@ import net.minecraft.text.Text
|
||||
* @since January 16th, 2022
|
||||
* @author Deltric, Hiroku
|
||||
*/
|
||||
@Suppress("unused", "MemberVisibilityCanBePrivate")
|
||||
open class PokemonBattle(
|
||||
val format: BattleFormat,
|
||||
val side1: BattleSide,
|
||||
@@ -67,8 +69,11 @@ open class PokemonBattle(
|
||||
side1.battle = this
|
||||
side2.battle = this
|
||||
this.actors.forEach { actor ->
|
||||
actor.battle = this
|
||||
actor.pokemonList.forEach { battlePokemon ->
|
||||
battlePokemon.criticalHits = 0
|
||||
battlePokemon.effectedPokemon.evolutionProxy.current().progress()
|
||||
.filterIsInstance<LastBattleCriticalHitsEvolutionProgress>()
|
||||
.forEach { it.reset() }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,12 +87,13 @@ open class PokemonBattle(
|
||||
val playerUUIDs: Iterable<UUID>
|
||||
get() = actors.flatMap { it.getPlayerUUIDs() }
|
||||
val players = playerUUIDs.mapNotNull { it.getPlayer() }
|
||||
val spectators = mutableListOf<UUID>()
|
||||
val spectators = mutableSetOf<UUID>()
|
||||
|
||||
val battleId = UUID.randomUUID()
|
||||
|
||||
val showdownMessages = mutableListOf<String>()
|
||||
val battleLog = mutableListOf<String>()
|
||||
val chatLog = mutableListOf<Text>()
|
||||
var started = false
|
||||
var ended = false
|
||||
// TEMP battle showcase stuff
|
||||
@@ -97,7 +103,7 @@ open class PokemonBattle(
|
||||
|
||||
|
||||
var dispatchResult = GO
|
||||
val dispatches = ConcurrentLinkedQueue<BattleDispatch>()
|
||||
val dispatches = ConcurrentLinkedDeque<BattleDispatch>()
|
||||
val afterDispatches = mutableListOf<() -> Unit>()
|
||||
|
||||
val captureActions = mutableListOf<BattleCaptureAction>()
|
||||
@@ -175,11 +181,8 @@ open class PokemonBattle(
|
||||
}
|
||||
|
||||
fun broadcastChatMessage(component: Text) {
|
||||
spectators.forEach { spectatorId ->
|
||||
spectatorId.getPlayer()?.let {
|
||||
CobblemonNetwork.sendPacketToPlayer(it, BattleMessagePacket(component))
|
||||
}
|
||||
}
|
||||
chatLog.add(component)
|
||||
sendSpectatorUpdate(BattleMessagePacket(component))
|
||||
return actors.forEach { it.sendMessage(component) }
|
||||
}
|
||||
|
||||
@@ -250,7 +253,6 @@ open class PokemonBattle(
|
||||
}
|
||||
}
|
||||
sendUpdate(BattleEndPacket())
|
||||
sendUpdate(BattleMusicPacket(null))
|
||||
BattleRegistry.closeBattle(this)
|
||||
}
|
||||
|
||||
@@ -317,6 +319,12 @@ open class PokemonBattle(
|
||||
|
||||
fun dispatch(dispatcher: () -> DispatchResult) {
|
||||
dispatches.add(BattleDispatch { dispatcher() })
|
||||
|
||||
}
|
||||
|
||||
fun dispatchToFront(dispatcher: () -> DispatchResult) {
|
||||
dispatches.addFirst(BattleDispatch { dispatcher() })
|
||||
|
||||
}
|
||||
|
||||
fun dispatchGo(dispatcher: () -> Unit) {
|
||||
@@ -348,6 +356,10 @@ open class PokemonBattle(
|
||||
dispatches.add(dispatcher)
|
||||
}
|
||||
|
||||
fun dispatchToFront(dispatcher: BattleDispatch) {
|
||||
dispatches.addFirst(dispatcher)
|
||||
}
|
||||
|
||||
fun doWhenClear(action: () -> Unit) {
|
||||
afterDispatches.add(action)
|
||||
}
|
||||
|
||||
+5
-16
@@ -9,26 +9,19 @@
|
||||
package com.cobblemon.mod.common.api.events.battles
|
||||
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.battles.BattleFormat
|
||||
import net.minecraft.text.MutableText
|
||||
|
||||
/**
|
||||
* Event fired before a [PokemonBattle] is started. Canceling this event prevents the battle from being
|
||||
* created and launched.
|
||||
*
|
||||
* @property reason The text used to inform the participants why the battle was canceled. Keep null for a default error.
|
||||
*
|
||||
* @author Segfault Guy
|
||||
* @since March 26th 2023
|
||||
*/
|
||||
data class BattleStartedPreEvent (
|
||||
|
||||
val participants: Collection<BattleActor>,
|
||||
val format: BattleFormat,
|
||||
val isPvP: Boolean,
|
||||
val isPvN: Boolean,
|
||||
val isPvW: Boolean
|
||||
|
||||
) : Cancelable()
|
||||
data class BattleStartedPreEvent (override val battle: PokemonBattle, var reason: MutableText? = null) : BattleEvent, Cancelable()
|
||||
|
||||
/**
|
||||
* Event fired after a [PokemonBattle] starts.
|
||||
@@ -36,8 +29,4 @@ data class BattleStartedPreEvent (
|
||||
* @author Segfault Guy
|
||||
* @since March 26th 2023
|
||||
*/
|
||||
data class BattleStartedPostEvent (
|
||||
|
||||
override val battle: PokemonBattle
|
||||
|
||||
) : BattleEvent
|
||||
data class BattleStartedPostEvent (override val battle: PokemonBattle) : BattleEvent
|
||||
@@ -196,6 +196,8 @@ fun drawPortraitPokemon(
|
||||
val context = RenderContext()
|
||||
PokemonModelRepository.getTextureNoSubstitute(species.resourceIdentifier, aspects, 0f).let { it -> context.put(RenderContext.TEXTURE, it) }
|
||||
context.put(RenderContext.SCALE, species.getForm(aspects).baseScale)
|
||||
context.put(RenderContext.SPECIES, species.resourceIdentifier)
|
||||
context.put(RenderContext.ASPECTS, aspects)
|
||||
|
||||
val renderType = model.getLayer(texture)
|
||||
|
||||
|
||||
@@ -66,7 +66,15 @@ interface PokemonSelectingItem {
|
||||
return if (entity != null) {
|
||||
val pokemon = entity.pokemon
|
||||
if (entity.ownerUuid == player.uuid) {
|
||||
applyToPokemon(player, stack, pokemon) ?: TypedActionResult.pass(stack)
|
||||
val typedActionResult = applyToPokemon(player, stack, pokemon)
|
||||
if (typedActionResult != null)
|
||||
{
|
||||
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(pokemon.species.resourceIdentifier, Registries.ITEM.getId(stack.item)))
|
||||
typedActionResult
|
||||
}
|
||||
else {
|
||||
TypedActionResult.pass(stack)
|
||||
}
|
||||
} else {
|
||||
TypedActionResult.fail(stack)
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@ object CobblemonPermissions {
|
||||
val HEAL_POKEMON_SELF = this.create("$HEAL_POKEMON_BASE.self", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
val HEAL_POKEMON_OTHER = this.create("$HEAL_POKEMON_BASE.other", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
|
||||
private const val LEVEL_UP_BASE = "${COMMAND_PREFIX}levelup"
|
||||
val LEVEL_UP_SELF = this.create("$LEVEL_UP_BASE.self", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
val LEVEL_UP_OTHER = this.create("$LEVEL_UP_BASE.other", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
val OPEN_STARTER_SCREEN = this.create("${COMMAND_PREFIX}openstarterscreen", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
val BEDROCK_PARTICLE = this.create("${COMMAND_PREFIX}bedrockparticle", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
private const val POKEMON_EDIT_BASE = "${COMMAND_PREFIX}pokemonedit"
|
||||
val POKEMON_EDIT_SELF = this.create("$POKEMON_EDIT_BASE.self", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
@@ -61,6 +61,7 @@ import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.math.Box
|
||||
import net.minecraft.world.biome.Biome
|
||||
import net.minecraft.world.gen.structure.Structure
|
||||
|
||||
object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
|
||||
@@ -93,6 +94,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, BiomeLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Block::class.java).type, BlockLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Structure::class.java).type, StructureLikeConditionAdapter)
|
||||
.registerTypeAdapter(EggGroup::class.java, EggGroupAdapter)
|
||||
.registerTypeAdapter(StatusEffect::class.java, RegistryElementAdapter<StatusEffect> { Registries.STATUS_EFFECT })
|
||||
.registerTypeAdapter(NbtItemPredicate::class.java, NbtItemPredicateAdapter)
|
||||
@@ -236,8 +238,8 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
"spd" to (form?.baseStats?.get(Stats.SPECIAL_DEFENCE) ?: species.baseStats[Stats.SPECIAL_DEFENCE] ?: 1),
|
||||
"spe" to (form?.baseStats?.get(Stats.SPEED) ?: species.baseStats[Stats.SPEED] ?: 1)
|
||||
)
|
||||
val heightm = form?.height ?: species.height
|
||||
val weightkg = form?.weight ?: species.weight
|
||||
val heightm = (form?.height ?: species.height) / 10
|
||||
val weightkg = (form?.weight ?: species.weight) / 10
|
||||
// This is ugly, but we already have it hardcoded in the mod anyway
|
||||
val maxHP = if (species.showdownId() == "shedinja") 1 else null
|
||||
val canGigantamax: String? = if (form?.gigantamaxMove != null) form.gigantamaxMove.name else null
|
||||
|
||||
+4
-2
@@ -8,14 +8,16 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.pokemon.evolution.progress
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.RecoilEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.UseMoveEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.*
|
||||
|
||||
object EvolutionProgressFactory {
|
||||
|
||||
private val variants = hashMapOf<String, () -> EvolutionProgress<*>>()
|
||||
|
||||
init {
|
||||
registerVariant(DamageTakenEvolutionProgress.ID.toString()) { DamageTakenEvolutionProgress() }
|
||||
registerVariant(DefeatEvolutionProgress.ID.toString()) { DefeatEvolutionProgress() }
|
||||
registerVariant(LastBattleCriticalHitsEvolutionProgress.ID.toString()) { LastBattleCriticalHitsEvolutionProgress() }
|
||||
registerVariant(RecoilEvolutionProgress.ID.toString()) { RecoilEvolutionProgress() }
|
||||
registerVariant(UseMoveEvolutionProgress.ID.toString()) { UseMoveEvolutionProgress() }
|
||||
}
|
||||
|
||||
+10
@@ -79,6 +79,16 @@ interface HeldItemManager {
|
||||
*/
|
||||
fun take(pokemon: BattlePokemon, showdownId: String)
|
||||
|
||||
/**
|
||||
* Tests if the given [BattlePokemon] should have their item consumed.
|
||||
* This method is expected to be used in each implementation when needed.
|
||||
*
|
||||
* @param pokemon The [BattlePokemon] being tested.
|
||||
* @param battle The [PokemonBattle] the [pokemon] is participating in.
|
||||
* @param showdownId The literal ID of the held item on Showdown.
|
||||
*/
|
||||
fun shouldConsumeItem(pokemon: BattlePokemon, battle: PokemonBattle, showdownId: String): Boolean = false
|
||||
|
||||
companion object {
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.pokemon.status
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.status.PersistentStatus
|
||||
import com.cobblemon.mod.common.pokemon.status.statuses.BurnStatus
|
||||
import com.cobblemon.mod.common.pokemon.status.statuses.FrozenStatus
|
||||
import com.cobblemon.mod.common.pokemon.status.statuses.ParalysisStatus
|
||||
@@ -39,4 +40,5 @@ object Statuses {
|
||||
|
||||
fun getStatus(name: Identifier) = allStatuses.find { status -> status.name == name }
|
||||
fun getStatus(showdownName: String) = allStatuses.find { it.showdownName == showdownName }
|
||||
fun getPersistentStatuses() = allStatuses.filterIsInstance<PersistentStatus>()
|
||||
}
|
||||
+6
-4
@@ -20,6 +20,7 @@ import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Box
|
||||
import net.minecraft.util.math.ChunkSectionPos.getSectionCoord
|
||||
import net.minecraft.util.math.Vec3d
|
||||
import net.minecraft.world.LightType
|
||||
import net.minecraft.world.chunk.Chunk
|
||||
import net.minecraft.world.chunk.ChunkStatus
|
||||
|
||||
@@ -69,7 +70,7 @@ object CobblemonSpawningProspector : SpawningProspector {
|
||||
.map { it.pos }
|
||||
|
||||
val defaultState = Blocks.STONE.defaultState
|
||||
val defaultBlockData = WorldSlice.BlockData(defaultState, 0)
|
||||
val defaultBlockData = WorldSlice.BlockData(defaultState, 0, 0)
|
||||
|
||||
val blocks = Array(area.length) { Array(height) { Array(area.width) { defaultBlockData } } }
|
||||
val skyLevel = Array(area.length) { Array(area.width) { world.topY } }
|
||||
@@ -77,6 +78,7 @@ object CobblemonSpawningProspector : SpawningProspector {
|
||||
|
||||
val chunks = mutableMapOf<Pair<Int, Int>, Chunk?>()
|
||||
val yRange = (baseY until baseY + height).reversed()
|
||||
val lightingProvider = world.lightingProvider
|
||||
for (x in area.baseX until area.baseX + area.length) {
|
||||
for (z in area.baseZ until area.baseZ + area.width) {
|
||||
val query = chunks.computeIfAbsent(Pair(getSectionCoord(x), getSectionCoord(z))) {
|
||||
@@ -85,16 +87,16 @@ object CobblemonSpawningProspector : SpawningProspector {
|
||||
|
||||
var canSeeSky = world.isSkyVisibleAllowingSea(pos.set(x, yRange.first, z))
|
||||
for (y in yRange) {
|
||||
val skyLight = lightingProvider.get(LightType.SKY).getLightLevel(pos.set(x, y, z))
|
||||
val state = query.getBlockState(pos.set(x, y, z))
|
||||
blocks[x - area.baseX][y - baseY][z - area.baseZ] = WorldSlice.BlockData(
|
||||
state = state,
|
||||
light = world.getLightLevel(pos)
|
||||
light = world.getLightLevel(pos),
|
||||
skyLight = skyLight
|
||||
)
|
||||
|
||||
if (canSeeSky) {
|
||||
skyLevel[x - area.baseX][z - area.baseZ] = y
|
||||
}
|
||||
|
||||
if (state.fluidState.isEmpty && !state.isIn(CobblemonBlockTags.SEES_SKY)) {
|
||||
canSeeSky = false
|
||||
}
|
||||
|
||||
@@ -31,12 +31,16 @@ open class SpawnerManager {
|
||||
|
||||
open fun registerSpawner(spawner: Spawner) {
|
||||
spawners.add(spawner)
|
||||
spawner.influences.addAll(influences)
|
||||
if (spawner !is TickingSpawner) {
|
||||
spawner.influences.addAll(influences)
|
||||
}
|
||||
}
|
||||
|
||||
open fun unregisterSpawner(spawner: Spawner) {
|
||||
spawners.remove(spawner)
|
||||
spawner.influences.removeAll(influences)
|
||||
if (spawner !is TickingSpawner) {
|
||||
spawner.influences.removeAll(influences)
|
||||
}
|
||||
}
|
||||
|
||||
open fun onServerStarted() {
|
||||
|
||||
@@ -44,7 +44,8 @@ class WorldSlice(
|
||||
) {
|
||||
class BlockData(
|
||||
val state: BlockState,
|
||||
val light: Int
|
||||
val light: Int,
|
||||
val skyLight: Int
|
||||
)
|
||||
|
||||
val length = blocks.size
|
||||
@@ -83,6 +84,15 @@ class WorldSlice(
|
||||
}
|
||||
fun getLight(position: BlockPos, elseLight: Int = 0) = getLight(position.x, position.y, position.z, elseLight)
|
||||
|
||||
fun getSkyLight(x: Int, y: Int, z: Int, elseLight: Int = 0): Int {
|
||||
return if (!isInBounds(x, y, z)) {
|
||||
elseLight
|
||||
} else {
|
||||
getBlockData(x, y, z).skyLight
|
||||
}
|
||||
}
|
||||
fun getSkyLight(position: BlockPos, elseLight: Int = 0) = getSkyLight(position.x, position.y, position.z, elseLight)
|
||||
|
||||
fun skySpaceAbove(x: Int, y: Int, z: Int): Int {
|
||||
return if (!isInBounds(x, y, z) || skyLevel[x - baseX][z - baseZ] > y) {
|
||||
0
|
||||
|
||||
+6
@@ -52,6 +52,8 @@ abstract class SpawningCondition<T : SpawningContext> {
|
||||
var maxZ: Float? = null
|
||||
var minLight: Int? = null
|
||||
var maxLight: Int? = null
|
||||
var minSkyLight: Int? = null
|
||||
var maxSkyLight: Int? = null
|
||||
var isRaining: Boolean? = null
|
||||
var isThundering: Boolean? = null
|
||||
var timeRange: TimeRange? = null
|
||||
@@ -88,6 +90,8 @@ abstract class SpawningCondition<T : SpawningContext> {
|
||||
return false
|
||||
} else if (ctx.light > maxLight.orMax() || ctx.light < minLight.orMin()) {
|
||||
return false
|
||||
} else if (ctx.skyLight > maxSkyLight.orMax() || ctx.skyLight < minSkyLight.orMin()) {
|
||||
return false
|
||||
} else if (timeRange != null && !timeRange!!.contains((ctx.world.timeOfDay % 24000).toInt())) {
|
||||
return false
|
||||
} else if (canSeeSky != null && canSeeSky != ctx.canSeeSky) {
|
||||
@@ -134,6 +138,8 @@ abstract class SpawningCondition<T : SpawningContext> {
|
||||
maxZ = merger.mergeSingle(maxZ, other.maxZ)
|
||||
minLight = merger.mergeSingle(minLight, other.minLight)
|
||||
maxLight = merger.mergeSingle(maxLight, other.maxLight)
|
||||
minSkyLight = merger.mergeSingle(minSkyLight, other.minSkyLight)
|
||||
maxSkyLight = merger.mergeSingle(maxSkyLight, other.maxSkyLight)
|
||||
timeRange = merger.mergeSingle(timeRange, other.timeRange)
|
||||
structures = merger.merge(structures, other.structures)?.toMutableList()
|
||||
}
|
||||
|
||||
+1
@@ -30,6 +30,7 @@ open class AreaSpawningContext(
|
||||
override val world: ServerWorld,
|
||||
override val position: BlockPos,
|
||||
override val light: Int,
|
||||
override val skyLight: Int,
|
||||
override val canSeeSky: Boolean,
|
||||
override val influences: MutableList<SpawningInfluence>,
|
||||
/** Space above. */
|
||||
|
||||
+10
-5
@@ -27,12 +27,13 @@ abstract class FlooredSpawningContext(
|
||||
world: ServerWorld,
|
||||
position: BlockPos,
|
||||
light: Int,
|
||||
skyLight: Int,
|
||||
canSeeSky: Boolean,
|
||||
influences: MutableList<SpawningInfluence>,
|
||||
height: Int,
|
||||
nearbyBlocks: List<BlockState>,
|
||||
slice: WorldSlice
|
||||
) : AreaSpawningContext(cause, world, position, light, canSeeSky, influences, height, nearbyBlocks, slice) {
|
||||
) : AreaSpawningContext(cause, world, position, light, skyLight, canSeeSky, influences, height, nearbyBlocks, slice) {
|
||||
/** The block that the spawning is occurring on. */
|
||||
val baseBlock = slice.getBlockState(position.x, position.y, position.z)
|
||||
}
|
||||
@@ -48,12 +49,13 @@ open class GroundedSpawningContext(
|
||||
world: ServerWorld,
|
||||
position: BlockPos,
|
||||
light: Int,
|
||||
skyLight: Int,
|
||||
canSeeSky: Boolean,
|
||||
influences: MutableList<SpawningInfluence>,
|
||||
height: Int,
|
||||
nearbyBlocks: List<BlockState>,
|
||||
slice: WorldSlice
|
||||
) : FlooredSpawningContext(cause, world, position, light, canSeeSky, influences, height, nearbyBlocks, slice)
|
||||
) : FlooredSpawningContext(cause, world, position, light, skyLight, canSeeSky, influences, height, nearbyBlocks, slice)
|
||||
|
||||
/**
|
||||
* A spawning context that occurs at the bottom of a body of water.
|
||||
@@ -66,12 +68,13 @@ open class SeafloorSpawningContext(
|
||||
world: ServerWorld,
|
||||
position: BlockPos,
|
||||
light: Int,
|
||||
skyLight: Int,
|
||||
canSeeSky: Boolean,
|
||||
influences: MutableList<SpawningInfluence>,
|
||||
height: Int,
|
||||
nearbyBlocks: List<BlockState>,
|
||||
slice: WorldSlice
|
||||
) : FlooredSpawningContext(cause, world, position, light, canSeeSky, influences, height, nearbyBlocks, slice) {
|
||||
) : FlooredSpawningContext(cause, world, position, light, skyLight, canSeeSky, influences, height, nearbyBlocks, slice) {
|
||||
override fun isSafeSpace(world: ServerWorld, pos: BlockPos, state: BlockState) = state.fluidState.isIn(FluidTags.WATER)
|
||||
}
|
||||
|
||||
@@ -86,12 +89,13 @@ open class LavafloorSpawningContext(
|
||||
world: ServerWorld,
|
||||
position: BlockPos,
|
||||
light: Int,
|
||||
skyLight: Int,
|
||||
canSeeSky: Boolean,
|
||||
influences: MutableList<SpawningInfluence>,
|
||||
height: Int,
|
||||
nearbyBlocks: List<BlockState>,
|
||||
slice: WorldSlice
|
||||
) : FlooredSpawningContext(cause, world, position, light, canSeeSky, influences, height, nearbyBlocks, slice) {
|
||||
) : FlooredSpawningContext(cause, world, position, light, skyLight, canSeeSky, influences, height, nearbyBlocks, slice) {
|
||||
override fun isSafeSpace(world: ServerWorld, pos: BlockPos, state: BlockState) = state.fluidState.isIn(FluidTags.LAVA)
|
||||
}
|
||||
|
||||
@@ -100,10 +104,11 @@ open class SurfaceSpawningContext(
|
||||
world: ServerWorld,
|
||||
position: BlockPos,
|
||||
light: Int,
|
||||
skyLight: Int,
|
||||
canSeeSky: Boolean,
|
||||
influences: MutableList<SpawningInfluence>,
|
||||
height: Int,
|
||||
val depth: Int,
|
||||
nearbyBlocks: List<BlockState>,
|
||||
slice: WorldSlice
|
||||
) : FlooredSpawningContext(cause, world, position, light, canSeeSky, influences, height, nearbyBlocks, slice)
|
||||
) : FlooredSpawningContext(cause, world, position, light, skyLight, canSeeSky, influences, height, nearbyBlocks, slice)
|
||||
+2
@@ -61,6 +61,8 @@ abstract class SpawningContext {
|
||||
abstract val position: BlockPos
|
||||
/** The light level at this location. */
|
||||
abstract val light: Int
|
||||
/** The sky light level at this location. (15 - The distance to the nearest block that would be illuminated by the sun */
|
||||
abstract val skyLight: Int
|
||||
/** Whether or not the sky is visible at this location. */
|
||||
abstract val canSeeSky: Boolean
|
||||
/** A list of [SpawningInfluence]s that apply due to this specific context. */
|
||||
|
||||
+2
-1
@@ -26,13 +26,14 @@ open class SubmergedSpawningContext(
|
||||
world: ServerWorld,
|
||||
position: BlockPos,
|
||||
light: Int,
|
||||
skyLight: Int,
|
||||
canSeeSky: Boolean,
|
||||
influences: MutableList<SpawningInfluence>,
|
||||
height: Int,
|
||||
val depth: Int,
|
||||
nearbyBlocks: List<BlockState>,
|
||||
slice: WorldSlice
|
||||
) : AreaSpawningContext(cause, world, position, light, canSeeSky, influences, height, nearbyBlocks, slice) {
|
||||
) : AreaSpawningContext(cause, world, position, light, skyLight, canSeeSky, influences, height, nearbyBlocks, slice) {
|
||||
val fluid = slice.getBlockState(position.x, position.y, position.z).fluidState
|
||||
|
||||
override fun isSafeSpace(world: ServerWorld, pos: BlockPos, state: BlockState) = state.fluidState.fluid == fluid.fluid
|
||||
|
||||
+2
@@ -45,6 +45,8 @@ interface AreaSpawningContextCalculator<O : AreaSpawningContext> : SpawningConte
|
||||
= input.slice.horizontalSpace(input.position.x + offsetX, input.position.y + offsetY, input.position.z + offsetZ, condition, maximum)
|
||||
fun getLight(input: AreaSpawningInput, elseLight: Int = 0): Int
|
||||
= input.slice.getLight(input.position.x, input.position.y + 1, input.position.z, elseLight)
|
||||
fun getSkyLight(input: AreaSpawningInput, elseLight: Int = 0): Int
|
||||
= input.slice.getSkyLight(input.position.x, input.position.y + 1, input.position.z, elseLight)
|
||||
fun getCanSeeSky(input: AreaSpawningInput): Boolean = input.slice.canSeeSky(input.position.x, input.position.y + 1, input.position.z)
|
||||
fun getSkySpaceAbove(input: AreaSpawningInput): Int = input.slice.skySpaceAbove(input.position.x, input.position.y, input.position.z)
|
||||
fun getNearbyBlocks(
|
||||
|
||||
+4
@@ -59,6 +59,7 @@ object GroundedSpawningContextCalculator : FlooredSpawningContextCalculator<Grou
|
||||
world = input.world,
|
||||
position = input.position.toImmutable(),
|
||||
light = getLight(input),
|
||||
skyLight = getSkyLight(input),
|
||||
canSeeSky = getCanSeeSky(input),
|
||||
influences = input.spawner.copyInfluences(),
|
||||
height = getHeight(input, surroundingCondition, config.maxVerticalSpace, offsetY = 1),
|
||||
@@ -85,6 +86,7 @@ object SeafloorSpawningContextCalculator : FlooredSpawningContextCalculator<Seaf
|
||||
world = input.world,
|
||||
position = input.position.toImmutable(),
|
||||
light = getLight(input),
|
||||
skyLight = getSkyLight(input),
|
||||
canSeeSky = getCanSeeSky(input),
|
||||
influences = input.spawner.copyInfluences(),
|
||||
height = getHeight(input, surroundingCondition, config.maxVerticalSpace, offsetY = 1),
|
||||
@@ -111,6 +113,7 @@ object LavafloorSpawningContextCalculator : FlooredSpawningContextCalculator<Lav
|
||||
world = input.world,
|
||||
position = input.position.toImmutable(),
|
||||
light = getLight(input),
|
||||
skyLight = getSkyLight(input),
|
||||
canSeeSky = getCanSeeSky(input),
|
||||
influences = input.spawner.copyInfluences(),
|
||||
height = getHeight(input, surroundingCondition, config.maxVerticalSpace, offsetY = 1),
|
||||
@@ -138,6 +141,7 @@ object SurfaceSpawningContextCalculator : FlooredSpawningContextCalculator<Surfa
|
||||
world = input.world,
|
||||
position = input.position.toImmutable(),
|
||||
light = getLight(input),
|
||||
skyLight = getSkyLight(input),
|
||||
canSeeSky = getCanSeeSky(input),
|
||||
influences = input.spawner.copyInfluences(),
|
||||
height = getHeight(input, surroundingCondition, config.maxVerticalSpace / 2, offsetY = 1),
|
||||
|
||||
+1
@@ -45,6 +45,7 @@ object SubmergedSpawningContextCalculator : AreaSpawningContextCalculator<Submer
|
||||
world = input.world,
|
||||
position = input.position.toImmutable(),
|
||||
light = getLight(input),
|
||||
skyLight = getSkyLight(input),
|
||||
canSeeSky = getCanSeeSky(input),
|
||||
influences = input.spawner.copyInfluences(),
|
||||
height = getHeight(input, fluidCondition, ceil(config.maxVerticalSpace / 2F)),
|
||||
|
||||
+4
-3
@@ -42,9 +42,9 @@ open class PlayerLevelRangeInfluence(
|
||||
|
||||
val party = Cobblemon.storage.getParty(uuid)
|
||||
previousRange = if (party.any()) {
|
||||
val minimumLevel = party.minOf { it.level }
|
||||
//val minimumLevel = party.minOf { it.level }
|
||||
val maximumLevel = party.maxOf { it.level }
|
||||
IntRange(max(minimumLevel - variation, 1), min(config.maxPokemonLevel, max(maximumLevel + variation, config.minimumLevelRangeMax)))
|
||||
IntRange(max(maximumLevel - variation, 1), min(config.maxPokemonLevel, max(maximumLevel + variation, config.minimumLevelRangeMax)))
|
||||
} else {
|
||||
noPokemonRange
|
||||
}
|
||||
@@ -63,7 +63,8 @@ open class PlayerLevelRangeInfluence(
|
||||
if (spawnLevelRange.isEmpty()){
|
||||
spawnLevelRange = if (derivedLevelRange.first > playerLevelRange.last) {
|
||||
derivedLevelRange.first..(derivedLevelRange.first + pokemonRangeWidth / 4F).toInt()
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
(derivedLevelRange.first + 3 * pokemonRangeWidth / 4F).toInt()..derivedLevelRange.last
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ abstract class AreaSpawner(
|
||||
val numberNearby = constrainedArea.world.getEntitiesByClass(
|
||||
PokemonEntity::class.java,
|
||||
areaBox
|
||||
) { true }.size
|
||||
) { pokemonEntity -> pokemonEntity.countsTowardsSpawnCap.get() }.size
|
||||
|
||||
val chunksCovered = CHUNK_REACH * CHUNK_REACH
|
||||
if (numberNearby.toFloat() / chunksCovered >= Cobblemon.config.pokemonPerChunk) {
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@ 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.detail.SpawnPool
|
||||
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
|
||||
import com.cobblemon.mod.common.api.spawning.selection.FlatSelector
|
||||
import com.cobblemon.mod.common.api.spawning.selection.FlatContextWeightedSelector
|
||||
import com.cobblemon.mod.common.api.spawning.selection.SpawningSelector
|
||||
import net.minecraft.entity.Entity
|
||||
|
||||
@@ -32,7 +32,7 @@ abstract class TickingSpawner(
|
||||
var spawns: SpawnPool,
|
||||
val manager: SpawnerManager
|
||||
) : Spawner {
|
||||
private var selector: SpawningSelector = FlatSelector()
|
||||
private var selector: SpawningSelector = FlatContextWeightedSelector()
|
||||
override val influences = mutableListOf<SpawningInfluence>()
|
||||
|
||||
override fun canSpawn() = active
|
||||
|
||||
+7
-1
@@ -25,6 +25,7 @@ import com.mongodb.client.model.ReplaceOptions
|
||||
import net.minecraft.util.WorldSavePath
|
||||
import org.bson.Document
|
||||
import java.util.UUID
|
||||
import java.util.Date
|
||||
|
||||
/**
|
||||
* A [FileStoreAdapter] for MongoDB. This allows a [PokemonStore] to be serialized to a MongoDB database.
|
||||
@@ -45,6 +46,7 @@ open class MongoDBStoreAdapter(
|
||||
override fun save(storeClass: Class<out PokemonStore<*>>, uuid: UUID, serialized: JsonObject) {
|
||||
val document = Document.parse(this.gson.toJson(serialized))
|
||||
document["uuid"] = uuid.toString()
|
||||
document["lastUpdated"] = Date()
|
||||
val collection = getCollection(storeClass)
|
||||
val filter = Document("uuid", uuid.toString())
|
||||
collection.replaceOne(filter, document, ReplaceOptions().upsert(true))
|
||||
@@ -67,7 +69,11 @@ open class MongoDBStoreAdapter(
|
||||
|
||||
if (document != null) {
|
||||
val json = this.gson.fromJson(document.toJson(), JsonObject::class.java)
|
||||
val store = storeClass.getConstructor(UUID::class.java).newInstance(uuid)
|
||||
val store = try {
|
||||
storeClass.getConstructor(UUID::class.java, UUID::class.java).newInstance(uuid, uuid)
|
||||
} catch (exception: NoSuchMethodException) {
|
||||
storeClass.getConstructor(UUID::class.java).newInstance(uuid)
|
||||
}
|
||||
store.loadFromJSON(json)
|
||||
return store
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ package com.cobblemon.mod.common.api.storage.player
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.net.messages.client.starter.SetClientPlayerDataPacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import java.util.UUID
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Identifier
|
||||
@@ -23,6 +23,7 @@ data class PlayerData(
|
||||
var starterSelected: Boolean,
|
||||
var starterUUID: UUID?,
|
||||
var keyItems: MutableSet<Identifier>,
|
||||
var battleTheme: Identifier?,
|
||||
val extraData: MutableMap<String, PlayerDataExtension>,
|
||||
) {
|
||||
var advancementData: PlayerAdvancementData = PlayerAdvancementData()
|
||||
@@ -40,6 +41,7 @@ data class PlayerData(
|
||||
starterSelected = false,
|
||||
starterUUID = null,
|
||||
keyItems = mutableSetOf(),
|
||||
battleTheme = CobblemonSounds.PVP_BATTLE.id,
|
||||
extraData = mutableMapOf()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ import net.minecraft.registry.tag.TagKey
|
||||
@Suppress("HasPlatformType", "unused")
|
||||
object CobblemonBlockTags {
|
||||
|
||||
@JvmField val ALL_HANGING_SIGNS = createTag("all_hanging_signs")
|
||||
@JvmField val ALL_SIGNS = createTag("all_signs")
|
||||
@JvmField val APRICORN_LEAVES = createTag("apricorn_leaves")
|
||||
@JvmField val APRICORN_LOGS = createTag("apricorn_logs")
|
||||
@JvmField val APRICORN_SAPLINGS = createTag("apricorn_saplings")
|
||||
@@ -29,6 +31,7 @@ object CobblemonBlockTags {
|
||||
@JvmField val BERRY_WILD_SOIL = createTag("berry_wild_soil")
|
||||
@JvmField val BERRY_SOIL = createTag("berry_soil")
|
||||
@JvmField val BERRY_REPLACEABLE = createTag("berry_replaceable")
|
||||
@JvmField val CEILING_HANGING_SIGNS = createTag("ceiling_hanging_signs")
|
||||
@JvmField val CROPS = createTag("crops")
|
||||
@JvmField val DRIPSTONE_GROWABLE = createTag("dripstone_growable")
|
||||
@JvmField val DRIPSTONE_REPLACEABLES = createTag("dripstone_replaceables")
|
||||
@@ -36,10 +39,15 @@ object CobblemonBlockTags {
|
||||
@JvmField val MEDICINAL_LEEK_PLANTABLE = createTag("medicinal_leek_plantable")
|
||||
@JvmField val MINTS = createTag("mints")
|
||||
@JvmField val ROOTS_SPREADABLE = createTag("roots_spreadable")
|
||||
@JvmField val SIGNS = createTag("signs")
|
||||
@JvmField val SMALL_FLOWERS = createTag("small_flowers")
|
||||
@JvmField val SEES_SKY = createTag("sees_sky")
|
||||
@JvmField val SNOW_BLOCK = createTag("snow_block")
|
||||
@JvmField val ROOTS = createTag("roots")
|
||||
@JvmField val STANDING_SIGNS = createTag("standing_signs")
|
||||
@JvmField val WALL_HANGING_SIGNS = createTag("wall_hanging_signs")
|
||||
@JvmField val WALL_SIGNS = createTag("wall_signs")
|
||||
|
||||
private fun createTag(name: String) = TagKey.of(RegistryKeys.BLOCK, cobblemonResource(name))
|
||||
|
||||
}
|
||||
@@ -9,15 +9,17 @@
|
||||
package com.cobblemon.mod.common.api.tags
|
||||
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.registry.Registries
|
||||
import net.minecraft.registry.RegistryKeys
|
||||
import net.minecraft.registry.tag.TagKey
|
||||
|
||||
/**
|
||||
* A collection of the Cobblemon [TagKey]s related to the [Registry.ENTITY_TYPE].
|
||||
* A collection of the Cobblemon [TagKey]s related to the [Registries.ENTITY_TYPE].
|
||||
*
|
||||
* @author Licious
|
||||
* @since March 6th, 2023
|
||||
*/
|
||||
@Suppress("HasPlatformType", "unused")
|
||||
object CobblemonEntityTypeTags {
|
||||
|
||||
|
||||
@@ -27,6 +29,9 @@ object CobblemonEntityTypeTags {
|
||||
@JvmField
|
||||
val CANNOT_HAVE_NAME_TAG = create("cannot_have_name_tag")
|
||||
|
||||
@JvmField
|
||||
val BOATS = create("boats")
|
||||
|
||||
private fun create(path: String) = TagKey.of(RegistryKeys.ENTITY_TYPE, cobblemonResource(path))
|
||||
|
||||
}
|
||||
@@ -9,16 +9,17 @@
|
||||
package com.cobblemon.mod.common.api.tags
|
||||
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.registry.Registry
|
||||
import net.minecraft.registry.Registries
|
||||
import net.minecraft.registry.RegistryKeys
|
||||
import net.minecraft.registry.tag.TagKey
|
||||
|
||||
/**
|
||||
* A collection of the Cobblemon [TagKey]s related to the [Registry.ITEM].
|
||||
* A collection of the Cobblemon [TagKey]s related to the [Registries.ITEM].
|
||||
*
|
||||
* @author Licious
|
||||
* @since January 8th, 2023
|
||||
*/
|
||||
@Suppress("unused", "HasPlatformType")
|
||||
object CobblemonItemTags {
|
||||
|
||||
@JvmField
|
||||
@@ -27,11 +28,47 @@ object CobblemonItemTags {
|
||||
val APRICORN_SEEDS = create("apricorn_seeds")
|
||||
@JvmField
|
||||
val APRICORNS = create("apricorns")
|
||||
/**
|
||||
* This tag is only used for a Torterra aspect based easter egg evolution at the moment.
|
||||
* It simply includes the 'minecraft:azalea' and 'minecraft:flowering_azalea' items by default.
|
||||
*/
|
||||
@JvmField
|
||||
val AZALEA_TREE = create("azalea_tree")
|
||||
@JvmField
|
||||
val BERRIES = create("berries")
|
||||
@JvmField
|
||||
val BOATS = create("boats")
|
||||
@JvmField
|
||||
val COBBLEMON_SEEDS = create("cobblemon_seeds")
|
||||
@JvmField
|
||||
val EVOLUTION_ITEMS = create("evolution_items")
|
||||
@JvmField
|
||||
val EVOLUTION_STONES = create("evolution_stones")
|
||||
@JvmField
|
||||
val EXPERIENCE_CANDIES = create("experience_candies")
|
||||
@JvmField
|
||||
val HANGING_SIGNS = create("hanging_signs")
|
||||
@JvmField
|
||||
val HERBS = create("herbs")
|
||||
@JvmField
|
||||
val MINT_LEAF = create("mint_leaf")
|
||||
@JvmField
|
||||
val MINTS = create("mints")
|
||||
@JvmField
|
||||
val MUTATED_BERRIES = create("mutated_berries")
|
||||
@JvmField
|
||||
val PLANTS = create("plants")
|
||||
@JvmField
|
||||
val POKEBALLS = create("poke_balls")
|
||||
@JvmField
|
||||
val PROTEIN_INGREDIENTS = create("protein_ingredients")
|
||||
@JvmField
|
||||
val SEEDS = create("seeds")
|
||||
@JvmField
|
||||
val SIGNS = create("signs")
|
||||
@JvmField
|
||||
val ZINC_INGREDIENTS = create("zinc_ingredients")
|
||||
@JvmField
|
||||
val ANY_HELD_ITEM = create("held/is_held_item")
|
||||
@JvmField
|
||||
val EXPERIENCE_SHARE = create("held/experience_share")
|
||||
@@ -54,19 +91,11 @@ object CobblemonItemTags {
|
||||
@JvmField
|
||||
val POWER_WEIGHT = create("held/power_weight")
|
||||
@JvmField
|
||||
val EVOLUTION_STONES = create("evolution_stones")
|
||||
val CONSUMED_IN_NPC_BATTLE = create("held/consumed_in_npc_battle")
|
||||
@JvmField
|
||||
val EVOLUTION_ITEMS = create("evolution_items")
|
||||
val CONSUMED_IN_PVP_BATTLE = create("held/consumed_in_pvp_battle")
|
||||
@JvmField
|
||||
val MINTS = create("mints")
|
||||
@JvmField
|
||||
val MINT_LEAVES = create("mint_leaves")
|
||||
|
||||
/**
|
||||
* This tag is only used for a Torterra aspect based easter egg evolution at the moment.
|
||||
* It simply includes the 'minecraft:azalea' and 'minecraft:flowering_azalea' items by default.
|
||||
*/
|
||||
val AZALEA_TREE = create("azalea_tree")
|
||||
val CONSUMED_IN_WILD_BATTLE = create("held/consumed_in_wild_battle")
|
||||
|
||||
private fun create(path: String) = TagKey.of(RegistryKeys.ITEM, cobblemonResource(path))
|
||||
|
||||
|
||||
@@ -9,16 +9,16 @@
|
||||
package com.cobblemon.mod.common.battles
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleStartedPreEvent
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore
|
||||
import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
|
||||
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.getBattleTheme
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import java.util.Optional
|
||||
@@ -63,18 +63,14 @@ object BattleBuilder {
|
||||
}
|
||||
|
||||
return if (errors.isEmpty) {
|
||||
CobblemonEvents.BATTLE_STARTED_PRE.postThen(
|
||||
BattleStartedPreEvent(listOf(player1Actor, player2Actor), battleFormat, true, false, false))
|
||||
{
|
||||
return SuccessfulBattleStart(
|
||||
BattleRegistry.startBattle(
|
||||
battleFormat = battleFormat,
|
||||
side1 = BattleSide(player1Actor),
|
||||
side2 = BattleSide(player2Actor)
|
||||
)
|
||||
)
|
||||
BattleRegistry.startBattle(
|
||||
battleFormat = battleFormat,
|
||||
side1 = BattleSide(player1Actor),
|
||||
side2 = BattleSide(player2Actor)
|
||||
).ifSuccessful {
|
||||
player1Actor.battleTheme = player2.getBattleTheme()
|
||||
player2Actor.battleTheme = player1.getBattleTheme()
|
||||
}
|
||||
errors
|
||||
} else {
|
||||
errors
|
||||
}
|
||||
@@ -125,20 +121,16 @@ object BattleBuilder {
|
||||
}
|
||||
|
||||
return if (errors.isEmpty) {
|
||||
CobblemonEvents.BATTLE_STARTED_PRE.postThen(
|
||||
BattleStartedPreEvent(listOf(playerActor, wildActor), battleFormat, false, false, true))
|
||||
{
|
||||
val battle = BattleRegistry.startBattle(
|
||||
battleFormat = battleFormat,
|
||||
side1 = BattleSide(playerActor),
|
||||
side2 = BattleSide(wildActor)
|
||||
)
|
||||
BattleRegistry.startBattle(
|
||||
battleFormat = battleFormat,
|
||||
side1 = BattleSide(playerActor),
|
||||
side2 = BattleSide(wildActor)
|
||||
).ifSuccessful {
|
||||
if (!cloneParties) {
|
||||
pokemonEntity.battleId.set(Optional.of(battle.battleId))
|
||||
pokemonEntity.battleId.set(Optional.of(it.battleId))
|
||||
}
|
||||
return SuccessfulBattleStart(battle)
|
||||
playerActor.battleTheme = pokemonEntity.getBattleTheme()
|
||||
}
|
||||
errors
|
||||
} else {
|
||||
errors
|
||||
}
|
||||
@@ -178,12 +170,21 @@ interface BattleStartError {
|
||||
requiredCount: Int,
|
||||
hadCount: Int
|
||||
) = InsufficientPokemonError(player, requiredCount, hadCount)
|
||||
|
||||
fun canceledByEvent(reason: MutableText?) = CanceledError(reason)
|
||||
}
|
||||
}
|
||||
|
||||
enum class CommonBattleStartError : BattleStartError {
|
||||
|
||||
}
|
||||
|
||||
class CanceledError(
|
||||
val reason: MutableText?
|
||||
): BattleStartError {
|
||||
override fun getMessageFor(entity: Entity) = reason ?: battleLang("error.canceled")
|
||||
}
|
||||
|
||||
class InsufficientPokemonError(
|
||||
val player: ServerPlayerEntity,
|
||||
val requiredCount: Int,
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleStartedPostEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleStartedPreEvent
|
||||
import com.cobblemon.mod.common.api.pokemon.helditem.HeldItemProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
@@ -145,17 +146,11 @@ object BattleRegistry {
|
||||
return team.joinToString("]")
|
||||
}
|
||||
|
||||
fun startBattle(
|
||||
battleFormat: BattleFormat,
|
||||
side1: BattleSide,
|
||||
side2: BattleSide
|
||||
): PokemonBattle {
|
||||
val battle = PokemonBattle(battleFormat, side1, side2)
|
||||
battleMap[battle.battleId] = battle
|
||||
private fun startShowdown(battle: PokemonBattle) {
|
||||
|
||||
// Build request message
|
||||
val messages = mutableListOf<String>()
|
||||
messages.add(">start { \"format\": ${battleFormat.toFormatJSON()} }")
|
||||
messages.add(">start { \"format\": ${battle.format.toFormatJSON()} }")
|
||||
|
||||
/*
|
||||
* Showdown IDs are like p1, p2, p3, etc. Showdown uses these keys to identify who is doing what to whom.
|
||||
@@ -174,19 +169,17 @@ object BattleRegistry {
|
||||
var actorIndex = 1
|
||||
for (actor in battle.side1.actors) {
|
||||
actor.showdownId = "p$actorIndex"
|
||||
actor.battle = battle
|
||||
actorIndex += 2
|
||||
}
|
||||
|
||||
actorIndex = 2
|
||||
for (actor in battle.side2.actors) {
|
||||
actor.showdownId = "p$actorIndex"
|
||||
actor.battle = battle
|
||||
actorIndex += 2
|
||||
}
|
||||
|
||||
for (actor in battle.actors) {
|
||||
repeat(battleFormat.battleType.slotsPerActor) {
|
||||
repeat(battle.format.battleType.slotsPerActor) {
|
||||
actor.activePokemon.add(ActiveBattlePokemon(actor))
|
||||
}
|
||||
val entities = actor.pokemonList.mapNotNull { it.entity }
|
||||
@@ -205,8 +198,25 @@ object BattleRegistry {
|
||||
|
||||
// Compiles the request and sends it off
|
||||
ShowdownService.service.startBattle(battle, messages.toTypedArray())
|
||||
CobblemonEvents.BATTLE_STARTED_POST.post(BattleStartedPostEvent(battle))
|
||||
return battle
|
||||
}
|
||||
|
||||
fun startBattle(
|
||||
battleFormat: BattleFormat,
|
||||
side1: BattleSide,
|
||||
side2: BattleSide,
|
||||
silent: Boolean = false
|
||||
): BattleStartResult {
|
||||
val battle = PokemonBattle(battleFormat, side1, side2)
|
||||
if (silent) return SuccessfulBattleStart(battle)
|
||||
|
||||
val preBattleEvent = BattleStartedPreEvent(battle)
|
||||
CobblemonEvents.BATTLE_STARTED_PRE.postThen(preBattleEvent) {
|
||||
battleMap[battle.battleId] = battle
|
||||
startShowdown(battle)
|
||||
CobblemonEvents.BATTLE_STARTED_POST.post(BattleStartedPostEvent(battle))
|
||||
return SuccessfulBattleStart(battle)
|
||||
}
|
||||
return ErroredBattleStart(mutableSetOf(BattleStartError.canceledByEvent(preBattleEvent.reason)))
|
||||
}
|
||||
|
||||
fun closeBattle(battle: PokemonBattle) {
|
||||
@@ -221,6 +231,10 @@ object BattleRegistry {
|
||||
return battleMap.values.find { it.getActor(serverPlayerEntity) != null }
|
||||
}
|
||||
|
||||
fun getBattleByParticipatingPlayerId(playerId: UUID): PokemonBattle? {
|
||||
return battleMap.values.find { playerId in it.playerUUIDs }
|
||||
}
|
||||
|
||||
fun tick() {
|
||||
battleMap.forEachValue(Long.MAX_VALUE) { it.tick() }
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ data class SwitchActionResponse(var newPokemonId: UUID) : ShowdownActionResponse
|
||||
val pokemon = activeBattlePokemon.actor.pokemonList.find { it.uuid == newPokemonId }
|
||||
return when {
|
||||
pokemon == null -> false // No such Pokémon
|
||||
pokemon.health <= 0 -> false // Pokémon is dead
|
||||
(!activeBattlePokemon.actor.request?.side?.pokemon?.get(0)?.reviving!! && pokemon.health <= 0) -> false // Checks if the active Pokémon is reviving, if so ignore this check. If not, return false if dead
|
||||
showdownMoveSet != null && showdownMoveSet.trapped -> false // You're not allowed to switch
|
||||
activeBattlePokemon.actor.getSide().activePokemon.any { it.battlePokemon?.uuid == newPokemonId } -> false // Pokémon is already sent out
|
||||
else -> true
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.cobblemon.mod.common.battles.interpreter.ContextManager
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.*
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.DamageTakenEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.LastBattleCriticalHitsEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.RecoilEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.UseMoveEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.status.PersistentStatus
|
||||
@@ -47,6 +48,7 @@ import net.minecraft.server.world.ServerWorld
|
||||
import net.minecraft.text.MutableText
|
||||
import net.minecraft.text.Text
|
||||
|
||||
@Suppress("KotlinPlaceholderCountMatchesArgumentCount", "UNUSED_PARAMETER")
|
||||
object ShowdownInterpreter {
|
||||
private val updateInstructions = mutableMapOf<String, (PokemonBattle, BattleMessage, MutableList<String>) -> Unit>()
|
||||
private val sideUpdateInstructions = mutableMapOf<String, (PokemonBattle, BattleActor, BattleMessage) -> Unit>()
|
||||
@@ -81,20 +83,23 @@ object ShowdownInterpreter {
|
||||
updateInstructions["|-mustrecharge|"] = this::handleRechargeInstructions
|
||||
updateInstructions["|-fail|"] = this::handleFailInstruction
|
||||
updateInstructions["|-start|"] = this::handleStartInstructions
|
||||
updateInstructions["|-block|"] = this::handleBlockInstructions
|
||||
updateInstructions["|-activate|"] = this::handleActivateInstructions
|
||||
updateInstructions["|-curestatus|"] = this::handleCureStatusInstruction
|
||||
updateInstructions["|-fieldstart|"] = this::handleFieldStartInstructions
|
||||
updateInstructions["|-fieldend|"] = this::handleFieldEndInstructions
|
||||
updateInstructions["|-ability|"] = this::handleAbilityInstructions
|
||||
//To-Do updateInstructions["|-endability|"] = this::handleEndAbilityInstruction
|
||||
updateInstructions["|-endability|"] = this::handleEndAbilityInstruction
|
||||
updateInstructions["|-nothing"] = { battle, _, _ ->
|
||||
battle.dispatchGo { battle.broadcastChatMessage(battleLang("nothing")) }
|
||||
}
|
||||
updateInstructions["|-clearallboost"] = this::handleClearAllBoostInstructions
|
||||
updateInstructions["|-singleturn|"] = this::handleSingleTurnInstruction
|
||||
updateInstructions["|-singlemove|"] = this::handleSingleMoveInstruction
|
||||
updateInstructions["|-transform|"] = this::handleTransformInstruction
|
||||
updateInstructions["|-prepare|"] = this::handlePrepareInstruction
|
||||
updateInstructions["|-swapboost"] = this::handleSwapBoostInstruction
|
||||
updateInstructions["|-copyboost|"] = this::handleCopyBoostInstruction
|
||||
updateInstructions["|-swapsideconditions|"] = this::handleSilently
|
||||
updateInstructions["|-unboost|"] = { battle, line, remainingLines -> boostInstruction(battle, line, remainingLines, false) }
|
||||
updateInstructions["|-boost|"] = { battle, line, remainingLines -> boostInstruction(battle, line, remainingLines, true) }
|
||||
@@ -102,6 +107,7 @@ object ShowdownInterpreter {
|
||||
updateInstructions["|t:|"] = {_, _, _ -> }
|
||||
updateInstructions["|pp_update|"] = this::handlePpUpdateInstruction
|
||||
updateInstructions["|-immune"] = this::handleImmuneInstruction
|
||||
updateInstructions["|-invertboost|"] = this::handleInvertBoostInstruction
|
||||
updateInstructions["|-status|"] = this::handleStatusInstruction
|
||||
updateInstructions["|-end|"] = this::handleEndInstruction
|
||||
updateInstructions["|-miss|"] = this::handleMissInstruction
|
||||
@@ -473,12 +479,10 @@ object ShowdownInterpreter {
|
||||
private fun handleTurnInstruction(battle: PokemonBattle, message: BattleMessage, remainingLines: MutableList<String>) {
|
||||
if (!battle.started) {
|
||||
battle.started = true
|
||||
battle.actors.forEach { actor ->
|
||||
if (actor.uuid.getPlayer() != null) {
|
||||
val initializePacket = BattleInitializePacket(battle, actor.getSide())
|
||||
actor.sendUpdate(initializePacket)
|
||||
actor.sendUpdate(BattleMusicPacket(battle))
|
||||
}
|
||||
battle.actors.filterIsInstance<PlayerBattleActor>().forEach { actor ->
|
||||
val initializePacket = BattleInitializePacket(battle, actor.getSide())
|
||||
actor.sendUpdate(initializePacket)
|
||||
actor.sendUpdate(BattleMusicPacket(actor.battleTheme))
|
||||
}
|
||||
battle.actors.forEach { actor ->
|
||||
actor.sendUpdate(BattleSetTeamPokemonPacket(actor.pokemonList.map { it.effectedPokemon }))
|
||||
@@ -652,6 +656,34 @@ object ShowdownInterpreter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format:
|
||||
* |-invertboost|POKEMON|MOVE
|
||||
*
|
||||
* The POKEMON had its stat changes inverted.
|
||||
*/
|
||||
private fun handleInvertBoostInstruction(battle: PokemonBattle, message: BattleMessage, remainingLines: MutableList<String>) {
|
||||
battle.dispatchWaiting {
|
||||
val pokemon = message.getBattlePokemon(0, battle) ?: return@dispatchWaiting
|
||||
val name = pokemon.getName()
|
||||
battle.broadcastChatMessage(battleLang("invertboost", name))
|
||||
|
||||
// update and invert BOOST and UNBOOST contexts
|
||||
val context = getContextFromAction(message, BattleContext.Type.BOOST, battle)
|
||||
val newUnboosts = pokemon.contextManager.get(BattleContext.Type.BOOST)?.map {
|
||||
BasicContext(it.id, context.turn, BattleContext.Type.UNBOOST, context.origin)
|
||||
}?.toTypedArray()
|
||||
val newBoosts = pokemon.contextManager.get(BattleContext.Type.UNBOOST)?.map {
|
||||
BasicContext(it.id, context.turn, BattleContext.Type.BOOST, context.origin)
|
||||
}?.toTypedArray()
|
||||
|
||||
pokemon.contextManager.clear(BattleContext.Type.BOOST, BattleContext.Type.UNBOOST)
|
||||
newBoosts?.let { pokemon.contextManager.add(*it) }
|
||||
newUnboosts?.let { pokemon.contextManager.add(*it) }
|
||||
battle.minorBattleActions[pokemon.uuid] = message
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format:
|
||||
* |move|POKEMON|MOVE|TARGET
|
||||
@@ -779,7 +811,10 @@ object ShowdownInterpreter {
|
||||
battle.broadcastChatMessage(battleLang("crit").yellow())
|
||||
this.lastCauser[battle.battleId]?.let { message ->
|
||||
val battlePokemon = message.getBattlePokemon(0, battle) ?: return@let
|
||||
battlePokemon.criticalHits++
|
||||
if (LastBattleCriticalHitsEvolutionProgress.supports(battlePokemon.effectedPokemon)) {
|
||||
val progress = battlePokemon.effectedPokemon.evolutionProxy.current().progressFirstOrCreate({ it is LastBattleCriticalHitsEvolutionProgress }) { LastBattleCriticalHitsEvolutionProgress() }
|
||||
progress.updateProgress(LastBattleCriticalHitsEvolutionProgress.Progress(progress.currentProgress().amount + 1))
|
||||
}
|
||||
}
|
||||
battle.minorBattleActions[pokemon.uuid] = message
|
||||
}
|
||||
@@ -822,10 +857,32 @@ object ShowdownInterpreter {
|
||||
*
|
||||
* The specified ACTION has failed against the POKEMON targetted.
|
||||
*/
|
||||
private fun handleFailInstruction(battle: PokemonBattle, message: BattleMessage, remainingLines: MutableList<String>){
|
||||
private fun handleFailInstruction(battle: PokemonBattle, message: BattleMessage, remainingLines: MutableList<String>) {
|
||||
battle.dispatchWaiting(1.5F){
|
||||
val pokemon = message.getBattlePokemon(0, battle) ?: return@dispatchWaiting
|
||||
battle.broadcastChatMessage(battleLang("fail").red())
|
||||
val pokemonName = pokemon.getName()
|
||||
val effectID = message.effectAt(1)?.id
|
||||
val cause = message.effect("from")
|
||||
val of = message.getSourceBattlePokemon(battle)
|
||||
|
||||
val lang = when (effectID) {
|
||||
null, "burnup", "doubleshock" -> battleLang("fail") // Moves that use default fail lang. (Null included for moves that fail with no effect, for example: Baton Pass.)
|
||||
"shedtail" -> battleLang("fail.substitute", pokemonName)
|
||||
"hyperspacefury", "aurawheel" -> battleLang("fail.darkvoid", pokemonName) // Moves that can only be used by one species and fail when any others try
|
||||
"corrosivegas" -> battleLang("fail.healblock", pokemonName)
|
||||
"dynamax" -> battleLang("fail.grassknot", pokemonName) // Covers weight moves that fail against dynamaxed Pokémon
|
||||
"unboost" -> {
|
||||
val statKey = message.argumentAt(2)
|
||||
val stat = statKey?.let { getStat(it).displayName }
|
||||
if (stat != null) {
|
||||
battleLang("fail.$effectID.single", pokemonName, stat)
|
||||
} else {
|
||||
battleLang("fail.$effectID", pokemonName)
|
||||
}
|
||||
}
|
||||
else -> battleLang("fail.$effectID", pokemonName)
|
||||
}
|
||||
battle.broadcastChatMessage(lang.red())
|
||||
battle.minorBattleActions[pokemon.uuid] = message
|
||||
}
|
||||
}
|
||||
@@ -889,6 +946,11 @@ object ShowdownInterpreter {
|
||||
val pokemon = message.getBattlePokemon(0, battle) ?: return@dispatch GO
|
||||
val effectID = message.effectAt(1)?.id ?: return@dispatch GO
|
||||
|
||||
val optionalEffect = message.effect()
|
||||
val optionalPokemon = message.getSourceBattlePokemon(battle)
|
||||
val optionalPokemonName = optionalPokemon?.getName()
|
||||
val extraEffect = message.effectAt(2)?.typelessData ?: Text.literal("UNKOWN")
|
||||
|
||||
// skip adding contexts for every time the perish counter decrements
|
||||
if (!effectID.contains("perish")) {
|
||||
// don't need to add unique: showdown won't send -start instruction if volatile status is already present
|
||||
@@ -897,13 +959,17 @@ object ShowdownInterpreter {
|
||||
battle.minorBattleActions[pokemon.uuid] = message
|
||||
|
||||
if (!message.hasOptionalArgument("silent")) {
|
||||
val lang = when (effectID) {
|
||||
"confusion", "perish3" -> return@dispatch GO // Skip
|
||||
"perish2", "perish1", "perish0" -> battleLang("start.perish", pokemon.getName(), effectID.last().digitToInt())
|
||||
"dynamax" -> battleLang("start.${message.effectAt(2)?.id ?: effectID}", pokemon.getName()).yellow()
|
||||
"curse" -> battleLang("start.curse", message.getSourceBattlePokemon(battle)!!.getName(), pokemon.getName())
|
||||
else -> battleLang("start.$effectID", pokemon.getName())
|
||||
}
|
||||
val lang = if (optionalEffect?.id == "reflecttype" && optionalPokemonName != null)
|
||||
battleLang("start.reflecttype", pokemon.getName(), optionalPokemonName)
|
||||
else
|
||||
when (effectID) {
|
||||
"confusion", "perish3" -> return@dispatch GO // Skip
|
||||
"perish2", "perish1", "perish0",
|
||||
"stockpile1", "stockpile2", "stockpile3" -> battleLang("start.${effectID.dropLast(1)}", pokemon.getName(), effectID.last().digitToInt())
|
||||
"dynamax" -> battleLang("start.${message.effectAt(2)?.id ?: effectID}", pokemon.getName()).yellow()
|
||||
"curse" -> battleLang("start.curse", message.getSourceBattlePokemon(battle)!!.getName(), pokemon.getName())
|
||||
else -> battleLang("start.$effectID", pokemon.getName(), extraEffect)
|
||||
}
|
||||
battle.broadcastChatMessage(lang)
|
||||
}
|
||||
WaitDispatch(1F)
|
||||
@@ -920,7 +986,7 @@ object ShowdownInterpreter {
|
||||
battle.dispatchWaiting(1.5F) {
|
||||
val pokemon = message.getBattlePokemon(0, battle) ?: return@dispatchWaiting
|
||||
val pokemonName = pokemon.getName()
|
||||
val sourceName = message.getSourceBattlePokemon(battle)?.getName() ?: return@dispatchWaiting
|
||||
val sourceName = message.getSourceBattlePokemon(battle)?.getName() ?: Text.literal("UNKOWN")
|
||||
val effectID = message.effectAt(1)?.id ?: return@dispatchWaiting
|
||||
val lang = battleLang("singleturn.$effectID", pokemonName, sourceName)
|
||||
battle.broadcastChatMessage(lang)
|
||||
@@ -928,6 +994,25 @@ object ShowdownInterpreter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format:
|
||||
* |-transform|POKEMON|POKEMON
|
||||
*
|
||||
* The Pokémon POKEMON used Transform to turn into Target Pokemon POKEMON
|
||||
*/
|
||||
private fun handleTransformInstruction(battle: PokemonBattle, message: BattleMessage, remainingLines: MutableList<String>) {
|
||||
battle.dispatchWaiting(1.5F) {
|
||||
val pokemon = message.getBattlePokemon(0, battle) ?: return@dispatchWaiting
|
||||
val pokemonName = pokemon.getName()
|
||||
val targetPokemon = message.getBattlePokemon(1, battle) ?: return@dispatchWaiting
|
||||
val targetPokemonName = targetPokemon.getName()
|
||||
|
||||
val lang = battleLang("transform", pokemonName, targetPokemonName)
|
||||
battle.broadcastChatMessage(lang)
|
||||
battle.minorBattleActions[pokemon.uuid] = message
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format:
|
||||
* |-singlemove|POKEMON|MOVE
|
||||
@@ -945,6 +1030,43 @@ object ShowdownInterpreter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format:
|
||||
* |-endability|POKEMON
|
||||
*
|
||||
* The Pokémon POKEMON's Ability was surpressed
|
||||
*/
|
||||
private fun handleEndAbilityInstruction(battle: PokemonBattle, message: BattleMessage, remainingLines: MutableList<String>) {
|
||||
battle.dispatchWaiting(1.5F) {
|
||||
val pokemon = message.getBattlePokemon(0, battle) ?: return@dispatchWaiting
|
||||
val pokemonName = pokemon.getName()
|
||||
|
||||
val lang = battleLang("endability", pokemonName)
|
||||
battle.broadcastChatMessage(lang)
|
||||
battle.minorBattleActions[pokemon.uuid] = message
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format:
|
||||
* |-block|POKEMON|EFFECT|MOVE|ATTACKER
|
||||
*
|
||||
* An effect targeted at POKEMON was blocked by EFFECT. This may optionally specify that the effect was a MOVE from ATTACKER.
|
||||
*
|
||||
* (of)SOURCE will note the owner of the EFFECT, in the case that it's not EFFECT (for instance, an ally with Aroma Veil.)
|
||||
*/
|
||||
private fun handleBlockInstructions(battle: PokemonBattle, message: BattleMessage, remainingLines: MutableList<String>) {
|
||||
battle.dispatchWaiting(1.5F) {
|
||||
val pokemon = message.getBattlePokemon(0, battle) ?: return@dispatchWaiting
|
||||
val pokemonName = pokemon.getName()
|
||||
val effectID = message.effectAt(1)?.id ?: return@dispatchWaiting
|
||||
val lang = battleLang("block.$effectID", pokemonName)
|
||||
|
||||
battle.broadcastChatMessage(lang)
|
||||
battle.minorBattleActions[pokemon.uuid] = message
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format:
|
||||
* |-activate|POKEMON|EFFECT
|
||||
@@ -956,6 +1078,7 @@ object ShowdownInterpreter {
|
||||
val pokemonName = pokemon.getName()
|
||||
val sourceName = message.getSourceBattlePokemon(battle)?.getName() ?: Text.literal("UNKOWN")
|
||||
val effect = message.effectAt(1) ?: return
|
||||
val extraEffect = message.effectAt(2)?.typelessData ?: Text.literal("UNKOWN")
|
||||
broadcastOptionalAbility(battle, effect, pokemonName)
|
||||
|
||||
battle.dispatch{
|
||||
@@ -966,7 +1089,7 @@ object ShowdownInterpreter {
|
||||
// Includes a 3rd argument being the magnitude level as a number
|
||||
"magnitude" -> battleLang("activate.magnitude", message.argumentAt(2)?.toIntOrNull() ?: 1)
|
||||
// Includes spited move and the PP it was reduced by
|
||||
"spite" -> battleLang("activate.spite", pokemonName, message.argumentAt(2)!!, message.argumentAt(3)!!)
|
||||
"spite", "eeriespell" -> battleLang("activate.spite", pokemonName, extraEffect, message.argumentAt(3)!!)
|
||||
// Don't need additional lang, announced elsewhere
|
||||
"toxicdebris", "shedskin" -> return@dispatch GO
|
||||
// Add activation to each Pokemon's history
|
||||
@@ -974,14 +1097,10 @@ object ShowdownInterpreter {
|
||||
battle.activePokemon.mapNotNull { it.battlePokemon?.uuid }.forEach { battle.minorBattleActions[it] = message }
|
||||
battleLang("activate.destinybond", pokemonName)
|
||||
}
|
||||
// Includes revealed move
|
||||
"forewarn" -> {
|
||||
val moveName = message.moveAt(2)?.displayName ?: run { println(message.argumentAt(2)); "(Unrecognized: ${message.argumentAt(2)})".text() }
|
||||
battleLang("activate.forewarn", sourceName, moveName)
|
||||
}
|
||||
"focussash", "focusband" -> battleLang("activate.focusband", pokemonName, message.effectAt(1)!!.typelessData)
|
||||
"focussash", "focusband" -> battleLang("activate.focusband", pokemonName, effect.typelessData)
|
||||
"maxguard", "protect" -> battleLang("activate.protect", pokemonName)
|
||||
else -> battleLang("activate.${effect.id}", pokemonName, sourceName)
|
||||
"shadowforce", "hyperspacefury", "hyperspacehole" -> battleLang("activate.phantomforce", pokemonName)
|
||||
else -> battleLang("activate.${effect.id}", pokemonName, sourceName, extraEffect)
|
||||
}
|
||||
battle.broadcastChatMessage(lang)
|
||||
WaitDispatch(1F)
|
||||
@@ -1047,7 +1166,7 @@ object ShowdownInterpreter {
|
||||
|
||||
/**
|
||||
* Format:
|
||||
* |-ability|POKEMON|ABILITY|[from]EFFECT
|
||||
* |-ability|POKEMON|ABILITY|(from)EFFECT
|
||||
*
|
||||
* The ABILITY of the POKEMON has been changed due to a move/ability EFFECT.
|
||||
*
|
||||
@@ -1060,15 +1179,28 @@ object ShowdownInterpreter {
|
||||
val pokemon = message.getBattlePokemon(0, battle) ?: return
|
||||
val pokemonName = pokemon.getName()
|
||||
val effect = message.effectAt(1) ?: return
|
||||
broadcastAbility(battle, effect, pokemonName)
|
||||
val optionalEffect = message.effect()
|
||||
val optionalPokemon = message.getSourceBattlePokemon(battle)
|
||||
val optionalPokemonName = optionalPokemon?.getName()
|
||||
|
||||
// If there is an optional effect causing the activation, broadcast that instead of the standard effect
|
||||
if (optionalEffect != null) {
|
||||
broadcastAbility(battle, optionalEffect, pokemonName)
|
||||
} else {
|
||||
broadcastAbility(battle, effect, pokemonName)
|
||||
}
|
||||
|
||||
battle.dispatch {
|
||||
this.lastCauser[battle.battleId] = message
|
||||
|
||||
val lang = when (effect.id) {
|
||||
"sturdy", "unnerve", "anticipation" -> battleLang("ability.${effect.id}", pokemonName) // Unique message
|
||||
"airlock", "cloudnine" -> battleLang("ability.airlock") // Cloud Nine shares the same text as Air Lock
|
||||
else -> null // Effect broadcasted by a succeeding instruction
|
||||
val lang = when (optionalEffect?.id) {
|
||||
"trace" -> optionalPokemonName?.let { battleLang("ability.trace", pokemonName, it, effect.typelessData) }
|
||||
"receiver", "powerofalchemy" -> optionalPokemonName?.let { battleLang("ability.receiver", it, effect.typelessData) } // Receiver and Power of Alchemy share the same text
|
||||
else -> when (effect.id) {
|
||||
"sturdy", "unnerve", "anticipation" -> battleLang("ability.${effect.id}", pokemonName) // Unique message
|
||||
"airlock", "cloudnine" -> battleLang("ability.airlock") // Cloud Nine shares the same text as Air Lock
|
||||
else -> null // Effect broadcasted by a succeeding instruction
|
||||
}
|
||||
}
|
||||
|
||||
battle.minorBattleActions[pokemon.uuid] = message
|
||||
@@ -1115,6 +1247,8 @@ object ShowdownInterpreter {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Format:
|
||||
* |-swapboost|SOURCE|TARGET|STATS
|
||||
@@ -1127,7 +1261,11 @@ object ShowdownInterpreter {
|
||||
val pokemonName = pokemon.getName()
|
||||
val targetPokemon = message.getBattlePokemon(1, battle) ?: return@dispatchWaiting
|
||||
val targetPokemonName = targetPokemon.getName()
|
||||
val lang = battleLang("swapboost.generic", pokemonName, targetPokemonName)
|
||||
val effectID = message.effect()?.id ?: return@dispatchWaiting
|
||||
val lang = when (effectID) {
|
||||
"guardswap", "powerswap", "heartswap" -> battleLang("swapboost.$effectID", pokemonName)
|
||||
else -> battleLang("swapboost.generic", pokemonName, targetPokemonName)
|
||||
}
|
||||
battle.broadcastChatMessage(lang)
|
||||
|
||||
pokemon.contextManager.swap(targetPokemon.contextManager, BattleContext.Type.BOOST)
|
||||
@@ -1136,6 +1274,26 @@ object ShowdownInterpreter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format:
|
||||
* |-copyboost|SOURCE|TARGET|[from]EFFECT
|
||||
*
|
||||
* Copies any stat changes from the TARGET Pokémon to the SOURCE Pokémon due to EFFECT.
|
||||
*/
|
||||
private fun handleCopyBoostInstruction(battle: PokemonBattle, message: BattleMessage, remainingLines: MutableList<String>) {
|
||||
battle.dispatchWaiting {
|
||||
val pokemon = message.getBattlePokemon(0, battle) ?: return@dispatchWaiting
|
||||
val pokemonName = pokemon.getName()
|
||||
val targetPokemon = message.getBattlePokemon(1, battle) ?: return@dispatchWaiting
|
||||
val targetPokemonName = targetPokemon.getName()
|
||||
val lang = battleLang("copyboost.generic", pokemonName, targetPokemonName)
|
||||
battle.broadcastChatMessage(lang)
|
||||
|
||||
pokemon.contextManager.copy(targetPokemon.contextManager, BattleContext.Type.BOOST, BattleContext.Type.UNBOOST)
|
||||
battle.minorBattleActions[pokemon.uuid] = message
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format:
|
||||
* |-end|POKEMON|EFFECT
|
||||
@@ -1412,6 +1570,8 @@ object ShowdownInterpreter {
|
||||
lang("status.$status.hurt", pokemonName)
|
||||
}
|
||||
"aftermath" -> battleLang("damage.generic", pokemonName)
|
||||
"chloroblast", "steelbeam" -> battleLang("damage.mindblown", pokemonName)
|
||||
"jumpkick" -> battleLang("damage.highjumpkick", pokemonName)
|
||||
else -> battleLang("damage.${effect.id}", pokemonName, sourceName)
|
||||
}
|
||||
battle.broadcastChatMessage(lang.red())
|
||||
@@ -1428,7 +1588,7 @@ object ShowdownInterpreter {
|
||||
val maxHealth = newHealth.split("/")[1].toInt()
|
||||
val difference = maxHealth - remainingHealth
|
||||
newHealthRatio = remainingHealth.toFloat() / maxHealth
|
||||
battle.dispatch {
|
||||
battle.dispatchToFront {
|
||||
battlePokemon.effectedPokemon.currentHealth = remainingHealth
|
||||
if (difference > 0) {
|
||||
battlePokemon.effectedPokemon.let { pokemon ->
|
||||
@@ -1444,6 +1604,7 @@ object ShowdownInterpreter {
|
||||
}
|
||||
privateMessage.pnxAndUuid(0)?.let { (pnx, _) -> battle.sendSidedUpdate(actor, BattleHealthChangePacket(pnx, remainingHealth.toFloat()), BattleHealthChangePacket(pnx, newHealthRatio)) }
|
||||
|
||||
|
||||
battle.minorBattleActions[battlePokemon.uuid] = privateMessage
|
||||
WaitDispatch(1F)
|
||||
}
|
||||
@@ -1502,7 +1663,7 @@ object ShowdownInterpreter {
|
||||
|
||||
/**
|
||||
* Format:
|
||||
* |-item|POKEMON|ITEM|[from]EFFECT
|
||||
* |-item|POKEMON|ITEM|(from)EFFECT
|
||||
*
|
||||
* The ITEM held by the POKEMON has been changed or revealed due to a move or ability EFFECT.
|
||||
*
|
||||
@@ -1525,7 +1686,7 @@ object ShowdownInterpreter {
|
||||
|
||||
/**
|
||||
* Format:
|
||||
* |-enditem|POKEMON|ITEM|[from]EFFECT
|
||||
* |-enditem|POKEMON|ITEM|(from)EFFECT
|
||||
*
|
||||
* The ITEM held by POKEMON has been destroyed by a move or ability, and it now holds no item.
|
||||
*
|
||||
@@ -1536,11 +1697,12 @@ object ShowdownInterpreter {
|
||||
*/
|
||||
fun handleEndItemInstruction(battle: PokemonBattle, message: BattleMessage, remainingLines: MutableList<String>) {
|
||||
battle.dispatchGo {
|
||||
// All logic regarding broadcasting battle messages is handled in CobblemonHeldItemManager
|
||||
val battlePokemon = message.getBattlePokemon(0, battle) ?: return@dispatchGo
|
||||
val item = message.effectAt(1) ?: return@dispatchGo
|
||||
val itemEffect = message.effectAt(1) ?: return@dispatchGo
|
||||
battlePokemon.heldItemManager.handleEndInstruction(battlePokemon, battle, message)
|
||||
battle.minorBattleActions[battlePokemon.uuid] = message
|
||||
battlePokemon.contextManager.remove(item.id, BattleContext.Type.ITEM)
|
||||
battlePokemon.contextManager.remove(itemEffect.id, BattleContext.Type.ITEM)
|
||||
if (message.hasOptionalArgument("eat")) {
|
||||
battlePokemon.entity?.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F)
|
||||
}
|
||||
@@ -1559,7 +1721,7 @@ object ShowdownInterpreter {
|
||||
val rawHpAndStatus = privateMessage.argumentAt(1)?.split(" ") ?: return
|
||||
val rawHpRatio = rawHpAndStatus.getOrNull(0) ?: return
|
||||
val newHealth = rawHpRatio.split("/").map { it.toFloatOrNull() ?: return }
|
||||
val newHealthRatio = rawHpRatio.split("/").map { it.toFloatOrNull()?.div(100) ?: return }
|
||||
val newHealthRatio = rawHpRatio.split("/").map { it.toFloatOrNull()?.div(newHealth[1]) ?: return }
|
||||
val effect = privateMessage.effect()
|
||||
val pokemonName = battlePokemon.getName()
|
||||
broadcastOptionalAbility(battle, effect, pokemonName)
|
||||
@@ -1607,7 +1769,7 @@ object ShowdownInterpreter {
|
||||
// This part is not always present
|
||||
val rawStatus = rawHpAndStatus.getOrNull(1) ?: return@dispatchWaiting
|
||||
val status = Statuses.getStatus(rawStatus) ?: return@dispatchWaiting
|
||||
if (status is PersistentStatus) {
|
||||
if (status is PersistentStatus && battlePokemon.effectedPokemon.status?.status != status) {
|
||||
battlePokemon.effectedPokemon.applyStatus(status)
|
||||
if (pnx != null) {
|
||||
battle.sendUpdate(BattlePersistentStatusPacket(pnx, status))
|
||||
@@ -1672,7 +1834,9 @@ object ShowdownInterpreter {
|
||||
message.hasOptionalArgument("zeffect") -> battleLang("clearallnegativeboost.zeffect", pokemonName)
|
||||
else -> battleLang("clearallnegativeboost", pokemonName)
|
||||
}
|
||||
battle.broadcastChatMessage(lang)
|
||||
if (!message.hasOptionalArgument("silent")) {
|
||||
battle.broadcastChatMessage(lang)
|
||||
}
|
||||
|
||||
battlePokemon.contextManager.clear(BattleContext.Type.UNBOOST)
|
||||
battle.minorBattleActions[battlePokemon.uuid] = message
|
||||
|
||||
@@ -17,10 +17,12 @@ import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.pokemon.experience.BattleExperienceSource
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMusicPacket
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
import java.util.UUID
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.sound.SoundEvent
|
||||
import net.minecraft.text.MutableText
|
||||
|
||||
class PlayerBattleActor(
|
||||
@@ -31,6 +33,14 @@ class PlayerBattleActor(
|
||||
override val entity: ServerPlayerEntity?
|
||||
get() = this.uuid.getPlayer()
|
||||
|
||||
/** The [SoundEvent] to play to the player during a battle. Will start playing as soon as the battle starts. */
|
||||
var battleTheme: SoundEvent? = null
|
||||
set(value) {
|
||||
if (field != value && this.battle.started)
|
||||
this.sendUpdate(BattleMusicPacket(value))
|
||||
field = value
|
||||
}
|
||||
|
||||
override fun getName(): MutableText = this.entity?.name?.copy() ?: "Offline Player".red()
|
||||
override fun nameOwned(name: String): MutableText = battleLang("owned_pokemon", this.getName(), name)
|
||||
override val type = ActorType.PLAYER
|
||||
|
||||
@@ -73,6 +73,15 @@ class ContextManager {
|
||||
}
|
||||
}
|
||||
|
||||
/** Copies all the [BattleContext]s belonging to the [bucketTypes] buckets of the [with] manager's respective buckets. */
|
||||
fun copy(with: ContextManager, vararg bucketTypes: BattleContext.Type) {
|
||||
bucketTypes.forEach { bucketType ->
|
||||
val newContexts = with.buckets[bucketType]?.toMutableList()
|
||||
this.clear(bucketType)
|
||||
newContexts?.let { this.add(*it.toTypedArray()) }
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets all [BattleContext]s belonging to the [bucketType] bucket. */
|
||||
fun get(bucketType: BattleContext.Type) : Collection<BattleContext>? {
|
||||
return buckets[bucketType]
|
||||
|
||||
@@ -64,11 +64,6 @@ open class BattlePokemon(
|
||||
/** A set of all the BattlePokemon that they faced during the battle (for exp purposes) */
|
||||
val facedOpponents = mutableSetOf<BattlePokemon>()
|
||||
|
||||
/**
|
||||
* A counter of critical hits during this battle, this is used for an evolution requirement.
|
||||
*/
|
||||
var criticalHits: Int = 0
|
||||
|
||||
/**
|
||||
* The [HeldItemManager] backing this [BattlePokemon].
|
||||
*/
|
||||
@@ -89,7 +84,12 @@ open class BattlePokemon(
|
||||
}
|
||||
|
||||
fun isSentOut() = actor.battle.activePokemon.any { it.battlePokemon == this }
|
||||
fun canBeSentOut() = !isSentOut() && !willBeSwitchedIn && health > 0
|
||||
fun canBeSentOut() =
|
||||
if (actor.request?.side?.pokemon?.get(0)?.reviving == true) {
|
||||
!isSentOut() && !willBeSwitchedIn && health <= 0
|
||||
} else {
|
||||
!isSentOut() && !willBeSwitchedIn && health > 0
|
||||
}
|
||||
|
||||
fun writeVariables(struct: VariableStruct) {
|
||||
effectedPokemon.writeVariables(struct)
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.block.entity
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.entity.BlockEntityType
|
||||
import net.minecraft.block.entity.HangingSignBlockEntity
|
||||
import net.minecraft.util.math.BlockPos
|
||||
|
||||
class CobblemonHangingSignBlockEntity(pos: BlockPos, state: BlockState) : HangingSignBlockEntity(pos, state) {
|
||||
|
||||
override fun getType(): BlockEntityType<*> = CobblemonBlockEntities.HANGING_SIGN
|
||||
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.block.entity
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.entity.BlockEntityType
|
||||
import net.minecraft.block.entity.SignBlockEntity
|
||||
import net.minecraft.util.math.BlockPos
|
||||
|
||||
class CobblemonSignBlockEntity(pos: BlockPos, state: BlockState) : SignBlockEntity(pos, state) {
|
||||
|
||||
override fun getType(): BlockEntityType<*> = CobblemonBlockEntities.SIGN
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.block.sign
|
||||
|
||||
import com.cobblemon.mod.common.block.entity.CobblemonHangingSignBlockEntity
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.HangingSignBlock
|
||||
import net.minecraft.block.WoodType
|
||||
import net.minecraft.block.entity.BlockEntity
|
||||
import net.minecraft.util.math.BlockPos
|
||||
|
||||
class CobblemonHangingSignBlock(settings: Settings, woodType: WoodType) : HangingSignBlock(settings, woodType) {
|
||||
|
||||
override fun createBlockEntity(pos: BlockPos, state: BlockState): BlockEntity = CobblemonHangingSignBlockEntity(pos, state)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.block.sign
|
||||
|
||||
import com.cobblemon.mod.common.block.entity.CobblemonSignBlockEntity
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.SignBlock
|
||||
import net.minecraft.block.WoodType
|
||||
import net.minecraft.block.entity.BlockEntity
|
||||
import net.minecraft.util.math.BlockPos
|
||||
|
||||
class CobblemonSignBlock(settings: Settings, woodType: WoodType) : SignBlock(settings, woodType) {
|
||||
|
||||
override fun createBlockEntity(pos: BlockPos, state: BlockState): BlockEntity = CobblemonSignBlockEntity(pos, state)
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.block.sign
|
||||
|
||||
import com.cobblemon.mod.common.block.entity.CobblemonHangingSignBlockEntity
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.WallHangingSignBlock
|
||||
import net.minecraft.block.WoodType
|
||||
import net.minecraft.block.entity.BlockEntity
|
||||
import net.minecraft.util.math.BlockPos
|
||||
|
||||
class CobblemonWallHangingSignBlock(settings: Settings, woodType: WoodType) : WallHangingSignBlock(settings, woodType) {
|
||||
|
||||
override fun createBlockEntity(pos: BlockPos, state: BlockState): BlockEntity = CobblemonHangingSignBlockEntity(pos, state)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.block.sign
|
||||
|
||||
import com.cobblemon.mod.common.block.entity.CobblemonSignBlockEntity
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.WallSignBlock
|
||||
import net.minecraft.block.WoodType
|
||||
import net.minecraft.block.entity.BlockEntity
|
||||
import net.minecraft.util.math.BlockPos
|
||||
|
||||
class CobblemonWallSignBlock(settings: Settings, woodType: WoodType) : WallSignBlock(settings, woodType) {
|
||||
|
||||
override fun createBlockEntity(pos: BlockPos, state: BlockState): BlockEntity = CobblemonSignBlockEntity(pos, state)
|
||||
|
||||
}
|
||||
@@ -9,74 +9,47 @@
|
||||
package com.cobblemon.mod.common.brewing
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.brewing.ingredient.CobblemonIngredient
|
||||
import com.cobblemon.mod.common.brewing.ingredient.CobblemonItemIngredient
|
||||
import com.cobblemon.mod.common.brewing.ingredient.CobblemonPotionIngredient
|
||||
import net.minecraft.item.Item
|
||||
import net.minecraft.potion.Potion
|
||||
import net.minecraft.potion.Potions
|
||||
import net.minecraft.recipe.BrewingRecipeRegistry
|
||||
import net.minecraft.recipe.Ingredient
|
||||
|
||||
object BrewingRecipes {
|
||||
// Put things here if you want them to be add-able to the bottom of the brewing stand (like where potions go)
|
||||
@JvmField
|
||||
val brewableItems = mutableListOf(
|
||||
CobblemonItems.MEDICINAL_BREW,
|
||||
CobblemonItems.POTION,
|
||||
CobblemonItems.SUPER_POTION,
|
||||
CobblemonItems.HYPER_POTION,
|
||||
CobblemonItems.MAX_POTION,
|
||||
CobblemonItems.FULL_RESTORE,
|
||||
CobblemonItems.FULL_HEAL,
|
||||
CobblemonItems.ANTIDOTE,
|
||||
CobblemonItems.AWAKENING,
|
||||
CobblemonItems.BURN_HEAL,
|
||||
CobblemonItems.ICE_HEAL,
|
||||
CobblemonItems.PARALYZE_HEAL,
|
||||
CobblemonItems.ETHER,
|
||||
CobblemonItems.MAX_ETHER,
|
||||
CobblemonItems.ELIXIR,
|
||||
CobblemonItems.MAX_ELIXIR
|
||||
)
|
||||
|
||||
fun registerPotionTypes() {
|
||||
brewableItems.forEach { item ->
|
||||
BrewingRecipeRegistry.POTION_TYPES.add(Ingredient.ofItems(item))
|
||||
}
|
||||
}
|
||||
|
||||
fun getPotionRecipes(): List<Triple<Potion, Ingredient, Potion>> {
|
||||
return listOf(
|
||||
Triple(Potions.WATER, Ingredient.ofItems(CobblemonItems.MEDICINAL_LEEK), Potions.WATER), // This one is Mixin'd to result in brew rather than water
|
||||
val recipes: List<Triple<CobblemonIngredient, CobblemonIngredient, Item>> by lazy {
|
||||
listOf(
|
||||
Triple(CobblemonPotionIngredient(Potions.WATER), CobblemonItemIngredient(CobblemonItems.MEDICINAL_LEEK), CobblemonItems.MEDICINAL_BREW),
|
||||
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.LEPPA_BERRY, CobblemonItems.ETHER),
|
||||
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.HOPO_BERRY, CobblemonItems.ELIXIR),
|
||||
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.ORAN_BERRY, CobblemonItems.POTION),
|
||||
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.SITRUS_BERRY, CobblemonItems.HYPER_POTION),
|
||||
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.LUM_BERRY, CobblemonItems.FULL_HEAL),
|
||||
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.PECHA_BERRY, CobblemonItems.ANTIDOTE),
|
||||
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.CHESTO_BERRY, CobblemonItems.AWAKENING),
|
||||
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.RAWST_BERRY, CobblemonItems.BURN_HEAL),
|
||||
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.ASPEAR_BERRY, CobblemonItems.ICE_HEAL),
|
||||
convert(CobblemonItems.MEDICINAL_BREW, CobblemonItems.CHERI_BERRY, CobblemonItems.PARALYZE_HEAL),
|
||||
convert(CobblemonItems.BURN_HEAL, CobblemonItems.LUM_BERRY, CobblemonItems.FULL_HEAL),
|
||||
convert(CobblemonItems.ANTIDOTE, CobblemonItems.LUM_BERRY, CobblemonItems.FULL_HEAL),
|
||||
convert(CobblemonItems.AWAKENING, CobblemonItems.LUM_BERRY, CobblemonItems.FULL_HEAL),
|
||||
convert(CobblemonItems.ICE_HEAL, CobblemonItems.LUM_BERRY, CobblemonItems.FULL_HEAL),
|
||||
convert(CobblemonItems.PARALYZE_HEAL, CobblemonItems.LUM_BERRY, CobblemonItems.FULL_HEAL),
|
||||
convert(CobblemonItems.ETHER, CobblemonItems.PEP_UP_FLOWER, CobblemonItems.MAX_ETHER),
|
||||
convert(CobblemonItems.ELIXIR, CobblemonItems.PEP_UP_FLOWER, CobblemonItems.MAX_ELIXIR),
|
||||
convert(CobblemonItems.POTION, CobblemonItems.ENERGY_ROOT, CobblemonItems.SUPER_POTION),
|
||||
convert(CobblemonItems.SUPER_POTION, CobblemonItems.FIGY_BERRY, CobblemonItems.HYPER_POTION),
|
||||
convert(CobblemonItems.SUPER_POTION, CobblemonItems.WIKI_BERRY, CobblemonItems.HYPER_POTION),
|
||||
convert(CobblemonItems.SUPER_POTION, CobblemonItems.MAGO_BERRY, CobblemonItems.HYPER_POTION),
|
||||
convert(CobblemonItems.SUPER_POTION, CobblemonItems.AGUAV_BERRY, CobblemonItems.HYPER_POTION),
|
||||
convert(CobblemonItems.SUPER_POTION, CobblemonItems.IAPAPA_BERRY, CobblemonItems.HYPER_POTION),
|
||||
convert(CobblemonItems.HYPER_POTION, CobblemonItems.VIVICHOKE, CobblemonItems.MAX_POTION),
|
||||
convert(CobblemonItems.MAX_POTION, CobblemonItems.LUM_BERRY, CobblemonItems.FULL_RESTORE)
|
||||
)
|
||||
}
|
||||
|
||||
fun getItemRecipes(): List<Triple<Item, Ingredient, Item>> {
|
||||
// This is where the majority of our recipes go. First arg is thing down the bottom, second is thing up the top, third is results.
|
||||
return listOf(
|
||||
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.LEPPA_BERRY), CobblemonItems.ETHER),
|
||||
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.HOPO_BERRY), CobblemonItems.ELIXIR),
|
||||
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.ORAN_BERRY), CobblemonItems.POTION),
|
||||
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.SITRUS_BERRY), CobblemonItems.HYPER_POTION),
|
||||
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.LUM_BERRY), CobblemonItems.FULL_HEAL),
|
||||
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.PECHA_BERRY), CobblemonItems.ANTIDOTE),
|
||||
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.CHESTO_BERRY), CobblemonItems.AWAKENING),
|
||||
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.RAWST_BERRY), CobblemonItems.BURN_HEAL),
|
||||
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.ASPEAR_BERRY), CobblemonItems.ICE_HEAL),
|
||||
Triple(CobblemonItems.MEDICINAL_BREW, Ingredient.ofItems(CobblemonItems.CHERI_BERRY), CobblemonItems.PARALYZE_HEAL),
|
||||
Triple(CobblemonItems.BURN_HEAL, Ingredient.ofItems(CobblemonItems.LUM_BERRY), CobblemonItems.FULL_HEAL),
|
||||
Triple(CobblemonItems.ANTIDOTE, Ingredient.ofItems(CobblemonItems.LUM_BERRY), CobblemonItems.FULL_HEAL),
|
||||
Triple(CobblemonItems.AWAKENING, Ingredient.ofItems(CobblemonItems.LUM_BERRY), CobblemonItems.FULL_HEAL),
|
||||
Triple(CobblemonItems.ICE_HEAL, Ingredient.ofItems(CobblemonItems.LUM_BERRY), CobblemonItems.FULL_HEAL),
|
||||
Triple(CobblemonItems.PARALYZE_HEAL, Ingredient.ofItems(CobblemonItems.LUM_BERRY), CobblemonItems.FULL_HEAL),
|
||||
Triple(CobblemonItems.ETHER, Ingredient.ofItems(CobblemonItems.PEP_UP_FLOWER), CobblemonItems.MAX_ETHER),
|
||||
Triple(CobblemonItems.ELIXIR, Ingredient.ofItems(CobblemonItems.PEP_UP_FLOWER), CobblemonItems.MAX_ELIXIR),
|
||||
Triple(CobblemonItems.POTION, Ingredient.ofItems(CobblemonItems.ENERGY_ROOT), CobblemonItems.SUPER_POTION),
|
||||
Triple(CobblemonItems.SUPER_POTION, Ingredient.ofItems(CobblemonItems.FIGY_BERRY), CobblemonItems.HYPER_POTION),
|
||||
Triple(CobblemonItems.SUPER_POTION, Ingredient.ofItems(CobblemonItems.WIKI_BERRY), CobblemonItems.HYPER_POTION),
|
||||
Triple(CobblemonItems.SUPER_POTION, Ingredient.ofItems(CobblemonItems.MAGO_BERRY), CobblemonItems.HYPER_POTION),
|
||||
Triple(CobblemonItems.SUPER_POTION, Ingredient.ofItems(CobblemonItems.AGUAV_BERRY), CobblemonItems.HYPER_POTION),
|
||||
Triple(CobblemonItems.SUPER_POTION, Ingredient.ofItems(CobblemonItems.IAPAPA_BERRY), CobblemonItems.HYPER_POTION),
|
||||
Triple(CobblemonItems.HYPER_POTION, Ingredient.ofItems(CobblemonItems.VIVICHOKE), CobblemonItems.MAX_POTION),
|
||||
Triple(CobblemonItems.MAX_POTION, Ingredient.ofItems(CobblemonItems.LUM_BERRY), CobblemonItems.FULL_RESTORE)
|
||||
)
|
||||
|
||||
private fun convert(input: Item, ingredient: Item, output: Item): Triple<CobblemonIngredient, CobblemonIngredient, Item> {
|
||||
return Triple(CobblemonItemIngredient(input), CobblemonItemIngredient(ingredient), output)
|
||||
}
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.brewing.ingredient
|
||||
|
||||
import net.minecraft.item.ItemStack
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
/**
|
||||
* The Cobblemon representation of a brewing ingredient.
|
||||
* This is done to abstract platform specific requirements for a more custom solution to brewing.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
sealed interface CobblemonIngredient {
|
||||
|
||||
/**
|
||||
* Tests if a given [stack] is valid for this ingredient.
|
||||
*
|
||||
* @param stack The [ItemStack] being tested.
|
||||
* @return If the given [stack] is valid for this ingredient.
|
||||
*/
|
||||
fun matches(stack: ItemStack): Boolean
|
||||
|
||||
/**
|
||||
* Resolves list of [ItemStack]s that is used by the vanilla Ingredient implementation when a platform requires wrapping.
|
||||
*
|
||||
* @return A list of [ItemStack]s
|
||||
*/
|
||||
fun matchingStacks(): List<ItemStack>
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.brewing.ingredient
|
||||
|
||||
import net.minecraft.item.Item
|
||||
import net.minecraft.item.ItemStack
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Internal
|
||||
class CobblemonItemIngredient(val item: Item) : CobblemonIngredient {
|
||||
|
||||
override fun matches(stack: ItemStack): Boolean = stack.isOf(this.item)
|
||||
|
||||
override fun matchingStacks(): List<ItemStack> = listOf(this.item.defaultStack)
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.brewing.ingredient
|
||||
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.item.Items
|
||||
import net.minecraft.potion.Potion
|
||||
import net.minecraft.potion.PotionUtil
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Internal
|
||||
class CobblemonPotionIngredient(val potion: Potion) : CobblemonIngredient {
|
||||
|
||||
override fun matches(stack: ItemStack): Boolean {
|
||||
val potion = PotionUtil.getPotion(stack)
|
||||
return potion == this.potion
|
||||
}
|
||||
|
||||
override fun matchingStacks(): List<ItemStack> {
|
||||
val list = arrayListOf<ItemStack>()
|
||||
list += PotionUtil.setPotion(Items.POTION.defaultStack, this.potion)
|
||||
list += PotionUtil.setPotion(Items.SPLASH_POTION.defaultStack, this.potion)
|
||||
list += PotionUtil.setPotion(Items.LINGERING_POTION.defaultStack, this.potion)
|
||||
return list
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,28 +18,34 @@ import com.cobblemon.mod.common.client.gui.battle.BattleOverlay
|
||||
import com.cobblemon.mod.common.client.particle.BedrockParticleEffectRepository
|
||||
import com.cobblemon.mod.common.client.render.block.BerryBlockRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.HealingMachineRenderer
|
||||
import com.cobblemon.mod.common.client.render.boat.CobblemonBoatRenderer
|
||||
import com.cobblemon.mod.common.client.render.item.CobblemonBuiltinItemRendererRegistry
|
||||
import com.cobblemon.mod.common.client.render.item.PokemonItemRenderer
|
||||
import com.cobblemon.mod.common.client.render.layer.PokemonOnShoulderRenderer
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.bedrock.animation.BedrockAnimationRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.BerryModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokeBallModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.client.render.pokeball.PokeBallRenderer
|
||||
import com.cobblemon.mod.common.client.render.pokemon.PokemonRenderer
|
||||
import com.cobblemon.mod.common.client.sound.battle.BattleMusicController
|
||||
import com.cobblemon.mod.common.client.starter.ClientPlayerData
|
||||
import com.cobblemon.mod.common.client.storage.ClientStorageManager
|
||||
import com.cobblemon.mod.common.client.trade.ClientTrade
|
||||
import com.cobblemon.mod.common.data.CobblemonDataProvider
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
|
||||
import com.cobblemon.mod.common.item.PokeBallItem
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.BerryModelRepository
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import net.minecraft.client.gui.DrawContext
|
||||
import net.minecraft.client.render.RenderLayer
|
||||
import net.minecraft.client.render.block.entity.HangingSignBlockEntityRenderer
|
||||
import net.minecraft.client.render.block.entity.SignBlockEntityRenderer
|
||||
import net.minecraft.client.render.entity.EntityRenderer
|
||||
import net.minecraft.client.render.entity.EntityRendererFactory
|
||||
import net.minecraft.client.render.entity.LivingEntityRenderer
|
||||
import net.minecraft.client.render.entity.model.BoatEntityModel
|
||||
import net.minecraft.client.render.entity.model.ChestBoatEntityModel
|
||||
import net.minecraft.client.render.entity.model.PlayerEntityModel
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.item.ItemStack
|
||||
@@ -83,12 +89,11 @@ object CobblemonClient {
|
||||
PlatformEvents.CLIENT_PLAYER_LOGIN.subscribe { onLogin() }
|
||||
PlatformEvents.CLIENT_PLAYER_LOGOUT.subscribe { onLogout() }
|
||||
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.HEALING_MACHINE, ::HealingMachineRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.BERRY, ::BerryBlockRenderer)
|
||||
|
||||
this.registerBlockEntityRenderers()
|
||||
registerBlockRenderTypes()
|
||||
//registerColors()
|
||||
registerFlywheelRenderers()
|
||||
this.registerEntityRenderers()
|
||||
|
||||
LOGGER.info("Registering custom BuiltinItemRenderers")
|
||||
CobblemonBuiltinItemRendererRegistry.register(CobblemonItems.POKEMON_MODEL, PokemonItemRenderer())
|
||||
@@ -96,6 +101,7 @@ object CobblemonClient {
|
||||
PlatformEvents.CLIENT_ITEM_TOOLTIP.subscribe { event ->
|
||||
val stack = event.stack
|
||||
val lines = event.lines
|
||||
val size = lines.size
|
||||
@Suppress("DEPRECATION")
|
||||
if (stack.item.registryEntry.key.isPresent && stack.item.registryEntry.key.get().value.namespace == Cobblemon.MODID) {
|
||||
if (stack.nbt?.getBoolean(DataKeys.HIDE_TOOLTIP) == true) {
|
||||
@@ -103,13 +109,14 @@ object CobblemonClient {
|
||||
}
|
||||
val language = Language.getInstance()
|
||||
val key = this.baseLangKeyForItem(stack)
|
||||
val offset = if (size > 1) 1 else 0
|
||||
if (language.hasTranslation(key)) {
|
||||
lines.add(key.asTranslated().gray())
|
||||
lines.add(size - offset, key.asTranslated().gray())
|
||||
}
|
||||
var i = 1
|
||||
var listKey = "${key}_$i"
|
||||
while(language.hasTranslation(listKey)) {
|
||||
lines.add(listKey.asTranslated().gray())
|
||||
lines.add(size - offset, listKey.asTranslated().gray())
|
||||
listKey = "${key}_${++i}"
|
||||
}
|
||||
}
|
||||
@@ -143,6 +150,10 @@ object CobblemonClient {
|
||||
RenderLayer.getCutout(),
|
||||
CobblemonBlocks.APRICORN_DOOR,
|
||||
CobblemonBlocks.APRICORN_TRAPDOOR,
|
||||
CobblemonBlocks.APRICORN_SIGN,
|
||||
CobblemonBlocks.APRICORN_WALL_SIGN,
|
||||
CobblemonBlocks.APRICORN_HANGING_SIGN,
|
||||
CobblemonBlocks.APRICORN_WALL_HANGING_SIGN,
|
||||
CobblemonBlocks.BLACK_APRICORN_SAPLING,
|
||||
CobblemonBlocks.BLUE_APRICORN_SAPLING,
|
||||
CobblemonBlocks.GREEN_APRICORN_SAPLING,
|
||||
@@ -176,6 +187,8 @@ object CobblemonClient {
|
||||
CobblemonBlocks.REVIVAL_HERB,
|
||||
*CobblemonBlocks.berries().values.toTypedArray()
|
||||
)
|
||||
|
||||
this.createBoatModelLayers()
|
||||
}
|
||||
|
||||
fun beforeChatRender(context: DrawContext, partialDeltaTicks: Float) {
|
||||
@@ -194,14 +207,22 @@ object CobblemonClient {
|
||||
renderer?.addFeature(PokemonOnShoulderRenderer(renderer))
|
||||
}
|
||||
|
||||
fun registerPokemonRenderer(context: EntityRendererFactory.Context): PokemonRenderer {
|
||||
LOGGER.info("Registering Pokémon renderer")
|
||||
return PokemonRenderer(context)
|
||||
private fun registerBlockEntityRenderers() {
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.HEALING_MACHINE, ::HealingMachineRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.BERRY, ::BerryBlockRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.SIGN, ::SignBlockEntityRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.HANGING_SIGN, ::HangingSignBlockEntityRenderer)
|
||||
}
|
||||
|
||||
fun registerPokeBallRenderer(context: EntityRendererFactory.Context): PokeBallRenderer {
|
||||
private fun registerEntityRenderers() {
|
||||
LOGGER.info("Registering Pokémon renderer")
|
||||
this.implementation.registerEntityRenderer(CobblemonEntities.POKEMON, ::PokemonRenderer)
|
||||
LOGGER.info("Registering PokéBall renderer")
|
||||
return PokeBallRenderer(context)
|
||||
this.implementation.registerEntityRenderer(CobblemonEntities.EMPTY_POKEBALL, ::PokeBallRenderer)
|
||||
LOGGER.info("Registering Boat renderer")
|
||||
this.implementation.registerEntityRenderer(CobblemonEntities.BOAT) { ctx -> CobblemonBoatRenderer(ctx, false) }
|
||||
LOGGER.info("Registering Boat with Chest renderer")
|
||||
this.implementation.registerEntityRenderer(CobblemonEntities.CHEST_BOAT) { ctx -> CobblemonBoatRenderer(ctx, true) }
|
||||
}
|
||||
|
||||
fun reloadCodedAssets(resourceManager: ResourceManager) {
|
||||
@@ -215,11 +236,12 @@ object CobblemonClient {
|
||||
PokeBallModelRepository.reload(resourceManager)
|
||||
BerryModelRepository.reload(resourceManager)
|
||||
LOGGER.info("Loaded assets")
|
||||
// PokeBallModelRepository.reload(resourceManager)
|
||||
}
|
||||
|
||||
fun endBattle() {
|
||||
battle = null
|
||||
battleOverlay.lastKnownBattle = null
|
||||
BattleMusicController.endMusic()
|
||||
}
|
||||
|
||||
private fun baseLangKeyForItem(stack: ItemStack): String {
|
||||
@@ -230,4 +252,11 @@ object CobblemonClient {
|
||||
return "${stack.translationKey}.tooltip"
|
||||
}
|
||||
|
||||
private fun createBoatModelLayers() {
|
||||
CobblemonBoatType.values().forEach { type ->
|
||||
this.implementation.registerLayer(CobblemonBoatRenderer.createBoatModelLayer(type, false), BoatEntityModel::getTexturedModelData)
|
||||
this.implementation.registerLayer(CobblemonBoatRenderer.createBoatModelLayer(type, true), ChestBoatEntityModel::getTexturedModelData)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -57,6 +57,8 @@ fun drawProfilePokemon(
|
||||
val context = RenderContext()
|
||||
PokemonModelRepository.getTextureNoSubstitute(species, aspects, 0f).let { it -> context.put(RenderContext.TEXTURE, it) }
|
||||
context.put(RenderContext.SCALE, PokemonSpecies.getByIdentifier(species)!!.getForm(aspects).baseScale)
|
||||
context.put(RenderContext.SPECIES, species)
|
||||
context.put(RenderContext.ASPECTS, aspects)
|
||||
|
||||
val renderType = model.getLayer(texture)
|
||||
|
||||
|
||||
@@ -13,12 +13,14 @@ import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.battle.ClientBattleActor
|
||||
import com.cobblemon.mod.common.client.battle.SingleActionRequest
|
||||
import com.cobblemon.mod.common.client.gui.battle.subscreen.BattleActionSelection
|
||||
import com.cobblemon.mod.common.client.gui.battle.subscreen.BattleBackButton
|
||||
import com.cobblemon.mod.common.client.gui.battle.subscreen.BattleGeneralActionSelection
|
||||
import com.cobblemon.mod.common.client.gui.battle.subscreen.BattleSwitchPokemonSelection
|
||||
import com.cobblemon.mod.common.client.gui.battle.widgets.BattleMessagePane
|
||||
import com.cobblemon.mod.common.client.keybind.boundKey
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.MinecraftClient
|
||||
@@ -41,6 +43,7 @@ class BattleGUI : Screen(battleLang("gui.title")) {
|
||||
private lateinit var messagePane: BattleMessagePane
|
||||
var opacity = 0F
|
||||
val actor = CobblemonClient.battle?.side1?.actors?.find { it.uuid == MinecraftClient.getInstance().player?.uuid }
|
||||
val specBackButton = BattleBackButton(12f, MinecraftClient.getInstance().window.scaledHeight - 32f)
|
||||
|
||||
var queuedActions = mutableListOf<() -> Unit>()
|
||||
|
||||
@@ -106,6 +109,10 @@ class BattleGUI : Screen(battleLang("gui.title")) {
|
||||
}
|
||||
}
|
||||
|
||||
if (battle.spectating) {
|
||||
specBackButton.render(context.matrices, mouseX, mouseY, delta)
|
||||
}
|
||||
|
||||
val currentSelection = getCurrentActionSelection()
|
||||
if (currentSelection == null || currentSelection is BattleGeneralActionSelection ) {
|
||||
drawScaledText(
|
||||
@@ -153,4 +160,13 @@ class BattleGUI : Screen(battleLang("gui.title")) {
|
||||
}
|
||||
return super.charTyped(chr, modifiers)
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
val battle = CobblemonClient.battle
|
||||
if (battle?.spectating == true && specBackButton.isHovered(mouseX, mouseY)) {
|
||||
RemoveSpectatorPacket(battle.battleId).sendToServer()
|
||||
CobblemonClient.endBattle()
|
||||
}
|
||||
return super.mouseClicked(mouseX, mouseY, button)
|
||||
}
|
||||
}
|
||||
+9
-4
@@ -9,8 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.gui.battle.subscreen
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.battles.ShowdownPokemon
|
||||
import com.cobblemon.mod.common.battles.SwitchActionResponse
|
||||
import com.cobblemon.mod.common.battles.*
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.battle.SingleActionRequest
|
||||
import com.cobblemon.mod.common.client.gui.battle.BattleGUI
|
||||
@@ -24,6 +23,7 @@ import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder
|
||||
import net.minecraft.client.sound.PositionedSoundInstance
|
||||
import net.minecraft.client.sound.SoundManager
|
||||
import net.minecraft.client.util.math.MatrixStack
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.math.MathHelper.ceil
|
||||
class BattleSwitchPokemonSelection(
|
||||
battleGUI: BattleGUI,
|
||||
@@ -83,7 +83,6 @@ class BattleSwitchPokemonSelection(
|
||||
partialTicks = deltaTicks
|
||||
)
|
||||
} catch (exception: Exception) {
|
||||
println(showdownPokemon.condition)
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
@@ -98,9 +97,15 @@ class BattleSwitchPokemonSelection(
|
||||
.find { it.uuid == showdownPokemon.uuid }
|
||||
?.let { showdownPokemon to it }
|
||||
}
|
||||
.filter {
|
||||
if (request.side.pokemon[0].reviving) {
|
||||
"fnt" in it.first.condition
|
||||
} else {
|
||||
"fnt" !in it.first.condition
|
||||
}
|
||||
}
|
||||
.filter { it.second.uuid !in battleGUI.actor!!.activePokemon.map { it.battlePokemon?.uuid } }
|
||||
.filter { it.second.uuid !in switchingInPokemon }
|
||||
.filter { "fnt" !in it.first.condition || it.first.reviving }
|
||||
|
||||
showdownPokemonToPokemon.forEachIndexed { index, (showdownPokemon, pokemon) ->
|
||||
val row = index / 2
|
||||
|
||||
+29
-10
@@ -10,7 +10,9 @@ package com.cobblemon.mod.common.client.gui.interact.wheel
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.interact.InteractPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.AcceptTradeRequestPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
|
||||
@@ -48,14 +50,14 @@ fun createPokemonInteractGui(pokemonID: UUID, canMountShoulder: Boolean): Intera
|
||||
return InteractWheelGUI(options, Text.translatable("cobblemon.ui.interact.pokemon"))
|
||||
}
|
||||
|
||||
fun createPlayerInteractGui(targetPlayer: PlayerEntity, pokemon: Pokemon): InteractWheelGUI {
|
||||
fun createPlayerInteractGui(optionsPacket: PlayerInteractOptionsPacket): InteractWheelGUI {
|
||||
val trade = InteractWheelOption(
|
||||
iconResource = cobblemonResource("textures/gui/interact/icon_trade.png"),
|
||||
colour = { if (CobblemonClient.requests.tradeOffers.any { it.traderId == targetPlayer.uuid }) Vector3f(0F, 0.6F, 0F) else null },
|
||||
colour = { if (CobblemonClient.requests.tradeOffers.any { it.traderId == optionsPacket.targetId }) Vector3f(0F, 0.6F, 0F) else null },
|
||||
onPress = {
|
||||
val tradeOffer = CobblemonClient.requests.tradeOffers.find { it.traderId == targetPlayer.uuid }
|
||||
val tradeOffer = CobblemonClient.requests.tradeOffers.find { it.traderId == optionsPacket.targetId }
|
||||
if (tradeOffer == null) {
|
||||
CobblemonNetwork.sendToServer(OfferTradePacket(targetPlayer.uuid))
|
||||
CobblemonNetwork.sendToServer(OfferTradePacket(optionsPacket.targetId))
|
||||
} else {
|
||||
CobblemonClient.requests.tradeOffers -= tradeOffer
|
||||
CobblemonNetwork.sendToServer(AcceptTradeRequestPacket(tradeOffer.tradeOfferId))
|
||||
@@ -65,18 +67,35 @@ fun createPlayerInteractGui(targetPlayer: PlayerEntity, pokemon: Pokemon): Inter
|
||||
)
|
||||
val battle = InteractWheelOption(
|
||||
iconResource = cobblemonResource("textures/gui/interact/icon_battle.png"),
|
||||
colour = { if (CobblemonClient.requests.battleChallenges.any { it.challengerId == targetPlayer.uuid }) Vector3f(0F, 0.6F, 0F) else null },
|
||||
colour = { if (CobblemonClient.requests.battleChallenges.any { it.challengerId == optionsPacket.targetId }) Vector3f(0F, 0.6F, 0F) else null },
|
||||
onPress = {
|
||||
val battleRequest = CobblemonClient.requests.battleChallenges.find { it.challengerId == targetPlayer.uuid }
|
||||
val battleRequest = CobblemonClient.requests.battleChallenges.find { it.challengerId == optionsPacket.targetId }
|
||||
// This can be improved in future with more detailed battle challenge data.
|
||||
BattleChallengePacket(targetPlayer.id, pokemon.uuid).sendToServer()
|
||||
BattleChallengePacket(optionsPacket.numericTargetId, optionsPacket.selectedPokemonId).sendToServer()
|
||||
closeGUI()
|
||||
}
|
||||
)
|
||||
val options = mutableMapOf(
|
||||
Orientation.TOP_LEFT to trade,
|
||||
Orientation.TOP_RIGHT to battle
|
||||
val spectate = InteractWheelOption(
|
||||
iconResource = cobblemonResource("textures/gui/interact/icon_spectate_battle.png"),
|
||||
colour = { if (CobblemonClient.requests.battleChallenges.any { it.challengerId == optionsPacket.targetId }) Vector3f(0F, 0.6F, 0F) else null },
|
||||
onPress = {
|
||||
SpectateBattlePacket(optionsPacket.targetId).sendToServer()
|
||||
closeGUI()
|
||||
}
|
||||
)
|
||||
val options = mutableMapOf<Orientation, InteractWheelOption>()
|
||||
//The way things are positioned should probably be more thought out if more options are added
|
||||
optionsPacket.options.map {
|
||||
if (it.equals(PlayerInteractOptionsPacket.Options.TRADE)) {
|
||||
options[Orientation.TOP_LEFT] = trade
|
||||
}
|
||||
if (it.equals(PlayerInteractOptionsPacket.Options.BATTLE)) {
|
||||
options[Orientation.TOP_RIGHT] = battle
|
||||
}
|
||||
if (it.equals(PlayerInteractOptionsPacket.Options.SPECTATE_BATTLE)) {
|
||||
options[Orientation.TOP_RIGHT] = spectate
|
||||
}
|
||||
}
|
||||
return InteractWheelGUI(options, Text.translatable("cobblemon.ui.interact.player"))
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -11,15 +11,14 @@ package com.cobblemon.mod.common.client.keybind.keybinds
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacketToServer
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.gui.battle.BattleGUI
|
||||
import com.cobblemon.mod.common.client.gui.interact.wheel.createPlayerInteractGui
|
||||
import com.cobblemon.mod.common.client.keybind.CobblemonBlockingKeyBinding
|
||||
import com.cobblemon.mod.common.client.keybind.KeybindCategories
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.RequestPlayerInteractionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.traceFirstEntityCollision
|
||||
import javax.swing.plaf.basic.BasicSliderUI.ScrollListener
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.client.network.ClientPlayerEntity
|
||||
import net.minecraft.client.util.InputUtil
|
||||
@@ -90,7 +89,9 @@ object PartySendBinding : CobblemonBlockingKeyBinding(
|
||||
private fun processEntityTarget(player: ClientPlayerEntity, pokemon: Pokemon, entity: LivingEntity) {
|
||||
when (entity) {
|
||||
is PlayerEntity -> {
|
||||
MinecraftClient.getInstance().setScreen(createPlayerInteractGui(entity, pokemon))
|
||||
//This sends a packet to the server with the id of the player
|
||||
//The server sends a packet back that opens the player interaction menu with the proper options
|
||||
sendPacketToServer(RequestPlayerInteractionsPacket(entity.uuid, entity.id, pokemon.uuid))
|
||||
}
|
||||
is PokemonEntity -> {
|
||||
if (!entity.canBattle(player)) return
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.net
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.client.gui.interact.wheel.createPlayerInteractGui
|
||||
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
|
||||
import net.minecraft.client.MinecraftClient
|
||||
|
||||
object PlayerInteractOptionsHandler : ClientNetworkPacketHandler<PlayerInteractOptionsPacket> {
|
||||
override fun handle(packet: PlayerInteractOptionsPacket, client: MinecraftClient) {
|
||||
MinecraftClient.getInstance().setScreen(createPlayerInteractGui(packet))
|
||||
}
|
||||
|
||||
}
|
||||
+3
-3
@@ -32,10 +32,10 @@ object BattleInitializeHandler : ClientNetworkPacketHandler<BattleInitializePack
|
||||
}
|
||||
|
||||
val otherSide = if (mySide == packet.side1) packet.side2 else packet.side1
|
||||
|
||||
side1.actors.addAll(mySide.actors.map{ actorFromDTO(it, true) })
|
||||
val sides = listOf(packet.side1, packet.side2)
|
||||
spectating = !sides.any { it.actors.any { it.uuid == MinecraftClient.getInstance().player?.uuid } }
|
||||
side1.actors.addAll(mySide.actors.map{ actorFromDTO(it, !spectating) })
|
||||
side2.actors.addAll(otherSide.actors.map{ actorFromDTO(it, false) })
|
||||
spectating = sides.any { it.actors.any { it.uuid == MinecraftClient.getInstance().player?.uuid } }
|
||||
for (side in listOf(side1, side2)) {
|
||||
side.battle = this
|
||||
for (actor in side.actors) {
|
||||
|
||||
+14
-82
@@ -9,101 +9,33 @@
|
||||
package com.cobblemon.mod.common.client.net.battle
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.access.SoundManagerDuck
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.mixin.accessor.MusicTrackerAccessor
|
||||
import com.cobblemon.mod.common.client.sound.battle.BattleMusicController
|
||||
import com.cobblemon.mod.common.client.sound.battle.BattleMusicInstance
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMusicPacket
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.client.sound.PositionedSoundInstance
|
||||
import net.minecraft.client.sound.SoundInstance
|
||||
import net.minecraft.client.sound.SoundManager
|
||||
import net.minecraft.client.sound.TickableSoundInstance
|
||||
import net.minecraft.sound.SoundCategory
|
||||
import net.minecraft.sound.SoundEvent
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.MathHelper
|
||||
|
||||
/**
|
||||
* The handler for [BattleMusicPacket]s. Interfaces with [BattleMusicController] to change battle music.
|
||||
*
|
||||
* @author Segfault Guy
|
||||
* @since April 22nd, 2023
|
||||
*/
|
||||
object BattleMusicHandler : ClientNetworkPacketHandler<BattleMusicPacket> {
|
||||
|
||||
// Keep a reference for look-up in SoundManager
|
||||
var music: BattleMusicInstance? = null
|
||||
// SoundCategories that are blocked while battle music is playing
|
||||
private val interferences = listOf(SoundCategory.AMBIENT, SoundCategory.RECORDS)
|
||||
|
||||
override fun handle(packet: BattleMusicPacket, client: MinecraftClient) {
|
||||
val soundManager = client.soundManager
|
||||
val newMusic = packet.music
|
||||
val currMusic = this.music
|
||||
val newMusic = packet.music?.let { BattleMusicInstance(it, packet.volume, packet.pitch) }
|
||||
val currMusic = BattleMusicController.music
|
||||
|
||||
if (newMusic == null)
|
||||
soundManager.endMusic()
|
||||
else if (currMusic == null)
|
||||
soundManager.initializeMusic(newMusic, packet.volume, packet.pitch)
|
||||
BattleMusicController.endMusic()
|
||||
else if (!soundManager.isPlaying(currMusic))
|
||||
BattleMusicController.initializeMusic(newMusic)
|
||||
else if (newMusic.id != currMusic.id)
|
||||
soundManager.switchMusic(newMusic, packet.volume, packet.pitch)
|
||||
BattleMusicController.switchMusic(newMusic)
|
||||
else
|
||||
LOGGER.error("Ignored BattleMusicPacket from server: ${packet.music?.id}")
|
||||
}
|
||||
|
||||
// stop all interference sounds currently playing and start a new BattleMusicInstance
|
||||
private fun SoundManager.initializeMusic(sound: SoundEvent, volume: Float, pitch: Float) {
|
||||
this.stopSounds(null, SoundCategory.MUSIC)
|
||||
interferences.forEach { this.stopSounds(null, it) }
|
||||
(this as SoundManagerDuck).toggleCategories(*interferences.toTypedArray())
|
||||
music = BattleMusicInstance(sound, volume, pitch)
|
||||
this.play(music)
|
||||
}
|
||||
|
||||
// switch (without fade) to a new BattleMusicInstance if one is already playing
|
||||
private fun SoundManager.switchMusic(sound: SoundEvent, volume: Float, pitch: Float) {
|
||||
this.stop(music)
|
||||
music = BattleMusicInstance(sound, volume, pitch)
|
||||
this.play(music)
|
||||
}
|
||||
|
||||
// fade out and end current BattleMusicInstance
|
||||
private fun SoundManager.endMusic() {
|
||||
(this as SoundManagerDuck).toggleCategories(*interferences.toTypedArray())
|
||||
music?.setFade()
|
||||
music = null
|
||||
}
|
||||
}
|
||||
|
||||
class BattleMusicInstance(sound: SoundEvent, volume: Float, pitch: Float) :
|
||||
PositionedSoundInstance(sound, SoundCategory.MUSIC, volume, pitch, SoundInstance.createRandom(), BlockPos.ORIGIN), TickableSoundInstance {
|
||||
|
||||
private var fade: Boolean = false
|
||||
private var done: Boolean = false
|
||||
private val tracker: MusicTrackerAccessor
|
||||
private var tickCount = 0
|
||||
private var fadeCount = 0
|
||||
private val fadeTime = 60.0
|
||||
private var initVolume = 1.0
|
||||
|
||||
init {
|
||||
this.relative = true
|
||||
this.repeat = true
|
||||
this.attenuationType = SoundInstance.AttenuationType.NONE
|
||||
this.tracker = MinecraftClient.getInstance().musicTracker as MusicTrackerAccessor
|
||||
this.initVolume = volume.toDouble()
|
||||
}
|
||||
|
||||
override fun isDone(): Boolean {
|
||||
return this.done
|
||||
}
|
||||
|
||||
fun setFade() {
|
||||
this.fade = true
|
||||
this.repeat = false
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
++tickCount
|
||||
if (fade) {
|
||||
++fadeCount
|
||||
this.volume = MathHelper.lerp(fadeCount/fadeTime, initVolume, 0.0).toFloat()
|
||||
if (volume <= 0) this.done = true
|
||||
}
|
||||
if (tickCount % 20 == 0) tracker.setTimeUntilNextSong(tracker.timeUntilNextSong() + 20)
|
||||
}
|
||||
}
|
||||
+5
-3
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.net.effect
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.client.particle.BedrockParticleEffectRepository
|
||||
import com.cobblemon.mod.common.client.particle.ParticleStorm
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
|
||||
@@ -23,10 +24,11 @@ object SpawnSnowstormParticleHandler : ClientNetworkPacketHandler<SpawnSnowstorm
|
||||
val wrapper = MatrixWrapper()
|
||||
val matrix = MatrixStack()
|
||||
matrix.translate(packet.position.x, packet.position.y, packet.position.z)
|
||||
matrix.multiply(POSITIVE_Y.rotationDegrees(packet.yawDegrees))
|
||||
matrix.multiply(NEGATIVE_X.rotationDegrees(packet.pitchDegrees))
|
||||
// matrix.multiply(POSITIVE_Y.rotationDegrees(packet.yawDegrees))
|
||||
// matrix.multiply(NEGATIVE_X.rotationDegrees(packet.pitchDegrees))
|
||||
wrapper.updateMatrix(matrix.peek().positionMatrix)
|
||||
val world = MinecraftClient.getInstance().world ?: return
|
||||
ParticleStorm(packet.effect, wrapper, world).spawn()
|
||||
val effect = BedrockParticleEffectRepository.getEffect(packet.effectId) ?: return
|
||||
ParticleStorm(effect, wrapper, world).spawn()
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.boat
|
||||
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatEntity
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.render.OverlayTexture
|
||||
import net.minecraft.client.render.RenderLayer
|
||||
import net.minecraft.client.render.VertexConsumerProvider
|
||||
import net.minecraft.client.render.entity.EntityRenderer
|
||||
import net.minecraft.client.render.entity.EntityRendererFactory
|
||||
import net.minecraft.client.render.entity.model.BoatEntityModel
|
||||
import net.minecraft.client.render.entity.model.ChestBoatEntityModel
|
||||
import net.minecraft.client.render.entity.model.EntityModelLayer
|
||||
import net.minecraft.client.util.math.MatrixStack
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.math.MathHelper
|
||||
import net.minecraft.util.math.RotationAxis
|
||||
import org.joml.Quaternionf
|
||||
|
||||
class CobblemonBoatRenderer(ctx: EntityRendererFactory.Context, private val hasChest: Boolean) : EntityRenderer<CobblemonBoatEntity>(ctx) {
|
||||
|
||||
private val boatModels = hashMapOf<CobblemonBoatType, Pair<Identifier, BoatEntityModel>>()
|
||||
|
||||
init {
|
||||
this.shadowRadius = 0.8F
|
||||
CobblemonBoatType.values().forEach { type ->
|
||||
this.boatModels[type] = generateTextureIdentifier(type, this.hasChest) to generateBoatModel(ctx, type, this.hasChest)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getTexture(entity: CobblemonBoatEntity): Identifier = this.boatModels[entity.boatType]!!.first
|
||||
|
||||
override fun render(entity: CobblemonBoatEntity, yaw: Float, tickDelta: Float, matrices: MatrixStack, vertexConsumers: VertexConsumerProvider, light: Int) {
|
||||
matrices.push()
|
||||
matrices.translate(0F, 0.375F, 0F)
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180F - yaw))
|
||||
val h = entity.damageWobbleTicks - tickDelta
|
||||
val j = (entity.damageWobbleStrength - tickDelta).coerceAtLeast(0F)
|
||||
if (h > 0F) {
|
||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(MathHelper.sin(h) * h * j / 10F * entity.damageWobbleSide))
|
||||
}
|
||||
val k = entity.interpolateBubbleWobble(tickDelta)
|
||||
if (!MathHelper.approximatelyEquals(k, 0F)) {
|
||||
matrices.multiply(Quaternionf().setAngleAxis(entity.interpolateBubbleWobble(tickDelta) * 0.017453292F, 1F, 0F, 1F))
|
||||
}
|
||||
val (identifier, entityModel) = this.boatModels[entity.boatType]!!
|
||||
matrices.scale(-1F, -1F, 1F)
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(90F))
|
||||
entityModel.setAngles(entity, tickDelta, 0F, -0.1F, 0F, 0F)
|
||||
val vertexConsumer = vertexConsumers.getBuffer(entityModel.getLayer(identifier))
|
||||
entityModel.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV, 1F, 1F, 1F, 1F)
|
||||
if (!entity.isSubmergedInWater) {
|
||||
val vertexConsumer2 = vertexConsumers.getBuffer(RenderLayer.getWaterMask())
|
||||
entityModel.waterPatch.render(matrices, vertexConsumer2, light, OverlayTexture.DEFAULT_UV)
|
||||
}
|
||||
matrices.pop()
|
||||
super.render(entity, yaw, tickDelta, matrices, vertexConsumers, light)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private fun generateTextureIdentifier(type: CobblemonBoatType, hasChest: Boolean): Identifier {
|
||||
val boatSubPath = if (hasChest) "chest_boat" else "boat"
|
||||
val path = "textures/entity/$boatSubPath/${type.name.lowercase()}.png"
|
||||
return cobblemonResource(path)
|
||||
}
|
||||
|
||||
private fun generateBoatModel(ctx: EntityRendererFactory.Context, type: CobblemonBoatType, hasChest: Boolean): BoatEntityModel {
|
||||
val modelLayer = this.createBoatModelLayer(type, hasChest)
|
||||
val modelPart = ctx.getPart(modelLayer)
|
||||
return if (hasChest) ChestBoatEntityModel(modelPart) else BoatEntityModel(modelPart)
|
||||
}
|
||||
|
||||
internal fun createBoatModelLayer(type: CobblemonBoatType, hasChest: Boolean): EntityModelLayer {
|
||||
val boatSubPath = if (hasChest) "chest_boat" else "boat"
|
||||
val path = "$boatSubPath/${type.name.lowercase()}"
|
||||
return EntityModelLayer(cobblemonResource(path), "main")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+8
-5
@@ -69,7 +69,7 @@ class PokemonOnShoulderRenderer<T : PlayerEntity>(renderLayerParent: FeatureRend
|
||||
matrixStack.push()
|
||||
val uuid = this.extractUuid(compoundTag)
|
||||
val cache = this.playerCache.getOrPut(livingEntity.uuid) { ShoulderCache() }
|
||||
val shoulderData: ShoulderData
|
||||
var shoulderData: ShoulderData? = null
|
||||
if (pLeftShoulder && cache.lastKnownLeft?.uuid != uuid) {
|
||||
shoulderData = this.extractData(compoundTag, uuid)
|
||||
cache.lastKnownLeft = shoulderData
|
||||
@@ -78,8 +78,9 @@ class PokemonOnShoulderRenderer<T : PlayerEntity>(renderLayerParent: FeatureRend
|
||||
shoulderData = this.extractData(compoundTag, uuid)
|
||||
cache.lastKnownRight = shoulderData
|
||||
}
|
||||
else {
|
||||
// should never be null but might as well be safe
|
||||
|
||||
if (shoulderData == null){
|
||||
// Could be null
|
||||
shoulderData = (if (pLeftShoulder) cache.lastKnownLeft else cache.lastKnownRight) ?: return
|
||||
}
|
||||
val scale = shoulderData.form.baseScale * shoulderData.scaleModifier
|
||||
@@ -136,13 +137,15 @@ class PokemonOnShoulderRenderer<T : PlayerEntity>(renderLayerParent: FeatureRend
|
||||
return shoulderNbt.getUuid(DataKeys.SHOULDER_UUID)
|
||||
}
|
||||
|
||||
private fun extractData(shoulderNbt: NbtCompound, pokemonUUID: UUID): ShoulderData {
|
||||
private fun extractData(shoulderNbt: NbtCompound, pokemonUUID: UUID): ShoulderData? {
|
||||
// To not crash with existing ones, this will still have the aspect issue
|
||||
if (!shoulderNbt.contains(DataKeys.SHOULDER_SPECIES)) {
|
||||
val pokemon = Pokemon().apply { isClient = true }.loadFromNBT(shoulderNbt.getCompound(DataKeys.POKEMON))
|
||||
return ShoulderData(pokemonUUID, pokemon.species, pokemon.form, pokemon.aspects, pokemon.scaleModifier)
|
||||
}
|
||||
val species = PokemonSpecies.getByIdentifier(Identifier(shoulderNbt.getString(DataKeys.SHOULDER_SPECIES)))!!
|
||||
val species = PokemonSpecies.getByIdentifier(Identifier(shoulderNbt.getString(DataKeys.SHOULDER_SPECIES)))
|
||||
?: return null
|
||||
|
||||
val formName = shoulderNbt.getString(DataKeys.SHOULDER_FORM)
|
||||
val form = species.forms.firstOrNull { it.name == formName } ?: species.standardForm
|
||||
val aspects = shoulderNbt.getList(DataKeys.SHOULDER_ASPECTS, NbtElement.STRING_TYPE.toInt()).map { it.asString() }.toSet()
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ import net.minecraft.client.model.ModelPart
|
||||
|
||||
class PokeBallModel(root: ModelPart) : PoseableEntityModel<EmptyPokeBallEntity>(), PokeBallFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("poke_ball")
|
||||
override val base = getPart("base")
|
||||
override val base = getPart("bottom")
|
||||
override val lid = getPart("lid")
|
||||
override val isForLivingEntityRenderer = false
|
||||
|
||||
|
||||
+2
@@ -97,6 +97,8 @@ abstract class PokemonPoseableModel : PoseableEntityModel<PokemonEntity>() {
|
||||
override fun setupEntityTypeContext(entity: PokemonEntity?) {
|
||||
entity?.let {
|
||||
context.put(RenderContext.SCALE, it.pokemon.form.baseScale)
|
||||
context.put(RenderContext.SPECIES, it.pokemon.species.resourceIdentifier)
|
||||
context.put(RenderContext.ASPECTS, it.pokemon.aspects)
|
||||
PokemonModelRepository.getTexture(it.pokemon.species.resourceIdentifier, it.pokemon.aspects, 0f).let { texture -> context.put(RenderContext.TEXTURE, texture) }
|
||||
}
|
||||
}
|
||||
|
||||
+37
-25
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen1
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.WingFlapIdleAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.asTransformed
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BiWingedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.TransformedModelPart
|
||||
@@ -23,44 +24,50 @@ import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class GolbatModel(root: ModelPart) : PokemonPoseableModel(), BiWingedFrame {
|
||||
class GolbatModel(root: ModelPart) : PokemonPoseableModel() {
|
||||
override val rootPart = root.registerChildWithAllChildren("golbat")
|
||||
override val leftWing = getPart("leftwing")
|
||||
override val rightWing = getPart("rightwing")
|
||||
|
||||
override val portraitScale = 1.55F
|
||||
override val portraitTranslation = Vec3d(0.0, -0.55, 0.0)
|
||||
override val portraitTranslation = Vec3d(-0.1, -0.1, 0.0)
|
||||
|
||||
override val profileScale = 0.9F
|
||||
override val profileTranslation = Vec3d(0.0, 0.4, 0.0)
|
||||
override val profileScale = 0.7F
|
||||
override val profileTranslation = Vec3d(0.0, 0.7, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
lateinit var hover: PokemonPose
|
||||
lateinit var fly: PokemonPose
|
||||
lateinit var battleidle: PokemonPose
|
||||
|
||||
// override val cryAnimation = CryProvider { _, _ -> bedrockStateful("golbat", "cry").setPreventsIdle(false) }
|
||||
|
||||
override fun registerPoses() {
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES - PoseType.HOVER,
|
||||
transformTicks = 10,
|
||||
idleAnimations = arrayOf(
|
||||
//bedrock("golbat", "ground_idle")
|
||||
)
|
||||
)
|
||||
val blink = quirk("blink") { bedrockStateful("golbat", "blink").setPreventsIdle(false) }
|
||||
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
idleAnimations = arrayOf(bedrock("golbat", "sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES - PoseType.HOVER,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
condition = { !it.isBattling },
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("golbat", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = MOVING_POSES - PoseType.FLY,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
//bedrock("golbat", "ground_walk")
|
||||
bedrock("golbat", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
@@ -68,12 +75,9 @@ class GolbatModel(root: ModelPart) : PokemonPoseableModel(), BiWingedFrame {
|
||||
poseName = "hover",
|
||||
poseType = PoseType.HOVER,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
WingFlapIdleAnimation(this,
|
||||
flapFunction = sineFunction(verticalShift = -10F.toRadians(), period = 0.9F, amplitude = 0.6F),
|
||||
timeVariable = { state, _, _ -> state?.animationSeconds ?: 0F },
|
||||
axis = TransformedModelPart.Y_AXIS
|
||||
)
|
||||
bedrock("golbat", "air_idle")
|
||||
)
|
||||
)
|
||||
|
||||
@@ -81,12 +85,20 @@ class GolbatModel(root: ModelPart) : PokemonPoseableModel(), BiWingedFrame {
|
||||
poseName = "fly",
|
||||
poseType = PoseType.FLY,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
WingFlapIdleAnimation(this,
|
||||
flapFunction = sineFunction(verticalShift = -14F.toRadians(), period = 0.9F, amplitude = 0.9F),
|
||||
timeVariable = { state, _, _ -> state?.animationSeconds ?: 0F },
|
||||
axis = TransformedModelPart.Y_AXIS
|
||||
)
|
||||
bedrock("golbat", "air_fly")
|
||||
)
|
||||
)
|
||||
|
||||
battleidle = registerPose(
|
||||
poseName = "battle_idle",
|
||||
poseTypes = PoseType.STATIONARY_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
condition = { it.isBattling },
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("golbat", "battle_idle")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
+8
-8
@@ -23,14 +23,14 @@ class GolemModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BipedFr
|
||||
override val rootPart = root.registerChildWithAllChildren("golem")
|
||||
override val head = getPart("head")
|
||||
|
||||
override val leftLeg = getPart("leg_left")
|
||||
override val rightLeg = getPart("leg_right")
|
||||
override val leftLeg = getPart("left_upper_leg")
|
||||
override val rightLeg = getPart("right_upper_leg")
|
||||
|
||||
override val portraitScale = 2.0F
|
||||
override val portraitTranslation = Vec3d(-0.55, -0.55, 0.0)
|
||||
override val portraitScale = 1.7F
|
||||
override val portraitTranslation = Vec3d(-0.6, -0.25, 0.0)
|
||||
|
||||
override val profileScale = 0.88F
|
||||
override val profileTranslation = Vec3d(0.0, 0.42, 0.0)
|
||||
override val profileScale = 0.75F
|
||||
override val profileTranslation = Vec3d(0.0, 0.55, 0.0)
|
||||
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
@@ -43,7 +43,7 @@ class GolemModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BipedFr
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("golem", "ground_idle")
|
||||
bedrock("golem", "test")
|
||||
)
|
||||
)
|
||||
|
||||
@@ -54,7 +54,7 @@ class GolemModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BipedFr
|
||||
idleAnimations = arrayOf(
|
||||
BipedWalkAnimation(this, periodMultiplier = 1.2F, amplitudeMultiplier = 0.9f),
|
||||
singleBoneLook(),
|
||||
bedrock("golem", "ground_idle")
|
||||
bedrock("golem", "test")
|
||||
//bedrock("golem", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
-1
@@ -37,7 +37,6 @@ class KadabraModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Biped
|
||||
override val profileScale = 0.75F
|
||||
override val profileTranslation = Vec3d(0.0, 0.6, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
lateinit var battleidle: PokemonPose
|
||||
|
||||
+88
-45
@@ -10,11 +10,14 @@ package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen1
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.EarJoint
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.RangeOfMotion
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.WingFlapIdleAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.asTransformed
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BiWingedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.EaredFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.TransformedModelPart
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.TransformedModelPart.Companion.X_AXIS
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.TransformedModelPart.Companion.Y_AXIS
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.TransformedModelPart.Companion.Z_AXIS
|
||||
@@ -27,81 +30,121 @@ import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.MathConstants.PI
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class ZubatModel(root: ModelPart) : PokemonPoseableModel(), BiWingedFrame, EaredFrame {
|
||||
class ZubatModel(root: ModelPart) : PokemonPoseableModel() {
|
||||
override val rootPart = root.registerChildWithAllChildren("zubat")
|
||||
|
||||
override val leftWing = getPart("leftwing")
|
||||
override val rightWing = getPart("rightwing")
|
||||
val wings_folded = getPart("wings_folded")
|
||||
val wings_open = getPart("wings_open")
|
||||
|
||||
private val leftEar = getPart("leftear")
|
||||
private val rightEar = getPart("rightear")
|
||||
override val leftEarJoint = EarJoint(leftEar, Z_AXIS, RangeOfMotion(70F.toRadians(), 40F.toRadians()))
|
||||
override val rightEarJoint = EarJoint(rightEar, Z_AXIS, RangeOfMotion((-70F).toRadians(), (-40F).toRadians()))
|
||||
override val portraitScale = 1.7F
|
||||
override val portraitTranslation = Vec3d(0.0, 0.0, 0.0)
|
||||
|
||||
override val portraitScale = 2.3F
|
||||
override val portraitTranslation = Vec3d(0.0, -0.5, 0.0)
|
||||
override val profileScale = 1.0F
|
||||
override val profileTranslation = Vec3d(0.0, 0.36, 0.0)
|
||||
override val profileScale = 0.7F
|
||||
override val profileTranslation = Vec3d(0.0, 0.7, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
lateinit var hover: PokemonPose
|
||||
lateinit var fly: PokemonPose
|
||||
lateinit var shoulderLeft: PokemonPose
|
||||
lateinit var shoulderRight: PokemonPose
|
||||
|
||||
val shoulderOffset = 0
|
||||
|
||||
override val cryAnimation = CryProvider { _, _ -> bedrockStateful("zubat", "cry").setPreventsIdle(false) }
|
||||
|
||||
override fun registerPoses() {
|
||||
val twitch = quirk("twitch") { bedrockStateful("zubat", "eartwitch").setPreventsIdle(false) }
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
transformedParts = arrayOf(
|
||||
wings_folded.asTransformed().withVisibility(visibility = false),
|
||||
wings_open.asTransformed().withVisibility(visibility = true),
|
||||
),
|
||||
quirks = arrayOf(twitch),
|
||||
idleAnimations = arrayOf(bedrock("zubat", "sleep"))
|
||||
)
|
||||
|
||||
registerPose(
|
||||
poseName = "hover",
|
||||
poseTypes = ALL_POSES - SHOULDER_POSES - PoseType.FLY - PoseType.SLEEP,
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES - PoseType.HOVER,
|
||||
transformedParts = arrayOf(
|
||||
wings_folded.asTransformed().withVisibility(visibility = false),
|
||||
wings_open.asTransformed().withVisibility(visibility = true),
|
||||
),
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(twitch),
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("zubat", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
registerPose(
|
||||
poseName = "fly",
|
||||
poseType = PoseType.FLY,
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = PoseType.MOVING_POSES - PoseType.FLY,
|
||||
transformedParts = arrayOf(
|
||||
wings_folded.asTransformed().withVisibility(visibility = false),
|
||||
wings_open.asTransformed().withVisibility(visibility = true),
|
||||
),
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(twitch),
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("zubat", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
registerPose(
|
||||
poseType = PoseType.SHOULDER_LEFT,
|
||||
idleAnimations = arrayOf(
|
||||
leftWing.rotation(
|
||||
function = sineFunction(
|
||||
amplitude = PI / 3,
|
||||
period = 1F
|
||||
),
|
||||
axis = Z_AXIS,
|
||||
timeVariable = { _, _, ageInTicks -> ageInTicks / 20 },
|
||||
)
|
||||
),
|
||||
hover = registerPose(
|
||||
poseName = "hover",
|
||||
poseType = PoseType.HOVER,
|
||||
transformedParts = arrayOf(
|
||||
rootPart.asTransformed().addRotation(X_AXIS, PI / 9).addPosition(Y_AXIS, 4F).addPosition(Z_AXIS, 3F),
|
||||
leftWing.asTransformed().addRotation(X_AXIS, PI / 3),
|
||||
rightWing.asTransformed().addRotation(X_AXIS, PI / 3).addRotation(Z_AXIS, -PI / 2)
|
||||
wings_folded.asTransformed().withVisibility(visibility = false),
|
||||
wings_open.asTransformed().withVisibility(visibility = true),
|
||||
),
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(twitch),
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("zubat", "air_idle")
|
||||
)
|
||||
)
|
||||
registerPose(
|
||||
poseType = PoseType.SHOULDER_RIGHT,
|
||||
|
||||
fly = registerPose(
|
||||
poseName = "fly",
|
||||
poseType = PoseType.FLY,
|
||||
transformedParts = arrayOf(
|
||||
wings_folded.asTransformed().withVisibility(visibility = false),
|
||||
wings_open.asTransformed().withVisibility(visibility = true),
|
||||
),
|
||||
quirks = arrayOf(twitch),
|
||||
transformTicks = 10,
|
||||
idleAnimations = arrayOf(
|
||||
rightWing.rotation(
|
||||
function = sineFunction(
|
||||
amplitude = PI / 3,
|
||||
period = 1F
|
||||
),
|
||||
axis = Z_AXIS,
|
||||
timeVariable = { _, _, ageInTicks -> ageInTicks / 20 },
|
||||
)
|
||||
bedrock("zubat", "air_fly")
|
||||
)
|
||||
)
|
||||
|
||||
shoulderLeft = registerPose(
|
||||
poseType = PoseType.SHOULDER_LEFT,
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("zubat", "shoulder_left")
|
||||
),
|
||||
transformedParts = arrayOf(
|
||||
rootPart.asTransformed().addRotation(X_AXIS, PI / 9).addPosition(Y_AXIS, 4F).addPosition(Z_AXIS, 3F),
|
||||
leftWing.asTransformed().addRotation(X_AXIS, PI / 3).addRotation(Z_AXIS, PI / 2),
|
||||
rightWing.asTransformed().addRotation(X_AXIS, PI / 3)
|
||||
rootPart.asTransformed().addPosition(TransformedModelPart.X_AXIS, shoulderOffset)
|
||||
)
|
||||
)
|
||||
|
||||
shoulderRight = registerPose(
|
||||
poseType = PoseType.SHOULDER_RIGHT,
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("zubat", "shoulder_right")
|
||||
),
|
||||
transformedParts = arrayOf(
|
||||
rootPart.asTransformed().addPosition(TransformedModelPart.X_AXIS, -shoulderOffset)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PoseableEntityState<PokemonEntity>
|
||||
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("zubat", "faint") else null
|
||||
}
|
||||
+36
-21
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen2
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.WingFlapIdleAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BiWingedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.TransformedModelPart
|
||||
@@ -19,26 +20,37 @@ import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class CrobatModel(root: ModelPart) : PokemonPoseableModel(), BiWingedFrame {
|
||||
class CrobatModel(root: ModelPart) : PokemonPoseableModel() {
|
||||
override val rootPart = root.registerChildWithAllChildren("crobat")
|
||||
override val leftWing = getPart("leftwings")
|
||||
override val rightWing = getPart("rightwings")
|
||||
|
||||
override val portraitScale = 1.8F
|
||||
override val portraitTranslation = Vec3d(-0.11, -0.77, 0.0)
|
||||
override val portraitScale = 1.2F
|
||||
override val portraitTranslation = Vec3d(-0.1, 1.8, 0.0)
|
||||
|
||||
override val profileScale = 0.9F
|
||||
override val profileTranslation = Vec3d(0.0, 0.35, 0.0)
|
||||
override val profileScale = 0.5F
|
||||
override val profileTranslation = Vec3d(0.0, 1.2, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
lateinit var hover: PokemonPose
|
||||
lateinit var fly: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
lateinit var battleidle: PokemonPose
|
||||
|
||||
override val cryAnimation = CryProvider { _, _ -> bedrockStateful("crobat", "cry").setPreventsIdle(false) }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk("blink") { bedrockStateful("crobat", "blink").setPreventsIdle(false) }
|
||||
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
idleAnimations = arrayOf(bedrock("crobat", "sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseType = PoseType.STAND,
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES - PoseType.HOVER,
|
||||
condition = { !it.isBattling },
|
||||
transformTicks = 10,
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("crobat", "ground_idle")
|
||||
)
|
||||
@@ -57,13 +69,9 @@ class CrobatModel(root: ModelPart) : PokemonPoseableModel(), BiWingedFrame {
|
||||
poseName = "hover",
|
||||
poseType = PoseType.HOVER,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("crobat", "ground_idle"),
|
||||
WingFlapIdleAnimation(this,
|
||||
flapFunction = sineFunction(verticalShift = -10F.toRadians(), period = 0.9F, amplitude = 0.6F),
|
||||
timeVariable = { state, _, _ -> state?.animationSeconds ?: 0F },
|
||||
axis = TransformedModelPart.Y_AXIS
|
||||
)
|
||||
bedrock("crobat", "air_idle")
|
||||
)
|
||||
)
|
||||
|
||||
@@ -71,13 +79,20 @@ class CrobatModel(root: ModelPart) : PokemonPoseableModel(), BiWingedFrame {
|
||||
poseName = "fly",
|
||||
poseType = PoseType.FLY,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("crobat", "ground_walk"),
|
||||
WingFlapIdleAnimation(this,
|
||||
flapFunction = sineFunction(verticalShift = -14F.toRadians(), period = 0.9F, amplitude = 0.9F),
|
||||
timeVariable = { state, _, _ -> state?.animationSeconds ?: 0F },
|
||||
axis = TransformedModelPart.Y_AXIS
|
||||
)
|
||||
bedrock("crobat", "air_fly")
|
||||
)
|
||||
)
|
||||
|
||||
battleidle = registerPose(
|
||||
poseName = "battle_idle",
|
||||
poseTypes = PoseType.STATIONARY_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
condition = { it.isBattling },
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("crobat", "battle_idle")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
+38
-17
@@ -8,42 +8,53 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen2
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BimanualSwingAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BipedWalkAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.asTransformed
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BimanualFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.TransformedModelPart
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class HitmontopModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BipedFrame, BimanualFrame {
|
||||
class HitmontopModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("hitmontop")
|
||||
override val head = getPart("head")
|
||||
|
||||
override val leftArm = getPart("arm_left")
|
||||
override val rightArm = getPart("arm_right")
|
||||
override val leftLeg = getPart("leg_left")
|
||||
override val rightLeg = getPart("leg_right")
|
||||
|
||||
override val portraitScale = 2.6F
|
||||
override val portraitTranslation = Vec3d(-0.26, -0.5, 0.0)
|
||||
|
||||
override val profileScale = 0.91F
|
||||
override val profileTranslation = Vec3d(0.0, 0.4, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
lateinit var battleidle: PokemonPose
|
||||
|
||||
// override val cryAnimation = CryProvider { _, _ -> bedrockStateful("hitmontop", "cry").setPreventsIdle(false) }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk("blink") { bedrockStateful("hitmontop", "blink").setPreventsIdle(false)}
|
||||
val blink = quirk("blink") { bedrockStateful("hitmontop", "blink").setPreventsIdle(false) }
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
idleAnimations = arrayOf(bedrock("hitmontop", "sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
transformTicks = 10,
|
||||
condition = { !it.isBattling },
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
@@ -53,19 +64,29 @@ class HitmontopModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bip
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = MOVING_POSES,
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("hitmontop", "ground_idle"),
|
||||
BipedWalkAnimation(this, periodMultiplier = 0.6F, amplitudeMultiplier = 0.9F),
|
||||
BimanualSwingAnimation(this, swingPeriodMultiplier = 0.6F, amplitudeMultiplier = 0.9F)
|
||||
bedrock("hitmontop", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
battleidle = registerPose(
|
||||
poseName = "battle_idle",
|
||||
poseTypes = PoseType.STATIONARY_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
condition = { it.isBattling },
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("hitmontop", "battle_idle")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PoseableEntityState<PokemonEntity>
|
||||
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("hitmontop", "faint") else null
|
||||
override fun getFaintAnimation(
|
||||
pokemonEntity: PokemonEntity,
|
||||
state: PoseableEntityState<PokemonEntity>
|
||||
) = bedrockStateful("hitmontop", "faint")
|
||||
}
|
||||
+70
-17
@@ -8,42 +8,59 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen2
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BimanualSwingAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BipedWalkAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.asTransformed
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BimanualFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.QuadrupedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.TransformedModelPart
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class TyrogueModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BipedFrame, BimanualFrame {
|
||||
class TyrogueModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("tyrogue")
|
||||
override val head = getPart("head")
|
||||
|
||||
override val leftArm = getPart("arm_left")
|
||||
override val rightArm = getPart("arm_right")
|
||||
override val leftLeg = getPart("leg_left")
|
||||
override val rightLeg = getPart("leg_right")
|
||||
|
||||
override val portraitScale = 2.56F
|
||||
override val portraitTranslation = Vec3d(-0.24, 0.1, 0.0)
|
||||
|
||||
override val profileScale = 0.73F
|
||||
override val profileTranslation = Vec3d(-0.03, 0.7, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
lateinit var shoulderLeft: PokemonPose
|
||||
lateinit var shoulderRight: PokemonPose
|
||||
lateinit var battleidle: PokemonPose
|
||||
|
||||
val shoulderOffset = 3
|
||||
|
||||
// override val cryAnimation = CryProvider { _, _ -> bedrockStateful("tyrogue", "cry").setPreventsIdle(false) }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk("blink") { bedrockStateful("tyrogue", "blink").setPreventsIdle(false)}
|
||||
val blink = quirk("blink") { bedrockStateful("tyrogue", "blink").setPreventsIdle(false) }
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
idleAnimations = arrayOf(bedrock("tyrogue", "sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
transformTicks = 10,
|
||||
condition = { !it.isBattling },
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
@@ -53,19 +70,55 @@ class TyrogueModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Biped
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = MOVING_POSES,
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("tyrogue", "ground_idle"),
|
||||
BipedWalkAnimation(this, periodMultiplier = 0.6F, amplitudeMultiplier = 0.9F),
|
||||
BimanualSwingAnimation(this, swingPeriodMultiplier = 0.6F, amplitudeMultiplier = 0.9F)
|
||||
bedrock("tyrogue", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
battleidle = registerPose(
|
||||
poseName = "battle_idle",
|
||||
poseTypes = PoseType.STATIONARY_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
condition = { it.isBattling },
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("tyrogue", "battle_idle")
|
||||
)
|
||||
)
|
||||
|
||||
shoulderLeft = registerPose(
|
||||
poseType = PoseType.SHOULDER_LEFT,
|
||||
quirks = arrayOf(blink),
|
||||
condition = { !it.isBattling },
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("tyrogue", "shoulder_left")
|
||||
),
|
||||
transformedParts = arrayOf(
|
||||
rootPart.asTransformed().addPosition(TransformedModelPart.X_AXIS, shoulderOffset)
|
||||
)
|
||||
)
|
||||
|
||||
shoulderRight = registerPose(
|
||||
poseType = PoseType.SHOULDER_RIGHT,
|
||||
quirks = arrayOf(blink),
|
||||
condition = { !it.isBattling },
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("tyrogue", "shoulder_right")
|
||||
),
|
||||
transformedParts = arrayOf(
|
||||
rootPart.asTransformed().addPosition(TransformedModelPart.X_AXIS, -shoulderOffset)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PoseableEntityState<PokemonEntity>
|
||||
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("tyrogue", "faint") else null
|
||||
override fun getFaintAnimation(
|
||||
pokemonEntity: PokemonEntity,
|
||||
state: PoseableEntityState<PokemonEntity>
|
||||
) = if (state.isPosedIn(standing, walk, battleidle, sleep)) bedrockStateful("tyrogue", "faint") else null
|
||||
}
|
||||
+3
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.client.render.models.blockbench.animation.BipedW
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BimanualFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
@@ -35,6 +36,8 @@ class BeldumModel (root: ModelPart) : PokemonPoseableModel() {
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var battleidle: PokemonPose
|
||||
|
||||
override val cryAnimation = CryProvider { _, _ -> bedrockStateful("beldum", "cry").setPreventsIdle(false) }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk("blink") { bedrockStateful("beldum", "blink").setPreventsIdle(false)}
|
||||
val quirk = quirk("quirk") { bedrockStateful("beldum", "quirk_spin").setPreventsIdle(false)}
|
||||
|
||||
+3
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen3
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
@@ -30,6 +31,8 @@ class MetagrossModel (root: ModelPart) : PokemonPoseableModel() {
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var battleidle: PokemonPose
|
||||
|
||||
override val cryAnimation = CryProvider { _, _ -> bedrockStateful("metagross", "cry").setPreventsIdle(false) }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk("blink") { bedrockStateful("metagross", "blink").setPreventsIdle(false)}
|
||||
|
||||
|
||||
+3
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen3
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
@@ -30,6 +31,8 @@ class MetangModel (root: ModelPart) : PokemonPoseableModel() {
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var battleidle: PokemonPose
|
||||
|
||||
override val cryAnimation = CryProvider { _, _ -> bedrockStateful("metang", "cry").setPreventsIdle(false) }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk("blink") { bedrockStateful("metang", "blink").setPreventsIdle(false)}
|
||||
|
||||
|
||||
+40
-17
@@ -8,64 +8,87 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen3
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.QuadrupedWalkAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.QuadrupedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class MightyenaModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, QuadrupedFrame {
|
||||
class MightyenaModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("mightyena")
|
||||
override val head = getPart("head")
|
||||
|
||||
override val hindLeftLeg = getPart("leg_left")
|
||||
override val hindRightLeg = getPart("leg_right")
|
||||
override val foreLeftLeg = getPart("arm_left")
|
||||
override val foreRightLeg = getPart("arm_right")
|
||||
|
||||
override val portraitScale = 2.2F
|
||||
override val portraitTranslation = Vec3d(-0.8, 0.6, 0.0)
|
||||
|
||||
override val profileScale = 0.6F
|
||||
override val profileTranslation = Vec3d(0.0, 0.8, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
lateinit var battleidle: PokemonPose
|
||||
|
||||
override val cryAnimation = CryProvider { _, _ -> bedrockStateful("mightyena", "cry").setPreventsIdle(false) }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk("blink") { bedrockStateful("mightyena", "blink").setPreventsIdle(false) }
|
||||
val laugh_out_battle = quirk("laugh_out_battle", secondsBetweenOccurrences = 120F to 240F) { bedrockStateful("mightyena", "quirk").setPreventsIdle(false) }
|
||||
val laugh_in_battle = quirk("laugh_in_battle", secondsBetweenOccurrences = 30F to 60F) { bedrockStateful("mightyena", "quirk").setPreventsIdle(false) }
|
||||
val sleep_quirk = quirk("sleep_quirk", secondsBetweenOccurrences = 30F to 60F) { bedrockStateful("mightyena", "sleep_quirk").setPreventsIdle(false) }
|
||||
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
quirks = arrayOf(sleep_quirk),
|
||||
idleAnimations = arrayOf(bedrock("mightyena", "sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = UI_POSES + STATIONARY_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
transformTicks = 10,
|
||||
condition = { !it.isBattling },
|
||||
quirks = arrayOf(blink,laugh_out_battle),
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("mightyena","ground_idle")
|
||||
bedrock("mightyena", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = MOVING_POSES,
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
QuadrupedWalkAnimation(this, periodMultiplier = 0.8F, amplitudeMultiplier = 0.8F),
|
||||
bedrock("mightyena","ground_idle")
|
||||
bedrock("mightyena", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
battleidle = registerPose(
|
||||
poseName = "battle_idle",
|
||||
poseTypes = PoseType.STATIONARY_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink,laugh_in_battle),
|
||||
condition = { it.isBattling },
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("mightyena", "battle_idle")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PoseableEntityState<PokemonEntity>
|
||||
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("mightyena", "faint") else null
|
||||
override fun getFaintAnimation(
|
||||
pokemonEntity: PokemonEntity,
|
||||
state: PoseableEntityState<PokemonEntity>
|
||||
) = bedrockStateful("mightyena", "faint")
|
||||
}
|
||||
+1
-1
@@ -49,7 +49,7 @@ class ShroomishModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bip
|
||||
poseName = "standing",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
condition = { it.isBattling },
|
||||
condition = { !it.isBattling },
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("shroomish", "ground_idle")
|
||||
|
||||
-2
@@ -68,7 +68,6 @@ class VolbeatModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bipe
|
||||
poseTypes = setOf(PoseType.HOVER, PoseType.FLOAT),
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
condition = { it.isTouchingWater },
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("volbeat", "air_idle")
|
||||
@@ -80,7 +79,6 @@ class VolbeatModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bipe
|
||||
poseTypes = setOf(PoseType.FLY, PoseType.SWIM),
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
condition = { it.isTouchingWater },
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("volbeat", "air_fly")
|
||||
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen4
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class DrifblimModel (root: ModelPart) : PokemonPoseableModel() {
|
||||
override val rootPart = root.registerChildWithAllChildren("drifblim")
|
||||
|
||||
override val portraitScale = 0.9F
|
||||
override val portraitTranslation = Vec3d(-0.35, 1.8, 0.0)
|
||||
|
||||
override val profileScale = 0.4F
|
||||
override val profileTranslation = Vec3d(0.0, 1.1, 0.0)
|
||||
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
lateinit var sleep: PokemonPose
|
||||
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk(name = "blink") { bedrockStateful("drifblim", "blink").setPreventsIdle(false) }
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("drifblim", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
transformTicks = 10,
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("drifblim", "ground_idle")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PoseableEntityState<PokemonEntity>
|
||||
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("drifblim", "faint") else null
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen4
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class DrifloonModel (root: ModelPart) : PokemonPoseableModel() {
|
||||
override val rootPart = root.registerChildWithAllChildren("drifloon")
|
||||
|
||||
override val portraitScale = 1.5F
|
||||
override val portraitTranslation = Vec3d(-0.1, 1.2, 0.0)
|
||||
|
||||
override val profileScale = 0.5F
|
||||
override val profileTranslation = Vec3d(0.0, 0.9, 0.0)
|
||||
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
lateinit var sleep: PokemonPose
|
||||
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk(name = "blink") { bedrockStateful("drifloon", "blink").setPreventsIdle(false) }
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("drifloon", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
transformTicks = 10,
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("drifloon", "ground_idle")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PoseableEntityState<PokemonEntity>
|
||||
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("drifloon", "faint") else null
|
||||
}
|
||||
+36
@@ -8,12 +8,16 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen4
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.asTransformed
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.QuadrupedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.TransformedModelPart
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
@@ -34,6 +38,10 @@ class TurtwigModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Quad
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
lateinit var shoulderLeft: PokemonPose
|
||||
lateinit var shoulderRight: PokemonPose
|
||||
|
||||
val shoulderOffset = 3
|
||||
|
||||
override val cryAnimation = CryProvider { _, _ -> bedrockStateful("turtwig", "cry").setPreventsIdle(false) }
|
||||
|
||||
@@ -65,5 +73,33 @@ class TurtwigModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Quad
|
||||
bedrock("turtwig", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
shoulderLeft = registerPose(
|
||||
poseType = PoseType.SHOULDER_LEFT,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("turtwig", "shoulder_left")
|
||||
),
|
||||
transformedParts = arrayOf(
|
||||
rootPart.asTransformed().addPosition(TransformedModelPart.X_AXIS, shoulderOffset)
|
||||
)
|
||||
)
|
||||
|
||||
shoulderRight = registerPose(
|
||||
poseType = PoseType.SHOULDER_RIGHT,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("turtwig", "shoulder_right")
|
||||
),
|
||||
transformedParts = arrayOf(
|
||||
rootPart.asTransformed().addPosition(TransformedModelPart.X_AXIS, -shoulderOffset)
|
||||
)
|
||||
)
|
||||
}
|
||||
override fun getFaintAnimation(
|
||||
pokemonEntity: PokemonEntity,
|
||||
state: PoseableEntityState<PokemonEntity>
|
||||
) = bedrockStateful("turtwig", "faint")
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen5
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class ChandelureModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("chandelure")
|
||||
override val head = getPart("head")
|
||||
|
||||
override val portraitScale = 2.0F
|
||||
override val portraitTranslation = Vec3d(-0.3, -1.2, 0.0)
|
||||
|
||||
override val profileScale = 0.8F
|
||||
override val profileTranslation = Vec3d(0.0, 0.5, 0.0)
|
||||
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
|
||||
override fun registerPoses() {
|
||||
// val blink = quirk("blink") { bedrockStateful("chandelure", "blink").setPreventsIdle(false) }
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
// quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("chandelure", "idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
// quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("chandelure", "idle")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PoseableEntityState<PokemonEntity>
|
||||
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("chandelure", "faint") else null
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen5
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class LampentModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("lampent")
|
||||
override val head = getPart("head")
|
||||
|
||||
override val portraitScale = 2.0F
|
||||
override val portraitTranslation = Vec3d(-0.3, -1.2, 0.0)
|
||||
|
||||
override val profileScale = 0.8F
|
||||
override val profileTranslation = Vec3d(0.0, 0.5, 0.0)
|
||||
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk("blink") { bedrockStateful("lampent", "blink").setPreventsIdle(false) }
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("lampent", "idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("lampent", "idle")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PoseableEntityState<PokemonEntity>
|
||||
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("lampent", "faint") else null
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen5
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class LitwickModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("litwick")
|
||||
override val head = getPart("head")
|
||||
|
||||
override val portraitScale = 2.0F
|
||||
override val portraitTranslation = Vec3d(-0.3, -1.2, 0.0)
|
||||
|
||||
override val profileScale = 0.8F
|
||||
override val profileTranslation = Vec3d(0.0, 0.5, 0.0)
|
||||
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk("blink") { bedrockStateful("litwick", "blink").setPreventsIdle(false) }
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("litwick", "idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("litwick", "idle")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PoseableEntityState<PokemonEntity>
|
||||
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("litwick", "faint") else null
|
||||
}
|
||||
+3
-2
@@ -41,9 +41,10 @@ class TrevenantModel (root: ModelPart) : PokemonPoseableModel() {
|
||||
poseType = PoseType.SLEEP,
|
||||
idleAnimations = arrayOf(bedrock("trevenant", "sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "stand",
|
||||
poseTypes = PoseType.STATIONARY_POSES - PoseType.HOVER - PoseType.FLOAT + PoseType.UI_POSES,
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
condition = { !it.isBattling },
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
@@ -53,7 +54,7 @@ class TrevenantModel (root: ModelPart) : PokemonPoseableModel() {
|
||||
)
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = PoseType.MOVING_POSES - PoseType.FLY - PoseType.SWIM,
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
transformTicks = 5,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
|
||||
-1
@@ -25,7 +25,6 @@ class KomalaModel (root: ModelPart) : PokemonPoseableModel() {
|
||||
override val profileScale = 0.8F
|
||||
override val profileTranslation = Vec3d(0.0, 0.5, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
|
||||
// override val cryAnimation = CryProvider { _, _ -> bedrockStateful("komala", "cry").setPreventsIdle(false) }
|
||||
|
||||
+1
-1
@@ -62,5 +62,5 @@ class EiscueModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override fun getFaintAnimation(
|
||||
pokemonEntity: PokemonEntity,
|
||||
state: PoseableEntityState<PokemonEntity>
|
||||
) = if (state.isPosedIn(standing, walk, sleep)) bedrockStateful("eiscue_ice", "faint") else null
|
||||
) = bedrockStateful("eiscue_ice", "faint")
|
||||
}
|
||||
+3
@@ -14,6 +14,7 @@ import com.cobblemon.mod.common.client.render.models.blockbench.animation.BipedW
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BimanualFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
@@ -37,6 +38,8 @@ class QuaxwellModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var battleidle: PokemonPose
|
||||
|
||||
override val cryAnimation = CryProvider { _, _ -> bedrockStateful("quaxwell", "cry").setPreventsIdle(false) }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk("blink") { bedrockStateful("quaxwell", "blink").setPreventsIdle(false) }
|
||||
sleep = registerPose(
|
||||
|
||||
Loaded 100 of 1157 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user