forked from mirrors/cobblemon
Compare commits
1057
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9eeeab340c | ||
|
|
9163046b45 | ||
|
|
325d1af484 | ||
|
|
6ae71f28e6 | ||
|
|
5687a71de4 | ||
|
|
8199f8d7c2 | ||
|
|
6b39251d65 | ||
|
|
cd03e6f8c4 | ||
|
|
a1b53f90ad | ||
|
|
c0677c6353 | ||
|
|
756989b0c0 | ||
|
|
58a4267f42 | ||
|
|
e8826a3d0e | ||
|
|
0606d57ef1 | ||
|
|
ef2578c1a7 | ||
|
|
3812de7558 | ||
|
|
ef558981c2 | ||
|
|
e4f928bce1 | ||
|
|
6090fce254 | ||
|
|
5a5d43404f | ||
|
|
931c3a7e6c | ||
|
|
d5a6e0dffd | ||
|
|
f56c357e4e | ||
|
|
4bfca0da43 | ||
|
|
52cff2e99d | ||
|
|
52f21ffc82 | ||
|
|
9c31899f3c | ||
|
|
9a5172f1cc | ||
|
|
11051f2b54 | ||
|
|
8b48cfaa50 | ||
|
|
50c3ffc774 | ||
|
|
daf32a5cf3 | ||
|
|
af4d2077ae | ||
|
|
3f090ce691 | ||
|
|
b1a3cbf29d | ||
|
|
130c50a2d6 | ||
|
|
0b65259ee7 | ||
|
|
53897a2613 | ||
|
|
8e6681b3aa | ||
|
|
50427965ab | ||
|
|
3318ee801a | ||
|
|
0b97d139af | ||
|
|
3966607373 | ||
|
|
b7c5f489fd | ||
|
|
39ec6187b5 | ||
|
|
b7681b43f9 | ||
|
|
ae594a0790 | ||
|
|
6af299406d | ||
|
|
29833df50e | ||
|
|
01d42abdb2 | ||
|
|
baa3f47769 | ||
|
|
16e716411a | ||
|
|
3bbc551fd7 | ||
|
|
74381d8e3c | ||
|
|
6688c32a1d | ||
|
|
45dcf6f23b | ||
|
|
e4d92ead6a | ||
|
|
9631f3c9d5 | ||
|
|
0787f2772d | ||
|
|
4011502e54 | ||
|
|
06855f6404 | ||
|
|
815955b904 | ||
|
|
df9eed0da3 | ||
|
|
99b73aa8dd | ||
|
|
f2d5073c7c | ||
|
|
3fda5f7c7a | ||
|
|
9b81666437 | ||
|
|
b43f969c02 | ||
|
|
02c4947513 | ||
|
|
6158b36103 | ||
|
|
2e14f8f8e8 | ||
|
|
bc80d6a171 | ||
|
|
65a7fc6fd7 | ||
|
|
ce019631ce | ||
|
|
0534e0d201 | ||
|
|
895e3ca378 | ||
|
|
3048e3d81d | ||
|
|
77fb94d9ef | ||
|
|
9078ee2191 | ||
|
|
06edc2810e | ||
|
|
81b83aabc1 | ||
|
|
6e7895c3b3 | ||
|
|
c69de804b9 | ||
|
|
fbbed7b20a | ||
|
|
a1b5f0a567 | ||
|
|
e42e06781d | ||
|
|
6a7b71d5a7 | ||
|
|
0a48014931 | ||
|
|
a70fed25c5 | ||
|
|
c2daed803f | ||
|
|
a56ffe1742 | ||
|
|
658fed638d | ||
|
|
3faa2a0467 | ||
|
|
77788a91b7 | ||
|
|
6d1570302d | ||
|
|
811e9d3352 | ||
|
|
745b48e77b | ||
|
|
9a4815f453 | ||
|
|
2ff41cdf9b | ||
|
|
d5268e8751 | ||
|
|
518799ee25 | ||
|
|
b597bb0818 | ||
|
|
1b39a64927 | ||
|
|
e610aa18d7 | ||
|
|
42ecd3e813 | ||
|
|
1299b8fee8 | ||
|
|
a12cf17cfa | ||
|
|
74faca60f2 | ||
|
|
6420176787 | ||
|
|
6ee81fe2ab | ||
|
|
96f4f988f8 | ||
|
|
4ccfbbcb37 | ||
|
|
ed0aa83013 | ||
|
|
b94394f8d1 | ||
|
|
b16687c132 | ||
|
|
56767b3e31 | ||
|
|
67eb3e1046 | ||
|
|
dda128e9e3 | ||
|
|
952ea8d3b7 | ||
|
|
cc764ff9db | ||
|
|
2e1f8af700 | ||
|
|
6c6a8e4679 | ||
|
|
9e9a22eb14 | ||
|
|
32bfaf152d | ||
|
|
d1b947b264 | ||
|
|
6122fb6107 | ||
|
|
14c7ee3216 | ||
|
|
1a00ae7fb8 | ||
|
|
36b3cbe3b8 | ||
|
|
49686a1670 | ||
|
|
2354888a73 | ||
|
|
f64065d54f | ||
|
|
005ab0ca74 | ||
|
|
c13307e931 | ||
|
|
bd21a6e1ca | ||
|
|
94ea15b9c5 | ||
|
|
bc6c9def56 | ||
|
|
9ca6a2e461 | ||
|
|
599603501a | ||
|
|
891ed6045d | ||
|
|
f7560a12ad | ||
|
|
8bc1767917 | ||
|
|
8b29d3a533 | ||
|
|
de1248b97e | ||
|
|
a654225ed5 | ||
|
|
2d18113e27 | ||
|
|
cdadc6fa67 | ||
|
|
a15aa86c66 | ||
|
|
ff7ef1b67e | ||
|
|
d91c819700 | ||
|
|
259e1d05cb | ||
|
|
549b88a4c2 | ||
|
|
68b60e7d50 | ||
|
|
a7787707f2 | ||
|
|
539097e681 | ||
|
|
8b70a4124d | ||
|
|
7e8b000311 | ||
|
|
00c86b89cb | ||
|
|
b2c9d96829 | ||
|
|
8ea5ea6804 | ||
|
|
1305e8a11d | ||
|
|
909cd8a6eb | ||
|
|
d60abdc940 | ||
|
|
ec8e6f58c8 | ||
|
|
12967e4813 | ||
|
|
d754cc69fe | ||
|
|
a2b54643fe | ||
|
|
896c195dd9 | ||
|
|
206bfacba0 | ||
|
|
b6ffbd1ed8 | ||
|
|
829900fb58 | ||
|
|
be3066f7b2 | ||
|
|
fb56ab5865 | ||
|
|
a3f02a8a7c | ||
|
|
6c2757b94b | ||
|
|
139ef56fdf | ||
|
|
d3e473ff85 | ||
|
|
fdebc5987e | ||
|
|
caeeb756fe | ||
|
|
67b5e5c6a8 | ||
|
|
720eef5e75 | ||
|
|
ebc7f67655 | ||
|
|
3c508c5bd1 | ||
|
|
c7052d295c | ||
|
|
9193e9a372 | ||
|
|
f6244cbe12 | ||
|
|
5743a04db7 | ||
|
|
439a5077c2 | ||
|
|
a8a028bb7a | ||
|
|
1984990a7e | ||
|
|
984e10a780 | ||
|
|
ad0571a782 | ||
|
|
a18581ae1c | ||
|
|
49e2e635db | ||
|
|
177ad70172 | ||
|
|
98fb731270 | ||
|
|
a98dbcf267 | ||
|
|
62e9294c8a | ||
|
|
314bd19dc6 | ||
|
|
c0344f5604 | ||
|
|
d795dca4fa | ||
|
|
503511e0ae | ||
|
|
2f8a9f207c | ||
|
|
8c1416514c | ||
|
|
575c33612d | ||
|
|
889d193ad1 | ||
|
|
57ef37099e | ||
|
|
d7d311764d | ||
|
|
d7fb65d23b | ||
|
|
3e4449aed1 | ||
|
|
55aa50654c | ||
|
|
489170cf00 | ||
|
|
930eb42e76 | ||
|
|
87d76e8788 | ||
|
|
6d8bf59eee | ||
|
|
a8f431868a | ||
|
|
0c6e355c6b | ||
|
|
a2f6ab0ea4 | ||
|
|
719a56e7c3 | ||
|
|
bd4397ec55 | ||
|
|
d5e3781fc5 | ||
|
|
776ab05ac1 | ||
|
|
a7f8a281a8 | ||
|
|
5ba6679a84 | ||
|
|
4ecd64bdf6 | ||
|
|
0da5d27851 | ||
|
|
48b28bc509 | ||
|
|
5547326798 | ||
|
|
bcf730a07f | ||
|
|
8be1e78fee | ||
|
|
c463c99b0f | ||
|
|
255829a9f8 | ||
|
|
46758b7ab0 | ||
|
|
aebcf42df8 | ||
|
|
2268640dbc | ||
|
|
bf3739c598 | ||
|
|
9c4ae189a1 | ||
|
|
502a314a6c | ||
|
|
ca1ea6385d | ||
|
|
6863cd0602 | ||
|
|
9749acbb0c | ||
|
|
81d4e4ded1 | ||
|
|
3e5ab4328b | ||
|
|
d1993574f6 | ||
|
|
2b531ec32f | ||
|
|
a9985bbea8 | ||
|
|
8d00da2c57 | ||
|
|
f4d866537a | ||
|
|
e9f942687f | ||
|
|
d67d73351d | ||
|
|
74d3ce793d | ||
|
|
3223c8dfeb | ||
|
|
a84a897e84 | ||
|
|
92bf3ba2a2 | ||
|
|
84f79c89c5 | ||
|
|
248967256b | ||
|
|
ea19721998 | ||
|
|
e9408db7a1 | ||
|
|
b9e6d63049 | ||
|
|
15ab84297d | ||
|
|
94cfb23e66 | ||
|
|
cb002ff530 | ||
|
|
19da349e78 | ||
|
|
30c3b605a3 | ||
|
|
2fbffa5b66 | ||
|
|
108b769928 | ||
|
|
3db39547f0 | ||
|
|
b8e79d2d3e | ||
|
|
c4688c5db9 | ||
|
|
b0385fc37f | ||
|
|
60c2721b53 | ||
|
|
b6f2ab25e1 | ||
|
|
6417f8cfa8 | ||
|
|
1d473437de | ||
|
|
c24b60785f | ||
|
|
08df2fef6c | ||
|
|
e491e7de81 | ||
|
|
f7974767d1 | ||
|
|
d41e89ddbd | ||
|
|
37293d396a | ||
|
|
d598335112 | ||
|
|
b3b63941e7 | ||
|
|
596122ecf0 | ||
|
|
e934ebf781 | ||
|
|
3b7bd22567 | ||
|
|
bae3da9411 | ||
|
|
a30ca92f0a | ||
|
|
dd5ec25345 | ||
|
|
40309e9913 | ||
|
|
5346f0f864 | ||
|
|
c4e0d19613 | ||
|
|
de9fe73a31 | ||
|
|
47fd191fea | ||
|
|
e3f3f4e1b7 | ||
|
|
004890d050 | ||
|
|
e690a0ed92 | ||
|
|
1e240d879f | ||
|
|
db7745589a | ||
|
|
65f0f69726 | ||
|
|
19263ddec6 | ||
|
|
dde4680ce0 | ||
|
|
a2939e34a0 | ||
|
|
6a937492dd | ||
|
|
5f52625b05 | ||
|
|
a64f201fd2 | ||
|
|
10746bea10 | ||
|
|
af1f607994 | ||
|
|
db9cefc8ba | ||
|
|
952eee67a6 | ||
|
|
87d7049a64 | ||
|
|
c467f9cad2 | ||
|
|
5f7fa85b58 | ||
|
|
eb3ffdfbd4 | ||
|
|
c7e512bc32 | ||
|
|
6889cb7936 | ||
|
|
b4af502997 | ||
|
|
9bffdf8df4 | ||
|
|
8dbdd78c86 | ||
|
|
d13e456d17 | ||
|
|
e36de84927 | ||
|
|
e6812891b5 | ||
|
|
6a3c98ed1c | ||
|
|
991ec7cc1a | ||
|
|
54cbaa9a10 | ||
|
|
1eaca5110b | ||
|
|
d7f2b1dce1 | ||
|
|
4952b3bda7 | ||
|
|
dbe743b50a | ||
|
|
82acd07ea5 | ||
|
|
7d26870a13 | ||
|
|
a418cbd118 | ||
|
|
e45af26af3 | ||
|
|
bcb1d412b1 | ||
|
|
c4a21c19ea | ||
|
|
5d86d03a13 | ||
|
|
867eb5f0d9 | ||
|
|
e59f4e7891 | ||
|
|
bdc260abca | ||
|
|
d9e5e52d9f | ||
|
|
a481bde4f5 | ||
|
|
787faf38e7 | ||
|
|
9a42c82a37 | ||
|
|
654d0f8975 | ||
|
|
66b3c4a4c6 | ||
|
|
77333d9a13 | ||
|
|
045613ef79 | ||
|
|
d78963daf3 | ||
|
|
2fc2f24dee | ||
|
|
0988411e13 | ||
|
|
b39fadcde8 | ||
|
|
61cfdd485e | ||
|
|
6f263845a0 | ||
|
|
51720489ae | ||
|
|
c12f991b18 | ||
|
|
977d66dafd | ||
|
|
f0b1843b71 | ||
|
|
785e63c7d4 | ||
|
|
61c3c995aa | ||
|
|
8221386767 | ||
|
|
8d2cf1ad81 | ||
|
|
e230d6fda5 | ||
|
|
5dc56bd4fc | ||
|
|
274f7e6c81 | ||
|
|
664f8e4484 | ||
|
|
d4700bcbd3 | ||
|
|
f9afd1d3e6 | ||
|
|
9d7198e4cd | ||
|
|
311a3e1005 | ||
|
|
aeb6bddba6 | ||
|
|
e11d1cb77c | ||
|
|
774e62bb4b | ||
|
|
716ab4fb95 | ||
|
|
766625bf31 | ||
|
|
14cde609c6 | ||
|
|
199128bb0d | ||
|
|
4d2b7f319c | ||
|
|
698cc5218d | ||
|
|
da6ac4b8d6 | ||
|
|
804dfe9131 | ||
|
|
afd007856e | ||
|
|
43ef224444 | ||
|
|
c99bf99052 | ||
|
|
e8019a0623 | ||
|
|
4c95cfc1b3 | ||
|
|
51a096913d | ||
|
|
980d95819e | ||
|
|
24aa65b2f1 | ||
|
|
19f33fe530 | ||
|
|
bbe8a6948a | ||
|
|
e46aaa5725 | ||
|
|
fc6c302c71 | ||
|
|
76cf856907 | ||
|
|
145d56e205 | ||
|
|
969b070300 | ||
|
|
d65d23ad02 | ||
|
|
e474ef607c | ||
|
|
a2ecccfac4 | ||
|
|
1a475bff87 | ||
|
|
8b6f5f55e6 | ||
|
|
39ed65e8ca | ||
|
|
35dab86ef4 | ||
|
|
3ad609b63e | ||
|
|
765a9e83ec | ||
|
|
ec8373ed04 | ||
|
|
2a7c663071 | ||
|
|
2cc14d26b1 | ||
|
|
c29da11541 | ||
|
|
8188ce0ed2 | ||
|
|
301de140e3 | ||
|
|
1b78cae080 | ||
|
|
4cf0dda554 | ||
|
|
ac55636c51 | ||
|
|
18eb50d4d2 | ||
|
|
87276de14d | ||
|
|
b7dc9ea6f6 | ||
|
|
ff59604526 | ||
|
|
b620ad27b6 | ||
|
|
5565f22610 | ||
|
|
7582b08d56 | ||
|
|
2e101f023f | ||
|
|
d98cccfc0f | ||
|
|
f83bde399c | ||
|
|
af77534b96 | ||
|
|
fa5193a3db | ||
|
|
e3c95aa4a5 | ||
|
|
72740fb418 | ||
|
|
e32b540deb | ||
|
|
f416567005 | ||
|
|
dda0c08fae | ||
|
|
d5e0364372 | ||
|
|
250f9e3cec | ||
|
|
26078ec29d | ||
|
|
5b68889689 | ||
|
|
bb3e86ac02 | ||
|
|
b96a6282d8 | ||
|
|
14ee3cd754 | ||
|
|
9c66c65b9e | ||
|
|
9ffbd14a81 | ||
|
|
fb36ba9720 | ||
|
|
87c2ce8f1a | ||
|
|
bb128fa7e1 | ||
|
|
dfcc6f2243 | ||
|
|
5053c765fb | ||
|
|
bfe8d41102 | ||
|
|
ad3cfe3708 | ||
|
|
a4a094a624 | ||
|
|
109895c0ff | ||
|
|
96bcffcc84 | ||
|
|
dc4f204db6 | ||
|
|
c07c78c331 | ||
|
|
e902e034ad | ||
|
|
77218f5250 | ||
|
|
0215a30c8d | ||
|
|
a0283b890b | ||
|
|
0b4d0d3e2e | ||
|
|
4bca5dc092 | ||
|
|
b4ce5f0ee6 | ||
|
|
561b5f25bb | ||
|
|
603bf45998 | ||
|
|
4f5799e5df | ||
|
|
54ea4903ba | ||
|
|
28ad0cce83 | ||
|
|
1daf931a49 | ||
|
|
7fe1929609 | ||
|
|
e03082a75e | ||
|
|
8d0c27f0e4 | ||
|
|
91fc2dc896 | ||
|
|
ab1ca295a3 | ||
|
|
d12003cc7d | ||
|
|
4723d26c13 | ||
|
|
664da45376 | ||
|
|
d8d017b7b3 | ||
|
|
f7acc73482 | ||
|
|
a15d413ce8 | ||
|
|
5cbe937e23 | ||
|
|
4fa196da94 | ||
|
|
6bcbc58b0a | ||
|
|
a1218f6c1e | ||
|
|
b1eb21150b | ||
|
|
43aa0ec04a | ||
|
|
b4bf044f76 | ||
|
|
a062b64588 | ||
|
|
d35db46c1b | ||
|
|
ee01ad20d9 | ||
|
|
b0b5aa4169 | ||
|
|
6b042cea47 | ||
|
|
1461b7231a | ||
|
|
f115443bea | ||
|
|
3bd946fb6b | ||
|
|
10818d4578 | ||
|
|
b8a6c94fcb | ||
|
|
b069e448c1 | ||
|
|
18f41407c8 | ||
|
|
b659a662a2 | ||
|
|
dbb2e45e14 | ||
|
|
da491015a6 | ||
|
|
55db0d8af1 | ||
|
|
211821bc0f | ||
|
|
0cda6d13b7 | ||
|
|
16a21f9d2e | ||
|
|
e69060bde6 | ||
|
|
ebdbbd5176 | ||
|
|
6e163d08f0 | ||
|
|
56d4a18474 | ||
|
|
13c7b75b19 | ||
|
|
1ad36e39c5 | ||
|
|
f13b6ddde7 | ||
|
|
c3d119c197 | ||
|
|
eb7527c26c | ||
|
|
f4d67b9b64 | ||
|
|
3c84afb95d | ||
|
|
2e615800ae | ||
|
|
0fc1239c77 | ||
|
|
38a0d149c5 | ||
|
|
4a4aaf3a94 | ||
|
|
53ca8f009d | ||
|
|
5b5c756d3c | ||
|
|
75410c3a72 | ||
|
|
87d001da80 | ||
|
|
8fee0e7f91 | ||
|
|
7985aed6bf | ||
|
|
5543b8a660 | ||
|
|
33ceb6ce32 | ||
|
|
be97509127 | ||
|
|
508e9dc923 | ||
|
|
f3565e2ab7 | ||
|
|
b1facea991 | ||
|
|
7b4f7b06ed | ||
|
|
d7d855adc2 | ||
|
|
4fd50b8d2b | ||
|
|
be466ad252 | ||
|
|
53749e014b | ||
|
|
b4cdf371fe | ||
|
|
e0e30e7e11 | ||
|
|
cfec4e10cb | ||
|
|
614799cfcb | ||
|
|
ec367fd4df | ||
|
|
8ab0534482 | ||
|
|
a00ab40c82 | ||
|
|
b6bc03d2b7 | ||
|
|
029a338aaf | ||
|
|
e415b281ee | ||
|
|
265aa6e124 | ||
|
|
2765a5584f | ||
|
|
46cba69ab7 | ||
|
|
d77cb36149 | ||
|
|
b1ed170f99 | ||
|
|
b3f794ddaa | ||
|
|
d37d95ee70 | ||
|
|
1c95686bf9 | ||
|
|
63f8e6251e | ||
|
|
5a3e9bb236 | ||
|
|
2fce916f05 | ||
|
|
52c4c35c0d | ||
|
|
40f4f80d6e | ||
|
|
55b1e7c672 | ||
|
|
721025281f | ||
|
|
08e6f68693 | ||
|
|
1e3fcf3e84 | ||
|
|
92a67ca0ca | ||
|
|
42600fc840 | ||
|
|
3867738d11 | ||
|
|
00e4864507 | ||
|
|
c46403268b | ||
|
|
c2dab93619 | ||
|
|
9917b57e1a | ||
|
|
b5e2f69207 | ||
|
|
c6c83c065b | ||
|
|
687381dc1b | ||
|
|
f088dd62bc | ||
|
|
3d1f9458f6 | ||
|
|
470d3807f1 | ||
|
|
e532fbf2ae | ||
|
|
c7348d3dba | ||
|
|
b978bbe60e | ||
|
|
1c74d498e6 | ||
|
|
4d3c46acc4 | ||
|
|
fbec87d2e0 | ||
|
|
397f8db5a0 | ||
|
|
36cd5f3894 | ||
|
|
b86f08b069 | ||
|
|
026897719d | ||
|
|
c4451ffb4f | ||
|
|
710b6404e7 | ||
|
|
b8f59110f0 | ||
|
|
75927fc1a9 | ||
|
|
0a0c1edffc | ||
|
|
18403c833d | ||
|
|
b9824e5708 | ||
|
|
57c1201ad0 | ||
|
|
4637bef5d2 | ||
|
|
e49dd8eb54 | ||
|
|
bf0c47c377 | ||
|
|
37e0030d08 | ||
|
|
628db514b3 | ||
|
|
6207a01ae3 | ||
|
|
9046217867 | ||
|
|
40aaef68f9 | ||
|
|
09c7bd8e61 | ||
|
|
8df8cb9cfe | ||
|
|
c048e5752b | ||
|
|
e8aa06d633 | ||
|
|
64979ff742 | ||
|
|
0163619e87 | ||
|
|
258ffd25ea | ||
|
|
2dd0d3dcf1 | ||
|
|
cc5b65a1dd | ||
|
|
b7de250457 | ||
|
|
8d0c5bc05c | ||
|
|
f4e242a270 | ||
|
|
da3a513905 | ||
|
|
33af6a1557 | ||
|
|
62b07f7f8a | ||
|
|
7bddbcfc67 | ||
|
|
993c7a5cf0 | ||
|
|
44da19f3e0 | ||
|
|
6d97c6ea34 | ||
|
|
2a55ef114d | ||
|
|
c236d8147a | ||
|
|
cf90bf0b0f | ||
|
|
b109ff6edf | ||
|
|
31c492c032 | ||
|
|
85a2142319 | ||
|
|
83e3d65918 | ||
|
|
9b053bef90 | ||
|
|
4ea288cc34 | ||
|
|
98540294b1 | ||
|
|
5535a6a7cb | ||
|
|
dd426423a1 | ||
|
|
6237e44e7c | ||
|
|
09561f736a | ||
|
|
21d1ae4eb5 | ||
|
|
3fd18319ee | ||
|
|
14e4fe66ac | ||
|
|
975c68cea0 | ||
|
|
6b77adbcef | ||
|
|
4d2b3697cc | ||
|
|
a9166bbf13 | ||
|
|
c7b2155a7c | ||
|
|
f8cec9843f | ||
|
|
d12a8704a9 | ||
|
|
52fc6b2575 | ||
|
|
68ffe0bdbc | ||
|
|
d417f95da7 | ||
|
|
d9b9b75e0e | ||
|
|
48e91bcb72 | ||
|
|
b4e3072020 | ||
|
|
4734c0a3cb | ||
|
|
1ed4d9ff9a | ||
|
|
8d0fc77be2 | ||
|
|
c45ef65645 | ||
|
|
0adfc64e35 | ||
|
|
80b4238c7e | ||
|
|
e16ae2544c | ||
|
|
f182cf4335 | ||
|
|
f5840c4794 | ||
|
|
cff65ab22e | ||
|
|
1d550b2cac | ||
|
|
c859cbae76 | ||
|
|
10e7962d85 | ||
|
|
767f820b7a | ||
|
|
06e4783f16 | ||
|
|
fe83b9d58e | ||
|
|
709e6f4a63 | ||
|
|
17f686488e | ||
|
|
4d1fe48e99 | ||
|
|
db574332e5 | ||
|
|
73b72ff19d | ||
|
|
15aac5e20a | ||
|
|
b88f4335ee | ||
|
|
76211e81ff | ||
|
|
6916cd51f7 | ||
|
|
b2ebfcc3b0 | ||
|
|
2cace9d153 | ||
|
|
33ad8ca12b | ||
|
|
8cce2c59b9 | ||
|
|
bdcb8da6b7 | ||
|
|
d0cfae8713 | ||
|
|
3b73493801 | ||
|
|
bfb48e8583 | ||
|
|
1bfe5e2044 | ||
|
|
ace65eda66 | ||
|
|
01c44537d0 | ||
|
|
e414dd94c3 | ||
|
|
2d4800a733 | ||
|
|
90e193e5a0 | ||
|
|
c7e86cf767 | ||
|
|
d8906992a3 | ||
|
|
972c259f6d | ||
|
|
8228424191 | ||
|
|
9bb67087b3 | ||
|
|
0f08446732 | ||
|
|
af09a6a0c7 | ||
|
|
b4d2f39c48 | ||
|
|
693b53704d | ||
|
|
3c46e3b5b9 | ||
|
|
5dec5ed008 | ||
|
|
22a479633e | ||
|
|
1d93df56ae | ||
|
|
136d47bd2f | ||
|
|
8ded0af5e9 | ||
|
|
36462b0a85 | ||
|
|
8a447a2487 | ||
|
|
bdc2c4d9de | ||
|
|
8d9a7d67b5 | ||
|
|
e1d9b2780a | ||
|
|
fafee79da9 | ||
|
|
71c6c12656 | ||
|
|
4e07128c80 | ||
|
|
df8640ce48 | ||
|
|
59e0a6369d | ||
|
|
8913252b79 | ||
|
|
f7bedc9866 | ||
|
|
e47529c10a | ||
|
|
3e6c6c21a6 | ||
|
|
1a12bbd493 | ||
|
|
8a24f635cf | ||
|
|
d6e066ddcd | ||
|
|
50335135c9 | ||
|
|
1ee6f83a5b | ||
|
|
e8b747a432 | ||
|
|
2b59276384 | ||
|
|
8f8804f3f4 | ||
|
|
d4f13b9435 | ||
|
|
e7b60abe2d | ||
|
|
85da2bd0cc | ||
|
|
ef826158ce | ||
|
|
d32314742d | ||
|
|
e8e0ca47dd | ||
|
|
ebcac6e782 | ||
|
|
63bfa634ae | ||
|
|
c3d482c78f | ||
|
|
7ea85dbd1e | ||
|
|
6cdb14d2f8 | ||
|
|
f041049576 | ||
|
|
e1aa6445fa | ||
|
|
f1b7ee5b9c | ||
|
|
9ea0f7e4f8 | ||
|
|
d0edd6ecbc | ||
|
|
b6188af659 | ||
|
|
f0a2f55054 | ||
|
|
fe27cbf56a | ||
|
|
ea273d6466 | ||
|
|
3da96ccaaa | ||
|
|
37c9a903a1 | ||
|
|
1372505486 | ||
|
|
a4ce4bf99b | ||
|
|
7effc4c853 | ||
|
|
4cd504126b | ||
|
|
60ee7b819c | ||
|
|
28548d5b19 | ||
|
|
e6ec690811 | ||
|
|
dac49c2f42 | ||
|
|
d72dad355c | ||
|
|
40b5726c5b | ||
|
|
7d57c1450e | ||
|
|
b7af57f6e1 | ||
|
|
ca5b7e1aec | ||
|
|
2ec81679e4 | ||
|
|
08c048f4ba | ||
|
|
6589279339 | ||
|
|
4465e47f2e | ||
|
|
570d42df7a | ||
|
|
044e83449d | ||
|
|
6617558e71 | ||
|
|
eff410b714 | ||
|
|
d32aa46832 | ||
|
|
4aee0b291c | ||
|
|
bcff96013e | ||
|
|
be46c59934 | ||
|
|
73c1a92a17 | ||
|
|
04a773d35c | ||
|
|
5068e66fa7 | ||
|
|
01a7461a9a | ||
|
|
482b682595 | ||
|
|
ffecc58979 | ||
|
|
eaaf2ca05c | ||
|
|
e91651553b | ||
|
|
482a7d9493 | ||
|
|
430891971c | ||
|
|
d88f2d80a3 | ||
|
|
874a5d2e8f | ||
|
|
70e49bbbdb | ||
|
|
39fce8ca06 | ||
|
|
d288fe46da | ||
|
|
cefc97320a | ||
|
|
a2094677cd | ||
|
|
2a3d74bd85 | ||
|
|
de94986156 | ||
|
|
f8afcb6a8f | ||
|
|
3c0cf1dc5b | ||
|
|
eae4eb5121 | ||
|
|
ed3a008515 | ||
|
|
462074ce43 | ||
|
|
d54a85aa68 | ||
|
|
bf8433f6e9 | ||
|
|
374fc44089 | ||
|
|
8225898a66 | ||
|
|
49faf60ea1 | ||
|
|
f7664a04db | ||
|
|
51b0f768a0 | ||
|
|
106e487035 | ||
|
|
2d772f5bf7 | ||
|
|
71bd4fb610 | ||
|
|
509feae420 | ||
|
|
5045a95cd0 | ||
|
|
07dfc89f63 | ||
|
|
34b6a3cc47 | ||
|
|
c56529030b | ||
|
|
bd81f84643 | ||
|
|
e840eb6e70 | ||
|
|
ed64b0cbc6 | ||
|
|
d821677411 | ||
|
|
c42d090862 | ||
|
|
2b85024b75 | ||
|
|
63af1713b9 | ||
|
|
8fecb12829 | ||
|
|
d0b50a1ee0 | ||
|
|
07497d653e | ||
|
|
2ecbe28c87 | ||
|
|
80112e0b70 | ||
|
|
dfb28ed185 | ||
|
|
0cc9a75255 | ||
|
|
abfd718681 | ||
|
|
ab6d08ad14 | ||
|
|
fa64eb7333 | ||
|
|
5dd17752b6 | ||
|
|
3a351a3195 | ||
|
|
81922a8d2c | ||
|
|
8271b7a979 | ||
|
|
251c2df78e | ||
|
|
c03e30bd9c | ||
|
|
f776542365 | ||
|
|
ecc793350a | ||
|
|
98fd61ec29 | ||
|
|
e1e545dd05 | ||
|
|
c403103018 | ||
|
|
d6a1d3f2bd | ||
|
|
87edf2bfd6 | ||
|
|
7711535a26 | ||
|
|
045ca3a07f | ||
|
|
a71bad07bd | ||
|
|
2085f12fef | ||
|
|
f819909446 | ||
|
|
dd195317f9 | ||
|
|
ab00285a4c | ||
|
|
953d724c87 | ||
|
|
863b43f902 | ||
|
|
f65f6fd2c9 | ||
|
|
a4e144854d | ||
|
|
d6f7cd4b83 | ||
|
|
36cf258410 | ||
|
|
89df2a01e2 | ||
|
|
0a930cb54f | ||
|
|
2448fec2c4 | ||
|
|
ea2071b644 | ||
|
|
bae0d77699 | ||
|
|
f5f5cb19bc | ||
|
|
9aa7c65279 | ||
|
|
8f4071e181 | ||
|
|
9c4470bc51 | ||
|
|
c785480c32 | ||
|
|
4a50700bb9 | ||
|
|
0ad2ff552b | ||
|
|
44c5d4ea2e | ||
|
|
46661908e0 | ||
|
|
01372f2850 | ||
|
|
204ce8f003 | ||
|
|
784ddcb19a | ||
|
|
11d7cbfa46 | ||
|
|
f3325caaea | ||
|
|
123c348f73 | ||
|
|
29aae87f01 | ||
|
|
9f6ad98acb | ||
|
|
cecd291566 | ||
|
|
2f9d6a9f83 | ||
|
|
1e9ccbddcb | ||
|
|
9b5a381436 | ||
|
|
ed5bd7e899 | ||
|
|
587a90bb70 | ||
|
|
f883578046 | ||
|
|
b5d348eba6 | ||
|
|
fce389edfd | ||
|
|
b6954b4e07 | ||
|
|
f28a16c7cc | ||
|
|
230071a773 | ||
|
|
63534a242c | ||
|
|
1afb574aec | ||
|
|
ac9adb03cd | ||
|
|
f3a22b19b3 | ||
|
|
1769af7385 | ||
|
|
572e77c4f5 | ||
|
|
889a012932 | ||
|
|
eca4c6cd4c | ||
|
|
b570a6ec8b | ||
|
|
1f1c302bc9 | ||
|
|
adc1fa0063 | ||
|
|
ddc3a781a0 | ||
|
|
9eb3281c6f | ||
|
|
0cd5804e67 | ||
|
|
7000d0d82a | ||
|
|
b7695e55ea | ||
|
|
bea3ebe62b | ||
|
|
73cf736077 | ||
|
|
d31f8f0eff | ||
|
|
88dca4d7b1 | ||
|
|
27db85ee32 | ||
|
|
5e3561eba5 | ||
|
|
9dfa8a323e | ||
|
|
15c0d86996 | ||
|
|
0fbb5e7d95 | ||
|
|
5e8d27779c | ||
|
|
a4fabcd45d | ||
|
|
5259b8c93d | ||
|
|
41b1e25816 | ||
|
|
7c9490db2a | ||
|
|
88e38bfa1a | ||
|
|
507a9a54b5 | ||
|
|
0b72a072bd | ||
|
|
c927cae609 | ||
|
|
474918e414 | ||
|
|
0e93383c90 | ||
|
|
abb44cf696 | ||
|
|
e6bd7cad72 | ||
|
|
e53b4fc36b | ||
|
|
5eef6628c3 | ||
|
|
509f44dca0 | ||
|
|
2e3db889a3 | ||
|
|
4c81e244e3 | ||
|
|
cc4a381956 | ||
|
|
a4ee09f4f7 | ||
|
|
c3a13e35a0 | ||
|
|
1897992093 | ||
|
|
4dfed5ffcf | ||
|
|
150ebff24f | ||
|
|
40721c1ce5 | ||
|
|
89fbf299d2 | ||
|
|
83961e80a3 | ||
|
|
e2db59c837 | ||
|
|
10bf69a79b | ||
|
|
172293c813 | ||
|
|
9bb653b8b7 | ||
|
|
7d06f1e2cd | ||
|
|
397c2decbf | ||
|
|
12b6e7e49c | ||
|
|
242c1b01af | ||
|
|
7b992802ce | ||
|
|
ba12ed5f98 | ||
|
|
56f68ff0a9 | ||
|
|
e7d27686e8 | ||
|
|
3592ef4150 | ||
|
|
dd76a16e08 | ||
|
|
f882c89485 | ||
|
|
06a989df5e | ||
|
|
def77d197f | ||
|
|
382b740505 | ||
|
|
7a65ec3602 | ||
|
|
57abb2b020 | ||
|
|
4decbe421b | ||
|
|
a7b55e5d03 | ||
|
|
28db655376 | ||
|
|
006736cd71 | ||
|
|
e7746e2fa4 | ||
|
|
862dc0176c | ||
|
|
7123d40084 | ||
|
|
cd21e0faf8 | ||
|
|
26586599a7 | ||
|
|
d5b5e1055b | ||
|
|
06732e89fd | ||
|
|
d153dd49b7 | ||
|
|
6e3cc5054a | ||
|
|
c06969815a | ||
|
|
502bd38aa7 | ||
|
|
11071eb44a | ||
|
|
dd6ca6c803 | ||
|
|
3ebba90f98 | ||
|
|
304f368ae1 | ||
|
|
9e8d6a4f39 | ||
|
|
e22eeafdea | ||
|
|
662efa55c6 | ||
|
|
efb9e538f3 | ||
|
|
f240dc1963 | ||
|
|
535c5f2e67 | ||
|
|
8b209e081b | ||
|
|
f7f276ecfb | ||
|
|
889ace7632 | ||
|
|
ee76e19b85 | ||
|
|
2aac6cc9e7 | ||
|
|
3faa305f09 | ||
|
|
d1bbf5f079 | ||
|
|
52fa646420 | ||
|
|
f7c47d46cf | ||
|
|
e82c361bcb | ||
|
|
fa6d8e0f08 | ||
|
|
7eea6c8b49 | ||
|
|
c537ca438b | ||
|
|
d5cea9b9ad | ||
|
|
fc0cd0dac4 | ||
|
|
019245472f | ||
|
|
cefb502f10 | ||
|
|
ee5e4d33b2 | ||
|
|
0fd954ffa5 | ||
|
|
60d3d737f9 | ||
|
|
6c2494b7ab | ||
|
|
a5ab523ac1 | ||
|
|
bd493a147c | ||
|
|
1e4665d600 | ||
|
|
847ae12ad5 | ||
|
|
cece9e051b | ||
|
|
02141ccd3e | ||
|
|
1dc3acc47d | ||
|
|
03374c5c78 | ||
|
|
594eca13d3 | ||
|
|
bf1bdc2475 | ||
|
|
6f6f9b088e | ||
|
|
2bbc00022b | ||
|
|
14f4e04a86 | ||
|
|
944d342d36 | ||
|
|
638524f7f7 | ||
|
|
47750e894b | ||
|
|
9e31d8e1e1 | ||
|
|
59d8adc48d | ||
|
|
f4ab23c167 | ||
|
|
b7a8582ae8 | ||
|
|
b68910897c | ||
|
|
7204ea828f | ||
|
|
0a4a71123c | ||
|
|
ec385b9963 | ||
|
|
1d40d424d0 | ||
|
|
938721c0bb | ||
|
|
8aa37fda9d | ||
|
|
52533236ca | ||
|
|
1caf963323 | ||
|
|
bb94f872a9 | ||
|
|
d560918b55 | ||
|
|
427bf34a56 | ||
|
|
479daa49ce | ||
|
|
729156924d | ||
|
|
47e9491e4e | ||
|
|
c4713b522b | ||
|
|
42c711cfc7 | ||
|
|
1296acd151 | ||
|
|
1a5ef95879 | ||
|
|
681d5f8bcc | ||
|
|
a52d8452b4 | ||
|
|
e65298b587 | ||
|
|
f8c09b8e26 | ||
|
|
5d1019afd5 | ||
|
|
a34db1dc1b | ||
|
|
f36f126a2b | ||
|
|
eb9bd116b2 | ||
|
|
da40245fa6 | ||
|
|
70bf4d6654 | ||
|
|
080a5b9c74 | ||
|
|
b0be0b2dca | ||
|
|
d8300436c9 | ||
|
|
65ab0f48e4 |
+10
-3
@@ -2,14 +2,21 @@
|
||||
- Rebuilt Pokémon AI to use Minecraft's Brain system, allowing for more complex behaviours and interactions.
|
||||
- As an early pass of this, pastured Pokémon will now sleep when appropriate, and may come up to you when they see you.
|
||||
- Probably also added a whole bunch of bugs.
|
||||
- Growlithe and Arcanine intimidate Skeletons.
|
||||
- Meowth intimidate Creepers and Phantoms.
|
||||
- Dog Pokémon (Growlithe, Arcanine, etc.) intimidate Skeletons.
|
||||
- Cat Pokémon (Meowth, Persian, etc.) intimidate Creepers and Phantoms.
|
||||
- Sleep-related Pokémon (Munsharna, Komala, etc.) intimidate Phantoms.
|
||||
- Some Pokémon naturally hunt each other.
|
||||
- Added a Behaviour Editor to the NPC editing screen.
|
||||
- Added /behaviouredit command for opening the Behaviour Editor on Pokémon and NPCs.
|
||||
- Editing variables for Pokémon is not yet supported.
|
||||
|
||||
### Developer
|
||||
- baseScale in NPCs has been removed from classes and presets, and in the entity it is replaced with hitboxScale and renderScale.
|
||||
- Added `EntityCallbacks` to `NPCEntity` and `PokemonEntity`. You can trigger custom callback types by using `[Entity].callbacks.process(...)`
|
||||
|
||||
### MoLang & Datapacks
|
||||
- Added a `behaviours` datapack folder which motivates the Behaviour Editor screen on NPCs and Pokémon.
|
||||
- Added many default behaviours.
|
||||
- Added "callback" support on PokemonEntity and NPCEntity that allows MoLang scripts to be executed in response to certain scenarios.
|
||||
- Added very many behaviours to choose from.
|
||||
- Removed many NPC presets that now exist as behaviours. This is a breaking change if you are using NPCs with these presets.
|
||||
- NPCs with these presets should be modified to instead list under `"behaviours"` all the equivalent behaviours.
|
||||
@@ -4,6 +4,30 @@
|
||||
- There is a different pot for each apricorn colour because at this point I think we may have an addiction.
|
||||
- Added Aprijuice, made from the Campfire Pot using apricorns with seasoning to give flavours.
|
||||
- Aprijuice can be fed to ride-able Pokémon to improve their riding characteristics, depending on the flavour and the Pokémon's nature.
|
||||
- Added Lure Cakes, made from the Campfire Pot using honey and berries.
|
||||
- Lure Cakes can be used to modify the spawn rate of Pokémon in the wild.
|
||||
- Added the Saccharine Tree, which can be found in the wild and is used to obtain Honey Bottles.
|
||||
- The leaves of the tree can be harvested to obtain honey, which can be used in the Campfire Pot to make Lure Cakes.
|
||||
- The Log of the tree can be interacted with using a honey bottle to create a Honey-Slathered Saccharine Log, which increases the change of spawning a Pokémon with a Hidden Ability.
|
||||
- Added Hearty Grains
|
||||
- Clicking on the Progress Arrow will show the JEI Recipe Book for the Campfire Pot, which will show all recipes that can be made with it.
|
||||
- Added a Ton of Redstone Compatibility.
|
||||
- Dispenser can now Honey and Unhoney:
|
||||
- Saccharine Log
|
||||
- Saccharine Leaves
|
||||
- Redstone can Close and Open the Lid of a Cooking Pot
|
||||
- Powered = Closed
|
||||
- Unpowered = Open
|
||||
- Hoppers can be used to insert items into a Cooking pot
|
||||
- Top = Seasonals
|
||||
- All Sides = Crafting
|
||||
- Bottom = Extract the Result
|
||||
- Observer will recognise when a Cooking pot is Closed or Opened
|
||||
- Comparator Calculates a Signal Strength depending on the items inside the cooking pot
|
||||
- Sculk Sensor
|
||||
- Saccharine Leaves
|
||||
- Opening and Closing the Cooking Pot
|
||||
- Saccharine Log
|
||||
|
||||
### Datapack and Addon Changes
|
||||
- Renamed the fishing_baits datapack folder to spawn_bait_effects.
|
||||
|
||||
@@ -4,9 +4,16 @@
|
||||
- The button on the right allows for changing the box wallpaper.
|
||||
- The option buttons on the left side allow for sorting the box by name, level, Pokédex number, gender, and type. Shift clicking allows for sorting in reverse order.
|
||||
- Added filter functionality in PC UI, which supports `PokemonProperties` (e.g. `shiny=yes` shows all shiny Pokémon).
|
||||
- Names can be filtered by exact or partial matches, e.g. entering "cha" will show Charmander, Charmeleon, etc.
|
||||
- Added `/changewallpaper <player> <boxNumber> <wallpaper>` command to change a box wallpaper through commands.
|
||||
- Added `/renamebox <player> <boxNumber> <name>` command to rename a PC box through commands.
|
||||
- Added IVs and EVs stat displays in PC.
|
||||
- Added ability to change boxes by scrolling.
|
||||
- PC will now open to last box viewed within a session.
|
||||
|
||||
### Changes
|
||||
- Slots in pastures will now have darker backgrounds and italicised Pokémon names if the Pokémon is not owned by the player.
|
||||
- The pasture slot will show the name of the Pokémon owner when hovered if the Pokémon is not owned.
|
||||
|
||||
### Developer
|
||||
- Added `RenamePCBoxEvent.Pre` and `RenamePCBoxEvent.Post` events to prevent players from renaming a box or changing their input.
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
### Additions
|
||||
- Pokémon can now spawn in herds, either as distinct herd groupings or simply several Pokémon spawning at once.
|
||||
|
||||
### Fixes
|
||||
- Fixed the "enabled" property in spawn files not actually being respected. Where do they find these devs?
|
||||
|
||||
### Developer
|
||||
- Spawning Influences now have the context of what the other buckets are when adjusting bucket weights. This will break existing influences that do bucket weight adjustment.
|
||||
- Renamed heaps of things in the spawning system to make more sense.
|
||||
- SpawningContext is now SpawnablePosition
|
||||
- WorldSlice is SpawningZone
|
||||
- SpawningProspector is now SpawningZoneGenerator
|
||||
- Renamed things in Spawn Rules to go with the other renames:
|
||||
- contextSelector is now spawnablePositionSelector
|
||||
- context is now spawnable_position
|
||||
+205
-6
@@ -7,6 +7,7 @@
|
||||
- Added `/cobblemonconfig reload` command to reload `main.json` configuration. **Note:** Some settings require a server restart to take effect; use this command cautiously.
|
||||
- Added `blacklisted_items_to_hold` and `whitelisted_items_to_hold` tags to allow for controlling which items players can give to their Pokémon. If the whitelist is empty, it will consider all item as allowed (unless they are in the blacklist).
|
||||
- Pokémon now follow the mouse cursor on the Summary screen, with an option to disable this in the settings.
|
||||
- Added Datapackable Item interactions with Pokemon
|
||||
- Pokémon's held items can now be rendered, with a visibility toggle in the Summary screen.
|
||||
- Added cosmetic item functionality for Pokémon. Certain cosmetic items can be given to applicable Pokémon via the interact menu.
|
||||
- Added the various log blocks as cosmetic items for Timburr and Komala.
|
||||
@@ -17,10 +18,29 @@
|
||||
- Added cosmetics for Gurdurr, Conkeldurr, Squirtle Line, Sneasler, Sandle line, Treecko line, Braixen, Delphox, and Dragonite.
|
||||
- Added `/transformmodelpart (position|rotation|scale) <modelPart> <transform: x y z>` command that can add transformations to a pokemon's model part.
|
||||
- The player executing the command must be facing the target pokemon entity. Transformations are not persistent and will revert when resources are reloaded.
|
||||
- Added `legacy` and `special` sourced moves to Pokémon.
|
||||
- Added lang keys for all moves and abilities up to Generation 9.
|
||||
- Fixed Moon Ball moon phase logic to actually work correctly
|
||||
- Added `translucent_cull` boolean option into resolver's layer to allow for translucent textures with culling
|
||||
- Added [LambDynamicLights](https://modrinth.com/mod/lambdynamiclights) support for items held by Pokémon.
|
||||
- Added [LambDynamicLights](https://modrinth.com/mod/lambdynamiclights) support for items held by Pokémon, evolution stone blocks, evolution stone items, Pokédex, Luminous Moss, Flame Orb, and Magmarizer.
|
||||
- Added the Clear Amulet, Grip Claw, Lagging Tail, Luminous Moss, Metal Alloy, Scroll of Darkness, Scroll of Waters
|
||||
- Added Recipes for Masterpiece Cup, Eject Pack
|
||||
- Added modification to Minecraft Creative Inventory search to account for item names that contain `poké` when input contains `poke`.
|
||||
- Added Campfire Pot as well as loads of new food items (Poke Puffs, Ponigiri, Sinister Tea, etc)
|
||||
- Added Hearty Grains, a new crop used in the new cooking mechanic
|
||||
- Added Tatami blocks and Tatami Mat blocks, made from Hearty Grain, for decorating builds
|
||||
- Added `/pcsearch <player> <pokemonProperties>` command that searches for a specific Pokémon within a player's PC.
|
||||
- Added `/pctake <player> <box> <slot>` command that takes a specific Pokémon from a player's PC. Removes the pokemon if target is self or ran from the server.
|
||||
- Added Hyper Training items (IV Modification) as well as some additional candy items to do so (Health Candy, Sickly Candy)
|
||||
- Added Galarica Nut Bushes
|
||||
- Many Pokémon (mostly cats) are now feared by phantoms
|
||||
- Lightning is now affected by a Pokemon's ability/typing
|
||||
- Pokémon with the ability Lightning Rod draw in lightning similar to a lightning rod block albeit with a lower priority and range, gain immunity to lightning damage, and receive a temporary damage buff.
|
||||
- Pokémon with the ability Motor Drive are immune to lightning damage and receive a temporary speed buff when struck by lightning
|
||||
- Pokémon with the ability Volt Absorb are immune to lightning damage and receive Regeneration II for a short duration
|
||||
- Ground type Pokémon are immune to lightning damage
|
||||
- Added functionality to Everstone when held by a Pokémon; suppresses evolution notification and hides evolve button in summary interface.
|
||||
- Added new optional property `attachment_options` for most EmitterShapes to be attached to the locator/entities scale, rotation, and/or position. Position is true by default.
|
||||
- Galarica Nut bushes now generate on beaches
|
||||
|
||||
### Pokémon Added
|
||||
|
||||
@@ -32,12 +52,17 @@
|
||||
- Grumpig
|
||||
- Snorunt
|
||||
- Glalie
|
||||
- Latias
|
||||
- Latios
|
||||
|
||||
#### Gen 4
|
||||
- Bronzor
|
||||
- Bronzong
|
||||
- Croagunk
|
||||
- Toxicroak
|
||||
- Froslass
|
||||
- Glameow
|
||||
- Purugly
|
||||
|
||||
#### Gen 5
|
||||
- Pansage
|
||||
@@ -50,10 +75,24 @@
|
||||
- Musharna
|
||||
- Blitzle
|
||||
- Zebstrika
|
||||
- Drilbur
|
||||
- Excadrill
|
||||
- Trubbish
|
||||
- Garbodor
|
||||
- Gothita
|
||||
- Gothorita
|
||||
- Gothitelle
|
||||
- Solosis
|
||||
- Duosion
|
||||
- Reuniclus
|
||||
- Mienfoo
|
||||
- Mienshao
|
||||
|
||||
#### Gen 6
|
||||
- Inkay
|
||||
- Malamar
|
||||
- Hawlucha
|
||||
- Dedenne
|
||||
- Noibat
|
||||
- Noivern
|
||||
|
||||
@@ -63,13 +102,20 @@
|
||||
#### Gen 8
|
||||
- Silicobra
|
||||
- Sandaconda
|
||||
- Sinistea
|
||||
- Polteageist
|
||||
|
||||
#### Gen 9
|
||||
- Smoliv
|
||||
- Dolliv
|
||||
- Arboliva
|
||||
- Tarountula
|
||||
- Spidops
|
||||
- Orthworm
|
||||
- Dudunsparce
|
||||
- Cyclizar
|
||||
- Poltchageist
|
||||
- Sinistcha
|
||||
|
||||
### Animation updates for the following Pokémon
|
||||
- Garchomp
|
||||
@@ -82,6 +128,15 @@
|
||||
- Delphox
|
||||
- Cinderace
|
||||
- Kangaskhan
|
||||
- Gossifleur
|
||||
- Eldegoss
|
||||
- Stonjourner
|
||||
- Wailmer
|
||||
- Lechonk
|
||||
- Oinkologne
|
||||
- Dratini
|
||||
- Dragonair
|
||||
- Dragonite
|
||||
|
||||
### Model updates for the following Pokémon
|
||||
- Gyarados
|
||||
@@ -99,27 +154,69 @@
|
||||
- Grovyle
|
||||
- Sceptile
|
||||
- Honchkrow
|
||||
- Gible
|
||||
- Gabite
|
||||
- Garchomp
|
||||
- Pidgeot
|
||||
- Nosepass
|
||||
- Probopass
|
||||
- Kangaskhan
|
||||
- Cinderace
|
||||
- Magnemite
|
||||
- Magneton
|
||||
- Magnezone
|
||||
- Beldum
|
||||
- Metang
|
||||
- Metagross
|
||||
- Hoothoot
|
||||
- Noctowl
|
||||
- Teddiursa
|
||||
- Ursaring
|
||||
- Ursaluna
|
||||
- Heatmor
|
||||
- Bouffalant
|
||||
- Sigilyph
|
||||
- Sharpedo
|
||||
- Maractus
|
||||
- Clodsire
|
||||
- Scyther
|
||||
- Scizor
|
||||
- Cacturne
|
||||
- Taillow
|
||||
- Swellow
|
||||
- Added Syrupy Apples.
|
||||
- Seel
|
||||
- Dewgong
|
||||
- Honedge
|
||||
- Doublade
|
||||
- Aegislash
|
||||
|
||||
### Changes
|
||||
- Changed pokemon caught and seen count to update based on the current pokedex being looked
|
||||
- Renamed `chargeGainedPerTick` config to `secondsToChargeHealingMachine`.
|
||||
- Added config setting `maxPokedexScanningDetectionRange` to control from what distance the player can scan Pokémon using the Pokédex.
|
||||
- Added the `is_standing_on_blocks(depth, blocks...)` MoLang function, which returns whether the specified entity is standing on a specific block or set of blocks. Example usage: `q.is_standing_on_blocks(2, minecraft:sand)`
|
||||
- Added config setting `hideUnimplementedPokemonInThePokedex` which hides unimplemented Pokémon from the Pokédex when set to true.
|
||||
- Added molang particle queries for getting distance to targeted entities
|
||||
- Added debug renderer for poseable entity locators
|
||||
- Added time zone as a config option
|
||||
- Added optional boolean to use time zone for MoLang function "date_local_time" and "date_of"
|
||||
- Added "irlDateRange" and "irlTimeRange" as a condition for spawning
|
||||
- Added an optional MoValue to either use system timezone when set as true, or use the supplied string as a timezone for MoLang functions `date_local_time` and `date_of`. If the timezone supplied fails to parse this function now returns `0.0`.
|
||||
|
||||
### Additions
|
||||
- Added time zone as a config option
|
||||
- Added optional boolean to use time zone for MoLang function "date_local_time" and "date_of"
|
||||
- Made Blocks of Gold count as Big Nuggets when held by a Pokémon (for Fling functionality)
|
||||
- Players can now eat Sweet and Tart Apples, Whipped Dreams, and the Alcremie Sweets.
|
||||
- Updated Sweet and Tart Apple sprites
|
||||
- Updated the following recipes: Air Balloon, Assault Vest, Binding Band, Black Belt, Blunder Policy, Choice Band, Choice Scarf, Cleanse Tag, Covert Cloak, Destiny Knot, Eject Button, Expert Belt, Focus Band, Focus Sash, Magnet, Metronome, Muscle Band, Power Anklet, Power Band, Power Belt, Power Bracer, Power Lens, Power Weight, Protective Pads, Protein, Punching Glove, Reaper Cloth, Rocky Helmet, Room Service, Sachet, Safety Goggles, Silk Scarf, Spell Tag, Utility Umbrella, Weakness Policy, Zinc
|
||||
- Added alternate ingredient options to the following recipes: Cell Battery, Charcoal Stick, Dragon Fang, Miracle Seed, Mystic Water, Never Melt Ice, Twisted Spoon, Damp Rock, Heat Rock, Icy Rock, Smooth Rock
|
||||
- Updated the following recipes: Air Balloon, Assault Vest, Binding Band, Black Belt, Blunder Policy, Choice Band, Choice Scarf, Cleanse Tag, Covert Cloak, Destiny Knot, Eject Button, Expert Belt, Focus Band, Focus Sash, Magnet, Metronome, Muscle Band, Power Anklet, Power Band, Power Belt, Power Bracer, Power Lens, Power Weight, Protective Pads, Protein, Punching Glove, Reaper Cloth, Rocky Helmet, Room Service, Sachet, Safety Goggles, Silk Scarf, Spell Tag, Utility Umbrella, Weakness Policy, Zinc, Chipped Pot, Cracked Pot, Unremarkable Cup, Loaded Dice, Charcoal Stick, Dragon Fang, Miracle Seed, Mystic Water, Never Melt Ice, Twisted Spoon, Black Glasses, Fairy Feather, Hard Stone, Silver Powder, Soft Sand
|
||||
- Added alternate ingredient options to the following recipes: Cell Battery, Damp Rock, Heat Rock, Icy Rock, Smooth Rock
|
||||
- Grouped together some recipes within the Recipe Book. Groups include: the seven basic Poké Balls, the seven basic Ancient Poké Balls, Gilded Chests, Pokedexes, and the Weather Rocks.
|
||||
- Updated some item tags to better integrate behaviours between Cobblemon, Vanilla Minecraft, and other mods
|
||||
- Removed Cooked Meat, Raw Meat, Protein Ingredients, and Zinc Ingredients, the first two are now using `c` namespace tags, the latter have better integrated use of tags within their recipes which removes need for custom tags.
|
||||
- Added our seeds tag into `#c:seeds`, which is now made use of for the Miracle Seed recipe.
|
||||
- Added our seeds tag into `#c:seeds`, which is now made use of for the Miracle Seed recipe.
|
||||
- Added herbs and snowballs to the consumable in PvE and Wild battle tags
|
||||
- Tweaked the Natural Materials Vanilla file to fit with the changes to tags
|
||||
- Substantially optimised spawning checks mainly by front-loading biome filtering.
|
||||
- When using the `cobblemon` or `generation_9` capture calculators a critical capture with a single shake will always play for successful captures when you've already registered the Pokémon as caught in your Pokédex.
|
||||
@@ -134,10 +231,31 @@
|
||||
- Improved parity with vanilla mobs' drop behavior; loot and XP drop on death instead of after the entire death sequence finishes.
|
||||
- Quirk animations no longer play in the battle GUI since they were pretty distracting.
|
||||
- A number of Pokemon that float above the ground visually (Gastly, Klingklang, etc.) are no longer considered to be touching the ground
|
||||
- Changed the recipes for Level, Lure, and Moon Balls to be cleaner
|
||||
- Renamed `pokemonId` and `type` to `species` in relevant Advancement triggers for conformity, this is a breaking change.
|
||||
- Added a separate `species` argument to the `pick_starter`, `pasture_use` and `resurrect_pokemon` Advancement triggers.
|
||||
- Made `CobblemonAgingDespawner` thresholds configurable via the config file.
|
||||
- Tweaked Berry flavor data to balance cooking pot mechanics
|
||||
- Made Red, Yellow, Green, Blue, Pink, Black, and White Apricorn Sprout and Saccharine Sapling able to be placed into flower pots.
|
||||
- Added all Potted Apricorn Sprouts, Potted Saccharine Saplings, and Potted Pep-Up Flowers to the `#minecraft:flower_pots` block tag
|
||||
- Corrected the healing values of the remedies and energy root, and reintroduced the friendship lowering mechanics for them, revivl herb, and heal powder
|
||||
- Updated battle language keys for side effects to use position-specific formats, improving grammatical consistency
|
||||
- Saccharine Leaves are now Collectable
|
||||
- Saccharine Leaves Age 1 or higher will now show Yellow particles when broken
|
||||
- Destroying a Saccharine Honey Log will now drop a Saccharine Log in stead of nothing
|
||||
- Reworked some compost chances
|
||||
- Updated interaction interface to include 4 more option spaces
|
||||
- Made lecterns that hold a Pokédex emit light.
|
||||
- Updated light levels for active PC, Pasture, Healing Machine, and Data Monitor.
|
||||
- Vivichokes now always drop one seed when harvested, and converting a fully grown Vivichoke to seeds via crafting results in 1 seed.
|
||||
- Healing Machine recipe rebalanced.
|
||||
- Reorganised the `block` texture folder to be more organised, in line with the `item` texture folder.
|
||||
- Offset in EmitterShape now ignores scale to be more like Blockbench by default. You can get this behaviour back by adding `"scale": true` in the `attachment_options` property in most EmitterShapes.
|
||||
- Not specifying a dex in `/pokedex printcalculations {player} {dex}` will now print the National Dex statistics instead of showing all dexes. `/pokedex printcalculations {player} all` is how to view all dex statistics in one command.
|
||||
- Removed Braised Vivichoke
|
||||
|
||||
### Fixes
|
||||
- Fixed game crashing when removing national pokedex using datapacks
|
||||
- Fixed Particles sometimes facing the wrong direction (looking at you, Swords Dance)
|
||||
- Fixed PCs always opening at box 2 instead of box 1.
|
||||
- Fixed not being able to do complex item requirements aside from just NBT with evolution conditions, requirements and fossil items.
|
||||
@@ -164,11 +282,46 @@
|
||||
- Fixed Pokémon marked as silent still playing shiny sounds and effects.
|
||||
- Fixed an issue with newer versions of Fabric API where underground Pokémon were spawning in The End.
|
||||
- Fixed spawning not working well when you're at high points surrounded by lower altitude spawning areas, such as flying.
|
||||
- Fixed some Pokémon having erroneous tutor moves if another move included a valid tutor move as a substring.
|
||||
- Fixed certain Pokémon with forms not having appropriate stock Pokédex entries.
|
||||
- Fixed issue with Pokédex Scanner that caused the open/close overlay to have the wrong opacity values
|
||||
- Fixed dragon's breath not being usable on the restoration tank when it should be
|
||||
- Fixed Moon Stones not interacting properly with dripstone blocks.
|
||||
- Fixed some effects like particles from fishing rods appearing for players in the same coordinates in another world.
|
||||
- Fixed an issue with Sketch where the Pokémon using Sketch would not properly learn moves with special characters in their name (e.g. King's Shield, Baby-Doll Eyes, etc.)
|
||||
- Fixed wild Pokémon sometimes spawning with incorrect friendship values
|
||||
- Fixed typo while saving/loading NPCEntity causes data loss
|
||||
- Fixed an issue where catching a Pokémon while it was leashed to a fence would not update the fence.
|
||||
- Fixed the `dimensions` spawning condition using the incorrect ResourceLocation, causing it to not function properly.
|
||||
- Fix issue where locator X axis was not aligned with blockbench.
|
||||
- Fix issue where particle effects that play on frame 1 on sendout would never play (Gastly)
|
||||
- The Wiglett line will now sink in water again.
|
||||
- Fixed the Sprigatito line's portraits being zoomed in too far.
|
||||
- Fixed Floragato's battle cry animation from breaking.
|
||||
- Fixed the block texture name for the Pep-Up Flower being inaccurate
|
||||
- Fixed issue where the restoration tank would not accept valid items from a hopper.
|
||||
- Fixed energy root not being shearable
|
||||
- Fixed energy root always spreading into more energy roots instead of by chance (same as big root)
|
||||
- Fixed issue where Pokémon spawned by the "spawnallpokemon" command potentially receiving a raft.
|
||||
- Fixed logspam on NeoForge when adorn is not installed
|
||||
- Fixed Cobblemon crashing if it tries to load a bedrock model not meant for cobblemon (example: Qlipoth Awakening)
|
||||
- Fixed Berries (and thus mulches) not being plantable on Farmers delight rich soil farmland
|
||||
- Fixed wild Pokémon vanishing when third party mods try to tame them the "vanilla" way
|
||||
- Fixed Pokémon not being able to path over skulk veins, pressure plates, fence gates, signs, lanterns, chains, and many other short blocks.
|
||||
- Fixed some cases in which Pokémon could not path over fence posts situations.
|
||||
- Fixed flyers not being able to do vertical takeoff if surrounded by blocks.
|
||||
- Fixed swimming Pokémon attempting to swim up through solid blocks.
|
||||
- Fixed Pokémon surface swimming diving downward a block for the duration of the swim.
|
||||
- Improved flyers avoiding getting stuck on fence posts.
|
||||
- Fixed air balloon battle text not correctly displaying the Pokémon or item name
|
||||
- Fixed an issue where items retrieved from a Display case would disappear if a player's inventory is full
|
||||
- Fixed Pokédex Scanner not respecting the "Invert Mouse" option.
|
||||
- Fixed a crash due to a ConcurrentModificationException that could occur during world generation.
|
||||
- Fixed Moon Ball moon phase logic to actually work correctly
|
||||
- Fixed `/pokedex printcalculations` to now show the correct percentage completed of the Pokedex
|
||||
- Fixed mod incompatibility with the `Raised` mod
|
||||
- Fixed a vulnerability that could cause party and PC rollbacks under specific circumstances.
|
||||
- Fixed a rare edge case where sorting your PC could be rolled back later.
|
||||
|
||||
### Developer
|
||||
- A finished battle now has winners and losers set inside of `PokemonBattle` instead of them always being empty.
|
||||
@@ -187,6 +340,11 @@
|
||||
- Updated NPCEntity pokeball throw positioning to properly account for the baseScale property.
|
||||
- Fixed `[Pokemon].copyFrom` error causing forms, IVs, and EVs to not be applied properly when using `[Pokemon].loadFromJSON` or `[Pokemon].loadFromNBT`
|
||||
- Added new item class, `WearableItem`. Instances of this class should have a corresponding 3D model. These models render when the items display context is `HEAD`.
|
||||
- Added new LearnsetQuery types:
|
||||
- `LEGAL` for moves that are innately compatible and learnable by the Pokémon.
|
||||
- `LEGACY` for moves that were once officially learnable by the Pokémon but aren't due to GameFreak's re-balancing.
|
||||
- `SPECIAL` for moves that are not learnable by the Pokémon but may have appeared in a special event or distribution.
|
||||
|
||||
- Pokemon now have a fireImmune attribute in their behaviour that can be set to true to ignore all fire damage (lava, magma blocks, etc.)
|
||||
`JSON
|
||||
{
|
||||
@@ -195,6 +353,17 @@
|
||||
}
|
||||
}
|
||||
`
|
||||
- The IVs class has now been extended to include Hyper Trained values.
|
||||
- Added `Pokemon#hyperTrainIV()` and `IVs#setHyperTrainedIV(Stat, Int)`.
|
||||
- Added `HyperTrainedIvEvent.Pre` and `HyperTrainedIvEvent.Post`.
|
||||
- Added `Pokemon#validateMoveSet()` to validate an existing Pokemon's moveset, clearing illegal moves.
|
||||
- Added a `hoverText` option to PartySelectCallback, to display a tooltip on hovering over a Pokémon in the selection screen.
|
||||
- `PokemonEntity` instances spawned into the world now appropriately finalize the spawn for mod compatibility.
|
||||
- Added PokedexManager.obtain as a replacement for .catch which is not a friendly function name in Java.
|
||||
|
||||
- Added `Pokemon#hyperTrainIV()` and `IVs#setHyperTrainedIV(Stat, Int)`
|
||||
- `ElementalType` now implements `ShowdownIdentifiable` to ensure the communcation with showdown stays consistent (also in regards to TeraTypes)
|
||||
- Pokemon no longer have a change observable
|
||||
|
||||
### MoLang & Datapacks
|
||||
- The following usages for item predicates can now use item conditions like advancements do, you can learn about them in the [Minecraft wiki](https://minecraft.wiki/w/Advancement_definition#minecraft:filled_bucket)
|
||||
@@ -213,7 +382,36 @@
|
||||
- Added `pokemon` as an available Molang function for the `battleActor` functions.
|
||||
- Fixed `heldItem` property inside spawn files not working and causing crashes
|
||||
- Fixed `spawn_bedrock_particles` MoLang causing crashes when used in a server environment
|
||||
- The following move sources are now valid for the `moves` array in species data:
|
||||
- `legacy:{move}`
|
||||
- `special:{move}`
|
||||
- The Pokédex form lang key definition now follows `cobblemon.ui.pokedex.info.form.{species}-{formname}` instead of `cobblemon.ui.pokedex.info.form.{formname}`.
|
||||
- Added `play_sound_on_server` as an available Molang function for the `worldHolder` & `player` functions.
|
||||
- Added `run_molang_after` as an available Molang function for the `entity` functions when schedulable.
|
||||
- Added an optional parameter for `run_molang` to schedule the function.
|
||||
- Added `labels` & `has_label` as available Molang functions for the `speciesFunctions`
|
||||
- Added datapack-defined starter categories via `data/<namespace>/starters/*.json`, with built-in fallback and `useConfigStarters` merge option.
|
||||
- The format of the `remedies.json` file has changed to allow for individual friendshipDrop amounts per remedy
|
||||
- Fixed `entity.find_nearby_block` causing crashes when attempting to use a block tag
|
||||
- Spawn Filters can now access `v.spawn.class` to get the identifier of an NPC class for when trying to influence NPC spawns
|
||||
- Added Molang functions for Party and PC: `set_pokemon`
|
||||
- Added Molang functions for Pokémon: `pokeball`, `held_item`, `remove_held_item`, `hyper_train_iv`, `validate_moveset`, `initialize_moveset`, and `add_exp`.
|
||||
- Added Molang functions for Pokémon: `aspects`, `form_aspects`, `unlearn_move`, `teach_learnable_moves`, `cosmetic_item`, and `remove_cosmetic_item`.
|
||||
- Added Molang functions for Pokémon: `ability`, `set_iv`, `set_ev`, `teach_move`, and `can_learn_move`.
|
||||
- Adds Flows for `STARTER_CHOSEN`, `SHOULDER_MOUNTED`, `EV_GAINED`, `POKEMON_RELEASED`, `POKEMON_NICKNAMED`, `HELD_ITEM`, and `TRADE_COMPLETED` events
|
||||
- Adds Flows for `POKEMON_HEALED`, `POKEMON_SCANNED`, `BERRY_HARVEST`, `LOOT_DROPPED`, `POKEMON_SEEN`, `COLLECT_EGG`, `HATCH_EGG`, and `EXPERIENCE_GAINED`.
|
||||
- Adds Flows for `POKEMON_CATCH_RATE`, `BAIT_SET`, `BAIT_SET_PRE`, `BAIT_CONSUMED`, `POKEROD_CAST_PRE`, `POKEROD_CAST_POST`, `POKEROD_REEL`, and `BOBBER_SPAWN_POKEMON_PRE`.
|
||||
- Adds Flows for `POKEMON_ASPECTS_CHANGED`, `FRIENDSHIP_UPDATED`, `CHANGE_PC_BOX_WALLPAPER_EVENT_PRE`, `CHANGE_PC_BOX_WALLPAPER_EVENT_POST`, and `FULLNESS_UPDATED`.
|
||||
- MoLang triggered battles may now set the battle format, whether to clone the player's party, set level, or heal prior.
|
||||
- Added Molang function for Player: `inventory`
|
||||
- Adds Flows for `STARTER_CHOSEN`, `EV_GAINED`, `POKEMON_RELEASED`, `POKEMON_NICKNAMED`, `HELD_ITEM`, and `TRADE_COMPLETED` events
|
||||
- Adds Pokemon functions for `pokeball`, `held_item`, `remove_held_item`, `add_aspects`, and `remove_aspects`
|
||||
- Added `pokemon.hyper_train_iv` as an available Molang function.
|
||||
- Added `prepare_{effect}` and `damage_{effect}` action effect hooks in battles for more battle particle effects.
|
||||
- Added `q.has_argument(<argument_name>, [argument_value])` MoLang function to several battle-related action effect contexts.
|
||||
- Added `q.has_argument_at(<index>, [argument_value])` MoLang function to several battle-related action effect contexts.
|
||||
- Added `q.hit_count` MoLang function to move action effect contexts.
|
||||
- Added `is_included`, `to_lower`, `to_upper`, and `string_length` as available Molang functions.
|
||||
|
||||
## [1.6.1 (January 26th, 2025)](#1-6-1)
|
||||
|
||||
@@ -1028,6 +1226,7 @@
|
||||
}
|
||||
`
|
||||
- Added support for custom stashes, similar to Gimmighoul's coin and scrap stashes.
|
||||
- Added the ability to create custom brewing stand recipes.
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
@@ -2335,4 +2534,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.
|
||||
@@ -1,6 +1,5 @@
|
||||
plugins {
|
||||
id("cobblemon.root-conventions")
|
||||
id ("net.nemerosa.versioning") version "3.1.0"
|
||||
}
|
||||
|
||||
version = "${project.property("mod_version")}+${project.property("mc_version")}"
|
||||
|
||||
@@ -21,7 +21,6 @@ plugins {
|
||||
|
||||
id("net.kyori.blossom")
|
||||
id("org.jetbrains.gradle.plugin.idea-ext")
|
||||
id("net.nemerosa.versioning") version "3.1.0"
|
||||
}
|
||||
|
||||
architectury {
|
||||
|
||||
@@ -11,6 +11,7 @@ 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.item.PokedexItem;
|
||||
import com.cobblemon.mod.common.pokemon.FormData;
|
||||
import com.cobblemon.mod.common.pokemon.lighthing.LightingData;
|
||||
import dev.lambdaurora.lambdynlights.LambDynLights;
|
||||
@@ -36,20 +37,20 @@ public class LambDynamicLightsCompat {
|
||||
public static void hookCompat() {
|
||||
// Pokémon entities
|
||||
DynamicLightHandlers.registerDynamicLightHandler(
|
||||
CobblemonEntities.POKEMON,
|
||||
DynamicLightHandler.makeHandler(
|
||||
LambDynamicLightsCompat::resolvedPokemonLightLevel,
|
||||
pokemon -> false
|
||||
)
|
||||
CobblemonEntities.POKEMON,
|
||||
DynamicLightHandler.makeHandler(
|
||||
LambDynamicLightsCompat::resolvedPokemonLightLevel,
|
||||
pokemon -> false
|
||||
)
|
||||
);
|
||||
|
||||
// Shouldered Pokémon
|
||||
DynamicLightHandlers.registerDynamicLightHandler(
|
||||
EntityType.PLAYER,
|
||||
DynamicLightHandler.makeHandler(
|
||||
LambDynamicLightsCompat::resolvedShoulderLightLevel,
|
||||
player -> false
|
||||
)
|
||||
EntityType.PLAYER,
|
||||
DynamicLightHandler.makeHandler(
|
||||
LambDynamicLightsCompat::resolvedPlayerLightLevel,
|
||||
player -> false
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -63,11 +64,13 @@ public class LambDynamicLightsCompat {
|
||||
return Math.max(itemLightLevel, formLightLevel);
|
||||
}
|
||||
|
||||
private static int resolvedShoulderLightLevel(Player player) {
|
||||
private static int resolvedPlayerLightLevel(Player player) {
|
||||
var underwater = !player.level().getFluidState(BlockPos.containing(player.getX(), player.getEyeY(), player.getZ())).isEmpty();
|
||||
final int leftLightLevel = extractShoulderLightLevel(PokemonOnShoulderRenderer.shoulderDataFrom(player.getShoulderEntityLeft()), underwater);
|
||||
final int rightLightLevel = extractShoulderLightLevel(PokemonOnShoulderRenderer.shoulderDataFrom(player.getShoulderEntityRight()), underwater);
|
||||
return Math.max(leftLightLevel, rightLightLevel);
|
||||
final int leftShoulderLightLevel = extractShoulderLightLevel(PokemonOnShoulderRenderer.shoulderDataFrom(player.getShoulderEntityLeft()), underwater);
|
||||
final int rightShoulderLightLevel = extractShoulderLightLevel(PokemonOnShoulderRenderer.shoulderDataFrom(player.getShoulderEntityRight()), underwater);
|
||||
final int itemLightLevel = customHeldItemLightLevel(player.getMainHandItem(), player.getOffhandItem());
|
||||
|
||||
return Math.max(itemLightLevel, Math.max(leftShoulderLightLevel, rightShoulderLightLevel));
|
||||
}
|
||||
|
||||
private static Optional<Integer> extractFormLightLevel(@NotNull FormData form, boolean underwater) {
|
||||
@@ -83,14 +86,17 @@ public class LambDynamicLightsCompat {
|
||||
}
|
||||
|
||||
ItemStack item = shoulderData.getShownItem();
|
||||
int itemLightLevel = item.isEmpty()?0:LambDynLights.getLuminanceFromItemStack(item, underwater);
|
||||
int itemLightLevel = item.isEmpty() ? 0 :LambDynLights.getLuminanceFromItemStack(item, underwater);
|
||||
int formLightLevel = extractFormLightLevel(shoulderData.getForm(), underwater).orElse(0);
|
||||
|
||||
return Math.max(itemLightLevel, formLightLevel);
|
||||
}
|
||||
|
||||
private static int customHeldItemLightLevel(ItemStack mainhand, ItemStack offhand) {
|
||||
return (mainhand.getItem() instanceof PokedexItem || offhand.getItem() instanceof PokedexItem) ? 13 : 0;
|
||||
}
|
||||
|
||||
private static boolean liquidGlowModeSupport(@NotNull LightingData.LiquidGlowMode liquidGlowMode, boolean underwater) {
|
||||
return underwater ? liquidGlowMode.getGlowsUnderwater() : liquidGlowMode.getGlowsInLand();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.duck;
|
||||
|
||||
public interface ChannelDuck {
|
||||
void cobblemon$applyLowPassFilter(float gain, float hfGain);
|
||||
void cobblemon$inverseAttenuation(float rolloffFactor);
|
||||
void cobblemon$clearFilters();
|
||||
|
||||
// void cobblemon$exponentialAttenuation(float rolloff, float refDistance, float maxDistance);
|
||||
}
|
||||
+6
-4
@@ -6,8 +6,10 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.item
|
||||
package com.cobblemon.mod.common.duck;
|
||||
|
||||
class GalaricaNutItem : CobblemonItem(Properties()) {
|
||||
// Eventually, put some logic here for planting it or something
|
||||
}
|
||||
import net.minecraft.world.item.crafting.RecipeManager;
|
||||
|
||||
public interface RecipeAwareSlot {
|
||||
void setRecipeManager(RecipeManager recipeManager);
|
||||
}
|
||||
@@ -12,14 +12,12 @@ import com.cobblemon.mod.common.block.SaccharineLeafBlock;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
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.Desc;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
import org.spongepowered.asm.mixin.injection.Slice;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@@ -42,8 +40,9 @@ public abstract class BeeEntityMixin {
|
||||
if (block instanceof SaccharineLeafBlock) {
|
||||
|
||||
int age = blockState.getValue(SaccharineLeafBlock.Companion.getAGE());
|
||||
boolean waterlogged = blockState.getValue(BlockStateProperties.WATERLOGGED);
|
||||
|
||||
if (age < 2) {
|
||||
if (age < 2 && !waterlogged) {
|
||||
this.cobblemon$result = blockState.setValue(SaccharineLeafBlock.Companion.getAGE(), age + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.duck.ChannelDuck;
|
||||
import com.mojang.blaze3d.audio.Channel;
|
||||
import org.lwjgl.openal.AL10;
|
||||
import org.lwjgl.openal.EXTEfx;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
@Mixin(Channel.class)
|
||||
public abstract class ChannelMixin implements ChannelDuck {
|
||||
|
||||
@Shadow
|
||||
private int source;
|
||||
|
||||
// Id of filter applied when sound is obstructed
|
||||
private int cobblemon$lowPassFilterId = 0;
|
||||
|
||||
@Override
|
||||
public void cobblemon$applyLowPassFilter(float gain, float hfGain) {
|
||||
// Delete old filter if it exists
|
||||
if (cobblemon$lowPassFilterId != 0) {
|
||||
AL10.alSourcei(source, EXTEfx.AL_DIRECT_FILTER, 0); // Detach filter from source
|
||||
EXTEfx.alDeleteFilters(cobblemon$lowPassFilterId); // Delete old filter
|
||||
cobblemon$lowPassFilterId = 0;
|
||||
}
|
||||
|
||||
// Generate a fresh filter
|
||||
int filterId = EXTEfx.alGenFilters();
|
||||
if (!EXTEfx.alIsFilter(filterId)) {
|
||||
System.err.println("Failed to create OpenAL low-pass filter");
|
||||
return;
|
||||
}
|
||||
|
||||
EXTEfx.alFilteri(filterId, EXTEfx.AL_FILTER_TYPE, EXTEfx.AL_FILTER_LOWPASS);
|
||||
EXTEfx.alFilterf(filterId, EXTEfx.AL_LOWPASS_GAIN, gain);
|
||||
EXTEfx.alFilterf(filterId, EXTEfx.AL_LOWPASS_GAINHF, hfGain);
|
||||
|
||||
AL10.alSourcei(source, EXTEfx.AL_DIRECT_FILTER, filterId);
|
||||
|
||||
// Save the new filter ID
|
||||
cobblemon$lowPassFilterId = filterId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cobblemon$inverseAttenuation(float rolloffFactor) {
|
||||
AL10.alSourcei(source, AL10.AL_DISTANCE_MODEL, AL10.AL_INVERSE_DISTANCE);
|
||||
AL10.alSourcef(source, AL10.AL_ROLLOFF_FACTOR, rolloffFactor);
|
||||
AL10.alSourcef(source, AL10.AL_REFERENCE_DISTANCE, 1.0f);
|
||||
AL10.alSourcef(source, AL10.AL_MAX_DISTANCE, 0.0f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cobblemon$clearFilters() {
|
||||
AL10.alSourcei(source, EXTEfx.AL_DIRECT_FILTER, 0);
|
||||
|
||||
if (EXTEfx.alIsFilter(cobblemon$lowPassFilterId)) {
|
||||
EXTEfx.alDeleteFilters(cobblemon$lowPassFilterId);
|
||||
cobblemon$lowPassFilterId = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
@Mixin(ClientPacketListener.class)
|
||||
public class ClientPacketListenerMixin {
|
||||
|
||||
@Shadow private ClientLevel level;
|
||||
|
||||
@Inject(method = "handleSetEntityPassengersPacket", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/world/entity/Entity;hasIndirectPassenger(Lnet/minecraft/world/entity/Entity;)Z", shift = At.Shift.BEFORE), cancellable = true)
|
||||
private void cobblemon$handlePokemonPassengers(ClientboundSetPassengersPacket packet, CallbackInfo ci) {
|
||||
Entity entity = this.level.getEntity(packet.getVehicle());
|
||||
if (entity instanceof PokemonEntity pokemon) {
|
||||
var passengers = new ArrayList<Entity>();
|
||||
for (int passenger : packet.getPassengers()) {
|
||||
passengers.add(this.level.getEntity(passenger));
|
||||
}
|
||||
Arrays
|
||||
.stream(pokemon.getOccupiedSeats())
|
||||
.filter(x -> !passengers.contains(x))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(Entity::stopRiding);
|
||||
|
||||
var occupiedSeats = Arrays.asList(pokemon.getOccupiedSeats());
|
||||
passengers.stream()
|
||||
.filter(x -> !occupiedSeats.contains(x))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(x -> x.startRiding(pokemon, true));
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import net.minecraft.world.entity.monster.Phantom;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
||||
@Mixin(targets = "net/minecraft/world/entity/monster/Phantom$PhantomSweepAttackGoal")
|
||||
public class EntityPhantomMixin {
|
||||
// TODO: Figure out how to access the outer class that wraps SwoopMovementGoal
|
||||
// Need to find the cat mons that are near the phantom
|
||||
|
||||
// @Inject(method = "shouldContinue", at = @At(value = "RETURN"), cancellable = true)
|
||||
// public void cobblemon$shouldContinue(CallbackInfoReturnable<Boolean> ci) {
|
||||
//// var goalSelectorField = PhantomEntity.class.getClasses();// PhantomEntity.class.getFields();// .class.getDeclaredField("goalSelector");
|
||||
//
|
||||
//// goalSelectorField.setAccessible(true);
|
||||
//// GoalSelector goalSelector = (GoalSelector) goalSelectorField.get(mobEntity);
|
||||
//// final SwoopMovementGoal phantom = (SwoopMovementGoal) (Object) this;
|
||||
//// if(ci.getReturnValue() == false) {
|
||||
//// var result = this$0.getWorld().getEntitiesByClass(
|
||||
//// PokemonEntity.class,
|
||||
//// this$0.getBoundingBox().expand(16.0),
|
||||
//// entity -> {
|
||||
//// return ((PokemonEntity) entity).getBehaviour().getEntityInteract().getAvoidedByPhantom();
|
||||
//// }
|
||||
//// ).isEmpty();
|
||||
////
|
||||
//// ci.setReturnValue(result);
|
||||
//// }
|
||||
// }
|
||||
}
|
||||
|
||||
+22
-11
@@ -9,20 +9,19 @@
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState;
|
||||
import com.cobblemon.mod.common.entity.PosableEntity;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||
import net.minecraft.client.resources.PlayerSkin;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.joml.Vector3f;
|
||||
import org.spongepowered.asm.mixin.Debug;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -30,11 +29,6 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.Map;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||
import net.minecraft.client.resources.PlayerSkin;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
||||
@Mixin(EntityRenderDispatcher.class)
|
||||
public class EntityRenderDispatcherMixin {
|
||||
@@ -77,6 +71,23 @@ public class EntityRenderDispatcherMixin {
|
||||
0F,
|
||||
1F
|
||||
);
|
||||
|
||||
/*if (locator.contains("middle")){
|
||||
PoseStack.Pose pose = poseStack.last();
|
||||
Vector3f vec = matrix.getMatrix().getRotation(new AxisAngle4f()).transform(new Vector3f(0, 0, -1));
|
||||
buffer.addVertex(pose, pos.toVector3f()).setColor(0xffff00ff).setNormal(pose, vec.x, vec.y, vec.z); //Forward, pink
|
||||
buffer.addVertex(pose, (float)(pos.x() + vec.x), (float)(pos.y() + vec.y), (float)(pos.z() + vec.z)).setColor(0xffff00ff).setNormal(pose, vec.x, vec.y, vec.z);
|
||||
|
||||
vec = matrix.getMatrix().getRotation(new AxisAngle4f()).transform(new Vector3f(0, 1, 0));
|
||||
buffer.addVertex(pose, pos.toVector3f()).setColor(0xffffff00).setNormal(pose, vec.x, vec.y, vec.z); //Up, yellow
|
||||
buffer.addVertex(pose, (float)(pos.x() + vec.x), (float)(pos.y() + vec.y), (float)(pos.z() + vec.z)).setColor(0xffffff00).setNormal(pose, vec.x, vec.y, vec.z);
|
||||
|
||||
vec = matrix.getMatrix().getRotation(new AxisAngle4f()).transform(new Vector3f(-1, 0, 0));
|
||||
buffer.addVertex(pose, pos.toVector3f()).setColor(0xff00ffff).setNormal(pose, vec.x, vec.y, vec.z); //Left, cyan
|
||||
buffer.addVertex(pose, (float)(pos.x() + vec.x), (float)(pos.y() + vec.y), (float)(pos.z() + vec.z)).setColor(0xff00ffff).setNormal(pose, vec.x, vec.y, vec.z);
|
||||
}*/
|
||||
|
||||
|
||||
poseStack.popPose();
|
||||
});
|
||||
|
||||
|
||||
@@ -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.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LightningBolt;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Mixin(LightningBolt.class)
|
||||
public abstract class LightningBoltMixin {
|
||||
|
||||
@Inject(method = "spawnFire", at = @At(value = "Head"), cancellable = true)
|
||||
private void cobblemon$spawnFire(int extraIgnitions, CallbackInfo ci) {
|
||||
// This prevents fire from spawning around Pokemon who otherwise should be immune to lightning and effectively absorb the hit
|
||||
final LightningBolt lightningBolt = (LightningBolt) (Object) this;
|
||||
List<Entity> list = lightningBolt.level().getEntities(
|
||||
lightningBolt,
|
||||
new AABB(lightningBolt.getX() - 2.0, lightningBolt.getY() - 2.0, lightningBolt.getZ() - 2.0, lightningBolt.getX() + 2.0, lightningBolt.getY() + 2.0, lightningBolt.getZ() + 2.0),
|
||||
it -> {
|
||||
if (!it.isAlive() || !(it instanceof PokemonEntity)) {
|
||||
return false;
|
||||
}
|
||||
String abilityName = ((PokemonEntity) it).getPokemon().getAbility().getName();
|
||||
return abilityName.equals("lightningrod") || abilityName.equals("voltabsorb") || abilityName.equals("motordrive");
|
||||
});
|
||||
if (!list.isEmpty()) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.OrientationControllable;
|
||||
import com.cobblemon.mod.common.api.orientation.OrientationController;
|
||||
import com.cobblemon.mod.common.api.riding.Seat;
|
||||
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate;
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.client.CameraType;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.ClipContext;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Vector3f;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Mixin(LocalPlayer.class)
|
||||
public abstract class LocalPlayerMixin extends AbstractClientPlayer implements OrientationControllable {
|
||||
@Shadow
|
||||
private float jumpRidingScale;
|
||||
|
||||
public LocalPlayerMixin(ClientLevel clientLevel, GameProfile gameProfile) {
|
||||
super(clientLevel, gameProfile);
|
||||
}
|
||||
|
||||
@Inject(method = "getJumpRidingScale", at = @At("HEAD"), cancellable = true)
|
||||
public void modifyJumpRidingScale(CallbackInfoReturnable<Float> cir) {
|
||||
LocalPlayer player = (LocalPlayer) (Object) this;
|
||||
if (player.isPassenger() && player.getVehicle() instanceof PokemonEntity pokemonEntity) {
|
||||
var rideValue = pokemonEntity.<Float>ifRidingAvailableSupply(null, (behaviour, settings, state) -> {
|
||||
if (behaviour.canJump(settings, state, pokemonEntity, player)) return null;
|
||||
return behaviour.setRideBar(settings, state, pokemonEntity, player);
|
||||
});
|
||||
if (rideValue != null) {
|
||||
cir.setReturnValue(rideValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public HitResult pick(double hitDistance, float partialTicks, boolean hitFluids) {
|
||||
Entity vehicle = this.getVehicle();
|
||||
if (vehicle instanceof PokemonEntity pokemonEntity) {
|
||||
int seatIndex = pokemonEntity.getPassengers().indexOf(this);
|
||||
Seat seat = pokemonEntity.getSeats().get(seatIndex);
|
||||
|
||||
PokemonClientDelegate delegate = (PokemonClientDelegate) pokemonEntity.getDelegate();
|
||||
MatrixWrapper locator = delegate.getLocatorStates().get(seat.getLocator());
|
||||
|
||||
if (locator == null) {
|
||||
super.pick(hitDistance, partialTicks, hitFluids);
|
||||
}
|
||||
|
||||
Vec3 locatorOffset = new Vec3(locator.getMatrix().getTranslation(new Vector3f()));
|
||||
|
||||
OrientationController controller = this.getOrientationController();
|
||||
|
||||
float currEyeHeight = this.getEyeHeight();
|
||||
Vector3f offset = new Vector3f(new Vector3f(0f, currEyeHeight - (this.getBbHeight() / 2), 0f));
|
||||
|
||||
if (Minecraft.getInstance().options.getCameraType() == CameraType.FIRST_PERSON) {
|
||||
PosableModel model = VaryingModelRepository.INSTANCE.getPoser(pokemonEntity.getPokemon().getSpecies().getResourceIdentifier(), new FloatingState());
|
||||
offset.add(cobblemon$getFirstPersonOffset(model, seat));
|
||||
}
|
||||
|
||||
Matrix3f orientation = controller.isActive() && controller.getOrientation() != null ? controller.getOrientation() : new Matrix3f();
|
||||
Vec3 rotatedEyeHeight = new Vec3(orientation.transform(offset));
|
||||
|
||||
Vec3 eyePosition = locatorOffset.add(pokemonEntity.position()).add(rotatedEyeHeight);
|
||||
|
||||
Vec3 viewVector = this.getViewVector(partialTicks);
|
||||
Vec3 viewDistanceVector = eyePosition.add(viewVector.x * hitDistance, viewVector.y * hitDistance, viewVector.z * hitDistance);
|
||||
return this.level()
|
||||
.clip(
|
||||
new ClipContext(
|
||||
eyePosition, viewDistanceVector, ClipContext.Block.OUTLINE, hitFluids ? net.minecraft.world.level.ClipContext.Fluid.ANY : net.minecraft.world.level.ClipContext.Fluid.NONE, this
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return super.pick(hitDistance, partialTicks, hitFluids);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private static @NotNull Vector3f cobblemon$getFirstPersonOffset(PosableModel model, Seat seat) {
|
||||
Map<String, Vec3> cameraOffsets = model.getFirstPersonCameraOffset();
|
||||
|
||||
if (cameraOffsets.containsKey(seat.getLocator())) {
|
||||
return cameraOffsets.get(seat.getLocator()).toVector3f();
|
||||
} else {
|
||||
return new Vector3f(0f, 0f, 0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.pokemon.ai.EntityBehaviour;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.ai.goal.Goal;
|
||||
import net.minecraft.world.entity.monster.Phantom;
|
||||
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;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
|
||||
|
||||
@Mixin(targets = "net.minecraft.world.entity.monster.Phantom$PhantomSweepAttackGoal")
|
||||
public abstract class PhantomSweepAttackGoalMixin extends Goal {
|
||||
|
||||
@Unique
|
||||
private Phantom phantomSelf; // Allows access to the outer class
|
||||
|
||||
@Inject(method = "<init>", at = @At("TAIL"))
|
||||
private void onInit(Phantom phantom, CallbackInfo ci) {
|
||||
this.phantomSelf = phantom;
|
||||
}
|
||||
|
||||
@Inject(method = "canContinueToUse", at = @At("RETURN"), cancellable = true)
|
||||
private void modifyCanContinueToUse(CallbackInfoReturnable<Boolean> cir) {
|
||||
Phantom phantom = this.phantomSelf; // Outer class instance
|
||||
if(phantom == null) return;
|
||||
|
||||
if (cir.getReturnValue()) {
|
||||
var nearbyFearedEntities = phantom.level().getEntities(phantom, phantom.getBoundingBox().inflate(16.0),
|
||||
(entity -> ((entity instanceof PokemonEntity && ((PokemonEntity) entity).getBeamMode() == 0 && ((PokemonEntity) entity).getBehaviour().getEntityInteract().getAvoidedByPhantom())
|
||||
|| (entity instanceof ServerPlayer && EntityBehaviour.Companion.hasPhantomFearedShoulderMount((ServerPlayer)entity)))));
|
||||
if (!nearbyFearedEntities.isEmpty()) {
|
||||
nearbyFearedEntities.forEach(entity -> {
|
||||
if (entity instanceof PokemonEntity) {
|
||||
((PokemonEntity) entity).cry();
|
||||
}
|
||||
//TODO: Find a way to make shoulder mounted Pokemon cry
|
||||
});
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
@Mixin(ServerLevel.class)
|
||||
public abstract class ServerLevelMixin {
|
||||
|
||||
@Inject(method = "findLightningRod", at = @At(value = "RETURN"), cancellable = true)
|
||||
private void cobblemon$findLightningRod(BlockPos blockPos, CallbackInfoReturnable<Optional<BlockPos>> ci) {
|
||||
final ServerLevel serverLevel = (ServerLevel) (Object) this;
|
||||
if (ci.getReturnValue().isEmpty()) {
|
||||
// Search for Pokemon with the ability Lightning Rod and redirect to them
|
||||
AABB aABB = AABB.encapsulatingFullBlocks(blockPos, new BlockPos(blockPos.atY(serverLevel.getMaxBuildHeight()))).inflate(64.0);
|
||||
List<LivingEntity> list = serverLevel.getEntitiesOfClass(LivingEntity.class, aABB, (livingEntity) -> livingEntity != null
|
||||
&& livingEntity.isAlive()
|
||||
&& livingEntity instanceof PokemonEntity
|
||||
&& ((PokemonEntity) livingEntity).getBeamMode() == 0
|
||||
&& ((PokemonEntity) livingEntity).getPokemon().getAbility().getName().equals("lightningrod"));
|
||||
if (!list.isEmpty()) {
|
||||
ci.setReturnValue(Optional.of((list.get(serverLevel.random.nextInt(list.size()))).blockPosition()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.block.HeartyGrainsBlock;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.DoublePlantBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
import net.minecraft.world.level.levelgen.feature.SimpleBlockFeature;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.SimpleBlockConfiguration;
|
||||
import org.spongepowered.asm.mixin.Debug;
|
||||
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(SimpleBlockFeature.class)
|
||||
@Debug(export = true, print = true)
|
||||
public class SimpleBlockFeatureMixin {
|
||||
//this mixin inserts the logic needed to ensure that when hearty grains are of a certain age, they place with the upper block too
|
||||
//similarly to what the doubleblock logic is here
|
||||
@Inject(method = "place", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;canSurvive(Lnet/minecraft/world/level/LevelReader;Lnet/minecraft/core/BlockPos;)Z", shift = At.Shift.AFTER), cancellable = true)
|
||||
public void place(FeaturePlaceContext<SimpleBlockConfiguration> context, CallbackInfoReturnable<Boolean> cir,
|
||||
@Local BlockState blockState, @Local BlockPos blockPos, @Local WorldGenLevel worldGenLevel) {
|
||||
if (!(blockState.getBlock() instanceof HeartyGrainsBlock)) {
|
||||
return;
|
||||
}
|
||||
if (blockState.getValue(HeartyGrainsBlock.Companion.getAGE()) <= HeartyGrainsBlock.AGE_AFTER_HARVEST) {
|
||||
return; //block is too young to be double
|
||||
}
|
||||
if (!worldGenLevel.isEmptyBlock(blockPos.above())) {
|
||||
cir.setReturnValue(false); //no space for the 2nd block above
|
||||
return;
|
||||
}
|
||||
DoublePlantBlock.placeAt(worldGenLevel, blockState, blockPos, Block.UPDATE_CLIENTS);
|
||||
cir.setReturnValue(true);
|
||||
}
|
||||
}
|
||||
@@ -8,23 +8,33 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.api.riding.sound.RideAttenuationModel;
|
||||
import com.cobblemon.mod.common.api.riding.sound.RideLoopSound;
|
||||
import com.cobblemon.mod.common.client.sound.BattleMusicController;
|
||||
import com.cobblemon.mod.common.duck.ChannelDuck;
|
||||
import com.cobblemon.mod.common.duck.SoundEngineDuck;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import com.mojang.blaze3d.audio.Channel;
|
||||
import net.minecraft.client.resources.sounds.Sound;
|
||||
import net.minecraft.client.resources.sounds.SoundInstance;
|
||||
import net.minecraft.client.resources.sounds.TickableSoundInstance;
|
||||
import net.minecraft.client.sounds.ChannelAccess;
|
||||
import net.minecraft.client.sounds.SoundEngine;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
@Mixin(SoundEngine.class)
|
||||
@@ -45,6 +55,86 @@ public abstract class SoundEngineMixin implements SoundEngineDuck {
|
||||
@Shadow
|
||||
public abstract boolean isActive(SoundInstance sound);
|
||||
|
||||
@Inject(method = "play",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/sounds/ChannelAccess$ChannelHandle;execute(Ljava/util/function/Consumer;)V"
|
||||
),
|
||||
cancellable = true
|
||||
)
|
||||
private void cobblemon$overrideChannelExecute(
|
||||
SoundInstance sound,
|
||||
CallbackInfo ci,
|
||||
@Local(name = "h") float h,
|
||||
@Local(name = "i") float i,
|
||||
@Local(name = "g") float g,
|
||||
@Local(name = "bl2") boolean bl2,
|
||||
@Local(name = "bl3") boolean bl3,
|
||||
@Local(name = "bl") boolean bl,
|
||||
@Local(name = "vec3") Vec3 vec3,
|
||||
@Local(name = "channelHandle") ChannelAccess.ChannelHandle handle
|
||||
) {
|
||||
if (!(sound instanceof RideLoopSound rideSound)) return;
|
||||
|
||||
if (handle == null) return;
|
||||
|
||||
handle.execute((channel) -> {
|
||||
channel.setPitch(i);
|
||||
channel.setVolume(h);
|
||||
|
||||
if (rideSound.getRideAttenuation() == RideAttenuationModel.LINEAR) {
|
||||
channel.linearAttenuation(g);
|
||||
} else if (rideSound.getRideAttenuation() == RideAttenuationModel.EXPONENTIAL){
|
||||
((ChannelDuck) channel).cobblemon$inverseAttenuation(g);
|
||||
} else {
|
||||
channel.disableAttenuation();
|
||||
}
|
||||
|
||||
// Apply low pass filter if the rideSound dictate that it should be muffled
|
||||
if (rideSound.getShouldMuffle()) {
|
||||
((ChannelDuck) channel).cobblemon$applyLowPassFilter(1.0f, rideSound.getMuffleAmount());
|
||||
} else {
|
||||
((ChannelDuck) channel).cobblemon$clearFilters();
|
||||
}
|
||||
|
||||
channel.setLooping(bl2 && !bl3);
|
||||
channel.setSelfPosition(vec3);
|
||||
channel.setRelative(bl);
|
||||
});
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "tickNonPaused",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/sounds/ChannelAccess$ChannelHandle;execute(Ljava/util/function/Consumer;)V",
|
||||
ordinal = 0
|
||||
)
|
||||
)
|
||||
private void cobblemon$tickableSoundTick(
|
||||
CallbackInfo ci,
|
||||
@Local(name = "tickableSoundInstance") TickableSoundInstance instance,
|
||||
@Local(name = "channelHandle", ordinal = 0) ChannelAccess.ChannelHandle handle,
|
||||
@Local(name = "f", ordinal = 0) float volume,
|
||||
@Local(name = "g", ordinal = 0) float pitch,
|
||||
@Local(name = "vec3", ordinal = 0) Vec3 vec3
|
||||
) {
|
||||
if (!(instance instanceof RideLoopSound rideSound)) return;
|
||||
|
||||
handle.execute(channel -> {
|
||||
channel.setVolume(volume);
|
||||
channel.setPitch(pitch);
|
||||
channel.setSelfPosition(vec3);
|
||||
|
||||
// Apply low pass filter if the rideSound dictate that it should be muffled
|
||||
if (rideSound.getShouldMuffle()) {
|
||||
((ChannelDuck) channel).cobblemon$applyLowPassFilter(1.0f, rideSound.getMuffleAmount());
|
||||
} else {
|
||||
((ChannelDuck) channel).cobblemon$clearFilters();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Resumes the Source belonging to the queried SoundInstance. */
|
||||
private void resume(SoundInstance sound) {
|
||||
ChannelAccess.ChannelHandle sourceManager = this.instanceToChannel.get(sound);
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.world.CobblemonStructureIDs;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.RandomState;
|
||||
import net.minecraft.world.level.levelgen.structure.Structure;
|
||||
import net.minecraft.world.level.levelgen.structure.StructurePiece;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
|
||||
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.CallbackInfoReturnable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@Mixin(Structure.class)
|
||||
public abstract class StructureMixin {
|
||||
// Define a set of structures that should not spawn below Sea Level
|
||||
@Unique
|
||||
private static final Set<ResourceLocation> RESTRICTED_STRUCTURES = new HashSet<>(Arrays.asList(
|
||||
CobblemonStructureIDs.STONJOURNER_HENGE,
|
||||
CobblemonStructureIDs.LUNA_HENGE,
|
||||
CobblemonStructureIDs.SOL_HENGE
|
||||
));
|
||||
|
||||
@Inject(method = "generate", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/structure/StructureStart;isValid()Z"),
|
||||
cancellable = true)
|
||||
public void cobblemon$isValid(RegistryAccess registryAccess, ChunkGenerator chunkGenerator, BiomeSource biomeSource,
|
||||
RandomState randomState, StructureTemplateManager structureTemplateManager, long seed,
|
||||
ChunkPos chunkPos, int references, LevelHeightAccessor heightAccessor,
|
||||
Predicate<Holder<Biome>> validBiome,
|
||||
CallbackInfoReturnable<StructureStart> cir,
|
||||
@Local StructureStart structureStart) {
|
||||
ResourceLocation structureKey = registryAccess.registryOrThrow(Registries.STRUCTURE).getKey((Structure) (Object) this);
|
||||
if(!RESTRICTED_STRUCTURES.contains(structureKey)) {
|
||||
return;
|
||||
}
|
||||
for (StructurePiece piece : structureStart.getPieces()) {
|
||||
if (piece.getBoundingBox().minY() < chunkGenerator.getSeaLevel()) {
|
||||
cir.setReturnValue(StructureStart.INVALID_START);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+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.mixin.brewing;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonRecipeTypes;
|
||||
import com.cobblemon.mod.common.item.crafting.brewingstand.BrewingStandInput;
|
||||
import com.cobblemon.mod.common.item.crafting.brewingstand.BrewingStandRecipe;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.world.Containers;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.alchemy.PotionBrewing;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.item.crafting.RecipeManager;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.LevelEvent;
|
||||
import net.minecraft.world.level.block.entity.BrewingStandBlockEntity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@Mixin(BrewingStandBlockEntity.class)
|
||||
public class BrewingStandBlockEntityMixin {
|
||||
|
||||
@WrapOperation(method = "serverTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/BrewingStandBlockEntity;doBrew(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/NonNullList;)V"))
|
||||
private static void cobblemon$doBrew(Level level, BlockPos pos, NonNullList<ItemStack> slots, Operation<Void> original) {
|
||||
var recipe = cobblemon$fetchBrewingRecipe(slots, level);
|
||||
if(recipe == null) {
|
||||
original.call(level, pos, slots);
|
||||
return;
|
||||
}
|
||||
//copied from vanilla doBrew logic, but slightly tweaked to work for cobblemon, this was needed as replacing the loop was not quite possible inside doBrew
|
||||
ItemStack itemStack = slots.get(3);
|
||||
for(int i = 0; i < 3; ++i) {
|
||||
slots.set(i, recipe.getResult().copy());
|
||||
}
|
||||
|
||||
itemStack.shrink(1);
|
||||
if (itemStack.getItem().hasCraftingRemainingItem()) {
|
||||
ItemStack itemStack2 = new ItemStack(itemStack.getItem().getCraftingRemainingItem());
|
||||
if (itemStack.isEmpty()) {
|
||||
itemStack = itemStack2;
|
||||
} else {
|
||||
Containers.dropItemStack(level, pos.getX(), pos.getY(), pos.getZ(), itemStack2);
|
||||
}
|
||||
}
|
||||
|
||||
slots.set(3, itemStack);
|
||||
level.levelEvent(LevelEvent.SOUND_BREWING_STAND_BREW, pos, 0);
|
||||
}
|
||||
|
||||
@WrapOperation(method = "serverTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/BrewingStandBlockEntity;isBrewable(Lnet/minecraft/world/item/alchemy/PotionBrewing;Lnet/minecraft/core/NonNullList;)Z"))
|
||||
private static boolean cobblemon$isBrewable(PotionBrewing potionBrewing, NonNullList<ItemStack> items, Operation<Boolean> original,
|
||||
@Local(argsOnly = true) Level level) {
|
||||
return cobblemon$fetchBrewingRecipe(items, level) != null || original.call(potionBrewing, items);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private static BrewingStandRecipe cobblemon$fetchBrewingRecipe(NonNullList<ItemStack> items, Level level) {
|
||||
ItemStack ingredient = items.get(3);
|
||||
List<ItemStack> bottles = items.subList(0, 3);
|
||||
|
||||
boolean allBottlesEmpty = true;
|
||||
for (ItemStack bottle : bottles) {
|
||||
if (!bottle.isEmpty()) {
|
||||
allBottlesEmpty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ingredient.isEmpty() || allBottlesEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BrewingStandInput input = new BrewingStandInput(ingredient, bottles);
|
||||
RecipeManager recipeManager = level.getRecipeManager();
|
||||
|
||||
Optional<RecipeHolder<BrewingStandRecipe>> recipeHolder =
|
||||
recipeManager.getRecipeFor(CobblemonRecipeTypes.INSTANCE.getBREWING_STAND(), input, level);
|
||||
|
||||
return recipeHolder.map(RecipeHolder::value).orElse(null);
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.brewing;
|
||||
|
||||
import com.cobblemon.mod.common.duck.RecipeAwareSlot;
|
||||
import com.cobblemon.mod.common.item.crafting.brewingstand.BrewingStandRecipe;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.BrewingStandMenu;
|
||||
import net.minecraft.world.inventory.ContainerData;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.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(BrewingStandMenu.class)
|
||||
public abstract class BrewingStandMenuMixin {
|
||||
|
||||
@Inject(method = "<init>(ILnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/world/Container;Lnet/minecraft/world/inventory/ContainerData;)V", at = @At("TAIL"))
|
||||
private void captureLevel(int containerId, Inventory playerInventory, Container brewingStandContainer, ContainerData brewingStandData, CallbackInfo ci) {
|
||||
var recipeManager = playerInventory.player.level().getRecipeManager();
|
||||
for (Slot slot : ((BrewingStandMenu) (Object) this).slots) {
|
||||
if (slot instanceof RecipeAwareSlot awareSlot) {
|
||||
awareSlot.setRecipeManager(recipeManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@WrapOperation(method = "quickMoveStack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/BrewingStandMenu$PotionSlot;mayPlaceItem(Lnet/minecraft/world/item/ItemStack;)Z"))
|
||||
private boolean cobblemon$isPotionBottle(ItemStack stack, Operation<Boolean> original, @Local(argsOnly = true) Player player) {
|
||||
return BrewingStandRecipe.Companion.isBottle(stack, player.level().getRecipeManager()) || original.call(stack);
|
||||
}
|
||||
}
|
||||
@@ -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.mixin.brewing;
|
||||
|
||||
import com.cobblemon.mod.common.duck.RecipeAwareSlot;
|
||||
import com.cobblemon.mod.common.item.crafting.brewingstand.BrewingStandRecipe;
|
||||
import net.minecraft.world.inventory.BrewingStandMenu;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeManager;
|
||||
import net.minecraft.world.level.Level;
|
||||
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.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(BrewingStandMenu.IngredientsSlot.class)
|
||||
public class IngredientSlotMixin implements RecipeAwareSlot {
|
||||
|
||||
@Unique
|
||||
private RecipeManager cobblemon$recipeManager;
|
||||
|
||||
@Override
|
||||
public void setRecipeManager(RecipeManager recipeManager) {
|
||||
this.cobblemon$recipeManager = recipeManager;
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "mayPlace",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true
|
||||
)
|
||||
private void cobblemon$mayPlace(ItemStack stack, CallbackInfoReturnable<Boolean> cir) {
|
||||
if (BrewingStandRecipe.Companion.isInput(stack, cobblemon$recipeManager)) {
|
||||
cir.setReturnValue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.mixin.brewing;
|
||||
|
||||
import com.cobblemon.mod.common.duck.RecipeAwareSlot;
|
||||
import com.cobblemon.mod.common.item.crafting.brewingstand.BrewingStandRecipe;
|
||||
import net.minecraft.world.inventory.BrewingStandMenu;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeManager;
|
||||
import net.minecraft.world.level.Level;
|
||||
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.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(BrewingStandMenu.PotionSlot.class)
|
||||
public class PotionSlotMixin implements RecipeAwareSlot {
|
||||
|
||||
@Unique
|
||||
private RecipeManager cobblemon$recipeManager;
|
||||
|
||||
@Override
|
||||
public void setRecipeManager(RecipeManager recipeManager) {
|
||||
this.cobblemon$recipeManager = recipeManager;
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "mayPlace",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true
|
||||
)
|
||||
private void cobblemon$mayPlace(ItemStack stack, CallbackInfoReturnable<Boolean> cir) {
|
||||
if (BrewingStandRecipe.Companion.isBottle(stack, cobblemon$recipeManager)) {
|
||||
cir.setReturnValue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-10
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.mixin.client;
|
||||
import com.cobblemon.mod.common.CobblemonRecipeCategories;
|
||||
import com.cobblemon.mod.common.item.crafting.CookingPotBookCategory;
|
||||
import com.cobblemon.mod.common.item.crafting.CookingPotRecipe;
|
||||
import com.cobblemon.mod.common.item.crafting.CookingPotRecipeBase;
|
||||
import com.cobblemon.mod.common.item.crafting.CookingPotShapelessRecipe;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
@@ -19,7 +20,6 @@ import net.minecraft.client.ClientRecipeBook;
|
||||
import net.minecraft.client.RecipeBookCategories;
|
||||
import net.minecraft.client.gui.screens.recipebook.RecipeCollection;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
|
||||
import net.minecraft.world.item.crafting.Recipe;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -40,23 +40,23 @@ public abstract class ClientRecipeBookMixin {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Shadow private Map<RecipeBookCategories, List<RecipeCollection>> collectionsByTab;
|
||||
@Shadow
|
||||
private Map<RecipeBookCategories, List<RecipeCollection>> collectionsByTab;
|
||||
|
||||
@Shadow private List<RecipeCollection> allCollections;
|
||||
@Shadow
|
||||
private List<RecipeCollection> allCollections;
|
||||
|
||||
@Inject(method = "getCategory", at = @At(value = "HEAD"), cancellable = true)
|
||||
private static void addCustomCategory(RecipeHolder<?> recipe, CallbackInfoReturnable<RecipeBookCategories> cir) {
|
||||
Recipe<?> recipe2 = recipe.value();
|
||||
if (recipe2 instanceof CookingPotRecipe || recipe2 instanceof CookingPotShapelessRecipe) {
|
||||
CookingPotBookCategory category = recipe2 instanceof CookingPotRecipe
|
||||
? ((CookingPotRecipe) recipe2).getCategory()
|
||||
: ((CookingPotShapelessRecipe) recipe2).category();
|
||||
if (recipe2 instanceof CookingPotRecipeBase) {
|
||||
CookingPotBookCategory category = ((CookingPotRecipeBase) recipe2).getCategory();
|
||||
RecipeBookCategories var7;
|
||||
switch (category) {
|
||||
case MISC -> var7 = CobblemonRecipeCategories.COOKING_POT_MISC.toVanillaCategory();
|
||||
case FOODS -> var7 = CobblemonRecipeCategories.COOKING_POT_FOODS.toVanillaCategory();
|
||||
case MEDICINES -> var7 = CobblemonRecipeCategories.COOKING_POT_MEDICINES.toVanillaCategory();
|
||||
case BAITS -> var7 = CobblemonRecipeCategories.COOKING_POT_BAITS.toVanillaCategory();
|
||||
case COMPLEX_DISHES -> var7 = CobblemonRecipeCategories.COOKING_POT_COMPLEX_DISHES.toVanillaCategory();
|
||||
default -> throw new MatchException(null, null);
|
||||
}
|
||||
cir.setReturnValue(var7);
|
||||
@@ -76,8 +76,8 @@ public abstract class ClientRecipeBookMixin {
|
||||
.collect(ImmutableList.toImmutableList());
|
||||
map2.put(recipeBookCategories, collections);
|
||||
});
|
||||
RecipeBookCategories.AGGREGATE_CATEGORIES.forEach((recipeBookCategories, list) -> map2.put(recipeBookCategories, (List)list.stream().flatMap((recipeBookCategoriesx) -> ((List)map2.getOrDefault(recipeBookCategoriesx, ImmutableList.of())).stream()).collect(ImmutableList.toImmutableList())));
|
||||
CobblemonRecipeCategories.Companion.getCustomAggregateCategories().forEach((recipeBookCategories, list) -> map2.put(recipeBookCategories, (List)list.stream().flatMap((recipeBookCategoriesx) -> ((List)map2.getOrDefault(recipeBookCategoriesx, ImmutableList.of())).stream()).collect(ImmutableList.toImmutableList())));
|
||||
RecipeBookCategories.AGGREGATE_CATEGORIES.forEach((recipeBookCategories, list) -> map2.put(recipeBookCategories, (List) list.stream().flatMap((recipeBookCategoriesx) -> ((List) map2.getOrDefault(recipeBookCategoriesx, ImmutableList.of())).stream()).collect(ImmutableList.toImmutableList())));
|
||||
CobblemonRecipeCategories.Companion.getCustomAggregateCategories().forEach((recipeBookCategories, list) -> map2.put(recipeBookCategories, (List) list.stream().flatMap((recipeBookCategoriesx) -> ((List) map2.getOrDefault(recipeBookCategoriesx, ImmutableList.of())).stream()).collect(ImmutableList.toImmutableList())));
|
||||
|
||||
this.collectionsByTab = ImmutableMap.copyOf(map2);
|
||||
this.allCollections = builder.build();
|
||||
|
||||
+5
-6
@@ -9,22 +9,21 @@
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.gui.ScrollingWidget;
|
||||
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||
import net.minecraft.client.gui.components.AbstractSelectionList;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.Constant;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyConstant;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
||||
@Mixin(AbstractSelectionList.class)
|
||||
public abstract class EntryListWidgetMixin {
|
||||
|
||||
@SuppressWarnings("ConstantValue")
|
||||
@ModifyConstant(method = "getEntryAtPosition", constant = @Constant(intValue = 4))
|
||||
public int cobblemon$adjustOnlyIfNecessary(int input) {
|
||||
@ModifyExpressionValue(method = "getEntryAtPosition", at = @At(value = "CONSTANT", args = {"intValue=4"}))
|
||||
public int cobblemon$adjustOnlyIfNecessary(int original) {
|
||||
if(ScrollingWidget.class.isInstance(this)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return input;
|
||||
return original;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,27 +10,51 @@ package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork;
|
||||
import com.cobblemon.mod.common.OrientationControllable;
|
||||
import com.cobblemon.mod.common.api.orientation.OrientationController;
|
||||
import com.cobblemon.mod.common.api.riding.Seat;
|
||||
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate;
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.net.messages.server.orientation.ServerboundUpdateOrientationPacket;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.client.CameraType;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.level.ClipContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Vector3f;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Mixin(LocalPlayer.class)
|
||||
public abstract class LocalPlayerMixin extends LivingEntity {
|
||||
public abstract class LocalPlayerMixin extends AbstractClientPlayer implements OrientationControllable{
|
||||
|
||||
@Unique Matrix3f cobblemon$lastOrientation;
|
||||
|
||||
protected LocalPlayerMixin(EntityType<? extends LivingEntity> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
@Shadow
|
||||
private float jumpRidingScale;
|
||||
|
||||
public LocalPlayerMixin(ClientLevel clientLevel, GameProfile gameProfile) {
|
||||
super(clientLevel, gameProfile);
|
||||
}
|
||||
|
||||
// @Inject(method = "sendPosition", at = @At("TAIL"))
|
||||
@@ -76,4 +100,71 @@ public abstract class LocalPlayerMixin extends LivingEntity {
|
||||
if (!(this instanceof OrientationControllable controllable)) return;
|
||||
controllable.getOrientationController().setActive(false);
|
||||
}
|
||||
|
||||
@Inject(method = "getJumpRidingScale", at = @At("HEAD"), cancellable = true)
|
||||
public void modifyJumpRidingScale(CallbackInfoReturnable<Float> cir) {
|
||||
LocalPlayer player = (LocalPlayer) (Object) this;
|
||||
if (player.isPassenger() && player.getVehicle() instanceof PokemonEntity pokemonEntity) {
|
||||
var rideValue = pokemonEntity.<Float>ifRidingAvailableSupply(null, (behaviour, settings, state) -> {
|
||||
if (behaviour.canJump(settings, state, pokemonEntity, player)) return null;
|
||||
return behaviour.setRideBar(settings, state, pokemonEntity, player);
|
||||
});
|
||||
if (rideValue != null) {
|
||||
cir.setReturnValue(rideValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public HitResult pick(double hitDistance, float partialTicks, boolean hitFluids) {
|
||||
Entity vehicle = this.getVehicle();
|
||||
if (vehicle instanceof PokemonEntity pokemonEntity) {
|
||||
PokemonClientDelegate delegate = (PokemonClientDelegate) pokemonEntity.getDelegate();
|
||||
String locatorName = delegate.getSeatLocator(this);
|
||||
MatrixWrapper locator = delegate.getLocatorStates().get(locatorName);
|
||||
|
||||
if (locator == null) {
|
||||
return super.pick(hitDistance, partialTicks, hitFluids);
|
||||
}
|
||||
|
||||
Vec3 locatorOffset = new Vec3(locator.getMatrix().getTranslation(new Vector3f()));
|
||||
|
||||
OrientationController controller = this.getOrientationController();
|
||||
|
||||
float currEyeHeight = this.getEyeHeight();
|
||||
Vector3f offset = new Vector3f(new Vector3f(0f, currEyeHeight - (this.getBbHeight() / 2), 0f));
|
||||
|
||||
if (Minecraft.getInstance().options.getCameraType() == CameraType.FIRST_PERSON) {
|
||||
PosableModel model = VaryingModelRepository.INSTANCE.getPoser(pokemonEntity.getPokemon().getSpecies().getResourceIdentifier(), new FloatingState());
|
||||
offset.add(cobblemon$getFirstPersonOffset(model, locatorName));
|
||||
}
|
||||
|
||||
Matrix3f orientation = controller.isActive() && controller.getOrientation() != null ? controller.getOrientation() : new Matrix3f();
|
||||
Vec3 rotatedEyeHeight = new Vec3(orientation.transform(offset));
|
||||
|
||||
Vec3 eyePosition = locatorOffset.add(pokemonEntity.position()).add(rotatedEyeHeight);
|
||||
|
||||
Vec3 viewVector = this.getViewVector(partialTicks);
|
||||
Vec3 viewDistanceVector = eyePosition.add(viewVector.x * hitDistance, viewVector.y * hitDistance, viewVector.z * hitDistance);
|
||||
return this.level()
|
||||
.clip(
|
||||
new ClipContext(
|
||||
eyePosition, viewDistanceVector, ClipContext.Block.OUTLINE, hitFluids ? net.minecraft.world.level.ClipContext.Fluid.ANY : net.minecraft.world.level.ClipContext.Fluid.NONE, this
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return super.pick(hitDistance, partialTicks, hitFluids);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private static @NotNull Vector3f cobblemon$getFirstPersonOffset(PosableModel model, String locatorName) {
|
||||
Map<String, Vec3> cameraOffsets = model.getFirstPersonCameraOffset();
|
||||
|
||||
if (cameraOffsets.containsKey(locatorName)) {
|
||||
return cameraOffsets.get(locatorName).toVector3f();
|
||||
} else {
|
||||
return new Vector3f(0f, 0f, 0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(MouseHandler.class)
|
||||
public abstract class MouseHandlerMixin {
|
||||
@@ -121,11 +120,12 @@ public abstract class MouseHandlerMixin {
|
||||
if (usageContext.getScanningGuiOpen()) {
|
||||
this.smoothTurnY.reset();
|
||||
this.smoothTurnX.reset();
|
||||
var defaultSensitivity = this.minecraft.options.sensitivity().get() * 0.6000000238418579 + 0.20000000298023224;
|
||||
var defaultSensitivity = this.minecraft.options.sensitivity().get() * 0.6 + 0.2;
|
||||
var spyglassSensitivity = Math.pow(defaultSensitivity, 3);
|
||||
var lookSensitivity = spyglassSensitivity * 8.0;
|
||||
var sensitivity = Mth.lerp(usageContext.getFovMultiplier(), spyglassSensitivity, lookSensitivity);
|
||||
player.turn(this.accumulatedDX * sensitivity, (this.accumulatedDY * sensitivity));
|
||||
var yRotationFlip = this.minecraft.options.invertYMouse().get() ? -1 : 1;
|
||||
player.turn(this.accumulatedDX * sensitivity, (this.accumulatedDY * sensitivity * yRotationFlip));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -50,10 +50,10 @@ public class RecipeBookCategoriesMixin {
|
||||
private static void cobblemon$addRecipeBookType(CallbackInfo ci) {
|
||||
ArrayList<RecipeBookCategories> types = new ArrayList<>(List.of($VALUES));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_SEARCH", $VALUES.length, new ItemStack(Items.COMPASS)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_FOODS", $VALUES.length + 1, new ItemStack(CobblemonItems.ROASTED_LEEK)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_MEDICINES", $VALUES.length + 2, new ItemStack(CobblemonItems.HP_UP)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_BAITS", $VALUES.length + 3, new ItemStack(CobblemonItems.PERSIM_BERRY)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_MISC", $VALUES.length + 4, new ItemStack(CobblemonItems.MIRROR_HERB)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_FOODS", $VALUES.length + 1, new ItemStack(CobblemonItems.LEEK_AND_POTATO_STEW)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_MEDICINES", $VALUES.length + 2, new ItemStack(CobblemonItems.POTION)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_COMPLEX_DISHES", $VALUES.length + 3, new ItemStack(CobblemonItems.POKE_PUFF)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_MISC", $VALUES.length + 4, new ItemStack(CobblemonItems.PROTEIN)));
|
||||
$VALUES = types.toArray(RecipeBookCategories[]::new);
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ public class RecipeBookCategoriesMixin {
|
||||
CobblemonRecipeCategories.COOKING_POT_SEARCH.toVanillaCategory(),
|
||||
CobblemonRecipeCategories.COOKING_POT_FOODS.toVanillaCategory(),
|
||||
CobblemonRecipeCategories.COOKING_POT_MEDICINES.toVanillaCategory(),
|
||||
CobblemonRecipeCategories.COOKING_POT_BAITS.toVanillaCategory(),
|
||||
CobblemonRecipeCategories.COOKING_POT_COMPLEX_DISHES.toVanillaCategory(),
|
||||
CobblemonRecipeCategories.COOKING_POT_MISC.toVanillaCategory());
|
||||
cir.setReturnValue(var10000);
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.client;
|
||||
|
||||
import net.minecraft.client.searchtree.IdSearchTree;
|
||||
import net.minecraft.client.searchtree.SearchTree;
|
||||
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.CallbackInfoReturnable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Mixin(IdSearchTree.class)
|
||||
public abstract class SearchTreeMixin {
|
||||
@Unique
|
||||
private static final ThreadLocal<Boolean> reentryFlag = ThreadLocal.withInitial(() -> false);
|
||||
|
||||
/**
|
||||
* Runs an additional search using the original search term where every instance of 'e' is replaced with 'é'
|
||||
* Appends additional search results to original search results.
|
||||
*/
|
||||
@Inject(method = "search(Ljava/lang/String;)Ljava/util/List;", at = @At("RETURN"), cancellable = true)
|
||||
private void onSearch(String string, CallbackInfoReturnable<List> cir) {
|
||||
// If flag is true, skip to avoid infinite loop
|
||||
if (reentryFlag.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
reentryFlag.set(true);
|
||||
List originalResults = cir.getReturnValue();
|
||||
|
||||
if (!string.contains("poke")) {
|
||||
return;
|
||||
}
|
||||
|
||||
String modifiedString = string.replace("poke", "poké");
|
||||
List additionalResults = ((SearchTree)this).search(modifiedString);
|
||||
|
||||
Set combinedSet = new LinkedHashSet<>();
|
||||
combinedSet.addAll(originalResults);
|
||||
combinedSet.addAll(additionalResults);
|
||||
|
||||
cir.setReturnValue(new ArrayList<>(combinedSet));
|
||||
} finally {
|
||||
reentryFlag.set(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
+72
@@ -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.mixin.client.snapshots;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBuildDetails;
|
||||
import com.cobblemon.mod.common.client.gui.snapshots.SnapshotWarningScreen;
|
||||
import com.cobblemon.mod.common.client.snapshots.SnapshotAcknowledgementData;
|
||||
import com.cobblemon.mod.common.client.snapshots.SnapshotAcknowledgementReader;
|
||||
import kotlin.Unit;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
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;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Mixin(Minecraft.class)
|
||||
public final class SnapshotWarningMixin {
|
||||
|
||||
@Unique
|
||||
private final Pattern VERSION = Pattern.compile("^(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)$");
|
||||
|
||||
@Inject(method = "addInitialScreens", at = @At("TAIL"))
|
||||
public void cobblemon$addSnapshotWarningScreen(List<Function<Runnable, Screen>> output, CallbackInfo callback) {
|
||||
if (CobblemonBuildDetails.SNAPSHOT && !this.cobblemon$isAcknowledged() && !SharedConstants.IS_RUNNING_IN_IDE) {
|
||||
output.add((runnable) -> new SnapshotWarningScreen((acknowledgement, dsa) -> {
|
||||
if (acknowledgement == SnapshotWarningScreen.Acknowledgement.NO) {
|
||||
Minecraft.getInstance().stop();
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
|
||||
SnapshotAcknowledgementReader.INSTANCE.write(new SnapshotAcknowledgementData(CobblemonBuildDetails.VERSION, dsa));
|
||||
|
||||
runnable.run();
|
||||
return Unit.INSTANCE;
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Unique
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
private boolean cobblemon$isAcknowledged() {
|
||||
SnapshotAcknowledgementData data = SnapshotAcknowledgementReader.INSTANCE.read();
|
||||
if (data == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Matcher current = VERSION.matcher(CobblemonBuildDetails.VERSION);
|
||||
current.find();
|
||||
|
||||
Matcher when = VERSION.matcher(data.getVersion());
|
||||
when.find();
|
||||
|
||||
boolean alert = current.group("minor").compareTo(when.group("minor")) > 0 || current.group("major").compareTo(when.group("major")) > 0;
|
||||
return !alert && data.getDontShowAgain();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -40,9 +40,9 @@ import com.cobblemon.mod.common.api.properties.CustomPokemonProperty
|
||||
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
|
||||
import com.cobblemon.mod.common.api.spawning.prospecting.SpawningProspector
|
||||
import com.cobblemon.mod.common.api.spawning.CobblemonSpawningZoneGenerator
|
||||
import com.cobblemon.mod.common.api.spawning.position.AreaSpawnablePositionResolver
|
||||
import com.cobblemon.mod.common.api.spawning.SpawningZoneGenerator
|
||||
import com.cobblemon.mod.common.api.starter.StarterHandler
|
||||
import com.cobblemon.mod.common.api.storage.PokemonStoreManager
|
||||
import com.cobblemon.mod.common.api.storage.adapter.conversions.ReforgedConversion
|
||||
@@ -63,13 +63,10 @@ import com.cobblemon.mod.common.api.storage.player.adapter.PlayerDataMongoBacken
|
||||
import com.cobblemon.mod.common.api.storage.player.factory.CachedPlayerDataStoreFactory
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonEntityTypeTags
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.battles.BagItems
|
||||
import com.cobblemon.mod.common.battles.BattleFormat
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
import com.cobblemon.mod.common.battles.BattleSide
|
||||
import com.cobblemon.mod.common.battles.ShowdownThread
|
||||
import com.cobblemon.mod.common.battles.*
|
||||
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.block.DispenserBehaviorRegistry
|
||||
import com.cobblemon.mod.common.client.CobblemonPack
|
||||
import com.cobblemon.mod.common.command.argument.*
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
@@ -78,6 +75,7 @@ import com.cobblemon.mod.common.config.constraint.IntConstraint
|
||||
import com.cobblemon.mod.common.config.starter.StarterConfig
|
||||
import com.cobblemon.mod.common.data.CobblemonDataProvider
|
||||
import com.cobblemon.mod.common.events.AdvancementHandler
|
||||
import com.cobblemon.mod.common.events.EntityCallbackHandler
|
||||
import com.cobblemon.mod.common.events.FlowHandler
|
||||
import com.cobblemon.mod.common.events.PokedexHandler
|
||||
import com.cobblemon.mod.common.events.ServerTickHandler
|
||||
@@ -91,23 +89,11 @@ import com.cobblemon.mod.common.pokemon.aspects.SHINY_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.BlockClickEvolution
|
||||
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.pokemon.properties.AspectPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.BattleCloneProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.FreezeFrameProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.HiddenAbilityPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.NoAIProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.UnaspectPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.*
|
||||
import com.cobblemon.mod.common.pokemon.properties.tags.PokemonFlagProperty
|
||||
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
|
||||
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.ifDedicatedServer
|
||||
import com.cobblemon.mod.common.util.isLaterVersion
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import com.cobblemon.mod.common.util.requestWallpapers
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.world.feature.CobblemonPlacedFeatures
|
||||
import com.cobblemon.mod.common.world.feature.ore.CobblemonOrePlacedFeatures
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
@@ -115,20 +101,8 @@ 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 java.util.concurrent.TimeUnit
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.properties.Delegates
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import kotlin.reflect.jvm.javaField
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.commands.synchronization.SingletonArgumentInfo
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
@@ -139,6 +113,17 @@ import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.storage.LevelResource
|
||||
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 java.util.concurrent.TimeUnit
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.properties.Delegates
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import kotlin.reflect.jvm.javaField
|
||||
|
||||
object Cobblemon {
|
||||
const val MODID = CobblemonBuildDetails.MOD_ID
|
||||
@@ -160,8 +145,8 @@ object Cobblemon {
|
||||
var isDedicatedServer = false
|
||||
val showdownThread = ShowdownThread()
|
||||
lateinit var config: CobblemonConfig
|
||||
var prospector: SpawningProspector = CobblemonSpawningProspector
|
||||
var areaContextResolver: AreaContextResolver = object : AreaContextResolver {}
|
||||
var spawningZoneGenerator: SpawningZoneGenerator = CobblemonSpawningZoneGenerator
|
||||
var areaSpawnablePositionResolver: AreaSpawnablePositionResolver = object : AreaSpawnablePositionResolver {}
|
||||
val bestSpawner = BestSpawner
|
||||
val battleRegistry = BattleRegistry
|
||||
var storage = PokemonStoreManager()
|
||||
@@ -213,6 +198,7 @@ object Cobblemon {
|
||||
implementation.registerEntityDataSerializers()
|
||||
implementation.registerCriteria()
|
||||
implementation.registerEntitySubPredicates()
|
||||
DispenserBehaviorRegistry.registerDispenserBehaviors()
|
||||
|
||||
DropEntry.register("command", CommandDropEntry::class.java)
|
||||
DropEntry.register("item", ItemDropEntry::class.java, isDefault = true)
|
||||
@@ -312,9 +298,6 @@ object Cobblemon {
|
||||
SpeciesFeatures.types["flag"] = FlagSpeciesFeatureProvider::class.java
|
||||
SpeciesFeatures.types["integer"] = IntSpeciesFeatureProvider::class.java
|
||||
|
||||
SpeciesFeatures.register(
|
||||
DataKeys.CAN_BE_MILKED,
|
||||
FlagSpeciesFeatureProvider(keys = listOf(DataKeys.CAN_BE_MILKED), default = true))
|
||||
SpeciesFeatures.register(
|
||||
DataKeys.HAS_BEEN_SHEARED,
|
||||
FlagSpeciesFeatureProvider(keys = listOf(DataKeys.HAS_BEEN_SHEARED), default = false))
|
||||
@@ -331,6 +314,7 @@ object Cobblemon {
|
||||
CobblemonEvents.POKEMON_PROPERTY_INITIALISED.emit(Unit)
|
||||
|
||||
FlowHandler.setup()
|
||||
EntityCallbackHandler.setup()
|
||||
|
||||
ifDedicatedServer {
|
||||
isDedicatedServer = true
|
||||
|
||||
@@ -18,6 +18,8 @@ object CobblemonActivities {
|
||||
val POKEMON_SLEEPING_ACTIVITY = register(Activity("pokemon_sleeping"))
|
||||
val POKEMON_GROW_CROP = register(Activity("pokemon_grow_crop"))
|
||||
val POKEMON_SLEEP_ON_TRAINER_BED = register(Activity("pokemon_sleep_on_trainer_bed"))
|
||||
val POKEMON_HERD = register(Activity("pokemon_herd"))
|
||||
val POKEMON_POLLINATION = register(Activity("pokemon_pollination"))
|
||||
|
||||
fun register(activity: Activity): Activity {
|
||||
activities.add(activity)
|
||||
|
||||
@@ -25,6 +25,8 @@ import com.cobblemon.mod.common.util.adapters.ExpressionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionOrEntityVariableAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.MemoryModuleTypeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.SensorTypeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.TaskConfigAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.TranslatedTextAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
@@ -39,6 +41,8 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.server.packs.resources.ResourceManager
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
object CobblemonBehaviours : JsonDataRegistry<CobblemonBehaviour> {
|
||||
@@ -47,6 +51,8 @@ object CobblemonBehaviours : JsonDataRegistry<CobblemonBehaviour> {
|
||||
.registerTypeAdapter(Activity::class.java, ActivityAdapter)
|
||||
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(MemoryModuleType::class.java, MemoryModuleTypeAdapter)
|
||||
.registerTypeAdapter(SensorType::class.java, SensorTypeAdapter)
|
||||
.registerTypeAdapter(BehaviourConfig::class.java, BehaviourConfigAdapter)
|
||||
.registerTypeAdapter(TaskConfig::class.java, TaskConfigAdapter)
|
||||
.registerTypeAdapter(
|
||||
@@ -72,6 +78,9 @@ object CobblemonBehaviours : JsonDataRegistry<CobblemonBehaviour> {
|
||||
*/
|
||||
val autoPokemonBehaviours = mutableListOf<CobblemonBehaviour>()
|
||||
|
||||
/** See [autoPokemonBehaviours] but think npc instead of pokemon*/
|
||||
val autoNPCBehaviours = mutableListOf<CobblemonBehaviour>()
|
||||
|
||||
val behaviours = mutableMapOf<ResourceLocation, CobblemonBehaviour>()
|
||||
|
||||
override fun sync(player: ServerPlayer) {
|
||||
@@ -88,6 +97,8 @@ object CobblemonBehaviours : JsonDataRegistry<CobblemonBehaviour> {
|
||||
val behaviour = parse(reader, resolvedIdentifier)
|
||||
if ("pokemon/auto/" in identifier.path) {
|
||||
autoPokemonBehaviours.add(behaviour)
|
||||
} else if ("npc/auto/" in identifier.path) {
|
||||
autoNPCBehaviours.add(behaviour)
|
||||
}
|
||||
data[resolvedIdentifier] = behaviour
|
||||
}
|
||||
|
||||
@@ -15,10 +15,14 @@ import com.cobblemon.mod.common.block.LecternBlock
|
||||
import com.cobblemon.mod.common.block.MintBlock.MintType
|
||||
import com.cobblemon.mod.common.block.campfirepot.CampfirePotBlock
|
||||
import com.cobblemon.mod.common.block.chest.GildedChestBlock
|
||||
import com.cobblemon.mod.common.block.general.BaleBlock
|
||||
import com.cobblemon.mod.common.block.grower.SaccharineTreeGrower
|
||||
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 com.cobblemon.mod.common.block.general.HorizontalRotationCarpetBlock
|
||||
import com.cobblemon.mod.common.block.general.HorizontalRotationalBlock
|
||||
import com.cobblemon.mod.common.mixin.invoker.*
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
@@ -172,14 +176,14 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val SACCHARINE_LOG = this.create("saccharine_log", SaccharineLogBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava()))
|
||||
@JvmField
|
||||
val SACCHARINE_HONEY_LOG = this.create("saccharine_honey_log", SaccharineHoneyLogBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava()))
|
||||
val SACCHARINE_LOG_SLATHERED = this.create("saccharine_log_slathered", SaccharineLogSlatheredBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava()))
|
||||
|
||||
@JvmField
|
||||
val STRIPPED_SACCHARINE_LOG = this.create("stripped_saccharine_log", SaccharineStrippedLogBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava())) //log("stripped_saccharine_log")
|
||||
val STRIPPED_SACCHARINE_LOG = this.create("stripped_saccharine_log", RotatedPillarBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava())) //log("stripped_saccharine_log")
|
||||
@JvmField
|
||||
val SACCHARINE_WOOD = log("saccharine_wood")
|
||||
@JvmField
|
||||
val STRIPPED_SACCHARINE_WOOD = this.create("stripped_saccharine_wood", SaccharineStrippedLogBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava())) //log("stripped_saccharine_log")
|
||||
val STRIPPED_SACCHARINE_WOOD = this.create("stripped_saccharine_wood", RotatedPillarBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava())) //log("stripped_saccharine_log")
|
||||
@JvmField
|
||||
val SACCHARINE_PLANKS = this.create("saccharine_planks", Block(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
|
||||
@JvmField
|
||||
@@ -201,7 +205,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
val SACCHARINE_FENCE = this.create("saccharine_fence", FenceBlock(BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
|
||||
@JvmField
|
||||
val SACCHARINE_FENCE_GATE = this.create("saccharine_fence_gate", FenceGateBlock(SACCHARINE_WOOD_TYPE, BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
|
||||
|
||||
@JvmField
|
||||
val SACCHARINE_BUTTON = this.create("saccharine_button", BlocksInvoker.createWoodenButtonBlock(BlockSetType.OAK))
|
||||
@JvmField
|
||||
val SACCHARINE_PRESSURE_PLATE = this.create("saccharine_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(SACCHARINE_BLOCK_SET_TYPE, BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).noCollission().strength(0.5f).sound(SoundType.WOOD)))
|
||||
@@ -222,7 +226,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val SACCHARINE_TRAPDOOR = this.create("saccharine_trapdoor", TrapdoorBlockInvoker.`cobblemon$create`(SACCHARINE_BLOCK_SET_TYPE, BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).strength(3.0F).sound(SoundType.WOOD).noOcclusion()))
|
||||
@JvmField
|
||||
val SACCHARINE_SAPLING = this.create("saccharine_sapling", SaccharineSaplingBlock(PLANT_PROPERTIES))
|
||||
val SACCHARINE_SAPLING = this.create("saccharine_sapling", SaplingBlock(SaccharineTreeGrower(), PLANT_PROPERTIES))
|
||||
|
||||
@JvmField
|
||||
val MEDICINAL_LEEK = this.create("medicinal_leek", MedicinalLeekBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).ignitedByLava().mapColor(MapColor.CRIMSON_NYLIUM).noCollission().randomTicks().instabreak().sound(CobblemonSounds.MEDICINAL_LEEK_SOUNDS)))
|
||||
@@ -446,7 +450,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
|
||||
@JvmField
|
||||
val CAMPFIRE = create("campfire", CampfireBlock(BlockBehaviour.Properties.of().sound(SoundType.WOOD).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.PODZOL).strength(2.0F).lightLevel { if ((it.getValue(CampfireBlock.SOUL) as Boolean)) 9 else 14 }))
|
||||
|
||||
|
||||
@JvmField
|
||||
val RELIC_COIN_POUCH = create("relic_coin_pouch", CoinPouchBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.RELIC_COIN_POUCH_SOUNDS).pushReaction(PushReaction.DESTROY).noOcclusion(), true))
|
||||
@JvmField
|
||||
@@ -470,29 +474,29 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
val GIMMIGHOUL_CHEST = create("gimmighoul_chest", GildedChestBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS), GildedChestBlock.Type.FAKE))
|
||||
|
||||
@JvmField
|
||||
val MONITOR = create("monitor", MonitorBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).lightLevel { if (it.getValue(MonitorBlock.SCREEN) != MonitorBlock.MonitorScreen.OFF) 15 else 0 }))
|
||||
val MONITOR = create("monitor", MonitorBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).lightLevel { if (it.getValue(MonitorBlock.SCREEN) != MonitorBlock.MonitorScreen.OFF) 13 else 0 }))
|
||||
@JvmField
|
||||
val FOSSIL_ANALYZER = create("fossil_analyzer", FossilAnalyzerBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).noOcclusion()))
|
||||
@JvmField
|
||||
val RESTORATION_TANK = create("restoration_tank", RestorationTankBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.GLASS).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).noOcclusion()))
|
||||
|
||||
@JvmField
|
||||
val HEALING_MACHINE = create("healing_machine", HealingMachineBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2f).noOcclusion().lightLevel { if (it.getValue(HealingMachineBlock.CHARGE_LEVEL) >= HealingMachineBlock.MAX_CHARGE_LEVEL) 7 else 2 }))
|
||||
val HEALING_MACHINE = create("healing_machine", HealingMachineBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2f).noOcclusion().lightLevel { if (it.getValue(HealingMachineBlock.CHARGE_LEVEL) >= HealingMachineBlock.MAX_CHARGE_LEVEL) 12 else 5 }))
|
||||
|
||||
@JvmField
|
||||
val PC = create("pc", PCBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F).noOcclusion().lightLevel { if ((it.getValue(PCBlock.ON) as Boolean) && (it.getValue(PCBlock.PART) == PCBlock.PCPart.TOP)) 10 else 0 }))
|
||||
val PC = create("pc", PCBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F).noOcclusion().lightLevel { if ((it.getValue(PCBlock.ON) as Boolean) && (it.getValue(PCBlock.PART) == PCBlock.PCPart.TOP)) 13 else 0 }))
|
||||
|
||||
@JvmField
|
||||
val LECTERN = create("lectern", LecternBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).sound(SoundType.WOOD).strength(2.5F).ignitedByLava()))
|
||||
val LECTERN = create("lectern", LecternBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).sound(SoundType.WOOD).strength(2.5F).ignitedByLava().lightLevel { if (it.getValue(LecternBlock.EMIT_LIGHT) as Boolean) 13 else 0 }))
|
||||
|
||||
@JvmField
|
||||
val DISPLAY_CASE = create("display_case", DisplayCaseBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.DISPLAY_CASE_SOUNDS).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.STONE).strength(0.3F)))
|
||||
val DISPLAY_CASE = create("display_case", DisplayCaseBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.DISPLAY_CASE_SOUNDS).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.STONE).strength(0.3F).requiresCorrectToolForDrops()))
|
||||
|
||||
@JvmField
|
||||
val INCENSE_SWEET = create("incense_sweet", SweetIncenseBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.DISPLAY_CASE_SOUNDS).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.STONE).strength(0.3f)))
|
||||
|
||||
@JvmField
|
||||
val PASTURE = create("pasture", PastureBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BROWN).sound(SoundType.WOOD).strength(2F).noOcclusion().pushReaction(PushReaction.BLOCK).lightLevel { if ((it.getValue(PastureBlock.ON) as Boolean) && (it.getValue(PastureBlock.PART) == PastureBlock.PasturePart.TOP)) 10 else 0 }))
|
||||
val PASTURE = create("pasture", PastureBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BROWN).sound(SoundType.WOOD).strength(2F).noOcclusion().pushReaction(PushReaction.BLOCK).lightLevel { if ((it.getValue(PastureBlock.ON) as Boolean) && (it.getValue(PastureBlock.PART) == PastureBlock.PasturePart.TOP)) 13 else 0 }))
|
||||
|
||||
val RED_MINT = create("red_mint", MintBlock(MintType.RED, BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_RED).noCollission().randomTicks().instabreak().sound(CobblemonSounds.MINT_SOUNDS).pushReaction(PushReaction.DESTROY)))
|
||||
@JvmField
|
||||
@@ -515,6 +519,33 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val HEARTY_GRAINS = this.create("hearty_grains", HeartyGrainsBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).ignitedByLava().mapColor(MapColor.PLANT).noCollission().randomTicks().instabreak().sound(CobblemonSounds.VIVICHOKE_SOUNDS)))
|
||||
|
||||
@JvmField
|
||||
val GALARICA_NUT_BUSH = this.create("galarica_nut_bush", NutBushBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).randomTicks().noCollission().sound(SoundType.SWEET_BERRY_BUSH).pushReaction(PushReaction.DESTROY)))
|
||||
|
||||
@JvmField
|
||||
val POTTED_RED_APRICORN_SAPLING = this.create("potted_red_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(RED_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_YELLOW_APRICORN_SAPLING = this.create("potted_yellow_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(YELLOW_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_GREEN_APRICORN_SAPLING = this.create("potted_green_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(GREEN_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_BLUE_APRICORN_SAPLING = this.create("potted_blue_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(BLUE_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_PINK_APRICORN_SAPLING = this.create("potted_pink_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(PINK_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_BLACK_APRICORN_SAPLING = this.create("potted_black_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(BLACK_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_WHITE_APRICORN_SAPLING = this.create("potted_white_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(WHITE_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_SACCHARINE_SAPLING = this.create("potted_saccharine_sapling", BlocksInvoker.createFlowerPotBlock(SACCHARINE_SAPLING))
|
||||
|
||||
@JvmField
|
||||
val HEARTY_GRAIN_BALE = this.create("hearty_grain_bale", BaleBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).instrument(NoteBlockInstrument.BANJO).strength(0.5F).sound(SoundType.GRASS)))
|
||||
@JvmField
|
||||
val TATAMI_BLOCK = this.create("tatami_block", HorizontalRotationalBlock(BlockBehaviour.Properties.of().ignitedByLava().mapColor(MapColor.PLANT).strength(0.1F).sound(SoundType.MOSS_CARPET)))
|
||||
@JvmField
|
||||
val TATAMI_MAT = this.create("tatami_mat", HorizontalRotationCarpetBlock(BlockBehaviour.Properties.of().ignitedByLava().mapColor(MapColor.PLANT).strength(0.1F).sound(SoundType.MOSS_CARPET)))
|
||||
|
||||
/**
|
||||
* Returns a map of all the blocks that can be stripped with an axe in the format of input - output.
|
||||
*
|
||||
@@ -525,11 +556,9 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
APRICORN_LOG to STRIPPED_APRICORN_LOG,
|
||||
SACCHARINE_WOOD to STRIPPED_SACCHARINE_WOOD,
|
||||
SACCHARINE_LOG to STRIPPED_SACCHARINE_LOG,
|
||||
SACCHARINE_HONEY_LOG to STRIPPED_SACCHARINE_LOG
|
||||
SACCHARINE_LOG_SLATHERED to STRIPPED_SACCHARINE_LOG
|
||||
)
|
||||
|
||||
|
||||
|
||||
private fun apricornBlock(name: String, apricorn: Apricorn): ApricornBlock = this.create(name, ApricornBlock(BlockBehaviour.Properties.of().mapColor(apricorn.mapColor()).randomTicks().strength(Blocks.OAK_LOG.defaultDestroyTime(), Blocks.OAK_LOG.explosionResistance).sound(SoundType.WOOD).noOcclusion(), apricorn))
|
||||
|
||||
private fun tumblestoneBlock(name: String, stage: Int, height: Int, xzOffset: Int, nextStage: Block?) : Block {
|
||||
@@ -629,7 +658,19 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
Triple(APRICORN_FENCE, 5, 20),
|
||||
Triple(APRICORN_FENCE_GATE, 5, 20),
|
||||
Triple(APRICORN_SLAB, 5, 20),
|
||||
Triple(APRICORN_STAIRS, 5, 20)
|
||||
Triple(APRICORN_STAIRS, 5, 20),
|
||||
Triple(SACCHARINE_LOG, 5, 5),
|
||||
Triple(SACCHARINE_LOG_SLATHERED, 5, 5),
|
||||
Triple(STRIPPED_SACCHARINE_LOG, 5, 5),
|
||||
Triple(SACCHARINE_WOOD, 5, 5),
|
||||
Triple(STRIPPED_SACCHARINE_WOOD, 5, 5),
|
||||
Triple(SACCHARINE_PLANKS, 5, 20),
|
||||
Triple(SACCHARINE_LEAVES, 30, 60),
|
||||
Triple(SACCHARINE_FENCE, 5, 20),
|
||||
Triple(SACCHARINE_FENCE_GATE, 5, 20),
|
||||
Triple(SACCHARINE_SLAB, 5, 20),
|
||||
Triple(SACCHARINE_STAIRS, 5, 20)
|
||||
|
||||
).onEach{ data -> setFlammable(data.first, data.second, data.third) }
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,8 @@ object CobblemonCommands {
|
||||
MarkGiveCommand.register(dispatcher)
|
||||
MarkTakeCommand.register(dispatcher)
|
||||
MarkGiveAllCommand.register(dispatcher)
|
||||
PcSearchCommand.register(dispatcher)
|
||||
PcTakeCommand.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
|
||||
|
||||
@@ -93,6 +93,8 @@ object CobblemonFlows : DataRegistry {
|
||||
functions: Map<String, (MoParams) -> Any> = emptyMap(),
|
||||
cancelable: Cancelable? = null
|
||||
) {
|
||||
if (eventResourceLocation !in flows) return
|
||||
|
||||
if (cancelable == null) {
|
||||
runtime.environment.query.functions.remove("cancel")
|
||||
} else {
|
||||
|
||||
@@ -8,18 +8,14 @@
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.block.PotComponent
|
||||
import com.cobblemon.mod.common.item.components.BaitEffectsComponent
|
||||
import com.cobblemon.mod.common.item.components.FlavourComponent
|
||||
import com.cobblemon.mod.common.item.components.FoodColourComponent
|
||||
import com.cobblemon.mod.common.item.components.HeldItemCapableComponent
|
||||
import com.cobblemon.mod.common.item.components.PokemonItemComponent
|
||||
import com.cobblemon.mod.common.item.components.RodBaitComponent
|
||||
import com.cobblemon.mod.common.item.components.*
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import com.mojang.serialization.Codec
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.core.component.DataComponentType
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.network.codec.ByteBufCodecs
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
@@ -60,6 +56,25 @@ object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>
|
||||
.networkSynchronized(FoodColourComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
val INGREDIENT: DataComponentType<IngredientComponent> = create("ingredient", DataComponentType.builder<IngredientComponent>()
|
||||
.persistent(IngredientComponent.CODEC)
|
||||
.networkSynchronized(IngredientComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
val FOOD: DataComponentType<FoodComponent> = create("food", DataComponentType.builder<FoodComponent>()
|
||||
.persistent(FoodComponent.CODEC)
|
||||
.networkSynchronized(FoodComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
val MOB_EFFECTS: DataComponentType<MobEffectsComponent> = create("mob_effects", DataComponentType.builder<MobEffectsComponent>()
|
||||
.persistent(MobEffectsComponent.CODEC)
|
||||
.networkSynchronized(MobEffectsComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
val CRAFTED: DataComponentType<Boolean> = create("crafted", DataComponentType.builder<Boolean>()
|
||||
.persistent(Codec.BOOL)
|
||||
.networkSynchronized(ByteBufCodecs.BOOL)
|
||||
.build())
|
||||
|
||||
fun register() {
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:pokemon_item"), POKEMON_ITEM)
|
||||
@@ -68,6 +83,9 @@ object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:bait_effects"), BAIT_EFFECTS)
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:flavour"), FLAVOUR)
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:food_colour"), FOOD_COLOUR)
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:ingredient"), INGREDIENT)
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:food"), FOOD)
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:mob_effects"), MOB_EFFECTS)
|
||||
}
|
||||
|
||||
override val registry = BuiltInRegistries.DATA_COMPONENT_TYPE
|
||||
|
||||
@@ -13,6 +13,7 @@ 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
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
import com.cobblemon.mod.common.api.text.blue
|
||||
@@ -34,10 +35,13 @@ import com.cobblemon.mod.common.item.berry.PPRestoringBerryItem
|
||||
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.food.PonigiriItem
|
||||
import com.cobblemon.mod.common.item.food.SinisterTeaItem
|
||||
import com.cobblemon.mod.common.item.interactive.*
|
||||
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.IVs
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.core.Registry
|
||||
@@ -53,6 +57,8 @@ import net.minecraft.world.food.FoodProperties
|
||||
import net.minecraft.world.item.BlockItem
|
||||
import net.minecraft.world.item.HangingSignItem
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.Item.Properties
|
||||
import net.minecraft.world.item.ItemNameBlockItem
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.item.Rarity
|
||||
@@ -186,28 +192,35 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
|
||||
val campfire_pots = mutableListOf<CampfirePotItem>()
|
||||
@JvmField
|
||||
val CAMPFIRE_POT_BLACK = campfirePotItem(CobblemonBlocks.BLACK_CAMPFIRE_POT, "black")
|
||||
val CAMPFIRE_POT_RED = campfirePotItem(CobblemonBlocks.RED_CAMPFIRE_POT, "red")
|
||||
@JvmField
|
||||
val CAMPFIRE_POT_BLUE = campfirePotItem(CobblemonBlocks.BLUE_CAMPFIRE_POT, "blue")
|
||||
val CAMPFIRE_POT_YELLOW = campfirePotItem(CobblemonBlocks.YELLOW_CAMPFIRE_POT, "yellow")
|
||||
@JvmField
|
||||
val CAMPFIRE_POT_GREEN = campfirePotItem(CobblemonBlocks.GREEN_CAMPFIRE_POT, "green")
|
||||
@JvmField
|
||||
val CAMPFIRE_POT_BLUE = campfirePotItem(CobblemonBlocks.BLUE_CAMPFIRE_POT, "blue")
|
||||
@JvmField
|
||||
val CAMPFIRE_POT_PINK = campfirePotItem(CobblemonBlocks.PINK_CAMPFIRE_POT, "pink")
|
||||
@JvmField
|
||||
val CAMPFIRE_POT_RED = campfirePotItem(CobblemonBlocks.RED_CAMPFIRE_POT, "red")
|
||||
val CAMPFIRE_POT_BLACK = campfirePotItem(CobblemonBlocks.BLACK_CAMPFIRE_POT, "black")
|
||||
@JvmField
|
||||
val CAMPFIRE_POT_WHITE = campfirePotItem(CobblemonBlocks.WHITE_CAMPFIRE_POT, "white")
|
||||
@JvmField
|
||||
val CAMPFIRE_POT_YELLOW = campfirePotItem(CobblemonBlocks.YELLOW_CAMPFIRE_POT, "yellow")
|
||||
|
||||
@JvmField
|
||||
val Hearty_Grains = compostableItem("hearty_grains", HeartyGrainsItem(CobblemonBlocks.HEARTY_GRAINS))
|
||||
val HEARTY_GRAINS = compostableItem("hearty_grains", ItemNameBlockItem(CobblemonBlocks.HEARTY_GRAINS, Properties().rarity(Rarity.COMMON)))
|
||||
@JvmField
|
||||
val HEARTY_GRAIN_BALE = compostableBlockItem("hearty_grain_bale", CobblemonBlocks.HEARTY_GRAIN_BALE, 0.85f)
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE = compostableItem("vivichoke")
|
||||
val TATAMI_BLOCK = blockItem("tatami_block", CobblemonBlocks.TATAMI_BLOCK)
|
||||
@JvmField
|
||||
val TATAMI_MAT = blockItem("tatami_mat", CobblemonBlocks.TATAMI_MAT)
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE_SEEDS = compostableItem("vivichoke_seeds", VivichokeItem(CobblemonBlocks.VIVICHOKE_SEEDS))
|
||||
val VIVICHOKE = compostableItem("vivichoke", CobblemonItem(Item.Properties()), 0.80f)
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE_SEEDS = compostableItem("vivichoke_seeds", VivichokeItem(CobblemonBlocks.VIVICHOKE_SEEDS), 0.30f)
|
||||
|
||||
@JvmField
|
||||
val RED_APRICORN = apricornItem("red", ApricornItem(CobblemonBlocks.RED_APRICORN))
|
||||
@@ -250,7 +263,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val APRICORN_PLANKS = blockItem("apricorn_planks", CobblemonBlocks.APRICORN_PLANKS)
|
||||
@JvmField
|
||||
val APRICORN_LEAVES = compostableBlockItem("apricorn_leaves", CobblemonBlocks.APRICORN_LEAVES)
|
||||
val APRICORN_LEAVES = compostableBlockItem("apricorn_leaves", CobblemonBlocks.APRICORN_LEAVES, 0.30f)
|
||||
@JvmField
|
||||
val APRICORN_BOAT = create("apricorn_boat", CobblemonBoatItem(CobblemonBoatType.APRICORN, false, Item.Properties().stacksTo(1)))
|
||||
@JvmField
|
||||
@@ -297,7 +310,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val SACCHARINE_LOG = blockItem("saccharine_log", CobblemonBlocks.SACCHARINE_LOG)
|
||||
@JvmField
|
||||
val SACCHARINE_HONEY_LOG = blockItem("saccharine_honey_log", CobblemonBlocks.SACCHARINE_HONEY_LOG)
|
||||
val SACCHARINE_LOG_SLATHERED = blockItem("saccharine_log_slathered", CobblemonBlocks.SACCHARINE_LOG_SLATHERED)
|
||||
@JvmField
|
||||
val STRIPPED_SACCHARINE_LOG = blockItem("stripped_saccharine_log", CobblemonBlocks.STRIPPED_SACCHARINE_LOG)
|
||||
@JvmField
|
||||
@@ -307,7 +320,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val SACCHARINE_PLANKS = blockItem("saccharine_planks", CobblemonBlocks.SACCHARINE_PLANKS)
|
||||
@JvmField
|
||||
val SACCHARINE_LEAVES = compostableBlockItem("saccharine_leaves", CobblemonBlocks.SACCHARINE_LEAVES)
|
||||
val SACCHARINE_LEAVES = compostableBlockItem("saccharine_leaves", CobblemonBlocks.SACCHARINE_LEAVES, 0.35f)
|
||||
@JvmField
|
||||
val SACCHARINE_BOAT = create("saccharine_boat", CobblemonBoatItem(CobblemonBoatType.SACCHARINE, false, Item.Properties().stacksTo(1)))
|
||||
@JvmField
|
||||
@@ -334,10 +347,10 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val SACCHARINE_HANGING_SIGN = this.create("saccharine_hanging_sign", HangingSignItem(CobblemonBlocks.SACCHARINE_HANGING_SIGN, CobblemonBlocks.SACCHARINE_WALL_HANGING_SIGN, Item.Properties().stacksTo(16)))
|
||||
@JvmField
|
||||
val SACCHARINE_SAPLING = saccharineSaplingItem("saccharine_sapling", SaccharineSaplingItem(CobblemonBlocks.SACCHARINE_SAPLING))
|
||||
val SACCHARINE_SAPLING = compostableBlockItem("saccharine_sapling", CobblemonBlocks.SACCHARINE_SAPLING, 0.30f)
|
||||
|
||||
@JvmField
|
||||
val BUGWORT = bugwortItem("bugwort", BugwortItem(CobblemonBlocks.BUGWORT))
|
||||
val BUGWORT = compostableBlockItem("bugwort", CobblemonBlocks.BUGWORT)
|
||||
@JvmField
|
||||
val POKE_BAIT = noSettingsItem("poke_bait")
|
||||
|
||||
@@ -348,260 +361,85 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
|
||||
val aprijuices = mutableListOf<AprijuiceItem>()
|
||||
@JvmField
|
||||
val APRIJUICE_BLACK = aprijuiceItem(Apricorn.BLACK)
|
||||
@JvmField
|
||||
val APRIJUICE_RED = aprijuiceItem(Apricorn.RED)
|
||||
@JvmField
|
||||
val APRIJUICE_BLUE = aprijuiceItem(Apricorn.BLUE)
|
||||
@JvmField
|
||||
val APRIJUICE_GREEN = aprijuiceItem(Apricorn.GREEN)
|
||||
@JvmField
|
||||
val APRIJUICE_YELLOW = aprijuiceItem(Apricorn.YELLOW)
|
||||
@JvmField
|
||||
val APRIJUICE_WHITE = aprijuiceItem(Apricorn.WHITE)
|
||||
val APRIJUICE_GREEN = aprijuiceItem(Apricorn.GREEN)
|
||||
@JvmField
|
||||
val APRIJUICE_BLUE = aprijuiceItem(Apricorn.BLUE)
|
||||
@JvmField
|
||||
val APRIJUICE_PINK = aprijuiceItem(Apricorn.PINK)
|
||||
@JvmField
|
||||
val APRIJUICE_BLACK = aprijuiceItem(Apricorn.BLACK)
|
||||
@JvmField
|
||||
val APRIJUICE_WHITE = aprijuiceItem(Apricorn.WHITE)
|
||||
|
||||
@JvmField
|
||||
val POKE_PUFF = noSettingsItem("poke_puff") // todo make a PokePuffItem class for friendship boosting purposes
|
||||
val PONIGIRI = create("ponigiri", PonigiriItem())
|
||||
|
||||
@JvmField
|
||||
val SINISTER_TEA = create("sinister_tea", SinisterTeaItem())
|
||||
|
||||
@JvmField
|
||||
val POKE_PUFF = pokepuffItem("poke_puff")
|
||||
|
||||
// FOODS
|
||||
@JvmField
|
||||
val SWEET_HEART = noSettingsItem("sweet_heart") // todo make a SweetHeartItem class for breeding purposes
|
||||
|
||||
@JvmField
|
||||
val PEWTER_CRUNCHIES = create("pewter_crunchies", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10)
|
||||
.saturationModifier(1.2F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.build())) {
|
||||
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
|
||||
user.removeAllEffects()
|
||||
return super.finishUsingItem(stack, world, user)
|
||||
}
|
||||
})
|
||||
val TASTY_TAIL = create("tasty_tail", foodItem(3, 0.3f))
|
||||
|
||||
@JvmField
|
||||
val RAGE_CANDY_BAR = create("rage_candy_bar", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10)
|
||||
.saturationModifier(1.2F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.build())) {
|
||||
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
|
||||
user.removeAllEffects()
|
||||
return super.finishUsingItem(stack, world, user)
|
||||
}
|
||||
})
|
||||
|
||||
val PEWTER_CRUNCHIES = regionalFoodItem("pewter_crunchies", 16, 7, 0.343f, false)
|
||||
@JvmField
|
||||
val LAVA_COOKIE = create("lava_cookie", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10)
|
||||
.saturationModifier(1.2F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.build())) {
|
||||
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
|
||||
user.removeAllEffects()
|
||||
return super.finishUsingItem(stack, world, user)
|
||||
}
|
||||
})
|
||||
|
||||
val RAGE_CANDY_BAR = regionalFoodItem("rage_candy_bar", 16, 8, 0.2f, false)
|
||||
@JvmField
|
||||
val OLD_GATEAU = create("old_gateau", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10)
|
||||
.saturationModifier(1.2F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.build())) {
|
||||
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
|
||||
user.removeAllEffects()
|
||||
return super.finishUsingItem(stack, world, user)
|
||||
}
|
||||
})
|
||||
|
||||
val LAVA_COOKIE = regionalFoodItem("lava_cookie", 16, 7, 0.343f, false)
|
||||
@JvmField
|
||||
val CASTELIACONE = create("casteliacone", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10)
|
||||
.saturationModifier(1.2F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.build())) {
|
||||
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
|
||||
user.removeAllEffects()
|
||||
return super.finishUsingItem(stack, world, user)
|
||||
}
|
||||
})
|
||||
|
||||
val OLD_GATEAU = regionalFoodItem("old_gateau", 16, 9, 0.1335f, false)
|
||||
@JvmField
|
||||
val SHALOR_SABLE = create("shalor_sable", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10)
|
||||
.saturationModifier(1.2F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.build())) {
|
||||
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
|
||||
user.removeAllEffects()
|
||||
return super.finishUsingItem(stack, world, user)
|
||||
}
|
||||
})
|
||||
|
||||
val CASTELIACONE = regionalFoodItem("casteliacone", 16, 5, .28f, false)
|
||||
@JvmField
|
||||
val LUMIOSE_GALETTE = create("lumiose_galette", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10)
|
||||
.saturationModifier(1.2F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.build())) {
|
||||
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
|
||||
user.removeAllEffects()
|
||||
return super.finishUsingItem(stack, world, user)
|
||||
}
|
||||
})
|
||||
|
||||
val LUMIOSE_GALETTE = regionalFoodItem("lumiose_galette", 16, 8, 0.2f, false)
|
||||
@JvmField
|
||||
val BIG_MALASADA = create("big_malasada", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10)
|
||||
.saturationModifier(1.2F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.build())) {
|
||||
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
|
||||
user.removeAllEffects()
|
||||
return super.finishUsingItem(stack, world, user)
|
||||
}
|
||||
})
|
||||
|
||||
/*@JvmField // todo see what we are doing for these (are there different kinds?)
|
||||
val CURRY = create("curry", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10)
|
||||
.saturationModifier(1.2F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.usingConvertsTo(Items.BOWL)
|
||||
.build())) {
|
||||
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
|
||||
user.removeAllEffects()
|
||||
return super.finishUsingItem(stack, world, user)
|
||||
}
|
||||
})*/
|
||||
|
||||
val BIG_MALASADA = regionalFoodItem("big_malasada", 16, 7, 0.343f, false)
|
||||
@JvmField
|
||||
val JUBILIFE_MUFFIN = create("jubilife_muffin", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10)
|
||||
.saturationModifier(1.2F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.build())) {
|
||||
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
|
||||
user.removeAllEffects()
|
||||
return super.finishUsingItem(stack, world, user)
|
||||
}
|
||||
})
|
||||
val SMOKED_TAIL_CURRY = regionalFoodItem("smoked_tail_curry", 16, 10, 0.6f, false, ItemStack(Items.BOWL, 1))
|
||||
@JvmField
|
||||
val JUBILIFE_MUFFIN = regionalFoodItem("jubilife_muffin", 16, 8, 0.2f, false)
|
||||
@JvmField
|
||||
val OPEN_FACED_SANDWICH = regionalFoodItem("open_faced_sandwich", 16, 13, 0.5f, false)
|
||||
|
||||
/*@JvmField // todo see what we are doing for these (are there different kinds?)
|
||||
val SANDWICH = create("sandwich", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10)
|
||||
.saturationModifier(1.2F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.usingConvertsTo(Items.BOWL)
|
||||
.build())) {
|
||||
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
|
||||
user.removeAllEffects()
|
||||
return super.finishUsingItem(stack, world, user)
|
||||
}
|
||||
})*/
|
||||
|
||||
// todo we might need to wait on these for later?
|
||||
// todo we might need to wait on these for later? These impact battles and may be harder to do
|
||||
/*@JvmField
|
||||
val CHOICE_DUMPLING = noSettingsItem("choice_dumpling") // todo make a ChoiceDumpingItem class for breeding purposes
|
||||
val CHOICE_DUMPLING = noSettingsItem("choice_dumpling") // todo make a ChoiceDumpingItem class for battle purposes
|
||||
@JvmField
|
||||
val SWAP_SNACK = noSettingsItem("swap_snack") // todo make a SwapSnackItem class for breeding purposes
|
||||
val SWAP_SNACK = noSettingsItem("swap_snack") // todo make a SwapSnackItem class for battle purposes
|
||||
@JvmField
|
||||
val TWICE_SPICED_BEETROOT = noSettingsItem("twice_spiced_beetroot") // todo make a TwiceSpiceBeetrootItem class for breeding purposes
|
||||
val TWICE_SPICED_BEETROOT = noSettingsItem("twice_spiced_beetroot") // todo make a TwiceSpiceBeetrootItem class for battle purposes
|
||||
*/
|
||||
@JvmField
|
||||
val POTATO_MOCHI = create("potato_mochi", object : Item(Properties().stacksTo(16)
|
||||
val POTATO_MOCHI = create("potato_mochi", CobblemonItem(Properties().stacksTo(16)
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10)
|
||||
.saturationModifier(1.2F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.build())) {
|
||||
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
|
||||
user.removeAllEffects()
|
||||
return super.finishUsingItem(stack, world, user)
|
||||
}
|
||||
})
|
||||
.nutrition(8)
|
||||
.saturationModifier(0.2375F)
|
||||
.build())))
|
||||
@JvmField
|
||||
val FRIED_RICE = create("fried_rice", object : Item(Properties().stacksTo(16)
|
||||
val CANDIED_APPLE = create("candied_apple", CobblemonItem(Properties().stacksTo(16)
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10)
|
||||
.saturationModifier(1.2F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.build())) {
|
||||
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
|
||||
user.removeAllEffects()
|
||||
return super.finishUsingItem(stack, world, user)
|
||||
}
|
||||
})
|
||||
.nutrition(6)
|
||||
.saturationModifier(0.2335F)
|
||||
.usingConvertsTo(Items.STICK)
|
||||
.build())))
|
||||
@JvmField
|
||||
val CANDIED_APPLE = create("candied_apple", object : Item(Properties().stacksTo(16)
|
||||
val CANDIED_BERRY = create("candied_berry", CobblemonItem(Properties().stacksTo(16)
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10)
|
||||
.saturationModifier(1.2F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.build())) {
|
||||
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
|
||||
user.removeAllEffects()
|
||||
return super.finishUsingItem(stack, world, user)
|
||||
}
|
||||
})
|
||||
@JvmField
|
||||
val CANDIED_BERRY = create("candied_berry", object : Item(Properties().stacksTo(16)
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10)
|
||||
.saturationModifier(1.2F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.build())) {
|
||||
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
|
||||
user.removeAllEffects()
|
||||
return super.finishUsingItem(stack, world, user)
|
||||
}
|
||||
})
|
||||
@JvmField
|
||||
val JELLY_DOUGHNUT = create("jelly_doughnut", object : Item(Properties().stacksTo(16)
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10)
|
||||
.saturationModifier(1.2F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.build())) {
|
||||
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
|
||||
user.removeAllEffects()
|
||||
return super.finishUsingItem(stack, world, user)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
// todo etc?
|
||||
.nutrition(5)
|
||||
.saturationModifier(0.22F)
|
||||
.usingConvertsTo(Items.STICK)
|
||||
.build())))
|
||||
|
||||
//@JvmField
|
||||
//val SCATTER_BANG = this.create("scatter_bang", ScatterBangItem(Item.Settings()))
|
||||
@@ -653,9 +491,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@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 = create("sweet_apple", foodItem(4, 0.3f))
|
||||
@JvmField val TART_APPLE = create("tart_apple", foodItem(4, 0.3f))
|
||||
@JvmField val SYRUPY_APPLE = create("syrupy_apple", foodItem(4, 0.3f))
|
||||
@JvmField val SWEET_APPLE = compostableItem("sweet_apple", foodItem(4, 0.3f), 0.65f)
|
||||
@JvmField val TART_APPLE = compostableItem("tart_apple", foodItem(4, 0.3f), 0.65f)
|
||||
@JvmField val SYRUPY_APPLE = compostableItem("syrupy_apple", foodItem(4, 0.3f), 0.65f)
|
||||
@JvmField val GALARICA_CUFF = noSettingsItem("galarica_cuff")
|
||||
@JvmField val GALARICA_WREATH = noSettingsItem("galarica_wreath")
|
||||
@JvmField val BLACK_AUGURITE = noSettingsItem("black_augurite")
|
||||
@@ -665,6 +503,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField val AUSPICIOUS_ARMOR = heldItem("auspicious_armor")
|
||||
@JvmField val MALICIOUS_ARMOR = heldItem("malicious_armor")
|
||||
@JvmField val SHELL_HELMET = heldItem("shell_helmet")
|
||||
@JvmField val METAL_ALLOY = noSettingsItem("metal_alloy")
|
||||
@JvmField val SCROLL_OF_DARKNESS = noSettingsItem("scroll_of_darkness")
|
||||
@JvmField val SCROLL_OF_WATERS = noSettingsItem("scroll_of_waters")
|
||||
|
||||
private val berries = mutableMapOf<ResourceLocation, BerryItem>()
|
||||
// Plants
|
||||
@@ -741,7 +582,34 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField val BERRY_JUICE = this.create("berry_juice", BerryJuiceItem())
|
||||
|
||||
@JvmField
|
||||
val GALARICA_NUTS = create("galarica_nuts", GalaricaNutItem())
|
||||
val GALARICA_NUTS = compostableItemNameBlockItem("galarica_nuts", CobblemonBlocks.GALARICA_NUT_BUSH)
|
||||
|
||||
// Hyper Training Items
|
||||
val hyperTrainingItems = mutableListOf<HyperTrainingItem>()
|
||||
@JvmField
|
||||
val HEALTH_CANDY = hyperTrainingItem("health_candy", 1, setOf(Stats.HP), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val MIGHTY_CANDY = hyperTrainingItem("mighty_candy", 1, setOf(Stats.ATTACK), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val TOUGH_CANDY = hyperTrainingItem("tough_candy", 1, setOf(Stats.DEFENCE), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val SMART_CANDY = hyperTrainingItem("smart_candy", 1, setOf(Stats.SPECIAL_ATTACK), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val COURAGE_CANDY = hyperTrainingItem("courage_candy", 1, setOf(Stats.SPECIAL_DEFENCE), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val QUICK_CANDY = hyperTrainingItem("quick_candy", 1, setOf(Stats.SPEED), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val SICKLY_CANDY = hyperTrainingItem("sickly_candy", -1, setOf(Stats.HP), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val WEAK_CANDY = hyperTrainingItem("weak_candy", -1, setOf(Stats.ATTACK), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val BRITTLE_CANDY = hyperTrainingItem("brittle_candy", -1, setOf(Stats.DEFENCE), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val NUMB_CANDY = hyperTrainingItem("numb_candy", -1, setOf(Stats.SPECIAL_ATTACK), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val COWARD_CANDY = hyperTrainingItem("coward_candy", -1, setOf(Stats.SPECIAL_DEFENCE), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val SLOW_CANDY = hyperTrainingItem("slow_candy", -1, setOf(Stats.SPEED), 0..IVs.MAX_VALUE)
|
||||
|
||||
// Medicine
|
||||
@JvmField
|
||||
@@ -797,14 +665,12 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val MEDICINAL_LEEK = heldItem("medicinal_leek", MedicinalLeekItem(CobblemonBlocks.MEDICINAL_LEEK, Item.Properties().food(FoodProperties.Builder().fast().nutrition(1).saturationModifier(0.2f).build())), "leek")
|
||||
@JvmField
|
||||
val ROASTED_LEEK = create("roasted_leek", Item(Item.Properties().food(FoodProperties.Builder().fast().nutrition(3).saturationModifier(0.3f).build())))
|
||||
val ROASTED_LEEK = compostableItem("roasted_leek", CobblemonItem(Item.Properties().food(FoodProperties.Builder().fast().nutrition(3).saturationModifier(0.2f).build())), 0.85f)
|
||||
@JvmField
|
||||
val BRAISED_VIVICHOKE = create("braised_vivichoke", Item(Item.Properties().food(FoodProperties.Builder().nutrition(6).saturationModifier(0.6f).build())))
|
||||
@JvmField
|
||||
val VIVICHOKE_DIP = create("vivichoke_dip", object : Item(Properties().stacksTo(1)
|
||||
val VIVICHOKE_DIP = create("vivichoke_dip", object : CobblemonItem(Properties().stacksTo(1)
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10)
|
||||
.saturationModifier(1.2F)
|
||||
.saturationModifier(0.6F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.usingConvertsTo(Items.BOWL)
|
||||
@@ -815,19 +681,21 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
}
|
||||
})
|
||||
@JvmField
|
||||
val ENERGY_ROOT = compostableItem("energy_root", EnergyRootItem(CobblemonBlocks.ENERGY_ROOT, Item.Properties().food(FoodProperties.Builder().nutrition(1).fast().saturationModifier(0.2f).build())))
|
||||
val ENERGY_ROOT = compostableItem("energy_root", EnergyRootItem(CobblemonBlocks.ENERGY_ROOT, Properties()), 0.60f)
|
||||
@JvmField
|
||||
val REVIVAL_HERB = compostableItem("revival_herb", RevivalHerbItem(CobblemonBlocks.REVIVAL_HERB))
|
||||
@JvmField
|
||||
val PEP_UP_FLOWER = compostableBlockItem("pep_up_flower", CobblemonBlocks.PEP_UP_FLOWER)
|
||||
@JvmField
|
||||
val MEDICINAL_BREW = create("medicinal_brew", Item(Item.Properties()))
|
||||
val MEDICINAL_BREW = noSettingsItem("medicinal_brew")
|
||||
@JvmField
|
||||
val REMEDY = create("remedy", RemedyItem(RemedyItem.NORMAL))
|
||||
val REMEDY = compostableItem("remedy", RemedyItem(RemedyItem.NORMAL), 0.65f)
|
||||
@JvmField
|
||||
val FINE_REMEDY = create("fine_remedy", RemedyItem(RemedyItem.FINE))
|
||||
val FINE_REMEDY = compostableItem("fine_remedy", RemedyItem(RemedyItem.FINE), 0.75f)
|
||||
@JvmField
|
||||
val SUPERB_REMEDY = create("superb_remedy", RemedyItem(RemedyItem.SUPERB))
|
||||
val SUPERB_REMEDY = compostableItem("superb_remedy", RemedyItem(RemedyItem.SUPERB), 0.85f)
|
||||
@JvmField
|
||||
val MOOMOO_MILK = noSettingsItem("moomoo_milk")
|
||||
|
||||
@JvmField
|
||||
val POTION = create("potion", PotionItem(PotionType.POTION))
|
||||
@@ -843,7 +711,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val HEAL_POWDER = create("heal_powder", HealPowderItem())
|
||||
@JvmField
|
||||
val LEEK_AND_POTATO_STEW = create("leek_and_potato_stew", Item(Item.Properties().food(FoodProperties.Builder().nutrition(8).saturationModifier(0.6f).usingConvertsTo(Items.BOWL).build()).stacksTo(1)))
|
||||
val LEEK_AND_POTATO_STEW = create("leek_and_potato_stew", CobblemonItem(Item.Properties().food(FoodProperties.Builder().nutrition(6).saturationModifier(0.6f).usingConvertsTo(Items.BOWL).build()).stacksTo(1)))
|
||||
@JvmField
|
||||
val REVIVE = create("revive", ReviveItem(max = false))
|
||||
@JvmField
|
||||
@@ -1045,7 +913,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val ASSAULT_VEST = heldItem("assault_vest")
|
||||
@JvmField
|
||||
val BIG_ROOT = blockItem("big_root", CobblemonBlocks.BIG_ROOT)
|
||||
val BIG_ROOT = compostableBlockItem("big_root", CobblemonBlocks.BIG_ROOT, 0.40f)
|
||||
@JvmField
|
||||
val BINDING_BAND = heldItem("binding_band")
|
||||
@JvmField
|
||||
@@ -1062,8 +930,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
val CHOICE_SCARF = heldItem("choice_scarf")
|
||||
@JvmField
|
||||
val CLEANSE_TAG = heldItem("cleanse_tag")
|
||||
// @JvmField
|
||||
// val CLEAR_AMULET = heldItem("clear_amulet")
|
||||
@JvmField
|
||||
val CLEAR_AMULET = heldItem("clear_amulet")
|
||||
@JvmField
|
||||
val COVERT_CLOAK = heldItem("covert_cloak")
|
||||
@JvmField
|
||||
@@ -1092,18 +960,18 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
val FOCUS_SASH = heldItem("focus_sash")
|
||||
@JvmField
|
||||
val GRASSY_SEED = heldItem("grassy_seed")
|
||||
// @JvmField
|
||||
// val GRIP_CLAW = heldItem("grip_claw")
|
||||
@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")
|
||||
val LAGGING_TAIL = heldItem("lagging_tail")
|
||||
@JvmField
|
||||
val LEFTOVERS = compostableHeldItem("leftovers", null, 0.50f)
|
||||
@JvmField
|
||||
val LIFE_ORB = heldItem("life_orb")
|
||||
@JvmField
|
||||
@@ -1114,8 +982,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
val LOADED_DICE = heldItem("loaded_dice")
|
||||
@JvmField
|
||||
val LUCKY_EGG = heldItem("lucky_egg")
|
||||
// @JvmField
|
||||
// val LUMINOUS_MOSS = heldItem("luminous_moss")
|
||||
@JvmField
|
||||
val LUMINOUS_MOSS = heldItem("luminous_moss")
|
||||
@JvmField
|
||||
val MAGNET = heldItem("magnet")
|
||||
@JvmField
|
||||
@@ -1590,6 +1458,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
|
||||
private fun blockItem(name: String, block: Block, rarity: Rarity = Rarity.COMMON): BlockItem = this.create(name, BlockItem(block, Item.Properties().rarity(rarity)))
|
||||
|
||||
private fun itemNameBlockItem(name: String, block: Block, rarity: Rarity = Rarity.COMMON): ItemNameBlockItem = this.create(name, ItemNameBlockItem(block, Item.Properties().rarity(rarity)))
|
||||
|
||||
private fun noSettingsItem(name: String): CobblemonItem = this.create(name, CobblemonItem(Item.Properties()))
|
||||
|
||||
private fun itemWithRarity(name: String, rarity: Rarity): CobblemonItem = this.create(name, CobblemonItem(Item.Properties().rarity(rarity)))
|
||||
@@ -1642,6 +1512,38 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
return item
|
||||
}
|
||||
|
||||
private fun pokepuffItem(name: String): PokePuffItem {
|
||||
val item = create("poke_puff", PokePuffItem())
|
||||
return item
|
||||
}
|
||||
|
||||
private fun regionalFoodItem(
|
||||
name: String,
|
||||
stacksTo: Int,
|
||||
nutrition: Int,
|
||||
saturationModifier: Float,
|
||||
alwaysEdible: Boolean = false,
|
||||
convertsToOnUse: ItemStack? = null
|
||||
): RegionalFoodItem {
|
||||
val foodPropertiesBuilder = FoodProperties.Builder()
|
||||
.nutrition(nutrition)
|
||||
.saturationModifier(saturationModifier)
|
||||
|
||||
if (alwaysEdible == true) {
|
||||
foodPropertiesBuilder.alwaysEdible()
|
||||
}
|
||||
|
||||
if (convertsToOnUse != null && !convertsToOnUse.isEmpty) {
|
||||
foodPropertiesBuilder.usingConvertsTo(convertsToOnUse.item)
|
||||
}
|
||||
|
||||
val properties = Item.Properties()
|
||||
.stacksTo(stacksTo)
|
||||
.food(foodPropertiesBuilder.build())
|
||||
|
||||
return create(name, RegionalFoodItem(properties))
|
||||
}
|
||||
|
||||
private fun heldItem(name: String, remappedName: String? = null): CobblemonItem = create(
|
||||
name,
|
||||
CobblemonItem(Item.Properties()).also {
|
||||
@@ -1653,11 +1555,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
private fun heldItem(name: String, item: Item, remappedName: String? = null) = create(
|
||||
name = name,
|
||||
entry = item.also {
|
||||
if (remappedName != null) {
|
||||
remappedName?.let { remappedName ->
|
||||
CobblemonHeldItemManager.registerRemap(it, remappedName)
|
||||
CobblemonHeldItemManager.registerRemap(Items.BONE, "thickclub")
|
||||
CobblemonHeldItemManager.registerRemap(Items.SNOWBALL, "snowball")
|
||||
CobblemonHeldItemManager.registerRemap(Items.GOLD_BLOCK, "bignugget")
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -1683,7 +1582,13 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
private fun mintItem(name: String, mintItem: MintItem): MintItem {
|
||||
val item = this.create(name, mintItem)
|
||||
mints[item.nature.displayName] = item
|
||||
compostable(item, .65f)
|
||||
compostable(item, .95f)
|
||||
return item
|
||||
}
|
||||
|
||||
private fun hyperTrainingItem(name: String, increaseAmount: Int, targetStats: Set<Stat>, validRange: IntRange): HyperTrainingItem {
|
||||
val item = this.create(name, HyperTrainingItem(increaseAmount, targetStats, validRange))
|
||||
hyperTrainingItems.add(item)
|
||||
return item
|
||||
}
|
||||
|
||||
@@ -1697,21 +1602,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
private fun apricornSeedItem(name: String, apricornSeedItem: ApricornSeedItem): ApricornSeedItem {
|
||||
val finalName = "${name}_apricorn_seed"
|
||||
val item = this.create(finalName, apricornSeedItem)
|
||||
compostable(item, .65f)
|
||||
return item
|
||||
}
|
||||
|
||||
private fun saccharineSaplingItem(name: String, saccharineSaplingItem: SaccharineSaplingItem): SaccharineSaplingItem {
|
||||
val finalName = "saccharine_sapling"
|
||||
val item = this.create(finalName, saccharineSaplingItem)
|
||||
compostable(item, .65f)
|
||||
return item
|
||||
}
|
||||
|
||||
private fun bugwortItem(name: String, bugwortItem: BugwortItem): BugwortItem {
|
||||
val finalName = "bugwort"
|
||||
val item = this.create(finalName, bugwortItem)
|
||||
compostable(item, .65f)
|
||||
compostable(item, .30f)
|
||||
return item
|
||||
}
|
||||
|
||||
@@ -1719,19 +1610,19 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
private fun mintSeed(name: String, mintBlock: MintBlock): Item {
|
||||
val finalName = "${name}_mint_seeds"
|
||||
val item = this.blockItem(finalName, mintBlock)
|
||||
compostable(item, .65f)
|
||||
compostable(item, .30f)
|
||||
return item
|
||||
}
|
||||
|
||||
private fun mintLeaf(name: String, mintLeafItem: MintLeafItem): MintLeafItem {
|
||||
val finalName = "${name}_mint_leaf"
|
||||
val item = this.create(finalName, mintLeafItem)
|
||||
compostable(item, .65f)
|
||||
compostable(item, .50f)
|
||||
return item
|
||||
}
|
||||
|
||||
private fun compostableItem(name: String, item: Item? = null, increaseLevelChance: Float = .65f): Item {
|
||||
val createdItem = this.create(name, item ?: Item(Item.Properties()))
|
||||
val createdItem = this.create(name, item ?: CobblemonItem(Item.Properties()))
|
||||
compostable(createdItem, increaseLevelChance)
|
||||
return createdItem
|
||||
}
|
||||
@@ -1742,13 +1633,19 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
return createdItem
|
||||
}
|
||||
|
||||
private fun compostableBlockItem(name: String, block: Block, increaseLevelChance: Float = .65f): Item {
|
||||
private fun compostableBlockItem(name: String, block: Block, increaseLevelChance: Float = .85f): Item {
|
||||
val createdItem = this.blockItem(name, block)
|
||||
compostable(createdItem, increaseLevelChance)
|
||||
return createdItem
|
||||
}
|
||||
|
||||
private fun compostableItemNameBlockItem(name: String, block: Block, increaseLevelChance: Float = .30f): Item {
|
||||
val createdItem = this.itemNameBlockItem(name, block)
|
||||
compostable(createdItem, increaseLevelChance)
|
||||
return createdItem
|
||||
}
|
||||
|
||||
private fun foodItem(nutrition: Int, saturationModifier: Float): Item {
|
||||
return Item(Item.Properties().food(FoodProperties.Builder().nutrition(nutrition).saturationModifier(saturationModifier).build()))
|
||||
return CobblemonItem(Item.Properties().food(FoodProperties.Builder().nutrition(nutrition).saturationModifier(saturationModifier).build()))
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.CobblemonAttackTargetData
|
||||
import com.cobblemon.mod.common.api.ai.CobblemonWanderControl
|
||||
import com.cobblemon.mod.common.api.dialogue.ActiveDialogue
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.mojang.serialization.Codec
|
||||
@@ -42,6 +44,16 @@ object CobblemonMemories {
|
||||
val NEAREST_VISIBLE_ATTACKER = register<LivingEntity>("nearest_visible_attacker")
|
||||
val NEARBY_GROWABLE_CROPS = register<BlockPos>("nearby_growable_crops")
|
||||
val RECENTLY_ATE_GRASS = register<Boolean>("recently_ate_grass")
|
||||
val HIVE_LOCATION = register<BlockPos>("hive_location")
|
||||
val HIVE_COOLDOWN = register<Boolean>("hive_cooldown")
|
||||
val NEARBY_FLOWERS = register<List<BlockPos>>("nearby_flower")
|
||||
val POLLINATED = register<Boolean>("pollinated", PrimitiveCodec.BOOL)
|
||||
/** who am i following rn? */
|
||||
val HERD_LEADER = register<String>("herd_leader", PrimitiveCodec.STRING)
|
||||
/** how many are following me rn? */
|
||||
val HERD_SIZE = register<Int>("herd_size") // Don't bother saving it, we'll try to keep count roughly.
|
||||
val ATTACK_TARGET_DATA = register<CobblemonAttackTargetData>("attack_target_data") // This is used to store additional information about the attack target, such as when to give up pursuit.
|
||||
val WANDER_CONTROL = register<CobblemonWanderControl>("wander_control")
|
||||
|
||||
fun <U> register(id: String, codec: Codec<U>): MemoryModuleType<U> {
|
||||
val memoryModule = MemoryModuleType(Optional.of(codec))
|
||||
|
||||
@@ -10,9 +10,7 @@ package com.cobblemon.mod.common
|
||||
|
||||
|
||||
import com.cobblemon.mod.common.block.campfirepot.CookingPotMenu
|
||||
import com.cobblemon.mod.common.client.gui.cookingpot.CookingPotScreen
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import net.minecraft.client.gui.screens.MenuScreens
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.core.registries.Registries
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.cobblemon.mod.common.client.net.data.UnlockReloadPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.dialogue.DialogueClosedHandler
|
||||
import com.cobblemon.mod.common.client.net.dialogue.DialogueOpenedHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.RunPosableMoLangHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.SaccharineLogBlockParticlesHandler
|
||||
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
|
||||
@@ -36,6 +37,7 @@ import com.cobblemon.mod.common.client.net.pasture.ClosePastureHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.OpenPastureHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.PokemonPasturedHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.PokemonUnpasturedHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.UpdatePastureConflictFlagHandler
|
||||
import com.cobblemon.mod.common.client.net.pokedex.ServerConfirmedRegisterHandler
|
||||
import com.cobblemon.mod.common.client.net.pokemon.update.ClientboundUpdateRidingStateHandler
|
||||
import com.cobblemon.mod.common.client.net.pokemon.update.PokemonUpdatePacketHandler
|
||||
@@ -76,6 +78,7 @@ import com.cobblemon.mod.common.net.messages.client.data.*
|
||||
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueClosedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueOpenedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SaccharineLogBlockParticlesPacket
|
||||
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.npc.CloseNPCEditorPacket
|
||||
@@ -85,6 +88,7 @@ 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
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonUnpasturedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.UpdatePastureConflictFlagPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokedex.ServerConfirmedRegisterPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.*
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.AddEvolutionPacket
|
||||
@@ -140,6 +144,7 @@ import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamRequestPack
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamResponsePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.behaviour.DamageOnCollisionPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.behaviour.SetEntityBehaviourPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectCancelledPacket
|
||||
@@ -155,6 +160,7 @@ import com.cobblemon.mod.common.net.messages.server.dialogue.InputToDialoguePack
|
||||
import com.cobblemon.mod.common.net.messages.server.npc.SaveNPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.orientation.ServerboundUpdateOrientationPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.PasturePokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.SetPastureConflictPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpastureAllPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.FinishScanningPacket
|
||||
@@ -166,6 +172,7 @@ import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetActiveMark
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetMarkingsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.ServerboundUpdateRidingStatePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.evolution.AcceptEvolutionPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.riding.DismountPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.starter.RequestStarterScreenPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.SwapPCPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokemonPacket
|
||||
@@ -187,6 +194,7 @@ import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamLeaveHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestResponseHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.behaviour.DamageOnCollisionPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.behaviour.SetEntityBehaviourHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.block.AdjustBlockEntityViewerCountHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectCancelledHandler
|
||||
@@ -203,6 +211,7 @@ import com.cobblemon.mod.common.net.serverhandling.evolution.AcceptEvolutionHand
|
||||
import com.cobblemon.mod.common.net.serverhandling.npc.SaveNPCHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.orientation.OrientationPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.PasturePokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.SetPastureConflictHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpastureAllPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpasturePokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.FinishScanningHandler
|
||||
@@ -213,6 +222,7 @@ import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetNicknameHan
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetActiveMarkHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetMarkingsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.ServerboundUpdateRidingStateHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.riding.DismountPokemonPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.starter.RequestStarterScreenHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.starter.SelectStarterPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.BenchMoveHandler
|
||||
@@ -259,6 +269,7 @@ object CobblemonNetwork {
|
||||
|
||||
// Pokemon Update Packets
|
||||
list.add(PacketRegisterInfo(FriendshipUpdatePacket.ID, FriendshipUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(FullnessUpdatePacket.ID, FullnessUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(MoveSetUpdatePacket.ID, MoveSetUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(NatureUpdatePacket.ID, NatureUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(ShinyUpdatePacket.ID, ShinyUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
@@ -393,6 +404,7 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler))
|
||||
list.add(PacketRegisterInfo(SpawnSnowstormEntityParticlePacket.ID, SpawnSnowstormEntityParticlePacket::decode, SpawnSnowstormEntityParticleHandler))
|
||||
list.add(PacketRegisterInfo(RunPosableMoLangPacket.ID, RunPosableMoLangPacket::decode, RunPosableMoLangHandler))
|
||||
list.add(PacketRegisterInfo(SaccharineLogBlockParticlesPacket.ID, SaccharineLogBlockParticlesPacket::decode, SaccharineLogBlockParticlesHandler))
|
||||
|
||||
// Hax
|
||||
list.add(PacketRegisterInfo(UnvalidatedPlaySoundS2CPacket.ID, UnvalidatedPlaySoundS2CPacket::decode, UnvalidatedPlaySoundS2CPacketHandler))
|
||||
@@ -417,6 +429,7 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(ClosePasturePacket.ID, ClosePasturePacket::decode, ClosePastureHandler))
|
||||
list.add(PacketRegisterInfo(PokemonPasturedPacket.ID, PokemonPasturedPacket::decode, PokemonPasturedHandler))
|
||||
list.add(PacketRegisterInfo(PokemonUnpasturedPacket.ID, PokemonUnpasturedPacket::decode, PokemonUnpasturedHandler))
|
||||
list.add(PacketRegisterInfo(UpdatePastureConflictFlagPacket.ID, UpdatePastureConflictFlagPacket::decode, UpdatePastureConflictFlagHandler))
|
||||
|
||||
// Orientation
|
||||
list.add(PacketRegisterInfo(ClientboundUpdateOrientationPacket.ID, ClientboundUpdateOrientationPacket::decode, S2CUpdateOrientationHandler))
|
||||
@@ -527,6 +540,8 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(PasturePokemonPacket.ID, PasturePokemonPacket::decode, PasturePokemonHandler))
|
||||
list.add(PacketRegisterInfo(UnpasturePokemonPacket.ID, UnpasturePokemonPacket::decode, UnpasturePokemonHandler))
|
||||
list.add(PacketRegisterInfo(UnpastureAllPokemonPacket.ID, UnpastureAllPokemonPacket::decode, UnpastureAllPokemonHandler))
|
||||
list.add(PacketRegisterInfo(SetPastureConflictPacket.ID, SetPastureConflictPacket::decode, SetPastureConflictHandler))
|
||||
|
||||
|
||||
// Block entity
|
||||
list.add(PacketRegisterInfo(AdjustBlockEntityViewerCountPacket.ID, AdjustBlockEntityViewerCountPacket::decode, AdjustBlockEntityViewerCountHandler))
|
||||
@@ -555,12 +570,14 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(ServerboundUpdateRidingStatePacket.ID, ServerboundUpdateRidingStatePacket::decode, ServerboundUpdateRidingStateHandler))
|
||||
list.add(PacketRegisterInfo(ServerboundUpdateRidingStatsPacket.ID, ServerboundUpdateRidingStatsPacket::decode, ServerboundUpdateRidingStatsHandler))
|
||||
list.add(PacketRegisterInfo(ServerboundUpdateRidingStatRangePacket.ID, ServerboundUpdateRidingStatRangePacket::decode, ServerboundUpdateRidingStatRangeHandler))
|
||||
list.add(PacketRegisterInfo(DismountPokemonPacket.ID, DismountPokemonPacket::decode, DismountPokemonPacketHandler))
|
||||
|
||||
// Cooking
|
||||
list.add(PacketRegisterInfo(ToggleCookingPotLidPacket.ID, ToggleCookingPotLidPacket::decode, ToggleCookingPotLidHandler))
|
||||
|
||||
// Behaviour Packets
|
||||
list.add(PacketRegisterInfo(SetEntityBehaviourPacket.ID, SetEntityBehaviourPacket::decode, SetEntityBehaviourHandler))
|
||||
list.add(PacketRegisterInfo(DamageOnCollisionPacket.ID, DamageOnCollisionPacket::decode, DamageOnCollisionPacketHandler))
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
@@ -24,23 +24,18 @@ object CobblemonPoiTypes: PlatformRegistry<Registry<PoiType>, ResourceKey<Regist
|
||||
override val resourceKey: ResourceKey<Registry<PoiType>> = Registries.POINT_OF_INTEREST_TYPE
|
||||
|
||||
@JvmField
|
||||
val NURSE_KEY: ResourceKey<PoiType> = createKey("nurse")
|
||||
val NURSE_KEY = createKey("nurse", CobblemonBlocks.HEALING_MACHINE, 1, 1)
|
||||
@JvmField
|
||||
val NURSE = create(NURSE_KEY.location().path, PoiType(getBlockStates(CobblemonBlocks.HEALING_MACHINE), 1, 1))
|
||||
val LURE_CAKE_KEY = createKey("lure_cake", CobblemonBlocks.LURE_CAKE, 0, 1)
|
||||
@JvmField
|
||||
val LURE_CAKE_KEY: ResourceKey<PoiType> = createKey("lure_cake")
|
||||
val SACCHARINE_LOG_SLATHERED_KEY = createKey("saccharine_log_slathered", CobblemonBlocks.SACCHARINE_LOG_SLATHERED, 0, 1)
|
||||
@JvmField
|
||||
val LURE_CAKE = create(LURE_CAKE_KEY.location().path, PoiType(getBlockStates(CobblemonBlocks.LURE_CAKE), 0, 1))
|
||||
@JvmField
|
||||
val SACCHARINE_HONEY_LOG_KEY: ResourceKey<PoiType> = createKey("saccharine_honey_log")
|
||||
@JvmField
|
||||
val SACCHARINE_HONEY_LOG = create(SACCHARINE_HONEY_LOG_KEY.location().path, PoiType(getBlockStates(CobblemonBlocks.SACCHARINE_HONEY_LOG), 0, 1))
|
||||
@JvmField
|
||||
val INCENSE_SWEET_KEY: ResourceKey<PoiType> = createKey("saccharine_honey_log")
|
||||
@JvmField
|
||||
val INCENSE_SWEET = create(INCENSE_SWEET_KEY.location().path, PoiType(getBlockStates(CobblemonBlocks.INCENSE_SWEET), 0, 1))
|
||||
val INCENSE_SWEET_KEY = createKey("incense_sweet", CobblemonBlocks.INCENSE_SWEET, 0, 1)
|
||||
|
||||
private fun createKey(string: String): ResourceKey<PoiType> = ResourceKey.create(Registries.POINT_OF_INTEREST_TYPE, cobblemonResource(string))
|
||||
private fun createKey(string: String, block: Block, maxTickets: Int, validRange: Int ): ResourceKey<PoiType> =
|
||||
ResourceKey.create(Registries.POINT_OF_INTEREST_TYPE, cobblemonResource(string)).also { resourceKey ->
|
||||
create(resourceKey.location().path, PoiType(getBlockStates(block), maxTickets, validRange))
|
||||
}
|
||||
|
||||
private fun getBlockStates(block: Block): Set<BlockState> = ImmutableSet.copyOf(block.stateDefinition.possibleStates)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,13 @@ enum class CobblemonRecipeCategories {
|
||||
COOKING_POT_SEARCH("COOKING_POT_SEARCH"),
|
||||
COOKING_POT_FOODS("COOKING_POT_FOODS"),
|
||||
COOKING_POT_MEDICINES("COOKING_POT_MEDICINES"),
|
||||
COOKING_POT_BAITS("COOKING_POT_BAITS"),
|
||||
COOKING_POT_COMPLEX_DISHES("COOKING_POT_COMPLEX_DISHES"),
|
||||
COOKING_POT_MISC("COOKING_POT_MISC");
|
||||
|
||||
companion object {
|
||||
val customAggregateCategories: Map<RecipeBookCategories, List<RecipeBookCategories>> = mapOf(
|
||||
COOKING_POT_SEARCH.toVanillaCategory() to listOf(
|
||||
COOKING_POT_FOODS.toVanillaCategory(), COOKING_POT_MISC.toVanillaCategory(), COOKING_POT_MEDICINES.toVanillaCategory(), COOKING_POT_BAITS.toVanillaCategory()
|
||||
COOKING_POT_FOODS.toVanillaCategory(), COOKING_POT_MISC.toVanillaCategory(), COOKING_POT_MEDICINES.toVanillaCategory(), COOKING_POT_COMPLEX_DISHES.toVanillaCategory()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.item.crafting.CookingPotRecipe
|
||||
import com.cobblemon.mod.common.item.crafting.CookingPotShapelessRecipe
|
||||
import com.cobblemon.mod.common.item.crafting.brewingstand.BrewingStandRecipe
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
@@ -24,6 +25,8 @@ object CobblemonRecipeSerializers : PlatformRegistry<Registry<RecipeSerializer<*
|
||||
val COOKING_POT_COOKING: RecipeSerializer<*> = register("cobblemon:cooking_pot", CookingPotRecipe.Serializer())
|
||||
val COOKING_POT_SHAPELESS: RecipeSerializer<*> = register("cobblemon:cooking_pot_shapeless", CookingPotShapelessRecipe.Serializer())
|
||||
|
||||
val BREWING_STAND: RecipeSerializer<*> = register("cobblemon:brewing_stand", BrewingStandRecipe.Serializer())
|
||||
|
||||
override val registry: Registry<RecipeSerializer<*>>
|
||||
get() = BuiltInRegistries.RECIPE_SERIALIZER
|
||||
override val resourceKey: ResourceKey<Registry<RecipeSerializer<*>>>
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.item.crafting.CookingPotRecipe
|
||||
import com.cobblemon.mod.common.item.crafting.CookingPotShapelessRecipe
|
||||
import com.cobblemon.mod.common.item.crafting.brewingstand.BrewingStandRecipe
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
@@ -24,6 +25,8 @@ object CobblemonRecipeTypes : PlatformRegistry<Registry<RecipeType<*>>, Resource
|
||||
val COOKING_POT_COOKING: RecipeType<CookingPotRecipe> = register("cobblemon:cooking_pot")
|
||||
val COOKING_POT_SHAPELESS: RecipeType<CookingPotShapelessRecipe> = register("cobblemon:cooking_pot_shapeless")
|
||||
|
||||
val BREWING_STAND: RecipeType<BrewingStandRecipe> = register("cobblemon:brewing_stand")
|
||||
|
||||
override val registry: Registry<RecipeType<*>>
|
||||
get() = BuiltInRegistries.RECIPE_TYPE
|
||||
override val resourceKey: ResourceKey<Registry<RecipeType<*>>>
|
||||
|
||||
@@ -8,10 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.sensors.DefendOwnerSensor
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.sensors.DrowsySensor
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.sensors.PokemonAdultSensor
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.sensors.PokemonGrowableCropSensor
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.sensors.*
|
||||
import com.cobblemon.mod.common.pokemon.ai.PokemonDisturbancesSensor
|
||||
import com.cobblemon.mod.common.entity.sensor.BattlingPokemonSensor
|
||||
import com.cobblemon.mod.common.entity.sensor.NPCBattlingSensor
|
||||
@@ -36,6 +33,10 @@ object CobblemonSensors {
|
||||
|
||||
val NEARBY_GROWABLE_CROPS = register("nearby_growable_crops", ::PokemonGrowableCropSensor)
|
||||
|
||||
val NEARBY_BEE_HIVE = register("nearby_bee_hive", ::BeeHiveSensor)
|
||||
|
||||
val NEARBY_FLOWER = register("nearby_flower", ::FlowerSensor)
|
||||
|
||||
fun <E : Entity, U : Sensor<E>> register(id: String, supplier: Supplier<U>): SensorType<U> {
|
||||
val sensor = SensorType(supplier)
|
||||
sensors[id] = sensor
|
||||
|
||||
@@ -125,6 +125,7 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
@JvmField
|
||||
val MOCHI_USE = this.create("item.medicine.feather.use")
|
||||
|
||||
|
||||
@JvmField
|
||||
val MULCH_PLACE = this.create("block.mulch.place")
|
||||
@JvmField
|
||||
@@ -216,6 +217,8 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
val BERRY_HARVEST = this.create("block.berry_bush.harvest")
|
||||
@JvmField
|
||||
val BERRY_EAT = this.create("item.berry.eat")
|
||||
@JvmField
|
||||
val BERRY_EAT_FULL = this.create("item.berry.eat.full")
|
||||
|
||||
@JvmField
|
||||
val BIG_ROOT_BREAK = this.create("block.big_root.break")
|
||||
@@ -272,6 +275,11 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
RELIC_COIN_SACK_STEP
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val RIDE_LOOP_LEATHER = create("ride.loop.leather")
|
||||
@JvmField
|
||||
val RIDE_LOOP_PLUMAGE = create("ride.loop.plumage")
|
||||
|
||||
@JvmField
|
||||
val MOVE_QUICKATTACK_TARGET = this.create("move.quickattack.target")
|
||||
@JvmField
|
||||
@@ -316,6 +324,8 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
@JvmField
|
||||
val IMPACT_WATER = this.create("impact.water")
|
||||
|
||||
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE_SOUNDS = SoundType(1f, 1.1f,
|
||||
TUMBLESTONE_BREAK,
|
||||
|
||||
+2
-1
@@ -32,6 +32,7 @@ class PokemonCriterion(
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: Pokemon): Boolean {
|
||||
return (species.equals(context.species.resourceIdentifier.path) || species.equals(context.species.resourceIdentifier)) && properties.matches(context)
|
||||
var speciesCheck = (species.equals(context.species.resourceIdentifier.path) || species.equals(context.species.resourceIdentifier.toString())) || species.equals("any")
|
||||
return speciesCheck && properties.matches(context)
|
||||
}
|
||||
}
|
||||
|
||||
+49
-2
@@ -8,10 +8,20 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.api.ai.config.BehaviourConfig
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.entity.MoLangScriptingEntity
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.serialization.Dynamic
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
import net.minecraft.world.entity.schedule.Schedule
|
||||
|
||||
@@ -22,13 +32,41 @@ class BehaviourConfigurationContext {
|
||||
var coreActivities = setOf(Activity.CORE)
|
||||
val activities = mutableListOf<ActivityConfigurationContext>()
|
||||
val schedule = Schedule.EMPTY
|
||||
val memories = mutableSetOf<MemoryModuleType<*>>()
|
||||
val sensors = mutableSetOf<SensorType<*>>()
|
||||
|
||||
val onAddScripts = mutableListOf<ResourceLocation>()
|
||||
val onAdd = mutableListOf<ExpressionLike>()
|
||||
|
||||
fun getOrCreateActivity(activity: Activity): ActivityConfigurationContext {
|
||||
return activities.firstOrNull { it.activity == activity } ?: ActivityConfigurationContext(activity).also(activities::add)
|
||||
}
|
||||
|
||||
fun apply(entity: LivingEntity, behaviourConfigs: List<BehaviourConfig>) {
|
||||
val brain = entity.brain
|
||||
fun addMemories(vararg memory: MemoryModuleType<*>) {
|
||||
memories.addAll(memory)
|
||||
}
|
||||
|
||||
fun addMemories(memories: Collection<MemoryModuleType<*>>) {
|
||||
this.memories.addAll(memories)
|
||||
}
|
||||
|
||||
fun addSensors(vararg sensor: SensorType<*>) {
|
||||
sensors.addAll(sensor)
|
||||
}
|
||||
|
||||
fun addSensors(sensors: Collection<SensorType<*>>) {
|
||||
this.sensors.addAll(sensors)
|
||||
}
|
||||
|
||||
fun addOnAddScript(script: ResourceLocation) {
|
||||
onAddScripts.add(script)
|
||||
}
|
||||
|
||||
fun addOnAddScript(script: ExpressionLike) {
|
||||
onAdd.add(script)
|
||||
}
|
||||
|
||||
fun apply(entity: LivingEntity, behaviourConfigs: List<BehaviourConfig>, dynamic: Dynamic<*>) {
|
||||
|
||||
if (entity is MoLangScriptingEntity) {
|
||||
entity.registerVariables(behaviourConfigs.flatMap { it.getVariables(entity) })
|
||||
@@ -38,7 +76,16 @@ class BehaviourConfigurationContext {
|
||||
// Setup the brain config
|
||||
behaviourConfigs.forEach { it.configure(entity, this) }
|
||||
|
||||
var brain = entity.brain
|
||||
// Apply the brain config
|
||||
if (entity is MoLangScriptingEntity) {
|
||||
brain = entity.assignNewBrainWithMemoriesAndSensors(dynamic, memories, sensors)
|
||||
|
||||
val runtime = MoLangRuntime().setup()
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
onAddScripts.forEach { CobblemonScripts.run(it, runtime) }
|
||||
onAdd.forEach { runtime.resolve(it) }
|
||||
}
|
||||
activities.forEach { it.apply(entity) }
|
||||
brain.setCoreActivities(coreActivities)
|
||||
brain.setDefaultActivity(defaultActivity)
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
import net.minecraft.world.entity.Entity
|
||||
|
||||
/**
|
||||
* This is used in the AI system to store optional additional information about the attack target,
|
||||
* mainly things like when to give up pursuit, what sort of attacks are permitted, whatever. It's
|
||||
* a temporary memory, same as ATTACK_TARGET, so relogs will clear it and that's why it has no codec.
|
||||
*
|
||||
* To help you get a sense of a use case, imagine a Pidgeotto has an AI task that says it should hunt
|
||||
* Magikarp that are close to the surface. Once they've found one and chosen them as the attack target,
|
||||
* they should give up the target if the Magikarp goes too deep, but if it's attacking an entity because
|
||||
* they attacked its owner, it shouldn't give up on the target for that reason. To address this, when
|
||||
* hunting Magikarp, the Pidgeotto will set this memory to a CobblemonAttackTargetData with some
|
||||
* [Expression] that encourages the entity to give up the target if the Magikarp goes too deep.
|
||||
*
|
||||
* To make this work, any transition from the FIGHT activity will erase this memory.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since June 23rd, 2025
|
||||
*/
|
||||
class CobblemonAttackTargetData(
|
||||
/** An expression that returns false when the target is no longer worth attacking. */
|
||||
var shouldContinue: Expression = "true".asExpression(),
|
||||
var hitsUntilDisengage: Int = -1, // -1 means no limit
|
||||
var disengageAction: (entity: Entity) -> Unit = {}
|
||||
) {
|
||||
val struct = ObjectValue<CobblemonAttackTargetData>(this).also {
|
||||
it.addFunction("hits_until_disengage") { DoubleValue(hitsUntilDisengage.toDouble()) }
|
||||
it.addFunction("set_hits_until_disengage") { params ->
|
||||
val value = params.getDouble(0)
|
||||
hitsUntilDisengage = value.toInt()
|
||||
DoubleValue(hitsUntilDisengage.toDouble())
|
||||
}
|
||||
it.addFunction("set_disengage_action") { params ->
|
||||
val script = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val function = CobblemonScripts.scripts[script] ?: run {
|
||||
Cobblemon.LOGGER.warn("set_disengage_action was given script '$script' which does not exist.")
|
||||
return@addFunction DoubleValue.ZERO
|
||||
}
|
||||
disengageAction = { entity ->
|
||||
val runtime = MoLangRuntime().setup()
|
||||
runtime.environment.query.addFunction("entity") { entity.asMostSpecificMoLangValue() }
|
||||
runtime.resolve(function)
|
||||
}
|
||||
DoubleValue.ONE
|
||||
}
|
||||
it.addFunction("unset_disengage_action") { params ->
|
||||
disengageAction = {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -28,23 +29,35 @@ class CobblemonBehaviour(
|
||||
val visible: Boolean = true,
|
||||
val entityType: ResourceLocation? = null,
|
||||
val configurations: List<BehaviourConfig> = mutableListOf(),
|
||||
val undo: ExpressionLike? = null,
|
||||
val undoScript: ResourceLocation? = null,
|
||||
// I feel like the onAdd+onAddScript etc could be merged using some interface and a clever deserializer,
|
||||
// detect if it's a ResourceLocation and failing that, Expression. The on[..]Script fields are kinda fringe though.
|
||||
@SerializedName("onRemove", alternate = ["undo"])
|
||||
val onRemove: ExpressionLike? = null,
|
||||
@SerializedName("onRemoveScript", alternate = ["undoScript"])
|
||||
val onRemoveScript: ResourceLocation? = null,
|
||||
val onAdd: ExpressionLike? = null,
|
||||
val onAddScript: ResourceLocation? = null,
|
||||
) {
|
||||
fun canBeApplied(entity: LivingEntity) = entityType?.let { entityType == entity.type.builtInRegistryHolder().unwrapKey().get().location() } != false
|
||||
fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (onAdd != null) {
|
||||
behaviourConfigurationContext.addOnAddScript(onAdd)
|
||||
}
|
||||
if (onAddScript != null) {
|
||||
behaviourConfigurationContext.addOnAddScript(onAddScript)
|
||||
}
|
||||
configurations.forEach { it.configure(entity, behaviourConfigurationContext) }
|
||||
}
|
||||
|
||||
/** Undoes anything that needs undoing once this configuration is being removed from an entity that had it before. */
|
||||
fun undo(entity: LivingEntity) {
|
||||
fun onRemove(entity: LivingEntity) {
|
||||
val runtime = MoLangRuntime().setup()
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (undoScript != null) {
|
||||
CobblemonScripts.run(undoScript, runtime)
|
||||
if (onRemoveScript != null) {
|
||||
CobblemonScripts.run(onRemoveScript, runtime)
|
||||
}
|
||||
if (undo != null) {
|
||||
runtime.resolve(undo)
|
||||
if (onRemove != null) {
|
||||
runtime.resolve(onRemove)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.ai
|
||||
|
||||
import net.minecraft.world.entity.ai.behavior.BlockPosTracker
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
/**
|
||||
* Wraps around [BlockPosTracker] to add additional flags for Cobblemon-specific behavior.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since August 4th, 2025
|
||||
*/
|
||||
class CobblemonBlockPosTracker(
|
||||
pos: Vec3,
|
||||
val flags: Set<String> = emptySet(),
|
||||
) : BlockPosTracker(pos) {
|
||||
companion object {
|
||||
const val BATTLE_LOOK_BYPASS_FLAG = "battle_look_bypass"
|
||||
}
|
||||
|
||||
fun isBattleLookBypass() = flags.contains(BATTLE_LOOK_BYPASS_FLAG)
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.util.getBooleanOrNull
|
||||
import com.cobblemon.mod.common.util.getDoubleOrNull
|
||||
import kotlin.math.sqrt
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
|
||||
/**
|
||||
* Used to maintain some settings around how the entity should wander this tick. The idea is you
|
||||
* reset this with some script task at priority 0 then some number of steps before it gets to the wander
|
||||
* tasks you can have other conditional tasks jump in to configure parts of this.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since July 18, 2025
|
||||
*/
|
||||
class CobblemonWanderControl(
|
||||
var center: WanderCenter? = null,
|
||||
var maxAttempts: Int = 4, // How many times to try to find a suitable point before giving up on that tick.
|
||||
var allowLand: Boolean = true,
|
||||
var allowWater: Boolean = false,
|
||||
var allowAir: Boolean = false,
|
||||
var pathCooldownTicks: Int = 20 * 5, // Used to mitigate the cost of pathfinding.
|
||||
var wanderSpeed: Float = 0.35F,
|
||||
) {
|
||||
class WanderCenter(val x: Number, val y: Number, val z: Number, val minRange: Float, val maxRange: Float)
|
||||
|
||||
@Transient
|
||||
val struct: QueryStruct = QueryStruct(hashMapOf())
|
||||
.addFunction("center_x") { center?.x ?: 0.0 }
|
||||
.addFunction("center_y") { center?.y ?: 0.0 }
|
||||
.addFunction("center_z") { center?.z ?: 0.0 }
|
||||
.addFunction("max_attempts") { maxAttempts.toDouble() }
|
||||
.addFunction("min_range") { center?.minRange ?: 0.0 }
|
||||
.addFunction("max_range") { center?.maxRange ?: 0.0 }
|
||||
.addFunction("allow_land") { if (allowLand) 1.0 else 0.0 }
|
||||
.addFunction("allow_water") { if (allowWater) 1.0 else 0.0 }
|
||||
.addFunction("allow_air") { if (allowAir) 1.0 else 0.0 }
|
||||
.addFunction("path_cooldown_ticks") { pathCooldownTicks.toDouble() }
|
||||
.addFunction("wander_speed") { wanderSpeed }
|
||||
.addFunction("set_center") { params ->
|
||||
if (params.params.size < 3) {
|
||||
throw IllegalArgumentException("set_center requires at least 3 parameters: x, y, z")
|
||||
}
|
||||
val x = params.getDouble(0)
|
||||
val y = params.getDouble(1)
|
||||
val z = params.getDouble(2)
|
||||
val minRange = params.getDoubleOrNull(3) ?: 0.0
|
||||
val maxRange = params.getDoubleOrNull(4) ?: Float.MAX_VALUE.toDouble()
|
||||
center = WanderCenter(
|
||||
x = x,
|
||||
y = y,
|
||||
z = z,
|
||||
minRange = minRange.toFloat(),
|
||||
maxRange = maxRange.toFloat(),
|
||||
)
|
||||
}
|
||||
.addFunction("set_max_attempts") { params -> maxAttempts = params.getDoubleOrNull(0)?.toInt() ?: 4 }
|
||||
.addFunction("set_allow_land") { params -> allowLand = params.getBooleanOrNull(0) ?: true }
|
||||
.addFunction("set_allow_water") { params -> allowWater = params.getBooleanOrNull(0) ?: false }
|
||||
.addFunction("set_allow_air") { params -> allowAir = params.getBooleanOrNull(0) ?: false }
|
||||
.addFunction("set_path_cooldown_ticks") { params -> pathCooldownTicks = params.getDoubleOrNull(0)?.toInt() ?: (20 * 5) }
|
||||
.addFunction("set_wander_speed") { params -> wanderSpeed = params.getDoubleOrNull(0)?.toFloat() ?: 0.35F }
|
||||
.addFunction("reset") {
|
||||
center = null
|
||||
allowLand = false
|
||||
allowWater = false
|
||||
allowAir = false
|
||||
pathCooldownTicks = 20 * 5
|
||||
wanderSpeed = 0.35F
|
||||
maxAttempts = 4
|
||||
}
|
||||
|
||||
fun isSuitable(position: BlockPos): Boolean {
|
||||
val center = center ?: return true
|
||||
val centerPos = BlockPos(center.x.toInt(), center.y.toInt(), center.z.toInt())
|
||||
val distance = sqrt(centerPos.distSqr(position))
|
||||
val suitable = distance >= center.minRange && distance <= center.maxRange
|
||||
return suitable
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,11 @@ import kotlin.jvm.optionals.getOrNull
|
||||
|
||||
typealias ExpressionOrEntityVariable = Either<Expression, MoLangConfigVariable>
|
||||
|
||||
/**
|
||||
* In the case of [ExpressionOrEntityVariable] the right side is the only one that requires visibility for a user,
|
||||
* this function is a shorthand for finding all of the values in the list that have something to show the user to
|
||||
* potentially edit.
|
||||
*/
|
||||
fun List<ExpressionOrEntityVariable>.asVariables() = mapNotNull { it.right().getOrNull() }
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,20 @@ import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
/**
|
||||
* A wrapper for [BehaviorControl] that allows it to be used with any [LivingEntity]. If the class the task was
|
||||
* actually intended for is not the same as the entity being passed in, the task will just not run. This is just
|
||||
* a trick to allow type safety.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 19th, 2024
|
||||
*/
|
||||
class WrapperLivingEntityTask<T : LivingEntity>(val task: BehaviorControl<T>, val clazz: Class<T>) : BehaviorControl<LivingEntity> {
|
||||
companion object {
|
||||
inline fun <reified E : LivingEntity> BehaviorControl<E>.wrapped(): BehaviorControl<LivingEntity> {
|
||||
return WrapperLivingEntityTask(this, E::class.java)
|
||||
}
|
||||
}
|
||||
override fun tryStart(level: ServerLevel, entity: LivingEntity, gameTime: Long): Boolean {
|
||||
if (clazz.isInstance(entity)) {
|
||||
return task.tryStart(level, entity as T, gameTime)
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
/**
|
||||
* Does nothing except conditionally add some memories and sensors to the brain of the entity.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since June 27th, 2025
|
||||
*/
|
||||
class AddMemoriesAndSensorsConfig : BehaviourConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val memories: Set<MemoryModuleType<*>> = emptySet()
|
||||
val sensors: Set<SensorType<*>> = mutableSetOf()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition).asVariables()
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (!checkCondition(entity, condition)) return
|
||||
behaviourConfigurationContext.addMemories(memories)
|
||||
behaviourConfigurationContext.addSensors(sensors)
|
||||
}
|
||||
}
|
||||
@@ -23,8 +23,8 @@ class AddTasksToActivity : BehaviourConfig {
|
||||
val activities = mutableListOf<Activity>()
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val tasksByPriority = mutableMapOf<Int, List<TaskConfig>>()
|
||||
override fun getVariables(entity: LivingEntity) = tasksByPriority.values.flatten().flatMap { it.getVariables(entity) } + listOf(condition).asVariables()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = tasksByPriority.values.flatten().flatMap { it.getVariables(entity) } + listOf(condition).asVariables()
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (!checkCondition(entity, condition)) return
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ class ApplyBehaviours : BehaviourConfig {
|
||||
var condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
@SerializedName("behaviours", alternate = ["behaviors"])
|
||||
val behaviours = mutableListOf<ResourceLocation>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return if (checkCondition(entity, condition)) {
|
||||
behaviours.flatMap {
|
||||
|
||||
@@ -44,6 +44,7 @@ interface BehaviourConfig {
|
||||
cobblemonResource("set_core_activities") to SetCoreActivities::class.java,
|
||||
cobblemonResource("add_variables") to AddVariablesConfig::class.java,
|
||||
cobblemonResource("set_variables") to SetVariablesConfig::class.java,
|
||||
cobblemonResource("add_memories_and_sensors") to AddMemoriesAndSensorsConfig::class.java,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+10
-4
@@ -21,19 +21,25 @@ import com.cobblemon.mod.common.util.resolve
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class CustomScriptBehaviourConfig : BehaviourConfig {
|
||||
var condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val variables: List<MoLangConfigVariable> = emptyList()
|
||||
val script: ExpressionLike = "0".asExpressionLike()
|
||||
|
||||
companion object {
|
||||
val runtime = MoLangRuntime().setup()
|
||||
}
|
||||
|
||||
var condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val variables: List<MoLangConfigVariable> = emptyList()
|
||||
val script: ExpressionLike = "0".asExpressionLike()
|
||||
val memories = emptySet<MemoryModuleType<*>>()
|
||||
val sensors = emptySet<SensorType<*>>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = variables
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (!checkCondition(entity, condition)) return
|
||||
behaviourConfigurationContext.addMemories(memories)
|
||||
behaviourConfigurationContext.addSensors(sensors)
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
runtime.resolve(script)
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ Example:
|
||||
```json
|
||||
{
|
||||
"type": "set_variables",
|
||||
"variables": {
|
||||
"variableValues": {
|
||||
"aggressive": true,
|
||||
"attack_range": "10"
|
||||
}
|
||||
|
||||
+15
-6
@@ -14,6 +14,7 @@ import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.ai.ActivityConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addStandardFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
@@ -21,34 +22,42 @@ import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.util.activityRegistry
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import com.mojang.datafixers.util.Pair
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class ScriptBehaviourConfig : BehaviourConfig {
|
||||
val condition = "true".asExpressionLike()
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val script = cobblemonResource("dummy")
|
||||
val variables = mutableListOf<MoLangConfigVariable>()
|
||||
val memories = emptySet<MemoryModuleType<*>>()
|
||||
val sensors = emptySet<SensorType<*>>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = variables
|
||||
|
||||
override fun configure(entity: LivingEntity, context: BehaviourConfigurationContext) {
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (!checkCondition(entity, condition)) return
|
||||
val runtime = MoLangRuntime().setup()
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!runtime.resolveBoolean(condition)) return
|
||||
|
||||
val struct = createBrainStruct(entity, context)
|
||||
val struct = createBrainStruct(entity, behaviourConfigurationContext)
|
||||
val script = CobblemonScripts.scripts[this.script]
|
||||
?: run {
|
||||
Cobblemon.LOGGER.error("Tried loading script $script as part of an entity brain but that script does not exist")
|
||||
return
|
||||
}
|
||||
|
||||
behaviourConfigurationContext.addMemories(memories)
|
||||
behaviourConfigurationContext.addSensors(sensors)
|
||||
|
||||
runtime.resolve(script, mapOf("brain" to struct))
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
class SetDefaultActivity : BehaviourConfig {
|
||||
val activity: Activity = Activity.IDLE
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
behaviourConfigurationContext.defaultActivity = activity
|
||||
|
||||
@@ -23,7 +23,6 @@ class SetVariablesConfig : BehaviourConfig {
|
||||
var variableValues = mutableMapOf<String, ExpressionLike>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
val runtime = MoLangRuntime().setup()
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.OneShot
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
class ActivityChangeTaskConfig : SingleTaskConfig {
|
||||
val activity: Activity = Activity.IDLE
|
||||
val condition: ExpressionLike = "false".asExpressionLike()
|
||||
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> = emptyList()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
return object : OneShot<LivingEntity>() {
|
||||
override fun trigger(serverLevel: ServerLevel, livingEntity: LivingEntity, l: Long): Boolean {
|
||||
runtime.withQueryValue("entity", livingEntity.asMostSpecificMoLangValue())
|
||||
if (condition.resolveBoolean(runtime)) {
|
||||
livingEntity.brain.setActiveActivityIfPossible(activity)
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-2
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
@@ -47,13 +48,15 @@ class AirWanderTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.WALK_TARGET, MemoryModuleType.LOOK_TARGET, CobblemonMemories.PATH_COOLDOWN)
|
||||
val wanderChanceExpression = wanderChance.asSimplifiedExpression(entity)
|
||||
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(MemoryModuleType.WALK_TARGET),
|
||||
it.registered(MemoryModuleType.LOOK_TARGET)
|
||||
).apply(it) { walkTarget, lookTarget ->
|
||||
it.registered(MemoryModuleType.LOOK_TARGET),
|
||||
it.absent(CobblemonMemories.PATH_COOLDOWN)
|
||||
).apply(it) { walkTarget, lookTarget, pathCooldown ->
|
||||
Trigger { world, entity, time ->
|
||||
if (entity !is PathfinderMob || entity.isInWater) {
|
||||
return@Trigger false
|
||||
@@ -64,6 +67,7 @@ class AirWanderTaskConfig : SingleTaskConfig {
|
||||
if (wanderChance <= 0 || world.random.nextFloat() > wanderChance) return@Trigger false
|
||||
|
||||
val rotVec = entity.getViewVector(0F)
|
||||
pathCooldown.setWithExpiry(true, 60L)
|
||||
val target = HoverRandomPos.getPos(entity, horizontalRange.resolveInt(), verticalRange.resolveInt(), rotVec.x, rotVec.y, 1.5707964f, minUpwardsMovement.resolveInt(), minDownwardsMovement.resolveInt())
|
||||
?: return@Trigger false
|
||||
walkTarget.set(WalkTarget(target, speedMultiplier.resolveFloat(), 3))
|
||||
|
||||
+2
-9
@@ -10,9 +10,7 @@ package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
@@ -23,19 +21,14 @@ class AllOfTaskConfig : TaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val tasks: List<TaskConfig> = emptyList()
|
||||
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return if (checkCondition(entity, condition))
|
||||
tasks.flatMap { it.getVariables(entity) } + listOf(condition).asVariables()
|
||||
else
|
||||
listOf(condition).asVariables()
|
||||
}
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = tasks.flatMap { it.getVariables(entity) }
|
||||
override fun createTasks(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): List<BehaviorControl<in LivingEntity>> {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return emptyList()
|
||||
|
||||
return tasks.flatMap { it.createTasks(entity, behaviourConfigurationContext) }
|
||||
}
|
||||
}
|
||||
+5
-8
@@ -8,24 +8,21 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.ai.AttackAngryAtTask
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class AttackAngryAtTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(SharedEntityVariables.ATTACKING_CATEGORY, "should_attack_angry_at", true).asExpressible()
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition).asVariables()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.ANGRY_AT, MemoryModuleType.ATTACK_TARGET, CobblemonMemories.POKEMON_SLEEPING)
|
||||
return AttackAngryAtTask.create()
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.AttackHostileMobsTask
|
||||
import com.mojang.serialization.Codec
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class AttackHostileMobsTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return emptyList<MoLangConfigVariable>()
|
||||
}
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
return AttackHostileMobsTask.create()
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CODEC: Codec<AttackHostileMobsTaskConfig> = Codec.unit(AttackHostileMobsTaskConfig())
|
||||
}
|
||||
}
|
||||
+10
-1
@@ -12,22 +12,31 @@ import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.VillagerCalmDown
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class CalmDownTaskConfig : SingleTaskConfig {
|
||||
var condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.HURT_BY,
|
||||
MemoryModuleType.HURT_BY_ENTITY,
|
||||
MemoryModuleType.NEAREST_HOSTILE,
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.VILLAGER_HOSTILES)
|
||||
return VillagerCalmDown.create()
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
/**
|
||||
* Checks nearby entities and counts how many have nominated this entity as their leader.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since June 17th, 2025
|
||||
*/
|
||||
class CountFollowersTaskConfig : SingleTaskConfig {
|
||||
val checkTicks: ExpressionOrEntityVariable = Either.left("10".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf(checkTicks).asVariables()
|
||||
}
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val checkTicksValue = checkTicks.resolveInt()
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||||
CobblemonMemories.HERD_SIZE,
|
||||
CobblemonMemories.HERD_LEADER
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
return BehaviorBuilder.create { instance ->
|
||||
instance.group(
|
||||
instance.present(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES),
|
||||
instance.registered(CobblemonMemories.HERD_SIZE)
|
||||
).apply(instance) { nearbyEntities, herdCount ->
|
||||
Trigger { world, entity, _ ->
|
||||
if (world.gameTime % checkTicksValue != 0L) {
|
||||
return@Trigger false
|
||||
}
|
||||
val myUUID = entity.uuid.toString()
|
||||
val followersCount = instance.get(nearbyEntities).findAll {
|
||||
it is PokemonEntity
|
||||
&& it.brain.hasMemoryValue(CobblemonMemories.HERD_LEADER)
|
||||
&& it.brain.getMemory(CobblemonMemories.HERD_LEADER).getOrNull() == myUUID
|
||||
}.count()
|
||||
if (followersCount == 0) {
|
||||
herdCount.erase()
|
||||
} else {
|
||||
herdCount.set(followersCount)
|
||||
}
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -23,7 +23,7 @@ class DoNothingTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val minDurationTicks: ExpressionOrEntityVariable = Either.left("40".asExpression())
|
||||
val maxDurationTicks: ExpressionOrEntityVariable = Either.left("80".asExpression())
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition, minDurationTicks, maxDurationTicks).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = listOf(minDurationTicks, maxDurationTicks).asVariables()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
|
||||
+4
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
@@ -16,6 +17,7 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.EatGrassTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class EatGrassTaskConfig : SingleTaskConfig {
|
||||
companion object {
|
||||
@@ -47,6 +49,8 @@ class EatGrassTaskConfig : SingleTaskConfig {
|
||||
return null
|
||||
}
|
||||
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.WALK_TARGET, CobblemonMemories.RECENTLY_ATE_GRASS)
|
||||
|
||||
return WrapperLivingEntityTask(
|
||||
EatGrassTask(
|
||||
chance,
|
||||
|
||||
+13
-1
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
@@ -21,6 +22,7 @@ import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class ExitBattleWhenHurtTaskConfig : SingleTaskConfig {
|
||||
var condition = booleanVariable(SharedEntityVariables.BATTLING_CATEGORY, "exit_battle_when_hurt", true).asExpressible()
|
||||
@@ -36,10 +38,19 @@ class ExitBattleWhenHurtTaskConfig : SingleTaskConfig {
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val includePassiveDamage = includePassiveDamage.resolveBoolean()
|
||||
if (!condition.resolveBoolean()) return null
|
||||
|
||||
val includePassiveDamage = includePassiveDamage.resolveBoolean()
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.HURT_BY,
|
||||
MemoryModuleType.HURT_BY_ENTITY
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.HURT_BY)
|
||||
|
||||
if (entity is NPCEntity) {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.NPC_BATTLING)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.NPC_BATTLING)
|
||||
fun cancelNPCBattles(npcEntity: NPCEntity): Boolean {
|
||||
val battles = npcEntity.battleIds.mapNotNull(BattleRegistry::getBattle)
|
||||
battles.forEach { it.end() }
|
||||
@@ -58,6 +69,7 @@ class ExitBattleWhenHurtTaskConfig : SingleTaskConfig {
|
||||
}
|
||||
}
|
||||
} else if (entity is PokemonEntity) {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.POKEMON_BATTLE)
|
||||
fun cancelPokemonBattle(pokemonEntity: PokemonEntity): Boolean {
|
||||
val battle = BattleRegistry.getBattle(pokemonEntity.battleId ?: return false)
|
||||
battle?.end()
|
||||
|
||||
+4
@@ -43,6 +43,10 @@ class FindAirTaskConfig : SingleTaskConfig {
|
||||
if (entity !is PathfinderMob) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
CobblemonMemories.PATH_COOLDOWN
|
||||
)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(MemoryModuleType.WALK_TARGET),
|
||||
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.ai.ToleratedHerdLeader
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class FindHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
companion object {
|
||||
/**
|
||||
* Logic used to choose the best herd leader from nearby visible entities.
|
||||
*
|
||||
* - Higher tier leaders are always preferred.
|
||||
* - Same-tier leaders that are closer are preferred except for when they're the same tier as the current leader.
|
||||
* - We don't want to exceed the target's herd size limit.
|
||||
* - We don't want to choose a leader that is themselves following a leader.
|
||||
* - Some leader definitions allow lower-level Pokémon to lead them.
|
||||
* - Leaders just have to not be in a party - pastured and wild Pokémon can mingle.
|
||||
*/
|
||||
fun getBestHerdLeader(
|
||||
currentLeader: Pair<PokemonEntity, ToleratedHerdLeader>?,
|
||||
nearbyEntities: NearestVisibleLivingEntities,
|
||||
entity: PokemonEntity
|
||||
): PokemonEntity? {
|
||||
var bestLeader: PokemonEntity? = null
|
||||
val (currentLeaderEntity, currentLeaderDefinition) = currentLeader ?: Pair(null, null)
|
||||
var bestTier = currentLeaderDefinition?.tier?.let { it + 1 } ?: 0 // Only upgrade to a higher tier leader
|
||||
var bestDistance = Float.MAX_VALUE
|
||||
nearbyEntities.findAll {
|
||||
it is PokemonEntity &&
|
||||
it != currentLeader &&
|
||||
it.pokemon.storeCoordinates.get()?.store !is PartyStore &&
|
||||
it.getHerdSize() < it.behaviour.herd.maxSize
|
||||
}.forEach { possibleLeader ->
|
||||
possibleLeader as PokemonEntity
|
||||
val matchingHerdLeader = entity.behaviour.herd.bestMatchLeader(entity, possibleLeader) ?: return@forEach
|
||||
val alreadyIsALeader = possibleLeader.brain.hasMemoryValue(CobblemonMemories.HERD_SIZE)
|
||||
val nestedHerdTier = currentLeaderEntity?.getHerdTier() ?: 0
|
||||
if (nestedHerdTier >= matchingHerdLeader.tier) {
|
||||
return@forEach // This leader is following a leader of a higher tier, we can't replace them
|
||||
}
|
||||
val distance = entity.distanceTo(possibleLeader)
|
||||
if (matchingHerdLeader.tier < bestTier) {
|
||||
return@forEach // No need to check further if this leader is worse than the best found so far
|
||||
} else if ((distance > bestDistance && !alreadyIsALeader) && matchingHerdLeader.tier == bestTier) {
|
||||
return@forEach // No need to check further if this leader is farther than the best found so far, unless they are already a leader - I'd prefer to join a pack
|
||||
} else {
|
||||
bestLeader = possibleLeader
|
||||
bestDistance = distance
|
||||
bestTier = matchingHerdLeader.tier
|
||||
}
|
||||
}
|
||||
return bestLeader ?: currentLeaderEntity
|
||||
}
|
||||
}
|
||||
|
||||
// How frequently to check for whether it should herd. Probably isn't that expensive but might use this for chance.
|
||||
val checkTicks: ExpressionOrEntityVariable = Either.left("60".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf(checkTicks).asVariables()
|
||||
}
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||||
CobblemonMemories.HERD_LEADER,
|
||||
MemoryModuleType.WALK_TARGET
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val checkTicksValue = checkTicks.resolveInt()
|
||||
return BehaviorBuilder.create { instance ->
|
||||
instance.group(
|
||||
instance.present(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES),
|
||||
instance.absent(CobblemonMemories.HERD_LEADER)
|
||||
).apply(instance) { nearbyEntities, herdLeader ->
|
||||
Trigger { world, entity, _ ->
|
||||
if (world.gameTime % checkTicksValue != 0L) {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
entity as PokemonEntity
|
||||
val bestLeader = getBestHerdLeader(
|
||||
currentLeader = null,
|
||||
nearbyEntities = instance.get(nearbyEntities),
|
||||
entity = entity
|
||||
) ?: return@Trigger false
|
||||
|
||||
herdLeader.set(bestLeader.uuid.toString())
|
||||
bestLeader.brain.eraseMemory(CobblemonMemories.HERD_LEADER)
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
@@ -8,6 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
@@ -18,6 +20,7 @@ import com.cobblemon.mod.common.util.asExpression
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class FindRestingPlaceTaskConfig : SingleTaskConfig {
|
||||
val horizontalSearchDistance: ExpressionOrEntityVariable = Either.left("16".asExpression())
|
||||
@@ -28,6 +31,13 @@ class FindRestingPlaceTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(
|
||||
CobblemonMemories.PATH_COOLDOWN,
|
||||
CobblemonMemories.POKEMON_DROWSY,
|
||||
MemoryModuleType.WALK_TARGET
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.POKEMON_DROWSY)
|
||||
|
||||
return WrapperLivingEntityTask(
|
||||
FindRestingPlaceTask.create(horizontalSearchDistance.resolveInt(), verticalSearchDistance.resolveInt()),
|
||||
PokemonEntity::class.java
|
||||
|
||||
+5
@@ -20,6 +20,7 @@ import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.SetWalkTargetAwayFrom
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class FleeAttackerTaskConfig : SingleTaskConfig {
|
||||
var condition = booleanVariable(SharedEntityVariables.FEAR_CATEGORY, "flee_attacker", true).asExpressible()
|
||||
@@ -38,6 +39,10 @@ class FleeAttackerTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean() || entity !is PathfinderMob) return null
|
||||
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.WALK_TARGET)
|
||||
behaviourConfigurationContext.addSensors(SensorType.HURT_BY)
|
||||
|
||||
val speedMultiplier = speedMultiplier.resolveFloat()
|
||||
val desiredDistance = desiredDistance.resolveInt()
|
||||
return WrapperLivingEntityTask(
|
||||
|
||||
+3
@@ -20,6 +20,7 @@ import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.SetWalkTargetAwayFrom
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class FleeNearestHostileTaskConfig : SingleTaskConfig {
|
||||
var condition = booleanVariable(SharedEntityVariables.FEAR_CATEGORY, "flee_nearest_hostile", true).asExpressible()
|
||||
@@ -34,6 +35,8 @@ class FleeNearestHostileTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean() || entity !is PathfinderMob) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.NEAREST_HOSTILE, MemoryModuleType.WALK_TARGET)
|
||||
behaviourConfigurationContext.addSensors(SensorType.VILLAGER_HOSTILES)
|
||||
val speedMultiplier = speedMultiplier.resolveFloat()
|
||||
val desiredDistance = desiredDistance.resolveInt()
|
||||
return WrapperLivingEntityTask(
|
||||
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask.Companion.wrapped
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.ai.config.task.WanderTaskConfig.Companion.WANDER
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.ai.CircleAroundTask
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class FlyInCirclesTaskConfig : SingleTaskConfig {
|
||||
val poseTypes: Set<PoseType> = setOf(
|
||||
PoseType.FLY,
|
||||
PoseType.HOVER
|
||||
)
|
||||
|
||||
val minAngularVelocityDegrees = numberVariable(WANDER, "min_fly_circling_angular_velocity", 0.0).asExpressible()
|
||||
val maxAngularVelocityDegrees = numberVariable(WANDER, "max_fly_circling_angular_velocity", 1.0).asExpressible()
|
||||
val speed = numberVariable(WANDER, "fly_circling_speed", 0.6).asExpressible()
|
||||
val verticalSpeed: ExpressionOrEntityVariable = Either.left("0.0".asExpression())
|
||||
val minDurationTicks: ExpressionOrEntityVariable = Either.left("60".asExpression())
|
||||
val maxDurationTicks: ExpressionOrEntityVariable = Either.left("180".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf(
|
||||
minAngularVelocityDegrees,
|
||||
maxAngularVelocityDegrees,
|
||||
speed,
|
||||
verticalSpeed,
|
||||
minDurationTicks,
|
||||
maxDurationTicks
|
||||
).asVariables()
|
||||
}
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.WALK_TARGET, MemoryModuleType.PATH)
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
return CircleAroundTask(
|
||||
poseTypes = poseTypes,
|
||||
minTurnAngleDegrees = minAngularVelocityDegrees.resolveFloat(),
|
||||
maxTurnAngleDegrees = maxAngularVelocityDegrees.resolveFloat(),
|
||||
speed = speed.resolveFloat(),
|
||||
verticalSpeed = verticalSpeed.resolveFloat(),
|
||||
minDurationTicks = minDurationTicks.resolveFloat().toInt(),
|
||||
maxDurationTicks = maxDurationTicks.resolveFloat().toInt()
|
||||
).wrapped<PokemonEntity>()
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask.Companion.wrapped
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.ai.FollowHerdLeaderTask
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class FollowHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf()
|
||||
}
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.HERD_LEADER, MemoryModuleType.WALK_TARGET)
|
||||
return FollowHerdLeaderTask().wrapped<PokemonEntity>()
|
||||
}
|
||||
}
|
||||
+2
@@ -20,6 +20,7 @@ import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class FollowWalkTargetTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
@@ -30,6 +31,7 @@ class FollowWalkTargetTaskConfig : SingleTaskConfig {
|
||||
|
||||
override fun createTask(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): BehaviorControl<LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.WALK_TARGET, MemoryModuleType.PATH, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)
|
||||
return WrapperLivingEntityTask(
|
||||
FollowWalkTargetTask(minRunTicks.resolveInt(), maxRunTicks.resolveInt()),
|
||||
PathfinderMob::class.java
|
||||
|
||||
+7
@@ -16,6 +16,8 @@ import com.cobblemon.mod.common.entity.ai.GetAngryAtAttackerTask
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class GetAngryAtAttackerTaskConfig : SingleTaskConfig {
|
||||
companion object {
|
||||
@@ -32,6 +34,11 @@ class GetAngryAtAttackerTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.HURT_BY_ENTITY,
|
||||
MemoryModuleType.ANGRY_AT,
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.HURT_BY)
|
||||
return GetAngryAtAttackerTask.create()
|
||||
}
|
||||
}
|
||||
+10
-1
@@ -8,6 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
@@ -18,6 +20,8 @@ import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class GoToHealingMachineTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(SELF_HEALING, USE_HEALING_MACHINES, true).asExpressible()
|
||||
@@ -39,7 +43,12 @@ class GoToHealingMachineTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
MemoryModuleType.LOOK_TARGET,
|
||||
CobblemonMemories.NPC_BATTLING
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.NPC_BATTLING)
|
||||
return GoToHealingMachineTask.create(
|
||||
horizontalSearchRange = horizontalSearchRange.asExpression(),
|
||||
verticalSearchRange = verticalSearchRange.asExpression(),
|
||||
|
||||
+9
-3
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.OmniPathingEntity
|
||||
import com.cobblemon.mod.common.util.closestPosition
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.floor
|
||||
@@ -43,7 +44,10 @@ class GoToLandTaskConfig : SingleTaskConfig {
|
||||
if (entity !is PathfinderMob) {
|
||||
return null
|
||||
}
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
CobblemonMemories.PATH_COOLDOWN
|
||||
)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(MemoryModuleType.WALK_TARGET),
|
||||
@@ -56,6 +60,8 @@ class GoToLandTaskConfig : SingleTaskConfig {
|
||||
|
||||
entity as PathfinderMob
|
||||
|
||||
val walkSpeedValue = walkSpeed.resolveFloat()
|
||||
|
||||
val iterable = BlockPos.betweenClosed(
|
||||
Mth.floor(entity.x - 8.0),
|
||||
entity.blockY,
|
||||
@@ -71,7 +77,7 @@ class GoToLandTaskConfig : SingleTaskConfig {
|
||||
isSafeLandPosAround(entity.level() as ServerLevel, it, entity)
|
||||
} ?: return@Trigger false
|
||||
|
||||
walkTarget.set(WalkTarget(blockPos.above(), 0.35F, 1))
|
||||
walkTarget.set(WalkTarget(blockPos.above(), walkSpeedValue, 0))
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
@@ -82,7 +88,7 @@ class GoToLandTaskConfig : SingleTaskConfig {
|
||||
val blockState = world.getBlockState(pos)
|
||||
|
||||
val isFluid = world.getFluidState(pos.above()).isEmpty.not()
|
||||
val solidBelow = blockState.isSolid
|
||||
val solidBelow = blockState.isSolid || (mob is OmniPathingEntity && mob.canFly())
|
||||
|
||||
if (isFluid || !solidBelow) {
|
||||
return false
|
||||
|
||||
+12
@@ -8,6 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
@@ -15,6 +17,7 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.GoToSleepTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class GoToSleepTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
@@ -22,6 +25,15 @@ class GoToSleepTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
CobblemonMemories.POKEMON_DROWSY,
|
||||
CobblemonMemories.POKEMON_SLEEPING
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.POKEMON_DROWSY)
|
||||
return WrapperLivingEntityTask(GoToSleepTask.create(), PokemonEntity::class.java)
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
/**
|
||||
* Immediately gets angry at the nearest visible entity that matches the [entityCondition] and is within the [range].
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since June 23rd, 2025
|
||||
*/
|
||||
class HateEntityTaskConfig : SingleTaskConfig {
|
||||
val entityCondition: Expression = "true".asExpression()
|
||||
val range: ExpressionOrEntityVariable = Either.left("24".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
val range = range.resolveFloat()
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||||
MemoryModuleType.ANGRY_AT
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
return BehaviorBuilder.create { instance ->
|
||||
instance.group(
|
||||
instance.present(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES),
|
||||
instance.registered(MemoryModuleType.ANGRY_AT)
|
||||
).apply(instance) { entities, angryAt ->
|
||||
Trigger { world, entity, _ ->
|
||||
val target = instance.get(entities).findClosest {
|
||||
runtime.withQueryValue("entity", it.asMostSpecificMoLangValue())
|
||||
return@findClosest runtime.resolveBoolean(entityCondition)
|
||||
}.orElse(null)
|
||||
|
||||
if (target != null && target.distanceTo(entity) <= range) {
|
||||
angryAt.set(target.uuid)
|
||||
}
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -8,6 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
@@ -20,6 +22,7 @@ import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class HealUsingHealingMachineTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(SELF_HEALING, USE_HEALING_MACHINES, true).asExpressible()
|
||||
@@ -34,6 +37,8 @@ class HealUsingHealingMachineTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.WALK_TARGET, CobblemonMemories.NPC_BATTLING,)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.NPC_BATTLING)
|
||||
return HealUsingHealingMachineTask(horizontalUseRange.asExpression(), verticalUseRange.asExpression())
|
||||
}
|
||||
}
|
||||
+8
@@ -8,6 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
@@ -18,6 +20,7 @@ import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class LookAtBattlingPokemonTaskConfig : SingleTaskConfig {
|
||||
companion object {
|
||||
@@ -40,6 +43,11 @@ class LookAtBattlingPokemonTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!resolveBooleanVariable(LOOK_AT_BATTLING_POKEMON)) return null
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.LOOK_TARGET,
|
||||
CobblemonMemories.BATTLING_POKEMON
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.BATTLING_POKEMON)
|
||||
return LookAtBattlingPokemonTask.create(
|
||||
minDurationTicks = minDurationTicks.resolveInt(),
|
||||
maxDurationTicks = maxDurationTicks.resolveInt()
|
||||
|
||||
+4
@@ -16,6 +16,8 @@ import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.SetEntityLookTarget
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class LookAtEntitiesTaskConfig : SingleTaskConfig {
|
||||
companion object {
|
||||
@@ -36,6 +38,8 @@ class LookAtEntitiesTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.LOOK_TARGET)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
return SetEntityLookTarget.create(maxDistance.resolveFloat())
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -8,15 +8,19 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.npc.ai.LookAtSpeakerTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class LookAtSpeakerTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
) = LookAtSpeakerTask.create()
|
||||
) = LookAtSpeakerTask.create().also {
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.LOOK_TARGET, CobblemonMemories.DIALOGUES)
|
||||
}
|
||||
}
|
||||
+4
@@ -20,6 +20,8 @@ import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.Mob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.LookAtTargetSink
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class LookAtTargetTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
@@ -38,6 +40,8 @@ class LookAtTargetTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.LOOK_TARGET, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
return WrapperLivingEntityTask(LookAtTargetSink(minDurationTicks.resolveInt(), maxDurationTicks.resolveInt()), Mob::class.java)
|
||||
}
|
||||
}
|
||||
+11
-1
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
@@ -15,13 +16,22 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.LookAtTargetedBattlePokemonTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class LookAtTargetedBattlePokemonTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity> {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(
|
||||
CobblemonMemories.POKEMON_BATTLE,
|
||||
CobblemonMemories.TARGETED_BATTLE_POKEMON,
|
||||
MemoryModuleType.LOOK_TARGET,
|
||||
)
|
||||
return WrapperLivingEntityTask(LookAtTargetedBattlePokemonTask.create(), PokemonEntity::class.java)
|
||||
}
|
||||
}
|
||||
+4
-1
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.ai.config.task.SharedEntityVariables.LOOKING_CATEGORY
|
||||
import com.cobblemon.mod.common.entity.ai.LookInDirectionTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class LookInDirectionTaskConfig : SingleTaskConfig {
|
||||
var condition = booleanVariable(LOOKING_CATEGORY, "locked_rotation", true).asExpressible()
|
||||
@@ -32,5 +33,7 @@ class LookInDirectionTaskConfig : SingleTaskConfig {
|
||||
shouldLock = condition.asExpression(),
|
||||
yaw = yaw.asExpression(),
|
||||
pitch = pitch.asExpression()
|
||||
)
|
||||
).also {
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.LOOK_TARGET)
|
||||
}
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import java.util.UUID
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
/**
|
||||
* Task that looks around for a better herd leader or gives up on a leader
|
||||
* that is themselves following a different Pokémon.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since June 16th, 2025
|
||||
*/
|
||||
class MaintainHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
// How frequently to check for a better herd leader
|
||||
val checkTicks: ExpressionOrEntityVariable = Either.left("60".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf(checkTicks).asVariables()
|
||||
}
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(
|
||||
CobblemonMemories.HERD_LEADER,
|
||||
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val checkTicks = checkTicks.resolveInt()
|
||||
return BehaviorBuilder.create { instance ->
|
||||
instance.group(
|
||||
instance.present(CobblemonMemories.HERD_LEADER),
|
||||
instance.present(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES)
|
||||
).apply(instance) { herdLeader, nearbyEntities ->
|
||||
Trigger { world, entity, _ ->
|
||||
entity as PokemonEntity
|
||||
if (world.gameTime % checkTicks != 0L) {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
val leader = instance.get(herdLeader).let(UUID::fromString).let(world::getEntity) as? PokemonEntity
|
||||
val currentLeaderDefinition = leader?.let { leader ->
|
||||
entity.behaviour.herd.toleratedLeaders.find { it.pokemon.matches(leader) }
|
||||
}
|
||||
if (leader == null || currentLeaderDefinition == null) {
|
||||
entity.brain.eraseMemory(CobblemonMemories.HERD_LEADER)
|
||||
return@Trigger true // No leader, so we erase the memory
|
||||
} else {
|
||||
val bestLeader = FindHerdLeaderTaskConfig.getBestHerdLeader(
|
||||
currentLeader = (leader to currentLeaderDefinition),
|
||||
nearbyEntities = instance.get(nearbyEntities),
|
||||
entity = entity
|
||||
)
|
||||
|
||||
if (bestLeader != null && bestLeader != leader) {
|
||||
bestLeader.brain.eraseMemory(CobblemonMemories.HERD_LEADER)
|
||||
entity.brain.setMemory(CobblemonMemories.HERD_LEADER, bestLeader.uuid.toString())
|
||||
}
|
||||
}
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.ManageFlightInBattleTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class ManageFlightInBattleTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.POKEMON_BATTLE)
|
||||
return ManageFlightInBattleTask.create()
|
||||
}
|
||||
}
|
||||
+6
-2
@@ -15,11 +15,12 @@ import com.cobblemon.mod.common.entity.npc.ai.MeleeAttackTask
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class MeleeAttackTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(SharedEntityVariables.ATTACKING_CATEGORY, "attacks_melee", true).asExpressible()
|
||||
val range = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "melee_range", 1.5F).asExpressible()
|
||||
val cooldownTicks = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "melee_cooldown", 30).asExpressible()
|
||||
val cooldownTicks = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "melee_cooldown", 20).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
condition,
|
||||
@@ -33,7 +34,10 @@ class MeleeAttackTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.ATTACK_TARGET,
|
||||
MemoryModuleType.ATTACK_COOLING_DOWN
|
||||
)
|
||||
return MeleeAttackTask.create(
|
||||
range = range.asExpression(),
|
||||
cooldownTicks = cooldownTicks.asExpression()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user