forked from mirrors/cobblemon
Compare commits
443
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2895c0a2ef | ||
|
|
acc87f9eae | ||
|
|
928dfcdadf | ||
|
|
21363405fc | ||
|
|
08c4f4a0ff | ||
|
|
c4a1704a8b | ||
|
|
837aa5acf5 | ||
|
|
969d6ac7fc | ||
|
|
46bb9e1aec | ||
|
|
9792ff3392 | ||
|
|
e863c6d094 | ||
|
|
a070dc56bd | ||
|
|
79f9e0f0f2 | ||
|
|
8500eb58ef | ||
|
|
e835b833b3 | ||
|
|
3b653b745e | ||
|
|
d03541ff6f | ||
|
|
0d7aff0349 | ||
|
|
c904888c6a | ||
|
|
c07d7d304e | ||
|
|
5f94999b4f | ||
|
|
6515bfa108 | ||
|
|
c502fec709 | ||
|
|
756ef48ba2 | ||
|
|
2c4df6622a | ||
|
|
f1213abdf4 | ||
|
|
9b1d847f59 | ||
|
|
bf900a0167 | ||
|
|
703282eca1 | ||
|
|
4e3e6405d0 | ||
|
|
1e161a52ee | ||
|
|
65b2204783 | ||
|
|
a9115bfb15 | ||
|
|
f2c5113f0b | ||
|
|
e29a2402e9 | ||
|
|
aa4857abbb | ||
|
|
d29653233d | ||
|
|
1b51a128d7 | ||
|
|
245011cf5e | ||
|
|
20a97984a2 | ||
|
|
d1517548bd | ||
|
|
3e1f9dc9b0 | ||
|
|
fd19e65f79 | ||
|
|
6b10d81bc8 | ||
|
|
f3b9c03fc2 | ||
|
|
2b95138c46 | ||
|
|
864e6be461 | ||
|
|
c02fa1f85e | ||
|
|
503b1069fd | ||
|
|
f1d593d53c | ||
|
|
55dd486044 | ||
|
|
3263837137 | ||
|
|
a471fcd948 | ||
|
|
a14bfd55d1 | ||
|
|
725e819e89 | ||
|
|
b52b843206 | ||
|
|
74c65e22cb | ||
|
|
c348520a9b | ||
|
|
78dd5f334a | ||
|
|
67318c9307 | ||
|
|
31c48407df | ||
|
|
0957de86c7 | ||
|
|
daae444fa9 | ||
|
|
79423ef5ee | ||
|
|
6255f7dc31 | ||
|
|
ff10306372 | ||
|
|
aaf7daa45b | ||
|
|
ae550f78c4 | ||
|
|
66e4194a3e | ||
|
|
12e6b76504 | ||
|
|
93861af71f | ||
|
|
0c80748012 | ||
|
|
fcf832c22c | ||
|
|
a065aff744 | ||
|
|
d77f424a83 | ||
|
|
d5d2a2cec3 | ||
|
|
036e150191 | ||
|
|
0bf1d84675 | ||
|
|
b1b8e658b2 | ||
|
|
f984b21929 | ||
|
|
0a5193b209 | ||
|
|
43f1f1c30d | ||
|
|
c16597ae41 | ||
|
|
f76e7582d2 | ||
|
|
40761d87db | ||
|
|
89a9ad0bfb | ||
|
|
20291c54a5 | ||
|
|
d6fdfe6ebc | ||
|
|
9f63b62651 | ||
|
|
392632b7d4 | ||
|
|
0d377dcbe0 | ||
|
|
88c31bcb7b | ||
|
|
8efea17ae6 | ||
|
|
cdbf569bbc | ||
|
|
8b81b13d01 | ||
|
|
f19d9410c0 | ||
|
|
9ac3a9249d | ||
|
|
4f340b2eee | ||
|
|
0415cf8a69 | ||
|
|
79af092888 | ||
|
|
5cff52df5f | ||
|
|
ca311fa97c | ||
|
|
27020d3068 | ||
|
|
3ac4b8622f | ||
|
|
acd7a0583c | ||
|
|
e341948bd4 | ||
|
|
1a465abf9d | ||
|
|
e56a6e5b1a | ||
|
|
33d707a73b | ||
|
|
e3c3cd380c | ||
|
|
578ce789b1 | ||
|
|
460e8f7501 | ||
|
|
2fee86e7bc | ||
|
|
f73e631f81 | ||
|
|
0ca0c1a552 | ||
|
|
b3bf2c5ded | ||
|
|
7875006c8e | ||
|
|
67bb63b638 | ||
|
|
511f97b963 | ||
|
|
54c426f5ff | ||
|
|
f89902ece8 | ||
|
|
52c6bbd842 | ||
|
|
8246a822cf | ||
|
|
54202bed98 | ||
|
|
e6313cf4c5 | ||
|
|
7debc6e047 | ||
|
|
bf9b69a143 | ||
|
|
d7f34972c1 | ||
|
|
fa7356d2ed | ||
|
|
812d42a42f | ||
|
|
3f114706fa | ||
|
|
8d1f41919d | ||
|
|
b40c21d99e | ||
|
|
461d8bd282 | ||
|
|
84d34709a3 | ||
|
|
b6c04e8746 | ||
|
|
81a96afaa6 | ||
|
|
724332dd34 | ||
|
|
f5bfd64495 | ||
|
|
bf8f7f628f | ||
|
|
898fdf983f | ||
|
|
a547e0f535 | ||
|
|
564ced926c | ||
|
|
a93dd14fd8 | ||
|
|
f0535901cb | ||
|
|
7a42df591f | ||
|
|
616419880f | ||
|
|
9fa38430c0 | ||
|
|
26012278e7 | ||
|
|
2c0967d293 | ||
|
|
885fc72d93 | ||
|
|
8130cd0998 | ||
|
|
447d35f28b | ||
|
|
bf82def925 | ||
|
|
dace364701 | ||
|
|
d737444ac9 | ||
|
|
95f58ba557 | ||
|
|
8993b007a5 | ||
|
|
c84f9dd112 | ||
|
|
eea7477f7f | ||
|
|
241abd79d7 | ||
|
|
35618cea46 | ||
|
|
31b97d391d | ||
|
|
7769a73246 | ||
|
|
65bf9507d3 | ||
|
|
6d336fc27b | ||
|
|
9514a1d470 | ||
|
|
16df7695c4 | ||
|
|
8fd63912a3 | ||
|
|
04941a9a38 | ||
|
|
1853a1677a | ||
|
|
94f8de8ddc | ||
|
|
7ea866d82a | ||
|
|
ea529a52c2 | ||
|
|
1f6dd03064 | ||
|
|
d62ea394ee | ||
|
|
d0b8a3368c | ||
|
|
6d23e762d6 | ||
|
|
6edb0c19c4 | ||
|
|
71e9adae1f | ||
|
|
35b53daa09 | ||
|
|
937c30fca5 | ||
|
|
141249e6c7 | ||
|
|
94f9bf9f50 | ||
|
|
4638b01279 | ||
|
|
e39d59c37a | ||
|
|
072071d679 | ||
|
|
aa4400395b | ||
|
|
09ad3d0a4d | ||
|
|
de7df10f36 | ||
|
|
897bcf6fc0 | ||
|
|
1e14042455 | ||
|
|
8583c9af4d | ||
|
|
ce756997d6 | ||
|
|
4efc5b6748 | ||
|
|
7ed6075410 | ||
|
|
320d995672 | ||
|
|
8ae91587aa | ||
|
|
61362fa1b1 | ||
|
|
d010129864 | ||
|
|
282f002895 | ||
|
|
863f6de059 | ||
|
|
8ddf628f19 | ||
|
|
8762d518c1 | ||
|
|
46798d694e | ||
|
|
056dd0fd4b | ||
|
|
3ac00d976b | ||
|
|
b30a76855b | ||
|
|
e976556ae3 | ||
|
|
9f16eca621 | ||
|
|
f4a94bd732 | ||
|
|
b6c964e03b | ||
|
|
aed2204483 | ||
|
|
3ed46cb7af | ||
|
|
cf9efe9b8c | ||
|
|
02b9431731 | ||
|
|
a30ae0ccef | ||
|
|
a2905f4d37 | ||
|
|
b3aba1532c | ||
|
|
6369bdb612 | ||
|
|
b5db5605ef | ||
|
|
0207459a0f | ||
|
|
0e2fdfbce8 | ||
|
|
8c9da885c7 | ||
|
|
a5b6529f3c | ||
|
|
6e9bdb6019 | ||
|
|
b430b7db76 | ||
|
|
8015ff0e20 | ||
|
|
ee78657e3d | ||
|
|
6cc84cd38c | ||
|
|
31d6ff541e | ||
|
|
841a40c973 | ||
|
|
e1a4086f24 | ||
|
|
df049a315c | ||
|
|
9ce5486189 | ||
|
|
b1992a94d3 | ||
|
|
167a1ea8eb | ||
|
|
f95beaa7a1 | ||
|
|
1c0f7bbf8f | ||
|
|
34cc2cda46 | ||
|
|
696e58bd1a | ||
|
|
10412b80ca | ||
|
|
458c2ce0ed | ||
|
|
6182715644 | ||
|
|
b41c4c21a8 | ||
|
|
e1893f50ae | ||
|
|
a1bdf3ded6 | ||
|
|
a458b31c9f | ||
|
|
03b5336eb8 | ||
|
|
9e2d00df63 | ||
|
|
e8003bb29a | ||
|
|
a248d661fa | ||
|
|
59390f4d84 | ||
|
|
99b7e4a89e | ||
|
|
fb37e543cf | ||
|
|
c0c75a9735 | ||
|
|
3febee21b6 | ||
|
|
c3a017687c | ||
|
|
afd082c966 | ||
|
|
a6a1f7b75b | ||
|
|
72738a45e6 | ||
|
|
8a0076acb4 | ||
|
|
f7e1def555 | ||
|
|
c13f6ae627 | ||
|
|
c24ab2049d | ||
|
|
b7b1850a4e | ||
|
|
8995c107f7 | ||
|
|
d6a412b91a | ||
|
|
5984d7a126 | ||
|
|
6d8e645092 | ||
|
|
55f0db2263 | ||
|
|
411788a07e | ||
|
|
f6151041c5 | ||
|
|
ac65910380 | ||
|
|
ba6847be9a | ||
|
|
5ddbcd1830 | ||
|
|
47605646d0 | ||
|
|
d9fdf089c2 | ||
|
|
e9a405694c | ||
|
|
8555168a6a | ||
|
|
1b5c0be975 | ||
|
|
5924398eff | ||
|
|
a08855ab37 | ||
|
|
91abe39cdd | ||
|
|
ad8aab7c19 | ||
|
|
aa6b196c29 | ||
|
|
5268447fa3 | ||
|
|
818b39e945 | ||
|
|
30666349a1 | ||
|
|
fb34d4bd23 | ||
|
|
6ca1337ff9 | ||
|
|
98106cad12 | ||
|
|
0d344337dd | ||
|
|
3d27681aaa | ||
|
|
352202203a | ||
|
|
62cfbd7087 | ||
|
|
5a64e8ea1b | ||
|
|
8dc9863a5d | ||
|
|
9280258413 | ||
|
|
51a11163dd | ||
|
|
d5ad84a495 | ||
|
|
1560b142d2 | ||
|
|
b01086270a | ||
|
|
8d5eb5883d | ||
|
|
d5fa693f43 | ||
|
|
0d12bf1190 | ||
|
|
4f773f63cb | ||
|
|
3f3ae74535 | ||
|
|
7429fea802 | ||
|
|
ac5cd47715 | ||
|
|
9901d39f9b | ||
|
|
c635a1d331 | ||
|
|
cf2173a281 | ||
|
|
710d37f453 | ||
|
|
1fb3416211 | ||
|
|
f49f2a7305 | ||
|
|
b0e9c1ab28 | ||
|
|
ac1c7d8b78 | ||
|
|
dec5151eb8 | ||
|
|
196edc2711 | ||
|
|
18015a26fd | ||
|
|
aa296a79a9 | ||
|
|
92dd85643e | ||
|
|
8849de1bfd | ||
|
|
2a349697b4 | ||
|
|
a4055e6206 | ||
|
|
03bda4e27d | ||
|
|
5d8abbd4c7 | ||
|
|
6b167a7a17 | ||
|
|
5c64bc94ff | ||
|
|
d36c24075c | ||
|
|
d1a8122296 | ||
|
|
a8e6e684ab | ||
|
|
188fc2b5d9 | ||
|
|
2bc2e3f020 | ||
|
|
7a15e6b004 | ||
|
|
6ee6beddeb | ||
|
|
b92960da77 | ||
|
|
99618184e7 | ||
|
|
fcdff126fd | ||
|
|
3b285cc8bd | ||
|
|
4dead98e6b | ||
|
|
db36f8da2a | ||
|
|
3a448071d7 | ||
|
|
7215860d74 | ||
|
|
dc899ffc1b | ||
|
|
88fe55bbb9 | ||
|
|
3d3c421b5c | ||
|
|
3c2cfa4ffc | ||
|
|
89a4edb327 | ||
|
|
ab37580258 | ||
|
|
c116c01fd6 | ||
|
|
e3ad8f8079 | ||
|
|
a491d508b6 | ||
|
|
3e11d0550f | ||
|
|
e8b50f8115 | ||
|
|
02fb825328 | ||
|
|
8df6eea107 | ||
|
|
1376bb68f4 | ||
|
|
beb8f2ccf1 | ||
|
|
510dfec0e5 | ||
|
|
e54932c876 | ||
|
|
dd14c3bbdd | ||
|
|
5ea237f8a0 | ||
|
|
fb154ba457 | ||
|
|
f7812896a8 | ||
|
|
b0d57dd875 | ||
|
|
6c09e2b553 | ||
|
|
593104fb0a | ||
|
|
e314664731 | ||
|
|
d0a38a9704 | ||
|
|
6e155d7651 | ||
|
|
ae8f8a2fb8 | ||
|
|
5a6a83aac1 | ||
|
|
e8236b55a4 | ||
|
|
2ea07899ea | ||
|
|
d0ce03cd5e | ||
|
|
8ae0c409a3 | ||
|
|
2782cb5f34 | ||
|
|
2f10707211 | ||
|
|
f40a9d762a | ||
|
|
17587f97e5 | ||
|
|
5230820657 | ||
|
|
61c55e136f | ||
|
|
22cced74f5 | ||
|
|
3cd2dec8e0 | ||
|
|
cea930893a | ||
|
|
8662364ca8 | ||
|
|
1fd079b1b4 | ||
|
|
244876a26c | ||
|
|
e7790f530f | ||
|
|
04a9ab0e67 | ||
|
|
3f338d27c3 | ||
|
|
5da3dfb451 | ||
|
|
fd329e00cd | ||
|
|
6da47a8b2c | ||
|
|
860c73fac9 | ||
|
|
e26fdd4bdd | ||
|
|
8e642f71b8 | ||
|
|
f17884b4e1 | ||
|
|
c40b456948 | ||
|
|
7e74e85315 | ||
|
|
21fd4d7cbf | ||
|
|
908bff9892 | ||
|
|
fa14f70bbb | ||
|
|
188ae2ac85 | ||
|
|
346559f292 | ||
|
|
331b282fcf | ||
|
|
7f97eeafed | ||
|
|
51f5a1f5a8 | ||
|
|
7c0535b8bd | ||
|
|
4f15ac0cbc | ||
|
|
35a0d8a80d | ||
|
|
c0270d3ef0 | ||
|
|
82a1eb2a55 | ||
|
|
a528ea952a | ||
|
|
af2df51a2a | ||
|
|
95a0f9603c | ||
|
|
d38aa6b1a2 | ||
|
|
4566e1b33f | ||
|
|
f2d16ca9b7 | ||
|
|
d6fbb70db0 | ||
|
|
150a5c668a | ||
|
|
1bf01a2826 | ||
|
|
4d1bf677a1 | ||
|
|
069f56acfd | ||
|
|
19cdc8fbef | ||
|
|
1408b94f06 | ||
|
|
de081dc514 | ||
|
|
1538f12934 | ||
|
|
857f67604c | ||
|
|
ae49e3f977 | ||
|
|
ec01a03820 | ||
|
|
96cc3671da | ||
|
|
ad7c9c560c | ||
|
|
ee15ff6b35 | ||
|
|
ca83103703 | ||
|
|
1aeb894b09 | ||
|
|
8e9ab26963 | ||
|
|
44b4fbcfe3 | ||
|
|
42cc1dd8a9 | ||
|
|
d69310e52c | ||
|
|
a0f89274d1 |
+132
-3
@@ -1,5 +1,6 @@
|
||||
# Changelog
|
||||
## [1.5.0](#1-5-0)
|
||||
|
||||
### Additions
|
||||
- Added over (number here) ruin structures, where you can find Pokémon-themed Armor Trims and Pottery Sherds, Tumblestones, and more.
|
||||
- Added (number here) fossil structures, where you can brush Suspicious Sand/Gravel for Fossils.
|
||||
@@ -14,23 +15,133 @@
|
||||
- Added the hidden "True Vivillionaire" advancement.
|
||||
- The "Poké Ball" Vivillon variant is now obtainable by evolving a Spewpa after obtaining the "Aspiring Vivillionaire" advancement.
|
||||
- Added dynamic lighting support for any Species or Forms when using [LambDynamicLights](https://modrinth.com/mod/lambdynamiclights) or [Dynamic Lights Reforged](https://www.curseforge.com/minecraft/mc-mods/dynamiclights-reforged), at this time we don't ship with any defaults for this feature but addon creators can make use of this feature.
|
||||
- Added a Display Case block! Use it to display your archaeological findings, or other items.
|
||||
- Added 6 Pokémon-themed Pottery Sherds, obtained from ruin structures.
|
||||
- Added a Pokémon-themed armor trim, obtained from ruin structures.
|
||||
- You can now find Nether Fire Stone Ore in, surprisingly, the Nether.
|
||||
- You'll also find Terracotta Sun Stone Ore in Badlands biomes.
|
||||
- Added effects for many Poké Balls when sending out Pokémon or capturing.
|
||||
- Added a new send-out ball toss animation that showcases the ball used for the Pokémon.
|
||||
- Added simple move animations for Pokémon in battle with a proof of concept for more complicated animations.
|
||||
- Added the EV Boosting Feathers.
|
||||
- Added Type Gems.
|
||||
- Added various new tags for searchability and better compatibility.
|
||||
- Added the [Ability Capsule](https://bulbapedia.bulbagarden.net/wiki/Ability_Capsule) and [Patch](https://bulbapedia.bulbagarden.net/wiki/Ability_Patch), these have no acquisition method for now and only work as intended with the traditional ability format of 1 to 2 common abilities and 1 hidden ability.
|
||||
- Added Gilded Chests, available in all Apricorn colors.
|
||||
- Added Relic Coins, Relic Coin Pouches, and Relic Coin Sacks.
|
||||
- Added Gimmighoul.
|
||||
- Added various new tags for searchability and better compatibility.
|
||||
- Added Type Gems. These items hold no functionality for now. Start collecting though...
|
||||
- Added 6 custom Pottery Sherds, obtained from ruin structures.
|
||||
- Added cries to Meowth, Alolan Meowth, Galaraian Meowth,
|
||||
- Completed the advancement for placing a Tumblestone near Lava or Magma to make it grow.
|
||||
- Added new held items: Ability Shield, Absorb Bulb, Air Balloon, Binding Band, Blunder Policy, Cell Battery, Covert Cloak, Damp Rock, Eject Button, Eviolite, Expert Belt, Float Stone, Focus Sash, Heat Rock, Icy Rock, Iron Ball, Light Ball, Loaded Dice, Red Card, Shell Bell, Sticky Barb, Smooth Rock, Soothe Bell and Weakness Policy.
|
||||
|
||||
### Pokémon Added
|
||||
#### Gen 2
|
||||
- Sentret
|
||||
- Furret
|
||||
- Qwilfish
|
||||
- Heracross
|
||||
- Skarmory
|
||||
- Ferroseed
|
||||
- Ferrothorn
|
||||
|
||||
#### Gen 3
|
||||
- Lileep
|
||||
- Cradily
|
||||
- Anorith
|
||||
- Armaldo
|
||||
- Tropius
|
||||
- Roselia
|
||||
|
||||
#### Gen 4
|
||||
- Shieldon
|
||||
- Bastiodon
|
||||
- Cranidos
|
||||
- Rampardos
|
||||
- Budew
|
||||
- Roserade
|
||||
|
||||
#### Gen 5
|
||||
- Tirtouga
|
||||
- Carracosta
|
||||
- Archen
|
||||
- Archeops
|
||||
- Zorua
|
||||
- Zoroark
|
||||
- Petilil
|
||||
- Lilligant
|
||||
- Darumaka
|
||||
- Darmanitan
|
||||
- Woobat
|
||||
- Swoobat
|
||||
- Sandile
|
||||
- Krokorok
|
||||
- Krookodile
|
||||
- Frillish
|
||||
- Jellicent
|
||||
- Cubchoo
|
||||
- Beartic
|
||||
- Deino
|
||||
- Zweilous
|
||||
- Hydreigon
|
||||
- Larvesta
|
||||
- Volcarona
|
||||
|
||||
#### Gen 6
|
||||
- Tyrunt
|
||||
- Tyrantrum
|
||||
- Amaura
|
||||
- Aurorus
|
||||
- Goomy
|
||||
- Sliggoo
|
||||
- Goodra
|
||||
|
||||
#### Gen 7
|
||||
- Turtonator
|
||||
- Fomantis
|
||||
- Lurantis
|
||||
- Salandit
|
||||
- Salazzle
|
||||
- Jangmo-o
|
||||
- Hakamo-o
|
||||
- Kommo-o
|
||||
|
||||
#### Gen 8
|
||||
- Gossifleur
|
||||
- Eldegoss
|
||||
- Arctozolt
|
||||
- Arctovish
|
||||
- Dracozolt
|
||||
- Dracovish
|
||||
- Basculegion
|
||||
- Hisuian Zorua
|
||||
- Hisuian Zoroark
|
||||
- Hisuian Voltorb
|
||||
- Hisuian Electrode
|
||||
- Hisuian Qwilfish
|
||||
- Overqwil
|
||||
- Hisuian Sneasel
|
||||
- Sneasler
|
||||
- Stonjourner
|
||||
- Cufant
|
||||
- Copperajah
|
||||
- Dreepy
|
||||
- Drakloak
|
||||
- Dragapult
|
||||
- Hisuian Sliggoo
|
||||
- Hisuian Goodra
|
||||
|
||||
#### Gen 9
|
||||
- Gimmighoul.
|
||||
- Using Relic Coins, you can increase Gimmighoul's Coin Stash. Upon reaching 999, it can be evolved into Gholdengo.
|
||||
- Additionally, if you give Gimmighoul a Netherite Scrap, you can increase its Netherite Stash. Who knows what might happen if it fills up?
|
||||
|
||||
|
||||
### Changes
|
||||
- Pokémon now transition more smoothly between different poses.
|
||||
- Updated models for Mimikyu, Alcremie, Squirtle, Wartortle, Blastoise, Omanyte, Omastar, Growlithe, Swinub, Piloswine, Basculine, Rowlet, Dartrix, Decidueye, Kabuto, Kabutops, Piplup, Prinplup, Elekid, Electabuzz, Cubone, Marowak, Paras, Drifloon, Drifblim, Venonat, Venomoth, Yanma, Yanmega, and Raboot.
|
||||
- Updated animations for Diglett, Dugtrio, Dragonite, Omanyte, Omastar, Pinsir, Falinks, Lechonk, Litwick, Lampent, Chandelure, Carnivine, Galarian Meowth, Galarian Rapidash, Venonat, Venomoth, Phanphy, Donphan, Dratini, Dragonair, Happiny, Chansey, Blissey, Volbeat, Illumise, Numel, Drifloon, and Drifblim.
|
||||
- Added more held items to the held item tag, and Metal Coat to the held item tab.
|
||||
- Added all ores to the modloader ore tags, and added tags for each ore type to the mod (both blocks and items).
|
||||
- Changed the Destiny Knot to be crafted with a Ghast Tear, rather than a diamond.
|
||||
@@ -41,8 +152,16 @@
|
||||
- Apricorn Sprouts can now be planted directly on Apricorn leaves to create a new Apricorn of the same color.
|
||||
- Added tooltips to interaction GUIs to make it clearer what they do.
|
||||
- Poké Ball recipes now use tags for their center ingredient, rather than specificied Copper Ingot, Iron Ingot, Gold Ingot, and Diamond, allowing for further datapack customisation.
|
||||
- Starter Toast now closes once corresponding button is pressed once.
|
||||
- Moved some items in the vanilla Food & Drinks category.
|
||||
- Stacked Cobblemon Potion Bases can now be quick moved into Brewing Stands.
|
||||
- Changed Healer recipe to swap the Max Revive for a Revive.
|
||||
- Upped the rate that Gastly drop Ghast Tears from 2.5% to 5%.
|
||||
- Pokémon with a low Blaze Powder drop chance now drop it more frequently in the Nether.
|
||||
- Reorganised a few advancements.
|
||||
|
||||
### Fixes
|
||||
- Resized Snorlax.
|
||||
- Re-added the recipe for the Iron Vitamin.
|
||||
- Cleaned up empty evolutions declaration in species files (no, I'm not listing all 169 by name).
|
||||
- Fixed Exeggcute not being able to evolve.
|
||||
@@ -61,6 +180,8 @@
|
||||
- Fixed incompatibility with [Just Enough Resources](https://modrinth.com/mod/just-enough-resources-jer).
|
||||
- Fixed incompatibility with [Visual Overhaul](https://modrinth.com/mod/visual-overhaul).
|
||||
- Fixed an issue that allowed Pokemon to spawn on rails.
|
||||
- Fixed the data set on Pokémon when abilities are given via properties such as in ``/spawnpokemon``.
|
||||
- Fixed sometimes Pokémon losing hidden abilities when evolving, this fix will only take effect to newly created Pokémon.
|
||||
|
||||
### Developer
|
||||
- Significantly changed the way properties in PokemonEntity work. This could break some plugins (not in a big way, but changes will be needed).
|
||||
@@ -72,7 +193,13 @@
|
||||
- Made PokemonProperties.parse more interoperable with Java.
|
||||
- Added the ``HeldItemEvent``, this comes with 2 implementation ``HeldItemEvent.Pre`` and ``HeldItemEvent.Post``.
|
||||
- API to support dynamic lighting in any mod that implements this feature has been added to all Species & Forms, see LightingData class for details.
|
||||
- Added a Mixin for the BrewingStandScreenHandler to fix the incorrect handling of quickMove in Fabric.
|
||||
- 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.
|
||||
- ``AbilityChanger`` has been added to API alongside some implementations, this is subject to change as the ability capsule and patch currently only expect the traditional behaviour in the Pokémon games of 1 to 2 regular abilities and 1 hidden.
|
||||
- ``Pokemon#rollAbility`` has been added, this rerolls a legal ability for the Pokémon.
|
||||
- `docs/cobblemon-tags` tags and spawn-presets can now be auto-generated from the current tags in the cobblemon mod with the `generateSpawnPresetList.py` and `generateTagList.py` scripts.
|
||||
- `public_spawns_to_json.py` script has been added to give the powerful spawn.json generator a simplistic UI.
|
||||
|
||||
### Datapack & Resourcepack Creators
|
||||
- The maximum amount of fossils that can fit in the Fossil Analyzer can be adjusted in the config.
|
||||
@@ -107,6 +234,8 @@
|
||||
}
|
||||
```
|
||||
- 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.
|
||||
|
||||
## [1.4.1 (December 23rd, 2023)](#1-4-1)
|
||||
|
||||
@@ -1042,4 +1171,4 @@ Thank you so much to all of our community translators that bring the mod to the
|
||||
- Added species, ability, and move translations for `ko_ko`, `jp_jp`, `fr_fr`, `es_es`, `it_it`, and `zh_cn`.
|
||||
|
||||
## [1.0.0 (November 12th, 2022)](#1-0-0)
|
||||
- Initial release.
|
||||
- Initial release.
|
||||
@@ -15,4 +15,7 @@ dependencies {
|
||||
implementation(libs.shadow)
|
||||
implementation(libs.loom)
|
||||
implementation(libs.architecturyPlugin)
|
||||
|
||||
implementation(libs.blossom)
|
||||
implementation(libs.ideaExt)
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
import extensions.VersionType
|
||||
import extensions.writeVersion
|
||||
|
||||
plugins {
|
||||
java
|
||||
`java-library`
|
||||
@@ -31,7 +34,7 @@ publishing {
|
||||
|
||||
groupId = "com.cobblemon"
|
||||
artifactId = project.findProperty("maven.artifactId")?.toString() ?: project.name
|
||||
version = rootProject.version.toString()
|
||||
version = project.writeVersion(VersionType.PUBLISHING)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package extensions
|
||||
|
||||
import org.gradle.api.Project
|
||||
|
||||
fun Project.version(): String {
|
||||
return rootProject.property("mod_version").toString()
|
||||
}
|
||||
|
||||
fun Project.isSnapshot(): Boolean {
|
||||
return rootProject.property("snapshot") == "true"
|
||||
}
|
||||
|
||||
fun Project.writeVersion(type: VersionType = VersionType.FULL): String {
|
||||
val version = "${rootProject.property("mod_version")}+${rootProject.property("mc_version")}"
|
||||
return when (type) {
|
||||
VersionType.PUBLISHING -> if(this.isSnapshot()) "$version-SNAPSHOT" else version
|
||||
VersionType.FULL -> if(this.isSnapshot()) rootProject.version.toString() else version
|
||||
}
|
||||
}
|
||||
|
||||
enum class VersionType {
|
||||
PUBLISHING,
|
||||
FULL
|
||||
}
|
||||
+2
-2
@@ -9,5 +9,5 @@ version = "${project.property("mod_version")}+${project.property("mc_version")}"
|
||||
|
||||
val isSnapshot = project.property("snapshot")?.equals("true") ?: false
|
||||
if (isSnapshot) {
|
||||
version = "$version-SNAPSHOT-${versioning.info.branch}-${versioning.info.build}"
|
||||
}
|
||||
version = "$version-${versioning.info.branch}-${versioning.info.build}"
|
||||
}
|
||||
|
||||
+42
-2
@@ -1,3 +1,9 @@
|
||||
import extensions.isSnapshot
|
||||
import extensions.version
|
||||
import java.time.OffsetDateTime
|
||||
import java.time.ZoneOffset
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
/*
|
||||
*
|
||||
* * Copyright (C) 2023 Cobblemon Contributors
|
||||
@@ -11,6 +17,10 @@
|
||||
plugins {
|
||||
id("cobblemon.base-conventions")
|
||||
id("cobblemon.publish-conventions")
|
||||
|
||||
id("net.kyori.blossom")
|
||||
id("org.jetbrains.gradle.plugin.idea-ext")
|
||||
id ("net.nemerosa.versioning") version "2.8.2"
|
||||
}
|
||||
|
||||
architectury {
|
||||
@@ -44,8 +54,7 @@ dependencies {
|
||||
modCompileOnly(libs.mongoDriverCore)
|
||||
modCompileOnly(libs.mongoDriverSync)
|
||||
|
||||
testRuntimeOnly(libs.junitEngine)
|
||||
testImplementation(libs.junitApi)
|
||||
testImplementation(libs.fabricJunit)
|
||||
testImplementation(libs.junitParams)
|
||||
testImplementation(libs.mockito)
|
||||
testImplementation(libs.mockk)
|
||||
@@ -59,3 +68,34 @@ tasks.withType<Test> {
|
||||
setExceptionFormat("full")
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
blossom {
|
||||
kotlinSources {
|
||||
fun generateLicenseHeader() : String {
|
||||
val builder = StringBuilder()
|
||||
builder.append("/*\n")
|
||||
rootProject.file("HEADER").forEachLine {
|
||||
if(it.isEmpty()) {
|
||||
builder.append(" *").append("\n")
|
||||
} else {
|
||||
builder.append(" * ").append(it).append("\n")
|
||||
}
|
||||
}
|
||||
|
||||
return builder.append(" */").append("\n").toString()
|
||||
}
|
||||
|
||||
property("license", generateLicenseHeader())
|
||||
property("modid", "cobblemon")
|
||||
property("version", project.version())
|
||||
property("isSnapshot", if(rootProject.isSnapshot()) "true" else "false")
|
||||
property("gitCommit", versioning.info.commit)
|
||||
property("branch", versioning.info.branch)
|
||||
System.getProperty("buildNumber")?.let { property("buildNumber", it) }
|
||||
property("timestamp", OffsetDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss")) + " UTC")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBuildDetails;
|
||||
import net.minecraft.util.crash.CrashReport;
|
||||
import net.minecraft.util.crash.CrashReportSection;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(CrashReport.class)
|
||||
public final class CrashReportMixin {
|
||||
|
||||
@Inject(method = "addStackTrace", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/SystemDetails;writeTo(Ljava/lang/StringBuilder;)V"))
|
||||
public void cobblemon$printCobblemonDetails(StringBuilder builder, CallbackInfo callback) {
|
||||
CrashReportSection cobblemon = new CrashReportSection("Cobblemon");
|
||||
cobblemon.add("Version", CobblemonBuildDetails.VERSION);
|
||||
cobblemon.add("Is Snapshot", CobblemonBuildDetails.SNAPSHOT);
|
||||
cobblemon.add("Git Commit", CobblemonBuildDetails.INSTANCE.smallCommitHash() + " (" + "https://gitlab.com/cable-mc/cobblemon/-/commit/" + CobblemonBuildDetails.GIT_COMMIT + ")");
|
||||
cobblemon.add("Branch", CobblemonBuildDetails.BRANCH);
|
||||
cobblemon.add("Timestamp", CobblemonBuildDetails.TIMESTAMP);
|
||||
|
||||
cobblemon.addStackTrace(builder);
|
||||
builder.append("\n\n");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,18 +9,23 @@
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.mob.PiglinEntity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(PiglinEntity.class)
|
||||
public class PiglinEntityMixin {
|
||||
@Redirect(method = "equipToOffHand", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;isOf(Lnet/minecraft/item/Item;)Z"))
|
||||
public boolean cobblemon$isValidBarteringItem(ItemStack stack, Item item) {
|
||||
//TODO: Make a tag?
|
||||
return stack.isOf(item) || stack.isOf(CobblemonItems.RELIC_COIN_POUCH);
|
||||
public abstract class PiglinEntityMixin {
|
||||
@Inject(method = "equipToOffHand", at = @At(value = "HEAD"), cancellable = true)
|
||||
public void cobblemon$isValidBarteringItem(ItemStack stack, CallbackInfo ci) {
|
||||
PiglinEntity entity = (PiglinEntity)(Object) this;
|
||||
if (stack.isOf(CobblemonItems.RELIC_COIN_POUCH)) {
|
||||
entity.equipStack(EquipmentSlot.OFFHAND, stack);
|
||||
entity.updateDropChances(EquipmentSlot.OFFHAND);
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{{ license }}
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
object CobblemonBuildDetails {
|
||||
|
||||
const val MOD_ID = "{{ modid }}"
|
||||
const val VERSION = "{{ version }}"
|
||||
const val SNAPSHOT = {{ isSnapshot }}
|
||||
|
||||
const val GIT_COMMIT = "{{ gitCommit | default("Not Specified") }}"
|
||||
const val BRANCH = "{{ branch | default("Not Specified") }}"
|
||||
const val TIMESTAMP = "{{ timestamp }}"
|
||||
|
||||
fun smallCommitHash(): String {
|
||||
return this.GIT_COMMIT.substring(0, 7)
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBuildDetails.smallCommitHash
|
||||
import com.cobblemon.mod.common.advancement.CobblemonCriteria
|
||||
import com.cobblemon.mod.common.advancement.criterion.EvolvePokemonContext
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
@@ -16,10 +17,10 @@ import com.cobblemon.mod.common.api.data.DataProvider
|
||||
import com.cobblemon.mod.common.api.drop.CommandDropEntry
|
||||
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.BATTLE_VICTORY
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.DATA_SYNCHRONIZED
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.EVOLUTION_COMPLETE
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.HELD_ITEM_UPDATED
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.LEVEL_UP_EVENT
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.POKEMON_CAPTURED
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.TRADE_COMPLETED
|
||||
@@ -35,7 +36,10 @@ import com.cobblemon.mod.common.api.pokemon.effect.ShoulderEffectRegistry
|
||||
import com.cobblemon.mod.common.api.pokemon.experience.ExperienceCalculator
|
||||
import com.cobblemon.mod.common.api.pokemon.experience.ExperienceGroups
|
||||
import com.cobblemon.mod.common.api.pokemon.experience.StandardExperienceCalculator
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.*
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.ChoiceSpeciesFeatureProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.FlagSpeciesFeatureProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.IntSpeciesFeatureProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.SpeciesFeatures
|
||||
import com.cobblemon.mod.common.api.pokemon.helditem.HeldItemProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.EvCalculator
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Generation8EvCalculator
|
||||
@@ -62,6 +66,7 @@ import com.cobblemon.mod.common.api.storage.player.PlayerDataStoreManager
|
||||
import com.cobblemon.mod.common.api.storage.player.factory.JsonPlayerDataStoreFactory
|
||||
import com.cobblemon.mod.common.api.storage.player.factory.MongoPlayerDataStoreFactory
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonEntityTypeTags
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.battles.BagItems
|
||||
import com.cobblemon.mod.common.battles.BattleFormat
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
@@ -93,7 +98,6 @@ import com.cobblemon.mod.common.pokemon.aspects.SHINY_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.BlockClickEvolution
|
||||
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.pokemon.misc.GimmighoulStashHandler
|
||||
import com.cobblemon.mod.common.pokemon.properties.HiddenAbilityPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.tags.PokemonFlagProperty
|
||||
@@ -115,31 +119,32 @@ 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
|
||||
import java.io.PrintWriter
|
||||
import java.util.UUID
|
||||
import kotlin.properties.Delegates
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import kotlin.reflect.jvm.javaField
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.command.argument.serialize.ConstantArgumentSerializer
|
||||
import net.minecraft.entity.data.TrackedDataHandlerRegistry
|
||||
import net.minecraft.item.Items
|
||||
import net.minecraft.item.NameTagItem
|
||||
import net.minecraft.registry.RegistryKey
|
||||
import net.minecraft.sound.SoundCategory
|
||||
import net.minecraft.util.WorldSavePath
|
||||
import net.minecraft.world.World
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import org.apache.logging.log4j.Logger
|
||||
import java.io.File
|
||||
import java.io.FileReader
|
||||
import java.io.FileWriter
|
||||
import java.io.PrintWriter
|
||||
import java.util.*
|
||||
import kotlin.properties.Delegates
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import kotlin.reflect.jvm.javaField
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
object Cobblemon {
|
||||
const val MODID = "cobblemon"
|
||||
const val VERSION = "1.4.0"
|
||||
const val CONFIG_PATH = "config/$MODID/main.json"
|
||||
val LOGGER = LogManager.getLogger()
|
||||
val LOGGER: Logger = LogManager.getLogger()
|
||||
|
||||
lateinit var implementation: CobblemonImplementation
|
||||
@Deprecated("This field is now a config value", ReplaceWith("Cobblemon.config.captureCalculator"))
|
||||
@@ -169,6 +174,14 @@ object Cobblemon {
|
||||
|
||||
fun preInitialize(implementation: CobblemonImplementation) {
|
||||
this.implementation = implementation
|
||||
|
||||
this.LOGGER.info("Launching Cobblemon ${CobblemonBuildDetails.VERSION}${if(CobblemonBuildDetails.SNAPSHOT) "-SNAPSHOT" else ""} ")
|
||||
if(CobblemonBuildDetails.SNAPSHOT) {
|
||||
this.LOGGER.info(" - Git Commit: ${smallCommitHash()} (https://gitlab.com/cable-mc/cobblemon/-/commit/${CobblemonBuildDetails.GIT_COMMIT})")
|
||||
this.LOGGER.info(" - Branch: ${CobblemonBuildDetails.BRANCH}")
|
||||
this.LOGGER.info(" - Timestamp: ${CobblemonBuildDetails.TIMESTAMP}")
|
||||
}
|
||||
|
||||
implementation.registerPermissionValidator()
|
||||
implementation.registerSoundEvents()
|
||||
implementation.registerBlocks()
|
||||
@@ -231,6 +244,9 @@ object Cobblemon {
|
||||
}
|
||||
}
|
||||
|
||||
// Register the grow_tumblestone advancement
|
||||
PlatformEvents.RIGHT_CLICK_BLOCK.subscribe { AdvancementHandler.onTumbleStonePlaced(it) }
|
||||
|
||||
PlatformEvents.CHANGE_DIMENSION.subscribe {
|
||||
it.player.party().forEach { pokemon -> pokemon.entity?.recallWithAnimation() }
|
||||
}
|
||||
@@ -240,6 +256,16 @@ object Cobblemon {
|
||||
TrackedDataHandlerRegistry.register(PoseTypeDataSerializer)
|
||||
TrackedDataHandlerRegistry.register(IdentifierDataSerializer)
|
||||
|
||||
// Lowest priority because this applies after luxury ball bonus as of gen 4
|
||||
CobblemonEvents.FRIENDSHIP_UPDATED.subscribe(Priority.LOWEST) { event ->
|
||||
var increment = (event.newFriendship - event.pokemon.friendship).toFloat()
|
||||
// Our Luxury ball spec is diff from official, but we will still assume these stack
|
||||
if (event.pokemon.heldItemNoCopy().isIn(CobblemonItemTags.IS_FRIENDSHIP_BOOSTER)) {
|
||||
increment += increment * 0.5F
|
||||
}
|
||||
event.newFriendship = event.pokemon.friendship + increment.roundToInt()
|
||||
}
|
||||
|
||||
HeldItemProvider.register(CobblemonHeldItemManager, Priority.LOWEST)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.block.entity.FossilMultiblockEntity
|
||||
import com.cobblemon.mod.common.block.entity.RestorationTankBlockEntity
|
||||
import com.cobblemon.mod.common.block.multiblock.FossilMultiblockBuilder
|
||||
import com.cobblemon.mod.common.block.entity.*
|
||||
import com.cobblemon.mod.common.block.entity.DisplayCaseBlockEntity
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import net.minecraft.block.entity.BlockEntityType
|
||||
import net.minecraft.registry.Registries
|
||||
@@ -77,4 +78,9 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
|
||||
CobblemonBlocks.FOSSIL_ANALYZER
|
||||
).build(null)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val DISPLAY_CASE: BlockEntityType<DisplayCaseBlockEntity> = this.create("display_case",
|
||||
BlockEntityType.Builder.create(::DisplayCaseBlockEntity, CobblemonBlocks.DISPLAY_CASE).build(null)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -72,6 +72,8 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
@JvmField
|
||||
val SUN_STONE_ORE = evolutionStoneOre("sun_stone_ore")
|
||||
@JvmField
|
||||
val TERRACOTTA_SUN_STONE_ORE = evolutionStoneOre("terracotta_sun_stone_ore")
|
||||
@JvmField
|
||||
val THUNDER_STONE_ORE = evolutionStoneOre("thunder_stone_ore")
|
||||
@JvmField
|
||||
val WATER_STONE_ORE = evolutionStoneOre("water_stone_ore")
|
||||
@@ -158,7 +160,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
@JvmField
|
||||
val BIG_ROOT = this.create("big_root", BigRootBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DARK_GREEN).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.BIG_ROOT_SOUNDS)))
|
||||
@JvmField
|
||||
val REVIVAL_HERB = this.create("revival_herb", RevivalHerbBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).mapColor(MapColor.DARK_GREEN).burnable().noCollision().breakInstantly().sounds(BlockSoundGroup.CROP)))
|
||||
val REVIVAL_HERB = this.create("revival_herb", RevivalHerbBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).mapColor(MapColor.DARK_GREEN).burnable().noCollision().breakInstantly().sounds(CobblemonSounds.REVIVAL_HERB_SOUNDS)))
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE_CLUSTER = tumblestoneBlock("tumblestone_cluster", GrowableStoneBlock.STAGE_3, 7, 3, null)
|
||||
@@ -387,6 +389,18 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val DISPLAY_CASE = create(
|
||||
"display_case",
|
||||
DisplayCaseBlock(
|
||||
AbstractBlock.Settings.create()
|
||||
.sounds(CobblemonSounds.DISPLAY_CASE_SOUNDS)
|
||||
.nonOpaque()
|
||||
.pistonBehavior(PistonBehavior.BLOCK)
|
||||
.mapColor(MapColor.STONE_GRAY)
|
||||
.strength(0.3f)
|
||||
)
|
||||
)
|
||||
|
||||
val RED_MINT = create("red_mint", MintBlock(MintType.RED, AbstractBlock.Settings.create().mapColor(MapColor.RED).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MINT_SOUNDS)))
|
||||
@JvmField
|
||||
val BLUE_MINT = create("blue_mint", MintBlock(MintType.BLUE, AbstractBlock.Settings.create().mapColor(MapColor.BLUE).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MINT_SOUNDS)))
|
||||
@@ -414,7 +428,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE_SEEDS = this.create("vivichoke_seeds", VivichokeBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DARK_GREEN).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
|
||||
val VIVICHOKE_SEEDS = this.create("vivichoke_seeds", VivichokeBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DARK_GREEN).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.VIVICHOKE_SOUNDS)))
|
||||
@JvmField
|
||||
val PEP_UP_FLOWER = this.create("pep_up_flower", FlowerBlock(StatusEffects.LEVITATION, 10, AbstractBlock.Settings.create().mapColor(MapColor.DARK_GREEN).noCollision().breakInstantly().sounds(BlockSoundGroup.GRASS).offset(AbstractBlock.OffsetType.XZ).pistonBehavior(PistonBehavior.DESTROY)))
|
||||
@JvmField
|
||||
|
||||
@@ -48,5 +48,9 @@ object CobblemonCommands {
|
||||
PokemonRestartCommand.register(dispatcher)
|
||||
BedrockParticleCommand.register(dispatcher)
|
||||
OpenDialogueCommand.register(dispatcher)
|
||||
|
||||
// Possibly lock down registration if and only if under dev environment or running in an environment
|
||||
// with a certain system environment variable set
|
||||
CobblemonInfoCommand.register(dispatcher)
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.item.ability.AbilityChanger
|
||||
import com.cobblemon.mod.common.api.mulch.MulchVariant
|
||||
import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.api.pokemon.Natures
|
||||
@@ -29,6 +30,8 @@ import com.cobblemon.mod.common.item.berry.PortionHealingBerryItem
|
||||
import com.cobblemon.mod.common.item.berry.StatusCuringBerryItem
|
||||
import com.cobblemon.mod.common.item.berry.VolatileCuringBerryItem
|
||||
import com.cobblemon.mod.common.item.interactive.*
|
||||
import com.cobblemon.mod.common.item.interactive.PotionItem
|
||||
import com.cobblemon.mod.common.item.interactive.ability.AbilityChangeItem
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import com.cobblemon.mod.common.pokeball.PokeBall
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
@@ -37,14 +40,7 @@ import net.minecraft.block.Block
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.entity.effect.StatusEffectInstance
|
||||
import net.minecraft.entity.effect.StatusEffects
|
||||
import net.minecraft.item.BlockItem
|
||||
import net.minecraft.item.FoodComponent
|
||||
import net.minecraft.item.HangingSignItem
|
||||
import net.minecraft.item.Item
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.item.SignItem
|
||||
import net.minecraft.item.SmithingTemplateItem
|
||||
import net.minecraft.item.StewItem
|
||||
import net.minecraft.item.*
|
||||
import net.minecraft.registry.Registries
|
||||
import net.minecraft.registry.Registry
|
||||
import net.minecraft.registry.RegistryKey
|
||||
@@ -258,6 +254,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
val PC = blockItem("pc", CobblemonBlocks.PC)
|
||||
@JvmField
|
||||
val PASTURE = blockItem("pasture", CobblemonBlocks.PASTURE)
|
||||
@JvmField
|
||||
val DISPLAY_CASE = blockItem("display_case", CobblemonBlocks.DISPLAY_CASE)
|
||||
|
||||
// Evolution items
|
||||
@JvmField val LINK_CABLE = create("link_cable", LinkCableItem())
|
||||
@@ -285,6 +283,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
@JvmField val RIBBON_SWEET = noSettingsItem("ribbon_sweet")
|
||||
@JvmField val CHIPPED_POT = noSettingsItem("chipped_pot")
|
||||
@JvmField val CRACKED_POT = noSettingsItem("cracked_pot")
|
||||
@JvmField val MASTERPIECE_TEACUP = noSettingsItem("masterpiece_teacup")
|
||||
@JvmField val UNREMARKABLE_TEACUP = noSettingsItem("unremarkable_teacup")
|
||||
@JvmField val SWEET_APPLE = noSettingsItem("sweet_apple")
|
||||
@JvmField val TART_APPLE = noSettingsItem("tart_apple")
|
||||
@JvmField val GALARICA_CUFF = noSettingsItem("galarica_cuff")
|
||||
@@ -408,7 +408,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
@JvmField
|
||||
val CLEVER_FEATHER = create("clever_feather", FeatherItem(Stats.SPECIAL_DEFENCE))
|
||||
@JvmField
|
||||
val MEDICINAL_LEEK = create("medicinal_leek", MedicinalLeekItem(CobblemonBlocks.MEDICINAL_LEEK, Item.Settings().food(FoodComponent.Builder().snack().hunger(1).saturationModifier(0.2f).build())))
|
||||
val MEDICINAL_LEEK = heldItem("medicinal_leek", MedicinalLeekItem(CobblemonBlocks.MEDICINAL_LEEK, Item.Settings().food(FoodComponent.Builder().snack().hunger(1).saturationModifier(0.2f).build())), "leek")
|
||||
@JvmField
|
||||
val ROASTED_LEEK = create("roasted_leek", Item(Item.Settings().food(FoodComponent.Builder().snack().hunger(3).saturationModifier(0.3f).build())))
|
||||
@JvmField
|
||||
@@ -558,6 +558,11 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
@JvmField val ELIXIR = create("elixir", ElixirItem(max = false))
|
||||
@JvmField val MAX_ELIXIR = create("max_elixir", ElixirItem(max = true))
|
||||
|
||||
@JvmField
|
||||
val ABILITY_CAPSULE = this.create("ability_capsule", AbilityChangeItem(AbilityChanger.COMMON_ABILITY))
|
||||
@JvmField
|
||||
val ABILITY_PATCH = this.create("ability_patch", AbilityChangeItem(AbilityChanger.HIDDEN_ABILITY))
|
||||
|
||||
/**
|
||||
* Evolution Ores and Stones
|
||||
*/
|
||||
@@ -578,6 +583,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
@JvmField
|
||||
val SUN_STONE_ORE = blockItem("sun_stone_ore", CobblemonBlocks.SUN_STONE_ORE)
|
||||
@JvmField
|
||||
val TERRACOTTA_SUN_STONE_ORE = blockItem("terracotta_sun_stone_ore", CobblemonBlocks.TERRACOTTA_SUN_STONE_ORE)
|
||||
@JvmField
|
||||
val THUNDER_STONE_ORE = blockItem("thunder_stone_ore", CobblemonBlocks.THUNDER_STONE_ORE)
|
||||
@JvmField
|
||||
val WATER_STONE_ORE = blockItem("water_stone_ore", CobblemonBlocks.WATER_STONE_ORE)
|
||||
@@ -629,16 +636,28 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
|
||||
// Held Items
|
||||
@JvmField
|
||||
val ABILITY_SHIELD = heldItem("ability_shield")
|
||||
@JvmField
|
||||
val ABSORB_BULB = heldItem("absorb_bulb")
|
||||
@JvmField
|
||||
val AIR_BALLOON = heldItem("air_balloon")
|
||||
@JvmField
|
||||
val ASSAULT_VEST = heldItem("assault_vest")
|
||||
@JvmField
|
||||
val BIG_ROOT = blockItem("big_root", CobblemonBlocks.BIG_ROOT)
|
||||
@JvmField
|
||||
val BINDING_BAND = heldItem("binding_band")
|
||||
@JvmField
|
||||
val BLACK_BELT = heldItem("black_belt")
|
||||
@JvmField
|
||||
val BLACK_GLASSES = heldItem("black_glasses")
|
||||
@JvmField
|
||||
val BLACK_SLUDGE = heldItem("black_sludge")
|
||||
@JvmField
|
||||
val BLUNDER_POLICY = heldItem("blunder_policy")
|
||||
@JvmField
|
||||
val CELL_BATTERY = heldItem("cell_battery")
|
||||
@JvmField
|
||||
val CHARCOAL = heldItem("charcoal_stick", remappedName = "charcoal")
|
||||
@JvmField
|
||||
val CHOICE_BAND = heldItem("choice_band")
|
||||
@@ -649,26 +668,64 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
@JvmField
|
||||
val CLEANSE_TAG = heldItem("cleanse_tag")
|
||||
@JvmField
|
||||
val CLEAR_AMULET = heldItem("clear_amulet")
|
||||
@JvmField
|
||||
val COVERT_CLOAK = heldItem("covert_cloak")
|
||||
@JvmField
|
||||
val DESTINY_KNOT = heldItem("destiny_knot")
|
||||
@JvmField
|
||||
val DRAGON_FANG = heldItem("dragon_fang")
|
||||
@JvmField
|
||||
val EJECT_BUTTON = heldItem("eject_button")
|
||||
@JvmField
|
||||
val EJECT_PACK = heldItem("eject_pack")
|
||||
@JvmField
|
||||
val EVERSTONE = heldItem("everstone")
|
||||
@JvmField
|
||||
val EVIOLITE = heldItem("eviolite")
|
||||
@JvmField
|
||||
val EXP_SHARE = heldItem("exp_share")
|
||||
@JvmField
|
||||
val EXPERT_BELT = heldItem("expert_belt")
|
||||
@JvmField
|
||||
val FAIRY_FEATHER = heldItem("fairy_feather")
|
||||
@JvmField
|
||||
val FLAME_ORB = heldItem("flame_orb")
|
||||
@JvmField
|
||||
val FLOAT_STONE = heldItem("float_stone")
|
||||
@JvmField
|
||||
val FOCUS_BAND = heldItem("focus_band")
|
||||
@JvmField
|
||||
val FOCUS_SASH = heldItem("focus_sash")
|
||||
@JvmField
|
||||
val GRIP_CLAW = heldItem("grip_claw")
|
||||
@JvmField
|
||||
val HARD_STONE = heldItem("hard_stone")
|
||||
@JvmField
|
||||
val HEAVY_DUTY_BOOTS = heldItem("heavy_duty_boots")
|
||||
@JvmField
|
||||
val IRON_BALL = heldItem("iron_ball")
|
||||
@JvmField
|
||||
val LAGGING_TAIL = heldItem("lagging_tail")
|
||||
@JvmField
|
||||
val LEFTOVERS = heldItem("leftovers")
|
||||
@JvmField
|
||||
val LIFE_ORB = heldItem("life_orb")
|
||||
@JvmField
|
||||
val LIGHT_BALL = heldItem("light_ball")
|
||||
@JvmField
|
||||
val LIGHT_CLAY = heldItem("light_clay")
|
||||
@JvmField
|
||||
val LOADED_DICE = heldItem("loaded_dice")
|
||||
@JvmField
|
||||
val LUCKY_EGG = heldItem("lucky_egg")
|
||||
@JvmField
|
||||
val LUMINOUS_MOSS = heldItem("luminous_moss")
|
||||
@JvmField
|
||||
val MAGNET = heldItem("magnet")
|
||||
@JvmField
|
||||
val METRONOME = heldItem("metronome")
|
||||
@JvmField
|
||||
val MIRACLE_SEED = heldItem("miracle_seed")
|
||||
@JvmField
|
||||
val MUSCLE_BAND = heldItem("muscle_band")
|
||||
@@ -679,14 +736,42 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
@JvmField
|
||||
val POISON_BARB = heldItem("poison_barb")
|
||||
@JvmField
|
||||
val POWER_ANKLET = heldItem("power_anklet")
|
||||
@JvmField
|
||||
val POWER_BAND = heldItem("power_band")
|
||||
@JvmField
|
||||
val POWER_BELT = heldItem("power_belt")
|
||||
@JvmField
|
||||
val POWER_BRACER = heldItem("power_bracer")
|
||||
@JvmField
|
||||
val POWER_LENS = heldItem("power_lens")
|
||||
@JvmField
|
||||
val POWER_WEIGHT = heldItem("power_weight")
|
||||
@JvmField
|
||||
val PROTECTIVE_PADS = heldItem("protective_pads")
|
||||
@JvmField
|
||||
val PUNCHING_GLOVE = heldItem("punching_glove")
|
||||
@JvmField
|
||||
val QUICK_CLAW = heldItem("quick_claw")
|
||||
@JvmField
|
||||
val RED_CARD = heldItem("red_card")
|
||||
@JvmField
|
||||
val RING_TARGET = heldItem("ring_target")
|
||||
@JvmField
|
||||
val ROCKY_HELMET = heldItem("rocky_helmet")
|
||||
@JvmField
|
||||
val ROOM_SERVICE = heldItem("room_service")
|
||||
@JvmField
|
||||
val SAFETY_GOGGLES = heldItem("safety_goggles")
|
||||
@JvmField
|
||||
val SCOPE_LENS = heldItem("scope_lens")
|
||||
@JvmField
|
||||
val SHARP_BEAK = heldItem("sharp_beak")
|
||||
@JvmField
|
||||
val SHED_SHELL = heldItem("shed_shell")
|
||||
@JvmField
|
||||
val SHELL_BELL = heldItem("shell_bell")
|
||||
@JvmField
|
||||
val SILK_SCARF = heldItem("silk_scarf")
|
||||
@JvmField
|
||||
val SILVER_POWDER = heldItem("silver_powder")
|
||||
@@ -695,10 +780,30 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
@JvmField
|
||||
val SPELL_TAG = heldItem("spell_tag")
|
||||
@JvmField
|
||||
val SMOKE_BALL = heldItem("smoke_ball")
|
||||
@JvmField
|
||||
val SOOTHE_BELL = heldItem("soothe_bell")
|
||||
@JvmField
|
||||
val STICKY_BARB = heldItem("sticky_barb")
|
||||
@JvmField
|
||||
val TERRAIN_EXTENDER = heldItem("terrain_extender")
|
||||
@JvmField
|
||||
val THROAT_SPRAY = heldItem("throat_spray")
|
||||
@JvmField
|
||||
val TOXIC_ORB = heldItem("toxic_orb")
|
||||
@JvmField
|
||||
val TWISTED_SPOON = heldItem("twisted_spoon")
|
||||
@JvmField
|
||||
val UTILITY_UMBRELLA = heldItem("utility_umbrella")
|
||||
@JvmField
|
||||
val WEAKNESS_POLICY = heldItem("weakness_policy")
|
||||
@JvmField
|
||||
val WIDE_LENS = heldItem("wide_lens")
|
||||
@JvmField
|
||||
val WISE_GLASSES = heldItem("wise_glasses")
|
||||
@JvmField
|
||||
val ZOOM_LENS = heldItem("zoom_lens")
|
||||
@JvmField
|
||||
val MENTAL_HERB = compostableHeldItem("mental_herb", null, 1F)
|
||||
@JvmField
|
||||
val MIRROR_HERB = compostableHeldItem("mirror_herb", null, 1F)
|
||||
@@ -713,29 +818,13 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
@JvmField
|
||||
val QUICK_POWDER = heldItem("quick_powder")
|
||||
@JvmField
|
||||
val DESTINY_KNOT = heldItem("destiny_knot")
|
||||
val DAMP_ROCK = heldItem("damp_rock")
|
||||
@JvmField
|
||||
val EVERSTONE = heldItem("everstone")
|
||||
val HEAT_ROCK = heldItem("heat_rock")
|
||||
@JvmField
|
||||
val POWER_ANKLET = heldItem("power_anklet")
|
||||
val SMOOTH_ROCK = heldItem("smooth_rock")
|
||||
@JvmField
|
||||
val POWER_BAND = heldItem("power_band")
|
||||
@JvmField
|
||||
val POWER_BELT = heldItem("power_belt")
|
||||
@JvmField
|
||||
val POWER_BRACER = heldItem("power_bracer")
|
||||
@JvmField
|
||||
val POWER_LENS = heldItem("power_lens")
|
||||
@JvmField
|
||||
val POWER_WEIGHT = heldItem("power_weight")
|
||||
@JvmField
|
||||
val FLAME_ORB = heldItem("flame_orb")
|
||||
@JvmField
|
||||
val LIFE_ORB = heldItem("life_orb")
|
||||
@JvmField
|
||||
val TOXIC_ORB = heldItem("toxic_orb")
|
||||
@JvmField
|
||||
val SMOKE_BALL = heldItem("smoke_ball")
|
||||
val ICY_ROCK = heldItem("icy_rock")
|
||||
|
||||
// Mulch
|
||||
@JvmField
|
||||
@@ -922,6 +1011,16 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
}
|
||||
}
|
||||
)
|
||||
private fun heldItem(name: String, item: Item, remappedName: String? = null) = create(
|
||||
name = name,
|
||||
entry = item.also {
|
||||
if (remappedName != null) {
|
||||
CobblemonHeldItemManager.registerRemap(it, remappedName)
|
||||
CobblemonHeldItemManager.registerRemap(Items.BONE, "thickclub")
|
||||
CobblemonHeldItemManager.registerRemap(Items.SNOWBALL, "snowball")
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
private fun compostable(item: Item, increaseLevelChance: Float) = Cobblemon.implementation.registerCompostable(item, increaseLevelChance)
|
||||
|
||||
|
||||
@@ -99,27 +99,27 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
|
||||
val MULCH_REMOVE = this.create("mulch.remove")
|
||||
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_ACTIVATE = this.create("fossilmachine.activate")
|
||||
val FOSSIL_MACHINE_ACTIVATE = this.create("fossil_machine.activate")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_ACTIVE_LOOP = this.create("fossilmachine.active_loop")
|
||||
val FOSSIL_MACHINE_ACTIVE_LOOP = this.create("fossil_machine.active_loop")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_ASSEMBLE = this.create("fossilmachine.assemble")
|
||||
val FOSSIL_MACHINE_ASSEMBLE = this.create("fossil_machine.assemble")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_DNA_FULL = this.create("fossilmachine.dna_full")
|
||||
val FOSSIL_MACHINE_DNA_FULL = this.create("fossil_machine.dna_full")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_FINISHED = this.create("fossilmachine.finished")
|
||||
val FOSSIL_MACHINE_FINISHED = this.create("fossil_machine.finished")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_INSERT_DNA = this.create("fossilmachine.insert_dna")
|
||||
val FOSSIL_MACHINE_INSERT_DNA = this.create("fossil_machine.insert_dna")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_INSERT_DNA_SMALL = this.create("fossilmachine.insert_dna_small")
|
||||
val FOSSIL_MACHINE_INSERT_DNA_SMALL = this.create("fossil_machine.insert_dna_small")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_INSERT_FOSSIL = this.create("fossilmachine.insert_fossil")
|
||||
val FOSSIL_MACHINE_INSERT_FOSSIL = this.create("fossil_machine.insert_fossil")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_RETRIEVE_FOSSIL = this.create("fossilmachine.retrieve_fossil")
|
||||
val FOSSIL_MACHINE_RETRIEVE_FOSSIL = this.create("fossil_machine.retrieve_fossil")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_RETRIEVE_POKEMON = this.create("fossilmachine.retrieve_pokemon")
|
||||
val FOSSIL_MACHINE_RETRIEVE_POKEMON = this.create("fossil_machine.retrieve_pokemon")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_UNPROTECTED = this.create("fossilmachine.unprotected")
|
||||
val FOSSIL_MACHINE_UNPROTECTED = this.create("fossil_machine.unprotected")
|
||||
|
||||
@JvmField
|
||||
val COIN_POUCH_BREAK = this.create("coin_pouch.break")
|
||||
@@ -155,11 +155,21 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
|
||||
@JvmField
|
||||
val ENERGY_ROOT_PLACE = this.create("energy_root.place")
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE_BREAK = this.create("vivichoke.break")
|
||||
@JvmField
|
||||
val VIVICHOKE_PLACE = this.create("vivichoke.place")
|
||||
|
||||
@JvmField
|
||||
val MINT_BREAK = this.create("mint.break")
|
||||
@JvmField
|
||||
val MINT_PLACE = this.create("mint.place")
|
||||
|
||||
@JvmField
|
||||
val REVIVAL_HERB_BREAK = this.create("revival_herb.break")
|
||||
@JvmField
|
||||
val REVIVAL_HERB_PLACE = this.create("revival_herb.place")
|
||||
|
||||
@JvmField
|
||||
val MEDICINAL_LEEK_BREAK = this.create("medicinal_leek.break")
|
||||
@JvmField
|
||||
@@ -277,6 +287,15 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
|
||||
SoundEvents.BLOCK_GRASS_FALL
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
VIVICHOKE_BREAK,
|
||||
SoundEvents.BLOCK_GRASS_STEP,
|
||||
VIVICHOKE_PLACE,
|
||||
SoundEvents.BLOCK_GRASS_HIT,
|
||||
SoundEvents.BLOCK_GRASS_FALL
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val MINT_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
MINT_BREAK,
|
||||
@@ -286,6 +305,15 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
|
||||
SoundEvents.BLOCK_GRASS_FALL
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val REVIVAL_HERB_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
REVIVAL_HERB_BREAK,
|
||||
SoundEvents.BLOCK_GRASS_STEP,
|
||||
REVIVAL_HERB_PLACE,
|
||||
SoundEvents.BLOCK_GRASS_HIT,
|
||||
SoundEvents.BLOCK_GRASS_FALL
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val GILDED_CHEST_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
GILDED_CHEST_BREAK,
|
||||
@@ -295,5 +323,27 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
|
||||
GILDED_CHEST_STEP
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val DISPLAY_CASE_ADD_ITEM = this.create("display_case.add_item")
|
||||
@JvmField
|
||||
val DISPLAY_CASE_REMOVE_ITEM = this.create("display_case.remove_item")
|
||||
@JvmField
|
||||
val DISPLAY_CASE_BREAK = this.create("display_case.break")
|
||||
@JvmField
|
||||
val DISPLAY_CASE_HIT = this.create("display_case.hit")
|
||||
@JvmField
|
||||
val DISPLAY_CASE_PLACE = this.create("display_case.place")
|
||||
@JvmField
|
||||
val DISPLAY_CASE_STEP = this.create("display_case.step")
|
||||
|
||||
@JvmField
|
||||
val DISPLAY_CASE_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
DISPLAY_CASE_BREAK,
|
||||
DISPLAY_CASE_STEP,
|
||||
DISPLAY_CASE_PLACE,
|
||||
DISPLAY_CASE_HIT,
|
||||
DISPLAY_CASE_STEP
|
||||
)
|
||||
|
||||
private fun create(name: String): SoundEvent = this.create(name, SoundEvent.of(cobblemonResource(name)))
|
||||
}
|
||||
@@ -113,6 +113,14 @@ object CobblemonCriteria {
|
||||
)
|
||||
)
|
||||
|
||||
// Advancement criteria for [grow_tumblestone.json]
|
||||
val PLANT_TUMBLESTONE = this.create(
|
||||
SimpleCriterionTrigger(
|
||||
cobblemonResource("plant_tumblestone"),
|
||||
PlantTumblestoneCriterionCondition::class.java
|
||||
)
|
||||
)
|
||||
|
||||
private fun <T : Criterion<*>> create(criteria: T): T = Cobblemon.implementation.registerCriteria(criteria)
|
||||
|
||||
}
|
||||
+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.advancement.criterion
|
||||
|
||||
import com.cobblemon.mod.common.block.TumblestoneBlock
|
||||
import com.google.gson.JsonObject
|
||||
import net.minecraft.predicate.entity.LootContextPredicate
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.math.BlockPos
|
||||
|
||||
/**
|
||||
* A criterion condition for when a tumblestone block is planted
|
||||
* @param id The identifier of the criterion
|
||||
* @param predicate The predicate for the criterion
|
||||
*
|
||||
* @author Aethen
|
||||
* @since 02/28/2024
|
||||
*/
|
||||
class PlantTumblestoneCriterionCondition(id: Identifier, predicate: LootContextPredicate) :
|
||||
SimpleCriterionCondition<PlantTumblestoneContext>(id, predicate) {
|
||||
override fun toJson(json: JsonObject) {
|
||||
// Add properties to json if needed. None needed for this criterion
|
||||
}
|
||||
|
||||
override fun fromJson(json: JsonObject) {
|
||||
// Parse properties from json if needed. None needed for this criterion
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the tumblestone block can grow at the given position
|
||||
* @param player The player that planted the tumblestone block
|
||||
* @param context The context of the criterion
|
||||
* @return True if the tumblestone block can grow at the given position, false otherwise
|
||||
*/
|
||||
override fun matches(player: ServerPlayerEntity, context: PlantTumblestoneContext): Boolean {
|
||||
return context.tumbleStoneBlock.canGrow(context.pos, player.world)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The context of the [PlantTumblestoneCriterionCondition]
|
||||
* @param pos The position of the tumblestone block
|
||||
* @param tumbleStoneBlock The tumblestone block
|
||||
*/
|
||||
open class PlantTumblestoneContext(var pos: BlockPos, var tumbleStoneBlock: TumblestoneBlock)
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.abilities
|
||||
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.google.gson.JsonObject
|
||||
import net.minecraft.nbt.NbtCompound
|
||||
@@ -21,7 +22,7 @@ import net.minecraft.nbt.NbtCompound
|
||||
* @author Qu
|
||||
* @since January 9th, 2022
|
||||
*/
|
||||
open class Ability internal constructor(var template: AbilityTemplate, var forced: Boolean) {
|
||||
open class Ability internal constructor(var template: AbilityTemplate, forced: Boolean) {
|
||||
|
||||
val name: String
|
||||
get() = template.name
|
||||
@@ -34,16 +35,26 @@ open class Ability internal constructor(var template: AbilityTemplate, var force
|
||||
|
||||
/**
|
||||
* This represents the last known index of this backing ability in the species data.
|
||||
* If -1 the ability will attempt to find the correct index or reroll itself, this is done in order to be compatible with existing data
|
||||
* The value can be mutated however this is not recommended by API users.
|
||||
* @see [Pokemon.updateAbility].
|
||||
*/
|
||||
var forced: Boolean = forced
|
||||
internal set
|
||||
|
||||
/**
|
||||
* This represents the last known index of this backing ability in the species data.
|
||||
*
|
||||
* @see [Pokemon.updateAbility].
|
||||
*/
|
||||
var index: Int = -1
|
||||
internal set
|
||||
|
||||
/**
|
||||
* The last known priority of this ability in the species data.
|
||||
* The value can be mutated however this is not recommended by API users.
|
||||
*
|
||||
* @see [Pokemon.updateAbility].
|
||||
*/
|
||||
var priority = Priority.LOWEST
|
||||
internal set
|
||||
|
||||
open fun saveToNBT(nbt: NbtCompound): NbtCompound {
|
||||
nbt.putString(DataKeys.POKEMON_ABILITY_NAME, name)
|
||||
@@ -62,19 +73,23 @@ open class Ability internal constructor(var template: AbilityTemplate, var force
|
||||
}
|
||||
|
||||
open fun loadFromNBT(nbt: NbtCompound): Ability {
|
||||
forced = nbt.getBoolean(DataKeys.POKEMON_ABILITY_FORCED)
|
||||
this.template = Abilities.getOrException(nbt.getString(DataKeys.POKEMON_ABILITY_NAME))
|
||||
this.forced = nbt.getBoolean(DataKeys.POKEMON_ABILITY_FORCED)
|
||||
if (nbt.contains(DataKeys.POKEMON_ABILITY_INDEX) && nbt.contains(DataKeys.POKEMON_ABILITY_PRIORITY)) {
|
||||
this.index = nbt.getInt(DataKeys.POKEMON_ABILITY_INDEX)
|
||||
this.priority = Priority.valueOf(nbt.getString(DataKeys.POKEMON_ABILITY_PRIORITY))
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
open fun loadFromJSON(json: JsonObject): Ability {
|
||||
forced = json.get(DataKeys.POKEMON_ABILITY_FORCED)?.asBoolean ?: false
|
||||
this.template = Abilities.getOrException(json.get(DataKeys.POKEMON_ABILITY_NAME).asString)
|
||||
this.forced = json.get(DataKeys.POKEMON_ABILITY_FORCED)?.asBoolean ?: false
|
||||
if (json.has(DataKeys.POKEMON_ABILITY_INDEX) && json.has(DataKeys.POKEMON_ABILITY_PRIORITY)) {
|
||||
this.index = json.get(DataKeys.POKEMON_ABILITY_INDEX).asInt
|
||||
this.priority = Priority.valueOf(json.get(DataKeys.POKEMON_ABILITY_PRIORITY).asString)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,7 +28,6 @@ class AbilityTemplate(
|
||||
*/
|
||||
fun create(forced: Boolean = false) = builder(this, forced)
|
||||
|
||||
|
||||
/**
|
||||
* Returns the Ability and loads the given NBT Tag into it.
|
||||
*
|
||||
@@ -42,4 +41,5 @@ class AbilityTemplate(
|
||||
* Ability extensions need to write and read their needed data from here.
|
||||
*/
|
||||
fun create(json: JsonObject) = create().loadFromJSON(json)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.ability
|
||||
|
||||
import com.cobblemon.mod.common.api.abilities.*
|
||||
import com.cobblemon.mod.common.item.interactive.ability.AbilityTypeChanger
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.abilities.HiddenAbility
|
||||
import com.cobblemon.mod.common.pokemon.abilities.HiddenAbilityType
|
||||
|
||||
/**
|
||||
* Represents a change operation for a [Pokemon.ability].
|
||||
* This is backed by the associated [PotentialAbility].
|
||||
*
|
||||
* @param T The type of [PotentialAbility].
|
||||
*/
|
||||
interface AbilityChanger<T : PotentialAbility> {
|
||||
|
||||
/**
|
||||
* The [PotentialAbilityType] of type [T].
|
||||
*/
|
||||
val type: PotentialAbilityType<T>
|
||||
|
||||
/**
|
||||
* Collects all the possible targets for the [type] and the given [pokemon].
|
||||
*
|
||||
* @param pokemon The [Pokemon] being queried.
|
||||
* @return A set containing all their legal abilities associated with [type], can be empty.
|
||||
*/
|
||||
fun queryPossible(pokemon: Pokemon): Set<AbilityTemplate>
|
||||
|
||||
/**
|
||||
* Attempts to update the ability of the given [pokemon].
|
||||
*
|
||||
* @param pokemon The [Pokemon] attempting to change an ability.
|
||||
* @return If the operation was successful.
|
||||
*/
|
||||
fun performChange(pokemon: Pokemon): Boolean
|
||||
|
||||
/**
|
||||
* Checks if the current [PotentialAbilityType] of a [Pokemon.ability] is possible to swap from with this.
|
||||
*
|
||||
* @param type The [PotentialAbilityType] or null if the ability is forced and/or illegal.
|
||||
* @return If the operation can be performed.
|
||||
*/
|
||||
fun canChangeFrom(type: PotentialAbilityType<*>?): Boolean
|
||||
|
||||
companion object {
|
||||
|
||||
/**
|
||||
* An implementation of [AbilityChanger] for [CommonAbility].
|
||||
*
|
||||
* While this can be used in custom data scenarios this functions most "game-like" if the Pokémon only has 2 common abilities.
|
||||
*/
|
||||
@JvmStatic
|
||||
val COMMON_ABILITY: AbilityChanger<CommonAbility> = AbilityTypeChanger(CommonAbilityType) { other -> other == CommonAbilityType }
|
||||
|
||||
/**
|
||||
* An implementation of [AbilityChanger] for [HiddenAbility].
|
||||
*
|
||||
* While this can be used in custom data scenarios this functions most "game-like" if the Pokémon only has 1 hidden ability.
|
||||
*/
|
||||
@JvmStatic
|
||||
val HIDDEN_ABILITY: AbilityChanger<HiddenAbility> = AbilityTypeChanger(HiddenAbilityType) { other -> other == CommonAbilityType || other == HiddenAbilityType }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,8 +35,8 @@ abstract class MultiblockBlock(properties: Settings) : BlockWithEntity(propertie
|
||||
itemStack: ItemStack?
|
||||
) {
|
||||
if (world is ServerWorld) {
|
||||
val multiblockEntity = world.getBlockEntity(pos) as MultiblockEntity
|
||||
multiblockEntity.multiblockBuilder?.validate(world)
|
||||
val multiblockEntity = world.getBlockEntity(pos) as? MultiblockEntity
|
||||
multiblockEntity?.multiblockBuilder?.validate(world)
|
||||
}
|
||||
super.onPlaced(world, pos, state, placer, itemStack)
|
||||
}
|
||||
@@ -52,8 +52,8 @@ abstract class MultiblockBlock(properties: Settings) : BlockWithEntity(propertie
|
||||
if(hand == Hand.OFF_HAND) {
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
val entity = world.getBlockEntity(pos) as MultiblockEntity
|
||||
if (entity.multiblockStructure != null) {
|
||||
val entity = world.getBlockEntity(pos) as MultiblockEntity?
|
||||
if (entity?.multiblockStructure != null) {
|
||||
return entity.multiblockStructure!!.onUse(state, world, pos, player, hand, hit)
|
||||
}
|
||||
return super.onUse(state, world, pos, player, hand, hit)
|
||||
|
||||
@@ -205,8 +205,8 @@ object PokeBalls : JsonDataRegistry<PokeBall> {
|
||||
createDefault("ancient_wing_ball", throwPower = 2.5f, ancient = true)
|
||||
createDefault("ancient_jet_ball", throwPower = 2.5f, ancient = true)
|
||||
createDefault("ancient_origin_ball", GuaranteedModifier(), ancient = true)
|
||||
// Luxury ball effect
|
||||
CobblemonEvents.FRIENDSHIP_UPDATED.subscribe(priority = Priority.LOWEST) { event ->
|
||||
// Luxury ball effect, low priority as it must be triggered before soothe bell as of gen 4
|
||||
CobblemonEvents.FRIENDSHIP_UPDATED.subscribe(priority = Priority.LOW) { event ->
|
||||
var increment = (event.newFriendship - event.pokemon.friendship).toFloat()
|
||||
if (increment <= 1F) {
|
||||
event.pokemon.caughtBall.effects.filterIsInstance<FriendshipEarningBoostEffect>()
|
||||
|
||||
@@ -13,12 +13,14 @@ import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.abilities.Abilities
|
||||
import com.cobblemon.mod.common.api.abilities.Ability
|
||||
import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.api.pokemon.aspect.AspectProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
import com.cobblemon.mod.common.api.properties.CustomPokemonProperty
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.api.types.tera.TeraTypes
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.*
|
||||
import com.cobblemon.mod.common.pokemon.status.PersistentStatus
|
||||
@@ -294,6 +296,18 @@ open class PokemonProperties {
|
||||
)
|
||||
|
||||
fun apply(pokemon: Pokemon) {
|
||||
// Custom properties check could be duplicated but can't assume 3rd party hasn't done anything type specific
|
||||
this.customProperties.forEach { it.apply(pokemon) }
|
||||
this.commonApply(pokemon)
|
||||
}
|
||||
|
||||
fun apply(pokemonEntity: PokemonEntity) {
|
||||
// Custom properties check could be duplicated but can't assume 3rd party hasn't done anything type specific
|
||||
this.customProperties.forEach { it.apply(pokemonEntity) }
|
||||
this.commonApply(pokemonEntity.pokemon)
|
||||
}
|
||||
|
||||
private fun commonApply(pokemon: Pokemon) {
|
||||
species?.let {
|
||||
return@let try {
|
||||
if (it == "random") {
|
||||
@@ -313,8 +327,8 @@ open class PokemonProperties {
|
||||
friendship?.let { pokemon.setFriendship(it) }
|
||||
pokeball?.let { PokeBalls.getPokeBall(it.asIdentifierDefaultingNamespace())?.let { pokeball -> pokemon.caughtBall = pokeball } }
|
||||
nature?.let { Natures.getNature(it.asIdentifierDefaultingNamespace())?.let { nature -> pokemon.nature = nature } }
|
||||
ability?.let { Abilities.getOrException(it).create(true).let { ability -> pokemon.ability = ability } }
|
||||
status?.let { Statuses.getStatus(it)?.let { pokemon.applyStatus(it as PersistentStatus) } }
|
||||
ability?.let { this.createAbility(it, pokemon.form)?.let(pokemon::updateAbility) }
|
||||
status?.let { Statuses.getStatus(it)?.let { status -> if (status is PersistentStatus) pokemon.applyStatus(status) } }
|
||||
customProperties.forEach { it.apply(pokemon) }
|
||||
ivs?.let { ivs ->
|
||||
ivs.forEach { stat ->
|
||||
@@ -326,7 +340,7 @@ open class PokemonProperties {
|
||||
pokemon.setEV(stat.key, stat.value)
|
||||
}
|
||||
}
|
||||
teraType?.let { ElementalTypes.get(it)?.let { type -> pokemon.teraType = type } }
|
||||
teraType?.let { TeraTypes.get(it.asIdentifierDefaultingNamespace())?.let { type -> pokemon.teraType = type } }
|
||||
dmaxLevel?.let { pokemon.dmaxLevel = it }
|
||||
gmaxFactor?.let { pokemon.gmaxFactor = it }
|
||||
tradeable?.let { pokemon.tradeable = it }
|
||||
@@ -355,69 +369,17 @@ open class PokemonProperties {
|
||||
pokemon.updateAspects()
|
||||
}
|
||||
|
||||
fun apply(pokemonEntity: PokemonEntity) {
|
||||
species?.let {
|
||||
return@let try {
|
||||
if (it == "random") {
|
||||
PokemonSpecies.species.random()
|
||||
} else {
|
||||
PokemonSpecies.getByIdentifier(it.asIdentifierDefaultingNamespace())
|
||||
}
|
||||
} catch (e: InvalidIdentifierException) {
|
||||
null
|
||||
}
|
||||
}?.let { pokemonEntity.pokemon.species = it }
|
||||
nickname?.let { pokemonEntity.pokemon.nickname = it }
|
||||
form?.let { formID -> pokemonEntity.pokemon.species.forms.firstOrNull { it.formOnlyShowdownId().equals(formID, true) } }?.let { form -> pokemonEntity.pokemon.form = form }
|
||||
level?.let { pokemonEntity.pokemon.level = it }
|
||||
shiny?.let { pokemonEntity.pokemon.shiny = it }
|
||||
gender?.let { pokemonEntity.pokemon.gender = it }
|
||||
friendship?.let { pokemonEntity.pokemon.setFriendship(it) }
|
||||
pokeball?.let { PokeBalls.getPokeBall(it.asIdentifierDefaultingNamespace())?.let { pokeball -> pokemonEntity.pokemon.caughtBall = pokeball } }
|
||||
nature?.let { Natures.getNature(it.asIdentifierDefaultingNamespace())?.let { nature -> pokemonEntity.pokemon.nature = nature } }
|
||||
ability?.let { Abilities.getOrException(it).create(true).let { ability -> pokemonEntity.pokemon.ability = ability } }
|
||||
status?.let { Statuses.getStatus(it)?.let { pokemonEntity.pokemon.applyStatus(it as PersistentStatus) } }
|
||||
customProperties.forEach { it.apply(pokemonEntity) }
|
||||
ivs?.let { ivs ->
|
||||
ivs.forEach { stat ->
|
||||
pokemonEntity.pokemon.setIV(stat.key, stat.value)
|
||||
}
|
||||
}
|
||||
evs?.let { evs ->
|
||||
evs.forEach { stat ->
|
||||
pokemonEntity.pokemon.setEV(stat.key, stat.value)
|
||||
}
|
||||
}
|
||||
teraType?.let { ElementalTypes.get(it)?.let { type -> pokemonEntity.pokemon.teraType = type } }
|
||||
dmaxLevel?.let { pokemonEntity.pokemon.dmaxLevel = it }
|
||||
gmaxFactor?.let { pokemonEntity.pokemon.gmaxFactor = it }
|
||||
tradeable?.let { pokemonEntity.pokemon.tradeable = it }
|
||||
// If it has been explicitly set to NONE, clear the stored information, including the originalTrainer property
|
||||
originalTrainerType?.let {
|
||||
if (it == OriginalTrainerType.NONE) {
|
||||
pokemonEntity.pokemon.removeOriginalTrainer()
|
||||
originalTrainer = null
|
||||
}
|
||||
}
|
||||
originalTrainer?.let { ot ->
|
||||
val type = originalTrainerType ?: pokemonEntity.pokemon.originalTrainerType
|
||||
when (type) {
|
||||
OriginalTrainerType.PLAYER -> {
|
||||
when (ot.length) {
|
||||
in 3..16 -> server()?.userCache?.findByName(ot)?.get()?.id // OT is a Username
|
||||
36 -> UUID.fromString(ot) // OT is a UUID
|
||||
else -> null // OT is invalid
|
||||
}?.let { uuid -> pokemonEntity.pokemon.setOriginalTrainer(uuid) }
|
||||
}
|
||||
OriginalTrainerType.NPC -> pokemonEntity.pokemon.setOriginalTrainer(ot)
|
||||
else -> {}
|
||||
}
|
||||
pokemonEntity.pokemon.refreshOriginalTrainer()
|
||||
}
|
||||
pokemonEntity.pokemon.updateAspects()
|
||||
fun matches(pokemon: Pokemon): Boolean {
|
||||
// Custom properties check could be duplicated but can't assume 3rd party hasn't done anything type specific
|
||||
return this.commonMatches(pokemon) && this.customProperties.none { !it.matches(pokemon) }
|
||||
}
|
||||
|
||||
fun matches(pokemon: Pokemon): Boolean {
|
||||
fun matches(pokemonEntity: PokemonEntity): Boolean {
|
||||
// Custom properties check could be duplicated but can't assume 3rd party hasn't done anything type specific
|
||||
return this.commonMatches(pokemonEntity.pokemon) && this.customProperties.none { !it.matches(pokemonEntity) }
|
||||
}
|
||||
|
||||
private fun commonMatches(pokemon: Pokemon): Boolean {
|
||||
level?.takeIf { it != pokemon.level }?.let { return false }
|
||||
shiny?.takeIf { it != pokemon.shiny }?.let { return false }
|
||||
gender?.takeIf { it != pokemon.gender }?.let { return false }
|
||||
@@ -448,59 +410,23 @@ open class PokemonProperties {
|
||||
evs?.forEach{ stat ->
|
||||
if (stat.value != pokemon.evs[stat.key]) { return false }
|
||||
}
|
||||
teraType?.takeIf { it != pokemon.teraType.name }?.let { return false }
|
||||
teraType?.takeIf { it.asIdentifierDefaultingNamespace() != pokemon.teraType.id }?.let { return false }
|
||||
dmaxLevel?.takeIf { it != pokemon.dmaxLevel }?.let { return false }
|
||||
gmaxFactor?.takeIf { it != pokemon.gmaxFactor }?.let { return false }
|
||||
tradeable?.takeIf { it != pokemon.tradeable }?.let { return false }
|
||||
originalTrainer?.takeIf { it != pokemon.originalTrainer }?.let{ return false }
|
||||
originalTrainerType?.takeIf { it != pokemon.originalTrainerType }?.let{ return false }
|
||||
return customProperties.none { !it.matches(pokemon) }
|
||||
}
|
||||
|
||||
fun matches(pokemonEntity: PokemonEntity): Boolean {
|
||||
level?.takeIf { it != pokemonEntity.pokemon.level }?.let { return false }
|
||||
shiny?.takeIf { it != ("shiny" in pokemonEntity.pokemon.aspects) }?.let { return false }
|
||||
gender?.takeIf { it != pokemonEntity.pokemon.gender }?.let { return false }
|
||||
species?.run {
|
||||
try {
|
||||
val species = if (this == "random") {
|
||||
PokemonSpecies.species.random()
|
||||
} else {
|
||||
PokemonSpecies.getByIdentifier(this.asIdentifierDefaultingNamespace()) ?: return@run
|
||||
}
|
||||
if (pokemonEntity.pokemon.species != species) {
|
||||
return false
|
||||
}
|
||||
} catch (e: InvalidIdentifierException) {}
|
||||
}
|
||||
nickname?.takeIf { it != pokemonEntity.pokemon.nickname }?.let { return false }
|
||||
form?.takeIf { !it.equals(pokemonEntity.pokemon.form.name, true) }?.let { return false }
|
||||
friendship?.takeIf { it != pokemonEntity.pokemon.friendship }?.let { return false }
|
||||
pokeball?.takeIf { it != pokemonEntity.pokemon.caughtBall.name.toString() }?.let { return false }
|
||||
nature?.takeIf { it != pokemonEntity.pokemon.nature.name.toString() }?.let { return false }
|
||||
ability?.takeIf { it != pokemonEntity.pokemon.ability.name }?.let { return false }
|
||||
status?.takeIf { it != pokemonEntity.pokemon.status?.status?.showdownName }?.let { return false }
|
||||
ivs?.forEach{ stat ->
|
||||
if (stat.value != pokemonEntity.pokemon.ivs[stat.key]) { return false }
|
||||
}
|
||||
evs?.forEach{ stat ->
|
||||
if (stat.value != pokemonEntity.pokemon.evs[stat.key]) { return false }
|
||||
}
|
||||
teraType?.takeIf { it != pokemonEntity.pokemon.teraType.name }?.let { return false }
|
||||
dmaxLevel?.takeIf { it != pokemonEntity.pokemon.dmaxLevel }?.let { return false }
|
||||
gmaxFactor?.takeIf { it != pokemonEntity.pokemon.gmaxFactor }?.let { return false }
|
||||
tradeable?.takeIf { it != pokemonEntity.pokemon.tradeable }?.let { return false }
|
||||
originalTrainer?.takeIf { it != pokemonEntity.pokemon.originalTrainer }?.let{ return false }
|
||||
originalTrainerType?.takeIf { it != pokemonEntity.pokemon.originalTrainerType }?.let{ return false }
|
||||
return customProperties.none { !it.matches(pokemonEntity) }
|
||||
return true
|
||||
}
|
||||
|
||||
// TODO Review the need for this, usage for us is in commands that deviate from the behavior established by multiple Pokémon query equivalent
|
||||
fun isSubSetOf(properties: PokemonProperties): Boolean {
|
||||
level?.takeIf { it != properties.level }?.let { return false }
|
||||
shiny?.takeIf { it != ("shiny" in properties.aspects) }?.let { return false }
|
||||
gender?.takeIf { it != properties.gender }?.let { return false }
|
||||
species?.run {
|
||||
try {
|
||||
// TODO get context on this bit, it's highly unlikely two randoms would result in the same Pokémon, doesn't mean the prop is not equal?
|
||||
val species = if (this == "random") {
|
||||
PokemonSpecies.species.random()
|
||||
} else {
|
||||
@@ -509,7 +435,7 @@ open class PokemonProperties {
|
||||
if (properties.species != species.toString()) {
|
||||
return false
|
||||
}
|
||||
} catch (e: InvalidIdentifierException) {}
|
||||
} catch (_: InvalidIdentifierException) {}
|
||||
}
|
||||
nickname?.takeIf { it != properties.nickname }?.let { return false }
|
||||
form?.takeIf { !it.equals(properties.form, true) }?.let { return false }
|
||||
@@ -551,20 +477,18 @@ open class PokemonProperties {
|
||||
|
||||
// TEST YOUR LUCK!
|
||||
fun roll(pokemon: Pokemon) {
|
||||
val baseTypes = pokemon.species.types.toList()
|
||||
val baseTypes = pokemon.form.types.toList()
|
||||
if (this.shiny == null) pokemon.shiny = Cobblemon.config.shinyRate.checkRate()
|
||||
if (this.teraType == null) pokemon.teraType =
|
||||
if (Cobblemon.config.teraTypeRate.checkRate()) ElementalTypes.all().filter { !baseTypes.contains(it) }.random()
|
||||
else baseTypes.random()
|
||||
if (Cobblemon.config.teraTypeRate.checkRate()) TeraTypes.random(true)
|
||||
else TeraTypes.forElementalType(baseTypes.random())
|
||||
}
|
||||
|
||||
// If the config value is at least 1, then do 1/x and use that as the property chance
|
||||
private fun Float.checkRate(): Boolean = this >= 1 && (Random.Default.nextFloat() < 1 / this)
|
||||
|
||||
fun createEntity(world: World): PokemonEntity {
|
||||
return PokemonEntity(world, create())
|
||||
}
|
||||
|
||||
// TODO Codecs at some point
|
||||
fun saveToNBT(): NbtCompound {
|
||||
val nbt = NbtCompound()
|
||||
originalString.let { nbt.putString(DataKeys.POKEMON_PROPERTIES_ORIGINAL_TEXT, it) }
|
||||
@@ -593,6 +517,7 @@ open class PokemonProperties {
|
||||
return nbt
|
||||
}
|
||||
|
||||
// TODO Codecs at some point
|
||||
fun loadFromNBT(tag: NbtCompound): PokemonProperties {
|
||||
originalString = tag.getString(DataKeys.POKEMON_PROPERTIES_ORIGINAL_TEXT)
|
||||
level = if (tag.contains(DataKeys.POKEMON_LEVEL)) tag.getInt(DataKeys.POKEMON_LEVEL) else null
|
||||
@@ -621,6 +546,7 @@ open class PokemonProperties {
|
||||
return this
|
||||
}
|
||||
|
||||
// TODO Codecs at some point
|
||||
fun saveToJSON(): JsonObject {
|
||||
val json = JsonObject()
|
||||
originalString.let { json.addProperty(DataKeys.POKEMON_PROPERTIES_ORIGINAL_TEXT, it) }
|
||||
@@ -650,6 +576,7 @@ open class PokemonProperties {
|
||||
return json
|
||||
}
|
||||
|
||||
// TODO Codecs at some point
|
||||
fun loadFromJSON(json: JsonObject): PokemonProperties {
|
||||
originalString = json.get(DataKeys.POKEMON_PROPERTIES_ORIGINAL_TEXT)?.asString ?: ""
|
||||
level = json.get(DataKeys.POKEMON_LEVEL)?.asInt
|
||||
@@ -727,4 +654,21 @@ open class PokemonProperties {
|
||||
fun copy(): PokemonProperties {
|
||||
return PokemonProperties().loadFromJSON(saveToJSON())
|
||||
}
|
||||
|
||||
// If the config value is at least 1, then do 1/x and use that as the property chance
|
||||
private fun Float.checkRate(): Boolean = this >= 1 && (Random.Default.nextFloat() < 1 / this)
|
||||
|
||||
/**
|
||||
* Attempts to find an ability by ID and resolve if it should be forced or if it's legal for the given form.
|
||||
*
|
||||
* @param id The literal ID of the [Ability] being mapped.
|
||||
* @param form The [FormData] whose [FormData.abilities] is queried for legality.
|
||||
* @return The [Ability] with the [Ability.forced] state necessary for the given [form].
|
||||
*/
|
||||
private fun createAbility(id: String, form: FormData): Ability? {
|
||||
val ability = Abilities.get(id) ?: return null
|
||||
val potentialAbility = form.abilities.firstOrNull { potential -> potential.template == ability } ?: return ability.create(true)
|
||||
return potentialAbility.template.create(false)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.mojang.serialization.codecs.PrimitiveCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
/**
|
||||
* Effect details for the actual particles of a particle effect.
|
||||
@@ -44,48 +43,106 @@ class BedrockParticle(
|
||||
var cameraMode: ParticleCameraMode = RotateXYZCameraMode(),
|
||||
var tinting: ParticleTinting = ExpressionParticleTinting(),
|
||||
var collision: ParticleCollision = ParticleCollision(),
|
||||
var environmentLighting: Boolean = false
|
||||
var environmentLighting: Boolean = false,
|
||||
var creationEvents: MutableList<SimpleEventTrigger> = mutableListOf(),
|
||||
var expirationEvents: MutableList<SimpleEventTrigger> = mutableListOf(),
|
||||
var timeline: EventTriggerTimeline = EventTriggerTimeline(mutableMapOf())
|
||||
) {
|
||||
class ExpressionSet(
|
||||
val sizeX: Expression,
|
||||
val sizeY: Expression,
|
||||
val maxAge: Expression,
|
||||
val killExpression: Expression,
|
||||
val updateExpressions: MutableList<Expression>,
|
||||
val renderExpressions: MutableList<Expression>
|
||||
)
|
||||
|
||||
/*
|
||||
"creation_event": "event_sendspark",
|
||||
"expiration_event": ["event_spark", "event_afterspark", "event_capturestar"],
|
||||
"timeline": {
|
||||
"21.00": "event_spark"
|
||||
}
|
||||
*/
|
||||
|
||||
class EventSet(
|
||||
val creationEvents: MutableList<SimpleEventTrigger>,
|
||||
val expirationEvents: MutableList<SimpleEventTrigger>,
|
||||
val timeline: EventTriggerTimeline
|
||||
)
|
||||
|
||||
// kill plane maybe
|
||||
companion object {
|
||||
val CODEC: Codec<BedrockParticle> = RecordCodecBuilder.create { instance ->
|
||||
val EXPRESSION_SET_CODEC = RecordCodecBuilder.create<ExpressionSet> { instance ->
|
||||
instance.group(
|
||||
Identifier.CODEC.fieldOf("texture").forGetter { it.texture },
|
||||
PrimitiveCodec.STRING.fieldOf("material").forGetter { it.material.name },
|
||||
ParticleUVMode.codec.fieldOf("uvMode").forGetter { it.uvMode },
|
||||
EXPRESSION_CODEC.fieldOf("sizeX").forGetter { it.sizeX },
|
||||
EXPRESSION_CODEC.fieldOf("sizeY").forGetter { it.sizeY },
|
||||
EXPRESSION_CODEC.fieldOf("maxAge").forGetter { it.maxAge },
|
||||
EXPRESSION_CODEC.fieldOf("killExpression").forGetter { it.killExpression },
|
||||
ListCodec(EXPRESSION_CODEC).fieldOf("updateExpressions").forGetter { it.updateExpressions },
|
||||
ListCodec(EXPRESSION_CODEC).fieldOf("renderExpressions").forGetter { it.renderExpressions },
|
||||
ListCodec(EXPRESSION_CODEC).fieldOf("renderExpressions").forGetter { it.renderExpressions }
|
||||
).apply(instance, ::ExpressionSet)
|
||||
}
|
||||
|
||||
val EVENT_SET_CODEC = RecordCodecBuilder.create<EventSet> { instance ->
|
||||
instance.group(
|
||||
ListCodec(SimpleEventTrigger.CODEC).fieldOf("creationEvents").forGetter { it.creationEvents },
|
||||
ListCodec(SimpleEventTrigger.CODEC).fieldOf("expirationEvents").forGetter { it.expirationEvents },
|
||||
EventTriggerTimeline.CODEC.fieldOf("timeline").forGetter { it.timeline }
|
||||
).apply(instance, ::EventSet)
|
||||
}
|
||||
|
||||
val CODEC: Codec<BedrockParticle> = RecordCodecBuilder.create { instance ->
|
||||
instance.group(
|
||||
Identifier.CODEC.fieldOf("texture").forGetter { it.texture },
|
||||
PrimitiveCodec.STRING.fieldOf("material").forGetter { it.material.name },
|
||||
ParticleUVMode.codec.fieldOf("uvMode").forGetter { it.uvMode },
|
||||
EXPRESSION_SET_CODEC.fieldOf("expressionSet").forGetter {
|
||||
ExpressionSet(
|
||||
it.sizeX,
|
||||
it.sizeY,
|
||||
it.maxAge,
|
||||
it.killExpression,
|
||||
it.updateExpressions,
|
||||
it.renderExpressions
|
||||
)
|
||||
},
|
||||
ParticleMotion.codec.fieldOf("motion").forGetter { it.motion },
|
||||
ParticleRotation.codec.fieldOf("rotation").forGetter { it.rotation },
|
||||
ParticleViewDirection.codec.fieldOf("viewDirection").forGetter { it.viewDirection },
|
||||
ParticleCameraMode.codec.fieldOf("cameraMode").forGetter { it.cameraMode },
|
||||
ParticleTinting.codec.fieldOf("tinting").forGetter { it.tinting },
|
||||
ParticleCollision.CODEC.fieldOf("collision").forGetter { it.collision },
|
||||
PrimitiveCodec.BOOL.fieldOf("environmentLighting").forGetter { it.environmentLighting }
|
||||
PrimitiveCodec.BOOL.fieldOf("environmentLighting").forGetter { it.environmentLighting },
|
||||
EVENT_SET_CODEC.fieldOf("eventSet").forGetter {
|
||||
EventSet(
|
||||
it.creationEvents,
|
||||
it.expirationEvents,
|
||||
it.timeline
|
||||
)
|
||||
}
|
||||
).apply(instance) {
|
||||
texture, materialStr, uvMode, sizeX, sizeY, maxAge, killExpression, updateExpressions,
|
||||
renderExpressions, motion, rotation, viewDirection, cameraMode, tinting, collision, environmentLighting ->
|
||||
texture, materialStr, uvMode, expressionSet, motion, rotation, viewDirection, cameraMode, tinting, collision, environmentLighting, eventSet ->
|
||||
BedrockParticle(
|
||||
texture = texture,
|
||||
material = ParticleMaterial.valueOf(materialStr),
|
||||
uvMode = uvMode,
|
||||
sizeX = sizeX,
|
||||
sizeY = sizeY,
|
||||
maxAge = maxAge,
|
||||
killExpression = killExpression,
|
||||
updateExpressions = updateExpressions,
|
||||
renderExpressions = renderExpressions,
|
||||
sizeX = expressionSet.sizeX,
|
||||
sizeY = expressionSet.sizeY,
|
||||
maxAge = expressionSet.maxAge,
|
||||
killExpression = expressionSet.killExpression,
|
||||
updateExpressions = expressionSet.updateExpressions,
|
||||
renderExpressions = expressionSet.renderExpressions,
|
||||
motion = motion,
|
||||
rotation = rotation,
|
||||
viewDirection = viewDirection,
|
||||
cameraMode = cameraMode,
|
||||
tinting = tinting,
|
||||
collision = collision,
|
||||
environmentLighting = environmentLighting
|
||||
environmentLighting = environmentLighting,
|
||||
creationEvents = eventSet.creationEvents,
|
||||
expirationEvents = eventSet.expirationEvents,
|
||||
timeline = eventSet.timeline
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -108,6 +165,9 @@ class BedrockParticle(
|
||||
ParticleTinting.writeToBuffer(buffer, tinting)
|
||||
collision.writeToBuffer(buffer)
|
||||
buffer.writeBoolean(environmentLighting)
|
||||
buffer.writeCollection(creationEvents) { pb, event -> event.encode(pb) }
|
||||
buffer.writeCollection(expirationEvents) { pb, event -> event.encode(pb) }
|
||||
timeline.encode(buffer)
|
||||
}
|
||||
|
||||
fun readFromBuffer(buffer: PacketByteBuf) {
|
||||
@@ -127,5 +187,8 @@ class BedrockParticle(
|
||||
tinting = ParticleTinting.readFromBuffer(buffer)
|
||||
collision.readFromBuffer(buffer)
|
||||
environmentLighting = buffer.readBoolean()
|
||||
creationEvents = buffer.readList { SimpleEventTrigger("").also { it.decode(buffer) } }
|
||||
expirationEvents = buffer.readList { SimpleEventTrigger("").also { it.decode(buffer) } }
|
||||
timeline.decode(buffer)
|
||||
}
|
||||
}
|
||||
+11
-4
@@ -10,7 +10,9 @@ package com.cobblemon.mod.common.api.snowstorm
|
||||
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.ListCodec
|
||||
import com.mojang.serialization.codecs.PrimitiveCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import com.mojang.serialization.codecs.UnboundedMapCodec
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
@@ -27,7 +29,8 @@ class BedrockParticleEffect(
|
||||
var emitter: BedrockParticleEmitter = BedrockParticleEmitter(),
|
||||
var particle: BedrockParticle = BedrockParticle(),
|
||||
var curves: MutableList<MoLangCurve> = mutableListOf(),
|
||||
var space: ParticleSpace = ParticleSpace()
|
||||
var space: ParticleSpace = ParticleSpace(),
|
||||
var events: MutableMap<String, ParticleEvent> = mutableMapOf()
|
||||
) {
|
||||
companion object {
|
||||
val CODEC: Codec<BedrockParticleEffect> = RecordCodecBuilder.create { instance ->
|
||||
@@ -36,14 +39,16 @@ class BedrockParticleEffect(
|
||||
BedrockParticleEmitter.CODEC.fieldOf("emitter").forGetter { it.emitter },
|
||||
BedrockParticle.CODEC.fieldOf("particle").forGetter { it.particle },
|
||||
ListCodec(MoLangCurve.codec).fieldOf("curves").forGetter { it.curves },
|
||||
ParticleSpace.CODEC.fieldOf("space").forGetter { it.space }
|
||||
).apply(instance) { id, emitter, particle, curves, space ->
|
||||
ParticleSpace.CODEC.fieldOf("space").forGetter { it.space },
|
||||
UnboundedMapCodec(PrimitiveCodec.STRING, ParticleEvent.CODEC).fieldOf("events").forGetter { it.events }
|
||||
).apply(instance) { id, emitter, particle, curves, space, events ->
|
||||
BedrockParticleEffect(
|
||||
id = id,
|
||||
emitter = emitter,
|
||||
particle = particle,
|
||||
curves = curves.toMutableList(),
|
||||
space = space
|
||||
space = space,
|
||||
events = events
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -55,6 +60,7 @@ class BedrockParticleEffect(
|
||||
particle.writeToBuffer(buffer)
|
||||
buffer.writeCollection(curves) { pb, curve -> MoLangCurve.writeToBuffer(buffer, curve) }
|
||||
space.writeToBuffer(buffer)
|
||||
buffer.writeMap(events, { _, v -> buffer.writeString(v) }) { _, event -> event.encode(buffer) }
|
||||
}
|
||||
|
||||
fun readFromBuffer(buffer: PacketByteBuf) {
|
||||
@@ -63,5 +69,6 @@ class BedrockParticleEffect(
|
||||
particle.readFromBuffer(buffer)
|
||||
curves = buffer.readList { MoLangCurve.readFromBuffer(buffer) }
|
||||
space.readFromBuffer(buffer)
|
||||
events = buffer.readMap({ buffer.readString() }) { ParticleEvent().also { it.decode(buffer) } }
|
||||
}
|
||||
}
|
||||
+29
-4
@@ -29,7 +29,12 @@ class BedrockParticleEmitter(
|
||||
var updateExpressions: MutableList<Expression> = mutableListOf(),
|
||||
var rate: ParticleEmitterRate = InstantParticleEmitterRate(),
|
||||
var shape: ParticleEmitterShape = SphereParticleEmitterShape(),
|
||||
var lifetime: ParticleEmitterLifetime = OnceEmitterLifetime(NumberExpression(1.0))
|
||||
var lifetime: ParticleEmitterLifetime = OnceEmitterLifetime(NumberExpression(1.0)),
|
||||
var eventTimeline: EventTriggerTimeline = EventTriggerTimeline(mutableMapOf()),
|
||||
var creationEvents: MutableList<SimpleEventTrigger> = mutableListOf(),
|
||||
var expirationEvents: MutableList<SimpleEventTrigger> = mutableListOf(),
|
||||
var travelDistanceEvents: EventTriggerTimeline = EventTriggerTimeline(mutableMapOf()),
|
||||
var loopingTravelDistanceEvents: MutableList<LoopingTravelDistanceEventTrigger> = mutableListOf()
|
||||
) {
|
||||
companion object {
|
||||
val CODEC: Codec<BedrockParticleEmitter> = RecordCodecBuilder.create { instance ->
|
||||
@@ -38,14 +43,24 @@ class BedrockParticleEmitter(
|
||||
ListCodec(EXPRESSION_CODEC).fieldOf("updateExpressions").forGetter { it.updateExpressions },
|
||||
ParticleEmitterRate.codec.fieldOf("rate").forGetter { it.rate },
|
||||
ParticleEmitterShape.codec.fieldOf("shape").forGetter { it.shape },
|
||||
ParticleEmitterLifetime.codec.fieldOf("lifetime").forGetter { it.lifetime }
|
||||
).apply(instance) { startExpressions, updateExpressions, rate, shape, lifetime ->
|
||||
ParticleEmitterLifetime.codec.fieldOf("lifetime").forGetter { it.lifetime },
|
||||
EventTriggerTimeline.CODEC.fieldOf("eventTimeline").forGetter { it.eventTimeline },
|
||||
ListCodec(SimpleEventTrigger.CODEC).fieldOf("creationEvents").forGetter { it.creationEvents },
|
||||
ListCodec(SimpleEventTrigger.CODEC).fieldOf("expirationEvents").forGetter { it.expirationEvents },
|
||||
EventTriggerTimeline.CODEC.fieldOf("travelDistanceEvents").forGetter { it.travelDistanceEvents },
|
||||
ListCodec(LoopingTravelDistanceEventTrigger.CODEC).fieldOf("loopingTravelDistanceEvents").forGetter { it.loopingTravelDistanceEvents }
|
||||
).apply(instance) { startExpressions, updateExpressions, rate, shape, lifetime, eventTimeline, creationEvents, expirationEvents, travelDistanceEvents, loopingTravelDistanceEvents ->
|
||||
BedrockParticleEmitter(
|
||||
startExpressions = startExpressions,
|
||||
updateExpressions = updateExpressions,
|
||||
shape = shape,
|
||||
rate = rate,
|
||||
lifetime = lifetime
|
||||
lifetime = lifetime,
|
||||
eventTimeline = eventTimeline,
|
||||
creationEvents = creationEvents,
|
||||
expirationEvents = expirationEvents,
|
||||
travelDistanceEvents = travelDistanceEvents,
|
||||
loopingTravelDistanceEvents = loopingTravelDistanceEvents
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -57,6 +72,11 @@ class BedrockParticleEmitter(
|
||||
ParticleEmitterRate.writeToBuffer(buffer, rate)
|
||||
ParticleEmitterShape.writeToBuffer(buffer, shape)
|
||||
ParticleEmitterLifetime.writeToBuffer(buffer, lifetime)
|
||||
eventTimeline.encode(buffer)
|
||||
buffer.writeCollection(creationEvents) { pb, event -> event.encode(pb) }
|
||||
buffer.writeCollection(expirationEvents) { pb, event -> event.encode(pb) }
|
||||
travelDistanceEvents.encode(buffer)
|
||||
buffer.writeCollection(loopingTravelDistanceEvents) { pb, event -> event.encode(pb) }
|
||||
}
|
||||
|
||||
fun readFromBuffer(buffer: PacketByteBuf) {
|
||||
@@ -65,5 +85,10 @@ class BedrockParticleEmitter(
|
||||
rate = ParticleEmitterRate.readFromBuffer(buffer)
|
||||
shape = ParticleEmitterShape.readFromBuffer(buffer)
|
||||
lifetime = ParticleEmitterLifetime.readFromBuffer(buffer)
|
||||
eventTimeline.decode(buffer)
|
||||
creationEvents = buffer.readList { SimpleEventTrigger("").also { it.decode(buffer) } }
|
||||
expirationEvents = buffer.readList { SimpleEventTrigger("").also { it.decode(buffer) } }
|
||||
travelDistanceEvents.decode(buffer)
|
||||
loopingTravelDistanceEvents = buffer.readList { LoopingTravelDistanceEventTrigger(0.0, mutableListOf()).also { it.decode(buffer) } }
|
||||
}
|
||||
}
|
||||
+5
@@ -136,6 +136,11 @@ class LoopingEmitterLifetime(var activeTime: Expression = 1.0.asExpression(), va
|
||||
val interval = activeTimeValue + sleepTime
|
||||
val displacement = emitterAge % interval
|
||||
runtime.environment.setSimpleVariable("emitter_lifetime", activeTime)
|
||||
|
||||
if (emitterAge > activeTimeValue && sleepTime == 0.0) {
|
||||
return ParticleEmitterAction.STOP
|
||||
}
|
||||
|
||||
return if (displacement < activeTimeValue) {
|
||||
ParticleEmitterAction.GO
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -145,7 +145,7 @@ class PointParticleEmitterShape(
|
||||
override val type = ParticleEmitterShapeType.POINT
|
||||
override fun getNewParticlePosition(runtime: MoLangRuntime, entity: Entity?) = runtime.resolveVec3d(offset)
|
||||
override fun getCenter(runtime: MoLangRuntime, entity: Entity?): Vec3d {
|
||||
return getNewParticlePosition(runtime, entity) // Questionable
|
||||
return Vec3d.ZERO
|
||||
}
|
||||
|
||||
override fun <T> encode(ops: DynamicOps<T>) = CODEC.encodeStart(ops, this)
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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.snowstorm
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.getQueryStruct
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.net.Decodable
|
||||
import com.cobblemon.mod.common.api.net.Encodable
|
||||
import com.cobblemon.mod.common.client.particle.BedrockParticleEffectRepository
|
||||
import com.cobblemon.mod.common.client.particle.ParticleStorm
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper
|
||||
import com.cobblemon.mod.common.client.render.SnowstormParticle
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.PrimitiveCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
import net.minecraft.sound.SoundCategory
|
||||
import net.minecraft.sound.SoundEvent
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
/**
|
||||
* An event that can be referenced from various particle event triggers. The events are not necessarily particles,
|
||||
* but can be combinations of particles, sounds, and MoLang expressions.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since March 2nd, 2024
|
||||
*/
|
||||
class ParticleEvent(
|
||||
var particleEffect: EventParticleEffect? = null,
|
||||
var soundEffect: EventSoundEffect? = null,
|
||||
var expression: ExpressionLike? = null
|
||||
): Encodable, Decodable {
|
||||
companion object {
|
||||
val CODEC: Codec<ParticleEvent> = RecordCodecBuilder.create { instance ->
|
||||
instance.group(
|
||||
EventParticleEffect.CODEC.optionalFieldOf("particle_effect", null).forGetter { it.particleEffect },
|
||||
EventSoundEffect.CODEC.optionalFieldOf("sound_effect", null).forGetter { it.soundEffect },
|
||||
PrimitiveCodec.STRING.optionalFieldOf("expression", null).forGetter { it.expression?.toString() }
|
||||
).apply(instance) { particleEffect, soundEffect, expression ->
|
||||
ParticleEvent(
|
||||
particleEffect,
|
||||
soundEffect,
|
||||
expression?.asExpressionLike()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun encode(buffer: PacketByteBuf) {
|
||||
buffer.writeNullable(particleEffect) { pb, effect ->
|
||||
pb.writeIdentifier(effect.effect)
|
||||
pb.writeEnumConstant(effect.type)
|
||||
pb.writeNullable(effect.expression) { pb, expr -> pb.writeString(expr.toString()) }
|
||||
}
|
||||
buffer.writeNullable(soundEffect) { pb, effect -> pb.writeIdentifier(effect.sound) }
|
||||
buffer.writeNullable(expression) { pb, expr -> pb.writeString(expr.toString()) }
|
||||
}
|
||||
override fun decode(buffer: PacketByteBuf) {
|
||||
particleEffect = buffer.readNullable { pb -> EventParticleEffect(
|
||||
pb.readIdentifier(),
|
||||
pb.readEnumConstant(EventParticleEffect.EventParticleType::class.java),
|
||||
pb.readNullable { pb.readString().asExpressionLike() }
|
||||
) }
|
||||
soundEffect = buffer.readNullable { pb -> EventSoundEffect(pb.readIdentifier()) }
|
||||
expression = buffer.readNullable { pb -> pb.readString().asExpressionLike() }
|
||||
}
|
||||
|
||||
fun run(storm: ParticleStorm, particle: SnowstormParticle?) {
|
||||
particleEffect?.let { effect ->
|
||||
val bedrockParticleEffect = BedrockParticleEffectRepository.getEffect(effect.effect) ?: return@let
|
||||
val rootMatrix = when (effect.type) {
|
||||
EventParticleEffect.EventParticleType.EMITTER -> MatrixWrapper().updatePosition(storm.matrixWrapper.getOrigin())
|
||||
EventParticleEffect.EventParticleType.EMITTER_BOUND -> storm.matrixWrapper
|
||||
EventParticleEffect.EventParticleType.PARTICLE,
|
||||
EventParticleEffect.EventParticleType.PARTICLE_WITH_VELOCITY -> (particle?.let { Vec3d(it.getX(), it.getY(), it.getZ()) } ?: Vec3d(storm.getX(), storm.getY(), storm.getZ())).let { MatrixWrapper().updatePosition(it) }
|
||||
}
|
||||
|
||||
val sourceVelocity = when (effect.type) {
|
||||
EventParticleEffect.EventParticleType.EMITTER -> storm.sourceVelocity().let { { it } }
|
||||
EventParticleEffect.EventParticleType.EMITTER_BOUND -> storm.sourceVelocity
|
||||
EventParticleEffect.EventParticleType.PARTICLE -> { { Vec3d.ZERO } }
|
||||
EventParticleEffect.EventParticleType.PARTICLE_WITH_VELOCITY -> (particle?.let { Vec3d(it.getVelocityX(), it.getVelocityY(), it.getVelocityZ()) } ?: Vec3d.ZERO).let { { it } }
|
||||
}
|
||||
|
||||
val newStorm = ParticleStorm(
|
||||
effect = bedrockParticleEffect,
|
||||
matrixWrapper = rootMatrix,
|
||||
world = storm.world,
|
||||
sourceVelocity = sourceVelocity,
|
||||
sourceAlive = storm.sourceAlive,
|
||||
sourceVisible = storm.sourceVisible,
|
||||
onDespawn = {},
|
||||
runtime = MoLangRuntime().setup().also { it.environment.structs["query"] = storm.runtime.environment.getQueryStruct() },
|
||||
entity = storm.entity
|
||||
)
|
||||
|
||||
effect.expression?.resolve(newStorm.runtime)
|
||||
|
||||
newStorm.spawn()
|
||||
}
|
||||
soundEffect?.let { effect ->
|
||||
val position = particle?.let { Vec3d(it.getX(), it.getY(), it.getZ()) } ?: Vec3d(storm.getX(), storm.getY(), storm.getZ())
|
||||
val world = storm.world
|
||||
val soundEvent = SoundEvent.of(effect.sound)
|
||||
world.playSound(position.x, position.y, position.z, soundEvent, SoundCategory.NEUTRAL, 1F, 1F, true)
|
||||
}
|
||||
expression?.resolve(storm.runtime)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A particle component of a [ParticleEvent]. It contains the effect to play, the spawning type, and a pre-run
|
||||
* expression to run in the new storm's runtime.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since March 2nd, 2024
|
||||
*/
|
||||
class EventParticleEffect(
|
||||
val effect: Identifier,
|
||||
val type: EventParticleType,
|
||||
val expression: ExpressionLike? = null
|
||||
) {
|
||||
companion object {
|
||||
val CODEC = RecordCodecBuilder.create<EventParticleEffect> { instance ->
|
||||
instance.group(
|
||||
Identifier.CODEC.fieldOf("effect").forGetter { it.effect },
|
||||
PrimitiveCodec.STRING.fieldOf("type").forGetter { it.type.name },
|
||||
PrimitiveCodec.STRING.optionalFieldOf("expression", null).forGetter { it.expression?.toString() }
|
||||
).apply(instance) { effect, type, expression ->
|
||||
EventParticleEffect(
|
||||
effect,
|
||||
EventParticleType.valueOf(type),
|
||||
expression?.asExpressionLike()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class EventParticleType {
|
||||
EMITTER,
|
||||
EMITTER_BOUND,
|
||||
PARTICLE,
|
||||
PARTICLE_WITH_VELOCITY
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple sound effect component of a [ParticleEvent]. Plays a sound at the particle location, or if run from an
|
||||
* emitter event, at the emitter's location.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since March 2nd, 2024
|
||||
*/
|
||||
class EventSoundEffect(
|
||||
val sound: Identifier,
|
||||
) {
|
||||
companion object {
|
||||
val CODEC = RecordCodecBuilder.create<EventSoundEffect> { instance ->
|
||||
instance.group(
|
||||
Identifier.CODEC.fieldOf("sound").forGetter { it.sound }
|
||||
).apply(instance, ::EventSoundEffect)
|
||||
}
|
||||
}
|
||||
}
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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.snowstorm
|
||||
|
||||
import com.cobblemon.mod.common.api.net.Decodable
|
||||
import com.cobblemon.mod.common.api.net.Encodable
|
||||
import com.cobblemon.mod.common.client.particle.ParticleStorm
|
||||
import com.cobblemon.mod.common.client.render.SnowstormParticle
|
||||
import com.mojang.serialization.codecs.PrimitiveCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import com.mojang.serialization.codecs.UnboundedMapCodec
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
|
||||
/*
|
||||
* The different references to events that can be triggered by an effect.
|
||||
*/
|
||||
|
||||
/**
|
||||
* It really is simple.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since March 2nd, 2024
|
||||
*/
|
||||
class SimpleEventTrigger(var event: String): Encodable, Decodable {
|
||||
companion object {
|
||||
val CODEC = RecordCodecBuilder.create<SimpleEventTrigger> { instance ->
|
||||
instance.group(
|
||||
PrimitiveCodec.STRING.fieldOf("event").forGetter { it.event }
|
||||
).apply(instance, ::SimpleEventTrigger)
|
||||
}
|
||||
}
|
||||
|
||||
override fun encode(buffer: PacketByteBuf) {
|
||||
buffer.writeString(event)
|
||||
}
|
||||
|
||||
override fun decode(buffer: PacketByteBuf) {
|
||||
event = buffer.readString()
|
||||
}
|
||||
|
||||
fun trigger(storm: ParticleStorm, particle: SnowstormParticle?) {
|
||||
val event = storm.effect.events[event] ?: return
|
||||
event.run(storm, particle)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An event trigger that outlines specific times at which point groups of effects will play. This can be used
|
||||
* on the basis of time but is also used in the case of travel distance.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since March 2nd, 2024
|
||||
*/
|
||||
class EventTriggerTimeline(var map: MutableMap<Double, MutableList<String>>): Encodable, Decodable {
|
||||
companion object {
|
||||
val CODEC = RecordCodecBuilder.create<EventTriggerTimeline> { instance ->
|
||||
instance.group(
|
||||
UnboundedMapCodec(PrimitiveCodec.DOUBLE, PrimitiveCodec.STRING.listOf()).fieldOf("map").forGetter { it.map }
|
||||
).apply(instance, ::EventTriggerTimeline)
|
||||
}
|
||||
}
|
||||
|
||||
override fun encode(buffer: PacketByteBuf) {
|
||||
buffer.writeMap(map, { pb, k -> pb.writeDouble(k) }, { pb, v -> pb.writeCollection(v) { _, s -> pb.writeString(s) } })
|
||||
}
|
||||
|
||||
override fun decode(buffer: PacketByteBuf) {
|
||||
map = buffer.readMap({ pb -> pb.readDouble() }, { pb -> pb.readList { pb.readString() } })
|
||||
}
|
||||
|
||||
fun check(storm: ParticleStorm, particle: SnowstormParticle?, previousTime: Double, newTime: Double) {
|
||||
val events = map.entries.filter { it.key in previousTime..newTime }.flatMap { it.value }
|
||||
events.forEach { event ->
|
||||
val event = storm.effect.events[event] ?: return
|
||||
event.run(storm, particle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An event trigger that takes the total distance travelled by the emitter and modulos it across [distance] to know
|
||||
* if we need to play it again.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since March 2nd, 2024
|
||||
*/
|
||||
class LoopingTravelDistanceEventTrigger(var distance: Double, var events: MutableList<String>): Encodable, Decodable {
|
||||
companion object {
|
||||
val CODEC = RecordCodecBuilder.create<LoopingTravelDistanceEventTrigger> { instance ->
|
||||
instance.group(
|
||||
PrimitiveCodec.DOUBLE.fieldOf("distance").forGetter { it.distance },
|
||||
PrimitiveCodec.STRING.listOf().fieldOf("events").forGetter { it.events }
|
||||
).apply(instance, ::LoopingTravelDistanceEventTrigger)
|
||||
}
|
||||
}
|
||||
|
||||
override fun encode(buffer: PacketByteBuf) {
|
||||
buffer.writeDouble(distance)
|
||||
buffer.writeCollection(events) { _, s -> buffer.writeString(s) }
|
||||
}
|
||||
|
||||
override fun decode(buffer: PacketByteBuf) {
|
||||
distance = buffer.readDouble()
|
||||
events = buffer.readList { buffer.readString() }
|
||||
}
|
||||
|
||||
fun check(storm: ParticleStorm, particle: SnowstormParticle?, previousDistance: Double, currentDistance: Double) {
|
||||
if (previousDistance < distance && currentDistance >= distance) {
|
||||
events.mapNotNull { storm.effect.events[it] }.forEach { it.run(storm, particle) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,7 +140,7 @@ class InwardsMotionDirection : ParticleMotionDirection {
|
||||
return if (particlePos == emitterPos) {
|
||||
Vec3d(storm.world.random.nextDouble() - 0.5, storm.world.random.nextDouble() - 0.5, storm.world.random.nextDouble() - 0.5)
|
||||
} else {
|
||||
particlePos.subtract(emitterPos)
|
||||
emitterPos.subtract(particlePos)
|
||||
}.normalize()
|
||||
}
|
||||
override fun <T> encode(ops: DynamicOps<T>) = CODEC.encodeStart(ops, this)
|
||||
|
||||
+3
-1
@@ -12,6 +12,8 @@ import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.PlayerSpawner
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.PlayerSpawnerFactory
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
import java.util.UUID
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
|
||||
@@ -34,7 +36,7 @@ object CobblemonWorldSpawnerManager : SpawnerManager() {
|
||||
|
||||
fun onPlayerLogin(player: ServerPlayerEntity) {
|
||||
// Disables spawning
|
||||
if (!Cobblemon.config.enableSpawning) {
|
||||
if (!Cobblemon.config.enableSpawning || server()?.gameRules?.getBoolean(CobblemonGameRules.DO_POKEMON_SPAWNING) == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.Spawner
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.TickingSpawner
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules.DO_POKEMON_SPAWNING
|
||||
|
||||
/**
|
||||
* A manager of various spawners. This is a class in which you should register
|
||||
@@ -49,7 +51,7 @@ open class SpawnerManager {
|
||||
|
||||
open fun onServerTick() {
|
||||
// Disables spawning
|
||||
if (!Cobblemon.config.enableSpawning) {
|
||||
if (!Cobblemon.config.enableSpawning || server()?.gameRules?.getBoolean(DO_POKEMON_SPAWNING) == false) {
|
||||
return
|
||||
}
|
||||
influences.removeIf { it.isExpired() }
|
||||
|
||||
+10
-3
@@ -30,9 +30,16 @@ abstract class SingleEntitySpawnAction<T : Entity>(
|
||||
override fun run(): EntitySpawnResult? {
|
||||
val e = createEntity() ?: return null
|
||||
e.setPosition(ctx.position.toVec3d().add(0.5, 1.0, 0.5))
|
||||
entity.emit(e)
|
||||
CobblemonEvents.ENTITY_SPAWN.postThen(SpawnEvent(e, ctx), ifSucceeded = { ctx.world.spawnEntity(e) })
|
||||
return EntitySpawnResult(listOf(e))
|
||||
var shouldSpawn = false
|
||||
CobblemonEvents.ENTITY_SPAWN.postThen(SpawnEvent(e, ctx), ifSucceeded = {
|
||||
ctx.world.spawnEntity(e)
|
||||
shouldSpawn = true
|
||||
})
|
||||
|
||||
return if (shouldSpawn) {
|
||||
this.entity.emit(e)
|
||||
EntitySpawnResult(listOf(e))
|
||||
} else null
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -63,9 +63,6 @@ abstract class AreaSpawner(
|
||||
|
||||
override fun run(cause: SpawnCause): Pair<SpawningContext, SpawnDetail>? {
|
||||
val area = getArea(cause)
|
||||
if (area?.world?.gameRules?.getBoolean(DO_POKEMON_SPAWNING) == false) {
|
||||
return null
|
||||
}
|
||||
val constrainedArea = if (area != null) constrainArea(area) else null
|
||||
if (constrainedArea != null) {
|
||||
|
||||
|
||||
+4
-2
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.storage.adapter.conversions
|
||||
|
||||
import com.cobblemon.mod.common.api.abilities.Abilities
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.api.pokemon.Natures
|
||||
@@ -98,8 +99,9 @@ class ReforgedConversion(val base: Path) : CobblemonConverter<NbtCompound> {
|
||||
result.level = nbt.getInt("Level")
|
||||
result.addExperience(SidemodExperienceSource("Reforged"), nbt.getInt("EXP"))
|
||||
result.setFriendship(nbt.getInt("Friendship"))
|
||||
result.ability = (result.form.abilities.find { it.template.name == nbt.getString("Ability") } ?: result.form.abilities.first())
|
||||
.template.create()
|
||||
Abilities.get(nbt.getString("Ability"))?.let { template ->
|
||||
result.updateAbility(template.create(forced = result.form.abilities.none { it.template == template }))
|
||||
}
|
||||
result.nature = Natures.getNature(Identifier(ReforgedNatures.values()[nbt.getInt("Nature")].name.lowercase())) ?: Natures.getRandomNature()
|
||||
result.mintedNature = Natures.getNature(Identifier(ReforgedNatures.values()[nbt.getInt("MintNature")].name.lowercase()))
|
||||
result.currentHealth = nbt.getInt("Health")
|
||||
|
||||
@@ -22,107 +22,15 @@ import net.minecraft.registry.tag.TagKey
|
||||
object CobblemonBiomeTags {
|
||||
|
||||
@JvmField
|
||||
val IS_DEEP_DARK = create("is_deep_dark")
|
||||
val IS_AUTUMN = create("has_season/autumn")
|
||||
@JvmField
|
||||
val IS_ARID = create("is_arid")
|
||||
val IS_SPRING = create("has_season/spring")
|
||||
@JvmField
|
||||
val IS_AUTUMN = create("is_autumn")
|
||||
@JvmField
|
||||
val IS_BADLANDS = create("is_badlands")
|
||||
@JvmField
|
||||
val IS_BAMBOO = create("is_bamboo")
|
||||
@JvmField
|
||||
val IS_CAVE = create("is_cave")
|
||||
@JvmField
|
||||
val IS_COAST = create("is_coast")
|
||||
@JvmField
|
||||
val IS_COLD = create("is_cold")
|
||||
@JvmField
|
||||
val IS_DEEP_OCEAN = create("is_deep_ocean")
|
||||
@JvmField
|
||||
val IS_DESERT = create("is_desert")
|
||||
@JvmField
|
||||
val IS_DRIPSTONE = create("is_dripstone")
|
||||
@JvmField
|
||||
val IS_FLORAL = create("is_floral")
|
||||
@JvmField
|
||||
val IS_FOREST = create("is_forest")
|
||||
@JvmField
|
||||
val IS_FREEZING = create("is_freezing")
|
||||
@JvmField
|
||||
val IS_FRESHWATER = create("is_freshwater")
|
||||
@JvmField
|
||||
val IS_COLD_OCEAN = create("is_cold_ocean")
|
||||
@JvmField
|
||||
val IS_FROZEN_OCEAN = create("is_frozen_ocean")
|
||||
@JvmField
|
||||
val IS_GLACIAL = create("is_glacial")
|
||||
@JvmField
|
||||
val IS_GRASSLAND = create("is_grassland")
|
||||
@JvmField
|
||||
val IS_HIGHLANDS = create("is_highlands")
|
||||
@JvmField
|
||||
val IS_HILLS = create("is_hills")
|
||||
@JvmField
|
||||
val IS_ISLAND = create("is_island")
|
||||
@JvmField
|
||||
val IS_JUNGLE = create("is_jungle")
|
||||
@JvmField
|
||||
val IS_LUKEWARM_OCEAN = create("is_lukewarm_ocean")
|
||||
@JvmField
|
||||
val IS_LUSH = create("is_lush")
|
||||
@JvmField
|
||||
val IS_MAGICAL = create("is_magical")
|
||||
@JvmField
|
||||
val IS_MOUNTAIN = create("is_mountain")
|
||||
@JvmField
|
||||
val IS_MUSHROOM = create("is_mushroom")
|
||||
@JvmField
|
||||
val IS_OVERWORLD = create("is_overworld")
|
||||
@JvmField
|
||||
val IS_PEAK = create("is_peak")
|
||||
@JvmField
|
||||
val IS_PLAINS = create("is_plains")
|
||||
@JvmField
|
||||
val IS_PLATEAU = create("is_plateau")
|
||||
@JvmField
|
||||
val IS_WARM_OCEAN = create("is_warm_ocean")
|
||||
@JvmField
|
||||
val IS_RIVER = create("is_river")
|
||||
@JvmField
|
||||
val IS_SANDY = create("is_sandy")
|
||||
@JvmField
|
||||
val IS_SAVANNA = create("is_savanna")
|
||||
@JvmField
|
||||
val IS_SKY = create("is_sky")
|
||||
@JvmField
|
||||
val IS_SNOWY_FOREST = create("is_snowy_forest")
|
||||
@JvmField
|
||||
val IS_SPOOKY = create("is_spooky")
|
||||
@JvmField
|
||||
val IS_SPRING = create("is_spring")
|
||||
@JvmField
|
||||
val IS_SUMMER = create("is_summer")
|
||||
@JvmField
|
||||
val IS_SWAMP = create("is_swamp")
|
||||
@JvmField
|
||||
val IS_TAIGA = create("is_taiga")
|
||||
val IS_SUMMER = create("has_season/summer")
|
||||
@JvmField
|
||||
val IS_TEMPERATE = create("is_temperate")
|
||||
@JvmField
|
||||
val IS_THERMAL = create("is_thermal")
|
||||
@JvmField
|
||||
val IS_TUNDRA = create("is_tundra")
|
||||
@JvmField
|
||||
val IS_VOID = create("is_void")
|
||||
@JvmField
|
||||
val IS_VOlCANIC = create("is_volcanic")
|
||||
@JvmField
|
||||
val IS_WINTER = create("is_winter")
|
||||
@JvmField
|
||||
val IS_SPARSE = create("is_sparse")
|
||||
@JvmField
|
||||
val IS_DENSE = create("is_dense")
|
||||
val IS_WINTER = create("has_season/winter")
|
||||
|
||||
// Has Feature tags
|
||||
@JvmField
|
||||
@@ -180,16 +88,5 @@ object CobblemonBiomeTags {
|
||||
@JvmField
|
||||
val HAS_WATER_STONE_ORE_RARE = create("has_ore/ore_water_stone_rare")
|
||||
|
||||
// ToDo remove in 1.3
|
||||
@Deprecated(message = "This tag no longer exists", level = DeprecationLevel.ERROR)
|
||||
@JvmField
|
||||
val IS_CRAG = create("is_crag")
|
||||
@Deprecated(message = "This tag no longer exists", level = DeprecationLevel.ERROR)
|
||||
@JvmField
|
||||
val IS_ICY = create("is_icy")
|
||||
@Deprecated(message = "This tag no longer exists", replaceWith = ReplaceWith("com.cobblemon.mod.common.api.tags.CobblemonBiomeTags.IS_CAVE"), level = DeprecationLevel.ERROR)
|
||||
@JvmField
|
||||
val IS_UNDERGROUND = create("is_underground")
|
||||
|
||||
private fun create(path: String) = TagKey.of(RegistryKeys.BIOME, cobblemonResource(path))
|
||||
}
|
||||
@@ -144,6 +144,12 @@ object CobblemonItemTags {
|
||||
@JvmField
|
||||
val POTTERY_SHERDS = create("decorated_pot_sherds")
|
||||
|
||||
@JvmField
|
||||
val ABILITY_CHANGERS = create("ability_changers")
|
||||
|
||||
@JvmField
|
||||
val IS_FRIENDSHIP_BOOSTER = create("is_friendship_booster")
|
||||
|
||||
private fun create(path: String) = TagKey.of(RegistryKeys.ITEM, cobblemonResource(path))
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.types.tera
|
||||
|
||||
import com.cobblemon.mod.common.api.data.ShowdownIdentifiable
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
/**
|
||||
* The representation of the Pokémons Tera type.
|
||||
*
|
||||
* @see [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Terastal_phenomenon)
|
||||
*
|
||||
*/
|
||||
interface TeraType : ShowdownIdentifiable {
|
||||
|
||||
/**
|
||||
* The [Identifier] associated to this type.
|
||||
*/
|
||||
val id: Identifier
|
||||
|
||||
/**
|
||||
* If this tera type can be selected naturally.
|
||||
*/
|
||||
val legalAsStatic: Boolean
|
||||
|
||||
/**
|
||||
* The display name of this type.
|
||||
*/
|
||||
val displayName: Text
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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.types.tera
|
||||
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.api.types.tera.elemental.ElementalTypeTeraType
|
||||
import com.cobblemon.mod.common.api.types.tera.gimmick.StellarTeraType
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
/**
|
||||
* The registry of all [TeraType]s.
|
||||
*/
|
||||
@Suppress("unused")
|
||||
object TeraTypes {
|
||||
private val types = hashMapOf<Identifier, TeraType>()
|
||||
|
||||
@JvmStatic
|
||||
val NORMAL = this.create(cobblemonResource("normal"), ElementalTypeTeraType(ElementalTypes.NORMAL))
|
||||
|
||||
@JvmStatic
|
||||
val FIRE = this.create(cobblemonResource("fire"), ElementalTypeTeraType(ElementalTypes.FIRE))
|
||||
|
||||
@JvmStatic
|
||||
val WATER = this.create(cobblemonResource("water"), ElementalTypeTeraType(ElementalTypes.WATER))
|
||||
|
||||
@JvmStatic
|
||||
val GRASS = this.create(cobblemonResource("grass"), ElementalTypeTeraType(ElementalTypes.GRASS))
|
||||
|
||||
@JvmStatic
|
||||
val ELECTRIC = this.create(cobblemonResource("electric"), ElementalTypeTeraType(ElementalTypes.ELECTRIC))
|
||||
|
||||
@JvmStatic
|
||||
val ICE = this.create(cobblemonResource("ice"), ElementalTypeTeraType(ElementalTypes.ICE))
|
||||
|
||||
@JvmStatic
|
||||
val FIGHTING = this.create(cobblemonResource("fighting"), ElementalTypeTeraType(ElementalTypes.FIGHTING))
|
||||
|
||||
@JvmStatic
|
||||
val POISON = this.create(cobblemonResource("poison"), ElementalTypeTeraType(ElementalTypes.POISON))
|
||||
|
||||
@JvmStatic
|
||||
val GROUND = this.create(cobblemonResource("ground"), ElementalTypeTeraType(ElementalTypes.GROUND))
|
||||
|
||||
@JvmStatic
|
||||
val FLYING = this.create(cobblemonResource("flying"), ElementalTypeTeraType(ElementalTypes.FLYING))
|
||||
|
||||
@JvmStatic
|
||||
val PSYCHIC = this.create(cobblemonResource("psychic"), ElementalTypeTeraType(ElementalTypes.PSYCHIC))
|
||||
|
||||
@JvmStatic
|
||||
val BUG = this.create(cobblemonResource("bug"), ElementalTypeTeraType(ElementalTypes.BUG))
|
||||
|
||||
@JvmStatic
|
||||
val ROCK = this.create(cobblemonResource("rock"), ElementalTypeTeraType(ElementalTypes.ROCK))
|
||||
|
||||
@JvmStatic
|
||||
val GHOST = this.create(cobblemonResource("ghost"), ElementalTypeTeraType(ElementalTypes.GHOST))
|
||||
|
||||
@JvmStatic
|
||||
val DRAGON = this.create(cobblemonResource("dragon"), ElementalTypeTeraType(ElementalTypes.DRAGON))
|
||||
|
||||
@JvmStatic
|
||||
val DARK = this.create(cobblemonResource("dark"), ElementalTypeTeraType(ElementalTypes.DARK))
|
||||
|
||||
@JvmStatic
|
||||
val STEEL = this.create(cobblemonResource("steel"), ElementalTypeTeraType(ElementalTypes.STEEL))
|
||||
|
||||
@JvmStatic
|
||||
val FAIRY = this.create(cobblemonResource("fairy"), ElementalTypeTeraType(ElementalTypes.FAIRY))
|
||||
|
||||
@JvmStatic
|
||||
val STELLAR = this.create(StellarTeraType.ID, StellarTeraType())
|
||||
|
||||
/**
|
||||
* Pick a random [TeraType].
|
||||
*
|
||||
* @param legalOnly If [TeraType.legalAsStatic] should be respected.
|
||||
* @return The selected [TeraType].
|
||||
*/
|
||||
@JvmStatic
|
||||
fun random(legalOnly: Boolean): TeraType {
|
||||
val possible = this.types.values
|
||||
if (legalOnly) {
|
||||
return possible.filter(TeraType::legalAsStatic).random()
|
||||
}
|
||||
return possible.random()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a [TeraType] by its [id].
|
||||
*
|
||||
* @param id The [Identifier] expected to match against a [TeraType.id].
|
||||
* @return The found [TeraType] or null.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun get(id: Identifier): TeraType? = this.types[id]
|
||||
|
||||
/**
|
||||
* Gets a [TeraType] by its [id].
|
||||
*
|
||||
* @param id The string representation of a [Identifier] if no namespace is present assumes Cobblemon' instead of Minecraft'.
|
||||
* @return The found [TeraType] or null.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun get(id: String): TeraType? = this.get(cobblemonResource(id))
|
||||
|
||||
/**
|
||||
* Gets the corresponding tera type for a [ElementalType].
|
||||
*
|
||||
* @param type The [ElementalType] being checked.
|
||||
* @return The associated [TeraType].
|
||||
*/
|
||||
@JvmStatic
|
||||
fun forElementalType(type: ElementalType): TeraType = this.get(cobblemonResource(type.name))!! // it's safe to do
|
||||
|
||||
private fun create(id: Identifier, type: TeraType): TeraType {
|
||||
this.types[id] = type
|
||||
return type
|
||||
}
|
||||
}
|
||||
+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.types.tera.elemental
|
||||
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.tera.TeraType
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
class ElementalTypeTeraType(val type: ElementalType) : TeraType {
|
||||
override val legalAsStatic: Boolean = true
|
||||
|
||||
override val id: Identifier = cobblemonResource(this.type.name)
|
||||
|
||||
override val displayName: Text = this.type.displayName
|
||||
|
||||
override fun showdownId(): String = this.type.name
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.types.tera.gimmick
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.types.tera.TeraType
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
class StellarTeraType : TeraType {
|
||||
override val id: Identifier = ID
|
||||
|
||||
override val legalAsStatic: Boolean = false
|
||||
|
||||
override val displayName: Text = LANG
|
||||
|
||||
override fun showdownId(): String = ID.path
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("stellar")
|
||||
private val LANG = Text.translatable("${Cobblemon.MODID}.terra_type.stellar")
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import com.cobblemon.mod.common.net.messages.client.battle.BattleChallengeExpire
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
import com.google.gson.GsonBuilder
|
||||
import java.time.Instant
|
||||
import java.util.Optional
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
@@ -139,7 +138,7 @@ object BattleRegistry {
|
||||
// 0 - 9, empty == 10
|
||||
packedTeamBuilder.append("${if (pk.dmaxLevel < 10) pk.dmaxLevel else ""},")
|
||||
// Teratype
|
||||
packedTeamBuilder.append("${pokemon.effectedPokemon.teraType.name},")
|
||||
packedTeamBuilder.append("${pokemon.effectedPokemon.teraType.showdownId()},")
|
||||
|
||||
team.add(packedTeamBuilder.toString())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
import com.cobblemon.mod.common.block.entity.DisplayCaseBlockEntity
|
||||
import com.cobblemon.mod.common.item.PokeBallItem
|
||||
import net.minecraft.block.*
|
||||
import net.minecraft.block.HorizontalFacingBlock.*
|
||||
import net.minecraft.entity.ai.pathing.NavigationType
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.item.BlockItem
|
||||
import net.minecraft.item.ItemPlacementContext
|
||||
import net.minecraft.state.StateManager
|
||||
import net.minecraft.util.ActionResult
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.ItemScatterer
|
||||
import net.minecraft.util.hit.BlockHitResult
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.world.BlockView
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.world.WorldAccess
|
||||
|
||||
@Suppress("OVERRIDE_DEPRECATION")
|
||||
class DisplayCaseBlock(settings: Settings) : BlockWithEntity(settings) {
|
||||
init {
|
||||
this.defaultState = this.stateManager.defaultState
|
||||
.with(FACING, Direction.NORTH)
|
||||
}
|
||||
|
||||
override fun getPlacementState(ctx: ItemPlacementContext): BlockState? {
|
||||
var blockState = defaultState
|
||||
val worldView = ctx.world
|
||||
val blockPos = ctx.blockPos
|
||||
ctx.placementDirections.forEach { direction ->
|
||||
if (direction.axis.isHorizontal) {
|
||||
blockState = blockState.with(FACING, direction) as BlockState
|
||||
if (blockState.canPlaceAt(worldView, blockPos)) {
|
||||
return blockState
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
|
||||
builder.add(FACING)
|
||||
}
|
||||
|
||||
override fun createBlockEntity(pos: BlockPos, state: BlockState): DisplayCaseBlockEntity {
|
||||
return DisplayCaseBlockEntity(pos, state)
|
||||
}
|
||||
|
||||
override fun getStateForNeighborUpdate(
|
||||
state: BlockState,
|
||||
direction: Direction,
|
||||
neighborState: BlockState,
|
||||
world: WorldAccess,
|
||||
pos: BlockPos,
|
||||
neighborPos: BlockPos
|
||||
): BlockState {
|
||||
return if (direction == state.get(FACING) && !state.canPlaceAt(world, pos)) Blocks.AIR.defaultState
|
||||
else super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos)
|
||||
}
|
||||
|
||||
override fun onUse(
|
||||
state: BlockState,
|
||||
world: World,
|
||||
pos: BlockPos,
|
||||
player: PlayerEntity,
|
||||
hand: Hand,
|
||||
hit: BlockHitResult
|
||||
): ActionResult {
|
||||
val entity = world.getBlockEntity(pos) as DisplayCaseBlockEntity
|
||||
val result = entity.updateItem(player, hand)
|
||||
if ((hit.side != Direction.UP && hit.side != Direction.DOWN) && result == ActionResult.SUCCESS) {
|
||||
world.setBlockState(pos, state.with(FACING, hit.side.opposite))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
override fun onBreak(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity) {
|
||||
val entity = world.getBlockEntity(pos) as DisplayCaseBlockEntity
|
||||
if (!entity.getStack().isEmpty && !player.isCreative) {
|
||||
ItemScatterer.spawn(world, pos, entity.inv)
|
||||
}
|
||||
super.onBreak(world, pos, state, player)
|
||||
}
|
||||
|
||||
override fun getRenderType(state: BlockState?) = BlockRenderType.MODEL
|
||||
|
||||
override fun getComparatorOutput(state: BlockState, world: World, pos: BlockPos): Int {
|
||||
val stack = (world.getBlockEntity(pos) as DisplayCaseBlockEntity).getStack()
|
||||
|
||||
if (stack.isEmpty) return 0
|
||||
if (stack.item is PokeBallItem) return 3
|
||||
if (stack.item is BlockItem) return 2
|
||||
return 1
|
||||
}
|
||||
|
||||
override fun hasComparatorOutput(state: BlockState?) = true
|
||||
|
||||
override fun canPathfindThrough(state: BlockState, world: BlockView, pos: BlockPos, type: NavigationType) = false
|
||||
|
||||
}
|
||||
@@ -62,8 +62,8 @@ class MonitorBlock(properties: Settings) : MultiblockBlock(properties) {
|
||||
if(world == null || pos == null) {
|
||||
return 0
|
||||
}
|
||||
val monitorEntity = world.getBlockEntity(pos) as MultiblockEntity
|
||||
val multiBlockEntity = monitorEntity.multiblockStructure
|
||||
val monitorEntity = world.getBlockEntity(pos) as? MultiblockEntity
|
||||
val multiBlockEntity = monitorEntity?.multiblockStructure
|
||||
if(multiBlockEntity != null) {
|
||||
return multiBlockEntity.getComparatorOutput(state, world, pos)
|
||||
}
|
||||
|
||||
@@ -149,8 +149,8 @@ class RestorationTankBlock(properties: Settings) : MultiblockBlock(properties),
|
||||
if(world == null || pos == null) {
|
||||
return 0
|
||||
}
|
||||
val tankEntity = world.getBlockEntity(pos) as MultiblockEntity
|
||||
val multiBlockEntity = tankEntity.multiblockStructure
|
||||
val tankEntity = world.getBlockEntity(pos) as? MultiblockEntity
|
||||
val multiBlockEntity = tankEntity?.multiblockStructure
|
||||
if(multiBlockEntity != null) {
|
||||
return multiBlockEntity.getComparatorOutput(state, world, pos)
|
||||
}
|
||||
@@ -180,7 +180,7 @@ class RestorationTankBlock(properties: Settings) : MultiblockBlock(properties),
|
||||
return
|
||||
}
|
||||
val tankEntity = world.getBlockEntity(pos) as? MultiblockEntity
|
||||
tankEntity?.multiblockStructure!!.onTriggerEvent(state, world, pos, random)
|
||||
tankEntity?.multiblockStructure?.onTriggerEvent(state, world, pos, random)
|
||||
}
|
||||
|
||||
override fun getOutlineShape(
|
||||
|
||||
@@ -23,13 +23,18 @@ import net.minecraft.block.BlockWithEntity
|
||||
import net.minecraft.block.Blocks
|
||||
import net.minecraft.block.HorizontalFacingBlock
|
||||
import net.minecraft.block.ShapeContext
|
||||
import net.minecraft.block.Waterloggable
|
||||
import net.minecraft.entity.ai.pathing.NavigationType
|
||||
import net.minecraft.entity.mob.PiglinBrain
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.fluid.FluidState
|
||||
import net.minecraft.fluid.Fluids
|
||||
import net.minecraft.item.ItemPlacementContext
|
||||
import net.minecraft.screen.ScreenHandler
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.sound.SoundCategory
|
||||
import net.minecraft.state.StateManager
|
||||
import net.minecraft.state.property.BooleanProperty
|
||||
import net.minecraft.state.property.Properties
|
||||
import net.minecraft.text.MutableText
|
||||
import net.minecraft.text.Text
|
||||
@@ -46,17 +51,21 @@ import net.minecraft.util.shape.VoxelShape
|
||||
import net.minecraft.util.shape.VoxelShapes
|
||||
import net.minecraft.world.BlockView
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.world.WorldAccess
|
||||
|
||||
@Suppress("OVERRIDE_DEPRECATION")
|
||||
class GildedChestBlock(settings: Settings, val type: Type = Type.RED) : BlockWithEntity(settings) {
|
||||
class GildedChestBlock(settings: Settings, val type: Type = Type.RED) : BlockWithEntity(settings), Waterloggable {
|
||||
|
||||
init {
|
||||
defaultState = defaultState.with(Properties.HORIZONTAL_FACING, Direction.SOUTH)
|
||||
defaultState = defaultState
|
||||
.with(Properties.HORIZONTAL_FACING, Direction.SOUTH)
|
||||
.with(WATERLOGGED, false)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val POKEMON_ARGS = "gimmighoul"
|
||||
val LEVEL_RANGE = 5..30
|
||||
val WATERLOGGED = BooleanProperty.of("waterlogged")
|
||||
|
||||
val SOUTH_OUTLINE = VoxelShapes.union(
|
||||
VoxelShapes.cuboid(0.0, 0.0, 0.25, 1.0, 1.0, 0.9375)
|
||||
@@ -88,9 +97,28 @@ class GildedChestBlock(settings: Settings, val type: Type = Type.RED) : BlockWit
|
||||
}
|
||||
}
|
||||
|
||||
override fun getStateForNeighborUpdate(
|
||||
state: BlockState,
|
||||
direction: Direction,
|
||||
neighborState: BlockState,
|
||||
world: WorldAccess,
|
||||
pos: BlockPos,
|
||||
neighborPos: BlockPos
|
||||
): BlockState {
|
||||
if (state.get(WATERLOGGED)) world.scheduleFluidTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world))
|
||||
return super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos)
|
||||
}
|
||||
|
||||
override fun getFluidState(state: BlockState): FluidState {
|
||||
return if (state.get(WATERLOGGED)) {
|
||||
Fluids.WATER.getStill(false)
|
||||
} else super.getFluidState(state)
|
||||
}
|
||||
|
||||
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
|
||||
super.appendProperties(builder)
|
||||
builder.add(Properties.HORIZONTAL_FACING)
|
||||
builder.add(WATERLOGGED)
|
||||
}
|
||||
|
||||
private val facingToYaw: HashMap<Direction, Float> = hashMapOf(
|
||||
@@ -111,7 +139,7 @@ class GildedChestBlock(settings: Settings, val type: Type = Type.RED) : BlockWit
|
||||
if (player is ServerPlayerEntity) {
|
||||
spawnPokemon(world, pos, state, player)
|
||||
}
|
||||
world.setBlockState(pos, Blocks.AIR.defaultState)
|
||||
world.setBlockState(pos, if (state.fluidState.isOf(Fluids.WATER)) Blocks.WATER.defaultState else Blocks.AIR.defaultState)
|
||||
} else super.onBreak(world, pos, state, player)
|
||||
}
|
||||
|
||||
@@ -188,12 +216,9 @@ class GildedChestBlock(settings: Settings, val type: Type = Type.RED) : BlockWit
|
||||
override fun getRenderType(state: BlockState?) = BlockRenderType.ENTITYBLOCK_ANIMATED
|
||||
|
||||
override fun getPlacementState(blockPlaceContext: ItemPlacementContext): BlockState? {
|
||||
// val abovePosition = blockPlaceContext.blockPos.up()
|
||||
// val world = blockPlaceContext.world
|
||||
// if (world.getBlockState(abovePosition).canReplace(blockPlaceContext) && !world.isOutOfHeightLimit(abovePosition)) {
|
||||
return defaultState.with(HorizontalFacingBlock.FACING, blockPlaceContext.horizontalPlayerFacing.opposite)
|
||||
// }
|
||||
// return null
|
||||
return defaultState
|
||||
.with(HorizontalFacingBlock.FACING, blockPlaceContext.horizontalPlayerFacing.opposite)
|
||||
.with(WATERLOGGED, blockPlaceContext.world.getFluidState(blockPlaceContext.blockPos).fluid == Fluids.WATER)
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
@@ -205,6 +230,14 @@ class GildedChestBlock(settings: Settings, val type: Type = Type.RED) : BlockWit
|
||||
) as BlockState
|
||||
}
|
||||
|
||||
override fun hasComparatorOutput(state: BlockState?): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getComparatorOutput(state: BlockState?, world: World, pos: BlockPos?): Int {
|
||||
return ScreenHandler.calculateComparatorOutput(world.getBlockEntity(pos))
|
||||
}
|
||||
|
||||
override fun mirror(state: BlockState, mirror: BlockMirror): BlockState {
|
||||
return state.rotate(mirror.getRotation(state.get(Properties.HORIZONTAL_FACING) as Direction))
|
||||
}
|
||||
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.block.entity
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.entity.BlockEntity
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.inventory.Inventories
|
||||
import net.minecraft.inventory.SidedInventory
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.item.Items
|
||||
import net.minecraft.nbt.NbtCompound
|
||||
import net.minecraft.network.listener.ClientPlayPacketListener
|
||||
import net.minecraft.network.packet.Packet
|
||||
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket
|
||||
import net.minecraft.sound.SoundCategory
|
||||
import net.minecraft.util.ActionResult
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.collection.DefaultedList
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.world.World
|
||||
|
||||
class DisplayCaseBlockEntity(pos: BlockPos, state: BlockState) : BlockEntity(CobblemonBlockEntities.DISPLAY_CASE, pos, state), SidedInventory {
|
||||
|
||||
val inv: DefaultedList<ItemStack> = DefaultedList.ofSize(1, ItemStack.EMPTY)
|
||||
|
||||
/**
|
||||
* Updates the [ItemStack] stored in this entity
|
||||
*
|
||||
* @param player The [PlayerEntity] that performed this interaction
|
||||
* @param hand The [Hand] the player used to perform this interaction
|
||||
* @author whatsy
|
||||
*/
|
||||
fun updateItem(player: PlayerEntity, hand: Hand): ActionResult {
|
||||
val playerStack = player.getStackInHand(hand)
|
||||
|
||||
// Player and case item are the same - do nothing
|
||||
if (playerStack.item == getStack().item) {
|
||||
return if (playerStack.item != Items.AIR) ActionResult.SUCCESS else ActionResult.FAIL
|
||||
}
|
||||
|
||||
// Player's hand is empty, case is not empty - give player the item in the case
|
||||
if (playerStack.isEmpty && !getStack().isEmpty) {
|
||||
if (!player.isCreative) player.setStackInHand(hand, getStack())
|
||||
setCaseStack(ItemStack.EMPTY)
|
||||
return ActionResult.success(true)
|
||||
}
|
||||
|
||||
// Case is empty, player's hand is not - put playerStack in the case
|
||||
if (getStack().isEmpty && !playerStack.isEmpty) {
|
||||
setCaseStack(playerStack.copy())
|
||||
if (!player.isCreative) playerStack.decrement(1)
|
||||
return ActionResult.success(true)
|
||||
}
|
||||
|
||||
// Player has item, case has item - swap items
|
||||
if (!getStack().isEmpty && !playerStack.isEmpty) {
|
||||
val oldCaseStack = getStack()
|
||||
setCaseStack(playerStack.copy())
|
||||
if (!player.isCreative) {
|
||||
playerStack.decrement(1)
|
||||
player.giveItemStack(oldCaseStack)
|
||||
}
|
||||
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
|
||||
return ActionResult.FAIL
|
||||
}
|
||||
|
||||
fun getStack(): ItemStack {
|
||||
return inv[0]
|
||||
}
|
||||
|
||||
private fun setCaseStack(newStack: ItemStack) {
|
||||
if (world == null) return
|
||||
val oldState = world!!.getBlockState(pos)
|
||||
newStack.count = 1
|
||||
inv[0] = newStack
|
||||
if (newStack.isEmpty) {
|
||||
world!!.playSound(null, pos, CobblemonSounds.DISPLAY_CASE_REMOVE_ITEM, SoundCategory.BLOCKS)
|
||||
} else {
|
||||
world!!.playSound(null, pos, CobblemonSounds.DISPLAY_CASE_ADD_ITEM, SoundCategory.BLOCKS)
|
||||
}
|
||||
world!!.updateListeners(pos, oldState, world!!.getBlockState(pos), Block.NOTIFY_LISTENERS)
|
||||
world!!.updateComparators(pos, world!!.getBlockState(pos).block)
|
||||
}
|
||||
|
||||
override fun writeNbt(nbt: NbtCompound) {
|
||||
super.writeNbt(nbt)
|
||||
Inventories.writeNbt(nbt, inv, true)
|
||||
}
|
||||
|
||||
override fun readNbt(nbt: NbtCompound) {
|
||||
super.readNbt(nbt)
|
||||
inv.clear()
|
||||
Inventories.readNbt(nbt, inv)
|
||||
}
|
||||
|
||||
override fun toUpdatePacket(): Packet<ClientPlayPacketListener>? {
|
||||
return BlockEntityUpdateS2CPacket.create(this)
|
||||
}
|
||||
|
||||
override fun toInitialChunkDataNbt(): NbtCompound {
|
||||
return this.createNbt()
|
||||
}
|
||||
|
||||
private fun onItemUpdated(world: World, oldState: BlockState, newState: BlockState) {
|
||||
markDirty()
|
||||
world.updateListeners(pos, oldState, newState, Block.NOTIFY_LISTENERS)
|
||||
world.updateComparators(pos, world.getBlockState(pos).block)
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
inv.clear()
|
||||
}
|
||||
|
||||
override fun size(): Int {
|
||||
return inv.size
|
||||
}
|
||||
|
||||
override fun isEmpty(): Boolean {
|
||||
return getStack().isEmpty
|
||||
}
|
||||
|
||||
override fun getStack(slot: Int): ItemStack {
|
||||
return getStack()
|
||||
}
|
||||
|
||||
override fun removeStack(slot: Int, amount: Int): ItemStack {
|
||||
val oldState = cachedState
|
||||
val result = Inventories.splitStack(inv, slot, amount)
|
||||
if (world != null) onItemUpdated(world!!, oldState, world!!.getBlockState(pos))
|
||||
return result
|
||||
}
|
||||
|
||||
override fun removeStack(slot: Int): ItemStack {
|
||||
val oldState = cachedState
|
||||
val result = Inventories.removeStack(inv, slot)
|
||||
if (world != null) onItemUpdated(world!!, oldState, world!!.getBlockState(pos))
|
||||
return result
|
||||
}
|
||||
|
||||
override fun setStack(slot: Int, stack: ItemStack) {
|
||||
val oldState = cachedState
|
||||
inv[slot] = stack
|
||||
if (stack.count > stack.maxCount) {
|
||||
stack.count = stack.maxCount
|
||||
}
|
||||
if (world != null) onItemUpdated(world!!, oldState, world!!.getBlockState(pos))
|
||||
}
|
||||
|
||||
override fun canPlayerUse(player: PlayerEntity?) = false
|
||||
|
||||
override fun getAvailableSlots(side: Direction?): IntArray {
|
||||
val result = IntArray(inv.size)
|
||||
for (i in result.indices) {
|
||||
result[i] = i
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
override fun getMaxCountPerStack() = 1
|
||||
|
||||
override fun canInsert(slot: Int, stack: ItemStack?, dir: Direction?): Boolean {
|
||||
if(dir == Direction.DOWN) return false
|
||||
return getStack().isEmpty
|
||||
}
|
||||
override fun canExtract(slot: Int, stack: ItemStack?, dir: Direction?): Boolean = (dir == Direction.DOWN)
|
||||
}
|
||||
+7
-2
@@ -19,6 +19,7 @@ import net.minecraft.block.entity.BlockEntityType
|
||||
import net.minecraft.nbt.NbtCompound
|
||||
import net.minecraft.nbt.NbtHelper
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.ChunkPos
|
||||
|
||||
open class FossilMultiblockEntity(
|
||||
pos: BlockPos,
|
||||
@@ -39,8 +40,12 @@ open class FossilMultiblockEntity(
|
||||
get() {
|
||||
return if (field != null) {
|
||||
field
|
||||
} else if (masterBlockPos != null && masterBlockPos != pos && world?.getBlockEntity(masterBlockPos) != null) {
|
||||
field = (world?.getBlockEntity(masterBlockPos) as FossilMultiblockEntity).multiblockStructure
|
||||
} else if (masterBlockPos != null && masterBlockPos != pos) {
|
||||
val chunkPos = ChunkPos(masterBlockPos)
|
||||
if (world?.chunkManager?.isChunkLoaded(chunkPos.x, chunkPos.z) == true) {
|
||||
val entity: FossilMultiblockEntity? = world?.getBlockEntity(masterBlockPos) as FossilMultiblockEntity?
|
||||
field = entity?.multiblockStructure
|
||||
}
|
||||
field
|
||||
} else {
|
||||
null
|
||||
|
||||
+20
-2
@@ -20,6 +20,7 @@ import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.entity.player.PlayerInventory
|
||||
import net.minecraft.inventory.DoubleInventory
|
||||
import net.minecraft.inventory.Inventories
|
||||
import net.minecraft.inventory.SidedInventory
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NbtCompound
|
||||
import net.minecraft.screen.GenericContainerScreenHandler
|
||||
@@ -28,9 +29,10 @@ import net.minecraft.state.property.Properties
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.collection.DefaultedList
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.world.World
|
||||
|
||||
class GildedChestBlockEntity(pos: BlockPos, state: BlockState, val type: Type = Type.RED) : LootableContainerBlockEntity(CobblemonBlockEntities.GILDED_CHEST, pos, state) {
|
||||
class GildedChestBlockEntity(pos: BlockPos, state: BlockState, val type: Type = Type.RED) : LootableContainerBlockEntity(CobblemonBlockEntities.GILDED_CHEST, pos, state), SidedInventory {
|
||||
var inventoryContents: DefaultedList<ItemStack> = DefaultedList.ofSize(NUM_SLOTS, ItemStack.EMPTY)
|
||||
val poseableState: GildedState = GildedState()
|
||||
|
||||
@@ -69,7 +71,7 @@ class GildedChestBlockEntity(pos: BlockPos, state: BlockState, val type: Type =
|
||||
|
||||
override fun getContainerName() = Text.translatable("block.cobblemon.gilded_chest")
|
||||
override fun createScreenHandler(syncId: Int, playerInventory: PlayerInventory?) =
|
||||
GenericContainerScreenHandler.createGeneric9x3(syncId, playerInventory, this);
|
||||
GenericContainerScreenHandler.createGeneric9x3(syncId, playerInventory, this)
|
||||
|
||||
override fun onOpen(player: PlayerEntity) {
|
||||
if (!this.removed && !player.isSpectator && type != Type.FAKE) {
|
||||
@@ -83,6 +85,22 @@ class GildedChestBlockEntity(pos: BlockPos, state: BlockState, val type: Type =
|
||||
}
|
||||
}
|
||||
|
||||
override fun getAvailableSlots(side: Direction): IntArray {
|
||||
return if (type == Type.FAKE) IntArray(0) else IntArray(NUM_SLOTS)
|
||||
}
|
||||
|
||||
override fun canInsert(slot: Int, stack: ItemStack?, dir: Direction?): Boolean {
|
||||
if (type == Type.FAKE) return false
|
||||
return dir != Direction.DOWN
|
||||
}
|
||||
|
||||
override fun canExtract(slot: Int, stack: ItemStack?, dir: Direction?): Boolean {
|
||||
if (type == Type.FAKE) return false
|
||||
return dir == Direction.DOWN
|
||||
}
|
||||
|
||||
override fun canPlayerUse(player: PlayerEntity) = !player.isSpectator
|
||||
|
||||
override fun getInvStackList(): DefaultedList<ItemStack> = inventoryContents
|
||||
|
||||
override fun setInvStackList(list: DefaultedList<ItemStack>) {
|
||||
|
||||
+12
-12
@@ -117,10 +117,10 @@ class FossilMultiblockBuilder(val centerPos: BlockPos) : MultiblockStructureBuil
|
||||
val monitorPos = monitorPositions[fossilTankIndex]
|
||||
val fossilAnalyzerPos = fossilAnalyzerPositions[fossilTankIndex]!!
|
||||
val restorationTankPos = restorationTankPositions[fossilTankIndex]!!
|
||||
val monitorEntity = world.getBlockEntity(monitorPos) as MultiblockEntity
|
||||
val analyzerEntity = world.getBlockEntity(fossilAnalyzerPos) as MultiblockEntity
|
||||
val tankBaseEntity = world.getBlockEntity(restorationTankPos) as MultiblockEntity
|
||||
val tankTopEntity = world.getBlockEntity(restorationTankPos.up()) as MultiblockEntity
|
||||
val monitorEntity = world.getBlockEntity(monitorPos) as? MultiblockEntity
|
||||
val analyzerEntity = world.getBlockEntity(fossilAnalyzerPos) as? MultiblockEntity
|
||||
val tankBaseEntity = world.getBlockEntity(restorationTankPos) as? MultiblockEntity
|
||||
val tankTopEntity = world.getBlockEntity(restorationTankPos.up()) as? MultiblockEntity
|
||||
val structure = FossilMultiblockStructure(monitorPos, fossilAnalyzerPos, restorationTankPos)
|
||||
|
||||
structure.tankConnectorDirection = dirsToCheck.filter {
|
||||
@@ -128,20 +128,20 @@ class FossilMultiblockBuilder(val centerPos: BlockPos) : MultiblockStructureBuil
|
||||
return@filter adjPos == fossilAnalyzerPos
|
||||
}.first()
|
||||
|
||||
analyzerEntity.multiblockStructure = structure
|
||||
tankBaseEntity.multiblockStructure = structure
|
||||
tankTopEntity.multiblockStructure = structure
|
||||
monitorEntity.multiblockStructure = structure
|
||||
analyzerEntity?.multiblockStructure = structure
|
||||
tankBaseEntity?.multiblockStructure = structure
|
||||
tankTopEntity?.multiblockStructure = structure
|
||||
monitorEntity?.multiblockStructure = structure
|
||||
structure.syncToClient(world)
|
||||
structure.markDirty(world)
|
||||
|
||||
world.playSound(null, centerPos, CobblemonSounds.FOSSIL_MACHINE_ASSEMBLE, SoundCategory.BLOCKS)
|
||||
|
||||
//Set these to null so the builders can be freed
|
||||
analyzerEntity.multiblockBuilder = null
|
||||
tankBaseEntity.multiblockBuilder = null
|
||||
tankTopEntity.multiblockBuilder = null
|
||||
monitorEntity.multiblockBuilder = null
|
||||
analyzerEntity?.multiblockBuilder = null
|
||||
tankBaseEntity?.multiblockBuilder = null
|
||||
tankTopEntity?.multiblockBuilder = null
|
||||
monitorEntity?.multiblockBuilder = null
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
+87
-92
@@ -98,101 +98,97 @@ class FossilMultiblockStructure (
|
||||
): ActionResult {
|
||||
val stack = player.getStackInHand(interactionHand)
|
||||
|
||||
if (this.createdPokemon != null) {
|
||||
|
||||
if (!stack.isIn(CobblemonItemTags.POKE_BALLS) || stack.item !is PokeBallItem) {
|
||||
return ActionResult.PASS
|
||||
}
|
||||
|
||||
if(stack.isIn(CobblemonItemTags.POKE_BALLS) || stack.item is PokeBallItem) {
|
||||
if (player !is ServerPlayerEntity) {
|
||||
return ActionResult.CONSUME
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
if (this.createdPokemon != null) {
|
||||
|
||||
if (this.fossilOwnerUUID != null && player.uuid != this.fossilOwnerUUID) {
|
||||
var ownerName : String = "UNKNOWN_USER" // TODO: lang agnostic fallback
|
||||
server()?.userCache?.getByUuid(this.fossilOwnerUUID)?.orElse(null)?.name?.let {
|
||||
ownerName = it
|
||||
if (this.fossilOwnerUUID != null && player.uuid != this.fossilOwnerUUID) {
|
||||
var ownerName : String = "UNKNOWN_USER" // TODO: lang agnostic fallback
|
||||
server()?.userCache?.getByUuid(this.fossilOwnerUUID)?.orElse(null)?.name?.let {
|
||||
ownerName = it
|
||||
}
|
||||
player.sendMessage(lang("fossilmachine.protected", ownerName), true)
|
||||
return ActionResult.FAIL
|
||||
}
|
||||
player.sendMessage(lang("fossilmachine.protected", ownerName), true)
|
||||
return ActionResult.FAIL
|
||||
|
||||
|
||||
|
||||
val ballType = (stack.item as PokeBallItem).pokeBall
|
||||
if (!player.isCreative) {
|
||||
stack?.decrement(1)
|
||||
}
|
||||
|
||||
this.createdPokemon!!.caughtBall = ballType
|
||||
player.party().add(this.createdPokemon!!)
|
||||
this.fossilState.growthState = "Taken"
|
||||
player.playSound(CobblemonSounds.FOSSIL_MACHINE_RETRIEVE_POKEMON, SoundCategory.BLOCKS, 1.0F, 1.0F)
|
||||
CobblemonCriteria.RESURRECT_POKEMON.trigger(player, createdPokemon!!)
|
||||
|
||||
// Turn the monitor off
|
||||
val monitorState = world.getBlockState(monitorPos)
|
||||
if(!monitorState.equals(MonitorBlock.MonitorScreen.OFF)) {
|
||||
world.setBlockState(monitorPos, monitorState.with(MonitorBlock.SCREEN, MonitorBlock.MonitorScreen.OFF))
|
||||
}
|
||||
|
||||
this.createdPokemon = null
|
||||
this.fossilOwnerUUID = null
|
||||
this.protectionTime = -1
|
||||
this.updateFossilType(world)
|
||||
this.syncToClient(world)
|
||||
this.markDirty(world)
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
|
||||
|
||||
|
||||
val ballType = (stack.item as PokeBallItem).pokeBall
|
||||
if (!player.isCreative) {
|
||||
stack?.decrement(1)
|
||||
}
|
||||
|
||||
this.createdPokemon!!.caughtBall = ballType
|
||||
player.party().add(this.createdPokemon!!)
|
||||
this.fossilState.growthState = "Taken"
|
||||
player.playSound(CobblemonSounds.FOSSIL_MACHINE_RETRIEVE_POKEMON, SoundCategory.BLOCKS, 1.0F, 1.0F)
|
||||
CobblemonCriteria.RESURRECT_POKEMON.trigger(player, createdPokemon!!)
|
||||
|
||||
// Turn the monitor off
|
||||
val monitorState = world.getBlockState(monitorPos)
|
||||
if(!monitorState.equals(MonitorBlock.MonitorScreen.OFF)) {
|
||||
world.setBlockState(monitorPos, monitorState.with(MonitorBlock.SCREEN, MonitorBlock.MonitorScreen.OFF))
|
||||
}
|
||||
|
||||
this.createdPokemon = null
|
||||
this.fossilOwnerUUID = null
|
||||
this.protectionTime = -1
|
||||
this.updateFossilType(world)
|
||||
this.syncToClient(world)
|
||||
this.markDirty(world)
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
|
||||
if (this.isRunning()) {
|
||||
return ActionResult.PASS
|
||||
}
|
||||
|
||||
// Reclaim the last fossil from the machine if their hand is empty
|
||||
if (player.getStackInHand(interactionHand).isEmpty) {
|
||||
if (fossilInventory.isEmpty()) {
|
||||
return ActionResult.CONSUME
|
||||
}
|
||||
if(!this.isRunning() && this.createdPokemon == null) {
|
||||
if (fossilInventory.isEmpty()) {
|
||||
return ActionResult.CONSUME
|
||||
}
|
||||
player.setStackInHand(interactionHand, fossilInventory.last())
|
||||
|
||||
player.setStackInHand(interactionHand, fossilInventory.last())
|
||||
|
||||
// remove last fossil in the fossil machine stack when grabbed out of the machine
|
||||
this.fossilInventory.removeAt(fossilInventory.size - 1)
|
||||
if(!world.isClient) {
|
||||
world.playSound(null, analyzerPos, CobblemonSounds.FOSSIL_MACHINE_RETRIEVE_FOSSIL, SoundCategory.BLOCKS)
|
||||
this.updateFossilType(world)
|
||||
this.syncToClient(world)
|
||||
this.markDirty(world)
|
||||
// remove last fossil in the fossil machine stack when grabbed out of the machine
|
||||
this.fossilInventory.removeAt(fossilInventory.size - 1)
|
||||
if(!world.isClient) {
|
||||
world.playSound(null, analyzerPos, CobblemonSounds.FOSSIL_MACHINE_RETRIEVE_FOSSIL, SoundCategory.BLOCKS)
|
||||
this.updateFossilType(world)
|
||||
this.syncToClient(world)
|
||||
this.markDirty(world)
|
||||
}
|
||||
}
|
||||
return ActionResult.CONSUME
|
||||
}
|
||||
|
||||
// Check if the player is holding a fossil and if so insert it into the machine.
|
||||
if (Fossils.isFossilIngredient(stack)) {
|
||||
if (fossilInventory.size > Cobblemon.config.maxInsertedFossilItems) {
|
||||
return ActionResult.FAIL
|
||||
}
|
||||
if(!this.isRunning() && this.createdPokemon == null) {
|
||||
if (fossilInventory.size > Cobblemon.config.maxInsertedFossilItems) {
|
||||
return ActionResult.FAIL
|
||||
}
|
||||
|
||||
val copyFossilStack = stack.copyWithCount(1)
|
||||
if (!player.isCreative) {
|
||||
stack?.decrement(1)
|
||||
}
|
||||
val copyFossilStack = stack.copyWithCount(1)
|
||||
if (!player.isCreative) {
|
||||
stack?.decrement(1)
|
||||
}
|
||||
|
||||
fossilOwnerUUID = player.uuid
|
||||
fossilInventory.add(copyFossilStack)
|
||||
if(!world.isClient) {
|
||||
this.updateFossilType(world)
|
||||
world.playSound(null, analyzerPos, CobblemonSounds.FOSSIL_MACHINE_INSERT_FOSSIL, SoundCategory.BLOCKS)
|
||||
this.syncToClient(world)
|
||||
this.markDirty(world)
|
||||
fossilOwnerUUID = player.uuid
|
||||
fossilInventory.add(copyFossilStack)
|
||||
if(!world.isClient) {
|
||||
this.updateFossilType(world)
|
||||
world.playSound(null, analyzerPos, CobblemonSounds.FOSSIL_MACHINE_INSERT_FOSSIL, SoundCategory.BLOCKS)
|
||||
this.syncToClient(world)
|
||||
this.markDirty(world)
|
||||
}
|
||||
}
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
|
||||
// Check if the player is holding a natural material and if so, feed it to the machine.
|
||||
if (NaturalMaterials.isNaturalMaterial(stack) && this.organicMaterialInside < MATERIAL_TO_START) {
|
||||
if (insertOrganicMaterial(stack, world)) {
|
||||
if (NaturalMaterials.isNaturalMaterial(stack)) {
|
||||
if (!this.isRunning() && this.createdPokemon == null && this.organicMaterialInside < MATERIAL_TO_START && insertOrganicMaterial(stack, world)) {
|
||||
this.lastInteraction = world.time
|
||||
if (!player.isCreative) {
|
||||
val returnItem = NaturalMaterials.getReturnItem(stack)
|
||||
@@ -200,7 +196,6 @@ class FossilMultiblockStructure (
|
||||
player.giveOrDropItemStack(ItemStack(Registries.ITEM.get(returnItem)), false)
|
||||
}
|
||||
}
|
||||
|
||||
return ActionResult.success(world.isClient)
|
||||
}
|
||||
|
||||
@@ -311,22 +306,22 @@ class FossilMultiblockStructure (
|
||||
}
|
||||
|
||||
override fun onBreak(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity?) {
|
||||
val monitorEntity = world.getBlockEntity(monitorPos) as MultiblockEntity
|
||||
val analyzerEntity = world.getBlockEntity(analyzerPos) as MultiblockEntity
|
||||
val tankBaseEntity = world.getBlockEntity(tankBasePos) as MultiblockEntity
|
||||
val tankTopEntity = world.getBlockEntity(tankBasePos.up()) as MultiblockEntity
|
||||
val state = world.getBlockState(tankBaseEntity.pos)
|
||||
val monitorEntity = world.getBlockEntity(monitorPos) as? MultiblockEntity
|
||||
val analyzerEntity = world.getBlockEntity(analyzerPos) as? MultiblockEntity
|
||||
val tankBaseEntity = world.getBlockEntity(tankBasePos) as? MultiblockEntity
|
||||
val tankTopEntity = world.getBlockEntity(tankBasePos.up()) as? MultiblockEntity
|
||||
val state = world.getBlockState(tankBaseEntity?.pos)
|
||||
val direction = state.get(HorizontalFacingBlock.FACING).getOpposite()
|
||||
val wildPokemon: Pokemon? = this.createdPokemon
|
||||
|
||||
monitorEntity.multiblockStructure = null
|
||||
analyzerEntity.multiblockStructure = null
|
||||
tankBaseEntity.multiblockStructure = null
|
||||
tankTopEntity.multiblockStructure = null
|
||||
monitorEntity.masterBlockPos = null
|
||||
analyzerEntity.masterBlockPos = null
|
||||
tankBaseEntity.masterBlockPos = null
|
||||
tankTopEntity.masterBlockPos = null
|
||||
monitorEntity?.multiblockStructure = null
|
||||
analyzerEntity?.multiblockStructure = null
|
||||
tankBaseEntity?.multiblockStructure = null
|
||||
tankTopEntity?.multiblockStructure = null
|
||||
monitorEntity?.masterBlockPos = null
|
||||
analyzerEntity?.masterBlockPos = null
|
||||
tankBaseEntity?.masterBlockPos = null
|
||||
tankTopEntity?.masterBlockPos = null
|
||||
|
||||
// Drop fossils from machine as long as the machine is not started or near completion
|
||||
if (this.timeRemaining == -1 || this.timeRemaining >= 20) {
|
||||
@@ -544,7 +539,7 @@ class FossilMultiblockStructure (
|
||||
}
|
||||
|
||||
if (natureValue < 0 && organicMaterialInside == 0) return false
|
||||
val oldFillStage = organicMaterialInside / 8
|
||||
val oldFillStage = organicMaterialInside * 8 / MATERIAL_TO_START
|
||||
|
||||
// to prevent over/under filling the tank causing a crash
|
||||
if ((organicMaterialInside + natureValue) > MATERIAL_TO_START) {
|
||||
@@ -562,7 +557,7 @@ class FossilMultiblockStructure (
|
||||
world.playSound(null, this.tankBasePos, CobblemonSounds.FOSSIL_MACHINE_INSERT_DNA, SoundCategory.BLOCKS, 1.0F, 1.0F)
|
||||
}
|
||||
this.markDirty(world)
|
||||
if (oldFillStage != (organicMaterialInside / 8)) {
|
||||
if (oldFillStage != (organicMaterialInside * 8 / MATERIAL_TO_START)) {
|
||||
this.syncToClient(world)
|
||||
}
|
||||
return true
|
||||
@@ -624,10 +619,10 @@ class FossilMultiblockStructure (
|
||||
}
|
||||
|
||||
const val TICKS_PER_MINUTE = 1200
|
||||
const val MATERIAL_TO_START = 64
|
||||
const val TIME_TO_TAKE = TICKS_PER_MINUTE * 1
|
||||
const val MATERIAL_TO_START = 128
|
||||
const val TIME_TO_TAKE = TICKS_PER_MINUTE * 12
|
||||
const val TIME_PER_STAGE = TIME_TO_TAKE / 8
|
||||
const val PROTECTION_TIME = 6000
|
||||
const val PROTECTION_TIME = TICKS_PER_MINUTE * 5
|
||||
|
||||
fun fromNbt(nbt: NbtCompound, animAge: Int = -1, partialTicks: Float = 0f): FossilMultiblockStructure {
|
||||
val monitorPos = NbtHelper.toBlockPos(nbt.getCompound(DataKeys.MONITOR_POS))
|
||||
@@ -662,7 +657,7 @@ class FossilMultiblockStructure (
|
||||
if (nbt.contains(DataKeys.CREATED_POKEMON)) {
|
||||
result.createdPokemon = Pokemon.loadFromNBT(nbt.getCompound(DataKeys.CREATED_POKEMON))
|
||||
}
|
||||
result.fillLevel = result.organicMaterialInside / 8
|
||||
result.fillLevel = result.organicMaterialInside * 8 / MATERIAL_TO_START
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,9 @@ import com.cobblemon.mod.common.client.render.block.FossilAnalyzerRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.RestorationTankRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.GildedChestBlockRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.HealingMachineRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.*
|
||||
import com.cobblemon.mod.common.client.render.boat.CobblemonBoatRenderer
|
||||
import com.cobblemon.mod.common.client.render.generic.GenericBedrockRenderer
|
||||
import com.cobblemon.mod.common.client.render.item.CobblemonBuiltinItemRendererRegistry
|
||||
import com.cobblemon.mod.common.client.render.item.PokemonItemRenderer
|
||||
import com.cobblemon.mod.common.client.render.layer.PokemonOnShoulderRenderer
|
||||
@@ -46,6 +48,7 @@ import com.cobblemon.mod.common.data.CobblemonDataProvider
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
|
||||
import com.cobblemon.mod.common.item.PokeBallItem
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.FossilModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.GenericBedrockEntityModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.MiscModelRepository
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
@@ -117,7 +120,6 @@ object CobblemonClient {
|
||||
PlatformEvents.CLIENT_ITEM_TOOLTIP.subscribe { event ->
|
||||
val stack = event.stack
|
||||
val lines = event.lines
|
||||
val size = lines.size
|
||||
@Suppress("DEPRECATION")
|
||||
if (stack.item.registryEntry.key.isPresent && stack.item.registryEntry.key.get().value.namespace == Cobblemon.MODID) {
|
||||
if (stack.nbt?.getBoolean(DataKeys.HIDE_TOOLTIP) == true) {
|
||||
@@ -125,14 +127,14 @@ object CobblemonClient {
|
||||
}
|
||||
val language = Language.getInstance()
|
||||
val key = this.baseLangKeyForItem(stack)
|
||||
val offset = if (size > 1) 1 else 0
|
||||
val offset = if (lines.size > 1) 1 else 0
|
||||
if (language.hasTranslation(key)) {
|
||||
lines.add(size - offset, key.asTranslated().gray())
|
||||
lines.add(lines.size - offset, key.asTranslated().gray())
|
||||
}
|
||||
var i = 1
|
||||
var listKey = "${key}_$i"
|
||||
while(language.hasTranslation(listKey)) {
|
||||
lines.add(size - offset, listKey.asTranslated().gray())
|
||||
lines.add(lines.size - offset, listKey.asTranslated().gray())
|
||||
listKey = "${key}_${++i}"
|
||||
}
|
||||
}
|
||||
@@ -218,7 +220,8 @@ object CobblemonClient {
|
||||
CobblemonBlocks.MEDIUM_BUDDING_SKY_TUMBLESTONE,
|
||||
CobblemonBlocks.LARGE_BUDDING_SKY_TUMBLESTONE,
|
||||
CobblemonBlocks.SKY_TUMBLESTONE_CLUSTER,
|
||||
CobblemonBlocks.GIMMIGHOUL_CHEST
|
||||
CobblemonBlocks.GIMMIGHOUL_CHEST,
|
||||
CobblemonBlocks.DISPLAY_CASE
|
||||
)
|
||||
|
||||
this.createBoatModelLayers()
|
||||
@@ -249,6 +252,7 @@ object CobblemonClient {
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.FOSSIL_ANALYZER, ::FossilAnalyzerRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.RESTORATION_TANK, ::RestorationTankRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.GILDED_CHEST, ::GildedChestBlockRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.DISPLAY_CASE, ::DisplayCaseRenderer)
|
||||
}
|
||||
|
||||
private fun registerEntityRenderers() {
|
||||
@@ -260,6 +264,8 @@ object CobblemonClient {
|
||||
this.implementation.registerEntityRenderer(CobblemonEntities.BOAT) { ctx -> CobblemonBoatRenderer(ctx, false) }
|
||||
LOGGER.info("Registering Boat with Chest renderer")
|
||||
this.implementation.registerEntityRenderer(CobblemonEntities.CHEST_BOAT) { ctx -> CobblemonBoatRenderer(ctx, true) }
|
||||
LOGGER.info("Registering Generic Bedrock Entity renderer")
|
||||
this.implementation.registerEntityRenderer(CobblemonEntities.GENERIC_BEDROCK_ENTITY, ::GenericBedrockRenderer)
|
||||
}
|
||||
|
||||
fun reloadCodedAssets(resourceManager: ResourceManager) {
|
||||
@@ -267,13 +273,14 @@ object CobblemonClient {
|
||||
BedrockParticleEffectRepository.loadEffects(resourceManager)
|
||||
BedrockAnimationRepository.loadAnimations(
|
||||
resourceManager = resourceManager,
|
||||
directories = PokemonModelRepository.animationDirectories + PokeBallModelRepository.animationDirectories + FossilModelRepository.animationDirectories + BlockEntityModelRepository.animationDirectories
|
||||
directories = PokemonModelRepository.animationDirectories + PokeBallModelRepository.animationDirectories + FossilModelRepository.animationDirectories + BlockEntityModelRepository.animationDirectories + GenericBedrockEntityModelRepository.animationDirectories
|
||||
)
|
||||
PokemonModelRepository.reload(resourceManager)
|
||||
PokeBallModelRepository.reload(resourceManager)
|
||||
BerryModelRepository.reload(resourceManager)
|
||||
FossilModelRepository.reload(resourceManager)
|
||||
BlockEntityModelRepository.reload(resourceManager)
|
||||
GenericBedrockEntityModelRepository.reload(resourceManager)
|
||||
MiscModelRepository.reload(resourceManager)
|
||||
LOGGER.info("Loaded assets")
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ class PartyOverlay : InGameHud(MinecraftClient.getInstance(), MinecraftClient.ge
|
||||
BattleGUI::class.java
|
||||
)
|
||||
|
||||
private val starterToast = CobblemonToast(
|
||||
val starterToast = CobblemonToast(
|
||||
MathHelper.randomUuid(),
|
||||
CobblemonItems.POKE_BALL.defaultStack,
|
||||
lang("ui.starter.choose_starter_title", SummaryBinding.boundKey().localizedText).red(),
|
||||
@@ -104,24 +104,12 @@ class PartyOverlay : InGameHud(MinecraftClient.getInstance(), MinecraftClient.ge
|
||||
!CobblemonClient.checkedStarterScreen
|
||||
) {
|
||||
if (!this.attachedToast) {
|
||||
// Adding starter toast on start and connect of client to server.
|
||||
minecraft.toastManager.add(this.starterToast)
|
||||
this.attachedToast = true
|
||||
}
|
||||
/*
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.starter.chooseyourstarter", SummaryBinding.boundKey().localizedText),
|
||||
x = minecraft.window.scaledWidth / 2,
|
||||
y = 70,
|
||||
centered = true,
|
||||
shadow = true
|
||||
)
|
||||
*/
|
||||
}
|
||||
return
|
||||
}
|
||||
if (this.starterToast.nextVisibility != Toast.Visibility.HIDE) {
|
||||
this.starterToast.nextVisibility = Toast.Visibility.HIDE
|
||||
return // Don't render the stuff below if no Pokémon in party
|
||||
}
|
||||
|
||||
val totalHeight = party.slots.size * SLOT_HEIGHT
|
||||
|
||||
+5
-3
@@ -10,6 +10,8 @@ package com.cobblemon.mod.common.client.gui.battle.subscreen
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.api.text.yellow
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.battle.SingleActionRequest
|
||||
import com.cobblemon.mod.common.client.gui.battle.BattleGUI
|
||||
@@ -21,7 +23,6 @@ import net.minecraft.client.gui.Selectable
|
||||
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder
|
||||
import net.minecraft.client.sound.PositionedSoundInstance
|
||||
import net.minecraft.client.sound.SoundManager
|
||||
import net.minecraft.client.util.math.MatrixStack
|
||||
import net.minecraft.text.MutableText
|
||||
import net.minecraft.util.Identifier
|
||||
class BattleGeneralActionSelection(
|
||||
@@ -61,8 +62,9 @@ class BattleGeneralActionSelection(
|
||||
}
|
||||
|
||||
addOption(rank++, battleLang("ui.run"), BattleGUI.runResource) {
|
||||
|
||||
MinecraftClient.getInstance().player?.sendMessage(battleLang("flee"))
|
||||
CobblemonClient.battle?.minimised = true
|
||||
MinecraftClient.getInstance().player?.sendMessage(battleLang("run_prompt"), false)
|
||||
playDownSound(MinecraftClient.getInstance().soundManager)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-1
@@ -15,6 +15,7 @@ import com.cobblemon.mod.common.api.gui.ColourLibrary
|
||||
import com.cobblemon.mod.common.api.gui.MultiLineLabelK
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.startselection.widgets.CategoryList
|
||||
import com.cobblemon.mod.common.client.gui.startselection.widgets.ExitButton
|
||||
@@ -37,7 +38,7 @@ import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.client.gui.DrawContext
|
||||
import net.minecraft.client.gui.screen.Screen
|
||||
import net.minecraft.client.sound.PositionedSoundInstance
|
||||
import net.minecraft.client.util.math.MatrixStack
|
||||
import net.minecraft.client.toast.Toast
|
||||
import net.minecraft.text.Text
|
||||
|
||||
/**
|
||||
@@ -74,6 +75,12 @@ class StarterSelectionScreen(private val categories: List<RenderableStarterCateg
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
// Hide toast once checkedStarterScreen was set, which happens during the opening of the starter screen.
|
||||
if (CobblemonClient.checkedStarterScreen) {
|
||||
if (CobblemonClient.overlay.starterToast.nextVisibility != Toast.Visibility.HIDE) {
|
||||
CobblemonClient.overlay.starterToast.nextVisibility = Toast.Visibility.HIDE
|
||||
}
|
||||
}
|
||||
|
||||
val x = (width - BASE_WIDTH) / 2
|
||||
val y = (height - BASE_HEIGHT) / 2
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.moves.Move
|
||||
import com.cobblemon.mod.common.api.moves.MoveSet
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies.species
|
||||
import com.cobblemon.mod.common.api.reactive.Observable.Companion.emitWhile
|
||||
import com.cobblemon.mod.common.api.reactive.ObservableSubscription
|
||||
import com.cobblemon.mod.common.api.scheduling.Schedulable
|
||||
@@ -34,6 +35,7 @@ import com.cobblemon.mod.common.client.gui.summary.widgets.screens.moves.MoveSwa
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.screens.moves.MovesWidget
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.screens.stats.StatWidget
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
@@ -613,6 +615,27 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
|
||||
) {
|
||||
this.focused = null
|
||||
}
|
||||
if (Cobblemon.config.enableDebugKeys) {
|
||||
val model = PokemonModelRepository.getPoser(selectedPokemon.species.resourceIdentifier, selectedPokemon.aspects)
|
||||
if (keyCode == InputUtil.GLFW_KEY_UP) {
|
||||
model.profileTranslation = model.profileTranslation.add(0.0, -0.01, 0.0)
|
||||
}
|
||||
if (keyCode == InputUtil.GLFW_KEY_DOWN) {
|
||||
model.profileTranslation = model.profileTranslation.add(0.0, 0.01, 0.0)
|
||||
}
|
||||
if (keyCode == InputUtil.GLFW_KEY_LEFT) {
|
||||
model.profileTranslation = model.profileTranslation.add(-0.01, 0.0, 0.0)
|
||||
}
|
||||
if (keyCode == InputUtil.GLFW_KEY_RIGHT) {
|
||||
model.profileTranslation = model.profileTranslation.add(0.01, 0.0, 0.0)
|
||||
}
|
||||
if (keyCode == InputUtil.GLFW_KEY_EQUAL) {
|
||||
model.profileScale += 0.01F
|
||||
}
|
||||
if (keyCode == InputUtil.GLFW_KEY_MINUS) {
|
||||
model.profileScale -= 0.01F
|
||||
}
|
||||
}
|
||||
return super.keyPressed(keyCode, scanCode, modifiers)
|
||||
}
|
||||
|
||||
@@ -620,4 +643,14 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
|
||||
MinecraftClient.getInstance().soundManager.play(PositionedSoundInstance.master(soundEvent, 1.0F))
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
if (Cobblemon.config.enableDebugKeys) {
|
||||
val model = PokemonModelRepository.getPoser(selectedPokemon.species.resourceIdentifier, selectedPokemon.aspects)
|
||||
MinecraftClient.getInstance().player?.sendMessage(Text.of("Profile Translation: ${model.profileTranslation}"))
|
||||
MinecraftClient.getInstance().player?.sendMessage(Text.of("Profile Scale: ${model.profileScale}"))
|
||||
Cobblemon.LOGGER.info("override var profileTranslation = Vec3d(${model.profileTranslation.x}, ${model.profileTranslation.y}, ${model.profileTranslation.z})")
|
||||
Cobblemon.LOGGER.info("override var profileScale = ${model.profileScale}F")
|
||||
}
|
||||
super.close()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,14 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.keybind
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.DebugKeybindings
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.DownShiftPartyBinding
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.HidePartyBinding
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.SummaryBinding
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.UpShiftPartyBinding
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import net.minecraft.client.option.KeyBinding
|
||||
|
||||
@@ -23,13 +26,17 @@ import net.minecraft.client.option.KeyBinding
|
||||
* @since 2022-02-17
|
||||
*/
|
||||
object CobblemonKeyBinds {
|
||||
private val keyBinds = arrayListOf<CobblemonKeyBinding>()
|
||||
|
||||
init {
|
||||
PlatformEvents.CLIENT_TICK_POST.subscribe { this.onTick() }
|
||||
if (Cobblemon.config.enableDebugKeys) {
|
||||
DebugKeybindings.keybindings.forEach {
|
||||
this.queue(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val keyBinds = arrayListOf<CobblemonKeyBinding>()
|
||||
|
||||
val HIDE_PARTY = this.queue(HidePartyBinding)
|
||||
// ToDo enable again down the line
|
||||
//val POKENAV = this.queue(PokeNavigatorBinding)
|
||||
|
||||
+22
@@ -9,7 +9,9 @@
|
||||
package com.cobblemon.mod.common.client.keybind
|
||||
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.text.yellow
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.SummaryBinding
|
||||
import com.cobblemon.mod.common.net.messages.server.starter.RequestStarterScreenPacket
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.MinecraftClient
|
||||
@@ -25,12 +27,20 @@ abstract class CobblemonPartyLockedKeyBinding(
|
||||
category: String
|
||||
) : CobblemonKeyBinding(name, type, key, category) {
|
||||
|
||||
private var skippedStarterSelectionMessageShown = false
|
||||
|
||||
override fun onTick() {
|
||||
if (this.wasPressed() && this.hasPartyMembers()) {
|
||||
this.onPress()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player has any party members, and
|
||||
*
|
||||
* - Handles the starter selection if the player doesn't have any party members.
|
||||
* - Shows a message if the player initially skipped the starter selection.
|
||||
*/
|
||||
private fun hasPartyMembers(): Boolean {
|
||||
val havePokemon = CobblemonClient.storage.myParty.slots.any { it != null }
|
||||
val starterSelected = CobblemonClient.clientPlayerData.starterSelected
|
||||
@@ -42,6 +52,18 @@ abstract class CobblemonPartyLockedKeyBinding(
|
||||
RequestStarterScreenPacket().sendToServer()
|
||||
}
|
||||
return false
|
||||
} else if (!startersLocked && !starterSelected && havePokemon) {
|
||||
if (!skippedStarterSelectionMessageShown) {
|
||||
MinecraftClient.getInstance().player?.sendMessage(
|
||||
lang(
|
||||
"ui.starter.skippedchoosing",
|
||||
SummaryBinding.boundKey().localizedText
|
||||
).yellow(), false
|
||||
)
|
||||
/** Only show the info message about skipping the selection once per MC instance */
|
||||
skippedStarterSelectionMessageShown = true
|
||||
}
|
||||
return true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -10,4 +10,5 @@ package com.cobblemon.mod.common.client.keybind
|
||||
|
||||
object KeybindCategories {
|
||||
const val COBBLEMON_CATEGORY = "key.cobblemon.categories.cobblemon"
|
||||
const val COBBLEMON_DEBUG_CATEGORY = "key.cobblemon.categories.cobblemon.debug"
|
||||
}
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.keybind.keybinds
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.keybind.CobblemonKeyBinding
|
||||
import com.cobblemon.mod.common.client.keybind.KeybindCategories
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.client.util.InputUtil
|
||||
import net.minecraft.text.Text
|
||||
|
||||
object DebugKeybindings {
|
||||
val keybindings = listOf(
|
||||
ScaleUpKeybinding(),
|
||||
ScaleDownKeybinding(),
|
||||
TranslateLeftKeybinding(),
|
||||
TranslateRightKeybinding(),
|
||||
TranslateUpKeybinding(),
|
||||
TranslateDownKeybinding(),
|
||||
PrintModelSettingsKeybinding()
|
||||
)
|
||||
class ScaleUpKeybinding(): CobblemonKeyBinding(
|
||||
"key.cobblemon.scaleportraitup",
|
||||
InputUtil.Type.KEYSYM,
|
||||
InputUtil.GLFW_KEY_EQUAL,
|
||||
KeybindCategories.COBBLEMON_DEBUG_CATEGORY
|
||||
) {
|
||||
override fun onPress() {
|
||||
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
|
||||
if (currentlySelectedPokemon != null) {
|
||||
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, currentlySelectedPokemon.aspects)
|
||||
model.portraitScale += 0.01F
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
class ScaleDownKeybinding(): CobblemonKeyBinding(
|
||||
"key.cobblemon.scaleportraitdown",
|
||||
InputUtil.Type.KEYSYM,
|
||||
InputUtil.GLFW_KEY_MINUS,
|
||||
KeybindCategories.COBBLEMON_DEBUG_CATEGORY
|
||||
) {
|
||||
override fun onPress() {
|
||||
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
|
||||
if (currentlySelectedPokemon != null) {
|
||||
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, currentlySelectedPokemon.aspects)
|
||||
model.portraitScale -= 0.01F
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class TranslateUpKeybinding: CobblemonKeyBinding(
|
||||
"key.cobblemon.translateportraitup",
|
||||
InputUtil.Type.KEYSYM,
|
||||
InputUtil.GLFW_KEY_I,
|
||||
KeybindCategories.COBBLEMON_DEBUG_CATEGORY
|
||||
) {
|
||||
override fun onPress() {
|
||||
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
|
||||
if (currentlySelectedPokemon != null) {
|
||||
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, currentlySelectedPokemon.aspects)
|
||||
model.portraitTranslation = model.portraitTranslation.add(0.0, -0.01, 0.0)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
class TranslateDownKeybinding(): CobblemonKeyBinding(
|
||||
"key.cobblemon.translateportraitdown",
|
||||
InputUtil.Type.KEYSYM,
|
||||
InputUtil.GLFW_KEY_K,
|
||||
KeybindCategories.COBBLEMON_DEBUG_CATEGORY
|
||||
) {
|
||||
override fun onPress() {
|
||||
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
|
||||
if (currentlySelectedPokemon != null) {
|
||||
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, currentlySelectedPokemon.aspects)
|
||||
model.portraitTranslation = model.portraitTranslation.add(0.0, 0.01, 0.0)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class TranslateLeftKeybinding(): CobblemonKeyBinding(
|
||||
"key.cobblemon.translateportraitleft",
|
||||
InputUtil.Type.KEYSYM,
|
||||
InputUtil.GLFW_KEY_J,
|
||||
KeybindCategories.COBBLEMON_DEBUG_CATEGORY
|
||||
) {
|
||||
override fun onPress() {
|
||||
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
|
||||
if (currentlySelectedPokemon != null) {
|
||||
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, currentlySelectedPokemon.aspects)
|
||||
model.portraitTranslation = model.portraitTranslation.add(-0.01, 0.0, 0.0)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class TranslateRightKeybinding(): CobblemonKeyBinding(
|
||||
"key.cobblemon.translateportraitright",
|
||||
InputUtil.Type.KEYSYM,
|
||||
InputUtil.GLFW_KEY_L,
|
||||
KeybindCategories.COBBLEMON_DEBUG_CATEGORY
|
||||
) {
|
||||
override fun onPress() {
|
||||
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
|
||||
if (currentlySelectedPokemon != null) {
|
||||
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, currentlySelectedPokemon.aspects)
|
||||
model.portraitTranslation = model.portraitTranslation.add(0.01, 0.0, 0.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PrintModelSettingsKeybinding() : CobblemonKeyBinding(
|
||||
"key.cobblemon.printmodelsettings",
|
||||
InputUtil.Type.KEYSYM,
|
||||
InputUtil.GLFW_KEY_PERIOD,
|
||||
KeybindCategories.COBBLEMON_DEBUG_CATEGORY
|
||||
) {
|
||||
override fun onPress() {
|
||||
val currentlySelectedPokemon = CobblemonClient.storage.myParty.get(CobblemonClient.storage.selectedSlot)
|
||||
if (currentlySelectedPokemon != null) {
|
||||
val model = PokemonModelRepository.getPoser(currentlySelectedPokemon.species.resourceIdentifier, currentlySelectedPokemon.aspects)
|
||||
MinecraftClient.getInstance().player?.sendMessage(Text.of("Portrait Translation: ${model.portraitTranslation}"))
|
||||
MinecraftClient.getInstance().player?.sendMessage(Text.of("Portrait Scale: ${model.portraitScale}"))
|
||||
Cobblemon.LOGGER.info("override var portraitTranslation = Vec3d(${model.portraitTranslation.x}, ${model.portraitTranslation.y}, ${model.portraitTranslation.z})")
|
||||
Cobblemon.LOGGER.info("override var portraitScale = ${model.portraitScale}F")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -40,7 +40,8 @@ object SpawnSnowstormEntityParticleHandler : ClientNetworkPacketHandler<SpawnSno
|
||||
runtime = particleRuntime,
|
||||
sourceVelocity = { entity.velocity },
|
||||
sourceAlive = { !entity.isRemoved },
|
||||
sourceVisible = { !entity.isInvisible }
|
||||
sourceVisible = { !entity.isInvisible },
|
||||
entity = entity
|
||||
)
|
||||
|
||||
storm.spawn()
|
||||
|
||||
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.client.particle
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.getQueryStruct
|
||||
import com.cobblemon.mod.common.api.snowstorm.BedrockParticleEffect
|
||||
import com.cobblemon.mod.common.api.snowstorm.ParticleEmitterAction
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper
|
||||
@@ -42,6 +43,11 @@ class ParticleStorm(
|
||||
): NoRenderParticle(world, matrixWrapper.getOrigin().x, matrixWrapper.getOrigin().y, matrixWrapper.getOrigin().z) {
|
||||
fun spawn() {
|
||||
if (entity != null) {
|
||||
runtime.environment.getQueryStruct()
|
||||
.addFunction("entity_width") { DoubleValue(entity.boundingBox.xLength) }
|
||||
.addFunction("entity_height") { DoubleValue(entity.boundingBox.yLength) }
|
||||
.addFunction("entity_size") { DoubleValue(entity.boundingBox.run { if (xLength > yLength) xLength else yLength }) }
|
||||
.addFunction("entity_radius") { DoubleValue(entity.boundingBox.run { if (xLength > yLength) xLength else yLength } / 2) }
|
||||
// TODO replace with a generified call to if (entity is MoLangEntity) entity.applyVariables(env) or w/e
|
||||
runtime.environment.setSimpleVariable("entity_width", DoubleValue(entity.boundingBox.xLength))
|
||||
runtime.environment.setSimpleVariable("entity_height", DoubleValue(entity.boundingBox.yLength))
|
||||
@@ -67,6 +73,8 @@ class ParticleStorm(
|
||||
// The idea is that some instantaneous particle effects could teeeechnically be over before they start.
|
||||
var hasPlayedOnce = false
|
||||
|
||||
var distanceTravelled = 0F
|
||||
|
||||
companion object {
|
||||
var contextStorm: ParticleStorm? = null
|
||||
}
|
||||
@@ -75,6 +83,7 @@ class ParticleStorm(
|
||||
|
||||
init {
|
||||
runtime.execute(effect.emitter.startExpressions)
|
||||
effect.emitter.creationEvents.forEach { it.trigger(this, null) }
|
||||
}
|
||||
|
||||
override fun getMaxAge(): Int {
|
||||
@@ -84,6 +93,7 @@ class ParticleStorm(
|
||||
override fun markDead() {
|
||||
super.markDead()
|
||||
if (!despawned) {
|
||||
effect.emitter.expirationEvents.forEach { it.trigger(this, null) }
|
||||
despawned = true
|
||||
onDespawn()
|
||||
}
|
||||
@@ -116,6 +126,12 @@ class ParticleStorm(
|
||||
y = pos.y
|
||||
z = pos.z
|
||||
|
||||
val oldDistanceTravelled = distanceTravelled
|
||||
distanceTravelled += Vec3d(x - prevPosX, y - prevPosY, z - prevPosZ).length().toFloat()
|
||||
|
||||
effect.emitter.travelDistanceEvents.check(this, null, oldDistanceTravelled.toDouble(), distanceTravelled.toDouble())
|
||||
effect.emitter.loopingTravelDistanceEvents.forEach { it.check(this, null, oldDistanceTravelled.toDouble(), distanceTravelled.toDouble()) }
|
||||
effect.emitter.eventTimeline.check(this, null, (age - 1) / 20.0, age / 20.0)
|
||||
|
||||
runtime.environment.setSimpleVariable("emitter_random_1", DoubleValue(Random.Default.nextDouble()))
|
||||
runtime.environment.setSimpleVariable("emitter_random_2", DoubleValue(Random.Default.nextDouble()))
|
||||
@@ -137,18 +153,27 @@ class ParticleStorm(
|
||||
}
|
||||
}
|
||||
|
||||
fun spawnParticle() {
|
||||
fun getNextParticleSpawnPosition(): Vec3d {
|
||||
runtime.environment.setSimpleVariable("particle_random_1", DoubleValue(Random.Default.nextDouble()))
|
||||
runtime.environment.setSimpleVariable("particle_random_2", DoubleValue(Random.Default.nextDouble()))
|
||||
runtime.environment.setSimpleVariable("particle_random_3", DoubleValue(Random.Default.nextDouble()))
|
||||
runtime.environment.setSimpleVariable("particle_random_4", DoubleValue(Random.Default.nextDouble()))
|
||||
|
||||
val center = transformPosition(effect.emitter.shape.getCenter(runtime, entity))
|
||||
val newPosition = transformPosition(effect.emitter.shape.getNewParticlePosition(runtime, entity))
|
||||
val initialVelocity = effect.particle.motion.getInitialVelocity(runtime, storm = this, particlePos = newPosition, emitterPos = center)
|
||||
val velocity = initialVelocity
|
||||
return newPosition
|
||||
}
|
||||
|
||||
fun getNextParticleVelocity(nextParticlePosition: Vec3d): Vec3d {
|
||||
val center = transformPosition(effect.emitter.shape.getCenter(runtime, entity))
|
||||
val initialVelocity = effect.particle.motion.getInitialVelocity(runtime, storm = this, particlePos = nextParticlePosition, emitterPos = center)
|
||||
return initialVelocity
|
||||
.multiply(1 / 20.0)
|
||||
.add(if (effect.space.localVelocity) sourceVelocity() else Vec3d.ZERO)
|
||||
}
|
||||
|
||||
fun spawnParticle() {
|
||||
val newPosition = getNextParticleSpawnPosition()
|
||||
val velocity = getNextParticleVelocity(newPosition)
|
||||
|
||||
contextStorm = this
|
||||
world.addParticle(particleEffect, newPosition.x, newPosition.y, newPosition.z, velocity.x, velocity.y, velocity.z)
|
||||
|
||||
@@ -89,6 +89,14 @@ class SnowstormParticle(
|
||||
var viewDirection = Vec3d.ZERO
|
||||
var originPos = Vec3d(storm.getX(), storm.getY(), storm.getZ())
|
||||
|
||||
fun getX() = x
|
||||
fun getY() = y
|
||||
fun getZ() = z
|
||||
|
||||
fun getVelocityX() = velocityX
|
||||
fun getVelocityY() = velocityY
|
||||
fun getVelocityZ() = velocityZ
|
||||
|
||||
fun getSpriteFromAtlas(): Sprite {
|
||||
val atlas = MinecraftClient.getInstance().particleManager.particleAtlasTexture
|
||||
|
||||
@@ -118,6 +126,7 @@ class SnowstormParticle(
|
||||
storm.particles.add(this)
|
||||
gravityStrength = 0F
|
||||
particleTextureSheet = if (invisible) NO_RENDER else PARTICLE_SHEET_TRANSLUCENT
|
||||
storm.effect.particle.creationEvents.forEach { it.trigger(storm, this) }
|
||||
// when (storm.effect.particle.material) {
|
||||
// ParticleMaterial.ALPHA -> ParticleMaterials.ALPHA
|
||||
// ParticleMaterial.OPAQUE -> ParticleMaterials.OPAQUE
|
||||
@@ -180,8 +189,8 @@ class SnowstormParticle(
|
||||
viewDirection = viewDirection
|
||||
)
|
||||
|
||||
val xSize = storm.runtime.resolveDouble(storm.effect.particle.sizeX).toFloat()
|
||||
val ySize = storm.runtime.resolveDouble(storm.effect.particle.sizeY).toFloat()
|
||||
val xSize = storm.runtime.resolveDouble(storm.effect.particle.sizeX).toFloat() / 1.5.toFloat()
|
||||
val ySize = storm.runtime.resolveDouble(storm.effect.particle.sizeY).toFloat() / 1.5.toFloat()
|
||||
|
||||
val particleVertices = arrayOf(
|
||||
Vector3f(-xSize, -ySize, 0.0f),
|
||||
@@ -245,6 +254,7 @@ class SnowstormParticle(
|
||||
angularVelocity += storm.effect.particle.rotation.getAngularAcceleration(storm.runtime, angularVelocity) / 20
|
||||
|
||||
if (age > maxAge || storm.runtime.resolveBoolean(storm.effect.particle.killExpression)) {
|
||||
storm.effect.particle.expirationEvents.forEach { it.trigger(storm, this)}
|
||||
markDead()
|
||||
return
|
||||
} else {
|
||||
@@ -285,6 +295,8 @@ class SnowstormParticle(
|
||||
age++
|
||||
|
||||
this.move(velocityX, velocityY, velocityZ)
|
||||
|
||||
storm.effect.particle.timeline.check(storm, this, (age - 1) / 20.0, age / 20.0)
|
||||
}
|
||||
|
||||
override fun move(dx: Double, dy: Double, dz: Double) {
|
||||
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.block
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBlocks
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.block.entity.DisplayCaseBlockEntity
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.item.PokeBallItem
|
||||
import com.cobblemon.mod.common.item.PokemonItem
|
||||
import net.minecraft.block.HorizontalFacingBlock
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.client.render.OverlayTexture
|
||||
import net.minecraft.client.render.VertexConsumer
|
||||
import net.minecraft.client.render.VertexConsumerProvider
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderer
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory
|
||||
import net.minecraft.client.render.model.json.ModelTransformationMode
|
||||
import net.minecraft.client.util.math.MatrixStack
|
||||
import net.minecraft.item.BannerItem
|
||||
import net.minecraft.item.BedItem
|
||||
import net.minecraft.item.Item
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.item.Items
|
||||
import net.minecraft.nbt.NbtInt
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.util.math.RotationAxis
|
||||
import net.minecraft.world.World
|
||||
|
||||
class DisplayCaseRenderer(ctx: BlockEntityRendererFactory.Context) : BlockEntityRenderer<DisplayCaseBlockEntity> {
|
||||
val coinPouchStack: ItemStack by lazy { ItemStack(CobblemonItems.RELIC_COIN_POUCH).also { it.setSubNbt("CustomModelData", NbtInt.of(1)) } }
|
||||
override fun render(
|
||||
entity: DisplayCaseBlockEntity,
|
||||
tickDelta: Float,
|
||||
matrices: MatrixStack,
|
||||
vertexConsumers: VertexConsumerProvider,
|
||||
light: Int,
|
||||
overlay: Int
|
||||
) {
|
||||
val stack: ItemStack = if (entity.getStack().isOf(CobblemonItems.RELIC_COIN_POUCH)) {
|
||||
coinPouchStack
|
||||
} else {
|
||||
entity.getStack()
|
||||
}
|
||||
val world = entity.world ?: return
|
||||
val posType = getPositioningType(stack, world)
|
||||
val blockState = if (entity.world != null) entity.cachedState
|
||||
else (CobblemonBlocks.DISPLAY_CASE.defaultState.with(HorizontalFacingBlock.FACING, Direction.NORTH))
|
||||
val yRot = if (posType == PositioningType.ITEM_MODEL) blockState.get(HorizontalFacingBlock.FACING).opposite.asRotation()
|
||||
else blockState.get(HorizontalFacingBlock.FACING).asRotation()
|
||||
|
||||
if (stack.item is PokemonItem) {
|
||||
renderPokemon(
|
||||
matrices,
|
||||
vertexConsumers,
|
||||
light,
|
||||
stack,
|
||||
yRot
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
matrices.push()
|
||||
matrices.translate(0.5f, 0.4f, 0.5f)
|
||||
|
||||
matrices.scale(posType.scaleX, posType.scaleY, posType.scaleZ)
|
||||
matrices.translate(posType.transX, posType.transY, posType.transZ)
|
||||
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-yRot))
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(posType.rotY))
|
||||
|
||||
MinecraftClient.getInstance().itemRenderer.renderItem(
|
||||
stack,
|
||||
ModelTransformationMode.GROUND,
|
||||
light,
|
||||
overlay,
|
||||
matrices,
|
||||
vertexConsumers,
|
||||
entity.world,
|
||||
0
|
||||
)
|
||||
|
||||
matrices.pop()
|
||||
|
||||
}
|
||||
|
||||
private fun renderPokemon(
|
||||
matrices: MatrixStack,
|
||||
vertexConsumers: VertexConsumerProvider,
|
||||
light: Int,
|
||||
stack: ItemStack,
|
||||
yRot: Float
|
||||
) {
|
||||
val item = stack.item as? PokemonItem ?: return
|
||||
val pokemon = item.asPokemon(stack) ?: return
|
||||
val model = PokemonModelRepository.getPoser(pokemon.species.resourceIdentifier, pokemon.aspects)
|
||||
val renderLayer = model.getLayer(PokemonModelRepository.getTexture(pokemon.species.resourceIdentifier, pokemon.aspects, 0F))
|
||||
val tint = item.tint(stack)
|
||||
val vertexConsumer: VertexConsumer = vertexConsumers.getBuffer(renderLayer)
|
||||
val scale = 0.25f
|
||||
|
||||
matrices.push()
|
||||
matrices.scale(1f, -1f, -1f)
|
||||
matrices.translate(0.5f, -0.69f, -0.5f)
|
||||
matrices.scale(scale, scale, scale)
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(yRot))
|
||||
|
||||
model.setupAnimStateless(PoseType.PROFILE)
|
||||
|
||||
model.withLayerContext(vertexConsumers, null, PokemonModelRepository.getLayers(pokemon.species.resourceIdentifier, pokemon.aspects)) {
|
||||
model.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV, tint.x, tint.y, tint.z, tint.w)
|
||||
}
|
||||
|
||||
matrices.pop()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val mobHeads = listOf<Item>(
|
||||
Items.SKELETON_SKULL,
|
||||
Items.WITHER_SKELETON_SKULL,
|
||||
Items.ZOMBIE_HEAD,
|
||||
Items.PIGLIN_HEAD,
|
||||
Items.PLAYER_HEAD,
|
||||
Items.DRAGON_HEAD,
|
||||
Items.CREEPER_HEAD
|
||||
)
|
||||
|
||||
private fun getPositioningType(stack: ItemStack, world: World) = when {
|
||||
mobHeads.contains(stack.item) -> PositioningType.MOB_HEAD
|
||||
stack.item is BedItem -> PositioningType.BED
|
||||
stack.item is BannerItem -> PositioningType.BANNER
|
||||
stack.item is PokeBallItem -> PositioningType.POKE_BALL
|
||||
stack.item == CobblemonItems.RELIC_COIN_POUCH -> PositioningType.COIN_POUCH
|
||||
stack.item == CobblemonItems.PASTURE -> PositioningType.PASTURE
|
||||
stack.item == CobblemonItems.POKEMON_MODEL -> PositioningType.ITEM_MODEL
|
||||
stack.item == Items.SHIELD -> PositioningType.SHIELD
|
||||
stack.item == Items.DECORATED_POT -> PositioningType.MOB_HEAD
|
||||
MinecraftClient.getInstance().itemRenderer.getModel(stack, world, null, 0).hasDepth() -> PositioningType.BLOCK_MODEL
|
||||
else -> PositioningType.ITEM_MODEL
|
||||
}
|
||||
}
|
||||
|
||||
private enum class PositioningType(
|
||||
val scaleX: Float, val scaleY: Float, val scaleZ: Float,
|
||||
val transX: Float, val transY: Float, val transZ: Float,
|
||||
val rotY: Float = 0f
|
||||
) {
|
||||
POKE_BALL(1f, 1f, 1f, 0f, 0.04f, 0f),
|
||||
BLOCK_MODEL(1f, 1f, 1f, 0f, -0.15f, 0f),
|
||||
ITEM_MODEL(1f, 1f, 1f, 0f, 0.04f, 0f),
|
||||
BED(1f, 1f, 1f, 0f, -0.02f, 0f),
|
||||
BANNER(1f, 1f, 1f, 0f, -0.02f, 0f, 180f),
|
||||
MOB_HEAD(1f, 1f, 1f, 0f, -0.025f, 0f, 180f),
|
||||
SHIELD(1f, 1f, 1f, 0f, -0.045f, 0f, 180f),
|
||||
PASTURE(1f, 1f, 1f, 0f, 0.0375f, 0f),
|
||||
COIN_POUCH(1f, 1f, 1f, 0f, 0.415f, 0f)
|
||||
}
|
||||
}
|
||||
+16
-6
@@ -19,8 +19,10 @@ import net.minecraft.client.render.block.entity.BlockEntityRenderer
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory
|
||||
import net.minecraft.client.render.model.json.ModelTransformationMode
|
||||
import net.minecraft.client.util.math.MatrixStack
|
||||
import net.minecraft.state.property.DirectionProperty
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.util.math.RotationAxis
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class FossilAnalyzerRenderer(ctx: BlockEntityRendererFactory.Context) : BlockEntityRenderer<FossilAnalyzerBlockEntity> {
|
||||
|
||||
@@ -34,21 +36,29 @@ class FossilAnalyzerRenderer(ctx: BlockEntityRendererFactory.Context) : BlockEnt
|
||||
) {
|
||||
val blockState = if (entity.world != null) entity.cachedState
|
||||
else (CobblemonBlocks.FOSSIL_ANALYZER.defaultState.with(HorizontalFacingBlock.FACING, Direction.SOUTH) as BlockState)
|
||||
val yRot = blockState.get(HorizontalFacingBlock.FACING).asRotation()
|
||||
//We shouldnt have to do any complex rendering when the block isn't a multiblock
|
||||
// We shouldn't have to do any complex rendering when the block isn't a multiblock
|
||||
if (entity.multiblockStructure == null) {
|
||||
return
|
||||
}
|
||||
val direction = blockState.get(HorizontalFacingBlock.FACING)
|
||||
val yRot = direction.asRotation() + if(direction == Direction.WEST || direction == Direction.EAST) 180F else 0F
|
||||
val struct = entity.multiblockStructure as FossilMultiblockStructure
|
||||
|
||||
struct.fossilInventory.forEachIndexed { index, fossilStack ->
|
||||
matrices.push()
|
||||
|
||||
matrices.translate(0.5, 0.4 + (index * 0.1F), 0.55)
|
||||
matrices.scale(0.7F, 0.7F, 0.7F)
|
||||
|
||||
val dirOffset = when (direction) {
|
||||
Direction.NORTH -> Vec3d(0.0, 0.0, 0.05)
|
||||
Direction.SOUTH -> Vec3d(0.0, 0.0, -0.05)
|
||||
Direction.EAST -> Vec3d(-0.05, 0.0, 0.0)
|
||||
Direction.WEST -> Vec3d(0.05, 0.0, 0.0)
|
||||
else -> Vec3d.ZERO
|
||||
}
|
||||
matrices.translate(0.5 + dirOffset.x,0.4 + (index * 0.1) + dirOffset.y, 0.5 + dirOffset.z)
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(yRot))
|
||||
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(180F))
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-yRot))
|
||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90F))
|
||||
matrices.scale(0.7F, 0.7F, 0.7F)
|
||||
|
||||
MinecraftClient.getInstance().itemRenderer.renderItem(fossilStack, ModelTransformationMode.NONE, light, overlay, matrices, vertexConsumers, entity.world, 0)
|
||||
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ class RestorationTankRenderer(ctx: BlockEntityRendererFactory.Context) : BlockEn
|
||||
|
||||
val fluidModel = if (struct.isRunning()) FLUID_MODELS[8]
|
||||
else if (struct.createdPokemon != null) FLUID_MODELS[7]
|
||||
else FLUID_MODELS[fillLevel-1]
|
||||
else FLUID_MODELS[fillLevel.coerceAtMost(FLUID_MODELS.size - 1) - 1]
|
||||
fluidModel.getQuads(entity.cachedState, null, entity.world?.random).forEach { quad ->
|
||||
transparentBuffer?.quad(matrices.peek(), quad, 0.75f, 0.75f, 0.75f, light, OverlayTexture.DEFAULT_UV)
|
||||
}
|
||||
|
||||
+6
-7
@@ -18,7 +18,6 @@ import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.getQueryStruct
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.scheduling.afterOnClient
|
||||
import com.cobblemon.mod.common.client.ClientMoLangFunctions.setupClient
|
||||
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper
|
||||
@@ -46,6 +45,7 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.getDoubleOrNull
|
||||
import com.cobblemon.mod.common.util.getStringOrNull
|
||||
import com.cobblemon.mod.common.util.plus
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.client.render.OverlayTexture
|
||||
import net.minecraft.client.render.RenderLayer
|
||||
@@ -697,6 +697,7 @@ abstract class PoseableEntityModel<T : Entity>(
|
||||
val portion = (state.animationSeconds - primaryAnimation.started) / primaryAnimation.duration
|
||||
state.primaryOverridePortion = 1 - primaryAnimation.curve(portion)
|
||||
if (!primaryAnimation.run(entity, this, state, limbSwing, limbSwingAmount, ageInTicks, headYaw, headPitch, 1 - state.primaryOverridePortion)) {
|
||||
primaryAnimation.afterAction.accept(Unit)
|
||||
state.primaryAnimation = null
|
||||
state.primaryOverridePortion = 1F
|
||||
}
|
||||
@@ -715,6 +716,7 @@ abstract class PoseableEntityModel<T : Entity>(
|
||||
//This is used to set additional entity type specific context
|
||||
open fun setupEntityTypeContext(entity: T?) {}
|
||||
|
||||
//Called by LivingEntityRenderer's render method before calling model.render (which is this.render in this case)
|
||||
override fun setAngles(
|
||||
entity: T,
|
||||
limbSwing: Float,
|
||||
@@ -745,19 +747,16 @@ abstract class PoseableEntityModel<T : Entity>(
|
||||
curve = { 1F }
|
||||
)
|
||||
state.addPrimaryAnimation(primaryAnimation)
|
||||
afterOnClient(seconds = primaryAnimation.duration) {
|
||||
primaryAnimation.afterAction += {
|
||||
state.setPose(desirablePose.poseName)
|
||||
if (state.primaryAnimation == primaryAnimation) {
|
||||
state.primaryAnimation = null
|
||||
}
|
||||
}
|
||||
} else if (transition != null) {
|
||||
val animation = transition(previousPose, desirablePose)
|
||||
val primaryAnimation = if (animation is PrimaryAnimation) animation else PrimaryAnimation(animation, curve = { 1F })
|
||||
state.addPrimaryAnimation(primaryAnimation)
|
||||
afterOnClient(seconds = primaryAnimation.duration) {
|
||||
primaryAnimation.afterAction += {
|
||||
state.setPose(desirablePose.poseName)
|
||||
}
|
||||
state.addPrimaryAnimation(primaryAnimation)
|
||||
} else {
|
||||
state.setPose(poses.values.first { desirablePoseType in it.poseTypes && (it.condition == null || (entity != null && it.condition.invoke(entity))) }.poseName)
|
||||
}
|
||||
|
||||
+8
-1
@@ -56,6 +56,8 @@ import net.minecraft.util.math.Vec3d
|
||||
* handling all the state for an entity's model, and needs to be conscious of the fact that the
|
||||
* model may change without this state changing.
|
||||
*
|
||||
* This also handles setting up the molang runtime that animations have access to
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since December 5th, 2021
|
||||
*/
|
||||
@@ -164,6 +166,11 @@ abstract class PoseableEntityState<T : Entity> : Schedulable {
|
||||
val previousAge = age
|
||||
updateAge(age + 1)
|
||||
runEffects(entity, previousAge, age)
|
||||
val primaryAnimation = primaryAnimation ?: return
|
||||
if (primaryAnimation.started + primaryAnimation.duration <= animationSeconds) {
|
||||
this.primaryAnimation = null
|
||||
primaryAnimation.afterAction.accept(Unit)
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun updatePartialTicks(partialTicks: Float)
|
||||
@@ -268,7 +275,7 @@ abstract class PoseableEntityState<T : Entity> : Schedulable {
|
||||
val pose = currentPose?.let(model::getPose)
|
||||
allStatefulAnimations.forEach { it.applyEffects(entity, this, previousSeconds, currentSeconds) }
|
||||
primaryAnimation?.animation?.applyEffects(entity, this, previousSeconds, currentSeconds)
|
||||
pose?.idleAnimations?.filter { shouldIdleRun(it, 0.5F) }
|
||||
pose?.idleAnimations?.filter { shouldIdleRun(it, 0.5F) }?.forEach { it.applyEffects(entity, this, previousSeconds, currentSeconds) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityMo
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.ModelFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.WaveFunction
|
||||
import java.util.function.Consumer
|
||||
import net.minecraft.entity.Entity
|
||||
|
||||
/**
|
||||
@@ -39,6 +40,7 @@ class PrimaryAnimation<T : Entity>(
|
||||
): StatefulAnimation<T, ModelFrame> {
|
||||
var started = -1F
|
||||
override val duration: Float = animation.duration
|
||||
var afterAction: Consumer<Unit> = Consumer { }
|
||||
|
||||
override fun run(
|
||||
entity: T?,
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import net.minecraft.entity.Entity
|
||||
|
||||
/**
|
||||
* An animation that can run without an entity associated. These are
|
||||
* locked to a specific frame, and CAN be given an entity along with
|
||||
* locked to a specific [ModelFrame], and CAN be given an entity along with
|
||||
* limb swing and age information, but might not.
|
||||
*
|
||||
* @author Hiroku
|
||||
|
||||
+2
-2
@@ -32,11 +32,11 @@ class BlockEntityModel(val root: Bone) : PoseableEntityModel<Entity>() {
|
||||
)
|
||||
|
||||
closedPose.transitions[openPose.poseName] = { _, _ ->
|
||||
bedrockStateful("gilded_chest", "opening").andThen { _, state -> state.setPose(openPose.poseName) }
|
||||
bedrockStateful("gilded_chest", "opening")
|
||||
}
|
||||
|
||||
openPose.transitions[closedPose.poseName] = { _, _ ->
|
||||
bedrockStateful("gilded_chest", "closing").andThen { _, state -> state.setPose(closedPose.poseName) }
|
||||
bedrockStateful("gilded_chest", "closing")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -51,8 +51,8 @@ class AncientPokeBallModel(root: ModelPart) : PokeBallModel(root), PokeBallFrame
|
||||
transformTicks = 0
|
||||
)
|
||||
|
||||
shut.transitions[open.poseName] = { _, _ -> bedrockStateful("ancient_poke_ball", "open").andThen { entity, state -> state.setPose(open.poseName) } }
|
||||
open.transitions[shut.poseName] = { _, _ -> bedrockStateful("ancient_poke_ball", "shut").andThen { entity, state -> state.setPose(shut.poseName) } }
|
||||
shut.transitions[open.poseName] = { _, _ -> bedrockStateful("ancient_poke_ball", "open") }
|
||||
open.transitions[shut.poseName] = { _, _ -> bedrockStateful("ancient_poke_ball", "shut") }
|
||||
midair.transitions[open.poseName] = shut.transitions[open.poseName]!!
|
||||
}
|
||||
}
|
||||
|
||||
+9
-5
@@ -91,14 +91,18 @@ class JsonPokemonPoseableModel(override val rootPart: Bone) : PokemonPoseableMod
|
||||
@SerializedName("profileTranslation")
|
||||
private val _profileTranslation: Vec3d? = null
|
||||
|
||||
override val portraitScale
|
||||
//Some weirdness going on here, vars have to be initialized, gson doesn't like multiple fields with the same name
|
||||
@Transient
|
||||
override var portraitScale = 1F
|
||||
get() = _portraitScale ?: 1F
|
||||
override val portraitTranslation
|
||||
@Transient
|
||||
override var portraitTranslation = Vec3d.ZERO
|
||||
get() = _portraitTranslation ?: Vec3d(0.0, 0.0, 0.0)
|
||||
|
||||
override val profileScale
|
||||
@Transient
|
||||
override var profileScale = 1F
|
||||
get() = _profileScale ?: 1F
|
||||
override val profileTranslation
|
||||
@Transient
|
||||
override var profileTranslation = Vec3d.ZERO
|
||||
get() = _profileTranslation ?: Vec3d(0.0, 0.0, 0.0)
|
||||
|
||||
|
||||
|
||||
+4
-4
@@ -56,14 +56,14 @@ abstract class PokemonPoseableModel : PoseableEntityModel<PokemonEntity>() {
|
||||
}
|
||||
|
||||
@Transient
|
||||
open val portraitScale: Float = 1F
|
||||
open var portraitScale: Float = 1F
|
||||
@Transient
|
||||
open val portraitTranslation: Vec3d = Vec3d.ZERO
|
||||
open var portraitTranslation: Vec3d = Vec3d.ZERO
|
||||
|
||||
@Transient
|
||||
open val profileScale: Float = 1F
|
||||
open var profileScale: Float = 1F
|
||||
@Transient
|
||||
open val profileTranslation: Vec3d = Vec3d.ZERO
|
||||
open var profileTranslation: Vec3d = Vec3d.ZERO
|
||||
|
||||
open fun getFaintAnimation(
|
||||
pokemonEntity: PokemonEntity,
|
||||
|
||||
+4
-4
@@ -24,11 +24,11 @@ class AbraModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("abra")
|
||||
override val head = getPart("head")
|
||||
|
||||
override val portraitScale = 1.8F
|
||||
override val portraitTranslation = Vec3d(0.0, 0.2, 0.0)
|
||||
override var portraitScale = 1.8F
|
||||
override var portraitTranslation = Vec3d(0.0, 0.2, 0.0)
|
||||
|
||||
override val profileScale = 0.85F
|
||||
override val profileTranslation = Vec3d(0.0, 0.7, 0.0)
|
||||
override var profileScale = 0.85F
|
||||
override var profileTranslation = Vec3d(0.0, 0.7, 0.0)
|
||||
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walking: PokemonPose
|
||||
|
||||
+4
-4
@@ -20,11 +20,11 @@ class AerodactylModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("aerodactyl")
|
||||
override val head = getPart("head")
|
||||
|
||||
override val portraitScale = 1.9F
|
||||
override val portraitTranslation = Vec3d(-1.0, -0.65, 0.0)
|
||||
override var portraitScale = 1.9F
|
||||
override var portraitTranslation = Vec3d(-1.0, -0.65, 0.0)
|
||||
|
||||
override val profileScale = 0.55F
|
||||
override val profileTranslation = Vec3d(0.0, 0.55, 0.0)
|
||||
override var profileScale = 0.55F
|
||||
override var profileTranslation = Vec3d(0.0, 0.55, 0.0)
|
||||
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
|
||||
+4
-4
@@ -30,11 +30,11 @@ class AlakazamModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bipe
|
||||
override val leftLeg = getPart("left_upper_leg")
|
||||
override val rightLeg = getPart("right_upper_leg")
|
||||
|
||||
override val portraitScale = 1.75F
|
||||
override val portraitTranslation = Vec3d(-0.25, 0.85, 0.0)
|
||||
override var portraitScale = 1.75F
|
||||
override var portraitTranslation = Vec3d(-0.25, 0.85, 0.0)
|
||||
|
||||
override val profileScale = 0.73F
|
||||
override val profileTranslation = Vec3d(0.0, 0.65, 0.0)
|
||||
override var profileScale = 0.73F
|
||||
override var profileTranslation = Vec3d(0.0, 0.65, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
|
||||
+4
-4
@@ -29,11 +29,11 @@ class ArbokModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("arbok")
|
||||
override val head = getPart("head_ai")
|
||||
|
||||
override val portraitScale = 1.5F
|
||||
override val portraitTranslation = Vec3d(-0.4, 1.0, 0.0)
|
||||
override var portraitScale = 1.5F
|
||||
override var portraitTranslation = Vec3d(-0.4, 1.0, 0.0)
|
||||
|
||||
override val profileScale = 0.67F
|
||||
override val profileTranslation = Vec3d(0.0, 0.7, 0.0)
|
||||
override var profileScale = 0.67F
|
||||
override var profileTranslation = Vec3d(0.0, 0.7, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
|
||||
+4
-4
@@ -27,11 +27,11 @@ class ArcanineModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Quad
|
||||
override val hindLeftLeg = getPart("leg_back_left")
|
||||
override val hindRightLeg = getPart("leg_back_right")
|
||||
|
||||
override val portraitScale = 1.5F
|
||||
override val portraitTranslation = Vec3d(-0.4, 0.7, 0.0)
|
||||
override var portraitScale = 1.5F
|
||||
override var portraitTranslation = Vec3d(-0.4, 0.7, 0.0)
|
||||
|
||||
override val profileScale = 0.76F
|
||||
override val profileTranslation = Vec3d(0.0, 0.57, 0.0)
|
||||
override var profileScale = 0.76F
|
||||
override var profileTranslation = Vec3d(0.0, 0.57, 0.0)
|
||||
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
|
||||
+4
-4
@@ -31,11 +31,11 @@ class ArticunoModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bipe
|
||||
override val leftWing = getPart("leftwing")
|
||||
override val rightWing = getPart("rightwing")
|
||||
|
||||
override val portraitScale = 2.8F
|
||||
override val portraitTranslation = Vec3d(-0.35, 0.6, 0.0)
|
||||
override var portraitScale = 2.8F
|
||||
override var portraitTranslation = Vec3d(-0.35, 0.6, 0.0)
|
||||
|
||||
override val profileScale = 0.85F
|
||||
override val profileTranslation = Vec3d(0.0, 0.5, 0.0)
|
||||
override var profileScale = 0.85F
|
||||
override var profileTranslation = Vec3d(0.0, 0.5, 0.0)
|
||||
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
|
||||
+4
-4
@@ -28,11 +28,11 @@ class BeedrillModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BiWi
|
||||
override val leftWing = getPart("wing_left")
|
||||
override val rightWing = getPart("wing_right")
|
||||
|
||||
override val portraitScale = 1.9F
|
||||
override val portraitTranslation = Vec3d(0.05, 0.9, 0.0)
|
||||
override var portraitScale = 1.9F
|
||||
override var portraitTranslation = Vec3d(0.05, 0.9, 0.0)
|
||||
|
||||
override val profileScale = 0.8F
|
||||
override val profileTranslation = Vec3d(-0.1, 0.9, 0.0)
|
||||
override var profileScale = 0.8F
|
||||
override var profileTranslation = Vec3d(-0.1, 0.9, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
|
||||
+4
-4
@@ -21,11 +21,11 @@ class BellsproutModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("bellsprout")
|
||||
override val head = getPart("head")
|
||||
|
||||
override val portraitScale = 2.0F
|
||||
override val portraitTranslation = Vec3d(-0.1, 0.41, 0.0)
|
||||
override var portraitScale = 2.0F
|
||||
override var portraitTranslation = Vec3d(-0.1, 0.41, 0.0)
|
||||
|
||||
override val profileScale = 0.75F
|
||||
override val profileTranslation = Vec3d(0.0, 0.64, 0.0)
|
||||
override var profileScale = 0.75F
|
||||
override var profileTranslation = Vec3d(0.0, 0.64, 0.0)
|
||||
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
|
||||
+4
-4
@@ -27,10 +27,10 @@ class BulbasaurModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Qua
|
||||
override val hindLeftLeg = getPart("leg_back_left")
|
||||
override val hindRightLeg = getPart("leg_back_right")
|
||||
|
||||
override val portraitScale = 2.0F
|
||||
override val portraitTranslation = Vec3d(-0.26, -1.20, 0.0)
|
||||
override val profileScale = 0.9F
|
||||
override val profileTranslation = Vec3d(0.0, 0.4, 0.0)
|
||||
override var portraitScale = 2.0F
|
||||
override var portraitTranslation = Vec3d(-0.26, -1.20, 0.0)
|
||||
override var profileScale = 0.9F
|
||||
override var profileTranslation = Vec3d(0.0, 0.4, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
|
||||
+4
-4
@@ -27,11 +27,11 @@ class ButterfreeModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bi
|
||||
val leftWingBack = getPart("wing_left2")
|
||||
val rightWingBack = getPart("wing_right2")
|
||||
|
||||
override val portraitScale = 2.4F
|
||||
override val portraitTranslation = Vec3d(-0.1, 0.2, 0.0)
|
||||
override var portraitScale = 2.4F
|
||||
override var portraitTranslation = Vec3d(-0.1, 0.2, 0.0)
|
||||
|
||||
override val profileScale = 0.7F
|
||||
override val profileTranslation = Vec3d(0.1, 0.8, 0.0)
|
||||
override var profileScale = 0.7F
|
||||
override var profileTranslation = Vec3d(0.1, 0.8, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
|
||||
|
||||
+4
-4
@@ -25,10 +25,10 @@ class CaterpieModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("caterpie")
|
||||
override val head = getPart("head")
|
||||
|
||||
override val portraitScale = 2.1F
|
||||
override val portraitTranslation = Vec3d(-0.55, -1.55, 0.0)
|
||||
override val profileScale = 0.8F
|
||||
override val profileTranslation = Vec3d(0.0, 0.55, 0.0)
|
||||
override var portraitScale = 2.1F
|
||||
override var portraitTranslation = Vec3d(-0.55, -1.55, 0.0)
|
||||
override var profileScale = 0.8F
|
||||
override var profileTranslation = Vec3d(0.0, 0.55, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
|
||||
+23
-12
@@ -8,13 +8,16 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen1
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BipedWalkAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
@@ -23,17 +26,27 @@ class ChanseyModel(root: ModelPart) : PokemonPoseableModel(), BipedFrame {
|
||||
override val leftLeg = getPart("left_foot")
|
||||
override val rightLeg = getPart("right_foot")
|
||||
|
||||
override val portraitScale = 1.5F
|
||||
override val portraitTranslation = Vec3d(-0.35, 0.3, 0.0)
|
||||
override var portraitScale = 1.5F
|
||||
override var portraitTranslation = Vec3d(-0.35, 0.3, 0.0)
|
||||
|
||||
override val profileScale = 0.8F
|
||||
override val profileTranslation = Vec3d(0.0, 0.55, 0.0)
|
||||
override var profileScale = 0.8F
|
||||
override var profileTranslation = Vec3d(0.0, 0.55, 0.0)
|
||||
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
lateinit var sleep: PokemonPose
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk { bedrockStateful("chansey", "blink")}
|
||||
val blink = quirk { bedrockStateful("chansey", "blink") }
|
||||
|
||||
sleep = registerPose(
|
||||
poseName = "sleep",
|
||||
poseType = PoseType.SLEEP,
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("chansey", "ground_sleep")
|
||||
)
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
@@ -49,15 +62,13 @@ class ChanseyModel(root: ModelPart) : PokemonPoseableModel(), BipedFrame {
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("chansey", "ground_idle"),
|
||||
BipedWalkAnimation(this),
|
||||
//bedrock("chansey", "ground_walk")
|
||||
bedrock("chansey", "ground_walk")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PoseableEntityState<PokemonEntity>
|
||||
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("chansey", "faint") else null
|
||||
override fun getFaintAnimation(
|
||||
pokemonEntity: PokemonEntity,
|
||||
state: PoseableEntityState<PokemonEntity>
|
||||
) = bedrockStateful("chansey", "faint")
|
||||
}
|
||||
+4
-4
@@ -34,11 +34,11 @@ class CharizardModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bip
|
||||
override val leftWing = getPart("wing_left")
|
||||
override val rightWing = getPart("wing_right")
|
||||
|
||||
override val portraitScale = 1.9F
|
||||
override val portraitTranslation = Vec3d(-0.5, 1.4, 0.0)
|
||||
override var portraitScale = 1.9F
|
||||
override var portraitTranslation = Vec3d(-0.5, 1.4, 0.0)
|
||||
|
||||
override val profileScale = 0.55F
|
||||
override val profileTranslation = Vec3d(0.05, 0.93, 0.0)
|
||||
override var profileScale = 0.55F
|
||||
override var profileTranslation = Vec3d(0.05, 0.93, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
|
||||
+4
-4
@@ -31,11 +31,11 @@ class CharmanderModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bi
|
||||
override val rightLeg = getPart("leg_right")
|
||||
override val leftLeg = getPart("leg_left")
|
||||
|
||||
override val portraitScale = 2.2F
|
||||
override val portraitTranslation = Vec3d(-0.1, -0.1, 0.0)
|
||||
override var portraitScale = 2.2F
|
||||
override var portraitTranslation = Vec3d(-0.1, -0.1, 0.0)
|
||||
|
||||
override val profileScale = 0.71F
|
||||
override val profileTranslation = Vec3d(0.0, 0.72, 0.0)
|
||||
override var profileScale = 0.71F
|
||||
override var profileTranslation = Vec3d(0.0, 0.72, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
|
||||
+4
-4
@@ -29,11 +29,11 @@ class CharmeleonModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bi
|
||||
override val rightLeg = getPart("leg_right")
|
||||
override val leftLeg = getPart("leg_left")
|
||||
|
||||
override val portraitScale = 1.9F
|
||||
override val portraitTranslation = Vec3d(-0.16, 0.55, 0.0)
|
||||
override var portraitScale = 1.9F
|
||||
override var portraitTranslation = Vec3d(-0.16, 0.55, 0.0)
|
||||
|
||||
override val profileScale = 0.65F
|
||||
override val profileTranslation = Vec3d(0.0, 0.79, 0.0)
|
||||
override var profileScale = 0.65F
|
||||
override var profileTranslation = Vec3d(0.0, 0.79, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
|
||||
+4
-4
@@ -23,11 +23,11 @@ import net.minecraft.util.math.Vec3d
|
||||
class ClefableModel(root: ModelPart) : PokemonPoseableModel() {
|
||||
override val rootPart = root.registerChildWithAllChildren("clefable")
|
||||
|
||||
override val portraitScale = 2.0F
|
||||
override val portraitTranslation = Vec3d(-0.1, -0.7, 0.0)
|
||||
override var portraitScale = 2.0F
|
||||
override var portraitTranslation = Vec3d(-0.1, -0.7, 0.0)
|
||||
|
||||
override val profileScale = 1.15F
|
||||
override val profileTranslation = Vec3d(0.0, 0.02, 0.0)
|
||||
override var profileScale = 1.15F
|
||||
override var profileTranslation = Vec3d(0.0, 0.02, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
|
||||
+4
-4
@@ -23,11 +23,11 @@ import net.minecraft.util.math.Vec3d
|
||||
class ClefairyModel(root: ModelPart) : PokemonPoseableModel() {
|
||||
override val rootPart = root.registerChildWithAllChildren("clefairy")
|
||||
|
||||
override val portraitScale = 2.0F
|
||||
override val portraitTranslation = Vec3d(0.0, -1.0, 0.0)
|
||||
override var portraitScale = 2.0F
|
||||
override var portraitTranslation = Vec3d(0.0, -1.0, 0.0)
|
||||
|
||||
override val profileScale = 1.1F
|
||||
override val profileTranslation = Vec3d(0.0, 0.08, 0.0)
|
||||
override var profileScale = 1.1F
|
||||
override var profileTranslation = Vec3d(0.0, 0.08, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
|
||||
+4
-4
@@ -19,11 +19,11 @@ import net.minecraft.util.math.Vec3d
|
||||
class CloysterModel(root: ModelPart) : PokemonPoseableModel() {
|
||||
override val rootPart = root.registerChildWithAllChildren("cloyster")
|
||||
|
||||
override val portraitScale = 2.0F
|
||||
override val portraitTranslation = Vec3d(-0.25, -0.85, 0.0)
|
||||
override var portraitScale = 2.0F
|
||||
override var portraitTranslation = Vec3d(-0.25, -0.85, 0.0)
|
||||
|
||||
override val profileScale = 0.9F
|
||||
override val profileTranslation = Vec3d(0.0, 0.37, 0.0)
|
||||
override var profileScale = 0.9F
|
||||
override var profileTranslation = Vec3d(0.0, 0.37, 0.0)
|
||||
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
|
||||
+12
-8
@@ -23,26 +23,29 @@ class CuboneModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BipedF
|
||||
override val rootPart = root.registerChildWithAllChildren("cubone")
|
||||
override val head = getPart("head")
|
||||
|
||||
override val leftLeg = getPart("leftleg")
|
||||
override val rightLeg = getPart("rightleg")
|
||||
override val leftLeg = getPart("left_leg")
|
||||
override val rightLeg = getPart("right_leg")
|
||||
|
||||
override val portraitScale = 2.0F
|
||||
override val portraitTranslation = Vec3d(0.1, -0.7, 0.0)
|
||||
override var portraitScale = 2.0F
|
||||
override var portraitTranslation = Vec3d(0.1, -0.7, 0.0)
|
||||
|
||||
override val profileScale = 1.0F
|
||||
override val profileTranslation = Vec3d(0.0, 0.25, 0.0)
|
||||
override var profileScale = 1.0F
|
||||
override var profileTranslation = Vec3d(0.0, 0.25, 0.0)
|
||||
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk { bedrockStateful("cubone", "blink") }
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("cubone", "ground_idle")
|
||||
bedrock("cubone", "idle")
|
||||
)
|
||||
)
|
||||
|
||||
@@ -50,10 +53,11 @@ class CuboneModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BipedF
|
||||
poseName = "walk",
|
||||
poseTypes = MOVING_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
BipedWalkAnimation(this, periodMultiplier = 1.1F, amplitudeMultiplier = 1.15f),
|
||||
singleBoneLook(),
|
||||
bedrock("cubone", "ground_idle")
|
||||
bedrock("cubone", "idle")
|
||||
//bedrock("cubone", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
+4
-4
@@ -21,11 +21,11 @@ class DewgongModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("dewgong")
|
||||
override val head = getPart("head")
|
||||
|
||||
override val portraitScale = 2.5F
|
||||
override val portraitTranslation = Vec3d(-0.6, -2.0, 0.0)
|
||||
override var portraitScale = 2.5F
|
||||
override var portraitTranslation = Vec3d(-0.6, -2.0, 0.0)
|
||||
|
||||
override val profileScale = 1.1F
|
||||
override val profileTranslation = Vec3d(0.0, 0.0, 0.0)
|
||||
override var profileScale = 1.1F
|
||||
override var profileTranslation = Vec3d(0.0, 0.0, 0.0)
|
||||
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var float: PokemonPose
|
||||
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen1
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class DiglettAlolanModel(root: ModelPart) : PokemonPoseableModel() {
|
||||
override val rootPart = root.registerChildWithAllChildren("diglett_alolan")
|
||||
|
||||
override var portraitScale = 1.8F
|
||||
override var portraitTranslation = Vec3d(-0.06, -0.86, 0.0)
|
||||
|
||||
override var profileScale = 0.9F
|
||||
override var profileTranslation = Vec3d(0.0, 0.32, 0.0)
|
||||
|
||||
lateinit var stand: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
// lateinit var battleidle: PokemonPose
|
||||
// lateinit var sleep: PokemonPose
|
||||
|
||||
// override val cryAnimation = CryProvider { _, _ -> bedrockStateful("diglett_alolan", "cry") }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk { bedrockStateful("diglett_alolan", "blink")}
|
||||
// val quirk = quirk { bedrockStateful("diglett_alolan", "quirk_idle")}
|
||||
|
||||
// sleep = registerPose(
|
||||
// poseName = "sleep",
|
||||
// poseType = PoseType.SLEEP,
|
||||
// idleAnimations = arrayOf(bedrock("diglett_alolan", "sleep"))
|
||||
// )
|
||||
|
||||
stand = registerPose(
|
||||
poseName = "stand",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(bedrock("diglett_alolan", "ground_idle"))
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = MOVING_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(bedrock("diglett_alolan", "ground_idle"))
|
||||
)
|
||||
|
||||
// battleidle = registerPose(
|
||||
// poseName = "battleidle",
|
||||
// poseTypes = STATIONARY_POSES,
|
||||
// quirks = arrayOf(blink),
|
||||
// idleAnimations = arrayOf(bedrock("diglett_alolan", "battle_idle"))
|
||||
// )
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PoseableEntityState<PokemonEntity>
|
||||
// ) = bedrockStateful("diglett_alolan", "faint")
|
||||
}
|
||||
+25
-10
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen1
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
@@ -22,35 +23,49 @@ import net.minecraft.util.math.Vec3d
|
||||
class DiglettModel(root: ModelPart) : PokemonPoseableModel() {
|
||||
override val rootPart = root.registerChildWithAllChildren("diglett")
|
||||
|
||||
override val portraitScale = 1.8F
|
||||
override val portraitTranslation = Vec3d(0.05, -1.0, 0.0)
|
||||
override var portraitScale = 1.8F
|
||||
override var portraitTranslation = Vec3d(-0.06, -0.86, 0.0)
|
||||
|
||||
override val profileScale = 0.9F
|
||||
override val profileTranslation = Vec3d(0.0, 0.15, 0.0)
|
||||
override var profileScale = 0.9F
|
||||
override var profileTranslation = Vec3d(0.0, 0.32, 0.0)
|
||||
|
||||
lateinit var stand: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
lateinit var battleidle: PokemonPose
|
||||
lateinit var sleep: PokemonPose
|
||||
|
||||
override val cryAnimation = CryProvider { _, _ -> bedrockStateful("diglett", "cry") }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk { bedrockStateful("diglett", "blink")}
|
||||
val quirk = quirk { bedrockStateful("diglett", "quirk_idle")}
|
||||
|
||||
sleep = registerPose(
|
||||
poseName = "sleep",
|
||||
poseType = PoseType.SLEEP,
|
||||
idleAnimations = arrayOf(bedrock("diglett", "sleep"))
|
||||
)
|
||||
|
||||
stand = registerPose(
|
||||
poseName = "stand",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
quirks = arrayOf(blink, quirk),
|
||||
idleAnimations = arrayOf(bedrock("diglett", "ground_idle"))
|
||||
)
|
||||
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
idleAnimations = arrayOf(bedrock("diglett", "sleep"))
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = MOVING_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(bedrock("diglett", "ground_walk"))
|
||||
)
|
||||
|
||||
battleidle = registerPose(
|
||||
poseName = "battleidle",
|
||||
poseTypes = STATIONARY_POSES,
|
||||
quirks = arrayOf(blink, quirk),
|
||||
idleAnimations = arrayOf(bedrock("diglett", "battle_idle"))
|
||||
)
|
||||
}
|
||||
|
||||
override fun getFaintAnimation(
|
||||
|
||||
+4
-4
@@ -23,11 +23,11 @@ import net.minecraft.util.math.Vec3d
|
||||
class DittoModel(root: ModelPart) : PokemonPoseableModel() {
|
||||
override val rootPart = root.registerChildWithAllChildren("ditto")
|
||||
|
||||
override val portraitScale = 3.2F
|
||||
override val portraitTranslation = Vec3d(0.0, -2.2, 0.0)
|
||||
override var portraitScale = 3.2F
|
||||
override var portraitTranslation = Vec3d(0.0, -2.2, 0.0)
|
||||
|
||||
override val profileScale = 1.4F
|
||||
override val profileTranslation = Vec3d(0.0, -0.34, 0.0)
|
||||
override var profileScale = 1.4F
|
||||
override var profileTranslation = Vec3d(0.0, -0.34, 0.0)
|
||||
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
|
||||
+4
-4
@@ -20,11 +20,11 @@ import net.minecraft.util.math.Vec3d
|
||||
class DodrioModel (root: ModelPart) : PokemonPoseableModel() {
|
||||
override val rootPart = root.registerChildWithAllChildren("dodrio")
|
||||
|
||||
override val portraitScale = 1.5F
|
||||
override val portraitTranslation = Vec3d(-0.15, 0.9, 0.0)
|
||||
override var portraitScale = 1.5F
|
||||
override var portraitTranslation = Vec3d(-0.15, 0.9, 0.0)
|
||||
|
||||
override val profileScale = 0.8F
|
||||
override val profileTranslation = Vec3d(0.0, 0.6, 0.0)
|
||||
override var profileScale = 0.8F
|
||||
override var profileTranslation = Vec3d(0.0, 0.6, 0.0)
|
||||
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walking: PokemonPose
|
||||
|
||||
+4
-4
@@ -20,11 +20,11 @@ import net.minecraft.util.math.Vec3d
|
||||
class DoduoModel (root: ModelPart) : PokemonPoseableModel() {
|
||||
override val rootPart = root.registerChildWithAllChildren("doduo")
|
||||
|
||||
override val portraitScale = 2.0F
|
||||
override val portraitTranslation = Vec3d(-0.1, 0.35, 0.0)
|
||||
override var portraitScale = 2.0F
|
||||
override var portraitTranslation = Vec3d(-0.1, 0.35, 0.0)
|
||||
|
||||
override val profileScale = 0.85F
|
||||
override val profileTranslation = Vec3d(0.0, 0.5, 0.0)
|
||||
override var profileScale = 0.85F
|
||||
override var profileTranslation = Vec3d(0.0, 0.5, 0.0)
|
||||
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walking: PokemonPose
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user