mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-30 13:58:53 -04:00
Compare commits
842
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d0baab2ba | ||
|
|
767e279cf1 | ||
|
|
6ace08aaa6 | ||
|
|
8b81b13d01 | ||
|
|
f19d9410c0 | ||
|
|
9ac3a9249d | ||
|
|
4f340b2eee | ||
|
|
5cff52df5f | ||
|
|
ca311fa97c | ||
|
|
27020d3068 | ||
|
|
3ac4b8622f | ||
|
|
acd7a0583c | ||
|
|
e341948bd4 | ||
|
|
1a465abf9d | ||
|
|
e56a6e5b1a | ||
|
|
33d707a73b | ||
|
|
ba8e40d5a7 | ||
|
|
e3c3cd380c | ||
|
|
578ce789b1 | ||
|
|
460e8f7501 | ||
|
|
2fee86e7bc | ||
|
|
f73e631f81 | ||
|
|
0ca0c1a552 | ||
|
|
b3bf2c5ded | ||
|
|
7875006c8e | ||
|
|
67bb63b638 | ||
|
|
511f97b963 | ||
|
|
54c426f5ff | ||
|
|
f89902ece8 | ||
|
|
52c6bbd842 | ||
|
|
8246a822cf | ||
|
|
54202bed98 | ||
|
|
e6313cf4c5 | ||
|
|
7debc6e047 | ||
|
|
bf9b69a143 | ||
|
|
d7f34972c1 | ||
|
|
fa7356d2ed | ||
|
|
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 | ||
|
|
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 | ||
|
|
a270371632 | ||
|
|
a9caf92d2f | ||
|
|
9e2d00df63 | ||
|
|
e8003bb29a | ||
|
|
a248d661fa | ||
|
|
59390f4d84 | ||
|
|
99b7e4a89e | ||
|
|
fb37e543cf | ||
|
|
c0c75a9735 | ||
|
|
3febee21b6 | ||
|
|
c3a017687c | ||
|
|
afd082c966 | ||
|
|
a6a1f7b75b | ||
|
|
72738a45e6 | ||
|
|
ff4d9ae208 | ||
|
|
a87d522f6d | ||
|
|
8a0076acb4 | ||
|
|
f7e1def555 | ||
|
|
c13f6ae627 | ||
|
|
c24ab2049d | ||
|
|
b7b1850a4e | ||
|
|
8995c107f7 | ||
|
|
dca6b5273d | ||
|
|
d6a412b91a | ||
|
|
2e8483cdc7 | ||
|
|
5984d7a126 | ||
|
|
6d8e645092 | ||
|
|
6b1c2e2074 | ||
|
|
8af5b5e07a | ||
|
|
7ae19ca774 | ||
|
|
830f00553e | ||
|
|
55f0db2263 | ||
|
|
411788a07e | ||
|
|
f6151041c5 | ||
|
|
c87f56c83f | ||
|
|
4478532bcb | ||
|
|
184348d6fa | ||
|
|
04d288ed7e | ||
|
|
0d5cce730e | ||
|
|
3e01535203 | ||
|
|
f0d99a9d83 | ||
|
|
b4eb46d632 | ||
|
|
7e52336255 | ||
|
|
2b40b5b689 | ||
|
|
da889f220b | ||
|
|
ac65910380 | ||
|
|
ba6847be9a | ||
|
|
5ddbcd1830 | ||
|
|
47605646d0 | ||
|
|
d9fdf089c2 | ||
|
|
41db2a53ce | ||
|
|
85d8779818 | ||
|
|
e9a405694c | ||
|
|
d817ce1471 | ||
|
|
ce09b66db5 | ||
|
|
d0c666a20d | ||
|
|
04cef915e4 | ||
|
|
e50412443e | ||
|
|
3fe1f87f18 | ||
|
|
5a0fc199ff | ||
|
|
beb769c2a5 | ||
|
|
a7b6fae4ed | ||
|
|
af2ff7bbfa | ||
|
|
4f3575b2c6 | ||
|
|
8555168a6a | ||
|
|
98c248ef13 | ||
|
|
4a2c69d47c | ||
|
|
1b5c0be975 | ||
|
|
5924398eff | ||
|
|
a08855ab37 | ||
|
|
91abe39cdd | ||
|
|
ad8aab7c19 | ||
|
|
aa6b196c29 | ||
|
|
c23cb644d9 | ||
|
|
a8b12cfca3 | ||
|
|
5268447fa3 | ||
|
|
b489e747bb | ||
|
|
acf467c8a3 | ||
|
|
08f957e33b | ||
|
|
e17d38c53a | ||
|
|
0ff5b95c44 | ||
|
|
818b39e945 | ||
|
|
0397e39735 | ||
|
|
6ca1d23f45 | ||
|
|
30666349a1 | ||
|
|
44def2be76 | ||
|
|
507f70c2d5 | ||
|
|
d91118d05f | ||
|
|
07d8e6ed09 | ||
|
|
fb34d4bd23 | ||
|
|
6ca1337ff9 | ||
|
|
98106cad12 | ||
|
|
0d344337dd | ||
|
|
64d160020b | ||
|
|
fb4c80f68c | ||
|
|
3d27681aaa | ||
|
|
2b5433f9da | ||
|
|
352202203a | ||
|
|
62cfbd7087 | ||
|
|
5a64e8ea1b | ||
|
|
8dc9863a5d | ||
|
|
9bad141c3f | ||
|
|
9280258413 | ||
|
|
51a11163dd | ||
|
|
fe8e4dcaff | ||
|
|
e0bd6766fc | ||
|
|
4da800d396 | ||
|
|
f3246ae14a | ||
|
|
8d7ebeef4f | ||
|
|
d5ad84a495 | ||
|
|
1560b142d2 | ||
|
|
47f87b1be3 | ||
|
|
b01086270a | ||
|
|
da6a09c942 | ||
|
|
8d5eb5883d | ||
|
|
d5fa693f43 | ||
|
|
0d12bf1190 | ||
|
|
4217938ada | ||
|
|
4c5f88db06 | ||
|
|
4f773f63cb | ||
|
|
cfd743c4c0 | ||
|
|
1bbfc6dce5 | ||
|
|
6f2235c751 | ||
|
|
50a0f2d858 | ||
|
|
27210512f6 | ||
|
|
53aa124de6 | ||
|
|
a18b54849f | ||
|
|
c868c63a5f | ||
|
|
31df7c92f4 | ||
|
|
3f3ae74535 | ||
|
|
7429fea802 | ||
|
|
3b65d1967e | ||
|
|
f30b15003f | ||
|
|
c4c1b7ac27 | ||
|
|
ea9287cfb5 | ||
|
|
02f845af5c | ||
|
|
ac5cd47715 | ||
|
|
3bb3a00cef | ||
|
|
f1ae4163c9 | ||
|
|
05957f2106 | ||
|
|
4b9ea1d4cd | ||
|
|
78dff75db9 | ||
|
|
dbab6404a1 | ||
|
|
9901d39f9b | ||
|
|
e5c4240ae0 | ||
|
|
317112f9bb | ||
|
|
c635a1d331 | ||
|
|
58fda2e261 | ||
|
|
cf2173a281 | ||
|
|
3b442d387a | ||
|
|
710d37f453 | ||
|
|
2b575c888f | ||
|
|
6e5e572412 | ||
|
|
ce87d0dc48 | ||
|
|
d43c91129c | ||
|
|
d66b9c8d3b | ||
|
|
1fb3416211 | ||
|
|
dc37b381a0 | ||
|
|
1206aaaf13 | ||
|
|
95bcb9a7b8 | ||
|
|
c7d879ec57 | ||
|
|
f49f2a7305 | ||
|
|
b0e9c1ab28 | ||
|
|
d5752982d7 | ||
|
|
f1439ec724 | ||
|
|
0cac5714ac | ||
|
|
8529bb119f | ||
|
|
ac1c7d8b78 | ||
|
|
b68b3ad55e | ||
|
|
dec5151eb8 | ||
|
|
70c6b74f0f | ||
|
|
196edc2711 | ||
|
|
5cb7a51163 | ||
|
|
a68b6928aa | ||
|
|
0c26cb026c | ||
|
|
6078e22b14 | ||
|
|
cb1226013d | ||
|
|
0c8318d317 | ||
|
|
8d80bcfd6b | ||
|
|
cfd4fa1785 | ||
|
|
86bd70177c | ||
|
|
18015a26fd | ||
|
|
aa296a79a9 | ||
|
|
92dd85643e | ||
|
|
8849de1bfd | ||
|
|
ce668b31ff | ||
|
|
943d6e0c55 | ||
|
|
7d82a2f7c8 | ||
|
|
782ba524df | ||
|
|
c571d79035 | ||
|
|
054c22b926 | ||
|
|
d2fce5edb5 | ||
|
|
cba32b7443 | ||
|
|
4a81c24a3d | ||
|
|
776e629850 | ||
|
|
9afb8b04c2 | ||
|
|
2a349697b4 | ||
|
|
a4055e6206 | ||
|
|
03bda4e27d | ||
|
|
5d8abbd4c7 | ||
|
|
6b167a7a17 | ||
|
|
5c64bc94ff | ||
|
|
90c74eddc8 | ||
|
|
3600178d3b | ||
|
|
66d8a01917 | ||
|
|
68e32b21b5 | ||
|
|
670882bb4d | ||
|
|
d36c24075c | ||
|
|
d1a8122296 | ||
|
|
a8e6e684ab | ||
|
|
188fc2b5d9 | ||
|
|
9c0708651f | ||
|
|
1b3bb3b5bc | ||
|
|
cd03ef68c3 | ||
|
|
69716b5050 | ||
|
|
015deb4eeb | ||
|
|
96023077ad | ||
|
|
d96c68b5b4 | ||
|
|
dc27867502 | ||
|
|
bfbea377c1 | ||
|
|
f5954fcb33 | ||
|
|
eaa909a9f2 | ||
|
|
5ba4d460b1 | ||
|
|
09143b7ad6 | ||
|
|
aa1e14b4ac | ||
|
|
0f29cdeaf9 | ||
|
|
b976b9dd68 | ||
|
|
2bc2e3f020 | ||
|
|
fa94ca8033 | ||
|
|
f206352b6e | ||
|
|
cdee981933 | ||
|
|
f2fc32b6a9 | ||
|
|
f46b581327 | ||
|
|
ff1241304b | ||
|
|
7a15e6b004 | ||
|
|
6ee6beddeb | ||
|
|
b92960da77 | ||
|
|
dd746e6775 | ||
|
|
99618184e7 | ||
|
|
fcdff126fd | ||
|
|
44956ec6da | ||
|
|
83e7a1968a | ||
|
|
3b285cc8bd | ||
|
|
553ecc8509 | ||
|
|
7b0d488b7c | ||
|
|
4dead98e6b | ||
|
|
db36f8da2a | ||
|
|
3f7a5e1318 | ||
|
|
ce7485f557 | ||
|
|
b5ca5c29d4 | ||
|
|
43f60da22e | ||
|
|
0102c8b392 | ||
|
|
3a448071d7 | ||
|
|
6bb5c5dadf | ||
|
|
dd21fe2ea3 | ||
|
|
656c46817a | ||
|
|
a373f437fa | ||
|
|
0fe3637034 | ||
|
|
7215860d74 | ||
|
|
dc899ffc1b | ||
|
|
88fe55bbb9 | ||
|
|
4b4be0e2cc | ||
|
|
3e673ae8f0 | ||
|
|
4b3b7443d3 | ||
|
|
70c1b42ede | ||
|
|
b2048bb66f | ||
|
|
9956f1c159 | ||
|
|
25857dafc5 | ||
|
|
80345b3810 | ||
|
|
d4dc24ec49 | ||
|
|
2209ee10b6 | ||
|
|
a91aa9835c | ||
|
|
0e980a846c | ||
|
|
3d3c421b5c | ||
|
|
f54bbe754f | ||
|
|
92fff27b4e | ||
|
|
255874cbe4 | ||
|
|
824bc1b080 | ||
|
|
3ee55f24d8 | ||
|
|
c3379ddf21 | ||
|
|
5983b17e87 | ||
|
|
27986d28a7 | ||
|
|
8807f2134e | ||
|
|
d74b1228c1 | ||
|
|
a3dcfe8bfb | ||
|
|
8725ef2b54 | ||
|
|
3c2cfa4ffc | ||
|
|
3074b067dc | ||
|
|
8d0ee6dd6f | ||
|
|
a1c1c9bc90 | ||
|
|
5e52d350c1 | ||
|
|
e3ad34e023 | ||
|
|
f308918fd1 | ||
|
|
82a8257fa9 | ||
|
|
6c06c91cca | ||
|
|
c5e44031a6 | ||
|
|
6be2e14af4 | ||
|
|
5cae25c059 | ||
|
|
87e4f94af5 | ||
|
|
90ac9ae4df | ||
|
|
527518d0c2 | ||
|
|
bcb326cd87 | ||
|
|
89a4edb327 | ||
|
|
ab37580258 | ||
|
|
c116c01fd6 | ||
|
|
e3ad8f8079 | ||
|
|
a491d508b6 | ||
|
|
43075f1cb8 | ||
|
|
3e11d0550f | ||
|
|
e1b1e3d5e9 | ||
|
|
c226b80430 | ||
|
|
935f7039cf | ||
|
|
e8b50f8115 | ||
|
|
02fb825328 | ||
|
|
a7095b30a3 | ||
|
|
ac5a03eebc | ||
|
|
8df6eea107 | ||
|
|
1376bb68f4 | ||
|
|
beb8f2ccf1 | ||
|
|
bd79b58571 | ||
|
|
7c164fc4c8 | ||
|
|
5e1c233493 | ||
|
|
95e95afef3 | ||
|
|
bf9c54e539 | ||
|
|
d9de8f2678 | ||
|
|
2ccda57c66 | ||
|
|
846acaef88 | ||
|
|
510dfec0e5 | ||
|
|
e54932c876 | ||
|
|
5fa12ff1c5 | ||
|
|
2b3db32243 | ||
|
|
4b54405017 | ||
|
|
dd14c3bbdd | ||
|
|
5ea237f8a0 | ||
|
|
b7addd0203 | ||
|
|
7e64938ec9 | ||
|
|
3824531735 | ||
|
|
618f66c775 | ||
|
|
9eb9c782ce | ||
|
|
49149c9c54 | ||
|
|
fd1d1075db | ||
|
|
1648926aa6 | ||
|
|
7784794689 | ||
|
|
07b41d7c0a | ||
|
|
f5287c7e83 | ||
|
|
fb154ba457 | ||
|
|
f7812896a8 | ||
|
|
b0d57dd875 | ||
|
|
6c09e2b553 | ||
|
|
593104fb0a | ||
|
|
e314664731 | ||
|
|
d0a38a9704 | ||
|
|
63a30dcfd0 | ||
|
|
9cc63b59e6 | ||
|
|
cb17c29be5 | ||
|
|
fd16d59ea2 | ||
|
|
6e155d7651 | ||
|
|
ae8f8a2fb8 | ||
|
|
5a6a83aac1 | ||
|
|
e8236b55a4 | ||
|
|
2ea07899ea | ||
|
|
d0ce03cd5e | ||
|
|
8ae0c409a3 | ||
|
|
2782cb5f34 | ||
|
|
2f10707211 | ||
|
|
f40a9d762a | ||
|
|
17587f97e5 | ||
|
|
5230820657 | ||
|
|
61c55e136f | ||
|
|
22cced74f5 | ||
|
|
3cd2dec8e0 | ||
|
|
3ce22c0759 | ||
|
|
cea930893a | ||
|
|
8662364ca8 | ||
|
|
1fd079b1b4 | ||
|
|
244876a26c | ||
|
|
e7790f530f | ||
|
|
04a9ab0e67 | ||
|
|
3f338d27c3 | ||
|
|
5da3dfb451 | ||
|
|
fd329e00cd | ||
|
|
6da47a8b2c | ||
|
|
860c73fac9 | ||
|
|
e26fdd4bdd | ||
|
|
8e642f71b8 | ||
|
|
797eeb09cc | ||
|
|
e6df322556 | ||
|
|
744d1e1263 | ||
|
|
7987713179 | ||
|
|
f8efe0a7d1 | ||
|
|
be558ed0ab | ||
|
|
a786adee9e | ||
|
|
2d6c7f5148 | ||
|
|
f3f3bfead4 | ||
|
|
506ff8d1e4 | ||
|
|
4764264c9a | ||
|
|
7a761003c5 | ||
|
|
f9fa9dcf24 | ||
|
|
dfc4873ce3 | ||
|
|
f17884b4e1 | ||
|
|
65bd00033c | ||
|
|
f82fa2b4e6 | ||
|
|
c40b456948 | ||
|
|
7e74e85315 | ||
|
|
21fd4d7cbf | ||
|
|
908bff9892 | ||
|
|
966acecf6d | ||
|
|
fa14f70bbb | ||
|
|
2cd09af4d0 | ||
|
|
1bc22f1afc | ||
|
|
3480085a29 | ||
|
|
f5c0bfb40e | ||
|
|
9dc9740363 | ||
|
|
be16d00dd5 | ||
|
|
777ece02cc | ||
|
|
188ae2ac85 | ||
|
|
388e03e261 | ||
|
|
346559f292 | ||
|
|
331b282fcf | ||
|
|
7f97eeafed | ||
|
|
51f5a1f5a8 | ||
|
|
1829f7d48a | ||
|
|
bcc3c885d7 | ||
|
|
e2a6dbc709 | ||
|
|
b32ca4af5d | ||
|
|
a2e728905e | ||
|
|
7c0535b8bd | ||
|
|
ead232be6f | ||
|
|
feaba85ba0 | ||
|
|
6a8822ca76 | ||
|
|
4f15ac0cbc | ||
|
|
8fc6d93be4 | ||
|
|
97f8dc562a | ||
|
|
35a0d8a80d | ||
|
|
6616cd1d4c | ||
|
|
f9635cf03f | ||
|
|
49db87737f | ||
|
|
a414213255 | ||
|
|
59a8c21429 | ||
|
|
b67fda7a37 | ||
|
|
4392a61ab5 | ||
|
|
a9d96818ec | ||
|
|
6b285e48e9 | ||
|
|
c0270d3ef0 | ||
|
|
82a1eb2a55 | ||
|
|
a528ea952a | ||
|
|
532ef09acd | ||
|
|
f0f7bb96ad | ||
|
|
af2df51a2a | ||
|
|
ecfb6c60c3 | ||
|
|
5be436f25c | ||
|
|
2ddc265b0f | ||
|
|
52af8ceb99 | ||
|
|
14a5060100 | ||
|
|
9d33586b44 | ||
|
|
d4f328157e | ||
|
|
c4331043f7 | ||
|
|
9945d8a069 | ||
|
|
2595d6ee91 | ||
|
|
95a0f9603c | ||
|
|
f16e024bbe | ||
|
|
87a5522acc | ||
|
|
2c812cdc3c | ||
|
|
f6e910038e | ||
|
|
5c7d96897d | ||
|
|
862d892c84 | ||
|
|
9246e1e8ee | ||
|
|
0715cb465f | ||
|
|
2e251972aa | ||
|
|
de89c11f24 | ||
|
|
7a1f96e31e | ||
|
|
d405b099b3 | ||
|
|
a8e4f87c59 | ||
|
|
74322e2f48 | ||
|
|
f16d233693 | ||
|
|
54d2711583 | ||
|
|
e54f179ccf | ||
|
|
40a37fedd2 | ||
|
|
3bc6c50d79 | ||
|
|
1ef9f44a1b | ||
|
|
d38aa6b1a2 | ||
|
|
f1ed339d9d | ||
|
|
f07930ef16 | ||
|
|
4566e1b33f | ||
|
|
c6d18cda44 | ||
|
|
263b86e833 | ||
|
|
953560051d | ||
|
|
bf3904a214 | ||
|
|
c426f4154b | ||
|
|
a326eb3832 | ||
|
|
1708eb9b3e | ||
|
|
0dee18dbfd | ||
|
|
f2d16ca9b7 | ||
|
|
7ee7aaab76 | ||
|
|
3dd4f515dd | ||
|
|
f24310d043 | ||
|
|
61bfe02322 | ||
|
|
7cbcb30aff | ||
|
|
6fc8fa5b60 | ||
|
|
7763a6d3e7 | ||
|
|
1288469172 | ||
|
|
86cf79bff9 | ||
|
|
22441e0b09 | ||
|
|
8c6f7335a5 | ||
|
|
8418bc87c8 | ||
|
|
c747d089ca | ||
|
|
8c881ab85a | ||
|
|
ec43a78ae4 | ||
|
|
762a53923c | ||
|
|
1cf03d4a0d | ||
|
|
48f7be485f | ||
|
|
89364a9fd0 | ||
|
|
43d965f2a1 | ||
|
|
e4a698b04b | ||
|
|
33cfbf7d1c | ||
|
|
d6fbb70db0 | ||
|
|
150a5c668a | ||
|
|
09da392c36 | ||
|
|
94ad2f1250 | ||
|
|
6ddf048984 | ||
|
|
f396b63a34 | ||
|
|
253cfd55d8 | ||
|
|
1bf01a2826 | ||
|
|
e75d0c564f | ||
|
|
1e97143a6a | ||
|
|
4d1bf677a1 | ||
|
|
069f56acfd | ||
|
|
7b4e63001b | ||
|
|
bd4df4485e | ||
|
|
19cdc8fbef | ||
|
|
1408b94f06 | ||
|
|
58fba24f01 | ||
|
|
f49265ae52 | ||
|
|
de081dc514 | ||
|
|
001864e20c | ||
|
|
0c9fe19da3 | ||
|
|
28ebd1dec1 | ||
|
|
94bbc0e574 | ||
|
|
034e7d315c | ||
|
|
fb785b4204 | ||
|
|
ac807ce25b | ||
|
|
c065f0f8fd | ||
|
|
9c7d286dd8 | ||
|
|
69d8e4fab9 | ||
|
|
b788fe3984 | ||
|
|
cfd90fac04 | ||
|
|
1cf2359195 | ||
|
|
6868d7f26c | ||
|
|
3e58229a89 | ||
|
|
d76f1524bd | ||
|
|
58b5eb155d | ||
|
|
fd9caa537b | ||
|
|
5262972a8d | ||
|
|
011a095314 | ||
|
|
3520c50541 | ||
|
|
3eccac861f | ||
|
|
7a85b0b690 | ||
|
|
ff3aa5d782 | ||
|
|
9e6dec8605 | ||
|
|
1fe223c772 | ||
|
|
d89ccc110e | ||
|
|
72c337195a | ||
|
|
28a2ec3fc0 | ||
|
|
72bba7fdfd | ||
|
|
a258e48582 | ||
|
|
21a15686b2 | ||
|
|
5da7183ae3 | ||
|
|
d847972bb1 | ||
|
|
5e88e73e3f | ||
|
|
e9086ec2bd | ||
|
|
866db464c4 | ||
|
|
3dbcc2d28c | ||
|
|
1538f12934 | ||
|
|
857f67604c | ||
|
|
ae49e3f977 | ||
|
|
ec01a03820 | ||
|
|
96cc3671da | ||
|
|
ad7c9c560c | ||
|
|
ee15ff6b35 | ||
|
|
b8e95bd210 | ||
|
|
b14465f2a1 | ||
|
|
ca83103703 | ||
|
|
1aeb894b09 | ||
|
|
8e9ab26963 | ||
|
|
44b4fbcfe3 | ||
|
|
42cc1dd8a9 | ||
|
|
2a60048f7e | ||
|
|
d69310e52c | ||
|
|
a0f89274d1 | ||
|
|
eefc125f24 | ||
|
|
f95f17d0c6 | ||
|
|
ba7e98e95c | ||
|
|
02067929a2 | ||
|
|
0bc3e8465b | ||
|
|
0ebf5712b9 | ||
|
|
4020e28da9 | ||
|
|
dbc074bfde | ||
|
|
17cdedf65f | ||
|
|
f96766505b | ||
|
|
fe96642be4 | ||
|
|
701af6cd8f | ||
|
|
5515fbfeda | ||
|
|
41a0dce7fc | ||
|
|
3b122b7bcc | ||
|
|
2b3500dfc3 | ||
|
|
e921253a57 | ||
|
|
da45797022 | ||
|
|
fc1f68711d | ||
|
|
da9c1f440c | ||
|
|
ae10ca9541 | ||
|
|
80d2f76dfc | ||
|
|
ebf3c9b82f | ||
|
|
af57ac45a2 | ||
|
|
0ad45df8f5 | ||
|
|
7f464f2e3e | ||
|
|
d8e209e4a2 | ||
|
|
41a87d0c8a | ||
|
|
45faed038f | ||
|
|
30a78f978d | ||
|
|
d8c1d50aa5 | ||
|
|
03f377cf0a | ||
|
|
eb7bf65e02 | ||
|
|
373092f572 | ||
|
|
c7d3164ff4 | ||
|
|
e6da43be6d | ||
|
|
8bfc0fefaf | ||
|
|
4e44807523 | ||
|
|
36251fea75 | ||
|
|
06206a7447 | ||
|
|
66e901f88d | ||
|
|
05f089d390 | ||
|
|
f52345036d | ||
|
|
bd99ff2bfd | ||
|
|
19510ca8ba | ||
|
|
23df8f70cf | ||
|
|
bd25e8682a | ||
|
|
0ece90bcf1 | ||
|
|
906cd54c98 | ||
|
|
c2894b4bf1 | ||
|
|
8c3958cdf0 | ||
|
|
92cb847755 | ||
|
|
fc4fed42b5 | ||
|
|
ea332515c4 | ||
|
|
49965d6856 | ||
|
|
a1897f69ca | ||
|
|
a88700969d | ||
|
|
91eb9e597e | ||
|
|
e762542e49 | ||
|
|
6e7694d650 | ||
|
|
a301779a42 | ||
|
|
440a07d1de | ||
|
|
b3e5734f39 | ||
|
|
fc7951cbcd | ||
|
|
2d5296288f | ||
|
|
44b58ab9a0 | ||
|
|
cab3f2bf38 | ||
|
|
d24a6fa75c | ||
|
|
fca867a8b8 | ||
|
|
9514c48eaa | ||
|
|
31efdc4254 | ||
|
|
34aace8a1b | ||
|
|
a877ad5a69 | ||
|
|
5a8c090055 | ||
|
|
98ccf39728 | ||
|
|
d029b4380a | ||
|
|
4c29c9726b | ||
|
|
af9fff9793 | ||
|
|
a8d84c4a28 | ||
|
|
5215388e33 | ||
|
|
93c7685ef7 | ||
|
|
5c395a1987 | ||
|
|
755d367760 | ||
|
|
3b26d24958 | ||
|
|
27afe40892 | ||
|
|
fcd4dccdad | ||
|
|
35e206a5d6 | ||
|
|
b51d007341 | ||
|
|
a85fd79818 | ||
|
|
3222e2ebca | ||
|
|
ba89ed1574 | ||
|
|
68ab953644 | ||
|
|
4d3030e20e | ||
|
|
2e324e65a1 | ||
|
|
a34b7481f5 | ||
|
|
d2a3905b03 | ||
|
|
16b3d76504 | ||
|
|
363fe76dd1 | ||
|
|
040a29f66e |
No files matched your search
@@ -33,3 +33,7 @@ common/src/main/resources/assets/cobblemon/showdown
|
||||
# Generated files
|
||||
*/generated/resources/*
|
||||
/fabric/src/generated/resources/cobblemon-common.accesswidener
|
||||
/.ignored/
|
||||
|
||||
# MacOS
|
||||
.DS_Store
|
||||
+236
-1
@@ -1,4 +1,237 @@
|
||||
# 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.
|
||||
- Added the Data Monitor, Fossil Compartment, and Restoration Tank. Placed in the correct formation, you can use these to create a Restoration Machine where you can bring fossils back to life.
|
||||
- Added 3 variants of Tumblestones, which can be planted near Lava or Magma to grow harvestable Tumblestone Clusters.
|
||||
- Added Tumblestone Blocks, a storage block crafted from 9 Tumblestones.
|
||||
- Added Ancient Poké Balls, which are aesthetic variants crafted from Tumblestones.
|
||||
- Added the Ancient Feather, Wing, and Jet Balls, which fly further than regular Poké Balls.
|
||||
- Added the Ancient Heavy, Leaden, and Gigaton Balls, which are heavier and don't fly as far as regular Poké Balls. These will receive more functionality in a future update.
|
||||
- Added Original Trainer functionality. To edit the OT through commands, you must specify originaltrainertype=<Player/NPC>, and originaltrainer=<Username or UUID/NPC Name>
|
||||
- Added support for planting Apricorn trees, berries, and mints in [Botany Pots](https://modrinth.com/mod/botany-pots)
|
||||
- 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 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.
|
||||
- You can now punch grown apricorns to harvest them.
|
||||
- Renamed the "Vivillionaire" advancement to "Aspiring Vivillionaire"
|
||||
- Removed the Inferno, Forsaken, Poké Ball, and Void patterns from the Aspiring Vivillionaire advancement.
|
||||
- Updated movesets to add Gen 9 DLC moves.
|
||||
- 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.
|
||||
|
||||
### 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.
|
||||
- Fixed battle lang for Poison Touch Ability
|
||||
- Fixed Cubone not being able to evolve into Alolan Marowak.
|
||||
- Fixed Squawkabilly forms not being recognized.
|
||||
- Fixed the bounce animation for Poké Balls being delayed by like, a full second.
|
||||
- Note blocks now play the correct sound on the Apricorn Plank based blocks.
|
||||
- Fixed an issue with transformed parts in posers causing whacky positional issues.
|
||||
- Fixed Poké Balls freezing in an open state if you look away when it's meant to close.
|
||||
- Adds a translation string name to the Empty Pokeball entity.
|
||||
- Fixed very many issues with Bedrock particle effects.
|
||||
- Fixed Arbok patterns not being as specific in spawning as they were intended.
|
||||
- Fixed Pokémon not avoiding danger at all when pathfinding.
|
||||
- Fixed Sobble line not being able to swim or breathe underwater.
|
||||
- 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).
|
||||
- Rebuilt the scheduling API to more clearly force side choices and temporal frames of reference for tasks.
|
||||
- Added dialogue API and data registry.
|
||||
- Opened up the ItemDropEntry class to allow for it to be extended.
|
||||
- Added a new "advancement" evolution variant that takes an advancement identifier and succeeds if the player has the advancement.
|
||||
- Made spawning API capable of non-entity spawning
|
||||
- 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.
|
||||
|
||||
### Datapack & Resourcepack Creators
|
||||
- The maximum amount of fossils that can fit in the Fossil Analyzer can be adjusted in the config.
|
||||
- Custom fossils can be defined using a list of items and the resulting Pokémon. An example of `aerodactyl.json`:
|
||||
```JSON
|
||||
{
|
||||
"result": "aerodactyl",
|
||||
"fossils": [
|
||||
"cobblemon:old_amber_fossil"
|
||||
]
|
||||
}
|
||||
```
|
||||
- Fetus models can be defined in `bedrock/fossils`.
|
||||
- Fetus textures can be defined in `textures/fossils`.
|
||||
- Fuel for the Restoration Machine is registered inside the `natural_materials` folder. To register more fuels, create a JSON file containing an array of objects. Each object supports the following fields:
|
||||
- `content`: Integer containing the amount of fuel to add.
|
||||
- `item` OR `tag`: Identifier of the item or item tag to be inserted.
|
||||
- `returnItem`: Identifier of an item to return to the player after consumption.
|
||||
- Added 3 new item tags: `ancient_poke_balls`, `fossils`, and `tumblestones`.
|
||||
- Added a spawn rules system to modify general spawning behaviour, see the [wiki](https://wiki.cobblemon.com/index.php/Spawn_Rules) for more information.
|
||||
- Added dialogue datapack folder and /opendialogue command.
|
||||
- Added the item tag ``cobblemon:held/leaves_leftovers`` this can be used to flag apple-like items that can create leftovers when eaten.
|
||||
- You can now add support for dynamic lighting implementations, Cobblemon ships with a default implementation for [LambDynamicLights](https://modrinth.com/mod/lambdynamiclights) and the [Dynamic Lights Reforged](https://www.curseforge.com/minecraft/mc-mods/dynamiclights-reforged), add the following to any species or form:
|
||||
```JSON
|
||||
{
|
||||
"lightingData": {
|
||||
"lightLevel": 14,
|
||||
"_lightLevelCommentRemoveMe": "Above supports 0 to 15",
|
||||
"liquidGlowMode": "LAND",
|
||||
"_liquidGlowModeCommentRemoveMe": "Above supports LAND, UNDERWATER or BOTH"
|
||||
}
|
||||
}
|
||||
```
|
||||
- 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)
|
||||
|
||||
### Additions
|
||||
@@ -15,6 +248,7 @@
|
||||
- Added cries to Beldum, Metang and Metagross.
|
||||
- Added a /bedrockparticle command to run Snowstorm-format particle effects.
|
||||
- Added data for Dipplin, Fezandipiti, Munkidori, Ogerpon, Okidogi, Poltchageist and Sinistcha.
|
||||
- Added additional nickname trigger "Grumm" for Inkay's evolution.
|
||||
|
||||
### Changes
|
||||
- Using Potions, Status Heals, Ethers, and Antidotes will now return a glass bottle
|
||||
@@ -100,6 +334,7 @@
|
||||
### Developer
|
||||
- Fixed the `SpawnEvent` not respecting usage of `Cancelable#cancel`.
|
||||
- Added the `EvolutionTestedEvent`, this allows listening and overriding the final result of evolution requirement tests.
|
||||
- Rebuilt the scheduling API to more clearly force side choices and allow more local temporal frames of reference for tasks.
|
||||
- Added utility script that can be used to generate all Spawn JSONS for all pokemon from the spawning spreadsheet in 1 click ([cobblemon_spawn_csv_to_json.py](utilityscripts%2Fcobblemon_spawn_csv_to_json.py)).
|
||||
- The `HeldItemManager` has a new method `shouldConsumeItem`, this will return false by default to prevent breaking changes, see the documentation and update your implementations as needed.
|
||||
- Added and implemented minSkyLight and maxSkyLight as config options for SpawnConditions
|
||||
@@ -931,4 +1166,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
|
||||
}
|
||||
+3
-2
@@ -1,6 +1,7 @@
|
||||
plugins {
|
||||
base
|
||||
id("cobblemon.root-conventions")
|
||||
id ("net.nemerosa.versioning") version "2.8.2"
|
||||
}
|
||||
|
||||
group = "com.cobblemon.mod"
|
||||
@@ -8,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"
|
||||
}
|
||||
version = "$version-${versioning.info.branch}-${versioning.info.build}"
|
||||
}
|
||||
+43
-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 {
|
||||
@@ -33,6 +43,7 @@ dependencies {
|
||||
modApi(libs.molang)
|
||||
compileOnlyApi(libs.jeiApi)
|
||||
modCompileOnly(libs.adornFabric)
|
||||
modCompileOnly(libs.lambDynamicLights) { isTransitive = false }
|
||||
|
||||
// For Showdown
|
||||
modCompileOnly(libs.graal)
|
||||
@@ -43,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)
|
||||
@@ -58,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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-3
@@ -8,12 +8,9 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pose;
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityModel;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.Entity;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.compat;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonEntities;
|
||||
import com.cobblemon.mod.common.client.render.layer.PokemonOnShoulderRenderer;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.pokemon.FormData;
|
||||
import com.cobblemon.mod.common.pokemon.lighthing.LightingData;
|
||||
import dev.lambdaurora.lambdynlights.api.DynamicLightHandler;
|
||||
import dev.lambdaurora.lambdynlights.api.DynamicLightHandlers;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.util.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
// Java class due to relying on entrypoint on Fabric side
|
||||
public class LambDynamicLightsCompat {
|
||||
|
||||
// This is all called on client side
|
||||
// These things are checked every tick so try to keep it as free as possible
|
||||
// That being said it's unlikely school Toshiba person is running dynamic lighting and shaders to enjoy this
|
||||
// Make sure not to call anything Fabric specific :)
|
||||
public static void hookCompat() {
|
||||
// Pokémon entities
|
||||
DynamicLightHandlers.registerDynamicLightHandler(
|
||||
CobblemonEntities.POKEMON,
|
||||
DynamicLightHandler.makeHandler(
|
||||
pokemon -> resolvedPokemonLightLevel(pokemon, false),
|
||||
pokemon -> true
|
||||
)
|
||||
);
|
||||
DynamicLightHandlers.registerDynamicLightHandler(
|
||||
CobblemonEntities.POKEMON,
|
||||
DynamicLightHandler.makeHandler(
|
||||
pokemon -> resolvedPokemonLightLevel(pokemon, true),
|
||||
pokemon -> false
|
||||
)
|
||||
);
|
||||
|
||||
// Shouldered Pokémon
|
||||
DynamicLightHandlers.registerDynamicLightHandler(
|
||||
EntityType.PLAYER,
|
||||
DynamicLightHandler.makeHandler(
|
||||
player -> resolvedShoulderLightLevel(player, false),
|
||||
player -> true
|
||||
)
|
||||
);
|
||||
DynamicLightHandlers.registerDynamicLightHandler(
|
||||
EntityType.PLAYER,
|
||||
DynamicLightHandler.makeHandler(
|
||||
player -> resolvedShoulderLightLevel(player, true),
|
||||
player -> false
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private static int resolvedPokemonLightLevel(PokemonEntity pokemon, boolean underwater) {
|
||||
return extractFormLightLevel(pokemon.getForm(), underwater).orElse(0);
|
||||
}
|
||||
|
||||
private static int resolvedShoulderLightLevel(PlayerEntity player, boolean underwater) {
|
||||
final Pair<PokemonOnShoulderRenderer.ShoulderData, PokemonOnShoulderRenderer.ShoulderData> shoulderDataPair = PokemonOnShoulderRenderer.shoulderDataOf(player);
|
||||
final Optional<Integer> leftLightLevel = extractShoulderLightLevel(shoulderDataPair.getLeft(), underwater);
|
||||
final Optional<Integer> rightLightLevel = extractShoulderLightLevel(shoulderDataPair.getRight(), underwater);
|
||||
return Math.max(leftLightLevel.orElse(0), rightLightLevel.orElse(0));
|
||||
}
|
||||
|
||||
private static Optional<Integer> extractFormLightLevel(@NotNull FormData form, boolean underwater) {
|
||||
if (form.getLightingData() == null || !liquidGlowModeSupport(form.getLightingData().getLiquidGlowMode(), underwater)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(form.getLightingData().getLightLevel());
|
||||
}
|
||||
|
||||
private static Optional<Integer> extractShoulderLightLevel(@Nullable PokemonOnShoulderRenderer.ShoulderData shoulderData, boolean underwater) {
|
||||
if (shoulderData == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return extractFormLightLevel(shoulderData.getForm(), underwater);
|
||||
}
|
||||
|
||||
private static boolean liquidGlowModeSupport(@NotNull LightingData.LiquidGlowMode liquidGlowMode, boolean underwater) {
|
||||
return underwater ? liquidGlowMode.getGlowsUnderwater() : liquidGlowMode.getGlowsInLand();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.sherds.CobblemonSherds;
|
||||
import net.minecraft.block.DecoratedPotPatterns;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(DecoratedPotPatterns.class)
|
||||
public abstract class DecoratedPotPatternsMixin {
|
||||
@Inject(method = "fromSherd", at=@At("HEAD"), cancellable = true)
|
||||
private static void cobblemon$getCobblemonSherdTexture(Item sherd,
|
||||
CallbackInfoReturnable<RegistryKey<String>> cir) {
|
||||
if (CobblemonSherds.INSTANCE.getSherdToPattern().containsKey(sherd)) {
|
||||
cir.setReturnValue(CobblemonSherds.INSTANCE.getSherdToPattern().get(sherd));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,20 +8,37 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.api.scheduling.ScheduledTaskTracker;
|
||||
import com.cobblemon.mod.common.api.scheduling.ClientTaskTracker;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.GameRenderer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(GameRenderer.class)
|
||||
public class GameRendererMixin {
|
||||
@Unique
|
||||
long lastTime = -1;
|
||||
|
||||
@Inject(
|
||||
method = "render",
|
||||
at = @At(value = "TAIL")
|
||||
)
|
||||
public void render(float tickDelta, long startTime, boolean tick, CallbackInfo ci) {
|
||||
ScheduledTaskTracker.INSTANCE.update();
|
||||
MinecraftClient client = MinecraftClient.getInstance();
|
||||
long newTime = System.currentTimeMillis();
|
||||
// Don't play scheduled animations when the game is paused
|
||||
if (client.isPaused()) {
|
||||
lastTime = newTime;
|
||||
return;
|
||||
}
|
||||
|
||||
if (lastTime != -1) {
|
||||
ClientTaskTracker.INSTANCE.update((newTime - lastTime) / 1000F);
|
||||
}
|
||||
lastTime = newTime;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonBakingOverrides;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import net.minecraft.client.color.block.BlockColors;
|
||||
import net.minecraft.client.render.model.ModelLoader;
|
||||
import net.minecraft.client.render.model.UnbakedModel;
|
||||
import net.minecraft.client.render.model.json.JsonUnbakedModel;
|
||||
import net.minecraft.client.util.ModelIdentifier;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.profiler.Profiler;
|
||||
import org.slf4j.Logger;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.InjectionPoint;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.points.BeforeStringInvoke;
|
||||
|
||||
@Mixin(ModelLoader.class)
|
||||
public abstract class ModelLoaderMixin {
|
||||
|
||||
@Shadow protected abstract void addModel(ModelIdentifier modelId);
|
||||
|
||||
@Final
|
||||
@Shadow
|
||||
private Map<Identifier, UnbakedModel> unbakedModels;
|
||||
|
||||
@Final
|
||||
@Shadow
|
||||
private static Logger LOGGER;
|
||||
|
||||
@Inject(
|
||||
method = "<init>",
|
||||
at = @At("TAIL")
|
||||
)
|
||||
public void init(BlockColors blockColors,
|
||||
Profiler profiler,
|
||||
Map jsonUnbakedModels,
|
||||
Map blockStates,
|
||||
CallbackInfo ci) {
|
||||
CobblemonBakingOverrides.INSTANCE.getModels().forEach(bakingOverride -> {
|
||||
try {
|
||||
this.unbakedModels.put(bakingOverride.getModelIdentifier(), this.loadModelFromJson(bakingOverride.getModelLocation()));
|
||||
this.addModel(bakingOverride.getModelIdentifier());
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Error loading a Cobblemon BakedModel:", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Shadow
|
||||
private JsonUnbakedModel loadModelFromJson(Identifier id) throws IOException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.api.snowstorm.ParticleMaterials;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.minecraft.client.particle.ParticleManager;
|
||||
import net.minecraft.client.particle.ParticleTextureSheet;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Mutable;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mixin(ParticleManager.class)
|
||||
final class ParticleManagerMixin {
|
||||
@Mutable
|
||||
@Final
|
||||
@Shadow
|
||||
private static List<ParticleTextureSheet> PARTICLE_TEXTURE_SHEETS;
|
||||
|
||||
@Inject(at = @At("RETURN"), method = "<clinit>")
|
||||
private static void lodestone$addTypes(CallbackInfo ci) {
|
||||
PARTICLE_TEXTURE_SHEETS = ImmutableList.<ParticleTextureSheet>builder().addAll(PARTICLE_TEXTURE_SHEETS)
|
||||
.add(ParticleMaterials.INSTANCE.getADD(), ParticleMaterials.INSTANCE.getALPHA(), ParticleMaterials.INSTANCE.getBLEND(), ParticleMaterials.INSTANCE.getOPAQUE()).build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems;
|
||||
import net.minecraft.entity.mob.PiglinBrain;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
|
||||
@Mixin(PiglinBrain.class)
|
||||
public class PiglinBarterMixin {
|
||||
|
||||
@Inject(method = "acceptsForBarter", at = @At(value = "RETURN"), cancellable = true)
|
||||
private static void cobblemon$acceptsForBarter(ItemStack stack, CallbackInfoReturnable<Boolean> ci) {
|
||||
if(!ci.getReturnValue()) {
|
||||
//TODO: Make a tag?
|
||||
if(stack.isOf(CobblemonItems.RELIC_COIN_POUCH))
|
||||
ci.setReturnValue(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
import net.minecraft.entity.mob.PiglinEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
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(PiglinEntity.class)
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import com.cobblemon.mod.common.api.events.CobblemonEvents;
|
||||
import com.cobblemon.mod.common.api.events.item.LeftoversCreatedEvent;
|
||||
import com.cobblemon.mod.common.api.storage.NoPokemonStoreException;
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore;
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags;
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon;
|
||||
import com.cobblemon.mod.common.util.CompoundTagExtensionsKt;
|
||||
import com.cobblemon.mod.common.util.DataKeys;
|
||||
@@ -22,11 +23,8 @@ import net.minecraft.entity.ItemEntity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.sound.SoundEvent;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.world.World;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
@@ -40,8 +38,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.cobblemon.mod.common.util.LocalizationUtilsKt.lang;
|
||||
|
||||
@Mixin(PlayerEntity.class)
|
||||
public abstract class PlayerMixin extends LivingEntity {
|
||||
|
||||
@@ -144,7 +140,7 @@ public abstract class PlayerMixin extends LivingEntity {
|
||||
)
|
||||
public void onEatFood(World world, ItemStack stack, CallbackInfoReturnable<ItemStack> cir) {
|
||||
if (!getWorld().isClient) {
|
||||
if (stack.getItem() == Items.APPLE && getWorld().random.nextDouble() < Cobblemon.config.getAppleLeftoversChance()) {
|
||||
if (stack.isIn(CobblemonItemTags.LEAVES_LEFTOVERS) && getWorld().random.nextDouble() < Cobblemon.config.getAppleLeftoversChance()) {
|
||||
ItemStack leftovers = new ItemStack(CobblemonItems.LEFTOVERS);
|
||||
ServerPlayerEntity player = Objects.requireNonNull(getServer()).getPlayerManager().getPlayer(uuid);
|
||||
assert player != null;
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.client.render.model.BakedModel
|
||||
import net.minecraft.client.util.ModelIdentifier
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
/**
|
||||
* Contains information for forcing a model to be baked
|
||||
*
|
||||
* @param modelLocation The location of the model
|
||||
* @param modelIdentifier The identifier that the BakedModel will be registered to
|
||||
*/
|
||||
data class BakingOverride(
|
||||
val modelLocation: Identifier,
|
||||
val modelIdentifier: ModelIdentifier
|
||||
) {
|
||||
fun getModel(): BakedModel {
|
||||
return MinecraftClient.getInstance().bakedModelManager.getModel(modelIdentifier)
|
||||
}
|
||||
}
|
||||
@@ -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,12 +17,14 @@ 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.LEVEL_UP_EVENT
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.POKEMON_CAPTURED
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.TRADE_COMPLETED
|
||||
import com.cobblemon.mod.common.api.net.serializers.IdentifierDataSerializer
|
||||
import com.cobblemon.mod.common.api.net.serializers.PoseTypeDataSerializer
|
||||
import com.cobblemon.mod.common.api.net.serializers.StringSetDataSerializer
|
||||
import com.cobblemon.mod.common.api.net.serializers.Vec3DataSerializer
|
||||
@@ -35,13 +38,15 @@ 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.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
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.StatProvider
|
||||
import com.cobblemon.mod.common.api.properties.CustomPokemonProperty
|
||||
import com.cobblemon.mod.common.api.scheduling.ScheduledTaskTracker
|
||||
import com.cobblemon.mod.common.api.scheduling.ServerRealTimeTaskTracker
|
||||
import com.cobblemon.mod.common.api.scheduling.ServerTaskTracker
|
||||
import com.cobblemon.mod.common.api.spawning.BestSpawner
|
||||
import com.cobblemon.mod.common.api.spawning.CobblemonSpawningProspector
|
||||
import com.cobblemon.mod.common.api.spawning.context.AreaContextResolver
|
||||
@@ -54,12 +59,14 @@ import com.cobblemon.mod.common.api.storage.adapter.flatfile.FileStoreAdapter
|
||||
import com.cobblemon.mod.common.api.storage.adapter.flatfile.JSONStoreAdapter
|
||||
import com.cobblemon.mod.common.api.storage.adapter.flatfile.NBTStoreAdapter
|
||||
import com.cobblemon.mod.common.api.storage.factory.FileBackedPokemonStoreFactory
|
||||
import com.cobblemon.mod.common.api.storage.molang.NbtMoLangDataStoreFactory
|
||||
import com.cobblemon.mod.common.api.storage.pc.PCStore
|
||||
import com.cobblemon.mod.common.api.storage.pc.link.PCLinkManager
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerDataStoreManager
|
||||
import com.cobblemon.mod.common.api.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
|
||||
@@ -67,6 +74,7 @@ import com.cobblemon.mod.common.battles.BattleSide
|
||||
import com.cobblemon.mod.common.battles.ShowdownThread
|
||||
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.command.argument.DialogueArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.MoveArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PartySlotArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PokemonArgumentType
|
||||
@@ -94,6 +102,7 @@ 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
|
||||
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
|
||||
import com.cobblemon.mod.common.sherds.CobblemonSherds
|
||||
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
|
||||
import com.cobblemon.mod.common.trade.TradeManager
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
@@ -110,15 +119,6 @@ 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
|
||||
@@ -128,12 +128,23 @@ import net.minecraft.registry.RegistryKey
|
||||
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"))
|
||||
@@ -153,6 +164,7 @@ object Cobblemon {
|
||||
val bestSpawner = BestSpawner
|
||||
val battleRegistry = BattleRegistry
|
||||
var storage = PokemonStoreManager()
|
||||
var molangData = NbtMoLangDataStoreFactory
|
||||
lateinit var playerData: PlayerDataStoreManager
|
||||
lateinit var starterConfig: StarterConfig
|
||||
val dataProvider: DataProvider = CobblemonDataProvider
|
||||
@@ -162,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()
|
||||
@@ -224,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() }
|
||||
}
|
||||
@@ -231,6 +254,17 @@ object Cobblemon {
|
||||
TrackedDataHandlerRegistry.register(Vec3DataSerializer)
|
||||
TrackedDataHandlerRegistry.register(StringSetDataSerializer)
|
||||
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)
|
||||
}
|
||||
@@ -246,6 +280,7 @@ object Cobblemon {
|
||||
|
||||
SpeciesFeatures.types["choice"] = ChoiceSpeciesFeatureProvider::class.java
|
||||
SpeciesFeatures.types["flag"] = FlagSpeciesFeatureProvider::class.java
|
||||
SpeciesFeatures.types["integer"] = IntSpeciesFeatureProvider::class.java
|
||||
|
||||
SpeciesFeatures.register(
|
||||
DataKeys.CAN_BE_MILKED,
|
||||
@@ -260,9 +295,15 @@ object Cobblemon {
|
||||
|
||||
ifDedicatedServer {
|
||||
isDedicatedServer = true
|
||||
PlatformEvents.SERVER_TICK_POST.subscribe { ScheduledTaskTracker.update() }
|
||||
}
|
||||
|
||||
PlatformEvents.SERVER_TICK_POST.subscribe {
|
||||
ServerTaskTracker.update(1/20F)
|
||||
ServerRealTimeTaskTracker.update()
|
||||
}
|
||||
PlatformEvents.SERVER_TICK_PRE.subscribe {
|
||||
ServerRealTimeTaskTracker.update()
|
||||
}
|
||||
PlatformEvents.SERVER_STARTING.subscribe { event ->
|
||||
val server = event.server
|
||||
playerData = PlayerDataStoreManager().also { it.setup(server) }
|
||||
@@ -375,6 +416,8 @@ object Cobblemon {
|
||||
true
|
||||
).ifSuccessful { it.mute = true }
|
||||
}
|
||||
|
||||
CobblemonSherds.registerSherds()
|
||||
}
|
||||
|
||||
fun getLevel(dimension: RegistryKey<World>): World? {
|
||||
@@ -478,6 +521,7 @@ object Cobblemon {
|
||||
this.implementation.registerCommandArgument(cobblemonResource("move"), MoveArgumentType::class, ConstantArgumentSerializer.of(MoveArgumentType::move))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("party_slot"), PartySlotArgumentType::class, ConstantArgumentSerializer.of(PartySlotArgumentType::partySlot))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("pokemon_store"), PokemonStoreArgumentType::class, ConstantArgumentSerializer.of(PokemonStoreArgumentType::pokemonStore))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("dialogue"), DialogueArgumentType::class, ConstantArgumentSerializer.of(DialogueArgumentType::dialogue))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import net.minecraft.entity.ai.brain.Activity
|
||||
|
||||
object CobblemonActivities {
|
||||
val activities = mutableListOf<Activity>()
|
||||
val BATTLING_ACTIVITY = Activity("pokemon_battling")
|
||||
|
||||
fun register(activity: Activity): Activity {
|
||||
activities.add(activity)
|
||||
return activity
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,16 @@
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.block.entity.BerryBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.HealingMachineBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.PCBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.PokemonPastureBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.FossilAnalyzerBlockEntity
|
||||
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
|
||||
@@ -23,9 +32,13 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
|
||||
|
||||
@JvmField
|
||||
val HEALING_MACHINE: BlockEntityType<HealingMachineBlockEntity> = this.create("healing_machine", BlockEntityType.Builder.create(::HealingMachineBlockEntity, CobblemonBlocks.HEALING_MACHINE).build(null))
|
||||
|
||||
@JvmField
|
||||
val PC: BlockEntityType<PCBlockEntity> = this.create("pc", BlockEntityType.Builder.create(::PCBlockEntity, CobblemonBlocks.PC).build(null))
|
||||
|
||||
@JvmField
|
||||
val BERRY = this.create("berry", BlockEntityType.Builder.create(::BerryBlockEntity, *CobblemonBlocks.berries().values.toTypedArray()).build(null))
|
||||
|
||||
@JvmField
|
||||
val PASTURE: BlockEntityType<PokemonPastureBlockEntity> = this.create("pasture", BlockEntityType.Builder.create(::PokemonPastureBlockEntity, CobblemonBlocks.PASTURE).build(null))
|
||||
@JvmField
|
||||
@@ -33,4 +46,41 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
|
||||
@JvmField
|
||||
val HANGING_SIGN: BlockEntityType<CobblemonHangingSignBlockEntity> = this.create("hanging_sign", BlockEntityType.Builder.create(::CobblemonHangingSignBlockEntity, CobblemonBlocks.APRICORN_HANGING_SIGN, CobblemonBlocks.APRICORN_WALL_HANGING_SIGN).build(null))
|
||||
|
||||
}
|
||||
@JvmField
|
||||
val GILDED_CHEST: BlockEntityType<GildedChestBlockEntity> = this.create("chest", BlockEntityType.Builder.create(::GildedChestBlockEntity,
|
||||
CobblemonBlocks.GILDED_CHEST,
|
||||
CobblemonBlocks.BLUE_GILDED_CHEST,
|
||||
CobblemonBlocks.YELLOW_GILDED_CHEST,
|
||||
CobblemonBlocks.PINK_GILDED_CHEST,
|
||||
CobblemonBlocks.BLACK_GILDED_CHEST,
|
||||
CobblemonBlocks.WHITE_GILDED_CHEST,
|
||||
CobblemonBlocks.GREEN_GILDED_CHEST,
|
||||
CobblemonBlocks.GIMMIGHOUL_CHEST
|
||||
).build(null))
|
||||
|
||||
@JvmField
|
||||
val FOSSIL_MULTIBLOCK: BlockEntityType<FossilMultiblockEntity> = this.create("fossil_multiblock",
|
||||
BlockEntityType.Builder.create({ pos, state -> FossilMultiblockEntity(pos, state, FossilMultiblockBuilder(pos)) },
|
||||
CobblemonBlocks.MONITOR
|
||||
).build(null)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val RESTORATION_TANK: BlockEntityType<RestorationTankBlockEntity> = this.create("restoration_tank",
|
||||
BlockEntityType.Builder.create({ pos, state -> RestorationTankBlockEntity(pos, state, FossilMultiblockBuilder(pos)) },
|
||||
CobblemonBlocks.RESTORATION_TANK
|
||||
).build(null)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val FOSSIL_ANALYZER: BlockEntityType<FossilAnalyzerBlockEntity> = this.create("fossil_analyzer",
|
||||
BlockEntityType.Builder.create({ pos, state -> FossilAnalyzerBlockEntity(pos, state, FossilMultiblockBuilder(pos)) },
|
||||
CobblemonBlocks.FOSSIL_ANALYZER
|
||||
).build(null)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val DISPLAY_CASE: BlockEntityType<DisplayCaseBlockEntity> = this.create("display_case",
|
||||
BlockEntityType.Builder.create(::DisplayCaseBlockEntity, CobblemonBlocks.DISPLAY_CASE).build(null)
|
||||
)
|
||||
}
|
||||
@@ -11,6 +11,9 @@ package com.cobblemon.mod.common
|
||||
import com.cobblemon.mod.common.api.apricorn.Apricorn
|
||||
import com.cobblemon.mod.common.block.*
|
||||
import com.cobblemon.mod.common.block.MintBlock.MintType
|
||||
import com.cobblemon.mod.common.block.FossilAnalyzerBlock
|
||||
import com.cobblemon.mod.common.block.MonitorBlock
|
||||
import com.cobblemon.mod.common.block.RestorationTankBlock
|
||||
import com.cobblemon.mod.common.mixin.invoker.DoorBlockInvoker
|
||||
import com.cobblemon.mod.common.mixin.invoker.PressurePlateBlockInvoker
|
||||
import com.cobblemon.mod.common.mixin.invoker.StairsBlockInvoker
|
||||
@@ -19,11 +22,13 @@ import com.cobblemon.mod.common.mixin.invoker.*
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.block.BerryBlock
|
||||
import com.cobblemon.mod.common.block.chest.GildedChestBlock
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonHangingSignBlock
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonSignBlock
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonWallHangingSignBlock
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonWallSignBlock
|
||||
import net.minecraft.block.*
|
||||
import net.minecraft.block.enums.Instrument
|
||||
import net.minecraft.block.piston.PistonBehavior
|
||||
import net.minecraft.entity.effect.StatusEffects
|
||||
import net.minecraft.registry.Registries
|
||||
@@ -53,6 +58,8 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
@JvmField
|
||||
val FIRE_STONE_ORE = evolutionStoneOre("fire_stone_ore")
|
||||
@JvmField
|
||||
val NETHER_FIRE_STONE_ORE = evolutionStoneOre("nether_fire_stone_ore")
|
||||
@JvmField
|
||||
val ICE_STONE_ORE = evolutionStoneOre("ice_stone_ore")
|
||||
@JvmField
|
||||
val LEAF_STONE_ORE = evolutionStoneOre("leaf_stone_ore")
|
||||
@@ -65,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")
|
||||
@@ -100,17 +109,17 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
@JvmField
|
||||
val STRIPPED_APRICORN_WOOD = log("stripped_apricorn_wood")
|
||||
@JvmField
|
||||
val APRICORN_PLANKS = this.create("apricorn_planks", Block(AbstractBlock.Settings.create().mapColor(MapColor.DIRT_BROWN).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
|
||||
val APRICORN_PLANKS = this.create("apricorn_planks", Block(AbstractBlock.Settings.create().mapColor(MapColor.DIRT_BROWN).instrument(Instrument.BASS).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
|
||||
@JvmField
|
||||
val APRICORN_LEAVES = leaves("apricorn_leaves")
|
||||
@JvmField
|
||||
val APRICORN_FENCE = this.create("apricorn_fence", FenceBlock(AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
|
||||
val APRICORN_FENCE = this.create("apricorn_fence", FenceBlock(AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).instrument(Instrument.BASS).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
|
||||
@JvmField
|
||||
val APRICORN_FENCE_GATE = this.create("apricorn_fence_gate", FenceGateBlock(AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD), APRICORN_WOOD_TYPE))
|
||||
val APRICORN_FENCE_GATE = this.create("apricorn_fence_gate", FenceGateBlock(AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).instrument(Instrument.BASS).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD), APRICORN_WOOD_TYPE))
|
||||
@JvmField // Note At the time of 1.20.0 we don't need our own BlockSetType for Apricorn wood
|
||||
val APRICORN_BUTTON = this.create("apricorn_button", BlocksInvoker.createWoodenButtonBlock(BlockSetType.OAK))
|
||||
@JvmField
|
||||
val APRICORN_PRESSURE_PLATE = this.create("apricorn_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(PressurePlateBlock.ActivationRule.EVERYTHING, AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).noCollision().strength(0.5f).sounds(BlockSoundGroup.WOOD), APRICORN_BLOCK_SET_TYPE))
|
||||
val APRICORN_PRESSURE_PLATE = this.create("apricorn_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(PressurePlateBlock.ActivationRule.EVERYTHING, AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).instrument(Instrument.BASS).noCollision().strength(0.5f).sounds(BlockSoundGroup.WOOD), APRICORN_BLOCK_SET_TYPE))
|
||||
@JvmField
|
||||
val APRICORN_SIGN = this.create("apricorn_sign", CobblemonSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_SIGN), APRICORN_WOOD_TYPE))
|
||||
@JvmField
|
||||
@@ -120,13 +129,13 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
@JvmField
|
||||
val APRICORN_WALL_HANGING_SIGN = this.create("apricorn_wall_hanging_sign", CobblemonWallHangingSignBlock(AbstractBlock.Settings.copy(Blocks.OAK_HANGING_SIGN), APRICORN_WOOD_TYPE))
|
||||
@JvmField
|
||||
val APRICORN_SLAB = this.create("apricorn_slab", SlabBlock(AbstractBlock.Settings.create().mapColor(MapColor.OAK_TAN).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
|
||||
val APRICORN_SLAB = this.create("apricorn_slab", SlabBlock(AbstractBlock.Settings.create().mapColor(MapColor.OAK_TAN).instrument(Instrument.BASS).strength(2.0f, 3.0f).sounds(BlockSoundGroup.WOOD)))
|
||||
@JvmField
|
||||
val APRICORN_STAIRS = this.create("apricorn_stairs", StairsBlockInvoker.`cobblemon$create`(APRICORN_PLANKS.defaultState, AbstractBlock.Settings.copy(APRICORN_PLANKS)))
|
||||
@JvmField
|
||||
val APRICORN_DOOR = this.create("apricorn_door", DoorBlockInvoker.`cobblemon$create`(AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).strength(3.0F).sounds(BlockSoundGroup.WOOD).nonOpaque(), APRICORN_BLOCK_SET_TYPE))
|
||||
val APRICORN_DOOR = this.create("apricorn_door", DoorBlockInvoker.`cobblemon$create`(AbstractBlock.Settings.create().mapColor(APRICORN_PLANKS.defaultMapColor).instrument(Instrument.BASS).strength(3.0F).sounds(BlockSoundGroup.WOOD).nonOpaque(), APRICORN_BLOCK_SET_TYPE))
|
||||
@JvmField
|
||||
val APRICORN_TRAPDOOR = this.create("apricorn_trapdoor", TrapdoorBlockInvoker.`cobblemon$create`(AbstractBlock.Settings.create().mapColor(MapColor.OAK_TAN).strength(3.0F).sounds(BlockSoundGroup.WOOD).nonOpaque().allowsSpawning { _, _, _, _ -> false }, APRICORN_BLOCK_SET_TYPE))
|
||||
val APRICORN_TRAPDOOR = this.create("apricorn_trapdoor", TrapdoorBlockInvoker.`cobblemon$create`(AbstractBlock.Settings.create().mapColor(MapColor.OAK_TAN).instrument(Instrument.BASS).strength(3.0F).sounds(BlockSoundGroup.WOOD).nonOpaque().allowsSpawning { _, _, _, _ -> false }, APRICORN_BLOCK_SET_TYPE))
|
||||
|
||||
private val PLANT_PROPERTIES = AbstractBlock.Settings.create().mapColor(MapColor.DARK_GREEN).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.GRASS).pistonBehavior(PistonBehavior.DESTROY)
|
||||
@JvmField
|
||||
@@ -145,14 +154,66 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
val YELLOW_APRICORN_SAPLING = this.create("yellow_apricorn_sapling", ApricornSaplingBlock(PLANT_PROPERTIES, Apricorn.YELLOW))
|
||||
|
||||
@JvmField
|
||||
val MEDICINAL_LEEK = this.create("medicinal_leek", MedicinalLeekBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DULL_RED).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
|
||||
val MEDICINAL_LEEK = this.create("medicinal_leek", MedicinalLeekBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DULL_RED).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MEDICINAL_LEEK_SOUNDS)))
|
||||
@JvmField
|
||||
val ENERGY_ROOT = this.create("energy_root", EnergyRootBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DIRT_BROWN).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.ROOTS)))
|
||||
val ENERGY_ROOT = this.create("energy_root", EnergyRootBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DIRT_BROWN).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.ENERGY_ROOT_SOUNDS)))
|
||||
@JvmField
|
||||
val BIG_ROOT = this.create("big_root", BigRootBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DARK_GREEN).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.ROOTS)))
|
||||
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)))
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE_CLUSTER = tumblestoneBlock("tumblestone_cluster", GrowableStoneBlock.STAGE_3, 7, 3, null)
|
||||
@JvmField
|
||||
val LARGE_BUDDING_TUMBLESTONE = tumblestoneBlock("large_budding_tumblestone", GrowableStoneBlock.STAGE_2, 5, 3, TUMBLESTONE_CLUSTER)
|
||||
@JvmField
|
||||
val MEDIUM_BUDDING_TUMBLESTONE = tumblestoneBlock("medium_budding_tumblestone", GrowableStoneBlock.STAGE_1, 4, 3, LARGE_BUDDING_TUMBLESTONE)
|
||||
@JvmField
|
||||
val SMALL_BUDDING_TUMBLESTONE = tumblestoneBlock("small_budding_tumblestone", GrowableStoneBlock.STAGE_0, 3, 4, MEDIUM_BUDDING_TUMBLESTONE)
|
||||
|
||||
@JvmField
|
||||
val SKY_TUMBLESTONE_CLUSTER = tumblestoneBlock("sky_tumblestone_cluster", GrowableStoneBlock.STAGE_3, 7, 3, null)
|
||||
@JvmField
|
||||
val LARGE_BUDDING_SKY_TUMBLESTONE = tumblestoneBlock("large_budding_sky_tumblestone", GrowableStoneBlock.STAGE_2, 5, 3, SKY_TUMBLESTONE_CLUSTER)
|
||||
@JvmField
|
||||
val MEDIUM_BUDDING_SKY_TUMBLESTONE = tumblestoneBlock("medium_budding_sky_tumblestone", GrowableStoneBlock.STAGE_1, 4, 3, LARGE_BUDDING_SKY_TUMBLESTONE)
|
||||
@JvmField
|
||||
val SMALL_BUDDING_SKY_TUMBLESTONE = tumblestoneBlock("small_budding_sky_tumblestone", GrowableStoneBlock.STAGE_0, 3, 4, MEDIUM_BUDDING_SKY_TUMBLESTONE)
|
||||
|
||||
@JvmField
|
||||
val BLACK_TUMBLESTONE_CLUSTER = tumblestoneBlock("black_tumblestone_cluster", GrowableStoneBlock.STAGE_3, 7, 3, null)
|
||||
@JvmField
|
||||
val LARGE_BUDDING_BLACK_TUMBLESTONE = tumblestoneBlock("large_budding_black_tumblestone", GrowableStoneBlock.STAGE_2, 5, 3, BLACK_TUMBLESTONE_CLUSTER)
|
||||
@JvmField
|
||||
val MEDIUM_BUDDING_BLACK_TUMBLESTONE = tumblestoneBlock("medium_budding_black_tumblestone", GrowableStoneBlock.STAGE_1, 4, 3, LARGE_BUDDING_BLACK_TUMBLESTONE)
|
||||
@JvmField
|
||||
val SMALL_BUDDING_BLACK_TUMBLESTONE = tumblestoneBlock("small_budding_black_tumblestone", GrowableStoneBlock.STAGE_0, 3, 4, MEDIUM_BUDDING_BLACK_TUMBLESTONE)
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE_BLOCK = this.create("tumblestone_block", Block(AbstractBlock.Settings.create()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
.strength(1.0F)
|
||||
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresTool()
|
||||
.instrument(Instrument.BASEDRUM)
|
||||
))
|
||||
@JvmField
|
||||
val SKY_TUMBLESTONE_BLOCK = this.create("sky_tumblestone_block", Block(AbstractBlock.Settings.create()
|
||||
.mapColor(MapColor.LIGHT_BLUE)
|
||||
.strength(1.0F)
|
||||
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresTool()
|
||||
.instrument(Instrument.BASEDRUM)
|
||||
))
|
||||
@JvmField
|
||||
val BLACK_TUMBLESTONE_BLOCK = this.create("black_tumblestone_block", Block(AbstractBlock.Settings.create()
|
||||
.mapColor(MapColor.TERRACOTTA_BLACK)
|
||||
.strength(1.0F)
|
||||
.sounds(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresTool()
|
||||
.instrument(Instrument.BASEDRUM)
|
||||
))
|
||||
|
||||
@JvmField
|
||||
val BLACK_APRICORN = apricornBlock("black_apricorn", Apricorn.BLACK)
|
||||
@JvmField
|
||||
@@ -168,6 +229,138 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
@JvmField
|
||||
val YELLOW_APRICORN = apricornBlock("yellow_apricorn", Apricorn.YELLOW)
|
||||
|
||||
@JvmField
|
||||
val RELIC_COIN_POUCH = create(
|
||||
"relic_coin_pouch",
|
||||
CoinPouchBlock(
|
||||
AbstractBlock.Settings.create()
|
||||
.sounds(CobblemonSounds.COIN_POUCH_SOUNDS)
|
||||
.pistonBehavior(PistonBehavior.DESTROY)
|
||||
.strength(0.4f)
|
||||
.nonOpaque(), true
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val RELIC_COIN_SACK = create(
|
||||
"relic_coin_sack",
|
||||
CoinPouchBlock(
|
||||
AbstractBlock.Settings.create()
|
||||
.sounds(CobblemonSounds.COIN_POUCH_SOUNDS)
|
||||
.pistonBehavior(PistonBehavior.DESTROY)
|
||||
.strength(0.4f), false
|
||||
))
|
||||
|
||||
@JvmField
|
||||
val GILDED_CHEST = create(
|
||||
"gilded_chest",
|
||||
GildedChestBlock(
|
||||
AbstractBlock.Settings.copy(Blocks.CHEST).nonOpaque().sounds(CobblemonSounds.GILDED_CHEST_SOUNDS),
|
||||
GildedChestBlock.Type.RED
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val BLUE_GILDED_CHEST = create(
|
||||
"blue_gilded_chest",
|
||||
GildedChestBlock(
|
||||
AbstractBlock.Settings.copy(Blocks.CHEST).nonOpaque().sounds(CobblemonSounds.GILDED_CHEST_SOUNDS),
|
||||
GildedChestBlock.Type.BLUE
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val BLACK_GILDED_CHEST = create(
|
||||
"black_gilded_chest",
|
||||
GildedChestBlock(
|
||||
AbstractBlock.Settings.copy(Blocks.CHEST).nonOpaque().sounds(CobblemonSounds.GILDED_CHEST_SOUNDS),
|
||||
GildedChestBlock.Type.BLACK
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val YELLOW_GILDED_CHEST = create(
|
||||
"yellow_gilded_chest",
|
||||
GildedChestBlock(
|
||||
AbstractBlock.Settings.copy(Blocks.CHEST).nonOpaque().sounds(CobblemonSounds.GILDED_CHEST_SOUNDS),
|
||||
GildedChestBlock.Type.YELLOW
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val WHITE_GILDED_CHEST = create(
|
||||
"white_gilded_chest",
|
||||
GildedChestBlock(
|
||||
AbstractBlock.Settings.copy(Blocks.CHEST).nonOpaque().sounds(CobblemonSounds.GILDED_CHEST_SOUNDS),
|
||||
GildedChestBlock.Type.WHITE
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val GREEN_GILDED_CHEST = create(
|
||||
"green_gilded_chest",
|
||||
GildedChestBlock(
|
||||
AbstractBlock.Settings.copy(Blocks.CHEST).nonOpaque().sounds(CobblemonSounds.GILDED_CHEST_SOUNDS),
|
||||
GildedChestBlock.Type.GREEN
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val PINK_GILDED_CHEST = create(
|
||||
"pink_gilded_chest",
|
||||
GildedChestBlock(
|
||||
AbstractBlock.Settings.copy(Blocks.CHEST).nonOpaque().sounds(CobblemonSounds.GILDED_CHEST_SOUNDS),
|
||||
GildedChestBlock.Type.PINK
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val GIMMIGHOUL_CHEST = create(
|
||||
"gimmighoul_chest",
|
||||
GildedChestBlock(
|
||||
AbstractBlock.Settings.copy(Blocks.CHEST).nonOpaque().sounds(CobblemonSounds.GILDED_CHEST_SOUNDS),
|
||||
GildedChestBlock.Type.FAKE
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val MONITOR = create(
|
||||
"monitor",
|
||||
MonitorBlock(
|
||||
AbstractBlock.Settings.create()
|
||||
.mapColor(MapColor.IRON_GRAY)
|
||||
.sounds(BlockSoundGroup.METAL)
|
||||
.pistonBehavior(PistonBehavior.BLOCK)
|
||||
.requiresTool()
|
||||
.strength(5.0F, 6.0F)
|
||||
.luminance { if (it.get(MonitorBlock.SCREEN) != MonitorBlock.MonitorScreen.OFF) 15 else 0 }
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val FOSSIL_ANALYZER = create(
|
||||
"fossil_analyzer",
|
||||
FossilAnalyzerBlock(
|
||||
AbstractBlock.Settings.create()
|
||||
.mapColor(MapColor.IRON_GRAY)
|
||||
.sounds(BlockSoundGroup.METAL)
|
||||
.pistonBehavior(PistonBehavior.BLOCK)
|
||||
.requiresTool()
|
||||
.strength(5.0F, 6.0F)
|
||||
.nonOpaque()
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val RESTORATION_TANK = create(
|
||||
"restoration_tank",
|
||||
RestorationTankBlock(
|
||||
AbstractBlock.Settings.create()
|
||||
.mapColor(MapColor.IRON_GRAY)
|
||||
.sounds(BlockSoundGroup.GLASS)
|
||||
.pistonBehavior(PistonBehavior.BLOCK)
|
||||
.requiresTool()
|
||||
.strength(5.0F, 6.0F)
|
||||
.nonOpaque()
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val HEALING_MACHINE = create(
|
||||
"healing_machine",
|
||||
@@ -196,17 +389,29 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val RED_MINT = create("red_mint", MintBlock(MintType.RED, AbstractBlock.Settings.create().mapColor(MapColor.RED).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
|
||||
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(BlockSoundGroup.CROP)))
|
||||
val BLUE_MINT = create("blue_mint", MintBlock(MintType.BLUE, AbstractBlock.Settings.create().mapColor(MapColor.BLUE).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MINT_SOUNDS)))
|
||||
@JvmField
|
||||
val CYAN_MINT = create("cyan_mint", MintBlock(MintType.CYAN, AbstractBlock.Settings.create().mapColor(MapColor.CYAN).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
|
||||
val CYAN_MINT = create("cyan_mint", MintBlock(MintType.CYAN, AbstractBlock.Settings.create().mapColor(MapColor.CYAN).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MINT_SOUNDS)))
|
||||
@JvmField
|
||||
val PINK_MINT = create("pink_mint", MintBlock(MintType.PINK, AbstractBlock.Settings.create().mapColor(MapColor.PINK).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
|
||||
val PINK_MINT = create("pink_mint", MintBlock(MintType.PINK, AbstractBlock.Settings.create().mapColor(MapColor.PINK).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MINT_SOUNDS)))
|
||||
@JvmField
|
||||
val GREEN_MINT = create("green_mint", MintBlock(MintType.GREEN, AbstractBlock.Settings.create().mapColor(MapColor.GREEN).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
|
||||
val GREEN_MINT = create("green_mint", MintBlock(MintType.GREEN, AbstractBlock.Settings.create().mapColor(MapColor.GREEN).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MINT_SOUNDS)))
|
||||
@JvmField
|
||||
val WHITE_MINT = create("white_mint", MintBlock(MintType.WHITE, AbstractBlock.Settings.create().mapColor(MapColor.WHITE).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
|
||||
val WHITE_MINT = create("white_mint", MintBlock(MintType.WHITE, AbstractBlock.Settings.create().mapColor(MapColor.WHITE).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.MINT_SOUNDS)))
|
||||
|
||||
@JvmField
|
||||
val PASTURE = create(
|
||||
@@ -243,6 +448,15 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
|
||||
private fun apricornBlock(name: String, apricorn: Apricorn): ApricornBlock = this.create(name, ApricornBlock(AbstractBlock.Settings.create().mapColor(apricorn.mapColor()).ticksRandomly().strength(Blocks.OAK_LOG.hardness, Blocks.OAK_LOG.blastResistance).sounds(BlockSoundGroup.WOOD).nonOpaque(), apricorn))
|
||||
|
||||
private fun tumblestoneBlock(name: String, stage: Int, height: Int, xzOffset: Int, nextStage: Block?) : Block {
|
||||
return this.create(name, TumblestoneBlock(AbstractBlock.Settings.create()
|
||||
.pistonBehavior(PistonBehavior.DESTROY)
|
||||
.nonOpaque()
|
||||
.strength(1.5F)
|
||||
.sounds(CobblemonSounds.TUMBLESTONE_SOUNDS),
|
||||
stage, height, xzOffset, nextStage))
|
||||
}
|
||||
|
||||
private val berries = mutableMapOf<Identifier, BerryBlock>()
|
||||
|
||||
val AGUAV_BERRY = this.berryBlock("aguav")
|
||||
@@ -338,7 +552,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
|
||||
private fun berryBlock(name: String): BerryBlock {
|
||||
val identifier = cobblemonResource("${name}_berry")
|
||||
val block = this.create(identifier.path, BerryBlock(identifier, AbstractBlock.Settings.copy(Blocks.WHEAT).dynamicBounds().sounds(BlockSoundGroup.CROP).strength(0.2F)))
|
||||
val block = this.create(identifier.path, BerryBlock(identifier, AbstractBlock.Settings.copy(Blocks.WHEAT).dynamicBounds().sounds(CobblemonSounds.BERRY_BUSH_SOUNDS).strength(0.2F)))
|
||||
this.berries[identifier] = block
|
||||
return block
|
||||
}
|
||||
|
||||
@@ -47,5 +47,10 @@ object CobblemonCommands {
|
||||
ClearPCCommand.register(dispatcher)
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common
|
||||
import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatEntity
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonChestBoatEntity
|
||||
import com.cobblemon.mod.common.entity.generic.GenericBedrockEntity
|
||||
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
@@ -65,6 +66,15 @@ object CobblemonEntities : PlatformRegistry<Registry<EntityType<*>>, RegistryKey
|
||||
.build(CHEST_BOAT_KEY.toString())
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val GENERIC_BEDROCK_ENTITY_KEY = cobblemonResource("generic_bedrock")
|
||||
@JvmField
|
||||
val GENERIC_BEDROCK_ENTITY: EntityType<GenericBedrockEntity> = this.create(
|
||||
GENERIC_BEDROCK_ENTITY_KEY.path,
|
||||
EntityType.Builder.create({ _, world -> GenericBedrockEntity(world) }, SpawnGroup.MISC)
|
||||
.build(GENERIC_BEDROCK_ENTITY_KEY.toString())
|
||||
)
|
||||
|
||||
fun registerAttributes(consumer: (EntityType<out LivingEntity>, DefaultAttributeContainer.Builder) -> Unit) {
|
||||
consumer(POKEMON, PokemonEntity.createAttributes())
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -18,6 +19,7 @@ import com.cobblemon.mod.common.block.MintBlock
|
||||
import com.cobblemon.mod.common.block.MintBlock.MintType
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
|
||||
import com.cobblemon.mod.common.item.*
|
||||
import com.cobblemon.mod.common.item.armor.CobblemonArmorTrims
|
||||
import com.cobblemon.mod.common.item.battle.DireHitItem
|
||||
import com.cobblemon.mod.common.item.battle.GuardSpecItem
|
||||
import com.cobblemon.mod.common.item.battle.XStatItem
|
||||
@@ -28,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
|
||||
@@ -36,13 +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.StewItem
|
||||
import net.minecraft.item.*
|
||||
import net.minecraft.registry.Registries
|
||||
import net.minecraft.registry.Registry
|
||||
import net.minecraft.registry.RegistryKey
|
||||
@@ -121,6 +119,38 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
val MASTER_BALL = pokeBallItem(PokeBalls.MASTER_BALL)
|
||||
@JvmField
|
||||
val CHERISH_BALL = pokeBallItem(PokeBalls.CHERISH_BALL)
|
||||
@JvmField
|
||||
val ANCIENT_POKE_BALL = pokeBallItem(PokeBalls.ANCIENT_POKE_BALL)
|
||||
@JvmField
|
||||
val ANCIENT_CITRINE_BALL = pokeBallItem(PokeBalls.ANCIENT_CITRINE_BALL)
|
||||
@JvmField
|
||||
val ANCIENT_VERDANT_BALL = pokeBallItem(PokeBalls.ANCIENT_VERDANT_BALL)
|
||||
@JvmField
|
||||
val ANCIENT_AZURE_BALL = pokeBallItem(PokeBalls.ANCIENT_AZURE_BALL)
|
||||
@JvmField
|
||||
val ANCIENT_ROSEATE_BALL = pokeBallItem(PokeBalls.ANCIENT_ROSEATE_BALL)
|
||||
@JvmField
|
||||
val ANCIENT_SLATE_BALL = pokeBallItem(PokeBalls.ANCIENT_SLATE_BALL)
|
||||
@JvmField
|
||||
val ANCIENT_IVORY_BALL = pokeBallItem(PokeBalls.ANCIENT_IVORY_BALL)
|
||||
@JvmField
|
||||
val ANCIENT_GREAT_BALL = pokeBallItem(PokeBalls.ANCIENT_GREAT_BALL)
|
||||
@JvmField
|
||||
val ANCIENT_ULTRA_BALL = pokeBallItem(PokeBalls.ANCIENT_ULTRA_BALL)
|
||||
@JvmField
|
||||
val ANCIENT_FEATHER_BALL = pokeBallItem(PokeBalls.ANCIENT_FEATHER_BALL)
|
||||
@JvmField
|
||||
val ANCIENT_WING_BALL = pokeBallItem(PokeBalls.ANCIENT_WING_BALL)
|
||||
@JvmField
|
||||
val ANCIENT_JET_BALL = pokeBallItem(PokeBalls.ANCIENT_JET_BALL)
|
||||
@JvmField
|
||||
val ANCIENT_HEAVY_BALL = pokeBallItem(PokeBalls.ANCIENT_HEAVY_BALL)
|
||||
@JvmField
|
||||
val ANCIENT_LEADEN_BALL = pokeBallItem(PokeBalls.ANCIENT_LEADEN_BALL)
|
||||
@JvmField
|
||||
val ANCIENT_GIGATON_BALL = pokeBallItem(PokeBalls.ANCIENT_GIGATON_BALL)
|
||||
@JvmField
|
||||
val ANCIENT_ORIGIN_BALL = pokeBallItem(PokeBalls.ANCIENT_ORIGIN_BALL)
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE = compostableItem("vivichoke")
|
||||
@@ -144,19 +174,19 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
val WHITE_APRICORN = apricornItem("white", ApricornItem(CobblemonBlocks.WHITE_APRICORN))
|
||||
|
||||
@JvmField
|
||||
val RED_APRICORN_SEED = apricornSeedItem("red", ApricornSeedItem(CobblemonBlocks.RED_APRICORN_SAPLING))
|
||||
val RED_APRICORN_SEED = apricornSeedItem("red", ApricornSeedItem(CobblemonBlocks.RED_APRICORN_SAPLING, CobblemonBlocks.RED_APRICORN))
|
||||
@JvmField
|
||||
val YELLOW_APRICORN_SEED = apricornSeedItem("yellow", ApricornSeedItem(CobblemonBlocks.YELLOW_APRICORN_SAPLING))
|
||||
val YELLOW_APRICORN_SEED = apricornSeedItem("yellow", ApricornSeedItem(CobblemonBlocks.YELLOW_APRICORN_SAPLING, CobblemonBlocks.YELLOW_APRICORN))
|
||||
@JvmField
|
||||
val GREEN_APRICORN_SEED = apricornSeedItem("green", ApricornSeedItem(CobblemonBlocks.GREEN_APRICORN_SAPLING))
|
||||
val GREEN_APRICORN_SEED = apricornSeedItem("green", ApricornSeedItem(CobblemonBlocks.GREEN_APRICORN_SAPLING, CobblemonBlocks.GREEN_APRICORN))
|
||||
@JvmField
|
||||
val BLUE_APRICORN_SEED = apricornSeedItem("blue", ApricornSeedItem(CobblemonBlocks.BLUE_APRICORN_SAPLING))
|
||||
val BLUE_APRICORN_SEED = apricornSeedItem("blue", ApricornSeedItem(CobblemonBlocks.BLUE_APRICORN_SAPLING, CobblemonBlocks.BLUE_APRICORN))
|
||||
@JvmField
|
||||
val PINK_APRICORN_SEED = apricornSeedItem("pink", ApricornSeedItem(CobblemonBlocks.PINK_APRICORN_SAPLING))
|
||||
val PINK_APRICORN_SEED = apricornSeedItem("pink", ApricornSeedItem(CobblemonBlocks.PINK_APRICORN_SAPLING, CobblemonBlocks.PINK_APRICORN))
|
||||
@JvmField
|
||||
val BLACK_APRICORN_SEED = apricornSeedItem("black", ApricornSeedItem(CobblemonBlocks.BLACK_APRICORN_SAPLING))
|
||||
val BLACK_APRICORN_SEED = apricornSeedItem("black", ApricornSeedItem(CobblemonBlocks.BLACK_APRICORN_SAPLING, CobblemonBlocks.BLACK_APRICORN))
|
||||
@JvmField
|
||||
val WHITE_APRICORN_SEED = apricornSeedItem("white", ApricornSeedItem(CobblemonBlocks.WHITE_APRICORN_SAPLING))
|
||||
val WHITE_APRICORN_SEED = apricornSeedItem("white", ApricornSeedItem(CobblemonBlocks.WHITE_APRICORN_SAPLING, CobblemonBlocks.WHITE_APRICORN))
|
||||
|
||||
@JvmField
|
||||
val APRICORN_LOG = blockItem("apricorn_log", CobblemonBlocks.APRICORN_LOG)
|
||||
@@ -195,13 +225,37 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
val APRICORN_SIGN = this.create("apricorn_sign", SignItem(Item.Settings().maxCount(16), CobblemonBlocks.APRICORN_SIGN, CobblemonBlocks.APRICORN_WALL_SIGN))
|
||||
@JvmField
|
||||
val APRICORN_HANGING_SIGN = this.create("apricorn_hanging_sign", HangingSignItem(CobblemonBlocks.APRICORN_HANGING_SIGN, CobblemonBlocks.APRICORN_WALL_HANGING_SIGN, Item.Settings().maxCount(16)))
|
||||
@JvmField
|
||||
val GILDED_CHEST = this.create("gilded_chest", BlockItem(CobblemonBlocks.GILDED_CHEST, Item.Settings()))
|
||||
@JvmField
|
||||
val BLUE_GILDED_CHEST = this.create("blue_gilded_chest", BlockItem(CobblemonBlocks.BLUE_GILDED_CHEST, Item.Settings()))
|
||||
@JvmField
|
||||
val YELLOW_GILDED_CHEST = this.create("yellow_gilded_chest", BlockItem(CobblemonBlocks.YELLOW_GILDED_CHEST, Item.Settings()))
|
||||
@JvmField
|
||||
val PINK_GILDED_CHEST = this.create("pink_gilded_chest", BlockItem(CobblemonBlocks.PINK_GILDED_CHEST, Item.Settings()))
|
||||
@JvmField
|
||||
val BLACK_GILDED_CHEST = this.create("black_gilded_chest", BlockItem(CobblemonBlocks.BLACK_GILDED_CHEST, Item.Settings()))
|
||||
@JvmField
|
||||
val WHITE_GILDED_CHEST = this.create("white_gilded_chest", BlockItem(CobblemonBlocks.WHITE_GILDED_CHEST, Item.Settings()))
|
||||
@JvmField
|
||||
val GREEN_GILDED_CHEST = this.create("green_gilded_chest", BlockItem(CobblemonBlocks.GREEN_GILDED_CHEST, Item.Settings()))
|
||||
@JvmField
|
||||
val GIMMIGHOUL_CHEST = this.create("gimmighoul_chest", BlockItem(CobblemonBlocks.GIMMIGHOUL_CHEST, Item.Settings()))
|
||||
|
||||
@JvmField
|
||||
val RESTORATION_TANK = blockItem("restoration_tank", CobblemonBlocks.RESTORATION_TANK)
|
||||
@JvmField
|
||||
val FOSSIL_ANALYZER = blockItem("fossil_analyzer", CobblemonBlocks.FOSSIL_ANALYZER)
|
||||
@JvmField
|
||||
val MONITOR = blockItem("monitor", CobblemonBlocks.MONITOR)
|
||||
@JvmField
|
||||
val HEALING_MACHINE = blockItem("healing_machine", CobblemonBlocks.HEALING_MACHINE)
|
||||
@JvmField
|
||||
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())
|
||||
@@ -229,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")
|
||||
@@ -340,7 +396,19 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
@JvmField
|
||||
val ZINC = create("zinc", VitaminItem(Stats.SPECIAL_DEFENCE))
|
||||
@JvmField
|
||||
val MEDICINAL_LEEK = create("medicinal_leek", MedicinalLeekItem(CobblemonBlocks.MEDICINAL_LEEK, Item.Settings().food(FoodComponent.Builder().snack().hunger(1).saturationModifier(0.2f).build())))
|
||||
val GENIUS_FEATHER = create("genius_feather", FeatherItem(Stats.SPECIAL_ATTACK))
|
||||
@JvmField
|
||||
val SWIFT_FEATHER = create("swift_feather", FeatherItem(Stats.SPEED))
|
||||
@JvmField
|
||||
val HEALTH_FEATHER = create("health_feather", FeatherItem(Stats.HP))
|
||||
@JvmField
|
||||
val RESIST_FEATHER = create("resist_feather", FeatherItem(Stats.DEFENCE))
|
||||
@JvmField
|
||||
val MUSCLE_FEATHER = create("muscle_feather", FeatherItem(Stats.ATTACK))
|
||||
@JvmField
|
||||
val CLEVER_FEATHER = create("clever_feather", FeatherItem(Stats.SPECIAL_DEFENCE))
|
||||
@JvmField
|
||||
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
|
||||
@@ -490,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
|
||||
*/
|
||||
@@ -510,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)
|
||||
@@ -535,6 +610,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
val DEEPSLATE_WATER_STONE_ORE = blockItem("deepslate_water_stone_ore", CobblemonBlocks.DEEPSLATE_WATER_STONE_ORE)
|
||||
@JvmField
|
||||
val DRIPSTONE_MOON_STONE_ORE = blockItem("dripstone_moon_stone_ore", CobblemonBlocks.DRIPSTONE_MOON_STONE_ORE)
|
||||
@JvmField
|
||||
val NETHER_FIRE_STONE_ORE = blockItem("nether_fire_stone_ore", CobblemonBlocks.NETHER_FIRE_STONE_ORE)
|
||||
|
||||
@JvmField
|
||||
val DAWN_STONE = noSettingsItem("dawn_stone")
|
||||
@JvmField
|
||||
@@ -558,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")
|
||||
@@ -578,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")
|
||||
@@ -608,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")
|
||||
@@ -624,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)
|
||||
@@ -642,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
|
||||
@@ -686,9 +846,145 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
@JvmField
|
||||
val SURPRISE_MULCH = mulchItem("surprise_mulch", MulchVariant.SURPRISE)
|
||||
|
||||
// Archaeology
|
||||
@JvmField
|
||||
val ARMOR_FOSSIL = noSettingsItem("armor_fossil")
|
||||
@JvmField
|
||||
val FOSSILIZED_BIRD = noSettingsItem("fossilized_bird")
|
||||
@JvmField
|
||||
val CLAW_FOSSIL = noSettingsItem("claw_fossil")
|
||||
@JvmField
|
||||
val COVER_FOSSIL = noSettingsItem("cover_fossil")
|
||||
@JvmField
|
||||
val FOSSILIZED_DINO = noSettingsItem("fossilized_dino")
|
||||
@JvmField
|
||||
val DOME_FOSSIL = noSettingsItem("dome_fossil")
|
||||
@JvmField
|
||||
val FOSSILIZED_DRAKE = noSettingsItem("fossilized_drake")
|
||||
@JvmField
|
||||
val FOSSILIZED_FISH = noSettingsItem("fossilized_fish")
|
||||
@JvmField
|
||||
val HELIX_FOSSIL = noSettingsItem("helix_fossil")
|
||||
@JvmField
|
||||
val JAW_FOSSIL = noSettingsItem("jaw_fossil")
|
||||
@JvmField
|
||||
val OLD_AMBER_FOSSIL = noSettingsItem("old_amber_fossil")
|
||||
@JvmField
|
||||
val PLUME_FOSSIL = noSettingsItem("plume_fossil")
|
||||
@JvmField
|
||||
val ROOT_FOSSIL = noSettingsItem("root_fossil")
|
||||
@JvmField
|
||||
val SAIL_FOSSIL = noSettingsItem("sail_fossil")
|
||||
@JvmField
|
||||
val SKULL_FOSSIL = noSettingsItem("skull_fossil")
|
||||
|
||||
@JvmField
|
||||
val BYGONE_SHERD = noSettingsItem("bygone_sherd")
|
||||
@JvmField
|
||||
val CAPTURE_SHERD = noSettingsItem("capture_sherd")
|
||||
@JvmField
|
||||
val DOME_SHERD = noSettingsItem("dome_sherd")
|
||||
@JvmField
|
||||
val HELIX_SHERD = noSettingsItem("helix_sherd")
|
||||
@JvmField
|
||||
val NOSTALGIC_SHERD = noSettingsItem("nostalgic_sherd")
|
||||
@JvmField
|
||||
val SUSPICIOUS_SHERD = noSettingsItem("suspicious_sherd")
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE = this.create("tumblestone", TumblestoneItem(Item.Settings(), CobblemonBlocks.SMALL_BUDDING_TUMBLESTONE))
|
||||
@JvmField
|
||||
val BLACK_TUMBLESTONE = this.create("black_tumblestone", TumblestoneItem(Item.Settings(), CobblemonBlocks.SMALL_BUDDING_BLACK_TUMBLESTONE))
|
||||
@JvmField
|
||||
val SKY_TUMBLESTONE = this.create("sky_tumblestone", TumblestoneItem(Item.Settings(), CobblemonBlocks.SMALL_BUDDING_SKY_TUMBLESTONE))
|
||||
|
||||
@JvmField
|
||||
val SMALL_BUDDING_TUMBLESTONE = blockItem("small_budding_tumblestone", CobblemonBlocks.SMALL_BUDDING_TUMBLESTONE)
|
||||
@JvmField
|
||||
val MEDIUM_BUDDING_TUMBLESTONE = blockItem("medium_budding_tumblestone", CobblemonBlocks.MEDIUM_BUDDING_TUMBLESTONE)
|
||||
@JvmField
|
||||
val LARGE_BUDDING_TUMBLESTONE = blockItem("large_budding_tumblestone", CobblemonBlocks.LARGE_BUDDING_TUMBLESTONE)
|
||||
@JvmField
|
||||
val TUMBLESTONE_CLUSTER = blockItem("tumblestone_cluster", CobblemonBlocks.TUMBLESTONE_CLUSTER)
|
||||
|
||||
@JvmField
|
||||
val SMALL_BUDDING_SKY_TUMBLESTONE = blockItem("small_budding_sky_tumblestone", CobblemonBlocks.SMALL_BUDDING_SKY_TUMBLESTONE)
|
||||
@JvmField
|
||||
val MEDIUM_BUDDING_SKY_TUMBLESTONE = blockItem("medium_budding_sky_tumblestone", CobblemonBlocks.MEDIUM_BUDDING_SKY_TUMBLESTONE)
|
||||
@JvmField
|
||||
val LARGE_BUDDING_SKY_TUMBLESTONE = blockItem("large_budding_sky_tumblestone", CobblemonBlocks.LARGE_BUDDING_SKY_TUMBLESTONE)
|
||||
@JvmField
|
||||
val SKY_TUMBLESTONE_CLUSTER = blockItem("sky_tumblestone_cluster", CobblemonBlocks.SKY_TUMBLESTONE_CLUSTER)
|
||||
|
||||
@JvmField
|
||||
val SMALL_BUDDING_BLACK_TUMBLESTONE = blockItem("small_budding_black_tumblestone", CobblemonBlocks.SMALL_BUDDING_BLACK_TUMBLESTONE)
|
||||
@JvmField
|
||||
val MEDIUM_BUDDING_BLACK_TUMBLESTONE = blockItem("medium_budding_black_tumblestone", CobblemonBlocks.MEDIUM_BUDDING_BLACK_TUMBLESTONE)
|
||||
@JvmField
|
||||
val LARGE_BUDDING_BLACK_TUMBLESTONE = blockItem("large_budding_black_tumblestone", CobblemonBlocks.LARGE_BUDDING_BLACK_TUMBLESTONE)
|
||||
@JvmField
|
||||
val BLACK_TUMBLESTONE_CLUSTER = blockItem("black_tumblestone_cluster", CobblemonBlocks.BLACK_TUMBLESTONE_CLUSTER)
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE_BLOCK = blockItem("tumblestone_block", CobblemonBlocks.TUMBLESTONE_BLOCK)
|
||||
@JvmField
|
||||
val SKY_TUMBLESTONE_BLOCK = blockItem("sky_tumblestone_block", CobblemonBlocks.SKY_TUMBLESTONE_BLOCK)
|
||||
@JvmField
|
||||
val BLACK_TUMBLESTONE_BLOCK = blockItem("black_tumblestone_block", CobblemonBlocks.BLACK_TUMBLESTONE_BLOCK)
|
||||
|
||||
@JvmField
|
||||
val AUTOMATON_ARMOR_TRIM_SMITHING_TEMPLATE: SmithingTemplateItem = this.create(
|
||||
"automaton_armor_trim_smithing_template",
|
||||
SmithingTemplateItem.of(CobblemonArmorTrims.AUTOMATON)
|
||||
)
|
||||
|
||||
// Misc
|
||||
@JvmField
|
||||
val POKEMON_MODEL = this.create("pokemon_model", PokemonItem())
|
||||
@JvmField
|
||||
val RELIC_COIN = noSettingsItem("relic_coin")
|
||||
@JvmField
|
||||
val RELIC_COIN_POUCH = blockItem("relic_coin_pouch", CobblemonBlocks.RELIC_COIN_POUCH)
|
||||
@JvmField
|
||||
val RELIC_COIN_SACK = blockItem("relic_coin_sack", CobblemonBlocks.RELIC_COIN_SACK)
|
||||
|
||||
// Type Gems
|
||||
@JvmField
|
||||
val NORMAL_GEM = noSettingsItem("normal_gem")
|
||||
@JvmField
|
||||
val FIRE_GEM = noSettingsItem("fire_gem")
|
||||
@JvmField
|
||||
val WATER_GEM = noSettingsItem("water_gem")
|
||||
@JvmField
|
||||
val GRASS_GEM = noSettingsItem("grass_gem")
|
||||
@JvmField
|
||||
val ELECTRIC_GEM = noSettingsItem("electric_gem")
|
||||
@JvmField
|
||||
val ICE_GEM = noSettingsItem("ice_gem")
|
||||
@JvmField
|
||||
val FIGHTING_GEM = noSettingsItem("fighting_gem")
|
||||
@JvmField
|
||||
val POISON_GEM = noSettingsItem("poison_gem")
|
||||
@JvmField
|
||||
val GROUND_GEM = noSettingsItem("ground_gem")
|
||||
@JvmField
|
||||
val FLYING_GEM = noSettingsItem("flying_gem")
|
||||
@JvmField
|
||||
val PSYCHIC_GEM = noSettingsItem("psychic_gem")
|
||||
@JvmField
|
||||
val BUG_GEM = noSettingsItem("bug_gem")
|
||||
@JvmField
|
||||
val ROCK_GEM = noSettingsItem("rock_gem")
|
||||
@JvmField
|
||||
val GHOST_GEM = noSettingsItem("ghost_gem")
|
||||
@JvmField
|
||||
val DRAGON_GEM = noSettingsItem("dragon_gem")
|
||||
@JvmField
|
||||
val DARK_GEM = noSettingsItem("dark_gem")
|
||||
@JvmField
|
||||
val STEEL_GEM = noSettingsItem("steel_gem")
|
||||
@JvmField
|
||||
val FAIRY_GEM = noSettingsItem("fairy_gem")
|
||||
|
||||
private fun blockItem(name: String, block: Block): BlockItem = this.create(name, BlockItem(block, Item.Settings()))
|
||||
|
||||
@@ -715,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)
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.PlayerInteractOptionsHandler
|
||||
import com.cobblemon.mod.common.client.net.SetClientPlayerDataHandler
|
||||
import com.cobblemon.mod.common.client.net.animation.PlayPoseableAnimationHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleApplyPassResponseHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleCaptureEndHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleCaptureShakeHandler
|
||||
@@ -37,6 +38,10 @@ import com.cobblemon.mod.common.client.net.callback.party.OpenPartyCallbackHandl
|
||||
import com.cobblemon.mod.common.client.net.callback.partymove.OpenPartyMoveCallbackHandler
|
||||
import com.cobblemon.mod.common.client.net.data.DataRegistrySyncPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.data.UnlockReloadPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.RunPosableMoLangHandler
|
||||
import com.cobblemon.mod.common.client.net.dialogue.DialogueClosedHandler
|
||||
import com.cobblemon.mod.common.client.net.dialogue.DialogueOpenedHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormEntityParticleHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormParticleHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.InteractPokemonUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
|
||||
@@ -46,7 +51,6 @@ import com.cobblemon.mod.common.client.net.pasture.PokemonPasturedHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.PokemonUnpasturedHandler
|
||||
import com.cobblemon.mod.common.client.net.pokemon.update.PokemonUpdatePacketHandler
|
||||
import com.cobblemon.mod.common.client.net.settings.ServerSettingsPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.sound.PokemonCryHandler
|
||||
import com.cobblemon.mod.common.client.net.sound.UnvalidatedPlaySoundS2CPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.spawn.SpawnExtraDataEntityHandler
|
||||
import com.cobblemon.mod.common.client.net.starter.StarterUIPacketHandler
|
||||
@@ -71,17 +75,27 @@ import com.cobblemon.mod.common.client.net.trade.TradeOfferNotificationHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeStartedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeUpdatedHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.animation.PlayPoseableAnimationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.*
|
||||
import com.cobblemon.mod.common.net.messages.client.callback.OpenMoveCallbackPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyCallbackPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyMoveCallbackPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.AbilityRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.BerryRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.GlobalSpeciesFeatureSyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.MovesRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.PropertiesCompletionRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.SpeciesFeatureAssignmentSyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.SpeciesRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.StandardSpeciesFeatureSyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.UnlockReloadPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueClosedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueOpenedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.fossil.FossilRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.fossil.NaturalMaterialRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.ClosePasturePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.OpenPasturePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonPasturedPacket
|
||||
@@ -91,8 +105,8 @@ import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.Add
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.ClearEvolutionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.RemoveEvolutionPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.sound.PokemonCryPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnGenericBedrockPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokeballPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.starter.OpenStarterUIPacket
|
||||
@@ -129,6 +143,8 @@ import com.cobblemon.mod.common.net.messages.server.callback.party.PartyPokemonS
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.party.PartySelectCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.partymove.PartyMoveSelectCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.partymove.PartyPokemonMoveSelectedPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.dialogue.EscapeDialoguePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.dialogue.InputToDialoguePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.PasturePokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpastureAllPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPacket
|
||||
@@ -162,6 +178,8 @@ import com.cobblemon.mod.common.net.serverhandling.callback.party.PartyPokemonSe
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.party.PartySelectCancelledHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.partymove.PartyMoveSelectCancelledHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.partymove.PartyPokemonMoveSelectedHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.dialogue.EscapeDialogueHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.dialogue.InputToDialogueHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.evolution.AcceptEvolutionHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.PasturePokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpastureAllPokemonHandler
|
||||
@@ -233,6 +251,8 @@ object CobblemonNetwork : NetworkManager {
|
||||
this.createClientBound(PokemonStateUpdatePacket.ID, PokemonStateUpdatePacket::decode, PokemonUpdatePacketHandler())
|
||||
this.createClientBound(TetheringUpdatePacket.ID, TetheringUpdatePacket::decode, PokemonUpdatePacketHandler())
|
||||
this.createClientBound(TradeableUpdatePacket.ID, TradeableUpdatePacket::decode, PokemonUpdatePacketHandler())
|
||||
this.createClientBound(SpeciesFeatureUpdatePacket.ID, SpeciesFeatureUpdatePacket::decode, PokemonUpdatePacketHandler())
|
||||
this.createClientBound(OriginalTrainerUpdatePacket.ID, OriginalTrainerUpdatePacket::decode, PokemonUpdatePacketHandler())
|
||||
|
||||
// Evolution start
|
||||
this.createClientBound(AddEvolutionPacket.ID, AddEvolutionPacket::decode, PokemonUpdatePacketHandler())
|
||||
@@ -298,15 +318,23 @@ object CobblemonNetwork : NetworkManager {
|
||||
this.createClientBound(PropertiesCompletionRegistrySyncPacket.ID, PropertiesCompletionRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
|
||||
this.createClientBound(UnlockReloadPacket.ID, UnlockReloadPacket::decode, UnlockReloadPacketHandler)
|
||||
this.createClientBound(BerryRegistrySyncPacket.ID, BerryRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
|
||||
this.createClientBound(StandardSpeciesFeatureSyncPacket.ID, StandardSpeciesFeatureSyncPacket::decode, DataRegistrySyncPacketHandler())
|
||||
this.createClientBound(GlobalSpeciesFeatureSyncPacket.ID, GlobalSpeciesFeatureSyncPacket::decode, DataRegistrySyncPacketHandler())
|
||||
this.createClientBound(SpeciesFeatureAssignmentSyncPacket.ID, SpeciesFeatureAssignmentSyncPacket::decode, DataRegistrySyncPacketHandler())
|
||||
this.createClientBound(NaturalMaterialRegistrySyncPacket.ID, NaturalMaterialRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
|
||||
this.createClientBound(FossilRegistrySyncPacket.ID, FossilRegistrySyncPacket::decode, DataRegistrySyncPacketHandler())
|
||||
|
||||
// Effects
|
||||
this.createClientBound(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler)
|
||||
this.createClientBound(SpawnSnowstormEntityParticlePacket.ID, SpawnSnowstormEntityParticlePacket::decode, SpawnSnowstormEntityParticleHandler)
|
||||
this.createClientBound(RunPosableMoLangPacket.ID, RunPosableMoLangPacket::decode, RunPosableMoLangHandler)
|
||||
|
||||
// Hax
|
||||
this.createClientBound(UnvalidatedPlaySoundS2CPacket.ID, UnvalidatedPlaySoundS2CPacket::decode, UnvalidatedPlaySoundS2CPacketHandler)
|
||||
this.createClientBound(SpawnPokemonPacket.ID, SpawnPokemonPacket::decode, SpawnExtraDataEntityHandler())
|
||||
this.createClientBound(SpawnPokeballPacket.ID, SpawnPokeballPacket::decode, SpawnExtraDataEntityHandler())
|
||||
this.createClientBound(ToastPacket.ID, ToastPacket::decode, ToastPacketHandler)
|
||||
this.createClientBound(SpawnGenericBedrockPacket.ID, SpawnGenericBedrockPacket::decode, SpawnExtraDataEntityHandler())
|
||||
|
||||
// Trade packets
|
||||
this.createClientBound(TradeAcceptanceChangedPacket.ID, TradeAcceptanceChangedPacket::decode, TradeAcceptanceChangedHandler)
|
||||
@@ -324,7 +352,7 @@ object CobblemonNetwork : NetworkManager {
|
||||
this.createClientBound(PokemonUnpasturedPacket.ID, PokemonUnpasturedPacket::decode, PokemonUnpasturedHandler)
|
||||
|
||||
// Behaviours
|
||||
this.createClientBound(PokemonCryPacket.ID, PokemonCryPacket::decode, PokemonCryHandler)
|
||||
this.createClientBound(PlayPoseableAnimationPacket.ID, PlayPoseableAnimationPacket::decode, PlayPoseableAnimationHandler)
|
||||
|
||||
// Move select packets
|
||||
this.createClientBound(OpenMoveCallbackPacket.ID, OpenMoveCallbackPacket::decode, OpenMoveCallbackHandler)
|
||||
@@ -334,6 +362,10 @@ object CobblemonNetwork : NetworkManager {
|
||||
|
||||
// Party move select packets
|
||||
this.createClientBound(OpenPartyMoveCallbackPacket.ID, OpenPartyMoveCallbackPacket::decode, OpenPartyMoveCallbackHandler)
|
||||
|
||||
// Dialogue packets
|
||||
this.createClientBound(DialogueClosedPacket.ID, DialogueClosedPacket::decode, DialogueClosedHandler)
|
||||
this.createClientBound(DialogueOpenedPacket.ID, DialogueOpenedPacket::decode, DialogueOpenedHandler)
|
||||
}
|
||||
|
||||
override fun registerServerBound() {
|
||||
@@ -399,6 +431,10 @@ object CobblemonNetwork : NetworkManager {
|
||||
// Party move select packets
|
||||
this.createServerBound(PartyPokemonMoveSelectedPacket.ID, PartyPokemonMoveSelectedPacket::decode, PartyPokemonMoveSelectedHandler)
|
||||
this.createServerBound(PartyMoveSelectCancelledPacket.ID, PartyMoveSelectCancelledPacket::decode, PartyMoveSelectCancelledHandler)
|
||||
|
||||
// Dialogue packets
|
||||
this.createServerBound(EscapeDialoguePacket.ID, EscapeDialoguePacket::decode, EscapeDialogueHandler)
|
||||
this.createServerBound(InputToDialoguePacket.ID, InputToDialoguePacket::decode, InputToDialogueHandler)
|
||||
}
|
||||
|
||||
private inline fun <reified T : NetworkPacket<T>> createClientBound(identifier: Identifier, noinline decoder: (PacketByteBuf) -> T, handler: ClientNetworkPacketHandler<T>) {
|
||||
|
||||
@@ -14,7 +14,9 @@ import net.minecraft.registry.Registries
|
||||
import net.minecraft.registry.Registry
|
||||
import net.minecraft.registry.RegistryKey
|
||||
import net.minecraft.registry.RegistryKeys
|
||||
import net.minecraft.sound.BlockSoundGroup
|
||||
import net.minecraft.sound.SoundEvent
|
||||
import net.minecraft.sound.SoundEvents
|
||||
|
||||
object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Registry<SoundEvent>>, SoundEvent>() {
|
||||
|
||||
@@ -54,6 +56,10 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
|
||||
val POKE_BALL_SEND_OUT = this.create("poke_ball.send_out")
|
||||
@JvmField
|
||||
val POKE_BALL_RECALL = this.create("poke_ball.recall")
|
||||
@JvmField
|
||||
val POKE_BALL_THROW = this.create("poke_ball.throw")
|
||||
@JvmField
|
||||
val POKE_BALL_TRAIL = this.create("poke_ball.trail")
|
||||
|
||||
@JvmField
|
||||
val ITEM_USE = this.create("item.use")
|
||||
@@ -61,6 +67,8 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
|
||||
val CAN_EVOLVE = this.create("pokemon.can_evolve")
|
||||
@JvmField
|
||||
val EVOLVING = this.create("pokemon.evolving")
|
||||
@JvmField
|
||||
val EVOLVE = this.create("evolution.evolve")
|
||||
|
||||
@JvmField
|
||||
val PVN_BATTLE = this.create("battle.pvn.default")
|
||||
@@ -77,6 +85,8 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
|
||||
val MEDICINE_PILLS_USE = this.create("medicine_pills.use")
|
||||
@JvmField
|
||||
val MEDICINE_SPRAY_USE = this.create("medicine_spray.use")
|
||||
@JvmField
|
||||
val MEDICINE_FEATHER_USE = this.create("medicine_feather.use")
|
||||
|
||||
@JvmField
|
||||
val BERRY_HARVEST = this.create("berry.harvest")
|
||||
@@ -88,6 +98,224 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
|
||||
@JvmField
|
||||
val MULCH_REMOVE = this.create("mulch.remove")
|
||||
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_ACTIVATE = this.create("fossilmachine.activate")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_ACTIVE_LOOP = this.create("fossilmachine.active_loop")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_ASSEMBLE = this.create("fossilmachine.assemble")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_DNA_FULL = this.create("fossilmachine.dna_full")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_FINISHED = this.create("fossilmachine.finished")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_INSERT_DNA = this.create("fossilmachine.insert_dna")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_INSERT_DNA_SMALL = this.create("fossilmachine.insert_dna_small")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_INSERT_FOSSIL = this.create("fossilmachine.insert_fossil")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_RETRIEVE_FOSSIL = this.create("fossilmachine.retrieve_fossil")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_RETRIEVE_POKEMON = this.create("fossilmachine.retrieve_pokemon")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_UNPROTECTED = this.create("fossilmachine.unprotected")
|
||||
|
||||
@JvmField
|
||||
val COIN_POUCH_BREAK = this.create("coin_pouch.break")
|
||||
@JvmField
|
||||
val COIN_POUCH_HIT = this.create("coin_pouch.hit")
|
||||
@JvmField
|
||||
val COIN_POUCH_STEP = this.create("coin_pouch.step")
|
||||
@JvmField
|
||||
val COIN_POUCH_PLACE = this.create("coin_pouch.place")
|
||||
@JvmField
|
||||
val TUMBLESTONE_BREAK = this.create("tumblestone.break")
|
||||
@JvmField
|
||||
val TUMBLESTONE_BLOCK_BREAK = this.create("tumblestone.block_break")
|
||||
@JvmField
|
||||
val TUMBLESTONE_HIT = this.create("tumblestone.hit")
|
||||
@JvmField
|
||||
val TUMBLESTONE_PLACE = this.create("tumblestone.place")
|
||||
@JvmField
|
||||
val TUMBLESTONE_STEP = this.create("tumblestone.step")
|
||||
|
||||
@JvmField
|
||||
val GIMMIGHOUL_GIVE_ITEM_SMALL = this.create("gimmighoul.give_item_small")
|
||||
@JvmField
|
||||
val GIMMIGHOUL_REVEAL = this.create("gimmighoul.reveal")
|
||||
|
||||
@JvmField
|
||||
val BERRY_BUSH_BREAK = this.create("berry_bush.break")
|
||||
@JvmField
|
||||
val BERRY_BUSH_PLACE = this.create("berry_bush.place")
|
||||
|
||||
@JvmField
|
||||
val BIG_ROOT_BREAK = this.create("big_root.break")
|
||||
@JvmField
|
||||
val ENERGY_ROOT_PLACE = this.create("energy_root.place")
|
||||
|
||||
@JvmField
|
||||
val MINT_BREAK = this.create("mint.break")
|
||||
@JvmField
|
||||
val MINT_PLACE = this.create("mint.place")
|
||||
|
||||
@JvmField
|
||||
val MEDICINAL_LEEK_BREAK = this.create("medicinal_leek.break")
|
||||
@JvmField
|
||||
val MEDICINAL_LEEK_PLACE = this.create("medicinal_leek.plant")
|
||||
|
||||
@JvmField
|
||||
val GILDED_CHEST_OPEN = this.create("gilded_chest.open")
|
||||
@JvmField
|
||||
val GILDED_CHEST_CLOSE = this.create("gilded_chest.close")
|
||||
@JvmField
|
||||
val GILDED_CHEST_STEP = this.create("gilded_chest.step")
|
||||
@JvmField
|
||||
val GILDED_CHEST_HIT = this.create("gilded_chest.hit")
|
||||
@JvmField
|
||||
val GILDED_CHEST_BREAK = this.create("gilded_chest.break")
|
||||
@JvmField
|
||||
val GILDED_CHEST_PLACE = this.create("gilded_chest.place")
|
||||
|
||||
@JvmField
|
||||
val COIN_POUCH_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
COIN_POUCH_BREAK,
|
||||
COIN_POUCH_STEP,
|
||||
COIN_POUCH_PLACE,
|
||||
COIN_POUCH_HIT,
|
||||
COIN_POUCH_STEP
|
||||
)
|
||||
@JvmField
|
||||
val IMPACT_NORMAL = this.create("impact.normal")
|
||||
@JvmField
|
||||
val IMPACT_BUG = this.create("impact.bug")
|
||||
@JvmField
|
||||
val IMPACT_DARK = this.create("impact.dark")
|
||||
@JvmField
|
||||
val IMPACT_DRAGON = this.create("impact.dragon")
|
||||
@JvmField
|
||||
val IMPACT_ELECTRIC = this.create("impact.electric")
|
||||
@JvmField
|
||||
val IMPACT_FAIRY = this.create("impact.fairy")
|
||||
@JvmField
|
||||
val IMPACT_FIGHTING = this.create("impact.fighting")
|
||||
@JvmField
|
||||
val IMPACT_FIRE = this.create("impact.fire")
|
||||
@JvmField
|
||||
val IMPACT_FLYING = this.create("impact.flying")
|
||||
@JvmField
|
||||
val IMPACT_GHOST = this.create("impact.ghost")
|
||||
@JvmField
|
||||
val IMPACT_GRASS = this.create("impact.grass")
|
||||
@JvmField
|
||||
val IMPACT_GROUND = this.create("impact.ground")
|
||||
@JvmField
|
||||
val IMPACT_ICE = this.create("impact.ice")
|
||||
@JvmField
|
||||
val IMPACT_POISON = this.create("impact.poison")
|
||||
@JvmField
|
||||
val IMPACT_PSYCHIC = this.create("impact.psychic")
|
||||
@JvmField
|
||||
val IMPACT_ROCK = this.create("impact.rock")
|
||||
@JvmField
|
||||
val IMPACT_STEEL = this.create("impact.steel")
|
||||
@JvmField
|
||||
val IMPACT_WATER = this.create("impact.water")
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
TUMBLESTONE_BREAK,
|
||||
TUMBLESTONE_STEP,
|
||||
TUMBLESTONE_PLACE,
|
||||
TUMBLESTONE_HIT,
|
||||
TUMBLESTONE_STEP
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE_BLOCK_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
TUMBLESTONE_BLOCK_BREAK,
|
||||
TUMBLESTONE_STEP,
|
||||
TUMBLESTONE_PLACE,
|
||||
TUMBLESTONE_HIT,
|
||||
TUMBLESTONE_STEP
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val BERRY_BUSH_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
BERRY_BUSH_BREAK,
|
||||
SoundEvents.BLOCK_GRASS_STEP,
|
||||
BERRY_BUSH_PLACE,
|
||||
SoundEvents.BLOCK_GRASS_HIT,
|
||||
SoundEvents.BLOCK_GRASS_STEP
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val BIG_ROOT_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
BIG_ROOT_BREAK,
|
||||
SoundEvents.BLOCK_ROOTS_STEP,
|
||||
SoundEvents.BLOCK_ROOTS_PLACE,
|
||||
SoundEvents.BLOCK_ROOTS_HIT,
|
||||
SoundEvents.BLOCK_ROOTS_FALL
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val ENERGY_ROOT_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
SoundEvents.BLOCK_ROOTS_BREAK,
|
||||
SoundEvents.BLOCK_ROOTS_STEP,
|
||||
ENERGY_ROOT_PLACE,
|
||||
SoundEvents.BLOCK_ROOTS_HIT,
|
||||
SoundEvents.BLOCK_ROOTS_FALL
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val MEDICINAL_LEEK_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
MEDICINAL_LEEK_BREAK,
|
||||
SoundEvents.BLOCK_GRASS_STEP,
|
||||
MEDICINAL_LEEK_PLACE,
|
||||
SoundEvents.BLOCK_GRASS_HIT,
|
||||
SoundEvents.BLOCK_GRASS_FALL
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val MINT_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
MINT_BREAK,
|
||||
SoundEvents.BLOCK_GRASS_STEP,
|
||||
MINT_PLACE,
|
||||
SoundEvents.BLOCK_GRASS_HIT,
|
||||
SoundEvents.BLOCK_GRASS_FALL
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val GILDED_CHEST_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
GILDED_CHEST_BREAK,
|
||||
GILDED_CHEST_STEP,
|
||||
GILDED_CHEST_PLACE,
|
||||
GILDED_CHEST_HIT,
|
||||
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)))
|
||||
}
|
||||
@@ -99,6 +99,13 @@ object CobblemonCriteria {
|
||||
)
|
||||
)
|
||||
|
||||
val RESURRECT_POKEMON = this.create(
|
||||
SimpleCriterionTrigger(
|
||||
cobblemonResource("resurrect_pokemon"),
|
||||
PickStarterCriterionCondition::class.java
|
||||
)
|
||||
)
|
||||
|
||||
val TRADE_POKEMON = this.create(
|
||||
SimpleCriterionTrigger(
|
||||
cobblemonResource("trade_pokemon"),
|
||||
@@ -106,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)
|
||||
|
||||
}
|
||||
+23
-20
@@ -135,28 +135,31 @@ class BattleMessage(rawMessage: String) {
|
||||
return this.actorAndActivePokemon(pnx, battle)
|
||||
}
|
||||
|
||||
/*
|
||||
Example:
|
||||
|-curestatus|p1: a8e5710e-6835-4387-99d3-331b45f848e6|slp|[msg]
|
||||
|-curestatus|p1: 0686b20d-3019-4167-92e2-786834245743|slp|[msg]
|
||||
// Function used to grab BattlePokemon (As we need to be able to grab non active pokemon to cure their status)
|
||||
// by using playerNumber(actorID) and pokemon uuid(pokemonID)
|
||||
/**
|
||||
* Queries an argument at the given [index] for a 'pnx' and uuid that will be parsed into a [BattlePokemon].
|
||||
*
|
||||
* @param index The index of the argument referencing the [BattlePokemon].
|
||||
* @param battle The [PokemonBattle] being queried.
|
||||
* @return The [BattlePokemon] if the argument exists and is successfully parsed; otherwise null.
|
||||
*/
|
||||
fun getBattlePokemon(index: Int, battle: PokemonBattle): BattlePokemon? {
|
||||
val actorAndPokemonID = this.argumentAt(index)?.takeIf { it.length >= 2 }?.split(": ") ?: return null
|
||||
if (actorAndPokemonID.count() < 2) return null
|
||||
val actorID = actorAndPokemonID[0]
|
||||
val pokemonID = actorAndPokemonID[1]
|
||||
return this.getBattlePokemon(actorID, pokemonID, battle)
|
||||
fun battlePokemon(index: Int, battle: PokemonBattle): BattlePokemon? {
|
||||
val (actorID, pokemonID) = this.pnxAndUuid(index) ?: return null
|
||||
return this.battlePokemon(actorID, pokemonID, battle)
|
||||
}
|
||||
|
||||
fun getSourceBattlePokemon(battle: PokemonBattle): BattlePokemon? {
|
||||
val sourcePokemonArgument = this.optionalArguments.get("of") ?: return null
|
||||
val actorAndPokemonID = sourcePokemonArgument.takeIf { it.length >= 2 }?.split(": ") ?: return null
|
||||
if (actorAndPokemonID.count() < 2) return null
|
||||
val actorID = actorAndPokemonID[0]
|
||||
val pokemonID = actorAndPokemonID[1]
|
||||
return this.getBattlePokemon(actorID, pokemonID, battle)
|
||||
/**
|
||||
* Queries an optional argument identified by [optionalArg] for a 'pnx' and uuid that will be parsed into a [BattlePokemon].
|
||||
*
|
||||
* @param optionalArg The id of the optional argument referencing the [BattlePokemon].
|
||||
* @param battle The [PokemonBattle] being queried.
|
||||
* @return The [BattlePokemon] if the argument exists and is successfully parsed; otherwise null.
|
||||
*/
|
||||
fun battlePokemonFromOptional(battle: PokemonBattle, optionalArg: String = "of"): BattlePokemon? {
|
||||
val optional = this.optionalArguments.get(optionalArg) ?: return null
|
||||
val pokemonID = optional.takeIf { it.length >= 2 }?.split(":")?.takeIf { it.size == 2 } ?: return null
|
||||
val pnx = pokemonID[0].takeIf { it.matches(PNX_MATCHER) || it.matches(PN_MATCHER) } ?: return null
|
||||
val uuid = pokemonID[1].trim()
|
||||
return this.battlePokemon(pnx, uuid, battle)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,7 +237,7 @@ class BattleMessage(rawMessage: String) {
|
||||
null
|
||||
}
|
||||
|
||||
private fun getBattlePokemon(pnx: String, pokemonID: String, battle: PokemonBattle): BattlePokemon? = try {
|
||||
private fun battlePokemon(pnx: String, pokemonID: String, battle: PokemonBattle): BattlePokemon? = try {
|
||||
battle.getBattlePokemon(pnx, pokemonID)
|
||||
} catch (_: Exception) {
|
||||
null
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.battles.model
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.CobblemonNetwork
|
||||
@@ -38,7 +40,6 @@ import com.cobblemon.mod.common.battles.runner.ShowdownService
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleEndPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMusicPacket
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.DefeatEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.LastBattleCriticalHitsEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.evolution.requirements.DefeatRequirement
|
||||
@@ -101,6 +102,11 @@ open class PokemonBattle(
|
||||
var turn: Int = 1
|
||||
private set
|
||||
|
||||
private var ticks: Int = 0
|
||||
set(value) { field = value.coerceAtMost(Int.MAX_VALUE) } // go outside
|
||||
|
||||
/** The current duration of the battle in seconds. */
|
||||
val time: Int get() = ticks % 20
|
||||
|
||||
var dispatchResult = GO
|
||||
val dispatches = ConcurrentLinkedDeque<BattleDispatch>()
|
||||
@@ -160,7 +166,7 @@ open class PokemonBattle(
|
||||
fun getActor(player: ServerPlayerEntity) = actors.firstOrNull { it.isForPlayer(player) }
|
||||
|
||||
/**
|
||||
* Gets a BattleActor and an [ActiveBattlePokemon] from a pnx key, e.g. p2a
|
||||
* Gets a [BattleActor] and an [ActiveBattlePokemon] from a pnx key, e.g. p2a
|
||||
*
|
||||
* Returns null if either the pn or x is invalid.
|
||||
*/
|
||||
@@ -173,6 +179,11 @@ open class PokemonBattle(
|
||||
return actor to pokemon
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a [BattlePokemon] from a pnx key and uuid.
|
||||
*
|
||||
* Returns null if the pnx key is invalid or the uuid does not exist.
|
||||
*/
|
||||
fun getBattlePokemon(pnx: String, pokemonID: String): BattlePokemon {
|
||||
val actor = actors.find { it.showdownId == pnx.substring(0, 2) }
|
||||
?: throw IllegalStateException("Invalid pnx: $pnx - unknown actor")
|
||||
@@ -384,8 +395,9 @@ open class PokemonBattle(
|
||||
return
|
||||
}
|
||||
|
||||
if (started && isPvW && !ended && dispatches.isEmpty()) {
|
||||
checkFlee()
|
||||
if (started) {
|
||||
ticks++
|
||||
if (isPvW && !ended && dispatches.isEmpty()) checkFlee()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,4 +476,13 @@ open class PokemonBattle(
|
||||
LOGGER.error("Missing interpretation on '{}' action: \nPublic » {}\nPrivate » {}", publicMessage.id, publicMessage.rawMessage, privateMessage.rawMessage)
|
||||
return Text.literal("Missing interpretation on '${publicMessage.id}' action please report to the developers").red()
|
||||
}
|
||||
|
||||
fun addQueryFunctions(queryStruct: QueryStruct): QueryStruct {
|
||||
queryStruct.addFunction("pvp") { DoubleValue(isPvP) }
|
||||
queryStruct.addFunction("pvn") { DoubleValue(isPvN) }
|
||||
queryStruct.addFunction("pvw") { DoubleValue(isPvW) }
|
||||
queryStruct.addFunction("has_rule") { params -> DoubleValue(params.getString(0) in format.ruleSet) }
|
||||
|
||||
return queryStruct
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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.dialogue
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.struct.MoStruct
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.dialogue.input.ActiveInput
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addStandardFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.getQueryStruct
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.scheduling.ServerRealTimeTaskTracker
|
||||
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueOpenedPacket
|
||||
import java.util.UUID
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
|
||||
/**
|
||||
* An active instance of [Dialogue]. Bound to a player. These all need to be created through DialogueManager
|
||||
* or things will go to shit.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since December 27th, 2023
|
||||
*/
|
||||
class ActiveDialogue(var playerEntity: ServerPlayerEntity, var dialogueReference: Dialogue) {
|
||||
val dialogueId = UUID.randomUUID()
|
||||
val runtime = MoLangRuntime().setup()
|
||||
var currentPage = dialogueReference.pages[0]
|
||||
val playerStruct = playerEntity.asMoLangValue()
|
||||
var activeInput = ActiveInput(this, currentPage.input)
|
||||
|
||||
init {
|
||||
runtime.environment.getQueryStruct().addFunctions(
|
||||
mapOf(
|
||||
"dialogue" to java.util.function.Function { _ -> toMoLangStruct() },
|
||||
"player" to java.util.function.Function { _ -> playerStruct }
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val currentPageIndex
|
||||
get() = dialogueReference.pages.indexOf(currentPage)
|
||||
|
||||
fun setPage(value: MoValue) {
|
||||
val page = if (value is StringValue) {
|
||||
dialogueReference.pages.find { it.id == value.value }
|
||||
?: return Cobblemon.LOGGER.error("Dialogue requested page ${value.value} but it doesn't exist")
|
||||
} else {
|
||||
val pageNum = value.asDouble().toInt()
|
||||
if (pageNum < 0 || pageNum >= dialogueReference.pages.size) {
|
||||
return Cobblemon.LOGGER.error("Dialogue requested page $pageNum but it doesn't exist")
|
||||
} else {
|
||||
dialogueReference.pages[pageNum]
|
||||
}
|
||||
}
|
||||
setPage(page)
|
||||
}
|
||||
|
||||
fun isActive() = DialogueManager.activeDialogues[playerEntity.uuid] == this
|
||||
|
||||
fun incrementPage() {
|
||||
setPage(currentPageIndex + 1)
|
||||
}
|
||||
|
||||
fun setPage(page: DialoguePage) {
|
||||
currentPage = page
|
||||
activeInput = ActiveInput(this, currentPage.input)
|
||||
val deadline = currentPage.input.timeout?.duration
|
||||
val inputId = activeInput.inputId
|
||||
if (deadline != null && deadline > 0) {
|
||||
ServerRealTimeTaskTracker.after(seconds = deadline) {
|
||||
if (inputId == activeInput.inputId && isActive()) {
|
||||
activeInput.dialogueInput.timeout?.action?.invoke(this, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
playerEntity.sendPacket(DialogueOpenedPacket(this, false))
|
||||
}
|
||||
|
||||
fun setPage(index: Int) {
|
||||
if (index == dialogueReference.pages.size) {
|
||||
return close()
|
||||
}
|
||||
|
||||
if (index < 0 || index > dialogueReference.pages.size) {
|
||||
return Cobblemon.LOGGER.error("Dialogue requested page $index but it doesn't exist")
|
||||
}
|
||||
|
||||
setPage(dialogueReference.pages[index])
|
||||
}
|
||||
|
||||
fun toMoLangStruct(): MoStruct {
|
||||
return QueryStruct(
|
||||
hashMapOf(
|
||||
"current_page" to java.util.function.Function { _ -> currentPage.toMoLangStruct(this) },
|
||||
"current_page_number" to java.util.function.Function { _ -> DoubleValue(currentPageIndex) },
|
||||
"next_page" to java.util.function.Function { _ -> incrementPage() },
|
||||
"set_page" to java.util.function.Function { args -> setPage(args[0]) },
|
||||
"close" to java.util.function.Function { _ -> close() },
|
||||
"input" to java.util.function.Function { params -> activeInput.handle(if (params.params.size > 0) params.get<MoValue>(0).asString() else "") },
|
||||
)
|
||||
).addStandardFunctions()
|
||||
}
|
||||
|
||||
fun close() {
|
||||
DialogueManager.stopDialogue(playerEntity)
|
||||
}
|
||||
|
||||
fun escape() {
|
||||
val action = currentPage.escapeAction ?: dialogueReference.escapeAction
|
||||
action(this, null)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.dialogue
|
||||
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
|
||||
/**
|
||||
* A dialogue that could be sent to players.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since December 27th, 2023
|
||||
*/
|
||||
class Dialogue(
|
||||
val pages: List<DialoguePage> = mutableListOf(),
|
||||
val escapeAction: DialogueAction = FunctionDialogueAction { dialogue, _ -> dialogue.close() },
|
||||
val speakers: Map<String, DialogueSpeaker> = emptyMap()
|
||||
) {
|
||||
companion object {
|
||||
fun of(
|
||||
pages: Iterable<DialoguePage>,
|
||||
escapeAction: ExpressionLike,
|
||||
speakers: Map<String, DialogueSpeaker>
|
||||
): Dialogue {
|
||||
return Dialogue(
|
||||
pages = pages.toList(),
|
||||
escapeAction = ExpressionLikeDialogueAction(escapeAction),
|
||||
speakers = speakers
|
||||
)
|
||||
}
|
||||
|
||||
fun of(
|
||||
pages: Iterable<DialoguePage>,
|
||||
escapeAction: (ActiveDialogue) -> Unit,
|
||||
speakers: Map<String, DialogueSpeaker>
|
||||
): Dialogue {
|
||||
val dialogue = Dialogue(
|
||||
pages = pages.toList(),
|
||||
escapeAction = FunctionDialogueAction { activeDialogue, _ -> escapeAction(activeDialogue) },
|
||||
speakers = speakers
|
||||
)
|
||||
return dialogue
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.dialogue
|
||||
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
|
||||
/**
|
||||
* Something that can happen in the context of an [ActiveDialogue]. The input field is nullable because I'm reusing
|
||||
* this for dialogue input timeouts which don't have an input. It'll be fine.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since December 29th, 2023
|
||||
*/
|
||||
interface DialogueAction {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
val types = mutableMapOf<String, Class<out DialogueAction>>()
|
||||
}
|
||||
|
||||
operator fun invoke(dialogue: ActiveDialogue, input: String? = null)
|
||||
}
|
||||
|
||||
class FunctionDialogueAction(val consumer: (ActiveDialogue, String?) -> Unit) : DialogueAction {
|
||||
override fun invoke(dialogue: ActiveDialogue, input: String?) {
|
||||
consumer(dialogue, input)
|
||||
}
|
||||
}
|
||||
|
||||
class ExpressionLikeDialogueAction(val expression: ExpressionLike) : DialogueAction {
|
||||
override fun invoke(dialogue: ActiveDialogue, input: String?) {
|
||||
if (input != null) {
|
||||
dialogue.runtime.environment.setSimpleVariable("selected_option", StringValue(input))
|
||||
}
|
||||
dialogue.runtime.resolve(expression)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.dialogue
|
||||
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import java.util.UUID
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
/**
|
||||
* Something that produces a dialogue's renderable face. This is sealed because the client has very particular handling for this.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since January 1st, 2024
|
||||
*/
|
||||
sealed interface DialogueFaceProvider {
|
||||
companion object {
|
||||
val types = mutableMapOf(
|
||||
"player" to PlayerDialogueFaceProvider::class.java,
|
||||
"standard" to ArtificialDialogueFaceProvider::class.java,
|
||||
"expression" to ExpressionLikeDialogueFaceProvider::class.java
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class ArtificialDialogueFaceProvider(
|
||||
val modelType: String = "",
|
||||
val identifier: Identifier = cobblemonResource("bulbasaur"),
|
||||
val aspects: Set<String> = setOf()
|
||||
) : DialogueFaceProvider
|
||||
|
||||
class ReferenceDialogueFaceProvider(
|
||||
val entityId: Int
|
||||
): DialogueFaceProvider
|
||||
|
||||
class PlayerDialogueFaceProvider(val playerId: UUID) : DialogueFaceProvider
|
||||
|
||||
class ExpressionLikeDialogueFaceProvider(
|
||||
val providerExpression: ExpressionLike
|
||||
): DialogueFaceProvider
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.dialogue
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueClosedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueOpenedPacket
|
||||
import com.cobblemon.mod.common.util.activeDialogue
|
||||
import java.util.UUID
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
|
||||
/**
|
||||
* Manages the active dialogues for players. Map is indexed by player UUID.
|
||||
* You really need to make sure any dialogues you start with a player go through this otherwise
|
||||
* the player won't be able to close the dialogue.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since December 27th, 2023
|
||||
*/
|
||||
object DialogueManager {
|
||||
val activeDialogues = mutableMapOf<UUID, ActiveDialogue>()
|
||||
|
||||
fun startDialogue(playerEntity: ServerPlayerEntity, dialogue: Dialogue) {
|
||||
val activeDialogue = ActiveDialogue(playerEntity, dialogue)
|
||||
activeDialogues[playerEntity.uuid] = activeDialogue
|
||||
val packet = DialogueOpenedPacket(activeDialogue, includeFaces = true)
|
||||
playerEntity.sendPacket(packet)
|
||||
}
|
||||
|
||||
fun stopDialogue(playerEntity: ServerPlayerEntity) {
|
||||
val activeDialogue = playerEntity.activeDialogue ?: return
|
||||
DialogueClosedPacket(activeDialogue.dialogueId).sendToPlayer(playerEntity)
|
||||
activeDialogues.remove(activeDialogue.dialogueId)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.dialogue
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.struct.MoStruct
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.dialogue.input.DialogueInput
|
||||
import com.cobblemon.mod.common.api.dialogue.input.DialogueNoInput
|
||||
import com.google.gson.JsonArray
|
||||
import net.minecraft.text.MutableText
|
||||
|
||||
/**
|
||||
* A page of a dialogue. This has lines of text and also some kind of input expected from the player.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since December 27th, 2023
|
||||
*/
|
||||
class DialoguePage(
|
||||
var id: String = "",
|
||||
var speaker: String? = null,
|
||||
var lines: MutableList<DialogueText> = mutableListOf(),
|
||||
var input: DialogueInput = DialogueNoInput(),
|
||||
var clientActions: MutableList<Expression> = mutableListOf(),
|
||||
var escapeAction: DialogueAction? = null,
|
||||
) {
|
||||
companion object {
|
||||
@JvmOverloads
|
||||
fun of(
|
||||
/** The ID is optional, but if you want to be able to jump to this page from other pages then you probably want to set this. */
|
||||
id: String = "",
|
||||
speaker: String? = null,
|
||||
lines: Iterable<MutableText>,
|
||||
input: DialogueInput = DialogueNoInput(),
|
||||
clientActions: Iterable<Expression> = emptyList(),
|
||||
/** The thing to do when the player presses ESC while on this page. If null, falls back to the same property on [Dialogue]. */
|
||||
escapeAction: ((ActiveDialogue) -> Unit)? = null,
|
||||
): DialoguePage {
|
||||
return DialoguePage(
|
||||
id = id,
|
||||
speaker = speaker,
|
||||
lines = lines.map { WrappedDialogueText(it) }.toMutableList(),
|
||||
input = input,
|
||||
clientActions = clientActions.toMutableList(),
|
||||
escapeAction = escapeAction?.let { func -> FunctionDialogueAction { activeDialogue, _ -> func(activeDialogue) } }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun toMoLangStruct(activeDialogue: ActiveDialogue): MoStruct {
|
||||
return QueryStruct(
|
||||
hashMapOf(
|
||||
"id" to java.util.function.Function { _ -> StringValue(id) },
|
||||
"input" to java.util.function.Function { _ -> activeDialogue.activeInput.struct },
|
||||
"lines" to java.util.function.Function { _ ->
|
||||
val array = JsonArray()
|
||||
lines.forEach { array.add(it(activeDialogue).string) }
|
||||
MoValue.of(array)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.dialogue
|
||||
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
|
||||
/**
|
||||
* A predicate loaded for a particular dialogue. Tests arbitrary conditions about the dialogue context.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since December 29th, 2023
|
||||
*/
|
||||
interface DialoguePredicate {
|
||||
companion object {
|
||||
val types = mutableMapOf<String, Class<out DialoguePredicate>>()
|
||||
}
|
||||
|
||||
operator fun invoke(dialogue: ActiveDialogue): Boolean
|
||||
}
|
||||
|
||||
class ExpressionLikeDialoguePredicate(val expression: ExpressionLike = "true".asExpressionLike()) : DialoguePredicate {
|
||||
override fun invoke(dialogue: ActiveDialogue) = dialogue.runtime.resolveBoolean(expression)
|
||||
}
|
||||
|
||||
class FunctionDialoguePredicate(val predicate: (ActiveDialogue) -> Boolean = { true }) : DialoguePredicate {
|
||||
override fun invoke(dialogue: ActiveDialogue) = predicate(dialogue)
|
||||
}
|
||||
@@ -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.dialogue
|
||||
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import net.minecraft.text.MutableText
|
||||
|
||||
/**
|
||||
* A kind of speaker in a dialogue. They include a name and a face, each optional.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since January 1st, 2024
|
||||
*/
|
||||
class DialogueSpeaker(
|
||||
val name: DialogueText? = null,
|
||||
val face: DialogueFaceProvider? = null
|
||||
) {
|
||||
fun of(name: MutableText = "".text(), face: DialogueFaceProvider? = null) = DialogueSpeaker(WrappedDialogueText(name), face)
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.dialogue
|
||||
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveString
|
||||
import net.minecraft.text.MutableText
|
||||
|
||||
/**
|
||||
* Some kind of text-resolving property. This is to hide where sometimes we want literals,
|
||||
* sometimes we want the text to come from a function, and sometimes we want it to be the
|
||||
* product of a MoLang script.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since December 29th, 2023
|
||||
*/
|
||||
interface DialogueText {
|
||||
companion object {
|
||||
val types = mutableMapOf<String, Class<out DialogueText>>(
|
||||
"expression" to ExpressionLikeDialogueText::class.java,
|
||||
)
|
||||
}
|
||||
|
||||
operator fun invoke(activeDialogue: ActiveDialogue): MutableText
|
||||
}
|
||||
|
||||
class FunctionDialogueText(val function: (ActiveDialogue) -> MutableText = { "".text() }) : DialogueText {
|
||||
override fun invoke(activeDialogue: ActiveDialogue) = function(activeDialogue)
|
||||
}
|
||||
|
||||
class WrappedDialogueText(val text: MutableText = "".text()) : DialogueText {
|
||||
override fun invoke(activeDialogue: ActiveDialogue) = text.copy()
|
||||
}
|
||||
|
||||
class ExpressionLikeDialogueText(val expression: ExpressionLike = "''".asExpressionLike()) : DialogueText {
|
||||
override fun invoke(activeDialogue: ActiveDialogue): MutableText {
|
||||
return activeDialogue.runtime.resolveString(expression).text()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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.dialogue
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.dialogue.input.DialogueInput
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.util.adapters.DialogueActionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.DialogueFaceProviderAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.DialogueInputAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.DialoguePredicateAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.DialogueTextAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.TextAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.resource.ResourceType
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.text.MutableText
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
/**
|
||||
* Registry for dialogue data.
|
||||
*
|
||||
* @see Dialogue
|
||||
* @since December 29th, 2023
|
||||
* @author Hiroku
|
||||
*/
|
||||
object Dialogues : JsonDataRegistry<Dialogue> {
|
||||
override val id = cobblemonResource("dialogues")
|
||||
override val type = ResourceType.SERVER_DATA
|
||||
override val observable = SimpleObservable<Dialogues>()
|
||||
|
||||
val dialogues = mutableMapOf<Identifier, Dialogue>()
|
||||
/** If you need custom adapters registered, subscribe to this and register them. */
|
||||
val gsonObservable: SimpleObservable<GsonBuilder> = SimpleObservable()
|
||||
|
||||
override fun sync(player: ServerPlayerEntity) {}
|
||||
|
||||
override val gson = GsonBuilder()
|
||||
.registerTypeAdapter(DialogueAction::class.java, DialogueActionAdapter)
|
||||
.registerTypeAdapter(DialoguePredicate::class.java, DialoguePredicateAdapter)
|
||||
.registerTypeAdapter(DialogueInput::class.java, DialogueInputAdapter)
|
||||
.registerTypeAdapter(DialogueFaceProvider::class.java, DialogueFaceProviderAdapter)
|
||||
.registerTypeAdapter(DialogueText::class.java, DialogueTextAdapter)
|
||||
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(MutableText::class.java, TextAdapter)
|
||||
.registerTypeAdapter(Identifier::class.java, IdentifierAdapter)
|
||||
.also { gsonObservable.emit(it) }
|
||||
.create()
|
||||
|
||||
override val typeToken = TypeToken.get(Dialogue::class.java)
|
||||
override val resourcePath = "dialogues"
|
||||
|
||||
override fun reload(data: Map<Identifier, Dialogue>) {
|
||||
dialogues.putAll(data)
|
||||
observable.emit(this)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.dialogue.input
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.api.dialogue.ActiveDialogue
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* An active input waiting for the player as part of an [ActiveDialogue]. The purpose of this is to
|
||||
* maintain some data integrity and track how long it's taken to choose an action.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since December 27th, 2023
|
||||
*/
|
||||
class ActiveInput(
|
||||
val activeDialogue: ActiveDialogue,
|
||||
val dialogueInput: DialogueInput
|
||||
) {
|
||||
val inputId = UUID.randomUUID()
|
||||
val startTime = server()!!.overworld.time
|
||||
|
||||
val struct = toMoLangStruct()
|
||||
|
||||
fun handle(input: String) {
|
||||
val secondsToChoose = (server()!!.overworld.time - startTime) / 20F
|
||||
activeDialogue.runtime.environment.setSimpleVariable("seconds_taken_to_input", DoubleValue(secondsToChoose))
|
||||
dialogueInput.handle(this, input)
|
||||
}
|
||||
|
||||
fun toMoLangStruct(): MoValue {
|
||||
return dialogueInput.toMoLangStruct(this)
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.dialogue.input
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.dialogue.DialogueAction
|
||||
import com.cobblemon.mod.common.api.dialogue.FunctionDialogueAction
|
||||
|
||||
/**
|
||||
* Input that has no input but has an action that will run after a delay.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since December 27th, 2023
|
||||
*/
|
||||
class DialogueAutoContinueInput : DialogueInput {
|
||||
val delay = 5F
|
||||
/** Whether the player can click to move on in a hurry or if they must wait. */
|
||||
var allowSkip = true
|
||||
var showTimer = false
|
||||
val action: DialogueAction = FunctionDialogueAction { dialogue, _ -> dialogue.incrementPage() }
|
||||
|
||||
override var timeout: DialogueTimeout?
|
||||
get() = DialogueTimeout(duration = delay, showTimer = showTimer, action)
|
||||
set(_) {}
|
||||
|
||||
override fun toMoLangStruct(activeInput: ActiveInput) = QueryStruct(hashMapOf())
|
||||
|
||||
|
||||
override fun handle(activeInput: ActiveInput, value: String) {
|
||||
if (!allowSkip) {
|
||||
return Cobblemon.LOGGER.warn("A no-skip dialogue received input from ${activeInput.activeDialogue.playerEntity.gameProfile.name}, is this person a hacker or something")
|
||||
}
|
||||
|
||||
action.invoke(activeInput.activeDialogue)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.dialogue.input
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.MoStruct
|
||||
import com.cobblemon.mod.common.api.dialogue.DialoguePage
|
||||
|
||||
/**
|
||||
* A type of input to [DialoguePage]s. This is sealed because the client needs to know about it. Sorry.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since December 27th, 2023
|
||||
*/
|
||||
sealed interface DialogueInput {
|
||||
var timeout: DialogueTimeout?
|
||||
fun toMoLangStruct(activeInput: ActiveInput): MoStruct
|
||||
fun handle(activeInput: ActiveInput, value: String)
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.dialogue.input
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.cobblemon.mod.common.api.dialogue.DialogueAction
|
||||
import com.cobblemon.mod.common.api.dialogue.FunctionDialogueAction
|
||||
|
||||
/**
|
||||
* An input type that's really just waiting for the player to click or something.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since December 27th, 2023
|
||||
|
||||
*/
|
||||
class DialogueNoInput(
|
||||
var action: DialogueAction = FunctionDialogueAction { dialogue, _ -> dialogue.incrementPage() }
|
||||
) : DialogueInput {
|
||||
override var timeout: DialogueTimeout?
|
||||
get() = null
|
||||
set(_) {}
|
||||
|
||||
override fun toMoLangStruct(activeInput: ActiveInput) = VariableStruct()
|
||||
override fun handle(activeInput: ActiveInput, value: String) {
|
||||
action(activeInput.activeDialogue)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.dialogue.input
|
||||
|
||||
import com.cobblemon.mod.common.api.dialogue.DialogueAction
|
||||
import com.cobblemon.mod.common.api.dialogue.DialoguePredicate
|
||||
import com.cobblemon.mod.common.api.dialogue.DialogueText
|
||||
import com.cobblemon.mod.common.api.dialogue.FunctionDialogueAction
|
||||
import com.cobblemon.mod.common.api.dialogue.FunctionDialoguePredicate
|
||||
import com.cobblemon.mod.common.api.dialogue.WrappedDialogueText
|
||||
|
||||
/**
|
||||
* A choosable option as part of a [DialogueOptionSetInput].
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since December 27th, 2023
|
||||
*/
|
||||
class DialogueOption(
|
||||
var text: DialogueText = WrappedDialogueText(),
|
||||
/** The value is a unique identifier so the client can tell the server what they selected. Don't forget this. */
|
||||
var value: String = "",
|
||||
/** The action to run when they click it. */
|
||||
var action: DialogueAction = FunctionDialogueAction { _, _ -> },
|
||||
val isVisible: DialoguePredicate = FunctionDialoguePredicate(),
|
||||
val isSelectable: DialoguePredicate = FunctionDialoguePredicate()
|
||||
)
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.dialogue.input
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.dialogue.ActiveDialogue
|
||||
|
||||
/**
|
||||
* A type of [DialogueInput] that has the player choose from a list of options.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since December 27th, 2023
|
||||
*/
|
||||
class DialogueOptionSetInput(
|
||||
var options: MutableList<DialogueOption>,
|
||||
override var timeout: DialogueTimeout? = null,
|
||||
/** Whether the buttons should be stacked vertically. */
|
||||
var vertical: Boolean = false,
|
||||
) : DialogueInput {
|
||||
|
||||
// JSON uses this. Basically so that the main constructor can force people to specify options
|
||||
constructor() : this(mutableListOf(), null, false)
|
||||
|
||||
fun getVisibleOptions(activeDialogue: ActiveDialogue) = options.filter { it.isVisible(activeDialogue) }
|
||||
override fun toMoLangStruct(activeInput: ActiveInput) = QueryStruct(hashMapOf())
|
||||
override fun handle(activeInput: ActiveInput, value: String) {
|
||||
val option = options.firstOrNull { it.value == value }
|
||||
if (option != null) {
|
||||
if (!option.isSelectable(activeInput.activeDialogue)) {
|
||||
Cobblemon.LOGGER.warn("Dialogue option $value is not selectable but ${activeInput.activeDialogue.playerEntity.gameProfile.name} selected it anyway")
|
||||
activeInput.activeDialogue.close()
|
||||
} else if (!option.isVisible(activeInput.activeDialogue)) {
|
||||
Cobblemon.LOGGER.warn("Dialogue option $value is not visible but ${activeInput.activeDialogue.playerEntity.gameProfile.name} selected it anyway")
|
||||
activeInput.activeDialogue.close()
|
||||
}
|
||||
|
||||
option.action(activeInput.activeDialogue, value)
|
||||
} else {
|
||||
Cobblemon.LOGGER.warn("No option with value $value found in dialogue option set")
|
||||
}
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.dialogue.input
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.dialogue.DialogueAction
|
||||
import com.cobblemon.mod.common.api.dialogue.FunctionDialogueAction
|
||||
|
||||
/**
|
||||
* A text input for dialogues where the player can enter free text.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since December 27th, 2023
|
||||
*/
|
||||
class DialogueTextInput : DialogueInput {
|
||||
override var timeout: DialogueTimeout? = null
|
||||
val action: DialogueAction = FunctionDialogueAction { dialogue, _ -> dialogue.setPage(dialogue.currentPageIndex + 1) }
|
||||
override fun toMoLangStruct(activeInput: ActiveInput) = QueryStruct(hashMapOf())
|
||||
|
||||
override fun handle(activeInput: ActiveInput, value: String) {
|
||||
action.invoke(activeInput.activeDialogue, value)
|
||||
}
|
||||
}
|
||||
@@ -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.dialogue.input
|
||||
|
||||
import com.cobblemon.mod.common.api.dialogue.DialogueAction
|
||||
import com.cobblemon.mod.common.api.dialogue.FunctionDialogueAction
|
||||
|
||||
/**
|
||||
* A deadline for dialogue input. This is used to have something occur if the player spends
|
||||
* too long on one page of dialogue.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since December 27th, 2023
|
||||
*/
|
||||
class DialogueTimeout(
|
||||
var duration: Float = 10F,
|
||||
var showTimer: Boolean = true,
|
||||
var action: DialogueAction = FunctionDialogueAction { dialogue, _ -> dialogue.close() }
|
||||
)
|
||||
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.api.drop
|
||||
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.LOOT_DROPPED
|
||||
import com.cobblemon.mod.common.api.events.drops.LootDroppedEvent
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
@@ -88,6 +89,8 @@ class DropTable {
|
||||
amount: IntRange = this.amount
|
||||
) {
|
||||
val drops = getDrops(amount).toMutableList()
|
||||
val heldItem = (entity as PokemonEntity).pokemon.heldItemNoCopy()
|
||||
if (!heldItem.isEmpty) entity.dropItem(heldItem.item)
|
||||
LOOT_DROPPED.postThen(
|
||||
event = LootDroppedEvent(this, player, entity, drops),
|
||||
ifSucceeded = { it.drops.forEach { it.drop(entity, world, pos, player) } }
|
||||
|
||||
@@ -31,14 +31,14 @@ import net.minecraft.util.math.Vec3d
|
||||
* @author Hiroku
|
||||
* @since July 24th, 2022
|
||||
*/
|
||||
class ItemDropEntry : DropEntry {
|
||||
open class ItemDropEntry : DropEntry {
|
||||
override val percentage = 100F
|
||||
override val quantity = 1
|
||||
val quantityRange: IntRange? = null
|
||||
open val quantityRange: IntRange? = null
|
||||
override val maxSelectableTimes = 1
|
||||
val dropMethod: ItemDropMethod? = null
|
||||
val item = Identifier("minecraft:fish")
|
||||
val nbt: NbtCompound? = null
|
||||
open val dropMethod: ItemDropMethod? = null
|
||||
open val item = Identifier("minecraft:fish")
|
||||
open val nbt: NbtCompound? = null
|
||||
|
||||
override fun drop(entity: LivingEntity?, world: ServerWorld, pos: Vec3d, player: ServerPlayerEntity?) {
|
||||
val item = world.registryManager.get(RegistryKeys.ITEM).get(item) ?: return LOGGER.error("Unable to load drop item: $item")
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.entity
|
||||
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.entity.data.TrackedData
|
||||
|
||||
/**
|
||||
* Represents a delegation of a portion of an entity's logic to a particular side.
|
||||
@@ -16,4 +17,5 @@ import net.minecraft.entity.Entity
|
||||
interface EntitySideDelegate<T : Entity> {
|
||||
fun initialize(entity: T) {}
|
||||
fun tick(entity: T) {}
|
||||
fun onTrackedDataSet(data: TrackedData<*>) {}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.cobblemon.mod.common.api.entity.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.effects.IllusionEffect
|
||||
import com.cobblemon.mod.common.entity.pokemon.effects.TransformEffect
|
||||
import com.cobblemon.mod.common.pokemon.FormData
|
||||
import com.cobblemon.mod.common.pokemon.Species
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import net.minecraft.nbt.NbtCompound
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* Represents a temporary alteration to how a [PokemonEntity] is rendered and behaves. May include a temporary visual effect
|
||||
* when applied.
|
||||
*
|
||||
* @author Segfault Guy
|
||||
* @since March 5th, 2024
|
||||
*/
|
||||
interface EntityEffect {
|
||||
|
||||
/**
|
||||
* Starts this effect for the provided [PokemonEntity].
|
||||
*
|
||||
* @return A [CompletableFuture] that completes after the effect has been applied. Or null if the effect failed to start.
|
||||
*/
|
||||
fun start(entity: PokemonEntity): CompletableFuture<PokemonEntity>?
|
||||
|
||||
/**
|
||||
* Ends this effect for the provided [PokemonEntity].
|
||||
*
|
||||
* @return A [CompletableFuture] that completes after the effect has been reverted. Or null if the effect failed to end.
|
||||
*/
|
||||
fun end(entity: PokemonEntity): CompletableFuture<PokemonEntity>?
|
||||
|
||||
/** Saves this effect to NBT. */
|
||||
fun saveToNbt(): NbtCompound
|
||||
|
||||
/** Loads this effect from NBT. */
|
||||
fun loadFromNBT(nbt: NbtCompound)
|
||||
|
||||
companion object {
|
||||
|
||||
private val effects = mutableMapOf<String, KClass<out EntityEffect>>()
|
||||
private val defaults = mutableMapOf<String, () -> EntityEffect>()
|
||||
|
||||
init {
|
||||
register(IllusionEffect.ID, IllusionEffect::class, ::IllusionEffect)
|
||||
register(TransformEffect.ID, TransformEffect::class, ::TransformEffect)
|
||||
}
|
||||
|
||||
fun <T : EntityEffect> register(id: String, type: KClass<T>, default: () -> T) {
|
||||
effects[id] = type
|
||||
defaults[id] = default
|
||||
}
|
||||
|
||||
fun createDefault(id: String): EntityEffect? = defaults[id]?.invoke()
|
||||
|
||||
fun loadFromNbt(nbt: NbtCompound): EntityEffect? {
|
||||
if (nbt.contains(DataKeys.ENTITY_EFFECT_ID)) {
|
||||
val id = nbt.getString(DataKeys.ENTITY_EFFECT_ID)
|
||||
return createDefault(id)?.also { it.loadFromNBT(nbt) }
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** An [EntityEffect] that modifies the dimensions of a [PokemonEntity]. */
|
||||
interface PhysicalEffect : EntityEffect {
|
||||
val scale: Float
|
||||
}
|
||||
|
||||
/** An [EntityEffect] that alters the physical appearance of a [PokemonEntity] to match a [mock]. */
|
||||
interface MocKEffect : PhysicalEffect {
|
||||
val mock: PokemonProperties
|
||||
|
||||
val exposedSpecies: Species?
|
||||
get() = this.mock.species?.let { PokemonSpecies.getByIdentifier(it.asIdentifierDefaultingNamespace()) }
|
||||
|
||||
val exposedForm: FormData?
|
||||
get() = this.mock.form?.let {
|
||||
formID -> this.exposedSpecies?.forms?.firstOrNull { it.formOnlyShowdownId().equals(formID, true) } }
|
||||
?: this.exposedSpecies?.standardForm
|
||||
}
|
||||
@@ -33,6 +33,8 @@ import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEv
|
||||
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionDisplayEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionTestedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.interaction.ExperienceCandyUseEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.interaction.HeldItemUpdatedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.interaction.PokemonInteractionGUICreationEvent
|
||||
import com.cobblemon.mod.common.api.events.starter.StarterChosenEvent
|
||||
import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent
|
||||
import com.cobblemon.mod.common.api.events.world.BigRootPropagatedEvent
|
||||
@@ -65,6 +67,8 @@ object CobblemonEvents {
|
||||
val EVOLUTION_COMPLETE = EventObservable<EvolutionCompleteEvent>()
|
||||
@JvmField
|
||||
val POKEMON_NICKNAMED = CancelableObservable<PokemonNicknamedEvent>()
|
||||
@JvmField
|
||||
val HELD_ITEM_UPDATED = CancelableObservable<HeldItemUpdatedEvent>()
|
||||
|
||||
@JvmField
|
||||
val THROWN_POKEBALL_HIT = CancelableObservable<ThrownPokeballHitEvent>()
|
||||
@@ -100,6 +104,9 @@ object CobblemonEvents {
|
||||
@JvmField
|
||||
val LEVEL_UP_EVENT = EventObservable<LevelUpEvent>()
|
||||
|
||||
@JvmField
|
||||
/** CLIENT ONLY! */
|
||||
val POKEMON_INTERACTION_GUI_CREATION = EventObservable<PokemonInteractionGUICreationEvent>()
|
||||
@JvmField
|
||||
val POKEMON_ENTITY_SAVE = EventObservable<PokemonEntitySaveEvent>()
|
||||
@JvmField
|
||||
@@ -153,4 +160,8 @@ object CobblemonEvents {
|
||||
val LEFTOVERS_CREATED = CancelableObservable<LeftoversCreatedEvent>()
|
||||
@JvmField
|
||||
val BIG_ROOT_PROPAGATED = CancelableObservable<BigRootPropagatedEvent>()
|
||||
@JvmField
|
||||
val HELD_ITEM_PRE = CancelableObservable<HeldItemEvent.Pre>()
|
||||
@JvmField
|
||||
val HELD_ITEM_POST = EventObservable<HeldItemEvent.Post>()
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.item.ItemStack
|
||||
|
||||
/**
|
||||
* The base for all the events related to held items.
|
||||
*
|
||||
* @see [Pre]
|
||||
* @see [Post]
|
||||
*/
|
||||
interface HeldItemEvent {
|
||||
|
||||
/**
|
||||
* The [Pokemon] triggering this event.
|
||||
*/
|
||||
val pokemon: Pokemon
|
||||
|
||||
/**
|
||||
* Fired at the start of [Pokemon.swapHeldItem].
|
||||
*
|
||||
* This event should be used to mutate the results of this transaction.
|
||||
*
|
||||
* Canceling this event will prevent the operation and causes the return to be item attempted to be given originally.
|
||||
*
|
||||
* @property pokemon The [Pokemon] triggering this event.
|
||||
* @property receiving The [ItemStack] being sent received from the transaction. By default, this is the item that triggered the interaction.
|
||||
* @property returning The [ItemStack] being sent back from the transaction. By default, this is the currently held item.
|
||||
* @property decrement If the operation should decrement the [receiving] [ItemStack.count], this is handled in the implementation.
|
||||
*
|
||||
* @see [Post]
|
||||
*/
|
||||
data class Pre(override val pokemon: Pokemon, var receiving: ItemStack, var returning: ItemStack, var decrement: Boolean) : HeldItemEvent, Cancelable()
|
||||
|
||||
/**
|
||||
* Fired at the end of [Pokemon.swapHeldItem].
|
||||
*
|
||||
* @property pokemon The [Pokemon] triggering this event.
|
||||
* @property received The [ItemStack] considered as received and set to the [pokemon]. This is a copy and mutation will not be taken into account.
|
||||
* @property returned The [ItemStack] returned by the method call. This is a copy and mutation will not be taken into account.
|
||||
* @property decremented If the [received] [ItemStack] got decremented.
|
||||
*
|
||||
* @see [Pre]
|
||||
*/
|
||||
data class Post(override val pokemon: Pokemon, val received: ItemStack, val returned: ItemStack, val decremented: Boolean) : HeldItemEvent
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon.interaction
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.item.ItemStack
|
||||
|
||||
/**
|
||||
* Event published when a held item is being updated on a [Pokemon].
|
||||
* Cancelling the event will prevent any action from being taken on
|
||||
* the Pokémon.
|
||||
*
|
||||
* [newItem] differs from [originalStack] in that the former is a
|
||||
* one-sized version of the original (Pokémon cannot hold stacks) and
|
||||
* changing it in any way will not affect the original item held by
|
||||
* the player.
|
||||
*
|
||||
* @author Whatsy, Hiroku
|
||||
* @since November 13th, 2023
|
||||
*/
|
||||
data class HeldItemUpdatedEvent(
|
||||
val cause: LivingEntity?,
|
||||
val pokemon: Pokemon,
|
||||
val originalStack: ItemStack,
|
||||
val decrement: Boolean,
|
||||
val oldItem: ItemStack,
|
||||
val newItem: ItemStack
|
||||
) : Cancelable()
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon.interaction
|
||||
|
||||
import com.cobblemon.mod.common.client.gui.interact.wheel.InteractWheelOption
|
||||
import com.cobblemon.mod.common.client.gui.interact.wheel.Orientation
|
||||
import com.google.common.collect.Multimap
|
||||
import java.util.UUID
|
||||
|
||||
data class PokemonInteractionGUICreationEvent(
|
||||
val pokemonID: UUID,
|
||||
val mountShoulder: Boolean,
|
||||
val options: Multimap<Orientation, InteractWheelOption>
|
||||
) {
|
||||
fun addFillingOption(option: InteractWheelOption) {
|
||||
options.put(getNextFreeOrientation(), option)
|
||||
}
|
||||
|
||||
fun addOption(orientation: Orientation, option: InteractWheelOption) {
|
||||
options.put(orientation, option)
|
||||
}
|
||||
|
||||
private fun getNextFreeOrientation(): Orientation {
|
||||
var largest = Orientation.TOP_LEFT
|
||||
for(orientation in Orientation.values()) {
|
||||
if(!options.containsKey(orientation)) {
|
||||
return orientation
|
||||
} else {
|
||||
if(options.get(orientation).size < options.get(largest).size) {
|
||||
largest = orientation
|
||||
}
|
||||
}
|
||||
}
|
||||
return largest
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.fossil
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.pokemon.evolution.predicate.NbtItemPredicate
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.registry.Registries
|
||||
import net.minecraft.text.MutableText
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.StringIdentifiable
|
||||
|
||||
class Fossil(
|
||||
identifier: Identifier,
|
||||
val result: PokemonProperties,
|
||||
val fossils: List<NbtItemPredicate>
|
||||
): StringIdentifiable {
|
||||
|
||||
@Transient
|
||||
var identifier: Identifier = identifier
|
||||
internal set
|
||||
|
||||
override fun asString(): String {
|
||||
return identifier.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the fossil.
|
||||
* @return The name of the fossil.
|
||||
*/
|
||||
fun getName(): MutableText = Text.translatable("${identifier.namespace}.fossil.${identifier.path}.name")
|
||||
|
||||
/**
|
||||
* Whether the fossil ingredients match this fossil.
|
||||
* @param ingredients The ingredients to check.
|
||||
* @return True if the ingredients match, false otherwise.
|
||||
*/
|
||||
fun matchesIngredients(ingredients: List<ItemStack>): Boolean {
|
||||
if (this.fossils.size != ingredients.size) {
|
||||
return false
|
||||
}
|
||||
|
||||
return this.fossils.all { fossil ->
|
||||
ingredients.any { fossil.item.fits(it.item, Registries.ITEM) && fossil.nbt.test(it) }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the fossil ingredients match a subset of this fossil.
|
||||
* @param ingredients The ingredients to check.
|
||||
* @return True if the ingredients are a subset, false otherwise.
|
||||
*/
|
||||
fun matchesIngredientsSubSet(ingredients: List<ItemStack>): Boolean {
|
||||
if (this.fossils.size < ingredients.size) {
|
||||
return false
|
||||
}
|
||||
|
||||
return ingredients.all { ingredient ->
|
||||
ingredients.count { item -> ingredient.itemMatches(item.registryEntry) } <=
|
||||
this.fossils.count { fossil -> fossil.item.fits(ingredient.item, Registries.ITEM) && fossil.nbt.test(ingredient) }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the [ItemStack] is an ingredient for this fossil.
|
||||
* @param itemStack The [ItemStack] to check.
|
||||
* @return True if the [ItemStack] is an ingredient, false otherwise.
|
||||
*/
|
||||
fun isIngredient(itemStack: ItemStack): Boolean {
|
||||
return this.fossils.any { it.item.fits(itemStack.item, Registries.ITEM) && it.nbt.test(itemStack) }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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.fossil
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.net.messages.client.fossil.FossilRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.pokemon.evolution.adapters.NbtItemPredicateAdapter
|
||||
import com.cobblemon.mod.common.pokemon.evolution.predicate.NbtItemPredicate
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ItemLikeConditionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.pokemonPropertiesShortAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.item.Item
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.resource.ResourceType
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
object Fossils: JsonDataRegistry<Fossil> {
|
||||
|
||||
override val id: Identifier = cobblemonResource("fossils")
|
||||
override val type: ResourceType = ResourceType.SERVER_DATA
|
||||
override val observable = SimpleObservable<Fossils>()
|
||||
|
||||
override val gson = GsonBuilder()
|
||||
.disableHtmlEscaping()
|
||||
.setPrettyPrinting()
|
||||
.registerTypeAdapter(Identifier::class.java, IdentifierAdapter)
|
||||
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
|
||||
.registerTypeAdapter(NbtItemPredicate::class.java, NbtItemPredicateAdapter)
|
||||
.create()
|
||||
|
||||
override val typeToken: TypeToken<Fossil> = TypeToken.get(Fossil::class.java)
|
||||
override val resourcePath: String = "fossils"
|
||||
|
||||
private val fossils = hashMapOf<Identifier, Fossil>()
|
||||
|
||||
override fun reload(data: Map<Identifier, Fossil>) {
|
||||
this.fossils.clear()
|
||||
data.forEach { (identifier, fossil) ->
|
||||
try {
|
||||
fossil.identifier = identifier
|
||||
this.fossils[identifier] = fossil
|
||||
} catch (e: Exception) {
|
||||
Cobblemon.LOGGER.error("Skipped loading the {} fossil", identifier, e)
|
||||
}
|
||||
}
|
||||
Cobblemon.LOGGER.info("Loaded {} fossils", this.fossils.size)
|
||||
this.observable.emit(this)
|
||||
}
|
||||
|
||||
override fun sync(player: ServerPlayerEntity) {
|
||||
FossilRegistrySyncPacket(this.all()).sendToPlayer(player)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all loaded [Fossil]s.
|
||||
*/
|
||||
fun all() = this.fossils.values.toList()
|
||||
|
||||
/**
|
||||
* Gets a [Fossil] by its [Identifier].
|
||||
* @param identifier The identifier of the fossil.
|
||||
* @return The [Fossil] if loaded, otherwise null.
|
||||
*/
|
||||
fun getByIdentifier(identifier: Identifier): Fossil? = this.fossils[identifier]
|
||||
|
||||
/**
|
||||
* Looks for a [Fossil] that matches a [ItemStack].
|
||||
* @param fossilStacks The fossil [ItemStack]'s.
|
||||
* @return The [Fossil] if found, otherwise null.
|
||||
*/
|
||||
fun getFossilByItemStacks(fossilStacks: List<ItemStack>): Fossil? {
|
||||
return this.all().firstOrNull { it.matchesIngredients(fossilStacks) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks for a [Fossil] that is a superset of [ItemStack].
|
||||
* @param fossilStacks The fossil [ItemStack]'s.
|
||||
* @return The [Fossil] if found to be a superset, otherwise null.
|
||||
*/
|
||||
fun getSubFossilByItemStacks(fossilStacks: List<ItemStack>): Fossil? {
|
||||
return this.all().firstOrNull { it.matchesIngredientsSubSet(fossilStacks) }
|
||||
}
|
||||
/**
|
||||
* Checks if a [ItemStack] is a fossil ingredient.
|
||||
* @param itemStack The ingredient [ItemStack].
|
||||
* @return true if it's a fossil ingredient, otherwise false.
|
||||
*/
|
||||
fun isFossilIngredient(itemStack: ItemStack): Boolean {
|
||||
return this.all().any { it.isIngredient(itemStack) }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.fossil
|
||||
|
||||
import com.cobblemon.mod.common.registry.ItemTagCondition
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
data class NaturalMaterial(
|
||||
val content: Int = 0,
|
||||
val item: Identifier?,
|
||||
val tag: ItemTagCondition? = null,
|
||||
val returnItem: Identifier? = null
|
||||
)
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.fossil
|
||||
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.net.messages.client.fossil.NaturalMaterialRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.registry.ItemTagCondition
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ItemLikeConditionAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.registry.Registries
|
||||
import net.minecraft.resource.ResourceType
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
object NaturalMaterials : JsonDataRegistry<List<NaturalMaterial>>{
|
||||
override val id = cobblemonResource("natural_materials")
|
||||
override val type = ResourceType.SERVER_DATA
|
||||
override val observable = SimpleObservable<NaturalMaterials>()
|
||||
override val typeToken: TypeToken<List<NaturalMaterial>> =
|
||||
TypeToken.getParameterized(List::class.java, NaturalMaterial::class.java) as TypeToken<List<NaturalMaterial>>
|
||||
override val resourcePath = "natural_materials"
|
||||
override val gson: Gson = GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.registerTypeAdapter(Identifier::class.java, IdentifierAdapter)
|
||||
.registerTypeAdapter(ItemTagCondition::class.java, ItemLikeConditionAdapter)
|
||||
.create()
|
||||
|
||||
private val itemMap = mutableMapOf<Identifier, NaturalMaterial>()
|
||||
private val tagMap = mutableMapOf<ItemTagCondition, NaturalMaterial>()
|
||||
override fun sync(player: ServerPlayerEntity) {
|
||||
NaturalMaterialRegistrySyncPacket(this.itemMap.values.toList() + this.tagMap.values.toList()).sendToPlayer(player)
|
||||
}
|
||||
|
||||
override fun reload(data: Map<Identifier, List<NaturalMaterial>>) {
|
||||
data.forEach { entry ->
|
||||
entry.value.forEach {
|
||||
itemMap.remove(it.item)
|
||||
if (it.item != null) {
|
||||
itemMap[it.item] = it
|
||||
}
|
||||
if (it.tag != null) {
|
||||
tagMap[it.tag] = it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun isNaturalMaterial(item: ItemStack): Boolean {
|
||||
val itemId = Registries.ITEM.getId(item.item)
|
||||
return itemId in itemMap.keys || tagMap.keys.any {
|
||||
it.fits(item.item, Registries.ITEM)
|
||||
}
|
||||
}
|
||||
|
||||
fun getContent(item: ItemStack): Int? {
|
||||
val itemId = Registries.ITEM.getId(item.item)
|
||||
if (itemId in itemMap.keys) {
|
||||
return itemMap[itemId]?.content
|
||||
}
|
||||
val tag = tagMap.keys.firstOrNull { it.fits(item.item, Registries.ITEM) }
|
||||
if (tag != null) {
|
||||
return tagMap[tag]?.content
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun getReturnItem(item: ItemStack): Identifier? {
|
||||
val itemId = Registries.ITEM.getId(item.item)
|
||||
if (itemId in itemMap.keys) {
|
||||
return itemMap[itemId]?.returnItem
|
||||
}
|
||||
val tag = tagMap.keys.firstOrNull { it.fits(item.item, Registries.ITEM) }
|
||||
if (tag != null) {
|
||||
return tagMap[tag]?.returnItem
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -208,10 +208,12 @@ fun drawPortraitPokemon(
|
||||
if (state == null) {
|
||||
model.setupAnimStateless(setOf(PoseType.PORTRAIT, PoseType.PROFILE))
|
||||
} else {
|
||||
val originalPose = state.currentPose
|
||||
model.getPose(PoseType.PORTRAIT)?.let { state.setPose(it.poseName) }
|
||||
state.timeEnteredPose = 0F
|
||||
state.updatePartialTicks(partialTicks)
|
||||
model.setupAnimStateful(null, state, 0F, 0F, 0F, 0F, 0F)
|
||||
originalPose?.let { state.setPose(it) }
|
||||
}
|
||||
|
||||
matrixStack.push()
|
||||
|
||||
@@ -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 }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.molang
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
|
||||
/**
|
||||
* An object that can be given a [MoLangRuntime] to produce a single [MoValue]. This abstracts
|
||||
* the use of simple and complex [Expression]s as MoLang can be a single line or multiple.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 22nd, 2023
|
||||
*/
|
||||
interface ExpressionLike {
|
||||
/** Produces a [MoValue] for a [MoLangRuntime] to supply an environment. */
|
||||
fun resolve(runtime: MoLangRuntime): MoValue
|
||||
|
||||
fun resolveDouble(runtime: MoLangRuntime) = resolve(runtime).asDouble()
|
||||
fun resolveFloat(runtime: MoLangRuntime) = resolveDouble(runtime).toFloat()
|
||||
fun resolveString(runtime: MoLangRuntime) = resolve(runtime).asString()
|
||||
fun resolveInt(runtime: MoLangRuntime) = resolveDouble(runtime).toInt()
|
||||
fun resolveBoolean(runtime: MoLangRuntime) = resolveDouble(runtime) == 1.0
|
||||
fun resolveObject(runtime: MoLangRuntime) = resolve(runtime) as ObjectValue<*>
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.molang
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
|
||||
/**
|
||||
* An [ExpressionLike] that produces MoValues by evaluating a series of [Expression]s.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 22nd, 2023
|
||||
*/
|
||||
class ListExpression(val exprs: List<Expression>): ExpressionLike {
|
||||
override fun resolve(runtime: MoLangRuntime) = exprs.resolve(runtime)
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* 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.molang
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangEnvironment
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.struct.ArrayStruct
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.dialogue.PlayerDialogueFaceProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.WaveFunction
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.WaveFunctions
|
||||
import com.cobblemon.mod.common.util.isInt
|
||||
import com.cobblemon.mod.common.util.itemRegistry
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.nbt.NbtCompound
|
||||
import net.minecraft.nbt.NbtDouble
|
||||
import net.minecraft.nbt.NbtElement
|
||||
import net.minecraft.nbt.NbtList
|
||||
import net.minecraft.nbt.NbtString
|
||||
import net.minecraft.registry.Registry
|
||||
import net.minecraft.registry.RegistryKey
|
||||
import net.minecraft.registry.RegistryKeys
|
||||
import net.minecraft.registry.entry.RegistryEntry
|
||||
import net.minecraft.registry.tag.TagKey
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.world.biome.Biome
|
||||
import net.minecraft.world.dimension.DimensionType
|
||||
|
||||
/**
|
||||
* Holds a bunch of useful MoLang trickery that can be used or extended in API
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 2nd, 2023
|
||||
*/
|
||||
object MoLangFunctions {
|
||||
val generalFunctions = hashMapOf<String, java.util.function.Function<MoParams, Any>>(
|
||||
"is_int" to java.util.function.Function { params -> DoubleValue(params.get<MoValue>(0).asString().isInt()) },
|
||||
"is_number" to java.util.function.Function { params -> DoubleValue(params.get<MoValue>(0).asString().toDoubleOrNull() != null) },
|
||||
"to_number" to java.util.function.Function { params -> DoubleValue(params.get<MoValue>(0).asString().toDoubleOrNull() ?: 0.0) },
|
||||
"to_int" to java.util.function.Function { params -> DoubleValue(params.get<MoValue>(0).asString().toIntOrNull() ?: 0) },
|
||||
"to_string" to java.util.function.Function { params -> StringValue(params.get<MoValue>(0).asString()) },
|
||||
"do_effect_walks" to java.util.function.Function { _ ->
|
||||
DoubleValue(Cobblemon.config.walkingInBattleAnimations)
|
||||
},
|
||||
"random" to java.util.function.Function { params ->
|
||||
val options = mutableListOf<MoValue>()
|
||||
var index = 0
|
||||
while (params.contains(index)) {
|
||||
options.add(params.get(index))
|
||||
index++
|
||||
}
|
||||
return@Function options.random() // Can throw an exception if they specified no args. They'd be idiots though.
|
||||
},
|
||||
"curve" to java.util.function.Function { params ->
|
||||
val curveName = params.getString(0)
|
||||
val curve = WaveFunctions.functions[curveName] ?: throw IllegalArgumentException("Unknown curve: $curveName")
|
||||
return@Function ObjectValue(curve)
|
||||
},
|
||||
"array" to java.util.function.Function { params ->
|
||||
val values = params.params
|
||||
val array = ArrayStruct(hashMapOf())
|
||||
values.forEachIndexed { index, moValue -> array.setDirectly("$index", moValue) }
|
||||
return@Function array
|
||||
}
|
||||
)
|
||||
val biomeFunctions = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
val worldFunctions = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
val dimensionTypeFunctions = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
val blockFunctions = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
val playerFunctions = mutableListOf<(ServerPlayerEntity) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
|
||||
{ player ->
|
||||
hashMapOf(
|
||||
"username" to java.util.function.Function { _ -> StringValue(player.gameProfile.name) },
|
||||
"uuid" to java.util.function.Function { _ -> StringValue(player.gameProfile.id.toString()) },
|
||||
"data" to java.util.function.Function { _ -> return@Function Cobblemon.molangData.load(player.uuid) },
|
||||
"save_data" to java.util.function.Function { _ -> Cobblemon.molangData.save(player.uuid) },
|
||||
"main_held_item" to java.util.function.Function { _ -> player.world.itemRegistry.getEntry(player.mainHandStack.item).asMoLangValue(RegistryKeys.ITEM) },
|
||||
"off_held_item" to java.util.function.Function { _ -> player.world.itemRegistry.getEntry(player.offHandStack.item).asMoLangValue(RegistryKeys.ITEM) },
|
||||
"face" to java.util.function.Function { _ -> ObjectValue(PlayerDialogueFaceProvider(player.uuid)) }
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
fun RegistryEntry<Biome>.asBiomeMoLangValue() = asMoLangValue(RegistryKeys.BIOME).addFunctions(biomeFunctions)
|
||||
fun RegistryEntry<World>.asWorldMoLangValue() = asMoLangValue(RegistryKeys.WORLD).addFunctions(worldFunctions)
|
||||
fun RegistryEntry<Block>.asBlockMoLangValue() = asMoLangValue(RegistryKeys.BLOCK).addFunctions(blockFunctions)
|
||||
fun RegistryEntry<DimensionType>.asDimensionTypeMoLangValue() = asMoLangValue(RegistryKeys.DIMENSION_TYPE).addFunctions(dimensionTypeFunctions)
|
||||
fun ServerPlayerEntity.asMoLangValue(): ObjectValue<ServerPlayerEntity> {
|
||||
val value = ObjectValue(
|
||||
obj = this,
|
||||
stringify = { it.entityName }
|
||||
)
|
||||
value.addFunctions(playerFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
|
||||
return value
|
||||
}
|
||||
|
||||
fun <T> RegistryEntry<T>.asMoLangValue(key: RegistryKey<Registry<T>>): ObjectValue<RegistryEntry<T>> {
|
||||
val value = ObjectValue(
|
||||
obj = this,
|
||||
stringify = { it.key.get().value.toString() }
|
||||
)
|
||||
value.functions.put("is_in") {
|
||||
val tag = TagKey.of(key, Identifier(it.getString(0).replace("#", "")))
|
||||
return@put DoubleValue(if (value.obj.isIn(tag)) 1.0 else 0.0)
|
||||
}
|
||||
value.functions.put("is_of") {
|
||||
val identifier = Identifier(it.getString(0))
|
||||
return@put DoubleValue(if (value.obj.matchesId(identifier)) 1.0 else 0.0)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
fun QueryStruct.addStandardFunctions(): QueryStruct {
|
||||
functions.putAll(generalFunctions)
|
||||
return this
|
||||
}
|
||||
|
||||
fun <T : QueryStruct> T.addFunctions(functions: Map<String, java.util.function.Function<MoParams, Any>>): T {
|
||||
this.functions.putAll(functions)
|
||||
return this
|
||||
}
|
||||
|
||||
fun <T : QueryStruct> T.addFunction(name: String, function: java.util.function.Function<MoParams, Any>): T {
|
||||
this.functions[name] = function
|
||||
return this
|
||||
}
|
||||
|
||||
fun MoLangEnvironment.getQueryStruct(name: String = "query") = structs.getOrPut(name) { QueryStruct(hashMapOf()) } as QueryStruct
|
||||
|
||||
fun MoLangRuntime.setup(): MoLangRuntime {
|
||||
environment.getQueryStruct().addStandardFunctions()
|
||||
return this
|
||||
}
|
||||
|
||||
fun writeMoValueToNBT(value: MoValue): NbtElement? {
|
||||
return when (value) {
|
||||
is DoubleValue -> NbtDouble.of(value.value)
|
||||
is StringValue -> NbtString.of(value.value)
|
||||
is ArrayStruct -> {
|
||||
val list = value.map.values
|
||||
val nbtList = NbtList()
|
||||
list.mapNotNull(::writeMoValueToNBT).forEach(nbtList::add)
|
||||
nbtList
|
||||
}
|
||||
is VariableStruct -> {
|
||||
val nbt = NbtCompound()
|
||||
value.map.forEach { (key, value) ->
|
||||
val element = writeMoValueToNBT(value) ?: return@forEach
|
||||
nbt.put(key, element)
|
||||
}
|
||||
nbt
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
fun readMoValueFromNBT(nbt: NbtElement): MoValue {
|
||||
return when (nbt) {
|
||||
is NbtDouble -> DoubleValue(nbt.doubleValue())
|
||||
is NbtString -> StringValue(nbt.asString())
|
||||
is NbtList -> {
|
||||
val array = ArrayStruct(hashMapOf())
|
||||
var index = 0
|
||||
nbt.forEach { element ->
|
||||
val value = readMoValueFromNBT(element)
|
||||
array.setDirectly("$index", value)
|
||||
index++
|
||||
}
|
||||
array
|
||||
}
|
||||
is NbtCompound -> {
|
||||
val variable = VariableStruct(hashMapOf())
|
||||
nbt.keys.toList().forEach { key ->
|
||||
val value = readMoValueFromNBT(nbt[key]!!)
|
||||
variable.map[key] = value
|
||||
}
|
||||
variable
|
||||
}
|
||||
else -> null
|
||||
} ?: throw IllegalArgumentException("Invalid NBT element type: ${nbt.type}")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.molang
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
|
||||
/**
|
||||
* A [MoValue] that just wraps around some other object value. It's for good and valid reasons.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 2nd, 2023
|
||||
*/
|
||||
class ObjectValue<T>(
|
||||
var obj: T,
|
||||
val stringify: (T) -> String = { it.toString() },
|
||||
val doublify: (T) -> Double = { throw NotImplementedError("Doublify not implemented for this object value, are you doing weird molang") }
|
||||
) : QueryStruct(hashMapOf()) {
|
||||
override fun value() = this
|
||||
override fun asDouble() = doublify(obj)
|
||||
override fun asString() = stringify(obj)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.molang
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
|
||||
/**
|
||||
* A simple implementation of [ExpressionLike] that is just a single [Expression]. This
|
||||
* is as opposed to [ListExpression]s.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 22nd, 2023
|
||||
*/
|
||||
class SingleExpression(val expr: Expression) : ExpressionLike {
|
||||
override fun resolve(runtime: MoLangRuntime) = runtime.resolve(expr)
|
||||
}
|
||||
@@ -8,6 +8,12 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.moves
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.MoStruct
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunction
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectTimeline
|
||||
import com.cobblemon.mod.common.api.moves.categories.DamageCategories
|
||||
import com.cobblemon.mod.common.api.moves.categories.DamageCategory
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
@@ -45,8 +51,22 @@ open class MoveTemplate(
|
||||
val pp: Int,
|
||||
val priority: Int,
|
||||
val critRatio: Double,
|
||||
val effectChances: Array<Double>
|
||||
val effectChances: Array<Double>,
|
||||
val actionEffect: ActionEffectTimeline?
|
||||
) {
|
||||
val struct: MoStruct by lazy {
|
||||
QueryStruct(hashMapOf())
|
||||
.addFunction("name") { StringValue(name) }
|
||||
.addFunction("type") { StringValue(elementalType.name) }
|
||||
.addFunction("damage_category") { StringValue(damageCategory.name) }
|
||||
.addFunction("power") { DoubleValue(power) }
|
||||
.addFunction("target") { StringValue(target.name) }
|
||||
.addFunction("accuracy") { DoubleValue(accuracy) }
|
||||
.addFunction("pp") { DoubleValue(pp) }
|
||||
.addFunction("priority") { DoubleValue(priority) }
|
||||
.addFunction("crit_ratio") { DoubleValue(critRatio) }
|
||||
}
|
||||
|
||||
|
||||
val displayName: MutableText
|
||||
get() = lang("move.$name")
|
||||
@@ -65,7 +85,8 @@ open class MoveTemplate(
|
||||
pp = 5,
|
||||
priority = 0,
|
||||
critRatio = 0.0,
|
||||
effectChances = emptyArray()
|
||||
effectChances = emptyArray(),
|
||||
actionEffect = null
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -10,12 +10,15 @@ package com.cobblemon.mod.common.api.moves
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.data.DataRegistry
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectTimeline
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
|
||||
import com.cobblemon.mod.common.api.moves.categories.DamageCategories
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.battles.MoveTarget
|
||||
import com.cobblemon.mod.common.battles.runner.ShowdownService
|
||||
import com.cobblemon.mod.common.net.messages.client.data.MovesRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
@@ -72,7 +75,18 @@ object Moves : DataRegistry {
|
||||
effectChances += secondaryMember.get("chance").asDouble
|
||||
}
|
||||
}
|
||||
val move = MoveTemplate(id, num, elementalType, damageCategory, power, target, accuracy, pp, priority, critRatio, effectChances.toTypedArray())
|
||||
val actionEffect = ActionEffects.actionEffects[id.asIdentifierDefaultingNamespace()]
|
||||
?: run {
|
||||
ActionEffects.actionEffects["generic_move".asIdentifierDefaultingNamespace()]
|
||||
// if (damageCategory == DamageCategories.STATUS) {
|
||||
// ActionEffects.actionEffects[cobblemonResource("status")]
|
||||
// } else {
|
||||
// val type = elementalType.name.lowercase()
|
||||
// val category = damageCategory.name.lowercase()
|
||||
// ActionEffects.actionEffects["${category}_$type".asIdentifierDefaultingNamespace()]
|
||||
// }
|
||||
}
|
||||
val move = MoveTemplate(id, num, elementalType, damageCategory, power, target, accuracy, pp, priority, critRatio, effectChances.toTypedArray(), actionEffect)
|
||||
this.register(move)
|
||||
} catch (e: Exception) {
|
||||
Cobblemon.LOGGER.error("Caught exception trying to resolve the move '{}'", id, e)
|
||||
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.moves.animations
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.cobblemon.mod.common.api.moves.animations.keyframes.ActionEffectKeyframe
|
||||
import com.cobblemon.mod.common.api.scheduling.ScheduledTask
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import net.minecraft.entity.Entity
|
||||
|
||||
/**
|
||||
* An action effect will run and execute a series of 'keyframes', with each running once
|
||||
* the previous has completed. The entire effect is considered complete for the given context
|
||||
* once all the 'holds' provided in the context have been cleared or once every keyframe
|
||||
* has finished.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 20th, 2023
|
||||
*/
|
||||
class ActionEffectTimeline(
|
||||
val timeline: List<ActionEffectKeyframe> = mutableListOf(),
|
||||
val condition: Expression = "true".asExpression()
|
||||
) {
|
||||
companion object {
|
||||
val NONE = ActionEffectTimeline()
|
||||
}
|
||||
|
||||
fun run(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
return if (timeline.isEmpty() || !context.runtime.resolveBoolean(condition)) {
|
||||
CompletableFuture.completedFuture(Unit)
|
||||
} else {
|
||||
val finalFuture = CompletableFuture<Unit>()
|
||||
// .toList copy because I'm paranoid about iterators being trying to share between identical effects playing
|
||||
chainKeyframes(context, timeline.toList().iterator(), finalFuture)
|
||||
finalFuture
|
||||
}
|
||||
}
|
||||
|
||||
fun chainKeyframes(context: ActionEffectContext, iterator: Iterator<ActionEffectKeyframe>, finalFuture: CompletableFuture<Unit>) {
|
||||
if (!iterator.hasNext()) {
|
||||
finalFuture.complete(Unit)
|
||||
} else {
|
||||
val keyframe = iterator.next()
|
||||
context.currentKeyframes.add(keyframe)
|
||||
keyframe.play(context)
|
||||
.thenRun { context.currentKeyframes.remove(keyframe) }
|
||||
.thenApply { chainKeyframes(context, iterator, finalFuture) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ActionEffectContext(
|
||||
val actionEffect: ActionEffectTimeline,
|
||||
val holds: MutableSet<String> = mutableSetOf(),
|
||||
val providers: MutableList<Any> = mutableListOf(),
|
||||
val runtime: MoLangRuntime,
|
||||
var canBeInterrupted: Boolean = false,
|
||||
var interrupted: Boolean = false,
|
||||
var currentKeyframes: MutableList<ActionEffectKeyframe> = mutableListOf()
|
||||
) {
|
||||
inline fun <reified T> findOneProvider() = providers.filterIsInstance<T>().firstOrNull()
|
||||
|
||||
|
||||
}
|
||||
|
||||
class UsersProvider(users: List<Entity>): EntityProvider {
|
||||
override val entities = users
|
||||
constructor(vararg users: Entity): this(users.toList())
|
||||
}
|
||||
|
||||
class TargetsProvider(targets: List<Entity>): EntityProvider {
|
||||
override val entities = targets
|
||||
constructor(vararg targets: Entity): this(targets.toList())
|
||||
}
|
||||
|
||||
interface EntityProvider {
|
||||
val entities: List<Entity>
|
||||
}
|
||||
|
||||
//class MoveAnimationKeyframe(
|
||||
// val sound: Identifier? = null,
|
||||
// val animation: List<AnimationWithMoments> = listOf(),
|
||||
// val effects: List<ActionEffect> = listOf()
|
||||
//)
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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.moves.animations
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.moves.animations.keyframes.*
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.pokemon.adapters.CobblemonStatTypeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.*
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import java.awt.Color
|
||||
import net.minecraft.predicate.NumberRange
|
||||
import net.minecraft.resource.ResourceType
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.math.Box
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
/**
|
||||
* Data registry containing all of the [ActionEffectTimeline]s that can be triggered from various actions.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 21st, 2023
|
||||
*/
|
||||
object ActionEffects : JsonDataRegistry<ActionEffectTimeline> {
|
||||
override val id: Identifier = cobblemonResource("action_effects")
|
||||
override val type: ResourceType = ResourceType.SERVER_DATA
|
||||
override val observable = SimpleObservable<ActionEffects>()
|
||||
|
||||
init {
|
||||
ActionEffectKeyframe.register<AnimationActionEffectKeyframe>("animation")
|
||||
ActionEffectKeyframe.register<EntityMoLangActionEffectKeyframe>("entity_molang")
|
||||
ActionEffectKeyframe.register<MoLangActionEffectKeyframe>("molang")
|
||||
ActionEffectKeyframe.register<ParallelActionEffectKeyframe>("parallel")
|
||||
ActionEffectKeyframe.register<CanInterruptActionEffectKeyframe>("can_interrupt")
|
||||
ActionEffectKeyframe.register<CannotInterruptActionEffectKeyframe>("cannot_interrupt")
|
||||
ActionEffectKeyframe.register<RemoveHoldsActionEffectKeyframe>("remove_holds")
|
||||
ActionEffectKeyframe.register<AddHoldsActionEffectKeyframe>("add_holds")
|
||||
ActionEffectKeyframe.register<MoveToTargetActionEffectKeyframe>("move_to_target")
|
||||
ActionEffectKeyframe.register<ReturnToPositionActionEffectKeyframe>("return_to_position")
|
||||
ActionEffectKeyframe.register<PauseActionEffectKeyframe>("pause")
|
||||
ActionEffectKeyframe.register<SavePositionActionEffectKeyframe>("save_position")
|
||||
ActionEffectKeyframe.register<ForkActionEffectKeyframe>("fork")
|
||||
ActionEffectKeyframe.register<SequenceActionEffectKeyframe>("sequence")
|
||||
ActionEffectKeyframe.register<RunActionEffectKeyframe>("run_action_effect")
|
||||
ActionEffectKeyframe.register<EntityParticlesActionEffectKeyframe>("entity_particles")
|
||||
ActionEffectKeyframe.register<EntitySoundActionEffectKeyframe>("entity_sound")
|
||||
}
|
||||
|
||||
override val gson = GsonBuilder()
|
||||
.disableHtmlEscaping()
|
||||
.setPrettyPrinting()
|
||||
.registerTypeAdapter(ActionEffectKeyframe::class.java, ActionEffectKeyframeAdapter)
|
||||
.registerTypeAdapter(NumberRange.FloatRange::class.java, FloatNumberRangeAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(Collection::class.java, Box::class.java).type, BoxCollectionAdapter)
|
||||
.registerTypeAdapter(Box::class.java, BoxAdapter)
|
||||
.registerTypeAdapter(Vec3d::class.java, VerboseVec3dAdapter)
|
||||
.registerTypeAdapter(Identifier::class.java, IdentifierAdapter)
|
||||
.registerTypeAdapter(IntRange::class.java, VerboseIntRangeAdapter)
|
||||
.registerTypeAdapter(Color::class.java, LiteralHexColorAdapter)
|
||||
.registerTypeAdapter(Stat::class.java, CobblemonStatTypeAdapter)
|
||||
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(
|
||||
TypeToken.getParameterized(
|
||||
TypeToken.get(List::class.java).type,
|
||||
TypeToken.get(ActionEffectKeyframe::class.java).type
|
||||
).type,
|
||||
SingleToPluralAdapter(ActionEffectKeyframe::class.java) { it }
|
||||
)
|
||||
.create()
|
||||
|
||||
override val typeToken: TypeToken<ActionEffectTimeline> = TypeToken.get(ActionEffectTimeline::class.java)
|
||||
override val resourcePath = "action_effects"
|
||||
|
||||
val actionEffects = mutableMapOf<Identifier, ActionEffectTimeline>()
|
||||
override fun reload(data: Map<Identifier, ActionEffectTimeline>) {
|
||||
actionEffects.clear()
|
||||
actionEffects.putAll(data)
|
||||
observable.emit(this)
|
||||
}
|
||||
|
||||
override fun sync(player: ServerPlayerEntity) {}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
/**
|
||||
* A single component of an action effect. When played it must return a completable future that completes
|
||||
* when the action this keyframe represents is finished. [interrupt] is provided for when something successfully
|
||||
* interrupts the effect so that if any cancellation logic is necessary, it can be provided.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 26th, 2023
|
||||
*/
|
||||
interface ActionEffectKeyframe {
|
||||
companion object {
|
||||
val types = mutableMapOf<String, Class<out ActionEffectKeyframe>>()
|
||||
|
||||
inline fun <reified T : ActionEffectKeyframe> register(type: String) {
|
||||
types[type] = T::class.java
|
||||
}
|
||||
}
|
||||
|
||||
fun play(context: ActionEffectContext): CompletableFuture<Unit>
|
||||
fun interrupt(context: ActionEffectContext) {}
|
||||
fun skip(): CompletableFuture<Unit> = CompletableFuture.completedFuture(Unit)
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
/**
|
||||
* An [ActionEffectKeyframe] that adds some holds from the context for future code to recognize as blocking some
|
||||
* functionality from proceeding.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 27th, 2023
|
||||
*/
|
||||
class AddHoldsActionEffectKeyframe : ActionEffectKeyframe {
|
||||
val holds = mutableSetOf<String>()
|
||||
override fun play(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
context.holds.addAll(holds)
|
||||
return CompletableFuture.completedFuture(Unit)
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.moves.animations.keyframes
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.EntityProvider
|
||||
import com.cobblemon.mod.common.api.moves.animations.UsersProvider
|
||||
import com.cobblemon.mod.common.api.scheduling.delayedFuture
|
||||
import com.cobblemon.mod.common.net.messages.client.animation.PlayPoseableAnimationPacket
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
|
||||
class AnimationActionEffectKeyframe : ConditionalActionEffectKeyframe(), EntityConditionalActionEffectKeyframe {
|
||||
var delay = "0".asExpressionLike()
|
||||
var visibilityRange = 200
|
||||
var animation: Set<String> = setOf("physical")
|
||||
var variables: List<Expression> = listOf()
|
||||
override val entityCondition = "q.entity.is_user".asExpressionLike()
|
||||
|
||||
override fun playWhenTrue(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
val entities = context.providers
|
||||
.filterIsInstance<EntityProvider>()
|
||||
.flatMap { prov -> prov.entities.filter { test(context, it, isUser = prov is UsersProvider) } }
|
||||
|
||||
val expressions = variables.map { it.originalString }.toSet()
|
||||
|
||||
// Treat them as expressions if possible but otherwise yeah just send them as strings
|
||||
val animation = animation.map {
|
||||
try {
|
||||
it.asExpressionLike().resolveString(context.runtime).takeIf { it != "0.0" } ?: it
|
||||
} catch (e: Exception) {
|
||||
it
|
||||
}
|
||||
}.toSet()
|
||||
|
||||
for (entity in entities) {
|
||||
val world = entity.world as ServerWorld
|
||||
val players = world.getPlayers { it.distanceTo(entity) <= visibilityRange }
|
||||
val pkt = PlayPoseableAnimationPacket(entity.id, animation = animation, expressions = expressions)
|
||||
players.forEach { it.sendPacket(pkt) }
|
||||
}
|
||||
|
||||
return delayedFuture(seconds = delay.resolveFloat(context.runtime), serverThread = true)
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
class CanInterruptActionEffectKeyframe : ConditionalActionEffectKeyframe() {
|
||||
override fun playWhenTrue(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
context.canBeInterrupted = true
|
||||
return CompletableFuture.completedFuture(Unit)
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
class CannotInterruptActionEffectKeyframe : ConditionalActionEffectKeyframe() {
|
||||
override fun playWhenTrue(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
context.canBeInterrupted = true
|
||||
return CompletableFuture.completedFuture(Unit)
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
abstract class ConditionalActionEffectKeyframe : ActionEffectKeyframe {
|
||||
var condition: ExpressionLike = "true".asExpressionLike()
|
||||
override fun play(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
return if (condition.resolveBoolean(context.runtime)) {
|
||||
playWhenTrue(context)
|
||||
} else {
|
||||
skip()
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun playWhenTrue(context: ActionEffectContext): CompletableFuture<Unit>
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.moves.animations.keyframes
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.getQueryStruct
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import net.minecraft.entity.Entity
|
||||
|
||||
/**
|
||||
* An action effect keyframe that plays for all entities for which the condition is true.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since January 21st, 2024
|
||||
*/
|
||||
interface EntityConditionalActionEffectKeyframe {
|
||||
val entityCondition: ExpressionLike
|
||||
fun test(context: ActionEffectContext, entity: Entity, isUser: Boolean): Boolean {
|
||||
// TODO this should use the entity's own query struct
|
||||
context.runtime.environment.getQueryStruct().addFunction("entity") {
|
||||
QueryStruct(hashMapOf())
|
||||
.addFunction("uuid") { StringValue(entity.uuidAsString) }
|
||||
.addFunction("is_user") { DoubleValue(isUser) }
|
||||
}
|
||||
return entityCondition.resolveBoolean(context.runtime)
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.EntityProvider
|
||||
import com.cobblemon.mod.common.api.moves.animations.UsersProvider
|
||||
import com.cobblemon.mod.common.api.scheduling.delayedFuture
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
|
||||
/**
|
||||
* An action effect keyframe that will run client-side MoLang for all entities that fit the entity condition.
|
||||
*
|
||||
* This MoLang executes within that entity's runtime, meaning you can trigger animations or locational particles
|
||||
* or sounds.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 30th, 2023
|
||||
*/
|
||||
class EntityMoLangActionEffectKeyframe : ConditionalActionEffectKeyframe(), EntityConditionalActionEffectKeyframe {
|
||||
var delay = "0".asExpressionLike()
|
||||
val expressions = mutableSetOf<String>()
|
||||
val visibilityRange = 200
|
||||
override val entityCondition: ExpressionLike = "q.entity.is_user".asExpressionLike()
|
||||
|
||||
override fun playWhenTrue(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
val entities = context.providers
|
||||
.filterIsInstance<EntityProvider>()
|
||||
.flatMap { prov -> prov.entities.filter { test(context, it, isUser = prov is UsersProvider) } }
|
||||
|
||||
for (entity in entities) {
|
||||
val world = entity.world as ServerWorld
|
||||
val players = world.getPlayers { it.distanceTo(entity) <= visibilityRange }
|
||||
val pkt = RunPosableMoLangPacket(entityId = entity.id, expressions = expressions)
|
||||
players.forEach { it.sendPacket(pkt) }
|
||||
}
|
||||
|
||||
return delayedFuture(seconds = delay.resolveFloat(context.runtime), serverThread = true)
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.EntityProvider
|
||||
import com.cobblemon.mod.common.api.moves.animations.UsersProvider
|
||||
import com.cobblemon.mod.common.api.scheduling.delayedFuture
|
||||
import com.cobblemon.mod.common.entity.Poseable
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
|
||||
/**
|
||||
* Spawns particles on the entity based on the given particle effect and locator.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since January 21st, 2024
|
||||
*/
|
||||
class EntityParticlesActionEffectKeyframe : ConditionalActionEffectKeyframe(), EntityConditionalActionEffectKeyframe {
|
||||
override val entityCondition = "q.entity.is_user".asExpressionLike()
|
||||
var effect: String? = null
|
||||
var locator: String = "root"
|
||||
val delay: ExpressionLike = "0".asExpressionLike()
|
||||
val visibilityRange = 200
|
||||
|
||||
override fun playWhenTrue(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
val entities = context.providers
|
||||
.filterIsInstance<EntityProvider>()
|
||||
.flatMap { prov -> prov.entities.filter { test(context, it, isUser = prov is UsersProvider) } }
|
||||
|
||||
val effectIdentifier = try {
|
||||
effect?.asExpressionLike()?.resolveString(context.runtime)
|
||||
} catch (e: Exception) {
|
||||
effect
|
||||
}?.asIdentifierDefaultingNamespace() ?: return skip()
|
||||
|
||||
entities.filter { it is Poseable }.forEach { entity ->
|
||||
val packet = SpawnSnowstormEntityParticlePacket(effectIdentifier, entity.id, locator)
|
||||
val players = (entity.world as ServerWorld).getPlayers { it.distanceTo(entity) <= visibilityRange }
|
||||
packet.sendToPlayers(players)
|
||||
}
|
||||
|
||||
return delayedFuture(seconds = delay.resolveFloat(context.runtime), serverThread = true)
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.EntityProvider
|
||||
import com.cobblemon.mod.common.api.moves.animations.UsersProvider
|
||||
import com.cobblemon.mod.common.api.scheduling.delayedFuture
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import net.minecraft.registry.RegistryKeys
|
||||
|
||||
/**
|
||||
* An action effect keyframe that plays a positioned sound for all matching entities.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since January 21st, 2024
|
||||
*/
|
||||
class EntitySoundActionEffectKeyframe : ConditionalActionEffectKeyframe(), EntityConditionalActionEffectKeyframe {
|
||||
override val entityCondition = "q.entity.is_user".asExpressionLike()
|
||||
var sound: String? = null
|
||||
val delay: ExpressionLike = "0".asExpressionLike()
|
||||
|
||||
override fun playWhenTrue(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
val entities = context.providers
|
||||
.filterIsInstance<EntityProvider>()
|
||||
.flatMap { prov -> prov.entities.filter { test(context, it, isUser = prov is UsersProvider) } }
|
||||
|
||||
val soundIdentifier = try {
|
||||
sound?.asExpressionLike()?.resolveString(context.runtime)?.takeIf { it != "0.0" } ?: sound
|
||||
} catch (e: Exception) {
|
||||
sound
|
||||
}?.asIdentifierDefaultingNamespace() ?: return skip()
|
||||
|
||||
entities.forEach { entity ->
|
||||
val soundEvent = entity.world.registryManager.get(RegistryKeys.SOUND_EVENT).get(soundIdentifier) ?: return skip()
|
||||
entity.playSound(soundEvent, 1f, 1f)
|
||||
}
|
||||
|
||||
return delayedFuture(seconds = delay.resolveFloat(context.runtime), serverThread = true)
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
class ForkActionEffectKeyframe(
|
||||
val condition: ExpressionLike = "true".asExpressionLike(),
|
||||
val ifTrue: List<ActionEffectKeyframe> = listOf(),
|
||||
val ifFalse: List<ActionEffectKeyframe> = listOf()
|
||||
) : ActionEffectKeyframe {
|
||||
override fun play(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
val future = CompletableFuture<Unit>()
|
||||
/*
|
||||
* Using .toList() before running chainKeyframes because iterators can be weird about sharing,
|
||||
* .toList() creates a copy of the list and then grabs its iterator so much safer (three parachutes)
|
||||
*/
|
||||
if (!condition.resolveBoolean(context.runtime)) {
|
||||
context.actionEffect.chainKeyframes(context, ifFalse.toList().iterator(), future)
|
||||
} else {
|
||||
context.actionEffect.chainKeyframes(context, ifTrue.toList().iterator(), future)
|
||||
}
|
||||
|
||||
return future
|
||||
}
|
||||
}
|
||||
+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.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.scheduling.delayedFuture
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
/**
|
||||
* An action effect keyframe that simply executes some MoLang on the effect context's runtime.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since January 21st, 2024
|
||||
*/
|
||||
class MoLangActionEffectKeyframe : ActionEffectKeyframe {
|
||||
val expressions: ExpressionLike = "0".asExpressionLike()
|
||||
val delay: ExpressionLike = "0".asExpressionLike()
|
||||
override fun play(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
expressions.resolve(context.runtime)
|
||||
return delayedFuture(seconds = delay.resolveFloat(context.runtime), serverThread = true)
|
||||
}
|
||||
}
|
||||
+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.api.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectTimeline
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
|
||||
import com.cobblemon.mod.common.api.moves.animations.TargetsProvider
|
||||
import com.cobblemon.mod.common.api.moves.animations.UsersProvider
|
||||
import com.cobblemon.mod.common.api.scheduling.afterOnServer
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.PokemonNavigation
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sqrt
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
class MoveToTargetActionEffectKeyframe : ActionEffectKeyframe {
|
||||
val speed = 1F
|
||||
val timeout = "4".asExpressionLike()
|
||||
var proximity = -1F
|
||||
val timeoutActionEffect: Identifier? = null
|
||||
|
||||
override fun play(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
val user = context.findOneProvider<UsersProvider>()?.entities?.firstOrNull() as? PokemonEntity ?: return CompletableFuture.completedFuture(Unit)
|
||||
val target = context.findOneProvider<TargetsProvider>()?.entities?.firstOrNull() ?: return CompletableFuture.completedFuture(Unit)
|
||||
|
||||
val future = CompletableFuture<Unit>()
|
||||
|
||||
var timedOut = false
|
||||
|
||||
val proximity = this.proximity.takeIf { it != -1F } ?: (sqrt(2 * user.boundingBox.xLength.pow(2)) + 1.5F + sqrt(2 * target.boundingBox.xLength.pow(2))).toFloat()
|
||||
|
||||
if (target.distanceTo(user) !in proximity..20F) {
|
||||
future.complete(Unit)
|
||||
return future
|
||||
}
|
||||
|
||||
val timeoutEffect = timeoutActionEffect?.let { ActionEffects.actionEffects[it] } ?: ActionEffectTimeline.NONE
|
||||
|
||||
val nav = user.navigation
|
||||
val navContext = PokemonNavigation.NavigationContext(
|
||||
destinationProximity = proximity,
|
||||
onArrival = {
|
||||
if (!future.isDone && !timedOut) {
|
||||
future.complete(Unit)
|
||||
}
|
||||
},
|
||||
onCannotReach = {
|
||||
if (!future.isDone && !timedOut) {
|
||||
timedOut = true
|
||||
timeoutEffect.run(context).thenApply { future.complete(Unit) }
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
afterOnServer(seconds = timeout.resolveFloat(context.runtime)) {
|
||||
if (!future.isDone && !timedOut) {
|
||||
timedOut = true
|
||||
timeoutEffect.run(context).thenApply { future.complete(Unit) }
|
||||
nav.stop()
|
||||
}
|
||||
}
|
||||
|
||||
nav.startMovingTo(target.x, target.y, target.z, speed.toDouble(), navContext)
|
||||
return future
|
||||
}
|
||||
}
|
||||
+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.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
class ParallelActionEffectKeyframe : ConditionalActionEffectKeyframe() {
|
||||
var keyframes: MutableList<ActionEffectKeyframe> = mutableListOf()
|
||||
|
||||
override fun playWhenTrue(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
return CompletableFuture.allOf(
|
||||
*keyframes.map {
|
||||
context.currentKeyframes.add(it)
|
||||
it.play(context).thenRun { context.currentKeyframes.remove(it) }
|
||||
}.toTypedArray()
|
||||
).thenApply {} // Map Void -> Unit at the end
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.scheduling.delayedFuture
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
|
||||
class PauseActionEffectKeyframe : ConditionalActionEffectKeyframe() {
|
||||
val pause = "1".asExpressionLike()
|
||||
override fun playWhenTrue(context: ActionEffectContext) = delayedFuture(seconds = pause.resolveFloat(context.runtime), serverThread = true)
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.scheduling.delayedFuture
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
/**
|
||||
* An [ActionEffectKeyframe] that clears some holds from the context, potentially marking the effect as
|
||||
* complete as far as any blocked actions are concerned. If no holds are specified, then all holds are
|
||||
* removed.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 27th, 2023
|
||||
*/
|
||||
class RemoveHoldsActionEffectKeyframe : ActionEffectKeyframe {
|
||||
val delay = 0F
|
||||
val holds = mutableSetOf<String>()
|
||||
override fun play(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
return delayedFuture(seconds = delay, serverThread = true).thenApply {
|
||||
if (holds.isEmpty()) {
|
||||
context.holds.clear()
|
||||
} else {
|
||||
context.holds.removeAll(holds)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectTimeline
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
|
||||
import com.cobblemon.mod.common.api.moves.animations.UsersProvider
|
||||
import com.cobblemon.mod.common.api.scheduling.after
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.PokemonNavigation
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class ReturnToPositionActionEffectKeyframe : ActionEffectKeyframe {
|
||||
val speed = 1F
|
||||
val timeout = "4".asExpressionLike()
|
||||
val timeoutActionEffect: Identifier? = null
|
||||
|
||||
override fun play(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
val user = context.findOneProvider<UsersProvider>()?.entities?.firstOrNull() as? PokemonEntity ?: return skip()
|
||||
val future = CompletableFuture<Unit>()
|
||||
|
||||
val pos = (context.runtime.environment.getValue(setOf("${user.uuidAsString}-pos").iterator())?.value() as? ObjectValue<*>)?.obj as? Vec3d ?: return skip()
|
||||
|
||||
var timedOut = false
|
||||
|
||||
if (pos.distanceTo(user.pos) > 20) {
|
||||
future.complete(Unit)
|
||||
return future
|
||||
}
|
||||
|
||||
val timeoutEffect = timeoutActionEffect?.let { ActionEffects.actionEffects[it] } ?: ActionEffectTimeline.NONE
|
||||
|
||||
val nav = user.navigation
|
||||
val navContext = PokemonNavigation.NavigationContext(
|
||||
onArrival = {
|
||||
if (!future.isDone && !timedOut) {
|
||||
future.complete(Unit)
|
||||
}
|
||||
},
|
||||
onCannotReach = {
|
||||
if (!future.isDone && !timedOut) {
|
||||
timedOut = true
|
||||
timeoutEffect.run(context).thenApply { future.complete(Unit) }
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
after(seconds = timeout.resolveFloat(context.runtime), serverThread = true) {
|
||||
if (!future.isDone && !timedOut) {
|
||||
timedOut = true
|
||||
timeoutEffect.run(context).thenApply { future.complete(Unit) }
|
||||
nav.stop()
|
||||
}
|
||||
}
|
||||
|
||||
nav.startMovingTo(pos.x, pos.y, pos.z, speed.toDouble(), navContext)
|
||||
return future
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
/**
|
||||
* An action effect keyframe that simply runs another action effect based on an identifier. This action
|
||||
* effect is marked complete only when the action effect it runs is complete unless [waitForActionEffect] is
|
||||
* false.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since January 21st, 2024
|
||||
*/
|
||||
class RunActionEffectKeyframe : ConditionalActionEffectKeyframe() {
|
||||
val actionEffect: Identifier? = null
|
||||
val waitForActionEffect = true
|
||||
override fun playWhenTrue(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
return if (actionEffect != null) {
|
||||
ActionEffects.actionEffects[actionEffect]?.run(context)?.takeIf { waitForActionEffect } ?: skip()
|
||||
} else {
|
||||
skip()
|
||||
}
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.UsersProvider
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
class SavePositionActionEffectKeyframe: ConditionalActionEffectKeyframe() {
|
||||
override fun playWhenTrue(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
val user = context.findOneProvider<UsersProvider>()?.entities?.firstOrNull() ?: return skip()
|
||||
context.runtime.environment.setSimpleVariable("${user.uuidAsString}-pos", ObjectValue(user.pos))
|
||||
return skip()
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
/**
|
||||
* A sequence of action effects that are dependent on a condition.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 29th, 2023
|
||||
*/
|
||||
class SequenceActionEffectKeyframe(val keyframes: List<ActionEffectKeyframe> = listOf()) : ConditionalActionEffectKeyframe() {
|
||||
override fun playWhenTrue(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
val future = CompletableFuture<Unit>()
|
||||
context.actionEffect.chainKeyframes(context, keyframes.toList().iterator(), future)
|
||||
return future
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.multiblock
|
||||
|
||||
import com.cobblemon.mod.common.block.entity.FossilMultiblockEntity
|
||||
import net.minecraft.block.*
|
||||
import net.minecraft.block.entity.BlockEntity
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
import net.minecraft.util.ActionResult
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.hit.BlockHitResult
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.BlockView
|
||||
import net.minecraft.world.World
|
||||
|
||||
/**
|
||||
* A block that can be part of a [MultiblockStructure]
|
||||
*/
|
||||
abstract class MultiblockBlock(properties: Settings) : BlockWithEntity(properties) {
|
||||
|
||||
override fun onPlaced(
|
||||
world: World,
|
||||
pos: BlockPos,
|
||||
state: BlockState,
|
||||
placer: LivingEntity?,
|
||||
itemStack: ItemStack?
|
||||
) {
|
||||
if (world is ServerWorld) {
|
||||
val multiblockEntity = world.getBlockEntity(pos) as MultiblockEntity
|
||||
multiblockEntity.multiblockBuilder?.validate(world)
|
||||
}
|
||||
super.onPlaced(world, pos, state, placer, itemStack)
|
||||
}
|
||||
|
||||
override fun onUse(
|
||||
state: BlockState,
|
||||
world: World,
|
||||
pos: BlockPos,
|
||||
player: PlayerEntity,
|
||||
hand: Hand,
|
||||
hit: BlockHitResult
|
||||
): ActionResult {
|
||||
if(hand == Hand.OFF_HAND) {
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
override fun onBreak(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity?) {
|
||||
super.onBreak(world, pos, state, player)
|
||||
if (!world.isClient) {
|
||||
val entity = world.getBlockEntity(pos)
|
||||
if (entity is MultiblockEntity && entity.multiblockStructure != null) {
|
||||
entity.multiblockStructure!!.onBreak(world, pos, state, player)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun createBlockEntity(pos: BlockPos, state: BlockState): BlockEntity? {
|
||||
return createMultiBlockEntity(pos, state)
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun getRenderType(state: BlockState?): BlockRenderType {
|
||||
return BlockRenderType.MODEL
|
||||
}
|
||||
|
||||
override fun getPickStack(world: BlockView, pos: BlockPos, state: BlockState): ItemStack {
|
||||
val blockEntity = world.getBlockEntity(pos) as? MultiblockEntity ?: return ItemStack.EMPTY
|
||||
return if (blockEntity.multiblockStructure == null) super.getPickStack(world, pos, state) else ItemStack.EMPTY
|
||||
}
|
||||
|
||||
abstract fun createMultiBlockEntity(pos: BlockPos, state: BlockState): FossilMultiblockEntity
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.multiblock
|
||||
|
||||
import com.cobblemon.mod.common.api.multiblock.MultiblockStructure
|
||||
import com.cobblemon.mod.common.api.multiblock.builder.MultiblockStructureBuilder
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.entity.BlockEntity
|
||||
import net.minecraft.block.entity.BlockEntityType
|
||||
import net.minecraft.nbt.NbtCompound
|
||||
import net.minecraft.nbt.NbtHelper
|
||||
import net.minecraft.network.listener.ClientPlayPacketListener
|
||||
import net.minecraft.network.packet.Packet
|
||||
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket
|
||||
import net.minecraft.util.math.BlockPos
|
||||
|
||||
/**
|
||||
* Multiblock entities are kind of complicated. Basically every multiblock entity should have a MultiBlockStructureBuilder
|
||||
* that is checked when this block entity is created. The multiblock entity also contains a reference to a MultiblockStructure
|
||||
* which is shared between all MultiblockEntities in the structure. Finally, every Multiblock contains the location of the
|
||||
* block that controls this blockentities associated structure
|
||||
*/
|
||||
abstract class MultiblockEntity(
|
||||
type: BlockEntityType<*>,
|
||||
pos: BlockPos,
|
||||
state: BlockState,
|
||||
var multiblockBuilder: MultiblockStructureBuilder?
|
||||
) : BlockEntity(type, pos, state) {
|
||||
|
||||
abstract var multiblockStructure: MultiblockStructure?
|
||||
abstract var masterBlockPos: BlockPos?
|
||||
|
||||
override fun toUpdatePacket(): Packet<ClientPlayPacketListener>? {
|
||||
return BlockEntityUpdateS2CPacket.create(this)
|
||||
}
|
||||
|
||||
override fun toInitialChunkDataNbt(): NbtCompound {
|
||||
val result = NbtCompound()
|
||||
writeNbt(result)
|
||||
return result
|
||||
}
|
||||
|
||||
override fun writeNbt(nbt: NbtCompound) {
|
||||
super.writeNbt(nbt)
|
||||
//Used for checking build conditions in multiblocks (Dont count a block if it has the FORMED flag)
|
||||
nbt.putBoolean(DataKeys.FORMED, masterBlockPos != null)
|
||||
if (multiblockStructure != null && multiblockStructure!!.controllerBlockPos == pos) {
|
||||
nbt.put(DataKeys.MULTIBLOCK_STORAGE, multiblockStructure!!.writeToNbt())
|
||||
}
|
||||
else if (masterBlockPos != null) {
|
||||
nbt.put(DataKeys.CONTROLLER_BLOCK, NbtHelper.fromBlockPos(masterBlockPos))
|
||||
}
|
||||
}
|
||||
|
||||
abstract override fun readNbt(nbt: NbtCompound)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.multiblock
|
||||
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.nbt.NbtCompound
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
import net.minecraft.util.ActionResult
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.hit.BlockHitResult
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.random.Random
|
||||
import net.minecraft.world.World
|
||||
|
||||
interface MultiblockStructure {
|
||||
val controllerBlockPos: BlockPos
|
||||
|
||||
fun onUse(
|
||||
blockState: BlockState,
|
||||
world: World,
|
||||
blockPos: BlockPos,
|
||||
player: PlayerEntity,
|
||||
interactionHand: Hand,
|
||||
blockHitResult: BlockHitResult
|
||||
): ActionResult
|
||||
|
||||
fun onBreak(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity?)
|
||||
|
||||
fun tick(world: World)
|
||||
|
||||
fun syncToClient(world: World)
|
||||
|
||||
fun markDirty(world: World)
|
||||
fun writeToNbt(): NbtCompound
|
||||
fun getComparatorOutput(state: BlockState, world: World?, pos: BlockPos?): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
fun markRemoved(world: World):Unit
|
||||
fun onTriggerEvent(state: BlockState?, world: ServerWorld?, pos: BlockPos?, random: Random?)
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.multiblock.builder
|
||||
|
||||
import com.cobblemon.mod.common.api.multiblock.condition.MultiblockCondition
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
import net.minecraft.util.math.Box
|
||||
import net.minecraft.util.shape.VoxelShape
|
||||
|
||||
/**
|
||||
* Represents an area that has a potential to form a MultiBlockStructure
|
||||
* @property boundingBox The box that each condition checks in
|
||||
* @property conditions The [MultiblockCondition]s that must be met for the multiblock to form. All must be true.
|
||||
*
|
||||
* @author Apion
|
||||
* @since August 24, 2023
|
||||
*/
|
||||
interface MultiblockStructureBuilder {
|
||||
val boundingBox: VoxelShape
|
||||
val conditions: List<MultiblockCondition>
|
||||
|
||||
fun validate(world: ServerWorld): Boolean {
|
||||
conditions.forEach {
|
||||
if (!it.test(world, boundingBox)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
form(world)
|
||||
return true
|
||||
}
|
||||
|
||||
fun form(world: ServerWorld)
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.multiblock.condition
|
||||
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
import net.minecraft.util.math.Box
|
||||
import net.minecraft.util.shape.VoxelShape
|
||||
|
||||
class AndCondition(val conditionOne: MultiblockCondition, val conditionTwo: MultiblockCondition) :
|
||||
MultiblockCondition {
|
||||
override fun test(world: ServerWorld, box: VoxelShape): Boolean {
|
||||
return conditionOne.test(world, box) and conditionTwo.test(world, box)
|
||||
}
|
||||
|
||||
}
|
||||
Loaded 100 of 5699 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user