forked from mirrors/cobblemon
Compare commits
1700
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ccd0bbe11 | ||
|
|
d289880cc8 | ||
|
|
6609c7d038 | ||
|
|
88afe05c16 | ||
|
|
99aa25e1bf | ||
|
|
76faa50035 | ||
|
|
8ce989cb6b | ||
|
|
02030950aa | ||
|
|
6148b58fdc | ||
|
|
1e4936aeac | ||
|
|
15ea72e777 | ||
|
|
3c3d4e4552 | ||
|
|
796e416578 | ||
|
|
7608dfde94 | ||
|
|
b2b871617a | ||
|
|
bc4c8d13b7 | ||
|
|
0f9c51f7dd | ||
|
|
2c2623e0f9 | ||
|
|
8ec85e7d2f | ||
|
|
d5a08314eb | ||
|
|
062c32be2a | ||
|
|
09590b49cd | ||
|
|
420cbd2c99 | ||
|
|
0380013f37 | ||
|
|
6c1fcc103a | ||
|
|
59b01c3988 | ||
|
|
678fa2d0ce | ||
|
|
94abd79923 | ||
|
|
0a1931aaae | ||
|
|
85d76dcc29 | ||
|
|
bd0a9ef654 | ||
|
|
7a702e276c | ||
|
|
3f9a2825cb | ||
|
|
d1462bc27b | ||
|
|
211b14dbd0 | ||
|
|
47e83003c3 | ||
|
|
59134c4212 | ||
|
|
44b434562c | ||
|
|
7af9b0854a | ||
|
|
344b0750f9 | ||
|
|
10d9d97c11 | ||
|
|
94bcfba076 | ||
|
|
69a75ffcd4 | ||
|
|
cc1317dd06 | ||
|
|
e15ac73b1b | ||
|
|
6c6576c117 | ||
|
|
ebdfa7edc0 | ||
|
|
297e8eae77 | ||
|
|
ea8179018d | ||
|
|
14fccfae1d | ||
|
|
26386638ad | ||
|
|
5d1d99b64a | ||
|
|
a3c5a6c377 | ||
|
|
eb2a5837eb | ||
|
|
93298d9a87 | ||
|
|
abb5346305 | ||
|
|
9466f66721 | ||
|
|
716ea55bc7 | ||
|
|
4d1f46c37c | ||
|
|
15f0ad1821 | ||
|
|
a2101b5759 | ||
|
|
187a190ec6 | ||
|
|
0d433ff394 | ||
|
|
a16975c750 | ||
|
|
c0e6d87c40 | ||
|
|
91078b917e | ||
|
|
b7e27fa52a | ||
|
|
dc87ffd2a8 | ||
|
|
d873399d05 | ||
|
|
a7aab51e0d | ||
|
|
e8e2057558 | ||
|
|
56b5dba911 | ||
|
|
f0a66458e5 | ||
|
|
dba6a38f9e | ||
|
|
342c0041e9 | ||
|
|
cbeda361d4 | ||
|
|
a811b3347c | ||
|
|
80e593f5c6 | ||
|
|
ff617348fe | ||
|
|
1adecbf5f6 | ||
|
|
29dbb13a0e | ||
|
|
67e03ecebd | ||
|
|
215f48bdc7 | ||
|
|
d4beab1bfb | ||
|
|
f2c21ec902 | ||
|
|
c9f3912677 | ||
|
|
c21b7d1a7d | ||
|
|
26068694ad | ||
|
|
c86d8f0696 | ||
|
|
16468059e4 | ||
|
|
54dbe4769e | ||
|
|
82019c3722 | ||
|
|
079a2fb50d | ||
|
|
78f0951345 | ||
|
|
96aaab29e2 | ||
|
|
b1def44953 | ||
|
|
e2e38add1d | ||
|
|
1db0b0709a | ||
|
|
c3ce3db387 | ||
|
|
b5e6fd3816 | ||
|
|
5b5dcddb25 | ||
|
|
0158524bff | ||
|
|
2611e311a7 | ||
|
|
17061691a1 | ||
|
|
9c6d7ddfef | ||
|
|
e8119198c1 | ||
|
|
55c0e3e8a0 | ||
|
|
70443bc7b0 | ||
|
|
acb166b5b9 | ||
|
|
462c361998 | ||
|
|
76c90fb1ae | ||
|
|
27e11dee87 | ||
|
|
d7c8b8dd62 | ||
|
|
eb12ccf6d0 | ||
|
|
e7b58edcd1 | ||
|
|
ca5c2ba381 | ||
|
|
8aa538d8e7 | ||
|
|
1bd33a0635 | ||
|
|
ff9ca4ee09 | ||
|
|
1def8fcd1a | ||
|
|
d53603ec49 | ||
|
|
5362995fbb | ||
|
|
e2d0b12f94 | ||
|
|
b32c2cb81c | ||
|
|
98a7240191 | ||
|
|
84adc0e1cb | ||
|
|
3ab2dfa0b3 | ||
|
|
d67669a278 | ||
|
|
2a85dee373 | ||
|
|
86e8238230 | ||
|
|
bdc7b5a504 | ||
|
|
f3c165d282 | ||
|
|
9caf8376bc | ||
|
|
8661f7a01e | ||
|
|
e933a03e92 | ||
|
|
982fc054a9 | ||
|
|
cb73bfb31b | ||
|
|
5b84c2c8a0 | ||
|
|
9f998d92e6 | ||
|
|
b835bfe596 | ||
|
|
757e3d48cb | ||
|
|
2fbf77dd65 | ||
|
|
bd451bf951 | ||
|
|
d88a9dda92 | ||
|
|
86c2282cf8 | ||
|
|
ac85cddeb6 | ||
|
|
a9c2373979 | ||
|
|
6ac8523cf5 | ||
|
|
acb0aa854e | ||
|
|
d5cff3ba06 | ||
|
|
8e22538707 | ||
|
|
f161699b6a | ||
|
|
fdafb1e64a | ||
|
|
b0119e32c5 | ||
|
|
58bab4b94b | ||
|
|
a91bf60ff8 | ||
|
|
2d4c419216 | ||
|
|
981f7307e6 | ||
|
|
c04345a789 | ||
|
|
93e84e6ffd | ||
|
|
cc6305bfec | ||
|
|
7d38efaa50 | ||
|
|
9a3f5a605a | ||
|
|
bd525c8740 | ||
|
|
b9922057ce | ||
|
|
d9c765ca53 | ||
|
|
96c3f7764e | ||
|
|
255930751a | ||
|
|
d3f32ee645 | ||
|
|
e444206a55 | ||
|
|
209dee1d25 | ||
|
|
e58acd646f | ||
|
|
bdcc05aa78 | ||
|
|
bb899118ef | ||
|
|
71585174c0 | ||
|
|
1eedc4862a | ||
|
|
b1fbf9ca02 | ||
|
|
3449c98b56 | ||
|
|
5fda445274 | ||
|
|
60aa991d55 | ||
|
|
8da0fc34c6 | ||
|
|
41c55d80a8 | ||
|
|
09dfbccb8e | ||
|
|
ce0265e954 | ||
|
|
a66d263dd8 | ||
|
|
5a929e3901 | ||
|
|
da1654d9aa | ||
|
|
27132031cd | ||
|
|
cdc4a571b6 | ||
|
|
e8bc138e5d | ||
|
|
038d239f95 | ||
|
|
d95db24426 | ||
|
|
a64cbb7e8a | ||
|
|
9b2a1dc065 | ||
|
|
3c222a3349 | ||
|
|
e2ba1dc575 | ||
|
|
f7e381924e | ||
|
|
a1035608c9 | ||
|
|
2345565e38 | ||
|
|
f4c2a5197c | ||
|
|
620002c165 | ||
|
|
361a8fcbe1 | ||
|
|
e179e044ef | ||
|
|
d89224a684 | ||
|
|
f55d8737ba | ||
|
|
336180656e | ||
|
|
856eb2a1bd | ||
|
|
620589681d | ||
|
|
8359b1ade1 | ||
|
|
136d7c08b8 | ||
|
|
ddc03766bb | ||
|
|
81dccf9c07 | ||
|
|
ea93b8c1d8 | ||
|
|
8018c1142a | ||
|
|
cfca238573 | ||
|
|
e3cf367e45 | ||
|
|
b9b01af451 | ||
|
|
1abe39db3c | ||
|
|
4e7cdb6266 | ||
|
|
79b13acdc6 | ||
|
|
c68f637b70 | ||
|
|
d44126179a | ||
|
|
432b350d98 | ||
|
|
26677420dd | ||
|
|
a1487e4ee5 | ||
|
|
78b2a7d721 | ||
|
|
d4a3dfdb07 | ||
|
|
0f3dcb760e | ||
|
|
0ffd6fad90 | ||
|
|
3c9661dfd3 | ||
|
|
520f522f3c | ||
|
|
113ae1f749 | ||
|
|
61bf5ffab1 | ||
|
|
0e1b59fb25 | ||
|
|
3565015039 | ||
|
|
218b90860b | ||
|
|
a59573073f | ||
|
|
6475d7d732 | ||
|
|
c467e98345 | ||
|
|
6b206cfaaf | ||
|
|
8aac4c294f | ||
|
|
2e330076b8 | ||
|
|
e1cd217290 | ||
|
|
87da3e83a0 | ||
|
|
c325d0215a | ||
|
|
8afb4e6d16 | ||
|
|
60f00ca34d | ||
|
|
416a2ac390 | ||
|
|
0ffff6f4af | ||
|
|
690ada8271 | ||
|
|
b1b06f19b2 | ||
|
|
5bc41245ad | ||
|
|
490fa91ce7 | ||
|
|
8606d6928d | ||
|
|
5897b43564 | ||
|
|
9fd8d32215 | ||
|
|
03c278229b | ||
|
|
8ce3322105 | ||
|
|
364d084584 | ||
|
|
916e6de1d2 | ||
|
|
0b9e706a36 | ||
|
|
6d4f529fc0 | ||
|
|
015de548d3 | ||
|
|
04ca03b3a5 | ||
|
|
c7c145ab78 | ||
|
|
a376863953 | ||
|
|
2e68c3fc44 | ||
|
|
36f2eee7f9 | ||
|
|
71ac29ba8b | ||
|
|
781c82230e | ||
|
|
c58d49ebab | ||
|
|
fd8d5630f4 | ||
|
|
a86b11fdd5 | ||
|
|
829dca9d99 | ||
|
|
0f0368f3bd | ||
|
|
6533030d36 | ||
|
|
0efb0d9767 | ||
|
|
8151f9b3e6 | ||
|
|
4e8ffd3558 | ||
|
|
b88873fbc3 | ||
|
|
dba1ab26a5 | ||
|
|
cc2295d629 | ||
|
|
4d3d8d1607 | ||
|
|
1d09360844 | ||
|
|
079e75d828 | ||
|
|
a3567ead04 | ||
|
|
f4fef2855b | ||
|
|
6f614eb02e | ||
|
|
72b82858b3 | ||
|
|
361047c309 | ||
|
|
18f43f72ad | ||
|
|
cbb409b057 | ||
|
|
f8cec09f70 | ||
|
|
5579975b46 | ||
|
|
5a57f41fbb | ||
|
|
1845faf9ad | ||
|
|
0e93682457 | ||
|
|
cef69f478d | ||
|
|
5ea7bc9c48 | ||
|
|
bfc8ace83a | ||
|
|
e0f93fd797 | ||
|
|
ba13414ada | ||
|
|
66c63d54db | ||
|
|
9e836bcc3b | ||
|
|
27fb1f6c66 | ||
|
|
7f60885f92 | ||
|
|
cb7f6d7bba | ||
|
|
a3498fe03b | ||
|
|
af4af3395c | ||
|
|
3ab07ecbca | ||
|
|
b96eccbf2f | ||
|
|
afa7426116 | ||
|
|
a5ace52cb5 | ||
|
|
9f3940bb31 | ||
|
|
8a8c131a44 | ||
|
|
8b0fba4201 | ||
|
|
e1e04b19bf | ||
|
|
a04beb1ce8 | ||
|
|
bd9aea7c59 | ||
|
|
757e3a7ff7 | ||
|
|
66d03651f9 | ||
|
|
3c1577d58f | ||
|
|
dd7d562228 | ||
|
|
a01ac32e54 | ||
|
|
5c0ae854bf | ||
|
|
55c189b749 | ||
|
|
b5b81fa1aa | ||
|
|
eda58859ce | ||
|
|
3888a48cb0 | ||
|
|
c9b609a3f8 | ||
|
|
70fb7c87ad | ||
|
|
a24189b816 | ||
|
|
c0d80634a4 | ||
|
|
b52e4de85c | ||
|
|
7d37a98a58 | ||
|
|
a424796aa8 | ||
|
|
8518be0d44 | ||
|
|
24760270bd | ||
|
|
19f9490274 | ||
|
|
93a94f04a1 | ||
|
|
97eac48cd7 | ||
|
|
2c31f002b2 | ||
|
|
4f0eb16ab0 | ||
|
|
5004b61967 | ||
|
|
cf137efa02 | ||
|
|
862c0bda89 | ||
|
|
868874b06d | ||
|
|
068e4a1c92 | ||
|
|
267f2aa5a8 | ||
|
|
333d8fa732 | ||
|
|
e8d4e406d5 | ||
|
|
9e5c296309 | ||
|
|
69dc89b04f | ||
|
|
dd31fb1a51 | ||
|
|
9b3a729b3c | ||
|
|
ed732429b9 | ||
|
|
8d27394665 | ||
|
|
943c421b1d | ||
|
|
cc9541c146 | ||
|
|
538f72c474 | ||
|
|
c72ab20cfa | ||
|
|
3cfc915b1a | ||
|
|
b8541486d4 | ||
|
|
c69b38454e | ||
|
|
0e5787b8ab | ||
|
|
082be6f2d0 | ||
|
|
398f14efd5 | ||
|
|
4ba33c2a80 | ||
|
|
e8ace8ba05 | ||
|
|
1a78625111 | ||
|
|
596c2b95b4 | ||
|
|
38648111a6 | ||
|
|
149b8f27e6 | ||
|
|
dc78e40941 | ||
|
|
ca7e2054fe | ||
|
|
14ea73332f | ||
|
|
91433d7e13 | ||
|
|
85aadbabe9 | ||
|
|
8fed14e706 | ||
|
|
e64c1487cf | ||
|
|
2c16e5c20d | ||
|
|
21505bc5de | ||
|
|
a365aca9ca | ||
|
|
19b70e1fbb | ||
|
|
e1ec69f4cf | ||
|
|
c23e506570 | ||
|
|
28a4805cd3 | ||
|
|
8d3a895591 | ||
|
|
e8089d6a5d | ||
|
|
88988c21f1 | ||
|
|
cf4409e61d | ||
|
|
516343406c | ||
|
|
5ecbf33a6b | ||
|
|
4d866f6207 | ||
|
|
e81418836e | ||
|
|
03786a9845 | ||
|
|
d199e372ca | ||
|
|
8022bfefc8 | ||
|
|
eb82d6d6a9 | ||
|
|
5be8fdd03d | ||
|
|
3d779e637b | ||
|
|
bd0ad89971 | ||
|
|
0a0532c8cc | ||
|
|
586ced7bfb | ||
|
|
e1551ba70b | ||
|
|
9e05ef3e8c | ||
|
|
ea1608c8d2 | ||
|
|
218f2c67d3 | ||
|
|
045ddb30ca | ||
|
|
bf3e26874f | ||
|
|
bfbdadb519 | ||
|
|
6b2bd64eec | ||
|
|
59e300582c | ||
|
|
dd75b898a6 | ||
|
|
b3bd2e26cd | ||
|
|
475f8de2e6 | ||
|
|
096785d7ec | ||
|
|
c09c85ffd8 | ||
|
|
9f5acfbf62 | ||
|
|
d0ddf3bb11 | ||
|
|
50624a4e34 | ||
|
|
19733e53c9 | ||
|
|
277e72912c | ||
|
|
59b0397ea4 | ||
|
|
aadb78149c | ||
|
|
23c80bb82c | ||
|
|
143f9dba3c | ||
|
|
2fb019ce8a | ||
|
|
487b59f7b5 | ||
|
|
b06c2253ae | ||
|
|
3305874dd4 | ||
|
|
2f688291dc | ||
|
|
457c2ab84d | ||
|
|
1f099b231c | ||
|
|
c1ccc718cc | ||
|
|
972d09e920 | ||
|
|
74df81006b | ||
|
|
e7a87e299c | ||
|
|
c0bef49e2c | ||
|
|
44c9ca3c6b | ||
|
|
d02fe990f6 | ||
|
|
53e133ab94 | ||
|
|
c688e9f80c | ||
|
|
ac1897b41a | ||
|
|
40e8f4efa5 | ||
|
|
e00165aafb | ||
|
|
7d7c4fa3e2 | ||
|
|
3c5c4b9cd0 | ||
|
|
a83546a1da | ||
|
|
af6405b078 | ||
|
|
ae5021a851 | ||
|
|
ebbe4bb0e1 | ||
|
|
ebe93f531c | ||
|
|
e489bcde07 | ||
|
|
64a3f2dd28 | ||
|
|
ba15ca3d02 | ||
|
|
4b79d51f7b | ||
|
|
4c68b0f837 | ||
|
|
b2015c9cd8 | ||
|
|
eaf0d7ec80 | ||
|
|
d0b796f777 | ||
|
|
83488ec728 | ||
|
|
b3d387d8da | ||
|
|
d9770b17f0 | ||
|
|
b9b4b1c2e7 | ||
|
|
13f33f935c | ||
|
|
3fbcfe842d | ||
|
|
d5503f7fa9 | ||
|
|
fd3e599636 | ||
|
|
a70a258e64 | ||
|
|
8121cb4e87 | ||
|
|
a1ef50a8ec | ||
|
|
c9c5488be7 | ||
|
|
f356dd98b2 | ||
|
|
ce7e465d99 | ||
|
|
902c6751c5 | ||
|
|
463d341965 | ||
|
|
4088f144e4 | ||
|
|
3e592b21f1 | ||
|
|
b1186c8033 | ||
|
|
d038f63024 | ||
|
|
b5a0866b31 | ||
|
|
6b1d17ea5d | ||
|
|
49fe33f9db | ||
|
|
7a3088eb59 | ||
|
|
32ff4557a7 | ||
|
|
de51d2b1b2 | ||
|
|
3c3aa3d4a3 | ||
|
|
50e4829b79 | ||
|
|
e4b3136bc9 | ||
|
|
0815a93ee0 | ||
|
|
ebdd06a4a9 | ||
|
|
82fd4bae08 | ||
|
|
277a7dc32b | ||
|
|
f00d578f64 | ||
|
|
ea9fba72ec | ||
|
|
4654c3c2b8 | ||
|
|
b4496b30a9 | ||
|
|
431662b237 | ||
|
|
1299214d61 | ||
|
|
c5c2c3a059 | ||
|
|
64b7970cb5 | ||
|
|
ce6c777c4e | ||
|
|
284b032dd8 | ||
|
|
23d70ab1fe | ||
|
|
9414cc096a | ||
|
|
7f7774ce90 | ||
|
|
6fde014c67 | ||
|
|
3340239440 | ||
|
|
e513d52c3d | ||
|
|
ba54401c49 | ||
|
|
2d4723d981 | ||
|
|
d91292cfb6 | ||
|
|
7156c99b92 | ||
|
|
7320e3b9cc | ||
|
|
c217d6b754 | ||
|
|
87af7745ae | ||
|
|
91005cf217 | ||
|
|
e888012b8b | ||
|
|
43fef815ab | ||
|
|
0f55a28c65 | ||
|
|
0e724118ff | ||
|
|
88e843b46c | ||
|
|
06a5e67617 | ||
|
|
7b5eb7c869 | ||
|
|
cc283b200f | ||
|
|
44779c68f5 | ||
|
|
f43cd175ce | ||
|
|
a6f725df02 | ||
|
|
538bf148bc | ||
|
|
df67a6659b | ||
|
|
84d5634b79 | ||
|
|
f313e82004 | ||
|
|
c9320ca019 | ||
|
|
58b932e35e | ||
|
|
db9634c254 | ||
|
|
9ff9329c21 | ||
|
|
b06628e6ba | ||
|
|
e74012e2a7 | ||
|
|
b5cfcd5999 | ||
|
|
eccba938c7 | ||
|
|
d6f71abb51 | ||
|
|
92f55cd23f | ||
|
|
6dbd668856 | ||
|
|
d762ee2e1b | ||
|
|
ae87bb2423 | ||
|
|
7fd7abf7d6 | ||
|
|
13367df87b | ||
|
|
2eb7dfdfa2 | ||
|
|
bbb031d484 | ||
|
|
ad7bb84d5c | ||
|
|
69eb396229 | ||
|
|
06abdaf683 | ||
|
|
79e0c2f1bf | ||
|
|
d0b50bc2a8 | ||
|
|
dbee413af5 | ||
|
|
21a1d839ae | ||
|
|
353f7f6d33 | ||
|
|
1c5863877b | ||
|
|
374a6fa321 | ||
|
|
33a350089f | ||
|
|
35b28075e4 | ||
|
|
8066823186 | ||
|
|
9660e64dff | ||
|
|
d2e95ceefd | ||
|
|
f992a9cf0f | ||
|
|
c36f6933aa | ||
|
|
54112f02b5 | ||
|
|
e98fc55dcb | ||
|
|
2f907988fb | ||
|
|
8b350ddb4b | ||
|
|
cbf03289a6 | ||
|
|
57db94eb00 | ||
|
|
70850d546d | ||
|
|
5fe1dfbfff | ||
|
|
c81494bec2 | ||
|
|
cd965961ae | ||
|
|
52238abe35 | ||
|
|
7594582520 | ||
|
|
a240e4e48c | ||
|
|
4dc279b664 | ||
|
|
8b371127ed | ||
|
|
b3e59b5151 | ||
|
|
abfaec1d05 | ||
|
|
e503ddbc69 | ||
|
|
643b43d8bc | ||
|
|
5c5c236d1b | ||
|
|
ee4e9dd250 | ||
|
|
27cb0dc449 | ||
|
|
7efd4e182d | ||
|
|
5781c18868 | ||
|
|
b43e5e180e | ||
|
|
be439dfc24 | ||
|
|
913d11cccc | ||
|
|
d6f208366e | ||
|
|
d82c4ed444 | ||
|
|
6ddf2ee5f9 | ||
|
|
4f537a2b37 | ||
|
|
5060762894 | ||
|
|
dbf42cb102 | ||
|
|
db75ceefa8 | ||
|
|
abaec8778b | ||
|
|
f186f03f54 | ||
|
|
ad2949ceb1 | ||
|
|
ff79a17299 | ||
|
|
ac169120d6 | ||
|
|
3f6a4bbae4 | ||
|
|
6100252b3e | ||
|
|
27be7c6eaf | ||
|
|
18b3cf4236 | ||
|
|
194528b78d | ||
|
|
edd4d18150 | ||
|
|
8c7478d00a | ||
|
|
5c18bfdad3 | ||
|
|
0e328b2166 | ||
|
|
e9fcb80d8c | ||
|
|
01b3b2952d | ||
|
|
f28db32356 | ||
|
|
dd5f2c2821 | ||
|
|
51a65e6cec | ||
|
|
df1dc67cbb | ||
|
|
dd81579d72 | ||
|
|
a2b62bea48 | ||
|
|
c4323f79ba | ||
|
|
f1ac43c9c1 | ||
|
|
ce581de613 | ||
|
|
176b5143f5 | ||
|
|
be94e1c8ad | ||
|
|
bed13364c6 | ||
|
|
1fe392e57b | ||
|
|
4391b5947e | ||
|
|
499778dd21 | ||
|
|
9c7af03837 | ||
|
|
db740d7b5d | ||
|
|
58a4123db2 | ||
|
|
e10ccf2d1b | ||
|
|
25138beb88 | ||
|
|
d72332a3cc | ||
|
|
8986220597 | ||
|
|
e04e1db9d4 | ||
|
|
142ded7f61 | ||
|
|
a9eaeed47f | ||
|
|
de08562607 | ||
|
|
675855a22a | ||
|
|
da24a40b7e | ||
|
|
2049bf68b3 | ||
|
|
1aeb1e207b | ||
|
|
a37edfaa19 | ||
|
|
2d43bb518f | ||
|
|
e70b7a4d6e | ||
|
|
8f16e236e7 | ||
|
|
fce23a6898 | ||
|
|
483589dbec | ||
|
|
0177860ebf | ||
|
|
58b8c3676e | ||
|
|
32f6db33ae | ||
|
|
d8af56cab1 | ||
|
|
e04437f3d3 | ||
|
|
79aed2ac43 | ||
|
|
db6e604420 | ||
|
|
9b7856520f | ||
|
|
388b3891e5 | ||
|
|
50742f298d | ||
|
|
9cf4177f31 | ||
|
|
550383e275 | ||
|
|
4f0f08213d | ||
|
|
91042b5bb7 | ||
|
|
88261125c0 | ||
|
|
eb528e6534 | ||
|
|
2982ef1c30 | ||
|
|
813c949216 | ||
|
|
4ba2563e92 | ||
|
|
356f668067 | ||
|
|
85e2ccef63 | ||
|
|
8b34bb0229 | ||
|
|
c4999dc328 | ||
|
|
e484159a18 | ||
|
|
4ca850d2e7 | ||
|
|
3447caea22 | ||
|
|
f66a94649b | ||
|
|
c495e967af | ||
|
|
745bae1451 | ||
|
|
5fabc1bfaf | ||
|
|
3aa6969fba | ||
|
|
5ed69a17a4 | ||
|
|
73c9504d63 | ||
|
|
94f0796c44 | ||
|
|
63ea4c1261 | ||
|
|
63c352e5ca | ||
|
|
9a8c4a8630 | ||
|
|
0f9df28a82 | ||
|
|
886242e13b | ||
|
|
303ef76bd0 | ||
|
|
bfc6d8b446 | ||
|
|
af24f5acbe | ||
|
|
3986781a74 | ||
|
|
a16d374ff3 | ||
|
|
f224f32495 | ||
|
|
d31e65ea93 | ||
|
|
9e27c1ec85 | ||
|
|
b02edb7f78 | ||
|
|
04b0915290 | ||
|
|
aaa1338150 | ||
|
|
e2243feee1 | ||
|
|
c26bd59c21 | ||
|
|
b83f605da3 | ||
|
|
f7d2776f7d | ||
|
|
18ad6006ca | ||
|
|
46ba44545c | ||
|
|
cc446cb36e | ||
|
|
91e5ad88ab | ||
|
|
89a8a702c1 | ||
|
|
7a6a374acc | ||
|
|
60d18e6522 | ||
|
|
fc438520ba | ||
|
|
00836d8e51 | ||
|
|
e1290682f8 | ||
|
|
d82998bbeb | ||
|
|
3cb5b6fd3f | ||
|
|
e692afe86a | ||
|
|
61680b9f21 | ||
|
|
0a52e70027 | ||
|
|
8a06113b5e | ||
|
|
77397929cb | ||
|
|
402973f814 | ||
|
|
89d5660a5f | ||
|
|
8d513618d3 | ||
|
|
8b5bc78b5a | ||
|
|
1cfa1ce9fd | ||
|
|
f52ce88756 | ||
|
|
a5b7e335db | ||
|
|
b9f46447b5 | ||
|
|
f57050e4e3 | ||
|
|
e504ba4dc7 | ||
|
|
52036deb06 | ||
|
|
08f3adceb0 | ||
|
|
115493c3a4 | ||
|
|
c160545cf1 | ||
|
|
66d9e0ad9b | ||
|
|
9e7e116528 | ||
|
|
89fa5c7837 | ||
|
|
8bd9d113dc | ||
|
|
d7718b7f3e | ||
|
|
49944a073b | ||
|
|
90183cb81e | ||
|
|
1f81c42294 | ||
|
|
a7ed6400b2 | ||
|
|
188b504575 | ||
|
|
e59d5ee6f3 | ||
|
|
ea4d170756 | ||
|
|
d7c3107635 | ||
|
|
ef8a5ce76b | ||
|
|
85d2d4aca8 | ||
|
|
72a9b82bd9 | ||
|
|
adbfa16076 | ||
|
|
8055aed5ab | ||
|
|
95c0055932 | ||
|
|
d553257060 | ||
|
|
3069ae9722 | ||
|
|
ed05d7b754 | ||
|
|
2c546f00b3 | ||
|
|
f407051c4b | ||
|
|
9f179bb573 | ||
|
|
36d8c3520d | ||
|
|
6105d15a03 | ||
|
|
1176af0641 | ||
|
|
ad958f91fe | ||
|
|
4e821962e3 | ||
|
|
962720a12c | ||
|
|
e580d5abb1 | ||
|
|
f9821ad698 | ||
|
|
ad35bf1f8a | ||
|
|
02baa3f44f | ||
|
|
1cc4be5d28 | ||
|
|
f10e617203 | ||
|
|
a77a6d21eb | ||
|
|
8dc3b7be42 | ||
|
|
58286d8bb5 | ||
|
|
e41a6d7c7d | ||
|
|
a1b6bd79d2 | ||
|
|
3528f0bec0 | ||
|
|
dff6c3dc5c | ||
|
|
96b234a313 | ||
|
|
c97b94dcc2 | ||
|
|
87c8ae373b | ||
|
|
ed94d2bd1a | ||
|
|
d7ac0128a7 | ||
|
|
4c35714dfe | ||
|
|
660636034b | ||
|
|
f54ed2924d | ||
|
|
a432854023 | ||
|
|
40760f2c74 | ||
|
|
ae65b2c2b1 | ||
|
|
d917e81804 | ||
|
|
67a468a006 | ||
|
|
9ad39ffd8f | ||
|
|
e96958e1b7 | ||
|
|
f168e319a2 | ||
|
|
bc23445cbc | ||
|
|
58fed2361f | ||
|
|
5e13da3e65 | ||
|
|
19a6bf28e4 | ||
|
|
03bc8a1b40 | ||
|
|
7ea2746c2b | ||
|
|
38b6322649 | ||
|
|
e37e73f530 | ||
|
|
4f2fefe2bd | ||
|
|
a1d4f499e0 | ||
|
|
e7389bf129 | ||
|
|
79a6cb5a1d | ||
|
|
9e4720b233 | ||
|
|
426cd50bb1 | ||
|
|
51bc9b9c67 | ||
|
|
9439070325 | ||
|
|
cbe9356723 | ||
|
|
60baf23baa | ||
|
|
be6d4f80d8 | ||
|
|
df660329df | ||
|
|
0d33618e83 | ||
|
|
0803906f30 | ||
|
|
2c26046a3c | ||
|
|
641c91d335 | ||
|
|
bdab3d04cb | ||
|
|
98eb43d13d | ||
|
|
ca839432aa | ||
|
|
59488974d6 | ||
|
|
df6f200b63 | ||
|
|
3f0561456f | ||
|
|
5279767829 | ||
|
|
e3f8aacd9e | ||
|
|
d381dd0d21 | ||
|
|
23f98f3a7d | ||
|
|
02f3d87bc6 | ||
|
|
2dad3c3197 | ||
|
|
ea8e70d0fa | ||
|
|
64717be354 | ||
|
|
bc9314b9d9 | ||
|
|
541f2dac40 | ||
|
|
adba69c675 | ||
|
|
ab831a2d9d | ||
|
|
faa939986a | ||
|
|
b651bf1ded | ||
|
|
8eb77cfc97 | ||
|
|
a51c8ae6d1 | ||
|
|
5809b07443 | ||
|
|
3fb4ca05fe | ||
|
|
19323143e5 | ||
|
|
89de0c6392 | ||
|
|
ddddfec219 | ||
|
|
b3c6d205ab | ||
|
|
b1e2eec156 | ||
|
|
46bb33a95f | ||
|
|
39b169082c | ||
|
|
c13e9fb35d | ||
|
|
5cc7dfa353 | ||
|
|
d4dab7b88a | ||
|
|
6b697a7be1 | ||
|
|
90fbe3be49 | ||
|
|
50dd1b154d | ||
|
|
83eb483f0b | ||
|
|
ea3e389c41 | ||
|
|
10ed864325 | ||
|
|
0e9013c75e | ||
|
|
e54b22409a | ||
|
|
65afff1c3c | ||
|
|
230a2db160 | ||
|
|
0fdadc90e8 | ||
|
|
e03a3abe1d | ||
|
|
497f832995 | ||
|
|
5aeae2b350 | ||
|
|
ecd71fe077 | ||
|
|
9c5a04495d | ||
|
|
6d3ddece03 | ||
|
|
b60fc26a97 | ||
|
|
c1a95d0f3f | ||
|
|
99a0e83962 | ||
|
|
7572530a36 | ||
|
|
8ee0d904ed | ||
|
|
d8498d7a37 | ||
|
|
291196eda7 | ||
|
|
b94e6d65b9 | ||
|
|
3693e7eec0 | ||
|
|
7f9ed14be7 | ||
|
|
f3e6e5a94c | ||
|
|
325c4093eb | ||
|
|
2510b23401 | ||
|
|
d4b6f6e55e | ||
|
|
60c9f5d054 | ||
|
|
3d38dc2c99 | ||
|
|
6cc384abbb | ||
|
|
3fd04bcdb4 | ||
|
|
205ec6a228 | ||
|
|
943625056a | ||
|
|
06e0bbc502 | ||
|
|
d83d5cd3da | ||
|
|
6215f8afa5 | ||
|
|
60fdd3325e | ||
|
|
eedcdafcbe | ||
|
|
b39068283f | ||
|
|
34c4cc1579 | ||
|
|
e1541a3512 | ||
|
|
b2e1558e03 | ||
|
|
34595e01a9 | ||
|
|
60b9ca7b7f | ||
|
|
83aea117c6 | ||
|
|
1c1c3f51bb | ||
|
|
90bd717d7b | ||
|
|
78b348329c | ||
|
|
b64013c995 | ||
|
|
a945bad5b5 | ||
|
|
edde3b16bf | ||
|
|
85003c9829 | ||
|
|
d9133e854a | ||
|
|
500f1f53a4 | ||
|
|
9ed10bb217 | ||
|
|
ffaee877a7 | ||
|
|
186f7dbbce | ||
|
|
4ae9b25d35 | ||
|
|
b35fe23831 | ||
|
|
16165a2e68 | ||
|
|
cdec0e5640 | ||
|
|
2f6d4313e7 | ||
|
|
05afe191e6 | ||
|
|
87db8aadfe | ||
|
|
36921f439c | ||
|
|
e3b5067f31 | ||
|
|
bfa2d470f0 | ||
|
|
53c0b28deb | ||
|
|
d640a04fa6 | ||
|
|
5e9208d898 | ||
|
|
23a91ec2c9 | ||
|
|
9998a328e3 | ||
|
|
9f07747cac | ||
|
|
a7998bcec5 | ||
|
|
5983b29e9c | ||
|
|
749f441913 | ||
|
|
dabbcceb9c | ||
|
|
11f8313fc3 | ||
|
|
32b813620b | ||
|
|
8147067b2e | ||
|
|
f2d2ceb422 | ||
|
|
547ceae9ed | ||
|
|
24c6544e83 | ||
|
|
7749f346b5 | ||
|
|
a2fe6364cd | ||
|
|
a921d55812 | ||
|
|
b422ee4d29 | ||
|
|
a83867e153 | ||
|
|
523973d2c0 | ||
|
|
746160fa18 | ||
|
|
837ba9679b | ||
|
|
db7a319441 | ||
|
|
e284032c7e | ||
|
|
3db9dd02f2 | ||
|
|
e680ec8790 | ||
|
|
dc4f831e02 | ||
|
|
b3a00c40b5 | ||
|
|
f56fb0f50a | ||
|
|
ec732bc03d | ||
|
|
229abd4a13 | ||
|
|
7e92c17178 | ||
|
|
77aa3208a0 | ||
|
|
79688ebdad | ||
|
|
16d8c8bb19 | ||
|
|
e5738fecb0 | ||
|
|
a29bc68663 | ||
|
|
1358380905 | ||
|
|
a03090d0da | ||
|
|
d9d5229a1f | ||
|
|
34e64da0c6 | ||
|
|
a46ac372a8 | ||
|
|
b2ea715195 | ||
|
|
e6d2430405 | ||
|
|
6c425a43c6 | ||
|
|
2679885fb4 | ||
|
|
278c5d8e81 | ||
|
|
7327ae14fd | ||
|
|
8b6c8d27b7 | ||
|
|
a505bad554 | ||
|
|
e27e5a1d92 | ||
|
|
a55916998b | ||
|
|
cca2d54682 | ||
|
|
f5bd6a4054 | ||
|
|
13466815e5 | ||
|
|
5e0357101d | ||
|
|
5420f7419f | ||
|
|
43ed2d3c7d | ||
|
|
93500f59ed | ||
|
|
08912fd53f | ||
|
|
92c8fc0afc | ||
|
|
fae6bdb782 | ||
|
|
bba0100542 | ||
|
|
f9b66de742 | ||
|
|
3d0f1c826a | ||
|
|
2a59add285 | ||
|
|
35e4aafe99 | ||
|
|
0b83128aa0 | ||
|
|
e2b04ff770 | ||
|
|
4dabe50d43 | ||
|
|
3dd0795b88 | ||
|
|
70f1a8207f | ||
|
|
3ac18cce6e | ||
|
|
aa0a0672d0 | ||
|
|
ec2958400b | ||
|
|
fcb6bea78b | ||
|
|
5a76a39b77 | ||
|
|
b5a4acfb7a | ||
|
|
1248230e67 | ||
|
|
096db6cdcd | ||
|
|
72e416b9c7 | ||
|
|
9e8e80965b | ||
|
|
2325b436b1 | ||
|
|
57421a2884 | ||
|
|
4fdd3eba8e | ||
|
|
e6efe800c0 | ||
|
|
95aa99e18c | ||
|
|
270484e745 | ||
|
|
719addf633 | ||
|
|
31e386871f | ||
|
|
bfd7e596d0 | ||
|
|
eab6fa9b40 | ||
|
|
643545d54c | ||
|
|
e871047cf1 | ||
|
|
ea4af39853 | ||
|
|
1440ed692e | ||
|
|
444657a468 | ||
|
|
a1de8c95f6 | ||
|
|
fcb017f980 | ||
|
|
eb94bdb9c2 | ||
|
|
509c2365bb | ||
|
|
6271476ed3 | ||
|
|
f5cec10e3e | ||
|
|
b6f20c1d75 | ||
|
|
dd52da7c42 | ||
|
|
ff45def0e8 | ||
|
|
f078584e56 | ||
|
|
a11382b5a1 | ||
|
|
750d583770 | ||
|
|
05f0b439a8 | ||
|
|
1cb4ffd02f | ||
|
|
8600d026c3 | ||
|
|
8140dd773e | ||
|
|
23717a634c | ||
|
|
c966e93f22 | ||
|
|
f49c01916a | ||
|
|
4e24c764de | ||
|
|
d1b8094539 | ||
|
|
b8d79af911 | ||
|
|
98de423f91 | ||
|
|
89c2fb49cd | ||
|
|
ae05be2ce2 | ||
|
|
5f2984a3d0 | ||
|
|
de41fdf871 | ||
|
|
af491f02a2 | ||
|
|
e40a3331e2 | ||
|
|
6dac494a0f | ||
|
|
246ddc7a54 | ||
|
|
f7c560db78 | ||
|
|
bae7ad5ce1 | ||
|
|
2e59fa4f68 | ||
|
|
474cf1c6db | ||
|
|
8cd46a5a49 | ||
|
|
382bf67866 | ||
|
|
c7d93ebfc5 | ||
|
|
ef4fbecad6 | ||
|
|
96075ed34a | ||
|
|
e7cd9237f6 | ||
|
|
84e22c68c7 | ||
|
|
300f2fc53c | ||
|
|
2dfb88467b | ||
|
|
589aab3b1a | ||
|
|
e17ca3a422 | ||
|
|
0153846c7b | ||
|
|
155b4b2182 | ||
|
|
192d40a475 | ||
|
|
690ed845b2 | ||
|
|
8c86bb636d | ||
|
|
5dc43a8d58 | ||
|
|
68a3d7e3b1 | ||
|
|
f598f8d645 | ||
|
|
8e3e047646 | ||
|
|
551858df57 | ||
|
|
a7e3f4a7a1 | ||
|
|
94d64bb5c6 | ||
|
|
002e68b599 | ||
|
|
2ac2a57e12 | ||
|
|
b84002d142 | ||
|
|
8f4b2c3c0a | ||
|
|
6645cb68f7 | ||
|
|
e569acc648 | ||
|
|
7c374b6e29 | ||
|
|
3c128d9009 | ||
|
|
f5321a34c3 | ||
|
|
f96ea92a4c | ||
|
|
a1e10bf3b1 | ||
|
|
eccb4bb7af | ||
|
|
254d5e1343 | ||
|
|
4c5f330f2a | ||
|
|
00d445b793 | ||
|
|
a3cb3e8d9e | ||
|
|
69354fac58 | ||
|
|
d40f3599b9 | ||
|
|
cd236c2dea | ||
|
|
aebf40f78c | ||
|
|
52b28fb73f | ||
|
|
531ed8b827 | ||
|
|
fc844fca9e | ||
|
|
23bfa090d2 | ||
|
|
2754bfc525 | ||
|
|
9b75f20fff | ||
|
|
3d1aecce13 | ||
|
|
56b1fc1149 | ||
|
|
662ca83a60 | ||
|
|
d80ff055f5 | ||
|
|
898f48cf8f | ||
|
|
3bd5d4849c | ||
|
|
9519b51c8e | ||
|
|
a7198fd324 | ||
|
|
bc69ce91f3 | ||
|
|
1de1d8cdc3 | ||
|
|
c78e884e9e | ||
|
|
1688dd42b3 | ||
|
|
e98ba597dd | ||
|
|
7c93834b2c | ||
|
|
38cd081ad6 | ||
|
|
54a14ab805 | ||
|
|
633b45287c | ||
|
|
3619f42090 | ||
|
|
695453ffdb | ||
|
|
1f8171dd94 | ||
|
|
087bf75500 | ||
|
|
bac435ba7b | ||
|
|
b67bfca556 | ||
|
|
0fe8caf88f | ||
|
|
1b4360f0c6 | ||
|
|
74a6106eb6 | ||
|
|
5ec993ad3c | ||
|
|
b5bb385106 | ||
|
|
c4e8fe9c74 | ||
|
|
73a03d90da | ||
|
|
3ecaf2dd13 | ||
|
|
281afd74e6 | ||
|
|
e6fda6137e | ||
|
|
afae39acc8 | ||
|
|
37264aff0f | ||
|
|
2b60e6de77 | ||
|
|
3c2bf0e2b3 | ||
|
|
ac695b1092 | ||
|
|
4f29e7457c | ||
|
|
04a6ab31f4 | ||
|
|
a2cdc847dd | ||
|
|
0bca678f56 | ||
|
|
067c3607aa | ||
|
|
823c1f6444 | ||
|
|
bfc00635cd | ||
|
|
b2e5b85ac5 | ||
|
|
dd7066e8fa | ||
|
|
416f003927 | ||
|
|
3be3dc3de2 | ||
|
|
2c27476954 | ||
|
|
aab78d84fc | ||
|
|
cb632c2a65 | ||
|
|
8d219f1338 | ||
|
|
1e6a4ed984 | ||
|
|
64240c31fc | ||
|
|
d2222c3858 | ||
|
|
c7f31c3e14 | ||
|
|
740e846b2d | ||
|
|
246d00aa3f | ||
|
|
06f9d60595 | ||
|
|
a8f273737d | ||
|
|
a185805b3f | ||
|
|
defab6eaff | ||
|
|
b3ed47fbca | ||
|
|
72fc1f1fb9 | ||
|
|
f96c69ab54 | ||
|
|
3a6ad70b76 | ||
|
|
d51039dbb8 | ||
|
|
6d69b91243 | ||
|
|
a12aee34d9 | ||
|
|
8120270bf8 | ||
|
|
d54439ce14 | ||
|
|
32ee4bb72a | ||
|
|
7bcf47fc35 | ||
|
|
e7d2a46cc0 | ||
|
|
3ee94ec076 | ||
|
|
589293abc4 | ||
|
|
279865cc7c | ||
|
|
b597b149c3 | ||
|
|
b7f592f2a8 | ||
|
|
70e17c22e7 | ||
|
|
51b18ca0f6 | ||
|
|
a83f243a3b | ||
|
|
f5b088c708 | ||
|
|
dc454cbb68 | ||
|
|
3b99e38da2 | ||
|
|
483af57964 | ||
|
|
a941bdddf3 | ||
|
|
246ba4a93b | ||
|
|
3347c084ed | ||
|
|
8175cee454 | ||
|
|
37d54053a5 | ||
|
|
b8846bd74c | ||
|
|
1716e135c4 | ||
|
|
0ac804cfcb | ||
|
|
aecc132814 | ||
|
|
8b47876dff | ||
|
|
ffc108953a | ||
|
|
0a106174fe | ||
|
|
90210bee3c | ||
|
|
8603cd4ad0 | ||
|
|
7b2c6827c2 | ||
|
|
902b4a6d21 | ||
|
|
a847cb5926 | ||
|
|
050c6f5adc | ||
|
|
fb95fb3cf7 | ||
|
|
d507367411 | ||
|
|
faa19cebcb | ||
|
|
aced374367 | ||
|
|
d424a6f1d3 | ||
|
|
71bb1c32de | ||
|
|
f726fcedb9 | ||
|
|
77344ccc2f | ||
|
|
90bc16be90 | ||
|
|
d1b743a01f | ||
|
|
aed651c0a0 | ||
|
|
4c477e1675 | ||
|
|
d1cdc6789c | ||
|
|
70fe1682b0 | ||
|
|
9058bde326 | ||
|
|
bf425efd40 | ||
|
|
cd3127b983 | ||
|
|
68f5eff048 | ||
|
|
cebff87656 | ||
|
|
d24fb13877 | ||
|
|
c3d2918a2b | ||
|
|
1d82df464a | ||
|
|
0432525c06 | ||
|
|
a60f27e282 | ||
|
|
5f0182cb7e | ||
|
|
4a3ae9407b | ||
|
|
766c2838d2 | ||
|
|
4cb95589b4 | ||
|
|
a8d3c2dd52 | ||
|
|
cb5d7b6ad7 | ||
|
|
c7dcc64595 | ||
|
|
6573e08da7 | ||
|
|
cd695ade4a | ||
|
|
55cb413cfc | ||
|
|
4f1bf7fcbb | ||
|
|
154ee80ead | ||
|
|
1c9f9bb198 | ||
|
|
6836343f11 | ||
|
|
aa0d1cd943 | ||
|
|
798f1da8b3 | ||
|
|
d98efb52b6 | ||
|
|
f450d9d2d6 | ||
|
|
2f27a03f08 | ||
|
|
e33025b1fa | ||
|
|
ade2481f42 | ||
|
|
0752ab3cac | ||
|
|
576e2301ce | ||
|
|
a568d45d75 | ||
|
|
bc19a7e4c1 | ||
|
|
616e438f17 | ||
|
|
9bb11c46d5 | ||
|
|
5f470bb703 | ||
|
|
276f13cea5 | ||
|
|
ac069687f1 | ||
|
|
f248c22eed | ||
|
|
65a5687f92 | ||
|
|
ea50fa534b | ||
|
|
4bd3c4af58 | ||
|
|
283d80f7ed | ||
|
|
0238ca80f0 | ||
|
|
d24c5fe874 | ||
|
|
e65e21f2ff | ||
|
|
e1d417718f | ||
|
|
d4308b0a4f | ||
|
|
2a1d1e4474 | ||
|
|
bc0d530484 | ||
|
|
56650418d2 | ||
|
|
0543b84d34 | ||
|
|
1f50687a59 | ||
|
|
ed04faf0d8 | ||
|
|
1ed020f3e0 | ||
|
|
7e385d8c94 | ||
|
|
ee509b5438 | ||
|
|
ac9394131c | ||
|
|
d058a306a7 | ||
|
|
b9be0c3fcb | ||
|
|
b59b46568a | ||
|
|
408cbc8c49 | ||
|
|
1537816132 | ||
|
|
1705639950 | ||
|
|
ce32541dd6 | ||
|
|
3ffea4f4dd | ||
|
|
fe35a63769 | ||
|
|
f942d7c34a | ||
|
|
0f1ada4624 | ||
|
|
b4ee4629bf | ||
|
|
d0b64e2d82 | ||
|
|
a8ce3c2175 | ||
|
|
80ae127379 | ||
|
|
bd3a9fb3af | ||
|
|
d0eaccb81b | ||
|
|
1ed2042283 | ||
|
|
0b531d967e | ||
|
|
b0d1aec9ab | ||
|
|
f4d47098b5 | ||
|
|
1989b8aa92 | ||
|
|
948ca61ef3 | ||
|
|
e60aca30ba | ||
|
|
fb5055c39e | ||
|
|
dfb5650121 | ||
|
|
8a0cbf28fe | ||
|
|
a6b9060d57 | ||
|
|
8e57995e44 | ||
|
|
1d8257808c | ||
|
|
e290fe9c75 | ||
|
|
06a50cfeeb | ||
|
|
00888c8ad5 | ||
|
|
17cab186d9 | ||
|
|
e00136052d | ||
|
|
e3582ccfb4 | ||
|
|
4c6822b1c6 | ||
|
|
b23237ca9a | ||
|
|
2e6a4c7341 | ||
|
|
8edb5e1013 | ||
|
|
6fb139cbb9 | ||
|
|
c81c95142b | ||
|
|
afde822860 | ||
|
|
474c386535 | ||
|
|
3963e83717 | ||
|
|
7893e365da | ||
|
|
71b9ae8dee | ||
|
|
b87b47d62a | ||
|
|
2bb85718d7 | ||
|
|
ee187d7b89 | ||
|
|
b6a7051b2c | ||
|
|
3532cac278 | ||
|
|
1447ab25b4 | ||
|
|
9a06ca78c6 | ||
|
|
f6ba70634b | ||
|
|
148fd04a93 | ||
|
|
17f60623ee | ||
|
|
c5ece27c11 | ||
|
|
296ccd1a76 | ||
|
|
82a4f71f24 | ||
|
|
2cb1cf2f83 | ||
|
|
f13a4e0e24 | ||
|
|
17e1bbd6a1 | ||
|
|
c36ff0a0fe | ||
|
|
08b58e2f78 | ||
|
|
62d2b8db2d | ||
|
|
3869f7ed93 | ||
|
|
8dbb350230 | ||
|
|
c9c44872d6 | ||
|
|
cae53efedc | ||
|
|
52f9ffb1f6 | ||
|
|
5fac24cee8 | ||
|
|
1954dfec80 | ||
|
|
2eea2b64c2 | ||
|
|
a127a93be8 | ||
|
|
9b32f85817 | ||
|
|
ec139d2677 | ||
|
|
4327be0cf9 | ||
|
|
c25c832b31 | ||
|
|
eabaabc535 | ||
|
|
9acf97f5a0 | ||
|
|
24fc212c76 | ||
|
|
04f88bdd63 | ||
|
|
a4eb58aa57 | ||
|
|
030195e3ff | ||
|
|
d21a52ae68 | ||
|
|
3c1f1dbacb | ||
|
|
6704d4e5ee | ||
|
|
787c4851ff | ||
|
|
bf6e7fafd3 | ||
|
|
ea6df764c0 | ||
|
|
f242de272d | ||
|
|
5232e2e9bc | ||
|
|
ca35898243 | ||
|
|
869457d235 | ||
|
|
6736c8160b | ||
|
|
243c50550d | ||
|
|
fe7d3ef23a | ||
|
|
57ad77fc39 | ||
|
|
d70e7bd1b3 | ||
|
|
254cc931ea | ||
|
|
01fe5cffe8 | ||
|
|
3e18995a37 | ||
|
|
ff161c9c9b | ||
|
|
6b7b4f326d | ||
|
|
f50f7dec29 | ||
|
|
a5def20c58 | ||
|
|
b23204f9c9 | ||
|
|
4972de0aaa | ||
|
|
58a1f3d7b4 | ||
|
|
f516edb858 | ||
|
|
161aa952fa | ||
|
|
3b26a13ad6 | ||
|
|
014189217a | ||
|
|
978debb40c | ||
|
|
5be707811e | ||
|
|
ac44a98f8a | ||
|
|
03ecc2ae8d | ||
|
|
1518379107 | ||
|
|
a58c8c59e1 | ||
|
|
37959b5048 | ||
|
|
cbcc9fc6f1 | ||
|
|
d236aaa7da | ||
|
|
a2cd5a671c | ||
|
|
1d6a45bf4d | ||
|
|
5bfe703ed7 | ||
|
|
fc8485388e | ||
|
|
a5593b3131 | ||
|
|
9541bf3267 | ||
|
|
1037fe0a0e | ||
|
|
a6eea3198a | ||
|
|
b28e2313a8 | ||
|
|
0f0b4e6c86 | ||
|
|
e033467054 | ||
|
|
0f092bf6bf | ||
|
|
66ba762360 | ||
|
|
c7c11838a0 | ||
|
|
301d80fabe | ||
|
|
95d238ada0 | ||
|
|
c88087de29 | ||
|
|
fade5502d9 | ||
|
|
86bb802140 | ||
|
|
6b644b384d | ||
|
|
c370af8914 | ||
|
|
1cd6d2bfc7 | ||
|
|
fc720916fb | ||
|
|
ce55035408 | ||
|
|
d4665ddaeb | ||
|
|
4375c6f667 | ||
|
|
36456bfb0d | ||
|
|
d9661c356f | ||
|
|
1edeae2a60 | ||
|
|
409f1056b9 | ||
|
|
a66fad69cf | ||
|
|
95488ac54b | ||
|
|
19f2b71273 | ||
|
|
ba6e136a0b | ||
|
|
d8c470db3d | ||
|
|
c642c4b84b | ||
|
|
0b80f7e547 | ||
|
|
d543f45607 | ||
|
|
28ac437987 | ||
|
|
e5699c1cdc | ||
|
|
f4a7c6e873 | ||
|
|
a4935f19bb | ||
|
|
2b4fdfd219 | ||
|
|
c3e470f1de | ||
|
|
3bef1dad4a | ||
|
|
da50ee59cf | ||
|
|
1a3b655d3f | ||
|
|
1f5f278970 | ||
|
|
0b4eb5239a | ||
|
|
118e8f6205 | ||
|
|
cf126c5906 | ||
|
|
645cf61911 | ||
|
|
4139337f85 | ||
|
|
6e8985d97e | ||
|
|
19c4c0d50d | ||
|
|
b23110950e | ||
|
|
60c213c44b | ||
|
|
87d5ede3dd | ||
|
|
203e5d89cd | ||
|
|
ce611cc61c | ||
|
|
25bc2dea93 | ||
|
|
9dc3884ea6 | ||
|
|
89d95c6ab8 | ||
|
|
7b70aa5a1e | ||
|
|
8191b4d9b6 | ||
|
|
3df8dea71b | ||
|
|
3cca50b7cc | ||
|
|
1ff5622694 | ||
|
|
f6ad7ff865 | ||
|
|
d69627a9c8 | ||
|
|
411f388bd3 | ||
|
|
5b8d35604a | ||
|
|
84534fd041 | ||
|
|
619d002bc4 | ||
|
|
e6e1446eb1 | ||
|
|
7049656f64 | ||
|
|
39fbadc4fb | ||
|
|
3c2a9c1dfd | ||
|
|
921fcbe477 | ||
|
|
c90b6c86ab | ||
|
|
3ecf25502b | ||
|
|
b808112e17 | ||
|
|
1b2d31db03 | ||
|
|
c9f8445d14 | ||
|
|
acd879ebef | ||
|
|
f6889fd8ea | ||
|
|
21ccbef6c9 | ||
|
|
9349e6a668 | ||
|
|
28a7fe6a04 | ||
|
|
18e1ed79ef | ||
|
|
e6e7c2982d | ||
|
|
aafdb7688a | ||
|
|
73b53f9702 | ||
|
|
33317a57c7 | ||
|
|
72d8f26cdb | ||
|
|
aea1afe145 | ||
|
|
0fec45b7ea | ||
|
|
af98b823aa | ||
|
|
07d9da2ca9 | ||
|
|
c2c86b2ef1 | ||
|
|
54e8763470 | ||
|
|
db34687df0 | ||
|
|
7f008d85ff | ||
|
|
06ebf51078 | ||
|
|
39c5bcd73c | ||
|
|
8f5f158b60 | ||
|
|
3bc1e35125 | ||
|
|
460bedddae | ||
|
|
8b64c315f3 | ||
|
|
7c824a2b72 | ||
|
|
87a36020f6 | ||
|
|
82686b0511 | ||
|
|
f4eca30163 | ||
|
|
2814183012 | ||
|
|
bbc3c2a8d6 | ||
|
|
7eeb7feeae | ||
|
|
b2f850c1c8 | ||
|
|
9dac604a93 | ||
|
|
23db346070 | ||
|
|
d3b7d739bb | ||
|
|
eb6c134f4b | ||
|
|
22733e7117 | ||
|
|
aa0b8d88e8 | ||
|
|
3cf9425247 | ||
|
|
b5578e72bd | ||
|
|
3aea0909a4 | ||
|
|
5adef3336e | ||
|
|
1a96b418bc | ||
|
|
e373e86b60 | ||
|
|
6f3035184c | ||
|
|
7ae8b1957c | ||
|
|
824b9718ee | ||
|
|
8540a73885 | ||
|
|
ef43f6c087 | ||
|
|
c8a70caf79 | ||
|
|
25ce784a60 | ||
|
|
5358cccb62 | ||
|
|
ba11758e1f | ||
|
|
f0412d6b1d | ||
|
|
f5f87ce1a3 | ||
|
|
f28b269734 | ||
|
|
d545efd843 | ||
|
|
f8682c2123 | ||
|
|
f62e31a1eb | ||
|
|
ea623b08a6 | ||
|
|
ce3d5a413c | ||
|
|
698fa9dff9 | ||
|
|
d23fd6e23c | ||
|
|
59395a254d | ||
|
|
5d7c6c8d6f | ||
|
|
6529293d21 | ||
|
|
a1fce624ea | ||
|
|
b7773f7471 | ||
|
|
f927e47bfe | ||
|
|
48a37b2018 | ||
|
|
f6b2da6ed6 | ||
|
|
275779b20e | ||
|
|
2102f8ff88 | ||
|
|
a8949cf1f9 | ||
|
|
61db6334f9 | ||
|
|
117afcea32 | ||
|
|
3f89750ee5 | ||
|
|
d88be7ae05 | ||
|
|
8f462aab40 | ||
|
|
46d278ca55 | ||
|
|
339038956d | ||
|
|
116a93d8cc | ||
|
|
acebc35d3f | ||
|
|
24245331db | ||
|
|
d6d10d33e3 | ||
|
|
4d88c9b383 | ||
|
|
a3f597c589 | ||
|
|
2a3d88c12e | ||
|
|
9561f47337 | ||
|
|
f02c92db22 | ||
|
|
181ef5d50e | ||
|
|
aee89f1c92 | ||
|
|
870397ebb9 | ||
|
|
0ed413070d | ||
|
|
f66f5ffdf9 | ||
|
|
ca280a7b3e | ||
|
|
85284bff9d | ||
|
|
fa4d33f725 | ||
|
|
4ce42cdf6d | ||
|
|
1b8562ead8 | ||
|
|
b9d9b906fb | ||
|
|
e9d079a223 | ||
|
|
e2e42ee91c | ||
|
|
4b0208201b | ||
|
|
bec3f97733 | ||
|
|
16cfe37dac | ||
|
|
7381da863c | ||
|
|
b0902825fa | ||
|
|
31c489cba0 | ||
|
|
6a2f21d75a | ||
|
|
e2c42a57c7 | ||
|
|
8592b53216 | ||
|
|
49dcf0049f | ||
|
|
076bee923f | ||
|
|
aacdb33827 | ||
|
|
53e9ece930 | ||
|
|
87f08d9bab | ||
|
|
a50a6326af | ||
|
|
3c0eec833e | ||
|
|
5b0cfdffcb | ||
|
|
d788e0402e | ||
|
|
a347dc5e2a | ||
|
|
b2fe158a7b | ||
|
|
faab7e8df0 | ||
|
|
9070e198f1 | ||
|
|
45b2a0db4d | ||
|
|
65d39050ea | ||
|
|
5da16df5ae | ||
|
|
24fc4b05ab | ||
|
|
173902feb1 | ||
|
|
fd5f08fe84 | ||
|
|
d430ad6ca1 | ||
|
|
1309c18292 | ||
|
|
b6deebac97 | ||
|
|
83711f2dcb | ||
|
|
18e1a767af | ||
|
|
6ae3efb461 | ||
|
|
84e1934134 | ||
|
|
9aed9342ee | ||
|
|
e4d0bf39ca | ||
|
|
847fa6842e | ||
|
|
08aa4f29bd | ||
|
|
539218381b | ||
|
|
9dff39b4d7 | ||
|
|
1e578e94e5 | ||
|
|
ec35c9b9bb | ||
|
|
0deaeaeb7d | ||
|
|
ec3d9e1a56 | ||
|
|
814f84ae42 | ||
|
|
904be475ef | ||
|
|
5edecbe81b | ||
|
|
f357033404 | ||
|
|
4800ae6649 | ||
|
|
60b0690c1e | ||
|
|
82e31dd766 | ||
|
|
130e767e75 | ||
|
|
b1a1d509ec | ||
|
|
0698cf495e | ||
|
|
6047660405 | ||
|
|
aaf3495f83 | ||
|
|
ae6529c9fd | ||
|
|
45a96b2a42 | ||
|
|
4212903c67 | ||
|
|
be47dbcede | ||
|
|
9556c57c69 | ||
|
|
f72b65bfac | ||
|
|
6121700c9b | ||
|
|
91c968e743 | ||
|
|
8fed6f4823 | ||
|
|
34e4b39d75 | ||
|
|
a21c70ce46 | ||
|
|
8865a71f4c | ||
|
|
142cadc187 | ||
|
|
66f4c2531d | ||
|
|
3f8ddd5f7d | ||
|
|
c076e14cbd | ||
|
|
d724eb068b | ||
|
|
d3ac263e29 | ||
|
|
a6b7fe1f17 | ||
|
|
ec714ccb84 | ||
|
|
ab0a129ba1 | ||
|
|
a3f272b2aa | ||
|
|
77d91ed979 | ||
|
|
9907ba17c1 | ||
|
|
a6f0e19a44 | ||
|
|
7ee064b04d | ||
|
|
f2e4c735f7 | ||
|
|
5345bd321f | ||
|
|
eab8d0063b | ||
|
|
6877977234 | ||
|
|
60cb81362e | ||
|
|
088acb8e86 | ||
|
|
77f59f06cb | ||
|
|
a0882c6105 | ||
|
|
d50eb52172 | ||
|
|
5e5cadd314 | ||
|
|
75b06f82f0 | ||
|
|
2ab050aa60 | ||
|
|
6d2f645e4a | ||
|
|
9f937e29f2 | ||
|
|
abc61a96c8 | ||
|
|
b1d10822d4 | ||
|
|
09d984456d |
@@ -24,6 +24,7 @@ eclipse
|
||||
run
|
||||
runClient
|
||||
runServer
|
||||
utilityscripts/implementation/*.txt
|
||||
|
||||
# Files from Forge MDK
|
||||
forge*changelog.txt
|
||||
@@ -36,9 +37,11 @@ common/src/main/resources/assets/cobblemon/showdown
|
||||
# Generated files
|
||||
*/generated/resources/*
|
||||
/fabric/src/generated/resources/cobblemon-common.accesswidener
|
||||
/fabric/src/main/generated/*
|
||||
/.ignored/
|
||||
common/.fabric
|
||||
.kotlin/
|
||||
|
||||
# MacOS
|
||||
.DS_Store
|
||||
/common/config/*
|
||||
|
||||
+2
-2
@@ -71,8 +71,8 @@ setup_packsquash:
|
||||
- echo "Installing wget & unzip"
|
||||
- yum install -y wget unzip
|
||||
- echo "Downloading PackSquash"
|
||||
- wget https://github.com/ComunidadAylas/PackSquash/releases/download/v0.4.0/PackSquash.CLI.executable.x86_64-unknown-linux-musl.zip
|
||||
- unzip PackSquash.CLI.executable.x86_64-unknown-linux-musl.zip -d ./packsquash_bin
|
||||
- wget https://github.com/ComunidadAylas/PackSquash/releases/download/v0.4.1/packsquash-x86_64-unknown-linux-musl.zip
|
||||
- unzip packsquash-x86_64-unknown-linux-musl.zip -d ./packsquash_bin
|
||||
- echo "Creating PackSquash options.toml"
|
||||
- |
|
||||
cat <<EOF > ./options.toml
|
||||
|
||||
+460
-22
@@ -1,39 +1,477 @@
|
||||
# Changelog
|
||||
## [1.7.2 (MONTH Xth, YEAR)](#1-7-2)
|
||||
## [1.8.0 (MONTH Xth, 2026)](#1-8-0)
|
||||
|
||||
### Additions
|
||||
- Added riding statistics: `Distance by Pokémon on Land`, `Distance by Pokémon in Air` and `Distance by Pokémon in Liquid`.
|
||||
- Added the Partner Mark, which party Pokémon have a very small chance to earn as the player walks, provided they have enough friendship.
|
||||
- Added trades for Saccharine Saplings, Hearty Grains, Chipped Pot, and Masterpiece Teacup to the Wandering Trader.
|
||||
- Added brewing recipe for Throat Spray.
|
||||
- Added config options to award experience to fainted Pokémon for opponents they helped defeat (`awardExperienceToFaintedPokemon`) and to still award experience for defeated enemies even after battle loss/forfeit (`awardExperienceOnBattleLoss`)
|
||||
- Party Overlay Exp Gained Animation will now display the amount of EXP the Pokémon gained
|
||||
- Added a toast to notify players of how they can scroll through their party. Did you know you can hold R and scroll instead of using arrow keys??!
|
||||
- Added a new layer property that makes a layer scroll in a direction. "scrolling": {"speedU": 0.1, "speedV": 0.1}
|
||||
- Added missing crops to Botany Pots integration
|
||||
- Added a way to obtain Porygon by inserting the Upgrade or Dubious Disc into a data monitor
|
||||
- Added a new `cobblemon:structure`, which is a feature without any restrictions allowing the Builders to place certain structures in much more specific manner.
|
||||
- Added Configs for Infinite Use TMs and Unlocking all TMs
|
||||
- Added Type Gem blocks
|
||||
- Added Type Gem Clusters
|
||||
- Added TMs
|
||||
- Added TM Machine
|
||||
- Added Deepslate Core Block
|
||||
- Added /givetm Command
|
||||
- Added advancement triggers for learning TMs: `cobblemon:has_learn_specific_tm` (per-TM), `cobblemon:has_learn_all_tm` (all TMs learned), and `cobblemon:tms_learned` (count-based), backed by a new `totalTMLearnedCount` on player advancement data.
|
||||
- Added `cobblemon:catch_alpha_pokemon` advancement trigger and `totalAlphaCaptureCount` tracking for capturing Alpha Pokémon.
|
||||
- Added Move Dex to Pokédex
|
||||
- Added the Habitat Block, a spawner block for servers and adventure maps that controls spawning in an area.
|
||||
- Added Disk Rack for storing disks and being an audio sequencer for Noteblocks
|
||||
- Added intrinsic scaling to all mons (+-5%). Some rendering cases, such as shoulder mounting, revert to 1.0 scaling to preserve animation accuracy.
|
||||
- Added scaling to "baby" Pokémon (smaller (-20%) at level 1 → normally sized at level 10)
|
||||
- Added conditional seats for riding. Seats can be gated by molang such as "is_alpha".
|
||||
- Added Alpha Pokémon
|
||||
- Added alpha scaling (alphas are larger than their normal counterparts)
|
||||
- Alphas will always lead herds and will spawn in herds
|
||||
- Alphas spawn with two random TM moves from their learnset
|
||||
- Alpha Pokémon will always defend themselves from players that attack them
|
||||
- Added alpha level matching and stat boost (based on level)
|
||||
- Added pitch-down and reverb to alpha cries
|
||||
- Added alpha Pokémon bait effect
|
||||
- Added alpha eye rendering including eye overlay, bloom, eye trail, and particles.
|
||||
- Added cobweb block slowness immunity for spider Pokémon
|
||||
- Added 49 new habitat structures. 34 as typical Minecraft structures and 15 as structures that get placed as biome features to allow for more natural placement in generation. Structures placed as biome features will not be able to be located with the `/locate structure` command.
|
||||
- Vanilla village house template pools have been adjusted to account for the new abandoned village structure habitat. Weights have changed within the JSON file for every piece to ensure too many habitats don't generate in a single village.
|
||||
- Added 10 new ruin structures.
|
||||
- rooted_arch_ruins & crumbling_arch_ruins have been transferred over to biome features, allowing for better placement in generation.
|
||||
- All ruin structures that did not generate with a gimmighoul/gilded chest before will now generate with one.
|
||||
- All ruin structures gilded chest loot tables have been updated to include a guaranteed TM not learned naturally by any Pokémon through their level-up moveset. Each ruin gets its own specific TM, so you can now go hunting ruins to complete your move dex!
|
||||
- All fossil structures have been transferred over to biome features, allowing for better placement in generation.
|
||||
- The prehistoric_underwater_fissure & prehistoric_submerged_impact fossil structures now use the biome tag `#cobblemon:is_temperate_ocean`.
|
||||
- Gimmighoul towers now generate at ground level rather than sinking one block into the ground.
|
||||
- A new shipwreck cove structure called the "magma_shipwreck_cove" has been added.
|
||||
- Shipwreck coves now generate slightly more frequently.
|
||||
- Added equipment loot tables for shipwreck cove enemies.
|
||||
- Maps from abandoned fishing boats leading to shipwreck coves now will skip explored chunks, allowing the player to find more shipwreck coves easier.
|
||||
- The lush shipwreck cove's phantom mob spawner has been replaced with breezes.
|
||||
- The lush shipwreck cove structure itself has been slightly cleaned up to be less noisy with the blocks it is built out of.
|
||||
- All shipwreck coves' spawners have been adjusted to give compatible mobs enchanted iron or diamond armour and weapons while in its ominous state. The armour given to the mobs will also use the automaton trim. We upped the difficulty because it was too easy now that your Pokémon can fight for you.
|
||||
- One TM of the elemental hyper beams has been added as guaranteed loot to the main treasure chest in every shipwreck cove. (Magma cove gets blast burn, lush cove gets frenzy plant, and submerged cove gets hydro cannon)
|
||||
- Added 7 new advancements
|
||||
- Pressing the inventory key now closes the Pokémon interact wheel GUI
|
||||
- Pokémon cries now play when clicking Pokémon in the summary screen.
|
||||
- Pressing the Summary key while either the starter selection or summary screen are open now closes those screens
|
||||
- Ice type Pokémon are now immune to Packed Snow
|
||||
- Held item visibility can now be controlled by the held_item_visible command argument.
|
||||
|
||||
### New rideable Pokémon
|
||||
- Drampa
|
||||
- Archeops
|
||||
- Skarmory
|
||||
- Crobat
|
||||
- Goodra
|
||||
- Hisuian Goodra
|
||||
- Milotic
|
||||
|
||||
### Pokémon Added
|
||||
#### Generation 3
|
||||
- Wurmple
|
||||
- Silcoon
|
||||
- Beautifly
|
||||
- Cascoon
|
||||
- Dustox
|
||||
- Skitty
|
||||
- Delcatty
|
||||
- Seviper
|
||||
- Zangoose
|
||||
|
||||
#### Generation 4
|
||||
- Cherubi
|
||||
- Cherrim
|
||||
- Stunky
|
||||
- Skuntank
|
||||
|
||||
#### Generation 5
|
||||
- Audino
|
||||
- Pawniard
|
||||
- Bisharp
|
||||
|
||||
#### Generation 6
|
||||
- Pancham (+ Cosmetic with Black Glasses)
|
||||
- Pangoro (+ Cosmetic with Black Glasses)
|
||||
|
||||
#### Generation 7
|
||||
- Rockruff
|
||||
- Lycanroc
|
||||
|
||||
#### Generation 8
|
||||
- Rolycoly
|
||||
- Carkol
|
||||
- Coalossal
|
||||
- Runerigus
|
||||
- Snom
|
||||
- Frosmoth
|
||||
- Indeedee
|
||||
- Duraludon
|
||||
- Applin
|
||||
- Flapple
|
||||
- Appletun
|
||||
|
||||
#### Generation 9
|
||||
|
||||
- Nymble
|
||||
- Lokix
|
||||
- Kingambit
|
||||
- Dipplin
|
||||
- Archaludon
|
||||
- Hydrapple
|
||||
|
||||
#### Regional Forms
|
||||
- Sandshrew (Alolan Form)
|
||||
- Sandslash (Alolan Form)
|
||||
- Yamask (Galarian Form)
|
||||
- Avalugg (Hisuian Form)
|
||||
|
||||
### Model updates for the following Pokémon
|
||||
|
||||
- Sandshrew
|
||||
- Sandslash
|
||||
- Nidoking
|
||||
- Zubat
|
||||
- Golbat
|
||||
- Crobat
|
||||
- Ditto
|
||||
- Porygon
|
||||
- Porygon2
|
||||
- Porygon-Z
|
||||
- Skarmory
|
||||
- Smoochum
|
||||
- Jynx
|
||||
- Popplio
|
||||
- Brionne
|
||||
- Primarina
|
||||
- Fletchling
|
||||
- Fletchinder
|
||||
- Talonflame
|
||||
- Sableye
|
||||
- Mawile
|
||||
- Goomy
|
||||
- Sliggoo
|
||||
- Goodra
|
||||
- Nacli
|
||||
- Naclstack
|
||||
- Garganacl
|
||||
- Bidoof
|
||||
- Cranidos
|
||||
- Chatot
|
||||
- Yamask
|
||||
- Cofagrigus
|
||||
- Tyranitar
|
||||
- Turtonator
|
||||
- Arbok (New Patterns: Angry, Cartoon, Clown, Comedic, Crow, Grin, Ink, Modern, Rain, Scribble, Silence, Sloth, Suspicious, Will)
|
||||
|
||||
#### Model changes to the regional bias resource pack:
|
||||
|
||||
- Added Mime Jr. (Galar Bias)
|
||||
- Added Bergmite (Hisui Bias)
|
||||
- Changed models for every existing regional bias
|
||||
|
||||
### Animation updates for the following Pokémon
|
||||
- Skarmory
|
||||
- Skitty
|
||||
- Flygon
|
||||
- Shellos
|
||||
- Riolu
|
||||
- Lucario
|
||||
- Purrloin
|
||||
- Liepard
|
||||
- Joltik
|
||||
- Galvantula
|
||||
- Nidoking
|
||||
- Fletchling
|
||||
- Fletchinder
|
||||
- Talonflame
|
||||
- Archeops
|
||||
- Drampa
|
||||
- Sewaddle
|
||||
- Swadloon
|
||||
- Leavanny
|
||||
- Goomy
|
||||
- Sliggoo
|
||||
- Goodra
|
||||
- Shedinja
|
||||
- Skwovet
|
||||
- Greedent
|
||||
- Bidoof
|
||||
- Cranidos
|
||||
- Chatot
|
||||
- Yamask
|
||||
- Cofagrigus
|
||||
- Luvdisc
|
||||
|
||||
#### Added sounds to the following moves
|
||||
- Absorb
|
||||
- Aurora Beam
|
||||
- Double Team
|
||||
- Draco Meteor
|
||||
- Fire Punch
|
||||
- Fire Spin
|
||||
- Flame Charge
|
||||
- Flame Wheel
|
||||
- Giga Drain
|
||||
- Ice Punch
|
||||
- Leech Life
|
||||
- Magical Leaf
|
||||
- Mega Drain
|
||||
- Minimize
|
||||
- Poison Gas
|
||||
- Rock Throw
|
||||
- Scary Face
|
||||
- Seed bomb
|
||||
- Smokescreen
|
||||
- String Shot
|
||||
- Tail Whip
|
||||
|
||||
### Changes
|
||||
- Ride sounds have been separated into stereo for passengers and mono for other players. Riding will now sound more spacious.
|
||||
- Stat increase and decrease particles have been changed, with the addition of alpha boost particles.
|
||||
- Dragonite's mailbag cosmetic can now also be obtained with a chest in the cosmetic slot
|
||||
|
||||
### Fixes
|
||||
- Fixed orientation not getting reset after crashing while flying and getting back on the Pokémon.
|
||||
- Fixed Furfrou not being trimmable on NeoForge.
|
||||
- Fixed shiny Pokémon not respecting the silent flag on spawn.
|
||||
- Fixed honey from Saccharine Leaves being harvestable at less than the max age.
|
||||
- Items given from interacting with Saccharine Leaves are placed in the active hotbar slot if possible.
|
||||
- Fix all Pokémon being saved to chunks and never despawning.
|
||||
- Fixed PokeSnacks crashing if there was no available spawn.
|
||||
- Fixed Pokémon spawn influences not being specific to regional forms
|
||||
- Fixed crashing when viewing another player in spectator mode
|
||||
- Fixed missing apricorn textures for Adorn blocks
|
||||
- Fixed crashing when riding due to malformed json file, instead resetting it
|
||||
- Fixed mochi items consuming two items at a time
|
||||
- Fix item interaction sometimes not working properly when playing on servers.
|
||||
- Fixed Soothe Bell not being properly tagged as a held item.
|
||||
- Adjusted Croagunk's walkspeed
|
||||
- Fixed Blitzle's base scale being `1` rather than the intended `0.8`
|
||||
- Fixed Magnezone's emissive layer for the shiny having the wrong name, thus displaying wrongly
|
||||
- Fixed Litleo not blinking
|
||||
- Fixed Garchomp T-posing when sleeping while out of battle.
|
||||
- Sharp Beak can now be crafted
|
||||
- Metal Alloy can now be crafted
|
||||
- Ability Capsules can now be brewed
|
||||
- Using an Ability Capsule will now return an Empty Bottle
|
||||
- The following items can now be obtained by brushing the following Pokémon:
|
||||
- Pink Wool - Wigglytuff
|
||||
- White Wool - Swablu, Altaria
|
||||
- Shed Shell - Ekans, Arbok, Dratini, Dragonair, Dunsparce, Treecko, Grovyle, Sceptile, Seviper, Scraggy, Scrafty, Helioptile, Heliolisk, Salandit, Salazzle, Sobble, Drizzile, Inteleon, Silicoblra, Sandaconda, Toxel, Toxtricity, Orthworm, Dudunsparce
|
||||
- Phantom Membrane - Dreepy, Drakloak, Dragapult
|
||||
- The following items can now be obtained by evolving the following Pokémon into any of their evolutions:
|
||||
- Turtle Scute - Squirtle, Wartortle, Turtwig, Grotle, Tirtouga, Chewtle
|
||||
- Shed Shell - Metapod, Kakuna, Ekans, Paras, Venonat, Krabby, Scyther, Kabuto, Dratini, Dragonair, Ledyba, Spinarak, Yanma, Pineco, Dunsparce, GLigar, Pupitar, Treecko, Grovyle, Silcoon, Cascoon, Surskit, Nincada, Trapinch, Vibrava, Corphish, Anorith, Bagon, Shelgon, Kricketot, Burmy, Combee, Skorupi, Swadloon, Whirlipede, Dwebble, Scraggy, Karrablast, Joltik, Larvesta, Spewpa, Clauncher, Helioptile, Charjabug, Crabrawler, Cutiefly, Dewpider, Salandit, Wimpod, Poipole, Sobble, Drizzile, Dottler, Silicobra, Toxel, Sizzlipede, Snom, Tarountula, Nymble, Rellor
|
||||
- Saccharine Leaves now drop Tart, Sweet, or Syrupy Apples, depending on their honey coating stage, instead of vanilla Apples
|
||||
- Fixed the height of the Tumblestone Bud items when held in hand, placed on head, viewed in a GUI, and placed in an Item Frame
|
||||
- Refactored all advancements, removing several deemed unnecessary. Due to this refactor, all previously obtained advancements will be reset besides the root (for picking a starter Pokémon). We are sorry for the inconvience, but it makes the tab cleaner and simplifies future advancements.
|
||||
- Restructured Botany Pots integration folder structure
|
||||
- Decrease the default pastured mon wander radius to 32.
|
||||
- Factor in the weight of Pokémon when calculating pushing forces between hitboxes.
|
||||
- Remade the Starter Selection Screen with new assets
|
||||
- Refactored berry trees to be less impactful on TPS (more performant)
|
||||
- Changed the bait effects of the following items: (Vanilla) Sweet & Glow Berries, Golden & Enchanted Golden Apples (Cobblemon) Custap, Eggant, Hopo & Micle Berries, Sweet Hearts
|
||||
- Wild Pokémon now reliably have at least one offensive move if they can have offensive moves at that level.
|
||||
- Data Monitor can accept Disks (TMs, Music Disks, Upgrade, Dubious Disk, etc.) to change what's being displayed on the screen
|
||||
- Rider positioning is now client-driven (Remove poseOffsets and offset per seat/pose) in favour of sending real-time passenger position.
|
||||
- Cleaned up seat data. Removed all now unused fields from seats in all species files. Also made locator seat names explicit in the species files (however, this doesn't break the legacy format)
|
||||
- Marks can now provide aspects.
|
||||
- Added new shiny and Alpha chance configs
|
||||
- Apricorns now make a new sound when harvested
|
||||
- Lowered the volume of harvesting berries
|
||||
- Added alternate versions of the basic PC Wallpapers based on the original design of Cobblemon's PC, before public release
|
||||
- Improved compatibility with various mods
|
||||
- Farmer's Delight's cutting board can now be used to strip Apricorn and Saccharine's logs, or salvage their planks from various blocks. It can also separate their boats from chests
|
||||
- Farmer's Delight's cutting board can be used to get two white dye from Pep-Up Flowers and two magenta dye from Medicinal Leeks
|
||||
- Farmer's Delight's cutting board can separate Tumblestone Blocks back into Tumblestones
|
||||
- Farmer's Delight's cutting board can salvage Type Gems from their Gem Blocks
|
||||
- Farmer's Delight's Onions, Tomatoes, and Cabbages can be used to cook Open-Faced Sandwiches. Nature's Spirit's Olives also can be used
|
||||
- Farmer's Delight's cutting board can be used on Hearty Grains to obtain rice and straw, similarly to Farmer's Delight's Rice Panicles
|
||||
- Farmer's Delight's Apple Pies and Apple Ciders can now be made using Applin Apples, alongside the Vanilla counterpart
|
||||
- Amendments allows for cooking Leek and Potato Stew in a Cauldron
|
||||
- Any mods that utilise Moonlight's Soft Fluid system can store Leek and Potato Stew, Medicinal Brew, Antidote, Awakening, Burn Heal, Ice Heal, Paralyze Heal, Full Heal, Potion, Super Potion, Hyper Potion, Max Potion, Full Restore, Ability Capsules, Moomoo Milk, and Berry Juice in liquid form (such as Suplementaries' Jar or Goblet, or Cauldrons while using Amendments)
|
||||
- Supplementaries' Hourglass can now use Bright Powder, Quick Powder, Metal Powder, Heal Powder, Silver Powder, and Remedy
|
||||
- Berry Trees are now compatible with the Planter properly
|
||||
- Saccharine Way Signs (added by Supplementaries automagically) now use a premade texture to prevent odd visual issues
|
||||
- Supplementaries' Jar can now store various Cobblemon cookies, candies, and similar items
|
||||
- Some of Supplementaries' items have been added to the `#cobblemon:held/container_held_items` item tag, including sacks, safes, and lunch baskets
|
||||
- Experience Nuggets can be used in place of Sculk for making the EXP Candies if using Create
|
||||
- Rage Candy Bar has a Create Mixing recipe
|
||||
- All Cobblemon ores can now be crushed in Create's Crushing Wheels
|
||||
- All Gem and Tumblestone Clusters can be crushed for automatic, low return, gems
|
||||
- Hearty Grains can be milled like Farmer's Delight Rice Panicles if both Farmer's Delight and Create are installed
|
||||
- Big Roots and Revival Herbs can be milled to their respective powders
|
||||
- Pep-Up Flowers, Medicinal Leeks, and all 70 berries can be milled in Create's Millstone for additional dye drops
|
||||
- Auspicious Armor and Upgrades can be Haunted using Create's crafting systems
|
||||
- Applin Apples can be used to make Honeyed Apples in Create
|
||||
- Golden Apples can now be crafted using the Applin Apples
|
||||
- Prismarine Crystals and Amethyst Shards can now be used to craft Pokedexes
|
||||
- Updated Pokedex Screens item tag to support tagged variants of Redstone and Glowstone Dust
|
||||
- Sounds for interacting with various Cobblemon blocks now play from the center of the block, rather than the corner
|
||||
- The `/pc` command no longer plays PC activation sounds
|
||||
- Lowered the volume of Blitzle and Zebstrika's cry
|
||||
- Fixed Raichu (male) and Alolan Raichu (both genders) not displaying the correct Partner Cap when Pewter Crunchies are in the cosmetic slot.
|
||||
- Regional Foods will now prioritize being eaten instead of used for healing Pokémon, shift clicking will use it as healing
|
||||
- Resolved Z-Fighting on Pokédex Models
|
||||
- Restored Ninjask's ability to do barrel rolls
|
||||
- Fixed a crash caused by adding enchanted items to the Resurrection Machine
|
||||
- Fixed a crash that could occur when starting a PvN battle with only fainted Pokémon.
|
||||
- Fixed the Remember Riding Camera config not being respected when dismounting and resolved the incompatibility with the Auto Third Person mod
|
||||
- Fixed Full Heal block not dropping Full Heals
|
||||
- Fixed status cure items not returning an empty bottle when used
|
||||
- Fixed Panpour consuming its held item when evolving with a Water Stone
|
||||
- Fixed Smoked Tail Curry returning a Wooden Bowl when consumed despite it not being included in the recipe
|
||||
|
||||
### Fixes
|
||||
- Fixed Croagunk's walkspeed
|
||||
- Fixed Blitzle's base scale being `1` rather than the intended `0.8`
|
||||
- Fixed Magnezone's emissive layer for the shiny having the wrong name, thus displaying wrongly
|
||||
- Fixed Litleo not blinking
|
||||
- Fixed Pokédex layout for genderless variations
|
||||
- Fixed odd stacking behaviour with the poke_bait item.
|
||||
- Fixed a compatibility issue with World Game Rules which caused some log spam in specific cases.
|
||||
- Fixed improper validation of Pokémon when performing a trade.
|
||||
- Fixed an issue where particle like beam can disappear when you don't see the beginning of the beam, or you look away
|
||||
- Fixed Bedrock particle materials (alpha/opaque/blend/add) sharing one render batch, which caused incorrect culling on mixed batches; each material now batches and draws with its own blend and cull state, and the alpha material renders as a true cutout
|
||||
- Fixed an occasional crash on retrieving revived fossils
|
||||
- Fixed brushing not working on Neoforge
|
||||
- Fixed braking not working for submarines (whoops).
|
||||
- Fixed strafing not having the same friction as forward movement (funny whoops).
|
||||
- Fixed submarine's surface-water animations not playing when supposed to.
|
||||
- Fixed submarine camera freaking out when looking up or down on the surface.
|
||||
- Fixed pastured mons despawning and running away.
|
||||
- Fixed Apricorn trees crashing when other mods bonemeal it
|
||||
- Fixed the issue that caused Hover Behaviour rides without a ground style to be rendered useless upon touching the ground on a server.
|
||||
- Removed the "inAir" penalty for block destruction speed when on a hover mount.
|
||||
- Fixed horizontal and vertical collisions with hover mounts so they no longer accumulate or retain momentum
|
||||
- Fixed NeoForge brewing stand unexpectedly crashing users when shift clicking items within its menu
|
||||
- Fixed NPCs switching Pokémon very often during battles
|
||||
- Fixed Campfire pot causing crashes under certain circumstances
|
||||
- Fixed Type Gems not being consumed upon use
|
||||
- Fixed Ancient Pokéball's to their respective modifiers
|
||||
- Fixed a Server warning when recalling Pokémon
|
||||
- Fixed sliding particles incorrectly handling block collision
|
||||
- Fixed Full Heal not curing status conditions in battle
|
||||
- Fixed a rare issue with battles locking up when you are forced to switch, with the switch menu appearing instantly.
|
||||
- Fixed the combined effects of Pledge moves having broken Showdown message handling and localisation
|
||||
- Fixed rare Pokémon being far too likely to spawn multiple times in a single spawn cycle. The dev told me that the exact bug is too complicated to explain.
|
||||
- Resolved the niche issue where Structures would spawn in an incorrect location, creating very funky world gen.
|
||||
- Fixed Galarian Ponyta missing its cry.
|
||||
- Fixed various log warnings caused by redundant files and sound events.
|
||||
- Traded Pokémon will now retain the original friendship level when traded back to its OT
|
||||
- Clusters now display correctly on maps
|
||||
- Fixed removing mulch from berry trees with a shovel not working.
|
||||
- Fixed collecting honey from Saccharine Leaf blocks deleting Honey Bottles when the inventory was full
|
||||
- Fixed Stripped Saccharine Wood recipe being missing
|
||||
- Fixed CancelableSoundInstance causing lag by attempting to create sounds every tick when out of range of hearing
|
||||
- Fixed Stat Reducing Aprijuice not being possible to apply on a max out Pokémon, and the possibility of going into negatives
|
||||
- Fixed Exploit where you could take out the bait or drop your Pokérod with bait to avoid consuming bait, now the bobber will just disappear if you do so
|
||||
- Fixed Apricorn and Saccharine boats incorrectly using chest boat models
|
||||
- Fixed wild and trainer battle AI refusing to select moves with the `adjacentAlly` target type, even when it's their only option
|
||||
- Fixed Guilded chests being more accessible than intended
|
||||
- Fixed fished up Pokémon not being added as "seen" to the Pokedex
|
||||
- Fixed surprised Gimmighoul encounters not being added as "seen" to the Pokedex
|
||||
- Fixed a crash involving berry trees that have been world edited.
|
||||
- Fixed visual desync in multiplayer for players mounting Pokémon outside other players' loaded chunks
|
||||
|
||||
### Developer
|
||||
- Changed the `owner` parameter in the `OwnerQueryRequirement` interface from `ServerPlayer` to `Player`. This method is now also called on the client to verify whether a Pokémon interaction succeeded, so make sure to update your implementations to handle both server and client contexts.
|
||||
- Added `PokeSnackSpawnerFactory` which allows influence registration on PokeSnack encounters
|
||||
- Added `FishingSpawnerFactory` which allows influence registration on fishing encounters
|
||||
- Added `BattleFleeAttemptEvent` fired from `PokemonBattle.checkFleeAttempt`, allowing developers to intercept and control flee attempts
|
||||
- Tweaked the spawning selector interface to take a bucket function rather than a bucket directly.
|
||||
- Added a new `cobblemon:height_range` processor type to allow developers to restrict structure-spawning ranges.
|
||||
- Separated all the functions of MoLangFunctions.kt into their own files.
|
||||
- Spawn buckets and their base weights are now provided by the spawner, with different base weights for world, fishing, snack, and habitat spawn buckets.
|
||||
- Removed "SpawnBucket" class in favour of just storing maps of bucket names to weights.
|
||||
- Fixed nicknames not being applied to Pokémon spawned from `spawn_pool_world` files.
|
||||
- Added support for `profilePokedexScale`, `profilePokedexTranslation`, `profileSummaryScale`, and `profileSummaryTranslation` in poser files for finer control over profile displays.
|
||||
|
||||
### Molang & Datapacks
|
||||
- Added `moveset_builders` datapack folder for different styles of movesets.
|
||||
- Added `party_pools` datapack folder for defining groups of Pokémon for complex NPC party definitions.
|
||||
- Added `party_compositions` datapack folder for arranging parties on NPCs that rely on party pools.
|
||||
- Added `composed_pool` NPC party provider type which combines a party pool with a party composition to create more complex NPC parties.
|
||||
- Added basic chatter NPC Behaviour
|
||||
- Added `q.item.is_enchanted()`
|
||||
- Added `q.item.has_enchantment(minecraft:sharpness, 3)`
|
||||
- Added `has_chosen_starter` & `get_starter_uuid` as available Molang functions
|
||||
- Added `marks`, `has_mark`, & `remove_marks` as available Molang functions for Pokémon
|
||||
- Added Data Component support for species drops, eg `"components": {"minecraft:custom_model_data": 123}`
|
||||
- Added the new `sortOrder` field to mark entries, (defaults to 0 if not specified) which controls the order in which marks are rendered on the HUD, with higher numbers being rendered on top of lower numbers
|
||||
- Added optional `order` field to starter categories. It will allow explicitly sorting categories in the starter selection screen
|
||||
- SpeciesAdditions append vs override now matches wiki documentation
|
||||
- Added `weighted_choice` as a new feature type. It requires setting weights for each choice and allows developers to simplify the process of assigning random aspect choice based on marble chance
|
||||
- Added `q.world.spawn_loot_table_items(loot_table_id, x, y, z)` which spawns the items from the loot table at the position. (Use type: "minecraft:chest" for the loot table.)
|
||||
- Added `q.pokemon.entity` to access the entity of Pokémon.
|
||||
- Flamethrower and Seismic Toss had their action effect JSON cleaned up
|
||||
- Ride sounds can now be set as exclusive to passengers
|
||||
- Ride sounds no longer play when submerged unless specified with a new setting
|
||||
- NPC Trainers can now call a `command` animation when issuing a command in battle.
|
||||
- Added a q.failed function to move action effects.
|
||||
- Herd spawned Pokémon have their levels controlled differently. The `levelRange` property now acts as a clamp instead of a filter, with a new `herdLevelRange` property to do the filter behaviour.
|
||||
- `q.sound` now accepts three parameters (sound event, volume and pitch) instead of just the sound event and pitch.
|
||||
|
||||
### Particles
|
||||
|
||||
#### New Move Animations
|
||||
- Blizzard
|
||||
- Disarming Voice
|
||||
- Draco Meteor
|
||||
- Dragon Breath
|
||||
- Dragon Rage
|
||||
- Drain Punch
|
||||
- Fairy Wind
|
||||
- Fire Fang
|
||||
- Gust
|
||||
- Horn Drill
|
||||
- Hydro Pump
|
||||
- Ice Fang
|
||||
- Leafage
|
||||
- Leaf Storm
|
||||
- Light Screen
|
||||
- Night Shade
|
||||
- Play Rough
|
||||
- Pyro Ball
|
||||
- Reflect
|
||||
- Rock Slide
|
||||
- Sonic Boom
|
||||
- Sucker Punch
|
||||
- Supersonic
|
||||
- Thunder Fang
|
||||
|
||||
#### Tweaks and Fixes (Moves)
|
||||
|
||||
- Confusion
|
||||
- Dragon Claw
|
||||
- Eruption
|
||||
- Fire Punch
|
||||
- Flame Burst
|
||||
- Flame Charge
|
||||
- Flamethrower
|
||||
- Frost Breath
|
||||
- Hypnosis
|
||||
- Ice Punch
|
||||
- Icy Wind
|
||||
- Mud Sport
|
||||
- Poison Fang
|
||||
- Protect
|
||||
- Psychic
|
||||
- Quick Attack
|
||||
- Rage Powder
|
||||
- Razor Leaf
|
||||
- Sand Attack
|
||||
- Scratch
|
||||
- Shadow Claw
|
||||
- Sing
|
||||
- Spore
|
||||
- String Shot
|
||||
- Tackle
|
||||
- Tail Whip
|
||||
- Thunder
|
||||
- Thunder Punch
|
||||
- Thunder Wave
|
||||
- Water Gun
|
||||
- Water Pulse
|
||||
- Water Sport
|
||||
|
||||
#### Miscellaneous Particles
|
||||
|
||||
+ Added Wild Might particles for Alpha Pokémon
|
||||
+ Updated stat increase and decrease particles
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
- Updated translations for:
|
||||
- Japanese
|
||||
- German
|
||||
- Spanish
|
||||
- Ecuadorian Spanish
|
||||
- Brazilian Portuguese
|
||||
- Simplified Chinese
|
||||
- Traditional Chinese
|
||||
- Korean
|
||||
@@ -0,0 +1,9 @@
|
||||
- Some kind of particle effect for them? they're meant to have glowing eyes, so maybe some red particles on the eye locator
|
||||
--- global posers? stacked posers?
|
||||
--- red texture seems to be what some people wanted.
|
||||
|
||||
/- shoulder mounts part of it
|
||||
- omni boost
|
||||
- roar when player comes within reach, adjust levels
|
||||
|
||||
- Riding settings to control what the min scale is for a pokemon to be ridable.
|
||||
@@ -0,0 +1,137 @@
|
||||
# Changelog
|
||||
## [1.7.2 (January 25th, 2026)](#1-7-2)
|
||||
|
||||
### Additions
|
||||
- Added Saccharine wood furniture for Adorn.
|
||||
- Added the Partner Mark, which party Pokémon have a very small chance to earn as the player walks, provided they have enough friendship.
|
||||
- Added decorative block models for existing items: Potion, Super Potion, Hyper Potion, Max Potion, Full Restore, Antidote, Awakening, Burn Heal, Ice Heal, Paralyze Heal, Full Heal, Ether, Elixir, Max Ether, Max Elixir, X Accuracy, X Attack, X Defence, X Special Attack, X Special Defence, X Speed, Dire Hit, Guard Spec, Weakness Policy, Blunder Policy, Cleanse Tag, and Spell Tag.
|
||||
- Added decorative sign blocks called Plaques.
|
||||
- Added ride style labels to ride stats in Pokédex, as well as ride style icons in the summary GUI.
|
||||
- Added more seasonings for sinister tea:
|
||||
- Mental Herb - Mental Restoration I for 10 seconds, which staves off Insomnia.
|
||||
- White Herb - Removes negative effects.
|
||||
- Milk, Moomoo Milk - Removes effects.
|
||||
- Added dispenser support for:
|
||||
- Applying a Honey Bottle to Saccharine Logs.
|
||||
- Washing honey off of Saccharine Slathered Logs.
|
||||
- Applying and removing honey on Saccharine Leaves.
|
||||
- Added riding statistics: `Distance by Pokémon on Land`, `Distance by Pokémon in Air` and `Distance by Pokémon in Liquid`.
|
||||
|
||||
### New rideable Pokémon
|
||||
- Honchkrow
|
||||
- Mantine
|
||||
|
||||
### Pokémon Added
|
||||
|
||||
#### Gen 5
|
||||
- Throh
|
||||
- Sawk
|
||||
|
||||
#### Gen 6
|
||||
- Litleo
|
||||
- Pyroar
|
||||
- Spritzee
|
||||
- Aromatisse
|
||||
- Swirlix
|
||||
- Slurpuff
|
||||
|
||||
### Model updates for the following Pokémon
|
||||
- Falinks
|
||||
- Cottonee
|
||||
- Whimsicott
|
||||
- Ferroseed
|
||||
- Ferrothorn
|
||||
- Chingling
|
||||
- Chimecho
|
||||
|
||||
### Animation updates for the following Pokémon
|
||||
- Mantine (ride animations)
|
||||
- Flygon (ride jump animation)
|
||||
- Honchkrow (ride animations)
|
||||
- Croagunk
|
||||
- Toxicroak
|
||||
|
||||
### Changes
|
||||
- Added a new config option, `Enable In-Flight Dismounting` (default: off), which lets you dismount while riding a Pokémon in the air. This is the textbook definition of caveat emptor.
|
||||
- Ride sounds have been separated into stereo for passengers and mono for other players. Riding will now sound more spacious.
|
||||
- Battle AI now uses a smarter threshold for switching, reducing unnecessary switches.
|
||||
- AI will always use the most damaging move when at low HP and when it is not switching, improving endgame decision-making.
|
||||
- Items given from interacting with Saccharine Leaves are placed in the active hotbar slot if possible.
|
||||
- Added `label` as an alternate key to the `tag` property.
|
||||
|
||||
### Fixes
|
||||
- Fixed crashing when viewing another player in spectator mode. Some said this was reason to release this update a month ago. They were probably right.
|
||||
- Fixed crashing when sending a Pokémon out after editing its form.
|
||||
- Fixed all Pokémon being saved to chunks and never despawning even when they should be.
|
||||
- Fixed Poké Snacks crashing if there was no available spawn.
|
||||
- Fixed Poké Snack / Bait effects so that EV Yield, Type, and Egg Group filters now all apply together when weighting spawns. And you thought you were going crazy.
|
||||
- Fixed Furfrou not being trimmable on NeoForge specifically.
|
||||
- Fixed honey from Saccharine Leaves being harvestable at less than the max age.
|
||||
- Fixed possible error on world generation when Combee are placed in naturally generated bee nests.
|
||||
- Fixed Galarian Weezing crashing the world if it decides to blink the wrong way. The same could happen to you!
|
||||
- Fixed Galarian Mr. Mime incorrectly being rideable. Some would argue that regular Mr. Mime shouldn't be rideable, but that would make them wrong.
|
||||
- Fixed missing apricorn textures for Adorn blocks.
|
||||
- Fixed Apricorn block model rotation for counters/sinks/cupboards/drawers to match that of most recent version of Adorn.
|
||||
- Fixed item interaction sometimes not working properly when playing on servers.
|
||||
- Fixed Mint Leaves not being usable for filling the Resurrection Machine.
|
||||
- Fixed Super Potion recipes incorrectly using Hondew Berry instead of Aguav Berry. They look similar, to be fair.
|
||||
- Fixed Wishiwashi not schooling properly.
|
||||
- Fixed battle item duplication issue. How did it work? Wouldn't you like to know, weather boy.
|
||||
- Fixed the ordering of Aprijuice's riding stat boosts so they always have the same order.
|
||||
- Fixed the movesets of certain Pokémon being incorrectly sanitized upon reload, causing some forms to keep losing moves.
|
||||
- Fixed selected leading Pokémon in battle not being used when levels are set.
|
||||
- Fixed the bottom half of pasture blocks having an incorrect hit-box when facing north or south.
|
||||
- Fixed gimmicks not being usable in double and triple battles.
|
||||
- Fixed gimmick buttons showing when already used in the same turn in double and triple battles.
|
||||
- Fixed mochi items consuming two items at a time.
|
||||
- Fixed Fresh Start Mochi's EV reset not syncing health changes properly.
|
||||
- Fixed Pokémon spawn influences not being specific to regional forms.
|
||||
- Fixed memory leak from battles not being cleaned up after ending.
|
||||
- Fixed orientation not getting reset after crashing while flying and getting back on the Pokémon.
|
||||
- Fixed shiny Pokémon not respecting the `silent` flag on spawn.
|
||||
- Fixed 'Plain' prefix not being applied to all low-quality Aprijuice.
|
||||
- Fixed Pokémon interactions not playing sound effects when the volume was not specified.
|
||||
- Fixed Pokémon interaction cooldowns taking longer than intended when the Pokémon was in the player’s party.
|
||||
- Fixed Pokémon interactions occasionally crashing the game when spamming an interaction with a 0 cooldown.
|
||||
- Fixed Pokémon fullness decreasing more than intended when the Pokémon was pastured.
|
||||
- Fixed Scraggy line, Milcery line, and Morpeko spawning on unnatural blocks.
|
||||
- Fixed invulnerability-bypassed damage being resisted by invulnerable NPC entities.
|
||||
- Fixed Fabric network packets not being handled immediately, fixing incompatibilities with Supplementaries, Prometheus, Sleep Tight, and others.
|
||||
- Fixed killer not being set early enough on a wild Pokémon entity from `WinInstruction`.
|
||||
- Fixed requirements such as `biomeCondition` crashing the game when used to define Pokémon interactions.
|
||||
- Fixed an issue that prevented registering custom dispenser behaviours (no longer overrides vanilla behaviour).
|
||||
- Fixed an issue navigation that prevented Combee from pathing into and out of Saccharine Leaves.
|
||||
- Added Saccharine Boats and Saccharine Boat with Chests to relevant boat tags.
|
||||
- Fixed Soothe Bell not being properly tagged as a held item.
|
||||
- Fixed `/calculateseatpositions` expecting a locator format that even we don't use. It needs an underscore after "seat".
|
||||
- Fixed the `run_script` Molang function to not fail if the environment's context is null.
|
||||
- Fixed the Molang functions `date_local_time`, `date_of`, `date_is_after` to use the correct date format.
|
||||
|
||||
### Developer
|
||||
- Changed the `owner` parameter in the `OwnerQueryRequirement` interface from `ServerPlayer` to `Player`. This method is now also called on the client to verify whether a Pokémon interaction succeeded, so make sure to update your implementations to handle both server and client contexts.
|
||||
- Added the `pnx` to the `BattleFaintedEvent` and `FormeChangeEvent`.
|
||||
- Added register methods for custom instructions to `ShowdownInterpreter`.
|
||||
- Changed callback operations in `BattlePokemon` to allow multiple callbacks and be mutable.
|
||||
- Added `display_name`, `description`, and `max_pp` functions to the `MoveTemplate` struct.
|
||||
- Changed the implementations of `AIBattleActor` to be open classes to allow extension.
|
||||
- Changed the resource location of Poké Ball icons in the GUI to use the balls namespace instead of Cobblemon's, allowing mods to properly use their own namespace for these textures.
|
||||
|
||||
### Molang & Datapacks
|
||||
- Ride sounds can now be set as exclusive to passengers.
|
||||
- Ride sounds no longer play when submerged unless specified with a new setting.
|
||||
- Exception handling has been added to `run_molang`, resolving some crashes caused by malformed MoLang expressions.
|
||||
- Added the `create_itemstack`, `has_inventory_space`, `set_inventory_slot`, and `give_item` MoLang functions for item and inventory utility.
|
||||
- Added the `get_move_from_id` MoLang function for general move info queries without requiring a Moveset object to access.
|
||||
- Added support for optional message variants in battle activate instructions for more context-specific battle text.
|
||||
- Example: `this.add('-activate', pokemon, 'ability: example', '[msg]message1');` will parse to lang key `cobblemon.battle.activate.example.message1`.
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
- French
|
||||
- Canadian French
|
||||
- Simplified Chinese
|
||||
- Ukrainian
|
||||
- Brazilian Portuguese
|
||||
- Spanish
|
||||
- Korean
|
||||
- Japanese
|
||||
@@ -0,0 +1,22 @@
|
||||
# Changelog
|
||||
## [1.7.3 (January 31st, 2026)](#1-7-3)
|
||||
|
||||
### Fixes
|
||||
- Fixed mounted Pokémon not playing sounds.
|
||||
- Fixed players failing to join servers randomly.
|
||||
- Fixed some Pokémon having no stamina for flying.
|
||||
- Fixed `/pctake` not respecting the actual size of the PC.
|
||||
### Developer
|
||||
- Poké Ball GUI textures now respect the ball's namespace, enabling proper texture loading for custom balls from other mods.
|
||||
|
||||
### Molang & Datapacks
|
||||
- Added a `chance` requirement type for Pokémon interactions.
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
- French
|
||||
- Canadian French
|
||||
- Korean
|
||||
- Portuguese
|
||||
- Simplified Chinese
|
||||
- Spanish
|
||||
@@ -55,7 +55,7 @@ dependencies {
|
||||
// modCompileOnly(libs.flywheelFabric)
|
||||
|
||||
// Showdown
|
||||
modCompileOnly(libs.graal)
|
||||
modCompileOnly(libs.graal.core)
|
||||
|
||||
// Data Storage
|
||||
modCompileOnly(libs.bundles.mongo)
|
||||
@@ -72,6 +72,10 @@ tasks.withType<Test> {
|
||||
}
|
||||
}
|
||||
|
||||
tasks.processResources {
|
||||
exclude("data/**/README.md")
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
blossom {
|
||||
|
||||
@@ -13,5 +13,6 @@ public interface ChannelDuck {
|
||||
void cobblemon$inverseAttenuation(float rolloffFactor);
|
||||
void cobblemon$clearFilters();
|
||||
|
||||
// void cobblemon$exponentialAttenuation(float rolloff, float refDistance, float maxDistance);
|
||||
void cobblemon$applyReverb(float decayTime, float gain, float diffusion, float density);
|
||||
void cobblemon$clearReverb();
|
||||
}
|
||||
|
||||
@@ -11,7 +11,9 @@ package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories;
|
||||
import com.cobblemon.mod.common.api.ai.config.task.PathToBeeHiveTaskConfig;
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.world.feature.SaccharineTreeFeature;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
@@ -42,7 +44,21 @@ public abstract class BeeOccupantMixin {
|
||||
if (cir.getReturnValue() == null) {
|
||||
final BeehiveBlockEntity.Occupant occupant = (BeehiveBlockEntity.Occupant) (Object) this;
|
||||
CompoundTag compoundTag = occupant.entityData().copyTag();
|
||||
Entity entity = EntityType.loadEntityRecursive(compoundTag, level, (entityx) -> entityx);
|
||||
String id = compoundTag.getString("id");
|
||||
Entity entity = null;
|
||||
if (id.equals(SaccharineTreeFeature.Companion.getPOKEMON_PLACEHOLD_ID())) {
|
||||
// Special case for Pokemon stuffed into a beenest upon world gen.
|
||||
// For technical reasons we cannot create them as full entities during world gen.
|
||||
// So we look for this special id tag and complete the entity when it attempts to exit a hive.
|
||||
if (compoundTag.contains("pokemonProperties")) {
|
||||
String properties = compoundTag.getString("pokemonProperties");
|
||||
PokemonProperties pokemon = PokemonProperties.Companion.parse(properties);
|
||||
entity = pokemon.createEntity(level);
|
||||
}
|
||||
} else {
|
||||
entity = EntityType.loadEntityRecursive(compoundTag, level, (entityx) -> entityx);
|
||||
}
|
||||
|
||||
if (entity instanceof PokemonEntity pokemonEntity) {
|
||||
var state = level.getBlockState(pos);
|
||||
var newPos = Vec3.ZERO;
|
||||
|
||||
@@ -1,70 +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.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,15 +36,15 @@ public class ClientPacketListenerMixin {
|
||||
for (int passenger : packet.getPassengers()) {
|
||||
passengers.add(this.level.getEntity(passenger));
|
||||
}
|
||||
Arrays
|
||||
.stream(pokemon.getOccupiedSeats())
|
||||
pokemon.getOccupiedSeats().values().stream()
|
||||
.filter(x -> !passengers.contains(x))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(Entity::stopRiding);
|
||||
|
||||
var occupiedSeats = Arrays.asList(pokemon.getOccupiedSeats());
|
||||
// Mount passengers not yet in the map
|
||||
var currentPassengers = new ArrayList<>(pokemon.getOccupiedSeats().values());
|
||||
passengers.stream()
|
||||
.filter(x -> !occupiedSeats.contains(x))
|
||||
.filter(x -> !currentPassengers.contains(x))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(x -> x.startRiding(pokemon, true));
|
||||
ci.cancel();
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.mixin.accessor.SinglePoolElementAccessor;
|
||||
import com.cobblemon.mod.common.world.structureprocessors.HeightRangeStructureProcessor;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.level.levelgen.structure.Structure;
|
||||
import net.minecraft.world.level.levelgen.structure.pools.*;
|
||||
import net.minecraft.world.level.levelgen.structure.pools.alias.PoolAliasLookup;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.LiquidSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessor;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorList;
|
||||
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.Optional;
|
||||
|
||||
@Mixin(JigsawPlacement.class)
|
||||
public class JigsawPlacementMixin {
|
||||
|
||||
@Inject(
|
||||
method = "addPieces(Lnet/minecraft/world/level/levelgen/structure/Structure$GenerationContext;Lnet/minecraft/core/Holder;Ljava/util/Optional;ILnet/minecraft/core/BlockPos;ZLjava/util/Optional;ILnet/minecraft/world/level/levelgen/structure/pools/alias/PoolAliasLookup;Lnet/minecraft/world/level/levelgen/structure/pools/DimensionPadding;Lnet/minecraft/world/level/levelgen/structure/templatesystem/LiquidSettings;)Ljava/util/Optional;",
|
||||
at = @At("RETURN"),
|
||||
cancellable = true
|
||||
)
|
||||
private static void onAddPieces(
|
||||
Structure.GenerationContext context,
|
||||
Holder<StructureTemplatePool> startPool,
|
||||
Optional<ResourceLocation> startJigsawName,
|
||||
int maxDepth,
|
||||
BlockPos pos,
|
||||
boolean useExpansionHack,
|
||||
Optional<Heightmap.Types> projectStartToHeightmap,
|
||||
int maxDistanceFromCenter,
|
||||
PoolAliasLookup aliasLookup,
|
||||
DimensionPadding dimensionPadding,
|
||||
LiquidSettings liquidSettings,
|
||||
CallbackInfoReturnable<Optional<Structure.GenerationStub>> cir
|
||||
) {
|
||||
Optional<Structure.GenerationStub> result = cir.getReturnValue();
|
||||
if (result.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
BlockPos spawnPos = result.get().position();
|
||||
boolean canPlace = cobblemon$canAnyStartElementPlace(context, startPool, spawnPos);
|
||||
|
||||
if (canPlace) {
|
||||
return;
|
||||
}
|
||||
|
||||
cir.setReturnValue(Optional.empty());
|
||||
}
|
||||
|
||||
@Unique
|
||||
private static boolean cobblemon$canAnyStartElementPlace(
|
||||
Structure.GenerationContext generationContext,
|
||||
Holder<StructureTemplatePool> startPool,
|
||||
BlockPos startPos
|
||||
) {
|
||||
for (StructurePoolElement element : startPool.value().templates) {
|
||||
Optional<HeightRangeStructureProcessor> heightRangeProcessor = cobblemon$getHeightRangeProcessor(element);
|
||||
|
||||
if (heightRangeProcessor.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
HeightRangeStructureProcessor processor = heightRangeProcessor.get();
|
||||
boolean valid = processor.isValidPlacement(
|
||||
generationContext.chunkGenerator(),
|
||||
generationContext.heightAccessor(),
|
||||
generationContext.randomState(),
|
||||
startPos
|
||||
);
|
||||
|
||||
if (valid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Unique
|
||||
private static Optional<HeightRangeStructureProcessor> cobblemon$getHeightRangeProcessor(StructurePoolElement element) {
|
||||
if (!(element instanceof SinglePoolElement)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
StructureProcessorList processorList = ((SinglePoolElementAccessor) element).getProcessors().value();
|
||||
for (StructureProcessor processor : processorList.list()) {
|
||||
if (processor instanceof HeightRangeStructureProcessor heightRangeStructureProcessor) {
|
||||
return Optional.of(heightRangeStructureProcessor);
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.block.entity.DiscShelfBlockEntity;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.NoteBlock;
|
||||
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
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(NoteBlock.class)
|
||||
public abstract class NoteBlockMixin {
|
||||
@Inject(method = "triggerEvent", at = @At("HEAD"), cancellable = true)
|
||||
private void cobblemon$triggerTMShelfSequencer(BlockState state, Level level, BlockPos pos, int type, int data, CallbackInfoReturnable<Boolean> cir) {
|
||||
final BlockPos shelfPos = pos.below();
|
||||
final BlockEntity blockEntity = level.getBlockEntity(shelfPos);
|
||||
if (!(blockEntity instanceof DiscShelfBlockEntity discShelfBlockEntity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!level.isClientSide) {
|
||||
final BlockPos instrumentPos = shelfPos.below();
|
||||
final SoundEvent soundEvent;
|
||||
if (level.getBlockState(instrumentPos).isAir()) {
|
||||
soundEvent = SoundEvents.NOTE_BLOCK_BIT.value();
|
||||
} else {
|
||||
final NoteBlockInstrument instrument = level.getBlockState(instrumentPos).instrument();
|
||||
final Holder<SoundEvent> holder = instrument.getSoundEvent();
|
||||
soundEvent = holder.value();
|
||||
}
|
||||
discShelfBlockEntity.onNoteBlockPulse(level, pos, soundEvent);
|
||||
}
|
||||
|
||||
// Suppress vanilla note-block playback while it is on top of a TM Shelf.
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@ import com.cobblemon.mod.common.api.events.CobblemonEvents;
|
||||
import com.cobblemon.mod.common.api.events.item.LeftoversCreatedEvent;
|
||||
import com.cobblemon.mod.common.api.orientation.OrientationController;
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies;
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle;
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.air.HoverBehaviour;
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore;
|
||||
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore;
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags;
|
||||
@@ -59,6 +61,7 @@ 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.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@@ -169,6 +172,32 @@ public abstract class PlayerMixin extends LivingEntity implements ScannableEntit
|
||||
}
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "getDestroySpeed",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/entity/player/Player;onGround()Z"
|
||||
)
|
||||
)
|
||||
private boolean cobblemon$considerHoverOnGround(Player player) {
|
||||
// If riding a Hover Mount, return true to bypass the 5x slowdown
|
||||
if (player.getVehicle() instanceof PokemonEntity vehicle) {
|
||||
|
||||
var ridingController = vehicle.getRidingController();
|
||||
if (ridingController == null) player.onGround();
|
||||
|
||||
var activeContext = ridingController.getContext();
|
||||
if (activeContext == null) player.onGround();
|
||||
|
||||
if (activeContext.getStyle() == RidingStyle.AIR &&
|
||||
activeContext.getBehaviour().equals(HoverBehaviour.Companion.getKEY())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Otherwise, return the actual value
|
||||
return player.onGround();
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "eat",
|
||||
at = @At(
|
||||
|
||||
@@ -19,8 +19,10 @@ import com.cobblemon.mod.common.mixin.accessor.TrackedEntityAccessor;
|
||||
import com.cobblemon.mod.common.net.messages.client.orientation.ClientboundUpdateDriverInputPacket;
|
||||
import com.cobblemon.mod.common.net.messages.client.orientation.ClientboundUpdateOrientationPacket;
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.ClientboundUpdateRidingStatePacket;
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.ClientboundSeatAssignmentPacket;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.server.level.ServerEntity;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
@@ -37,6 +39,7 @@ 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.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -53,12 +56,15 @@ public abstract class ServerEntityMixin {
|
||||
private Matrix3f cobblemon$lastSentOrientation;
|
||||
@Unique
|
||||
private boolean cobblemon$lastSentActive;
|
||||
@Unique
|
||||
private List<Entity> cobblemon$lastSeatPassengers = List.of();
|
||||
|
||||
@Inject(method = "sendChanges", at = @At("TAIL"))
|
||||
private void cobblemon$sendChanges(CallbackInfo ci) {
|
||||
cobblemon$sendOrientationChanges();
|
||||
cobblemon$sendRidingStateChanges();
|
||||
cobblemon$sendDriverInput();
|
||||
cobblemon$sendOccupiedSeatsChange();
|
||||
}
|
||||
|
||||
private void cobblemon$sendRidingStateChanges() {
|
||||
@@ -101,6 +107,24 @@ public abstract class ServerEntityMixin {
|
||||
cobblemon$broadcast(new ClientboundUpdateDriverInputPacket(driverInput, entity.getId()));
|
||||
}
|
||||
|
||||
private void cobblemon$sendOccupiedSeatsChange() {
|
||||
if (!(this.entity instanceof PokemonEntity pokemon)) return;
|
||||
|
||||
List<Entity> currentPassengers = pokemon.getPassengers();
|
||||
if (currentPassengers.equals(cobblemon$lastSeatPassengers)) return;
|
||||
cobblemon$lastSeatPassengers = List.copyOf(currentPassengers);
|
||||
|
||||
pokemon.getOccupiedSeats().forEach((seat, passenger) -> {
|
||||
if (seat.getLocator() == null) return;
|
||||
if (passenger == null) return;
|
||||
cobblemon$broadcast(new ClientboundSeatAssignmentPacket(
|
||||
passenger.getId(),
|
||||
pokemon.getId(),
|
||||
seat.getLocator()
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
private void cobblemon$broadcast(NetworkPacket<?> packet) {
|
||||
if (!(entity.level() instanceof ServerLevel level)) return;
|
||||
ChunkMap chunkMap = level.getChunkSource().chunkMap;
|
||||
@@ -115,5 +139,4 @@ public abstract class ServerEntityMixin {
|
||||
CobblemonNetwork.INSTANCE.sendPacketToPlayer(player, packet);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ 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.util.Mth;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
@@ -32,6 +33,7 @@ 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.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
import java.util.Iterator;
|
||||
@@ -108,6 +110,17 @@ public abstract class SoundEngineMixin implements SoundEngineDuck {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TM Shelf can intentionally push note-block pitches above vanilla's 2.0f ceiling for octave-up playback.
|
||||
* Keep vanilla clamping for all other sounds.
|
||||
*/
|
||||
@Inject(method = "calculatePitch", at = @At("HEAD"), cancellable = true)
|
||||
private void cobblemon$allowExtendedNoteblockPitch(SoundInstance sound, CallbackInfoReturnable<Float> cir) {
|
||||
if (sound.getLocation().getPath().startsWith("block.note_block.")) {
|
||||
cir.setReturnValue(Mth.clamp(sound.getPitch(), 0.5F, 4.0F));
|
||||
}
|
||||
}
|
||||
|
||||
/** Different behavior for resuming SoundInstances while a BattleMusicInstance is being played. We do not want to resume filtered sounds. */
|
||||
@Inject(method = "resume()V", at = @At("HEAD"), cancellable = true)
|
||||
public void resume(CallbackInfo cb) {
|
||||
|
||||
@@ -1,67 +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.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.accessor;
|
||||
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.core.dispenser.DispenseItemBehavior;
|
||||
import net.minecraft.world.level.block.DispenserBlock;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(DispenserBlock.class)
|
||||
public interface DispenserBlockAccessor {
|
||||
@Accessor("DISPENSER_REGISTRY")
|
||||
static Map<Item, DispenseItemBehavior> getItemBehaviors() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.accessor;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.world.level.levelgen.structure.pools.SinglePoolElement;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorList;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(SinglePoolElement.class)
|
||||
public interface SinglePoolElementAccessor {
|
||||
@Accessor("processors")
|
||||
Holder<StructureProcessorList> getProcessors();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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 com.cobblemon.mod.common.duck.ChannelDuck;
|
||||
import com.mojang.blaze3d.audio.Channel;
|
||||
import org.lwjgl.openal.AL10;
|
||||
import org.lwjgl.openal.AL11;
|
||||
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;
|
||||
|
||||
// Ids of effects applied to the channel
|
||||
private int cobblemon$lowPassFilterId = 0;
|
||||
private int cobblemon$reverbEffectId = 0;
|
||||
private int cobblemon$reverbSlotId = 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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cobblemon$applyReverb(float decayTime, float gain, float diffusion, float density) {
|
||||
// Clean up existing reverb first if it exists
|
||||
cobblemon$clearReverb();
|
||||
|
||||
// Create the effect object
|
||||
int effectId = EXTEfx.alGenEffects();
|
||||
if (!EXTEfx.alIsEffect(effectId)) {
|
||||
System.err.println("Failed to create OpenAL reverb effect");
|
||||
return;
|
||||
}
|
||||
|
||||
EXTEfx.alEffecti(effectId, EXTEfx.AL_EFFECT_TYPE, EXTEfx.AL_EFFECT_REVERB);
|
||||
EXTEfx.alEffectf(effectId, EXTEfx.AL_REVERB_DECAY_TIME, decayTime);
|
||||
EXTEfx.alEffectf(effectId, EXTEfx.AL_REVERB_GAIN, gain);
|
||||
EXTEfx.alEffectf(effectId, EXTEfx.AL_REVERB_DIFFUSION, diffusion);
|
||||
EXTEfx.alEffectf(effectId, EXTEfx.AL_REVERB_DENSITY, density);
|
||||
|
||||
// Create auxiliary effect slot and load effect into it
|
||||
int slotId = EXTEfx.alGenAuxiliaryEffectSlots();
|
||||
if (!EXTEfx.alIsAuxiliaryEffectSlot(slotId)) {
|
||||
System.err.println("Failed to create OpenAL auxiliary effect slot");
|
||||
EXTEfx.alDeleteEffects(effectId);
|
||||
return;
|
||||
}
|
||||
|
||||
EXTEfx.alAuxiliaryEffectSloti(slotId, EXTEfx.AL_EFFECTSLOT_EFFECT, effectId);
|
||||
|
||||
// Route source through the slot — send 0, no direct filter
|
||||
AL11.alSource3i(source, EXTEfx.AL_AUXILIARY_SEND_FILTER, slotId, 0, EXTEfx.AL_FILTER_NULL);
|
||||
|
||||
cobblemon$reverbEffectId = effectId;
|
||||
cobblemon$reverbSlotId = slotId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cobblemon$clearReverb() {
|
||||
if (cobblemon$reverbSlotId != 0) {
|
||||
// Detach source from slot
|
||||
AL11.alSource3i(source, EXTEfx.AL_AUXILIARY_SEND_FILTER,
|
||||
EXTEfx.AL_EFFECTSLOT_NULL, 0, EXTEfx.AL_FILTER_NULL);
|
||||
EXTEfx.alDeleteAuxiliaryEffectSlots(cobblemon$reverbSlotId);
|
||||
cobblemon$reverbSlotId = 0;
|
||||
}
|
||||
if (cobblemon$reverbEffectId != 0) {
|
||||
EXTEfx.alDeleteEffects(cobblemon$reverbEffectId);
|
||||
cobblemon$reverbEffectId = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,13 @@
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.CobblemonItemComponents;
|
||||
import com.cobblemon.mod.common.CobblemonItems;
|
||||
import com.cobblemon.mod.common.ModAPI;
|
||||
import com.cobblemon.mod.common.item.PokeBallItem;
|
||||
import com.cobblemon.mod.common.item.PokedexItem;
|
||||
import com.cobblemon.mod.common.item.WearableItem;
|
||||
import com.cobblemon.mod.common.item.components.TMMoveComponent;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.ItemModelShaper;
|
||||
@@ -54,11 +57,17 @@ public abstract class ItemRendererMixin {
|
||||
cancellable = true
|
||||
)
|
||||
private void cobblemon$overrideItemModel(ItemStack stack, ItemDisplayContext renderMode, boolean leftHanded, PoseStack matrices, MultiBufferSource multiBufferSource, int light, int overlay, BakedModel model, CallbackInfo ci) {
|
||||
boolean shouldBe2d = renderMode == ItemDisplayContext.GUI || renderMode == ItemDisplayContext.FIXED;
|
||||
boolean shouldBe2d = renderMode == ItemDisplayContext.GUI || renderMode == ItemDisplayContext.FIXED || stack.getItem() == CobblemonItems.TECHNICAL_MACHINE;
|
||||
ResourceLocation resourceLocation = null;
|
||||
if (shouldBe2d) {
|
||||
if (stack.getItem() instanceof PokeBallItem pokeBallItem) resourceLocation = pokeBallItem.getPokeBall().getModel2d();
|
||||
else if (stack.getItem() instanceof PokedexItem pokedexItem) resourceLocation = pokedexItem.getType().getItemSpritePath();
|
||||
else if (stack.getItem() == CobblemonItems.TECHNICAL_MACHINE) {
|
||||
TMMoveComponent component = stack.get(CobblemonItemComponents.TM_MOVE);
|
||||
if (component != null) {
|
||||
resourceLocation = new ResourceLocation(Cobblemon.MODID, "tm/" + component.getMove().getElementalType().showdownId() + "_tm");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (renderMode != ItemDisplayContext.HEAD && stack.getItem() instanceof WearableItem wearableItem) resourceLocation = wearableItem.getModel2d();
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.cobblemon.mod.common.duck.RidePassenger;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.net.messages.server.orientation.ServerboundUpdateOrientationPacket;
|
||||
import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdateDriverInputPacket;
|
||||
import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdatePassengerPositionPacket;
|
||||
import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdateRiderRotationPacket;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.client.CameraType;
|
||||
@@ -148,10 +149,22 @@ public abstract class LocalPlayerMixin extends AbstractClientPlayer implements O
|
||||
cobblemon$lastRideYRot = rideYRot;
|
||||
cobblemon$lastRideEyePos = rideEyePos;
|
||||
|
||||
CobblemonNetwork.INSTANCE.sendToServer(new ServerboundUpdateRiderRotationPacket(rideXRot, rideYRot, rideEyePos));
|
||||
CobblemonNetwork.INSTANCE.sendToServer(
|
||||
new ServerboundUpdateRiderRotationPacket(rideXRot, rideYRot, rideEyePos)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "rideTick", at = @At("TAIL"))
|
||||
private void cobblemon$updatePassengerPosition(CallbackInfo ci) {
|
||||
if (Minecraft.getInstance().player != (Object)this) return;
|
||||
if (!(this.getVehicle() instanceof PokemonEntity pokemonEntity)) return;
|
||||
if (pokemonEntity.getSeatForPassenger(this) == null) return;
|
||||
|
||||
var offset = this.position().subtract(pokemonEntity.position());
|
||||
CobblemonNetwork.INSTANCE.sendToServer(
|
||||
new ServerboundUpdatePassengerPositionPacket(this.getId(), offset)
|
||||
);
|
||||
}
|
||||
|
||||
@Unique
|
||||
@@ -217,9 +230,10 @@ public abstract class LocalPlayerMixin extends AbstractClientPlayer implements O
|
||||
private void cobblemon$isHandsBusy(CallbackInfoReturnable<Boolean> cir) {
|
||||
Entity vehicle = this.getVehicle();
|
||||
if (vehicle instanceof PokemonEntity pokemonEntity) {
|
||||
int seatIndex = pokemonEntity.getPassengers().indexOf(this);
|
||||
Seat seat = pokemonEntity.getSeats().get(seatIndex);
|
||||
cir.setReturnValue(seat.getHandsBusy());
|
||||
Seat seat = pokemonEntity.getSeatForPassenger(this);;
|
||||
if (seat != null) {
|
||||
cir.setReturnValue(seat.getHandsBusy());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonBakingOverrides;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.color.block.BlockColors;
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import net.minecraft.client.resources.model.BlockStateModelLoader;
|
||||
@@ -18,29 +17,76 @@ import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.client.resources.model.UnbakedModel;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.Resource;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
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 java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mixin(ModelBakery.class)
|
||||
public abstract class ModelLoaderMixin {
|
||||
|
||||
@Shadow abstract UnbakedModel getModel(ResourceLocation resourceLocation);
|
||||
|
||||
@Shadow protected abstract void registerModel(ModelResourceLocation modelId, UnbakedModel unbakedModel);
|
||||
|
||||
@Shadow protected abstract void loadItemModelAndDependencies(ResourceLocation resourceLocation);
|
||||
|
||||
@Unique
|
||||
List<String> dynamicFolders = Arrays.asList("egg", "tm");
|
||||
|
||||
@Inject(
|
||||
method = "<init>",
|
||||
at = @At("TAIL")
|
||||
method = "<init>",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/util/profiling/ProfilerFiller;popPush(Ljava/lang/String;)V",
|
||||
ordinal = 1
|
||||
)
|
||||
)
|
||||
public void loadCustomItemModels(BlockColors blockColors,
|
||||
ProfilerFiller profiler,
|
||||
Map<ResourceLocation, BlockModel> jsonUnbakedModels,
|
||||
Map<ResourceLocation, List<BlockStateModelLoader.LoadedJson>> blockStates,
|
||||
CallbackInfo ci
|
||||
) {
|
||||
/*
|
||||
* The models/item/*.json's only get loaded if there's an item in the registry that actually asks for it. It
|
||||
* naively looks for things in the root with an item ID and calls upon it, and some of those JSONs reference
|
||||
* other model JSONs and so it cascades a little bit. Used for block models but more importantly here, sprites.
|
||||
*
|
||||
* The thing about the eggs (and TMs) is, we really want the eggs to be addon-compatible in a way that doesn't restrict
|
||||
* the species that can have eggs, so we can't pre-plan all of them. This mixin looks for the things inside the
|
||||
* egg subfolder (which won't get loaded automagically) and manually inserts them into the unbaked model list so
|
||||
* Minecraft loads them for us. We'll then dynamically call these models from the ItemRendererMixin; so it's
|
||||
* hacky at the init stage and hacky at the render stage. Pretty cool in the gameplay stage though.
|
||||
*
|
||||
* - Hiro
|
||||
*/
|
||||
|
||||
dynamicFolders.forEach(folder -> {
|
||||
Map<ResourceLocation, Resource> map = Minecraft.getInstance().getResourceManager().listResources("models/item/" + folder, (t) -> true);
|
||||
map.forEach((key, value) -> {
|
||||
ResourceLocation resourceLocation = new ResourceLocation(key.getNamespace(), key.getPath().replace("models/item/", "").replace(".json", ""));
|
||||
this.loadItemModelAndDependencies(resourceLocation);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "<init>",
|
||||
at = @At("TAIL")
|
||||
)
|
||||
public void init(BlockColors blockColors,
|
||||
ProfilerFiller profiler,
|
||||
Map<ResourceLocation, BlockModel> jsonUnbakedModels,
|
||||
Map<ResourceLocation, List<BlockStateModelLoader.LoadedJson>> blockStates,
|
||||
CallbackInfo ci) {
|
||||
ProfilerFiller profiler,
|
||||
Map<ResourceLocation, BlockModel> jsonUnbakedModels,
|
||||
Map<ResourceLocation, List<BlockStateModelLoader.LoadedJson>> blockStates,
|
||||
CallbackInfo ci) {
|
||||
CobblemonBakingOverrides.INSTANCE.getModels().forEach(bakingOverride -> {
|
||||
var unbakedModel = this.getModel(bakingOverride.getModelLocation());
|
||||
this.registerModel(bakingOverride.getModelIdentifier(), unbakedModel);
|
||||
|
||||
@@ -35,6 +35,7 @@ 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 com.cobblemon.mod.common.client.gui.party.PartyTutorialToasts;
|
||||
|
||||
import static com.google.common.primitives.Floats.min;
|
||||
import static net.minecraft.util.Mth.lerp;
|
||||
@@ -85,11 +86,13 @@ public abstract class MouseHandlerMixin {
|
||||
CobblemonClient.INSTANCE.getStorage().shiftSelected(false);
|
||||
ci.cancel();
|
||||
PartySendBinding.INSTANCE.actioned();
|
||||
PartyTutorialToasts.INSTANCE.onHoldKeyScrollSwitchedSlot();
|
||||
} else if (i < 0) {
|
||||
accumulatedScrollY -= i;
|
||||
CobblemonClient.INSTANCE.getStorage().shiftSelected(true);
|
||||
ci.cancel();
|
||||
PartySendBinding.INSTANCE.actioned();
|
||||
PartyTutorialToasts.INSTANCE.onHoldKeyScrollSwitchedSlot();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -310,7 +313,7 @@ public abstract class MouseHandlerMixin {
|
||||
var playerRotater = (RidePassenger)player;
|
||||
playerRotater.cobblemon$setRideXRot(playerRotater.cobblemon$getRideXRot() + f);
|
||||
playerRotater.cobblemon$setRideYRot(playerRotater.cobblemon$getRideYRot() + g);
|
||||
playerRotater.cobblemon$setRideXRot(Mth.clamp(playerRotater.cobblemon$getRideXRot(), -90.0F, 90.0F));
|
||||
playerRotater.cobblemon$setRideXRot(Mth.clamp(playerRotater.cobblemon$getRideXRot(), -89.0F, 89.0F));
|
||||
playerRotater.cobblemon$setRideYRot(Mth.clamp(playerRotater.cobblemon$getRideYRot(), -105.0F, 105.0F));
|
||||
if (player.getVehicle() != null) {
|
||||
player.getVehicle().onPassengerTurned(player);
|
||||
|
||||
@@ -14,9 +14,14 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import com.llamalad7.mixinextras.sugar.Share;
|
||||
import com.llamalad7.mixinextras.sugar.ref.LocalBooleanRef;
|
||||
import com.llamalad7.mixinextras.sugar.ref.LocalFloatRef;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
@@ -89,4 +94,61 @@ public abstract class EntityMixin {
|
||||
cir.setReturnValue(customEyePos);
|
||||
}
|
||||
|
||||
|
||||
@WrapOperation(
|
||||
method = "push(Lnet/minecraft/world/entity/Entity;)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;push(DDD)V", ordinal = 0)
|
||||
)
|
||||
public void cobblemon$customPusherLogic(Entity pusher, double x, double y, double z,
|
||||
Operation<Void> original,
|
||||
@Local(argsOnly = true) Entity pushee,
|
||||
@Local(name = "e") double e, @Local(name = "d") double d,
|
||||
@Share("pusherIsPlayerOrPokemon") LocalBooleanRef pusherIsPlayerOrPokemon,
|
||||
@Share("pusheeIsPlayerOrPokemon") LocalBooleanRef pusheeIsPlayerOrPokemon,
|
||||
@Share("pusheeReceivedForce")LocalFloatRef pusheeReceivedForce) {
|
||||
pusherIsPlayerOrPokemon.set(pusher instanceof PokemonEntity || pusher instanceof Player);
|
||||
pusheeIsPlayerOrPokemon.set(pushee instanceof PokemonEntity || pushee instanceof Player);
|
||||
|
||||
if (!pusheeIsPlayerOrPokemon.get() || !pusherIsPlayerOrPokemon.get()) {
|
||||
original.call(pusher, x, y, z);
|
||||
return;
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Custom portion of the code:
|
||||
* Handle collisions with weight in mind. Use
|
||||
* the weight value of pokemon to determine
|
||||
* which side gets what portion of the total
|
||||
* force.
|
||||
*********************************************/
|
||||
// Weights in hectograms
|
||||
// Check to see if the pusher or pushee is a player. 200ish pounds. Steve's like a 6'6 miner
|
||||
var pusherWeight = pusher instanceof PokemonEntity pusherPokemon ? pusherPokemon.getPokemon().getSpecies().getWeight() : 900F;
|
||||
var pusheeWeight = pushee instanceof PokemonEntity pusheePokemon ? pusheePokemon.getPokemon().getSpecies().getWeight() : 900F;
|
||||
|
||||
// Calculate the portion of force received for both entities. Bigger receives less from the
|
||||
// collision than the smaller one.
|
||||
var totalWeight = pusherWeight + pusheeWeight;
|
||||
var pusherReceivedForce = pusheeWeight / totalWeight * 2F;
|
||||
pusheeReceivedForce.set((pusherWeight / totalWeight) * 2F);
|
||||
|
||||
original.call(pusher, -d * pusherReceivedForce, 0.0, -e * pusherReceivedForce);
|
||||
}
|
||||
|
||||
@WrapOperation(
|
||||
method = "push(Lnet/minecraft/world/entity/Entity;)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;push(DDD)V", ordinal = 1)
|
||||
)
|
||||
public void cobblemon$customPusheeLogic(Entity pusher, double x, double y, double z, Operation<Void> original,
|
||||
@Local(name = "e") double e, @Local(name = "d") double d,
|
||||
@Share("pusherIsPlayerOrPokemon") LocalBooleanRef pusherIsPlayerOrPokemon,
|
||||
@Share("pusheeIsPlayerOrPokemon") LocalBooleanRef pusheeIsPlayerOrPokemon,
|
||||
@Share("pusheeReceivedForce")LocalFloatRef pusheeReceivedForce) {
|
||||
if (!pusheeIsPlayerOrPokemon.get() || !pusherIsPlayerOrPokemon.get()) {
|
||||
original.call(pusher, x, y, z);
|
||||
return;
|
||||
}
|
||||
|
||||
original.call(pusher, d * pusheeReceivedForce.get(), 0.0, e * pusheeReceivedForce.get());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.cobblemon.mod.common.api.drop.EvolutionItemDropEntry
|
||||
import com.cobblemon.mod.common.api.drop.ItemDropEntry
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.DATA_SYNCHRONIZED
|
||||
import com.cobblemon.mod.common.api.habitats.HabitatPools
|
||||
import com.cobblemon.mod.common.api.interaction.RequestManager
|
||||
import com.cobblemon.mod.common.api.molang.MoLangLoadedFilesCache
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
@@ -33,6 +34,7 @@ import com.cobblemon.mod.common.api.pokemon.feature.ChoiceSpeciesFeatureProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.FlagSpeciesFeatureProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.IntSpeciesFeatureProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.SpeciesFeatures
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.WeightedChoiceSpeciesFeatureProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.helditem.HeldItemProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.EvCalculator
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Generation8EvCalculator
|
||||
@@ -62,13 +64,19 @@ import com.cobblemon.mod.common.api.storage.player.adapter.DexDataMongoBackend
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.DexDataNbtBackend
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.PlayerDataJsonBackend
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.PlayerDataMongoBackend
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.TMMoveMongoBackend
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.TMMoveNbtBackend
|
||||
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.*
|
||||
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.actor.PokemonBattleActor
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.block.DispenserBehaviorRegistry
|
||||
import com.cobblemon.mod.common.block.dispenser.DispenserBehaviorRegistry
|
||||
import com.cobblemon.mod.common.client.CobblemonPack
|
||||
import com.cobblemon.mod.common.command.argument.*
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
@@ -76,22 +84,36 @@ import com.cobblemon.mod.common.config.LastChangedVersion
|
||||
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.*
|
||||
import com.cobblemon.mod.common.events.AdvancementHandler
|
||||
import com.cobblemon.mod.common.events.CallbackHandler
|
||||
import com.cobblemon.mod.common.events.EntityCallbackHandler
|
||||
import com.cobblemon.mod.common.events.PokedexHandler
|
||||
import com.cobblemon.mod.common.events.ServerTickHandler
|
||||
import com.cobblemon.mod.common.events.StatHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
|
||||
import com.cobblemon.mod.common.permission.LaxPermissionValidator
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.aspects.ALPHA_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.aspects.CHARACTERISTIC_RAINBOW_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.aspects.COSMETIC_SLOT_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.aspects.GENDER_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.aspects.MARK_ASPECT
|
||||
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.SlowpokeTailRegrowthSpeciesFeature
|
||||
import com.cobblemon.mod.common.pokemon.feature.SlowpokeTailRegrowthSpeciesFeatureProvider
|
||||
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.pokemon.properties.*
|
||||
import com.cobblemon.mod.common.pokemon.properties.tags.PokemonFlagProperty
|
||||
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.HeldItemVisibleProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.HiddenAbilityPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.LabelProperty
|
||||
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.stat.CobblemonStatProvider
|
||||
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
|
||||
import com.cobblemon.mod.common.util.*
|
||||
@@ -102,6 +124,17 @@ 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.resources.ResourceKey
|
||||
@@ -114,17 +147,6 @@ 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
|
||||
@@ -165,7 +187,7 @@ object Cobblemon {
|
||||
val statistics: CobblemonStats = CobblemonStats
|
||||
|
||||
@JvmStatic
|
||||
val builtinPacks = listOf<CobblemonPack>(
|
||||
val builtinPacks = listOf(
|
||||
CobblemonPack(id = "adorncompatibility", name = "Adorn Compatibility", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.ALWAYS_ENABLED, neededMods = setOf("adorn")),
|
||||
CobblemonPack(id = "gyaradosjump", name = "Gyarados Jump Patterns", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED),
|
||||
CobblemonPack(id = "regionbiasforms", name = "Region Bias Forms", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED),
|
||||
@@ -201,6 +223,7 @@ object Cobblemon {
|
||||
implementation.registerEntityDataSerializers()
|
||||
implementation.registerCriteria()
|
||||
implementation.registerEntitySubPredicates()
|
||||
implementation.registerMobEffects()
|
||||
DispenserBehaviorRegistry.registerDispenserBehaviors()
|
||||
|
||||
DropEntry.register("command", CommandDropEntry::class.java)
|
||||
@@ -222,6 +245,8 @@ object Cobblemon {
|
||||
|
||||
DATA_SYNCHRONIZED.subscribe {
|
||||
storage.onPlayerDataSync(it)
|
||||
it.tmList().scheduleFullSyncFromStores(it.party(), it.pc())
|
||||
it.pokedex().scheduleFullSyncFromStores(it.party(), it.pc())
|
||||
playerDataManager.syncAllToPlayer(it)
|
||||
starterHandler.handleJoin(it)
|
||||
it.requestWallpapers()
|
||||
@@ -284,6 +309,9 @@ object Cobblemon {
|
||||
this.config.maxPokemonLevel,
|
||||
this.config.maxPokemonFriendship,
|
||||
this.config.maxDynamaxLevel,
|
||||
this.config.unlockAllMoveDexMovesByDefault,
|
||||
this.config.pokemonIntrinsicSizeMin,
|
||||
this.config.pokemonIntrinsicSizeMax
|
||||
).sendToPlayer(player)
|
||||
}
|
||||
|
||||
@@ -297,8 +325,11 @@ object Cobblemon {
|
||||
GENDER_ASPECT.register()
|
||||
COSMETIC_SLOT_ASPECT.register()
|
||||
CHARACTERISTIC_RAINBOW_ASPECT.register()
|
||||
ALPHA_ASPECT.register()
|
||||
MARK_ASPECT.register()
|
||||
|
||||
SpeciesFeatures.types["choice"] = ChoiceSpeciesFeatureProvider::class.java
|
||||
SpeciesFeatures.types["weighted_choice"] = WeightedChoiceSpeciesFeatureProvider::class.java
|
||||
SpeciesFeatures.types["flag"] = FlagSpeciesFeatureProvider::class.java
|
||||
SpeciesFeatures.types["integer"] = IntSpeciesFeatureProvider::class.java
|
||||
|
||||
@@ -314,12 +345,13 @@ object Cobblemon {
|
||||
|
||||
CustomPokemonProperty.register(UncatchableProperty)
|
||||
CustomPokemonProperty.register(BattleCloneProperty)
|
||||
CustomPokemonProperty.register(PokemonFlagProperty)
|
||||
CustomPokemonProperty.register(LabelProperty)
|
||||
CustomPokemonProperty.register(HiddenAbilityPropertyType)
|
||||
CustomPokemonProperty.register(AspectPropertyType)
|
||||
CustomPokemonProperty.register(UnaspectPropertyType)
|
||||
CustomPokemonProperty.register(FreezeFrameProperty)
|
||||
CustomPokemonProperty.register(NoAIProperty)
|
||||
CustomPokemonProperty.register(HeldItemVisibleProperty)
|
||||
|
||||
CobblemonEvents.POKEMON_PROPERTY_INITIALISED.emit(Unit)
|
||||
|
||||
@@ -341,6 +373,7 @@ object Cobblemon {
|
||||
val server = event.server
|
||||
MoLangLoadedFilesCache.initialize(server)
|
||||
playerDataManager = PlayerInstancedDataStoreManager().also { it.setup(server) }
|
||||
HabitatPools.onServerLoading(server)
|
||||
|
||||
val mongoClient: MongoClient?
|
||||
|
||||
@@ -353,8 +386,12 @@ object Cobblemon {
|
||||
val pokedexNbtFactory = CachedPlayerDataStoreFactory(DexDataNbtBackend())
|
||||
pokedexNbtFactory.setup(server)
|
||||
|
||||
val tmMoveFactory = CachedPlayerDataStoreFactory(TMMoveNbtBackend())
|
||||
tmMoveFactory.setup(server)
|
||||
|
||||
playerDataManager.setFactory(generalJsonFactory, PlayerInstancedDataStoreTypes.GENERAL)
|
||||
playerDataManager.setFactory(pokedexNbtFactory, PlayerInstancedDataStoreTypes.POKEDEX)
|
||||
playerDataManager.setFactory(tmMoveFactory, PlayerInstancedDataStoreTypes.TM_MOVES)
|
||||
|
||||
if (config.storageFormat == "nbt") {
|
||||
NBTStoreAdapter(pokemonStoreRoot.absolutePath, useNestedFolders = true, folderPerClass = true)
|
||||
@@ -381,8 +418,14 @@ object Cobblemon {
|
||||
val pokedexMongoFactory = CachedPlayerDataStoreFactory(DexDataMongoBackend(mongoClient, config.mongoDBDatabaseName, "PokeDexCollection"))
|
||||
pokedexMongoFactory.setup(server)
|
||||
|
||||
val tmMovesMongoFactory = CachedPlayerDataStoreFactory(
|
||||
TMMoveMongoBackend(mongoClient, config.mongoDBDatabaseName, "TMMovesCollection")
|
||||
)
|
||||
tmMovesMongoFactory.setup(server)
|
||||
|
||||
playerDataManager.setFactory(generalMongoFactory, PlayerInstancedDataStoreTypes.GENERAL)
|
||||
playerDataManager.setFactory(pokedexMongoFactory, PlayerInstancedDataStoreTypes.POKEDEX)
|
||||
playerDataManager.setFactory(tmMovesMongoFactory, PlayerInstancedDataStoreTypes.TM_MOVES)
|
||||
MongoDBStoreAdapter(mongoClient, config.mongoDBDatabaseName)
|
||||
} catch (e: ClassNotFoundException) {
|
||||
LOGGER.error("MongoDB driver not found.")
|
||||
@@ -450,7 +493,7 @@ object Cobblemon {
|
||||
server()?.getLevel(dimension)
|
||||
} else {
|
||||
val mc = Minecraft.getInstance()
|
||||
return mc.singleplayerServer?.getLevel(dimension) ?: mc.level
|
||||
mc.singleplayerServer?.getLevel(dimension) ?: mc.level
|
||||
}
|
||||
}
|
||||
|
||||
@@ -566,6 +609,7 @@ object Cobblemon {
|
||||
this.implementation.registerCommandArgument(cobblemonResource("mark"), MarkArgumentType::class, SingletonArgumentInfo.contextFree(MarkArgumentType::mark))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("transform_type"), TransformTypeArgumentType::class, SingletonArgumentInfo.contextFree(TransformTypeArgumentType::transformType))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("model_part"), ModelPartArgumentType::class, SingletonArgumentInfo.contextFree(ModelPartArgumentType::modelPart))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("tm"), TmArgumentType::class, SingletonArgumentInfo.contextFree(TmArgumentType::tm))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,22 +8,15 @@
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.block.entity.BerryBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.HealingMachineBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.PCBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.PokemonPastureBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.FossilAnalyzerBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.FossilMultiblockEntity
|
||||
import com.cobblemon.mod.common.block.entity.RestorationTankBlockEntity
|
||||
import com.cobblemon.mod.common.block.multiblock.FossilMultiblockBuilder
|
||||
import com.cobblemon.mod.common.block.entity.*
|
||||
import com.cobblemon.mod.common.block.entity.DisplayCaseBlockEntity
|
||||
import com.cobblemon.mod.common.block.habitat.HabitatBlockEntity
|
||||
import com.cobblemon.mod.common.block.multiblock.FossilMultiblockBuilder
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
|
||||
object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, ResourceKey<Registry<BlockEntityType<*>>>, BlockEntityType<*>>() {
|
||||
|
||||
@@ -39,6 +32,9 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
|
||||
@JvmField
|
||||
val LECTERN: BlockEntityType<LecternBlockEntity> = this.create("lectern", BlockEntityType.Builder.of(::LecternBlockEntity, CobblemonBlocks.LECTERN).build(null))
|
||||
|
||||
@JvmField
|
||||
val DISC_SHELF: BlockEntityType<DiscShelfBlockEntity> = this.create("disc_shelf", BlockEntityType.Builder.of(::DiscShelfBlockEntity, CobblemonBlocks.DISC_SHELF).build(null))
|
||||
|
||||
@JvmField
|
||||
val BERRY = this.create("berry", BlockEntityType.Builder.of(::BerryBlockEntity, *CobblemonBlocks.berries().values.toTypedArray()).build(null))
|
||||
|
||||
@@ -48,6 +44,13 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
|
||||
val SIGN: BlockEntityType<CobblemonSignBlockEntity> = this.create("sign", BlockEntityType.Builder.of(::CobblemonSignBlockEntity, CobblemonBlocks.APRICORN_SIGN, CobblemonBlocks.APRICORN_WALL_SIGN, CobblemonBlocks.SACCHARINE_SIGN, CobblemonBlocks.SACCHARINE_WALL_SIGN).build(null))
|
||||
@JvmField
|
||||
val HANGING_SIGN: BlockEntityType<CobblemonHangingSignBlockEntity> = this.create("hanging_sign", BlockEntityType.Builder.of(::CobblemonHangingSignBlockEntity, CobblemonBlocks.APRICORN_HANGING_SIGN, CobblemonBlocks.APRICORN_WALL_HANGING_SIGN, CobblemonBlocks.SACCHARINE_HANGING_SIGN, CobblemonBlocks.SACCHARINE_WALL_HANGING_SIGN).build(null))
|
||||
@JvmField
|
||||
val TM_MACHINE: BlockEntityType<TMMachineBlockEntity> = this.create("tm_machine", BlockEntityType.Builder.of(::TMMachineBlockEntity, CobblemonBlocks.TM_MACHINE).build(null))
|
||||
|
||||
@JvmField
|
||||
val HABITAT_BLOCK: BlockEntityType<HabitatBlockEntity> = this.create("habitat_block",
|
||||
BlockEntityType.Builder.of(::HabitatBlockEntity, CobblemonBlocks.HABITAT_BLOCK).build(null)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val GILDED_CHEST: BlockEntityType<GildedChestBlockEntity> = this.create("chest", BlockEntityType.Builder.of(::GildedChestBlockEntity,
|
||||
|
||||
@@ -9,21 +9,29 @@
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.apricorn.Apricorn
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.block.*
|
||||
import com.cobblemon.mod.common.block.campfirepot.CampfireBlock
|
||||
import com.cobblemon.mod.common.block.LecternBlock
|
||||
import com.cobblemon.mod.common.block.MintBlock.MintType
|
||||
import com.cobblemon.mod.common.block.campfirepot.CampfireBlock
|
||||
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.general.HorizontalRotationCarpetBlock
|
||||
import com.cobblemon.mod.common.block.general.HorizontalRotationalBlock
|
||||
import com.cobblemon.mod.common.block.grower.SaccharineTreeGrower
|
||||
import com.cobblemon.mod.common.block.habitat.HabitatBlock
|
||||
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.block.tmmachine.TMMachineBlock
|
||||
import com.cobblemon.mod.common.mixin.invoker.BlocksInvoker
|
||||
import com.cobblemon.mod.common.mixin.invoker.DoorBlockInvoker
|
||||
import com.cobblemon.mod.common.mixin.invoker.FireBlockInvoker
|
||||
import com.cobblemon.mod.common.mixin.invoker.PressurePlateBlockInvoker
|
||||
import com.cobblemon.mod.common.mixin.invoker.StairsBlockInvoker
|
||||
import com.cobblemon.mod.common.mixin.invoker.TrapdoorBlockInvoker
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.core.BlockPos
|
||||
@@ -41,7 +49,6 @@ import net.minecraft.world.level.block.state.BlockBehaviour
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.properties.BlockSetType
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties.LIT
|
||||
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument
|
||||
import net.minecraft.world.level.block.state.properties.WoodType
|
||||
import net.minecraft.world.level.material.MapColor
|
||||
@@ -120,19 +127,19 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
val APRICORN_PLANKS = this.create("apricorn_planks",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of().mapColor(MapColor.DIRT).instrument(NoteBlockInstrument.BASS)
|
||||
.strength(2.0f, 3.0f).sound(SoundType.WOOD)
|
||||
.strength(2.0F, 3.0F).sound(SoundType.WOOD)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val APRICORN_LEAVES = leaves("apricorn_leaves")
|
||||
@JvmField
|
||||
val APRICORN_FENCE = this.create("apricorn_fence", FenceBlock(BlockBehaviour.Properties.of().mapColor(APRICORN_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
|
||||
val APRICORN_FENCE = this.create("apricorn_fence", FenceBlock(BlockBehaviour.Properties.of().mapColor(APRICORN_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(2.0F, 3.0F).sound(SoundType.WOOD)))
|
||||
@JvmField
|
||||
val APRICORN_FENCE_GATE = this.create("apricorn_fence_gate", FenceGateBlock(APRICORN_WOOD_TYPE, BlockBehaviour.Properties.of().mapColor(APRICORN_PLANKS.defaultMapColor()).strength(2.0f, 3.0f).sound(SoundType.WOOD).ignitedByLava().forceSolidOn()))
|
||||
val APRICORN_FENCE_GATE = this.create("apricorn_fence_gate", FenceGateBlock(APRICORN_WOOD_TYPE, BlockBehaviour.Properties.of().mapColor(APRICORN_PLANKS.defaultMapColor()).strength(2.0F, 3.0F).sound(SoundType.WOOD).ignitedByLava().forceSolidOn()))
|
||||
@JvmField
|
||||
val APRICORN_BUTTON = this.create("apricorn_button", BlocksInvoker.createWoodenButtonBlock(APRICORN_BLOCK_SET_TYPE))
|
||||
@JvmField
|
||||
val APRICORN_PRESSURE_PLATE = this.create("apricorn_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(APRICORN_BLOCK_SET_TYPE, BlockBehaviour.Properties.of().mapColor(APRICORN_PLANKS.defaultMapColor()).noCollission().strength(0.5f).sound(SoundType.WOOD)))
|
||||
val APRICORN_PRESSURE_PLATE = this.create("apricorn_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(APRICORN_BLOCK_SET_TYPE, BlockBehaviour.Properties.of().mapColor(APRICORN_PLANKS.defaultMapColor()).noCollission().strength(0.5F).sound(SoundType.WOOD)))
|
||||
@JvmField
|
||||
val APRICORN_SIGN = this.create("apricorn_sign", CobblemonSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_SIGN), APRICORN_WOOD_TYPE))
|
||||
|
||||
@@ -149,7 +156,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val APRICORN_WALL_HANGING_SIGN = this.create("apricorn_wall_hanging_sign", CobblemonWallHangingSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_HANGING_SIGN), APRICORN_WOOD_TYPE))
|
||||
@JvmField
|
||||
val APRICORN_SLAB = this.create("apricorn_slab", SlabBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
|
||||
val APRICORN_SLAB = this.create("apricorn_slab", SlabBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).strength(2.0F, 3.0F).sound(SoundType.WOOD)))
|
||||
@JvmField
|
||||
val APRICORN_STAIRS = this.create("apricorn_stairs", StairsBlockInvoker.`cobblemon$create`(APRICORN_PLANKS.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(APRICORN_PLANKS)))
|
||||
@JvmField
|
||||
@@ -186,12 +193,12 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
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)))
|
||||
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
|
||||
val SACCHARINE_LEAVES = this.create("saccharine_leaves", SaccharineLeafBlock(
|
||||
BlockBehaviour.Properties.of().mapColor(
|
||||
MapColor.PLANT
|
||||
).strength(0.2f).randomTicks().sound(SoundType.GRASS).noOcclusion()
|
||||
).strength(0.2F).randomTicks().sound(SoundType.GRASS).noOcclusion()
|
||||
.isValidSpawn { _: BlockState?, _: BlockGetter?, _: BlockPos?, entity: EntityType<*>? ->
|
||||
entity === EntityType.OCELOT || entity === EntityType.PARROT
|
||||
}.isSuffocating { _: BlockState?, _: BlockGetter?, _: BlockPos? ->
|
||||
@@ -203,13 +210,13 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
false
|
||||
}))
|
||||
@JvmField
|
||||
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)))
|
||||
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).ignitedByLava().forceSolidOn()))
|
||||
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).ignitedByLava().forceSolidOn()))
|
||||
@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)))
|
||||
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)))
|
||||
@JvmField
|
||||
val SACCHARINE_SIGN = this.create("saccharine_sign", CobblemonSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_SIGN), SACCHARINE_WOOD_TYPE))
|
||||
@JvmField
|
||||
@@ -219,7 +226,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val SACCHARINE_WALL_HANGING_SIGN = this.create("saccharine_wall_hanging_sign", CobblemonWallHangingSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_HANGING_SIGN), SACCHARINE_WOOD_TYPE))
|
||||
@JvmField
|
||||
val SACCHARINE_SLAB = this.create("saccharine_slab", SlabBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
|
||||
val SACCHARINE_SLAB = this.create("saccharine_slab", SlabBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).strength(2.0F, 3.0F).sound(SoundType.WOOD)))
|
||||
@JvmField
|
||||
val SACCHARINE_STAIRS = this.create("saccharine_stairs", StairsBlockInvoker.`cobblemon$create`(SACCHARINE_PLANKS.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(SACCHARINE_PLANKS)))
|
||||
@JvmField
|
||||
@@ -243,36 +250,36 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
val REVIVAL_HERB = this.create("revival_herb", RevivalHerbBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).mapColor(MapColor.PLANT).ignitedByLava().noCollission().instabreak().sound(CobblemonSounds.REVIVAL_HERB_SOUNDS)))
|
||||
|
||||
@JvmField
|
||||
val POKE_CAKE = this.create("poke_cake", PokeSnackBlock(BlockBehaviour.Properties.of().forceSolidOn().strength(0.5F).sound(SoundType.WOOL).pushReaction(PushReaction.DESTROY).lightLevel { if (it.getValue(LIT)) 3 else 0 }, false))
|
||||
val POKE_CAKE = this.create("poke_cake", PokeSnackBlock(BlockBehaviour.Properties.of().forceSolidOn().strength(0.5F).sound(SoundType.WOOL).pushReaction(PushReaction.DESTROY).lightLevel { if (it.getValue(BlockStateProperties.LIT)) 3 else 0 }, false))
|
||||
@JvmField
|
||||
val POKE_SNACK = this.create("poke_snack", PokeSnackBlock(BlockBehaviour.Properties.of().forceSolidOn().strength(0.5F).sound(SoundType.WOOL).pushReaction(PushReaction.DESTROY).lightLevel { if (it.getValue(LIT)) 3 else 0 }, true))
|
||||
val POKE_SNACK = this.create("poke_snack", PokeSnackBlock(BlockBehaviour.Properties.of().forceSolidOn().strength(0.5F).sound(SoundType.WOOL).pushReaction(PushReaction.DESTROY).lightLevel { if (it.getValue(BlockStateProperties.LIT)) 3 else 0 }, true))
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE_CLUSTER = tumblestoneBlock("tumblestone_cluster", GrowableStoneBlock.STAGE_3, 7, 3, null)
|
||||
val TUMBLESTONE_CLUSTER = tumblestoneBlock("tumblestone_cluster", TumblestoneBlock.STAGE_3, 7, 3, null, MapColor.TERRACOTTA_ORANGE)
|
||||
@JvmField
|
||||
val LARGE_BUDDING_TUMBLESTONE = tumblestoneBlock("large_budding_tumblestone", GrowableStoneBlock.STAGE_2, 5, 3, TUMBLESTONE_CLUSTER)
|
||||
val LARGE_BUDDING_TUMBLESTONE = tumblestoneBlock("large_budding_tumblestone", TumblestoneBlock.STAGE_2, 5, 3, TUMBLESTONE_CLUSTER, MapColor.TERRACOTTA_ORANGE)
|
||||
@JvmField
|
||||
val MEDIUM_BUDDING_TUMBLESTONE = tumblestoneBlock("medium_budding_tumblestone", GrowableStoneBlock.STAGE_1, 4, 3, LARGE_BUDDING_TUMBLESTONE)
|
||||
val MEDIUM_BUDDING_TUMBLESTONE = tumblestoneBlock("medium_budding_tumblestone", TumblestoneBlock.STAGE_1, 4, 3, LARGE_BUDDING_TUMBLESTONE, MapColor.TERRACOTTA_ORANGE)
|
||||
@JvmField
|
||||
val SMALL_BUDDING_TUMBLESTONE = tumblestoneBlock("small_budding_tumblestone", GrowableStoneBlock.STAGE_0, 3, 4, MEDIUM_BUDDING_TUMBLESTONE)
|
||||
val SMALL_BUDDING_TUMBLESTONE = tumblestoneBlock("small_budding_tumblestone", TumblestoneBlock.STAGE_0, 3, 4, MEDIUM_BUDDING_TUMBLESTONE, MapColor.TERRACOTTA_ORANGE)
|
||||
|
||||
@JvmField
|
||||
val SKY_TUMBLESTONE_CLUSTER = tumblestoneBlock("sky_tumblestone_cluster", GrowableStoneBlock.STAGE_3, 7, 3, null)
|
||||
val SKY_TUMBLESTONE_CLUSTER = tumblestoneBlock("sky_tumblestone_cluster", TumblestoneBlock.STAGE_3, 7, 3, null, MapColor.COLOR_LIGHT_BLUE)
|
||||
@JvmField
|
||||
val LARGE_BUDDING_SKY_TUMBLESTONE = tumblestoneBlock("large_budding_sky_tumblestone", GrowableStoneBlock.STAGE_2, 5, 3, SKY_TUMBLESTONE_CLUSTER)
|
||||
val LARGE_BUDDING_SKY_TUMBLESTONE = tumblestoneBlock("large_budding_sky_tumblestone", TumblestoneBlock.STAGE_2, 5, 3, SKY_TUMBLESTONE_CLUSTER, MapColor.COLOR_LIGHT_BLUE)
|
||||
@JvmField
|
||||
val MEDIUM_BUDDING_SKY_TUMBLESTONE = tumblestoneBlock("medium_budding_sky_tumblestone", GrowableStoneBlock.STAGE_1, 4, 3, LARGE_BUDDING_SKY_TUMBLESTONE)
|
||||
val MEDIUM_BUDDING_SKY_TUMBLESTONE = tumblestoneBlock("medium_budding_sky_tumblestone", TumblestoneBlock.STAGE_1, 4, 3, LARGE_BUDDING_SKY_TUMBLESTONE, MapColor.COLOR_LIGHT_BLUE)
|
||||
@JvmField
|
||||
val SMALL_BUDDING_SKY_TUMBLESTONE = tumblestoneBlock("small_budding_sky_tumblestone", GrowableStoneBlock.STAGE_0, 3, 4, MEDIUM_BUDDING_SKY_TUMBLESTONE)
|
||||
val SMALL_BUDDING_SKY_TUMBLESTONE = tumblestoneBlock("small_budding_sky_tumblestone", TumblestoneBlock.STAGE_0, 3, 4, MEDIUM_BUDDING_SKY_TUMBLESTONE, MapColor.COLOR_LIGHT_BLUE)
|
||||
|
||||
@JvmField
|
||||
val BLACK_TUMBLESTONE_CLUSTER = tumblestoneBlock("black_tumblestone_cluster", GrowableStoneBlock.STAGE_3, 7, 3, null)
|
||||
val BLACK_TUMBLESTONE_CLUSTER = tumblestoneBlock("black_tumblestone_cluster", TumblestoneBlock.STAGE_3, 7, 3, null, MapColor.TERRACOTTA_BLACK)
|
||||
@JvmField
|
||||
val LARGE_BUDDING_BLACK_TUMBLESTONE = tumblestoneBlock("large_budding_black_tumblestone", GrowableStoneBlock.STAGE_2, 5, 3, BLACK_TUMBLESTONE_CLUSTER)
|
||||
val LARGE_BUDDING_BLACK_TUMBLESTONE = tumblestoneBlock("large_budding_black_tumblestone", TumblestoneBlock.STAGE_2, 5, 3, BLACK_TUMBLESTONE_CLUSTER, MapColor.TERRACOTTA_BLACK)
|
||||
@JvmField
|
||||
val MEDIUM_BUDDING_BLACK_TUMBLESTONE = tumblestoneBlock("medium_budding_black_tumblestone", GrowableStoneBlock.STAGE_1, 4, 3, LARGE_BUDDING_BLACK_TUMBLESTONE)
|
||||
val MEDIUM_BUDDING_BLACK_TUMBLESTONE = tumblestoneBlock("medium_budding_black_tumblestone", TumblestoneBlock.STAGE_1, 4, 3, LARGE_BUDDING_BLACK_TUMBLESTONE, MapColor.TERRACOTTA_BLACK)
|
||||
@JvmField
|
||||
val SMALL_BUDDING_BLACK_TUMBLESTONE = tumblestoneBlock("small_budding_black_tumblestone", GrowableStoneBlock.STAGE_0, 3, 4, MEDIUM_BUDDING_BLACK_TUMBLESTONE)
|
||||
val SMALL_BUDDING_BLACK_TUMBLESTONE = tumblestoneBlock("small_budding_black_tumblestone", TumblestoneBlock.STAGE_0, 3, 4, MEDIUM_BUDDING_BLACK_TUMBLESTONE, MapColor.TERRACOTTA_BLACK)
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE_BLOCK = this.create("tumblestone_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_ORANGE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@@ -281,6 +288,87 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val BLACK_TUMBLESTONE_BLOCK = this.create("black_tumblestone_block", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BLACK).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
|
||||
@JvmField
|
||||
val TYPE_GEM_CORE = this.create("deepslate_crystal_core", TypeGemCoreBlock(BlockBehaviour.Properties.of().strength(4.0F, 10.0F).requiresCorrectToolForDrops().mapColor(MapColor.DEEPSLATE)))
|
||||
|
||||
private val typeGemBlocks = mutableMapOf<ResourceLocation, Block>()
|
||||
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_NORMAL = typeGemBlock("normal_gem_block", MapColor.QUARTZ)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_FIRE = typeGemBlock("fire_gem_block", MapColor.FIRE)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_WATER = typeGemBlock("water_gem_block", MapColor.WATER)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_GRASS = typeGemBlock("grass_gem_block", MapColor.COLOR_LIGHT_GREEN)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_ELECTRIC = typeGemBlock("electric_gem_block", MapColor.GOLD)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_ICE = typeGemBlock("ice_gem_block", MapColor.ICE)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_FIGHTING = typeGemBlock("fighting_gem_block", MapColor.COLOR_RED)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_POISON = typeGemBlock("poison_gem_block", MapColor.COLOR_PURPLE)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_GROUND = typeGemBlock("ground_gem_block", MapColor.PODZOL)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_FLYING = typeGemBlock("flying_gem_block", MapColor.COLOR_LIGHT_BLUE)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_PSYCHIC = typeGemBlock("psychic_gem_block", MapColor.COLOR_MAGENTA)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_BUG = typeGemBlock("bug_gem_block", MapColor.TERRACOTTA_LIGHT_GREEN)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_ROCK = typeGemBlock("rock_gem_block", MapColor.TERRACOTTA_LIGHT_GRAY)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_GHOST = typeGemBlock("ghost_gem_block", MapColor.TERRACOTTA_MAGENTA)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_DRAGON = typeGemBlock("dragon_gem_block", MapColor.COLOR_BLUE)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_DARK = typeGemBlock("dark_gem_block", MapColor.TERRACOTTA_BLACK)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_STEEL = typeGemBlock("steel_gem_block", MapColor.METAL)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_FAIRY = typeGemBlock("fairy_gem_block", MapColor.COLOR_PINK)
|
||||
|
||||
private val typeGemClusters = mutableMapOf<ResourceLocation, TypeGemClusterBlock>()
|
||||
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_NORMAL = typeGemCluster("normal_gem_cluster", TYPE_GEM_BLOCK_NORMAL, cobblemonResource("normal_gem"), MapColor.QUARTZ)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_FIRE = typeGemCluster("fire_gem_cluster", TYPE_GEM_BLOCK_FIRE, cobblemonResource("fire_gem"), MapColor.FIRE)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_WATER = typeGemCluster("water_gem_cluster", TYPE_GEM_BLOCK_WATER, cobblemonResource("water_gem"), MapColor.WATER)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_GRASS = typeGemCluster("grass_gem_cluster", TYPE_GEM_BLOCK_GRASS, cobblemonResource("grass_gem"), MapColor.COLOR_LIGHT_GREEN)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_ELECTRIC = typeGemCluster("electric_gem_cluster", TYPE_GEM_BLOCK_ELECTRIC, cobblemonResource("electric_gem"), MapColor.GOLD)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_ICE = typeGemCluster("ice_gem_cluster", TYPE_GEM_BLOCK_ICE, cobblemonResource("ice_gem"), MapColor.ICE)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_FIGHTING = typeGemCluster("fighting_gem_cluster", TYPE_GEM_BLOCK_FIGHTING, cobblemonResource("fighting_gem"), MapColor.COLOR_RED)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_POISON = typeGemCluster("poison_gem_cluster", TYPE_GEM_BLOCK_POISON, cobblemonResource("poison_gem"), MapColor.COLOR_PURPLE)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_GROUND = typeGemCluster("ground_gem_cluster", TYPE_GEM_BLOCK_GROUND, cobblemonResource("ground_gem"), MapColor.PODZOL)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_FLYING = typeGemCluster("flying_gem_cluster", TYPE_GEM_BLOCK_FLYING, cobblemonResource("flying_gem"), MapColor.COLOR_LIGHT_BLUE)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_PSYCHIC = typeGemCluster("psychic_gem_cluster", TYPE_GEM_BLOCK_PSYCHIC, cobblemonResource("psychic_gem"), MapColor.COLOR_MAGENTA)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_BUG = typeGemCluster("bug_gem_cluster", TYPE_GEM_BLOCK_BUG, cobblemonResource("bug_gem"), MapColor.TERRACOTTA_LIGHT_GREEN)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_ROCK = typeGemCluster("rock_gem_cluster", TYPE_GEM_BLOCK_ROCK, cobblemonResource("rock_gem"), MapColor.TERRACOTTA_LIGHT_GRAY)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_GHOST = typeGemCluster("ghost_gem_cluster", TYPE_GEM_BLOCK_GHOST, cobblemonResource("ghost_gem"), MapColor.TERRACOTTA_MAGENTA)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_DRAGON = typeGemCluster("dragon_gem_cluster", TYPE_GEM_BLOCK_DRAGON, cobblemonResource("dragon_gem"), MapColor.COLOR_BLUE)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_DARK = typeGemCluster("dark_gem_cluster", TYPE_GEM_BLOCK_DARK, cobblemonResource("dark_gem"), MapColor.TERRACOTTA_BLACK)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_STEEL = typeGemCluster("steel_gem_cluster", TYPE_GEM_BLOCK_STEEL, cobblemonResource("steel_gem"), MapColor.METAL)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_FAIRY = typeGemCluster("fairy_gem_cluster", TYPE_GEM_BLOCK_FAIRY, cobblemonResource("fairy_gem"), MapColor.COLOR_PINK)
|
||||
|
||||
@JvmField
|
||||
val POLISHED_TUMBLESTONE = this.create("polished_tumblestone", Block(BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_ORANGE).strength(1.0F).sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS).requiresCorrectToolForDrops().instrument(NoteBlockInstrument.BASEDRUM)))
|
||||
@JvmField
|
||||
@@ -449,6 +537,18 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val HABITAT_BLOCK = this.create(
|
||||
name = "habitat_block",
|
||||
entry = HabitatBlock(
|
||||
properties = BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.STONE)
|
||||
.strength(1.5F, Blocks.OBSIDIAN.explosionResistance)
|
||||
.pushReaction(PushReaction.BLOCK)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@JvmField
|
||||
val CAMPFIRE = create("campfire", CampfireBlock(BlockBehaviour.Properties.of().sound(SoundType.WOOD).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.PODZOL).strength(2.0F).lightLevel{14}, false))
|
||||
|
||||
@@ -458,7 +558,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@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
|
||||
val RELIC_COIN_SACK = create("relic_coin_sack", CoinPouchBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.RELIC_COIN_SACK_SOUNDS).pushReaction(PushReaction.DESTROY).strength(0.4f), false))
|
||||
val RELIC_COIN_SACK = create("relic_coin_sack", CoinPouchBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.RELIC_COIN_SACK_SOUNDS).pushReaction(PushReaction.DESTROY).strength(0.4F).mapColor(MapColor.GOLD), false))
|
||||
|
||||
@JvmField
|
||||
val GILDED_CHEST = create("gilded_chest", GildedChestBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS), GildedChestBlock.Type.RED))
|
||||
@@ -477,28 +577,139 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val GIMMIGHOUL_CHEST = create("gimmighoul_chest", GildedChestBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS), GildedChestBlock.Type.FAKE))
|
||||
|
||||
@JvmField
|
||||
val WHITE_PLAQUE = create("white_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val LIGHT_GRAY_PLAQUE = create("light_gray_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val GRAY_PLAQUE = create("gray_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val BLACK_PLAQUE = create("black_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val BROWN_PLAQUE = create("brown_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val RED_PLAQUE = create("red_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val ORANGE_PLAQUE = create("orange_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val YELLOW_PLAQUE = create("yellow_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val LIME_PLAQUE = create("lime_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val GREEN_PLAQUE = create("green_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val CYAN_PLAQUE = create("cyan_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val LIGHT_BLUE_PLAQUE = create("light_blue_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val BLUE_PLAQUE = create("blue_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val PURPLE_PLAQUE = create("purple_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val MAGENTA_PLAQUE = create("magenta_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
@JvmField
|
||||
val PINK_PLAQUE = create("pink_plaque", PlaqueBlock(BlockBehaviour.Properties.of().sound(SoundType.METAL).mapColor(MapColor.METAL).noOcclusion().pushReaction(PushReaction.DESTROY).strength(5.0F)))
|
||||
|
||||
@JvmField
|
||||
val CLEANSE_TAG = create("cleanse_tag", WallAttachedStackableItemBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.ITEM_BLOCK_PAPER_SMALL_SOUNDS).mapColor(MapColor.NONE).pushReaction(PushReaction.DESTROY).noOcclusion().noCollission(), WallAttachedStackableItemBlock.WallStackableItemBlockType.TAG))
|
||||
@JvmField
|
||||
val SPELL_TAG = create("spell_tag", WallAttachedStackableItemBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.ITEM_BLOCK_PAPER_SMALL_SOUNDS).mapColor(MapColor.NONE).pushReaction(PushReaction.DESTROY).noOcclusion().noCollission(), WallAttachedStackableItemBlock.WallStackableItemBlockType.TAG))
|
||||
|
||||
@JvmField
|
||||
val BLUNDER_POLICY = create("blunder_policy", WallAttachedDirectionalShapeBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.ITEM_BLOCK_PAPER_LARGE_SOUNDS).mapColor(MapColor.NONE).noOcclusion().noCollission(), 14, 12, 1))
|
||||
@JvmField
|
||||
val WEAKNESS_POLICY = create("weakness_policy", WallAttachedDirectionalShapeBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.ITEM_BLOCK_PAPER_LARGE_SOUNDS).mapColor(MapColor.NONE).noOcclusion().noCollission(), 14, 12, 1))
|
||||
|
||||
@JvmField
|
||||
val FULL_HEAL = create("full_heal", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.STATUS_RESTORE))
|
||||
@JvmField
|
||||
val ANTIDOTE = create("antidote", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.STATUS_RESTORE))
|
||||
@JvmField
|
||||
val AWAKENING = create("awakening", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.STATUS_RESTORE))
|
||||
@JvmField
|
||||
val BURN_HEAL = create("burn_heal", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.STATUS_RESTORE))
|
||||
@JvmField
|
||||
val ICE_HEAL = create("ice_heal", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.STATUS_RESTORE))
|
||||
@JvmField
|
||||
val PARALYZE_HEAL = create("paralyze_heal", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.STATUS_RESTORE))
|
||||
|
||||
@JvmField
|
||||
val ETHER = create("ether", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.ETHER))
|
||||
@JvmField
|
||||
val MAX_ETHER = create("max_ether", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.ETHER))
|
||||
@JvmField
|
||||
val ELIXIR = create("elixir", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.ETHER))
|
||||
@JvmField
|
||||
val MAX_ELIXIR = create("max_elixir", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.ETHER))
|
||||
|
||||
@JvmField
|
||||
val POTION = create("potion", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.POTION))
|
||||
@JvmField
|
||||
val SUPER_POTION = create("super_potion", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.POTION))
|
||||
@JvmField
|
||||
val HYPER_POTION = create("hyper_potion", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.POTION))
|
||||
@JvmField
|
||||
val MAX_POTION = create("max_potion", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.MAX_POTION))
|
||||
@JvmField
|
||||
val FULL_RESTORE = create("full_restore", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.MAX_POTION))
|
||||
|
||||
@JvmField
|
||||
val DIRE_HIT = create("dire_hit", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
|
||||
@JvmField
|
||||
val GUARD_SPEC = create("guard_spec", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
|
||||
@JvmField
|
||||
val X_ACCURACY = create("x_${Stats.ACCURACY.identifier.path}", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
|
||||
@JvmField
|
||||
val X_ATTACK = create("x_${Stats.ATTACK.identifier.path}", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
|
||||
@JvmField
|
||||
val X_DEFENSE = create("x_${Stats.DEFENCE.identifier.path}", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
|
||||
@JvmField
|
||||
val X_SP_ATK = create("x_${Stats.SPECIAL_ATTACK.identifier.path}", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
|
||||
@JvmField
|
||||
val X_SP_DEF = create("x_${Stats.SPECIAL_DEFENCE.identifier.path}", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
|
||||
@JvmField
|
||||
val X_SPEED = create("x_${Stats.SPEED.identifier.path}", StackableItemBlock(BlockBehaviour.Properties.of().sound(SoundType.CANDLE).mapColor(MapColor.NONE).noOcclusion(), StackableItemBlock.StackableItemBlockType.BATTLE_ITEM))
|
||||
|
||||
@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) 13 else 0 }))
|
||||
@JvmField
|
||||
val DAMAGED_MONITOR = create("damaged_monitor", DamagedMonitorBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).lightLevel { when (it.getValue(DamagedMonitorBlock.SCREEN)) { DamagedMonitorBlock.BrokenMonitorScreen.GLITCHING -> 10; 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) 12 else 5 }))
|
||||
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)) 13 else 0 }))
|
||||
|
||||
val TM_MACHINE = create(
|
||||
"tm_machine",
|
||||
TMMachineBlock(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_GREEN)
|
||||
.sound(SoundType.METAL)
|
||||
.pushReaction(PushReaction.BLOCK)
|
||||
.strength(2F)
|
||||
.noOcclusion()
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@JvmField
|
||||
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 DISC_SHELF = create("disc_shelf", DiscShelfBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).sound(SoundType.METAL).strength(2.5F)))
|
||||
|
||||
@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).requiresCorrectToolForDrops()))
|
||||
|
||||
// TODO after 1.7
|
||||
// @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)))
|
||||
// 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)) 13 else 0 }))
|
||||
@@ -566,8 +777,9 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
|
||||
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 {
|
||||
private fun tumblestoneBlock(name: String, stage: Int, height: Int, xzOffset: Int, nextStage: Block?, mapColor: MapColor) : Block {
|
||||
return this.create(name, TumblestoneBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(mapColor)
|
||||
.pushReaction(PushReaction.DESTROY)
|
||||
.noOcclusion()
|
||||
.strength(1.5F)
|
||||
@@ -796,4 +1008,28 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
val block = BlocksInvoker.createLeavesBlock(SoundType.GRASS)
|
||||
return this.create(name, block)
|
||||
}
|
||||
}
|
||||
|
||||
private fun typeGemBlock(name: String, mapColor: MapColor): Block {
|
||||
val typeGemBlock = this.create(name, Block(BlockBehaviour.Properties.of().mapColor(mapColor).strength(3.0F, 6.0F).sound(CobblemonSounds.TYPE_GEM_BLOCK_SOUNDS)))
|
||||
|
||||
val identifier = cobblemonResource(name)
|
||||
typeGemBlocks[identifier] = typeGemBlock
|
||||
|
||||
return typeGemBlock
|
||||
}
|
||||
|
||||
fun typeGemBlocks() = typeGemBlocks.toMap()
|
||||
|
||||
private fun typeGemCluster(name: String, gemBlock: Block, dropItemId: ResourceLocation, mapColor: MapColor): Block {
|
||||
val gemClusterBlock = this.create(name, TypeGemClusterBlock(BlockBehaviour.Properties.of().mapColor(mapColor).strength(2.0F, 3.0F).sound(CobblemonSounds.TYPE_GEM_CLUSTER_SOUNDS).pushReaction(PushReaction.DESTROY), gemBlock, dropItemId))
|
||||
|
||||
TypeGemClusterBlock.gemToClusterMap[gemBlock] = gemClusterBlock
|
||||
|
||||
val identifier = cobblemonResource(name)
|
||||
typeGemClusters[identifier] = gemClusterBlock
|
||||
|
||||
return gemClusterBlock
|
||||
}
|
||||
|
||||
fun typeGemClusters() = typeGemClusters.toMap()
|
||||
}
|
||||
|
||||
@@ -71,10 +71,11 @@ object CobblemonCommands {
|
||||
MarkGiveAllCommand.register(dispatcher)
|
||||
PcSearchCommand.register(dispatcher)
|
||||
PcTakeCommand.register(dispatcher)
|
||||
GiveTmCommand.register(dispatcher)
|
||||
TmCommand.register(dispatcher)
|
||||
|
||||
// Possibly lock down registration if and only if under dev environment or running in an environment
|
||||
// with a certain system environment variable set
|
||||
CobblemonInfoCommand.register(dispatcher)
|
||||
CalculateSeatPositionCommand.register(dispatcher)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.server.packs.resources.PreparableReloadListener
|
||||
import net.minecraft.tags.TagKey
|
||||
import net.minecraft.world.inventory.MenuType
|
||||
import net.minecraft.world.level.GameRules
|
||||
import net.minecraft.world.level.ItemLike
|
||||
import net.minecraft.world.level.biome.Biome
|
||||
@@ -117,6 +118,11 @@ interface CobblemonImplementation {
|
||||
|
||||
fun registerEntitySubPredicates()
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
fun registerMobEffects()
|
||||
|
||||
|
||||
/**
|
||||
* Add a feature to the current platform implementation.
|
||||
|
||||
@@ -69,6 +69,12 @@ object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>
|
||||
.networkSynchronized(FoodColourComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
@JvmField
|
||||
val TM_MOVE: DataComponentType<TMMoveComponent> = create("tm_move", DataComponentType.builder<TMMoveComponent>()
|
||||
.persistent(TMMoveComponent.CODEC)
|
||||
.networkSynchronized(TMMoveComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
@JvmField
|
||||
val INGREDIENT: DataComponentType<IngredientComponent> = create("ingredient", DataComponentType.builder<IngredientComponent>()
|
||||
.persistent(IngredientComponent.CODEC)
|
||||
@@ -101,6 +107,7 @@ object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:flavour"), FLAVOUR)
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:ride_boosts"), RIDE_BOOST)
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:food_colour"), FOOD_COLOUR)
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:tm_move"), TM_MOVE)
|
||||
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)
|
||||
|
||||
@@ -21,8 +21,8 @@ import com.cobblemon.mod.common.api.text.gray
|
||||
import com.cobblemon.mod.common.block.BerryBlock
|
||||
import com.cobblemon.mod.common.block.MintBlock
|
||||
import com.cobblemon.mod.common.block.MintBlock.MintType
|
||||
import com.cobblemon.mod.common.client.pokedex.PokedexType
|
||||
import com.cobblemon.mod.common.block.campfirepot.CampfirePotColor
|
||||
import com.cobblemon.mod.common.client.pokedex.PokedexType
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
|
||||
import com.cobblemon.mod.common.item.*
|
||||
import com.cobblemon.mod.common.item.armor.CobblemonArmorTrims
|
||||
@@ -35,7 +35,6 @@ import com.cobblemon.mod.common.item.berry.HealingBerryItem
|
||||
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.interactive.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
|
||||
@@ -406,7 +405,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val BIG_MALASADA = regionalFoodItem("big_malasada", 64, 7, 0.3f, false)
|
||||
@JvmField
|
||||
val SMOKED_TAIL_CURRY = regionalFoodItem("smoked_tail_curry", 64, 10, 0.6f, false, ItemStack(Items.BOWL, 1))
|
||||
val SMOKED_TAIL_CURRY = regionalFoodItem("smoked_tail_curry", 64, 10, 0.6f, false)
|
||||
@JvmField
|
||||
val JUBILIFE_MUFFIN = regionalFoodItem("jubilife_muffin", 64, 7, 0.3f, false)
|
||||
@JvmField
|
||||
@@ -453,10 +452,16 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val MONITOR = blockItem("monitor", CobblemonBlocks.MONITOR)
|
||||
@JvmField
|
||||
val DAMAGED_MONITOR = blockItem("damaged_monitor", CobblemonBlocks.DAMAGED_MONITOR)
|
||||
@JvmField
|
||||
val HEALING_MACHINE = blockItem("healing_machine", CobblemonBlocks.HEALING_MACHINE, Rarity.UNCOMMON)
|
||||
@JvmField
|
||||
val PC = blockItem("pc", CobblemonBlocks.PC)
|
||||
@JvmField
|
||||
val TM_MACHINE = blockItem("tm_machine", CobblemonBlocks.TM_MACHINE)
|
||||
@JvmField
|
||||
val DISC_SHELF = blockItem("disc_shelf", CobblemonBlocks.DISC_SHELF)
|
||||
@JvmField
|
||||
val PASTURE = blockItem("pasture", CobblemonBlocks.PASTURE)
|
||||
@JvmField
|
||||
val DISPLAY_CASE = blockItem("display_case", CobblemonBlocks.DISPLAY_CASE)
|
||||
@@ -507,6 +512,23 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField val SCROLL_OF_DARKNESS = noSettingsItem("scroll_of_darkness")
|
||||
@JvmField val SCROLL_OF_WATERS = noSettingsItem("scroll_of_waters")
|
||||
|
||||
@JvmField val WHITE_PLAQUE = blockItem("white_plaque", CobblemonBlocks.WHITE_PLAQUE)
|
||||
@JvmField val LIGHT_GRAY_PLAQUE = blockItem("light_gray_plaque", CobblemonBlocks.LIGHT_GRAY_PLAQUE)
|
||||
@JvmField val GRAY_PLAQUE = blockItem("gray_plaque", CobblemonBlocks.GRAY_PLAQUE)
|
||||
@JvmField val BLACK_PLAQUE = blockItem("black_plaque", CobblemonBlocks.BLACK_PLAQUE)
|
||||
@JvmField val BROWN_PLAQUE = blockItem("brown_plaque", CobblemonBlocks.BROWN_PLAQUE)
|
||||
@JvmField val RED_PLAQUE = blockItem("red_plaque", CobblemonBlocks.RED_PLAQUE)
|
||||
@JvmField val ORANGE_PLAQUE = blockItem("orange_plaque", CobblemonBlocks.ORANGE_PLAQUE)
|
||||
@JvmField val YELLOW_PLAQUE = blockItem("yellow_plaque", CobblemonBlocks.YELLOW_PLAQUE)
|
||||
@JvmField val LIME_PLAQUE = blockItem("lime_plaque", CobblemonBlocks.LIME_PLAQUE)
|
||||
@JvmField val GREEN_PLAQUE = blockItem("green_plaque", CobblemonBlocks.GREEN_PLAQUE)
|
||||
@JvmField val CYAN_PLAQUE = blockItem("cyan_plaque", CobblemonBlocks.CYAN_PLAQUE)
|
||||
@JvmField val LIGHT_BLUE_PLAQUE = blockItem("light_blue_plaque", CobblemonBlocks.LIGHT_BLUE_PLAQUE)
|
||||
@JvmField val BLUE_PLAQUE = blockItem("blue_plaque", CobblemonBlocks.BLUE_PLAQUE)
|
||||
@JvmField val PURPLE_PLAQUE = blockItem("purple_plaque", CobblemonBlocks.PURPLE_PLAQUE)
|
||||
@JvmField val MAGENTA_PLAQUE = blockItem("magenta_plaque", CobblemonBlocks.MAGENTA_PLAQUE)
|
||||
@JvmField val PINK_PLAQUE = blockItem("pink_plaque", CobblemonBlocks.PINK_PLAQUE)
|
||||
|
||||
private val berries = mutableMapOf<ResourceLocation, BerryItem>()
|
||||
// Plants
|
||||
@JvmField val CHERI_BERRY = berryItem("cheri", StatusCuringBerryItem(CobblemonBlocks.CHERI_BERRY, Statuses.PARALYSIS))
|
||||
@@ -582,6 +604,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
|
||||
@JvmField val BERRY_JUICE = this.create("berry_juice", BerryJuiceItem())
|
||||
|
||||
@JvmField
|
||||
val HABITAT_BLOCK = blockItem("habitat_block", CobblemonBlocks.HABITAT_BLOCK)
|
||||
|
||||
@JvmField
|
||||
val GALARICA_NUTS = compostableItemNameBlockItem("galarica_nuts", CobblemonBlocks.GALARICA_NUT_BUSH)
|
||||
|
||||
@@ -699,15 +724,15 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
val MOOMOO_MILK = create("moomoo_milk", MoomooMilk(Item.Properties().craftRemainder(Items.GLASS_BOTTLE).stacksTo((16))))
|
||||
|
||||
@JvmField
|
||||
val POTION = create("potion", PotionItem(PotionType.POTION))
|
||||
val POTION = create("potion", PotionItem(PotionType.POTION, CobblemonBlocks.POTION))
|
||||
@JvmField
|
||||
val SUPER_POTION = create("super_potion", PotionItem(PotionType.SUPER_POTION))
|
||||
val SUPER_POTION = create("super_potion", PotionItem(PotionType.SUPER_POTION, CobblemonBlocks.SUPER_POTION))
|
||||
@JvmField
|
||||
val HYPER_POTION = create("hyper_potion", PotionItem(PotionType.HYPER_POTION))
|
||||
val HYPER_POTION = create("hyper_potion", PotionItem(PotionType.HYPER_POTION, CobblemonBlocks.HYPER_POTION))
|
||||
@JvmField
|
||||
val MAX_POTION = create("max_potion", PotionItem(PotionType.MAX_POTION))
|
||||
val MAX_POTION = create("max_potion", PotionItem(PotionType.MAX_POTION, CobblemonBlocks.MAX_POTION))
|
||||
@JvmField
|
||||
val FULL_RESTORE = create("full_restore", PotionItem(PotionType.FULL_RESTORE))
|
||||
val FULL_RESTORE = create("full_restore", PotionItem(PotionType.FULL_RESTORE, CobblemonBlocks.FULL_RESTORE))
|
||||
|
||||
@JvmField
|
||||
val HEAL_POWDER = create("heal_powder", HealPowderItem())
|
||||
@@ -792,28 +817,27 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val SERIOUS_MINT = mintItem("serious_mint", MintItem(Natures.SERIOUS))
|
||||
|
||||
@JvmField val X_ACCURACY = create("x_${Stats.ACCURACY.identifier.path}", XStatItem(Stats.ACCURACY))
|
||||
@JvmField val X_ATTACK = create("x_${Stats.ATTACK.identifier.path}", XStatItem(Stats.ATTACK))
|
||||
@JvmField val X_DEFENSE = create("x_${Stats.DEFENCE.identifier.path}", XStatItem(Stats.DEFENCE))
|
||||
@JvmField val X_SP_ATK = create("x_${Stats.SPECIAL_ATTACK.identifier.path}", XStatItem(Stats.SPECIAL_ATTACK))
|
||||
@JvmField val X_SP_DEF = create("x_${Stats.SPECIAL_DEFENCE.identifier.path}", XStatItem(Stats.SPECIAL_DEFENCE))
|
||||
@JvmField val X_SPEED = create("x_${Stats.SPEED.identifier.path}", XStatItem(Stats.SPEED))
|
||||
@JvmField val X_ACCURACY = create("x_${Stats.ACCURACY.identifier.path}", XStatItem(Stats.ACCURACY, block = CobblemonBlocks.X_ACCURACY))
|
||||
@JvmField val X_ATTACK = create("x_${Stats.ATTACK.identifier.path}", XStatItem(Stats.ATTACK, block = CobblemonBlocks.X_ATTACK))
|
||||
@JvmField val X_DEFENSE = create("x_${Stats.DEFENCE.identifier.path}", XStatItem(Stats.DEFENCE, block = CobblemonBlocks.X_DEFENSE))
|
||||
@JvmField val X_SP_ATK = create("x_${Stats.SPECIAL_ATTACK.identifier.path}", XStatItem(Stats.SPECIAL_ATTACK, block = CobblemonBlocks.X_SP_ATK))
|
||||
@JvmField val X_SP_DEF = create("x_${Stats.SPECIAL_DEFENCE.identifier.path}", XStatItem(Stats.SPECIAL_DEFENCE, block = CobblemonBlocks.X_SP_DEF))
|
||||
@JvmField val X_SPEED = create("x_${Stats.SPEED.identifier.path}", XStatItem(Stats.SPEED, block = CobblemonBlocks.X_SPEED))
|
||||
|
||||
@JvmField val DIRE_HIT = create("dire_hit", DireHitItem())
|
||||
@JvmField val GUARD_SPEC = create("guard_spec", GuardSpecItem())
|
||||
@JvmField val DIRE_HIT = create("dire_hit", DireHitItem(CobblemonBlocks.DIRE_HIT))
|
||||
@JvmField val GUARD_SPEC = create("guard_spec", GuardSpecItem(CobblemonBlocks.GUARD_SPEC))
|
||||
|
||||
@JvmField val BURN_HEAL = create("burn_heal", StatusCureItem("item.cobblemon.burn_heal", Statuses.BURN))
|
||||
@JvmField val PARALYZE_HEAL = create("paralyze_heal", StatusCureItem("item.cobblemon.paralyze_heal", Statuses.PARALYSIS))
|
||||
@JvmField val ICE_HEAL = create("ice_heal", StatusCureItem("item.cobblemon.ice_heal", Statuses.FROZEN))
|
||||
@JvmField val ANTIDOTE = create("antidote", StatusCureItem("item.cobblemon.antidote", Statuses.POISON, Statuses.POISON_BADLY))
|
||||
@JvmField val AWAKENING = create("awakening", StatusCureItem("item.cobblemon.awakening", Statuses.SLEEP))
|
||||
@JvmField val FULL_HEAL = create("full_heal", StatusCureItem("item.cobblemon.full_heal", *Statuses.getPersistentStatuses().toTypedArray(), block = CobblemonBlocks.FULL_HEAL))
|
||||
@JvmField val ANTIDOTE = create("antidote", StatusCureItem("item.cobblemon.antidote", Statuses.POISON, Statuses.POISON_BADLY, block = CobblemonBlocks.ANTIDOTE))
|
||||
@JvmField val AWAKENING = create("awakening", StatusCureItem("item.cobblemon.awakening", Statuses.SLEEP, block = CobblemonBlocks.AWAKENING))
|
||||
@JvmField val BURN_HEAL = create("burn_heal", StatusCureItem("item.cobblemon.burn_heal", Statuses.BURN, block = CobblemonBlocks.BURN_HEAL))
|
||||
@JvmField val ICE_HEAL = create("ice_heal", StatusCureItem("item.cobblemon.ice_heal", Statuses.FROZEN, block = CobblemonBlocks.ICE_HEAL))
|
||||
@JvmField val PARALYZE_HEAL = create("paralyze_heal", StatusCureItem("item.cobblemon.paralyze_heal", Statuses.PARALYSIS, block = CobblemonBlocks.PARALYZE_HEAL))
|
||||
|
||||
@JvmField val FULL_HEAL = create("full_heal", StatusCureItem("item.cobblemon.full_heal"))
|
||||
|
||||
@JvmField val ETHER = create("ether", EtherItem(max = false))
|
||||
@JvmField val MAX_ETHER = create("max_ether", EtherItem(max = true))
|
||||
@JvmField val ELIXIR = create("elixir", ElixirItem(max = false))
|
||||
@JvmField val MAX_ELIXIR = create("max_elixir", ElixirItem(max = true))
|
||||
@JvmField val ETHER = create("ether", EtherItem(max = false, CobblemonBlocks.ETHER))
|
||||
@JvmField val MAX_ETHER = create("max_ether", EtherItem(max = true, CobblemonBlocks.MAX_ETHER))
|
||||
@JvmField val ELIXIR = create("elixir", ElixirItem(max = false, CobblemonBlocks.ELIXIR))
|
||||
@JvmField val MAX_ELIXIR = create("max_elixir", ElixirItem(max = true, CobblemonBlocks.MAX_ELIXIR))
|
||||
|
||||
@JvmField
|
||||
val ABILITY_CAPSULE = this.create("ability_capsule", AbilityChangeItem(AbilityChanger.COMMON_ABILITY))
|
||||
@@ -922,7 +946,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val BLACK_SLUDGE = heldItem("black_sludge")
|
||||
@JvmField
|
||||
val BLUNDER_POLICY = heldItem("blunder_policy")
|
||||
val BLUNDER_POLICY = itemNameBlockItem("blunder_policy", CobblemonBlocks.BLUNDER_POLICY)
|
||||
@JvmField
|
||||
val CELL_BATTERY = heldItem("cell_battery")
|
||||
@JvmField
|
||||
@@ -930,7 +954,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val CHOICE_SCARF = heldItem("choice_scarf")
|
||||
@JvmField
|
||||
val CLEANSE_TAG = heldItem("cleanse_tag")
|
||||
val CLEANSE_TAG = itemNameBlockItem("cleanse_tag", CobblemonBlocks.CLEANSE_TAG)
|
||||
@JvmField
|
||||
val CLEAR_AMULET = heldItem("clear_amulet")
|
||||
@JvmField
|
||||
@@ -1038,7 +1062,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val SOFT_SAND = heldItem("soft_sand")
|
||||
@JvmField
|
||||
val SPELL_TAG = heldItem("spell_tag")
|
||||
val SPELL_TAG = itemNameBlockItem("spell_tag", CobblemonBlocks.SPELL_TAG)
|
||||
@JvmField
|
||||
val SMOKE_BALL = heldItem("smoke_ball")
|
||||
@JvmField
|
||||
@@ -1056,7 +1080,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val UTILITY_UMBRELLA = heldItem("utility_umbrella")
|
||||
@JvmField
|
||||
val WEAKNESS_POLICY = heldItem("weakness_policy")
|
||||
val WEAKNESS_POLICY = itemNameBlockItem("weakness_policy", CobblemonBlocks.WEAKNESS_POLICY)
|
||||
@JvmField
|
||||
val WIDE_LENS = heldItem("wide_lens")
|
||||
@JvmField
|
||||
@@ -1192,6 +1216,83 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val BLACK_TUMBLESTONE_BLOCK = blockItem("black_tumblestone_block", CobblemonBlocks.BLACK_TUMBLESTONE_BLOCK)
|
||||
|
||||
@JvmField
|
||||
val TYPE_GEM_CORE = blockItem("deepslate_crystal_core", CobblemonBlocks.TYPE_GEM_CORE)
|
||||
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_NORMAL = blockItem("normal_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_NORMAL)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_FIRE = blockItem("fire_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_FIRE)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_WATER = blockItem("water_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_WATER)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_ELECTRIC = blockItem("electric_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_ELECTRIC)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_GRASS = blockItem("grass_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_GRASS)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_ICE = blockItem("ice_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_ICE)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_FIGHTING = blockItem("fighting_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_FIGHTING)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_POISON = blockItem("poison_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_POISON)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_GROUND = blockItem("ground_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_GROUND)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_FLYING = blockItem("flying_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_FLYING)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_PSYCHIC = blockItem("psychic_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_PSYCHIC)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_BUG = blockItem("bug_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_BUG)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_ROCK = blockItem("rock_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_ROCK)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_GHOST = blockItem("ghost_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_GHOST)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_DRAGON = blockItem("dragon_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_DRAGON)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_DARK = blockItem("dark_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_DARK)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_STEEL = blockItem("steel_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_STEEL)
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_FAIRY = blockItem("fairy_gem_cluster", CobblemonBlocks.TYPE_GEM_CLUSTER_FAIRY)
|
||||
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_NORMAL = blockItem("normal_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_NORMAL)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_FIRE = blockItem("fire_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_FIRE)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_WATER = blockItem("water_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_WATER)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_ELECTRIC = blockItem("electric_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_ELECTRIC)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_GRASS = blockItem("grass_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_GRASS)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_ICE = blockItem("ice_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_ICE)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_FIGHTING = blockItem("fighting_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_FIGHTING)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_POISON = blockItem("poison_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_POISON)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_GROUND = blockItem("ground_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_GROUND)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_FLYING = blockItem("flying_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_FLYING)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_PSYCHIC = blockItem("psychic_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_PSYCHIC)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_BUG = blockItem("bug_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_BUG)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_ROCK = blockItem("rock_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_ROCK)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_GHOST = blockItem("ghost_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_GHOST)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_DRAGON = blockItem("dragon_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_DRAGON)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_DARK = blockItem("dark_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_DARK)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_STEEL = blockItem("steel_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_STEEL)
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_FAIRY = blockItem("fairy_gem_block", CobblemonBlocks.TYPE_GEM_BLOCK_FAIRY)
|
||||
|
||||
@JvmField
|
||||
val POKEROD_SMITHING_TEMPLATE = create("pokerod_smithing_template", SmithingTemplateItem(
|
||||
Component.translatable("item.minecraft.fishing_rod").blue(),
|
||||
@@ -1416,44 +1517,49 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
val RELIC_COIN_POUCH = blockItem("relic_coin_pouch", CobblemonBlocks.RELIC_COIN_POUCH)
|
||||
@JvmField
|
||||
val RELIC_COIN_SACK = blockItem("relic_coin_sack", CobblemonBlocks.RELIC_COIN_SACK)
|
||||
@JvmField
|
||||
val TECHNICAL_MACHINE = this.create("technical_machine", TechnicalMachineItem(Properties()))
|
||||
@JvmField
|
||||
val BLANK_TM = this.create("blank_tm", CobblemonItem(Item.Properties()))
|
||||
|
||||
// Type Gems
|
||||
@JvmField
|
||||
val NORMAL_GEM = noSettingsItem("normal_gem")
|
||||
val NORMAL_GEM = this.create("normal_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_NORMAL))
|
||||
@JvmField
|
||||
val FIRE_GEM = noSettingsItem("fire_gem")
|
||||
val FIRE_GEM = this.create("fire_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_FIRE))
|
||||
@JvmField
|
||||
val WATER_GEM = noSettingsItem("water_gem")
|
||||
val WATER_GEM = this.create("water_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_WATER))
|
||||
@JvmField
|
||||
val GRASS_GEM = noSettingsItem("grass_gem")
|
||||
val GRASS_GEM = this.create("grass_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_GRASS))
|
||||
@JvmField
|
||||
val ELECTRIC_GEM = noSettingsItem("electric_gem")
|
||||
val ELECTRIC_GEM = this.create("electric_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_ELECTRIC))
|
||||
@JvmField
|
||||
val ICE_GEM = noSettingsItem("ice_gem")
|
||||
val ICE_GEM = this.create("ice_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_ICE))
|
||||
@JvmField
|
||||
val FIGHTING_GEM = noSettingsItem("fighting_gem")
|
||||
val FIGHTING_GEM = this.create("fighting_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_FIGHTING))
|
||||
@JvmField
|
||||
val POISON_GEM = noSettingsItem("poison_gem")
|
||||
val POISON_GEM = this.create("poison_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_POISON))
|
||||
@JvmField
|
||||
val GROUND_GEM = noSettingsItem("ground_gem")
|
||||
val GROUND_GEM = this.create("ground_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_GROUND))
|
||||
@JvmField
|
||||
val FLYING_GEM = noSettingsItem("flying_gem")
|
||||
val FLYING_GEM = this.create("flying_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_FLYING))
|
||||
@JvmField
|
||||
val PSYCHIC_GEM = noSettingsItem("psychic_gem")
|
||||
val PSYCHIC_GEM = this.create("psychic_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_PSYCHIC))
|
||||
@JvmField
|
||||
val BUG_GEM = noSettingsItem("bug_gem")
|
||||
val BUG_GEM = this.create("bug_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_BUG))
|
||||
@JvmField
|
||||
val ROCK_GEM = noSettingsItem("rock_gem")
|
||||
val ROCK_GEM = this.create("rock_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_ROCK))
|
||||
@JvmField
|
||||
val GHOST_GEM = noSettingsItem("ghost_gem")
|
||||
val GHOST_GEM = this.create("ghost_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_GHOST))
|
||||
@JvmField
|
||||
val DRAGON_GEM = noSettingsItem("dragon_gem")
|
||||
val DRAGON_GEM = this.create("dragon_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_DRAGON))
|
||||
@JvmField
|
||||
val DARK_GEM = noSettingsItem("dark_gem")
|
||||
val DARK_GEM = this.create("dark_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_DARK))
|
||||
@JvmField
|
||||
val STEEL_GEM = noSettingsItem("steel_gem")
|
||||
val STEEL_GEM = this.create("steel_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_STEEL))
|
||||
@JvmField
|
||||
val FAIRY_GEM = noSettingsItem("fairy_gem")
|
||||
val FAIRY_GEM = this.create("fairy_gem", GemItem(Item.Properties(), CobblemonBlocks.TYPE_GEM_CLUSTER_FAIRY))
|
||||
|
||||
//@JvmField
|
||||
//val BINDING_SOIL = blockItem("binding_soil", CobblemonBlocks.BINDING_SOIL)
|
||||
|
||||
@@ -1553,6 +1659,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
private fun heldItem(name: String, item: Item, remappedName: String? = null) = create(
|
||||
name = name,
|
||||
entry = item.also {
|
||||
|
||||
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common
|
||||
|
||||
|
||||
import com.cobblemon.mod.common.block.campfirepot.CookingPotMenu
|
||||
import com.cobblemon.mod.common.block.tmmachine.TMMachineMenu
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
@@ -19,7 +20,8 @@ import net.minecraft.world.inventory.MenuType
|
||||
|
||||
object CobblemonMenuType : PlatformRegistry<Registry<MenuType<*>>, ResourceKey<Registry<MenuType<*>>>, MenuType<*>>() {
|
||||
|
||||
val COOKING_POT = MenuType.register("cooking_pot", ::CookingPotMenu)
|
||||
val COOKING_POT = MenuType.register("cooking_pot_menu", ::CookingPotMenu)
|
||||
val TM_MACHINE = MenuType.register("tm_machine_menu", ::TMMachineMenu)
|
||||
|
||||
override val registry: Registry<MenuType<*>>
|
||||
get() = BuiltInRegistries.MENU
|
||||
|
||||
@@ -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
|
||||
|
||||
import com.cobblemon.mod.common.api.cooking.effects.CleanseAllEffect
|
||||
import com.cobblemon.mod.common.api.cooking.effects.CleanseNegativeEffect
|
||||
import com.cobblemon.mod.common.api.cooking.effects.MentalRestorationEffect
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
|
||||
object CobblemonMobEffects : PlatformRegistry<Registry<MobEffect>, ResourceKey<Registry<MobEffect>>, MobEffect>() {
|
||||
override val registry: Registry<MobEffect> = BuiltInRegistries.MOB_EFFECT
|
||||
override val resourceKey: ResourceKey<Registry<MobEffect>> = Registries.MOB_EFFECT
|
||||
|
||||
@JvmField
|
||||
val CLEANSE_NEGATIVE = create("cleanse_negative", CleanseNegativeEffect())
|
||||
|
||||
@JvmField
|
||||
val MENTAL_RESTORATION = create("mental_restoration", MentalRestorationEffect())
|
||||
|
||||
@JvmField
|
||||
val CLEANSE_ALL = create("cleanse_all", CleanseAllEffect())
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.moves.MoveSelector
|
||||
import com.cobblemon.mod.common.api.moves.MovesetBuilder
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.MovesetBuilderAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.StringToObjectAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
|
||||
object CobblemonMovesetBuilders : JsonDataRegistry<MovesetBuilder> {
|
||||
override val gson: Gson = GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.registerTypeAdapter(MovesetBuilder::class.java, MovesetBuilderAdapter)
|
||||
.registerTypeAdapter(MoveSelector::class.java, StringToObjectAdapter(MoveSelector.selectors))
|
||||
.create()
|
||||
|
||||
override val typeToken = TypeToken.get(MovesetBuilder::class.java)
|
||||
override val resourcePath = "moveset_builders"
|
||||
override val id: ResourceLocation = cobblemonResource("moveset_builders")
|
||||
override val type = PackType.SERVER_DATA
|
||||
override val observable = SimpleObservable<CobblemonMovesetBuilders>()
|
||||
|
||||
val movesetBuilders = mutableMapOf<ResourceLocation, MovesetBuilder>()
|
||||
|
||||
fun getOrThrow(id: ResourceLocation): MovesetBuilder {
|
||||
return movesetBuilders[id]
|
||||
?: throw IllegalArgumentException("Unknown MovesetBuilder id: $id")
|
||||
}
|
||||
|
||||
override fun sync(player: ServerPlayer) { /* These don't sync. But what if they did? Nah probably shouldn't sync. */ }
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, MovesetBuilder>) {
|
||||
movesetBuilders.clear()
|
||||
data.forEach { (id, value) -> value.id = id }
|
||||
movesetBuilders.putAll(data)
|
||||
observable.emit(this)
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.client.net.CalculateSeatPositionsHandler
|
||||
import com.cobblemon.mod.common.client.net.OpenBehaviourEditorHandler
|
||||
import com.cobblemon.mod.common.client.net.PlayerInteractOptionsHandler
|
||||
import com.cobblemon.mod.common.client.net.SetClientPlayerDataHandler
|
||||
@@ -21,21 +20,33 @@ import com.cobblemon.mod.common.client.net.callback.partymove.OpenPartyMoveCallb
|
||||
import com.cobblemon.mod.common.client.net.cooking.ToggleCookingPotLidHandler
|
||||
import com.cobblemon.mod.common.client.net.data.CobblemonMechanicsSyncHandler
|
||||
import com.cobblemon.mod.common.client.net.data.DataRegistrySyncPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.data.PokemonInteractionsSyncHandler
|
||||
import com.cobblemon.mod.common.client.net.data.RideSettingsSyncHandler
|
||||
import com.cobblemon.mod.common.client.net.debug.OpenRidingStatsDebugGUIHandler
|
||||
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.*
|
||||
import com.cobblemon.mod.common.client.net.effect.PokeSnackBlockParticlesHandler
|
||||
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.ExpGainedDataPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.InteractPokemonUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.PokedexUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.SetActiveTMPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.SetTMMachineContainerDataPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.SynchronizeActiveTMHandler
|
||||
import com.cobblemon.mod.common.client.net.habitat.OpenHabitatBlockEditorHandler
|
||||
import com.cobblemon.mod.common.client.net.npc.CloseNPCEditorHandler
|
||||
import com.cobblemon.mod.common.client.net.npc.OpenNPCEditorHandler
|
||||
import com.cobblemon.mod.common.client.net.orientation.ClientboundUpdateOrientationHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.*
|
||||
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.ClientboundSeatAssignmentPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.pokemon.update.ClientboundUpdateRidingStateHandler
|
||||
import com.cobblemon.mod.common.client.net.pokemon.update.PokemonUpdatePacketHandler
|
||||
import com.cobblemon.mod.common.client.net.riding.ClientboundUpdateDriverInputHandler
|
||||
@@ -52,9 +63,15 @@ import com.cobblemon.mod.common.client.net.storage.party.SetPartyPokemonHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.party.SetPartyReferenceHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.pc.*
|
||||
import com.cobblemon.mod.common.client.net.toast.ToastPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.*
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeAcceptanceChangedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeCancelledHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeCompletedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeOfferExpiredHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeOfferNotificationHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeProcessStartedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeStartedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeUpdatedHandler
|
||||
import com.cobblemon.mod.common.net.PacketRegisterInfo
|
||||
import com.cobblemon.mod.common.net.messages.client.CalculateSeatPositionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.OpenBehaviourEditorPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.SetClientPlayerDataPacket
|
||||
@@ -69,16 +86,26 @@ import com.cobblemon.mod.common.net.messages.client.data.*
|
||||
import com.cobblemon.mod.common.net.messages.client.debug.RequestOpenRidingStatsDebugGUIPacket
|
||||
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.*
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.PokeSnackBlockParticlesPacket
|
||||
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.habitat.OpenHabitatBlockEditorPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.npc.CloseNPCEditorPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.npc.OpenNPCEditorPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.orientation.ClientboundUpdateDriverInputPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.orientation.ClientboundUpdateOrientationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.*
|
||||
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
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.ClearEvolutionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.ClientboundSeatAssignmentPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.RemoveEvolutionPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.settings.OpenCobblemonConfigScreenPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
|
||||
@@ -94,22 +121,51 @@ import com.cobblemon.mod.common.net.messages.client.storage.party.InitializePart
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.MoveClientPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyReferencePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.ClosePCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.InitializePCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.MoveClientPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.OpenPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.RenamePCBoxPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.ChangePCBoxWallpaperPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.RequestPCBoxWallpapersPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.SetPCBoxWallpapersPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.UnlockPCBoxWallpaperPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.tms.TechnicalMachineRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.toast.ToastPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.*
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeAcceptanceChangedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeCompletedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferExpiredPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotificationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeProcessStartedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.ExpGainedDataPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.PokedexUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SetActiveTMPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SetTMMachineContainerDataPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.*
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.*
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SynchronizeActiveTMPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BattleChallengeResponsePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BenchMovePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.RequestMoveSwapPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.RequestPlayerInteractionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamLeavePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamRequestPacket
|
||||
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.block.TMMachineTeachMovePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectedPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.party.PartyPokemonSelectedPacket
|
||||
@@ -122,6 +178,7 @@ import com.cobblemon.mod.common.net.messages.server.debug.ServerboundUpdateRidin
|
||||
import com.cobblemon.mod.common.net.messages.server.debug.ServerboundUpdateRidingStatsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.dialogue.EscapeDialoguePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.dialogue.InputToDialoguePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.habitat.SaveHabitatBlockSettingsPacket
|
||||
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
|
||||
@@ -131,25 +188,42 @@ import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPack
|
||||
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.FinishScanningPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.StartScanningPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.interact.InteractPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.*
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.ServerboundUpdateRidingStatePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetActiveMarkPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetItemHiddenPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetMarkingsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePacket
|
||||
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.riding.ServerboundUpdateDriverInputPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdatePassengerPositionPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdateRiderRotationPacket
|
||||
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
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.PartyTutorialPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.ReleasePartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.*
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.AcceptTradeRequestPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.CancelTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptancePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.PerformTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.ChallengeResponseHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.RequestInteractionsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.RemoveSpectatorHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.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.block.TMMachineTeachMoveHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectCancelledHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectedHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.party.PartyPokemonSelectedHandler
|
||||
@@ -163,6 +237,7 @@ import com.cobblemon.mod.common.net.serverhandling.debug.ServerboundUpdateRiding
|
||||
import com.cobblemon.mod.common.net.serverhandling.dialogue.EscapeDialogueHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.dialogue.InputToDialogueHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.evolution.AcceptEvolutionHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.habitat.SaveHabitatBlockSettingsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.npc.SaveNPCHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.orientation.ServerboundUpdateOrientationHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.PasturePokemonHandler
|
||||
@@ -172,9 +247,14 @@ import com.cobblemon.mod.common.net.serverhandling.pasture.UnpasturePokemonHandl
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.FinishScanningHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.StartScanningHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.interact.InteractPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.ServerboundUpdateRidingStateHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetActiveMarkHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetItemHiddenHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetMarkingsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetNicknameHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.riding.DismountPokemonPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.riding.DriverInputPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.riding.ServerboundUpdatePassengerPositionHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.riding.ServerboundUpdateRiderRotationHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.starter.RequestStarterScreenHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.starter.SelectStarterPacketHandler
|
||||
@@ -183,10 +263,16 @@ import com.cobblemon.mod.common.net.serverhandling.storage.RequestMoveSwapHandle
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.SendOutPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.SwapPCPartyPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.party.MovePartyPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.party.PartyTutorialPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.party.ReleasePCPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.party.SwapPartyPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.AcceptTradeRequestHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.CancelTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.PerformTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
@@ -256,6 +342,8 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(MarkingsUpdatePacket.ID, MarkingsUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(RideBoostsUpdatePacket.ID, RideBoostsUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(RideStaminaUpdatePacket.ID, RideStaminaUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(AlphaUpdatePacket.ID, AlphaUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(ScaleModifierUpdatePacket.ID, ScaleModifierUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
|
||||
// Evolution start
|
||||
list.add(PacketRegisterInfo(AddEvolutionPacket.ID, AddEvolutionPacket::decode, PokemonUpdatePacketHandler()))
|
||||
@@ -289,6 +377,7 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(PlayerInteractOptionsPacket.ID, PlayerInteractOptionsPacket::decode, PlayerInteractOptionsHandler))
|
||||
list.add(PacketRegisterInfo(PokedexUIPacket.ID, PokedexUIPacket::decode, PokedexUIPacketHandler))
|
||||
list.add(PacketRegisterInfo(ExpGainedDataPacket.ID, ExpGainedDataPacket::decode, ExpGainedDataPacketHandler))
|
||||
list.add(PacketRegisterInfo(SynchronizeActiveTMPacket.ID, SynchronizeActiveTMPacket::decode, SynchronizeActiveTMHandler))
|
||||
|
||||
// Starter packets
|
||||
list.add(PacketRegisterInfo(OpenStarterUIPacket.ID, OpenStarterUIPacket::decode, StarterUIPacketHandler))
|
||||
@@ -332,7 +421,7 @@ object CobblemonNetwork {
|
||||
// Data registries
|
||||
list.add(PacketRegisterInfo(AbilityRegistrySyncPacket.ID, AbilityRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(CobblemonMechanicsSyncPacket.ID, CobblemonMechanicsSyncPacket::decode, CobblemonMechanicsSyncHandler))
|
||||
list.add(PacketRegisterInfo(PokemonInteractionsSyncPacket.ID, PokemonInteractionsSyncPacket::decode, PokemonInteractionsSyncHandler))
|
||||
list.add(PacketRegisterInfo(PokemonInteractionsSyncPacket.ID, PokemonInteractionsSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(MovesRegistrySyncPacket.ID, MovesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(BerryRegistrySyncPacket.ID, BerryRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(SpeciesRegistrySyncPacket.ID, SpeciesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
@@ -354,6 +443,7 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(BehaviourSyncPacket.ID, BehaviourSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(MarkRegistrySyncPacket.ID, MarkRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(RideSettingsSyncPacket.ID, RideSettingsSyncPacket::decode, RideSettingsSyncHandler))
|
||||
list.add(PacketRegisterInfo(TechnicalMachineRegistrySyncPacket.ID, TechnicalMachineRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
|
||||
// Effects
|
||||
list.add(PacketRegisterInfo(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler))
|
||||
@@ -416,16 +506,18 @@ object CobblemonNetwork {
|
||||
// Pokédex scanning
|
||||
list.add(PacketRegisterInfo(ServerConfirmedRegisterPacket.ID, ServerConfirmedRegisterPacket::decode, ServerConfirmedRegisterHandler))
|
||||
|
||||
// Debug / cheats
|
||||
list.add(PacketRegisterInfo(CalculateSeatPositionsPacket.ID, CalculateSeatPositionsPacket::decode, CalculateSeatPositionsHandler))
|
||||
|
||||
// Riding
|
||||
list.add(PacketRegisterInfo(ClientboundUpdateRidingStatePacket.ID, ClientboundUpdateRidingStatePacket::decode, ClientboundUpdateRidingStateHandler))
|
||||
list.add(PacketRegisterInfo(ClientboundUpdateDriverInputPacket.ID, ClientboundUpdateDriverInputPacket::decode, ClientboundUpdateDriverInputHandler))
|
||||
list.add(PacketRegisterInfo(ClientboundSeatAssignmentPacket.ID, ClientboundSeatAssignmentPacket::decode, ClientboundSeatAssignmentPacketHandler))
|
||||
|
||||
// Habitat blocks
|
||||
list.add(PacketRegisterInfo(OpenHabitatBlockEditorPacket.ID, OpenHabitatBlockEditorPacket::decode, OpenHabitatBlockEditorHandler))
|
||||
|
||||
// Debug
|
||||
list.add(PacketRegisterInfo(OpenRidingStatsDebugGUIPacket.ID, OpenRidingStatsDebugGUIPacket::decode, OpenRidingStatsDebugGUIHandler))
|
||||
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
@@ -460,7 +552,7 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(ReleasePCPokemonPacket.ID, ReleasePCPokemonPacket::decode, ReleasePCPokemonHandler))
|
||||
list.add(PacketRegisterInfo(UnlinkPlayerFromPCPacket.ID, UnlinkPlayerFromPCPacket::decode, UnlinkPlayerFromPCHandler))
|
||||
|
||||
list.add(PacketRegisterInfo(RequestRenamePCBoxPacket.Companion.ID, RequestRenamePCBoxPacket.Companion::decode, RequestRenamePCBoxHandler))
|
||||
list.add(PacketRegisterInfo(RequestRenamePCBoxPacket.ID, RequestRenamePCBoxPacket::decode, RequestRenamePCBoxHandler))
|
||||
list.add(PacketRegisterInfo(PCBoxWallpapersPacket.ID, PCBoxWallpapersPacket::decode, PCBoxWallpapersHandler))
|
||||
list.add(PacketRegisterInfo(RequestChangePCBoxWallpaperPacket.ID, RequestChangePCBoxWallpaperPacket::decode, RequestChangePCBoxWallpaperHandler))
|
||||
list.add(PacketRegisterInfo(MarkPCBoxWallpapersSeenPacket.ID, MarkPCBoxWallpapersSeenPacket::decode, MarkPCBoxWallpapersSeenHandler))
|
||||
@@ -505,6 +597,7 @@ object CobblemonNetwork {
|
||||
|
||||
// Block entity
|
||||
list.add(PacketRegisterInfo(AdjustBlockEntityViewerCountPacket.ID, AdjustBlockEntityViewerCountPacket::decode, AdjustBlockEntityViewerCountHandler))
|
||||
list.add(PacketRegisterInfo(TMMachineTeachMovePacket.ID, TMMachineTeachMovePacket::decode, TMMachineTeachMoveHandler))
|
||||
|
||||
// Move select packets
|
||||
list.add(PacketRegisterInfo(MoveSelectedPacket.ID, MoveSelectedPacket::decode, MoveSelectedHandler))
|
||||
@@ -518,6 +611,9 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(PartyPokemonMoveSelectedPacket.ID, PartyPokemonMoveSelectedPacket::decode, PartyPokemonMoveSelectedHandler))
|
||||
list.add(PacketRegisterInfo(PartyMoveSelectCancelledPacket.ID, PartyMoveSelectCancelledPacket::decode, PartyMoveSelectCancelledHandler))
|
||||
|
||||
//Party move tutorial toasts packets
|
||||
list.add(PacketRegisterInfo(PartyTutorialPacket.ID, PartyTutorialPacket::decode, PartyTutorialPacketHandler))
|
||||
|
||||
// Dialogue packets
|
||||
list.add(PacketRegisterInfo(EscapeDialoguePacket.ID, EscapeDialoguePacket::decode, EscapeDialogueHandler))
|
||||
list.add(PacketRegisterInfo(InputToDialoguePacket.ID, InputToDialoguePacket::decode, InputToDialogueHandler))
|
||||
@@ -534,17 +630,26 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(DismountPokemonPacket.ID, DismountPokemonPacket::decode, DismountPokemonPacketHandler))
|
||||
list.add(PacketRegisterInfo(ServerboundUpdateDriverInputPacket.ID, ServerboundUpdateDriverInputPacket::decode, DriverInputPacketHandler))
|
||||
list.add(PacketRegisterInfo(ServerboundUpdateRiderRotationPacket.ID, ServerboundUpdateRiderRotationPacket::decode, ServerboundUpdateRiderRotationHandler))
|
||||
list.add(PacketRegisterInfo(ServerboundUpdatePassengerPositionPacket.ID, ServerboundUpdatePassengerPositionPacket::decode, ServerboundUpdatePassengerPositionHandler))
|
||||
|
||||
// Cooking
|
||||
list.add(PacketRegisterInfo(ToggleCookingPotLidPacket.ID, ToggleCookingPotLidPacket::decode, ToggleCookingPotLidHandler))
|
||||
|
||||
// TM Machine
|
||||
list.add(PacketRegisterInfo(SetActiveTMPacket.ID, SetActiveTMPacket::decode, SetActiveTMPacketHandler))
|
||||
list.add(PacketRegisterInfo(SetTMMachineContainerDataPacket.ID, SetTMMachineContainerDataPacket::decode, SetTMMachineContainerDataPacketHandler))
|
||||
|
||||
// Behaviour Packets
|
||||
list.add(PacketRegisterInfo(SetEntityBehaviourPacket.ID, SetEntityBehaviourPacket::decode, SetEntityBehaviourHandler))
|
||||
list.add(PacketRegisterInfo(DamageOnCollisionPacket.ID, DamageOnCollisionPacket::decode, DamageOnCollisionPacketHandler))
|
||||
|
||||
// Debug
|
||||
// Habitat blocks
|
||||
list.add(PacketRegisterInfo(SaveHabitatBlockSettingsPacket.ID, SaveHabitatBlockSettingsPacket::decode, SaveHabitatBlockSettingsHandler))
|
||||
|
||||
// Debug / cheats
|
||||
list.add(PacketRegisterInfo(RequestOpenRidingStatsDebugGUIPacket.ID, RequestOpenRidingStatsDebugGUIPacket::decode, RequestOpenRidingStatsDebugGUIHandler))
|
||||
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.npc.PartyComposition
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
|
||||
object CobblemonPartyCompositions : JsonDataRegistry<PartyComposition> {
|
||||
override val id: ResourceLocation = cobblemonResource("party_compositions")
|
||||
override val type = PackType.SERVER_DATA
|
||||
override val typeToken: TypeToken<PartyComposition> = TypeToken.get(PartyComposition::class.java)
|
||||
override val resourcePath: String = "party_compositions"
|
||||
override val observable = SimpleObservable<CobblemonPartyCompositions>()
|
||||
override val gson: Gson = GsonBuilder()
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.setPrettyPrinting()
|
||||
.create()
|
||||
|
||||
val partyCompositions = mutableMapOf<ResourceLocation, PartyComposition>()
|
||||
|
||||
override fun sync(player: ServerPlayer) {
|
||||
// probably worth syncing which exist, yeah. the deeper details probably not. I'll get to this eventually.
|
||||
}
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, PartyComposition>) {
|
||||
data.entries.forEach { it.value.id = it.key }
|
||||
partyCompositions.clear()
|
||||
partyCompositions.putAll(data)
|
||||
observable.emit(this)
|
||||
Cobblemon.LOGGER.info("Loaded ${data.size} party compositions.")
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.moves.MovesetBuilder
|
||||
import com.cobblemon.mod.common.api.npc.PartyPool
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.util.ScriptableIntRange
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IntRangeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.MovesetBuilderReferenceAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.PokemonPropertiesAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ScriptableIntRangeAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
|
||||
object CobblemonPartyPools : JsonDataRegistry<PartyPool> {
|
||||
override val id: ResourceLocation = cobblemonResource("party_pools")
|
||||
override val type = PackType.SERVER_DATA
|
||||
override val typeToken: TypeToken<PartyPool> = TypeToken.get(PartyPool::class.java)
|
||||
override val resourcePath: String = "party_pools"
|
||||
override val observable = SimpleObservable<CobblemonPartyPools>()
|
||||
override val gson: Gson = GsonBuilder()
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.registerTypeAdapter(PokemonProperties::class.java, PokemonPropertiesAdapter(saveLong = false))
|
||||
.registerTypeAdapter(IntRange::class.java, IntRangeAdapter)
|
||||
.registerTypeAdapter(ScriptableIntRange::class.java, ScriptableIntRangeAdapter)
|
||||
.registerTypeAdapter(MovesetBuilder::class.java, MovesetBuilderReferenceAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.setPrettyPrinting()
|
||||
.create()
|
||||
|
||||
val partyPools = mutableMapOf<ResourceLocation, PartyPool>()
|
||||
|
||||
override fun sync(player: ServerPlayer) {
|
||||
// probably worth syncing. Knowing the details might help exploit the server? lot of effort for little though.
|
||||
}
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, PartyPool>) {
|
||||
data.entries.forEach { it.value.id = it.key }
|
||||
partyPools.clear()
|
||||
partyPools.putAll(data)
|
||||
observable.emit(this)
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,10 @@ object CobblemonPoiTypes: PlatformRegistry<Registry<PoiType>, ResourceKey<Regist
|
||||
// TODO after 1.7
|
||||
// @JvmField
|
||||
// val INCENSE_SWEET_KEY = createKey("incense_sweet", CobblemonBlocks.INCENSE_SWEET, 0, 1)
|
||||
@JvmField
|
||||
val HABITAT_BLOCK_KEY: ResourceKey<PoiType> = createKey("habitat_block", CobblemonBlocks.HABITAT_BLOCK, 0, 1)
|
||||
@JvmField
|
||||
val HABITAT_BLOCK = create(HABITAT_BLOCK_KEY.location().path, PoiType(getBlockStates(CobblemonBlocks.HABITAT_BLOCK), 0, 1))
|
||||
|
||||
private fun createKey(string: String, block: Block, maxTickets: Int, validRange: Int ): ResourceKey<PoiType> =
|
||||
ResourceKey.create(Registries.POINT_OF_INTEREST_TYPE, cobblemonResource(string)).also { resourceKey ->
|
||||
|
||||
@@ -37,6 +37,9 @@ object CobblemonSensors {
|
||||
@JvmField
|
||||
val POKEMON_DEFEND_OWNER = register("pokemon_owner_under_attack", ::DefendOwnerSensor)
|
||||
|
||||
@JvmField
|
||||
val ALPHA_LEVEL_MATCHING = register("alpha_level_matching", ::AlphaLevelMatchingSensor)
|
||||
|
||||
@JvmField
|
||||
val NEARBY_GROWABLE_CROPS = register("nearby_growable_crops", ::PokemonGrowableCropSensor)
|
||||
|
||||
|
||||
@@ -108,6 +108,9 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
@JvmField
|
||||
val LEVELUP = this.create("gui.levelup")
|
||||
|
||||
@JvmField
|
||||
val MOVE_LEARN = this.create("gui.move_learn")
|
||||
|
||||
@JvmField
|
||||
val PVN_BATTLE = this.create("battle.pvn.default")
|
||||
@JvmField
|
||||
@@ -136,6 +139,15 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
@JvmField
|
||||
val MULCH_REMOVE = this.create("block.mulch.remove")
|
||||
|
||||
@JvmField
|
||||
val MONITOR_BREAK = this.create("block.monitor.break")
|
||||
@JvmField
|
||||
val MONITOR_INSERT = this.create("block.monitor.insert")
|
||||
@JvmField
|
||||
val MONITOR_LOADING = this.create("block.monitor.loading")
|
||||
@JvmField
|
||||
val MONITOR_GLITCHING = this.create("block.monitor.glitching")
|
||||
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_ACTIVATE = this.create("block.fossil_machine.activate")
|
||||
@JvmField
|
||||
@@ -200,6 +212,28 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
@JvmField
|
||||
val TUMBLESTONE_STEP = this.create("block.tumblestone.step")
|
||||
|
||||
@JvmField
|
||||
val TM_USE = this.create("item.tm.use")
|
||||
@JvmField
|
||||
val TM_MACHINE_BURN_LOOP = this.create("block.tm_machine.burn_loop")
|
||||
@JvmField
|
||||
val TM_MACHINE_CRAFT = this.create("block.tm_machine.craft")
|
||||
@JvmField
|
||||
val TM_MACHINE_START = this.create("block.tm_machine.start")
|
||||
@JvmField
|
||||
val TM_MACHINE_OPEN = this.create("block.tm_machine.open")
|
||||
@JvmField
|
||||
val TM_MACHINE_CLOSE = this.create("block.tm_machine.close")
|
||||
@JvmField
|
||||
val TM_MACHINE_TM_INSERT = this.create("block.tm_machine.tm_insert")
|
||||
@JvmField
|
||||
val TM_MACHINE_TM_RETRIEVE = this.create("block.tm_machine.tm_retrieve")
|
||||
@JvmField
|
||||
val TM_MACHINE_ITEM_INSERT = this.create("block.tm_machine.item_insert")
|
||||
@JvmField
|
||||
val TM_MACHINE_ITEM_RETRIEVE = this.create("block.tm_machine.item_retrieve")
|
||||
|
||||
|
||||
@JvmField
|
||||
val EVOLUTION_STONE_BLOCK_BREAK = this.create("block.evolution_stone_block.break")
|
||||
@JvmField
|
||||
@@ -238,6 +272,9 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
@JvmField
|
||||
val BERRY_EAT_FULL = this.create("item.berry.eat.full")
|
||||
|
||||
@JvmField
|
||||
val APRICORN_HARVEST = this.create("block.apricorn.harvest")
|
||||
|
||||
@JvmField
|
||||
val BIG_ROOT_BREAK = this.create("block.big_root.break")
|
||||
@JvmField
|
||||
@@ -312,9 +349,13 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val RIDE_LOOP_LEATHER = create("ride.loop.leather")
|
||||
val RIDE_LOOP_LEATHER_MONO = create("ride.loop.leather.mono")
|
||||
@JvmField
|
||||
val RIDE_LOOP_PLUMAGE = create("ride.loop.plumage")
|
||||
val RIDE_LOOP_PLUMAGE_MONO = create("ride.loop.plumage.mono")
|
||||
@JvmField
|
||||
val RIDE_LOOP_LEATHER_STEREO = create("ride.loop.leather.stereo")
|
||||
@JvmField
|
||||
val RIDE_LOOP_PLUMAGE_STEREO = create("ride.loop.plumage.stereo")
|
||||
|
||||
@JvmField
|
||||
val MOVE_QUICKATTACK_TARGET = this.create("move.quickattack.target")
|
||||
@@ -380,6 +421,35 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
TUMBLESTONE_STEP
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_BREAK = this.create("block.type_gem_block.break")
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_BREAK = this.create("block.type_gem_cluster.break")
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_HIT = this.create("block.type_gem_block.hit")
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_PLACE = this.create("block.type_gem_block.place")
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_STEP = this.create("block.type_gem_block.step")
|
||||
|
||||
@JvmField
|
||||
val TYPE_GEM_CLUSTER_SOUNDS = SoundType(1f, 1.1f,
|
||||
TYPE_GEM_CLUSTER_BREAK,
|
||||
TYPE_GEM_BLOCK_STEP,
|
||||
TYPE_GEM_BLOCK_PLACE,
|
||||
TYPE_GEM_BLOCK_HIT,
|
||||
TYPE_GEM_BLOCK_STEP
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val TYPE_GEM_BLOCK_SOUNDS = SoundType(1f, 1.1f,
|
||||
TYPE_GEM_BLOCK_BREAK,
|
||||
TYPE_GEM_BLOCK_STEP,
|
||||
TYPE_GEM_BLOCK_PLACE,
|
||||
TYPE_GEM_BLOCK_HIT,
|
||||
TYPE_GEM_BLOCK_STEP
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val EVOLUTION_STONE_BLOCK_SOUNDS = SoundType(1f, 1.1f,
|
||||
EVOLUTION_STONE_BLOCK_BREAK,
|
||||
@@ -561,5 +631,31 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
CAMPFIRE_POT_STEP
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val ITEM_BLOCK_PAPER_SMALL_PLACE = this.create("block.item_block.paper_small.place")
|
||||
@JvmField
|
||||
val ITEM_BLOCK_PAPER_SMALL_BREAK = this.create("block.item_block.paper_small.break")
|
||||
@JvmField
|
||||
val ITEM_BLOCK_PAPER_SMALL_SOUNDS = SoundType(1f, 1.1f,
|
||||
ITEM_BLOCK_PAPER_SMALL_BREAK,
|
||||
SoundEvents.WOOL_STEP,
|
||||
ITEM_BLOCK_PAPER_SMALL_PLACE,
|
||||
SoundEvents.WOOL_HIT,
|
||||
SoundEvents.WOOL_FALL
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val ITEM_BLOCK_PAPER_LARGE_PLACE = this.create("block.item_block.paper_large.place")
|
||||
@JvmField
|
||||
val ITEM_BLOCK_PAPER_LARGE_BREAK = this.create("block.item_block.paper_large.break")
|
||||
@JvmField
|
||||
val ITEM_BLOCK_PAPER_LARGE_SOUNDS = SoundType(1f, 1.1f,
|
||||
ITEM_BLOCK_PAPER_LARGE_BREAK,
|
||||
SoundEvents.WOOL_STEP,
|
||||
ITEM_BLOCK_PAPER_LARGE_PLACE,
|
||||
SoundEvents.WOOL_HIT,
|
||||
SoundEvents.WOOL_FALL
|
||||
)
|
||||
|
||||
private fun create(name: String): SoundEvent = this.create(name, SoundEvent.createVariableRangeEvent(cobblemonResource(name)))
|
||||
}
|
||||
|
||||
@@ -32,6 +32,9 @@ object CobblemonCriteria : PlatformRegistry<Registry<CriterionTrigger<*>>, Resou
|
||||
@JvmField
|
||||
val CATCH_SHINY_POKEMON = this.create("catch_shiny_pokemon", SimpleCriterionTrigger(CountableCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val CATCH_ALPHA_POKEMON = this.create("catch_alpha_pokemon", SimpleCriterionTrigger(CountableCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val EGG_COLLECT = this.create("eggs_collected", SimpleCriterionTrigger(CountableCriterion.CODEC))
|
||||
|
||||
@@ -78,8 +81,20 @@ object CobblemonCriteria : PlatformRegistry<Registry<CriterionTrigger<*>>, Resou
|
||||
@JvmField
|
||||
val PLANT_TUMBLESTONE = this.create("plant_tumblestone", SimpleCriterionTrigger(PlantTumblestoneCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val PLANT_TYPE_GEM = this.create("plant_type_gem", SimpleCriterionTrigger(PlantTypeGemCriterion.CODEC))
|
||||
|
||||
val RIDING_STAT_BOOST = this.create("riding_stat_boost", SimpleCriterionTrigger(RidingStatBoostCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val LEARN_TM = this.create("has_learn_specific_tm", SimpleCriterionTrigger(LearnTMCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val LEARN_ALL_TM = this.create("has_learn_all_tm", SimpleCriterionTrigger(LearnAllTMCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val LEARN_TM_COUNT = this.create("tms_learned", SimpleCriterionTrigger(CountableCriterion.CODEC))
|
||||
|
||||
override val registry = BuiltInRegistries.TRIGGER_TYPES
|
||||
override val resourceKey = Registries.TRIGGER_TYPE
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.advancement.criterion
|
||||
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.advancements.critereon.ContextAwarePredicate
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import java.util.Optional
|
||||
|
||||
class LearnTMContext(val tm: ResourceLocation)
|
||||
|
||||
class LearnTMCriterion(
|
||||
playerCtx: Optional<ContextAwarePredicate>,
|
||||
val tm: String
|
||||
) : SimpleCriterionCondition<LearnTMContext>(playerCtx) {
|
||||
companion object {
|
||||
val CODEC: Codec<LearnTMCriterion> = RecordCodecBuilder.create { it.group(
|
||||
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(LearnTMCriterion::playerCtx),
|
||||
Codec.STRING.optionalFieldOf("tm", "any").forGetter(LearnTMCriterion::tm)
|
||||
).apply(it, ::LearnTMCriterion) }
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: LearnTMContext): Boolean {
|
||||
return tm == "any" || context.tm == tm.asIdentifierDefaultingNamespace()
|
||||
}
|
||||
}
|
||||
|
||||
class LearnAllTMContext
|
||||
|
||||
class LearnAllTMCriterion(
|
||||
playerCtx: Optional<ContextAwarePredicate>
|
||||
) : SimpleCriterionCondition<LearnAllTMContext>(playerCtx) {
|
||||
companion object {
|
||||
val CODEC: Codec<LearnAllTMCriterion> = RecordCodecBuilder.create { it.group(
|
||||
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(LearnAllTMCriterion::playerCtx)
|
||||
).apply(it, ::LearnAllTMCriterion) }
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: LearnAllTMContext) = true
|
||||
}
|
||||
+3
-39
@@ -14,7 +14,7 @@ import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.advancements.critereon.ContextAwarePredicate
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import java.util.Optional
|
||||
import java.util.*
|
||||
|
||||
class PlantTumblestoneContext(val pos: BlockPos, val block: TumblestoneBlock)
|
||||
|
||||
@@ -29,42 +29,6 @@ class PlantTumblestoneCriterion(
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: PlantTumblestoneContext): Boolean {
|
||||
return context.block.canGrow(context.pos, player.level())
|
||||
return context.block.canGrow(player.level().getBlockState(context.pos), context.pos, player.level())
|
||||
}
|
||||
}
|
||||
|
||||
///**
|
||||
// * A criterion condition for when a tumblestone block is planted
|
||||
// * @param id The identifier of the criterion
|
||||
// * @param predicate The predicate for the criterion
|
||||
// *
|
||||
// * @author Aethen
|
||||
// * @since 02/28/2024
|
||||
// */
|
||||
//class PlantTumblestoneCriterionCondition(id: Identifier, predicate: LootContextPredicate) :
|
||||
// SimpleCriterionCondition<PlantTumblestoneContext>(id, predicate) {
|
||||
// override fun toJson(json: JsonObject) {
|
||||
// // Add properties to json if needed. None needed for this criterion
|
||||
// }
|
||||
//
|
||||
// override fun fromJson(json: JsonObject) {
|
||||
// // Parse properties from json if needed. None needed for this criterion
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Checks if the tumblestone block can grow at the given position
|
||||
// * @param player The player that planted the tumblestone block
|
||||
// * @param context The context of the criterion
|
||||
// * @return True if the tumblestone block can grow at the given position, false otherwise
|
||||
// */
|
||||
// override fun matches(player: ServerPlayer, context: PlantTumblestoneContext): Boolean {
|
||||
// return context.tumbleStoneBlock.canGrow(context.pos, player.level())
|
||||
// }
|
||||
//}
|
||||
//
|
||||
///**
|
||||
// * The context of the [PlantTumblestoneCriterionCondition]
|
||||
// * @param pos The position of the tumblestone block
|
||||
// * @param tumbleStoneBlock The tumblestone block
|
||||
// */
|
||||
//open class PlantTumblestoneContext(var pos: BlockPos, var tumbleStoneBlock: TumblestoneBlock)
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.advancement.criterion
|
||||
|
||||
import com.cobblemon.mod.common.block.TypeGemClusterBlock
|
||||
import com.cobblemon.mod.common.block.TypeGemCoreBlock
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.advancements.critereon.ContextAwarePredicate
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import java.util.*
|
||||
|
||||
class PlantTypeGemContext(val pos: BlockPos, val block: TypeGemClusterBlock)
|
||||
|
||||
class PlantTypeGemCriterion(
|
||||
playerCtx: Optional<ContextAwarePredicate>
|
||||
): SimpleCriterionCondition<PlantTypeGemContext>(playerCtx) {
|
||||
|
||||
companion object {
|
||||
val CODEC: Codec<PlantTypeGemCriterion> = RecordCodecBuilder.create { it.group(
|
||||
ContextAwarePredicate.CODEC.optionalFieldOf("player").forGetter(PlantTypeGemCriterion::playerCtx)
|
||||
).apply(it, ::PlantTypeGemCriterion) }
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: PlantTypeGemContext): Boolean {
|
||||
return player.level().getBlockState(context.pos).block is TypeGemCoreBlock
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -48,7 +48,7 @@ class RidingStatBoostCriterion(
|
||||
val max = context.pokemon.pokemon.getMaxRideBoost(rideStat).toDouble()
|
||||
val min = context.pokemon.pokemon.getBaseRideStat(rideStat).toDouble()
|
||||
val value = context.pokemon.getRideStat(rideStat, ridingStyle, min, max)
|
||||
val isSufficient = (value >= this.statValue && this.statValue > 0.0) || !context.pokemon.pokemon.canAddRideBoost(rideStat)
|
||||
val isSufficient = (value >= this.statValue && this.statValue > 0.0) || !context.pokemon.pokemon.canApplyRideBoost(rideStat)
|
||||
if (isSufficient && this.rideStat == "any") {
|
||||
return true
|
||||
} else if (!isSufficient && this.rideStat == "all") {
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangV
|
||||
import com.cobblemon.mod.common.entity.OmniPathingEntity
|
||||
import com.cobblemon.mod.common.entity.ai.CobblemonRandomSurfacePos
|
||||
import com.cobblemon.mod.common.entity.ai.CobblemonWalkTarget
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.mainThreadRuntime
|
||||
import com.cobblemon.mod.common.util.resolveFloat
|
||||
@@ -184,6 +185,12 @@ class WanderTaskConfig : SingleTaskConfig {
|
||||
|
||||
if (targetVec == null) continue
|
||||
|
||||
// Ignore pathing targets outside of the pasture zone if the pokemon is pastured.
|
||||
val tethering = (entity as? PokemonEntity)?.tethering
|
||||
if (tethering?.canRoamTo(BlockPos.containing(targetVec)) == false) {
|
||||
continue
|
||||
}
|
||||
|
||||
pos = applyHeightConstraints(
|
||||
pos = BlockPos.containing(targetVec),
|
||||
minimumHeight = minimumHeight,
|
||||
|
||||
+41
-17
@@ -22,18 +22,21 @@ import com.cobblemon.mod.common.api.battles.model.actor.EntityBackedBattleActor
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.FleeableBattleActor
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleFledEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleFleeAttemptEvent
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.BattleEvSource
|
||||
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.text.white
|
||||
import com.cobblemon.mod.common.api.text.yellow
|
||||
import com.cobblemon.mod.common.battles.ActiveBattlePokemon
|
||||
import com.cobblemon.mod.common.battles.BattleCaptureAction
|
||||
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.FleeAttemptActionResponse
|
||||
import com.cobblemon.mod.common.battles.ForfeitActionResponse
|
||||
import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
|
||||
import com.cobblemon.mod.common.battles.dispatch.BattleDispatch
|
||||
@@ -48,7 +51,9 @@ import com.cobblemon.mod.common.entity.npc.NPCBattleActor
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleEndPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMakeChoicePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleQueueRequestPacket
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.DefeatEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.LastBattleCriticalHitsEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.requirements.DefeatRequirement
|
||||
@@ -132,11 +137,13 @@ open class PokemonBattle(
|
||||
|
||||
var dispatchResult = GO
|
||||
val dispatches = ConcurrentLinkedDeque<BattleDispatch>()
|
||||
val afterDispatches = mutableListOf<() -> Unit>()
|
||||
|
||||
val captureActions = mutableListOf<BattleCaptureAction>()
|
||||
|
||||
val majorBattleActions = hashMapOf<UUID, BattleMessage>()
|
||||
|
||||
/** Monotonically increasing counter to track faint ordering within this battle. */
|
||||
var faintCounter = 0
|
||||
val minorBattleActions = hashMapOf<UUID, BattleMessage>()
|
||||
val contextManager = ContextManager()
|
||||
|
||||
@@ -244,12 +251,23 @@ open class PokemonBattle(
|
||||
|
||||
fun end() {
|
||||
ended = true
|
||||
val awardToFainted = Cobblemon.config.awardExperienceToFaintedPokemon
|
||||
val awardOnLoss = Cobblemon.config.awardExperienceOnBattleLoss
|
||||
this.actors.forEach { actor ->
|
||||
val faintedPokemons = actor.pokemonList.filter { it.health <= 0 }
|
||||
actor.getSide().getOppositeSide().actors.forEach { opponent ->
|
||||
val opponentNonFaintedPokemons = opponent.pokemonList.filter { it.health > 0 }
|
||||
val opponentPokemons = if (awardToFainted) opponent.pokemonList else opponent.pokemonList.filter { it.health > 0 }
|
||||
faintedPokemons.forEach { faintedPokemon ->
|
||||
for (opponentPokemon in opponentNonFaintedPokemons) {
|
||||
for (opponentPokemon in opponentPokemons) {
|
||||
// Faint-order check: if awarding XP to fainted pokemon, only award for enemies that fainted before this pokemon did
|
||||
if (awardToFainted) {
|
||||
val enemyFaintedAt = faintedPokemon.faintedAt ?: continue
|
||||
val opponentFaintedAt = opponentPokemon.faintedAt
|
||||
if (opponentFaintedAt != null && opponentFaintedAt <= enemyFaintedAt) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
val facedFainted = opponentPokemon.facedOpponents.contains(faintedPokemon)
|
||||
val pokemon = opponentPokemon.effectedPokemon
|
||||
if (facedFainted) {
|
||||
@@ -270,7 +288,8 @@ open class PokemonBattle(
|
||||
else -> continue
|
||||
}
|
||||
val experience = Cobblemon.experienceCalculator.calculate(opponentPokemon, faintedPokemon, multiplier)
|
||||
if (experience > 0 && actor.pokemonList.all { it.health <= 0 }) {
|
||||
val enemyTeamWiped = actor.pokemonList.all { it.health <= 0 }
|
||||
if (experience > 0 && (enemyTeamWiped || awardOnLoss)) {
|
||||
opponent.awardExperience(opponentPokemon, experience)
|
||||
}
|
||||
Cobblemon.evYieldCalculator.calculate(opponentPokemon, faintedPokemon).forEach { (stat, amount) ->
|
||||
@@ -304,7 +323,8 @@ open class PokemonBattle(
|
||||
.forEach{it.pokemon.heal()}
|
||||
actors.forEach { actor ->
|
||||
actor.pokemonList.forEach { battlePokemon ->
|
||||
battlePokemon.entity?.let { entity -> battlePokemon.postBattleEntityOperation(entity) }
|
||||
battlePokemon.postBattlePokemonOperations.forEach { it(battlePokemon) }
|
||||
battlePokemon.entity?.let { entity -> battlePokemon.postBattleEntityOperations.forEach { it(entity) } }
|
||||
if (battlePokemon.effectedPokemon.entity != null
|
||||
&& battlePokemon.effectedPokemon.entity?.beamMode == 0
|
||||
&& battlePokemon.effectedPokemon.entity?.platform != PlatformType.NONE) {
|
||||
@@ -379,12 +399,10 @@ open class PokemonBattle(
|
||||
|
||||
fun dispatch(dispatcher: () -> DispatchResult) {
|
||||
dispatches.add(BattleDispatch { dispatcher() })
|
||||
|
||||
}
|
||||
|
||||
fun dispatchToFront(dispatcher: () -> DispatchResult) {
|
||||
dispatches.addFirst(BattleDispatch { dispatcher() })
|
||||
|
||||
}
|
||||
|
||||
fun dispatchWaitingToFront(delaySeconds: Float = 1F, dispatcher: () -> Unit) {
|
||||
@@ -435,21 +453,12 @@ open class PokemonBattle(
|
||||
dispatches.addFirst(dispatcher)
|
||||
}
|
||||
|
||||
fun doWhenClear(action: () -> Unit) {
|
||||
afterDispatches.add(action)
|
||||
}
|
||||
|
||||
fun tick() {
|
||||
try {
|
||||
while (dispatchResult.canProceed()) {
|
||||
val dispatch = dispatches.poll() ?: break
|
||||
dispatchResult = dispatch(this)
|
||||
}
|
||||
|
||||
if (dispatches.isEmpty()) {
|
||||
afterDispatches.toList().forEach { it() }
|
||||
afterDispatches.clear()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
LOGGER.error("Exception while ticking a battle. Saving battle log.", e)
|
||||
val message = battleLang("crash").red()
|
||||
@@ -498,12 +507,13 @@ open class PokemonBattle(
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
end()
|
||||
writeShowdownAction(">forcetie") // This will terminate the Showdown connection
|
||||
end()
|
||||
}
|
||||
|
||||
fun checkForInputDispatch() {
|
||||
if (checkForfeit()) return // ignore actors that are still choosing, their choices don't matter anymore
|
||||
if (checkFleeAttempt()) return
|
||||
val readyToInput = (actors.any { !it.mustChoose && it.responses.isNotEmpty() } && actors.none { it.mustChoose })
|
||||
if (readyToInput && captureActions.isEmpty()) {
|
||||
actors.filter { it.responses.isNotEmpty() }.forEach { it.writeShowdownResponse() }
|
||||
@@ -511,6 +521,20 @@ open class PokemonBattle(
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkFleeAttempt(): Boolean {
|
||||
val runner = actors.find { it.responses.any { it is FleeAttemptActionResponse } } as? PlayerBattleActor ?: return false
|
||||
CobblemonEvents.BATTLE_FLEE_ATTEMPT.post(BattleFleeAttemptEvent(this, runner))
|
||||
runner.responses.clear()
|
||||
|
||||
runner.mustChoose = true
|
||||
runner.request?.let { runner.sendUpdate(BattleQueueRequestPacket(it)) }
|
||||
runner.sendUpdate(BattleMakeChoicePacket())
|
||||
|
||||
runner.entity?.sendSystemMessage(battleLang("run_prompt").white())
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/** Forces Showdown to end the battle when a [BattleActor] chooses to forfeit. */
|
||||
private fun checkForfeit(): Boolean {
|
||||
val forfeit = actors.find { it.responses.any { it is ForfeitActionResponse } }
|
||||
|
||||
+8
-5
@@ -8,8 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.battles.model.actor
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
@@ -76,7 +74,7 @@ abstract class BattleActor(
|
||||
fun turn() {
|
||||
val request = request ?: return
|
||||
responses.clear()
|
||||
if(activePokemon.any { it.isAlive() }) {
|
||||
if (activePokemon.any { it.isAlive() }) {
|
||||
mustChoose = true
|
||||
sendUpdate(BattleMakeChoicePacket())
|
||||
}
|
||||
@@ -90,15 +88,15 @@ abstract class BattleActor(
|
||||
}
|
||||
}
|
||||
|
||||
fun upkeep() {
|
||||
fun postUpdate() {
|
||||
val request = request ?: return
|
||||
val forceSwitchPokemon = request.forceSwitch.mapIndexedNotNull { index, b -> if (b) activePokemon[index] else null }
|
||||
if (forceSwitchPokemon.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
mustChoose = true // This must happen before the sendUpdate, not after, otherwise AI-driven actors will get locked (they may reply instantly)
|
||||
sendUpdate(BattleMakeChoicePacket())
|
||||
mustChoose = true
|
||||
}
|
||||
|
||||
fun setActionResponses(responses: List<ShowdownActionResponse>) {
|
||||
@@ -154,6 +152,11 @@ abstract class BattleActor(
|
||||
open fun sendMessage(component: Component) {
|
||||
sendUpdate(BattleMessagePacket(component))
|
||||
}
|
||||
/**
|
||||
* Called when this actor's Pokemon uses a move. Default implementation does nothing.
|
||||
* Subclasses (NPC-backed actors, players, etc) may override to trigger animations or UI.
|
||||
*/
|
||||
open fun onUseMove(user: BattlePokemon, target: BattlePokemon?) {}
|
||||
open fun awardExperience(battlePokemon: BattlePokemon, experience: Int) {}
|
||||
open fun sendUpdate(packet: NetworkPacket<*>) {}
|
||||
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cooking.effects
|
||||
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
import net.minecraft.world.effect.MobEffectCategory
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
class CleanseAllEffect : MobEffect(MobEffectCategory.BENEFICIAL, 0xFFFFFF) {
|
||||
override fun isInstantenous() = true
|
||||
override fun applyInstantenousEffect(source: Entity?, indirect: Entity?, target: LivingEntity, amplifier: Int, proximity: Double) {
|
||||
target.removeAllEffects()
|
||||
}
|
||||
override fun shouldApplyEffectTickThisTick(duration: Int, amplifier: Int) = false
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.cooking.effects
|
||||
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
import net.minecraft.world.effect.MobEffectCategory
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
class CleanseNegativeEffect : MobEffect(MobEffectCategory.BENEFICIAL, 0xFFFFFF) {
|
||||
override fun isInstantenous() = true
|
||||
override fun applyInstantenousEffect(source: Entity?, indirect: Entity?, target: LivingEntity, amplifier: Int, proximity: Double) {
|
||||
val snapshot = target.activeEffects.toList()
|
||||
for (ei in snapshot) {
|
||||
if (ei.effect.value().category == MobEffectCategory.HARMFUL) {
|
||||
target.removeEffect(ei.effect)
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun shouldApplyEffectTickThisTick(duration: Int, amplifier: Int) = false
|
||||
}
|
||||
+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.cooking.effects
|
||||
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.stats.Stats
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
import net.minecraft.world.effect.MobEffectCategory
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
class MentalRestorationEffect : MobEffect(MobEffectCategory.BENEFICIAL, 0xAA66FF) {
|
||||
override fun applyEffectTick(entity: LivingEntity, amplifier: Int): Boolean {
|
||||
if (entity is ServerPlayer) {
|
||||
val stats = entity.stats
|
||||
val statType = Stats.CUSTOM.get(Stats.TIME_SINCE_REST)
|
||||
val current = stats.getValue(statType)
|
||||
val reduction = 31 * (amplifier + 1)// reduce by half a minute every second per level (30 ticks removed per tick + 1 to account for the tick passing)
|
||||
val newValue = Math.max(current - reduction, 0)
|
||||
stats.setValue(entity, statType, newValue)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun shouldApplyEffectTickThisTick(duration: Int, amplifier: Int): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.data
|
||||
|
||||
import com.cobblemon.mod.common.api.net.Decodable
|
||||
import com.cobblemon.mod.common.api.net.Encodable
|
||||
|
||||
// TODO this is implemented in multiple places but unused. Can we scratch this?
|
||||
/**
|
||||
* Represents an object that will possibly be synchronized to the client during datapack synchronization.
|
||||
*
|
||||
* @param T The type of the object being synchronized.
|
||||
*
|
||||
* @author Licious
|
||||
* @since October 14th, 2022
|
||||
*/
|
||||
interface ClientDataSynchronizer<T> : Decodable, Encodable {
|
||||
|
||||
/**
|
||||
* Compares an object of type [T] with this instance to see if synchronization is necessary.
|
||||
*
|
||||
* @param other The other instance of type [T].
|
||||
* @return If synchronization is necessary.
|
||||
*/
|
||||
fun shouldSynchronize(other: T): Boolean
|
||||
|
||||
}
|
||||
@@ -14,9 +14,11 @@ import com.cobblemon.mod.common.api.text.green
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.util.toBlockPos
|
||||
import net.minecraft.core.component.DataComponentMap
|
||||
import com.google.gson.JsonElement
|
||||
import com.mojang.serialization.JsonOps
|
||||
import net.minecraft.core.component.DataComponentPatch
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.RegistryOps
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
@@ -40,7 +42,7 @@ open class ItemDropEntry : DropEntry {
|
||||
override var maxSelectableTimes = 1
|
||||
open val dropMethod: ItemDropMethod? = null
|
||||
open var item = ResourceLocation.parse("minecraft:fish")
|
||||
open val components: DataComponentMap? = null
|
||||
open val components: JsonElement? = null
|
||||
|
||||
override fun drop(entity: LivingEntity?, world: ServerLevel, pos: Vec3, player: ServerPlayer?) {
|
||||
val item = world.registryAccess().registryOrThrow(Registries.ITEM).get(item) ?: return LOGGER.error("Unable to load drop item: $item")
|
||||
@@ -53,11 +55,15 @@ open class ItemDropEntry : DropEntry {
|
||||
it
|
||||
}
|
||||
}
|
||||
val builder = DataComponentPatch.builder()
|
||||
components?.forEach {
|
||||
builder.set(it)
|
||||
if (components != null) {
|
||||
val registryOps = RegistryOps.create(JsonOps.INSTANCE, world.registryAccess())
|
||||
val decodeResult = DataComponentPatch.CODEC.parse(registryOps, components)
|
||||
decodeResult.ifSuccess { patch ->
|
||||
stack.applyComponentsAndValidate(patch)
|
||||
}.ifError { error ->
|
||||
LOGGER.error("Unable to parse components for drop item $item: ${error.message()}")
|
||||
}
|
||||
}
|
||||
stack.applyComponentsAndValidate(builder.build())
|
||||
|
||||
if (dropMethod == ItemDropMethod.ON_PLAYER && player != null) {
|
||||
world.addFreshEntity(ItemEntity(player.level(), player.x, player.y, player.z, stack))
|
||||
|
||||
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.api.events
|
||||
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleFaintedEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleFledEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleFleeAttemptEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleStartedEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleVictoryEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.instruction.FormeChangeEvent
|
||||
@@ -22,9 +23,21 @@ import com.cobblemon.mod.common.api.events.berry.BerryMutationResultEvent
|
||||
import com.cobblemon.mod.common.api.events.berry.BerryYieldCalculationEvent
|
||||
import com.cobblemon.mod.common.api.events.cooking.PokeSnackSpawnPokemonEvent
|
||||
import com.cobblemon.mod.common.api.events.drops.LootDroppedEvent
|
||||
import com.cobblemon.mod.common.api.events.entity.*
|
||||
import com.cobblemon.mod.common.api.events.entity.PokemonEntityLoadEvent
|
||||
import com.cobblemon.mod.common.api.events.entity.PokemonEntitySaveEvent
|
||||
import com.cobblemon.mod.common.api.events.entity.PokemonEntitySaveToWorldEvent
|
||||
import com.cobblemon.mod.common.api.events.entity.SpawnBucketChosenEvent
|
||||
import com.cobblemon.mod.common.api.events.entity.SpawnEvent
|
||||
import com.cobblemon.mod.common.api.events.farming.ApricornHarvestEvent
|
||||
import com.cobblemon.mod.common.api.events.fishing.*
|
||||
import com.cobblemon.mod.common.api.events.fishing.BaitConsumedEvent
|
||||
import com.cobblemon.mod.common.api.events.fishing.BaitEffectFunctionRegistryEvent
|
||||
import com.cobblemon.mod.common.api.events.fishing.BaitSetEvent
|
||||
import com.cobblemon.mod.common.api.events.fishing.BaitSpawnPokemonEvent
|
||||
import com.cobblemon.mod.common.api.events.fishing.BobberSpawnPokemonEvent
|
||||
import com.cobblemon.mod.common.api.events.fishing.PokerodCastEvent
|
||||
import com.cobblemon.mod.common.api.events.fishing.PokerodReelEvent
|
||||
import com.cobblemon.mod.common.api.events.habitats.HabitatSpawnActivatedEvent
|
||||
import com.cobblemon.mod.common.api.events.habitats.SaveHabitatBlockSettingsEvent
|
||||
import com.cobblemon.mod.common.api.events.item.LeftoversCreatedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokeball.PokeBallCaptureCalculatedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokeball.PokemonCatchRateEvent
|
||||
@@ -39,7 +52,11 @@ import com.cobblemon.mod.common.api.events.pokemon.healing.PokemonHealedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.interaction.ExperienceCandyUseEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.interaction.PokemonInteractionGUICreationEvent
|
||||
import com.cobblemon.mod.common.api.events.starter.StarterChosenEvent
|
||||
import com.cobblemon.mod.common.api.events.storage.*
|
||||
import com.cobblemon.mod.common.api.events.storage.ChangePCBoxWallpaperEvent
|
||||
import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent
|
||||
import com.cobblemon.mod.common.api.events.storage.RenamePCBoxEvent
|
||||
import com.cobblemon.mod.common.api.events.storage.WallpaperCollectionEvent
|
||||
import com.cobblemon.mod.common.api.events.storage.WallpaperUnlockedEvent
|
||||
import com.cobblemon.mod.common.api.events.world.BigRootPropagatedEvent
|
||||
import com.cobblemon.mod.common.api.reactive.CancelableObservable
|
||||
import com.cobblemon.mod.common.api.reactive.EventObservable
|
||||
@@ -110,6 +127,9 @@ object CobblemonEvents {
|
||||
@JvmField
|
||||
val BATTLE_STARTED_POST = EventObservable<BattleStartedEvent.Post>()
|
||||
|
||||
@JvmField
|
||||
val BATTLE_FLEE_ATTEMPT = EventObservable<BattleFleeAttemptEvent>()
|
||||
|
||||
@JvmField
|
||||
val BATTLE_FLED = EventObservable<BattleFledEvent>()
|
||||
|
||||
@@ -361,4 +381,12 @@ object CobblemonEvents {
|
||||
// -------------------------------------------------------------------------------------
|
||||
@JvmField
|
||||
val SELECT_DRIVER = EventObservable<SelectDriverEvent>()
|
||||
|
||||
// Habitats
|
||||
@JvmField
|
||||
val HABITAT_SPAWN_ACTIVATED = CancelableObservable<HabitatSpawnActivatedEvent>()
|
||||
@JvmField
|
||||
val HABITAT_SETTINGS_SAVED_PRE = CancelableObservable<SaveHabitatBlockSettingsEvent.Pre>()
|
||||
@JvmField
|
||||
val HABITAT_SETTINGS_SAVED_POST = EventObservable<SaveHabitatBlockSettingsEvent.Post>()
|
||||
}
|
||||
|
||||
+6
-3
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.events.battles
|
||||
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleContext
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
@@ -25,7 +26,8 @@ import com.cobblemon.mod.common.util.asArrayValue
|
||||
data class BattleFaintedEvent(
|
||||
override val battle: PokemonBattle,
|
||||
val killed: BattlePokemon,
|
||||
val context: BattleContext
|
||||
val context: BattleContext,
|
||||
val pnx: String
|
||||
) : BattleEvent {
|
||||
val structContext = mutableMapOf<String, MoValue>(
|
||||
"battle" to battle.struct,
|
||||
@@ -33,6 +35,7 @@ data class BattleFaintedEvent(
|
||||
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
|
||||
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
|
||||
"pokemon" to killed.struct,
|
||||
"context" to context.getStruct()
|
||||
"context" to context.getStruct(),
|
||||
"pnx" to StringValue(pnx)
|
||||
)
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.battles
|
||||
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
|
||||
/**
|
||||
* Event fired when a [PokemonBattle] is fled by a [PlayerBattleActor].
|
||||
*
|
||||
* @author saultsc
|
||||
* @since March 31th 2026
|
||||
*/
|
||||
|
||||
data class BattleFleeAttemptEvent(
|
||||
override val battle: PokemonBattle,
|
||||
val player: PlayerBattleActor
|
||||
) : BattleEvent {
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"battle" to battle.struct,
|
||||
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
|
||||
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
|
||||
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct }
|
||||
)
|
||||
}
|
||||
+5
-3
@@ -25,7 +25,8 @@ import com.cobblemon.mod.common.util.asArrayValue
|
||||
data class FormeChangeEvent(
|
||||
override val battle: PokemonBattle,
|
||||
val pokemon: BattlePokemon,
|
||||
val formeName: String
|
||||
val formeName: String,
|
||||
val pnx: String
|
||||
) : BattleEvent {
|
||||
val context = mutableMapOf(
|
||||
"battle" to battle.struct,
|
||||
@@ -33,6 +34,7 @@ data class FormeChangeEvent(
|
||||
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
|
||||
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
|
||||
"pokemon" to pokemon.struct,
|
||||
"forme" to StringValue(formeName)
|
||||
"forme" to StringValue(formeName),
|
||||
"pnx" to StringValue(pnx)
|
||||
)
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.entity
|
||||
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnBucket
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnCause
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.Spawner
|
||||
|
||||
@@ -21,7 +20,7 @@ class SpawnBucketChosenEvent(
|
||||
/** The cause of the spawn. */
|
||||
val spawnCause: SpawnCause,
|
||||
/** The bucket that was chosen. You can alter this. */
|
||||
var bucket: SpawnBucket,
|
||||
var bucket: String,
|
||||
/** The final weights that were used to make the choice. */
|
||||
val bucketWeights: Map<SpawnBucket, Float>
|
||||
val bucketWeights: Map<String, Float>
|
||||
)
|
||||
@@ -10,7 +10,9 @@ package com.cobblemon.mod.common.api.events.entity
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.spawning.BestSpawner
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnCause
|
||||
import com.cobblemon.mod.common.api.spawning.position.SpawnablePosition
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.Spawner
|
||||
import net.minecraft.world.entity.Entity
|
||||
|
||||
/**
|
||||
@@ -21,4 +23,9 @@ import net.minecraft.world.entity.Entity
|
||||
* @author Hiroku
|
||||
* @since April 22nd, 2023
|
||||
*/
|
||||
class SpawnEvent<T : Entity>(val entity: T, val spawnablePosition: SpawnablePosition) : Cancelable()
|
||||
class SpawnEvent<T : Entity>(val entity: T, val spawnablePosition: SpawnablePosition) : Cancelable() {
|
||||
val cause: SpawnCause
|
||||
get() = spawnablePosition.cause
|
||||
val spawner: Spawner
|
||||
get() = spawnablePosition.spawner
|
||||
}
|
||||
+3
-4
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common.api.events.fishing
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnBucket
|
||||
import com.cobblemon.mod.common.entity.fishing.PokeRodFishingBobberEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.world.item.ItemStack
|
||||
@@ -27,7 +26,7 @@ interface BaitSpawnPokemonEvent {
|
||||
*/
|
||||
data class Pre(
|
||||
val bobber: PokeRodFishingBobberEntity, // todo replace this with the bait entity
|
||||
val chosenBucket: SpawnBucket,
|
||||
val chosenBucket: String,
|
||||
val rod: ItemStack
|
||||
) : Cancelable(), BobberSpawnPokemonEvent
|
||||
|
||||
@@ -38,7 +37,7 @@ interface BaitSpawnPokemonEvent {
|
||||
* @param pokemon The Pokemon that is modified.
|
||||
*/
|
||||
data class Modify(
|
||||
val chosenBucket: SpawnBucket,
|
||||
val chosenBucket: String,
|
||||
val rod: ItemStack,
|
||||
val pokemon: PokemonEntity
|
||||
) : BobberSpawnPokemonEvent
|
||||
@@ -52,7 +51,7 @@ interface BaitSpawnPokemonEvent {
|
||||
*/
|
||||
data class Post(
|
||||
val bobber: PokeRodFishingBobberEntity,
|
||||
val chosenBucket: SpawnBucket,
|
||||
val chosenBucket: String,
|
||||
val bait: ItemStack,
|
||||
val pokemon: PokemonEntity
|
||||
) : BobberSpawnPokemonEvent
|
||||
|
||||
+1
-3
@@ -8,12 +8,10 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.fishing
|
||||
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnBucket
|
||||
|
||||
/**
|
||||
* Event that is fired when a bucket is chosen by the bobber.
|
||||
* @param chosenBucket The bucket that is chosen.
|
||||
* @param buckets The list of buckets that the bobber can choose from.
|
||||
* @param luckOfTheSeaLevel The level of the Luck of the Sea enchantment on the rod.
|
||||
*/
|
||||
class BobberBucketChosenEvent(var chosenBucket: SpawnBucket, val buckets: MutableList<SpawnBucket>, val luckOfTheSeaLevel: Int)
|
||||
class BobberBucketChosenEvent(var chosenBucket: String, val buckets: MutableList<String>, val luckOfTheSeaLevel: Int)
|
||||
+2
-5
@@ -12,10 +12,7 @@ import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnBucket
|
||||
import com.cobblemon.mod.common.api.spawning.detail.SpawnAction
|
||||
import com.cobblemon.mod.common.entity.fishing.PokeRodFishingBobberEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
@@ -73,8 +70,8 @@ interface BobberSpawnPokemonEvent {
|
||||
val bait: ItemStack,
|
||||
val pokemon: PokemonEntity
|
||||
) : BobberSpawnPokemonEvent {
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"chosen_bucket" to ObjectValue(spawnAction.bucket, { it.name }),
|
||||
val context = mutableMapOf(
|
||||
"chosen_bucket" to StringValue(spawnAction.bucket),
|
||||
"bait" to pokemon.level().itemRegistry.wrapAsHolder(bait.item).asMoLangValue(Registries.ITEM),
|
||||
"pokemon_entity" to pokemon.asMoLangValue()
|
||||
)
|
||||
|
||||
+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.events.habitats
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.habitats.spawningstyle.ActivatedHabitatSpawning
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnCause
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.FixedAreaSpawner
|
||||
import com.cobblemon.mod.common.block.habitat.HabitatBlockEntity
|
||||
|
||||
/**
|
||||
* Event that fires when a habitat is about to attempt to spawn Pokémon. Cancelling this event will prevent
|
||||
* the habitat block from attempting to spawn anything for this activation.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since February 15th,2026
|
||||
*/
|
||||
class HabitatSpawnActivatedEvent(
|
||||
/** The habitat block entity that is responsible for the spawn. */
|
||||
val habitatBlockEntity: HabitatBlockEntity,
|
||||
/** The activation settings. You could have got it from the block entity but this is easier. */
|
||||
val activatedHabitatSpawning: ActivatedHabitatSpawning,
|
||||
/** The [SpawnCause] that will be used in the spawn action. This may contain a player that is nearest to the block. */
|
||||
var cause: SpawnCause,
|
||||
/** The maximum number of Pokémon the block will consider spawning (provided there is space). */
|
||||
var maxSpawns: Int
|
||||
) : Cancelable() {
|
||||
/** The spawner representing the habitat. */
|
||||
val spawner: FixedAreaSpawner
|
||||
get() = activatedHabitatSpawning.spawner
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.habitats
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.habitats.dto.HabitatSettingsDTO
|
||||
import com.cobblemon.mod.common.block.habitat.HabitatBlockEntity
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
interface SaveHabitatBlockSettingsEvent {
|
||||
val player: ServerPlayer
|
||||
val world: ServerLevel
|
||||
val blockPos: BlockPos
|
||||
val habitatBlockEntity: HabitatBlockEntity
|
||||
val settings: HabitatSettingsDTO
|
||||
|
||||
class Pre(
|
||||
override val player: ServerPlayer,
|
||||
override val world: ServerLevel,
|
||||
override val blockPos: BlockPos,
|
||||
override val habitatBlockEntity: HabitatBlockEntity,
|
||||
override val settings: HabitatSettingsDTO
|
||||
) : SaveHabitatBlockSettingsEvent, Cancelable()
|
||||
|
||||
class Post(
|
||||
override val player: ServerPlayer,
|
||||
override val world: ServerLevel,
|
||||
override val blockPos: BlockPos,
|
||||
override val habitatBlockEntity: HabitatBlockEntity,
|
||||
override val settings: HabitatSettingsDTO
|
||||
) : SaveHabitatBlockSettingsEvent
|
||||
}
|
||||
@@ -68,11 +68,14 @@ class SpawnBait(
|
||||
val TYPING = cobblemonResource("typing")
|
||||
val EGG_GROUP = cobblemonResource("egg_group")
|
||||
val SHINY_REROLL = cobblemonResource("shiny_reroll")
|
||||
val MARK_CHANCE = cobblemonResource("mark_chance")
|
||||
val DROPS_REROLL = cobblemonResource("drops_reroll")
|
||||
val HIDDEN_ABILITY_CHANCE = cobblemonResource("ha_chance")
|
||||
val ALPHA_CHANCE = cobblemonResource("alpha_chance")
|
||||
val POKEMON_CHANCE = cobblemonResource("pokemon_chance")
|
||||
val FRIENDSHIP = cobblemonResource("friendship")
|
||||
val RARITY_BUCKET = cobblemonResource("rarity_bucket")
|
||||
val SIZE = cobblemonResource("size")
|
||||
|
||||
fun registerEffect(type: ResourceLocation, effect: (PokemonEntity, Effect) -> Unit) {
|
||||
EFFECT_FUNCTIONS[type] = effect
|
||||
@@ -86,11 +89,14 @@ class SpawnBait(
|
||||
registerEffect(NATURE) { entity, effect -> FishingSpawnCause.alterNatureAttempt(entity, effect) }
|
||||
registerEffect(IV) { entity, effect -> FishingSpawnCause.alterIVAttempt(entity, effect) }
|
||||
registerEffect(SHINY_REROLL) { entity, effect -> FishingSpawnCause.shinyReroll(entity, effect) }
|
||||
registerEffect(MARK_CHANCE) { entity, effect -> FishingSpawnCause.alterMarksAttempt(entity, effect) }
|
||||
registerEffect(DROPS_REROLL) { entity, effect -> FishingSpawnCause.saveDropsReroll(entity, effect) }
|
||||
registerEffect(GENDER_CHANCE) { entity, effect -> FishingSpawnCause.alterGenderAttempt(entity, effect) }
|
||||
registerEffect(LEVEL_RAISE) { entity, effect -> FishingSpawnCause.alterLevelAttempt(entity, effect) }
|
||||
registerEffect(HIDDEN_ABILITY_CHANCE) { entity, _ -> FishingSpawnCause.alterHAAttempt(entity) }
|
||||
registerEffect(ALPHA_CHANCE) { entity, effect -> FishingSpawnCause.alterAlphaAttempt(entity) }
|
||||
registerEffect(FRIENDSHIP) { entity, effect -> FishingSpawnCause.alterFriendshipAttempt(entity, effect) }
|
||||
registerEffect(SIZE) { entity, effect -> FishingSpawnCause.alterSize(entity, effect) }
|
||||
CobblemonEvents.BAIT_EFFECT_REGISTRATION.post(BaitEffectFunctionRegistryEvent()) { event ->
|
||||
event.functions.forEach { (type, function) -> registerEffect(type, function) }
|
||||
}
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.habitats
|
||||
|
||||
import com.cobblemon.mod.common.api.habitats.spawningstyle.ActivatedHabitatSpawning
|
||||
import com.cobblemon.mod.common.api.spawning.detail.SpawnAction
|
||||
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.world.entity.Entity
|
||||
|
||||
/**
|
||||
* Influence added to the activated habitat spawner blocks so that they can track the entity and apply block modifiers.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since February 15th, 2026
|
||||
*/
|
||||
class ActivatedHabitatSpawningInfluence(val activatedHabitatSpawning: ActivatedHabitatSpawning) : SpawningInfluence {
|
||||
override fun affectSpawn(action: SpawnAction<*>, entity: Entity) {
|
||||
if (entity is PokemonEntity) {
|
||||
activatedHabitatSpawning.habitatBlockEntity.modifiers.apply(entity)
|
||||
activatedHabitatSpawning.habitatBlockEntity.spawnedEntityIDs.add(entity.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.habitats
|
||||
|
||||
/**
|
||||
* Controls how habitats change through all the possible phases.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since February 23rd, 2026
|
||||
*/
|
||||
enum class HabitatPhaseOrder {
|
||||
/** Literally in ascending order, 1-2-3-4. */
|
||||
SIMPLE,
|
||||
/** It randomly chooses an order then uses that order predictably. 3-1-4-2-3-1-4-2 for example */
|
||||
FIXED_RANDOM,
|
||||
/** Completely random phase each day. Like, 1-1-2-4-1-2-1-2-4-1-3 */
|
||||
FULL_RANDOM
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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.habitats
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.spawning.detail.PokemonSpawnDetail
|
||||
import com.cobblemon.mod.common.api.spawning.position.SpawnablePosition
|
||||
import com.cobblemon.mod.common.block.habitat.HabitatBlockEntity
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.nbt.Tag
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
/**
|
||||
* A pool of [HabitatSpawn]s. This is filled with [HabitatSpawn]s. The pool is responsible for converting
|
||||
* its spawns into [PokemonSpawnDetail]s.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since February 13th, 2026
|
||||
*/
|
||||
class HabitatPool {
|
||||
companion object {
|
||||
fun default() = HabitatPool().apply {
|
||||
id = ResourceLocation("cobblemon", "custom__default_pool")
|
||||
name = "Custom"
|
||||
}
|
||||
|
||||
fun writePoolToNBT(pool: HabitatPool, nbt: CompoundTag) {
|
||||
nbt.putString(DataKeys.HABITAT_POOL_ID, pool.id.toString())
|
||||
if (pool.id.path.startsWith("custom__")) {
|
||||
nbt.putString(DataKeys.HABITAT_POOL_NAME, pool.name)
|
||||
val spawnsListNBT = ListTag()
|
||||
for (spawn in pool.spawns) {
|
||||
val spawnTag = CompoundTag()
|
||||
spawn.writeToNBT(spawnTag)
|
||||
spawnsListNBT.add(spawnTag)
|
||||
}
|
||||
nbt.put(DataKeys.HABITAT_POOL_SPAWNS, spawnsListNBT)
|
||||
}
|
||||
}
|
||||
|
||||
fun readPoolFromNBT(nbt: CompoundTag): HabitatPool {
|
||||
val poolId = nbt.getString(DataKeys.HABITAT_POOL_ID).asIdentifierDefaultingNamespace()
|
||||
if (nbt.contains(DataKeys.HABITAT_POOL_NAME)) {
|
||||
// It's one that was stored on the block
|
||||
val pool = HabitatPool()
|
||||
pool.id = poolId
|
||||
pool.name = nbt.getString(DataKeys.HABITAT_POOL_NAME)
|
||||
val spawnsListNBT = nbt.getList(DataKeys.HABITAT_POOL_SPAWNS, Tag.TAG_COMPOUND.toInt())
|
||||
val spawns = mutableListOf<HabitatSpawn>()
|
||||
spawnsListNBT.forEach { spawnTag ->
|
||||
try {
|
||||
val spawn = HabitatSpawn().apply { readFromNBT(spawnTag as CompoundTag) }
|
||||
spawns.add(spawn)
|
||||
} catch (_: Exception) {
|
||||
// If there's an error reading a spawn, skip it and log the error.
|
||||
Cobblemon.LOGGER.error("Error reading activated habitat spawn from NBT for habitat block, skipping.")
|
||||
}
|
||||
}
|
||||
pool.spawns = spawns
|
||||
return pool
|
||||
} else {
|
||||
return HabitatPools.habitatPoolsById[poolId] ?: default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lateinit var id: ResourceLocation
|
||||
var name: String = ""
|
||||
var spawns: List<HabitatSpawn> = listOf()
|
||||
|
||||
/** Whether a pool is editable is just down to whether it's not from a datapack. */
|
||||
@Transient
|
||||
var editable: Boolean = false
|
||||
|
||||
fun validate() {
|
||||
for (spawn in spawns) {
|
||||
if (SpawnablePosition.getByName(spawn.spawnablePositionType) == null) {
|
||||
throw IllegalArgumentException("$id mentions non-existent spawnable position type ${spawn.spawnablePositionType} on spawn for ${spawn.species}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createSpawnDetails(habitatBlockEntity: HabitatBlockEntity): List<PokemonSpawnDetail> {
|
||||
return spawns.mapNotNull { it.createSpawnDetail(habitatBlockEntity) }
|
||||
}
|
||||
|
||||
fun getPhaseCount(): Int {
|
||||
return spawns
|
||||
.flatMap { it.phases?.ranges?.flatten() ?: emptySet() }
|
||||
.toSet()
|
||||
.count()
|
||||
.coerceAtLeast(1)
|
||||
}
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(id)
|
||||
buffer.writeUtf(name)
|
||||
buffer.writeCollection(spawns) { _, it -> it.encode(buffer) }
|
||||
}
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
id = buffer.readResourceLocation()
|
||||
name = buffer.readUtf()
|
||||
spawns = buffer.readList { HabitatSpawn().apply { decode(buffer) } }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.habitats
|
||||
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.spawning.IntRanges
|
||||
import com.cobblemon.mod.common.api.spawning.TimeRange
|
||||
import com.cobblemon.mod.common.api.spawning.position.SpawnablePositionType
|
||||
import com.cobblemon.mod.common.pokemon.Species
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IntRangeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IntRangesAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.RegisteredSpawnablePositionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.SpeciesAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.pokemonPropertiesShortAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.fromJson
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import java.io.File
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.world.level.storage.LevelResource
|
||||
|
||||
object HabitatPools : JsonDataRegistry<HabitatPool> {
|
||||
override val id = cobblemonResource("habitat_pools")
|
||||
override val type = PackType.SERVER_DATA
|
||||
override val observable = SimpleObservable<HabitatPools>()
|
||||
override val typeToken: TypeToken<HabitatPool> = TypeToken.get(HabitatPool::class.java)
|
||||
override val resourcePath = "habitat_pools"
|
||||
|
||||
override val gson: Gson = GsonBuilder()
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.registerTypeAdapter(SpawnablePositionType::class.java, RegisteredSpawnablePositionAdapter)
|
||||
.registerTypeAdapter(Species::class.java, SpeciesAdapter)
|
||||
.registerTypeAdapter(IntRange::class.java, IntRangeAdapter)
|
||||
.registerTypeAdapter(TimeRange::class.java, TimeRange.adapter)
|
||||
.registerTypeAdapter(IntRanges::class.java, IntRangesAdapter.basic)
|
||||
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
|
||||
.setPrettyPrinting()
|
||||
.create()
|
||||
|
||||
private val datapacked = mutableMapOf<ResourceLocation, HabitatPool>()
|
||||
private val worldSaved = mutableMapOf<ResourceLocation, HabitatPool>()
|
||||
|
||||
val habitatPoolsById = mutableMapOf<ResourceLocation, HabitatPool>()
|
||||
|
||||
private lateinit var worldSavedPoolsFolder: File
|
||||
|
||||
override fun sync(player: ServerPlayer) {}
|
||||
|
||||
fun onServerLoading(server: MinecraftServer) {
|
||||
worldSavedPoolsFolder = server.getWorldPath(LevelResource.ROOT).resolve("habitat_pools").toFile()
|
||||
if (!worldSavedPoolsFolder.exists()) {
|
||||
return
|
||||
}
|
||||
|
||||
worldSavedPoolsFolder.listFiles { it.endsWith(".json") }.forEach {
|
||||
val identifier = ResourceLocation.parse(it.nameWithoutExtension)
|
||||
val habitat = gson.fromJson<HabitatPool>(it.reader())
|
||||
habitat.id = identifier
|
||||
habitat.validate()
|
||||
habitat.editable = true
|
||||
worldSaved[identifier] = habitat
|
||||
}
|
||||
setupHabitatPoolsById()
|
||||
}
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, HabitatPool>) {
|
||||
datapacked.clear()
|
||||
datapacked.putAll(data)
|
||||
data.entries.forEach { (identifier, habitat) ->
|
||||
habitat.id = identifier
|
||||
habitat.validate()
|
||||
habitat.editable = false
|
||||
}
|
||||
setupHabitatPoolsById()
|
||||
}
|
||||
|
||||
fun setupHabitatPoolsById() {
|
||||
habitatPoolsById.clear()
|
||||
habitatPoolsById.putAll(datapacked)
|
||||
habitatPoolsById.putAll(worldSaved)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* 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.habitats
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.spawning.IntRanges
|
||||
import com.cobblemon.mod.common.api.spawning.TimeRange
|
||||
import com.cobblemon.mod.common.api.spawning.condition.AppendageCondition
|
||||
import com.cobblemon.mod.common.api.spawning.condition.SpawningCondition
|
||||
import com.cobblemon.mod.common.api.spawning.detail.PokemonSpawnDetail
|
||||
import com.cobblemon.mod.common.api.spawning.position.SpawnablePosition
|
||||
import com.cobblemon.mod.common.block.habitat.HabitatBlockEntity
|
||||
import com.cobblemon.mod.common.pokemon.Species
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.adapters.IntRangeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IntRangesAdapter
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.math.intersection
|
||||
import com.cobblemon.mod.common.util.math.intersects
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
/**
|
||||
* A kind of simplified spawn definition for the purposes of spawning from [HabitatBlockEntity] instances.
|
||||
*
|
||||
* These have only a small subset of the properties that a regular [PokemonSpawnDetail] would have to align with the
|
||||
* fact that these are configured from a simple GUI. There are limits to how many properties and conditions could be
|
||||
* exposed in a GUI before it becomes too difficult for the average user to understand what's going on.
|
||||
*
|
||||
* [HabitatSpawn]s are loaded from datapacks as pools of spawns but can also be modified from in-game, though those
|
||||
* made from in-game are stored separately to datapacks. Only non-datapacked habitat spawns can be modified.
|
||||
*
|
||||
* Upon edits to a habitat block, the spawn details are regenerated based off of these definitions.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since February 13th, 2026
|
||||
*/
|
||||
class HabitatSpawn {
|
||||
/** The species that will be spawned. */
|
||||
lateinit var species: Species
|
||||
/** The kind of position the Pokémon will spawn in. Things like "grounded", "seafloor", "fishing". */
|
||||
lateinit var spawnablePositionType: String
|
||||
/** The bucket to spawn from. */
|
||||
var bucket: String = "common"
|
||||
|
||||
/** Selection weight. */
|
||||
var weight: Float = 1F
|
||||
/** The possible levels for this spawn. */
|
||||
var levelRange: IntRange = 1..Int.MAX_VALUE // I can't access the up-to-date config value here.
|
||||
/** Additional modifiers to apply to the Pokémon, such as alolan=true, ability=intimidate, etc. */
|
||||
var modifiers: PokemonProperties? = null
|
||||
/** Which phases of the habitat this spawn will run in. See [HabitatBlockEntity] for more information. */
|
||||
var phases: IntRanges? = null
|
||||
/** The Minecraft time ranges for this spawn. */
|
||||
var timeRange: TimeRange? = null
|
||||
/** The minimum light level that the Pokémon can spawn in. */
|
||||
var minLight: Int? = null
|
||||
/** The maximum light level that the Pokémon can spawn in. */
|
||||
var maxLight: Int? = null
|
||||
|
||||
open fun writeToNBT(nbt: CompoundTag) {
|
||||
nbt.putString(DataKeys.HABITAT_POOL_SPAWN_SPECIES, species.resourceIdentifier.toString())
|
||||
nbt.putString(DataKeys.HABITAT_POOL_SPAWN_POSITION_TYPE, spawnablePositionType)
|
||||
nbt.putFloat(DataKeys.HABITAT_POOL_SPAWN_WEIGHT, weight)
|
||||
nbt.putString(DataKeys.HABITAT_POOL_SPAWN_LEVEL_RANGE, IntRangeAdapter.serialize(levelRange))
|
||||
modifiers?.let { nbt.putString(DataKeys.HABITAT_POOL_SPAWN_MODIFIERS, it.asString()) }
|
||||
phases?.let { nbt.putString(DataKeys.HABITAT_POOL_SPAWN_PHASES, IntRangesAdapter.basic.serialize(it)) }
|
||||
timeRange?.let { nbt.putString(DataKeys.HABITAT_POOL_SPAWN_TIMES, TimeRange.adapter.serialize(it)) }
|
||||
minLight?.let { nbt.putInt(DataKeys.HABITAT_POOL_SPAWN_MIN_LIGHT, it) }
|
||||
maxLight?.let { nbt.putInt(DataKeys.HABITAT_POOL_SPAWN_MAX_LIGHT, it) }
|
||||
nbt.putString(DataKeys.HABITAT_POOL_SPAWN_BUCKET, bucket)
|
||||
}
|
||||
|
||||
open fun readFromNBT(nbt: CompoundTag) {
|
||||
species = PokemonSpecies.getByIdentifier(nbt.getString(DataKeys.HABITAT_POOL_SPAWN_SPECIES).asIdentifierDefaultingNamespace())!!
|
||||
spawnablePositionType = nbt.getString(DataKeys.HABITAT_POOL_SPAWN_POSITION_TYPE)
|
||||
weight = nbt.getFloat(DataKeys.HABITAT_POOL_SPAWN_WEIGHT)
|
||||
levelRange = IntRangeAdapter.deserialize(nbt.getString(DataKeys.HABITAT_POOL_SPAWN_LEVEL_RANGE))
|
||||
modifiers = if (nbt.contains(DataKeys.HABITAT_POOL_SPAWN_MODIFIERS)) PokemonProperties.parse(nbt.getString(DataKeys.HABITAT_POOL_SPAWN_MODIFIERS)) else null
|
||||
phases = if (nbt.contains(DataKeys.HABITAT_POOL_SPAWN_PHASES)) IntRangesAdapter.basic.deserialize(nbt.getString(DataKeys.HABITAT_POOL_SPAWN_PHASES)) else null
|
||||
timeRange = if (nbt.contains(DataKeys.HABITAT_POOL_SPAWN_TIMES)) TimeRange.adapter.deserialize(nbt.getString(DataKeys.HABITAT_POOL_SPAWN_TIMES)) else null
|
||||
minLight = if (nbt.contains(DataKeys.HABITAT_POOL_SPAWN_MIN_LIGHT)) nbt.getInt(DataKeys.HABITAT_POOL_SPAWN_MIN_LIGHT) else null
|
||||
maxLight = if (nbt.contains(DataKeys.HABITAT_POOL_SPAWN_MAX_LIGHT)) nbt.getInt(DataKeys.HABITAT_POOL_SPAWN_MAX_LIGHT) else null
|
||||
bucket = if (nbt.contains(DataKeys.HABITAT_POOL_SPAWN_BUCKET)) nbt.getString(DataKeys.HABITAT_POOL_SPAWN_BUCKET) else "common"
|
||||
}
|
||||
|
||||
open fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(species.resourceIdentifier)
|
||||
buffer.writeUtf(spawnablePositionType)
|
||||
buffer.writeFloat(weight)
|
||||
buffer.writeUtf(IntRangeAdapter.serialize(levelRange))
|
||||
buffer.writeNullable(modifiers) { _, value -> buffer.writeUtf(value.asString()) }
|
||||
buffer.writeNullable(phases) { _, value -> buffer.writeUtf(IntRangesAdapter.basic.serialize(value)) }
|
||||
buffer.writeNullable(timeRange) { _, value -> buffer.writeUtf(TimeRange.adapter.serialize(value)) }
|
||||
buffer.writeNullable(minLight) { _, value -> buffer.writeInt(value) }
|
||||
buffer.writeNullable(maxLight) { _, value -> buffer.writeInt(value) }
|
||||
buffer.writeUtf(bucket)
|
||||
}
|
||||
|
||||
open fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
species = PokemonSpecies.getByIdentifier(buffer.readResourceLocation())!!
|
||||
spawnablePositionType = buffer.readUtf()
|
||||
weight = buffer.readFloat()
|
||||
levelRange = IntRangeAdapter.deserialize(buffer.readUtf())
|
||||
modifiers = buffer.readNullable { _ -> PokemonProperties.parse(buffer.readUtf()) }
|
||||
phases = buffer.readNullable { _ -> IntRangesAdapter.basic.deserialize(buffer.readUtf()) }
|
||||
timeRange = buffer.readNullable { _ -> TimeRange.adapter.deserialize(buffer.readUtf()) }
|
||||
minLight = buffer.readNullable { _ -> buffer.readInt() }
|
||||
maxLight = buffer.readNullable { _ -> buffer.readInt() }
|
||||
bucket = buffer.readUtf()
|
||||
}
|
||||
|
||||
/** Creates the [PokemonSpawnDetail] that will be used in the spawner. This is done per habitat block. */
|
||||
open fun createSpawnDetail(habitatBlockEntity: HabitatBlockEntity): PokemonSpawnDetail? {
|
||||
val spawnDetail = PokemonSpawnDetail()
|
||||
|
||||
// If the habitat block specifies a level range, it restricts how and if this spawn exists
|
||||
if (!levelRange.intersects(habitatBlockEntity.levelRange)) {
|
||||
return null
|
||||
}
|
||||
|
||||
val spawnablePositionType = SpawnablePosition.getByName(this.spawnablePositionType) ?: return null // How'd they get bad data into here
|
||||
|
||||
val levelRange = levelRange.intersection(habitatBlockEntity.levelRange)
|
||||
|
||||
val condition = createCondition(habitatBlockEntity)
|
||||
val properties = modifiers?.copy() ?: PokemonProperties()
|
||||
properties.species = species.resourceIdentifier.path
|
||||
|
||||
spawnDetail.apply {
|
||||
this.id = "habitat_${species.resourceIdentifier}"
|
||||
this.pokemon = properties
|
||||
this.bucket = this@HabitatSpawn.bucket
|
||||
this.weight = this@HabitatSpawn.weight
|
||||
this.levelRange = levelRange
|
||||
this.conditions = mutableListOf(condition)
|
||||
this.spawnablePositionType = spawnablePositionType
|
||||
}
|
||||
|
||||
return spawnDetail
|
||||
}
|
||||
|
||||
fun createCondition(habitatBlockEntity: HabitatBlockEntity): SpawningCondition<*> {
|
||||
val clazz = SpawningCondition.getByName(SpawnablePosition.getByName(this.spawnablePositionType)!!.defaultCondition)!!
|
||||
val condition = clazz.getConstructor().newInstance()
|
||||
condition.timeRange = timeRange
|
||||
condition.minLight = minLight
|
||||
condition.maxLight = maxLight
|
||||
val phases = phases
|
||||
if (phases != null) {
|
||||
condition.appendages.add(PhaseAppendageCondition(habitatBlockEntity, phases))
|
||||
}
|
||||
return condition
|
||||
}
|
||||
|
||||
class PhaseAppendageCondition(val habitatBlockEntity: HabitatBlockEntity, val phases: IntRanges) : AppendageCondition {
|
||||
override fun fits(spawnablePosition: SpawnablePosition) = habitatBlockEntity.currentPhase in phases
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.habitats.dto
|
||||
|
||||
import com.cobblemon.mod.common.api.habitats.spawningstyle.ActivatedHabitatSpawning
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class ActivatedHabitatSettingsDTO() {
|
||||
var chance = 1F
|
||||
var trigger: ActivatedHabitatSpawning.Trigger = ActivatedHabitatSpawning.Trigger.REDSTONE
|
||||
var cancelledNaturalSpawningRange = -1
|
||||
var spawnRange = 16
|
||||
var maxSpawns = -1
|
||||
var maxSpawnsPerActivation = 1
|
||||
|
||||
constructor(activatedHabitatSpawning: ActivatedHabitatSpawning): this() {
|
||||
this.chance = activatedHabitatSpawning.chance
|
||||
this.trigger = activatedHabitatSpawning.trigger
|
||||
this.cancelledNaturalSpawningRange = activatedHabitatSpawning.cancelledNaturalSpawningRange
|
||||
this.spawnRange = activatedHabitatSpawning.spawnRange
|
||||
this.maxSpawns = activatedHabitatSpawning.maxSpawns
|
||||
this.maxSpawnsPerActivation = activatedHabitatSpawning.maxSpawnsPerActivation
|
||||
}
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeFloat(chance)
|
||||
buffer.writeEnum(trigger)
|
||||
buffer.writeInt(cancelledNaturalSpawningRange)
|
||||
buffer.writeInt(spawnRange)
|
||||
buffer.writeInt(maxSpawns)
|
||||
buffer.writeInt(maxSpawnsPerActivation)
|
||||
}
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
this.chance = buffer.readFloat()
|
||||
this.trigger = buffer.readEnum(ActivatedHabitatSpawning.Trigger::class.java)
|
||||
this.cancelledNaturalSpawningRange = buffer.readInt()
|
||||
this.spawnRange = buffer.readInt()
|
||||
this.maxSpawns = buffer.readInt()
|
||||
this.maxSpawnsPerActivation = buffer.readInt()
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.habitats.dto
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.habitats.HabitatPool
|
||||
import com.cobblemon.mod.common.api.habitats.HabitatPools
|
||||
import com.cobblemon.mod.common.api.habitats.HabitatSpawn
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class HabitatPoolSettingsDTO() {
|
||||
lateinit var id: ResourceLocation
|
||||
var isReference = false
|
||||
|
||||
// Below properties are only there when it's not a reference, otherwise the handler will have to look them up from the id
|
||||
var name: String? = null
|
||||
var spawns: MutableList<HabitatSpawn>? = null
|
||||
|
||||
constructor(habitatPool: HabitatPool): this() {
|
||||
this.id = habitatPool.id
|
||||
this.isReference = !id.path.startsWith("custom__")
|
||||
if (!this.isReference) {
|
||||
this.name = habitatPool.name
|
||||
this.spawns = habitatPool.spawns.toMutableList()
|
||||
}
|
||||
}
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(id)
|
||||
buffer.writeBoolean(isReference)
|
||||
if (!isReference) {
|
||||
buffer.writeUtf(name!!)
|
||||
buffer.writeCollection(spawns!!) { _, spawn ->
|
||||
spawn.encode(buffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun decode(
|
||||
buffer: RegistryFriendlyByteBuf
|
||||
) {
|
||||
this.id = buffer.readResourceLocation()
|
||||
this.isReference = buffer.readBoolean()
|
||||
if (!isReference) {
|
||||
this.name = buffer.readUtf()
|
||||
this.spawns = buffer.readList {
|
||||
val spawn = HabitatSpawn()
|
||||
spawn.decode(buffer)
|
||||
spawn
|
||||
}.toMutableList()
|
||||
}
|
||||
}
|
||||
|
||||
fun toHabitatPool(): HabitatPool? {
|
||||
if (isReference) {
|
||||
val pool = HabitatPools.habitatPoolsById[id]
|
||||
if (pool == null) {
|
||||
Cobblemon.LOGGER.error("Could not find habitat pool with id $id")
|
||||
}
|
||||
return pool
|
||||
}
|
||||
val pool = HabitatPool()
|
||||
pool.id = id
|
||||
pool.name = name!!
|
||||
pool.spawns = spawns!!
|
||||
return pool
|
||||
}
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.habitats.dto
|
||||
|
||||
import com.cobblemon.mod.common.api.habitats.HabitatPhaseOrder
|
||||
import com.cobblemon.mod.common.api.habitats.HabitatPool
|
||||
import com.cobblemon.mod.common.api.habitats.spawningstyle.ActivatedHabitatSpawning
|
||||
import com.cobblemon.mod.common.api.habitats.spawningstyle.NaturalHabitatSpawning
|
||||
import com.cobblemon.mod.common.block.habitat.HabitatBlockEntity
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class HabitatSettingsDTO() {
|
||||
var phaseOrder = HabitatPhaseOrder.SIMPLE
|
||||
lateinit var levelRange: IntRange
|
||||
var modifiers: String = ""
|
||||
lateinit var mimicId: ResourceLocation
|
||||
var isActivatedSpawning = false
|
||||
var pool: HabitatPoolSettingsDTO = HabitatPoolSettingsDTO(HabitatPool.default())
|
||||
var activatedSettings: ActivatedHabitatSettingsDTO? = null
|
||||
var naturalSettings: NaturalHabitatSettingsDTO? = null
|
||||
|
||||
constructor(habitatBlockEntity: HabitatBlockEntity) : this() {
|
||||
this.phaseOrder = habitatBlockEntity.phaseOrder
|
||||
this.levelRange = habitatBlockEntity.levelRange
|
||||
this.modifiers = habitatBlockEntity.modifiers.asString()
|
||||
this.mimicId = habitatBlockEntity.mimicId
|
||||
this.pool = HabitatPoolSettingsDTO(habitatBlockEntity.pool)
|
||||
val style = habitatBlockEntity.spawningStyle
|
||||
if (style is ActivatedHabitatSpawning) {
|
||||
this.isActivatedSpawning = true
|
||||
this.activatedSettings = ActivatedHabitatSettingsDTO(style)
|
||||
} else if (style is NaturalHabitatSpawning) {
|
||||
this.naturalSettings = NaturalHabitatSettingsDTO(style)
|
||||
}
|
||||
}
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeEnum(phaseOrder)
|
||||
buffer.writeInt(levelRange.first)
|
||||
buffer.writeInt(levelRange.last)
|
||||
buffer.writeUtf(modifiers)
|
||||
buffer.writeResourceLocation(mimicId)
|
||||
pool.encode(buffer)
|
||||
buffer.writeBoolean(isActivatedSpawning)
|
||||
if (isActivatedSpawning) {
|
||||
activatedSettings?.encode(buffer)
|
||||
} else {
|
||||
naturalSettings?.encode(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
this.phaseOrder = buffer.readEnum(HabitatPhaseOrder::class.java)
|
||||
val levelRangeStart = buffer.readInt()
|
||||
val levelRangeEnd = buffer.readInt()
|
||||
this.levelRange = levelRangeStart..levelRangeEnd
|
||||
this.modifiers = buffer.readUtf()
|
||||
this.mimicId = buffer.readResourceLocation()
|
||||
this.pool = HabitatPoolSettingsDTO()
|
||||
this.pool.decode(buffer)
|
||||
if (buffer.readBoolean()) {
|
||||
this.isActivatedSpawning = true
|
||||
this.naturalSettings = null
|
||||
val activatedSettings = ActivatedHabitatSettingsDTO()
|
||||
activatedSettings.decode(buffer)
|
||||
this.activatedSettings = activatedSettings
|
||||
} else {
|
||||
this.activatedSettings = null
|
||||
val naturalSettings = NaturalHabitatSettingsDTO()
|
||||
naturalSettings.decode(buffer)
|
||||
this.naturalSettings = naturalSettings
|
||||
}
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.habitats.dto
|
||||
|
||||
import com.cobblemon.mod.common.api.habitats.spawningstyle.NaturalHabitatSpawning
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class NaturalHabitatSettingsDTO() {
|
||||
var replaceSpawns = false
|
||||
var rangeOfInfluence = 16
|
||||
|
||||
constructor(naturalHabitatSpawning: NaturalHabitatSpawning): this() {
|
||||
this.replaceSpawns = naturalHabitatSpawning.replaceSpawns
|
||||
this.rangeOfInfluence = naturalHabitatSpawning.rangeOfInfluence
|
||||
}
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeBoolean(replaceSpawns)
|
||||
buffer.writeInt(rangeOfInfluence)
|
||||
}
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf, ) {
|
||||
this.replaceSpawns = buffer.readBoolean()
|
||||
this.rangeOfInfluence = buffer.readInt()
|
||||
}
|
||||
}
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* 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.habitats.spawningstyle
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.habitats.HabitatSpawnActivatedEvent
|
||||
import com.cobblemon.mod.common.api.habitats.ActivatedHabitatSpawningInfluence
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnCause
|
||||
import com.cobblemon.mod.common.api.spawning.detail.SpawnPool
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.FixedAreaSpawner
|
||||
import com.cobblemon.mod.common.block.habitat.HabitatBlockEntity
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
|
||||
/**
|
||||
* A habitat spawning style defined by being triggered by something. The activation trigger, [trigger], is either
|
||||
* a redstone pulse, every tick, or every random tick.
|
||||
*
|
||||
* The spawn details are generated from the pool every time there is some change to the habitat block's settings,
|
||||
* then those spawn details are used for spawning Pokémon when the habitat block is triggered.
|
||||
*
|
||||
* The [chance] property is applied after the trigger logic so that not every activation necessarily results in a spawn
|
||||
* attempt.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since February 14th, 2026
|
||||
*/
|
||||
class ActivatedHabitatSpawning(val habitatBlockEntity: HabitatBlockEntity) : HabitatSpawningStyle {
|
||||
companion object {
|
||||
val TYPE = cobblemonResource("activated")
|
||||
}
|
||||
|
||||
enum class Trigger {
|
||||
/** Requires a redstone pulse. */
|
||||
REDSTONE,
|
||||
/** Tries every tick. */
|
||||
TICK,
|
||||
/** Tries every random tick. */
|
||||
RANDOM_TICK
|
||||
}
|
||||
|
||||
@Transient
|
||||
override val type = TYPE
|
||||
|
||||
/** The chance that an activation by the [trigger] will result in a spawn attempt. The spawn attempt may still fail. */
|
||||
var chance = 1F
|
||||
/** The thing that will activate the habitat block into attempting to spawn something. */
|
||||
var trigger = Trigger.REDSTONE
|
||||
/** What range, in blocks, around the habitat block in which natural spawning will not occur. */
|
||||
var cancelledNaturalSpawningRange = -1
|
||||
/** The range, in blocks, around the habitat block in which spawning will be attempted. */
|
||||
var spawnRange = 16
|
||||
/** The maximum number of Pokémon that can exist from this block's spawning before it pauses. -1 for infinite. */
|
||||
var maxSpawns = -1
|
||||
/** The maximum number of Pokémon that can spawn in a single activation. This will still be capped by [maxSpawns]. */
|
||||
var maxSpawnsPerActivation = 1
|
||||
|
||||
lateinit var spawner: FixedAreaSpawner
|
||||
|
||||
override fun writeToNBT(nbt: CompoundTag) {
|
||||
nbt.putString(DataKeys.HABITAT_SPAWNING_STYLE, type.toString())
|
||||
nbt.putFloat(DataKeys.HABITAT_ACTIVATED_CHANCE, chance)
|
||||
nbt.putString(DataKeys.HABITAT_ACTIVATED_TRIGGER, trigger.name)
|
||||
nbt.putInt(DataKeys.HABITAT_ACTIVATED_CANCEL_RANGE, cancelledNaturalSpawningRange)
|
||||
nbt.putInt(DataKeys.HABITAT_ACTIVATED_SPAWN_RANGE, spawnRange)
|
||||
nbt.putInt(DataKeys.HABITAT_ACTIVATED_MAX_SPAWNS, maxSpawns)
|
||||
nbt.putInt(DataKeys.HABITAT_ACTIVATED_MAX_SPAWNS_PER_ACTIVATION, maxSpawnsPerActivation)
|
||||
}
|
||||
|
||||
override fun readFromNBT(nbt: CompoundTag) {
|
||||
chance = nbt.getFloat(DataKeys.HABITAT_ACTIVATED_CHANCE)
|
||||
trigger = Trigger.valueOf(nbt.getString(DataKeys.HABITAT_ACTIVATED_TRIGGER) ?: Trigger.REDSTONE.name)
|
||||
cancelledNaturalSpawningRange = nbt.getInt(DataKeys.HABITAT_ACTIVATED_CANCEL_RANGE)
|
||||
spawnRange = nbt.getInt(DataKeys.HABITAT_ACTIVATED_SPAWN_RANGE)
|
||||
maxSpawns = nbt.getInt(DataKeys.HABITAT_ACTIVATED_MAX_SPAWNS)
|
||||
maxSpawnsPerActivation = nbt.getInt(DataKeys.HABITAT_ACTIVATED_MAX_SPAWNS_PER_ACTIVATION)
|
||||
}
|
||||
|
||||
fun generateSpawnDetails(world: ServerLevel, pos: BlockPos) {
|
||||
spawner = FixedAreaSpawner(
|
||||
name = "habitat_spawner_$pos",
|
||||
world = world,
|
||||
position = pos,
|
||||
spawnPool = SpawnPool("habitat_block").also {
|
||||
it.details.addAll(habitatBlockEntity.spawnDetails)
|
||||
it.precalculate()
|
||||
},
|
||||
buckets = Cobblemon.bestSpawner.config.activatedHabitatBuckets,
|
||||
maxPokemonPerChunk = 16F,
|
||||
verticalRadius = spawnRange,
|
||||
horizontalRadius = spawnRange
|
||||
)
|
||||
spawner.influences.add(ActivatedHabitatSpawningInfluence(this))
|
||||
}
|
||||
|
||||
fun activate(world: ServerLevel, pos: BlockPos) {
|
||||
// Check if the spawn attempt should even happen based on chance.
|
||||
if (chance < 1F && world.random.nextFloat() >= chance) {
|
||||
return
|
||||
} else if (habitatBlockEntity.spawnDetails.isEmpty()) {
|
||||
// If there are no spawn details, then there's no point in trying to spawn anything.
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the max spawns has been reached.
|
||||
if (maxSpawns != -1) {
|
||||
val existingSpawns = habitatBlockEntity.spawnedEntityIDs.size
|
||||
if (existingSpawns >= maxSpawns) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
val cause = SpawnCause(
|
||||
spawner = spawner,
|
||||
entity = world.getNearestPlayer(
|
||||
pos.x.toDouble(),
|
||||
pos.y.toDouble(),
|
||||
pos.z.toDouble(),
|
||||
64.0,
|
||||
true
|
||||
)
|
||||
)
|
||||
|
||||
val remainingUntilMaxSpawns = if (maxSpawns == -1) Int.MAX_VALUE else maxSpawns - habitatBlockEntity.spawnedEntityIDs.size
|
||||
val maxSpawnsForActivation = if (maxSpawnsPerActivation == -1) Int.MAX_VALUE else maxSpawnsPerActivation
|
||||
val maxSpawns = minOf(remainingUntilMaxSpawns, maxSpawnsForActivation)
|
||||
|
||||
val event = HabitatSpawnActivatedEvent(
|
||||
habitatBlockEntity = habitatBlockEntity,
|
||||
activatedHabitatSpawning = this,
|
||||
cause = cause,
|
||||
maxSpawns = maxSpawns
|
||||
)
|
||||
|
||||
CobblemonEvents.HABITAT_SPAWN_ACTIVATED.postThen(event = event) {
|
||||
spawner.run(
|
||||
cause = event.cause,
|
||||
maxSpawns = event.maxSpawns
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.habitats.spawningstyle
|
||||
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
/**
|
||||
* Holds habitat block specific details about the methodology behind how the habitat block will spawn Pokémon. This is
|
||||
* either an [ActivatedHabitatSpawning] or a [NaturalHabitatSpawning].
|
||||
*
|
||||
* @see ActivatedHabitatSpawning
|
||||
* @see NaturalHabitatSpawning
|
||||
* @author Hiroku
|
||||
* @since February 14th, 2026
|
||||
*/
|
||||
sealed interface HabitatSpawningStyle {
|
||||
val type: ResourceLocation
|
||||
|
||||
fun writeToNBT(nbt: CompoundTag)
|
||||
fun readFromNBT(nbt: CompoundTag)
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.habitats.spawningstyle
|
||||
|
||||
import com.cobblemon.mod.common.block.habitat.HabitatBlockEntity
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
/**
|
||||
* A habitat spawning style defined by tapping into regular spawning methods. This works by adding to the spawn list
|
||||
* for spawning that's occurring nearby. When [replaceSpawns] is set to true, the original spawns will be
|
||||
* removed completely in favour of the spawns provided in this habitat's pool.
|
||||
*
|
||||
* The spawn details are generated from the pool every time there is some change to the habitat block's settings,
|
||||
* then those spawn details are used for spawning Pokémon when world spawning is occurring nearby.
|
||||
*
|
||||
* Whether or not this interactions with overworld or fishing spawns is determined by whether the habitat pool has
|
||||
* overworld or fishing spawns respectively.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since February 22nd, 2026
|
||||
*/
|
||||
class NaturalHabitatSpawning(val habitatBlockEntity: HabitatBlockEntity) : HabitatSpawningStyle {
|
||||
companion object {
|
||||
val TYPE = cobblemonResource("natural")
|
||||
}
|
||||
|
||||
@Transient
|
||||
override val type: ResourceLocation = TYPE
|
||||
|
||||
var replaceSpawns = false
|
||||
var rangeOfInfluence = 16
|
||||
|
||||
@Transient
|
||||
var affectsFishing = false
|
||||
@Transient
|
||||
var affectsOverworld = false
|
||||
|
||||
fun generateSpawnDetails() {
|
||||
affectsFishing = habitatBlockEntity.spawnDetails.any { it.spawnablePositionType.name == "fishing" }
|
||||
affectsOverworld = habitatBlockEntity.spawnDetails.any { it.spawnablePositionType.name != "fishing" }
|
||||
}
|
||||
|
||||
override fun writeToNBT(nbt: CompoundTag) {
|
||||
nbt.putBoolean(DataKeys.HABITAT_NATURAL_REPLACE_SPAWNS, replaceSpawns)
|
||||
nbt.putInt(DataKeys.HABITAT_NATURAL_RANGE_OF_INFLUENCE, rangeOfInfluence)
|
||||
}
|
||||
|
||||
override fun readFromNBT(nbt: CompoundTag) {
|
||||
replaceSpawns = nbt.getBoolean(DataKeys.HABITAT_NATURAL_REPLACE_SPAWNS)
|
||||
rangeOfInfluence = nbt.getInt(DataKeys.HABITAT_NATURAL_RANGE_OF_INFLUENCE)
|
||||
}
|
||||
}
|
||||
+26
-23
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.interaction
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
@@ -29,6 +30,11 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.util.LowerCaseEnumTypeAdapterFactory
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.level.biome.Biome
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.levelgen.structure.Structure
|
||||
import net.minecraft.world.level.material.Fluid
|
||||
|
||||
object PokemonInteractions : JsonDataRegistry<PokemonInteractionSet> {
|
||||
override val id = cobblemonResource("pokemon_interactions")
|
||||
@@ -43,45 +49,42 @@ object PokemonInteractions : JsonDataRegistry<PokemonInteractionSet> {
|
||||
.registerTypeAdapter(Requirement::class.java, CobblemonRequirementAdapter)
|
||||
.registerTypeAdapter(InteractionEffect::class.java, InteractionEffectAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, BiomeLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Block::class.java).type, BlockLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Structure::class.java).type, StructureLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Fluid::class.java).type, FluidLikeConditionAdapter)
|
||||
.registerTypeAdapter(IntRange::class.java, IntRangeAdapter)
|
||||
.registerTypeAdapterFactory(LowerCaseEnumTypeAdapterFactory())
|
||||
.setPrettyPrinting()
|
||||
.create()
|
||||
|
||||
val speciesInteractions = mutableListOf<PokemonInteractionSet>()
|
||||
val generalInteractions = mutableListOf<PokemonInteractionSet>()
|
||||
val interactions = mutableListOf<PokemonInteractionSet>()
|
||||
|
||||
override fun sync(player: ServerPlayer) {
|
||||
PokemonInteractionsSyncPacket(
|
||||
speciesInteractions,
|
||||
generalInteractions,
|
||||
).sendToPlayer(player)
|
||||
PokemonInteractionsSyncPacket(interactions).sendToPlayer(player)
|
||||
}
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, PokemonInteractionSet>) {
|
||||
speciesInteractions.clear()
|
||||
generalInteractions.clear()
|
||||
val split = data.entries.partition { it.value.requirements.any { requirement -> requirement is PokemonPropertiesRequirement && requirement.target.species != null } }
|
||||
speciesInteractions.addAll(split.first.map {it.value})
|
||||
generalInteractions.addAll(split.second.map {it.value})
|
||||
Cobblemon.LOGGER.info("Loaded {} Pokémon interaction sets", data.size)
|
||||
interactions.clear()
|
||||
val split = data.entries
|
||||
.partition {
|
||||
it.value.requirements.any { requirement -> requirement is PokemonPropertiesRequirement && requirement.target.species != null }
|
||||
}
|
||||
|
||||
// Put the species specific interactions first as they take priority
|
||||
interactions.addAll(split.first.map {it.value})
|
||||
interactions.addAll(split.second.map {it.value})
|
||||
|
||||
Cobblemon.LOGGER.info("Loaded {} Pokémon interaction sets", interactions.size)
|
||||
}
|
||||
|
||||
fun findInteraction(pokemon: PokemonEntity): PokemonInteraction? {
|
||||
val setCheck: (PokemonInteractionSet) -> Boolean = { it.requirements.all { req -> req.check(pokemon.pokemon) }}
|
||||
val interactionCheck: (PokemonInteraction) -> Boolean = { it.requirements.all { req -> req.check(pokemon.pokemon) } && !pokemon.pokemon.isOnInteractionCooldown(it.grouping) }
|
||||
// species-specific interactions take priority
|
||||
val validInteractions = speciesInteractions
|
||||
return interactions
|
||||
.filter(setCheck)
|
||||
.flatMap { it.interactions }
|
||||
.filter(interactionCheck)
|
||||
.toMutableList()
|
||||
if (validInteractions.isEmpty()) { // if all species-specific interactions are absent/on cooldown, fallback to more generic ones
|
||||
validInteractions.addAll(generalInteractions.filter(setCheck).flatMap { it.interactions }
|
||||
.filter(interactionCheck)
|
||||
)
|
||||
}
|
||||
|
||||
return validInteractions.randomOrNull()
|
||||
.firstOrNull(interactionCheck)
|
||||
}
|
||||
}
|
||||
+30
-18
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
|
||||
import com.cobblemon.mod.common.pokemon.adapters.CobblemonRequirementAdapter
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
@@ -42,27 +43,23 @@ data class PokemonInteractionSet(
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: FriendlyByteBuf): PokemonInteractionSet {
|
||||
val requirements = buffer.readList { it ->
|
||||
CobblemonRequirementAdapter.decode(it)
|
||||
}
|
||||
val interactions = buffer.readList { it ->
|
||||
PokemonInteraction.decode(it)
|
||||
}
|
||||
|
||||
return PokemonInteractionSet(
|
||||
requirements,
|
||||
interactions,
|
||||
)
|
||||
val requirements = buffer.readList(CobblemonRequirementAdapter::decode)
|
||||
val interactions = buffer.readList(PokemonInteraction::decode)
|
||||
return PokemonInteractionSet(requirements, interactions)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class PokemonInteraction(
|
||||
val grouping: ResourceLocation,
|
||||
val requirements: List<Requirement> = listOf(),
|
||||
val effects: List<InteractionEffect> = listOf(),
|
||||
val cooldown: ExpressionLike = "0".asExpressionLike()
|
||||
) {
|
||||
// Not put as a necessary constructor parameter because then there isn't a default constructor
|
||||
// and that means Gson just gives null for everything in the constructor and falls back to the JSON
|
||||
// properties - completely ignoring the default values above.
|
||||
lateinit var grouping: ResourceLocation
|
||||
|
||||
fun encode(buffer: FriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(grouping)
|
||||
buffer.writeCollection(requirements) { it, requirement ->
|
||||
@@ -83,11 +80,12 @@ data class PokemonInteraction(
|
||||
val cooldown = buffer.readExpressionLike()
|
||||
|
||||
return PokemonInteraction(
|
||||
grouping,
|
||||
requirements,
|
||||
effects,
|
||||
cooldown,
|
||||
)
|
||||
).also {
|
||||
it.grouping = grouping
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,11 +141,12 @@ class GiveItemEffect(val item: ResourceLocation, val amount: IntRange?) : Intera
|
||||
class PlaySoundEffect(
|
||||
val sound: ResourceLocation,
|
||||
val soundSource: SoundSource?,
|
||||
val playAround: Boolean = true,
|
||||
val distance: Double = 64.0,
|
||||
val volume: Float = 1.0F,
|
||||
val pitch: Float = 1.0F
|
||||
@SerializedName("playAround") private val _playAround: Boolean?,
|
||||
@SerializedName("distance") private val _distance: Double?,
|
||||
@SerializedName("volume") private val _volume: Float?,
|
||||
@SerializedName("pitch") private val _pitch: Float?,
|
||||
) : InteractionEffect {
|
||||
|
||||
override fun applyEffect(
|
||||
pokemon: PokemonEntity,
|
||||
player: ServerPlayer
|
||||
@@ -161,6 +160,7 @@ class PlaySoundEffect(
|
||||
volume,
|
||||
pitch
|
||||
)
|
||||
|
||||
if (playAround) {
|
||||
packet.sendToPlayersAround(pokemon.x, pokemon.y, pokemon.z, distance, pokemon.level().dimension())
|
||||
} else {
|
||||
@@ -168,6 +168,18 @@ class PlaySoundEffect(
|
||||
}
|
||||
}
|
||||
|
||||
val playAround: Boolean
|
||||
get() = _playAround != false
|
||||
|
||||
val distance: Double
|
||||
get() = _distance ?: 64.0
|
||||
|
||||
val volume: Float
|
||||
get() = _volume ?: 1.0F
|
||||
|
||||
val pitch: Float
|
||||
get() = _pitch ?: 1.0F
|
||||
|
||||
companion object {
|
||||
val ID = "play_sound"
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ import net.minecraft.world.phys.AABB
|
||||
* @since July 29th, 2023
|
||||
*/
|
||||
interface PokemonSelectingItem {
|
||||
fun use(player: ServerPlayer, stack: ItemStack): InteractionResultHolder<ItemStack> {
|
||||
fun use(player: ServerPlayer, stack: ItemStack, ignoreShift: Boolean = false): InteractionResultHolder<ItemStack> {
|
||||
val range = player.entityInteractionRange()
|
||||
val entity = player.level()
|
||||
.getEntities(player, AABB.ofSize(player.position(), range, range, range))
|
||||
@@ -60,7 +60,7 @@ interface PokemonSelectingItem {
|
||||
return interactWithSpecificBattle(player, stack, battlePokemon)
|
||||
}
|
||||
} ?: run {
|
||||
if (!player.isShiftKeyDown) {
|
||||
if (ignoreShift || !player.isShiftKeyDown) {
|
||||
return if (entity != null) {
|
||||
val pokemon = entity.pokemon
|
||||
if (entity.ownerUUID == player.uuid) {
|
||||
|
||||
@@ -27,7 +27,9 @@ class Mark(
|
||||
val replace: List<ResourceLocation>?,
|
||||
val group: String?,
|
||||
val chance: Float = 0F,
|
||||
val indexNumber: Int?
|
||||
val indexNumber: Int?,
|
||||
val aspects: List<String>?,
|
||||
val sortOrder: Int = 0,
|
||||
): StringRepresentable {
|
||||
|
||||
companion object {
|
||||
@@ -42,7 +44,9 @@ class Mark(
|
||||
buffer.readNullable { buffer.readList { buffer.readResourceLocation() } },
|
||||
buffer.readNullable { buffer.readString() },
|
||||
buffer.readFloat(),
|
||||
buffer.readNullable { buffer.readInt() }
|
||||
buffer.readNullable { buffer.readInt() },
|
||||
buffer.readNullable { buffer.readList { buffer.readString() } },
|
||||
buffer.readInt(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -83,5 +87,7 @@ class Mark(
|
||||
buffer.writeNullable(group) { _, v -> buffer.writeString(v) }
|
||||
buffer.writeFloat(chance)
|
||||
buffer.writeNullable(indexNumber) { _, v -> buffer.writeInt(v) }
|
||||
buffer.writeNullable(aspects) { _, v -> buffer.writeCollection(v) { _, aspect -> buffer.writeString(aspect) } }
|
||||
buffer.writeInt(sortOrder)
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+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.molang.function
|
||||
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
|
||||
|
||||
/**
|
||||
* Abstract MoLang function holder
|
||||
* Effectively allows to attach molang functions to almost anything by extending it
|
||||
*
|
||||
* @sample BattleActorMoLangFunctions
|
||||
* @author Gito
|
||||
*/
|
||||
abstract class AbstractMoLangFunctionHolder<T> {
|
||||
val custom: MutableList<(T) -> Map<String, (MoParams) -> Any>> = mutableListOf()
|
||||
|
||||
protected abstract fun T.moLangFunctions(): MutableMap<String, (MoParams) -> Any>
|
||||
|
||||
fun attach(value: T): Map<String, (MoParams) -> Any> {
|
||||
return value.moLangFunctions().also { functions ->
|
||||
custom.forEach { definition ->
|
||||
functions.putAll(definition(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.molang.function
|
||||
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
|
||||
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
|
||||
import com.cobblemon.mod.common.entity.npc.NPCBattleActor
|
||||
|
||||
|
||||
object BattleActorMoLangFunctions : AbstractMoLangFunctionHolder<BattleActor>() {
|
||||
override fun BattleActor.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
|
||||
val actor = this
|
||||
val map = mutableMapOf<String, (MoParams) -> Any>(
|
||||
"is_npc" to { DoubleValue(actor.type == ActorType.NPC) },
|
||||
"is_player" to { DoubleValue(actor.type == ActorType.PLAYER) },
|
||||
"is_wild" to { DoubleValue(actor.type == ActorType.WILD) }
|
||||
)
|
||||
|
||||
when (actor) {
|
||||
is NPCBattleActor -> {
|
||||
map["npc"] = { actor.entity.struct }
|
||||
}
|
||||
|
||||
is PlayerBattleActor -> {
|
||||
map["player"] = { actor.entity?.asMoLangValue() ?: DoubleValue.ZERO }
|
||||
}
|
||||
|
||||
is PokemonBattleActor -> {
|
||||
map["pokemon"] = { actor.entity?.asMoLangValue() ?: DoubleValue.ZERO }
|
||||
}
|
||||
}
|
||||
|
||||
return map
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.molang.function
|
||||
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
|
||||
import com.cobblemon.mod.common.util.getStringOrNull
|
||||
|
||||
object BattleMessageMoLangFunctions : AbstractMoLangFunctionHolder<BattleMessage>() {
|
||||
override fun BattleMessage.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
|
||||
val battleMessage = this
|
||||
return mutableMapOf(
|
||||
"has_argument_at" to { params ->
|
||||
val index = params.getInt(0)
|
||||
val value = params.getStringOrNull(1) ?: ""
|
||||
DoubleValue(value == battleMessage.argumentAt(index))
|
||||
},
|
||||
"has_argument" to { params ->
|
||||
val argumentName = params.getString(0)
|
||||
val value = params.getStringOrNull(1) ?: ""
|
||||
DoubleValue(value == battleMessage.optionalArgument(argumentName))
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
+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.molang.function
|
||||
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
import java.util.*
|
||||
|
||||
object BattleMoLangFunctions : AbstractMoLangFunctionHolder<PokemonBattle>() {
|
||||
override fun PokemonBattle.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
|
||||
val battle = this
|
||||
return mutableMapOf(
|
||||
"environment" to { battle.runtime.environment },
|
||||
"battle_id" to { StringValue(battle.battleId.toString()) },
|
||||
"battle_type" to { StringValue(battle.format.toString()) },
|
||||
"is_pvn" to { DoubleValue(battle.isPvN) },
|
||||
"is_pvp" to { DoubleValue(battle.isPvP) },
|
||||
"is_pvw" to { DoubleValue(battle.isPvW) },
|
||||
"stop" to { battle.stop() },
|
||||
"actors" to { battle.actors.toList().asArrayValue { it.struct } },
|
||||
"get_actor" to getActor@{ params ->
|
||||
val uuid = UUID.fromString(params.getString(0))
|
||||
val actor = battle.actors.find { it.uuid == uuid } ?: return@getActor DoubleValue.ZERO
|
||||
actor.struct
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.molang.function
|
||||
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import net.minecraft.core.Holder
|
||||
import net.minecraft.world.level.biome.Biome
|
||||
|
||||
object BiomeMoLangFunctions: AbstractMoLangFunctionHolder<Holder<Biome>>() {
|
||||
override fun Holder<Biome>.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
|
||||
return mutableMapOf()
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.molang.function
|
||||
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import net.minecraft.core.Holder
|
||||
import net.minecraft.world.level.block.Block
|
||||
|
||||
object BlockMoLangFunctions: AbstractMoLangFunctionHolder<Holder<Block>>() {
|
||||
override fun Holder<Block>.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
|
||||
return mutableMapOf()
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.molang.function
|
||||
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import net.minecraft.core.Holder
|
||||
import net.minecraft.world.level.dimension.DimensionType
|
||||
|
||||
object DimensionTypeMoLangFunctions : AbstractMoLangFunctionHolder<Holder<DimensionType>>() {
|
||||
override fun Holder<DimensionType>.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
|
||||
return mutableMapOf()
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.molang.function
|
||||
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.drop.DropEntry
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.getOrNull
|
||||
|
||||
object DropEntryMoLangFunctions : AbstractMoLangFunctionHolder<DropEntry>() {
|
||||
override fun DropEntry.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
|
||||
val drop = this
|
||||
val map = mutableMapOf<String, (MoParams) -> Any>()
|
||||
|
||||
map["percentage"] = { DoubleValue(drop.percentage.toDouble()) }
|
||||
map["quantity"] = { DoubleValue(drop.quantity.toDouble()) }
|
||||
map["max_selectable_times"] = { DoubleValue(drop.maxSelectableTimes.toDouble()) }
|
||||
map["can_drop"] = { params ->
|
||||
val pokemon = params.getOrNull<ObjectValue<Pokemon>>(0)?.obj
|
||||
DoubleValue(if (drop.canDrop(pokemon)) 1.0 else 0.0)
|
||||
}
|
||||
return map
|
||||
}
|
||||
}
|
||||
+313
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.molang.function
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.struct.ArrayStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.dialogue.ReferenceDialogueFaceProvider
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asBiomeMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asWorldMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.scheduling.Schedulable
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.entity.MoLangScriptingEntity
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.asResource
|
||||
import com.cobblemon.mod.common.util.asUUID
|
||||
import com.cobblemon.mod.common.util.cloneFrom
|
||||
import com.cobblemon.mod.common.util.effectiveName
|
||||
import com.cobblemon.mod.common.util.getBlockStatesWithPos
|
||||
import com.cobblemon.mod.common.util.getBooleanOrNull
|
||||
import com.cobblemon.mod.common.util.getDoubleOrNull
|
||||
import com.cobblemon.mod.common.util.getIsSubmerged
|
||||
import com.cobblemon.mod.common.util.getOrNull
|
||||
import com.cobblemon.mod.common.util.getStringOrNull
|
||||
import com.cobblemon.mod.common.util.isStandingOn
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
import com.cobblemon.mod.common.util.worldRegistry
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.tags.TagKey
|
||||
import net.minecraft.world.damagesource.DamageSource
|
||||
import net.minecraft.world.damagesource.DamageTypes
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.TamableAnimal
|
||||
import net.minecraft.world.phys.AABB
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import java.util.UUID
|
||||
import kotlin.math.sqrt
|
||||
|
||||
object EntityMoLangFunctions : AbstractMoLangFunctionHolder<Entity>() {
|
||||
override fun Entity.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
|
||||
val thisEntity = this
|
||||
val map = mutableMapOf<String, (MoParams) -> Any>(
|
||||
"uuid" to { StringValue(thisEntity.uuid.toString()) },
|
||||
"name" to { _ -> StringValue(thisEntity.effectiveName().string) },
|
||||
"yaw" to { _ -> DoubleValue(thisEntity.yRot.toDouble()) },
|
||||
"pitch" to { _ -> DoubleValue(thisEntity.xRot.toDouble()) },
|
||||
"x" to { _ -> DoubleValue(thisEntity.x) },
|
||||
"y" to { _ -> DoubleValue(thisEntity.y) },
|
||||
"z" to { _ -> DoubleValue(thisEntity.z) },
|
||||
"velocity_x" to { _ -> DoubleValue(thisEntity.deltaMovement.x) },
|
||||
"velocity_y" to { _ -> DoubleValue(thisEntity.deltaMovement.y) },
|
||||
"velocity_z" to { _ -> DoubleValue(thisEntity.deltaMovement.z) },
|
||||
"width" to { DoubleValue(thisEntity.boundingBox.xsize) },
|
||||
"height" to { DoubleValue(thisEntity.boundingBox.ysize) },
|
||||
"this_size" to { DoubleValue(thisEntity.boundingBox.run { if (xsize > ysize) xsize else ysize }) },
|
||||
"this_width" to { DoubleValue(thisEntity.boundingBox.xsize) },
|
||||
"this_height" to { DoubleValue(thisEntity.boundingBox.ysize) },
|
||||
"id_modulo" to { params -> DoubleValue(thisEntity.uuid.hashCode() % params.getDouble(0)) },
|
||||
"horizontal_velocity" to { _ -> DoubleValue(thisEntity.deltaMovement.horizontalDistance()) },
|
||||
"vertical_velocity" to { DoubleValue(thisEntity.deltaMovement.y) },
|
||||
"is_on_ground" to { _ -> DoubleValue(thisEntity.onGround()) },
|
||||
"world" to { _ -> thisEntity.level().worldRegistry.wrapAsHolder(thisEntity.level()).asWorldMoLangValue() },
|
||||
"biome" to { _ -> thisEntity.level().getBiome(thisEntity.blockPosition()).asBiomeMoLangValue() },
|
||||
"is_passenger" to { DoubleValue(thisEntity.isPassenger) },
|
||||
"discard" to { thisEntity.discard() },
|
||||
"is_sneaking" to { _ -> DoubleValue(thisEntity.isShiftKeyDown) },
|
||||
"is_sprinting" to { _ -> DoubleValue(thisEntity.isSprinting) },
|
||||
"is_in_water" to { _ -> DoubleValue(thisEntity.isUnderWater) },
|
||||
"is_in_rain" to { _ -> DoubleValue(thisEntity.isInWaterOrRain && !thisEntity.isInWater) },
|
||||
"is_touching_water_or_rain" to { _ -> DoubleValue(thisEntity.isInWaterRainOrBubble) },
|
||||
"is_touching_water" to { _ -> DoubleValue(thisEntity.isInWater) },
|
||||
"is_underwater" to { DoubleValue(thisEntity.getIsSubmerged()) },
|
||||
"is_in_lava" to { _ -> DoubleValue(thisEntity.isInLava) },
|
||||
"is_on_fire" to { _ -> DoubleValue(thisEntity.isOnFire) },
|
||||
"is_invisible" to { _ -> DoubleValue(thisEntity.isInvisible) },
|
||||
"is_riding" to { _ -> DoubleValue(thisEntity.isPassenger) },
|
||||
"set_name" to { params ->
|
||||
val name = params.getString(0)
|
||||
thisEntity.customName = name.text()
|
||||
DoubleValue.ONE
|
||||
},
|
||||
"damage" to { params ->
|
||||
val amount = params.getDouble(0)
|
||||
val source = DamageSource(
|
||||
thisEntity.level().registryAccess().registryOrThrow(Registries.DAMAGE_TYPE)
|
||||
.getHolder(DamageTypes.GENERIC).get()
|
||||
)
|
||||
thisEntity.hurt(source, amount.toFloat())
|
||||
},
|
||||
"distance_to_owner" to distanceToOwner@{
|
||||
if (thisEntity !is TamableAnimal) {
|
||||
return@distanceToOwner DoubleValue.ZERO
|
||||
}
|
||||
val owner = thisEntity.owner ?: return@distanceToOwner DoubleValue.ZERO
|
||||
DoubleValue(thisEntity.distanceTo(owner))
|
||||
},
|
||||
"owner" to owner@{
|
||||
if (thisEntity !is TamableAnimal) return@owner DoubleValue.ZERO
|
||||
val owner = thisEntity.owner
|
||||
owner?.asMostSpecificMoLangValue() ?: DoubleValue.ZERO
|
||||
},
|
||||
"delta_movement" to {
|
||||
listOf(thisEntity.deltaMovement.x, thisEntity.deltaMovement.y, thisEntity.deltaMovement.z)
|
||||
.asArrayValue(::DoubleValue)
|
||||
},
|
||||
"tags" to {
|
||||
val tags = thisEntity.tags
|
||||
val array = ArrayStruct(hashMapOf())
|
||||
tags.forEachIndexed { index, tag -> array.setDirectly("$index", StringValue(tag)) }
|
||||
array
|
||||
},
|
||||
"add_tag" to { params ->
|
||||
val tag = params.getString(0)
|
||||
thisEntity.addTag(tag)
|
||||
DoubleValue.ONE
|
||||
},
|
||||
"remove_tag" to { params ->
|
||||
val tag = params.getString(0)
|
||||
thisEntity.removeTag(tag)
|
||||
DoubleValue.ONE
|
||||
},
|
||||
"has_tag" to { params ->
|
||||
val tag = params.getString(0)
|
||||
DoubleValue(thisEntity.tags.contains(tag))
|
||||
},
|
||||
"distance_to_pos" to { params ->
|
||||
val x = params.getDouble(0)
|
||||
val y = params.getDouble(1)
|
||||
val z = params.getDouble(2)
|
||||
DoubleValue(sqrt(thisEntity.distanceToSqr(Vec3(x, y, z))))
|
||||
},
|
||||
"type" to { _ ->
|
||||
thisEntity.registryAccess().registry(Registries.ENTITY_TYPE).get().getKey(thisEntity.type)?.toString()?.let {
|
||||
StringValue(it)
|
||||
} ?: DoubleValue.ZERO
|
||||
},
|
||||
"find_nearby_block" to findNearbyBlock@{ params ->
|
||||
val input = params.getString(0)
|
||||
val isTag = input.contains("#")
|
||||
val type = input.replace("#", "").asIdentifierDefaultingNamespace(namespace = "minecraft")
|
||||
val range = params.getDoubleOrNull(1) ?: 10
|
||||
val blockPos = thisEntity.level().getBlockStatesWithPos(
|
||||
AABB.ofSize(
|
||||
thisEntity.position(),
|
||||
range.toDouble(),
|
||||
range.toDouble(),
|
||||
range.toDouble()
|
||||
)
|
||||
)
|
||||
.filter { blockPosPair ->
|
||||
blockPosPair.first.blockHolder.let {
|
||||
if (isTag) it.`is`(
|
||||
TagKey.create(
|
||||
Registries.BLOCK,
|
||||
type
|
||||
)
|
||||
) else it.`is`(type)
|
||||
}
|
||||
}
|
||||
.minByOrNull { it.second.distSqr(thisEntity.blockPosition()) }
|
||||
?.second
|
||||
if (blockPos != null) {
|
||||
return@findNearbyBlock ArrayStruct(
|
||||
mapOf(
|
||||
"0" to DoubleValue(blockPos.x),
|
||||
"1" to DoubleValue(blockPos.y),
|
||||
"2" to DoubleValue(blockPos.z)
|
||||
)
|
||||
)
|
||||
}
|
||||
return@findNearbyBlock DoubleValue.ZERO
|
||||
},
|
||||
"get_nearby_entities" to { params ->
|
||||
val distance = params.getDouble(0)
|
||||
val entities =
|
||||
thisEntity.level().getEntities(thisEntity, AABB.ofSize(thisEntity.position(), distance, distance, distance))
|
||||
|
||||
entities
|
||||
.filterIsInstance<Entity>()
|
||||
.map { it.asMostSpecificMoLangValue() }
|
||||
.asArrayValue()
|
||||
},
|
||||
"is_standing_on_blocks" to { params ->
|
||||
val depth = params.getDouble(0).toInt()
|
||||
val blockStrings: MutableSet<String> = mutableSetOf()
|
||||
for (blockIndex in 1..<params.params.size) {
|
||||
blockStrings.add(params.getString(blockIndex))
|
||||
}
|
||||
|
||||
if (thisEntity.isStandingOn(blockStrings, depth)) DoubleValue.ONE else DoubleValue.ZERO
|
||||
},
|
||||
|
||||
// q.entity.spawn_bedrock_particles(effect, locator, [player])
|
||||
// sends to everyone nearby or just to the player if they're set.
|
||||
// Locator is necessary even if unused on non-posables.
|
||||
"spawn_bedrock_particles" to { params ->
|
||||
val particle = params.getString(0).asResource()
|
||||
val locator = params.getString(1)
|
||||
val player = params.getOrNull<MoValue>(2)?.let {
|
||||
when (it) {
|
||||
is StringValue -> thisEntity.level().getPlayerByUUID(UUID.fromString(it.value))
|
||||
is ObjectValue<*> -> it.obj
|
||||
else -> null
|
||||
}
|
||||
} as? ServerPlayer
|
||||
|
||||
val packet = SpawnSnowstormEntityParticlePacket(particle, thisEntity.id, listOf(locator))
|
||||
if (player == null) {
|
||||
packet.sendToPlayersAround(thisEntity.x, thisEntity.y, thisEntity.z, 64.0, thisEntity.level().dimension())
|
||||
} else {
|
||||
packet.sendToPlayer(player)
|
||||
}
|
||||
},
|
||||
"make_intangible" to { params ->
|
||||
val intangible = params.getBooleanOrNull(0) ?: true
|
||||
thisEntity.noPhysics = intangible
|
||||
DoubleValue.ONE
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
if (thisEntity is PosableEntity) {
|
||||
map["play_animation"] = playAnimation@{ params ->
|
||||
val animation = params.getString(0)
|
||||
val packet = PlayPosableAnimationPacket(thisEntity.id, setOf(animation), emptyList())
|
||||
val target = params.getStringOrNull(1)
|
||||
if (target != null) {
|
||||
val targetPlayer = if (target.asUUID != null) {
|
||||
thisEntity.level().getPlayerByUUID(target.asUUID!!) as ServerPlayer
|
||||
} else if (thisEntity.level() is ServerLevel) {
|
||||
thisEntity.level().server!!.playerList.getPlayerByName(target)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
if (targetPlayer != null) {
|
||||
packet.sendToPlayer(targetPlayer)
|
||||
return@playAnimation DoubleValue.ONE
|
||||
} else {
|
||||
return@playAnimation DoubleValue.ZERO
|
||||
}
|
||||
} else {
|
||||
packet.sendToPlayersAround(thisEntity.x, thisEntity.y, thisEntity.z, 64.0, thisEntity.level().dimension())
|
||||
return@playAnimation DoubleValue.ONE
|
||||
}
|
||||
}
|
||||
|
||||
map["face"] = { params ->
|
||||
ObjectValue(ReferenceDialogueFaceProvider(thisEntity.id, params.getBooleanOrNull(0) != false))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (thisEntity is Schedulable) {
|
||||
map["run_molang_after"] = { params ->
|
||||
val expression = params.getString(0).asExpressionLike()
|
||||
val delayInSeconds = params.getDouble(1).toFloat()
|
||||
val runtime = MoLangRuntime()
|
||||
runtime.environment.cloneFrom(params.environment)
|
||||
thisEntity.after(delayInSeconds) {
|
||||
runtime.resolve(expression)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (thisEntity is MoLangScriptingEntity) {
|
||||
map["add_callback"] = { params ->
|
||||
val type = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val callback = params.getString(1).asIdentifierDefaultingNamespace()
|
||||
val allowDuplicates = params.getBooleanOrNull(2) ?: false
|
||||
thisEntity.callbacks.addCallback(type, callback, allowDuplicates)
|
||||
}
|
||||
map["remove_callback"] = { params ->
|
||||
val type = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val callback = params.getString(1).asIdentifierDefaultingNamespace()
|
||||
thisEntity.callbacks.removeCallback(type, callback)
|
||||
}
|
||||
map["has_callback"] = { params ->
|
||||
val type = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val callback = params.getString(1).asIdentifierDefaultingNamespace()
|
||||
DoubleValue(callback in (thisEntity.callbacks[type] ?: emptySet()))
|
||||
}
|
||||
map["clear_callbacks"] = { params ->
|
||||
val type = params.getStringOrNull(0)?.asIdentifierDefaultingNamespace()
|
||||
if (type != null) {
|
||||
thisEntity.callbacks[type]?.clear()
|
||||
} else {
|
||||
thisEntity.callbacks.clear()
|
||||
}
|
||||
DoubleValue.ONE
|
||||
}
|
||||
}
|
||||
|
||||
return map
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.molang.function
|
||||
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolution
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.LevelUpEvolution
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.TradeEvolution
|
||||
|
||||
object EvolutionMoLangFunctions : AbstractMoLangFunctionHolder<Evolution>() {
|
||||
override fun Evolution.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
|
||||
val evolution = this
|
||||
val map = hashMapOf<String, (MoParams) -> Any>()
|
||||
|
||||
map["result"] = { evolution.result.asMoLangValue() }
|
||||
map["is_optional"] = { DoubleValue(evolution.optional) }
|
||||
map["consumes_held_item"] = { DoubleValue(evolution.consumeHeldItem) }
|
||||
|
||||
when (evolution) {
|
||||
is LevelUpEvolution -> {
|
||||
map["is_level_up"] = { DoubleValue.ONE }
|
||||
}
|
||||
|
||||
is TradeEvolution -> {
|
||||
map["is_trade"] = { DoubleValue.ONE }
|
||||
}
|
||||
|
||||
is ItemInteractionEvolution -> {
|
||||
map["is_item"] = { DoubleValue.ONE }
|
||||
}
|
||||
}
|
||||
|
||||
return map
|
||||
}
|
||||
}
|
||||
+311
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.molang.function
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.struct.ArrayStruct
|
||||
import com.bedrockk.molang.runtime.struct.ContextStruct
|
||||
import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.Environment
|
||||
import com.cobblemon.mod.common.api.molang.MoLangLoadedFilesCache
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.api.npc.partyproviders.SimplePartyProvider
|
||||
import com.cobblemon.mod.common.api.scheduling.ClientTaskTracker
|
||||
import com.cobblemon.mod.common.api.scheduling.ServerTaskTracker
|
||||
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.WaveFunctions
|
||||
import com.cobblemon.mod.common.pokemon.ai.ObtainableItem
|
||||
import com.cobblemon.mod.common.pokemon.ai.ObtainableItemCondition
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.getDoubleOrNull
|
||||
import com.cobblemon.mod.common.util.getIntOrNull
|
||||
import com.cobblemon.mod.common.util.getOrNull
|
||||
import com.cobblemon.mod.common.util.isInt
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import java.text.ParseException
|
||||
|
||||
object GeneralMoLangFunctions {
|
||||
val holder: HashMap<String, (MoParams) -> Any> = hashMapOf(
|
||||
"print" to { params ->
|
||||
val message = params.get<MoValue>(0).asString()
|
||||
LOGGER.info(message)
|
||||
},
|
||||
"delete_variable" to deleteVar@{ params ->
|
||||
val struct = params.get<VariableStruct>(0)
|
||||
val variable = params.getString(1)
|
||||
struct.map.remove(variable)
|
||||
return@deleteVar DoubleValue.ONE
|
||||
},
|
||||
"delete_variables" to { params ->
|
||||
val struct = params.get<VariableStruct>(0)
|
||||
struct.map.clear()
|
||||
DoubleValue.ONE
|
||||
},
|
||||
"get_variable" to { params ->
|
||||
val struct = params.get<VariableStruct>(0)
|
||||
val variable = params.getString(1)
|
||||
struct.map[variable] ?: DoubleValue.ZERO
|
||||
},
|
||||
"set_variable" to { params ->
|
||||
val struct = params.get<VariableStruct>(0)
|
||||
val variable = params.getString(1)
|
||||
val value = params.get<MoValue>(2)
|
||||
struct.map[variable] = value
|
||||
value
|
||||
},
|
||||
"set_query" to { params ->
|
||||
val variable = params.getString(0)
|
||||
val value = params.get<MoValue>(1)
|
||||
params.environment.query.addFunction(variable) { value }
|
||||
value
|
||||
},
|
||||
"replace" to { params ->
|
||||
val text = params.getString(0)
|
||||
val search = params.getString(1)
|
||||
val replace = params.getString(2)
|
||||
StringValue(text.replace(search, replace))
|
||||
},
|
||||
"is_included" to { params ->
|
||||
val text = params.getString(0)
|
||||
val search = params.getString(1)
|
||||
DoubleValue(text.contains(search))
|
||||
},
|
||||
"to_lower" to { params ->
|
||||
StringValue(params.getString(0).lowercase())
|
||||
},
|
||||
"to_upper" to { params ->
|
||||
StringValue(params.getString(0).uppercase())
|
||||
},
|
||||
"string_length" to { params ->
|
||||
DoubleValue(params.getString(0).length)
|
||||
},
|
||||
"split_string" to { params ->
|
||||
val text = params.getString(0)
|
||||
val delimiter = params.getString(1)
|
||||
val parts = text.split(delimiter).map { StringValue(it) }
|
||||
val struct = ArrayStruct(hashMapOf())
|
||||
parts.forEachIndexed { index, moValue -> struct.setDirectly("$index", moValue) }
|
||||
struct
|
||||
},
|
||||
"is_blank" to { params ->
|
||||
val arg = params.get<MoValue>(0)
|
||||
DoubleValue((arg is StringValue && (arg.value.isBlank() || arg.value.toDoubleOrNull() == 0.0)) || (arg is DoubleValue && arg.value == 0.0))
|
||||
},
|
||||
"run_command" to { params ->
|
||||
val command = params.getString(0)
|
||||
try {
|
||||
server()!!.commands.performPrefixedCommand(server()!!.createCommandSourceStack(), command)
|
||||
} catch (_: NullPointerException) {
|
||||
DoubleValue.ZERO
|
||||
}
|
||||
},
|
||||
"is_int" to { params -> DoubleValue(params.get<MoValue>(0).asString().isInt()) },
|
||||
"is_number" to { params ->
|
||||
DoubleValue(
|
||||
params.get<MoValue>(0).asString().toDoubleOrNull() != null
|
||||
)
|
||||
},
|
||||
"to_number" to { params ->
|
||||
DoubleValue(
|
||||
params.get<MoValue>(0).asString().toDoubleOrNull() ?: 0.0
|
||||
)
|
||||
},
|
||||
"to_int" to { params ->
|
||||
DoubleValue(
|
||||
params.get<MoValue>(0).asString().toIntOrNull() ?: 0
|
||||
)
|
||||
},
|
||||
"to_string" to { params -> StringValue(params.get<MoValue>(0).asString()) },
|
||||
"do_effect_walks" to { _ ->
|
||||
DoubleValue(Cobblemon.config.walkingInBattleAnimations)
|
||||
},
|
||||
"random" to { params ->
|
||||
val options = mutableListOf<MoValue>()
|
||||
var index = 0
|
||||
while (params.contains(index)) {
|
||||
options.add(params.get(index))
|
||||
index++
|
||||
}
|
||||
options.random() // Can throw an exception if they specified no args. They'd be idiots though.
|
||||
},
|
||||
"curve" to { params ->
|
||||
val curveName = params.getString(0)
|
||||
val curve =
|
||||
WaveFunctions.functions[curveName] ?: throw IllegalArgumentException("Unknown curve: $curveName")
|
||||
ObjectValue(curve)
|
||||
},
|
||||
"array" to { params ->
|
||||
val values = params.params
|
||||
val array = ArrayStruct(hashMapOf())
|
||||
values.forEachIndexed { index, moValue -> array.setDirectly("$index", moValue) }
|
||||
array
|
||||
},
|
||||
"length" to { params ->
|
||||
val array = (params.getOrNull<MoValue>(0) as? VariableStruct)
|
||||
if (array == null) {
|
||||
DoubleValue.ZERO
|
||||
} else {
|
||||
DoubleValue(array.map.size.toDouble())
|
||||
}
|
||||
},
|
||||
"append" to { params ->
|
||||
val array = params.get<ArrayStruct>(0)
|
||||
val value = params.get<MoValue>(1)
|
||||
val nextIndex = array.map.size
|
||||
array.setDirectly("$nextIndex", value)
|
||||
array
|
||||
},
|
||||
"insert" to { params ->
|
||||
val array = params.get<ArrayStruct>(0)
|
||||
val index = params.getInt(1)
|
||||
val value = params.get<MoValue>(2)
|
||||
val size = array.map.size
|
||||
|
||||
// Shift elements at and after index up by 1
|
||||
for (i in (size - 1) downTo index) {
|
||||
val current = array.map[i.toString()]
|
||||
if (current != null) {
|
||||
array.map[(i + 1).toString()] = current
|
||||
}
|
||||
}
|
||||
array.map[index.toString()] = value
|
||||
array
|
||||
},
|
||||
"delete" to { params ->
|
||||
val array = params.get<ArrayStruct>(0)
|
||||
val index = params.getInt(1)
|
||||
if (index in 0 until array.map.size) {
|
||||
array.map.remove(index.toString())
|
||||
// Re-index the array to keep keys sequential in numerical order
|
||||
val newMap = hashMapOf<String, MoValue>()
|
||||
array.map.keys.mapNotNull { it.toIntOrNull() }
|
||||
.sorted()
|
||||
.forEachIndexed { i, k -> newMap[i.toString()] = array.map[k.toString()]!! }
|
||||
array.map.clear()
|
||||
array.map.putAll(newMap)
|
||||
}
|
||||
array
|
||||
},
|
||||
"run_script" to { params ->
|
||||
val runtime = MoLangRuntime()
|
||||
runtime.environment.query = params.environment.query
|
||||
runtime.environment.variable = params.environment.variable
|
||||
val args = params.params.subList(1, params.params.size)
|
||||
runtime.environment.context = ContextStruct(
|
||||
(params.environment.context?.map
|
||||
?: emptyMap()) + args.mapIndexed { index, value -> "arg_${index + 1}" to value }.toMap()
|
||||
)
|
||||
val script = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
// store the args in the
|
||||
CobblemonScripts.run(script, runtime) ?: DoubleValue.ZERO
|
||||
},
|
||||
"run_molang" to { params ->
|
||||
val runtime = MoLangRuntime()
|
||||
runtime.environment.query = params.environment.query
|
||||
runtime.environment.variable = params.environment.variable
|
||||
runtime.environment.context = params.environment.context
|
||||
val expression = params.getString(0).asExpressionLike()
|
||||
val delayInSeconds = params.getDoubleOrNull(1)?.toFloat() ?: 0.0f
|
||||
|
||||
fun evaluate(): MoValue {
|
||||
return try {
|
||||
runtime.resolve(expression)
|
||||
} catch (ex: Exception) {
|
||||
LOGGER.warn(
|
||||
"Failed to evaluate MoLang expression${if (delayInSeconds > 0.0f) " (delayed)" else ""}: $expression",
|
||||
ex
|
||||
)
|
||||
DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
|
||||
if (delayInSeconds > 0.0f) {
|
||||
val tracker =
|
||||
if (Cobblemon.implementation.environment() == Environment.SERVER) ServerTaskTracker else ClientTaskTracker
|
||||
tracker.after(delayInSeconds) {
|
||||
evaluate()
|
||||
}
|
||||
DoubleValue.ONE
|
||||
} else {
|
||||
evaluate()
|
||||
}
|
||||
},
|
||||
"system_time_millis" to { _ ->
|
||||
DoubleValue(System.currentTimeMillis())
|
||||
},
|
||||
// the rest of the world use dd/MM/yyyy grow up america (this comment was generated by copilot)
|
||||
"date_local_time" to { _ ->
|
||||
val time = System.currentTimeMillis()
|
||||
val date = java.util.Date(time)
|
||||
val formatted = java.text.SimpleDateFormat("dd/MM/yyyy").format(date)
|
||||
StringValue(formatted)
|
||||
},
|
||||
"date_of" to { params ->
|
||||
val time = params.getDouble(0).toLong()
|
||||
val date = java.util.Date(time)
|
||||
val formatted = java.text.SimpleDateFormat("dd/MM/yyyy").format(date)
|
||||
StringValue(formatted)
|
||||
},
|
||||
"date_is_after" to { params ->
|
||||
val dateA = params.getString(0)
|
||||
val dateB = params.getString(1)
|
||||
val format = java.text.SimpleDateFormat("dd/MM/yyyy")
|
||||
val a = try {
|
||||
format.parse(dateA)
|
||||
} catch (_: ParseException) {
|
||||
throw RuntimeException("Cannot parse date ${dateA}, expected it to be in dd/MM/yyyy format, other provided")
|
||||
}
|
||||
val b = try {
|
||||
format.parse(dateB)
|
||||
} catch (_: ParseException) {
|
||||
throw RuntimeException("Cannot parse date ${dateB}, expected it to be in dd/MM/yyyy format, other provided")
|
||||
}
|
||||
DoubleValue(a.after(b))
|
||||
},
|
||||
"get_move_from_id" to { params ->
|
||||
val moveId = params.getString(0)
|
||||
val moveTemplate = Moves.getByName(moveId)
|
||||
moveTemplate?.struct ?: DoubleValue.ZERO
|
||||
},
|
||||
"create_simple_party_provider" to { _ ->
|
||||
val partyProvider = SimplePartyProvider()
|
||||
partyProvider.struct
|
||||
},
|
||||
"create_pickup_item" to { params ->
|
||||
val item = params.getOrNull<MoValue>(0)?.asString()?.let(ObtainableItemCondition::parseFromString)
|
||||
val pickupPriority = params.getIntOrNull(1) ?: 0
|
||||
val pickupItem = ObtainableItem(item = item, pickupPriority = pickupPriority)
|
||||
pickupItem.struct
|
||||
},
|
||||
"create_itemstack" to { params ->
|
||||
val itemId = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
try {
|
||||
val item = BuiltInRegistries.ITEM.get(itemId)
|
||||
val count = params.getIntOrNull(1) ?: 1
|
||||
val itemStack = ItemStack(item, count)
|
||||
ObjectValue(itemStack)
|
||||
} catch (_: NullPointerException) {
|
||||
LOGGER.error("Cannot create item stack from identifier: $itemId, item with that ID does not exist. Possible typo?")
|
||||
DoubleValue.ZERO
|
||||
}
|
||||
},
|
||||
"file" to { MoLangLoadedFilesCache.struct }
|
||||
)
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.molang.function
|
||||
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.getIntOrNull
|
||||
import net.minecraft.core.RegistryAccess
|
||||
import net.minecraft.core.component.DataComponents
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.tags.TagKey
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper
|
||||
|
||||
object ItemStackMoLangFunctions : AbstractMoLangFunctionHolder<Pair<ItemStack, RegistryAccess>>() {
|
||||
override fun Pair<ItemStack, RegistryAccess>.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
|
||||
val stack = this.first
|
||||
val registryAccess = this.second
|
||||
val itemRegistry = registryAccess.registryOrThrow(Registries.ITEM)
|
||||
val holder = itemRegistry.wrapAsHolder(stack.item)
|
||||
|
||||
val map = hashMapOf<String, (MoParams) -> Any>()
|
||||
map["item"] = { _ -> holder.asMoLangValue(Registries.ITEM) }
|
||||
map["count"] = { _ -> DoubleValue(stack.count.toDouble()) }
|
||||
map["damage_value"] = { _ -> DoubleValue(stack.damageValue) }
|
||||
map["max_damage"] = { _ -> DoubleValue(stack.maxDamage) }
|
||||
map["is_empty"] = { _ -> DoubleValue(stack.isEmpty) }
|
||||
map["shrink"] = { params -> stack.shrink(params.getInt(0)) }
|
||||
map["grow"] = { params -> stack.grow(params.getInt(0)) }
|
||||
map["is_of"] = { params ->
|
||||
DoubleValue(
|
||||
holder.`is`(
|
||||
params.getString(0).asIdentifierDefaultingNamespace()
|
||||
)
|
||||
)
|
||||
}
|
||||
map["is_in"] = { params ->
|
||||
DoubleValue(
|
||||
holder.`is`(
|
||||
TagKey.create(
|
||||
Registries.ITEM,
|
||||
params.getString(0).replace("#", "").asIdentifierDefaultingNamespace()
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
map["is_food"] = { _ -> DoubleValue(stack.has(DataComponents.FOOD)) }
|
||||
map["is_enchanted"] = { _ -> DoubleValue(stack.hasFoil()) }
|
||||
map["has_enchantment"] = put@{ params ->
|
||||
val enchantmentId = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val minLevel = params.getIntOrNull(1) ?: 1
|
||||
val enchantmentRegistry = registryAccess.registryOrThrow(Registries.ENCHANTMENT)
|
||||
val holder =
|
||||
enchantmentRegistry.getHolder(enchantmentId).orElse(null) ?: return@put DoubleValue.ZERO
|
||||
val level = EnchantmentHelper.getItemEnchantmentLevel(holder, stack)
|
||||
return@put DoubleValue(level >= minLevel)
|
||||
}
|
||||
return map
|
||||
}
|
||||
}
|
||||
+278
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.molang.function
|
||||
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.CobblemonBlockPosTracker
|
||||
import com.cobblemon.mod.common.api.ai.CobblemonWanderControl
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.asUUID
|
||||
import com.cobblemon.mod.common.util.getBooleanOrNull
|
||||
import com.cobblemon.mod.common.util.getDoubleOrNull
|
||||
import com.cobblemon.mod.common.util.getIntOrNull
|
||||
import com.cobblemon.mod.common.util.getMemorySafely
|
||||
import com.cobblemon.mod.common.util.hasMemoryFromString
|
||||
import com.cobblemon.mod.common.util.isDoingActivityFromString
|
||||
import com.cobblemon.mod.common.util.isLookingAt
|
||||
import com.cobblemon.mod.common.util.traceEntityCollision
|
||||
import net.minecraft.core.Position
|
||||
import net.minecraft.core.Vec3i
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.world.effect.MobEffectInstance
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.Mob
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.TamableAnimal
|
||||
import net.minecraft.world.entity.ai.behavior.BlockPosTracker
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.memory.MemoryStatus
|
||||
import net.minecraft.world.entity.ai.memory.WalkTarget
|
||||
import net.minecraft.world.entity.animal.Animal
|
||||
import net.minecraft.world.entity.monster.Monster
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.level.ClipContext
|
||||
import net.minecraft.world.level.pathfinder.PathType
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import java.util.*
|
||||
|
||||
object LivingEntityMoLangFunctions : AbstractMoLangFunctionHolder<LivingEntity>() {
|
||||
override fun LivingEntity.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
|
||||
val entity = this
|
||||
val map = mutableMapOf<String, (MoParams) -> Any>()
|
||||
map["is_player"] = { _ -> DoubleValue(entity is Player) }
|
||||
map["is_npc"] = { _ -> DoubleValue(entity is NPCEntity) }
|
||||
map["is_mob"] = { _ -> DoubleValue(entity is Mob) }
|
||||
map["is_pokemon"] = { _ -> DoubleValue(entity is PokemonEntity) }
|
||||
map["is_animal"] = { _ -> DoubleValue(entity is Animal) }
|
||||
map["is_tamable"] = { _ -> DoubleValue(entity is TamableAnimal) }
|
||||
map["is_tamed"] = { _ -> DoubleValue(entity is TamableAnimal && entity.isTame) }
|
||||
map["is_hostile"] = { _ -> DoubleValue(entity is Monster) }
|
||||
map["is_baby"] = { _ -> DoubleValue(entity.isBaby) }
|
||||
map["is_adult"] = { _ -> DoubleValue(!entity.isBaby) }
|
||||
map["remove_effect"] = put@{ params ->
|
||||
val effectId = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val effectHolder = BuiltInRegistries.MOB_EFFECT.getHolder(effectId).orElse(null)
|
||||
if (effectHolder != null) {
|
||||
entity.removeEffect(effectHolder)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
}
|
||||
map["add_effect"] = put@{ params ->
|
||||
val effectId = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val duration = params.getInt(1)
|
||||
val amplifier = params.getIntOrNull(2) ?: 0
|
||||
val ambient = params.getBooleanOrNull(3) ?: false
|
||||
val visible = params.getBooleanOrNull(4) ?: true
|
||||
val effectHolder = BuiltInRegistries.MOB_EFFECT.getHolder(effectId).orElse(null)
|
||||
if (effectHolder != null) {
|
||||
entity.addEffect(MobEffectInstance(effectHolder, duration, amplifier, ambient, visible))
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
}
|
||||
map["has_effect"] = put@{ params ->
|
||||
val effectId = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val effectHolder = BuiltInRegistries.MOB_EFFECT.getHolder(effectId).orElse(null)
|
||||
return@put DoubleValue(if (effectHolder != null) entity.hasEffect(effectHolder) else false)
|
||||
}
|
||||
map["heal"] = { params ->
|
||||
val amount = params.getDouble(0)
|
||||
entity.heal(amount.toFloat())
|
||||
}
|
||||
map["is_looking_at"] = put@{ params ->
|
||||
val targetEntity = params.get<MoValue>(0)
|
||||
val maxDistance = params.getDoubleOrNull(1)?.toFloat() ?: 2.0F
|
||||
|
||||
val entity = if (targetEntity is ObjectValue<*> && targetEntity.obj is Entity) {
|
||||
targetEntity.obj as Entity
|
||||
} else {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
|
||||
return@put DoubleValue(entity.isLookingAt(entity, maxDistance))
|
||||
}
|
||||
map["is_living_entity"] = { DoubleValue.ONE }
|
||||
map["is_flying"] = { _ -> DoubleValue(entity.isFallFlying) }
|
||||
map["is_sleeping"] = { _ -> DoubleValue(entity.isSleeping) }
|
||||
map["health"] = { _ -> DoubleValue(entity.health) }
|
||||
map["max_health"] = { _ -> DoubleValue(entity.maxHealth) }
|
||||
map["look_at_position"] = { params ->
|
||||
val x = params.getDouble(0)
|
||||
val y = params.getDouble(1)
|
||||
val z = params.getDouble(2)
|
||||
val duration = params.getIntOrNull(3) ?: 20
|
||||
val flags = params.params.subList(4, params.params.size).map { it.asString() }
|
||||
val brain = entity.brain
|
||||
brain.setMemoryWithExpiry(
|
||||
MemoryModuleType.LOOK_TARGET,
|
||||
CobblemonBlockPosTracker(Vec3(x, y, z), flags.toSet()),
|
||||
duration.toLong()
|
||||
)
|
||||
}
|
||||
map["get_wander_control_memory"] = put@{
|
||||
val value = entity.brain.getMemorySafely(CobblemonMemories.WANDER_CONTROL).orElse(null)
|
||||
?: CobblemonWanderControl()
|
||||
if (
|
||||
!entity.brain.checkMemory(CobblemonMemories.WANDER_CONTROL, MemoryStatus.VALUE_PRESENT)
|
||||
&& entity.brain.checkMemory(CobblemonMemories.WANDER_CONTROL, MemoryStatus.REGISTERED)
|
||||
) {
|
||||
entity.brain.setMemory(CobblemonMemories.WANDER_CONTROL, value)
|
||||
}
|
||||
return@put value.struct
|
||||
}
|
||||
map["get_position_memory"] = put@{ params ->
|
||||
val id = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val memoryType = BuiltInRegistries.MEMORY_MODULE_TYPE.get(id)
|
||||
if (entity.brain.checkMemory(memoryType, MemoryStatus.VALUE_PRESENT)) {
|
||||
return@put when (val memory = entity.brain.getMemory(memoryType).get()) {
|
||||
is Vec3i -> VariableStruct(
|
||||
mapOf(
|
||||
"x" to DoubleValue(memory.x),
|
||||
"y" to DoubleValue(memory.y),
|
||||
"z" to DoubleValue(memory.z)
|
||||
)
|
||||
)
|
||||
|
||||
is Position -> VariableStruct(
|
||||
mapOf(
|
||||
"x" to DoubleValue(memory.x()),
|
||||
"y" to DoubleValue(memory.y()),
|
||||
"z" to DoubleValue(memory.z())
|
||||
)
|
||||
)
|
||||
|
||||
else -> DoubleValue.ZERO
|
||||
}
|
||||
} else {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
map["set_uuid_memory"] = put@{ params ->
|
||||
val memory = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
.let(BuiltInRegistries.MEMORY_MODULE_TYPE::get) as MemoryModuleType<UUID>
|
||||
val uuid = params.getString(1).asUUID ?: return@put DoubleValue.ZERO
|
||||
val expiry = params.getIntOrNull(2) ?: -1
|
||||
if (expiry != -1) {
|
||||
entity.brain.setMemoryWithExpiry(memory, uuid, expiry.toLong())
|
||||
} else {
|
||||
entity.brain.setMemory(memory, uuid)
|
||||
}
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["erase_memory"] = put@{ params ->
|
||||
val memories = params.params.map { it.asString().asIdentifierDefaultingNamespace() }
|
||||
.map(BuiltInRegistries.MEMORY_MODULE_TYPE::get)
|
||||
memories.forEach { entity.brain.eraseMemory(it) }
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["has_memory_value"] = put@{ params ->
|
||||
for (param in params.params) {
|
||||
if (!entity.hasMemoryFromString(param.asString())) {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["lacks_memory_value"] = put@{ params ->
|
||||
for (param in params.params) {
|
||||
if (entity.hasMemoryFromString(param.asString())) {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["is_doing_activity"] = put@{ params ->
|
||||
for (param in params.params) {
|
||||
if (entity.isDoingActivityFromString(param.asString())) {
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
}
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
map["can_see"] = put@{ params ->
|
||||
val target = params.get<MoValue>(0)
|
||||
val range = params.getDoubleOrNull(1) ?: 32.0
|
||||
if (target is ObjectValue<*>) {
|
||||
val targetEntity = target.obj as? LivingEntity ?: return@put DoubleValue.ZERO
|
||||
val vector = targetEntity.eyePosition.subtract(entity.eyePosition).normalize()
|
||||
val trace = entity.traceEntityCollision(
|
||||
maxDistance = range.toFloat(),
|
||||
stepDistance = 0.1F,
|
||||
direction = vector,
|
||||
entityClass = targetEntity.javaClass,
|
||||
collideBlock = ClipContext.Fluid.NONE
|
||||
)
|
||||
return@put DoubleValue(targetEntity in (trace?.entities ?: emptyList()))
|
||||
} else {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
|
||||
if (entity is PathfinderMob) {
|
||||
map["walk_to"] = { params ->
|
||||
val x = params.getDouble(0)
|
||||
val y = params.getDouble(1)
|
||||
val z = params.getDouble(2)
|
||||
val speedMultiplier = params.getDoubleOrNull(3) ?: 0.35
|
||||
|
||||
if (entity.brain.checkMemory(MemoryModuleType.WALK_TARGET, MemoryStatus.REGISTERED)) {
|
||||
entity.brain.setMemory(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
WalkTarget(Vec3(x, y, z), speedMultiplier.toFloat(), 1)
|
||||
)
|
||||
entity.brain.setMemory(
|
||||
MemoryModuleType.LOOK_TARGET,
|
||||
BlockPosTracker(Vec3(x, y + entity.eyeHeight, z))
|
||||
)
|
||||
} else {
|
||||
entity.navigation.moveTo(x, y, z, speedMultiplier)
|
||||
entity.lookControl.setLookAt(Vec3(x, y + entity.eyeHeight, z))
|
||||
}
|
||||
}
|
||||
|
||||
map["has_walk_target"] = { _ ->
|
||||
DoubleValue(entity.brain.getMemorySafely(MemoryModuleType.WALK_TARGET).isPresent || entity.isPathFinding)
|
||||
}
|
||||
|
||||
map["set_can_float"] = { params ->
|
||||
val canFloat = params.getBooleanOrNull(0) != false
|
||||
entity.navigation.setCanFloat(canFloat)
|
||||
DoubleValue.ONE
|
||||
}
|
||||
|
||||
map["get_pathfinding_malus"] = put@{ params ->
|
||||
val type = PathType.entries.find { it.name == params.getString(0).uppercase() }
|
||||
if (type != null) {
|
||||
return@put DoubleValue(entity.getPathfindingMalus(type))
|
||||
}
|
||||
Cobblemon.LOGGER.error("Unknown pathfinding type: ${params.getString(0)}")
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
map["set_pathfinding_malus"] = put@{ params ->
|
||||
val type = PathType.entries.find { it.name == params.getString(0).uppercase() }
|
||||
val malus = params.getDouble(1).toFloat()
|
||||
if (type != null) {
|
||||
entity.setPathfindingMalus(type, malus)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
Cobblemon.LOGGER.error("Unknown pathfinding type: ${params.getString(0)}")
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
return map
|
||||
}
|
||||
}
|
||||
+272
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.molang.function
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.struct.ArrayStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonActivities
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
|
||||
import com.cobblemon.mod.common.api.moves.animations.NPCProvider
|
||||
import com.cobblemon.mod.common.api.npc.NPCClasses
|
||||
import com.cobblemon.mod.common.api.npc.configuration.interaction.DialogueNPCInteractionConfiguration
|
||||
import com.cobblemon.mod.common.api.npc.configuration.interaction.ScriptNPCInteractionConfiguration
|
||||
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.api.storage.party.NPCPartyStore
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
import com.cobblemon.mod.common.util.asBlockPos
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.asResource
|
||||
import com.cobblemon.mod.common.util.cloneFrom
|
||||
import com.cobblemon.mod.common.util.getBooleanOrNull
|
||||
import com.cobblemon.mod.common.util.getDoubleOrNull
|
||||
import com.cobblemon.mod.common.util.getStringOrNull
|
||||
import com.cobblemon.mod.common.util.withNPCValue
|
||||
import net.minecraft.commands.arguments.EntityAnchorArgument
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.entity.EntityDimensions
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import kotlin.collections.any
|
||||
|
||||
object NPCMoLangFunctions : AbstractMoLangFunctionHolder<NPCEntity>() {
|
||||
override fun NPCEntity.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
|
||||
val npc = this
|
||||
val map = hashMapOf<String, (MoParams) -> Any>()
|
||||
map["class"] = { StringValue(npc.npc.id.toString()) }
|
||||
map["name"] = { StringValue(npc.name.string) }
|
||||
map["level"] = { DoubleValue(npc.level) }
|
||||
map["has_aspect"] = { params -> DoubleValue(npc.aspects.contains(params.getString(0))) }
|
||||
map["in_battle"] = { DoubleValue(npc.isInBattle()) }
|
||||
map["battles"] = {
|
||||
ArrayStruct(npc.battleIds.mapNotNull { BattleRegistry.getBattle(it)?.struct }
|
||||
.mapIndexed { index, value -> "$index" to value }.toMap())
|
||||
}
|
||||
map["stop_battles"] = { _ -> npc.battleIds.forEach { BattleRegistry.getBattle(it)?.stop() } }
|
||||
map["run_script_on_client"] = { params ->
|
||||
val world = npc.level()
|
||||
if (world is ServerLevel) {
|
||||
val script = params.getString(0)
|
||||
val packet = RunPosableMoLangPacket(npc.id, setOf("q.run_script('$script')"))
|
||||
packet.sendToPlayers(world.players().toList())
|
||||
}
|
||||
Unit
|
||||
}
|
||||
map["run_script"] = { params ->
|
||||
val script = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val runtime = MoLangRuntime()
|
||||
runtime.environment.cloneFrom(params.environment)
|
||||
CobblemonScripts.run(script, runtime) ?: DoubleValue(0)
|
||||
}
|
||||
map["set_movable"] = put@{ params ->
|
||||
val movable = params.getBooleanOrNull(0) != false
|
||||
npc.isMovable = movable
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["set_invulnerable"] = put@{ params ->
|
||||
val invulnerable = params.getBooleanOrNull(0) != false
|
||||
npc.isInvulnerable = invulnerable
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["set_leashable"] = put@{ params ->
|
||||
val leashable = params.getBooleanOrNull(0) != false
|
||||
npc.isLeashable = leashable
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["set_allow_projectile_hits"] = put@{ params ->
|
||||
val allowProjectileHits = params.getBooleanOrNull(0) != false
|
||||
npc.allowProjectileHits = allowProjectileHits
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["set_name_tag_visible"] = put@{ params ->
|
||||
val nameTagVisible = params.getBooleanOrNull(0) != false
|
||||
npc.hideNameTag = !nameTagVisible
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["unset_interaction"] = put@{
|
||||
npc.interaction = null
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["set_dialogue_interaction"] = put@{ params ->
|
||||
val dialogue = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
npc.interaction = DialogueNPCInteractionConfiguration().also {
|
||||
it.dialogue = dialogue
|
||||
}
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["set_script_interaction"] = put@{ params ->
|
||||
val script = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
npc.interaction = ScriptNPCInteractionConfiguration().also {
|
||||
it.script = script
|
||||
}
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["set_player_texture"] = put@{ params ->
|
||||
val username = params.getString(0)
|
||||
// Re-applying it would be unnecessarily laggy.
|
||||
if (username == npc.data.map["player_texture_username"]?.asString()) {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
npc.loadTextureFromGameProfileName(username)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["unset_player_texture"] = put@{
|
||||
npc.unloadTexture()
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["set_resource_identifier"] = put@{ params ->
|
||||
val identifier = params.getStringOrNull(0)?.asIdentifierDefaultingNamespace()
|
||||
npc.forcedResourceIdentifier = identifier
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["unset_resource_identifier"] = put@{
|
||||
npc.forcedResourceIdentifier = null
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["set_class"] = put@{ params ->
|
||||
val identifier = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val npcClass = NPCClasses.getByIdentifier(identifier)
|
||||
if (npcClass != null) {
|
||||
npc.npc = npcClass
|
||||
return@put DoubleValue.ONE
|
||||
} else {
|
||||
Cobblemon.LOGGER.error("Unknown NPC class: $identifier")
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
map["set_render_scale"] = put@{ params ->
|
||||
val scale = params.getDouble(0)
|
||||
npc.renderScale = scale.toFloat()
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["render_scale"] = { _ -> DoubleValue(npc.renderScale) }
|
||||
map["set_hitbox_scale"] = put@{ params ->
|
||||
val scale = params.getDouble(0).toFloat()
|
||||
npc.hitboxScale = scale
|
||||
npc.refreshDimensions()
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["hitbox_scale"] = { _ -> DoubleValue(npc.hitboxScale) }
|
||||
map["set_hitbox"] = put@{ params ->
|
||||
if (params.params.isEmpty()) {
|
||||
npc.hitbox = null
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
val width = params.getDouble(0).toFloat()
|
||||
val height = params.getDouble(1).toFloat()
|
||||
val eyeHeight = params.getDoubleOrNull(2)?.toFloat() ?: (height * 0.85F)
|
||||
npc.hitbox = EntityDimensions.scalable(width, height).withEyeHeight(eyeHeight)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["unset_hitbox"] = put@{
|
||||
npc.hitbox = null
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["aspects"] = put@{
|
||||
val aspects = npc.aspects
|
||||
return@put aspects.asArrayValue { StringValue(it) }
|
||||
}
|
||||
map["add_aspect"] = put@{ params ->
|
||||
val aspects = params.params.map { it.asString() }
|
||||
npc.appliedAspects.addAll(aspects)
|
||||
npc.updateAspects()
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["remove_aspect"] = put@{ params ->
|
||||
val aspects = params.params.map { it.asString() }
|
||||
npc.appliedAspects.removeAll(aspects.toSet())
|
||||
npc.updateAspects()
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["party"] = put@{
|
||||
val party = npc.party ?: return@put DoubleValue.ZERO
|
||||
return@put party.asMoLangValue()
|
||||
}
|
||||
map["create_npc_party"] = put@{
|
||||
val party = NPCPartyStore(npc)
|
||||
return@put party.asMoLangValue()
|
||||
}
|
||||
map["set_npc_party"] = { params ->
|
||||
val party = params.get<MoValue>(0)
|
||||
if (party is ObjectValue<*>) {
|
||||
npc.party = party.obj as NPCPartyStore
|
||||
} else {
|
||||
npc.party = null
|
||||
}
|
||||
DoubleValue.ONE
|
||||
}
|
||||
map["run_action_effect"] = put@{ params ->
|
||||
val runtime = MoLangRuntime().setup()
|
||||
runtime.environment.cloneFrom(params.environment)
|
||||
runtime.withNPCValue(value = npc)
|
||||
val actionEffect = ActionEffects.actionEffects[params.getString(0).asIdentifierDefaultingNamespace()]
|
||||
if (actionEffect != null) {
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = actionEffect,
|
||||
providers = mutableListOf(NPCProvider(npc)),
|
||||
runtime = runtime,
|
||||
level = npc.level()
|
||||
)
|
||||
npc.actionEffect = context
|
||||
npc.brain.setMemory(CobblemonMemories.ACTIVE_ACTION_EFFECT, context)
|
||||
npc.brain.setActiveActivityIfPossible(CobblemonActivities.ACTION_EFFECT)
|
||||
actionEffect.run(context).thenRun {
|
||||
val npcActionEffect = npc.brain.getMemory(CobblemonMemories.ACTIVE_ACTION_EFFECT).orElse(null)
|
||||
if (npcActionEffect == context && npc.brain.isActive(CobblemonActivities.ACTION_EFFECT)) {
|
||||
npc.brain.eraseMemory(CobblemonMemories.ACTIVE_ACTION_EFFECT)
|
||||
npc.actionEffect = null
|
||||
}
|
||||
}
|
||||
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
map["put_pokemon_in_healer"] = put@{ params ->
|
||||
val healer = npc.level()
|
||||
.getBlockEntity(params.get<ArrayStruct>(0).asBlockPos(), CobblemonBlockEntities.HEALING_MACHINE)
|
||||
.orElse(null) ?: return@put DoubleValue.ZERO
|
||||
val party = npc.party ?: return@put DoubleValue.ZERO
|
||||
if (healer.canHeal(party)) {
|
||||
healer.activate(npc.uuid, party)
|
||||
return@put DoubleValue.ONE
|
||||
} else {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
map["look_at_position"] = { params ->
|
||||
val pos = Vec3(params.getDouble(0), params.getDouble(1), params.getDouble(2))
|
||||
npc.lookAt(EntityAnchorArgument.Anchor.EYES, pos)
|
||||
}
|
||||
map["environment"] = { _ -> npc.runtime.environment }
|
||||
map["party"] = { npc.party?.struct ?: DoubleValue.ZERO }
|
||||
map["has_party"] = { DoubleValue(npc.party != null) }
|
||||
map["is_npc"] = { DoubleValue.ONE }
|
||||
map["can_battle"] =
|
||||
{ DoubleValue(npc.party?.any { it.currentHealth > 0 } == true || npc.npc.party?.isStatic == false) }
|
||||
map["set_battle_theme"] = put@{ params ->
|
||||
val soundId = params.getString(0).asResource()
|
||||
npc.npc.battleTheme = soundId
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
return map
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.molang.function
|
||||
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.CobblemonUnlockableWallpapers
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.storage.pc.PCPosition
|
||||
import com.cobblemon.mod.common.api.storage.pc.PCStore
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.getBooleanOrNull
|
||||
|
||||
object PCMoLangFunctions : AbstractMoLangFunctionHolder<PCStore>() {
|
||||
override fun PCStore.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
|
||||
val pc = this
|
||||
val map = mutableMapOf<String, (MoParams) -> Any>()
|
||||
|
||||
map["get_pokemon"] = getPokemon@{ params ->
|
||||
val box = params.getInt(0)
|
||||
val slot = params.getInt(1)
|
||||
val pokemon = pc[PCPosition(box, slot)] ?: return@getPokemon DoubleValue.ZERO
|
||||
return@getPokemon pokemon.struct
|
||||
}
|
||||
map["set_pokemon"] = { params ->
|
||||
val box = params.getInt(0)
|
||||
val slot = params.getInt(1)
|
||||
val pokemon = params.get<ObjectValue<Pokemon>>(2).obj
|
||||
pc[PCPosition(box, slot)] = pokemon
|
||||
DoubleValue.ONE
|
||||
}
|
||||
map["resize"] = { params ->
|
||||
val newSize = params.getInt(0)
|
||||
val lockNewSize = params.getBooleanOrNull(1) == true
|
||||
pc.resize(newSize, lockNewSize)
|
||||
DoubleValue.ONE
|
||||
}
|
||||
map["get_box_count"] = { DoubleValue(pc.boxes.size.toDouble()) }
|
||||
map["has_unlocked_wallpaper"] = { params ->
|
||||
val wallpaper = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
DoubleValue(pc.unlockedWallpapers.contains(wallpaper))
|
||||
}
|
||||
map["get_unlocked_wallpapers"] = { pc.unlockedWallpapers.asArrayValue { StringValue(it.toString()) } }
|
||||
map["unlock_wallpaper"] = unlockWallpaper@{
|
||||
val wallpaper = it.getString(0).asIdentifierDefaultingNamespace()
|
||||
val playSound = it.getBooleanOrNull(1) != false
|
||||
CobblemonUnlockableWallpapers.unlockableWallpapers[wallpaper] ?: return@unlockWallpaper DoubleValue.ZERO
|
||||
return@unlockWallpaper DoubleValue(pc.unlockWallpaper(wallpaper, playSound))
|
||||
}
|
||||
|
||||
return map
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.molang.function
|
||||
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
object PartyMoLangFunctions: AbstractMoLangFunctionHolder<PartyStore>() {
|
||||
override fun PartyStore.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
|
||||
val party = this
|
||||
val map = hashMapOf<String, (MoParams) -> Any>()
|
||||
map["get_pokemon"] = getPokemon@{ params ->
|
||||
val index = params.getInt(0)
|
||||
val pokemon = party.get(index) ?: return@getPokemon DoubleValue.ZERO
|
||||
pokemon.struct
|
||||
}
|
||||
map["set_pokemon"] = { params ->
|
||||
val index = params.getInt(0)
|
||||
val pokemon = params.get<ObjectValue<Pokemon>>(1).obj
|
||||
party.set(index, pokemon)
|
||||
DoubleValue.ONE
|
||||
}
|
||||
return map
|
||||
}
|
||||
}
|
||||
+386
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.molang.function
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangEnvironment
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.struct.ArrayStruct
|
||||
import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import com.cobblemon.mod.common.api.dialogue.PlayerDialogueFaceProvider
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.battles.BattleBuilder
|
||||
import com.cobblemon.mod.common.battles.BattleFormat
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMusicPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.activeDialogue
|
||||
import com.cobblemon.mod.common.util.asBlockPos
|
||||
import com.cobblemon.mod.common.util.asResource
|
||||
import com.cobblemon.mod.common.util.asUUID
|
||||
import com.cobblemon.mod.common.util.getBattleState
|
||||
import com.cobblemon.mod.common.util.getBooleanOrNull
|
||||
import com.cobblemon.mod.common.util.getDoubleOrNull
|
||||
import com.cobblemon.mod.common.util.getIntOrNull
|
||||
import com.cobblemon.mod.common.util.getOrNull
|
||||
import com.cobblemon.mod.common.util.getStringOrNull
|
||||
import com.cobblemon.mod.common.util.isInBattle
|
||||
import com.cobblemon.mod.common.util.isInDialogue
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import com.cobblemon.mod.common.util.pc
|
||||
import com.cobblemon.mod.common.util.pokedex
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.GameType
|
||||
import kotlin.collections.iterator
|
||||
|
||||
object PlayerMoLangFunctions : AbstractMoLangFunctionHolder<Player>() {
|
||||
override fun Player.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
|
||||
val player = this
|
||||
val map = mutableMapOf<String, (MoParams) -> Any>()
|
||||
map["username"] = { _ -> StringValue(player.gameProfile.name) }
|
||||
map["uuid"] = { _ -> StringValue(player.gameProfile.id.toString()) }
|
||||
map["main_held_item"] = { _ -> player.mainHandItem.asMoLangValue(player.registryAccess()) }
|
||||
map["off_held_item"] = { _ -> player.offhandItem.asMoLangValue(player.registryAccess()) }
|
||||
map["inventory"] = put@{ _ ->
|
||||
val inventory = player.inventory
|
||||
val items = ArrayStruct(hashMapOf())
|
||||
for (i in 0 until inventory.containerSize) {
|
||||
items.setDirectly("$i", inventory.getItem(i).asMoLangValue(player.registryAccess()))
|
||||
}
|
||||
return@put items
|
||||
}
|
||||
map["has_inventory_space"] = put@{ _ ->
|
||||
val inventory = player.inventory
|
||||
return@put if (inventory.getFreeSlot() != -1) DoubleValue.ONE else DoubleValue.ZERO
|
||||
}
|
||||
map["set_inventory_slot"] = put@{ params ->
|
||||
val slot = params.getInt(0)
|
||||
val inventory = player.inventory
|
||||
if (slot !in 0 until inventory.containerSize) return@put DoubleValue.ZERO
|
||||
|
||||
val value = params.getOrNull<MoValue>(1) ?: return@put DoubleValue.ZERO
|
||||
|
||||
val stack: ItemStack? = when (value) {
|
||||
is ObjectValue<*> -> value.obj as? ItemStack
|
||||
is StringValue -> {
|
||||
val id = ResourceLocation.parse(value.value)
|
||||
val item = player.registryAccess().registryOrThrow(Registries.ITEM).get(id)
|
||||
?: return@put DoubleValue.ZERO
|
||||
ItemStack(item)
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (stack == null) return@put DoubleValue.ZERO
|
||||
|
||||
inventory.setItem(slot, stack)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["give_item"] = put@{ params ->
|
||||
val inventory = player.inventory
|
||||
val freeSlot = inventory.getFreeSlot()
|
||||
val value = params.getOrNull<MoValue>(0) ?: return@put DoubleValue.ZERO
|
||||
val dropIfFull = params.getBooleanOrNull(1) ?: false
|
||||
|
||||
val stack: ItemStack? = when (value) {
|
||||
is ObjectValue<*> -> value.obj as? ItemStack
|
||||
is StringValue -> {
|
||||
val id = ResourceLocation.parse(value.value)
|
||||
val item = player.registryAccess().registryOrThrow(Registries.ITEM).get(id)
|
||||
?: return@put DoubleValue.ZERO
|
||||
ItemStack(item)
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (stack == null) return@put DoubleValue.ZERO
|
||||
|
||||
if (freeSlot == -1) {
|
||||
if (dropIfFull) {
|
||||
player.drop(stack, false)
|
||||
return@put DoubleValue.ONE
|
||||
} else {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
|
||||
inventory.setItem(freeSlot, stack)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["face"] = { params ->
|
||||
ObjectValue(
|
||||
PlayerDialogueFaceProvider(
|
||||
player.uuid,
|
||||
params.getBooleanOrNull(0) != false
|
||||
)
|
||||
)
|
||||
}
|
||||
map["swing_hand"] = { _ -> player.swing(player.usedItemHand) }
|
||||
map["food_level"] = { _ -> DoubleValue(player.foodData.foodLevel) }
|
||||
map["saturation_level"] = { _ -> DoubleValue(player.foodData.saturationLevel) }
|
||||
map["tell"] = { params ->
|
||||
val message = params.getString(0).text()
|
||||
val overlay = params.getBooleanOrNull(1) == true
|
||||
player.displayClientMessage(message, overlay)
|
||||
}
|
||||
map["teleport"] = { params ->
|
||||
val x = params.getDouble(0)
|
||||
val y = params.getDouble(1)
|
||||
val z = params.getDouble(2)
|
||||
val playParticleOptionss = params.getBooleanOrNull(3) ?: false
|
||||
player.randomTeleport(x, y, z, playParticleOptionss)
|
||||
}
|
||||
map["heal"] = { params ->
|
||||
val amount = params.getDoubleOrNull(0) ?: player.maxHealth
|
||||
player.heal(amount.toFloat())
|
||||
}
|
||||
map["environment"] = {
|
||||
val environment = MoLangEnvironment()
|
||||
environment.query = player.asMoLangValue()
|
||||
environment
|
||||
}
|
||||
map["is_player"] = { DoubleValue.ONE }
|
||||
map["riding_pokemon"] = put@{
|
||||
val vehicle = player.vehicle
|
||||
if (vehicle is PokemonEntity) {
|
||||
return@put vehicle.struct
|
||||
} else {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
if (player is ServerPlayer) {
|
||||
map["seen_credits"] = { _ ->
|
||||
DoubleValue(player.seenCredits)
|
||||
}
|
||||
map["is_in_dialogue"] = { _ ->
|
||||
DoubleValue(player.isInDialogue)
|
||||
}
|
||||
map["active_dialogue"] = put@{ _ ->
|
||||
if (player.isInDialogue) {
|
||||
return@put player.activeDialogue?.toMoLangStruct() ?: DoubleValue.ZERO
|
||||
} else {
|
||||
DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
map["is_spectator"] = { DoubleValue(player.isSpectator) }
|
||||
map["is_creative"] = { DoubleValue(player.isCreative) }
|
||||
map["is_survival"] = { DoubleValue(player.gameMode.isSurvival) }
|
||||
map["is_adventure"] = { DoubleValue(player.gameMode.gameModeForPlayer == GameType.ADVENTURE) }
|
||||
map["run_command"] = { params ->
|
||||
val command = params.getString(0)
|
||||
player.server.commands.performPrefixedCommand(player.createCommandSourceStack(), command)
|
||||
}
|
||||
map["set_battle_theme"] = put@{ params ->
|
||||
val soundId = params.getString(0).asResource()
|
||||
Cobblemon.playerDataManager.getGenericData(player).battleTheme = soundId
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["battle_music"] = put@{ params ->
|
||||
val soundId = params.getString(0).asResource()
|
||||
val volume = params.getDoubleOrNull(1)?.toFloat() ?: 1.0f
|
||||
val pitch = params.getDoubleOrNull(2)?.toFloat() ?: 1.0f
|
||||
val restart = params.getBooleanOrNull(3) ?: true
|
||||
|
||||
if (soundId != null) {
|
||||
val packet = BattleMusicPacket(soundId, volume, pitch, restart)
|
||||
packet.sendToPlayer(player)
|
||||
return@put DoubleValue.ONE
|
||||
} else {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
map["stop_battle_music"] = put@{ _ ->
|
||||
val packet = BattleMusicPacket(null)
|
||||
packet.sendToPlayer(player)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["play_sound_on_server"] = { params ->
|
||||
val sound = params.getString(0).asResource()
|
||||
val soundSource = SoundSource.valueOf(params.getString(1).uppercase())
|
||||
val volume = params.getDoubleOrNull(2)?.toFloat() ?: 1.0f
|
||||
val pitch = params.getDoubleOrNull(3)?.toFloat() ?: 1.0f
|
||||
|
||||
val packet =
|
||||
UnvalidatedPlaySoundS2CPacket(sound, soundSource, player.x, player.y, player.z, volume, pitch)
|
||||
packet.sendToPlayer(player)
|
||||
}
|
||||
map["is_party_at_full_health"] = { _ ->
|
||||
DoubleValue(player.party().none(Pokemon::canBeHealed))
|
||||
}
|
||||
map["can_heal_at_healer"] = put@{ params ->
|
||||
val pos = params.get<ArrayStruct>(0).asBlockPos()
|
||||
val healer = player.level().getBlockEntity(pos, CobblemonBlockEntities.HEALING_MACHINE).orElse(null)
|
||||
?: return@put DoubleValue.ZERO
|
||||
val party = player.party()
|
||||
return@put DoubleValue(healer.canHeal(party))
|
||||
}
|
||||
map["put_pokemon_in_healer"] = put@{ params ->
|
||||
val healer = player.level()
|
||||
.getBlockEntity(params.get<ArrayStruct>(0).asBlockPos(), CobblemonBlockEntities.HEALING_MACHINE)
|
||||
.orElse(null) ?: return@put DoubleValue.ZERO
|
||||
val party = player.party()
|
||||
if (healer.canHeal(party)) {
|
||||
healer.activate(player.uuid, party)
|
||||
return@put DoubleValue.ONE
|
||||
} else {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
map["party"] = { player.party().struct }
|
||||
map["pc"] = { player.pc().struct }
|
||||
map["has_permission"] = { params ->
|
||||
DoubleValue(
|
||||
Cobblemon.permissionValidator.hasPermission(
|
||||
player,
|
||||
params.getString(0),
|
||||
params.getIntOrNull(1) ?: 4
|
||||
)
|
||||
)
|
||||
}
|
||||
map["data"] = { params -> Cobblemon.molangData.load(player.uuid, params.getStringOrNull(0)) }
|
||||
map["save_data"] = { params -> Cobblemon.molangData.save(player.uuid, params.getStringOrNull(0)) }
|
||||
map["in_battle"] = { DoubleValue(player.isInBattle()) }
|
||||
map["battle"] = { player.getBattleState()?.first?.struct ?: DoubleValue.ZERO }
|
||||
map["get_npc_data"] = put@{ params ->
|
||||
val npcId = ((params.get<MoValue>(0) as? ObjectValue<*>)?.obj as? NPCEntity)?.stringUUID
|
||||
?: params.getString(0)
|
||||
val data = Cobblemon.molangData.load(player.uuid, params.getStringOrNull(1))
|
||||
if (data.map.containsKey(npcId)) {
|
||||
return@put data.map[npcId]!!
|
||||
} else {
|
||||
val vars = VariableStruct()
|
||||
data.map[npcId] = vars
|
||||
return@put vars
|
||||
}
|
||||
}
|
||||
map["get_npc_variable"] = put@{ params ->
|
||||
val npcId = ((params.get<MoValue>(0) as? ObjectValue<*>)?.obj as? NPCEntity)?.stringUUID
|
||||
?: params.getString(0)
|
||||
val variable = params.getString(1)
|
||||
val data = Cobblemon.molangData.load(player.uuid, params.getStringOrNull(2))
|
||||
if (data.map.containsKey(npcId)) {
|
||||
return@put (data.map[npcId] as VariableStruct).map[variable] ?: DoubleValue.ZERO
|
||||
} else {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
map["set_npc_variable"] = put@{ params ->
|
||||
val npcId = ((params.get<MoValue>(0) as? ObjectValue<*>)?.obj as? NPCEntity)?.stringUUID
|
||||
?: params.getString(0)
|
||||
val variable = params.getString(1)
|
||||
val value = params.get<MoValue>(2)
|
||||
val saveAfterwards = params.getBooleanOrNull(3) != false
|
||||
val path = params.getStringOrNull(4)
|
||||
val data = Cobblemon.molangData.load(player.uuid, path)
|
||||
val npcData = data.map.getOrPut(npcId) { VariableStruct() } as VariableStruct
|
||||
npcData.map[variable] = value
|
||||
if (saveAfterwards) {
|
||||
Cobblemon.molangData.save(player.uuid, path)
|
||||
}
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map["pokedex"] = { player.pokedex().struct }
|
||||
map["has_advancement"] = put@{ params ->
|
||||
val requiredAdvancement = ResourceLocation.parse(params.getString(0))
|
||||
for (entry in player.advancements.progress) {
|
||||
if (entry.key.id == requiredAdvancement && entry.value.isDone) {
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
}
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
map["start_battle"] = put@{ params ->
|
||||
val opponentValue = params.get<MoValue>(0)
|
||||
val opponent = if (opponentValue is ObjectValue<*>) {
|
||||
opponentValue.obj as ServerPlayer
|
||||
} else {
|
||||
val paramString = opponentValue.asString()
|
||||
val playerUUID = paramString.asUUID
|
||||
if (playerUUID != null) {
|
||||
server()?.playerList?.getPlayer(playerUUID) ?: return@put DoubleValue.ZERO
|
||||
} else {
|
||||
server()?.playerList?.getPlayerByName(paramString) ?: return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
val format = params.getStringOrNull(1)
|
||||
?.let(BattleFormat::fromFormatIdentifier)
|
||||
?: BattleFormat.GEN_9_SINGLES
|
||||
|
||||
val setLevel = params.getIntOrNull(2) ?: -1
|
||||
format.adjustLevel = setLevel
|
||||
|
||||
val rules = params.getStringOrNull(5)
|
||||
?.split(",")
|
||||
?.toSet()
|
||||
?: emptySet()
|
||||
|
||||
val modifiedBattleFormat = BattleFormat.setBattleRules(
|
||||
battleFormat = format,
|
||||
rules = rules
|
||||
)
|
||||
|
||||
val cloneParties = (setLevel != -1) || (params.getBooleanOrNull(3) ?: false)
|
||||
val healFirst = params.getBooleanOrNull(4) ?: false
|
||||
|
||||
val battleStartResult = BattleBuilder.pvp1v1(
|
||||
player1 = player,
|
||||
player2 = opponent,
|
||||
battleFormat = modifiedBattleFormat,
|
||||
cloneParties = cloneParties,
|
||||
healFirst = healFirst
|
||||
)
|
||||
var returnValue: MoValue = DoubleValue.ZERO
|
||||
battleStartResult.ifSuccessful { returnValue = it.struct }
|
||||
return@put returnValue
|
||||
}
|
||||
map["get_custom_stat"] = put@{ params ->
|
||||
val statName = params.getString(0)
|
||||
|
||||
val resourceLocation = ResourceLocation.tryParse(statName) ?: return@put DoubleValue.ZERO
|
||||
val statResourceLocation =
|
||||
BuiltInRegistries.CUSTOM_STAT.get(resourceLocation) ?: return@put DoubleValue.ZERO
|
||||
|
||||
val exists = net.minecraft.stats.Stats.CUSTOM.contains(statResourceLocation)
|
||||
if (!exists) return@put DoubleValue.ZERO
|
||||
|
||||
val stat = net.minecraft.stats.Stats.CUSTOM.get(statResourceLocation)
|
||||
val value = player.stats.getValue(stat)
|
||||
|
||||
DoubleValue(value)
|
||||
}
|
||||
map["get_starter_uuid"] = { _ ->
|
||||
Cobblemon.playerDataManager.getGenericData(player).starterUUID?.let {
|
||||
StringValue(
|
||||
it.toString()
|
||||
)
|
||||
} ?: DoubleValue.ZERO
|
||||
}
|
||||
map["has_chosen_starter"] = { _ -> DoubleValue(Cobblemon.playerDataManager.getGenericData(player).starterSelected) }
|
||||
}
|
||||
|
||||
return map
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user