merge from main

This commit is contained in:
petrak@ 2023-02-18 17:21:35 -06:00
commit ca5ccf60f6
228 changed files with 3150 additions and 931 deletions

View file

@ -1,20 +1,25 @@
// 1.19.2 2023-01-22T12:41:02.49644171 Item Models: hexcasting
// 1.19.2 2023-02-17T23:19:00.76285061 Item Models: hexcasting
9af2754cb1e53eeaa85618cf92651b4878cf62b1 assets/hexcasting/models/block/quenched_allay_0.json
de4ff723b4332d4e26bd01f74e0485e28c9a2178 assets/hexcasting/models/block/quenched_allay_1.json
4c29163e07f3a903017e38a9cc102f4b37db20b1 assets/hexcasting/models/block/quenched_allay_2.json
487d34cd8e70b3e468337228b74af5c1b4d14c53 assets/hexcasting/models/block/quenched_allay_3.json
f2156b3a7041cf99891b528393db64c6b9ca1a4f assets/hexcasting/models/item/abacus.json
933059cd7c2dbaff0e643c644c14af0c0e77aa29 assets/hexcasting/models/item/acacia_staff.json
f183fcd384db929bf56e397965057218abc32ddb assets/hexcasting/models/item/acacia_staff.json
19730853397b109cfedd0c3bbda83d5de6cd15b9 assets/hexcasting/models/item/akashic_record.json
8c735feff09d46d00ed681311f46f61a50cfdc9b assets/hexcasting/models/item/amethyst_dust.json
d1b0892de9d751e7bebc763e6407d5285363c851 assets/hexcasting/models/item/artifact.json
7eb3eb776e70eb616c12ada500b9d1d6a3249a6a assets/hexcasting/models/item/artifact_filled.json
82e3be7bbdad92d2b4c728be54d9d2f2809a0ac2 assets/hexcasting/models/item/battery.json
d1310c25bca32980214aa1054eddb1772fb55d12 assets/hexcasting/models/item/birch_staff.json
71acb8ff7f0457c46683c16da339363f39c7ea8b assets/hexcasting/models/item/birch_staff.json
ec7c3a51882a432185fdbb6a449e66165b6a4c4c assets/hexcasting/models/item/charged_amethyst.json
d614c0fd8acb1c18b4211b090d438326d74507f8 assets/hexcasting/models/item/cherry_staff.json
c64ed609ece68994ce23dd2809145040bce13579 assets/hexcasting/models/item/conjured.json
c64ed609ece68994ce23dd2809145040bce13579 assets/hexcasting/models/item/conjured_block.json
c8da4227db3c80e3e2e7f2fb2ae2649656429d68 assets/hexcasting/models/item/creative_unlocker.json
b0ad71595b450f5b9a6bdc2a14fc03afef0b850a assets/hexcasting/models/item/crimson_staff.json
fd00d0c14663804b78911d7aa73606b88e90ef22 assets/hexcasting/models/item/crimson_staff.json
e47acd1d6ef29a3e1941afb1b212bd40b963cb72 assets/hexcasting/models/item/cypher.json
2db55347092ad6bc9e58bc968e88a3b6c5fd77c1 assets/hexcasting/models/item/cypher_filled.json
cfaf12703ca40959bc5bedac4d1c120273704fcf assets/hexcasting/models/item/dark_oak_staff.json
73ded6154a6e2f6929a05c5625372c9e0498db3d assets/hexcasting/models/item/dark_oak_staff.json
113c51af571a92009f5f687a82e10bc5ce97b010 assets/hexcasting/models/item/dye_colorizer_black.json
b5a04716775ba2e1b137abc513025b2f1065e5d1 assets/hexcasting/models/item/dye_colorizer_blue.json
0bb3afbd937b2e07523a581f6e3f389e11078595 assets/hexcasting/models/item/dye_colorizer_brown.json
@ -36,7 +41,7 @@ c9faada6299f388afc2d2798843d2b45159950d1 assets/hexcasting/models/item/edified_d
7f22e012a844cc2c5e30b0fcbdc2e7e4afac1c40 assets/hexcasting/models/item/edified_log.json
6b2c9d4aca0c869d7e18707c22b00c14e1d30f0c assets/hexcasting/models/item/edified_pressure_plate.json
31b4d60ff15a6d6de7aecb6feeba25a366bba2fd assets/hexcasting/models/item/edified_slab.json
ff0e3934116fdae9ecad0d006402868914ab42ec assets/hexcasting/models/item/edified_staff.json
aec5d99a7501bdbe7fd7d4ab3640e726682ef0f1 assets/hexcasting/models/item/edified_staff.json
2584421c2e9e1cdf22a703018b54cf449613d7d9 assets/hexcasting/models/item/edified_stairs.json
ae58c5b7c304d33cbde60caf44a4c4ee4ec1a633 assets/hexcasting/models/item/edified_trapdoor.json
084183e4351973c8165f6f459c0f0dba2463d957 assets/hexcasting/models/item/edified_wood.json
@ -44,11 +49,12 @@ ae58c5b7c304d33cbde60caf44a4c4ee4ec1a633 assets/hexcasting/models/item/edified_t
947d1539d88f9d6fd0afcdf831f4327356d19baf assets/hexcasting/models/item/focus_filled.json
cb2d973af25a2ec07e6094ecc106c896a06918dc assets/hexcasting/models/item/focus_sealed.json
6ec61fea7d8c49cc0c45b64857fd926451b4845f assets/hexcasting/models/item/jeweler_hammer.json
c34501cbfc0bb1b6943b4a9986fbe927ff177c61 assets/hexcasting/models/item/jungle_staff.json
0777d2158566f7389f4becd2fb2c77664de90c6a assets/hexcasting/models/item/jungle_staff.json
abfc028c974a02780aed3d7a5859352503bbd920 assets/hexcasting/models/item/lens.json
a34a6d777ae265c7e49c8bb23c15f04359236544 assets/hexcasting/models/item/lore_fragment.json
371c16c6c882d6d0370135a8953c408fa1658bed assets/hexcasting/models/item/mangrove_staff.json
a17e45161b6723e72c710695a536e39ba0905725 assets/hexcasting/models/item/oak_staff.json
dbd52dd3d429578cc81b8b3142d25f8d84501273 assets/hexcasting/models/item/mangrove_staff.json
b8fe3a6b792c6014831f047d4c40eaae9f939b1b assets/hexcasting/models/item/mindsplice_staff.json
4b65b6848d43cc27adf7e59ebdffd59281fe3937 assets/hexcasting/models/item/oak_staff.json
38d1dc73c49d185b86c098b13611bf3ec07b255c assets/hexcasting/models/item/old_staff.json
82fa0a2bb17e40c0b3f826e97b2e95445ec24ab8 assets/hexcasting/models/item/patchouli_book.json
d69d10e6cb967b98b3294cc86174182c671de671 assets/hexcasting/models/item/phial_large_0.json
@ -82,6 +88,13 @@ d60b723c44183b59cbadfd02a911dab5e89e0e61 assets/hexcasting/models/item/pride_col
6253bab7bd9162f75782c5bc899f46cd941d01ad assets/hexcasting/models/item/pride_colorizer_pansexual.json
c67e74e2a323872c3b34b113df99da8b77a501c6 assets/hexcasting/models/item/pride_colorizer_plural.json
7c4191ec2479b0a67e578da49d459deea8294ec4 assets/hexcasting/models/item/pride_colorizer_transgender.json
5038e069909e2dcf8664bcde81b229c8e27191ae assets/hexcasting/models/item/quenched_allay.json
a8859c93236b88f9ed46a4957f5723965ce04e03 assets/hexcasting/models/item/quenched_allay_shard.json
8105007d186fe2c6bea6958dd85d1b2ed3cecb58 assets/hexcasting/models/item/quenched_shard_0.json
aef7d4b759bcc8a1d5b886b8a0170657e447a8d8 assets/hexcasting/models/item/quenched_shard_1.json
4a08374ef00de51381df9659488cb305e7c8674f assets/hexcasting/models/item/quenched_shard_2.json
181aac0f66e5c3937f49da3f5d577f1c8045c635 assets/hexcasting/models/item/quenched_shard_3.json
628df1d43bb959bd7424253d2cf367947e147155 assets/hexcasting/models/item/quenched_staff.json
1ac1d158da25a8f8ec4b8771445d1ec9d42e9519 assets/hexcasting/models/item/scroll.json
ae2a8b6eb8a4ef17926e20c6982bc01120ff32b7 assets/hexcasting/models/item/scroll_ancient_large.json
7478e4b91169a3ab9def5af8662db9696eb33a34 assets/hexcasting/models/item/scroll_ancient_medium.json
@ -97,11 +110,17 @@ e6452f95b60240e0067769d7f32a0b9fa7718a1b assets/hexcasting/models/item/slate_wri
986674763b45e0f9381f9f34a708082e5230652a assets/hexcasting/models/item/spellbook.json
f962c13ab9e299885387cee35b16006651821e81 assets/hexcasting/models/item/spellbook_filled.json
c29e6e7b2168eeeb13b1fc3e93ffc3e0c9bd11ce assets/hexcasting/models/item/spellbook_sealed.json
2f422cc59c84f6c997475367967390186adce5f0 assets/hexcasting/models/item/spruce_staff.json
bc2dbafadff333484c397675325df15f95e8b9f1 assets/hexcasting/models/item/spruce_staff.json
65bbc32202a58cdae91165e059e53bcfb2c54e10 assets/hexcasting/models/item/staves/quenched_0.json
9d8d276d077fc9ee355d4af5b62d5f63087ed6e1 assets/hexcasting/models/item/staves/quenched_1.json
ff1f37ac81e58185d9ea63d1ef75558e30f2e193 assets/hexcasting/models/item/staves/quenched_2.json
5cb3a83a9e601d4955e0c5456c621c4ac3f3d76e assets/hexcasting/models/item/staves/quenched_3.json
d6ebc87cb0fa6f86bee3a4eade7329ebb0cf2d38 assets/hexcasting/models/item/stripped_edified_log.json
ea3f18f75776022127f3a108119e3f7a5c211c0f assets/hexcasting/models/item/stripped_edified_wood.json
0a100b64e77394606018320bbc5752a546fe0af4 assets/hexcasting/models/item/sub_sandwich.json
6a7f5af82cf8ec72c3457ef4c1ae11a76717bf88 assets/hexcasting/models/item/thought_knot.json
93b2191ffab47003f661b75a85cd833ec64f0c15 assets/hexcasting/models/item/thought_knot_written.json
5f4831d11d8f45b037a6f48e12d2e794ada7b961 assets/hexcasting/models/item/trinket.json
946970e74b8d3c76c15191f494bc1f3d7e36aa43 assets/hexcasting/models/item/trinket_filled.json
c6523de66cbfae3a1e6361c635cc693a0a089bb3 assets/hexcasting/models/item/uuid_colorizer.json
a882b3dbb46c9abee345c446fb83f4d293442c5f assets/hexcasting/models/item/warped_staff.json
30e95dd075eab5379410ce5a7e0cd53dfb606005 assets/hexcasting/models/item/warped_staff.json

View file

@ -1,4 +1,4 @@
// 1.19.2 2022-11-05T14:30:43.69127 Block States: hexcasting
// 1.19.2 2023-02-17T23:01:49.857526865 Block States: hexcasting
901e38574bdaa40ea4a0f6e773a88a95d9c03e55 assets/hexcasting/blockstates/akashic_bookshelf.json
32a77ef668198002563d68be35a24fa93c8d454a assets/hexcasting/blockstates/akashic_connector.json
85080ce0a0387583a839e4788517d675a1a35e24 assets/hexcasting/blockstates/akashic_record.json
@ -29,6 +29,7 @@ e44322f1178e121b70f45e5242d5b0e9a11c211c assets/hexcasting/blockstates/edified_w
4ffe2f23f6774045d40e3763efa161da84d777c8 assets/hexcasting/blockstates/impetus_look.json
1e45bbe847d2edbec8189249f9afb58acda3fe05 assets/hexcasting/blockstates/impetus_rightclick.json
1d568faf935ff3c67d6a7f074a5d0d3ef6406101 assets/hexcasting/blockstates/impetus_storedplayer.json
c41c3f2f39c9fa8a319a705e2183112df18cb4f8 assets/hexcasting/blockstates/quenched_allay.json
0aca7e2e67793a21ffc794c02fb2b22d02d2058a assets/hexcasting/blockstates/scroll_paper.json
e5c88e23be0552d4c06062510e8feeab510472ef assets/hexcasting/blockstates/scroll_paper_lantern.json
ef6b44bd2360926cb9dcde5bb3f1380385acea90 assets/hexcasting/blockstates/slate.json
@ -134,6 +135,7 @@ de2a5fd9b621e5086852f2191c360d9274b9b10c assets/hexcasting/models/block/impetus_
7ac5cb74f321b061c1e93b859540b508c7dcdaa4 assets/hexcasting/models/block/impetus_storedplayer_lit_south.json
46c29660e3fa78aeaa264268b43017f4b0c0d655 assets/hexcasting/models/block/impetus_storedplayer_lit_up.json
4d22557274958179da4671c43c2f387336a701a2 assets/hexcasting/models/block/impetus_storedplayer_lit_west.json
9af2754cb1e53eeaa85618cf92651b4878cf62b1 assets/hexcasting/models/block/quenched_allay.json
e1e7ce0bcc08a53b3e6634f7e5b7a6cf488cf45b assets/hexcasting/models/block/redstone_directrix_powered_dim_down.json
fb22e529f1ca638b7e952176694ab1912eb4274b assets/hexcasting/models/block/redstone_directrix_powered_dim_east.json
a5a53ec6a3cd54592dcb224245a4515a2b3b72ed assets/hexcasting/models/block/redstone_directrix_powered_dim_north.json

View file

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "hexcasting:block/quenched_allay"
}
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "hexcasting:block/quenched_allay_0"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "hexcasting:block/quenched_allay_0"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "hexcasting:block/quenched_allay_1"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "hexcasting:block/quenched_allay_2"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "hexcasting:block/quenched_allay_3"
}
}

View file

@ -8,9 +8,9 @@
}
},
{
"model": "hexcasting:item/old_staff",
"model": "hexcasting:item/cherry_staff",
"predicate": {
"hexcasting:funny_level": 1.0
"hexcasting:funny_level": 2.0
}
}
],

View file

@ -8,9 +8,9 @@
}
},
{
"model": "hexcasting:item/old_staff",
"model": "hexcasting:item/cherry_staff",
"predicate": {
"hexcasting:funny_level": 1.0
"hexcasting:funny_level": 2.0
}
}
],

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld_rod",
"textures": {
"layer0": "hexcasting:item/staves/cherry"
}
}

View file

@ -8,9 +8,9 @@
}
},
{
"model": "hexcasting:item/old_staff",
"model": "hexcasting:item/cherry_staff",
"predicate": {
"hexcasting:funny_level": 1.0
"hexcasting:funny_level": 2.0
}
}
],

View file

@ -8,9 +8,9 @@
}
},
{
"model": "hexcasting:item/old_staff",
"model": "hexcasting:item/cherry_staff",
"predicate": {
"hexcasting:funny_level": 1.0
"hexcasting:funny_level": 2.0
}
}
],

View file

@ -8,9 +8,9 @@
}
},
{
"model": "hexcasting:item/old_staff",
"model": "hexcasting:item/cherry_staff",
"predicate": {
"hexcasting:funny_level": 1.0
"hexcasting:funny_level": 2.0
}
}
],

View file

@ -8,9 +8,9 @@
}
},
{
"model": "hexcasting:item/old_staff",
"model": "hexcasting:item/cherry_staff",
"predicate": {
"hexcasting:funny_level": 1.0
"hexcasting:funny_level": 2.0
}
}
],

View file

@ -8,9 +8,9 @@
}
},
{
"model": "hexcasting:item/old_staff",
"model": "hexcasting:item/cherry_staff",
"predicate": {
"hexcasting:funny_level": 1.0
"hexcasting:funny_level": 2.0
}
}
],

View file

@ -0,0 +1,20 @@
{
"parent": "minecraft:item/handheld_rod",
"overrides": [
{
"model": "hexcasting:item/mindsplice_staff",
"predicate": {
"hexcasting:funny_level": 0.0
}
},
{
"model": "hexcasting:item/cherry_staff",
"predicate": {
"hexcasting:funny_level": 2.0
}
}
],
"textures": {
"layer0": "hexcasting:item/staves/mindsplice"
}
}

View file

@ -8,9 +8,9 @@
}
},
{
"model": "hexcasting:item/old_staff",
"model": "hexcasting:item/cherry_staff",
"predicate": {
"hexcasting:funny_level": 1.0
"hexcasting:funny_level": 2.0
}
}
],

