forked from mirrors/cobblemon
Compare commits
420
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1dcede488 | ||
|
|
aaec9ea397 | ||
|
|
5011607415 | ||
|
|
580b0f2ccf | ||
|
|
fcd3951815 | ||
|
|
5caa6d5950 | ||
|
|
352ac4e15d | ||
|
|
e6d35e709e | ||
|
|
83cfcdce43 | ||
|
|
96ae28ea91 | ||
|
|
062fd2451a | ||
|
|
235de329ee | ||
|
|
aede012933 | ||
|
|
1613cd281d | ||
|
|
706fcc8ca4 | ||
|
|
5568bb6a95 | ||
|
|
d5f22e7394 | ||
|
|
0dc8456623 | ||
|
|
f5228db99f | ||
|
|
de8ebc9fcb | ||
|
|
093e0f2811 | ||
|
|
1a782e4185 | ||
|
|
2e054dd5e1 | ||
|
|
5e47102c10 | ||
|
|
e56a7d5325 | ||
|
|
9b8261d23b | ||
|
|
e1705056f2 | ||
|
|
76db87d9a5 | ||
|
|
780d9ece59 | ||
|
|
4b55783785 | ||
|
|
e3fca67d52 | ||
|
|
932cdaaad3 | ||
|
|
e3f9937e78 | ||
|
|
5b46d04c27 | ||
|
|
c23aeaba78 | ||
|
|
ecff621084 | ||
|
|
83ce63325d | ||
|
|
4f33612bbb | ||
|
|
4624faf63e | ||
|
|
187674afb6 | ||
|
|
fe5cf5a7d8 | ||
|
|
3b3219ba69 | ||
|
|
0e98b07b7b | ||
|
|
57d380e18f | ||
|
|
086cdcdbd1 | ||
|
|
2b796f7e4c | ||
|
|
b7d1f9bb2d | ||
|
|
ba0f0657b2 | ||
|
|
8f59ec871f | ||
|
|
b3d4306165 | ||
|
|
20ddab8722 | ||
|
|
5327ff54b5 | ||
|
|
b5f8181118 | ||
|
|
64b164bfca | ||
|
|
93cb0f40f3 | ||
|
|
20a56b1ff0 | ||
|
|
97dd08c35d | ||
|
|
25c64841fe | ||
|
|
dc5f616c90 | ||
|
|
ff9033f6c4 | ||
|
|
9f937f6b3b | ||
|
|
c5c6bc340a | ||
|
|
90c7e5ab61 | ||
|
|
b3028dc45d | ||
|
|
f64b9e2fe7 | ||
|
|
1e7ffedd36 | ||
|
|
e4fab76f0b | ||
|
|
5a7b186478 | ||
|
|
79d30f4fa5 | ||
|
|
56dab6c18b | ||
|
|
6546a5ae05 | ||
|
|
57c243bd34 | ||
|
|
f2cd3fc435 | ||
|
|
9b75b1fb93 | ||
|
|
81f4b6e680 | ||
|
|
de783b6948 | ||
|
|
53c6f707e6 | ||
|
|
23142c6ece | ||
|
|
1fa3170355 | ||
|
|
9025b7b825 | ||
|
|
1487ae1036 | ||
|
|
dab1240d19 | ||
|
|
feb6622762 | ||
|
|
3c4e1c59b1 | ||
|
|
3cd30681d7 | ||
|
|
308a4e9c06 | ||
|
|
34cc6da0a9 | ||
|
|
6f1b7edca4 | ||
|
|
fdc7a3d61a | ||
|
|
9798ba28ec | ||
|
|
c8522488be | ||
|
|
f951e93875 | ||
|
|
d51c623168 | ||
|
|
fe57312d4f | ||
|
|
ee148954c0 | ||
|
|
6ffc7d45c3 | ||
|
|
a0301c85e8 | ||
|
|
6928b9a017 | ||
|
|
ce0d32a857 | ||
|
|
717e861c1d | ||
|
|
541dd1e284 | ||
|
|
f68384a505 | ||
|
|
f406e6da6b | ||
|
|
c75c5e4901 | ||
|
|
b4aedf9ec9 | ||
|
|
cba00fba13 | ||
|
|
90403d111b | ||
|
|
47460ef884 | ||
|
|
e48d44c6e6 | ||
|
|
8e522e3dd2 | ||
|
|
d9e0429ff4 | ||
|
|
bd35fc3c9a | ||
|
|
80d882a437 | ||
|
|
610f9dccc1 | ||
|
|
bddb5b9f40 | ||
|
|
84fc94cf4b | ||
|
|
e1186ebf2b | ||
|
|
e56a778246 | ||
|
|
a2d89f320f | ||
|
|
7e11c4d47b | ||
|
|
cc70fd18d5 | ||
|
|
334b47a778 | ||
|
|
a0c6ec7918 | ||
|
|
665883474d | ||
|
|
e0fce5386e | ||
|
|
d00829e609 | ||
|
|
de5b1e33fe | ||
|
|
f2e6ca1439 | ||
|
|
974bf73516 | ||
|
|
3c8fe3bff7 | ||
|
|
795a14a291 | ||
|
|
0dca4a26e5 | ||
|
|
edb98ae078 | ||
|
|
02ba40facb | ||
|
|
6fc87fdafd | ||
|
|
d430498243 | ||
|
|
2a17f76869 | ||
|
|
d5adfb70ea | ||
|
|
23b422bed6 | ||
|
|
f346b8db0c | ||
|
|
a951bd8d25 | ||
|
|
0d7ff74bd2 | ||
|
|
a36b832826 | ||
|
|
055583de1d | ||
|
|
63f2c49606 | ||
|
|
ff879f488e | ||
|
|
0942553bb7 | ||
|
|
ac7d2f6075 | ||
|
|
f1fcf60924 | ||
|
|
1d460555af | ||
|
|
904dcb61b0 | ||
|
|
b038841242 | ||
|
|
7efa155b51 | ||
|
|
07cef9c683 | ||
|
|
85b836ee28 | ||
|
|
74222fe727 | ||
|
|
a30dacb4be | ||
|
|
66473d9b47 | ||
|
|
0764a932e1 | ||
|
|
a227ef1001 | ||
|
|
d568644155 | ||
|
|
2d13b85488 | ||
|
|
a2edfcfdcb | ||
|
|
63ab04d3d8 | ||
|
|
34a8badd6f | ||
|
|
0f41194d22 | ||
|
|
54cb857224 | ||
|
|
36b1e926a9 | ||
|
|
b80b27e8f9 | ||
|
|
755ca9d261 | ||
|
|
24f64da512 | ||
|
|
b11f553af0 | ||
|
|
bce33acbc5 | ||
|
|
a42b88f22f | ||
|
|
fe7d3a51f9 | ||
|
|
c260594865 | ||
|
|
89a25ab03e | ||
|
|
b97589c934 | ||
|
|
b3ffcdd039 | ||
|
|
51e81d207e | ||
|
|
50a3aa6a4f | ||
|
|
f84cb41f28 | ||
|
|
6c95b3e50c | ||
|
|
60667794a7 | ||
|
|
f39f2c3e4a | ||
|
|
d104342df1 | ||
|
|
1d9f540198 | ||
|
|
ec34f51ead | ||
|
|
fa284636ed | ||
|
|
306ac74cd8 | ||
|
|
ff65613ffd | ||
|
|
21b6c1dc29 | ||
|
|
29a8522a86 | ||
|
|
1b41cc04eb | ||
|
|
45e7d8fe81 | ||
|
|
73af1863ec | ||
|
|
9cd8f0e7c2 | ||
|
|
2ff406453f | ||
|
|
29a9d3caba | ||
|
|
f6ae1b8a69 | ||
|
|
b2b4c934a2 | ||
|
|
b1815bc0cd | ||
|
|
8c431f2af5 | ||
|
|
04bcb0d41e | ||
|
|
d1e119ac9b | ||
|
|
7db059d4ba | ||
|
|
a930a71a3a | ||
|
|
87f0c6cf7a | ||
|
|
54037fc499 | ||
|
|
e2f6c02ad9 | ||
|
|
1fc24a5ee3 | ||
|
|
bf0f553b5e | ||
|
|
6b525a2ffe | ||
|
|
aa91c9e311 | ||
|
|
55349229d5 | ||
|
|
1408ff26a3 | ||
|
|
646234b90b | ||
|
|
7abedb0e60 | ||
|
|
d2d9647295 | ||
|
|
2edbfc2870 | ||
|
|
1a50ff829b | ||
|
|
c617e98f33 | ||
|
|
54aef4d66b | ||
|
|
76d35914c0 | ||
|
|
664cdc0937 | ||
|
|
e3913d1231 | ||
|
|
24b00e0839 | ||
|
|
92ce7fd395 | ||
|
|
3e0b280456 | ||
|
|
ee419596ce | ||
|
|
732eb344af | ||
|
|
3c7c820622 | ||
|
|
5d2f8edcb0 | ||
|
|
5a5a9113e9 | ||
|
|
7149116a68 | ||
|
|
7a40e71123 | ||
|
|
d1554f1ae5 | ||
|
|
e15f4f8ad1 | ||
|
|
f9afd30577 | ||
|
|
7f0d7d8e1a | ||
|
|
b63d7d8f3f | ||
|
|
a7ba8953ab | ||
|
|
1ea87c6cc7 | ||
|
|
f68966ce90 | ||
|
|
744e6faa53 | ||
|
|
8e84ce7615 | ||
|
|
1c5745c174 | ||
|
|
d357aff7dc | ||
|
|
e2ea9cd199 | ||
|
|
59d32e8254 | ||
|
|
3091e5b198 | ||
|
|
9c71e3cfd5 | ||
|
|
68427df817 | ||
|
|
c08cc48449 | ||
|
|
628941aa0e | ||
|
|
74bb66fd2b | ||
|
|
6b3d60fccc | ||
|
|
d733b1de68 | ||
|
|
b4e402c83d | ||
|
|
4b2b2f24ee | ||
|
|
f95389b01b | ||
|
|
8a94a6126a | ||
|
|
4cbd5c1745 | ||
|
|
f003406ffe | ||
|
|
ec3458b717 | ||
|
|
1117792bf7 | ||
|
|
164207ee10 | ||
|
|
df1ff47e0e | ||
|
|
a2add409c2 | ||
|
|
49aa5b4824 | ||
|
|
8b8db92ace | ||
|
|
cd6c4fe732 | ||
|
|
c0d889a4eb | ||
|
|
851854d675 | ||
|
|
8f8864eb38 | ||
|
|
22e55d97d3 | ||
|
|
95dad9a5d1 | ||
|
|
dbab502150 | ||
|
|
4a25894e68 | ||
|
|
c88bdf6060 | ||
|
|
8f14bba7f4 | ||
|
|
c46995fe88 | ||
|
|
804f0fa807 | ||
|
|
869216c8c8 | ||
|
|
4a21d8f1ef | ||
|
|
8e7a599d9d | ||
|
|
6996f8d07d | ||
|
|
a4d331dc77 | ||
|
|
e635d92cfc | ||
|
|
3c38b954a8 | ||
|
|
3ebbabd22a | ||
|
|
4ff1379f06 | ||
|
|
5d8515a756 | ||
|
|
5a1f2df5f1 | ||
|
|
e5a3bf7b4f | ||
|
|
09f8932f90 | ||
|
|
91574143e9 | ||
|
|
25084a6616 | ||
|
|
34ead9472d | ||
|
|
dc54895a6d | ||
|
|
8be3843359 | ||
|
|
b83dbfce33 | ||
|
|
2d7a0a09ea | ||
|
|
2391830f56 | ||
|
|
8537ebac3b | ||
|
|
e54597ba5d | ||
|
|
716187c61b | ||
|
|
b5eea5ad2c | ||
|
|
1c76c237a3 | ||
|
|
144f4fd267 | ||
|
|
11e45e2def | ||
|
|
822a8c97fd | ||
|
|
68dc8282b3 | ||
|
|
5ee195bac8 | ||
|
|
51929e6bcc | ||
|
|
28418c767d | ||
|
|
56b7c619a2 | ||
|
|
bde2e5ba60 | ||
|
|
70893ddfe1 | ||
|
|
3e746d5009 | ||
|
|
a4e4fb6bc7 | ||
|
|
f26c939f8a | ||
|
|
36b8119972 | ||
|
|
6cb1ff0abe | ||
|
|
9b18aabe94 | ||
|
|
48328416bf | ||
|
|
745866093e | ||
|
|
7c17888a13 | ||
|
|
2536a90ecc | ||
|
|
675e1eb39f | ||
|
|
9e61b2fb6b | ||
|
|
8d12897bc3 | ||
|
|
c14fc285e1 | ||
|
|
c06e5618ef | ||
|
|
1d15dc37e4 | ||
|
|
7033948b4e | ||
|
|
156ca6bd1b | ||
|
|
39c5d9b179 | ||
|
|
362538b1c0 | ||
|
|
ad84a9a967 | ||
|
|
487eeadccd | ||
|
|
a626f62ae5 | ||
|
|
249486e8bb | ||
|
|
8ccbe3ee8e | ||
|
|
20174aab11 | ||
|
|
b47da36c80 | ||
|
|
34519870b4 | ||
|
|
756396ceb6 | ||
|
|
dec88e34c5 | ||
|
|
4e68d81bbd | ||
|
|
02f1edd695 | ||
|
|
0a586c31f4 | ||
|
|
536ae20d1f | ||
|
|
38b0551a2d | ||
|
|
98416e9cbc | ||
|
|
afc1b9aaba | ||
|
|
3aaef40d07 | ||
|
|
9a509f8a80 | ||
|
|
7a9a12ac29 | ||
|
|
bc3d3702c9 | ||
|
|
6c1b9d31f7 | ||
|
|
bed47c7f04 | ||
|
|
f4746207d0 | ||
|
|
9aa6831a20 | ||
|
|
71f4345deb | ||
|
|
b9cd951c36 | ||
|
|
38d20dd69a | ||
|
|
caa46f13be | ||
|
|
54c0f2438c | ||
|
|
e2ee2f60c6 | ||
|
|
517841c2fa | ||
|
|
28e9d89ae3 | ||
|
|
3edb7fbd3a | ||
|
|
892a5a8fd3 | ||
|
|
ba155b99a2 | ||
|
|
6df544c279 | ||
|
|
44a1e5ae69 | ||
|
|
cf70263a22 | ||
|
|
536a241f90 | ||
|
|
a61eb1a847 | ||
|
|
672b72c091 | ||
|
|
6ec312ca5e | ||
|
|
265e4495ef | ||
|
|
36c355d5cd | ||
|
|
9c6cb90b93 | ||
|
|
cf6a997cfd | ||
|
|
5d437dcb2a | ||
|
|
450517cba3 | ||
|
|
9a7428841f | ||
|
|
ca71fe141a | ||
|
|
d1028a79ed | ||
|
|
112a3b9963 | ||
|
|
444f1e9f69 | ||
|
|
97c2711eb8 | ||
|
|
c25f3ce430 | ||
|
|
2ef13cf556 | ||
|
|
9bb594f07d | ||
|
|
559a30da29 | ||
|
|
e896067428 | ||
|
|
d1914dd434 | ||
|
|
8756ef5034 | ||
|
|
1649b9790b | ||
|
|
8728e3a69a | ||
|
|
b23c9b2133 | ||
|
|
eaeb918b33 | ||
|
|
f05af3d427 | ||
|
|
8f40ab45db | ||
|
|
1a1cf3ab7b | ||
|
|
3231c92baa | ||
|
|
a73c5fac86 | ||
|
|
79be2e64ae | ||
|
|
9ae31a3f5d | ||
|
|
bc6c9f5df8 | ||
|
|
1231e1b0f6 | ||
|
|
b99822e7da | ||
|
|
e66951debc | ||
|
|
1e8a8d0896 | ||
|
|
f9def3acf5 | ||
|
|
167e22cb9c | ||
|
|
5fe2ae9af1 |
+1
-1
@@ -37,7 +37,7 @@ common/src/main/resources/assets/cobblemon/showdown
|
||||
/fabric/src/generated/resources/cobblemon-common.accesswidener
|
||||
/.ignored/
|
||||
common/.fabric
|
||||
.kotlin/
|
||||
|
||||
# MacOS
|
||||
.DS_Store
|
||||
.kotlin/sessions/kotlin-compiler-16609242564043830292.salive
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
LambDynamicLights compat needs to be restored
|
||||
@@ -1,3 +0,0 @@
|
||||
### Additions
|
||||
- Added the Poké Dex as a craftable item.
|
||||
- Poké Dexes can be placed on lecterns.
|
||||
@@ -1,6 +0,0 @@
|
||||
### Additions
|
||||
- Added `moves` option to PokemonProperties, allowing you to set the moves of a Pokémon in commands and spawn files.
|
||||
- Added /spawnnpc and /spawnnpcat commands.
|
||||
|
||||
### Fixes
|
||||
- Fixed sync issues with recently learned moves where their PP would not go down until you logout and in.
|
||||
@@ -1,24 +0,0 @@
|
||||
### Additions
|
||||
- Pokémon are now animated when seen in any GUI that isn't the party GUI.
|
||||
- Quirk animations can now occur for Pokémon that are shoulder mounted.
|
||||
|
||||
### Changes
|
||||
- Improved the performance of display cases that contain Pokémon photos.
|
||||
|
||||
### Fixes
|
||||
- Fixed some Pokémon photos in display cases flashing if the Pokémon has gender differences.
|
||||
- Fixed Bidoof and Jigglypuff sleep animations stopping after some time, causing them to be 'asleep' while T-posing menacingly.
|
||||
- Fixed entities not changing poses unless you're looking at them.
|
||||
- Fixed cries not playing on send-out if the Pokémon is off-screen.
|
||||
|
||||
### Developer
|
||||
- Rebuilt large swaths of the model animation code to simplify it.
|
||||
- Renamed a bunch of things from %Poseable% to %Posable% because spelling.
|
||||
- Renamed StatelessAnimation to PoseAnimation.
|
||||
- Renamed StatefulAnimation to ActiveAnimation.
|
||||
- Documented the animation system.
|
||||
|
||||
### Data Pack & Resource Pack Creators
|
||||
- Added MoLang compatibility in the isVisible property for transformed parts.
|
||||
- Added q.has_aspect('some_aspect') function to animations, posers, and entity particle effects.
|
||||
- Added support for conditional pose animations.
|
||||
+346
-54
@@ -3,22 +3,24 @@
|
||||
#### "Now that there's a fishing mechanic, the mod is actually good!"
|
||||
|
||||
### Additions
|
||||
- Added the Poké Dex as a craftable item.
|
||||
- Poké Dexes can be placed on lecterns.
|
||||
- Added Pokémon (and item) fishing using modified fishing rods - Poké Rods! You'll need a Poké Rod smithing template, a fishing rod, and some type of Poké Ball. Each Poké Ball makes a differently themed rod. Why not?
|
||||
- Added Lure Ball functionality, increasing the catch rate of Pokémon that were caught on a fishing rod.
|
||||
- Added Repeat Ball functionality, increasing the catch rate of Pokémon that are already registered as caught in a player's Pokédex.
|
||||
- Added property chaining support for duplicate CustomPokemonPropertyType elements.
|
||||
- Added flat level battling with options to set all Pokemon to level 50, 100, or 5 for the duration of a battle. No experience or EVs are granted for a flat battle.
|
||||
- Added `aspect` and `unaspect` PokemonProperty arguments (which also includes commands such as `/pokemonedit`, `/spawnpokemon`, and `/givepokemon`) to allow forcing or un-forcing an aspect on a Pokémon.
|
||||
- Added `type` alternatively `elemental_type` PokemonProperty argument, this is only used for filtering and is not applied to Pokémon. Example `type=fire` would be true for Charmander but false for Squirtle.
|
||||
- Added support for Double Battles, Triple Battles, and Multi-battles.
|
||||
- Added support for Double Battles, Triple Battles, and Multi-battles.
|
||||
- CriticalCaptures and Pokédex progress capture multiplier now work with the Pokédex.
|
||||
- Added extra visuals to early berry growth stages.
|
||||
- Hidden Power now displays its effective typing.
|
||||
- Moves impacted by the abilities Pixelate, Refrigerate, Aerilate, Galvanize, and Normalize now display as their altered typing.
|
||||
- Added Polished Tumblestone and Tumblestone Brick block sets from Tumblestone, Black Tumblestone, and Sky Tumblestone.
|
||||
- Added Metronome, Protective Pads, Punching Glove, Room Service, Scope Lens, Shed Shell, Terrain Extender, Throat Spray, Utility Umbrella, Wide Lens, and Zoom Lens held items
|
||||
- Added particles for moves: Watersport, Mud Sport, and Psychic.
|
||||
- Added Fire, Water, Thunder, Leaf, Ice, Sun, Moon, Shiny, Dawn, and Dusk Stone storage blocks.
|
||||
- Added Eject Pack, Metronome, Protective Pads, Punching Glove, Room Service, Scope Lens, Shed Shell, Terrain Extender, Throat Spray, Utility Umbrella, Wide Lens, and Zoom Lens held items
|
||||
- Moves can now be benched without specifying a replacement move, allowing for empty move slots.
|
||||
- Moves learned via Sketch now persist after battle.
|
||||
- Added `stonjourner_henge_ruins`, `luna_henge_ruins`, and `sol_henge_ruins` structures.
|
||||
- Added a `battleInvulnerability` gamerule to make players invulnerable to any damage during a battle.
|
||||
- Added a `mobTargetInBattle` gamerule to exclude players from being targeted by mobs during a battle.
|
||||
@@ -30,9 +32,29 @@
|
||||
- New config setting `displayEntityNameLabel` and `displayEntityLabelsWhenCrouchingOnly` to control what and when is displayed for the pokemon label
|
||||
- `/freezepokemon` command to pause a Pokémon's animation at a specific point in time.
|
||||
- Added `no_ai` and `freeze_frame` options to the `/spawnpokemon` command.
|
||||
- Added shiny Pokémon effects.
|
||||
- Added effects for the burn status effect.
|
||||
- Added effects for the moves: Psychic, Water Sport, and Mud Sport.
|
||||
- Added a new universal locator called "top".
|
||||
- Added `moves` option to Pokémon properties, allowing you to set the moves of a Pokémon in commands and spawn files using comma-separated move names.
|
||||
- Added shiny Pokémon effects.
|
||||
- Added effects for the burn status effect.
|
||||
- Added effects for the moves: Seismic Toss, Withdraw, Bite, Crunch, Super Fang, Hyper Fang, Pursuit, Mist, Haze, Lick, Kinesis, Psychic, Water Sport, and Mud Sport.
|
||||
- Added a new universal locator called `top`.
|
||||
- Added shiny Pokémon particles with sound effects.
|
||||
- Added animation for trading.
|
||||
- Added icons for pending trade, team-up, and battle requests from other players.
|
||||
- Added `/spawnnpc` and `/spawnnpcat` commands.
|
||||
- Pokémon are now animated when seen in any GUI that isn't the party GUI.
|
||||
- Quirk animations can now occur for Pokémon that are shoulder mounted.
|
||||
- Added `fishing boat` structures that contain a map to a shipwreck cove and a pokerod smithing template.
|
||||
- Added `submerged_shipwreck_cove` and `lush_shipwreck_cove` structures.
|
||||
|
||||
### Pokémon Added
|
||||
#### Gen 1
|
||||
- Alola Bias Cubone
|
||||
- Alolan Marowak
|
||||
|
||||
#### Gen 2
|
||||
- Ledyba
|
||||
- Ledian
|
||||
@@ -40,19 +62,229 @@
|
||||
- Sunflora
|
||||
- Wobbuffet
|
||||
- Girafarig
|
||||
- Corsola
|
||||
- Remoraid
|
||||
- Octillery
|
||||
- Mantine
|
||||
- Smeargle
|
||||
|
||||
#### Gen 3
|
||||
- Slakoth
|
||||
- Vigoroth
|
||||
- Slaking
|
||||
- Corphish
|
||||
- Crawdaunt
|
||||
- Feebas
|
||||
- Milotic
|
||||
- Wynaut
|
||||
- Absol
|
||||
- Spheal
|
||||
- Sealeo
|
||||
- Walrein
|
||||
- Bagon
|
||||
- Shelgon
|
||||
- Salamence
|
||||
- Kecleon
|
||||
|
||||
#### Gen 4
|
||||
- Mantyke
|
||||
- Finneon
|
||||
- Lumineon
|
||||
- Shellos
|
||||
- Gastrodon
|
||||
- Rotom
|
||||
|
||||
#### Gen 5
|
||||
- Purrloin
|
||||
- Liepard
|
||||
- Scraggy
|
||||
- Scrafty
|
||||
|
||||
#### Gen 6
|
||||
- Clauncher
|
||||
- Clawitzer
|
||||
|
||||
#### Gen 7
|
||||
- Pikipek
|
||||
- Trumbeak
|
||||
- Toucannon
|
||||
- Mareanie
|
||||
- Toxapex
|
||||
- Sandygast
|
||||
- Palossand
|
||||
- Bruxish
|
||||
|
||||
#### Gen 8
|
||||
- Cramorant
|
||||
- Hatenna
|
||||
- Hattrem
|
||||
- Hatterene
|
||||
- Pincurchin
|
||||
|
||||
#### Gen 9
|
||||
- Wattrel
|
||||
- Kilowattrel
|
||||
- Wiglett
|
||||
- Wugtrio
|
||||
- Flamigo
|
||||
- Veluza
|
||||
- Farigiraf
|
||||
- Klawf
|
||||
- Finizen
|
||||
- Palafin
|
||||
- Wiglett
|
||||
- Wugtrio
|
||||
- Flamigo
|
||||
- Dondozo
|
||||
|
||||
#### Unique Forms
|
||||
- Magikarp Jump Variants
|
||||
- Gyarados Jump Variants
|
||||
|
||||
### Added cries to the following Pokémon
|
||||
- Sandshrew, Sandslash
|
||||
- Magnemite, Magneton, Magnezone
|
||||
- Gastly, Haunter, Gengar
|
||||
- Rhyhorn, Rhydon, Rhyperior
|
||||
- Happiny, Chansey
|
||||
- Horsea, Seadra, Kingdra
|
||||
- Magby, Magmar, Magmortar
|
||||
- Porygon, Porygon2, Porygon-Z
|
||||
- Sentret, Furret
|
||||
- Misdreavus, Mismagius
|
||||
- Corsola
|
||||
- Mantyke, Mantine
|
||||
- Girafarig, Farigiraf
|
||||
- Wynaut, Wobbuffet
|
||||
- Lunatone
|
||||
- Solrock
|
||||
- Corphish, Crawdaunt
|
||||
- Feebas, Milotic
|
||||
- Kecleon
|
||||
- Absol
|
||||
- Spheal, Sealeo, Walrein
|
||||
- Relicanth
|
||||
- Bagon, Shelgon, Salamence
|
||||
- Munchlax
|
||||
- Finneon, Lumineon
|
||||
- Purrloin, Liepard
|
||||
- Timburr, Gurdurr, Conkeldurr
|
||||
- Joltik, Galvantula
|
||||
- Elgyem, Beheeyem
|
||||
- Golett, Golurk
|
||||
- Deino, Zweilous, Hydreigon
|
||||
- Flabébé, Floette, Florges
|
||||
- Clauncher, Clawitzer
|
||||
- Mareanie, Toxapex
|
||||
- Wimpod, Golisopod
|
||||
- Bruxish
|
||||
- Hatenna, Hattrem, Hatterene
|
||||
- Pincurchin
|
||||
- Klawf
|
||||
- Finizen, Palafin \[Zero\], Palafin \[Hero\]
|
||||
- Dondozo
|
||||
|
||||
### Added shoulder mounts for the following Pokémon
|
||||
- Weedle
|
||||
- Caterpie
|
||||
- Spearow
|
||||
- Mew
|
||||
- Murkrow
|
||||
- Smoochum
|
||||
- Larvitar
|
||||
- Tailow
|
||||
- Plusle
|
||||
- Minun
|
||||
- Beldum
|
||||
- Starly
|
||||
- Buneary
|
||||
- Combee
|
||||
- Pachirisu
|
||||
- Tepig
|
||||
- Pidove
|
||||
- Petilil, Hisui Bias Petilil
|
||||
- Zorua, Hisui Bias Zorua
|
||||
- Elgyem
|
||||
- Fletchling
|
||||
- Skrelp
|
||||
- Klefki
|
||||
- Litten
|
||||
- Fomantis
|
||||
- Morelull
|
||||
- Dreepy
|
||||
- Sprigatito
|
||||
- Shroodle
|
||||
- Tatsugiri
|
||||
- Glimmet
|
||||
- Gimmighoul \[Roaming\]
|
||||
|
||||
### Animation updates for the following Pokémon
|
||||
- Bellsprout, Weepinbell, Victreebel
|
||||
- Shellder, Cloyster
|
||||
- Porygon, Porygon2, Porygon-Z
|
||||
- Furret
|
||||
- Swinub, Piloswine, Mamoswine
|
||||
- Skarmory
|
||||
- Tyrogue
|
||||
- Spinda
|
||||
- Torkoal
|
||||
- Nincada, Ninjask
|
||||
- Lunatone
|
||||
- Solrock
|
||||
- Buneary, Lopunny
|
||||
- Magnezone
|
||||
- Alomomola
|
||||
- Tepig, Pignite, Emboar
|
||||
- Flabebe, Floette, Florges
|
||||
- Litten, Torracat, Incineroar
|
||||
- Fomantis, Lurantis
|
||||
- Dreepy, Drakloak
|
||||
- Kleavor
|
||||
- Scorbunny
|
||||
- Gimmighoul \[Roaming\]
|
||||
|
||||
### Model updates for the following Pokémon
|
||||
- Bulbasaur, Ivysaur, Venusaur
|
||||
- Charmander, Charmeleon, Charizard
|
||||
- Kakuna, Beedrill
|
||||
- Lapras
|
||||
- Porygon, Porygon2, Porygon-Z
|
||||
- Igglybuff, Jigglypuff, Wigglytuff
|
||||
- Poliwhirl, Poliwrath
|
||||
- Bellsprout, Weepinbell, Victreebel
|
||||
- Shellder, Cloyster
|
||||
- Gastly, Haunter
|
||||
- Onix
|
||||
- Krabby, Kingler
|
||||
- Rhyhorn, Rhydon, Rhyperior
|
||||
- Horsea, Seadra, Kingdra
|
||||
- Goldeen, Seaking
|
||||
- Magby, Magmar, Magmortar
|
||||
- Magikarp, Gyarados
|
||||
- Munchlax, Snorlax
|
||||
- Swinub, Piloswine, Mamoswine
|
||||
- Mudkip, Marshtomp, Swampert
|
||||
- Baltoy, Claydol
|
||||
- Carvanha
|
||||
- Relicanth
|
||||
- Prinplup, Empoleon
|
||||
- Gible, Gabite, Garchomp
|
||||
- Riolu, Lucario
|
||||
- Snivy, Servine, Serperior
|
||||
- Tepig, Pignite, Emboar
|
||||
- Krookodile
|
||||
- Dwebble, Crustle
|
||||
- Joltik, Galvantula
|
||||
- Klink, Klang, Klinglang
|
||||
- Golett, Golurk
|
||||
- Fennekin, Braixen, Delphox
|
||||
- Phantump, Trevenant
|
||||
- Litten, Torracat, Incineroar
|
||||
- Popplio, Brionne, Primarina
|
||||
- Lurantis
|
||||
- Scorbunny, Cinderace
|
||||
- Quaxly
|
||||
- Tatsugiri
|
||||
|
||||
### Changes
|
||||
- Buffed Dusk Ball catch multipliers: Increased multiplier to 3.5 (from 3.0) in light level 0. Increased multiplier to 3.0 (from 1.5) in light levels 1-7.
|
||||
@@ -60,14 +292,13 @@
|
||||
- Adjusted some berry balance values like yield and growth times.
|
||||
- Adjusted volumes of sounds made by Display Cases, Berry Bushes, Energy Root, Medicinal Leek, Vivichoke, Mints, Revival Herbs and Gilded Chests.
|
||||
- Changes to mulch buffs/durations.
|
||||
- Dreepy is now shoulder mountable.
|
||||
- Updated potion sprites.
|
||||
- Weedle, Caterpie, Spearow, Smoochum, Mew, Murkrow, Larvitar, Taillow, Plusle, Minun, Beldum, Starly, Buneary, Combee, Pachirisu, Pidove, Petilil, Hisui Bias Petilil, Zorua, Hisuian Zorua, Elgyem, Fletchling, Skrelp, Klefki, Fomantis, Morelull, Dreepy, Shroodle, Tatsugiri, Glimmet, and Roaming Gimmighoul are now shoulder mountable.
|
||||
- Link Cable recipe has been redesigned.
|
||||
- Updated sounds for Medicinal Leeks, Big Roots, Energy Roots and Revival Herbs.
|
||||
- Updated UI sounds for clicking and evolving Pokémon.
|
||||
- Updated cries for Chansey, Crobat, Hoothoot, Noctowl.
|
||||
- Removed the interchangeable evolution results for the first stage Hisuian starters to prevent confusion. The method still exists for stage 2 to 3, but stage 1 to 2 was not distinguishable enough for many users.
|
||||
- Kakuna, Beedrill, Snorlax, Munchlax, Krabby, Kingler, and Lurantis received model updates.
|
||||
- Bulbasaur, Ivysaur, Venusaur, Kakuna, Beedrill, Snorlax, Munchlax, Krabby, Kingler, Lurantis, Horsea, Seadra, Kingdra, Litten, Torracat, Incineroar, Mudkip, Marshtomp, Swampert, Scorbunny, Cinderace, Prinplup, Empoleon, Relicanth, Goldeen, Seaking, Shellder, Cloyster, Tatsugiri, Igglybuff, Jigglypuff, Wigglytuff, Krookodile, Gible, Gabite, Garchomp, Rhyhorn, Rhydon, Rhyperior, and Carvanha received model updates.
|
||||
- Vivillon wings will stop being clear when you remove any Vivillon related resourcepacks. The default pattern will be the meadow wings.
|
||||
- Adjusted Pokémon sendout positions for single battles.
|
||||
- Wild Pokémon interaction range increased to 12 blocks (from 10 blocks).
|
||||
@@ -79,24 +310,34 @@
|
||||
- Updated dialogue GUI assets with proper assets.
|
||||
- Updated party switching interface when in battle.
|
||||
- Relic coin pouches can now be waterlogged.
|
||||
- Pokemon Name (and level) labels are now only visible when crouching by default, set the `displayEntityLabelsWhenCrouchingOnly` to `false` to always them even when not crouching
|
||||
- The "Press R to start battle prompt" will now disappear after a player's first battle has been won
|
||||
- Pokémon name and level labels are now only visible when crouching by default. Set the `displayEntityLabelsWhenCrouchingOnly` config to `false` to always have them displayed.
|
||||
- The "Press R to start battle prompt" will now disappear after a player's first battle has been won.
|
||||
- The default number of digits for the Pokédex number in the summary has been increased, from 3 to 4.
|
||||
- The pasture block model's screen is now off by default.
|
||||
- The Poké Balls creative tab is now named Utility Items as it also encompasses Poké Rod and Pokédex items.
|
||||
- Moves can now be benched without specifying a replacement move, allowing for empty move slots.
|
||||
- Moves learned via Sketch now persist after battle.
|
||||
- Updated potion sprites
|
||||
- Removed the interchangeable evolution results for the first stage Hisuian starters to prevent confusion. The method still exists for stage 2 to 3, but stage 1 to 2 was not distinguishable enough for many users.
|
||||
- Hidden Power now displays its effective typing.
|
||||
- Updated particles for moves: Confusion, Protect, Sand Attack, and Quick Attack.
|
||||
- Updated particles for status effects: Paralysis, Poison, and Sleep.
|
||||
- Updated particles on Gastly.
|
||||
- Revamped stat buff and de-buff particles.
|
||||
- Improved the performance of display cases that contain Pokémon photos.
|
||||
|
||||
### Fixes
|
||||
- Scaled down Amaura's fetus model to avoid clipping through the tank while animating.
|
||||
- Fixed Cubone's cry not having a sound.
|
||||
- Fixed the sendout sound erroneously playing when a wild Pokémon breaks out of a Poké ball.
|
||||
- Flamethrower is no longer missing sounds.
|
||||
- Fixed the Seafloor spawning context not being a usable context.
|
||||
- Fixed Pokemon spawning in non-full blocks like slabs.
|
||||
- Fixed Gilded Chests not dropping the chest itself when broken, only the contents.
|
||||
- Fixed Pokémon losing their Hidden Ability through evolution if the middle stage did not have a Hidden Ability.
|
||||
- Hidden Power no longer plays the water type action effect (It now plays the normal type action effect).
|
||||
- Fixed Chimchar and Monferno T-posing whenever they sleep.
|
||||
- Fixed the Magby line not having any placeholder walk animations.
|
||||
- Fixed Duskull and Dusclops using skylight levels for their nether spawn data. There is no sun in the Nether!
|
||||
- Fixed Hisuian Zoroark using base Zoroark stats.
|
||||
- Fixed Bellossom clipping into the player head when shoulder mounted.
|
||||
- Fixed Shroomish's look range to prevent it from looking higher than it should.
|
||||
- Fixed Cetitan's cry breaking its walk and sleep animations.
|
||||
- Fixed Crumbling Arch not blending in with the world.
|
||||
- Fixed Energy Root applying being usable on a fainted Pokémon.
|
||||
- Fixed Pokémon entity not spawning when starting a battle while recalling said Pokémon.
|
||||
@@ -127,9 +368,14 @@
|
||||
- Fixed Hisuian Zoroark using base Zoroark stats.
|
||||
- Fixed Bellossom clipping into the player head when shoulder mounted.
|
||||
- Fixed Shroomish's look range to prevent it from looking higher than it should.
|
||||
- Fixed Maushold's faint animations not playing. It's sadder than Tandemaus!
|
||||
- Fixed Slowking's battle idle.
|
||||
- Fixed Grafaiai's walk speed to prevent model sliding.
|
||||
- Fixed Maushold's faint animations not playing. It's sadder than Tandemaus!
|
||||
- Fixed Slowking's battle idle.
|
||||
- Fixed Grafaiai's walk speed to prevent model sliding.
|
||||
- Fixed Alolan Exeggutor's tail not showing in the party UI. It will now also stand in front of all Pokémon in the party menu :)
|
||||
- Fixed Timburr duplicating its log while fainting.
|
||||
- Fixed reviving items throwing an exception when used in battle.
|
||||
- Fixed messages for Focus Sash, Confusion, Mummy, Ice Face, Own Tempo, and Revive.
|
||||
- Improve error handling when loading spawn-sets to ensure invalid configurations don't crash the server.
|
||||
@@ -144,7 +390,18 @@
|
||||
- Pokémon whose current owner is not its Original Trainer now gains extra experience.
|
||||
- Fixed Fossil Resurrection advancement not being granted.
|
||||
- Fixed village generation caps not applying for berry farms. You were not meant to see more than two berry farms per village!
|
||||
- Fixed the Ice Face ability activation being displayed incorrectly in a battle
|
||||
- Fixed the Ice Face ability activation being displayed incorrectly in a battle.
|
||||
- Fixed edge case of F1 and R locking you in battle with no R functionality (requiring ESC to get out).
|
||||
- Fixed Poké Ball render orientation in battle interface when capturing.
|
||||
- Fixed sync issues with recently learned moves where their PP would not go down until you logout and in.
|
||||
- Fixed some Pokémon photos in display cases flashing if the Pokémon has gender differences.
|
||||
- Fixed Bidoof and Jigglypuff sleep animations stopping after some time, causing them to be 'asleep' while T-posing menacingly.
|
||||
- Fixed entities not changing poses unless you're looking at them.
|
||||
- Fixed cries not playing on send-out if the Pokémon is off-screen.
|
||||
- Fixed text row selection highlight in battle log.
|
||||
- Fixed top black border rendering in scroll interfaces in summary UI.
|
||||
- Fixed aspect tracking for Advancements.
|
||||
- Fixed illusion not copying aspects or caught ball.
|
||||
|
||||
### Developer
|
||||
- `SpawnCause` is now an implementation of `SpawningInfluence`.
|
||||
@@ -157,21 +414,55 @@
|
||||
- Serialization of PokemonStores and Pokemon themselves now require registry access, which will break some sidemods. This sucked for us more than it will suck for you! If you have a world or player instance, you can get it from there.
|
||||
- ``TeraTypes`` now implements ``Iterable``.
|
||||
- PokemonBattle now starts on turn 0.
|
||||
- All sounds related to evolving Pokémon have been moved to the "sounds/evolution" folder.
|
||||
- Added `forcedAspects` to Pokémon to make it easier to easily add basic aspects to a Pokémon in a way that persists. We already know that everyone is going to overuse this.
|
||||
- Made the `Pokemon.aspects` setter private. This could technically break side-mods but if you are affected by this then you were using it wrong! Use `Pokemon.forcedAspects` to fix it.
|
||||
- Cobblemon's main logger is properly static now.
|
||||
- PokemonEntity.enablePoseTypeRecalculation can be used to disable automatic pose type recalculation.
|
||||
- Added CollectEggEvent and HatchEggEvent for compatibility usage.
|
||||
- Added events for:
|
||||
- Showdown Instructions
|
||||
- Mega Showdown Instruction
|
||||
- Terastallize Showdown Instruction
|
||||
- ZPower Showdown Instruction
|
||||
- Bait Consumed, Bait Set, and an event to register custom BaitEffect Functions
|
||||
- Bobber Bucket Chosen
|
||||
- Bobber Spawn Pokémon
|
||||
- Pokérod Cast
|
||||
- Pokérod Reel
|
||||
- Pokémon Heal (with context)
|
||||
- Added HealingSource, an interface applied to all sources of healing from player actions, for easier tracking of healing sources.
|
||||
- Move Change
|
||||
- Shiny Chance Calculation Event (with player context)
|
||||
- Rebuilt large swaths of the model animation code to simplify it.
|
||||
- Renamed a bunch of things from %Poseable% to %Posable% because spelling.
|
||||
- Renamed StatelessAnimation to PoseAnimation.
|
||||
- Renamed StatefulAnimation to ActiveAnimation.
|
||||
- Documented the animation system.
|
||||
|
||||
### Data Pack & Resource Pack Creators
|
||||
- Added support for "shedders" similar to Shedinja's evolution logic.
|
||||
- Fixed the placeholder `WingFlapIdle` animation so the wings are not rotating opposite to each other.
|
||||
- 'player' type dialogue faces can now be explicitly stated so that NPC mods that use fake players can show in dialogue portraits.
|
||||
- Added `isLeftSide` field for dialogue faces. This determines what side of dialogue box the portrait is on.
|
||||
- "sounds/attacks" folder has been renamed to "sounds/move"
|
||||
- Moves sharing generic sounds now have unique sound events, allowing them to be changed with resource packs.
|
||||
- All move sound events have been renamed to "move.NAME.SOURCE" for consistency.
|
||||
- Status moves have been moved out of the 'attacks' folder and split into volatile and nonvolatile.
|
||||
- 'status.badlypoison.actor' sound event has been renamed to "status.toxpoison.actor"
|
||||
- Mulch and berry harvesting sound events have been renamed and moved to their respective folders in "sounds/block."
|
||||
- All sounds related to evolving Pokémon have been moved to the "sounds/evolution" folder.
|
||||
- Sound events for all blocks now start with "block."
|
||||
- Gimmighoul chest and item interaction sounds have been moved to where its cry is.
|
||||
- Unused sound files and sound events have been removed.
|
||||
- Added MoLang compatibility in the isVisible property for transformed parts.
|
||||
- Added q.has_aspect('some_aspect') function to animations, posers, and entity particle effects.
|
||||
- Added support for conditional pose animations.
|
||||
- Added a new universal locator called "top".
|
||||
- Added `eggs_collected` and `eggs_hatched` Advancement triggers.
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
- Czech, German, Greek, Spanish, Mexican Spanish, French, Canadian French, Hungarian, Italian, Japanese, Korean, Dutch, Polish, Portuguese, Brazilian Portuguese, Russian, Ukrainian, Simplified Chinese, and Traditional Chinese
|
||||
- Czech, German, Greek, Spanish, Mexican Spanish, French, Canadian French, Hungarian, Italian, Japanese, Korean, Dutch, Polish, Portuguese, Brazilian Portuguese, Russian, Ukrainian, Simplified Chinese, and Traditional Chinese
|
||||
- Migrated translation project to Weblate at https://lang.cobblemon.com/projects/cobblemon/mod/
|
||||
|
||||
|
||||
@@ -211,7 +502,7 @@
|
||||
### Changes
|
||||
- Sounds for Relic Coin Sacks have been correctly renamed. Relic Coin Pouches received new sounds for breaking and placing.
|
||||
- Readjusted Petilil portraits so they fit a bit better.
|
||||
- Improved handling of Pokémon taken from the Restoration Tank block to be a bit more stable.
|
||||
- Improved handling of Pokémon taken from the Restoration Tank block to be a bit more stable.
|
||||
- Made Mulch cheaper to craft.
|
||||
|
||||
### Fixes
|
||||
@@ -223,19 +514,19 @@
|
||||
- Fixed Supplementaries incompatibility.
|
||||
- Fixed Fossil Compartment crash with Jade / WAILA forks.
|
||||
- Fixed pasture block PC lookups when the player is offline.
|
||||
- Fixed an untranslated battle message that occurs when using a move that just ran out of PP (e.g. Fire Blast that just got spited mid-turn).
|
||||
- Fixed an untranslated battle message that occurs when using a move that just ran out of PP (e.g. Fire Blast that just got spited mid-turn).
|
||||
- Fixed held items being eaten even when the held item evolutions are already unlocked.
|
||||
- Fixed Hisuian Decidueye not being Grass/Fighting.
|
||||
- Fixed both Decidueye forms learning both Triple Arrows and Spirit Shackle.
|
||||
- Fixed Pineco being unable to evolve into Shulker Forretress.
|
||||
- Fixed Kabutops T-posing when underwater. It doesn't have proper swimming animations yet, though.
|
||||
- Fixed Kabutops T-posing when underwater. It doesn't have proper swimming animations yet, though.
|
||||
- Fixed Pidgey's missing walk animation.
|
||||
- Fixed Cyndaquil's hidden flames clipping if it was swimming.
|
||||
- Fixed Chimecho and Chingling being unable to spawn near bells. They are meant to!
|
||||
- Fixed Tyrantrum and Wailord Party Overlay models peeking through the chat box. It was kinda funny though.
|
||||
- Fixed hitbox sizes for Seedot, Nuzleaf, and Shiftry.
|
||||
- Fixed Budew and Lechonk sliding if they walked for too long.
|
||||
- Fixed Shedinja T-posing in battle.
|
||||
- Fixed Budew and Lechonk sliding if they walked for too long.
|
||||
- Fixed Shedinja T-posing in battle.
|
||||
- Fixed recoil evolution condition not working, making things like Basculegion unobtainable.
|
||||
- Fixed issue where poser debug tools didn't work on JSON posers.
|
||||
- Fixed issue where gilded chests don't close when going far away.
|
||||
@@ -253,7 +544,7 @@
|
||||
- Fixed generic battle effect sounds not sounding the way they were intended to.
|
||||
- Fixed particle effects often not having access to some specific entity functions from MoLang.
|
||||
- Fixed particles sometimes lasting a single tick too long, causing (very quick) visual glitches.
|
||||
- Fixed particle rotations being inverted.
|
||||
- Fixed particle rotations being inverted.
|
||||
- Fixed particle events not spawning at the instigating particle's location.
|
||||
- Fixed a bunch of spam during world generation.
|
||||
- Fixed a bug in which throwing a Poké Ball at a player owned Pokémon with the ability Illusion would reveal its true species. Hilarious meta strategy.
|
||||
@@ -272,13 +563,13 @@
|
||||
- Added parametric motion and rotation support to particle effects.
|
||||
- Added entity_scale as a molang var for particles (likely only applicable to Pokemon)
|
||||
- Added support for primary quirk animations using the following format:
|
||||
`JSON
|
||||
{
|
||||
"quirks": [
|
||||
"q.bedrock_primary_quirk('<pokemon>', '<animation>', <minSeconds>, <maxSeconds>, <loopTimes>, '<excludedLabels>', q.curve('<waveFunction>'))"
|
||||
]
|
||||
}
|
||||
`
|
||||
`JSON
|
||||
{
|
||||
"quirks": [
|
||||
"q.bedrock_primary_quirk('<pokemon>', '<animation>', <minSeconds>, <maxSeconds>, <loopTimes>, '<excludedLabels>', q.curve('<waveFunction>'))"
|
||||
]
|
||||
}
|
||||
`
|
||||
- Added support for custom stashes, similar to Gimmighoul's coin and scrap stashes.
|
||||
|
||||
### Localization
|
||||
@@ -578,7 +869,7 @@ These are our compromise for having both regular and Hisuian forms of these Pok
|
||||
- Fixed thrown Poké Balls technically having no name.
|
||||
- Fixed very many issues with Bedrock particle effects. There are probably many more. Life goes on.
|
||||
- Fixed Arbok patterns not being as specific in spawning as they were intended to be.
|
||||
- Fixed Pokémon not avoiding danger at all when pathfinding.
|
||||
- Fixed Pokémon not avoiding danger at all when pathfinding.
|
||||
- Fixed Pokémon pathing over snow layers and carpets.
|
||||
- Fixed the Sobble line not being able to swim or breathe underwater.
|
||||
- Fixed mod incompatibility with [Just Enough Resources](https://modrinth.com/mod/just-enough-resources-jer).
|
||||
@@ -587,7 +878,7 @@ These are our compromise for having both regular and Hisuian forms of these Pok
|
||||
- Fixed the data set on Pokémon when abilities are given via properties such as in `/spawnpokemon`.
|
||||
- Fixed Pokémon sometimes losing hidden abilities when evolving. This fix will only take effect for newly created Pokémon because of technical reasons that were explained to me but which I then forgot.
|
||||
- Fixed capture messages not displaying in battle.
|
||||
- Fixed the Illusion ability causing the wrong Pokémon to be targeted in battle.
|
||||
- Fixed the Illusion ability causing the wrong Pokémon to be targeted in battle.
|
||||
- Fixed battles started with fainted party members causing a soft-lock on defeat.
|
||||
- Fixed some issues with eyes in the faint animations of Hitmonlee and Phantump
|
||||
- Fixed missing evolution moves, for example Stone Axe for Kleavor.
|
||||
@@ -602,7 +893,7 @@ These are our compromise for having both regular and Hisuian forms of these Pok
|
||||
- Added a new "advancement" evolution variant that takes an advancement identifier and succeeds if the player has the advancement.
|
||||
- Made the spawning API capable of non-entity spawning. You can make it 'spawn' commands if you want. Go nuts.
|
||||
- Made `PokemonProperties.parse` more interoperable with Java. Save yourself and stop using Java.
|
||||
- Added the `HeldItemEvent`, this comes with 2 implementation `HeldItemEvent.Pre` and `HeldItemEvent.Post`.
|
||||
- Added the `HeldItemEvent`, this comes with 2 implementation `HeldItemEvent.Pre` and `HeldItemEvent.Post`.
|
||||
- Corrections to the ability implementation have been made that make `Ability.forced` function as intended and never reroll an ability for a Pokémon, please check your implementations to ensure the corrected behavior is intended for your use case.
|
||||
- `Pokemon.ability` no longer has a public setter. Please migrate to using `Pokemon#updateAbility`, this handles the ability coordinate storage for you when necessary.
|
||||
- `Ability.forced`, `Ability.index` and `Ability.priority` have all had their setters internalized, there is no longer any need to manually adjust these migrate to the method mentioned above to handle that process for you.
|
||||
@@ -616,14 +907,14 @@ These are our compromise for having both regular and Hisuian forms of these Pok
|
||||
### Datapack & Resourcepack Creators
|
||||
- The maximum amount of fossils that can fit in the Fossil Analyzer can be adjusted in the config.
|
||||
- Custom fossils can be defined using a list of items and the resulting Pokémon. An example of `aerodactyl.json`:
|
||||
`JSON
|
||||
{
|
||||
"result": "aerodactyl",
|
||||
"fossils": [
|
||||
"cobblemon:old_amber_fossil"
|
||||
]
|
||||
}
|
||||
`
|
||||
`JSON
|
||||
{
|
||||
"result": "aerodactyl",
|
||||
"fossils": [
|
||||
"cobblemon:old_amber_fossil"
|
||||
]
|
||||
}
|
||||
`
|
||||
- Fetus models can be defined in `bedrock/fossils`.
|
||||
- Fetus textures can be defined in `textures/fossils`.
|
||||
- Fuel for the Restoration Machine is registered inside the `natural_materials` folder. To register more fuels, create a JSON file containing an array of objects. Each object supports the following fields:
|
||||
@@ -635,16 +926,16 @@ These are our compromise for having both regular and Hisuian forms of these Pok
|
||||
- Added dialogue datapack folder and `/opendialogue` command.
|
||||
- Added the item tag `cobblemon:held/leaves_leftovers` this can be used to flag apple-like items that can create leftovers when eaten.
|
||||
- You can now add support for dynamic lighting implementations, Cobblemon ships with a default implementation for [LambDynamicLights](https://modrinth.com/mod/lambdynamiclights) and the [Dynamic Lights Reforged](https://www.curseforge.com/minecraft/mc-mods/dynamiclights-reforged), add the following to any species or form:
|
||||
`JSON
|
||||
{
|
||||
"lightingData": {
|
||||
"lightLevel": 14,
|
||||
"_lightLevelCommentRemoveMe": "Above supports 0 to 15",
|
||||
"liquidGlowMode": "LAND",
|
||||
"_liquidGlowModeCommentRemoveMe": "Above supports LAND, UNDERWATER or BOTH"
|
||||
`JSON
|
||||
{
|
||||
"lightingData": {
|
||||
"lightLevel": 14,
|
||||
"_lightLevelCommentRemoveMe": "Above supports 0 to 15",
|
||||
"liquidGlowMode": "LAND",
|
||||
"_liquidGlowModeCommentRemoveMe": "Above supports LAND, UNDERWATER or BOTH"
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
`
|
||||
- Following up on this change `light_source` was removed as a possible shoulder effect due to becoming unnecessary and never having had a default implementation.
|
||||
- Added the item tag `cobblemon:ability_changers`, contains the `cobblemon:ability_capsule` & `cobblemon:ability_patch` by default.
|
||||
- Added the item tag `cobblemon:held/is_friendship_booster`, allows items to give the Soothe Bell effect of a boost of 1.5x Friendship gained, contains `cobblemon:soothe_bell` by default.
|
||||
@@ -731,7 +1022,7 @@ These are our compromise for having both regular and Hisuian forms of these Pok
|
||||
- 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 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.
|
||||
@@ -751,7 +1042,7 @@ These are our compromise for having both regular and Hisuian forms of these Pok
|
||||
### 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.
|
||||
- Rebuilt the scheduling API to more clearly force side choices and allow more local temporal frames of reference for tasks.
|
||||
- Rebuilt the scheduling API to more clearly force side choices and allow more local temporal frames of reference for tasks.
|
||||
- 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
|
||||
@@ -777,7 +1068,7 @@ These are our compromise for having both regular and Hisuian forms of these Pok
|
||||
- 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)
|
||||
@@ -1188,7 +1479,7 @@ Thank you so much to all of our community translators that bring the mod to the
|
||||
- Species and FormData have had their evolutions, pre-evolution and labels properties exposed. It is still recommended to work using a Pokémon instance when possible.
|
||||
- Added capture check to BattleVictoryEvent.
|
||||
- The various hardcoded potion shoulder effects have been removed, make use of PotionBaseEffect.
|
||||
- Added ContextManager for tracking causes and contexts of conditions created during a battle. See BattleContext for types of conditions that are tracked.
|
||||
- Added ContextManager for tracking causes and contexts of conditions created during a battle. See BattleContext for types of conditions that are tracked.
|
||||
- Added MongoDB support for storing Pokémon and Player data. Must be enabled in config, requires MongoDB core and sync drivers (4.10.0+).
|
||||
- CobblemonShowdown updated to version 10.
|
||||
- Generation of a battle can be set in BattleFormat.
|
||||
@@ -1587,3 +1878,4 @@ Thank you so much to all of our community translators that bring the mod to the
|
||||
|
||||
## [1.0.0 (November 12th, 2022)](#1-0-0)
|
||||
- Initial release.
|
||||
|
||||
|
||||
@@ -13,11 +13,15 @@ import com.cobblemon.mod.common.client.render.layer.PokemonOnShoulderRenderer;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.pokemon.FormData;
|
||||
import com.cobblemon.mod.common.pokemon.lighthing.LightingData;
|
||||
import dev.lambdaurora.lambdynlights.api.DynamicLightHandler;
|
||||
import dev.lambdaurora.lambdynlights.api.DynamicLightHandlers;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
import net.minecraft.util.Tuple;
|
||||
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
||||
// Java class due to relying on entrypoint on Fabric side
|
||||
@@ -29,44 +33,32 @@ public class LambDynamicLightsCompat {
|
||||
// Make sure not to call anything Fabric specific :)
|
||||
public static void hookCompat() {
|
||||
// Pokémon entities
|
||||
// DynamicLightHandlers.registerDynamicLightHandler(
|
||||
// CobblemonEntities.POKEMON,
|
||||
// DynamicLightHandler.makeHandler(
|
||||
// pokemon -> resolvedPokemonLightLevel(pokemon, false),
|
||||
// pokemon -> true
|
||||
// )
|
||||
// );
|
||||
// DynamicLightHandlers.registerDynamicLightHandler(
|
||||
// CobblemonEntities.POKEMON,
|
||||
// DynamicLightHandler.makeHandler(
|
||||
// pokemon -> resolvedPokemonLightLevel(pokemon, true),
|
||||
// pokemon -> false
|
||||
// )
|
||||
// );
|
||||
DynamicLightHandlers.registerDynamicLightHandler(
|
||||
CobblemonEntities.POKEMON,
|
||||
DynamicLightHandler.makeHandler(
|
||||
LambDynamicLightsCompat::resolvedPokemonLightLevel,
|
||||
pokemon -> false
|
||||
)
|
||||
);
|
||||
|
||||
// Shouldered Pokémon
|
||||
// DynamicLightHandlers.registerDynamicLightHandler(
|
||||
// EntityType.PLAYER,
|
||||
// DynamicLightHandler.makeHandler(
|
||||
// player -> resolvedShoulderLightLevel(player, false),
|
||||
// player -> true
|
||||
// )
|
||||
// );
|
||||
// DynamicLightHandlers.registerDynamicLightHandler(
|
||||
// EntityType.PLAYER,
|
||||
// DynamicLightHandler.makeHandler(
|
||||
// player -> resolvedShoulderLightLevel(player, true),
|
||||
// player -> false
|
||||
// )
|
||||
// );
|
||||
DynamicLightHandlers.registerDynamicLightHandler(
|
||||
EntityType.PLAYER,
|
||||
DynamicLightHandler.makeHandler(
|
||||
LambDynamicLightsCompat::resolvedShoulderLightLevel,
|
||||
player -> false
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private static int resolvedPokemonLightLevel(PokemonEntity pokemon, boolean underwater) {
|
||||
private static int resolvedPokemonLightLevel(PokemonEntity pokemon) {
|
||||
var underwater = !pokemon.level().getFluidState(BlockPos.containing(pokemon.getX(), pokemon.getEyeY(), pokemon.getZ())).isEmpty();
|
||||
return extractFormLightLevel(pokemon.getForm(), underwater).orElse(0);
|
||||
}
|
||||
|
||||
private static int resolvedShoulderLightLevel(Player player, boolean underwater) {
|
||||
private static int resolvedShoulderLightLevel(Player player) {
|
||||
final var shoulderDataPair = PokemonOnShoulderRenderer.shoulderDataOf(player);
|
||||
var underwater = !player.level().getFluidState(BlockPos.containing(player.getX(), player.getEyeY(), player.getZ())).isEmpty();
|
||||
final Optional<Integer> leftLightLevel = extractShoulderLightLevel(shoulderDataPair.getFirst(), underwater);
|
||||
final Optional<Integer> rightLightLevel = extractShoulderLightLevel(shoulderDataPair.getSecond(), underwater);
|
||||
return Math.max(leftLightLevel.orElse(0), rightLightLevel.orElse(0));
|
||||
|
||||
+37
-3
@@ -10,11 +10,14 @@ package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding;
|
||||
import com.cobblemon.mod.common.item.PokedexItem;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext;
|
||||
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.MouseHandler;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.SmoothDouble;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -24,12 +27,20 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(MouseHandler.class)
|
||||
public class PartyScrollMixin {
|
||||
public class MouseHandlerMixin {
|
||||
@Shadow
|
||||
private double accumulatedScrollY;
|
||||
|
||||
@Shadow @Final private Minecraft minecraft;
|
||||
|
||||
@Shadow @Final private SmoothDouble smoothTurnY;
|
||||
|
||||
@Shadow @Final private SmoothDouble smoothTurnX;
|
||||
|
||||
@Shadow private double accumulatedDX;
|
||||
|
||||
@Shadow private double accumulatedDY;
|
||||
|
||||
@Inject(
|
||||
method = "onScroll",
|
||||
at = @At(
|
||||
@@ -74,4 +85,27 @@ public class PartyScrollMixin {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@WrapWithCondition(
|
||||
method = "turnPlayer",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/player/LocalPlayer;turn(DD)V"
|
||||
)
|
||||
)
|
||||
public boolean cobblemon$modifyRotation(LocalPlayer player, double cursorDeltaX, double cursorDeltaY, @Local(argsOnly = true) double d) {
|
||||
// I know this technically doesn't need to be a WrapWithCondition, but it'll make things easier later for riding.
|
||||
PokedexUsageContext usageContext = CobblemonClient.INSTANCE.getPokedexUsageContext();
|
||||
if (usageContext.getScanningGuiOpen()) {
|
||||
this.smoothTurnY.reset();
|
||||
this.smoothTurnX.reset();
|
||||
var defaultSensitivity = this.minecraft.options.sensitivity().get() * 0.6000000238418579 + 0.20000000298023224;
|
||||
var spyglassSensitivity = Math.pow(defaultSensitivity, 3);
|
||||
var lookSensitivity = spyglassSensitivity * 8.0;
|
||||
var sensitivity = Mth.lerp(usageContext.getFovMultiplier(), spyglassSensitivity, lookSensitivity);
|
||||
player.turn(this.accumulatedDX * sensitivity, (this.accumulatedDY * sensitivity));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,15 +12,23 @@ import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.CobblemonItems;
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents;
|
||||
import com.cobblemon.mod.common.api.events.item.LeftoversCreatedEvent;
|
||||
import com.cobblemon.mod.common.api.storage.NoPokemonStoreException;
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies;
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore;
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.ScannableEntity;
|
||||
import com.cobblemon.mod.common.pokemon.FormData;
|
||||
import com.cobblemon.mod.common.pokemon.Gender;
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon;
|
||||
import com.cobblemon.mod.common.pokemon.Species;
|
||||
import com.cobblemon.mod.common.util.CompoundTagExtensionsKt;
|
||||
import com.cobblemon.mod.common.util.CompoundTagUtilities;
|
||||
import com.cobblemon.mod.common.util.DataKeys;
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
@@ -30,19 +38,24 @@ import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.food.FoodProperties;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Mixin(Player.class)
|
||||
public abstract class PlayerMixin extends LivingEntity {
|
||||
public abstract class PlayerMixin extends LivingEntity implements ScannableEntity {
|
||||
|
||||
@Shadow public abstract CompoundTag getShoulderEntityLeft();
|
||||
|
||||
@@ -68,16 +81,16 @@ public abstract class PlayerMixin extends LivingEntity {
|
||||
@Inject(method = "respawnEntityOnShoulder", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;create(Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/world/level/Level;)Ljava/util/Optional;"), cancellable = true)
|
||||
private void cobblemon$removePokemon(CompoundTag nbt, CallbackInfo ci) {
|
||||
if (CompoundTagExtensionsKt.isPokemonEntity(nbt)) {
|
||||
final UUID uuid = this.getPokemonID(nbt);
|
||||
if (this.isShoulderPokemon(this.getShoulderEntityRight())) {
|
||||
final UUID uuidRight = this.getPokemonID(this.getShoulderEntityRight());
|
||||
final UUID uuid = CompoundTagUtilities.getPokemonID(nbt);
|
||||
if (CompoundTagUtilities.isShoulderPokemon(this.getShoulderEntityRight())) {
|
||||
final UUID uuidRight = CompoundTagUtilities.getPokemonID(this.getShoulderEntityRight());
|
||||
if (uuid.equals(uuidRight)) {
|
||||
this.recallPokemon(uuidRight);
|
||||
this.setShoulderEntityRight(new CompoundTag());
|
||||
}
|
||||
}
|
||||
if (this.isShoulderPokemon(this.getShoulderEntityLeft())) {
|
||||
final UUID uuidLeft = this.getPokemonID(this.getShoulderEntityLeft());
|
||||
if (CompoundTagUtilities.isShoulderPokemon(this.getShoulderEntityLeft())) {
|
||||
final UUID uuidLeft = CompoundTagUtilities.getPokemonID(this.getShoulderEntityLeft());
|
||||
if (uuid.equals(uuidLeft)) {
|
||||
this.recallPokemon(uuidLeft);
|
||||
this.setShoulderEntityLeft(new CompoundTag());
|
||||
@@ -101,22 +114,17 @@ public abstract class PlayerMixin extends LivingEntity {
|
||||
// We want to allow both of these to forcefully remove the entities
|
||||
if (this.isSpectator() || this.isDeadOrDying())
|
||||
return;
|
||||
if (!this.isShoulderPokemon(this.getShoulderEntityLeft())) {
|
||||
if (!CompoundTagUtilities.isShoulderPokemon(this.getShoulderEntityLeft())) {
|
||||
this.respawnEntityOnShoulder(this.getShoulderEntityLeft());
|
||||
this.setShoulderEntityLeft(new CompoundTag());
|
||||
}
|
||||
if (!this.isShoulderPokemon(this.getShoulderEntityRight())) {
|
||||
if (!CompoundTagUtilities.isShoulderPokemon(this.getShoulderEntityRight())) {
|
||||
this.respawnEntityOnShoulder(this.getShoulderEntityRight());
|
||||
this.setShoulderEntityRight(new CompoundTag());
|
||||
}
|
||||
ci.cancel();
|
||||
}
|
||||
|
||||
private UUID getPokemonID(CompoundTag nbt) {
|
||||
return nbt.getCompound(DataKeys.POKEMON)
|
||||
.getUUID(DataKeys.POKEMON_UUID);
|
||||
}
|
||||
|
||||
private void recallPokemon(UUID uuid) {
|
||||
// We need to do this cause the Entity doesn't store a reference to its storage
|
||||
final PartyStore party = Cobblemon.INSTANCE.getStorage().getParty(this.getUUID(), this.registryAccess());
|
||||
@@ -127,10 +135,6 @@ public abstract class PlayerMixin extends LivingEntity {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isShoulderPokemon(CompoundTag nbt) {
|
||||
return CompoundTagExtensionsKt.isPokemonEntity(nbt);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "eat",
|
||||
at = @At(
|
||||
@@ -171,4 +175,49 @@ public abstract class PlayerMixin extends LivingEntity {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override @Nullable
|
||||
public PokedexEntityData resolvePokemonScan() {
|
||||
if(CompoundTagUtilities.isShoulderPokemon(this.getShoulderEntityRight())){
|
||||
return getDataFromShoulderPokemon(this.getShoulderEntityRight());
|
||||
}
|
||||
if(CompoundTagUtilities.isShoulderPokemon(this.getShoulderEntityLeft())){
|
||||
return getDataFromShoulderPokemon(this.getShoulderEntityLeft());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable @Unique
|
||||
private PokedexEntityData getDataFromShoulderPokemon(CompoundTag shoulderTag) {
|
||||
CompoundTag pokemonTag = shoulderTag.getCompound(DataKeys.POKEMON);
|
||||
if(pokemonTag.isEmpty()) return null;
|
||||
Species species = PokemonSpecies.INSTANCE.getByIdentifier(ResourceLocation.parse(pokemonTag.getString(DataKeys.POKEMON_SPECIES_IDENTIFIER)));
|
||||
if(species == null) return null;
|
||||
String formId = pokemonTag.getString(DataKeys.POKEMON_FORM_ID);
|
||||
FormData form = species.getStandardForm();
|
||||
List<FormData> formList = species.getForms().stream().filter(it -> it.formOnlyShowdownId().equals(formId)).toList();
|
||||
if(!formList.isEmpty()) form = formList.getFirst();
|
||||
if(form == null) return null;
|
||||
String genderString = pokemonTag.getString(DataKeys.POKEMON_GENDER);
|
||||
if(genderString.isEmpty()) return null;
|
||||
Gender gender = Gender.valueOf(genderString);
|
||||
boolean shiny = pokemonTag.getBoolean(DataKeys.POKEMON_SHINY);
|
||||
int level = pokemonTag.getInt(DataKeys.POKEMON_LEVEL);
|
||||
Set<String> aspects = shoulderTag.getList(DataKeys.SHOULDER_ASPECTS, Tag.TAG_STRING).stream().map(Tag::getAsString).collect(Collectors.toSet());
|
||||
|
||||
return new PokedexEntityData(
|
||||
species,
|
||||
form,
|
||||
gender,
|
||||
aspects,
|
||||
shiny,
|
||||
level,
|
||||
this.getUUID()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LivingEntity resolveEntityScan() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import com.cobblemon.mod.common.client.render.ClientPlayerIcon;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
@@ -20,11 +20,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(PlayerRenderer.class)
|
||||
public class PlayerRendererMixin {
|
||||
@Inject(
|
||||
method = "render(Lnet/minecraft/client/player/AbstractClientPlayer;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V",
|
||||
at = @At(value = "TAIL")
|
||||
)
|
||||
|
||||
@Inject(method = "render", at = @At(value = "TAIL"))
|
||||
public void renderPlayer(AbstractClientPlayer player, float f, float g, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, CallbackInfo ci) {
|
||||
CobblemonClient.INSTANCE.getRequests().onRenderPlayer(player, g);
|
||||
ClientPlayerIcon.Companion.onRenderPlayer(player);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -9,6 +9,8 @@
|
||||
package com.cobblemon.mod.common.mixin.invoker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.cobblemon.mod.common.integration.AdornCompatibility;
|
||||
import juuxel.adorn.block.variant.BlockVariantSet;
|
||||
import juuxel.adorn.block.variant.BlockVariantSets;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
@@ -26,7 +28,7 @@ public abstract class AdornRegisterInvoker {
|
||||
private static List<BlockVariantSet> variantSets;
|
||||
|
||||
@Inject(method = "register()V", at = @At("HEAD"), remap = false)
|
||||
void register(CallbackInfo ci) {
|
||||
// variantSets.add(AdornCompatibility.INSTANCE);
|
||||
private static void register(CallbackInfo ci) {
|
||||
variantSets.add(new AdornCompatibility());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.api.drop.DropEntry
|
||||
import com.cobblemon.mod.common.api.drop.ItemDropEntry
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.DATA_SYNCHRONIZED
|
||||
import com.cobblemon.mod.common.api.interaction.RequestManager
|
||||
import com.cobblemon.mod.common.api.permission.PermissionValidator
|
||||
import com.cobblemon.mod.common.api.pokeball.catching.calculators.CaptureCalculator
|
||||
import com.cobblemon.mod.common.api.pokeball.catching.calculators.CaptureCalculators
|
||||
@@ -43,6 +44,7 @@ import com.cobblemon.mod.common.api.spawning.prospecting.SpawningProspector
|
||||
import com.cobblemon.mod.common.api.starter.StarterHandler
|
||||
import com.cobblemon.mod.common.api.storage.PokemonStoreManager
|
||||
import com.cobblemon.mod.common.api.storage.adapter.conversions.ReforgedConversion
|
||||
import com.cobblemon.mod.common.api.storage.adapter.database.MongoDBStoreAdapter
|
||||
import com.cobblemon.mod.common.api.storage.adapter.flatfile.FileStoreAdapter
|
||||
import com.cobblemon.mod.common.api.storage.adapter.flatfile.JSONStoreAdapter
|
||||
import com.cobblemon.mod.common.api.storage.adapter.flatfile.NBTStoreAdapter
|
||||
@@ -52,8 +54,7 @@ import com.cobblemon.mod.common.api.storage.pc.PCStore
|
||||
import com.cobblemon.mod.common.api.storage.pc.link.PCLinkManager
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreManager
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreTypes
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.DexDataNbtBackend
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.PlayerDataJsonBackend
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.*
|
||||
import com.cobblemon.mod.common.api.storage.player.factory.CachedPlayerDataStoreFactory
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonEntityTypeTags
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
@@ -97,6 +98,7 @@ import com.cobblemon.mod.common.pokemon.properties.HiddenAbilityPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.NoAIProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.UnaspectPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.BattleCloneProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.tags.PokemonFlagProperty
|
||||
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
|
||||
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
|
||||
@@ -105,7 +107,10 @@ import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.world.feature.CobblemonPlacedFeatures
|
||||
import com.cobblemon.mod.common.world.feature.ore.CobblemonOrePlacedFeatures
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
import com.mongodb.ConnectionString
|
||||
import com.mongodb.MongoClientSettings
|
||||
import com.mongodb.client.MongoClient
|
||||
import com.mongodb.client.MongoClients
|
||||
import java.io.File
|
||||
import java.io.FileReader
|
||||
import java.io.FileWriter
|
||||
@@ -209,7 +214,7 @@ object Cobblemon {
|
||||
BattleRegistry.onPlayerDisconnect(it.player)
|
||||
storage.onPlayerDisconnect(it.player)
|
||||
playerDataManager.onPlayerDisconnect(it.player)
|
||||
TradeManager.onLogoff(it.player)
|
||||
RequestManager.onLogoff(it.player)
|
||||
}
|
||||
PlatformEvents.PLAYER_DEATH.subscribe {
|
||||
PCLinkManager.removeLink(it.player.uuid)
|
||||
@@ -273,6 +278,7 @@ object Cobblemon {
|
||||
FlagSpeciesFeatureProvider(keys = listOf(DataKeys.HAS_BEEN_SHEARED), default = false))
|
||||
|
||||
CustomPokemonProperty.register(UncatchableProperty)
|
||||
CustomPokemonProperty.register(BattleCloneProperty)
|
||||
CustomPokemonProperty.register(PokemonFlagProperty)
|
||||
CustomPokemonProperty.register(HiddenAbilityPropertyType)
|
||||
CustomPokemonProperty.register(AspectPropertyType)
|
||||
@@ -280,6 +286,8 @@ object Cobblemon {
|
||||
CustomPokemonProperty.register(FreezeFrameProperty)
|
||||
CustomPokemonProperty.register(NoAIProperty)
|
||||
|
||||
CobblemonEvents.POKEMON_PROPERTY_INITIALISED.emit()
|
||||
|
||||
ifDedicatedServer {
|
||||
isDedicatedServer = true
|
||||
}
|
||||
@@ -320,9 +328,7 @@ object Cobblemon {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
"mongodb" -> {
|
||||
/*
|
||||
try {
|
||||
Class.forName("com.mongodb.client.MongoClient")
|
||||
|
||||
@@ -330,18 +336,22 @@ object Cobblemon {
|
||||
.applyConnectionString(ConnectionString(config.mongoDBConnectionString))
|
||||
.build()
|
||||
mongoClient = MongoClients.create(mongoClientSettings)
|
||||
val mongoFactory = MongoPlayerDataStoreFactory(mongoClient, config.mongoDBDatabaseName)
|
||||
playerData.setFactory(mongoFactory, PlayerInstancedDataStoreType.GENERAL)
|
||||
val generalMongoFactory = CachedPlayerDataStoreFactory(PlayerDataMongoBackend(mongoClient, config.mongoDBDatabaseName, "PlayerDataCollection"))
|
||||
generalMongoFactory.setup(server)
|
||||
|
||||
val pokedexMongoFactory = CachedPlayerDataStoreFactory(DexDataMongoBackend(mongoClient, config.mongoDBDatabaseName, "PokeDexCollection"))
|
||||
pokedexMongoFactory.setup(server)
|
||||
|
||||
playerDataManager.setFactory(generalMongoFactory, PlayerInstancedDataStoreTypes.GENERAL)
|
||||
playerDataManager.setFactory(pokedexMongoFactory, PlayerInstancedDataStoreTypes.POKEDEX)
|
||||
MongoDBStoreAdapter(mongoClient, config.mongoDBDatabaseName)
|
||||
} catch (e: ClassNotFoundException) {
|
||||
LOGGER.error("MongoDB driver not found.")
|
||||
throw e
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
else -> throw IllegalArgumentException("Unsupported storageFormat: ${config.storageFormat}")
|
||||
}
|
||||
@@ -378,6 +388,9 @@ object Cobblemon {
|
||||
}
|
||||
|
||||
registerEventHandlers()
|
||||
|
||||
CobblemonEvents.COBBLEMON_INITIALISED.emit()
|
||||
|
||||
}
|
||||
|
||||
fun registerEventHandlers() {
|
||||
|
||||
@@ -12,10 +12,10 @@ import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
object CobblemonActivities {
|
||||
val activities = mutableListOf<Activity>()
|
||||
val BATTLING_ACTIVITY = Activity("pokemon_battling")
|
||||
val NPC_BATTLING = Activity("npc_battling")
|
||||
val NPC_ACTION_EFFECT = Activity("npc_action_effect")
|
||||
val NPC_CHATTING = Activity("npc_chatting")
|
||||
val BATTLING_ACTIVITY = register(Activity("pokemon_battling"))
|
||||
val NPC_BATTLING = register(Activity("npc_battling"))
|
||||
val NPC_ACTION_EFFECT = register(Activity("npc_action_effect"))
|
||||
val NPC_CHATTING = register(Activity("npc_chatting"))
|
||||
|
||||
fun register(activity: Activity): Activity {
|
||||
activities.add(activity)
|
||||
|
||||
@@ -38,8 +38,6 @@ import net.minecraft.world.level.material.PushReaction
|
||||
@Suppress("SameParameterValue", "HasPlatformType", "MemberVisibilityCanBePrivate", "unused")
|
||||
object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<Block>>, Block>() {
|
||||
|
||||
|
||||
|
||||
override val registry: Registry<Block> = BuiltInRegistries.BLOCK
|
||||
override val resourceKey: ResourceKey<Registry<Block>> = Registries.BLOCK
|
||||
|
||||
@@ -117,8 +115,8 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
val APRICORN_FENCE = this.create("apricorn_fence", FenceBlock(BlockBehaviour.Properties.of().mapColor(APRICORN_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
|
||||
@JvmField
|
||||
val APRICORN_FENCE_GATE = this.create("apricorn_fence_gate", FenceGateBlock(APRICORN_WOOD_TYPE, BlockBehaviour.Properties.of().mapColor(APRICORN_PLANKS.defaultMapColor()).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
|
||||
@JvmField // Note At the time of 1.20.0 we don't need our own BlockSetType for Apricorn wood
|
||||
val APRICORN_BUTTON = this.create("apricorn_button", BlocksInvoker.createWoodenButtonBlock(BlockSetType.OAK))
|
||||
@JvmField
|
||||
val APRICORN_BUTTON = this.create("apricorn_button", BlocksInvoker.createWoodenButtonBlock(APRICORN_BLOCK_SET_TYPE))
|
||||
@JvmField
|
||||
val APRICORN_PRESSURE_PLATE = this.create("apricorn_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(APRICORN_BLOCK_SET_TYPE, BlockBehaviour.Properties.of().mapColor(APRICORN_PLANKS.defaultMapColor()).noCollission().strength(0.5f).sound(SoundType.WOOD)))
|
||||
@JvmField
|
||||
@@ -191,453 +189,113 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
val SMALL_BUDDING_BLACK_TUMBLESTONE = tumblestoneBlock("small_budding_black_tumblestone", GrowableStoneBlock.STAGE_0, 3, 4, MEDIUM_BUDDING_BLACK_TUMBLESTONE)
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE_BLOCK = this.create("tumblestone_block", Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
val TUMBLESTONE_BLOCK = this.create("tumblestone_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_ORANGE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val SKY_TUMBLESTONE_BLOCK = this.create("sky_tumblestone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_LIGHT_BLUE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
val SKY_TUMBLESTONE_BLOCK = this.create("sky_tumblestone_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val BLACK_TUMBLESTONE_BLOCK = this.create("black_tumblestone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_BLACK)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
val BLACK_TUMBLESTONE_BLOCK = this.create("black_tumblestone_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
|
||||
@JvmField
|
||||
val POLISHED_TUMBLESTONE = this.create("polished_tumblestone",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
val POLISHED_TUMBLESTONE = this.create("polished_tumblestone", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_ORANGE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val POLISHED_TUMBLESTONE_STAIRS = this.create("polished_tumblestone_stairs", StairsBlockInvoker.`cobblemon$create`(POLISHED_TUMBLESTONE.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(POLISHED_TUMBLESTONE)))
|
||||
@JvmField
|
||||
val POLISHED_TUMBLESTONE_SLAB = this.create("polished_tumblestone_slab", SlabBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
val POLISHED_TUMBLESTONE_SLAB = this.create("polished_tumblestone_slab", SlabBlock(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_ORANGE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val POLISHED_TUMBLESTONE_WALL = this.create("polished_tumblestone_wall", WallBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
val POLISHED_TUMBLESTONE_WALL = this.create("polished_tumblestone_wall", WallBlock(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_ORANGE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val CHISELED_POLISHED_TUMBLESTONE = this.create("chiseled_polished_tumblestone",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
val CHISELED_POLISHED_TUMBLESTONE = this.create("chiseled_polished_tumblestone", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_ORANGE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val SMOOTH_TUMBLESTONE = this.create("smooth_tumblestone",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
val SMOOTH_TUMBLESTONE = this.create("smooth_tumblestone", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_ORANGE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val SMOOTH_TUMBLESTONE_STAIRS = this.create("smooth_tumblestone_stairs", StairsBlockInvoker.`cobblemon$create`(SMOOTH_TUMBLESTONE.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(SMOOTH_TUMBLESTONE)))
|
||||
@JvmField
|
||||
val SMOOTH_TUMBLESTONE_SLAB = this.create("smooth_tumblestone_slab", SlabBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
val SMOOTH_TUMBLESTONE_SLAB = this.create("smooth_tumblestone_slab", SlabBlock(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_ORANGE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val TUMBLESTONE_BRICKS = this.create("tumblestone_bricks", Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
val TUMBLESTONE_BRICKS = this.create("tumblestone_bricks", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_ORANGE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val TUMBLESTONE_BRICK_STAIRS = this.create("tumblestone_brick_stairs", StairsBlockInvoker.`cobblemon$create`(TUMBLESTONE_BRICKS.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(TUMBLESTONE_BRICKS)))
|
||||
@JvmField
|
||||
val TUMBLESTONE_BRICK_SLAB = this.create("tumblestone_brick_slab", SlabBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
@JvmField
|
||||
val TUMBLESTONE_BRICK_WALL = this.create("tumblestone_brick_wall", WallBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
val TUMBLESTONE_BRICK_SLAB = this.create("tumblestone_brick_slab", SlabBlock(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_ORANGE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val CHISELED_TUMBLESTONE_BRICKS = this.create("chiseled_tumblestone_bricks",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
val TUMBLESTONE_BRICK_WALL = this.create("tumblestone_brick_wall", WallBlock(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_ORANGE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val POLISHED_SKY_TUMBLESTONE = this.create("polished_sky_tumblestone",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_LIGHT_BLUE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
val CHISELED_TUMBLESTONE_BRICKS = this.create("chiseled_tumblestone_bricks", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_ORANGE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
|
||||
@JvmField
|
||||
val POLISHED_SKY_TUMBLESTONE = this.create("polished_sky_tumblestone", Block(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val POLISHED_SKY_TUMBLESTONE_STAIRS = this.create("polished_sky_tumblestone_stairs", StairsBlockInvoker.`cobblemon$create`(POLISHED_SKY_TUMBLESTONE.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(POLISHED_SKY_TUMBLESTONE)))
|
||||
@JvmField
|
||||
val POLISHED_SKY_TUMBLESTONE_SLAB = this.create("polished_sky_tumblestone_slab", SlabBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_LIGHT_BLUE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
@JvmField
|
||||
val POLISHED_SKY_TUMBLESTONE_WALL = this.create("polished_sky_tumblestone_wall", WallBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_LIGHT_BLUE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
val POLISHED_SKY_TUMBLESTONE_SLAB = this.create("polished_sky_tumblestone_slab", SlabBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val CHISELED_POLISHED_SKY_TUMBLESTONE = this.create("chiseled_polished_sky_tumblestone",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_LIGHT_BLUE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
val POLISHED_SKY_TUMBLESTONE_WALL = this.create("polished_sky_tumblestone_wall", WallBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val SMOOTH_SKY_TUMBLESTONE = this.create("smooth_sky_tumblestone",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_LIGHT_BLUE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
val CHISELED_POLISHED_SKY_TUMBLESTONE = this.create("chiseled_polished_sky_tumblestone", Block(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val SMOOTH_SKY_TUMBLESTONE = this.create("smooth_sky_tumblestone", Block(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val SMOOTH_SKY_TUMBLESTONE_STAIRS = this.create("smooth_sky_tumblestone_stairs", StairsBlockInvoker.`cobblemon$create`(SMOOTH_SKY_TUMBLESTONE.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(SMOOTH_SKY_TUMBLESTONE)))
|
||||
@JvmField
|
||||
val SMOOTH_SKY_TUMBLESTONE_SLAB = this.create("smooth_sky_tumblestone_slab", SlabBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_LIGHT_BLUE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
val SMOOTH_SKY_TUMBLESTONE_SLAB = this.create("smooth_sky_tumblestone_slab", SlabBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val SKY_TUMBLESTONE_BRICKS = this.create("sky_tumblestone_bricks",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_LIGHT_BLUE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
val SKY_TUMBLESTONE_BRICKS = this.create("sky_tumblestone_bricks", Block(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val SKY_TUMBLESTONE_BRICK_STAIRS = this.create("sky_tumblestone_brick_stairs", StairsBlockInvoker.`cobblemon$create`(
|
||||
SKY_TUMBLESTONE_BRICKS.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(SKY_TUMBLESTONE_BRICKS)))
|
||||
val SKY_TUMBLESTONE_BRICK_STAIRS = this.create("sky_tumblestone_brick_stairs", StairsBlockInvoker.`cobblemon$create`(SKY_TUMBLESTONE_BRICKS.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(SKY_TUMBLESTONE_BRICKS)))
|
||||
@JvmField
|
||||
val SKY_TUMBLESTONE_BRICK_SLAB = this.create("sky_tumblestone_brick_slab", SlabBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_LIGHT_BLUE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
val SKY_TUMBLESTONE_BRICK_SLAB = this.create("sky_tumblestone_brick_slab", SlabBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val SKY_TUMBLESTONE_BRICK_WALL = this.create("sky_tumblestone_brick_wall", WallBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_LIGHT_BLUE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
val SKY_TUMBLESTONE_BRICK_WALL = this.create("sky_tumblestone_brick_wall", WallBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val CHISELED_SKY_TUMBLESTONE_BRICKS = this.create("chiseled_sky_tumblestone_bricks",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_LIGHT_BLUE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
val CHISELED_SKY_TUMBLESTONE_BRICKS = this.create("chiseled_sky_tumblestone_bricks", Block(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
|
||||
@JvmField
|
||||
val POLISHED_BLACK_TUMBLESTONE = this.create("polished_black_tumblestone",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_BLACK)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
val POLISHED_BLACK_TUMBLESTONE = this.create("polished_black_tumblestone", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val POLISHED_BLACK_TUMBLESTONE_STAIRS = this.create("polished_black_tumblestone_stairs", StairsBlockInvoker.`cobblemon$create`(POLISHED_BLACK_TUMBLESTONE.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(POLISHED_BLACK_TUMBLESTONE)))
|
||||
@JvmField
|
||||
val POLISHED_BLACK_TUMBLESTONE_SLAB = this.create("polished_black_tumblestone_slab", SlabBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_BLACK)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
@JvmField
|
||||
val POLISHED_BLACK_TUMBLESTONE_WALL = this.create("polished_black_tumblestone_wall", WallBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_BLACK)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
val POLISHED_BLACK_TUMBLESTONE_SLAB = this.create("polished_black_tumblestone_slab", SlabBlock(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val CHISELED_POLISHED_BLACK_TUMBLESTONE = this.create("chiseled_polished_black_tumblestone",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_BLACK)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
|
||||
val POLISHED_BLACK_TUMBLESTONE_WALL = this.create("polished_black_tumblestone_wall", WallBlock(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val SMOOTH_BLACK_TUMBLESTONE = this.create("smooth_black_tumblestone",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_BLACK)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
val CHISELED_POLISHED_BLACK_TUMBLESTONE = this.create("chiseled_polished_black_tumblestone", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val SMOOTH_BLACK_TUMBLESTONE = this.create("smooth_black_tumblestone", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val SMOOTH_BLACK_TUMBLESTONE_STAIRS = this.create("smooth_black_tumblestone_stairs", StairsBlockInvoker.`cobblemon$create`(SMOOTH_BLACK_TUMBLESTONE.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(SMOOTH_BLACK_TUMBLESTONE)))
|
||||
@JvmField
|
||||
val SMOOTH_BLACK_TUMBLESTONE_SLAB = this.create("smooth_black_tumblestone_slab", SlabBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_BLACK)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
val SMOOTH_BLACK_TUMBLESTONE_SLAB = this.create("smooth_black_tumblestone_slab", SlabBlock(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val BLACK_TUMBLESTONE_BRICKS = this.create("black_tumblestone_bricks",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_BLACK)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
val BLACK_TUMBLESTONE_BRICKS = this.create("black_tumblestone_bricks", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val BLACK_TUMBLESTONE_BRICK_STAIRS = this.create("black_tumblestone_brick_stairs", StairsBlockInvoker.`cobblemon$create`(
|
||||
BLACK_TUMBLESTONE_BRICKS.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(BLACK_TUMBLESTONE_BRICKS)))
|
||||
val BLACK_TUMBLESTONE_BRICK_STAIRS = this.create("black_tumblestone_brick_stairs", StairsBlockInvoker.`cobblemon$create`(BLACK_TUMBLESTONE_BRICKS.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(BLACK_TUMBLESTONE_BRICKS)))
|
||||
@JvmField
|
||||
val BLACK_TUMBLESTONE_BRICK_SLAB = this.create("black_tumblestone_brick_slab", SlabBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_BLACK)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
val BLACK_TUMBLESTONE_BRICK_SLAB = this.create("black_tumblestone_brick_slab", SlabBlock(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val BLACK_TUMBLESTONE_BRICK_WALL = this.create("black_tumblestone_brick_wall", WallBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_BLACK)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
val BLACK_TUMBLESTONE_BRICK_WALL = this.create("black_tumblestone_brick_wall", WallBlock(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
val CHISELED_BLACK_TUMBLESTONE_BRICKS = this.create("chiseled_black_tumblestone_bricks",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_BLACK)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
val CHISELED_BLACK_TUMBLESTONE_BRICKS = this.create("chiseled_black_tumblestone_bricks", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
|
||||
@JvmField
|
||||
val FIRE_STONE_BLOCK = this.create("fire_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.FIRE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val WATER_STONE_BLOCK = this.create("water_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.WATER)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
val FIRE_STONE_BLOCK = this.create("fire_stone_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.FIRE).strength(1.0F).sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BIT).lightLevel{13}))
|
||||
@JvmField
|
||||
val THUNDER_STONE_BLOCK = this.create("thunder_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.GLOW_LICHEN)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
val WATER_STONE_BLOCK = this.create("water_stone_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.WATER).strength(1.0F).sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BIT)))
|
||||
@JvmField
|
||||
val LEAF_STONE_BLOCK = this.create("leaf_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_GREEN)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
val THUNDER_STONE_BLOCK = this.create("thunder_stone_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.GLOW_LICHEN).strength(1.0F).sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BIT).lightLevel{8}))
|
||||
@JvmField
|
||||
val ICE_STONE_BLOCK = this.create("ice_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.ICE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
val LEAF_STONE_BLOCK = this.create("leaf_stone_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_GREEN).strength(1.0F).sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BIT)))
|
||||
@JvmField
|
||||
val SUN_STONE_BLOCK = this.create("sun_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
val ICE_STONE_BLOCK = this.create("ice_stone_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.ICE).strength(1.0F).sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BIT)))
|
||||
@JvmField
|
||||
val MOON_STONE_BLOCK = this.create("moon_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.DEEPSLATE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
val SUN_STONE_BLOCK = this.create("sun_stone_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_ORANGE).strength(1.0F).sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BIT).lightLevel{5}))
|
||||
@JvmField
|
||||
val SHINY_STONE_BLOCK = this.create("shiny_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.QUARTZ)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
val MOON_STONE_BLOCK = this.create("moon_stone_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.DEEPSLATE).strength(1.0F).sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BIT)))
|
||||
@JvmField
|
||||
val DAWN_STONE_BLOCK = this.create("dawn_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.DIAMOND)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
val SHINY_STONE_BLOCK = this.create("shiny_stone_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.QUARTZ).strength(1.0F).sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BIT).lightLevel{15}))
|
||||
@JvmField
|
||||
val DUSK_STONE_BLOCK = this.create("dusk_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.WARPED_HYPHAE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
val DAWN_STONE_BLOCK = this.create("dawn_stone_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.DIAMOND).strength(1.0F).sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BIT).lightLevel{15}))
|
||||
@JvmField
|
||||
val DUSK_STONE_BLOCK = this.create("dusk_stone_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.WARPED_HYPHAE).strength(1.0F).sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BIT)))
|
||||
|
||||
@JvmField
|
||||
val BLACK_APRICORN = apricornBlock("black_apricorn", Apricorn.BLACK)
|
||||
@@ -655,188 +313,48 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
val YELLOW_APRICORN = apricornBlock("yellow_apricorn", Apricorn.YELLOW)
|
||||
|
||||
@JvmField
|
||||
val RELIC_COIN_POUCH = create(
|
||||
"relic_coin_pouch",
|
||||
CoinPouchBlock(
|
||||
BlockBehaviour.Properties.of()
|
||||
.sound(CobblemonSounds.RELIC_COIN_POUCH_SOUNDS)
|
||||
.pushReaction(PushReaction.DESTROY)
|
||||
.noOcclusion(), true
|
||||
)
|
||||
)
|
||||
val RELIC_COIN_POUCH = create("relic_coin_pouch", CoinPouchBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.RELIC_COIN_POUCH_SOUNDS).pushReaction(PushReaction.DESTROY).noOcclusion(), true))
|
||||
@JvmField
|
||||
val RELIC_COIN_SACK = create(
|
||||
"relic_coin_sack",
|
||||
CoinPouchBlock(
|
||||
BlockBehaviour.Properties.of()
|
||||
.sound(CobblemonSounds.RELIC_COIN_SACK_SOUNDS)
|
||||
.pushReaction(PushReaction.DESTROY)
|
||||
.strength(0.4f), false
|
||||
))
|
||||
val RELIC_COIN_SACK = create("relic_coin_sack", CoinPouchBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.RELIC_COIN_SACK_SOUNDS).pushReaction(PushReaction.DESTROY).strength(0.4f), false))
|
||||
|
||||
@JvmField
|
||||
val GILDED_CHEST = create(
|
||||
"gilded_chest",
|
||||
GildedChestBlock(
|
||||
BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS),
|
||||
GildedChestBlock.Type.RED
|
||||
)
|
||||
)
|
||||
val GILDED_CHEST = create("gilded_chest", GildedChestBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS), GildedChestBlock.Type.RED))
|
||||
@JvmField
|
||||
val BLUE_GILDED_CHEST = create("blue_gilded_chest", GildedChestBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS), GildedChestBlock.Type.BLUE))
|
||||
@JvmField
|
||||
val BLACK_GILDED_CHEST = create("black_gilded_chest", GildedChestBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS), GildedChestBlock.Type.BLACK))
|
||||
@JvmField
|
||||
val YELLOW_GILDED_CHEST = create("yellow_gilded_chest", GildedChestBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS), GildedChestBlock.Type.YELLOW))
|
||||
@JvmField
|
||||
val WHITE_GILDED_CHEST = create("white_gilded_chest", GildedChestBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS), GildedChestBlock.Type.WHITE))
|
||||
@JvmField
|
||||
val GREEN_GILDED_CHEST = create("green_gilded_chest", GildedChestBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS), GildedChestBlock.Type.GREEN))
|
||||
@JvmField
|
||||
val PINK_GILDED_CHEST = create("pink_gilded_chest", GildedChestBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS), GildedChestBlock.Type.PINK))
|
||||
@JvmField
|
||||
val GIMMIGHOUL_CHEST = create("gimmighoul_chest", GildedChestBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS), GildedChestBlock.Type.FAKE))
|
||||
|
||||
@JvmField
|
||||
val BLUE_GILDED_CHEST = create(
|
||||
"blue_gilded_chest",
|
||||
GildedChestBlock(
|
||||
BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS),
|
||||
GildedChestBlock.Type.BLUE
|
||||
)
|
||||
)
|
||||
val MONITOR = create("monitor", MonitorBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).lightLevel { if (it.getValue(MonitorBlock.SCREEN) != MonitorBlock.MonitorScreen.OFF) 15 else 0 }))
|
||||
@JvmField
|
||||
val FOSSIL_ANALYZER = create("fossil_analyzer", FossilAnalyzerBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).noOcclusion()))
|
||||
@JvmField
|
||||
val RESTORATION_TANK = create("restoration_tank", RestorationTankBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.GLASS).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).noOcclusion()))
|
||||
|
||||
@JvmField
|
||||
val BLACK_GILDED_CHEST = create(
|
||||
"black_gilded_chest",
|
||||
GildedChestBlock(
|
||||
BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS),
|
||||
GildedChestBlock.Type.BLACK
|
||||
)
|
||||
)
|
||||
val HEALING_MACHINE = create("healing_machine", HealingMachineBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2f).noOcclusion().lightLevel { if (it.getValue(HealingMachineBlock.CHARGE_LEVEL) >= HealingMachineBlock.MAX_CHARGE_LEVEL) 7 else 2 }))
|
||||
|
||||
@JvmField
|
||||
val YELLOW_GILDED_CHEST = create(
|
||||
"yellow_gilded_chest",
|
||||
GildedChestBlock(
|
||||
BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS),
|
||||
GildedChestBlock.Type.YELLOW
|
||||
)
|
||||
)
|
||||
val PC = create("pc", PCBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F).noOcclusion().lightLevel { if ((it.getValue(PCBlock.ON) as Boolean) && (it.getValue(PCBlock.PART) == PCBlock.PCPart.TOP)) 10 else 0 }))
|
||||
|
||||
@JvmField
|
||||
val WHITE_GILDED_CHEST = create(
|
||||
"white_gilded_chest",
|
||||
GildedChestBlock(
|
||||
BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS),
|
||||
GildedChestBlock.Type.WHITE
|
||||
)
|
||||
)
|
||||
val LECTERN = create("lectern", LecternBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).sound(SoundType.WOOD).strength(2.5F).ignitedByLava()))
|
||||
|
||||
@JvmField
|
||||
val GREEN_GILDED_CHEST = create(
|
||||
"green_gilded_chest",
|
||||
GildedChestBlock(
|
||||
BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS),
|
||||
GildedChestBlock.Type.GREEN
|
||||
)
|
||||
)
|
||||
val DISPLAY_CASE = create("display_case", DisplayCaseBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.DISPLAY_CASE_SOUNDS).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.STONE).strength(0.3F)))
|
||||
|
||||
@JvmField
|
||||
val PINK_GILDED_CHEST = create(
|
||||
"pink_gilded_chest",
|
||||
GildedChestBlock(
|
||||
BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS),
|
||||
GildedChestBlock.Type.PINK
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val GIMMIGHOUL_CHEST = create(
|
||||
"gimmighoul_chest",
|
||||
GildedChestBlock(
|
||||
BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS),
|
||||
GildedChestBlock.Type.FAKE
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val MONITOR = create(
|
||||
"monitor",
|
||||
MonitorBlock(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.METAL)
|
||||
.sound(SoundType.METAL)
|
||||
.pushReaction(PushReaction.BLOCK)
|
||||
.requiresCorrectToolForDrops()
|
||||
.strength(5.0F, 6.0F)
|
||||
.lightLevel { if (it.getValue(MonitorBlock.SCREEN) != MonitorBlock.MonitorScreen.OFF) 15 else 0 }
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val FOSSIL_ANALYZER = create(
|
||||
"fossil_analyzer",
|
||||
FossilAnalyzerBlock(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.METAL)
|
||||
.sound(SoundType.METAL)
|
||||
.pushReaction(PushReaction.BLOCK)
|
||||
.requiresCorrectToolForDrops()
|
||||
.strength(5.0F, 6.0F)
|
||||
.noOcclusion()
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val RESTORATION_TANK = create(
|
||||
"restoration_tank",
|
||||
RestorationTankBlock(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.METAL)
|
||||
.sound(SoundType.GLASS)
|
||||
.pushReaction(PushReaction.BLOCK)
|
||||
.requiresCorrectToolForDrops()
|
||||
.strength(5.0F, 6.0F)
|
||||
.noOcclusion()
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val HEALING_MACHINE = create(
|
||||
"healing_machine",
|
||||
HealingMachineBlock(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.METAL)
|
||||
.sound(SoundType.METAL)
|
||||
.pushReaction(PushReaction.BLOCK)
|
||||
.strength(2f)
|
||||
.noOcclusion()
|
||||
.lightLevel { if (it.getValue(HealingMachineBlock.CHARGE_LEVEL) >= HealingMachineBlock.MAX_CHARGE_LEVEL) 7 else 2 }
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val PC = create(
|
||||
"pc",
|
||||
PCBlock(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.METAL)
|
||||
.sound(SoundType.METAL)
|
||||
.pushReaction(PushReaction.BLOCK)
|
||||
.strength(2F)
|
||||
.noOcclusion()
|
||||
.lightLevel { if ((it.getValue(PCBlock.ON) as Boolean) && (it.getValue(PCBlock.PART) == PCBlock.PCPart.TOP)) 10 else 0 }
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val LECTERN = create(
|
||||
"lectern",
|
||||
LecternBlock(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.WOOD)
|
||||
.instrument(NoteBlockInstrument.BASS)
|
||||
.sound(SoundType.WOOD)
|
||||
.strength(2.5F)
|
||||
.ignitedByLava()
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val DISPLAY_CASE = create(
|
||||
"display_case",
|
||||
DisplayCaseBlock(
|
||||
BlockBehaviour.Properties.of()
|
||||
.sound(CobblemonSounds.DISPLAY_CASE_SOUNDS)
|
||||
.noOcclusion()
|
||||
.pushReaction(PushReaction.BLOCK)
|
||||
.mapColor(MapColor.STONE)
|
||||
.strength(0.3F)
|
||||
)
|
||||
)
|
||||
val PASTURE = create("pasture", PastureBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BROWN).sound(SoundType.WOOD).strength(2F).noOcclusion().pushReaction(PushReaction.BLOCK).lightLevel { if ((it.getValue(PastureBlock.ON) as Boolean) && (it.getValue(PastureBlock.PART) == PastureBlock.PasturePart.TOP)) 10 else 0 }))
|
||||
|
||||
val RED_MINT = create("red_mint", MintBlock(MintType.RED, BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_RED).noCollission().randomTicks().instabreak().sound(CobblemonSounds.MINT_SOUNDS).pushReaction(PushReaction.DESTROY)))
|
||||
@JvmField
|
||||
@@ -850,20 +368,6 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val WHITE_MINT = create("white_mint", MintBlock(MintType.WHITE, BlockBehaviour.Properties.of().mapColor(MapColor.SNOW).noCollission().randomTicks().instabreak().sound(CobblemonSounds.MINT_SOUNDS).pushReaction(PushReaction.DESTROY)))
|
||||
|
||||
@JvmField
|
||||
val PASTURE = create(
|
||||
"pasture",
|
||||
PastureBlock(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_BROWN)
|
||||
.sound(SoundType.WOOD)
|
||||
.strength(2F)
|
||||
.noOcclusion()
|
||||
.pushReaction(PushReaction.BLOCK)
|
||||
.lightLevel { if ((it.getValue(PastureBlock.ON) as Boolean) && (it.getValue(PastureBlock.PART) == PastureBlock.PasturePart.TOP)) 10 else 0 }
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE_SEEDS = this.create("vivichoke_seeds", VivichokeBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).ignitedByLava().mapColor(MapColor.PLANT).noCollission().randomTicks().instabreak().sound(CobblemonSounds.VIVICHOKE_SOUNDS)))
|
||||
@JvmField
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.api.ai.config.BrainConfig
|
||||
import com.cobblemon.mod.common.api.ai.config.task.TaskConfig
|
||||
import com.cobblemon.mod.common.api.data.DataRegistry
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.util.adapters.ActivityAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.BrainConfigAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.TaskConfigAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
object CobblemonBrainConfigs : JsonDataRegistry<List<BrainConfig>> {
|
||||
override val gson: Gson = GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.registerTypeAdapter(Activity::class.java, ActivityAdapter)
|
||||
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(BrainConfig::class.java, BrainConfigAdapter)
|
||||
.registerTypeAdapter(TaskConfig::class.java, TaskConfigAdapter)
|
||||
.create()
|
||||
|
||||
override val typeToken = TypeToken.getParameterized(List::class.java, BrainConfig::class.java) as TypeToken<List<BrainConfig>>
|
||||
override val resourcePath = "brain_presets"
|
||||
override val id: ResourceLocation = cobblemonResource("brain_presets")
|
||||
override val type = PackType.SERVER_DATA
|
||||
override val observable = SimpleObservable<CobblemonBrainConfigs>()
|
||||
|
||||
val presets = mutableMapOf<ResourceLocation, List<BrainConfig>>()
|
||||
|
||||
override fun sync(player: ServerPlayer) {
|
||||
// TODO implement probs ay
|
||||
}
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, List<BrainConfig>>) {
|
||||
presets.clear()
|
||||
presets.putAll(data)
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ object CobblemonCommands {
|
||||
SpawnNPCCommand.register(dispatcher)
|
||||
GivePokemon.register(dispatcher)
|
||||
TakePokemon.register(dispatcher)
|
||||
ChangeEyeHeight.register(dispatcher)
|
||||
ChangeScaleAndSize.register(dispatcher)
|
||||
ChangeWalkSpeed.register(dispatcher)
|
||||
TestCommand.register(dispatcher)
|
||||
|
||||
@@ -153,20 +153,21 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val ANCIENT_ORIGIN_BALL = pokeBallItem(PokeBalls.ANCIENT_ORIGIN_BALL)
|
||||
|
||||
val pokedexes = mutableListOf<PokedexItem>()
|
||||
@JvmField
|
||||
val POKEDEX_BLACK = create("pokedex_black", PokedexItem(PokedexTypes.BLACK))
|
||||
val POKEDEX_RED = pokedexItem(PokedexTypes.RED)
|
||||
@JvmField
|
||||
val POKEDEX_BLUE = create("pokedex_blue", PokedexItem(PokedexTypes.BLUE))
|
||||
val POKEDEX_YELLOW = pokedexItem(PokedexTypes.YELLOW)
|
||||
@JvmField
|
||||
val POKEDEX_GREEN = create("pokedex_green", PokedexItem(PokedexTypes.GREEN))
|
||||
val POKEDEX_GREEN = pokedexItem(PokedexTypes.GREEN)
|
||||
@JvmField
|
||||
val POKEDEX_PINK = create("pokedex_pink", PokedexItem(PokedexTypes.PINK))
|
||||
val POKEDEX_BLUE = pokedexItem(PokedexTypes.BLUE)
|
||||
@JvmField
|
||||
val POKEDEX_RED = create("pokedex_red", PokedexItem(PokedexTypes.RED))
|
||||
val POKEDEX_PINK = pokedexItem(PokedexTypes.PINK)
|
||||
@JvmField
|
||||
val POKEDEX_WHITE = create("pokedex_white", PokedexItem(PokedexTypes.WHITE))
|
||||
val POKEDEX_BLACK = pokedexItem(PokedexTypes.BLACK)
|
||||
@JvmField
|
||||
val POKEDEX_YELLOW = create("pokedex_yellow", PokedexItem(PokedexTypes.YELLOW))
|
||||
val POKEDEX_WHITE = pokedexItem(PokedexTypes.WHITE)
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE = compostableItem("vivichoke")
|
||||
@@ -1247,6 +1248,12 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
return item
|
||||
}
|
||||
|
||||
private fun pokedexItem(type: PokedexTypes): PokedexItem {
|
||||
val item = create("pokedex_${type.name.lowercase()}", PokedexItem(type))
|
||||
pokedexes.add(item)
|
||||
return item
|
||||
}
|
||||
|
||||
private fun heldItem(name: String, remappedName: String? = null): CobblemonItem = create(
|
||||
name,
|
||||
CobblemonItem(Item.Properties()).also {
|
||||
|
||||
@@ -51,13 +51,7 @@ import com.cobblemon.mod.common.client.net.storage.pc.OpenPCHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.pc.SetPCBoxPokemonHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.pc.SetPCPokemonHandler
|
||||
import com.cobblemon.mod.common.client.net.toast.ToastPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeAcceptanceChangedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeCancelledHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeCompletedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeOfferExpiredHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeOfferNotificationHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeStartedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeUpdatedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.*
|
||||
import com.cobblemon.mod.common.net.PacketRegisterInfo
|
||||
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimationPacket
|
||||
@@ -100,20 +94,10 @@ import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyPokemo
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyReferencePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.messages.client.toast.ToastPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeAcceptanceChangedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeCompletedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferExpiredPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotificationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.PokedexUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.*
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.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
|
||||
@@ -141,15 +125,7 @@ import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePartyPokemonT
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.ReleasePCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.SwapPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.UnlinkPlayerFromPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.AcceptTradeRequestPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.CancelTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptancePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.*
|
||||
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
|
||||
@@ -185,10 +161,15 @@ import com.cobblemon.mod.common.net.serverhandling.trade.CancelTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.*
|
||||
import com.cobblemon.mod.common.net.messages.client.pokedex.ServerConfirmedRegisterPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.*
|
||||
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.FinishScanningPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.FinishScanningHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.StartScanningHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.*
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
@@ -341,6 +322,7 @@ object CobblemonNetwork {
|
||||
|
||||
// Trade packets
|
||||
list.add(PacketRegisterInfo(TradeAcceptanceChangedPacket.ID, TradeAcceptanceChangedPacket::decode, TradeAcceptanceChangedHandler))
|
||||
list.add(PacketRegisterInfo(TradeProcessStartedPacket.ID, TradeProcessStartedPacket::decode, TradeProcessStartedHandler))
|
||||
list.add(PacketRegisterInfo(TradeCancelledPacket.ID, TradeCancelledPacket::decode, TradeCancelledHandler))
|
||||
list.add(PacketRegisterInfo(TradeCompletedPacket.ID, TradeCompletedPacket::decode, TradeCompletedHandler))
|
||||
list.add(PacketRegisterInfo(TradeUpdatedPacket.ID, TradeUpdatedPacket::decode, TradeUpdatedHandler))
|
||||
@@ -428,6 +410,7 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(AcceptTradeRequestPacket.ID, AcceptTradeRequestPacket::decode, AcceptTradeRequestHandler))
|
||||
list.add(PacketRegisterInfo(CancelTradePacket.ID, CancelTradePacket::decode, CancelTradeHandler))
|
||||
list.add(PacketRegisterInfo(ChangeTradeAcceptancePacket.ID, ChangeTradeAcceptancePacket::decode, ChangeTradeAcceptanceHandler))
|
||||
list.add(PacketRegisterInfo(PerformTradePacket.ID, PerformTradePacket::decode, PerformTradeHandler))
|
||||
list.add(PacketRegisterInfo(OfferTradePacket.ID, OfferTradePacket::decode, OfferTradeHandler))
|
||||
list.add(PacketRegisterInfo(UpdateTradeOfferPacket.ID, UpdateTradeOfferPacket::decode, UpdateTradeOfferHandler))
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
|
||||
@JvmField
|
||||
val GUI_CLICK = this.create("gui.click")
|
||||
@JvmField
|
||||
val GUI_TRADE = this.create("gui.trade")
|
||||
|
||||
@JvmField
|
||||
val PC_ON = this.create("pc.on")
|
||||
@@ -42,7 +44,7 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
@JvmField
|
||||
val VILLAGER_WORK_NURSE = this.create("entity.villager.work_nurse")
|
||||
@JvmField
|
||||
val HEALING_MACHINE_ACTIVE = this.create("healing_machine.active")
|
||||
val HEALING_MACHINE_ACTIVE = this.create("block.healing_machine.active")
|
||||
|
||||
@JvmField
|
||||
val POKE_BALL_CAPTURE_STARTED = this.create("poke_ball.capture_started")
|
||||
@@ -107,61 +109,56 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
val PVW_BATTLE = this.create("battle.pvw.default")
|
||||
|
||||
@JvmField
|
||||
val MEDICINE_HERB_USE = this.create("medicine_herb.use")
|
||||
val MEDICINE_HERB_USE = this.create("item.medicine.herb.use")
|
||||
@JvmField
|
||||
val MEDICINE_LIQUID_USE = this.create("medicine_liquid.use")
|
||||
val MEDICINE_LIQUID_USE = this.create("item.medicine.liquid.use")
|
||||
@JvmField
|
||||
val MEDICINE_PILLS_USE = this.create("medicine_pills.use")
|
||||
val MEDICINE_PILLS_USE = this.create("item.medicine.pills.use")
|
||||
@JvmField
|
||||
val MEDICINE_SPRAY_USE = this.create("medicine_spray.use")
|
||||
val MEDICINE_SPRAY_USE = this.create("item.medicine.spray.use")
|
||||
@JvmField
|
||||
val MEDICINE_FEATHER_USE = this.create("medicine_feather.use")
|
||||
val MEDICINE_FEATHER_USE = this.create("item.medicine.feather.use")
|
||||
|
||||
@JvmField
|
||||
val BERRY_HARVEST = this.create("berry.harvest")
|
||||
val MULCH_PLACE = this.create("block.mulch.place")
|
||||
@JvmField
|
||||
val BERRY_EAT = this.create("berry.eat")
|
||||
val MULCH_REMOVE = this.create("block.mulch.remove")
|
||||
|
||||
@JvmField
|
||||
val MULCH_PLACE = this.create("mulch.place")
|
||||
val FOSSIL_MACHINE_ACTIVATE = this.create("block.fossil_machine.activate")
|
||||
@JvmField
|
||||
val MULCH_REMOVE = this.create("mulch.remove")
|
||||
val FOSSIL_MACHINE_ACTIVE_LOOP = this.create("block.fossil_machine.active_loop")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_ASSEMBLE = this.create("block.fossil_machine.assemble")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_DNA_FULL = this.create("block.fossil_machine.dna_full")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_FINISHED = this.create("block.fossil_machine.finished")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_INSERT_DNA = this.create("block.fossil_machine.insert_dna")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_INSERT_DNA_SMALL = this.create("block.fossil_machine.insert_dna_small")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_INSERT_FOSSIL = this.create("block.fossil_machine.insert_fossil")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_RETRIEVE_FOSSIL = this.create("block.fossil_machine.retrieve_fossil")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_RETRIEVE_POKEMON = this.create("block.fossil_machine.retrieve_pokemon")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_UNPROTECTED = this.create("block.fossil_machine.unprotected")
|
||||
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_ACTIVATE = this.create("fossil_machine.activate")
|
||||
val RELIC_COIN_SACK_BREAK = this.create("block.relic_coin_sack.break")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_ACTIVE_LOOP = this.create("fossil_machine.active_loop")
|
||||
val RELIC_COIN_SACK_HIT = this.create("block.relic_coin_sack.hit")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_ASSEMBLE = this.create("fossil_machine.assemble")
|
||||
val RELIC_COIN_SACK_STEP = this.create("block.relic_coin_sack.step")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_DNA_FULL = this.create("fossil_machine.dna_full")
|
||||
val RELIC_COIN_SACK_PLACE = this.create("block.relic_coin_sack.place")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_FINISHED = this.create("fossil_machine.finished")
|
||||
val RELIC_COIN_POUCH_BREAK = this.create("block.relic_coin_pouch.break")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_INSERT_DNA = this.create("fossil_machine.insert_dna")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_INSERT_DNA_SMALL = this.create("fossil_machine.insert_dna_small")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_INSERT_FOSSIL = this.create("fossil_machine.insert_fossil")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_RETRIEVE_FOSSIL = this.create("fossil_machine.retrieve_fossil")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_RETRIEVE_POKEMON = this.create("fossil_machine.retrieve_pokemon")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_UNPROTECTED = this.create("fossil_machine.unprotected")
|
||||
|
||||
@JvmField
|
||||
val RELIC_COIN_SACK_BREAK = this.create("relic_coin_sack.break")
|
||||
@JvmField
|
||||
val RELIC_COIN_SACK_HIT = this.create("relic_coin_sack.hit")
|
||||
@JvmField
|
||||
val RELIC_COIN_SACK_STEP = this.create("relic_coin_sack.step")
|
||||
@JvmField
|
||||
val RELIC_COIN_SACK_PLACE = this.create("relic_coin_sack.place")
|
||||
@JvmField
|
||||
val RELIC_COIN_POUCH_BREAK = this.create("relic_coin_pouch.break")
|
||||
@JvmField
|
||||
val RELIC_COIN_POUCH_PLACE = this.create("relic_coin_pouch.place")
|
||||
val RELIC_COIN_POUCH_PLACE = this.create("block.relic_coin_pouch.place")
|
||||
|
||||
@JvmField
|
||||
val FISHING_NOTIFICATION = this.create("fishing.notification")
|
||||
@@ -179,73 +176,78 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
val FISHING_BAIT_ATTACH = this.create("fishing.bait_attach")
|
||||
@JvmField
|
||||
val FISHING_BAIT_DETACH = this.create("fishing.bait_detach")
|
||||
@JvmField
|
||||
val TUMBLESTONE_BREAK = this.create("tumblestone.break")
|
||||
@JvmField
|
||||
val TUMBLESTONE_BLOCK_BREAK = this.create("tumblestone.block_break")
|
||||
@JvmField
|
||||
val TUMBLESTONE_HIT = this.create("tumblestone.hit")
|
||||
@JvmField
|
||||
val TUMBLESTONE_PLACE = this.create("tumblestone.place")
|
||||
@JvmField
|
||||
val TUMBLESTONE_STEP = this.create("tumblestone.step")
|
||||
|
||||
@JvmField
|
||||
val EVOLUTION_STONE_BLOCK_BREAK = this.create("evolution_stone_block.break")
|
||||
val TUMBLESTONE_BREAK = this.create("block.tumblestone.break")
|
||||
@JvmField
|
||||
val EVOLUTION_STONE_BLOCK_HIT = this.create("evolution_stone_block.hit")
|
||||
val TUMBLESTONE_BLOCK_BREAK = this.create("block.tumblestone.block_break")
|
||||
@JvmField
|
||||
val EVOLUTION_STONE_BLOCK_PLACE = this.create("evolution_stone_block.place")
|
||||
val TUMBLESTONE_HIT = this.create("block.tumblestone.hit")
|
||||
@JvmField
|
||||
val EVOLUTION_STONE_BLOCK_STEP = this.create("evolution_stone_block.step")
|
||||
val TUMBLESTONE_PLACE = this.create("block.tumblestone.place")
|
||||
@JvmField
|
||||
val TUMBLESTONE_STEP = this.create("block.tumblestone.step")
|
||||
|
||||
@JvmField
|
||||
val GIMMIGHOUL_GIVE_ITEM_SMALL = this.create("gimmighoul.give_item_small")
|
||||
val EVOLUTION_STONE_BLOCK_BREAK = this.create("block.evolution_stone_block.break")
|
||||
@JvmField
|
||||
val GIMMIGHOUL_REVEAL = this.create("gimmighoul.reveal")
|
||||
val EVOLUTION_STONE_BLOCK_HIT = this.create("block.evolution_stone_block.hit")
|
||||
@JvmField
|
||||
val EVOLUTION_STONE_BLOCK_PLACE = this.create("block.evolution_stone_block.place")
|
||||
@JvmField
|
||||
val EVOLUTION_STONE_BLOCK_STEP = this.create("block.evolution_stone_block.step")
|
||||
|
||||
@JvmField
|
||||
val BERRY_BUSH_BREAK = this.create("berry_bush.break")
|
||||
val GIMMIGHOUL_GIVE_ITEM = this.create("pokemon.gimmighoul.give_item")
|
||||
@JvmField
|
||||
val BERRY_BUSH_PLACE = this.create("berry_bush.place")
|
||||
val GIMMIGHOUL_REVEAL = this.create("pokemon.gimmighoul.reveal")
|
||||
|
||||
@JvmField
|
||||
val BIG_ROOT_BREAK = this.create("big_root.break")
|
||||
val BERRY_BUSH_BREAK = this.create("block.berry_bush.break")
|
||||
@JvmField
|
||||
val ENERGY_ROOT_PLACE = this.create("energy_root.place")
|
||||
val BERRY_BUSH_PLACE = this.create("block.berry_bush.place")
|
||||
@JvmField
|
||||
val BERRY_HARVEST = this.create("block.berry_bush.harvest")
|
||||
@JvmField
|
||||
val BERRY_EAT = this.create("item.berry.eat")
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE_BREAK = this.create("vivichoke.break")
|
||||
val BIG_ROOT_BREAK = this.create("block.big_root.break")
|
||||
@JvmField
|
||||
val VIVICHOKE_PLACE = this.create("vivichoke.place")
|
||||
val ENERGY_ROOT_PLACE = this.create("block.energy_root.place")
|
||||
|
||||
@JvmField
|
||||
val MINT_BREAK = this.create("mint.break")
|
||||
val VIVICHOKE_BREAK = this.create("block.vivichoke.break")
|
||||
@JvmField
|
||||
val MINT_PLACE = this.create("mint.place")
|
||||
val VIVICHOKE_PLACE = this.create("block.vivichoke.place")
|
||||
|
||||
@JvmField
|
||||
val REVIVAL_HERB_BREAK = this.create("revival_herb.break")
|
||||
val MINT_BREAK = this.create("block.mint.break")
|
||||
@JvmField
|
||||
val REVIVAL_HERB_PLACE = this.create("revival_herb.place")
|
||||
val MINT_PLACE = this.create("block.mint.place")
|
||||
|
||||
@JvmField
|
||||
val MEDICINAL_LEEK_BREAK = this.create("medicinal_leek.break")
|
||||
val REVIVAL_HERB_BREAK = this.create("block.revival_herb.break")
|
||||
@JvmField
|
||||
val MEDICINAL_LEEK_PLACE = this.create("medicinal_leek.plant")
|
||||
val REVIVAL_HERB_PLACE = this.create("block.revival_herb.place")
|
||||
|
||||
@JvmField
|
||||
val GILDED_CHEST_OPEN = this.create("gilded_chest.open")
|
||||
val MEDICINAL_LEEK_BREAK = this.create("block.medicinal_leek.break")
|
||||
@JvmField
|
||||
val GILDED_CHEST_CLOSE = this.create("gilded_chest.close")
|
||||
val MEDICINAL_LEEK_PLACE = this.create("block.medicinal_leek.plant")
|
||||
|
||||
@JvmField
|
||||
val GILDED_CHEST_STEP = this.create("gilded_chest.step")
|
||||
val GILDED_CHEST_OPEN = this.create("block.gilded_chest.open")
|
||||
@JvmField
|
||||
val GILDED_CHEST_HIT = this.create("gilded_chest.hit")
|
||||
val GILDED_CHEST_CLOSE = this.create("block.gilded_chest.close")
|
||||
@JvmField
|
||||
val GILDED_CHEST_BREAK = this.create("gilded_chest.break")
|
||||
val GILDED_CHEST_STEP = this.create("block.gilded_chest.step")
|
||||
@JvmField
|
||||
val GILDED_CHEST_PLACE = this.create("gilded_chest.place")
|
||||
val GILDED_CHEST_HIT = this.create("block.gilded_chest.hit")
|
||||
@JvmField
|
||||
val GILDED_CHEST_BREAK = this.create("block.gilded_chest.break")
|
||||
@JvmField
|
||||
val GILDED_CHEST_PLACE = this.create("block.gilded_chest.place")
|
||||
|
||||
@JvmField
|
||||
val RELIC_COIN_SACK_SOUNDS = SoundType(1f, 1.1f,
|
||||
@@ -401,17 +403,17 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val DISPLAY_CASE_ADD_ITEM = this.create("display_case.add_item")
|
||||
val DISPLAY_CASE_ADD_ITEM = this.create("block.display_case.add_item")
|
||||
@JvmField
|
||||
val DISPLAY_CASE_REMOVE_ITEM = this.create("display_case.remove_item")
|
||||
val DISPLAY_CASE_REMOVE_ITEM = this.create("block.display_case.remove_item")
|
||||
@JvmField
|
||||
val DISPLAY_CASE_BREAK = this.create("display_case.break")
|
||||
val DISPLAY_CASE_BREAK = this.create("block.display_case.break")
|
||||
@JvmField
|
||||
val DISPLAY_CASE_HIT = this.create("display_case.hit")
|
||||
val DISPLAY_CASE_HIT = this.create("block.display_case.hit")
|
||||
@JvmField
|
||||
val DISPLAY_CASE_PLACE = this.create("display_case.place")
|
||||
val DISPLAY_CASE_PLACE = this.create("block.display_case.place")
|
||||
@JvmField
|
||||
val DISPLAY_CASE_STEP = this.create("display_case.step")
|
||||
val DISPLAY_CASE_STEP = this.create("block.display_case.step")
|
||||
|
||||
@JvmField
|
||||
val DISPLAY_CASE_SOUNDS = SoundType(1f, 1f,
|
||||
|
||||
@@ -29,6 +29,8 @@ object CobblemonCriteria : PlatformRegistry<Registry<CriterionTrigger<*>>, Resou
|
||||
|
||||
val CATCH_SHINY_POKEMON = this.create("catch_shiny_pokemon", SimpleCriterionTrigger(CountableCriterion.CODEC))
|
||||
|
||||
val EGG_COLLECT = this.create("eggs_collected", SimpleCriterionTrigger(CountableCriterion.CODEC))
|
||||
|
||||
val EGG_HATCH = this.create("eggs_hatched", SimpleCriterionTrigger(CountableCriterion.CODEC))
|
||||
|
||||
val EVOLVE_POKEMON = this.create("pokemon_evolved", SimpleCriterionTrigger(EvolvePokemonCriterion.CODEC))
|
||||
@@ -58,4 +60,4 @@ object CobblemonCriteria : PlatformRegistry<Registry<CriterionTrigger<*>>, Resou
|
||||
|
||||
override val registry = BuiltInRegistries.TRIGGER_TYPES
|
||||
override val resourceKey = Registries.TRIGGER_TYPE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import net.minecraft.nbt.NbtOps
|
||||
* @author Qu
|
||||
* @since January 9th, 2022
|
||||
*/
|
||||
open class Ability internal constructor(var template: AbilityTemplate, forced: Boolean) {
|
||||
open class Ability internal constructor(var template: AbilityTemplate, forced: Boolean, priority: Priority) {
|
||||
|
||||
val name: String
|
||||
get() = template.name
|
||||
@@ -57,7 +57,7 @@ open class Ability internal constructor(var template: AbilityTemplate, forced: B
|
||||
*
|
||||
* @see [Pokemon.updateAbility].
|
||||
*/
|
||||
var priority = Priority.LOWEST
|
||||
var priority = priority
|
||||
internal set
|
||||
|
||||
@Deprecated("Please use the Codec instead", ReplaceWith("Ability.CODEC"))
|
||||
@@ -111,7 +111,7 @@ open class Ability internal constructor(var template: AbilityTemplate, forced: B
|
||||
Codec.BOOL.optionalFieldOf(DataKeys.POKEMON_ABILITY_FORCED, false).forGetter(Ability::forced),
|
||||
Codec.INT.optionalFieldOf(DataKeys.POKEMON_ABILITY_INDEX, -1).forGetter(Ability::index),
|
||||
Priority.CODEC.optionalFieldOf(DataKeys.POKEMON_ABILITY_PRIORITY, Priority.LOWEST).forGetter(Ability::priority)
|
||||
).apply(it) { template, forced, index, priority -> Ability(template, forced).apply {
|
||||
).apply(it) { template, forced, index, priority -> Ability(template, forced, priority).apply {
|
||||
this.index = index
|
||||
this.priority = priority
|
||||
} }
|
||||
|
||||
@@ -23,7 +23,7 @@ import com.cobblemon.mod.common.pokemon.Species
|
||||
*/
|
||||
open class AbilityPool : PrioritizedList<PotentialAbility>() {
|
||||
fun select(species: Species, aspects: Set<String>): Pair<Ability, Priority> {
|
||||
for (priority in Priority.values()) {
|
||||
for (priority in Priority.entries) {
|
||||
val potentialAbilities = priorityMap[priority]?.filter { it.isSatisfiedBy(aspects) } ?: continue
|
||||
if (potentialAbilities.isNotEmpty()) {
|
||||
return potentialAbilities.random().template.create() to priority
|
||||
@@ -31,7 +31,7 @@ open class AbilityPool : PrioritizedList<PotentialAbility>() {
|
||||
}
|
||||
|
||||
LOGGER.error("Unable to select an ability from the pool for $species and aspects: ${aspects.joinToString()}")
|
||||
LOGGER.error("Usually this happens when a client is doing logic it shouldn't. Please show this to the Cobblemon developers!")
|
||||
LOGGER.error("Please show this to the Cobblemon developers!")
|
||||
Exception().printStackTrace()
|
||||
return Abilities.first().create() to Priority.LOWEST
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.abilities
|
||||
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.util.codec.CodecUtils
|
||||
import com.google.gson.JsonObject
|
||||
import com.mojang.serialization.Codec
|
||||
@@ -21,14 +22,14 @@ import net.minecraft.nbt.CompoundTag
|
||||
*/
|
||||
class AbilityTemplate(
|
||||
val name: String = "",
|
||||
var builder: (AbilityTemplate, forced: Boolean) -> Ability = { template, forced -> Ability(template, forced) },
|
||||
var builder: (AbilityTemplate, forced: Boolean, priority: Priority) -> Ability = { template, forced, priority -> Ability(template, forced, priority) },
|
||||
val displayName: String = "cobblemon.ability.$name",
|
||||
val description: String = "cobblemon.ability.$name.desc"
|
||||
) {
|
||||
/**
|
||||
* Returns the Ability or if applicable the extension connected to this template
|
||||
*/
|
||||
fun create(forced: Boolean = false) = builder(this, forced)
|
||||
fun create(forced: Boolean = false, priority: Priority = Priority.LOWEST) = builder(this, forced, priority)
|
||||
|
||||
/**
|
||||
* Returns the Ability and loads the given NBT Tag into it.
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
import com.mojang.datafixers.util.Pair
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.Mob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
class ActivityConfigurationContext(val activity: Activity) {
|
||||
val tasks = mutableListOf<Pair<Int, BehaviorControl<in LivingEntity>>>()
|
||||
|
||||
fun addTasks(weight: Int, vararg tasks: BehaviorControl<in LivingEntity>) {
|
||||
this.tasks.addAll(tasks.map { Pair.of(weight, it) })
|
||||
}
|
||||
|
||||
fun apply(entity: LivingEntity) {
|
||||
entity.brain.addActivity(activity, ImmutableList.copyOf(tasks))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.config.BrainConfig
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
import net.minecraft.world.entity.schedule.Schedule
|
||||
|
||||
class BrainConfigurationContext {
|
||||
|
||||
var defaultActivity = Activity.IDLE
|
||||
var coreActivities = setOf(Activity.CORE)
|
||||
val activities = mutableListOf<ActivityConfigurationContext>()
|
||||
val schedule = Schedule.EMPTY
|
||||
|
||||
fun getOrCreateActivity(activity: Activity): ActivityConfigurationContext {
|
||||
return activities.firstOrNull { it.activity == activity } ?: ActivityConfigurationContext(activity).also(activities::add)
|
||||
}
|
||||
|
||||
fun apply(entity: LivingEntity, brainConfigs: List<BrainConfig>) {
|
||||
val brain = entity.brain
|
||||
|
||||
// Setup the brain config
|
||||
brainConfigs.forEach { it.configure(entity, this) }
|
||||
|
||||
// Apply the brain config
|
||||
activities.forEach { it.apply(entity) }
|
||||
brain.setCoreActivities(coreActivities)
|
||||
brain.setDefaultActivity(defaultActivity)
|
||||
brain.schedule = schedule
|
||||
brain.setActiveActivityIfPossible(defaultActivity)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai
|
||||
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class WrapperLivingEntityTask<T : LivingEntity>(val task: BehaviorControl<T>, val clazz: Class<T>) : BehaviorControl<LivingEntity> {
|
||||
override fun tryStart(level: ServerLevel, entity: LivingEntity, gameTime: Long): Boolean {
|
||||
if (clazz.isInstance(entity)) {
|
||||
return task.tryStart(level, entity as T, gameTime)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
override fun debugString() = task.debugString()
|
||||
override fun tickOrStop(level: ServerLevel, entity: LivingEntity, gameTime: Long) {
|
||||
task.tickOrStop(level, entity as T, gameTime)
|
||||
}
|
||||
|
||||
override fun getStatus() = task.status
|
||||
override fun doStop(level: ServerLevel, entity: LivingEntity, gameTime: Long) = task.doStop(level, entity as T, gameTime)
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.config.task.TaskConfig
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
class AddTasksToActivity : BrainConfig {
|
||||
val activity = Activity.IDLE
|
||||
val condition = "true".asExpressionLike()
|
||||
val tasksByPriority = mutableMapOf<Int, List<TaskConfig>>()
|
||||
|
||||
override fun configure(entity: LivingEntity, brainConfigurationContext: BrainConfigurationContext) {
|
||||
val runtime = MoLangRuntime().setup()
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return
|
||||
|
||||
val activity = brainConfigurationContext.getOrCreateActivity(activity)
|
||||
tasksByPriority.forEach { (priority, taskConfigs) ->
|
||||
val tasks = taskConfigs.flatMap { it.createTasks(entity, brainConfigurationContext) }
|
||||
activity.addTasks(priority, *tasks.toTypedArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonBrainConfigs
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
class ApplyPresets : BrainConfig {
|
||||
val condition = "true".asExpressionLike()
|
||||
val presets = mutableListOf<ResourceLocation>()
|
||||
override fun configure(entity: LivingEntity, brainConfigurationContext: BrainConfigurationContext) {
|
||||
val runtime = MoLangRuntime().setup()
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return
|
||||
|
||||
val presetConfigs = presets.flatMap { CobblemonBrainConfigs.presets[it] ?: return Cobblemon.LOGGER.warn("Preset $it not found") }
|
||||
presetConfigs.forEach { it.configure(entity, brainConfigurationContext) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
/**
|
||||
* Something that contributes to the construction of an entity's brain. Implementations are expected to make
|
||||
* their changes using the provided [BrainConfigurationContext] which helps stage the details of the entity's
|
||||
* brain before locking into the highly immutable structure that Mojang uses.
|
||||
*
|
||||
* A brain config has access to the [LivingEntity] it's for but note that this is, in most cases, an extremely
|
||||
* young version of the entity that is not fully initialized and might die if you try getting exotic with it.
|
||||
*
|
||||
* @see BrainConfigurationContext
|
||||
* @author Hiroku
|
||||
* @since October 13th, 2024
|
||||
*/
|
||||
interface BrainConfig {
|
||||
companion object {
|
||||
val types = mutableMapOf<String, Class<out BrainConfig>>(
|
||||
"script" to ScriptBrainConfig::class.java,
|
||||
"add_tasks_to_activity" to AddTasksToActivity::class.java,
|
||||
"apply_presets" to ApplyPresets::class.java,
|
||||
"set_default_activity" to SetDefaultActivity::class.java,
|
||||
"set_core_activities" to SetCoreActivities::class.java
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
// fun encode(buffer: RegistryFriendlyByteBuf)
|
||||
// fun decode(buffer: RegistryFriendlyByteBuf)
|
||||
fun configure(entity: LivingEntity, brainConfigurationContext: BrainConfigurationContext)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
object DummyBrainConfig : BrainConfig {
|
||||
override fun configure(entity: LivingEntity, brainConfigurationContext: BrainConfigurationContext) {}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.ai.ActivityConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addStandardFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.util.activityRegistry
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Pair
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class ScriptBrainConfig : BrainConfig {
|
||||
val condition = "true".asExpressionLike()
|
||||
val script = cobblemonResource("dummy")
|
||||
|
||||
override fun configure(entity: LivingEntity, context: BrainConfigurationContext) {
|
||||
val runtime = MoLangRuntime().setup()
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return
|
||||
|
||||
val struct = createBrainStruct(entity, context)
|
||||
val script = CobblemonScripts.scripts[this.script]
|
||||
?: run {
|
||||
Cobblemon.LOGGER.error("Tried loading script $script as part of an entity brain but that script does not exist")
|
||||
return
|
||||
}
|
||||
runtime.resolve(script, mapOf("brain" to struct))
|
||||
}
|
||||
|
||||
fun createBrainStruct(entity: LivingEntity, brainConfigurationContext: BrainConfigurationContext): QueryStruct {
|
||||
return QueryStruct(hashMapOf()).addStandardFunctions()
|
||||
.addFunction("entity") { (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()) }
|
||||
.addFunction("create_activity") { params ->
|
||||
val name = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val activity = entity.level().activityRegistry.get(name) ?: return@addFunction run {
|
||||
Cobblemon.LOGGER.error("Tried loading activity $name as part of an entity brain but that activity does not exist")
|
||||
DoubleValue.ZERO
|
||||
}
|
||||
val existingActivityBuilder = brainConfigurationContext.activities.find { it.activity == activity }
|
||||
if (existingActivityBuilder != null) {
|
||||
return@addFunction createActivityStruct(existingActivityBuilder)
|
||||
} else {
|
||||
val activityConfigurationContext = ActivityConfigurationContext(activity)
|
||||
brainConfigurationContext.activities.add(activityConfigurationContext)
|
||||
return@addFunction createActivityStruct(activityConfigurationContext)
|
||||
}
|
||||
}
|
||||
.addFunction("set_core_activities") { params ->
|
||||
brainConfigurationContext.coreActivities = params.params.map { (it as ObjectValue<ActivityConfigurationContext>).obj.activity }.toSet()
|
||||
return@addFunction DoubleValue.ONE
|
||||
}
|
||||
.addFunction("set_default_activity") { params ->
|
||||
brainConfigurationContext.defaultActivity = params.get<ObjectValue<ActivityConfigurationContext>>(0).obj.activity
|
||||
return@addFunction DoubleValue.ONE
|
||||
}
|
||||
}
|
||||
|
||||
fun createActivityStruct(activityConfigurationContext: ActivityConfigurationContext): ObjectValue<ActivityConfigurationContext> {
|
||||
val struct = ObjectValue(activityConfigurationContext)
|
||||
struct.addStandardFunctions()
|
||||
.addFunction("add_task") { params ->
|
||||
val priority = params.getInt(0)
|
||||
val task = params.get(1) as ObjectValue<BehaviorControl<in LivingEntity>>
|
||||
activityConfigurationContext.tasks.add(Pair(priority, task.obj))
|
||||
}
|
||||
return struct
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
class SetCoreActivities : BrainConfig {
|
||||
val activities = mutableListOf<Activity>()
|
||||
override fun configure(entity: LivingEntity, brainConfigurationContext: BrainConfigurationContext) {
|
||||
brainConfigurationContext.coreActivities = activities.toSet()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
class SetDefaultActivity : BrainConfig {
|
||||
val activity: Activity = Activity.IDLE
|
||||
override fun configure(entity: LivingEntity, brainConfigurationContext: BrainConfigurationContext) {
|
||||
brainConfigurationContext.defaultActivity = activity
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class AllOfTaskConfig : TaskConfig {
|
||||
val condition = "true".asExpressionLike()
|
||||
val tasks: List<TaskConfig> = emptyList()
|
||||
|
||||
override fun createTasks(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
): List<BehaviorControl<in LivingEntity>> {
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return emptyList()
|
||||
return tasks.flatMap { it.createTasks(entity, brainConfigurationContext) }
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.entity.ai.AttackAngryAtTask
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class AttackAngryAtTaskConfig : SingleTaskConfig {
|
||||
val condition = "true".asExpressionLike()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return null
|
||||
return AttackAngryAtTask.create()
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.resolveInt
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.DoNothing
|
||||
|
||||
class DoNothingTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionLike = "true".asExpressionLike()
|
||||
val minDurationTicks = "40".asExpression()
|
||||
val maxDurationTicks = "80".asExpression()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return null
|
||||
return DoNothing(runtime.resolveInt(minDurationTicks), runtime.resolveInt(maxDurationTicks))
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.entity.ai.FollowWalkTargetTask
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.resolveInt
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class FollowWalkTargetTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionLike = "true".asExpressionLike()
|
||||
val minRunTime: Expression = "150".asExpression()
|
||||
val maxRunTime: Expression = "250".asExpression()
|
||||
|
||||
override fun createTask(entity: LivingEntity, brainConfigurationContext: BrainConfigurationContext): BehaviorControl<LivingEntity>? {
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return null
|
||||
return WrapperLivingEntityTask(
|
||||
FollowWalkTargetTask(runtime.resolveInt(minRunTime), runtime.resolveInt(maxRunTime)),
|
||||
PathfinderMob::class.java
|
||||
)
|
||||
}
|
||||
}
|
||||
+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.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.entity.ai.GetAngryAtAttackerTask
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class GetAngryAtAttackerTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionLike = "true".asExpressionLike()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return null
|
||||
return GetAngryAtAttackerTask.create()
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.entity.npc.ai.GoToHealingMachineTask
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class GoToHealingMachineTaskConfig(
|
||||
val condition: ExpressionLike = "true".asExpressionLike(),
|
||||
val horizontalSearchRange: Expression = "10".asExpression(),
|
||||
val verticalSearchRange: Expression = "5".asExpression(),
|
||||
val speedMultiplier: Expression = "0.33".asExpression(),
|
||||
val completionRange: Expression = "1".asExpression()
|
||||
) : SingleTaskConfig {
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return null
|
||||
|
||||
return GoToHealingMachineTask.create(
|
||||
horizontalSearchRange = horizontalSearchRange,
|
||||
verticalSearchRange = verticalSearchRange,
|
||||
speedMultiplier = speedMultiplier,
|
||||
completionRange = completionRange
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
+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.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.entity.npc.ai.HealUsingHealingMachineTask
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class HealUsingHealingMachineTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionLike = "true".asExpressionLike()
|
||||
val horizontalUseRange = "3".asExpression()
|
||||
val verticalUseRange = "2".asExpression()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return null
|
||||
return HealUsingHealingMachineTask(horizontalUseRange, verticalUseRange)
|
||||
}
|
||||
}
|
||||
+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.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.entity.npc.ai.LookAtBattlingPokemonTask
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.resolveInt
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class LookAtBattlingPokemonTaskConfig : SingleTaskConfig {
|
||||
val minDurationTicks = "40".asExpression()
|
||||
val maxDurationTicks = "80".asExpression()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
return LookAtBattlingPokemonTask.create(
|
||||
minDurationTicks = runtime.resolveInt(minDurationTicks),
|
||||
maxDurationTicks = runtime.resolveInt(maxDurationTicks)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
+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.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.resolveFloat
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.SetEntityLookTarget
|
||||
|
||||
class LookAtEntitiesTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionLike = "true".asExpressionLike()
|
||||
val maxDistance = "15".asExpression()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return null
|
||||
return SetEntityLookTarget.create(runtime.resolveFloat(maxDistance))
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.entity.npc.ai.LookAtSpeakerTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
class LookAtSpeakerTaskConfig : SingleTaskConfig {
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
) = LookAtSpeakerTask.create()
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.resolveInt
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.Mob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.LookAtTargetSink
|
||||
|
||||
class LookAtTargetTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionLike = "true".asExpressionLike()
|
||||
val minDurationTicks: Expression = "40".asExpression()
|
||||
val maxDurationTicks: Expression = "80".asExpression()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return null
|
||||
return WrapperLivingEntityTask(LookAtTargetSink(runtime.resolveInt(minDurationTicks), runtime.resolveInt(maxDurationTicks)), Mob::class.java)
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.entity.npc.ai.MeleeAttackTask
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class MeleeAttackTaskConfig : SingleTaskConfig {
|
||||
val condition = "true".asExpressionLike()
|
||||
val range = "1.5".asExpression()
|
||||
val cooldownTicks = "30".asExpression()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return null
|
||||
|
||||
return MeleeAttackTask.create(
|
||||
range = range,
|
||||
cooldownTicks = cooldownTicks
|
||||
)
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.entity.ai.MoveToAttackTargetTask
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
class MoveToAttackTargetTaskConfig : SingleTaskConfig {
|
||||
val speedMultiplier = "0.5".asExpression()
|
||||
val closeEnoughDistance = "1".asExpression()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
) = MoveToAttackTargetTask.create(
|
||||
speedMultiplier = speedMultiplier,
|
||||
closeEnoughDistance = closeEnoughDistance
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.toDF
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.DoNothing
|
||||
import net.minecraft.world.entity.ai.behavior.RunOne
|
||||
|
||||
/**
|
||||
* A task where each time the brain is ticked, a different task might run. This differs from [RandomTaskConfig] in that
|
||||
* the same entity can run all of the different possibilities, rather than [RandomTaskConfig] where once the entity
|
||||
* spawns, it will only use whichever was selected at the time of spawning.
|
||||
*
|
||||
* This is most useful for making a single entity randomly choose what to do at a given moment.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 19th, 2024
|
||||
*/
|
||||
class OneOfTaskConfig : SingleTaskConfig {
|
||||
class OneOfTaskOption {
|
||||
val weight: Int = 1
|
||||
val task: TaskConfig = SingleTaskConfig { _, _ -> DoNothing(0, 1) }
|
||||
}
|
||||
|
||||
val condition: ExpressionLike = "true".asExpressionLike()
|
||||
val options = mutableListOf<OneOfTaskOption>()
|
||||
|
||||
override fun createTask(entity: LivingEntity, brainConfigurationContext: BrainConfigurationContext): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return null
|
||||
return RunOne(options.map { it.task.createTasks(entity, brainConfigurationContext).first() toDF it.weight })
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.weightedSelection
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.DoNothing
|
||||
|
||||
/**
|
||||
* Randomly chooses one of the possible tasks to add to the brain. This differs from [OneOfTaskConfig] in that
|
||||
* the randomization happens before the brain is created, rather than [OneOfTaskConfig] where the randomization
|
||||
* happens each time the brain is ticked.
|
||||
*
|
||||
* This is most useful when the goal is to apply something like a specialization to an entity where it varies
|
||||
* but once put on the entity, it sticks.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 19th, 2024
|
||||
*/
|
||||
class RandomTaskConfig : TaskConfig {
|
||||
class RandomTaskChoice {
|
||||
val weight = 1.0
|
||||
val task: TaskConfig = SingleTaskConfig { _, _ -> DoNothing(0, 1) }
|
||||
}
|
||||
|
||||
val condition: ExpressionLike = "true".asExpressionLike()
|
||||
val choices = mutableListOf<RandomTaskChoice>()
|
||||
|
||||
override fun createTasks(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
): List<BehaviorControl<in LivingEntity>> {
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return emptyList()
|
||||
val task = choices.weightedSelection { it.weight }?.task ?: throw IllegalStateException("No tasks to choose from in random_task config")
|
||||
return task.createTasks(entity, brainConfigurationContext)
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
fun interface SingleTaskConfig : TaskConfig {
|
||||
override fun createTasks(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
): List<BehaviorControl<in LivingEntity>> {
|
||||
return createTask(entity, brainConfigurationContext)?.let { listOf(it) } ?: emptyList()
|
||||
}
|
||||
|
||||
fun createTask(entity: LivingEntity, brainConfigurationContext: BrainConfigurationContext): BehaviorControl<in LivingEntity>?
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.entity.ai.StayAfloatTask
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.resolveFloat
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class StayAfloatTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionLike = "true".asExpressionLike()
|
||||
val chance: Expression = "0.01".asExpression()
|
||||
override fun createTask(entity: LivingEntity, brainConfigurationContext: BrainConfigurationContext): BehaviorControl<LivingEntity>? {
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return null
|
||||
val chance = runtime.resolveFloat(chance)
|
||||
return WrapperLivingEntityTask(
|
||||
StayAfloatTask(chance),
|
||||
PathfinderMob::class.java
|
||||
)
|
||||
}
|
||||
}
|
||||
+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.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.StopBeingAngryIfTargetDead
|
||||
|
||||
class StopBeingAngryIfAttackerDeadTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionLike = "true".asExpressionLike()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return null
|
||||
return StopBeingAngryIfTargetDead.create()
|
||||
}
|
||||
}
|
||||
+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.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.entity.npc.ai.SwitchFromActionEffectTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
class SwitchFromActionEffectTaskConfig : SingleTaskConfig {
|
||||
val activity = Activity.IDLE
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
) = SwitchFromActionEffectTask.create(activity)
|
||||
}
|
||||
+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.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
class SwitchFromChattingTaskConfig : SingleTaskConfig {
|
||||
val activity = Activity.IDLE
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
) = BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(CobblemonMemories.DIALOGUES)
|
||||
).apply(it) { _ ->
|
||||
Trigger { world, entity, _ ->
|
||||
entity.brain.setActiveActivityIfPossible(activity)
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+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.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
class SwitchFromFightTaskConfig : SingleTaskConfig {
|
||||
val activity = Activity.IDLE
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
) = BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(MemoryModuleType.ATTACK_TARGET)
|
||||
).apply(it) { _ ->
|
||||
Trigger { world, entity, _ ->
|
||||
entity.brain.setActiveActivityIfPossible(activity)
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.entity.npc.ai.SwitchFromBattleTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
class SwitchFromNPCBattleTaskConfig : SingleTaskConfig {
|
||||
val activity: Activity = Activity.IDLE
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
return SwitchFromBattleTask.create(activity)
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonActivities
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
|
||||
class SwitchToActionEffectTaskConfig : SingleTaskConfig {
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(CobblemonMemories.ACTIVE_ACTION_EFFECT)
|
||||
).apply(it) { _ ->
|
||||
Trigger { world, entity, time ->
|
||||
entity.brain.setActiveActivityIfPossible(CobblemonActivities.NPC_ACTION_EFFECT)
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.CobblemonActivities
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class SwitchToChattingTaskConfig : SingleTaskConfig {
|
||||
val condition = "true".asExpressionLike()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
) = BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.present(CobblemonMemories.DIALOGUES),
|
||||
it.registered(MemoryModuleType.WALK_TARGET)
|
||||
).apply(it) { _, walkTarget ->
|
||||
Trigger { world, entity, _ ->
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return@Trigger false
|
||||
walkTarget.erase()
|
||||
entity.brain.setActiveActivityIfPossible(CobblemonActivities.NPC_CHATTING)
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.Difficulty
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
class SwitchToFightTaskConfig : SingleTaskConfig {
|
||||
val condition = "true".asExpressionLike()
|
||||
val activity = Activity.FIGHT
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
) = BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.present(MemoryModuleType.ATTACK_TARGET)
|
||||
).apply(it) { _ ->
|
||||
Trigger { world, entity, _ ->
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return@Trigger false
|
||||
if (entity.commandSenderWorld.getCurrentDifficultyAt(entity.blockPosition()).difficulty == Difficulty.PEACEFUL) return@Trigger false
|
||||
|
||||
entity.brain.setActiveActivityIfPossible(activity)
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+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.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.entity.npc.ai.SwitchToBattleTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class SwitchToNPCBattleTaskConfig : SingleTaskConfig {
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
): BehaviorControl<in LivingEntity> = SwitchToBattleTask.create()
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
/**
|
||||
* A configuration for a brain task. Its purpose is to generate a list of tasks to add to the brain of
|
||||
* an entity when it spawns.
|
||||
*
|
||||
* This is essentially a builder for tasks.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 14th, 2024
|
||||
*/
|
||||
fun interface TaskConfig {
|
||||
companion object {
|
||||
val types = mutableMapOf<String, Class<out TaskConfig>>(
|
||||
"one_of" to OneOfTaskConfig::class.java,
|
||||
"wander" to WanderTaskConfig::class.java,
|
||||
"look_at_target" to LookAtTargetTaskConfig::class.java,
|
||||
"follow_walk_target" to FollowWalkTargetTaskConfig::class.java,
|
||||
"random" to RandomTaskConfig::class.java,
|
||||
"stay_afloat" to StayAfloatTaskConfig::class.java,
|
||||
"look_at_entities" to LookAtEntitiesTaskConfig::class.java,
|
||||
"do_nothing" to DoNothingTaskConfig::class.java,
|
||||
"get_angry_at_attacker" to GetAngryAtAttackerTaskConfig::class.java,
|
||||
"stop_being_angry_if_attacker_dead" to StopBeingAngryIfAttackerDeadTaskConfig::class.java,
|
||||
"switch_npc_to_battle" to SwitchToNPCBattleTaskConfig::class.java,
|
||||
"look_at_battling_pokemon" to LookAtBattlingPokemonTaskConfig::class.java,
|
||||
"switch_npc_from_battle" to SwitchFromNPCBattleTaskConfig::class.java,
|
||||
"go_to_healing_machine" to GoToHealingMachineTaskConfig::class.java,
|
||||
"heal_using_healing_machine" to HealUsingHealingMachineTaskConfig::class.java,
|
||||
"all_of" to AllOfTaskConfig::class.java,
|
||||
"attack_angry_at" to AttackAngryAtTaskConfig::class.java,
|
||||
"move_to_attack_target" to MoveToAttackTargetTaskConfig::class.java,
|
||||
"melee_attack" to MeleeAttackTaskConfig::class.java,
|
||||
"switch_from_fight" to SwitchFromFightTaskConfig::class.java,
|
||||
"switch_to_fight" to SwitchToFightTaskConfig::class.java,
|
||||
"switch_to_chatting" to SwitchToChattingTaskConfig::class.java,
|
||||
"switch_from_chatting" to SwitchFromChattingTaskConfig::class.java,
|
||||
"look_at_speaker" to LookAtSpeakerTaskConfig::class.java,
|
||||
"switch_to_action_effect" to SwitchToActionEffectTaskConfig::class.java,
|
||||
"switch_from_action_effect" to SwitchFromActionEffectTaskConfig::class.java,
|
||||
)
|
||||
|
||||
val runtime = MoLangRuntime().setup()
|
||||
}
|
||||
|
||||
val runtime: MoLangRuntime
|
||||
get() = Companion.runtime
|
||||
|
||||
/** Given the entity in construction, returns a list of tasks. */
|
||||
fun createTasks(entity: LivingEntity, brainConfigurationContext: BrainConfigurationContext): List<BehaviorControl<in LivingEntity>>
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.resolveDouble
|
||||
import com.cobblemon.mod.common.util.resolveFloat
|
||||
import com.cobblemon.mod.common.util.resolveInt
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.BlockPosTracker
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.memory.WalkTarget
|
||||
import net.minecraft.world.entity.ai.util.LandRandomPos
|
||||
|
||||
class WanderTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionLike = "true".asExpressionLike()
|
||||
val shouldWander: ExpressionLike = "math.random(0, 20 * 8) <= 1".asExpressionLike()
|
||||
val horizontalRange: Expression = "10".asExpression()
|
||||
val verticalRange: Expression = "5".asExpression()
|
||||
val speedMultiplier: Expression = "0.35".asExpression()
|
||||
val completionRange: Expression = "1".asExpression()
|
||||
val lookTargetYOffset: Expression = "1.5".asExpression()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BrainConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(condition)) return null
|
||||
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(MemoryModuleType.WALK_TARGET),
|
||||
it.registered(MemoryModuleType.LOOK_TARGET)
|
||||
).apply(it) { walkTarget, lookTarget ->
|
||||
Trigger { world, entity, time ->
|
||||
if (entity !is PathfinderMob) {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
runtime.withQueryValue("entity", (entity as? PosableEntity)?.struct ?: QueryStruct(hashMapOf()))
|
||||
if (!runtime.resolveBoolean(shouldWander)) return@Trigger false
|
||||
|
||||
val targetVec = LandRandomPos.getPos(entity, runtime.resolveInt(horizontalRange), runtime.resolveInt(verticalRange)) ?: return@Trigger false
|
||||
walkTarget.set(WalkTarget(targetVec, runtime.resolveFloat(speedMultiplier), runtime.resolveInt(completionRange)))
|
||||
lookTarget.set(BlockPosTracker(targetVec.add(0.0, runtime.resolveDouble(lookTargetYOffset), 0.0)))
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.battles.interpreter
|
||||
|
||||
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
|
||||
|
||||
/**
|
||||
* An exception thrown when properties from a [BattleMessage] cannot be interpreted for an [InterpreterInstruction].
|
||||
*
|
||||
* @author Segfault Guy
|
||||
* @since November 10th, 2024
|
||||
*/
|
||||
class InvalidInstructionException(battleMessage: BattleMessage) : Exception("Failed to interpret ${battleMessage.rawMessage}")
|
||||
@@ -25,6 +25,7 @@ import com.cobblemon.mod.common.api.events.battles.BattleFledEvent
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.text.yellow
|
||||
@@ -83,6 +84,8 @@ open class PokemonBattle(
|
||||
|
||||
val onEndHandlers: MutableList<(PokemonBattle) -> Unit> = mutableListOf()
|
||||
|
||||
val battlePartyStores = mutableListOf<PlayerPartyStore>()
|
||||
|
||||
init {
|
||||
side1.battle = this
|
||||
side2.battle = this
|
||||
@@ -371,6 +374,13 @@ open class PokemonBattle(
|
||||
|
||||
}
|
||||
|
||||
fun dispatchWaitingToFront(delaySeconds: Float = 1F, dispatcher: () -> Unit) {
|
||||
dispatches.addFirst(BattleDispatch {
|
||||
dispatcher()
|
||||
WaitDispatch(delaySeconds)
|
||||
})
|
||||
}
|
||||
|
||||
fun dispatchGo(dispatcher: () -> Unit) {
|
||||
dispatch {
|
||||
dispatcher()
|
||||
|
||||
@@ -172,7 +172,8 @@ class Berry(
|
||||
val treeEntity = world.getBlockEntity(pos) as BerryBlockEntity
|
||||
if (BerryBlock.getMulch(treeEntity) == MulchVariant.RICH) {
|
||||
//I hope the upper bound isnt exclusive, especially when there's a method called nextBetweenExclusive
|
||||
yield += world.random.nextIntBetweenInclusive(1, 3)
|
||||
// update: it was meant to be exclusive, which caused #1124. I've lowered the upper bound from 3 to 2.
|
||||
yield += world.random.nextIntBetweenInclusive(1, 2)
|
||||
treeEntity.decrementMulchDuration(world, pos, state)
|
||||
}
|
||||
val event = BerryYieldCalculationEvent(this, world, state, pos, placer, yield, bonus.second)
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.api.data
|
||||
import com.cobblemon.mod.common.api.net.Decodable
|
||||
import com.cobblemon.mod.common.api.net.Encodable
|
||||
|
||||
// TODO this is implemented in multiple places but unused. Can we scratch this?
|
||||
/**
|
||||
* Represents an object that will possibly be synchronized to the client during datapack synchronization.
|
||||
*
|
||||
|
||||
@@ -11,11 +11,12 @@ package com.cobblemon.mod.common.api.drop
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.LOOT_DROPPED
|
||||
import com.cobblemon.mod.common.api.events.drops.LootDroppedEvent
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import kotlin.random.Random
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import kotlin.random.Random
|
||||
|
||||
/**
|
||||
* A table of drops that can produce a list of [DropEntry]. You can produce a drop list from [getDrops] to
|
||||
@@ -96,4 +97,14 @@ class DropTable {
|
||||
ifSucceeded = { it.drops.forEach { it.drop(entity, world, pos, player) } }
|
||||
)
|
||||
}
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeInt(this.entries.size)
|
||||
this.entries.filterIsInstance<ItemDropEntry>().forEach { it.encode(buffer) }
|
||||
}
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
val entries = buffer.readInt()
|
||||
repeat(entries) { this.entries.add(ItemDropEntry().decode(buffer)) }
|
||||
}
|
||||
}
|
||||
@@ -17,9 +17,10 @@ import com.cobblemon.mod.common.util.toBlockPos
|
||||
import net.minecraft.core.component.DataComponentMap
|
||||
import net.minecraft.core.component.DataComponentPatch
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.item.ItemEntity
|
||||
import net.minecraft.world.item.ItemStack
|
||||
@@ -33,12 +34,12 @@ import net.minecraft.world.phys.Vec3
|
||||
* @since July 24th, 2022
|
||||
*/
|
||||
open class ItemDropEntry : DropEntry {
|
||||
override val percentage = 100F
|
||||
override val quantity = 1
|
||||
open val quantityRange: IntRange? = null
|
||||
override val maxSelectableTimes = 1
|
||||
override var percentage = 100F
|
||||
override var quantity = 1
|
||||
open var quantityRange: IntRange? = null
|
||||
override var maxSelectableTimes = 1
|
||||
open val dropMethod: ItemDropMethod? = null
|
||||
open val item = ResourceLocation.parse("minecraft:fish")
|
||||
open var item = ResourceLocation.parse("minecraft:fish")
|
||||
open val components: DataComponentMap? = null
|
||||
|
||||
override fun drop(entity: LivingEntity?, world: ServerLevel, pos: Vec3, player: ServerPlayer?) {
|
||||
@@ -76,4 +77,19 @@ open class ItemDropEntry : DropEntry {
|
||||
world.addFreshEntity(ItemEntity(world, pos.x, pos.y, pos.z, stack))
|
||||
}
|
||||
}
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeFloat(this.percentage)
|
||||
buffer.writeVarInt(this.quantity)
|
||||
buffer.writeResourceLocation(this.item)
|
||||
buffer.writeNullable(this.quantityRange) { _, it -> buffer.writeVarInt(it.first); buffer.writeVarInt(it.last) }
|
||||
}
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): ItemDropEntry {
|
||||
this.percentage = buffer.readFloat()
|
||||
this.quantity = buffer.readVarInt()
|
||||
this.item = buffer.readResourceLocation()
|
||||
this.quantityRange = buffer.readNullable { buffer.readVarInt()..buffer.readVarInt() }
|
||||
return this
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,13 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.entity.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.effects.IllusionEffect
|
||||
import com.cobblemon.mod.common.entity.pokemon.effects.TransformEffect
|
||||
import com.cobblemon.mod.common.pokeball.PokeBall
|
||||
import com.cobblemon.mod.common.pokemon.FormData
|
||||
import com.cobblemon.mod.common.pokemon.Species
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
@@ -95,4 +97,7 @@ interface MocKEffect : PhysicalEffect {
|
||||
get() = this.mock.form?.let {
|
||||
formID -> this.exposedSpecies?.forms?.firstOrNull { it.formOnlyShowdownId().equals(formID, true) } }
|
||||
?: this.exposedSpecies?.standardForm
|
||||
|
||||
val exposedBall: PokeBall?
|
||||
get() = this.mock.pokeball?.let { PokeBalls.getPokeBall(it.asIdentifierDefaultingNamespace()) }
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ import com.cobblemon.mod.common.api.events.battles.BattleFledEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleStartedPostEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleStartedPreEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleVictoryEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.instruction.MegaEvolutionEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.instruction.TerastallizationEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.instruction.ZMoveUsedEvent
|
||||
import com.cobblemon.mod.common.api.events.berry.BerryHarvestEvent
|
||||
import com.cobblemon.mod.common.api.events.berry.BerryMutationOfferEvent
|
||||
import com.cobblemon.mod.common.api.events.berry.BerryMutationResultEvent
|
||||
@@ -23,6 +26,7 @@ import com.cobblemon.mod.common.api.events.entity.PokemonEntitySaveEvent
|
||||
import com.cobblemon.mod.common.api.events.entity.PokemonEntitySaveToWorldEvent
|
||||
import com.cobblemon.mod.common.api.events.entity.SpawnEvent
|
||||
import com.cobblemon.mod.common.api.events.farming.ApricornHarvestEvent
|
||||
import com.cobblemon.mod.common.api.events.fishing.*
|
||||
import com.cobblemon.mod.common.api.events.item.LeftoversCreatedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokeball.PokeBallCaptureCalculatedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokeball.PokemonCatchRateEvent
|
||||
@@ -33,15 +37,14 @@ import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionAcceptedEv
|
||||
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionDisplayEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionTestedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.healing.PokemonHealedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.interaction.ExperienceCandyUseEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.interaction.HeldItemUpdatedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.interaction.PokemonInteractionGUICreationEvent
|
||||
import com.cobblemon.mod.common.api.events.starter.StarterChosenEvent
|
||||
import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent
|
||||
import com.cobblemon.mod.common.api.events.world.BigRootPropagatedEvent
|
||||
import com.cobblemon.mod.common.api.reactive.CancelableObservable
|
||||
import com.cobblemon.mod.common.api.reactive.EventObservable
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.Observable.Companion.filter
|
||||
import com.cobblemon.mod.common.api.reactive.Observable.Companion.map
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
@@ -51,6 +54,10 @@ import net.minecraft.server.level.ServerPlayer
|
||||
@Suppress("unused")
|
||||
object CobblemonEvents {
|
||||
|
||||
@JvmField
|
||||
val POKEMON_PROPERTY_INITIALISED = SimpleObservable<Unit>()
|
||||
@JvmField
|
||||
val COBBLEMON_INITIALISED = SimpleObservable<Unit>()
|
||||
@JvmField
|
||||
val DATA_SYNCHRONIZED = SimpleObservable<ServerPlayer>()
|
||||
@JvmField
|
||||
@@ -80,8 +87,6 @@ object CobblemonEvents {
|
||||
val POKEMON_CAPTURED = EventObservable<PokemonCapturedEvent>()
|
||||
@JvmField
|
||||
val FOSSIL_REVIVED = EventObservable<FossilRevivedEvent>()
|
||||
// @JvmField
|
||||
// val EGG_HATCH = EventObservable<HatchEggEvent>()
|
||||
@JvmField
|
||||
val BATTLE_STARTED_PRE = CancelableObservable<BattleStartedPreEvent>()
|
||||
@JvmField
|
||||
@@ -93,6 +98,14 @@ object CobblemonEvents {
|
||||
@JvmField
|
||||
val BATTLE_FAINTED = EventObservable<BattleFaintedEvent>()
|
||||
|
||||
// instructions
|
||||
@JvmField
|
||||
val MEGA_EVOLUTON = EventObservable<MegaEvolutionEvent>()
|
||||
@JvmField
|
||||
val TERASTALLIZATION = EventObservable<TerastallizationEvent>()
|
||||
@JvmField
|
||||
val ZPOWER_USED = EventObservable<ZMoveUsedEvent>()
|
||||
|
||||
@JvmField
|
||||
val POKEMON_SENT_PRE = CancelableObservable<PokemonSentPreEvent>()
|
||||
@JvmField
|
||||
@@ -106,6 +119,9 @@ object CobblemonEvents {
|
||||
@JvmField
|
||||
val LEVEL_UP_EVENT = EventObservable<LevelUpEvent>()
|
||||
|
||||
@JvmField
|
||||
val POKEMON_HEALED = CancelableObservable<PokemonHealedEvent>()
|
||||
|
||||
@JvmField
|
||||
/** CLIENT ONLY! */
|
||||
val POKEMON_INTERACTION_GUI_CREATION = EventObservable<PokemonInteractionGUICreationEvent>()
|
||||
@@ -117,6 +133,8 @@ object CobblemonEvents {
|
||||
val POKEMON_ENTITY_SAVE_TO_WORLD = CancelableObservable<PokemonEntitySaveToWorldEvent>()
|
||||
@JvmField
|
||||
val ENTITY_SPAWN = CancelableObservable<SpawnEvent<*>>()
|
||||
@JvmField
|
||||
val SHINY_CHANCE_CALCULATION = EventObservable<ShinyChanceCalculationEvent>()
|
||||
|
||||
@JvmField
|
||||
val POKEMON_ENTITY_SPAWN = ENTITY_SPAWN
|
||||
@@ -174,4 +192,35 @@ object CobblemonEvents {
|
||||
val POKEMON_GAINED = EventObservable<PokemonGainedEvent>()
|
||||
@JvmField
|
||||
val POKEMON_SEEN = EventObservable<PokemonSeenEvent>()
|
||||
|
||||
// Fishing
|
||||
@JvmField
|
||||
val BAIT_SET = CancelableObservable<BaitSetEvent>()
|
||||
@JvmField
|
||||
val BAIT_SET_PRE = CancelableObservable<BaitSetEvent>()
|
||||
@JvmField
|
||||
val BAIT_CONSUMED = CancelableObservable<BaitConsumedEvent>()
|
||||
@JvmField
|
||||
val POKEROD_CAST_PRE = CancelableObservable<PokerodCastEvent.Pre>()
|
||||
@JvmField
|
||||
val POKEROD_CAST_POST = EventObservable<PokerodCastEvent.Post>()
|
||||
@JvmField
|
||||
val POKEROD_REEL = CancelableObservable<PokerodReelEvent>()
|
||||
@JvmField
|
||||
val BOBBER_BUCKET_CHOSEN = EventObservable<BobberBucketChosenEvent>()
|
||||
@JvmField
|
||||
val BOBBER_SPAWN_POKEMON_PRE = CancelableObservable<BobberSpawnPokemonEvent.Pre>()
|
||||
@JvmField
|
||||
val BOBBER_SPAWN_POKEMON_MODIFY = EventObservable<BobberSpawnPokemonEvent.Modify>()
|
||||
@JvmField
|
||||
val BOBBER_SPAWN_POKEMON_POST = EventObservable<BobberSpawnPokemonEvent.Post>()
|
||||
@JvmField
|
||||
val BAIT_EFFECT_REGISTRATION = EventObservable<BaitEffectFunctionRegistryEvent>()
|
||||
|
||||
@JvmField
|
||||
val COLLECT_EGG = CancelableObservable<CollectEggEvent>()
|
||||
@JvmField
|
||||
val HATCH_EGG_PRE = CancelableObservable<HatchEggEvent.Pre>()
|
||||
@JvmField
|
||||
val HATCH_EGG_POST = EventObservable<HatchEggEvent.Post>()
|
||||
}
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.battles.instruction
|
||||
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
|
||||
/**
|
||||
* Event that is fired when a Pokemon Mega Evolves.
|
||||
* @param battle The Pokemon Battle.
|
||||
* @param pokemon The Pokemon that Mega Evolves.
|
||||
*/
|
||||
data class MegaEvolutionEvent(val battle: PokemonBattle, val pokemon: BattlePokemon)
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.battles.instruction
|
||||
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.types.tera.TeraType
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
|
||||
/**
|
||||
* Event that is fired when a Pokemon Terastallizes.
|
||||
* @param battle The Pokemon Battle.
|
||||
* @param pokemon The Pokemon that Terastallizes.
|
||||
* @param teraType The TeraType of the Terastallization.
|
||||
*/
|
||||
data class TerastallizationEvent(
|
||||
val battle: PokemonBattle,
|
||||
val pokemon: BattlePokemon,
|
||||
val teraType: TeraType
|
||||
)
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.battles.instruction
|
||||
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
|
||||
/**
|
||||
* Event that is fired when a Pokemon uses a Z-Move.
|
||||
* @param battle The Pokemon Battle.
|
||||
* @param pokemon The Pokemon that uses the Z-Move.
|
||||
*/
|
||||
data class ZMoveUsedEvent(val battle: PokemonBattle, val pokemon: BattlePokemon)
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.fishing
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
/**
|
||||
* Event that is fired when a bait is consumed.
|
||||
* @param rod The ItemStack of the rod that consumed the bait.
|
||||
*/
|
||||
class BaitConsumedEvent(val rod: ItemStack) : Cancelable()
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.fishing
|
||||
|
||||
import com.cobblemon.mod.common.api.fishing.FishingBait
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
/**
|
||||
* Event to register code-based functions for bait effects.
|
||||
* @see FishingBait.Effect
|
||||
* @see FishingBait.Effects
|
||||
*/
|
||||
class BaitEffectFunctionRegistryEvent {
|
||||
val functions = mutableMapOf<ResourceLocation, (PokemonEntity, FishingBait.Effect) -> Unit>()
|
||||
|
||||
fun registerFunction(id: ResourceLocation, function: (PokemonEntity, FishingBait.Effect) -> Unit) {
|
||||
functions[id] = function
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.fishing
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.reactive.CancelableObservable
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
/**
|
||||
* Event that is fired when a bait is set on a fishing rod.
|
||||
* @param rod The ItemStack of the rod that the bait is set on.
|
||||
* @param bait The ItemStack of the bait that is set on the rod.
|
||||
*/
|
||||
class BaitSetEvent(val rod: ItemStack, val bait: ItemStack) : Cancelable()
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.fishing
|
||||
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnBucket
|
||||
|
||||
/**
|
||||
* Event that is fired when a bucket is chosen by the bobber.
|
||||
* @param chosenBucket The bucket that is chosen.
|
||||
* @param buckets The list of buckets that the bobber can choose from.
|
||||
* @param luckOfTheSeaLevel The level of the Luck of the Sea enchantment on the rod.
|
||||
*/
|
||||
class BobberBucketChosenEvent(var chosenBucket: SpawnBucket, val buckets: MutableList<SpawnBucket>, val luckOfTheSeaLevel: Int)
|
||||
+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.api.events.fishing
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnBucket
|
||||
import com.cobblemon.mod.common.entity.fishing.PokeRodFishingBobberEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
/**
|
||||
* Event that is fired when a Pokemon is spawned by a bobber.
|
||||
*/
|
||||
interface BobberSpawnPokemonEvent {
|
||||
|
||||
/**
|
||||
* Event that is fired before a Pokemon is spawned by a bobber.
|
||||
* @param bobber The PokeRodFishingBobberEntity that is spawning the Pokemon.
|
||||
* @param chosenBucket The bucket that is chosen.
|
||||
* @param rod The ItemStack of the rod that the bobber is attached to.
|
||||
*/
|
||||
data class Pre(
|
||||
val bobber: PokeRodFishingBobberEntity,
|
||||
val chosenBucket: SpawnBucket,
|
||||
val rod: ItemStack
|
||||
) : Cancelable(), BobberSpawnPokemonEvent
|
||||
|
||||
/**
|
||||
* Event that is fired when a Pokemon is modified before it is spawned by a bobber.
|
||||
* @param chosenBucket The bucket that is chosen.
|
||||
* @param rod The ItemStack of the rod that the bobber is attached to.
|
||||
* @param pokemon The Pokemon that is modified.
|
||||
*/
|
||||
data class Modify(
|
||||
val chosenBucket: SpawnBucket,
|
||||
val rod: ItemStack,
|
||||
val pokemon: PokemonEntity
|
||||
) : BobberSpawnPokemonEvent
|
||||
|
||||
/**
|
||||
* Event that is fired after a Pokemon is spawned by a bobber.
|
||||
* @param bobber The PokeRodFishingBobberEntity that is spawning the Pokemon.
|
||||
* @param chosenBucket The bucket that is chosen.
|
||||
* @param bait The ItemStack of the bait that is set on the rod.
|
||||
* @param pokemon The Pokemon that is spawned.
|
||||
*/
|
||||
data class Post(
|
||||
val bobber: PokeRodFishingBobberEntity,
|
||||
val chosenBucket: SpawnBucket,
|
||||
val bait: ItemStack,
|
||||
val pokemon: PokemonEntity
|
||||
) : BobberSpawnPokemonEvent
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.fishing
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.entity.fishing.PokeRodFishingBobberEntity
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
/**
|
||||
* Event that is fired when a fishing rod is cast.
|
||||
*/
|
||||
interface PokerodCastEvent {
|
||||
val rod: ItemStack
|
||||
|
||||
/**
|
||||
* Event that is fired before a fishing rod is cast.
|
||||
* @param rod The ItemStack of the rod that is being cast.
|
||||
* @param bobber The PokeRodFishingBobberEntity that is being cast.
|
||||
* @param bait The ItemStack of the bait that is set on the rod.
|
||||
*/
|
||||
data class Pre(
|
||||
override var rod: ItemStack,
|
||||
var bobber: PokeRodFishingBobberEntity,
|
||||
var bait: ItemStack
|
||||
) : PokerodCastEvent, Cancelable()
|
||||
|
||||
/**
|
||||
* Event that is fired after a fishing rod is cast.
|
||||
* @param rod The ItemStack of the rod that is being cast.
|
||||
* @param bobber The PokeRodFishingBobberEntity that is being cast.
|
||||
* @param bait The ItemStack of the bait that is set on the rod.
|
||||
*/
|
||||
data class Post(
|
||||
override var rod: ItemStack,
|
||||
var bobber: PokeRodFishingBobberEntity,
|
||||
var bait: ItemStack
|
||||
) : PokerodCastEvent
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.fishing
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
/**
|
||||
* Event that is fired when a fishing rod is reeled.
|
||||
* @param rod The ItemStack of the rod that is being reeled.
|
||||
*/
|
||||
class PokerodReelEvent(val rod: ItemStack) : Cancelable()
|
||||
+6
-6
@@ -8,14 +8,14 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokedex.scanning
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData
|
||||
import com.cobblemon.mod.common.pokedex.scanner.ScannableEntity
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
data class PokemonScannedEvent(val player: ServerPlayer, val scannedEntity: PokemonEntity) {
|
||||
val pokemon: Pokemon
|
||||
get() = scannedEntity.pokemon
|
||||
data class PokemonScannedEvent(val player: ServerPlayer, val scannedPokemonEntityData: PokedexEntityData, val scannedEntity: ScannableEntity) {
|
||||
val pokedexEntityData: PokedexEntityData
|
||||
get() = scannedPokemonEntityData
|
||||
|
||||
val isOwned: Boolean
|
||||
get() = pokemon.getOwnerPlayer() == player
|
||||
get() = scannedPokemonEntityData.ownerUUID == player.uuid
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
class CollectEggEvent (
|
||||
val egg : PokemonProperties,
|
||||
val maleParent : Pokemon,
|
||||
val femaleParent : Pokemon,
|
||||
val player : ServerPlayer
|
||||
) : Cancelable()
|
||||
+12
-4
@@ -8,7 +8,15 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
//data class HatchEggEvent (
|
||||
// val pokemon: Pokemon,
|
||||
// val player: ServerPlayer
|
||||
//)
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
interface HatchEggEvent {
|
||||
val egg: PokemonProperties
|
||||
val player: ServerPlayer
|
||||
|
||||
data class Pre(override var egg : PokemonProperties, override var player: ServerPlayer) : HatchEggEvent, Cancelable()
|
||||
|
||||
data class Post(override var egg : PokemonProperties, override var player: ServerPlayer) : HatchEggEvent
|
||||
}
|
||||
|
||||
+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.api.events.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
/**
|
||||
* An event to modify the shiny chance of a Pokémon.
|
||||
*/
|
||||
class ShinyChanceCalculationEvent(
|
||||
val baseChance: Float,
|
||||
val pokemon: Pokemon
|
||||
) {
|
||||
val chance: Float = baseChance
|
||||
var isShiny: Boolean = false
|
||||
private val modifiers = mutableListOf<Float>()
|
||||
private val modificationFunctions = mutableListOf<(Float, ServerPlayer?, Pokemon) -> Float>()
|
||||
|
||||
/**
|
||||
* Adds a modifier to the shiny chance.
|
||||
*/
|
||||
fun addModifier(modifier: Float) {
|
||||
modifiers.add(modifier)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a function to modify the shiny chance.
|
||||
*/
|
||||
fun addModificationFunction(function: (Float, ServerPlayer?, Pokemon) -> Float) {
|
||||
modificationFunctions.add(function)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the shiny chance of a Pokémon.
|
||||
*/
|
||||
fun calculate(player: ServerPlayer?): Float {
|
||||
var result = baseChance
|
||||
for (modifier in modifiers) {
|
||||
result += modifier
|
||||
}
|
||||
for (function in modificationFunctions) {
|
||||
result = function(result, player, pokemon)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun isShiny(player: ServerPlayer?): Boolean {
|
||||
return calculate(player) >= chance || isShiny
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon.healing
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.item.HealingSource
|
||||
import com.cobblemon.mod.common.item.berry.HealingBerryItem
|
||||
import com.cobblemon.mod.common.item.interactive.PotionItem
|
||||
import com.cobblemon.mod.common.item.interactive.PotionType
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
/**
|
||||
* Event that is fired when a Pokemon is healed.
|
||||
* @param pokemon The Pokemon that is being healed.
|
||||
* @param amount The amount of healing that is being applied. If -1, the Pokemon is fully healed.
|
||||
* @param source The HealingSource that is being used to heal the Pokemon.
|
||||
*
|
||||
* @see HealingSource
|
||||
*/
|
||||
class PokemonHealedEvent(
|
||||
val pokemon: Pokemon,
|
||||
var amount: Int = -1,
|
||||
val source: HealingSource = HealingSource.Force
|
||||
) : Cancelable() {
|
||||
fun isFullHeal() = amount == -1
|
||||
fun isHealed() = amount > 0
|
||||
}
|
||||
@@ -8,11 +8,17 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.fishing
|
||||
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.fishing.BaitEffectFunctionRegistryEvent
|
||||
import com.cobblemon.mod.common.api.spawning.fishing.FishingSpawnCause
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.nbt.StringTag
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
@@ -75,18 +81,41 @@ data class FishingBait(
|
||||
}
|
||||
|
||||
object Effects {
|
||||
private val EFFECT_FUNCTIONS: MutableMap<ResourceLocation, (PokemonEntity, Effect) -> Unit> = mutableMapOf()
|
||||
val NATURE = cobblemonResource("nature")
|
||||
val IV = cobblemonResource("iv")
|
||||
val EV = cobblemonResource("ev")
|
||||
val BITE_TIME = cobblemonResource("bite_time")
|
||||
val GENDER_CHANCE = cobblemonResource("gender_chance")
|
||||
val LEVEL_RAISE = cobblemonResource("level_raise")
|
||||
val TERA = cobblemonResource("tera")
|
||||
val TYPING = cobblemonResource("typing")
|
||||
val EGG_GROUP = cobblemonResource("egg_group")
|
||||
val SHINY_REROLL = cobblemonResource("shiny_reroll")
|
||||
val HIDDEN_ABILITY_CHANCE = cobblemonResource("ha_chance")
|
||||
val POKEMON_CHANCE = cobblemonResource("pokemon_chance")
|
||||
val FRIENDSHIP = cobblemonResource("friendship")
|
||||
val INERT = cobblemonResource("inert")
|
||||
|
||||
fun registerEffect(type: ResourceLocation, effect: (PokemonEntity, Effect) -> Unit) {
|
||||
EFFECT_FUNCTIONS[type] = effect
|
||||
}
|
||||
|
||||
fun getEffectFunction(type: ResourceLocation): ((PokemonEntity, Effect) -> Unit)? {
|
||||
return EFFECT_FUNCTIONS[type]
|
||||
}
|
||||
|
||||
fun setupEffects() {
|
||||
EFFECT_FUNCTIONS[NATURE] = { entity, effect -> FishingSpawnCause.alterNatureAttempt(entity, effect) }
|
||||
EFFECT_FUNCTIONS[IV] = { entity, effect -> FishingSpawnCause.alterIVAttempt(entity, effect) }
|
||||
EFFECT_FUNCTIONS[SHINY_REROLL] = { entity, effect -> FishingSpawnCause.shinyReroll(entity, effect) }
|
||||
EFFECT_FUNCTIONS[GENDER_CHANCE] = { entity, effect -> FishingSpawnCause.alterGenderAttempt(entity, effect) }
|
||||
EFFECT_FUNCTIONS[LEVEL_RAISE] = { entity, effect -> FishingSpawnCause.alterLevelAttempt(entity, effect) }
|
||||
EFFECT_FUNCTIONS[HIDDEN_ABILITY_CHANCE] = { entity, _ -> FishingSpawnCause.alterHAAttempt(entity) }
|
||||
EFFECT_FUNCTIONS[FRIENDSHIP] = { entity, effect -> FishingSpawnCause.alterFriendshipAttempt(entity, effect) }
|
||||
CobblemonEvents.BAIT_EFFECT_REGISTRATION.post(BaitEffectFunctionRegistryEvent()) { event ->
|
||||
EFFECT_FUNCTIONS.putAll(event.functions)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.interaction
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.text.yellow
|
||||
import com.cobblemon.mod.common.battles.TeamManager
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* Represents an interaction request between players.
|
||||
*
|
||||
* @author Segfault Guy
|
||||
* @since September 3rd, 2024
|
||||
*/
|
||||
interface PlayerActionRequest {
|
||||
/** The unique ID of this request. */
|
||||
val requestID: UUID
|
||||
|
||||
/** The unique ID of the party that's initiating this request. */
|
||||
val senderID: UUID
|
||||
|
||||
/** The amount of seconds this request is valid for. */
|
||||
val expiryTime: Int
|
||||
}
|
||||
|
||||
/**
|
||||
* An outbound [PlayerActionRequest].
|
||||
*
|
||||
* @author Segfault Guy
|
||||
* @since September 29th, 2024
|
||||
*/
|
||||
interface ServerPlayerActionRequest : PlayerActionRequest {
|
||||
|
||||
/** The subkey identifying lang entries associated with this request. */
|
||||
val key: String
|
||||
|
||||
/** The player initiating this interaction request. */
|
||||
val sender: ServerPlayer
|
||||
|
||||
/** The player that's the target of this interaction request. */
|
||||
val receiver: ServerPlayer
|
||||
|
||||
/** The unique ID of the party that's the target of this request. */
|
||||
val receiverID: UUID get() = receiver.uuid
|
||||
|
||||
override val senderID: UUID get() = sender.uuid
|
||||
|
||||
/** Sends [packet] to sending party of this request. */
|
||||
fun sendToSender(packet: NetworkPacket<*>) = sender.sendPacket(packet)
|
||||
|
||||
/** Sends [packet] to receiving party of this request. */
|
||||
fun sendToReceiver(packet: NetworkPacket<*>) = receiver.sendPacket(packet)
|
||||
|
||||
/** Notifies the sending party of this request about [langKey]. */
|
||||
fun notifySender(error: Boolean, langKey: String, vararg params: Any) = notify(sender, error, "$key.$langKey", *params)
|
||||
|
||||
/** Notifies the receiving party of this request about [langKey]. */
|
||||
fun notifyReceiver(error: Boolean, langKey: String, vararg params: Any) = notify(receiver, error, "$key.$langKey", *params)
|
||||
|
||||
/** System message to inform individual [player] about [langKey]. */
|
||||
fun notify(player: ServerPlayer, error: Boolean, langKey: String, vararg params: Any) {
|
||||
val lang = lang(langKey, *params).apply { if (error) red() else yellow() }
|
||||
player.sendSystemMessage(lang, false)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An outbound [PlayerActionRequest] made on behalf of a team.
|
||||
*
|
||||
* @author Segfault Guy
|
||||
* @since October 29th, 2024
|
||||
*/
|
||||
interface ServerTeamActionRequest : ServerPlayerActionRequest {
|
||||
|
||||
/** The team initiating this request. */
|
||||
val senderTeam: TeamManager.MultiBattleTeam
|
||||
|
||||
/** The team that's the target of this request. */
|
||||
val receiverTeam: TeamManager.MultiBattleTeam
|
||||
|
||||
override val senderID: UUID get() = senderTeam.teamID
|
||||
|
||||
override val receiverID: UUID get() = receiverTeam.teamID
|
||||
|
||||
override fun sendToSender(packet: NetworkPacket<*>) = CobblemonNetwork.sendPacketToPlayers(senderTeam.teamPlayers, packet)
|
||||
|
||||
override fun sendToReceiver(packet: NetworkPacket<*>) = CobblemonNetwork.sendPacketToPlayers(receiverTeam.teamPlayers, packet)
|
||||
|
||||
override fun notifySender(error: Boolean, langKey: String, vararg params: Any) =
|
||||
senderTeam.teamPlayers.forEach { this.notify(it, error, "$key.$langKey", *params) }
|
||||
|
||||
override fun notifyReceiver(error: Boolean, langKey: String, vararg params: Any) =
|
||||
receiverTeam.teamPlayers.forEach { this.notify(it, error, "$key.$langKey", *params) }
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.interaction
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.scheduling.afterOnServer
|
||||
import com.cobblemon.mod.common.api.text.aqua
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.battles.TeamManager
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Defines a manager for organizing active interaction requests between parties. Responsible for dispatching requests to clients,
|
||||
* notifying senders and receivers of requests, and handling their acceptance, expiration, or cancellation.
|
||||
*
|
||||
* Implementations can manage either PLAYER-to-PLAYER requests or TEAM-to-TEAM requests.
|
||||
*
|
||||
* @param T The type of interaction request this manager tracks.
|
||||
*
|
||||
* @author Segfault Guy
|
||||
* @since October 26th, 2024
|
||||
*/
|
||||
abstract class RequestManager<T : ServerPlayerActionRequest> {
|
||||
|
||||
/**
|
||||
* Tracking of the active [ServerPlayerActionRequest]s by their sender.
|
||||
*
|
||||
* NOTE: only 1 request can be sent by a sender at a time.
|
||||
*/
|
||||
private val outboundRequests = mutableMapOf<UUID, T>()
|
||||
|
||||
/**
|
||||
* Tracking of the active [ServerPlayerActionRequest]s by their recipient.
|
||||
*
|
||||
* NOTE: a recipient can receive multiple requests from different senders at the same time.
|
||||
*/
|
||||
private val inboundRequests = mutableMapOf<UUID, MutableList<T>>()
|
||||
|
||||
// we use the term 'sender' because BattleChallenges can be sent TEAM-to-TEAM instead of PLAYER-to-PLAYER for multi battles
|
||||
|
||||
/** Queries the latest pending request that was sent by [senderID]. */
|
||||
fun getOutboundRequest(senderID: UUID) = outboundRequests.get(senderID)
|
||||
|
||||
/** Queries the pending request of [requestID] that was sent by [senderID]. */
|
||||
fun getOutboundRequest(senderID: UUID, requestID: UUID) = this.getOutboundRequest(senderID)?.takeIf { it.requestID == requestID }
|
||||
|
||||
/** Queries the pending request that was sent by [senderID] and received by [receiverID]. */
|
||||
fun getOutboundRequestByRecipient(senderID: UUID, receiverID: UUID) = this.getOutboundRequest(senderID)?.takeIf { it.receiverID == receiverID }
|
||||
|
||||
/** Queries the pending request of [requestID] that was sent by [sender] or their team. */
|
||||
fun getOutboundRequest(sender: ServerPlayer, requestID: UUID) = TeamManager.getTeam(sender)?.let { this.getOutboundRequest(it.teamID, requestID) }
|
||||
?: this.getOutboundRequest(sender.uuid, requestID)
|
||||
|
||||
/** Queries all pending requests that were received by [receiverID]. */
|
||||
fun getInboundRequests(receiverID: UUID) = inboundRequests.get(receiverID)
|
||||
|
||||
/** Queries the pending request of [requestID] that was received by [receiverID]. */
|
||||
fun getInboundRequest(receiverID: UUID, requestID: UUID) = this.getInboundRequests(receiverID)?.find { it.requestID == requestID }
|
||||
|
||||
/** Queries the pending request that was sent by [senderID] and received by [receiverID]. */
|
||||
fun getInboundRequestBySender(receiverID: UUID, senderID: UUID) = this.getInboundRequests(receiverID)?.find { it.senderID == senderID }
|
||||
|
||||
/** Queries the pending request of [requestID] that was received by [receiver] or their team. */
|
||||
fun getInboundRequest(receiver: ServerPlayer, requestID: UUID) = TeamManager.getTeam(receiver)?.let { this.getInboundRequest(it.teamID, requestID) }
|
||||
?: this.getInboundRequest(receiver.uuid, requestID)
|
||||
|
||||
/** Determines whether [player] can receive a [T]. */
|
||||
open fun isBusy(player: ServerPlayer): Boolean = player.isInBattle() || player.isTrading()
|
||||
|
||||
/** Determines if the [target] is a valid interaction request target. */
|
||||
abstract fun isValidInteraction(player: ServerPlayer, target: ServerPlayer): Boolean
|
||||
|
||||
/** Determines whether [request] response is valid and can be accepted. If invalid, notifies the sender and receiver of the request why. */
|
||||
protected abstract fun canAccept(request: T): Boolean
|
||||
|
||||
/** Creates a packet for notifying a recipient about a received request. */
|
||||
protected abstract fun notificationPacket(request: T): NetworkPacket<*>
|
||||
|
||||
/** Creates a packet for canceling received requests. */
|
||||
protected abstract fun expirationPacket(request: T): NetworkPacket<*>
|
||||
|
||||
protected fun addRequest(request: T) {
|
||||
outboundRequests.put(request.senderID, request)
|
||||
inboundRequests.computeIfAbsent(request.receiverID) { mutableListOf() }.add(request)
|
||||
request.sendToReceiver(this.notificationPacket(request))
|
||||
}
|
||||
|
||||
protected fun removeRequest(request: T): Boolean {
|
||||
val inbound = inboundRequests.get(request.receiverID)
|
||||
val removeOutbound = outboundRequests.remove(request.senderID, request)
|
||||
val removeInbound = inbound?.remove(request) == true
|
||||
if (removeInbound && inbound?.size == 0) inboundRequests.remove(request.receiverID, inbound)
|
||||
if (removeInbound != removeOutbound)
|
||||
Cobblemon.LOGGER.error("RequestManager: PlayerActionRequest desync") // USE ADDREQUEST AND REMOVEREQUEST
|
||||
|
||||
val isRemoved = removeInbound && removeOutbound
|
||||
if (isRemoved) request.sendToReceiver(this.expirationPacket(request))
|
||||
return isRemoved
|
||||
}
|
||||
|
||||
/** Notifies and removes an outbound request [T] sent by [ServerPlayerActionRequest.sender] to [ServerPlayerActionRequest.receiver]. */
|
||||
open fun cancelRequest(request: T, expired: Boolean = false) {
|
||||
if (!this.removeRequest(request)) return
|
||||
// canceled by expiration
|
||||
if (expired) {
|
||||
request.notifySender(true, "expired.sender", request.receiver.name.copy().aqua())
|
||||
request.notifyReceiver(true, "expired.receiver", request.sender.name.copy().aqua())
|
||||
}
|
||||
// canceled by sender
|
||||
else {
|
||||
request.notifySender(true, "canceled.sender", request.receiver.name.copy().aqua())
|
||||
request.notifyReceiver(true, "canceled.receiver", request.sender.name.copy().aqua())
|
||||
}
|
||||
// receivers DECLINE, not cancel
|
||||
}
|
||||
|
||||
/** Hook into [sendRequest] immediately after the [request] is sent and added to the manager. Default behavior is to notify parties. */
|
||||
protected open fun onSend(request: T) {
|
||||
request.notifySender(false, "sent", request.receiver.name.copy().aqua())
|
||||
request.notifyReceiver(false, "received", request.sender.name.copy().aqua())
|
||||
}
|
||||
|
||||
/** Sends an outbound request [T] from [ServerPlayerActionRequest.sender] to [ServerPlayerActionRequest.receiver]. */
|
||||
fun sendRequest(request: T): Boolean {
|
||||
val existingRequest = this.getOutboundRequest(request.senderID)
|
||||
val pendingRequest = this.getInboundRequestBySender(request.senderID, request.receiverID)
|
||||
|
||||
// old request
|
||||
if (existingRequest != null && existingRequest.receiverID != request.receiverID)
|
||||
this.cancelRequest(existingRequest)
|
||||
// if sender already has a request awaiting a response from the receiver they're trying to send to.
|
||||
if (existingRequest != null && existingRequest.receiverID == request.receiverID)
|
||||
request.notify(request.sender, true, "${request.key}.error.duplicate", request.receiver.name.copy().aqua())
|
||||
// if sender already has a pending request from the receiver they're trying to send to.
|
||||
else if (pendingRequest != null)
|
||||
request.notify(request.sender, true, "${request.key}.error.pending", request.receiver.name.copy().aqua())
|
||||
// verify sending player can interact with target player
|
||||
else if (!this.isValidInteraction(request.sender, request.receiver))
|
||||
request.notify(request.sender, true, "ui.interact.failed")
|
||||
else if (this.isBusy(request.receiver)) // TODO call to isBusy when setting up the interaction packet
|
||||
request.notify(request.sender, true, "ui.interact.unavailable")
|
||||
// new request
|
||||
else {
|
||||
this.addRequest(request)
|
||||
afterOnServer(seconds = request.expiryTime.toFloat()) { this.cancelRequest(request, true) }
|
||||
this.onSend(request)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/** Hook into [acceptRequest] immediately after the [request] is accepted and removed from the manager. Default behavior is to notify parties. */
|
||||
protected open fun onAccept(request: T) {
|
||||
request.notifySender(false, "accept.sender", request.receiver.name.copy().aqua())
|
||||
request.notifyReceiver(false, "accept.receiver", request.sender.name.copy().aqua())
|
||||
}
|
||||
|
||||
/** Accepts a pending inbound [requestID] for [player]. */
|
||||
fun acceptRequest(player: ServerPlayer, requestID: UUID, target: ServerPlayer? = null): Boolean {
|
||||
var accepted = false
|
||||
val request = this.getInboundRequest(player, requestID)
|
||||
|
||||
// verify request being responded to still valid
|
||||
if (request == null)
|
||||
player.sendSystemMessage(lang("ui.interact.request_already_expired").red(), false)
|
||||
// verify accepting player can respond to sending player
|
||||
else if (!this.isValidInteraction(player, target ?: request.sender)) // with teams anyone can accept
|
||||
request.notify(player, true, "ui.interact.failed")
|
||||
// if sending player is occupied, can't accept response
|
||||
else if (this.isBusy(request.sender)) // TODO enhancement: allow retries - modify client so we don't remove request when sending acceptance
|
||||
request.notify(player, true, "ui.interact.unavailable")
|
||||
// if no condition is blocking acceptance, accept
|
||||
else if (this.canAccept(request))
|
||||
accepted = true
|
||||
|
||||
request?.let {
|
||||
this.removeRequest(it)
|
||||
if (accepted) this.onAccept(request) // order matters
|
||||
}
|
||||
return accepted
|
||||
}
|
||||
|
||||
/** Hook into [declineRequest] immediately after the [request] is declined and removed from the manager. Default behavior is to notify parties. */
|
||||
protected open fun onDecline(request: T) {
|
||||
request.notifySender(true, "decline.sender", request.receiver.name.copy().aqua())
|
||||
request.notifyReceiver(false, "decline.receiver", request.sender.name.copy().aqua())
|
||||
}
|
||||
|
||||
/** Declines a pending [request]. */
|
||||
fun declineRequest(request: T) {
|
||||
this.removeRequest(request)
|
||||
this.onDecline(request)
|
||||
}
|
||||
|
||||
/** Declines an inbound request [requestID] for [receiver]. */
|
||||
fun declineRequest(receiver: ServerPlayer, requestID: UUID) {
|
||||
val request = this.getInboundRequest(receiver, requestID) ?: return
|
||||
this.declineRequest(request)
|
||||
}
|
||||
|
||||
/** Cancels pending outbound requests sent from, and pending inbound request sent to, [player]. */
|
||||
protected open fun onLogoff(player: ServerPlayer) {
|
||||
// ONLY regarding the player. see TeamManager for how team requests are canceled on team disband.
|
||||
outboundRequests.get(player.uuid)?.let { request ->
|
||||
this.cancelRequest(request)
|
||||
}
|
||||
inboundRequests.get(player.uuid)?.toMutableList()?.let { requests ->
|
||||
requests.forEach { request ->
|
||||
this.declineRequest(player, request.requestID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val managers = mutableListOf<RequestManager<*>>()
|
||||
|
||||
fun register(manager: RequestManager<*>) = managers.add(manager)
|
||||
|
||||
fun onLogoff(player: ServerPlayer) = managers.forEach { it.onLogoff(player) }
|
||||
}
|
||||
}
|
||||
@@ -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.api.item
|
||||
|
||||
import com.cobblemon.mod.common.item.interactive.PotionItem
|
||||
|
||||
/**
|
||||
* Interface that represents a source of healing.
|
||||
*/
|
||||
interface HealingSource {
|
||||
/**
|
||||
* A source of healing that is forced, i.e it has no specific source.
|
||||
*/
|
||||
object Force : HealingSource
|
||||
}
|
||||
|
||||
@@ -28,9 +28,13 @@ import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
|
||||
import com.cobblemon.mod.common.api.moves.animations.NPCProvider
|
||||
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.WaveFunctions
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonBehaviourFlag
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.PokemonMoveControl
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.*
|
||||
@@ -52,6 +56,7 @@ import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.tags.TagKey
|
||||
import net.minecraft.world.damagesource.DamageSource
|
||||
import net.minecraft.world.damagesource.DamageTypes
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.level.Level
|
||||
@@ -191,6 +196,7 @@ object MoLangFunctions {
|
||||
map.put("is_in_water") { _ -> DoubleValue(entity.isUnderWater) }
|
||||
map.put("is_touching_water_or_rain") { _ -> DoubleValue(entity.isInWaterRainOrBubble) }
|
||||
map.put("is_touching_water") { _ -> DoubleValue(entity.isInWater) }
|
||||
map.put("is_underwater") { DoubleValue(entity.getIsSubmerged()) }
|
||||
map.put("is_in_lava") { _ -> DoubleValue(entity.isInLava) }
|
||||
map.put("is_on_fire") { _ -> DoubleValue(entity.isOnFire) }
|
||||
map.put("is_invisible") { _ -> DoubleValue(entity.isInvisible) }
|
||||
@@ -207,10 +213,18 @@ object MoLangFunctions {
|
||||
map.put("velocity_x") { _ -> DoubleValue(entity.deltaMovement.x) }
|
||||
map.put("velocity_y") { _ -> DoubleValue(entity.deltaMovement.y) }
|
||||
map.put("velocity_z") { _ -> DoubleValue(entity.deltaMovement.z) }
|
||||
map.put("width") { DoubleValue(entity.boundingBox.xsize) }
|
||||
map.put("height") { DoubleValue(entity.boundingBox.ysize) }
|
||||
map.put("entity_size") { DoubleValue(entity.boundingBox.run { if (xsize > ysize) xsize else ysize }) }
|
||||
map.put("entity_width") { DoubleValue(entity.boundingBox.xsize) }
|
||||
map.put("entity_height") { DoubleValue(entity.boundingBox.ysize) }
|
||||
|
||||
map.put("horizontal_velocity") { _ -> DoubleValue(entity.deltaMovement.horizontalDistance()) }
|
||||
map.put("vertical_velocity") { DoubleValue(entity.deltaMovement.y) }
|
||||
map.put("is_on_ground") { _ -> DoubleValue(entity.onGround()) }
|
||||
map.put("world") { _ -> entity.level().worldRegistry.wrapAsHolder(entity.level()).asWorldMoLangValue() }
|
||||
map.put("biome") { _ -> entity.level().getBiome(entity.blockPosition()).asBiomeMoLangValue() }
|
||||
map.put("is_passenger") { DoubleValue(entity.isPassenger) }
|
||||
map.put("is_healer_in_use") { params ->
|
||||
val pos = params.get<ArrayStruct>(0).asBlockPos()
|
||||
val healer = entity.level().getBlockEntity(pos, CobblemonBlockEntities.HEALING_MACHINE).orElse(null) ?: return@put DoubleValue.ONE
|
||||
@@ -238,6 +252,8 @@ object MoLangFunctions {
|
||||
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
map.put("class") { StringValue(npc.npc.id.toString()) }
|
||||
map.put("name") { StringValue(npc.name.string) }
|
||||
map.put("level") { DoubleValue(npc.level) }
|
||||
map.put("has_aspect") { params -> DoubleValue(npc.aspects.contains(params.getString(0))) }
|
||||
map.put("face") { params -> ObjectValue(ReferenceDialogueFaceProvider(npc.id, params.getBooleanOrNull(0) != false)) }
|
||||
map.put("in_battle") { DoubleValue(npc.isInBattle()) }
|
||||
map.put("run_script_on_client") { params ->
|
||||
@@ -283,7 +299,7 @@ object MoLangFunctions {
|
||||
}
|
||||
map.put("put_pokemon_in_healer") { params ->
|
||||
val healer = npc.level().getBlockEntity(params.get<ArrayStruct>(0).asBlockPos(), CobblemonBlockEntities.HEALING_MACHINE).orElse(null) ?: return@put DoubleValue.ZERO
|
||||
val party = npc.staticParty ?: return@put DoubleValue.ZERO
|
||||
val party = npc.party ?: return@put DoubleValue.ZERO
|
||||
if (healer.canHeal(party)) {
|
||||
healer.activate(npc.uuid, party)
|
||||
return@put DoubleValue.ONE
|
||||
@@ -318,6 +334,43 @@ object MoLangFunctions {
|
||||
}
|
||||
)
|
||||
|
||||
val pokemonFunctions = mutableListOf<(Pokemon) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
|
||||
{ pokemon ->
|
||||
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
map.put("is_wild") { DoubleValue(pokemon.entity?.let { it.ownerUUID == null } == true) }
|
||||
map.put("is_shiny") { DoubleValue(pokemon.shiny) }
|
||||
map.put("form") { StringValue(pokemon.form.name) }
|
||||
map.put("weight") { DoubleValue(pokemon.species.weight.toDouble()) }
|
||||
map
|
||||
}
|
||||
)
|
||||
|
||||
val pokemonEntityFunctions = mutableListOf<(PokemonEntity) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
|
||||
{ pokemonEntity ->
|
||||
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
map.put("in_battle") { DoubleValue(pokemonEntity.isBattling) }
|
||||
map.put("is_moving") { DoubleValue((pokemonEntity.moveControl as? PokemonMoveControl)?.hasWanted() == true) }
|
||||
map.put("is_flying") { DoubleValue(pokemonEntity.getBehaviourFlag(PokemonBehaviourFlag.FLYING)) }
|
||||
map.put("has_aspect") { DoubleValue(it.getString(0) in pokemonEntity.aspects) }
|
||||
map
|
||||
}
|
||||
)
|
||||
|
||||
val partyFunctions = mutableListOf<(PartyStore) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
|
||||
{ party ->
|
||||
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
map.put("get_pokemon") { params ->
|
||||
val index = params.getInt(0)
|
||||
val pokemon = party.get(index) ?: return@put DoubleValue.ZERO
|
||||
val struct = VariableStruct()
|
||||
pokemon.writeVariables(struct)
|
||||
return@put struct
|
||||
}
|
||||
map.put("healing_remainder_percent") { _ -> DoubleValue(party.getHealingRemainderPercent()) }
|
||||
|
||||
return@mutableListOf map
|
||||
})
|
||||
|
||||
fun Holder<Biome>.asBiomeMoLangValue() = asMoLangValue(Registries.BIOME).addFunctions(biomeFunctions)
|
||||
fun Holder<Level>.asWorldMoLangValue() = asMoLangValue(Registries.DIMENSION).addFunctions(worldFunctions)
|
||||
fun Holder<Block>.asBlockMoLangValue() = asMoLangValue(Registries.BLOCK).addFunctions(blockFunctions)
|
||||
@@ -372,6 +425,30 @@ object MoLangFunctions {
|
||||
return this
|
||||
}
|
||||
|
||||
fun QueryStruct.addEntityFunctions(entity: LivingEntity): QueryStruct {
|
||||
val addedFunctions = entityFunctions
|
||||
.flatMap { it.invoke(entity).entries }
|
||||
.associate { it.key to it.value }
|
||||
functions.putAll(addedFunctions)
|
||||
return this
|
||||
}
|
||||
|
||||
fun QueryStruct.addPokemonFunctions(pokemon: Pokemon): QueryStruct {
|
||||
val addedFunctions = pokemonFunctions
|
||||
.flatMap { it.invoke(pokemon).entries }
|
||||
.associate { it.key to it.value }
|
||||
functions.putAll(addedFunctions)
|
||||
return this
|
||||
}
|
||||
|
||||
fun QueryStruct.addPokemonEntityFunctions(pokemonEntity: PokemonEntity): QueryStruct {
|
||||
val addedFunctions = pokemonEntityFunctions
|
||||
.flatMap { it.invoke(pokemonEntity).entries }
|
||||
.associate { it.key to it.value }
|
||||
functions.putAll(addedFunctions)
|
||||
return this
|
||||
}
|
||||
|
||||
fun <T : QueryStruct> T.addFunctions(functions: Map<String, java.util.function.Function<MoParams, Any>>): T {
|
||||
this.functions.putAll(functions)
|
||||
return this
|
||||
|
||||
@@ -35,6 +35,14 @@ class BenchedMoves : Iterable<BenchedMove> {
|
||||
emit = previousEmit
|
||||
}
|
||||
|
||||
fun copyFrom(other: BenchedMoves) {
|
||||
doWithoutEmitting {
|
||||
clear()
|
||||
other.forEach { add(it) }
|
||||
}
|
||||
update()
|
||||
}
|
||||
|
||||
fun doThenEmit(action: () -> Unit) {
|
||||
doWithoutEmitting(action)
|
||||
update()
|
||||
|
||||
+5
-2
@@ -11,12 +11,14 @@ package com.cobblemon.mod.common.api.moves.animations.keyframes
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.EntityProvider
|
||||
import com.cobblemon.mod.common.api.moves.animations.TargetsProvider
|
||||
import com.cobblemon.mod.common.api.moves.animations.UsersProvider
|
||||
import com.cobblemon.mod.common.api.scheduling.delayedFuture
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import net.minecraft.commands.arguments.EntityArgument.getPlayers
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
|
||||
@@ -29,7 +31,8 @@ import net.minecraft.server.level.ServerLevel
|
||||
class EntityParticlesActionEffectKeyframe : ConditionalActionEffectKeyframe(), EntityConditionalActionEffectKeyframe {
|
||||
override val entityCondition = "q.entity.is_user".asExpressionLike()
|
||||
var effect: String? = null
|
||||
var locator: String = "root"
|
||||
var locators: List<String> = listOf("target")
|
||||
|
||||
val delay: ExpressionLike = "0".asExpressionLike()
|
||||
val visibilityRange = 200
|
||||
|
||||
@@ -45,7 +48,7 @@ class EntityParticlesActionEffectKeyframe : ConditionalActionEffectKeyframe(), E
|
||||
}?.asIdentifierDefaultingNamespace() ?: return skip()
|
||||
|
||||
entities.filter { it is PosableEntity }.forEach { entity ->
|
||||
val packet = SpawnSnowstormEntityParticlePacket(effectIdentifier, entity.id, listOf(locator))
|
||||
val packet = SpawnSnowstormEntityParticlePacket(effectIdentifier, entity.id, (locators).toList())
|
||||
val players = (entity.level() as ServerLevel).getPlayers { it.distanceTo(entity) <= visibilityRange }
|
||||
packet.sendToPlayers(players)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.api.npc
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.ai.config.BrainConfig
|
||||
import com.cobblemon.mod.common.api.npc.configuration.NPCBattleConfiguration
|
||||
import com.cobblemon.mod.common.api.npc.configuration.NPCConfigVariable
|
||||
import com.cobblemon.mod.common.api.npc.configuration.NPCInteractConfiguration
|
||||
@@ -39,13 +40,16 @@ class NPCClass {
|
||||
var aspects: MutableSet<String> = mutableSetOf() // These only make sense when applied via presets
|
||||
var hitbox = EntityDimensions.scalable(0.6F, 1.8F)
|
||||
var battleConfiguration = NPCBattleConfiguration()
|
||||
var aiScripts: MutableList<ResourceLocation> = mutableListOf()
|
||||
var interaction: NPCInteractConfiguration? = null
|
||||
var canDespawn = true
|
||||
var variations: MutableMap<String, NPCVariationProvider> = mutableMapOf()
|
||||
var config: MutableList<NPCConfigVariable> = mutableListOf()
|
||||
var variables = mutableMapOf<String, MoValue>() // Questionable whether this should be here.
|
||||
var party: NPCPartyProvider? = null
|
||||
var skill: Int = 0
|
||||
var autoHealParty: Boolean = false
|
||||
var battleTheme: ResourceLocation? = null
|
||||
var ai: MutableList<BrainConfig> = mutableListOf()
|
||||
|
||||
// If you're adding stuff here, add it to NPCPreset and NPCClassAdapter too
|
||||
|
||||
@@ -56,7 +60,6 @@ class NPCClass {
|
||||
buffer.writeFloat(this.hitbox.height)
|
||||
buffer.writeBoolean(this.hitbox.fixed)
|
||||
battleConfiguration.encode(buffer)
|
||||
buffer.writeCollection(aiScripts) { _, v -> buffer.writeString(v.toString()) }
|
||||
buffer.writeNullable(interaction) { _, value ->
|
||||
buffer.writeString(value.type)
|
||||
value.encode(buffer)
|
||||
@@ -75,10 +78,12 @@ class NPCClass {
|
||||
buffer.writeString(v.defaultValue)
|
||||
}
|
||||
buffer.writeInt(skill)
|
||||
buffer.writeBoolean(autoHealParty)
|
||||
buffer.writeMapK(size = IntSize.U_BYTE, map = variables) { (key, value) ->
|
||||
buffer.writeString(key)
|
||||
buffer.writeString(value.asString())
|
||||
}
|
||||
buffer.writeNullable(battleTheme) { _, v -> buffer.writeIdentifier(v) }
|
||||
}
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
@@ -90,7 +95,6 @@ class NPCClass {
|
||||
hitbox = if (fixed) EntityDimensions.fixed(length, width) else EntityDimensions.scalable(length, width)
|
||||
battleConfiguration = NPCBattleConfiguration()
|
||||
battleConfiguration.decode(buffer)
|
||||
aiScripts = buffer.readList { ResourceLocation.parse(buffer.readString()) }.toMutableList()
|
||||
interaction = buffer.readNullable {
|
||||
val type = buffer.readString()
|
||||
val configType = NPCInteractConfiguration.types[type] ?: return@readNullable null
|
||||
@@ -114,6 +118,7 @@ class NPCClass {
|
||||
NPCConfigVariable(variableName, displayName, description, type, defaultValue)
|
||||
}.toMutableList()
|
||||
skill = buffer.readInt()
|
||||
autoHealParty = buffer.readBoolean()
|
||||
buffer.readMapK(size = IntSize.U_BYTE, map = variables) {
|
||||
val key = buffer.readString()
|
||||
val value = buffer.readString()
|
||||
@@ -123,5 +128,6 @@ class NPCClass {
|
||||
return@readMapK key to StringValue(value)
|
||||
}
|
||||
}
|
||||
battleTheme = buffer.readNullable { buffer.readIdentifier() }
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,12 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.npc
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.ai.SleepDepth
|
||||
import com.cobblemon.mod.common.api.ai.config.BrainConfig
|
||||
import com.cobblemon.mod.common.api.ai.config.task.TaskConfig
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.drop.DropEntry
|
||||
@@ -37,6 +40,7 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.world.entity.EntityDimensions
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.level.biome.Biome
|
||||
import net.minecraft.world.level.block.Block
|
||||
@@ -60,12 +64,16 @@ object NPCClasses : JsonDataRegistry<NPCClass> {
|
||||
.registerTypeAdapter(CompoundTag::class.java, NbtCompoundAdapter)
|
||||
.registerTypeAdapter(NPCPartyProvider::class.java, NPCPartyProviderAdapter)
|
||||
.registerTypeAdapter(NPCInteractConfiguration::class.java, NPCInteractConfigurationAdapter)
|
||||
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(NPCVariationProvider::class.java, NPCVariationProviderAdapter)
|
||||
.registerTypeAdapter(MoValue::class.java, MoValueAdapter)
|
||||
.registerTypeAdapter(NPCClass::class.java, NPCClassAdapter)
|
||||
.registerTypeAdapter(Activity::class.java, ActivityAdapter)
|
||||
.registerTypeAdapter(Component::class.java, TextAdapter)
|
||||
.registerTypeAdapter(WeightedAspect::class.java, WeightedAspectAdapter)
|
||||
.registerTypeAdapter(BrainConfig::class.java, BrainConfigAdapter)
|
||||
.registerTypeAdapter(TaskConfig::class.java, TaskConfigAdapter)
|
||||
.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)
|
||||
|
||||
@@ -8,15 +8,11 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.npc
|
||||
|
||||
import com.cobblemon.mod.common.api.npc.partyproviders.DynamicPartyProvider
|
||||
import com.cobblemon.mod.common.api.npc.partyproviders.NPCParty
|
||||
import com.cobblemon.mod.common.api.npc.partyproviders.PoolPartyProvider
|
||||
import com.cobblemon.mod.common.api.npc.partyproviders.SimplePartyProvider
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore
|
||||
import com.cobblemon.mod.common.api.storage.party.NPCPartyStore
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.google.gson.JsonElement
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
/**
|
||||
* A provider of a party for battling the NPC. Completely custom party providers will only display
|
||||
@@ -29,11 +25,13 @@ interface NPCPartyProvider {
|
||||
companion object {
|
||||
val types = mutableMapOf<String, (String) -> NPCPartyProvider>(
|
||||
SimplePartyProvider.TYPE to { SimplePartyProvider() },
|
||||
DynamicPartyProvider.TYPE to { DynamicPartyProvider() }
|
||||
PoolPartyProvider.TYPE to { PoolPartyProvider() }
|
||||
)
|
||||
}
|
||||
|
||||
val type: String
|
||||
fun provide(npc: NPCEntity, level: Int): NPCParty
|
||||
val isStatic: Boolean
|
||||
fun provide(npc: NPCEntity, level: Int): NPCPartyStore
|
||||
// Why did I opt for manual JSON loading??? I must have had a reason but I can't remember. Maybe for S2C? Use a codec doofus
|
||||
fun loadFromJSON(json: JsonElement)
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.npc
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.config.BrainConfig
|
||||
import com.cobblemon.mod.common.api.npc.configuration.NPCConfigVariable
|
||||
import com.cobblemon.mod.common.api.npc.configuration.NPCInteractConfiguration
|
||||
import com.cobblemon.mod.common.api.npc.variation.NPCVariationProvider
|
||||
@@ -22,11 +23,14 @@ class NPCPreset {
|
||||
var variations: Map<String, NPCVariationProvider>? = null
|
||||
var config: List<NPCConfigVariable>? = null
|
||||
var party: NPCPartyProvider? = null
|
||||
var aiScripts: List<ResourceLocation>? = null
|
||||
var canDespawn: Boolean? = null
|
||||
var interaction: NPCInteractConfiguration? = null
|
||||
var names: MutableSet<Component>? = null
|
||||
var hitbox: EntityDimensions? = null
|
||||
var ai: List<BrainConfig>? = null
|
||||
var skill: Int? = null
|
||||
var autoHealParty: Boolean? = null
|
||||
var battleTheme: ResourceLocation? = null
|
||||
|
||||
fun applyTo(npcClass: NPCClass) {
|
||||
resourceIdentifier?.let { npcClass.resourceIdentifier = it }
|
||||
@@ -38,10 +42,14 @@ class NPCPreset {
|
||||
}
|
||||
variations?.entries?.forEach { (key, value) -> npcClass.variations[key] = value }
|
||||
party?.let { npcClass.party = it }
|
||||
aiScripts?.let { npcClass.aiScripts.addAll(it) }
|
||||
canDespawn?.let { npcClass.canDespawn = it }
|
||||
// aiScripts?.let { npcClass.aiScripts.addAll(it) }
|
||||
interaction?.let { npcClass.interaction = it }
|
||||
names?.let { npcClass.names.addAll(it) }
|
||||
hitbox?.let { npcClass.hitbox = it }
|
||||
skill?.let { npcClass.skill = it }
|
||||
autoHealParty?.let { npcClass.autoHealParty = it }
|
||||
battleTheme?.let { npcClass.battleTheme = it }
|
||||
ai?.let { npcClass.ai.addAll(it) }
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,11 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.npc
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.api.ai.SleepDepth
|
||||
import com.cobblemon.mod.common.api.ai.config.BrainConfig
|
||||
import com.cobblemon.mod.common.api.ai.config.task.TaskConfig
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.drop.DropEntry
|
||||
@@ -34,6 +37,7 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.world.entity.EntityDimensions
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.level.biome.Biome
|
||||
import net.minecraft.world.level.block.Block
|
||||
@@ -58,10 +62,14 @@ object NPCPresets : JsonDataRegistry<NPCPreset> {
|
||||
.registerTypeAdapter(NPCPartyProvider::class.java, NPCPartyProviderAdapter)
|
||||
.registerTypeAdapter(NPCInteractConfiguration::class.java, NPCInteractConfigurationAdapter)
|
||||
.registerTypeAdapter(WeightedAspect::class.java, WeightedAspectAdapter)
|
||||
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(NPCVariationProvider::class.java, NPCVariationProviderAdapter)
|
||||
.registerTypeAdapter(Activity::class.java, ActivityAdapter)
|
||||
.registerTypeAdapter(MoValue::class.java, MoValueAdapter)
|
||||
.registerTypeAdapter(Component::class.java, TextAdapter)
|
||||
.registerTypeAdapter(BrainConfig::class.java, BrainConfigAdapter)
|
||||
.registerTypeAdapter(TaskConfig::class.java, TaskConfigAdapter)
|
||||
.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)
|
||||
|
||||
@@ -73,6 +73,7 @@ any number of presets and the properties of those presets will be merged into th
|
||||
"battleConfiguration": {
|
||||
"canChallenge": true
|
||||
},
|
||||
"canDespawn": false,
|
||||
"skill": 5,
|
||||
"party": {
|
||||
"type": "simple",
|
||||
@@ -231,6 +232,10 @@ in this file. The script property can be a single string or an array of strings
|
||||
### battleConfiguration
|
||||
I don't really know whether this is going to stay tbh
|
||||
|
||||
### canDespawn
|
||||
Whether or not regular entity despawning logic applies. By default, NPCs will despawn over time. If the value
|
||||
of this property is set to false, the NPC will never despawn over time.
|
||||
|
||||
### skill
|
||||
The skill level when this NPC is used in battle. This is a number from 1 to 5, with 5 being most difficult
|
||||
to beat. This does not control their Pokémon's levels or moves, but it does control how well they use them.
|
||||
|
||||
+2
-2
@@ -8,15 +8,15 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.npc.configuration
|
||||
|
||||
import com.cobblemon.mod.common.api.npc.NPCPartyProvider
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class NPCBattleConfiguration {
|
||||
var canChallenge = false
|
||||
var party: NPCPartyProvider? = null
|
||||
@Deprecated("This is not likely to get used")
|
||||
var simultaneousBattles = false
|
||||
@Deprecated("This is not likely to get used")
|
||||
var healAfterwards = true
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.npc.partyproviders
|
||||
|
||||
import com.cobblemon.mod.common.api.npc.NPCPartyProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.google.gson.JsonElement
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
/**
|
||||
* A provider of a party for battling the NPC. It generates a [StaticNPCParty] but using a more complex process
|
||||
* that takes an input level and makes a randomized selection of Pokémon and movesets.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since July 12th, 2024
|
||||
*/
|
||||
class DynamicPartyProvider : NPCPartyProvider {
|
||||
companion object {
|
||||
val TYPE = "dynamic"
|
||||
}
|
||||
|
||||
class DynamicPool {
|
||||
val id = ResourceLocation.parse("cobblemon:pool")
|
||||
val pokemon: MutableList<DynamicPokemon> = mutableListOf()
|
||||
}
|
||||
|
||||
|
||||
class DynamicPokemon(
|
||||
val pokemon: PokemonProperties,
|
||||
val possibleLevels: IntRange,
|
||||
val selectableTimes: IntRange,
|
||||
val guaranteed: Boolean = false
|
||||
)
|
||||
|
||||
override val type = "dynamic"
|
||||
|
||||
override fun loadFromJSON(json: JsonElement) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun provide(npc: NPCEntity, level: Int): NPCParty {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.npc.partyproviders
|
||||
|
||||
import com.cobblemon.mod.common.api.storage.party.NPCPartyStore
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.net.IntSize
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.readSizedInt
|
||||
import com.cobblemon.mod.common.util.writeSizedInt
|
||||
import net.minecraft.core.RegistryAccess
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
/**
|
||||
* Represents a party of Pokemon that an NPC can have. This isn't directly a party of Pokémon so that
|
||||
* a dynamically generated party can exist where a party is generated at the time of a challenge.
|
||||
*
|
||||
* This interface is sealed. Implementations should be either [StaticNPCParty] or [DynamicNPCParty].
|
||||
* If you want a custom type then you should implement [DynamicNPCParty] and register it in the
|
||||
* [DynamicNPCParty.types] map.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since July 12th, 2024
|
||||
*/
|
||||
sealed interface NPCParty {
|
||||
fun getParty(player: ServerPlayer, npc: NPCEntity): PartyStore?
|
||||
fun encode(buffer: RegistryFriendlyByteBuf)
|
||||
fun decode(buffer: RegistryFriendlyByteBuf)
|
||||
fun saveToNBT(nbt: CompoundTag, registryAccess: RegistryAccess)
|
||||
fun loadFromNBT(nbt: CompoundTag, registryAccess: RegistryAccess)
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple wrapping around a [NPCPartyStore]. This is a straightforward party that is always the same.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since July 12th, 2024
|
||||
*/
|
||||
class StaticNPCParty(val party: NPCPartyStore) : NPCParty {
|
||||
override fun getParty(player: ServerPlayer, npc: NPCEntity) = party
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeSizedInt(IntSize.U_BYTE, party.size())
|
||||
for (pokemon in party) {
|
||||
Pokemon.S2C_CODEC.encode(buffer, pokemon)
|
||||
}
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
repeat(times = buffer.readSizedInt(IntSize.U_BYTE)) {
|
||||
party.add(Pokemon.S2C_CODEC.decode(buffer))
|
||||
}
|
||||
}
|
||||
|
||||
override fun saveToNBT(nbt: CompoundTag, registryAccess: RegistryAccess) {
|
||||
for ((index, pokemon) in party.withIndex()) {
|
||||
nbt.put(DataKeys.NPC_PARTY_POKEMON + index, pokemon.saveToNBT(registryAccess))
|
||||
}
|
||||
}
|
||||
|
||||
override fun loadFromNBT(nbt: CompoundTag, registryAccess: RegistryAccess) {
|
||||
var index = 0
|
||||
while (nbt.contains(DataKeys.NPC_PARTY_POKEMON + index)) {
|
||||
this.party.add(Pokemon().loadFromNBT(registryAccess, nbt.getCompound(DataKeys.NPC_PARTY_POKEMON + index)))
|
||||
index++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A dynamic party that is generated at the time of a challenge.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since July 12th, 2024
|
||||
*/
|
||||
interface DynamicNPCParty : NPCParty {
|
||||
companion object {
|
||||
val types = mutableMapOf<String, Class<out NPCParty>>()
|
||||
init {}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user