View file

@ -0,0 +1,28 @@
{
"overrides": [
{
"model": "hexcasting:block/quenched_allay_0",
"predicate": {
"hexcasting:variant": 0.0
}
},
{
"model": "hexcasting:block/quenched_allay_1",
"predicate": {
"hexcasting:variant": 1.0
}
},
{
"model": "hexcasting:block/quenched_allay_2",
"predicate": {
"hexcasting:variant": 2.0
}
},
{
"model": "hexcasting:block/quenched_allay_3",
"predicate": {
"hexcasting:variant": 3.0
}
}
]
}

View file

@ -0,0 +1,28 @@
{
"overrides": [
{
"model": "hexcasting:item/quenched_shard_0",
"predicate": {
"hexcasting:variant": 0.0
}
},
{
"model": "hexcasting:item/quenched_shard_1",
"predicate": {
"hexcasting:variant": 1.0
}
},
{
"model": "hexcasting:item/quenched_shard_2",
"predicate": {
"hexcasting:variant": 2.0
}
},
{
"model": "hexcasting:item/quenched_shard_3",
"predicate": {
"hexcasting:variant": 3.0
}
}
]
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "hexcasting:item/quenched_shard_0"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "hexcasting:item/quenched_shard_1"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "hexcasting:item/quenched_shard_2"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "hexcasting:item/quenched_shard_3"
}
}

View file

@ -0,0 +1,28 @@
{
"overrides": [
{
"model": "hexcasting:item/staves/quenched_0",
"predicate": {
"hexcasting:variant": 0.0
}
},
{
"model": "hexcasting:item/staves/quenched_1",
"predicate": {
"hexcasting:variant": 1.0
}
},
{
"model": "hexcasting:item/staves/quenched_2",
"predicate": {
"hexcasting:variant": 2.0
}
},
{
"model": "hexcasting:item/staves/quenched_3",
"predicate": {
"hexcasting:variant": 3.0
}
}
]
}

View file

@ -8,9 +8,9 @@
}
},
{
"model": "hexcasting:item/old_staff",
"model": "hexcasting:item/cherry_staff",
"predicate": {
"hexcasting:funny_level": 1.0
"hexcasting:funny_level": 2.0
}
}
],

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld_rod",
"textures": {
"layer0": "hexcasting:item/staves/quenched_0"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld_rod",
"textures": {
"layer0": "hexcasting:item/staves/quenched_1"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld_rod",
"textures": {
"layer0": "hexcasting:item/staves/quenched_2"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld_rod",
"textures": {
"layer0": "hexcasting:item/staves/quenched_3"
}
}

View file

@ -0,0 +1,20 @@
{
"parent": "minecraft:item/generated",
"overrides": [
{
"model": "hexcasting:item/thought_knot",
"predicate": {
"hexcasting:written": 0.0
}
},
{
"model": "hexcasting:item/thought_knot_written",
"predicate": {
"hexcasting:written": 1.0
}
}
],
"textures": {
"layer0": "hexcasting:item/thought_knot"
}
}

View file

@ -0,0 +1,7 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "hexcasting:item/thought_knot",
"layer1": "hexcasting:item/thought_knot_overlay"
}
}

View file

@ -8,9 +8,9 @@
}
},
{
"model": "hexcasting:item/old_staff",
"model": "hexcasting:item/cherry_staff",
"predicate": {
"hexcasting:funny_level": 1.0
"hexcasting:funny_level": 2.0
}
}
],

View file

@ -42,7 +42,7 @@ public interface ADMediaHolder {
/**
* The priority for this media holder to be selected when casting a hex. Higher priorities are taken first.
*
* <p>
* By default,
* * Charged Amethyst has priority 1000
* * Amethyst Shards have priority 2000
@ -58,9 +58,9 @@ public interface ADMediaHolder {
/**
* Withdraws media from the holder. Returns the amount of media extracted, which may be less or more than the cost.
*
* <p>
* Even if {@link ADMediaHolder#canProvide} is false, you can still withdraw media this way.
*
* <p>
* Withdrawing a negative amount will act as though you attempted to withdraw as much media as the holder contains.
*/
default int withdrawMedia(int cost, boolean simulate) {
@ -77,10 +77,11 @@ public interface ADMediaHolder {
/**
* Inserts media into the holder. Returns the amount of media inserted, which may be less than the requested amount.
*
* <p>
* Even if {@link ADMediaHolder#canRecharge} is false, you can still insert media this way.
*
* Inserting a negative amount will act as though you attempted to insert exactly as much media as the holder was missing.
* <p>
* Inserting a negative amount will act as though you attempted to insert exactly as much media as the holder was
* missing.
*/
default int insertMedia(int amount, boolean simulate) {
var mediaHere = getMedia();
@ -101,6 +102,7 @@ public interface ADMediaHolder {
return inserting;
}
int QUENCHED_ALLAY_PRIORITY = 900;
int CHARGED_AMETHYST_PRIORITY = 1000;
int AMETHYST_SHARD_PRIORITY = 2000;
int AMETHYST_DUST_PRIORITY = 3000;

View file

@ -6,6 +6,10 @@ import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.minecraft.server.level.ServerLevel
import net.minecraft.world.phys.Vec3
/**
* @param fuzziness the radius of the sphere the particle might happen in (pos)
* @param spread the max angle in radians the particle can move in, in relation to vel
*/
data class ParticleSpray(val pos: Vec3, val vel: Vec3, val fuzziness: Double, val spread: Double, val count: Int = 20) {
companion object {
@JvmStatic

View file

@ -4,4 +4,7 @@ public final class MediaConstants {
public static final int DUST_UNIT = 10000;
public static final int SHARD_UNIT = 5 * DUST_UNIT;
public static final int CRYSTAL_UNIT = 10 * DUST_UNIT;
public static final int QUENCHED_SHARD_UNIT = 3 * CRYSTAL_UNIT;
public static final int QUENCHED_BLOCK_UNIT = 4 * QUENCHED_SHARD_UNIT;
}

View file

@ -21,11 +21,21 @@ public class HexConfig {
double mediaToHealthRate();
int cypherCooldown();
int trinketCooldown();
int artifactCooldown();
int DEFAULT_DUST_MEDIA_AMOUNT = MediaConstants.DUST_UNIT;
int DEFAULT_SHARD_MEDIA_AMOUNT = MediaConstants.SHARD_UNIT;
int DEFAULT_CHARGED_MEDIA_AMOUNT = MediaConstants.CRYSTAL_UNIT;
double DEFAULT_MEDIA_TO_HEALTH_RATE = 2 * MediaConstants.CRYSTAL_UNIT / 20.0;
int DEFAULT_CYPHER_COOLDOWN = 8;
int DEFAULT_TRINKET_COOLDOWN = 5;
int DEFAULT_ARTIFACT_COOLDOWN = 3;
}
public interface ClientConfigAccess {

View file

@ -20,6 +20,10 @@ public class HexTags {
public static final TagKey<Item> GRANTS_ROOT_ADVANCEMENT = create("grants_root_advancement");
public static final TagKey<Item> SEAL_MATERIALS = create("seal_materials");
public static final TagKey<Item> IMPETI = create("impeti");
public static final TagKey<Item> DIRECTRICES = create("directrices");
public static final TagKey<Item> MINDFLAYED_CIRCLE_COMPONENTS = create("brainswept_circle_components");
public static TagKey<Item> create(String name) {
return create(modLoc(name));
}
@ -33,6 +37,11 @@ public class HexTags {
public static final TagKey<Block> EDIFIED_LOGS = create("edified_logs");
public static final TagKey<Block> EDIFIED_PLANKS = create("edified_planks");
public static final TagKey<Block> IMPETI = create("impeti");
public static final TagKey<Block> DIRECTRICES = create("directrices");
public static final TagKey<Block> MINDFLAYED_CIRCLE_COMPONENTS = create("brainswept_circle_components");
public static TagKey<Block> create(String name) {
return TagKey.create(Registry.BLOCK_REGISTRY, modLoc(name));
}

View file

@ -0,0 +1,10 @@
package at.petrak.hexcasting.api.player;
/**
* Note that this just keeps track of state, actually giving the player the elytra ability is handled
* differently per platform
*
* @param gracePeriod so the flight isn't immediately removed because the player started on the ground
*/
public record AltioraAbility(int gracePeriod) {
}

View file

@ -4,8 +4,9 @@ import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
public record FlightAbility(boolean allowed, int timeLeft, ResourceKey<Level> dimension, Vec3 origin, double radius) {
public static FlightAbility deny() {
return new FlightAbility(false, 0, Level.OVERWORLD, Vec3.ZERO, 0);
}
/**
* @param timeLeft sentinel of -1 for infinite
* @param radius sentinel of negative for infinite
*/
public record FlightAbility(int timeLeft, ResourceKey<Level> dimension, Vec3 origin, double radius) {
}

View file

@ -1,5 +1,6 @@
package at.petrak.hexcasting.client;
import at.petrak.hexcasting.client.render.GaslightingTracker;
import net.minecraft.client.Minecraft;
public class ClientTickCounter {
@ -7,7 +8,7 @@ public class ClientTickCounter {
public static float partialTicks = 0.0F;
public static float getTotal() {
return (float)ticksInGame + partialTicks;
return (float) ticksInGame + partialTicks;
}
public static void renderTickStart(float renderTickTime) {
@ -18,6 +19,7 @@ public class ClientTickCounter {
if (!Minecraft.getInstance().isPaused()) {
++ticksInGame;
partialTicks = 0.0F;
GaslightingTracker.postFrameCheckRendered();
}
}
}

View file

@ -1,66 +1,71 @@
package at.petrak.hexcasting.client;
import at.petrak.hexcasting.api.block.circle.BlockAbstractImpetus;
import at.petrak.hexcasting.api.block.circle.BlockEntityAbstractImpetus;
import at.petrak.hexcasting.api.casting.iota.IotaType;
import at.petrak.hexcasting.api.client.ScryingLensOverlayRegistry;
import at.petrak.hexcasting.api.item.IotaHolderItem;
import at.petrak.hexcasting.api.item.MediaHolderItem;
import at.petrak.hexcasting.api.misc.MediaConstants;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.client.be.BlockEntityAkashicBookshelfRenderer;
import at.petrak.hexcasting.client.be.BlockEntitySlateRenderer;
import at.petrak.hexcasting.client.entity.WallScrollRenderer;
import at.petrak.hexcasting.client.render.GaslightingTracker;
import at.petrak.hexcasting.client.render.ScryingLensOverlays;
import at.petrak.hexcasting.client.render.be.BlockEntityAkashicBookshelfRenderer;
import at.petrak.hexcasting.client.render.be.BlockEntityQuenchedAllayRenderer;
import at.petrak.hexcasting.client.render.be.BlockEntitySlateRenderer;
import at.petrak.hexcasting.common.blocks.BlockQuenchedAllay;
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicBookshelf;
import at.petrak.hexcasting.common.blocks.akashic.BlockEntityAkashicBookshelf;
import at.petrak.hexcasting.common.entities.HexEntities;
import at.petrak.hexcasting.common.items.*;
import at.petrak.hexcasting.common.items.ItemStaff;
import at.petrak.hexcasting.common.items.magic.ItemMediaBattery;
import at.petrak.hexcasting.common.items.magic.ItemPackagedHex;
import at.petrak.hexcasting.common.items.storage.*;
import at.petrak.hexcasting.common.lib.HexBlockEntities;
import at.petrak.hexcasting.common.lib.HexBlocks;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.xplat.IClientXplatAbstractions;
import com.mojang.datafixers.util.Pair;
import net.minecraft.ChatFormatting;
import net.minecraft.client.color.block.BlockColor;
import net.minecraft.client.color.item.ItemColor;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.Style;
import net.minecraft.network.chat.TextColor;
import net.minecraft.util.Mth;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.ComparatorMode;
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument;
import net.minecraft.world.level.block.state.properties.RailShape;
import net.minecraft.world.level.material.MaterialColor;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.ToIntFunction;
import java.util.function.UnaryOperator;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
public class RegisterClientStuff {
public static List<BakedModel> QUENCHED_ALLAY_VARIANTS = new ArrayList<>();
public static void init() {
registerDataHolderOverrides(HexItems.FOCUS,
registerSealableDataHolderOverrides(HexItems.FOCUS,
stack -> HexItems.FOCUS.readIotaTag(stack) != null,
ItemFocus::isSealed);
registerDataHolderOverrides(HexItems.SPELLBOOK,
registerSealableDataHolderOverrides(HexItems.SPELLBOOK,
stack -> HexItems.SPELLBOOK.readIotaTag(stack) != null,
ItemSpellbook::isSealed);
IClientXplatAbstractions.INSTANCE.registerItemProperty(HexItems.THOUGHT_KNOT, ItemThoughtKnot.WRITTEN_PRED,
(stack, level, holder, holderID) -> {
if (NBTHelper.contains(stack, ItemThoughtKnot.TAG_DATA)) {
return 1;
} else {
return 0;
}
});
registerPackagedSpellOverrides(HexItems.CYPHER);
registerPackagedSpellOverrides(HexItems.TRINKET);
@ -93,6 +98,12 @@ public class RegisterClientStuff {
registerWandOverrides(HexItems.STAFF_DARK_OAK);
registerWandOverrides(HexItems.STAFF_ACACIA);
registerWandOverrides(HexItems.STAFF_EDIFIED);
// purposely skip quenched
registerWandOverrides(HexItems.STAFF_MINDSPLICE);
registerGaslight4(HexItems.STAFF_QUENCHED);
registerGaslight4(HexBlocks.QUENCHED_ALLAY.asItem());
registerGaslight4(HexItems.QUENCHED_SHARD);
x.setRenderLayer(HexBlocks.CONJURED_LIGHT, RenderType.cutout());
x.setRenderLayer(HexBlocks.CONJURED_BLOCK, RenderType.cutout());
@ -106,6 +117,7 @@ public class RegisterClientStuff {
x.setRenderLayer(HexBlocks.CITRINE_EDIFIED_LEAVES, RenderType.cutoutMipped());
x.setRenderLayer(HexBlocks.AKASHIC_RECORD, RenderType.translucent());
x.setRenderLayer(HexBlocks.QUENCHED_ALLAY, RenderType.translucent());
x.registerEntityRenderer(HexEntities.WALL_SCROLL, WallScrollRenderer::new);
@ -117,13 +129,20 @@ public class RegisterClientStuff {
// Minecraft.getInstance().getTextureManager().bindForSetup(tex);
// }
addScryingLensStuff();
ScryingLensOverlays.addScryingLensStuff();
}
private static void registerGaslight4(Item item) {
IClientXplatAbstractions.INSTANCE.registerItemProperty(item,
GaslightingTracker.GASLIGHTING_PRED, (stack, level, holder, holderID) ->
Math.abs(GaslightingTracker.getGaslightingAmount() % 4));
}
public static void registerColorProviders(BiConsumer<ItemColor, Item> itemColorRegistry,
BiConsumer<BlockColor, Block> blockColorRegistry) {
itemColorRegistry.accept(makeIotaStorageColorizer(HexItems.FOCUS::getColor), HexItems.FOCUS);
itemColorRegistry.accept(makeIotaStorageColorizer(HexItems.SPELLBOOK::getColor), HexItems.SPELLBOOK);
itemColorRegistry.accept(makeIotaStorageColorizer(HexItems.THOUGHT_KNOT::getColor), HexItems.THOUGHT_KNOT);
blockColorRegistry.accept((bs, level, pos, idx) -> {
if (!bs.getValue(BlockAkashicBookshelf.HAS_BOOKS) || level == null || pos == null) {
@ -156,153 +175,7 @@ public class RegisterClientStuff {
};
}
private static void addScryingLensStuff() {
ScryingLensOverlayRegistry.addPredicateDisplayer(
(state, pos, observer, world, direction) -> state.getBlock() instanceof BlockAbstractImpetus,
(lines, state, pos, observer, world, direction) -> {
if (world.getBlockEntity(pos) instanceof BlockEntityAbstractImpetus beai) {
beai.applyScryingLensOverlay(lines, state, pos, observer, world, direction);
}
});
ScryingLensOverlayRegistry.addDisplayer(Blocks.NOTE_BLOCK,
(lines, state, pos, observer, world, direction) -> {
int note = state.getValue(NoteBlock.NOTE);
float rCol = Math.max(0.0F, Mth.sin((note / 24F + 0.0F) * Mth.TWO_PI) * 0.65F + 0.35F);
float gCol = Math.max(0.0F, Mth.sin((note / 24F + 0.33333334F) * Mth.TWO_PI) * 0.65F + 0.35F);
float bCol = Math.max(0.0F, Mth.sin((note / 24F + 0.6666667F) * Mth.TWO_PI) * 0.65F + 0.35F);
int noteColor = 0xFF_000000 | Mth.color(rCol, gCol, bCol);
var instrument = state.getValue(NoteBlock.INSTRUMENT);
lines.add(new Pair<>(
new ItemStack(Items.MUSIC_DISC_CHIRP),
Component.literal(String.valueOf(instrument.ordinal()))
.withStyle(color(instrumentColor(instrument)))));
lines.add(new Pair<>(
new ItemStack(Items.NOTE_BLOCK),
Component.literal(String.valueOf(note))
.withStyle(color(noteColor))));
});
ScryingLensOverlayRegistry.addDisplayer(HexBlocks.AKASHIC_BOOKSHELF,
(lines, state, pos, observer, world, direction) -> {
if (world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile) {
var iotaTag = tile.getIotaTag();
if (iotaTag != null) {
var display = IotaType.getDisplay(iotaTag);
lines.add(new Pair<>(new ItemStack(Items.BOOK), display));
}
}
});
ScryingLensOverlayRegistry.addDisplayer(Blocks.COMPARATOR,
(lines, state, pos, observer, world, direction) -> {
int comparatorValue = ScryingLensOverlayRegistry.getComparatorValue(true);
lines.add(new Pair<>(
new ItemStack(Items.REDSTONE),
Component.literal(comparatorValue == -1 ? "" : String.valueOf(comparatorValue))
.withStyle(redstoneColor(comparatorValue))));
boolean compare = state.getValue(ComparatorBlock.MODE) == ComparatorMode.COMPARE;
lines.add(new Pair<>(
new ItemStack(Items.REDSTONE_TORCH),
Component.literal(compare ? ">=" : "-")
.withStyle(redstoneColor(compare ? 0 : 15))));
});
ScryingLensOverlayRegistry.addDisplayer(Blocks.POWERED_RAIL,
(lines, state, pos, observer, world, direction) -> {
int power = getPoweredRailStrength(world, pos, state);
lines.add(new Pair<>(
new ItemStack(Items.POWERED_RAIL),
Component.literal(String.valueOf(power))
.withStyle(redstoneColor(power, 9))));
});
ScryingLensOverlayRegistry.addDisplayer(Blocks.REPEATER,
(lines, state, pos, observer, world, direction) -> lines.add(new Pair<>(
new ItemStack(Items.CLOCK),
Component.literal(String.valueOf(state.getValue(RepeaterBlock.DELAY)))
.withStyle(ChatFormatting.YELLOW))));
ScryingLensOverlayRegistry.addPredicateDisplayer(
(state, pos, observer, world, direction) -> state.getBlock() instanceof BeehiveBlock,
(lines, state, pos, observer, world, direction) -> {
int count = ScryingLensOverlayRegistry.getBeeValue();
lines.add(new Pair<>(new ItemStack(Items.BEE_NEST), count == -1 ? Component.empty() :
Component.translatable(
"hexcasting.tooltip.lens.bee" + (count == 1 ? ".single" : ""),
count
)));
});
ScryingLensOverlayRegistry.addPredicateDisplayer(
(state, pos, observer, world, direction) -> state.isSignalSource() && !state.is(
Blocks.COMPARATOR),
(lines, state, pos, observer, world, direction) -> {
int signalStrength = 0;
if (state.getBlock() instanceof RedStoneWireBlock) {
signalStrength = state.getValue(RedStoneWireBlock.POWER);
} else {
for (Direction dir : Direction.values()) {
signalStrength = Math.max(signalStrength, state.getSignal(world, pos, dir));
}
}
lines.add(0, new Pair<>(
new ItemStack(Items.REDSTONE),
Component.literal(String.valueOf(signalStrength))
.withStyle(redstoneColor(signalStrength))));
});
ScryingLensOverlayRegistry.addPredicateDisplayer(
(state, pos, observer, world, direction) -> state.hasAnalogOutputSignal(),
(lines, state, pos, observer, world, direction) -> {
int comparatorValue = ScryingLensOverlayRegistry.getComparatorValue(false);
lines.add(
new Pair<>(
new ItemStack(Items.COMPARATOR),
Component.literal(comparatorValue == -1 ? "" : String.valueOf(comparatorValue))
.withStyle(redstoneColor(comparatorValue))));
});
}
private static UnaryOperator<Style> color(int color) {
return (style) -> style.withColor(TextColor.fromRgb(color));
}
private static UnaryOperator<Style> redstoneColor(int power) {
return redstoneColor(power, 15);
}
private static UnaryOperator<Style> redstoneColor(int power, int max) {
return color(RedStoneWireBlock.getColorForPower(Mth.clamp((power * max) / 15, 0, 15)));
}
private static int instrumentColor(NoteBlockInstrument instrument) {
return switch (instrument) {
case BASEDRUM -> MaterialColor.STONE.col;
case SNARE, XYLOPHONE, PLING -> MaterialColor.SAND.col;
case HAT -> MaterialColor.QUARTZ.col;
case BASS -> MaterialColor.WOOD.col;
case FLUTE -> MaterialColor.CLAY.col;
case BELL -> MaterialColor.GOLD.col;
case GUITAR -> MaterialColor.WOOL.col;
case CHIME -> MaterialColor.ICE.col;
case IRON_XYLOPHONE -> MaterialColor.METAL.col;
case COW_BELL -> MaterialColor.COLOR_BROWN.col;
case DIDGERIDOO -> MaterialColor.COLOR_ORANGE.col;
case BIT -> MaterialColor.EMERALD.col;
case BANJO -> MaterialColor.COLOR_YELLOW.col;
default -> -1;
};
}
private static void registerDataHolderOverrides(IotaHolderItem item, Predicate<ItemStack> hasIota,
private static void registerSealableDataHolderOverrides(IotaHolderItem item, Predicate<ItemStack> hasIota,
Predicate<ItemStack> isSealed) {
IClientXplatAbstractions.INSTANCE.registerItemProperty((Item) item, ItemFocus.OVERLAY_PRED,
(stack, level, holder, holderID) -> {
@ -316,116 +189,6 @@ public class RegisterClientStuff {
});
}
private static int getPoweredRailStrength(Level level, BlockPos pos, BlockState state) {
if (level.hasNeighborSignal(pos))
return 9;
int positiveValue = findPoweredRailSignal(level, pos, state, true, 0);
int negativeValue = findPoweredRailSignal(level, pos, state, false, 0);
return Math.max(positiveValue, negativeValue);
}
// Copypasta from PoweredRailBlock.class
private static int findPoweredRailSignal(Level level, BlockPos pos, BlockState state, boolean travelPositive,
int depth) {
if (depth >= 8) {
return 0;
} else {
int x = pos.getX();
int y = pos.getY();
int z = pos.getZ();
boolean descending = true;
RailShape shape = state.getValue(PoweredRailBlock.SHAPE);
switch (shape) {
case NORTH_SOUTH:
if (travelPositive) {
++z;
} else {
--z;
}
break;
case EAST_WEST:
if (travelPositive) {
--x;
} else {
++x;
}
break;
case ASCENDING_EAST:
if (travelPositive) {
--x;
} else {
++x;
++y;
descending = false;
}
shape = RailShape.EAST_WEST;
break;
case ASCENDING_WEST:
if (travelPositive) {
--x;
++y;
descending = false;
} else {
++x;
}
shape = RailShape.EAST_WEST;
break;
case ASCENDING_NORTH:
if (travelPositive) {
++z;
} else {
--z;
++y;
descending = false;
}
shape = RailShape.NORTH_SOUTH;
break;
case ASCENDING_SOUTH:
if (travelPositive) {
++z;
++y;
descending = false;
} else {
--z;
}
shape = RailShape.NORTH_SOUTH;
}
int power = getPowerFromRail(level, new BlockPos(x, y, z), travelPositive, depth, shape);
if (power > 0) {
return power;
} else if (descending) {
return getPowerFromRail(level, new BlockPos(x, y - 1, z), travelPositive, depth, shape);
} else {
return 0;
}
}
}
private static int getPowerFromRail(Level level, BlockPos pos, boolean travelPositive, int depth, RailShape shape) {
BlockState otherState = level.getBlockState(pos);
if (!otherState.is(Blocks.POWERED_RAIL)) {
return 0;
} else {
RailShape otherShape = otherState.getValue(PoweredRailBlock.SHAPE);
if (shape == RailShape.EAST_WEST && (otherShape == RailShape.NORTH_SOUTH || otherShape == RailShape.ASCENDING_NORTH || otherShape == RailShape.ASCENDING_SOUTH)) {
return 0;
} else if (shape == RailShape.NORTH_SOUTH && (otherShape == RailShape.EAST_WEST || otherShape == RailShape.ASCENDING_EAST || otherShape == RailShape.ASCENDING_WEST)) {
return 0;
} else if (otherState.getValue(PoweredRailBlock.POWERED)) {
return level.hasNeighborSignal(pos) ? 8 - depth : findPoweredRailSignal(level, pos, otherState,
travelPositive, depth + 1);
} else {
return 0;
}
}
}
private static void registerScrollOverrides(ItemScroll scroll) {
IClientXplatAbstractions.INSTANCE.registerItemProperty(scroll, ItemScroll.ANCIENT_PREDICATE,
(stack, level, holder, holderID) -> NBTHelper.hasString(stack, ItemScroll.TAG_OP_ID) ? 1f : 0f);
@ -447,6 +210,8 @@ public class RegisterClientStuff {
var name = stack.getHoverName().getString().toLowerCase(Locale.ROOT);
if (name.contains("old")) {
return 1f;
} else if (name.contains("cherry")) {
return 2f;
} else {
return 0f;
}
@ -457,6 +222,8 @@ public class RegisterClientStuff {
registerer.registerBlockEntityRenderer(HexBlockEntities.SLATE_TILE, BlockEntitySlateRenderer::new);
registerer.registerBlockEntityRenderer(HexBlockEntities.AKASHIC_BOOKSHELF_TILE,
BlockEntityAkashicBookshelfRenderer::new);
registerer.registerBlockEntityRenderer(HexBlockEntities.QUENCHED_ALLAY_TILE,
BlockEntityQuenchedAllayRenderer::new);
}
@FunctionalInterface
@ -464,4 +231,18 @@ public class RegisterClientStuff {
<T extends BlockEntity> void registerBlockEntityRenderer(BlockEntityType<T> type,
BlockEntityRendererProvider<? super T> berp);
}
public static void onModelRegister(ResourceManager recMan, Consumer<ResourceLocation> extraModels) {
for (int i = 0; i < BlockQuenchedAllay.VARIANTS; i++) {
extraModels.accept(modLoc("block/quenched_allay_" + i));
}
}
public static void onModelBake(ModelBakery loader, Map<ResourceLocation, BakedModel> map) {
for (int i = 0; i < BlockQuenchedAllay.VARIANTS; i++) {
var variantLoc = modLoc("block/quenched_allay_" + i);
var model = map.get(variantLoc);
QUENCHED_ALLAY_VARIANTS.add(model);
}
}
}

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.client.entity;
import at.petrak.hexcasting.client.RenderLib;
import at.petrak.hexcasting.client.render.RenderLib;
import at.petrak.hexcasting.common.entities.EntityWallScroll;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
@ -39,7 +39,7 @@ public class WallScrollRenderer extends EntityRenderer<EntityWallScroll> {
// I do as the PaintingRenderer guides
@Override
public void render(EntityWallScroll wallScroll, float yaw, float partialTicks, PoseStack ps,
MultiBufferSource bufSource, int packedLight) {
MultiBufferSource bufSource, int packedLight) {
RenderSystem.setShader(GameRenderer::getPositionTexShader);
@ -158,8 +158,8 @@ public class WallScrollRenderer extends EntityRenderer<EntityWallScroll> {
}
private static void vertex(Matrix4f mat, Matrix3f normal, int light, VertexConsumer verts, float x, float y,
float z, float u,
float v, float nx, float ny, float nz) {
float z, float u,
float v, float nx, float ny, float nz) {
verts.vertex(mat, x, y, z)
.color(0xffffffff)
.uv(u, v).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(light)
@ -176,7 +176,7 @@ public class WallScrollRenderer extends EntityRenderer<EntityWallScroll> {
}
private static void theCoolerDrawLineSeq(Matrix4f mat, Matrix3f normalMat, int light, VertexConsumer verts,
List<Vec2> points, float width, int color
List<Vec2> points, float width, int color
) {
if (points.size() <= 1) {
return;
@ -285,7 +285,7 @@ public class WallScrollRenderer extends EntityRenderer<EntityWallScroll> {
}
private static void theCoolerDrawSpot(Matrix4f mat, Matrix3f normal, int light, VertexConsumer verts,
Vec2 point, float radius, int color) {
Vec2 point, float radius, int color) {
var fracOfCircle = 6;
for (int i = 0; i < fracOfCircle; i++) {
// We do need rects, irritatingly

View file

@ -12,8 +12,10 @@ import at.petrak.hexcasting.api.misc.DiscoveryHandlers
import at.petrak.hexcasting.api.mod.HexConfig
import at.petrak.hexcasting.api.mod.HexTags
import at.petrak.hexcasting.api.utils.asTranslatedComponent
import at.petrak.hexcasting.client.*
import at.petrak.hexcasting.client.ClientTickCounter
import at.petrak.hexcasting.client.ShiftScrollListener
import at.petrak.hexcasting.client.ktxt.accumulatedScroll
import at.petrak.hexcasting.client.render.*
import at.petrak.hexcasting.client.sound.GridSoundInstance
import at.petrak.hexcasting.common.lib.HexSounds
import at.petrak.hexcasting.common.network.MsgNewSpellPatternSyn

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.client.gui;
import at.petrak.hexcasting.api.casting.math.HexPattern;
import at.petrak.hexcasting.client.RenderLib;
import at.petrak.hexcasting.client.render.RenderLib;
import at.petrak.hexcasting.common.misc.PatternTooltip;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
@ -64,7 +64,7 @@ public class PatternTooltipComponent implements ClientTooltipComponent {
@Override
public void renderImage(Font font, int mouseX, int mouseY, PoseStack ps, ItemRenderer pItemRenderer,
int pBlitOffset) {
int pBlitOffset) {
var width = this.getWidth(font);
var height = this.getHeight();

View file

@ -24,46 +24,42 @@ public class ConjureParticle extends TextureSheetParticle {
private static final Random RANDOM = new Random();
private final SpriteSet sprites;
private final boolean light;
ConjureParticle(ClientLevel pLevel, double x, double y, double z, double dx, double dy, double dz,
SpriteSet pSprites, int color, boolean light) {
SpriteSet pSprites, int color) {
super(pLevel, x, y, z, dx, dy, dz);
this.light = light;
this.quadSize *= light ? 0.9f : 0.75f;
this.quadSize *= 0.9f;
this.setParticleSpeed(dx, dy, dz);
var r = FastColor.ARGB32.red(color);
var g = FastColor.ARGB32.green(color);
var b = FastColor.ARGB32.blue(color);
this.setColor(r / 255f, g / 255f, b / 255f);
this.setAlpha(light ? 0.3f : 1.0f);
this.setAlpha(0.3f);
this.friction = 0.96F;
this.gravity = light && dy != 0 && dx != 0 && dz != 0 ? -0.01F : 0F;
this.gravity = dy != 0 && dx != 0 && dz != 0 ? -0.01F : 0F;
this.speedUpWhenYMotionIsBlocked = true;
this.sprites = pSprites;
this.roll = RANDOM.nextFloat(360);
this.oRoll = this.roll;
this.lifetime = (int) ((light ? 64.0D : 32.0D) / ((Math.random() + 3f) * 0.25f));
this.lifetime = (int) (64.0 / ((Math.random() + 3f) * 0.25f));
this.hasPhysics = false;
this.setSpriteFromAge(pSprites);
}
public @NotNull ParticleRenderType getRenderType() {
return this.light ? LIGHT_RENDER_TYPE : CONJURE_RENDER_TYPE;
return CONJURE_RENDER_TYPE;
}
public void tick() {
super.tick();
this.setSpriteFromAge(this.sprites);
this.alpha = 1.0f - ((float) this.age / (float) this.lifetime);
if (light) {
this.alpha *= 0.3f;
this.quadSize *= 0.96f;
}
this.alpha *= 0.3f;
this.quadSize *= 0.96f;
}
public void setSpriteFromAge(@NotNull SpriteSet pSprite) {
@ -86,15 +82,14 @@ public class ConjureParticle extends TextureSheetParticle {
@Nullable
@Override
public Particle createParticle(ConjureParticleOptions type, ClientLevel level,
double pX, double pY, double pZ,
double pXSpeed, double pYSpeed, double pZSpeed) {
return new ConjureParticle(level, pX, pY, pZ, pXSpeed, pYSpeed, pZSpeed, this.sprite, type.color(),
type.isLight());
double pX, double pY, double pZ,
double pXSpeed, double pYSpeed, double pZSpeed) {
return new ConjureParticle(level, pX, pY, pZ, pXSpeed, pYSpeed, pZSpeed, this.sprite, type.color());
}
}
// https://github.com/VazkiiMods/Botania/blob/db85d778ab23f44c11181209319066d1f04a9e3d/Xplat/src/main/java/vazkii/botania/client/fx/FXWisp.java
private record ConjureRenderType(boolean light) implements ParticleRenderType {
private record ConjureRenderType() implements ParticleRenderType {
@Override
public void begin(BufferBuilder buf, TextureManager texMan) {
Minecraft.getInstance().gameRenderer.lightTexture().turnOnLightLayer();
@ -104,7 +99,7 @@ public class ConjureParticle extends TextureSheetParticle {
RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_PARTICLES);
var tex = texMan.getTexture(TextureAtlas.LOCATION_PARTICLES);
IClientXplatAbstractions.INSTANCE.setFilterSave(tex, this.light, false);
IClientXplatAbstractions.INSTANCE.setFilterSave(tex, true, false);
buf.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.PARTICLE);
RenderSystem.enableDepthTest();
}
@ -113,7 +108,7 @@ public class ConjureParticle extends TextureSheetParticle {
public void end(Tesselator tess) {
tess.end();
IClientXplatAbstractions.INSTANCE.restoreLastFilter(
Minecraft.getInstance().getTextureManager().getTexture(TextureAtlas.LOCATION_PARTICLES)
Minecraft.getInstance().getTextureManager().getTexture(TextureAtlas.LOCATION_PARTICLES)
);
RenderSystem.disableBlend();
RenderSystem.depthMask(true);
@ -121,10 +116,9 @@ public class ConjureParticle extends TextureSheetParticle {
@Override
public String toString() {
return HexAPI.MOD_ID + (light ? ":light" : ":conjure");
return HexAPI.MOD_ID + ":conjure";
}
}
public static final ConjureRenderType CONJURE_RENDER_TYPE = new ConjureRenderType(false);
public static final ConjureRenderType LIGHT_RENDER_TYPE = new ConjureRenderType(true);
public static final ConjureRenderType CONJURE_RENDER_TYPE = new ConjureRenderType();
}

View file

@ -0,0 +1,52 @@
package at.petrak.hexcasting.client.render;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.model.ElytraModel;
import net.minecraft.client.model.EntityModel;
import net.minecraft.client.model.geom.EntityModelSet;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.renderer.entity.RenderLayerParent;
import net.minecraft.client.renderer.entity.layers.RenderLayer;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.Items;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
public class AltioraLayer<M extends EntityModel<AbstractClientPlayer>> extends RenderLayer<AbstractClientPlayer, M> {
private static final ResourceLocation TEX_LOC = modLoc("textures/misc/altiora.png");
private final ElytraModel<AbstractClientPlayer> elytraModel;
public AltioraLayer(RenderLayerParent<AbstractClientPlayer, M> renderer, EntityModelSet ems) {
super(renderer);
this.elytraModel = new ElytraModel<>(ems.bakeLayer(HexModelLayers.ALTIORA));
}
@Override
public void render(PoseStack ps, MultiBufferSource buffer, int packedLight, AbstractClientPlayer player,
float limbSwing, float limbSwingAmount, float partialTick, float ageInTicks, float netHeadYaw,
float headPitch) {
var altiora = IXplatAbstractions.INSTANCE.getAltiora(player);
// do a best effort to not render over other elytra, although we can never patch up everything
var chestSlot = player.getItemBySlot(EquipmentSlot.CHEST);
if (altiora != null && !chestSlot.is(Items.ELYTRA)) {
ps.pushPose();
ps.translate(0.0, 0.0, 0.125);
this.getParentModel().copyPropertiesTo(this.elytraModel);
this.elytraModel.setupAnim(player, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch);
VertexConsumer verts = ItemRenderer.getArmorFoilBuffer(
buffer, RenderType.armorCutoutNoCull(TEX_LOC), false, true);
this.elytraModel.renderToBuffer(ps, verts, packedLight, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F);
ps.popPose();
}
}
}

View file

@ -0,0 +1,27 @@
package at.petrak.hexcasting.client.render;
import net.minecraft.resources.ResourceLocation;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
// *nothing* that changes can be looked at for changes
public class GaslightingTracker {
private static int GASLIGHTING_AMOUNT = 0;
private static int LOOKING_COOLDOWN_MAX = 40;
private static int LOOKING_COOLDOWN = LOOKING_COOLDOWN_MAX;
public static ResourceLocation GASLIGHTING_PRED = modLoc("variant");
public static int getGaslightingAmount() {
LOOKING_COOLDOWN = LOOKING_COOLDOWN_MAX;
return GASLIGHTING_AMOUNT;
}
public static void postFrameCheckRendered() {
if (LOOKING_COOLDOWN > 0) {
LOOKING_COOLDOWN -= 1;
} else {
GASLIGHTING_AMOUNT += 1;
}
}
}

View file

@ -1,8 +1,9 @@
package at.petrak.hexcasting.client;
package at.petrak.hexcasting.client.render;
import at.petrak.hexcasting.api.client.ScryingLensOverlayRegistry;
import at.petrak.hexcasting.api.misc.DiscoveryHandlers;
import at.petrak.hexcasting.api.player.Sentinel;
import at.petrak.hexcasting.client.ClientTickCounter;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import com.google.common.collect.Lists;
import com.mojang.blaze3d.platform.GlStateManager;

View file

@ -0,0 +1,30 @@
package at.petrak.hexcasting.client.render;
import net.minecraft.client.model.ElytraModel;
import net.minecraft.client.model.geom.ModelLayerLocation;
import net.minecraft.client.model.geom.builders.LayerDefinition;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
// https://github.com/VazkiiMods/Botania/blob/1.19.x/Xplat/src/main/java/vazkii/botania/client/model/BotaniaModelLayers.java
public class HexModelLayers {
public static final ModelLayerLocation ALTIORA = make("altiora");
private static ModelLayerLocation make(String name) {
return make(name, "main");
}
private static ModelLayerLocation make(String name, String layer) {
// Don't add to vanilla's ModelLayers. It seems to only be used for error checking
// And would be annoying to do under Forge's parallel mod loading
return new ModelLayerLocation(modLoc(name), layer);
}
// combine with https://github.com/VazkiiMods/Botania/blob/1.19.x/Xplat/src/main/java/vazkii/botania/client/model/BotaniaLayerDefinitions.java
public static void init(BiConsumer<ModelLayerLocation, Supplier<LayerDefinition>> consumer) {
consumer.accept(ALTIORA, ElytraModel::createLayer);
}
}

View file

@ -1,10 +1,11 @@
@file:JvmName("RenderLib")
package at.petrak.hexcasting.client
package at.petrak.hexcasting.client.render
import at.petrak.hexcasting.api.casting.math.HexPattern
import at.petrak.hexcasting.api.mod.HexConfig
import at.petrak.hexcasting.api.utils.TAU
import at.petrak.hexcasting.client.ClientTickCounter
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.DefaultVertexFormat
import com.mojang.blaze3d.vertex.PoseStack

View file

@ -0,0 +1,288 @@
package at.petrak.hexcasting.client.render;
import at.petrak.hexcasting.api.block.circle.BlockAbstractImpetus;
import at.petrak.hexcasting.api.block.circle.BlockEntityAbstractImpetus;
import at.petrak.hexcasting.api.client.ScryingLensOverlayRegistry;
import at.petrak.hexcasting.common.blocks.akashic.BlockEntityAkashicBookshelf;
import at.petrak.hexcasting.common.lib.HexBlocks;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import com.mojang.datafixers.util.Pair;
import net.minecraft.ChatFormatting;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.Style;
import net.minecraft.network.chat.TextColor;
import net.minecraft.util.Mth;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.ComparatorMode;
import net.minecraft.world.level.block.state.properties.NoteBlockInstrument;
import net.minecraft.world.level.block.state.properties.RailShape;
import net.minecraft.world.level.material.MaterialColor;
import java.util.function.UnaryOperator;
public class ScryingLensOverlays {
public static void addScryingLensStuff() {
ScryingLensOverlayRegistry.addPredicateDisplayer(
(state, pos, observer, world, direction) -> state.getBlock() instanceof BlockAbstractImpetus,
(lines, state, pos, observer, world, direction) -> {
if (world.getBlockEntity(pos) instanceof BlockEntityAbstractImpetus beai) {
beai.applyScryingLensOverlay(lines, state, pos, observer, world, direction);
}
});
ScryingLensOverlayRegistry.addDisplayer(Blocks.NOTE_BLOCK,
(lines, state, pos, observer, world, direction) -> {
int note = state.getValue(NoteBlock.NOTE);
float rCol = Math.max(0.0F, Mth.sin((note / 24F + 0.0F) * Mth.TWO_PI) * 0.65F + 0.35F);
float gCol = Math.max(0.0F, Mth.sin((note / 24F + 0.33333334F) * Mth.TWO_PI) * 0.65F + 0.35F);
float bCol = Math.max(0.0F, Mth.sin((note / 24F + 0.6666667F) * Mth.TWO_PI) * 0.65F + 0.35F);
int noteColor = 0xFF_000000 | Mth.color(rCol, gCol, bCol);
var instrument = state.getValue(NoteBlock.INSTRUMENT);
lines.add(new Pair<>(
new ItemStack(Items.MUSIC_DISC_CHIRP),
Component.literal(String.valueOf(instrument.ordinal()))
.withStyle(color(instrumentColor(instrument)))));
lines.add(new Pair<>(
new ItemStack(Items.NOTE_BLOCK),
Component.literal(String.valueOf(note))
.withStyle(color(noteColor))));
});
ScryingLensOverlayRegistry.addDisplayer(HexBlocks.AKASHIC_BOOKSHELF,
(lines, state, pos, observer, world, direction) -> {
if (world.getBlockEntity(pos) instanceof BlockEntityAkashicBookshelf tile) {
var iotaTag = tile.getIotaTag();
if (iotaTag != null) {
var display = HexIotaTypes.getDisplay(iotaTag);
lines.add(new Pair<>(new ItemStack(Items.BOOK), display));
}
}
});
ScryingLensOverlayRegistry.addDisplayer(Blocks.COMPARATOR,
(lines, state, pos, observer, world, direction) -> {
int comparatorValue = ScryingLensOverlayRegistry.getComparatorValue(true);
lines.add(new Pair<>(
new ItemStack(Items.REDSTONE),
Component.literal(comparatorValue == -1 ? "" : String.valueOf(comparatorValue))
.withStyle(redstoneColor(comparatorValue))));
boolean compare = state.getValue(ComparatorBlock.MODE) == ComparatorMode.COMPARE;
lines.add(new Pair<>(
new ItemStack(Items.REDSTONE_TORCH),
Component.literal(compare ? ">=" : "-")
.withStyle(redstoneColor(compare ? 0 : 15))));
});
ScryingLensOverlayRegistry.addDisplayer(Blocks.POWERED_RAIL,
(lines, state, pos, observer, world, direction) -> {
int power = getPoweredRailStrength(world, pos, state);
lines.add(new Pair<>(
new ItemStack(Items.POWERED_RAIL),
Component.literal(String.valueOf(power))
.withStyle(redstoneColor(power, 9))));
});
ScryingLensOverlayRegistry.addDisplayer(Blocks.REPEATER,
(lines, state, pos, observer, world, direction) -> lines.add(new Pair<>(
new ItemStack(Items.CLOCK),
Component.literal(String.valueOf(state.getValue(RepeaterBlock.DELAY)))
.withStyle(ChatFormatting.YELLOW))));
ScryingLensOverlayRegistry.addPredicateDisplayer(
(state, pos, observer, world, direction) -> state.getBlock() instanceof BeehiveBlock,
(lines, state, pos, observer, world, direction) -> {
int count = ScryingLensOverlayRegistry.getBeeValue();
lines.add(new Pair<>(new ItemStack(Items.BEE_NEST), count == -1 ? Component.empty() :
Component.translatable(
"hexcasting.tooltip.lens.bee" + (count == 1 ? ".single" : ""),
count
)));
});
ScryingLensOverlayRegistry.addPredicateDisplayer(
(state, pos, observer, world, direction) -> state.isSignalSource() && !state.is(
Blocks.COMPARATOR),
(lines, state, pos, observer, world, direction) -> {
int signalStrength = 0;
if (state.getBlock() instanceof RedStoneWireBlock) {
signalStrength = state.getValue(RedStoneWireBlock.POWER);
} else {
for (Direction dir : Direction.values()) {
signalStrength = Math.max(signalStrength, state.getSignal(world, pos, dir));
}
}
lines.add(0, new Pair<>(
new ItemStack(Items.REDSTONE),
Component.literal(String.valueOf(signalStrength))
.withStyle(redstoneColor(signalStrength))));
});
ScryingLensOverlayRegistry.addPredicateDisplayer(
(state, pos, observer, world, direction) -> state.hasAnalogOutputSignal(),
(lines, state, pos, observer, world, direction) -> {
int comparatorValue = ScryingLensOverlayRegistry.getComparatorValue(false);
lines.add(
new Pair<>(
new ItemStack(Items.COMPARATOR),
Component.literal(comparatorValue == -1 ? "" : String.valueOf(comparatorValue))
.withStyle(redstoneColor(comparatorValue))));
});
}
private static int getPoweredRailStrength(Level level, BlockPos pos, BlockState state) {
if (level.hasNeighborSignal(pos))
return 9;
int positiveValue = findPoweredRailSignal(level, pos, state, true, 0);
int negativeValue = findPoweredRailSignal(level, pos, state, false, 0);
return Math.max(positiveValue, negativeValue);
}
// Copypasta from PoweredRailBlock.class
private static int findPoweredRailSignal(Level level, BlockPos pos, BlockState state, boolean travelPositive,
int depth) {
if (depth >= 8) {
return 0;
} else {
int x = pos.getX();
int y = pos.getY();
int z = pos.getZ();
boolean descending = true;
RailShape shape = state.getValue(PoweredRailBlock.SHAPE);
switch (shape) {
case NORTH_SOUTH:
if (travelPositive) {
++z;
} else {
--z;
}
break;
case EAST_WEST:
if (travelPositive) {
--x;
} else {
++x;
}
break;
case ASCENDING_EAST:
if (travelPositive) {
--x;
} else {
++x;
++y;
descending = false;
}
shape = RailShape.EAST_WEST;
break;
case ASCENDING_WEST:
if (travelPositive) {
--x;
++y;
descending = false;
} else {
++x;
}
shape = RailShape.EAST_WEST;
break;
case ASCENDING_NORTH:
if (travelPositive) {
++z;
} else {
--z;
++y;
descending = false;
}
shape = RailShape.NORTH_SOUTH;
break;
case ASCENDING_SOUTH:
if (travelPositive) {
++z;
++y;
descending = false;
} else {
--z;
}
shape = RailShape.NORTH_SOUTH;
}
int power = getPowerFromRail(level, new BlockPos(x, y, z), travelPositive, depth,
shape);
if (power > 0) {
return power;
} else if (descending) {
return getPowerFromRail(level, new BlockPos(x, y - 1, z), travelPositive, depth,
shape);
} else {
return 0;
}
}
}
private static UnaryOperator<Style> color(int color) {
return (style) -> style.withColor(TextColor.fromRgb(color));
}
private static UnaryOperator<Style> redstoneColor(int power) {
return redstoneColor(power, 15);
}
private static UnaryOperator<Style> redstoneColor(int power, int max) {
return color(RedStoneWireBlock.getColorForPower(Mth.clamp((power * max) / 15, 0, 15)));
}
private static int instrumentColor(NoteBlockInstrument instrument) {
return switch (instrument) {
case BASEDRUM -> MaterialColor.STONE.col;
case SNARE, XYLOPHONE, PLING -> MaterialColor.SAND.col;
case HAT -> MaterialColor.QUARTZ.col;
case BASS -> MaterialColor.WOOD.col;
case FLUTE -> MaterialColor.CLAY.col;
case BELL -> MaterialColor.GOLD.col;
case GUITAR -> MaterialColor.WOOL.col;
case CHIME -> MaterialColor.ICE.col;
case IRON_XYLOPHONE -> MaterialColor.METAL.col;
case COW_BELL -> MaterialColor.COLOR_BROWN.col;
case DIDGERIDOO -> MaterialColor.COLOR_ORANGE.col;
case BIT -> MaterialColor.EMERALD.col;
case BANJO -> MaterialColor.COLOR_YELLOW.col;
default -> -1;
};
}
private static int getPowerFromRail(Level level, BlockPos pos, boolean travelPositive, int depth, RailShape shape) {
BlockState otherState = level.getBlockState(pos);
if (!otherState.is(Blocks.POWERED_RAIL)) {
return 0;
} else {
RailShape otherShape = otherState.getValue(PoweredRailBlock.SHAPE);
if (shape == RailShape.EAST_WEST && (otherShape == RailShape.NORTH_SOUTH || otherShape == RailShape.ASCENDING_NORTH || otherShape == RailShape.ASCENDING_SOUTH)) {
return 0;
} else if (shape == RailShape.NORTH_SOUTH && (otherShape == RailShape.EAST_WEST || otherShape == RailShape.ASCENDING_EAST || otherShape == RailShape.ASCENDING_WEST)) {
return 0;
} else if (otherState.getValue(PoweredRailBlock.POWERED)) {
return level.hasNeighborSignal(pos) ? 8 - depth : findPoweredRailSignal(level, pos, otherState,
travelPositive, depth + 1);
} else {
return 0;
}
}
}
}

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.client.be;
package at.petrak.hexcasting.client.render.be;
import at.petrak.hexcasting.api.casting.math.HexPattern;
import at.petrak.hexcasting.client.RenderLib;
import at.petrak.hexcasting.client.render.RenderLib;
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicBookshelf;
import at.petrak.hexcasting.common.blocks.akashic.BlockEntityAkashicBookshelf;
import com.mojang.blaze3d.systems.RenderSystem;
@ -22,7 +22,7 @@ public class BlockEntityAkashicBookshelfRenderer implements BlockEntityRenderer<
@Override
public void render(BlockEntityAkashicBookshelf tile, float pPartialTick, PoseStack ps,
MultiBufferSource buffer, int light, int overlay) {
MultiBufferSource buffer, int light, int overlay) {
HexPattern pattern = tile.getPattern();
if (pattern == null) {
return;

View file

@ -0,0 +1,54 @@
package at.petrak.hexcasting.client.render.be;
import at.petrak.hexcasting.client.RegisterClientStuff;
import at.petrak.hexcasting.client.render.GaslightingTracker;
import at.petrak.hexcasting.common.blocks.BlockQuenchedAllay;
import at.petrak.hexcasting.common.blocks.entity.BlockEntityQuenchedAllay;
import at.petrak.hexcasting.xplat.IClientXplatAbstractions;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.world.phys.AABB;
// TODO: this doesn't cover the block being *behind* something. Is it possible to cleanly do that?
// it would probably require some depth-texture bullshit that I don't want to worry about
public class BlockEntityQuenchedAllayRenderer implements BlockEntityRenderer<BlockEntityQuenchedAllay> {
private final BlockEntityRendererProvider.Context ctx;
public BlockEntityQuenchedAllayRenderer(BlockEntityRendererProvider.Context ctx) {
this.ctx = ctx;
}
private static void doRender(BlockRenderDispatcher dispatcher, PoseStack ps, MultiBufferSource bufSource,
int packedLight, int packedOverlay) {
var buffer = bufSource.getBuffer(RenderType.translucent());
var pose = ps.last();
var idx = Math.abs(GaslightingTracker.getGaslightingAmount() % BlockQuenchedAllay.VARIANTS);
var model = RegisterClientStuff.QUENCHED_ALLAY_VARIANTS.get(idx);
dispatcher.getModelRenderer().renderModel(pose, buffer, null, model, 1f, 1f, 1f, packedLight, packedOverlay);
}
@Override
public void render(BlockEntityQuenchedAllay blockEntity, float partialTick, PoseStack poseStack,
MultiBufferSource bufferSource, int packedLight, int packedOverlay) {
// https://github.com/MinecraftForge/MinecraftForge/blob/79dfdb0ace9694f9dd0f1d9e8c5c24a0ae2d77f8/patches/minecraft/net/minecraft/client/renderer/LevelRenderer.java.patch#L68
// Forge fixes BEs rendering offscreen; Fabric doesn't!
// So we do a special check on Fabric only
var pos = blockEntity.getBlockPos();
var aabb = new AABB(pos.offset(-1, 0, -1), pos.offset(1, 1, 1));
if (IClientXplatAbstractions.INSTANCE.fabricAdditionalQuenchFrustumCheck(aabb)) {
doRender(this.ctx.getBlockRenderDispatcher(), poseStack, bufferSource, packedLight, packedOverlay);
}
}
@Override
public boolean shouldRenderOffScreen(BlockEntityQuenchedAllay blockEntity) {
return false;
}
}

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.client.be;
package at.petrak.hexcasting.client.render.be;
import at.petrak.hexcasting.client.RenderLib;
import at.petrak.hexcasting.client.render.RenderLib;
import at.petrak.hexcasting.common.blocks.circles.BlockEntitySlate;
import at.petrak.hexcasting.common.blocks.circles.BlockSlate;
import com.mojang.blaze3d.systems.RenderSystem;
@ -22,7 +22,7 @@ public class BlockEntitySlateRenderer implements BlockEntityRenderer<BlockEntity
@Override
public void render(BlockEntitySlate tile, float pPartialTick, PoseStack ps,
MultiBufferSource buffer, int light, int overlay) {
MultiBufferSource buffer, int light, int overlay) {
if (tile.pattern == null) {
return;
}

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.client.shader;
package at.petrak.hexcasting.client.render.shader;
import at.petrak.hexcasting.mixin.accessor.client.AccessorCompositeRenderType;
import at.petrak.hexcasting.mixin.accessor.client.AccessorEmptyTextureStateShard;
@ -13,13 +13,14 @@ import org.jetbrains.annotations.NotNull;
import java.util.Optional;
import java.util.function.Function;
public record FakeBufferSource(MultiBufferSource parent, Function<ResourceLocation, RenderType> mapper) implements MultiBufferSource {
public record FakeBufferSource(MultiBufferSource parent,
Function<ResourceLocation, RenderType> mapper) implements MultiBufferSource {
@Override
@SuppressWarnings("ConstantConditions")
public @NotNull VertexConsumer getBuffer(@NotNull RenderType renderType) {
if (((AccessorRenderStateShard) renderType).hex$name().equals("entity_cutout_no_cull")
&& renderType instanceof RenderType.CompositeRenderType) {
&& renderType instanceof RenderType.CompositeRenderType) {
RenderType.CompositeState state = ((AccessorCompositeRenderType) renderType).hex$state();
RenderStateShard.EmptyTextureStateShard shard = state.textureState;
Optional<ResourceLocation> texture = ((AccessorEmptyTextureStateShard) shard).hex$cutoutTexture();

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.client.shader;
package at.petrak.hexcasting.client.render.shader;
import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.mixin.accessor.client.AccessorRenderType;
@ -13,27 +13,29 @@ import java.util.function.Function;
// https://github.com/VazkiiMods/Botania/blob/3a43accc2fbc439c9f2f00a698f8f8ad017503db/Common/src/main/java/vazkii/botania/client/core/helper/RenderHelper.java
public final class HexRenderTypes extends RenderType {
private HexRenderTypes(String string, VertexFormat vertexFormat, VertexFormat.Mode mode, int i, boolean bl, boolean bl2, Runnable runnable, Runnable runnable2) {
private HexRenderTypes(String string, VertexFormat vertexFormat, VertexFormat.Mode mode, int i, boolean bl,
boolean bl2, Runnable runnable, Runnable runnable2) {
super(string, vertexFormat, mode, i, bl, bl2, runnable, runnable2);
throw new UnsupportedOperationException("Should not be instantiated");
}
private static RenderType makeLayer(String name, VertexFormat format, VertexFormat.Mode mode,
int bufSize, boolean hasCrumbling, boolean sortOnUpload, RenderType.CompositeState glState) {
int bufSize, boolean hasCrumbling, boolean sortOnUpload, RenderType.CompositeState glState) {
return AccessorRenderType.hex$create(name, format, mode, bufSize, hasCrumbling, sortOnUpload, glState);
}
private static final Function<ResourceLocation, RenderType> GRAYSCALE_PROVIDER = Util.memoize(texture -> {
CompositeState glState = RenderType.CompositeState.builder()
.setShaderState(new ShaderStateShard(HexShaders::grayscale))
.setTextureState(new TextureStateShard(texture, false, false))
.setTransparencyState(NO_TRANSPARENCY)
.setCullState(NO_CULL)
.setLightmapState(LIGHTMAP)
.setOverlayState(OVERLAY)
.createCompositeState(true);
.setShaderState(new ShaderStateShard(HexShaders::grayscale))
.setTextureState(new TextureStateShard(texture, false, false))
.setTransparencyState(NO_TRANSPARENCY)
.setCullState(NO_CULL)
.setLightmapState(LIGHTMAP)
.setOverlayState(OVERLAY)
.createCompositeState(true);
return makeLayer(HexAPI.MOD_ID + ":grayscale", DefaultVertexFormat.NEW_ENTITY, VertexFormat.Mode.QUADS, 256, true, false, glState);
return makeLayer(HexAPI.MOD_ID + ":grayscale", DefaultVertexFormat.NEW_ENTITY, VertexFormat.Mode.QUADS, 256,
true, false, glState);
});
public static RenderType getGrayscaleLayer(ResourceLocation texture) {

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.client.shader;
package at.petrak.hexcasting.client.render.shader;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.datafixers.util.Pair;
@ -11,11 +11,12 @@ import java.util.function.Consumer;
// https://github.com/VazkiiMods/Botania/blob/3a43accc2fbc439c9f2f00a698f8f8ad017503db/Common/src/main/java/vazkii/botania/client/core/helper/CoreShaders.java
public class HexShaders {
private static ShaderInstance grayscale;
public static void init(ResourceManager resourceManager,
Consumer<Pair<ShaderInstance, Consumer<ShaderInstance>>> registrations) throws IOException {
Consumer<Pair<ShaderInstance, Consumer<ShaderInstance>>> registrations) throws IOException {
registrations.accept(Pair.of(
new ShaderInstance(resourceManager, "hexcasting__grayscale", DefaultVertexFormat.NEW_ENTITY),
inst -> grayscale = inst)
new ShaderInstance(resourceManager, "hexcasting__grayscale", DefaultVertexFormat.NEW_ENTITY),
inst -> grayscale = inst)
);
}

View file

@ -0,0 +1,59 @@
package at.petrak.hexcasting.common.blocks;
import at.petrak.hexcasting.common.blocks.entity.BlockEntityQuenchedAllay;
import at.petrak.hexcasting.common.particles.ConjureParticleOptions;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
public class BlockQuenchedAllay extends Block implements EntityBlock {
public static final int VARIANTS = 4;
public BlockQuenchedAllay(Properties properties) {
super(properties);
}
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new BlockEntityQuenchedAllay(pos, state);
}
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.INVISIBLE;
}
@Override
public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource rand) {
ParticleOptions options = new ConjureParticleOptions(0x8932b8);
Vec3 center = Vec3.atCenterOf(pos);
for (Direction direction : Direction.values()) {
int dX = direction.getStepX();
int dY = direction.getStepY();
int dZ = direction.getStepZ();
int count = rand.nextInt(10) / 4;
for (int i = 0; i < count; i++) {
double pX = center.x + (dX == 0 ? Mth.nextDouble(rand, -0.5D, 0.5D) : (double) dX * 0.55D);
double pY = center.y + (dY == 0 ? Mth.nextDouble(rand, -0.5D, 0.5D) : (double) dY * 0.55D);
double pZ = center.z + (dZ == 0 ? Mth.nextDouble(rand, -0.5D, 0.5D) : (double) dZ * 0.55D);
double vPerp = Mth.nextDouble(rand, 0.0, 0.01);
double vX = vPerp * dX;
double vY = vPerp * dY;
double vZ = vPerp * dZ;
level.addParticle(options, pX, pY, pZ, vX, vY, vZ);
}
}
}
}

View file

@ -2,7 +2,7 @@ package at.petrak.hexcasting.common.blocks.akashic;
import at.petrak.hexcasting.annotations.SoftImplement;
import at.petrak.hexcasting.api.casting.iota.PatternIota;
import at.petrak.hexcasting.common.items.ItemScroll;
import at.petrak.hexcasting.common.items.storage.ItemScroll;
import at.petrak.hexcasting.common.lib.HexSounds;
import at.petrak.hexcasting.xplat.IForgeLikeBlock;
import net.minecraft.core.BlockPos;

View file

@ -32,7 +32,7 @@ public class BlockSconce extends AmethystBlock {
var cy = pPos.getY() + 0.5;
var cz = pPos.getZ() + 0.5;
int[] colors = {0xff_6f4fab, 0xff_b38ef3, 0xff_cfa0f3, 0xff_cfa0f3, 0xff_fffdd5};
pLevel.addParticle(new ConjureParticleOptions(colors[rand.nextInt(colors.length)], true), cx, cy, cz,
pLevel.addParticle(new ConjureParticleOptions(colors[rand.nextInt(colors.length)]), cx, cy, cz,
rand.triangle(-0.01f, 0.01f), rand.triangle(0.01f, 0.05f), rand.triangle(-0.01f, 0.01f));
if (rand.nextFloat() < 0.08f) {
pLevel.playLocalSound(cx, cy, cz,

View file

@ -31,7 +31,7 @@ public class BlockEntityConjured extends HexBlockEntity {
.add(new Vec3(RANDOM.nextFloat(), RANDOM.nextFloat(), RANDOM.nextFloat()).scale(
RANDOM.nextFloat() * 3)));
assert level != null;
level.addParticle(new ConjureParticleOptions(color, false),
level.addParticle(new ConjureParticleOptions(color),
pEntity.getX() + (RANDOM.nextFloat() * 0.6D) - 0.3D,
getBlockPos().getY() + (RANDOM.nextFloat() * 0.05D) + 0.95D,
pEntity.getZ() + (RANDOM.nextFloat() * 0.6D) - 0.3D,
@ -50,7 +50,7 @@ public class BlockEntityConjured extends HexBlockEntity {
assert level != null;
if (getBlockState().getBlock() instanceof BlockConjuredLight) {
if (RANDOM.nextFloat() < 0.5) {
level.addParticle(new ConjureParticleOptions(color, true),
level.addParticle(new ConjureParticleOptions(color),
(double) getBlockPos().getX() + 0.45D + (RANDOM.nextFloat() * 0.1D),
(double) getBlockPos().getY() + 0.45D + (RANDOM.nextFloat() * 0.1D),
(double) getBlockPos().getZ() + 0.45D + (RANDOM.nextFloat() * 0.1D),
@ -60,7 +60,7 @@ public class BlockEntityConjured extends HexBlockEntity {
}
} else {
if (RANDOM.nextFloat() < 0.2) {
level.addParticle(new ConjureParticleOptions(color, false),
level.addParticle(new ConjureParticleOptions(color),
(double) getBlockPos().getX() + RANDOM.nextFloat(),
(double) getBlockPos().getY() + RANDOM.nextFloat(),
(double) getBlockPos().getZ() + RANDOM.nextFloat(),
@ -78,7 +78,7 @@ public class BlockEntityConjured extends HexBlockEntity {
.add(new Vec3(RANDOM.nextFloat(), RANDOM.nextFloat(), RANDOM.nextFloat()).scale(
RANDOM.nextFloat() * 3)));
assert level != null;
level.addParticle(new ConjureParticleOptions(color, false),
level.addParticle(new ConjureParticleOptions(color),
entity.getX() + (RANDOM.nextFloat() * 0.8D) - 0.2D,
getBlockPos().getY() + (RANDOM.nextFloat() * 0.05D) + 0.95D,
entity.getZ() + (RANDOM.nextFloat() * 0.8D) - 0.2D,

View file

@ -0,0 +1,26 @@
package at.petrak.hexcasting.common.blocks.entity;
import at.petrak.hexcasting.api.block.HexBlockEntity;
import at.petrak.hexcasting.common.lib.HexBlockEntities;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.state.BlockState;
/**
* No-op BE just to have a BER
*/
public class BlockEntityQuenchedAllay extends HexBlockEntity {
public BlockEntityQuenchedAllay(BlockPos pos, BlockState blockState) {
super(HexBlockEntities.QUENCHED_ALLAY_TILE, pos, blockState);
}
@Override
protected void saveModData(CompoundTag tag) {
}
@Override
protected void loadModData(CompoundTag tag) {
}
}

View file

@ -1,13 +1,13 @@
package at.petrak.hexcasting.common.casting.operators.spells
import at.petrak.hexcasting.api.misc.MediaConstants
import at.petrak.hexcasting.api.mod.HexConfig
import at.petrak.hexcasting.api.casting.ParticleSpray
import at.petrak.hexcasting.api.casting.RenderedSpell
import at.petrak.hexcasting.api.casting.castables.SpellAction
import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.getBlockPos
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.misc.MediaConstants
import at.petrak.hexcasting.api.mod.HexConfig
import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.minecraft.core.BlockPos
import net.minecraft.world.phys.Vec3
@ -25,7 +25,7 @@ object OpBreakBlock : SpellAction {
return Triple(
Spell(pos),
(MediaConstants.DUST_UNIT * 1.125).toInt(),
MediaConstants.DUST_UNIT / 8,
listOf(ParticleSpray.burst(Vec3.atCenterOf(pos), 1.0))
)
}

View file

@ -0,0 +1,197 @@
package at.petrak.hexcasting.common.casting.operators.spells
import at.petrak.hexcasting.api.casting.ParticleSpray
import at.petrak.hexcasting.api.casting.RenderedSpell
import at.petrak.hexcasting.api.casting.castables.SpellAction
import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.getPlayer
import at.petrak.hexcasting.api.casting.getPositiveDouble
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.misc.MediaConstants
import at.petrak.hexcasting.api.player.FlightAbility
import at.petrak.hexcasting.common.lib.HexItems
import at.petrak.hexcasting.common.lib.HexSounds
import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.minecraft.Util
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.sounds.SoundSource
import net.minecraft.util.Mth
import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.ItemStack
import net.minecraft.world.phys.Vec3
import kotlin.math.max
import kotlin.math.roundToInt
class OpFlight(val type: Type) : SpellAction {
override val argc = 2
override fun execute(
args: List<Iota>,
ctx: CastingEnvironment
): Triple<RenderedSpell, Int, List<ParticleSpray>> {
val target = args.getPlayer(0, argc)
val theArg = args.getPositiveDouble(1, argc)
ctx.assertEntityInRange(target)
val cost = when (this.type) {
Type.LimitRange -> theArg * MediaConstants.DUST_UNIT
// A second of flight should cost 1 shard
Type.LimitTime -> theArg * MediaConstants.SHARD_UNIT
}.roundToInt()
// Convert to ticks
return Triple(
Spell(this.type, target, theArg),
cost,
listOf(ParticleSpray(target.position(), Vec3(0.0, 2.0, 0.0), 0.0, 0.1))
)
}
enum class Type {
LimitRange,
LimitTime;
}
data class Spell(val type: Type, val target: ServerPlayer, val theArg: Double) : RenderedSpell {
override fun cast(ctx: CastingEnvironment) {
if (target.abilities.mayfly) {
// Don't accidentally clobber someone else's flight
// TODO make this a mishap?
return
}
val dim = target.level.dimension()
val origin = target.position()
val flight = when (this.type) {
Type.LimitRange -> FlightAbility(-1, dim, origin, theArg)
Type.LimitTime -> FlightAbility((theArg * 20.0).roundToInt(), dim, origin, -1.0)
}
IXplatAbstractions.INSTANCE.setFlight(target, flight)
target.abilities.mayfly = true
target.onUpdateAbilities()
}
}
companion object {
// blocks from the edge
private val DIST_DANGER_THRESHOLD = 4.0
// seconds left
private val TIME_DANGER_THRESHOLD = 7.0 * 20.0
@JvmStatic
fun tickAllPlayers(world: ServerLevel) {
for (player in world.players()) {
tickDownFlight(player)
}
}
@JvmStatic
fun tickDownFlight(player: ServerPlayer) {
val flight = IXplatAbstractions.INSTANCE.getFlight(player)
if (flight != null) {
val danger = getDanger(player, flight)
if (danger >= 1.0) {
IXplatAbstractions.INSTANCE.setFlight(player, null)
// stop shin smashing bonke
if (!player.isCreative && !player.isSpectator) {
val abilities = player.abilities
abilities.flying = false
abilities.mayfly = false
player.onUpdateAbilities()
}
player.level.playSound(null, player.x, player.y, player.z, HexSounds.FLIGHT_FINISH, SoundSource.PLAYERS, 2f, 1f)
val superDangerSpray = ParticleSpray(player.position(), Vec3(0.0, 1.0, 0.0), Math.PI, 0.4, count = 20)
superDangerSpray.sprayParticles(player.getLevel(), FrozenColorizer(ItemStack(HexItems.DYE_COLORIZERS[DyeColor.RED]!!), Util.NIL_UUID))
superDangerSpray.sprayParticles(player.getLevel(), FrozenColorizer(ItemStack(HexItems.DYE_COLORIZERS[DyeColor.BLACK]!!), Util.NIL_UUID))
} else {
if (!player.abilities.mayfly) {
player.abilities.mayfly = true
player.onUpdateAbilities()
}
val time2 = if (flight.timeLeft >= 0) {
flight.timeLeft - 1
} else {
flight.timeLeft
}
IXplatAbstractions.INSTANCE.setFlight(
player,
FlightAbility(
time2,
flight.dimension,
flight.origin,
flight.radius
)
)
val particleCount = 5
val dangerParticleCount = (particleCount * danger).roundToInt()
val okParticleCount = particleCount - dangerParticleCount
val oneDangerParticleCount = Mth.ceil(dangerParticleCount / 2.0)
val color = IXplatAbstractions.INSTANCE.getColorizer(player)
// TODO: have the particles go in the opposite direction of the velocity?
ParticleSpray(player.position(), Vec3(0.0, -0.6, 0.0), 0.6, Math.PI * 0.3, count = okParticleCount)
.sprayParticles(player.getLevel(), color)
val dangerSpray = ParticleSpray(player.position(), Vec3(0.0, 1.0, 0.0), 0.3, Math.PI * 0.75, count = 0)
dangerSpray.copy(count = oneDangerParticleCount)
.sprayParticles(player.getLevel(), FrozenColorizer(ItemStack(HexItems.DYE_COLORIZERS[DyeColor.BLACK]!!), Util.NIL_UUID))
dangerSpray.copy(count = oneDangerParticleCount)
.sprayParticles(player.getLevel(), FrozenColorizer(ItemStack(HexItems.DYE_COLORIZERS[DyeColor.RED]!!), Util.NIL_UUID))
if (player.level.random.nextFloat() < 0.02)
player.level.playSound(null, player.x, player.y, player.z, HexSounds.FLIGHT_AMBIENCE, SoundSource.PLAYERS, 0.2f, 1f)
if (flight.radius >= 0.0) {
// Show the origin
val spoofedOrigin = flight.origin.add(0.0, 1.0, 0.0)
ParticleSpray(spoofedOrigin, Vec3(0.0, 1.0, 0.0), 0.5, Math.PI * 0.1, count = 5)
.sprayParticles(player.getLevel(), color)
ParticleSpray(spoofedOrigin, Vec3(0.0, -1.0, 0.0), 1.5, Math.PI * 0.25, count = 5)
.sprayParticles(player.getLevel(), color)
}
}
}
}
// Return a number from 0 (totally fine) to 1 (danger will robinson, stop the flight)
// it's a double for particle reason
private fun getDanger(player: ServerPlayer, flight: FlightAbility): Double {
val radiusDanger = if (flight.radius >= 0.0) {
if (player.level.dimension() != flight.dimension) {
1.0
} else {
// Limit it only in X/Z
val posXZ = Vec3(player.x, 0.0, player.z)
val originXZ = Vec3(flight.origin.x, 0.0, flight.origin.z)
val dist = posXZ.distanceTo(originXZ)
val distFromEdge = flight.radius - dist
if (distFromEdge >= DIST_DANGER_THRESHOLD) {
0.0
} else if (dist > flight.radius) {
1.0
} else {
1.0 - (distFromEdge / DIST_DANGER_THRESHOLD)
}
}
} else 0.0
val timeDanger = if (flight.timeLeft >= 0) {
if (flight.timeLeft >= TIME_DANGER_THRESHOLD) {
0.0
} else {
val timeDanger = TIME_DANGER_THRESHOLD - flight.timeLeft
timeDanger / TIME_DANGER_THRESHOLD
}
} else 0.0
return max(radiusDanger, timeDanger)
}
}
}

View file

@ -0,0 +1,74 @@
package at.petrak.hexcasting.common.casting.operators.spells.great
import at.petrak.hexcasting.api.casting.ParticleSpray
import at.petrak.hexcasting.api.casting.RenderedSpell
import at.petrak.hexcasting.api.casting.castables.SpellAction
import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.getPlayer
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.misc.MediaConstants
import at.petrak.hexcasting.api.player.AltioraAbility
import at.petrak.hexcasting.common.lib.HexSounds
import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.sounds.SoundSource
import net.minecraft.world.phys.Vec3
import kotlin.math.max
object OpAltiora : SpellAction {
override val argc = 1
override fun execute(args: List<Iota>, ctx: CastingEnvironment): Triple<RenderedSpell, Int, List<ParticleSpray>> {
val target = args.getPlayer(0, argc)
ctx.assertEntityInRange(target)
return Triple(
Spell(target),
MediaConstants.CRYSTAL_UNIT,
listOf(
ParticleSpray.burst(target.position(), 0.5),
ParticleSpray(target.position(), Vec3(0.0, 2.0, 0.0), 0.0, 0.1)
)
)
}
private data class Spell(val target: ServerPlayer) : RenderedSpell {
override fun cast(ctx: CastingEnvironment) {
target.push(0.0, 1.5, 0.0)
// They won't move otherwise?
target.hurtMarked = true
IXplatAbstractions.INSTANCE.setAltiora(target, AltioraAbility(GRACE_PERIOD))
}
}
@JvmStatic
fun checkPlayerCollision(player: ServerPlayer) {
val altiora = IXplatAbstractions.INSTANCE.getAltiora(player);
if (altiora != null) {
if (altiora.gracePeriod == 0 && (player.isOnGround || player.horizontalCollision)) {
IXplatAbstractions.INSTANCE.setAltiora(player, null)
player.level.playSound(null, player.x, player.y, player.z, HexSounds.FLIGHT_FINISH, SoundSource.PLAYERS, 2f, 1f)
} else {
val grace2 = max(altiora.gracePeriod - 1, 0)
IXplatAbstractions.INSTANCE.setAltiora(player, AltioraAbility(grace2))
if (player.level.random.nextFloat() < 0.02)
player.level.playSound(null, player.x, player.y, player.z, HexSounds.FLIGHT_AMBIENCE, SoundSource.PLAYERS, 0.2f, 1f)
val color = IXplatAbstractions.INSTANCE.getColorizer(player)
ParticleSpray(player.position(), Vec3(0.0, -0.2, 0.0), 0.4, Math.PI * 0.5, count = 3)
.sprayParticles(player.getLevel(), color)
}
}
}
fun checkAllPlayers(world: ServerLevel) {
for (player in world.players()) {
checkPlayerCollision(player)
}
}
private val GRACE_PERIOD = 20
}

View file

@ -1,107 +0,0 @@
package at.petrak.hexcasting.common.casting.operators.spells.great
import at.petrak.hexcasting.api.casting.*
import at.petrak.hexcasting.api.casting.castables.SpellAction
import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.misc.MediaConstants
import at.petrak.hexcasting.api.player.FlightAbility
import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.phys.Vec3
import kotlin.math.roundToInt
object OpFlight : SpellAction {
override val argc = 3
override fun execute(
args: List<Iota>,
ctx: CastingEnvironment
): Triple<RenderedSpell, Int, List<ParticleSpray>> {
val target = args.getPlayer(0, argc)
val timeRaw = args.getPositiveDouble(1, argc)
val radiusRaw = args.getPositiveDouble(2, argc)
ctx.assertEntityInRange(target)
// Convert to ticks
val time = (timeRaw * 20.0).roundToInt()
return Triple(
Spell(target, time, radiusRaw, ctx.position),
(MediaConstants.DUST_UNIT * 0.25 * (timeRaw * radiusRaw + 1.0)).roundToInt(),
listOf(ParticleSpray(target.position(), Vec3(0.0, 2.0, 0.0), 0.0, 0.1))
)
}
data class Spell(val target: ServerPlayer, val time: Int, val radius: Double, val origin: Vec3) : RenderedSpell {
override fun cast(ctx: CastingEnvironment) {
if (target.abilities.mayfly) {
// Don't accidentally clobber someone else's flight
return
}
IXplatAbstractions.INSTANCE.setFlight(
target,
FlightAbility(
true,
time,
target.level.dimension(),
origin,
radius
)
)
target.abilities.mayfly = true
target.abilities.flying = true
target.onUpdateAbilities()
// Launch the player into the air to really emphasize the flight
target.push(0.0, 1.0, 0.0)
target.hurtMarked = true // Whyyyyy
}
}
fun tickDownFlight(entity: LivingEntity) {
if (entity !is ServerPlayer) return
val flight = IXplatAbstractions.INSTANCE.getFlight(entity)
if (flight.allowed) {
val flightTime = flight.timeLeft - 1
if (flightTime < 0 || flight.origin.distanceToSqr(entity.position()) > flight.radius * flight.radius || flight.dimension != entity.level.dimension()) {
if (!entity.isOnGround) {
entity.fallDistance = 1_000_000f
}
IXplatAbstractions.INSTANCE.setFlight(entity, FlightAbility.deny())
if (!entity.isCreative && !entity.isSpectator) {
val abilities = entity.abilities
abilities.flying = false
abilities.mayfly = false
entity.onUpdateAbilities()
}
} else {
if (!entity.abilities.mayfly) {
entity.abilities.mayfly = true
entity.onUpdateAbilities()
}
IXplatAbstractions.INSTANCE.setFlight(
entity,
FlightAbility(
true,
flightTime,
flight.dimension,
flight.origin,
flight.radius
)
)
}
}
}
fun tickAllPlayers(world: ServerLevel) {
for (player in world.players()) {
tickDownFlight(player)
}
}
}

View file

@ -3,7 +3,7 @@ package at.petrak.hexcasting.common.command;
import at.petrak.hexcasting.api.casting.iota.PatternIota;
import at.petrak.hexcasting.api.casting.math.HexPattern;
import at.petrak.hexcasting.common.casting.PatternRegistryManifest;
import at.petrak.hexcasting.common.items.ItemScroll;
import at.petrak.hexcasting.common.items.storage.ItemScroll;
import at.petrak.hexcasting.common.lib.HexItems;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.commands.CommandSourceStack;

View file

@ -3,8 +3,8 @@ package at.petrak.hexcasting.common.entities;
import at.petrak.hexcasting.api.casting.math.HexPattern;
import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.client.RenderLib;
import at.petrak.hexcasting.common.items.ItemScroll;
import at.petrak.hexcasting.client.render.RenderLib;
import at.petrak.hexcasting.common.items.storage.ItemScroll;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.common.lib.HexSounds;
import at.petrak.hexcasting.common.network.MsgNewWallScrollAck;
@ -53,7 +53,7 @@ public class EntityWallScroll extends HangingEntity {
}
public EntityWallScroll(Level world, BlockPos pos, Direction dir, ItemStack scroll, boolean showStrokeOrder,
int blockSize) {
int blockSize) {
super(HexEntities.WALL_SCROLL, world, pos);
this.setDirection(dir);
this.blockSize = blockSize;
@ -160,7 +160,7 @@ public class EntityWallScroll extends HangingEntity {
}
public void readSpawnData(BlockPos pos, Direction dir, ItemStack scrollItem,
boolean showsStrokeOrder, int blockSize) {
boolean showsStrokeOrder, int blockSize) {
this.pos = pos;
this.scroll = scrollItem;
this.blockSize = blockSize;
@ -203,7 +203,7 @@ public class EntityWallScroll extends HangingEntity {
@Override
public void lerpTo(double pX, double pY, double pZ, float pYaw, float pPitch, int pPosRotationIncrements,
boolean pTeleport) {
boolean pTeleport) {
BlockPos blockpos = this.pos.offset(pX - this.getX(), pY - this.getY(), pZ - this.getZ());
this.setPos(blockpos.getX(), blockpos.getY(), blockpos.getZ());
}

View file

@ -15,7 +15,7 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
public class ItemStaff extends Item {
// 0 = normal. 1 = old. 2 = bosnia
// 0 = normal. 1 = old. 2 = cherry preview
public static final ResourceLocation FUNNY_LEVEL_PREDICATE = new ResourceLocation(HexAPI.MOD_ID, "funny_level");
public ItemStaff(Properties pProperties) {

View file

@ -1,5 +1,6 @@
package at.petrak.hexcasting.common.items.magic;
import at.petrak.hexcasting.api.mod.HexConfig;
import net.minecraft.world.item.ItemStack;
public class ItemArtifact extends ItemPackagedHex {
@ -16,4 +17,9 @@ public class ItemArtifact extends ItemPackagedHex {
public boolean breakAfterDepletion() {
return false;
}
@Override
public int cooldown() {
return HexConfig.common().artifactCooldown();
}
}

View file

@ -1,5 +1,6 @@
package at.petrak.hexcasting.common.items.magic;
import at.petrak.hexcasting.api.mod.HexConfig;
import net.minecraft.world.item.ItemStack;
public class ItemCypher extends ItemPackagedHex {
@ -16,4 +17,9 @@ public class ItemCypher extends ItemPackagedHex {
public boolean breakAfterDepletion() {
return true;
}
@Override
public int cooldown() {
return HexConfig.common().cypherCooldown();
}
}

View file

@ -40,6 +40,8 @@ public abstract class ItemPackagedHex extends ItemMediaHolder implements HexHold
public abstract boolean breakAfterDepletion();
public abstract int cooldown();
@Override
public boolean canRecharge(ItemStack stack) {
return !breakAfterDepletion();
@ -120,7 +122,7 @@ public abstract class ItemPackagedHex extends ItemMediaHolder implements HexHold
}
player.awardStat(stat);
sPlayer.getCooldowns().addCooldown(this, 5);
sPlayer.getCooldowns().addCooldown(this, this.cooldown());
if (broken) {
stack.shrink(1);

View file

@ -1,5 +1,6 @@
package at.petrak.hexcasting.common.items.magic;
import at.petrak.hexcasting.api.mod.HexConfig;
import net.minecraft.world.item.ItemStack;
public class ItemTrinket extends ItemPackagedHex {
@ -16,4 +17,9 @@ public class ItemTrinket extends ItemPackagedHex {
public boolean breakAfterDepletion() {
return false;
}
@Override
public int cooldown() {
return HexConfig.common().trinketCooldown();
}
}

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.common.items;
package at.petrak.hexcasting.common.items.storage;
import at.petrak.hexcasting.api.casting.iota.DoubleIota;
import at.petrak.hexcasting.api.casting.iota.Iota;

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.common.items;
package at.petrak.hexcasting.common.items.storage;
import at.petrak.hexcasting.api.casting.iota.Iota;
import at.petrak.hexcasting.api.casting.iota.IotaType;

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.common.items;
package at.petrak.hexcasting.common.items.storage;
import at.petrak.hexcasting.api.casting.iota.Iota;
import at.petrak.hexcasting.api.casting.iota.PatternIota;

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.common.items;
package at.petrak.hexcasting.common.items.storage;
import at.petrak.hexcasting.annotations.SoftImplement;
import at.petrak.hexcasting.api.HexAPI;

View file

@ -1,4 +1,4 @@
package at.petrak.hexcasting.common.items;
package at.petrak.hexcasting.common.items.storage;
import at.petrak.hexcasting.api.casting.iota.Iota;
import at.petrak.hexcasting.api.casting.iota.IotaType;

View file

@ -0,0 +1,52 @@
package at.petrak.hexcasting.common.items.storage;
import at.petrak.hexcasting.api.casting.iota.Iota;
import at.petrak.hexcasting.api.item.IotaHolderItem;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import static at.petrak.hexcasting.api.HexAPI.modLoc;
// Would love to be able to just write to a piece of string but the api requires it to be the same item
public class ItemThoughtKnot extends Item implements IotaHolderItem {
public static final ResourceLocation WRITTEN_PRED = modLoc("written");
public static final String TAG_DATA = "data";
public ItemThoughtKnot(Properties properties) {
super(properties);
}
@Override
public @Nullable CompoundTag readIotaTag(ItemStack stack) {
return NBTHelper.getCompound(stack, TAG_DATA);
}
@Override
public boolean canWrite(ItemStack stack, @Nullable Iota iota) {
return iota != null && !NBTHelper.contains(stack, TAG_DATA);
}
@Override
public void writeDatum(ItemStack stack, @Nullable Iota iota) {
if (iota != null) {
NBTHelper.putCompound(stack, TAG_DATA, HexIotaTypes.serialize(iota));
}
}
@Override
public void appendHoverText(ItemStack pStack, @Nullable Level pLevel,
List<Component> pTooltipComponents, TooltipFlag pIsAdvanced) {
IotaHolderItem.appendHoverText(this, pStack, pTooltipComponents, pIsAdvanced);
}
}

View file

@ -3,10 +3,7 @@ package at.petrak.hexcasting.common.lib;
import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.common.blocks.akashic.BlockEntityAkashicBookshelf;
import at.petrak.hexcasting.common.blocks.circles.BlockEntitySlate;
import at.petrak.hexcasting.common.blocks.entity.BlockEntityConjured;
import at.petrak.hexcasting.common.blocks.entity.BlockEntityLookingImpetus;
import at.petrak.hexcasting.common.blocks.entity.BlockEntityRightClickImpetus;
import at.petrak.hexcasting.common.blocks.entity.BlockEntityStoredPlayerImpetus;
import at.petrak.hexcasting.common.blocks.entity.*;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
@ -51,6 +48,9 @@ public class HexBlockEntities {
"slate_tile",
BlockEntitySlate::new, HexBlocks.SLATE);
public static final BlockEntityType<BlockEntityQuenchedAllay> QUENCHED_ALLAY_TILE = register(
"quenched_allay_tile", BlockEntityQuenchedAllay::new, HexBlocks.QUENCHED_ALLAY);
private static <T extends BlockEntity> BlockEntityType<T> register(String id,
BiFunction<BlockPos, BlockState, T> func, Block... blocks) {
var ret = IXplatAbstractions.INSTANCE.createBlockEntityType(func, blocks);

View file

@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.block.circle.BlockAbstractImpetus;
import at.petrak.hexcasting.common.blocks.BlockConjured;
import at.petrak.hexcasting.common.blocks.BlockConjuredLight;
import at.petrak.hexcasting.common.blocks.BlockFlammable;
import at.petrak.hexcasting.common.blocks.BlockQuenchedAllay;
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicBookshelf;
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicLigature;
import at.petrak.hexcasting.common.blocks.akashic.BlockAkashicRecord;
@ -20,6 +21,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Rarity;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.material.Material;
@ -146,6 +148,13 @@ public class HexBlocks {
public static final BlockAkashicLigature AKASHIC_LIGATURE = blockItem("akashic_connector",
new BlockAkashicLigature(akashicWoodyHard().lightLevel(bs -> 4)));
// we have to make it emit light because otherwise it occludes itself and is always dark
public static final BlockQuenchedAllay QUENCHED_ALLAY = blockItem("quenched_allay", new BlockQuenchedAllay(
BlockBehaviour.Properties
.copy(Blocks.AMETHYST_BLOCK)
.lightLevel($ -> 4)
.noOcclusion()));
// Decoration?!
public static final Block SLATE_BLOCK = blockItem("slate_block", new Block(slateish().strength(2f, 4f)));
public static final SandBlock AMETHYST_DUST_BLOCK = blockItem("amethyst_dust_block",
@ -166,7 +175,8 @@ public class HexBlocks {
new BlockSconce(BlockBehaviour.Properties.of(Material.AMETHYST, MaterialColor.COLOR_PURPLE)
.sound(SoundType.AMETHYST)
.strength(1f)
.lightLevel($ -> 15)));
.lightLevel($ -> 15)),
HexItems.props().rarity(Rarity.RARE));
public static final BlockAkashicLog EDIFIED_LOG = blockItem("edified_log",
new BlockAkashicLog(edifiedWoody()));

View file

@ -1,10 +1,14 @@
package at.petrak.hexcasting.common.lib;
import at.petrak.hexcasting.common.items.*;
import at.petrak.hexcasting.common.items.ItemJewelerHammer;
import at.petrak.hexcasting.common.items.ItemLens;
import at.petrak.hexcasting.common.items.ItemLoreFragment;
import at.petrak.hexcasting.common.items.ItemStaff;
import at.petrak.hexcasting.common.items.colorizer.ItemDyeColorizer;
import at.petrak.hexcasting.common.items.colorizer.ItemPrideColorizer;
import at.petrak.hexcasting.common.items.colorizer.ItemUUIDColorizer;
import at.petrak.hexcasting.common.items.magic.*;
import at.petrak.hexcasting.common.items.storage.*;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import net.minecraft.Util;
import net.minecraft.resources.ResourceLocation;
@ -32,6 +36,8 @@ public class HexItems {
public static final Item AMETHYST_DUST = make("amethyst_dust", new Item(props()));
public static final Item CHARGED_AMETHYST = make("charged_amethyst", new Item(props()));
public static final Item QUENCHED_SHARD = make("quenched_allay_shard", new Item(props()));
public static final ItemStaff STAFF_OAK = make("oak_staff", new ItemStaff(unstackable()));
public static final ItemStaff STAFF_SPRUCE = make("spruce_staff", new ItemStaff(unstackable()));
public static final ItemStaff STAFF_BIRCH = make("birch_staff", new ItemStaff(unstackable()));
@ -42,6 +48,9 @@ public class HexItems {
public static final ItemStaff STAFF_WARPED = make("warped_staff", new ItemStaff(unstackable()));
public static final ItemStaff STAFF_MANGROVE = make("mangrove_staff", new ItemStaff(unstackable()));
public static final ItemStaff STAFF_EDIFIED = make("edified_staff", new ItemStaff(unstackable()));
public static final ItemStaff STAFF_QUENCHED = make("quenched_staff", new ItemStaff(unstackable()));
// mindsplice staffaratus
public static final ItemStaff STAFF_MINDSPLICE = make("mindsplice_staff", new ItemStaff(unstackable()));
public static final ItemLens SCRYING_LENS = make("lens", new ItemLens(
IXplatAbstractions.INSTANCE.addEquipSlotFabric(EquipmentSlot.HEAD)
@ -49,6 +58,7 @@ public class HexItems {
.tab(IXplatAbstractions.INSTANCE.getTab())));
public static final ItemAbacus ABACUS = make("abacus", new ItemAbacus(unstackable()));
public static final ItemThoughtKnot THOUGHT_KNOT = make("thought_knot", new ItemThoughtKnot(unstackable()));
public static final ItemFocus FOCUS = make("focus", new ItemFocus(unstackable()));
public static final ItemSpellbook SPELLBOOK = make("spellbook", new ItemSpellbook(unstackable()));

View file

@ -25,9 +25,7 @@ public class HexParticles {
private static final Map<ResourceLocation, ParticleType<?>> PARTICLES = new LinkedHashMap<>();
public static final ConjureParticleOptions.Type CONJURE_PARTICLE = register(
"conjure_block_particle", new ConjureParticleOptions.Type(false));
public static final ConjureParticleOptions.Type LIGHT_PARTICLE = register(
"conjure_light_particle", new ConjureParticleOptions.Type(false));
"conjure_particle", new ConjureParticleOptions.Type(false));
private static <O extends ParticleOptions, T extends ParticleType<O>> T register(String id, T particle) {
var old = PARTICLES.put(modLoc(id), particle);
@ -39,12 +37,12 @@ public class HexParticles {
public static class FactoryHandler {
public interface Consumer {
<T extends ParticleOptions> void register(ParticleType<T> type, Function<SpriteSet, ParticleProvider<T>> constructor);
<T extends ParticleOptions> void register(ParticleType<T> type,
Function<SpriteSet, ParticleProvider<T>> constructor);
}
public static void registerFactories(Consumer consumer) {
consumer.register(CONJURE_PARTICLE, ConjureParticle.Provider::new);
consumer.register(LIGHT_PARTICLE, ConjureParticle.Provider::new);
}
}
}

View file

@ -42,6 +42,9 @@ public class HexSounds {
public static final SoundEvent READ_LORE_FRAGMENT = sound("lore_fragment.read");
public static final SoundEvent FLIGHT_AMBIENCE = sound("flight.ambience");
public static final SoundEvent FLIGHT_FINISH = sound("flight.finish");
private static SoundEvent sound(String name) {
var id = modLoc(name);
var sound = new SoundEvent(id);

View file

@ -334,6 +334,13 @@ public class HexActions {
MediaConstants.DUST_UNIT / 3, true, true)
));
public static final ActionRegistryEntry FLIGHT$RANGE = make("flight/range",
new ActionRegistryEntry(HexPattern.fromAngles("awawaawq", HexDir.SOUTH_WEST),
new OpFlight(OpFlight.Type.LimitRange)));
public static final ActionRegistryEntry FLIGHT$TIME = make("flight/time",
new ActionRegistryEntry(HexPattern.fromAngles("dwdwdewq", HexDir.NORTH_EAST),
new OpFlight(OpFlight.Type.LimitTime)));
public static final ActionRegistryEntry SENTINEL$CREATE = make("sentinel/create",
new ActionRegistryEntry(HexPattern.fromAngles("waeawae", HexDir.EAST), new OpCreateSentinel(false)));
public static final ActionRegistryEntry SENTINEL$DESTROY = make("sentinel/destroy",
@ -345,8 +352,11 @@ public class HexActions {
public static final ActionRegistryEntry LIGHTNING = make("lightning",
new ActionRegistryEntry(HexPattern.fromAngles("waadwawdaaweewq", HexDir.EAST), OpLightning.INSTANCE));
public static final ActionRegistryEntry FLIGHT = make("flight",
new ActionRegistryEntry(HexPattern.fromAngles("eawwaeawawaa", HexDir.NORTH_WEST), OpFlight.INSTANCE));
public static final ActionRegistryEntry ALTIORA = make("flight",
new ActionRegistryEntry(HexPattern.fromAngles("eawwaeawawaa", HexDir.NORTH_WEST), OpAltiora.INSTANCE));
public static final ActionRegistryEntry CREATE_LAVA = make("create_lava",
new ActionRegistryEntry(HexPattern.fromAngles("eaqawqadaqd", HexDir.EAST), new OpCreateFluid(
MediaConstants.CRYSTAL_UNIT,

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.common.loot;
import at.petrak.hexcasting.common.casting.PatternRegistryManifest;
import at.petrak.hexcasting.common.items.ItemScroll;
import at.petrak.hexcasting.common.items.storage.ItemScroll;
import at.petrak.hexcasting.common.lib.HexLootFunctions;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.common.network;
import at.petrak.hexcasting.api.misc.FrozenColorizer;
import at.petrak.hexcasting.api.casting.ParticleSpray;
import at.petrak.hexcasting.api.misc.FrozenColorizer;
import at.petrak.hexcasting.common.particles.ConjureParticleOptions;
import io.netty.buffer.ByteBuf;
import net.minecraft.client.Minecraft;
@ -96,7 +96,7 @@ public record MsgCastParticleAck(ParticleSpray spray, FrozenColorizer colorizer)
var vel = velUnlen.scale(msg.spray().getVel().length() / 20);
Minecraft.getInstance().level.addParticle(
new ConjureParticleOptions(color, false),
new ConjureParticleOptions(color),
pos.x, pos.y, pos.z,
vel.x, vel.y, vel.z
);

View file

@ -2,8 +2,8 @@ package at.petrak.hexcasting.common.network;
import at.petrak.hexcasting.api.casting.iota.IotaType;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.common.items.ItemAbacus;
import at.petrak.hexcasting.common.items.ItemSpellbook;
import at.petrak.hexcasting.common.items.storage.ItemAbacus;
import at.petrak.hexcasting.common.items.storage.ItemSpellbook;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.common.lib.HexSounds;
import io.netty.buffer.ByteBuf;

View file

@ -11,21 +11,20 @@ import net.minecraft.network.FriendlyByteBuf;
import java.util.Locale;
public record ConjureParticleOptions(int color, boolean isLight) implements ParticleOptions {
public record ConjureParticleOptions(int color) implements ParticleOptions {
@Override
public ParticleType<?> getType() {
return (this.isLight ? HexParticles.LIGHT_PARTICLE : HexParticles.CONJURE_PARTICLE);
return HexParticles.CONJURE_PARTICLE;
}
@Override
public void writeToNetwork(FriendlyByteBuf buf) {
buf.writeInt(this.color);
buf.writeBoolean(this.isLight);
}
@Override
public String writeToString() {
return String.format(Locale.ROOT, "%s %s", this.color, this.isLight);
return String.format(Locale.ROOT, "%s %s", this.color);
}
public static final Deserializer<ConjureParticleOptions> DESERIALIZER = new Deserializer<>() {
@ -35,18 +34,14 @@ public record ConjureParticleOptions(int color, boolean isLight) implements Part
reader.expect(' ');
var color = reader.readInt();
reader.expect(' ');
var isLight = reader.readBoolean();
return new ConjureParticleOptions(color, isLight);
return new ConjureParticleOptions(color);
}
@Override
public ConjureParticleOptions fromNetwork(ParticleType<ConjureParticleOptions> type,
FriendlyByteBuf buf) {
var col = buf.readInt();
var isLight = buf.readBoolean();
return new ConjureParticleOptions(col, isLight);
return new ConjureParticleOptions(col);
}
};
@ -58,8 +53,7 @@ public record ConjureParticleOptions(int color, boolean isLight) implements Part
public static final Codec<ConjureParticleOptions> CODEC = RecordCodecBuilder.create(
instance -> instance.group(
Codec.INT.fieldOf("color")
.forGetter((ConjureParticleOptions o) -> o.color),
Codec.BOOL.fieldOf("isLight").forGetter(ConjureParticleOptions::isLight)
.forGetter((ConjureParticleOptions o) -> o.color)
)
.apply(instance, ConjureParticleOptions::new)
);

View file

@ -2,7 +2,7 @@ package at.petrak.hexcasting.common.recipe;
import at.petrak.hexcasting.api.item.IotaHolderItem;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.common.items.ItemSpellbook;
import at.petrak.hexcasting.common.items.storage.ItemSpellbook;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import net.minecraft.core.NonNullList;

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.common.recipe;
import at.petrak.hexcasting.api.mod.HexTags;
import at.petrak.hexcasting.common.items.ItemFocus;
import at.petrak.hexcasting.common.items.ItemSpellbook;
import at.petrak.hexcasting.common.items.storage.ItemFocus;
import at.petrak.hexcasting.common.items.storage.ItemSpellbook;
import at.petrak.hexcasting.common.lib.HexItems;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.StringRepresentable;

View file

@ -21,6 +21,7 @@ import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
import net.minecraft.world.level.block.state.properties.SlabType;
import net.minecraft.world.level.storage.loot.LootPool;
import net.minecraft.world.level.storage.loot.LootTable;
import net.minecraft.world.level.storage.loot.entries.AlternativesEntry;
import net.minecraft.world.level.storage.loot.entries.LootItem;
import net.minecraft.world.level.storage.loot.functions.ApplyBonusCount;
import net.minecraft.world.level.storage.loot.functions.ApplyExplosionDecay;
@ -74,10 +75,10 @@ public class HexLootTables extends PaucalLootTableProvider {
blockTables.put(HexBlocks.EDIFIED_DOOR, LootTable.lootTable().withPool(doorPool));
var noSilkTouchCond = MatchTool.toolMatches(
ItemPredicate.Builder.item().hasEnchantment(
new EnchantmentPredicate(Enchantments.SILK_TOUCH, MinMaxBounds.Ints.ANY)))
.invert();
var silkTouchCond = MatchTool.toolMatches(
ItemPredicate.Builder.item().hasEnchantment(
new EnchantmentPredicate(Enchantments.SILK_TOUCH, MinMaxBounds.Ints.ANY)));
var noSilkTouchCond = silkTouchCond.invert();
var goodAtAmethystingCond = MatchTool.toolMatches(
ItemPredicate.Builder.item().of(ItemTags.CLUSTER_MAX_HARVESTABLES)
);
@ -111,6 +112,18 @@ public class HexLootTables extends PaucalLootTableProvider {
.withPool(dustPoolWhenBad)
.withPool(isThatAnMFingBrandonSandersonReference)
.withPool(isThatAnMFingBadBrandonSandersonReference));
// it looks like loot groups are bugged?
// so instead we add some and then *increment* the amount, gated behind the cond
var quenchedPool = LootPool.lootPool().add(AlternativesEntry.alternatives(
LootItem.lootTableItem(HexBlocks.QUENCHED_ALLAY).when(silkTouchCond),
LootItem.lootTableItem(HexItems.QUENCHED_SHARD)
.apply(SetItemCountFunction.setCount(UniformGenerator.between(2f, 4f)))
.apply(SetItemCountFunction.setCount(ConstantValue.exactly(1), true)
.when(BonusLevelTableCondition.bonusLevelFlatChance(Enchantments.BLOCK_FORTUNE,
0.25f, 0.5f, 0.75f, 1.0f)))
));
blockTables.put(HexBlocks.QUENCHED_ALLAY, LootTable.lootTable().withPool(quenchedPool));
}
private void makeLeafTable(Map<Block, LootTable.Builder> lootTables, Block block) {

View file

@ -9,7 +9,6 @@ import at.petrak.hexcasting.common.lib.HexBlocks;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.common.recipe.SealThingsRecipe;
import at.petrak.hexcasting.common.recipe.ingredient.StateIngredientHelper;
import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.EntityTagIngredient;
import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.EntityTypeIngredient;
import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.VillagerIngredient;
import at.petrak.hexcasting.datagen.HexAdvancements;
@ -25,8 +24,6 @@ import net.minecraft.data.DataGenerator;
import net.minecraft.data.recipes.*;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.EntityTypeTags;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.npc.VillagerProfession;
@ -70,7 +67,14 @@ public class HexplatRecipes extends PaucalRecipeProvider {
staffRecipe(recipes, HexItems.STAFF_WARPED, Items.WARPED_PLANKS);
staffRecipe(recipes, HexItems.STAFF_MANGROVE, Items.MANGROVE_PLANKS);
staffRecipe(recipes, HexItems.STAFF_EDIFIED, HexBlocks.EDIFIED_PLANKS.asItem());
staffRecipe(recipes, HexItems.STAFF_QUENCHED, HexItems.QUENCHED_SHARD);
staffRecipe(recipes, HexItems.STAFF_MINDSPLICE, Ingredient.of(HexTags.Items.MINDFLAYED_CIRCLE_COMPONENTS));
ShapelessRecipeBuilder.shapeless(HexItems.THOUGHT_KNOT)
.requires(HexItems.AMETHYST_DUST)
.requires(Items.STRING)
.unlockedBy("has_item", hasItem(HexTags.Items.STAVES))
.save(recipes);
ShapedRecipeBuilder.shaped(HexItems.FOCUS)
.define('G', ingredients.glowstoneDust())
.define('L', ingredients.leather())
@ -229,6 +233,25 @@ public class HexplatRecipes extends PaucalRecipeProvider {
.pattern(" S ")
.unlockedBy("has_item", hasItem(Items.AMETHYST_SHARD)).save(recipes);
ShapelessRecipeBuilder.shapeless(HexItems.AMETHYST_DUST,
(MediaConstants.QUENCHED_SHARD_UNIT / MediaConstants.DUST_UNIT) + 1)
.requires(HexItems.QUENCHED_SHARD)
.requires(HexItems.AMETHYST_DUST)
.unlockedBy("has_item", hasItem(HexItems.QUENCHED_SHARD))
.save(recipes, modLoc("decompose_quenched_shard/dust"));
ShapelessRecipeBuilder.shapeless(Items.AMETHYST_SHARD,
(MediaConstants.QUENCHED_SHARD_UNIT / MediaConstants.SHARD_UNIT) + 1)
.requires(HexItems.QUENCHED_SHARD)
.requires(Items.AMETHYST_SHARD)
.unlockedBy("has_item", hasItem(HexItems.QUENCHED_SHARD))
.save(recipes, modLoc("decompose_quenched_shard/shard"));
ShapelessRecipeBuilder.shapeless(HexItems.CHARGED_AMETHYST,
(MediaConstants.QUENCHED_SHARD_UNIT / MediaConstants.CRYSTAL_UNIT) + 1)
.requires(HexItems.QUENCHED_SHARD)
.requires(HexItems.CHARGED_AMETHYST)
.unlockedBy("has_item", hasItem(HexItems.QUENCHED_SHARD))
.save(recipes, modLoc("decompose_quenched_shard/charged"));
ShapedRecipeBuilder.shaped(HexBlocks.SLATE_BLOCK)
.define('S', HexItems.SLATE)
.pattern("S")
@ -413,16 +436,11 @@ public class HexplatRecipes extends PaucalRecipeProvider {
.save(recipes, modLoc("brainsweep/akashic_record"));
// Temporary tests
new BrainsweepRecipeBuilder(StateIngredientHelper.of(BlockTags.SMALL_FLOWERS),
new BrainsweepRecipeBuilder(StateIngredientHelper.of(Blocks.AMETHYST_BLOCK),
new EntityTypeIngredient(EntityType.ALLAY),
Blocks.AMETHYST_CLUSTER.defaultBlockState(), MediaConstants.SHARD_UNIT)
HexBlocks.QUENCHED_ALLAY.defaultBlockState(), MediaConstants.CRYSTAL_UNIT)
.unlockedBy("enlightenment", enlightenment)
.save(recipes, modLoc("brainsweep/testing/flowey_the_flower"));
new BrainsweepRecipeBuilder(StateIngredientHelper.of(Blocks.SCAFFOLDING),
new EntityTagIngredient(EntityTypeTags.SKELETONS),
Blocks.BONE_BLOCK.defaultBlockState(), MediaConstants.SHARD_UNIT)
.unlockedBy("enlightenment", enlightenment)
.save(recipes, modLoc("brainsweep/testing/bad_to_the_bone"));
.save(recipes, modLoc("brainsweep/quench_allay"));
// Create compat
this.conditions.apply(new CreateCrushingRecipeBuilder()
@ -485,6 +503,10 @@ public class HexplatRecipes extends PaucalRecipeProvider {
}
private void staffRecipe(Consumer<FinishedRecipe> recipes, ItemStaff staff, Item plank) {
staffRecipe(recipes, staff, Ingredient.of(plank));
}
private void staffRecipe(Consumer<FinishedRecipe> recipes, ItemStaff staff, Ingredient plank) {
ShapedRecipeBuilder.shaped(staff)
.define('W', plank)
.define('S', Items.STICK)

View file

@ -17,12 +17,21 @@ public class HexBlockTagProvider extends PaucalBlockTagProvider {
@Override
public void addTags() {
tag(HexTags.Blocks.IMPETI)
.add(HexBlocks.IMPETUS_LOOK, HexBlocks.IMPETUS_RIGHTCLICK, HexBlocks.IMPETUS_STOREDPLAYER);
tag(HexTags.Blocks.DIRECTRICES)
.add(HexBlocks.DIRECTRIX_REDSTONE);
tag(HexTags.Blocks.MINDFLAYED_CIRCLE_COMPONENTS)
.addTag(HexTags.Blocks.IMPETI)
.addTag(HexTags.Blocks.DIRECTRICES);
tag(BlockTags.MINEABLE_WITH_PICKAXE)
.add(HexBlocks.SLATE_BLOCK, HexBlocks.SLATE,
HexBlocks.EMPTY_DIRECTRIX, HexBlocks.DIRECTRIX_REDSTONE,
HexBlocks.EMPTY_IMPETUS,
HexBlocks.IMPETUS_RIGHTCLICK, HexBlocks.IMPETUS_LOOK, HexBlocks.IMPETUS_STOREDPLAYER,
HexBlocks.AMETHYST_TILES, HexBlocks.SCONCE);
HexBlocks.AMETHYST_TILES, HexBlocks.SCONCE,
HexBlocks.QUENCHED_ALLAY);
tag(BlockTags.MINEABLE_WITH_SHOVEL)
.add(HexBlocks.AMETHYST_DUST_BLOCK);

View file

@ -27,7 +27,8 @@ public class HexItemTagProvider extends PaucalItemTagProvider {
tag(HexTags.Items.STAVES).add(HexItems.STAFF_EDIFIED,
HexItems.STAFF_OAK, HexItems.STAFF_SPRUCE, HexItems.STAFF_BIRCH,
HexItems.STAFF_JUNGLE, HexItems.STAFF_ACACIA, HexItems.STAFF_DARK_OAK,
HexItems.STAFF_CRIMSON, HexItems.STAFF_WARPED, HexItems.STAFF_MANGROVE);
HexItems.STAFF_CRIMSON, HexItems.STAFF_WARPED, HexItems.STAFF_MANGROVE,
HexItems.STAFF_QUENCHED, HexItems.STAFF_MINDSPLICE);
tag(HexTags.Items.PHIAL_BASE).add(Items.GLASS_BOTTLE);
tag(HexTags.Items.GRANTS_ROOT_ADVANCEMENT).add(HexItems.AMETHYST_DUST, Items.AMETHYST_SHARD,
@ -36,6 +37,9 @@ public class HexItemTagProvider extends PaucalItemTagProvider {
this.copy(HexTags.Blocks.EDIFIED_LOGS, HexTags.Items.EDIFIED_LOGS);
this.copy(HexTags.Blocks.EDIFIED_PLANKS, HexTags.Items.EDIFIED_PLANKS);
this.copy(HexTags.Blocks.IMPETI, HexTags.Items.IMPETI);
this.copy(HexTags.Blocks.DIRECTRICES, HexTags.Items.DIRECTRICES);
this.copy(HexTags.Blocks.MINDFLAYED_CIRCLE_COMPONENTS, HexTags.Items.MINDFLAYED_CIRCLE_COMPONENTS);
this.copy(BlockTags.LOGS_THAT_BURN, ItemTags.LOGS_THAT_BURN);
this.copy(BlockTags.LOGS, ItemTags.LOGS);
this.copy(BlockTags.PLANKS, ItemTags.PLANKS);

View file

@ -2,7 +2,7 @@ package at.petrak.hexcasting.interop.patchouli;
import at.petrak.hexcasting.api.casting.math.HexCoord;
import at.petrak.hexcasting.api.casting.math.HexPattern;
import at.petrak.hexcasting.client.RenderLib;
import at.petrak.hexcasting.client.render.RenderLib;
import at.petrak.hexcasting.interop.utils.PatternDrawingUtil;
import at.petrak.hexcasting.interop.utils.PatternEntry;
import com.mojang.blaze3d.vertex.PoseStack;

View file

@ -3,7 +3,7 @@ package at.petrak.hexcasting.interop.utils;
import at.petrak.hexcasting.api.casting.math.HexCoord;
import at.petrak.hexcasting.api.casting.math.HexPattern;
import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.client.RenderLib;
import at.petrak.hexcasting.client.render.RenderLib;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
@ -19,8 +19,8 @@ import java.util.List;
public final class PatternDrawingUtil {
public static void drawPattern(PoseStack poseStack, int x, int y, List<PatternEntry> patterns, List<Vec2> dots,
boolean strokeOrder, int outer, int innerLight, int innerDark,
int dotColor) {
boolean strokeOrder, int outer, int innerLight, int innerDark,
int dotColor) {
poseStack.pushPose();
poseStack.translate(x, y, 1);
var mat = poseStack.last().pose();
@ -61,7 +61,7 @@ public final class PatternDrawingUtil {
}
public static PatternRenderingData loadPatterns(List<Pair<HexPattern, HexCoord>> patterns,
float readabilityOffset, float lastLineLenProp) {
float readabilityOffset, float lastLineLenProp) {
var patternEntries = new ArrayList<PatternEntry>(patterns.size());
var fakeScale = 1;

View file

@ -0,0 +1,14 @@
package at.petrak.hexcasting.mixin.accessor.client;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.function.Supplier;
@Mixin(BlockEntityRenderDispatcher.class)
public interface AccessorBlockEntityRenderDispatcher {
@Accessor("blockRenderDispatcher")
Supplier<BlockRenderDispatcher> hex$getBlockRenderDispatcher();
}

View file

@ -21,14 +21,16 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
public abstract class MixinClientLevel {
@Inject(method = "doAnimateTick",
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/Block;animateTick(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/util/RandomSource;)V"),
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/Block;animateTick" +
"(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;" +
"Lnet/minecraft/core/BlockPos;Lnet/minecraft/util/RandomSource;)V"),
locals = LocalCapture.CAPTURE_FAILSOFT)
public void addBuddingAmethystParticles(int $$0, int $$1, int $$2, int $$3, RandomSource rand, Block $$5,
BlockPos.MutableBlockPos pos, CallbackInfo ci, int trueX, int trueY, int trueZ, BlockState state) {
ClientLevel self = ((ClientLevel) (Object) this);
if (state.is(Blocks.BUDDING_AMETHYST)) {
ParticleOptions options = new ConjureParticleOptions(0x8932b8, true);
ParticleOptions options = new ConjureParticleOptions(0x8932b8);
Vec3 center = Vec3.atCenterOf(pos);
for (Direction direction : Direction.values()) {
int dX = direction.getStepX();

Some files were not shown because too many files have changed in this diff Show more