Initial Work on Rituals
Added the framework for Rituals, including the automatic registration of rituals using the annotation. This includes: - The Master Ritual Stone - The regular Ritual Stones (all 7 types) - The Ritual Registration system - The activation crystal items. - Reintroduction of the Demon Will Aura (changed saved Dimension ID from Integer to ResourceLocation) Localization needs to be completed, as well as the implementation of all the rituals.
This commit is contained in:
parent
0a9717f1ed
commit
1f0dcb608a
|
@ -1,27 +1,42 @@
|
|||
cb435652c27b4978d8db83af2fd531ccaa82ada7 assets/bloodmagic/blockstates/accelerationrune.json
|
||||
43be0406da1c9f7cf734427bea235a65cda073d2 assets/bloodmagic/blockstates/airritualstone.json
|
||||
4a60c54def00d68368ed0a0d4783979aa63d5f60 assets/bloodmagic/blockstates/altarcapacityrune.json
|
||||
950fff9f06033741091aa8a66a62857da673efb9 assets/bloodmagic/blockstates/bettercapacityrune.json
|
||||
8a5edb859a6f4d0adfbe2f608bab6b8c8addf01a assets/bloodmagic/blockstates/blankrune.json
|
||||
904d9baa649250571bce5f965cf48fbec69c2c1a assets/bloodmagic/blockstates/bloodlight.json
|
||||
631b579c38652efbcd9e5771d09ad6e476f3ba00 assets/bloodmagic/blockstates/chargingrune.json
|
||||
6bd58d1d02a40416cec29409dee7ef80038b26d5 assets/bloodmagic/blockstates/dislocationrune.json
|
||||
ba1cd8a9475212843e3b26232c8a9943fa0d2d20 assets/bloodmagic/blockstates/duskritualstone.json
|
||||
bb3db171734f511fc0c259d86e869b49aa1d0c77 assets/bloodmagic/blockstates/earthritualstone.json
|
||||
e780d6d9e891082dc6ce83fde1697ce36281a02a assets/bloodmagic/blockstates/fireritualstone.json
|
||||
002795212cc7bf2cad2a91f873d85e2204c6367d assets/bloodmagic/blockstates/lightritualstone.json
|
||||
372ecd737f7082a4c2c70e46745f893b1179f885 assets/bloodmagic/blockstates/orbcapacityrune.json
|
||||
90daa355e528ab8a6582f796951201882f3c56da assets/bloodmagic/blockstates/ritualstone.json
|
||||
285618c1a8ec36e36d479f577190579ae7616529 assets/bloodmagic/blockstates/sacrificerune.json
|
||||
b03040d7a168653bf8df3600033b8fde2383db30 assets/bloodmagic/blockstates/selfsacrificerune.json
|
||||
487ffdc02ab7b65aafcb932e3b5cf6ea0500b21d assets/bloodmagic/blockstates/speedrune.json
|
||||
e6d9cf699667aaa47efff37b2b033895dee29c15 assets/bloodmagic/blockstates/waterritualstone.json
|
||||
f7a92ca94cbd68344d89b92dc6c26c15cd1b85b5 assets/bloodmagic/lang/en_us.json
|
||||
34445195b9f2459475cde53454bc8e37d32865d7 assets/bloodmagic/models/block/accelerationrune.json
|
||||
bcdbccc49d4509571be6988762ab87126275a4c8 assets/bloodmagic/models/block/airritualstone.json
|
||||
3c98a88c2283ad54f0efb9d7194361bbc3e93c17 assets/bloodmagic/models/block/altarcapacityrune.json
|
||||
7cd62092c6fb3109e016d42090cf89bfa3ab7fca assets/bloodmagic/models/block/bettercapacityrune.json
|
||||
1fe0f89895addb7abcacf6ce7e39b6ddc87b0d85 assets/bloodmagic/models/block/blankrune.json
|
||||
3c83e090a1cff00e2bb2c7eb475785954b6eb980 assets/bloodmagic/models/block/bloodlight.json
|
||||
320827ad2feaa51a90ebb7064a70bdc6d3765203 assets/bloodmagic/models/block/chargingrune.json
|
||||
6adbeedc17f649ef47419845a6da0d50cfc76742 assets/bloodmagic/models/block/dislocationrune.json
|
||||
81313327125e6e7396df0408595228bf0f63e1c9 assets/bloodmagic/models/block/duskritualstone.json
|
||||
c30064f4aa09c42d23e94d118ae5b148eadb3a6c assets/bloodmagic/models/block/earthritualstone.json
|
||||
4ff1cab1014cd8f655e5f032ecf60dd371f421c3 assets/bloodmagic/models/block/fireritualstone.json
|
||||
2e1a81c758bfeec2aee807b48239f23241302268 assets/bloodmagic/models/block/lightritualstone.json
|
||||
c3a813b735cd229f8597e41d04465926b2e65fe1 assets/bloodmagic/models/block/orbcapacityrune.json
|
||||
9b2bf2a44b788cbaecbe63a3e085e8de76672e1b assets/bloodmagic/models/block/ritualstone.json
|
||||
a8a1d06fcc2f8395530c72d2846133fff37d5537 assets/bloodmagic/models/block/sacrificerune.json
|
||||
791c9f2e27215ff0a45eed7efe385276bfc09aed assets/bloodmagic/models/block/selfsacrificerune.json
|
||||
65fe5e01ed2660e45a5c329ff2389a87e4d791ec assets/bloodmagic/models/block/speedrune.json
|
||||
6041f2e47f5437d90a58586e42d18dadc42df439 assets/bloodmagic/models/block/waterritualstone.json
|
||||
9462d62d9bc9408359d30728de8651dc104aacf1 assets/bloodmagic/models/item/accelerationrune.json
|
||||
fe8e3deb3ad0107ca3ebd70694c1fc55a987d912 assets/bloodmagic/models/item/airritualstone.json
|
||||
17cbe9142ef3950ea1b6be11694b849f55e93f13 assets/bloodmagic/models/item/airsigil.json
|
||||
f150f178edf7d6d250bcfd84af1c28a21cff09c6 assets/bloodmagic/models/item/altarcapacityrune.json
|
||||
866b8cdd3da56e2e82dbd5f16ab5117b5a503749 assets/bloodmagic/models/item/apprenticebloodorb.json
|
||||
|
@ -40,11 +55,15 @@ f404148f9df3a61da3c18175885ffa56b2a85a6a assets/bloodmagic/models/item/daggerofs
|
|||
9671199681493a396e07d7bcab20137c22d981d5 assets/bloodmagic/models/item/demonslate.json
|
||||
7af07ab578bbd20e2f834b26d9cafb5fe23bc7d4 assets/bloodmagic/models/item/dislocationrune.json
|
||||
f4531e22aa1db1cff324db5ccb344d3b9fa85c8d assets/bloodmagic/models/item/divinationsigil.json
|
||||
10aceefca3ad3f0da773cb317c4effc6c06051ea assets/bloodmagic/models/item/duskritualstone.json
|
||||
4d56efd7fdbf430f49903ce201577047687c3804 assets/bloodmagic/models/item/earthritualstone.json
|
||||
4c39378f6c14dc243a7d52564e5a21df94683415 assets/bloodmagic/models/item/etherealslate.json
|
||||
c36bde4f98c0aeb3bf0f369ad3bc067e5f0dc916 assets/bloodmagic/models/item/fireritualstone.json
|
||||
44663089f348642bcca1c5020b5081c3ab172f92 assets/bloodmagic/models/item/growthsigil.json
|
||||
f68825f667ca73b4373fd5068a47f0d1ca9b2aad assets/bloodmagic/models/item/icesigil.json
|
||||
109b5485c25d978af55b46682d5bfa7008909458 assets/bloodmagic/models/item/infusedslate.json
|
||||
588c5208e3f4ef941cd8375aeceeed44484d85d3 assets/bloodmagic/models/item/lavasigil.json
|
||||
5a76914a87fc9b99079bb6afed1d4cfe3e4a532e assets/bloodmagic/models/item/lightritualstone.json
|
||||
15d8178b626da912334774142d40d1012fb21fa0 assets/bloodmagic/models/item/magicianbloodorb.json
|
||||
0a3566d3c86403f24c22977dd32ffaec727a9ad3 assets/bloodmagic/models/item/masterbloodorb.json
|
||||
7596826c5b40c2809eb0a42eb5f5f2089290e3e5 assets/bloodmagic/models/item/miningsigil.json
|
||||
|
@ -58,6 +77,7 @@ baafdb5915c5fbc99b84a54670ed64a6f26cb0fe assets/bloodmagic/models/item/reagentma
|
|||
95b2925e96a7df71d72568e0ed7b03290293cbe7 assets/bloodmagic/models/item/reagentvoid.json
|
||||
fd1447d943ddc4540a51a72dcbb245d77d45da71 assets/bloodmagic/models/item/reagentwater.json
|
||||
50bf796adbed412488df48ed9250fc9b0ecd851f assets/bloodmagic/models/item/reinforcedslate.json
|
||||
2722891c9c40b124d85bf9ff8eb885e175f5e6ff assets/bloodmagic/models/item/ritualstone.json
|
||||
db73abb3bcb1731b6fc389e3577910b6aab87b10 assets/bloodmagic/models/item/sacrificerune.json
|
||||
9403d6195d4d38d5876c2a42f4edfb9bdcd05210 assets/bloodmagic/models/item/sacrificialdagger.json
|
||||
cc71421e98ee7ee047a4cfbb6cb69529c2b02d4e assets/bloodmagic/models/item/selfsacrificerune.json
|
||||
|
@ -102,6 +122,7 @@ ec6f6bf7f520182b2044f3cc5a10f1d4c7a8d7ab assets/bloodmagic/models/item/variants/
|
|||
2029220112f89a3f4d432ab4749dff6143846659 assets/bloodmagic/models/item/variants/soulsword_vengeful_activated.json
|
||||
0f5a3e1e5993a03ccda156eed855b71fbd0be0a2 assets/bloodmagic/models/item/variants/soulsword_vengeful_deactivated.json
|
||||
836b5a7f19915af809795a72983a23f0d5f9c5b2 assets/bloodmagic/models/item/voidsigil.json
|
||||
a31019db55828cb937a071ac2f74b125a2d0c955 assets/bloodmagic/models/item/waterritualstone.json
|
||||
7426fed5f833ce3d08602f727f1467dd3e107991 assets/bloodmagic/models/item/watersigil.json
|
||||
f72efc172699d43405019add97f455bd6b7f452b assets/bloodmagic/models/item/weakbloodorb.json
|
||||
828c0f89e747d48d37c6a86030a8ec59ca5c29cb data/bloodmagic/advancements/recipes/bloodmagictab/blood_altar.json
|
||||
|
@ -116,6 +137,7 @@ e897d6f91e2a0bd12b0da0a50e5c897294989e7c data/bloodmagic/advancements/recipes/bl
|
|||
2d29dd0c24c4c11d7438cdeeb26b9357d4359e2c data/bloodmagic/advancements/recipes/bloodmagictab/soul_forge.json
|
||||
7a7f9f995d2414289d07c0a145647c8e735a6b78 data/bloodmagic/advancements/recipes/bloodmagictab/soul_snare.json
|
||||
639ebb2ccabb2eaece59be96c2e6f28c31f4d2f4 data/bloodmagic/loot_tables/blocks/accelerationrune.json
|
||||
26e3f34021426def32602e5ae7755e4672878320 data/bloodmagic/loot_tables/blocks/airritualstone.json
|
||||
443550be9eaf1021b11fd2bbe6afcfe2cee6f7ad data/bloodmagic/loot_tables/blocks/alchemyarray.json
|
||||
17d8dcc62320d5d2eeb781e925963d9b9d5eec54 data/bloodmagic/loot_tables/blocks/altar.json
|
||||
05bb6268d7e884c962061a632e162d5baf73271e data/bloodmagic/loot_tables/blocks/altarcapacityrune.json
|
||||
|
@ -124,11 +146,17 @@ e897d6f91e2a0bd12b0da0a50e5c897294989e7c data/bloodmagic/advancements/recipes/bl
|
|||
f1a8e3131d85077665563372cad868534a72fb31 data/bloodmagic/loot_tables/blocks/bloodlight.json
|
||||
779b809a2a51e6dab46f9e6799249f2f14653ebb data/bloodmagic/loot_tables/blocks/chargingrune.json
|
||||
a9fcfc656fab957328c10ee1d9d33807e697b7f7 data/bloodmagic/loot_tables/blocks/dislocationrune.json
|
||||
26e3f34021426def32602e5ae7755e4672878320 data/bloodmagic/loot_tables/blocks/duskritualstone.json
|
||||
26e3f34021426def32602e5ae7755e4672878320 data/bloodmagic/loot_tables/blocks/earthritualstone.json
|
||||
26e3f34021426def32602e5ae7755e4672878320 data/bloodmagic/loot_tables/blocks/fireritualstone.json
|
||||
26e3f34021426def32602e5ae7755e4672878320 data/bloodmagic/loot_tables/blocks/lightritualstone.json
|
||||
95442c1bb740fab2eb8ee051f7184813f6023afa data/bloodmagic/loot_tables/blocks/orbcapacityrune.json
|
||||
26e3f34021426def32602e5ae7755e4672878320 data/bloodmagic/loot_tables/blocks/ritualstone.json
|
||||
e0239eff7762a414a4e4faa0158d844dffb8c1f6 data/bloodmagic/loot_tables/blocks/sacrificerune.json
|
||||
9b697e37046b6238b3a19eae9113b88010ccff32 data/bloodmagic/loot_tables/blocks/selfsacrificerune.json
|
||||
f748a5ba8838b50de0502f132fe2a65f4726dae6 data/bloodmagic/loot_tables/blocks/soulforge.json
|
||||
015e07226fd90935f7ec663f4bcf3873a57a82d1 data/bloodmagic/loot_tables/blocks/speedrune.json
|
||||
26e3f34021426def32602e5ae7755e4672878320 data/bloodmagic/loot_tables/blocks/waterritualstone.json
|
||||
f41b0e9dfab608c42a85c3c5c5bbc050b03f02a1 data/bloodmagic/recipes/altar/apprenticebloodorb.json
|
||||
2a67e37497a571b5ee944375d315fddccea87697 data/bloodmagic/recipes/altar/daggerofsacrifice.json
|
||||
c5a4a256a7437f2e13c574a6f0c4d75fc2e718cb data/bloodmagic/recipes/altar/demonicslate.json
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "bloodmagic:block/airritualstone"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "bloodmagic:block/duskritualstone"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "bloodmagic:block/earthritualstone"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "bloodmagic:block/fireritualstone"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "bloodmagic:block/lightritualstone"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "bloodmagic:block/ritualstone"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "bloodmagic:block/waterritualstone"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "bloodmagic:block/airritualstone"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "bloodmagic:block/duskritualstone"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "bloodmagic:block/earthritualstone"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "bloodmagic:block/fireritualstone"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "bloodmagic:block/lightritualstone"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "bloodmagic:block/ritualstone"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "bloodmagic:block/waterritualstone"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"parent": "bloodmagic:block/airritualstone"
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"parent": "bloodmagic:block/duskritualstone"
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"parent": "bloodmagic:block/earthritualstone"
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"parent": "bloodmagic:block/fireritualstone"
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"parent": "bloodmagic:block/lightritualstone"
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"parent": "bloodmagic:block/ritualstone"
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"parent": "bloodmagic:block/waterritualstone"
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "bloodmagic:ritualstone"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "bloodmagic:ritualstone"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "bloodmagic:ritualstone"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "bloodmagic:ritualstone"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "bloodmagic:ritualstone"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "bloodmagic:ritualstone"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"rolls": 1,
|
||||
"entries": [
|
||||
{
|
||||
"type": "minecraft:item",
|
||||
"name": "bloodmagic:ritualstone"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "minecraft:survives_explosion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -49,6 +49,7 @@ import wayoftime.bloodmagic.core.recipe.IngredientBloodOrb;
|
|||
import wayoftime.bloodmagic.core.registry.OrbRegistry;
|
||||
import wayoftime.bloodmagic.network.BloodMagicPacketHandler;
|
||||
import wayoftime.bloodmagic.potion.BloodMagicPotions;
|
||||
import wayoftime.bloodmagic.ritual.RitualManager;
|
||||
import wayoftime.bloodmagic.tile.TileAlchemyArray;
|
||||
import wayoftime.bloodmagic.tile.TileAltar;
|
||||
import wayoftime.bloodmagic.tile.TileSoulForge;
|
||||
|
@ -66,6 +67,7 @@ public class BloodMagic
|
|||
private static Gson GSON = null;
|
||||
|
||||
public static final BloodMagicPacketHandler packetHandler = new BloodMagicPacketHandler();
|
||||
public static final RitualManager RITUAL_MANAGER = new RitualManager();
|
||||
|
||||
public BloodMagic()
|
||||
{
|
||||
|
@ -134,8 +136,11 @@ public class BloodMagic
|
|||
public void onLoadComplete(FMLLoadCompleteEvent event)
|
||||
{
|
||||
OrbRegistry.tierMap.put(BloodMagicItems.ORB_WEAK.get().getTier(), new ItemStack(BloodMagicItems.WEAK_BLOOD_ORB.get()));
|
||||
OrbRegistry.tierMap.put(BloodMagicItems.ORB_APPRENTICE.get().getTier(), new ItemStack(BloodMagicItems.APPRENTICE_BLOOD_ORB.get()));
|
||||
OrbRegistry.tierMap.put(BloodMagicItems.ORB_MAGICIAN.get().getTier(), new ItemStack(BloodMagicItems.MAGICIAN_BLOOD_ORB.get()));
|
||||
OrbRegistry.tierMap.put(BloodMagicItems.ORB_MASTER.get().getTier(), new ItemStack(BloodMagicItems.MASTER_BLOOD_ORB.get()));
|
||||
BloodMagicCorePlugin.INSTANCE.register(BloodMagicAPI.INSTANCE);
|
||||
|
||||
RITUAL_MANAGER.discover();
|
||||
}
|
||||
|
||||
public void registerTileEntityTypes(RegistryEvent.Register<TileEntityType<?>> event)
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package wayoftime.bloodmagic.block.enums;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import net.minecraft.util.IStringSerializable;
|
||||
|
||||
//TODO: Will want to probably discontinue this due to The Flattening
|
||||
public enum EnumRitualController implements IStringSerializable
|
||||
{
|
||||
MASTER, IMPERFECT, INVERTED,;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return name().toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString()
|
||||
{
|
||||
return this.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
package wayoftime.bloodmagic.common.block;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.SoundType;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
import net.minecraft.world.Explosion;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.ToolType;
|
||||
import wayoftime.bloodmagic.BloodMagic;
|
||||
import wayoftime.bloodmagic.common.item.ItemActivationCrystal;
|
||||
import wayoftime.bloodmagic.iface.IBindable;
|
||||
import wayoftime.bloodmagic.ritual.Ritual;
|
||||
import wayoftime.bloodmagic.tile.TileMasterRitualStone;
|
||||
import wayoftime.bloodmagic.util.helper.RitualHelper;
|
||||
|
||||
public class BlockMasterRitualStone extends Block
|
||||
{
|
||||
public final boolean isInverted;
|
||||
|
||||
public BlockMasterRitualStone(boolean isInverted)
|
||||
{
|
||||
super(Properties.create(Material.ROCK).sound(SoundType.STONE).hardnessAndResistance(2.0F, 5.0F).harvestTool(ToolType.PICKAXE).harvestLevel(2));
|
||||
this.isInverted = isInverted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResultType onBlockActivated(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult blockRayTraceResult)
|
||||
{
|
||||
ItemStack heldItem = player.getHeldItem(hand);
|
||||
TileEntity tile = world.getTileEntity(pos);
|
||||
|
||||
if (tile instanceof TileMasterRitualStone)
|
||||
{
|
||||
if (heldItem.getItem() instanceof ItemActivationCrystal)
|
||||
{
|
||||
if (((IBindable) heldItem.getItem()).getBinding(heldItem) == null)
|
||||
return ActionResultType.FAIL;
|
||||
|
||||
String key = RitualHelper.getValidRitual(world, pos);
|
||||
if (!key.isEmpty())
|
||||
{
|
||||
Ritual ritual = BloodMagic.RITUAL_MANAGER.getRitual(key);
|
||||
if (ritual != null)
|
||||
{
|
||||
Direction direction = RitualHelper.getDirectionOfRitual(world, pos, ritual);
|
||||
// TODO: Give a message stating that this ritual is not a valid ritual.
|
||||
if (direction != null && RitualHelper.checkValidRitual(world, pos, ritual, direction))
|
||||
{
|
||||
if (((TileMasterRitualStone) tile).activateRitual(heldItem, player, BloodMagic.RITUAL_MANAGER.getRitual(key)))
|
||||
{
|
||||
((TileMasterRitualStone) tile).setDirection(direction);
|
||||
if (isInverted)
|
||||
((TileMasterRitualStone) tile).setInverted(true);
|
||||
}
|
||||
} else
|
||||
{
|
||||
player.sendStatusMessage(new TranslationTextComponent("chat.bloodmagic.ritual.notValid"), true);
|
||||
}
|
||||
} else
|
||||
{
|
||||
player.sendStatusMessage(new TranslationTextComponent("chat.bloodmagic.ritual.notValid"), true);
|
||||
}
|
||||
} else
|
||||
{
|
||||
player.sendStatusMessage(new TranslationTextComponent("chat.bloodmagic.ritual.notValid"), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ActionResultType.FAIL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerDestroy(IWorld world, BlockPos blockPos, BlockState blockState)
|
||||
{
|
||||
TileMasterRitualStone tile = (TileMasterRitualStone) world.getTileEntity(blockPos);
|
||||
if (tile != null)
|
||||
((TileMasterRitualStone) tile).stopRitual(Ritual.BreakType.BREAK_MRS);
|
||||
|
||||
super.onPlayerDestroy(world, blockPos, blockState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving)
|
||||
{
|
||||
if (!state.isIn(newState.getBlock()))
|
||||
{
|
||||
TileEntity tile = worldIn.getTileEntity(pos);
|
||||
if (tile instanceof TileMasterRitualStone)
|
||||
{
|
||||
((TileMasterRitualStone) tile).stopRitual(Ritual.BreakType.BREAK_MRS);
|
||||
}
|
||||
|
||||
super.onReplaced(state, worldIn, pos, newState, isMoving);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExplosionDestroy(World world, BlockPos pos, Explosion explosion)
|
||||
{
|
||||
TileEntity tile = world.getTileEntity(pos);
|
||||
|
||||
if (tile instanceof TileMasterRitualStone)
|
||||
((TileMasterRitualStone) tile).stopRitual(Ritual.BreakType.EXPLOSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTileEntity(BlockState state)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity createTileEntity(BlockState state, IBlockReader world)
|
||||
{
|
||||
return new TileMasterRitualStone();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package wayoftime.bloodmagic.common.block;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.SoundType;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.ToolType;
|
||||
import wayoftime.bloodmagic.ritual.EnumRuneType;
|
||||
import wayoftime.bloodmagic.ritual.IRitualStone;
|
||||
|
||||
public class BlockRitualStone extends Block implements IRitualStone
|
||||
{
|
||||
private final EnumRuneType type;
|
||||
|
||||
public BlockRitualStone(EnumRuneType type)
|
||||
{
|
||||
super(Properties.create(Material.ROCK).hardnessAndResistance(2.0F, 5.0F).sound(SoundType.STONE).harvestTool(ToolType.PICKAXE).harvestLevel(2));
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInformation(ItemStack stack, @Nullable IBlockReader world, List<ITextComponent> tooltip, ITooltipFlag flag)
|
||||
{
|
||||
tooltip.add(new TranslationTextComponent("tooltip.bloodmagic.decoration.safe"));
|
||||
super.addInformation(stack, world, tooltip, flag);
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public int damageDropped(BlockState state)
|
||||
// {
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean canSilkHarvest(World world, BlockPos pos, BlockState state, PlayerEntity player)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public boolean isRuneType(World world, BlockPos pos, EnumRuneType runeType)
|
||||
{
|
||||
return type.equals(runeType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRuneType(World world, BlockPos pos, EnumRuneType runeType)
|
||||
{
|
||||
Block runeBlock = this;
|
||||
switch (type)
|
||||
{
|
||||
case AIR:
|
||||
runeBlock = BloodMagicBlocks.AIR_RITUAL_STONE.get();
|
||||
break;
|
||||
case BLANK:
|
||||
runeBlock = BloodMagicBlocks.BLANK_RITUAL_STONE.get();
|
||||
break;
|
||||
case DAWN:
|
||||
runeBlock = BloodMagicBlocks.DAWN_RITUAL_STONE.get();
|
||||
break;
|
||||
case DUSK:
|
||||
runeBlock = BloodMagicBlocks.DUSK_RITUAL_STONE.get();
|
||||
break;
|
||||
case EARTH:
|
||||
runeBlock = BloodMagicBlocks.EARTH_RITUAL_STONE.get();
|
||||
break;
|
||||
case FIRE:
|
||||
runeBlock = BloodMagicBlocks.FIRE_RITUAL_STONE.get();
|
||||
break;
|
||||
case WATER:
|
||||
runeBlock = BloodMagicBlocks.WATER_RITUAL_STONE.get();
|
||||
break;
|
||||
}
|
||||
|
||||
BlockState newState = runeBlock.getDefaultState();
|
||||
world.setBlockState(pos, newState);
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ import net.minecraftforge.registries.ForgeRegistries;
|
|||
import wayoftime.bloodmagic.BloodMagic;
|
||||
import wayoftime.bloodmagic.block.enums.BloodRuneType;
|
||||
import wayoftime.bloodmagic.common.item.BloodMagicItems;
|
||||
import wayoftime.bloodmagic.ritual.EnumRuneType;
|
||||
import wayoftime.bloodmagic.tile.contailer.ContainerSoulForge;
|
||||
|
||||
public class BloodMagicBlocks
|
||||
|
@ -48,6 +49,16 @@ public class BloodMagicBlocks
|
|||
public static final RegistryObject<Block> BLOOD_ALTAR = BLOCKS.register("altar", () -> new BlockAltar());
|
||||
public static final RegistryObject<Block> BLOOD_LIGHT = BLOCKS.register("bloodlight", () -> new BlockBloodLight());
|
||||
|
||||
public static final RegistryObject<Block> BLANK_RITUAL_STONE = BLOCKS.register("ritualstone", () -> new BlockRitualStone(EnumRuneType.BLANK));
|
||||
public static final RegistryObject<Block> AIR_RITUAL_STONE = BLOCKS.register("airritualstone", () -> new BlockRitualStone(EnumRuneType.AIR));
|
||||
public static final RegistryObject<Block> WATER_RITUAL_STONE = BLOCKS.register("waterritualstone", () -> new BlockRitualStone(EnumRuneType.WATER));
|
||||
public static final RegistryObject<Block> FIRE_RITUAL_STONE = BLOCKS.register("fireritualstone", () -> new BlockRitualStone(EnumRuneType.FIRE));
|
||||
public static final RegistryObject<Block> EARTH_RITUAL_STONE = BLOCKS.register("earthritualstone", () -> new BlockRitualStone(EnumRuneType.EARTH));
|
||||
public static final RegistryObject<Block> DUSK_RITUAL_STONE = BLOCKS.register("duskritualstone", () -> new BlockRitualStone(EnumRuneType.DUSK));
|
||||
public static final RegistryObject<Block> DAWN_RITUAL_STONE = BLOCKS.register("lightritualstone", () -> new BlockRitualStone(EnumRuneType.DAWN));
|
||||
|
||||
public static final RegistryObject<Block> MASTER_RITUAL_STONE = BASICBLOCKS.register("masterritualstone", () -> new BlockMasterRitualStone(false));
|
||||
|
||||
private static ForgeFlowingFluid.Properties makeProperties()
|
||||
{
|
||||
return new ForgeFlowingFluid.Properties(LIFE_ESSENCE_FLUID, LIFE_ESSENCE_FLUID_FLOWING, FluidAttributes.builder(FLUID_STILL, FLUID_FLOWING)).bucket(LIFE_ESSENCE_BUCKET).block(LIFE_ESSENCE_BLOCK);
|
||||
|
|
|
@ -28,6 +28,13 @@ public class GeneratorBlockStates extends BlockStateProvider
|
|||
}
|
||||
|
||||
buildCubeAll(BloodMagicBlocks.BLOOD_LIGHT.get());
|
||||
buildCubeAll(BloodMagicBlocks.BLANK_RITUAL_STONE.get());
|
||||
buildCubeAll(BloodMagicBlocks.AIR_RITUAL_STONE.get());
|
||||
buildCubeAll(BloodMagicBlocks.WATER_RITUAL_STONE.get());
|
||||
buildCubeAll(BloodMagicBlocks.FIRE_RITUAL_STONE.get());
|
||||
buildCubeAll(BloodMagicBlocks.EARTH_RITUAL_STONE.get());
|
||||
buildCubeAll(BloodMagicBlocks.DUSK_RITUAL_STONE.get());
|
||||
buildCubeAll(BloodMagicBlocks.DAWN_RITUAL_STONE.get());
|
||||
}
|
||||
|
||||
private void buildCubeAll(Block block)
|
||||
|
|
|
@ -36,6 +36,14 @@ public class GeneratorItemModels extends ItemModelProvider
|
|||
registerBlockModel(block.get());
|
||||
}
|
||||
|
||||
registerBlockModel(BloodMagicBlocks.BLANK_RITUAL_STONE.get());
|
||||
registerBlockModel(BloodMagicBlocks.AIR_RITUAL_STONE.get());
|
||||
registerBlockModel(BloodMagicBlocks.WATER_RITUAL_STONE.get());
|
||||
registerBlockModel(BloodMagicBlocks.FIRE_RITUAL_STONE.get());
|
||||
registerBlockModel(BloodMagicBlocks.EARTH_RITUAL_STONE.get());
|
||||
registerBlockModel(BloodMagicBlocks.DUSK_RITUAL_STONE.get());
|
||||
registerBlockModel(BloodMagicBlocks.DAWN_RITUAL_STONE.get());
|
||||
|
||||
registerToggleableItem(BloodMagicItems.GREEN_GROVE_SIGIL.get());
|
||||
registerToggleableItem(BloodMagicItems.FAST_MINER_SIGIL.get());
|
||||
registerToggleableItem(BloodMagicItems.MAGNETISM_SIGIL.get());
|
||||
|
|
|
@ -49,33 +49,17 @@ public class GeneratorLootTable extends LootTableProvider
|
|||
this.registerDropSelfLootTable(block.get());
|
||||
}
|
||||
|
||||
this.registerDropSelfLootTable(BloodMagicBlocks.BLOOD_ALTAR.get());
|
||||
registerDropSelfLootTable(BloodMagicBlocks.BLOOD_ALTAR.get());
|
||||
registerNoDropLootTable(BloodMagicBlocks.ALCHEMY_ARRAY.get());
|
||||
registerNoDropLootTable(BloodMagicBlocks.BLOOD_LIGHT.get());
|
||||
this.registerDropSelfLootTable(BloodMagicBlocks.SOUL_FORGE.get());
|
||||
|
||||
// LootPool.Builder builder = LootPool.builder().name(ModBlocks.GOO_BLOCK.get().getRegistryName().toString()).rolls(ConstantRange.of(1)).acceptCondition(SurvivesExplosion.builder()).addEntry(ItemLootEntry.builder(ModItems.GOO_RESIDUE.get()));
|
||||
// this.registerLootTable(ModBlocks.GOO_BLOCK.get(), LootTable.builder().addLootPool(builder));
|
||||
//
|
||||
// LootPool.Builder builder2 = LootPool.builder().name(ModBlocks.GOO_BLOCK_TERRAIN.get().getRegistryName().toString()).rolls(ConstantRange.of(1)).acceptCondition(SurvivesExplosion.builder()).addEntry(ItemLootEntry.builder(ModItems.GOO_RESIDUE.get()));
|
||||
// this.registerLootTable(ModBlocks.GOO_BLOCK_TERRAIN.get(), LootTable.builder().addLootPool(builder2));
|
||||
//
|
||||
// this.registerDropSelfLootTable(ModBlocks.GOO_BLOCK_POISON.get());
|
||||
// this.registerDropSelfLootTable(ModBlocks.GNT_BLOCK_T1.get());
|
||||
// this.registerDropSelfLootTable(ModBlocks.GNT_BLOCK_T2.get());
|
||||
// this.registerDropSelfLootTable(ModBlocks.GNT_BLOCK_T3.get());
|
||||
// this.registerDropSelfLootTable(ModBlocks.GNT_BLOCK_T4.get());
|
||||
// this.registerDropSelfLootTable(ModBlocks.TURRET_BLOCK.get());
|
||||
// this.registerDropSelfLootTable(ModBlocks.ZAPPER_TURRET_BLOCK.get());
|
||||
// this.registerDropSelfLootTable(ModBlocks.ANTI_GOO_BEACON.get());
|
||||
// this.registerDropSelfLootTable(ModBlocks.ANTI_GOO_FIELD_GEN.get());
|
||||
// this.registerDropSelfLootTable(ModBlocks.GOOLIMINATIONFIELDGEN.get());
|
||||
// this.registerDropSelfLootTable(ModBlocks.GOO_DETECTOR.get());
|
||||
// this.registerDropping(ModBlocks.GOO_RENDER.get(), ItemStack.EMPTY.getItem());
|
||||
// // this.registerDropping(ModBlocks.GOO_RENDER_BURST.get(),
|
||||
// // ItemStack.EMPTY.getItem());
|
||||
// this.registerDropping(ModBlocks.GOO_RENDER_TERRAIN.get(), ItemStack.EMPTY.getItem());
|
||||
|
||||
registerDropSelfLootTable(BloodMagicBlocks.SOUL_FORGE.get());
|
||||
registerDropSelfLootTable(BloodMagicBlocks.BLANK_RITUAL_STONE.get());
|
||||
registerDropping(BloodMagicBlocks.AIR_RITUAL_STONE.get(), BloodMagicBlocks.BLANK_RITUAL_STONE.get());
|
||||
registerDropping(BloodMagicBlocks.WATER_RITUAL_STONE.get(), BloodMagicBlocks.BLANK_RITUAL_STONE.get());
|
||||
registerDropping(BloodMagicBlocks.FIRE_RITUAL_STONE.get(), BloodMagicBlocks.BLANK_RITUAL_STONE.get());
|
||||
registerDropping(BloodMagicBlocks.EARTH_RITUAL_STONE.get(), BloodMagicBlocks.BLANK_RITUAL_STONE.get());
|
||||
registerDropping(BloodMagicBlocks.DUSK_RITUAL_STONE.get(), BloodMagicBlocks.BLANK_RITUAL_STONE.get());
|
||||
registerDropping(BloodMagicBlocks.DAWN_RITUAL_STONE.get(), BloodMagicBlocks.BLANK_RITUAL_STONE.get());
|
||||
}
|
||||
|
||||
private void registerNoDropLootTable(Block block)
|
||||
|
|
|
@ -54,6 +54,13 @@ public class BloodMagicItems
|
|||
public static final RegistryObject<Item> ORB_RUNE_ITEM = ITEMS.register("orbcapacityrune", () -> new BlockItem(BloodMagicBlocks.ORB_RUNE.get(), new Item.Properties().group(BloodMagic.TAB)));
|
||||
public static final RegistryObject<Item> ACCELERATION_RUNE_ITEM = ITEMS.register("accelerationrune", () -> new BlockItem(BloodMagicBlocks.ACCELERATION_RUNE.get(), new Item.Properties().group(BloodMagic.TAB)));
|
||||
public static final RegistryObject<Item> CHARGING_RUNE_ITEM = ITEMS.register("chargingrune", () -> new BlockItem(BloodMagicBlocks.CHARGING_RUNE.get(), new Item.Properties().group(BloodMagic.TAB)));
|
||||
public static final RegistryObject<Item> BLANK_RITUAL_STONE_ITEM = ITEMS.register("ritualstone", () -> new BlockItem(BloodMagicBlocks.BLANK_RITUAL_STONE.get(), new Item.Properties().group(BloodMagic.TAB)));
|
||||
public static final RegistryObject<Item> AIR_RITUAL_STONE_ITEM = ITEMS.register("airritualstone", () -> new BlockItem(BloodMagicBlocks.AIR_RITUAL_STONE.get(), new Item.Properties().group(BloodMagic.TAB)));
|
||||
public static final RegistryObject<Item> WATER_RITUAL_STONE_ITEM = ITEMS.register("waterritualstone", () -> new BlockItem(BloodMagicBlocks.WATER_RITUAL_STONE.get(), new Item.Properties().group(BloodMagic.TAB)));
|
||||
public static final RegistryObject<Item> FIRE_RITUAL_STONE_ITEM = ITEMS.register("fireritualstone", () -> new BlockItem(BloodMagicBlocks.FIRE_RITUAL_STONE.get(), new Item.Properties().group(BloodMagic.TAB)));
|
||||
public static final RegistryObject<Item> EARTH_RITUAL_STONE_ITEM = ITEMS.register("earthritualstone", () -> new BlockItem(BloodMagicBlocks.EARTH_RITUAL_STONE.get(), new Item.Properties().group(BloodMagic.TAB)));
|
||||
public static final RegistryObject<Item> DUSK_RITUAL_STONE_ITEM = ITEMS.register("duskritualstone", () -> new BlockItem(BloodMagicBlocks.DUSK_RITUAL_STONE.get(), new Item.Properties().group(BloodMagic.TAB)));
|
||||
public static final RegistryObject<Item> DAWN_RITUAL_STONE_ITEM = ITEMS.register("lightritualstone", () -> new BlockItem(BloodMagicBlocks.DAWN_RITUAL_STONE.get(), new Item.Properties().group(BloodMagic.TAB)));
|
||||
|
||||
public static final RegistryObject<Item> BLOOD_ALTAR_ITEM = ITEMS.register("altar", () -> new BlockItem(BloodMagicBlocks.BLOOD_ALTAR.get(), new Item.Properties().group(BloodMagic.TAB)));
|
||||
|
||||
|
@ -87,6 +94,10 @@ public class BloodMagicItems
|
|||
public static final RegistryObject<Item> ARCANE_ASHES = BASICITEMS.register("arcaneashes", () -> new ItemArcaneAshes());
|
||||
public static final RegistryObject<Item> DAGGER_OF_SACRIFICE = BASICITEMS.register("daggerofsacrifice", () -> new ItemDaggerOfSacrifice());
|
||||
|
||||
public static final RegistryObject<Item> WEAK_ACTIVATION_CRYSTAL = BASICITEMS.register("activationcrystalweak", () -> new ItemActivationCrystal(ItemActivationCrystal.CrystalType.WEAK));
|
||||
public static final RegistryObject<Item> AWAKENED_ACTIVATION_CRYSTAL = BASICITEMS.register("activationcrystalawakened", () -> new ItemActivationCrystal(ItemActivationCrystal.CrystalType.AWAKENED));
|
||||
public static final RegistryObject<Item> CREATIVE_ACTIVATION_CRYSTAL = BASICITEMS.register("activationcrystalcreative", () -> new ItemActivationCrystal(ItemActivationCrystal.CrystalType.CREATIVE));
|
||||
|
||||
// Reagents used to make the Sigils
|
||||
public static final RegistryObject<Item> REAGENT_WATER = BASICITEMS.register("reagentwater", () -> new ItemBase());
|
||||
public static final RegistryObject<Item> REAGENT_LAVA = BASICITEMS.register("reagentlava", () -> new ItemBase());
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
package wayoftime.bloodmagic.common.item;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import wayoftime.bloodmagic.BloodMagic;
|
||||
import wayoftime.bloodmagic.core.data.Binding;
|
||||
import wayoftime.bloodmagic.iface.IBindable;
|
||||
|
||||
public class ItemActivationCrystal extends Item implements IBindable
|
||||
{
|
||||
final CrystalType type;
|
||||
|
||||
public ItemActivationCrystal(CrystalType type)
|
||||
{
|
||||
super(new Item.Properties().maxStackSize(1).group(BloodMagic.TAB));
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void addInformation(ItemStack stack, World world, List<ITextComponent> tooltip, ITooltipFlag flag)
|
||||
{
|
||||
tooltip.add(new TranslationTextComponent("tooltip.bloodmagic.activation_crystal." + type.name().toLowerCase()));
|
||||
|
||||
if (!stack.hasTag())
|
||||
return;
|
||||
|
||||
Binding binding = getBinding(stack);
|
||||
if (binding != null)
|
||||
tooltip.add(new TranslationTextComponent("tooltip.bloodmagic.currentOwner", binding.getOwnerName()));
|
||||
|
||||
super.addInformation(stack, world, tooltip, flag);
|
||||
}
|
||||
|
||||
public int getCrystalLevel(ItemStack stack)
|
||||
{
|
||||
return this.type.equals(CrystalType.CREATIVE) ? Integer.MAX_VALUE : type.ordinal() + 1;
|
||||
}
|
||||
|
||||
public enum CrystalType
|
||||
{
|
||||
WEAK, AWAKENED, CREATIVE,;
|
||||
|
||||
@Nonnull
|
||||
public static ItemStack getStack(int level)
|
||||
{
|
||||
if (level < 0)
|
||||
{
|
||||
level = 0;
|
||||
}
|
||||
switch (level)
|
||||
{
|
||||
case 0:
|
||||
return new ItemStack(BloodMagicItems.WEAK_ACTIVATION_CRYSTAL.get());
|
||||
case 1:
|
||||
return new ItemStack(BloodMagicItems.AWAKENED_ACTIVATION_CRYSTAL.get());
|
||||
default:
|
||||
return new ItemStack(BloodMagicItems.CREATIVE_ACTIVATION_CRYSTAL.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
76
src/main/java/wayoftime/bloodmagic/demonaura/PosXY.java
Normal file
76
src/main/java/wayoftime/bloodmagic/demonaura/PosXY.java
Normal file
|
@ -0,0 +1,76 @@
|
|||
package wayoftime.bloodmagic.demonaura;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
public class PosXY implements Comparable<PosXY>
|
||||
{
|
||||
public int x;
|
||||
public int y;
|
||||
|
||||
public PosXY()
|
||||
{
|
||||
}
|
||||
|
||||
public PosXY(int x, int y)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(PosXY c)
|
||||
{
|
||||
return this.y == c.y ? this.x - c.x : this.y - c.y;
|
||||
}
|
||||
|
||||
public float getDistanceSquared(int x, int z)
|
||||
{
|
||||
float f = this.x - x;
|
||||
float f2 = this.y - z;
|
||||
return f * f + f2 * f2;
|
||||
}
|
||||
|
||||
public float getDistanceSquaredToChunkCoordinates(PosXY c)
|
||||
{
|
||||
return getDistanceSquared(c.x, c.y);
|
||||
}
|
||||
|
||||
public void setX(int x)
|
||||
{
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public void setY(int y)
|
||||
{
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return new ToStringBuilder(this).append("x", x).append("y", y).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof PosXY))
|
||||
return false;
|
||||
|
||||
PosXY posXY = (PosXY) o;
|
||||
|
||||
if (x != posXY.x)
|
||||
return false;
|
||||
return y == posXY.y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int result = x;
|
||||
result = 31 * result + y;
|
||||
return result;
|
||||
}
|
||||
}
|
72
src/main/java/wayoftime/bloodmagic/demonaura/WillChunk.java
Normal file
72
src/main/java/wayoftime/bloodmagic/demonaura/WillChunk.java
Normal file
|
@ -0,0 +1,72 @@
|
|||
package wayoftime.bloodmagic.demonaura;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import wayoftime.bloodmagic.will.DemonWillHolder;
|
||||
|
||||
public class WillChunk
|
||||
{
|
||||
PosXY loc;
|
||||
private short base;
|
||||
private DemonWillHolder currentWill = new DemonWillHolder();
|
||||
private WeakReference<Chunk> chunkRef;
|
||||
|
||||
public WillChunk(PosXY loc)
|
||||
{
|
||||
this.loc = loc;
|
||||
}
|
||||
|
||||
public WillChunk(Chunk chunk, short base, DemonWillHolder currentWill)
|
||||
{
|
||||
this.loc = new PosXY(chunk.getPos().x, chunk.getPos().z);
|
||||
this.chunkRef = new WeakReference(chunk);
|
||||
this.base = base;
|
||||
this.currentWill = currentWill;
|
||||
}
|
||||
|
||||
public boolean isModified()
|
||||
{
|
||||
return (this.chunkRef != null) && (this.chunkRef.get() != null) && this.chunkRef.get().isModified();
|
||||
}
|
||||
|
||||
public PosXY getLoc()
|
||||
{
|
||||
return loc;
|
||||
}
|
||||
|
||||
public void setLoc(PosXY loc)
|
||||
{
|
||||
this.loc = loc;
|
||||
}
|
||||
|
||||
public short getBase()
|
||||
{
|
||||
return base;
|
||||
}
|
||||
|
||||
public void setBase(short base)
|
||||
{
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
public DemonWillHolder getCurrentWill()
|
||||
{
|
||||
return currentWill;
|
||||
}
|
||||
|
||||
public void setCurrentWill(DemonWillHolder currentWill)
|
||||
{
|
||||
this.currentWill = currentWill;
|
||||
}
|
||||
|
||||
public WeakReference<Chunk> getChunkRef()
|
||||
{
|
||||
return chunkRef;
|
||||
}
|
||||
|
||||
public void setChunkRef(WeakReference<Chunk> chunkRef)
|
||||
{
|
||||
this.chunkRef = chunkRef;
|
||||
}
|
||||
}
|
49
src/main/java/wayoftime/bloodmagic/demonaura/WillWorld.java
Normal file
49
src/main/java/wayoftime/bloodmagic/demonaura/WillWorld.java
Normal file
|
@ -0,0 +1,49 @@
|
|||
package wayoftime.bloodmagic.demonaura;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class WillWorld
|
||||
{
|
||||
// TODO: It was noted I may need to use RegistryKey<World> instead.
|
||||
ResourceLocation dim;
|
||||
ConcurrentHashMap<PosXY, WillChunk> willChunks = new ConcurrentHashMap<>();
|
||||
|
||||
// private static ConcurrentHashMap<PosXY, AspectList> nodeTickets = new ConcurrentHashMap();
|
||||
|
||||
public WillWorld(ResourceLocation resourceLocation)
|
||||
{
|
||||
this.dim = resourceLocation;
|
||||
}
|
||||
|
||||
public WillChunk getWillChunkAt(int x, int y)
|
||||
{
|
||||
return getWillChunkAt(new PosXY(x, y));
|
||||
}
|
||||
|
||||
public WillChunk getWillChunkAt(PosXY loc)
|
||||
{
|
||||
return this.willChunks.get(loc);
|
||||
}
|
||||
|
||||
public ConcurrentHashMap<PosXY, WillChunk> getWillChunks()
|
||||
{
|
||||
return willChunks;
|
||||
}
|
||||
|
||||
public void setWillChunks(ConcurrentHashMap<PosXY, WillChunk> willChunks)
|
||||
{
|
||||
this.willChunks = willChunks;
|
||||
}
|
||||
|
||||
// public static ConcurrentHashMap<PosXY, AspectList> getNodeTickets()
|
||||
// {
|
||||
// return nodeTickets;
|
||||
// }
|
||||
//
|
||||
// public static void setNodeTickets(ConcurrentHashMap<PosXY, AspectList> nodeTickets)
|
||||
// {
|
||||
// nodeTickets = nodeTickets;
|
||||
// }
|
||||
}
|
|
@ -0,0 +1,218 @@
|
|||
package wayoftime.bloodmagic.demonaura;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import wayoftime.bloodmagic.util.BMLog;
|
||||
import wayoftime.bloodmagic.will.DemonWillHolder;
|
||||
import wayoftime.bloodmagic.will.EnumDemonWillType;
|
||||
|
||||
public class WorldDemonWillHandler
|
||||
{
|
||||
public static ConcurrentHashMap<ResourceLocation, CopyOnWriteArrayList<PosXY>> dirtyChunks = new ConcurrentHashMap<>();
|
||||
static ConcurrentHashMap<ResourceLocation, WillWorld> containedWills = new ConcurrentHashMap<>();
|
||||
|
||||
@Nullable
|
||||
public static DemonWillHolder getWillHolder(ResourceLocation resourceLocation, int x, int y)
|
||||
{
|
||||
WillChunk chunk = getWillChunk(resourceLocation, x, y);
|
||||
if (chunk != null)
|
||||
{
|
||||
return chunk.getCurrentWill();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static DemonWillHolder getWillHolder(World world, BlockPos pos)
|
||||
{
|
||||
return getWillHolder(getDimensionResourceLocation(world), pos.getX() >> 4, pos.getZ() >> 4);
|
||||
}
|
||||
|
||||
public static WillWorld getWillWorld(int dim)
|
||||
{
|
||||
return containedWills.get(dim);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static WillChunk getWillChunk(ResourceLocation resourceLocation, int x, int y)
|
||||
{
|
||||
if (!containedWills.containsKey(resourceLocation))
|
||||
{
|
||||
addWillWorld(resourceLocation);
|
||||
}
|
||||
|
||||
return (containedWills.get(resourceLocation)).getWillChunkAt(x, y);
|
||||
}
|
||||
|
||||
public static void addWillWorld(ResourceLocation resourceLocation)
|
||||
{
|
||||
if (!containedWills.containsKey(resourceLocation))
|
||||
{
|
||||
containedWills.put(resourceLocation, new WillWorld(resourceLocation));
|
||||
BMLog.DEBUG.info("Creating demon will cache for world {}", resourceLocation);
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeWillWorld(int dim)
|
||||
{
|
||||
containedWills.remove(dim);
|
||||
BMLog.DEBUG.info("Removing demon will cache for world {}", dim);
|
||||
}
|
||||
|
||||
public static void addWillChunk(ResourceLocation resourceLocation, Chunk chunk, short base, DemonWillHolder currentWill)
|
||||
{
|
||||
WillWorld aw = containedWills.get(resourceLocation);
|
||||
if (aw == null)
|
||||
{
|
||||
aw = new WillWorld(resourceLocation);
|
||||
}
|
||||
aw.getWillChunks().put(new PosXY(chunk.getPos().x, chunk.getPos().z), new WillChunk(chunk, base, currentWill));
|
||||
|
||||
containedWills.put(resourceLocation, aw);
|
||||
}
|
||||
|
||||
public static void removeWillChunk(ResourceLocation resourceLocation, int x, int y)
|
||||
{
|
||||
WillWorld aw = containedWills.get(resourceLocation);
|
||||
if (aw != null)
|
||||
{
|
||||
WillChunk chunk = aw.getWillChunks().remove(new PosXY(x, y));
|
||||
if (chunk != null)
|
||||
{
|
||||
markChunkAsDirty(chunk, resourceLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static EnumDemonWillType getHighestDemonWillType(World world, BlockPos pos)
|
||||
{
|
||||
double currentMax = 0;
|
||||
EnumDemonWillType currentHighest = EnumDemonWillType.DEFAULT;
|
||||
|
||||
WillChunk willChunk = getWillChunk(world, pos);
|
||||
|
||||
DemonWillHolder currentWill = willChunk.getCurrentWill();
|
||||
for (EnumDemonWillType type : EnumDemonWillType.values())
|
||||
{
|
||||
if (currentWill.getWill(type) > currentMax)
|
||||
{
|
||||
currentMax = currentWill.getWill(type);
|
||||
currentHighest = type;
|
||||
}
|
||||
}
|
||||
|
||||
return currentHighest;
|
||||
}
|
||||
|
||||
public static double drainWill(World world, BlockPos pos, EnumDemonWillType type, double amount, boolean doDrain)
|
||||
{
|
||||
WillChunk willChunk = getWillChunk(world, pos);
|
||||
|
||||
DemonWillHolder currentWill = willChunk.getCurrentWill();
|
||||
double drain = Math.min(currentWill.getWill(type), amount);
|
||||
if (!doDrain)
|
||||
{
|
||||
return drain;
|
||||
}
|
||||
|
||||
drain = currentWill.drainWill(type, drain);
|
||||
markChunkAsDirty(willChunk, getDimensionResourceLocation(world));
|
||||
|
||||
return drain;
|
||||
}
|
||||
|
||||
public static double fillWillToMaximum(World world, BlockPos pos, EnumDemonWillType type, double amount, double max, boolean doFill)
|
||||
{
|
||||
WillChunk willChunk = getWillChunk(world, pos);
|
||||
|
||||
DemonWillHolder currentWill = willChunk.getCurrentWill();
|
||||
double fill = Math.min(amount, max - currentWill.getWill(type));
|
||||
if (!doFill || fill <= 0)
|
||||
{
|
||||
return fill > 0 ? fill : 0;
|
||||
}
|
||||
|
||||
fill = currentWill.addWill(type, amount, max);
|
||||
markChunkAsDirty(willChunk, getDimensionResourceLocation(world));
|
||||
|
||||
return fill;
|
||||
}
|
||||
|
||||
public static double fillWill(World world, BlockPos pos, EnumDemonWillType type, double amount, boolean doFill)
|
||||
{
|
||||
WillChunk willChunk = getWillChunk(world, pos);
|
||||
|
||||
DemonWillHolder currentWill = willChunk.getCurrentWill();
|
||||
if (!doFill)
|
||||
{
|
||||
return amount;
|
||||
}
|
||||
|
||||
currentWill.addWill(type, amount);
|
||||
markChunkAsDirty(willChunk, getDimensionResourceLocation(world));
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
public static WillChunk getWillChunk(World world, BlockPos pos)
|
||||
{
|
||||
WillChunk willChunk = getWillChunk(getDimensionResourceLocation(world), pos.getX() >> 4, pos.getZ() >> 4);
|
||||
if (willChunk == null)
|
||||
{
|
||||
Chunk chunk = world.getChunk(pos.getX() >> 4, pos.getZ() >> 4);
|
||||
generateWill(chunk);
|
||||
|
||||
willChunk = getWillChunk(getDimensionResourceLocation(world), pos.getX() >> 4, pos.getZ() >> 4);
|
||||
}
|
||||
|
||||
return willChunk;
|
||||
}
|
||||
|
||||
public static double getCurrentWill(World world, BlockPos pos, EnumDemonWillType type)
|
||||
{
|
||||
WillChunk willChunk = getWillChunk(world, pos);
|
||||
|
||||
if (willChunk == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
DemonWillHolder currentWill = willChunk.getCurrentWill();
|
||||
return currentWill.getWill(type);
|
||||
}
|
||||
|
||||
private static void markChunkAsDirty(WillChunk chunk, ResourceLocation resourceLocation)
|
||||
{
|
||||
if (chunk.isModified())
|
||||
{
|
||||
return;
|
||||
}
|
||||
PosXY pos = new PosXY(chunk.loc.x, chunk.loc.y);
|
||||
if (!dirtyChunks.containsKey(resourceLocation))
|
||||
{
|
||||
dirtyChunks.put(resourceLocation, new CopyOnWriteArrayList<>());
|
||||
}
|
||||
CopyOnWriteArrayList<PosXY> dc = dirtyChunks.get(resourceLocation);
|
||||
if (!dc.contains(pos))
|
||||
{
|
||||
dc.add(pos);
|
||||
}
|
||||
}
|
||||
|
||||
public static void generateWill(Chunk chunk)
|
||||
{
|
||||
addWillChunk(chunk.getWorld().getDimensionKey().getLocation(), chunk, (short) 1, new DemonWillHolder());
|
||||
}
|
||||
|
||||
private static ResourceLocation getDimensionResourceLocation(World world)
|
||||
{
|
||||
return world.getDimensionKey().getLocation();
|
||||
}
|
||||
}
|
151
src/main/java/wayoftime/bloodmagic/event/RitualEvent.java
Normal file
151
src/main/java/wayoftime/bloodmagic/event/RitualEvent.java
Normal file
|
@ -0,0 +1,151 @@
|
|||
package wayoftime.bloodmagic.event;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import wayoftime.bloodmagic.ritual.IMasterRitualStone;
|
||||
import wayoftime.bloodmagic.ritual.Ritual;
|
||||
import wayoftime.bloodmagic.ritual.imperfect.IImperfectRitualStone;
|
||||
import wayoftime.bloodmagic.ritual.imperfect.ImperfectRitual;
|
||||
|
||||
public class RitualEvent extends Event
|
||||
{
|
||||
private final IMasterRitualStone mrs;
|
||||
private final UUID ownerId;
|
||||
private final Ritual ritual;
|
||||
|
||||
private RitualEvent(IMasterRitualStone mrs, UUID ownerId, Ritual ritual)
|
||||
{
|
||||
this.mrs = mrs;
|
||||
this.ownerId = ownerId;
|
||||
this.ritual = ritual;
|
||||
}
|
||||
|
||||
public IMasterRitualStone getRitualStone()
|
||||
{
|
||||
return mrs;
|
||||
}
|
||||
|
||||
public UUID getOwnerId()
|
||||
{
|
||||
return ownerId;
|
||||
}
|
||||
|
||||
public Ritual getRitual()
|
||||
{
|
||||
return ritual;
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is called when a ritual is activated. If cancelled, it will not
|
||||
* activate.
|
||||
* <p>
|
||||
* {@link WayofTime.bloodmagic.tile.TileMasterRitualStone#activateRitual(ItemStack, PlayerEntity, Ritual)}
|
||||
*/
|
||||
@Cancelable
|
||||
public static class RitualActivatedEvent extends RitualEvent
|
||||
{
|
||||
|
||||
private final PlayerEntity player;
|
||||
private final ItemStack crystalStack;
|
||||
private final int crystalTier;
|
||||
|
||||
public RitualActivatedEvent(IMasterRitualStone mrs, UUID ownerId, Ritual ritual, PlayerEntity player, ItemStack activationCrystal, int crystalTier)
|
||||
{
|
||||
super(mrs, ownerId, ritual);
|
||||
|
||||
this.player = player;
|
||||
this.crystalStack = activationCrystal;
|
||||
this.crystalTier = crystalTier;
|
||||
}
|
||||
|
||||
public PlayerEntity getPlayer()
|
||||
{
|
||||
return player;
|
||||
}
|
||||
|
||||
public ItemStack getCrystalStack()
|
||||
{
|
||||
return crystalStack;
|
||||
}
|
||||
|
||||
public int getCrystalTier()
|
||||
{
|
||||
return crystalTier;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is called when a Ritual effect is performed. If cancelled, the
|
||||
* effect will not happen.
|
||||
* <p>
|
||||
* {@link WayofTime.bloodmagic.tile.TileMasterRitualStone#performRitual(World, net.minecraft.util.math.BlockPos)}
|
||||
*/
|
||||
@Cancelable
|
||||
public static class RitualRunEvent extends RitualEvent
|
||||
{
|
||||
|
||||
public RitualRunEvent(IMasterRitualStone mrs, UUID ownerId, Ritual ritual)
|
||||
{
|
||||
super(mrs, ownerId, ritual);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is called when a Ritual is stopped by a {@link Ritual.BreakType}.
|
||||
* <p>
|
||||
* {@link WayofTime.bloodmagic.tile.TileMasterRitualStone#stopRitual(Ritual.BreakType)}
|
||||
*/
|
||||
public static class RitualStopEvent extends RitualEvent
|
||||
{
|
||||
|
||||
private final Ritual.BreakType method;
|
||||
|
||||
public RitualStopEvent(IMasterRitualStone mrs, UUID ownerId, Ritual ritual, Ritual.BreakType method)
|
||||
{
|
||||
super(mrs, ownerId, ritual);
|
||||
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public Ritual.BreakType getMethod()
|
||||
{
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
||||
@Cancelable
|
||||
public static class ImperfectRitualActivatedEvent extends Event
|
||||
{
|
||||
|
||||
private final IImperfectRitualStone ims;
|
||||
private final PlayerEntity activator;
|
||||
private final ImperfectRitual imperfectRitual;
|
||||
|
||||
public ImperfectRitualActivatedEvent(IImperfectRitualStone ims, PlayerEntity activator, ImperfectRitual imperfectRitual)
|
||||
{
|
||||
this.ims = ims;
|
||||
this.activator = activator;
|
||||
this.imperfectRitual = imperfectRitual;
|
||||
}
|
||||
|
||||
public IImperfectRitualStone getRitualStone()
|
||||
{
|
||||
return ims;
|
||||
}
|
||||
|
||||
public PlayerEntity getActivator()
|
||||
{
|
||||
return activator;
|
||||
}
|
||||
|
||||
public ImperfectRitual getImperfectRitual()
|
||||
{
|
||||
return imperfectRitual;
|
||||
}
|
||||
}
|
||||
}
|
654
src/main/java/wayoftime/bloodmagic/ritual/AreaDescriptor.java
Normal file
654
src/main/java/wayoftime/bloodmagic/ritual/AreaDescriptor.java
Normal file
|
@ -0,0 +1,654 @@
|
|||
package wayoftime.bloodmagic.ritual;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.gen.feature.template.PlacementSettings;
|
||||
import net.minecraft.world.gen.feature.template.Template;
|
||||
import wayoftime.bloodmagic.util.Constants;
|
||||
|
||||
public abstract class AreaDescriptor implements Iterator<BlockPos>
|
||||
{
|
||||
public List<BlockPos> getContainedPositions(BlockPos pos)
|
||||
{
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public AxisAlignedBB getAABB(BlockPos pos)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract void resetCache();
|
||||
|
||||
public abstract boolean isWithinArea(BlockPos pos);
|
||||
|
||||
public abstract void resetIterator();
|
||||
|
||||
public void readFromNBT(CompoundNBT tag)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void writeToNBT(CompoundNBT tag)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public abstract AreaDescriptor copy();
|
||||
|
||||
public abstract int getVolumeForOffsets(BlockPos offset1, BlockPos offset2);
|
||||
|
||||
public abstract boolean isWithinRange(BlockPos offset1, BlockPos offset2, int verticalLimit, int horizontalLimit);
|
||||
|
||||
public abstract int getVolume();
|
||||
|
||||
public abstract int getHeight();
|
||||
|
||||
public abstract boolean isWithinRange(int verticalLimit, int horizontalLimit);
|
||||
|
||||
/**
|
||||
* This method changes the area descriptor so that its range matches the two
|
||||
* blocks that are selected. When implementing this method, assume that these
|
||||
* positions are the blocks that are clicked by the player.
|
||||
*
|
||||
* @param pos1
|
||||
* @param pos2
|
||||
*/
|
||||
public abstract void modifyAreaByBlockPositions(BlockPos pos1, BlockPos pos2);
|
||||
|
||||
public abstract boolean intersects(AreaDescriptor descriptor);
|
||||
|
||||
public abstract AreaDescriptor offset(BlockPos offset);
|
||||
|
||||
public abstract AreaDescriptor rotateDescriptor(PlacementSettings settings);
|
||||
|
||||
public static class Rectangle extends AreaDescriptor
|
||||
{
|
||||
protected BlockPos minimumOffset;
|
||||
protected BlockPos maximumOffset; // Non-inclusive maximum offset.
|
||||
private BlockPos currentPosition;
|
||||
|
||||
private ArrayList<BlockPos> blockPosCache;
|
||||
private BlockPos cachedPosition;
|
||||
|
||||
private boolean cache = true;
|
||||
|
||||
/**
|
||||
* This constructor takes in the minimum and maximum BlockPos. The maximum
|
||||
* offset is non-inclusive, meaning if you pass in (0,0,0) and (1,1,1), calling
|
||||
* getContainedPositions() will only give (0,0,0).
|
||||
*
|
||||
* @param minimumOffset -
|
||||
* @param maximumOffset -
|
||||
*/
|
||||
public Rectangle(BlockPos minimumOffset, BlockPos maximumOffset)
|
||||
{
|
||||
setOffsets(minimumOffset, maximumOffset);
|
||||
}
|
||||
|
||||
public Rectangle(BlockPos minimumOffset, int sizeX, int sizeY, int sizeZ)
|
||||
{
|
||||
this(minimumOffset, minimumOffset.add(sizeX, sizeY, sizeZ));
|
||||
}
|
||||
|
||||
public Rectangle(BlockPos minimumOffset, int size)
|
||||
{
|
||||
this(minimumOffset, size, size, size);
|
||||
}
|
||||
|
||||
public Rectangle(AreaDescriptor.Rectangle rectangle)
|
||||
{
|
||||
this(rectangle.minimumOffset, rectangle.maximumOffset);
|
||||
}
|
||||
|
||||
public AreaDescriptor.Rectangle copy()
|
||||
{
|
||||
return new AreaDescriptor.Rectangle(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockPos> getContainedPositions(BlockPos pos)
|
||||
{
|
||||
if (!cache || !pos.equals(cachedPosition) || blockPosCache.isEmpty())
|
||||
{
|
||||
ArrayList<BlockPos> posList = new ArrayList<>();
|
||||
|
||||
for (int j = minimumOffset.getY(); j < maximumOffset.getY(); j++)
|
||||
{
|
||||
for (int i = minimumOffset.getX(); i < maximumOffset.getX(); i++)
|
||||
{
|
||||
for (int k = minimumOffset.getZ(); k < maximumOffset.getZ(); k++)
|
||||
{
|
||||
posList.add(pos.add(i, j, k));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blockPosCache = posList;
|
||||
cachedPosition = pos;
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(blockPosCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AxisAlignedBB getAABB(BlockPos pos)
|
||||
{
|
||||
AxisAlignedBB tempAABB = new AxisAlignedBB(minimumOffset, maximumOffset);
|
||||
return tempAABB.offset(pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight()
|
||||
{
|
||||
return this.maximumOffset.getY() - this.minimumOffset.getY();
|
||||
}
|
||||
|
||||
public BlockPos getMinimumOffset()
|
||||
{
|
||||
return minimumOffset;
|
||||
}
|
||||
|
||||
public BlockPos getMaximumOffset()
|
||||
{
|
||||
return maximumOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the offsets of the AreaDescriptor in a safe way that will make
|
||||
* minimumOffset the lowest corner
|
||||
*
|
||||
* @param offset1 -
|
||||
* @param offset2 -
|
||||
*/
|
||||
public void setOffsets(BlockPos offset1, BlockPos offset2)
|
||||
{
|
||||
this.minimumOffset = new BlockPos(Math.min(offset1.getX(), offset2.getX()), Math.min(offset1.getY(), offset2.getY()), Math.min(offset1.getZ(), offset2.getZ()));
|
||||
this.maximumOffset = new BlockPos(Math.max(offset1.getX(), offset2.getX()), Math.max(offset1.getY(), offset2.getY()), Math.max(offset1.getZ(), offset2.getZ()));
|
||||
blockPosCache = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetCache()
|
||||
{
|
||||
this.blockPosCache = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWithinArea(BlockPos pos)
|
||||
{
|
||||
int x = pos.getX();
|
||||
int y = pos.getY();
|
||||
int z = pos.getZ();
|
||||
|
||||
return x >= minimumOffset.getX() && x < maximumOffset.getX() && y >= minimumOffset.getY()
|
||||
&& y < maximumOffset.getY() && z >= minimumOffset.getZ() && z < maximumOffset.getZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext()
|
||||
{
|
||||
return currentPosition == null || !(currentPosition.getX() + 1 == maximumOffset.getX()
|
||||
&& currentPosition.getY() + 1 == maximumOffset.getY()
|
||||
&& currentPosition.getZ() + 1 == maximumOffset.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos next()
|
||||
{
|
||||
if (currentPosition != null)
|
||||
{
|
||||
int nextX = currentPosition.getX() + 1 >= maximumOffset.getX() ? minimumOffset.getX()
|
||||
: currentPosition.getX() + 1;
|
||||
int nextZ = nextX != minimumOffset.getX() ? currentPosition.getZ()
|
||||
: (currentPosition.getZ() + 1 >= maximumOffset.getZ() ? minimumOffset.getZ()
|
||||
: currentPosition.getZ() + 1);
|
||||
int nextY = (nextZ != minimumOffset.getZ() || nextX != minimumOffset.getX()) ? currentPosition.getY()
|
||||
: (currentPosition.getY() + 1);
|
||||
currentPosition = new BlockPos(nextX, nextY, nextZ);
|
||||
} else
|
||||
{
|
||||
currentPosition = minimumOffset;
|
||||
}
|
||||
|
||||
return currentPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetIterator()
|
||||
{
|
||||
currentPosition = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifyAreaByBlockPositions(BlockPos pos1, BlockPos pos2)
|
||||
{
|
||||
setOffsets(pos1, pos2);
|
||||
maximumOffset = maximumOffset.add(1, 1, 1);
|
||||
resetIterator();
|
||||
resetCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(CompoundNBT tag)
|
||||
{
|
||||
minimumOffset = new BlockPos(tag.getInt(Constants.NBT.X_COORD + "min"), tag.getInt(Constants.NBT.Y_COORD + "min"), tag.getInt(Constants.NBT.Z_COORD + "min"));
|
||||
maximumOffset = new BlockPos(tag.getInt(Constants.NBT.X_COORD + "max"), tag.getInt(Constants.NBT.Y_COORD + "max"), tag.getInt(Constants.NBT.Z_COORD + "max"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(CompoundNBT tag)
|
||||
{
|
||||
tag.putInt(Constants.NBT.X_COORD + "min", minimumOffset.getX());
|
||||
tag.putInt(Constants.NBT.Y_COORD + "min", minimumOffset.getY());
|
||||
tag.putInt(Constants.NBT.Z_COORD + "min", minimumOffset.getZ());
|
||||
tag.putInt(Constants.NBT.X_COORD + "max", maximumOffset.getX());
|
||||
tag.putInt(Constants.NBT.Y_COORD + "max", maximumOffset.getY());
|
||||
tag.putInt(Constants.NBT.Z_COORD + "max", maximumOffset.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVolumeForOffsets(BlockPos offset1, BlockPos offset2)
|
||||
{
|
||||
BlockPos minPos = new BlockPos(Math.min(offset1.getX(), offset2.getX()), Math.min(offset1.getY(), offset2.getY()), Math.min(offset1.getZ(), offset2.getZ()));
|
||||
BlockPos maxPos = new BlockPos(Math.max(offset1.getX(), offset2.getX()), Math.max(offset1.getY(), offset2.getY()), Math.max(offset1.getZ(), offset2.getZ()));
|
||||
|
||||
maxPos = maxPos.add(1, 1, 1);
|
||||
|
||||
return (maxPos.getX() - minPos.getX()) * (maxPos.getY() - minPos.getY()) * (maxPos.getZ() - minPos.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWithinRange(BlockPos offset1, BlockPos offset2, int verticalLimit, int horizontalLimit)
|
||||
{
|
||||
BlockPos minPos = new BlockPos(Math.min(offset1.getX(), offset2.getX()), Math.min(offset1.getY(), offset2.getY()), Math.min(offset1.getZ(), offset2.getZ()));
|
||||
BlockPos maxPos = new BlockPos(Math.max(offset1.getX(), offset2.getX()), Math.max(offset1.getY(), offset2.getY()), Math.max(offset1.getZ(), offset2.getZ()));
|
||||
|
||||
return minPos.getY() >= -verticalLimit && maxPos.getY() <= verticalLimit
|
||||
&& minPos.getX() >= -horizontalLimit && maxPos.getX() <= horizontalLimit
|
||||
&& minPos.getZ() >= -horizontalLimit && maxPos.getZ() <= horizontalLimit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVolume()
|
||||
{
|
||||
return (maximumOffset.getX() - minimumOffset.getX()) * (maximumOffset.getY() - minimumOffset.getY())
|
||||
* (maximumOffset.getZ() - minimumOffset.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWithinRange(int verticalLimit, int horizontalLimit)
|
||||
{
|
||||
return minimumOffset.getY() >= -verticalLimit && maximumOffset.getY() <= verticalLimit + 1
|
||||
&& minimumOffset.getX() >= -horizontalLimit && maximumOffset.getX() <= horizontalLimit + 1
|
||||
&& minimumOffset.getZ() >= -horizontalLimit && maximumOffset.getZ() <= horizontalLimit + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean intersects(AreaDescriptor descriptor)
|
||||
{
|
||||
if (descriptor instanceof AreaDescriptor.Rectangle)
|
||||
{
|
||||
AreaDescriptor.Rectangle rectangle = (AreaDescriptor.Rectangle) descriptor;
|
||||
|
||||
return !(minimumOffset.getX() >= rectangle.maximumOffset.getX()
|
||||
|| minimumOffset.getY() >= rectangle.maximumOffset.getY()
|
||||
|| minimumOffset.getZ() >= rectangle.maximumOffset.getZ()
|
||||
|| rectangle.minimumOffset.getX() >= maximumOffset.getX()
|
||||
|| rectangle.minimumOffset.getY() >= maximumOffset.getY()
|
||||
|| rectangle.minimumOffset.getZ() >= maximumOffset.getZ());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AreaDescriptor offset(BlockPos offset)
|
||||
{
|
||||
return new AreaDescriptor.Rectangle(this.minimumOffset.add(offset), this.maximumOffset.add(offset));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AreaDescriptor rotateDescriptor(PlacementSettings settings)
|
||||
{
|
||||
BlockPos rotatePos1 = Template.transformedBlockPos(settings, minimumOffset);
|
||||
BlockPos rotatePos2 = Template.transformedBlockPos(settings, maximumOffset.add(-1, -1, -1)); // It works,
|
||||
// shut up!
|
||||
|
||||
AreaDescriptor.Rectangle rectangle = new AreaDescriptor.Rectangle(this.minimumOffset, 1);
|
||||
rectangle.modifyAreaByBlockPositions(rotatePos1, rotatePos2);
|
||||
|
||||
return rectangle;
|
||||
}
|
||||
}
|
||||
|
||||
public static class HemiSphere extends AreaDescriptor
|
||||
{
|
||||
private BlockPos minimumOffset;
|
||||
private int radius;
|
||||
|
||||
private ArrayList<BlockPos> blockPosCache;
|
||||
private BlockPos cachedPosition;
|
||||
|
||||
private boolean cache = true;
|
||||
|
||||
public HemiSphere(BlockPos minimumOffset, int radius)
|
||||
{
|
||||
setRadius(minimumOffset, radius);
|
||||
}
|
||||
|
||||
public HemiSphere(AreaDescriptor.HemiSphere hemiSphere)
|
||||
{
|
||||
this(hemiSphere.minimumOffset, hemiSphere.radius);
|
||||
}
|
||||
|
||||
public AreaDescriptor.HemiSphere copy()
|
||||
{
|
||||
return new AreaDescriptor.HemiSphere(this);
|
||||
}
|
||||
|
||||
public void setRadius(BlockPos minimumOffset, int radius)
|
||||
{
|
||||
this.minimumOffset = new BlockPos(Math.min(minimumOffset.getX(), minimumOffset.getX()), Math.min(minimumOffset.getY(), minimumOffset.getY()), Math.min(minimumOffset.getZ(), minimumOffset.getZ()));
|
||||
this.radius = radius;
|
||||
blockPosCache = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight()
|
||||
{
|
||||
return this.radius * 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockPos> getContainedPositions(BlockPos pos)
|
||||
{
|
||||
if (!cache || !pos.equals(cachedPosition) || blockPosCache.isEmpty())
|
||||
{
|
||||
ArrayList<BlockPos> posList = new ArrayList<>();
|
||||
|
||||
int i = -radius;
|
||||
int j = minimumOffset.getY();
|
||||
int k = -radius;
|
||||
|
||||
// TODO For some reason the bottom of the hemisphere is not going up with the
|
||||
// minOffset
|
||||
|
||||
while (i <= radius)
|
||||
{
|
||||
while (j <= radius)
|
||||
{
|
||||
while (k <= radius)
|
||||
{
|
||||
if (i * i + j * j + k * k >= (radius + 0.5F) * (radius + 0.5F))
|
||||
{
|
||||
k++;
|
||||
continue;
|
||||
}
|
||||
|
||||
posList.add(pos.add(i, j, k));
|
||||
k++;
|
||||
}
|
||||
|
||||
k = -radius;
|
||||
j++;
|
||||
}
|
||||
|
||||
j = minimumOffset.getY();
|
||||
i++;
|
||||
}
|
||||
|
||||
blockPosCache = posList;
|
||||
cachedPosition = pos;
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(blockPosCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Since you can't make a box using a sphere, this returns null
|
||||
*/
|
||||
@Override
|
||||
public AxisAlignedBB getAABB(BlockPos pos)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetCache()
|
||||
{
|
||||
this.blockPosCache = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWithinArea(BlockPos pos)
|
||||
{
|
||||
return blockPosCache.contains(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos next()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetIterator()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifyAreaByBlockPositions(BlockPos pos1, BlockPos pos2)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVolumeForOffsets(BlockPos pos1, BlockPos pos2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWithinRange(BlockPos offset1, BlockPos offset2, int verticalLimit, int horizontalLimit)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVolume()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWithinRange(int verticalLimit, int horizontalLimit)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean intersects(AreaDescriptor descriptor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AreaDescriptor offset(BlockPos offset)
|
||||
{
|
||||
return new AreaDescriptor.HemiSphere(minimumOffset.add(offset), radius);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AreaDescriptor rotateDescriptor(PlacementSettings settings)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Cross extends AreaDescriptor
|
||||
{
|
||||
|
||||
private ArrayList<BlockPos> blockPosCache;
|
||||
private BlockPos cachedPosition;
|
||||
|
||||
private BlockPos centerPos;
|
||||
private int size;
|
||||
|
||||
private boolean cache = true;
|
||||
|
||||
public Cross(BlockPos center, int size)
|
||||
{
|
||||
this.centerPos = center;
|
||||
this.size = size;
|
||||
this.blockPosCache = new ArrayList<>();
|
||||
}
|
||||
|
||||
public Cross(AreaDescriptor.Cross cross)
|
||||
{
|
||||
this(cross.centerPos, cross.size);
|
||||
}
|
||||
|
||||
public AreaDescriptor.Cross copy()
|
||||
{
|
||||
return new AreaDescriptor.Cross(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight()
|
||||
{
|
||||
return this.size * 2 + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockPos> getContainedPositions(BlockPos pos)
|
||||
{
|
||||
if (!cache || !pos.equals(cachedPosition) || blockPosCache.isEmpty())
|
||||
{
|
||||
resetCache();
|
||||
|
||||
blockPosCache.add(centerPos.add(pos));
|
||||
for (int i = 1; i <= size; i++)
|
||||
{
|
||||
blockPosCache.add(centerPos.add(pos).add(i, 0, 0));
|
||||
blockPosCache.add(centerPos.add(pos).add(0, 0, i));
|
||||
blockPosCache.add(centerPos.add(pos).add(-i, 0, 0));
|
||||
blockPosCache.add(centerPos.add(pos).add(0, 0, -i));
|
||||
}
|
||||
}
|
||||
|
||||
cachedPosition = pos;
|
||||
|
||||
return Collections.unmodifiableList(blockPosCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetCache()
|
||||
{
|
||||
blockPosCache = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWithinArea(BlockPos pos)
|
||||
{
|
||||
return blockPosCache.contains(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos next()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetIterator()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifyAreaByBlockPositions(BlockPos pos1, BlockPos pos2)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVolumeForOffsets(BlockPos pos1, BlockPos pos2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWithinRange(BlockPos offset1, BlockPos offset2, int verticalLimit, int horizontalLimit)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVolume()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWithinRange(int verticalLimit, int horizontalLimit)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean intersects(AreaDescriptor descriptor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AreaDescriptor offset(BlockPos offset)
|
||||
{
|
||||
return new AreaDescriptor.Cross(centerPos.add(offset), size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AreaDescriptor rotateDescriptor(PlacementSettings settings)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package wayoftime.bloodmagic.ritual;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import net.minecraft.nbt.ByteNBT;
|
||||
import net.minecraft.nbt.INBT;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
|
||||
public final class CapabilityRuneType
|
||||
{
|
||||
public static class RuneTypeStorage implements Capability.IStorage<IRitualStone.Tile>
|
||||
{
|
||||
@Override
|
||||
public INBT writeNBT(Capability<IRitualStone.Tile> capability, IRitualStone.Tile instance, Direction side)
|
||||
{
|
||||
return ByteNBT.valueOf((byte) instance.getRuneType().ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readNBT(Capability<IRitualStone.Tile> capability, IRitualStone.Tile instance, Direction side, INBT nbt)
|
||||
{
|
||||
instance.setRuneType(EnumRuneType.byMetadata(((ByteNBT) nbt).getByte()));
|
||||
}
|
||||
}
|
||||
|
||||
public static class RuneTypeWrapper implements IRitualStone.Tile
|
||||
{
|
||||
private EnumRuneType type = EnumRuneType.BLANK;
|
||||
|
||||
@Override
|
||||
public boolean isRuneType(EnumRuneType runeType)
|
||||
{
|
||||
return type == runeType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumRuneType getRuneType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setRuneType(EnumRuneType runeType)
|
||||
{
|
||||
type = runeType;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Factory implements Callable<IRitualStone.Tile>
|
||||
{
|
||||
@Override
|
||||
public IRitualStone.Tile call()
|
||||
throws Exception
|
||||
{
|
||||
return new RuneTypeWrapper();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package wayoftime.bloodmagic.ritual;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import net.minecraft.util.IStringSerializable;
|
||||
|
||||
public enum EnumReaderBoundaries implements IStringSerializable
|
||||
{
|
||||
SUCCESS, VOLUME_TOO_LARGE, NOT_WITHIN_BOUNDARIES;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return name().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString()
|
||||
{
|
||||
return toString();
|
||||
}
|
||||
}
|
54
src/main/java/wayoftime/bloodmagic/ritual/EnumRuneType.java
Normal file
54
src/main/java/wayoftime/bloodmagic/ritual/EnumRuneType.java
Normal file
|
@ -0,0 +1,54 @@
|
|||
package wayoftime.bloodmagic.ritual;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import net.minecraft.util.IStringSerializable;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
|
||||
public enum EnumRuneType implements IStringSerializable
|
||||
{
|
||||
BLANK(TextFormatting.GRAY),
|
||||
WATER(TextFormatting.AQUA),
|
||||
FIRE(TextFormatting.RED),
|
||||
EARTH(TextFormatting.GREEN),
|
||||
AIR(TextFormatting.WHITE),
|
||||
DUSK(TextFormatting.DARK_GRAY),
|
||||
DAWN(TextFormatting.GOLD);
|
||||
|
||||
public final TextFormatting colorCode;
|
||||
|
||||
EnumRuneType(TextFormatting colorCode)
|
||||
{
|
||||
this.colorCode = colorCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return name().toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString()
|
||||
{
|
||||
return this.toString();
|
||||
}
|
||||
|
||||
// @Nonnull
|
||||
// public ItemStack getStack(int count)
|
||||
// {
|
||||
// ItemStack ret = new ItemStack(RegistrarBloodMagicItems.INSCRIPTION_TOOL, count, ordinal());
|
||||
// CompoundNBT tag = new CompoundNBT();
|
||||
// tag.putInt(Constants.NBT.USES, 10);
|
||||
// ret.setTag(tag);
|
||||
// return ret;
|
||||
// }
|
||||
|
||||
public static EnumRuneType byMetadata(int meta)
|
||||
{
|
||||
if (meta < 0 || meta >= values().length)
|
||||
meta = 0;
|
||||
|
||||
return values()[meta];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package wayoftime.bloodmagic.ritual;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import wayoftime.bloodmagic.core.data.SoulNetwork;
|
||||
import wayoftime.bloodmagic.core.data.SoulTicket;
|
||||
import wayoftime.bloodmagic.will.EnumDemonWillType;
|
||||
|
||||
/**
|
||||
* This interface is for internal implementation only.
|
||||
* <p>
|
||||
* It is provided via the API for easy obtaining of basic data.
|
||||
*/
|
||||
public interface IMasterRitualStone
|
||||
{
|
||||
UUID getOwner();
|
||||
|
||||
SoulNetwork getOwnerNetwork();
|
||||
|
||||
boolean activateRitual(ItemStack activationCrystal, PlayerEntity activator, Ritual ritual);
|
||||
|
||||
void performRitual(World world, BlockPos pos);
|
||||
|
||||
void stopRitual(Ritual.BreakType breakType);
|
||||
|
||||
int getCooldown();
|
||||
|
||||
void setCooldown(int cooldown);
|
||||
|
||||
boolean isActive();
|
||||
|
||||
void setActive(boolean active);
|
||||
|
||||
Direction getDirection();
|
||||
|
||||
boolean areTanksEmpty();
|
||||
|
||||
int getRunningTime();
|
||||
|
||||
World getWorldObj();
|
||||
|
||||
BlockPos getBlockPos();
|
||||
|
||||
String getNextBlockRange(String range);
|
||||
|
||||
void provideInformationOfRitualToPlayer(PlayerEntity player);
|
||||
|
||||
void provideInformationOfRangeToPlayer(PlayerEntity player, String range);
|
||||
|
||||
void provideInformationOfWillConfigToPlayer(PlayerEntity player, List<EnumDemonWillType> typeList);
|
||||
|
||||
void setActiveWillConfig(PlayerEntity player, List<EnumDemonWillType> typeList);
|
||||
|
||||
EnumReaderBoundaries setBlockRangeByBounds(PlayerEntity player, String range, BlockPos offset1, BlockPos offset2);
|
||||
|
||||
List<EnumDemonWillType> getActiveWillConfig();
|
||||
|
||||
default SoulTicket ticket(int amount)
|
||||
{
|
||||
return SoulTicket.block(getWorldObj(), getBlockPos(), amount);
|
||||
}
|
||||
|
||||
AreaDescriptor getBlockRange(String range);
|
||||
|
||||
void addBlockRanges(Map<String, AreaDescriptor> blockRanges);
|
||||
|
||||
void addBlockRange(String range, AreaDescriptor defaultRange);
|
||||
|
||||
void setBlockRanges(Map<String, AreaDescriptor> blockRanges);
|
||||
|
||||
void setBlockRange(String range, AreaDescriptor defaultRange);
|
||||
|
||||
Ritual getCurrentRitual();
|
||||
}
|
20
src/main/java/wayoftime/bloodmagic/ritual/IRitualStone.java
Normal file
20
src/main/java/wayoftime/bloodmagic/ritual/IRitualStone.java
Normal file
|
@ -0,0 +1,20 @@
|
|||
package wayoftime.bloodmagic.ritual;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public interface IRitualStone
|
||||
{
|
||||
boolean isRuneType(World world, BlockPos pos, EnumRuneType runeType);
|
||||
|
||||
void setRuneType(World world, BlockPos pos, EnumRuneType runeType);
|
||||
|
||||
interface Tile
|
||||
{
|
||||
boolean isRuneType(EnumRuneType runeType);
|
||||
|
||||
EnumRuneType getRuneType();
|
||||
|
||||
void setRuneType(EnumRuneType runeType);
|
||||
}
|
||||
}
|
427
src/main/java/wayoftime/bloodmagic/ritual/Ritual.java
Normal file
427
src/main/java/wayoftime/bloodmagic/ritual/Ritual.java
Normal file
|
@ -0,0 +1,427 @@
|
|||
package wayoftime.bloodmagic.ritual;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
import net.minecraft.world.World;
|
||||
import wayoftime.bloodmagic.demonaura.WorldDemonWillHandler;
|
||||
import wayoftime.bloodmagic.will.DemonWillHolder;
|
||||
import wayoftime.bloodmagic.will.EnumDemonWillType;
|
||||
|
||||
/**
|
||||
* Abstract class for creating new rituals. Register your ritual by annotating
|
||||
* it with {@link RitualRegister}
|
||||
*/
|
||||
public abstract class Ritual
|
||||
{
|
||||
|
||||
protected final Map<String, AreaDescriptor> modableRangeMap = new HashMap<>();
|
||||
protected final Map<String, Integer> volumeRangeMap = new HashMap<>();
|
||||
protected final Map<String, Integer> horizontalRangeMap = new HashMap<>();
|
||||
protected final Map<String, Integer> verticalRangeMap = new HashMap<>();
|
||||
private final String name;
|
||||
private final int crystalLevel;
|
||||
private final int activationCost;
|
||||
private final RitualRenderer renderer;
|
||||
private final String unlocalizedName;
|
||||
|
||||
public Ritual(String name, int crystalLevel, int activationCost, RitualRenderer renderer, String unlocalizedName)
|
||||
{
|
||||
this.name = name;
|
||||
this.crystalLevel = crystalLevel;
|
||||
this.activationCost = activationCost;
|
||||
this.renderer = renderer;
|
||||
this.unlocalizedName = unlocalizedName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name - The name of the ritual
|
||||
* @param crystalLevel - Required Activation Crystal tier
|
||||
* @param activationCost - Base LP cost for activating the ritual
|
||||
*/
|
||||
public Ritual(String name, int crystalLevel, int activationCost, String unlocalizedName)
|
||||
{
|
||||
this(name, crystalLevel, activationCost, null, unlocalizedName);
|
||||
}
|
||||
|
||||
public void readFromNBT(CompoundNBT tag)
|
||||
{
|
||||
ListNBT tags = tag.getList("areas", 10);
|
||||
if (tags.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < tags.size(); i++)
|
||||
{
|
||||
CompoundNBT newTag = tags.getCompound(i);
|
||||
String rangeKey = newTag.getString("key");
|
||||
|
||||
CompoundNBT storedTag = newTag.getCompound("area");
|
||||
AreaDescriptor desc = this.getBlockRange(rangeKey);
|
||||
if (desc != null)
|
||||
{
|
||||
desc.readFromNBT(storedTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void writeToNBT(CompoundNBT tag)
|
||||
{
|
||||
ListNBT tags = new ListNBT();
|
||||
|
||||
for (Entry<String, AreaDescriptor> entry : modableRangeMap.entrySet())
|
||||
{
|
||||
CompoundNBT newTag = new CompoundNBT();
|
||||
newTag.putString("key", entry.getKey());
|
||||
CompoundNBT storedTag = new CompoundNBT();
|
||||
|
||||
entry.getValue().writeToNBT(storedTag);
|
||||
|
||||
newTag.put("area", storedTag);
|
||||
|
||||
tags.add(newTag);
|
||||
}
|
||||
|
||||
tag.put("areas", tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the player attempts to activate the ritual.
|
||||
* <p>
|
||||
* {@link WayofTime.bloodmagic.tile.TileMasterRitualStone#activateRitual(ItemStack, PlayerEntity, Ritual)}
|
||||
*
|
||||
* @param masterRitualStone - The {@link IMasterRitualStone} that the ritual is
|
||||
* bound to
|
||||
* @param player - The activating player
|
||||
* @param owner - Owner of the crystal activating this ritual, or
|
||||
* the current owner of the ritual if being
|
||||
* reactivated.
|
||||
* @return - Whether activation was successful
|
||||
*/
|
||||
public boolean activateRitual(IMasterRitualStone masterRitualStone, PlayerEntity player, UUID owner)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every {@link #getRefreshTime()} ticks while active.
|
||||
* <p>
|
||||
* {@link WayofTime.bloodmagic.tile.TileMasterRitualStone#performRitual(World, BlockPos)}
|
||||
*
|
||||
* @param masterRitualStone - The {@link IMasterRitualStone} that the ritual is
|
||||
* bound to
|
||||
*/
|
||||
public abstract void performRitual(IMasterRitualStone masterRitualStone);
|
||||
|
||||
/**
|
||||
* Called when the ritual is stopped for a given {@link Ritual.BreakType}.
|
||||
* <p>
|
||||
* {@link WayofTime.bloodmagic.tile.TileMasterRitualStone#stopRitual(Ritual.BreakType)}
|
||||
*
|
||||
* @param masterRitualStone - The {@link IMasterRitualStone} that the ritual is
|
||||
* bound to
|
||||
* @param breakType - The type of break that caused the stoppage.
|
||||
*/
|
||||
public void stopRitual(IMasterRitualStone masterRitualStone, BreakType breakType)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to set the amount of LP drained every {@link #getRefreshTime()} ticks.
|
||||
*
|
||||
* @return - The amount of LP drained per refresh
|
||||
*/
|
||||
public abstract int getRefreshCost();
|
||||
|
||||
/**
|
||||
* Used to set the refresh rate of the ritual. (How often
|
||||
* {@link #performRitual(IMasterRitualStone)} is called.
|
||||
*
|
||||
* @return - How often to perform the effect in ticks.
|
||||
*/
|
||||
public int getRefreshTime()
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
|
||||
public void addBlockRange(String range, AreaDescriptor defaultRange)
|
||||
{
|
||||
modableRangeMap.put(range, defaultRange);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to grab the range of a ritual for a given effect.
|
||||
*
|
||||
* @param range - Range that needs to be pulled.
|
||||
* @return -
|
||||
*/
|
||||
public AreaDescriptor getBlockRange(String range)
|
||||
{
|
||||
if (modableRangeMap.containsKey(range))
|
||||
{
|
||||
return modableRangeMap.get(range);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<String> getListOfRanges()
|
||||
{
|
||||
return new ArrayList<>(modableRangeMap.keySet());
|
||||
}
|
||||
|
||||
public String getNextBlockRange(String range)
|
||||
{
|
||||
List<String> rangeList = getListOfRanges();
|
||||
|
||||
if (rangeList.isEmpty())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
if (!rangeList.contains(range))
|
||||
{
|
||||
return rangeList.get(0);
|
||||
}
|
||||
|
||||
boolean hasMatch = false;
|
||||
|
||||
for (String rangeCheck : rangeList)
|
||||
{
|
||||
if (hasMatch)
|
||||
{
|
||||
return rangeCheck;
|
||||
} else if (rangeCheck.equals(range))
|
||||
{
|
||||
hasMatch = true;
|
||||
}
|
||||
}
|
||||
|
||||
return rangeList.get(0);
|
||||
}
|
||||
|
||||
public EnumReaderBoundaries canBlockRangeBeModified(String range, AreaDescriptor descriptor, IMasterRitualStone master, BlockPos offset1, BlockPos offset2, DemonWillHolder holder)
|
||||
{
|
||||
List<EnumDemonWillType> willConfig = master.getActiveWillConfig();
|
||||
int maxVolume = getMaxVolumeForRange(range, willConfig, holder);
|
||||
int maxVertical = getMaxVerticalRadiusForRange(range, willConfig, holder);
|
||||
int maxHorizontal = getMaxHorizontalRadiusForRange(range, willConfig, holder);
|
||||
|
||||
return (maxVolume <= 0 || descriptor.getVolumeForOffsets(offset1, offset2) <= maxVolume)
|
||||
? descriptor.isWithinRange(offset1, offset2, maxVertical, maxHorizontal) ? EnumReaderBoundaries.SUCCESS
|
||||
: EnumReaderBoundaries.NOT_WITHIN_BOUNDARIES
|
||||
: EnumReaderBoundaries.VOLUME_TOO_LARGE;
|
||||
}
|
||||
|
||||
protected void setMaximumVolumeAndDistanceOfRange(String range, int volume, int horizontalRadius, int verticalRadius)
|
||||
{
|
||||
volumeRangeMap.put(range, volume);
|
||||
horizontalRangeMap.put(range, horizontalRadius);
|
||||
verticalRangeMap.put(range, verticalRadius);
|
||||
}
|
||||
|
||||
protected boolean checkDescriptorIsWithinRange(AreaDescriptor descriptor, int maxVolume, int maxHorizontal, int maxVertical)
|
||||
{
|
||||
return descriptor.getVolume() <= maxVolume && descriptor.isWithinRange(maxVertical, maxHorizontal);
|
||||
}
|
||||
|
||||
public int getMaxVolumeForRange(String range, List<EnumDemonWillType> activeTypes, DemonWillHolder holder)
|
||||
{
|
||||
return volumeRangeMap.get(range);
|
||||
}
|
||||
|
||||
public int getMaxVerticalRadiusForRange(String range, List<EnumDemonWillType> activeTypes, DemonWillHolder holder)
|
||||
{
|
||||
return verticalRangeMap.get(range);
|
||||
}
|
||||
|
||||
public int getMaxHorizontalRadiusForRange(String range, List<EnumDemonWillType> activeTypes, DemonWillHolder holder)
|
||||
{
|
||||
return horizontalRangeMap.get(range);
|
||||
}
|
||||
|
||||
public ITextComponent getErrorForBlockRangeOnFail(PlayerEntity player, String range, IMasterRitualStone master, BlockPos offset1, BlockPos offset2)
|
||||
{
|
||||
AreaDescriptor descriptor = this.getBlockRange(range);
|
||||
if (descriptor == null)
|
||||
{
|
||||
return new TranslationTextComponent("ritual.bloodmagic.blockRange.tooBig", "?");
|
||||
}
|
||||
|
||||
List<EnumDemonWillType> willConfig = master.getActiveWillConfig();
|
||||
DemonWillHolder holder = WorldDemonWillHandler.getWillHolder(master.getWorldObj(), master.getBlockPos());
|
||||
|
||||
int maxVolume = this.getMaxVolumeForRange(range, willConfig, holder);
|
||||
int maxVertical = this.getMaxVerticalRadiusForRange(range, willConfig, holder);
|
||||
int maxHorizontal = this.getMaxHorizontalRadiusForRange(range, willConfig, holder);
|
||||
|
||||
if (maxVolume > 0 && descriptor.getVolumeForOffsets(offset1, offset2) > maxVolume)
|
||||
{
|
||||
return new TranslationTextComponent("ritual.bloodmagic.blockRange.tooBig", maxVolume);
|
||||
} else
|
||||
{
|
||||
return new TranslationTextComponent("ritual.bloodmagic.blockRange.tooFar", maxVertical, maxHorizontal);
|
||||
}
|
||||
}
|
||||
|
||||
public ITextComponent[] provideInformationOfRitualToPlayer(PlayerEntity player)
|
||||
{
|
||||
return new ITextComponent[]
|
||||
{ new TranslationTextComponent(this.getTranslationKey() + ".info") };
|
||||
}
|
||||
|
||||
public ITextComponent provideInformationOfRangeToPlayer(PlayerEntity player, String range)
|
||||
{
|
||||
if (getListOfRanges().contains(range))
|
||||
{
|
||||
return new TranslationTextComponent(this.getTranslationKey() + "." + range + ".info");
|
||||
} else
|
||||
{
|
||||
return new TranslationTextComponent("ritual.bloodmagic.blockRange.noRange");
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void gatherComponents(Consumer<RitualComponent> components);
|
||||
|
||||
protected final void addRune(Consumer<RitualComponent> components, int offset1, int y, int offset2, EnumRuneType rune)
|
||||
{
|
||||
components.accept(new RitualComponent(new BlockPos(offset1, y, offset2), rune));
|
||||
}
|
||||
|
||||
protected final void addOffsetRunes(Consumer<RitualComponent> components, int offset1, int offset2, int y, EnumRuneType rune)
|
||||
{
|
||||
addRune(components, offset1, y, offset2, rune);
|
||||
addRune(components, offset2, y, offset1, rune);
|
||||
addRune(components, offset1, y, -offset2, rune);
|
||||
addRune(components, -offset2, y, offset1, rune);
|
||||
addRune(components, -offset1, y, offset2, rune);
|
||||
addRune(components, offset2, y, -offset1, rune);
|
||||
addRune(components, -offset1, y, -offset2, rune);
|
||||
addRune(components, -offset2, y, -offset1, rune);
|
||||
}
|
||||
|
||||
protected final void addCornerRunes(Consumer<RitualComponent> components, int offset, int y, EnumRuneType rune)
|
||||
{
|
||||
addRune(components, offset, y, offset, rune);
|
||||
addRune(components, offset, y, -offset, rune);
|
||||
addRune(components, -offset, y, -offset, rune);
|
||||
addRune(components, -offset, y, offset, rune);
|
||||
}
|
||||
|
||||
protected final void addParallelRunes(Consumer<RitualComponent> components, int offset, int y, EnumRuneType rune)
|
||||
{
|
||||
addRune(components, offset, y, 0, rune);
|
||||
addRune(components, -offset, y, 0, rune);
|
||||
addRune(components, 0, y, -offset, rune);
|
||||
addRune(components, 0, y, offset, rune);
|
||||
}
|
||||
|
||||
public double getWillRespectingConfig(World world, BlockPos pos, EnumDemonWillType type, List<EnumDemonWillType> willConfig)
|
||||
{
|
||||
return willConfig.contains(type) ? WorldDemonWillHandler.getCurrentWill(world, pos, type) : 0;
|
||||
}
|
||||
|
||||
public abstract Ritual getNewCopy();
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getCrystalLevel()
|
||||
{
|
||||
return crystalLevel;
|
||||
}
|
||||
|
||||
public int getActivationCost()
|
||||
{
|
||||
return activationCost;
|
||||
}
|
||||
|
||||
public RitualRenderer getRenderer()
|
||||
{
|
||||
return renderer;
|
||||
}
|
||||
|
||||
public String getTranslationKey()
|
||||
{
|
||||
return unlocalizedName;
|
||||
}
|
||||
|
||||
public Map<String, AreaDescriptor> getModableRangeMap()
|
||||
{
|
||||
return modableRangeMap;
|
||||
}
|
||||
|
||||
public Map<String, Integer> getVolumeRangeMap()
|
||||
{
|
||||
return volumeRangeMap;
|
||||
}
|
||||
|
||||
public Map<String, Integer> getHorizontalRangeMap()
|
||||
{
|
||||
return horizontalRangeMap;
|
||||
}
|
||||
|
||||
public Map<String, Integer> getVerticalRangeMap()
|
||||
{
|
||||
return verticalRangeMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return new ToStringBuilder(this).append("name", name).append("crystalLevel", crystalLevel).append("activationCost", activationCost).append("renderer", renderer).append("unlocalizedName", unlocalizedName).append("modableRangeMap", modableRangeMap).append("volumeRangeMap", volumeRangeMap).append("horizontalRangeMap", horizontalRangeMap).append("verticalRangeMap", verticalRangeMap).append("refreshTime", getRefreshTime()).append("listOfRanges", getListOfRanges()).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof Ritual))
|
||||
return false;
|
||||
|
||||
Ritual ritual = (Ritual) o;
|
||||
|
||||
if (crystalLevel != ritual.crystalLevel)
|
||||
return false;
|
||||
if (activationCost != ritual.activationCost)
|
||||
return false;
|
||||
if (name != null ? !name.equals(ritual.name) : ritual.name != null)
|
||||
return false;
|
||||
return unlocalizedName != null ? unlocalizedName.equals(ritual.unlocalizedName)
|
||||
: ritual.unlocalizedName == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int result = name != null ? name.hashCode() : 0;
|
||||
result = 31 * result + crystalLevel;
|
||||
result = 31 * result + activationCost;
|
||||
result = 31 * result + (unlocalizedName != null ? unlocalizedName.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
public enum BreakType
|
||||
{
|
||||
REDSTONE, BREAK_MRS, BREAK_STONE, ACTIVATE, DEACTIVATE, EXPLOSION,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package wayoftime.bloodmagic.ritual;
|
||||
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
/**
|
||||
* Used to set a {@link EnumRuneType} type to a given {@link BlockPos} for usage
|
||||
* in Ritual creation.
|
||||
*/
|
||||
public class RitualComponent
|
||||
{
|
||||
private final BlockPos offset;
|
||||
private final EnumRuneType runeType;
|
||||
|
||||
public RitualComponent(BlockPos offset, EnumRuneType runeType)
|
||||
{
|
||||
this.offset = offset;
|
||||
this.runeType = runeType;
|
||||
}
|
||||
|
||||
public int getX(Direction direction)
|
||||
{
|
||||
switch (direction)
|
||||
{
|
||||
case EAST:
|
||||
return -this.getOffset().getZ();
|
||||
case SOUTH:
|
||||
return -this.getOffset().getX();
|
||||
case WEST:
|
||||
return this.getOffset().getZ();
|
||||
default:
|
||||
return this.getOffset().getX();
|
||||
}
|
||||
}
|
||||
|
||||
public int getY()
|
||||
{
|
||||
return this.getOffset().getY();
|
||||
}
|
||||
|
||||
public int getZ(Direction direction)
|
||||
{
|
||||
switch (direction)
|
||||
{
|
||||
case EAST:
|
||||
return this.getOffset().getX();
|
||||
case SOUTH:
|
||||
return -this.getOffset().getZ();
|
||||
case WEST:
|
||||
return -this.getOffset().getX();
|
||||
default:
|
||||
return this.getOffset().getZ();
|
||||
}
|
||||
}
|
||||
|
||||
public BlockPos getOffset(Direction direction)
|
||||
{
|
||||
return new BlockPos(getX(direction), offset.getY(), getZ(direction));
|
||||
}
|
||||
|
||||
public BlockPos getOffset()
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
|
||||
public EnumRuneType getRuneType()
|
||||
{
|
||||
return runeType;
|
||||
}
|
||||
}
|
177
src/main/java/wayoftime/bloodmagic/ritual/RitualManager.java
Normal file
177
src/main/java/wayoftime/bloodmagic/ritual/RitualManager.java
Normal file
|
@ -0,0 +1,177 @@
|
|||
package wayoftime.bloodmagic.ritual;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import wayoftime.bloodmagic.ritual.imperfect.ImperfectRitual;
|
||||
import wayoftime.bloodmagic.util.BMLog;
|
||||
|
||||
public class RitualManager
|
||||
{
|
||||
public static final DamageSource RITUAL_DAMAGE = new DamageSource("ritual_damage").setDamageBypassesArmor();
|
||||
|
||||
private final Map<String, Ritual> rituals;
|
||||
private final Map<Ritual, String> ritualsReverse;
|
||||
private final List<Ritual> sortedRituals;
|
||||
private final Map<String, ImperfectRitual> imperfectRituals;
|
||||
private final Map<ImperfectRitual, String> imperfectRitualsReverse;
|
||||
// private final Configuration config;
|
||||
|
||||
public RitualManager()
|
||||
{
|
||||
this.rituals = Maps.newTreeMap();
|
||||
this.ritualsReverse = Maps.newHashMap();
|
||||
this.sortedRituals = Lists.newArrayList();
|
||||
this.imperfectRituals = Maps.newTreeMap();
|
||||
this.imperfectRitualsReverse = Maps.newHashMap();
|
||||
// this.config = config;
|
||||
}
|
||||
|
||||
// public void discover(ASMDataTable dataTable)
|
||||
public void discover()
|
||||
{
|
||||
ModList.get().getAllScanData().forEach(scan -> {
|
||||
scan.getAnnotations().forEach(a -> {
|
||||
if (a.getAnnotationType().getClassName().equals(RitualRegister.class.getName()))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
Class<?> clazz = Class.forName(a.getClassType().getClassName());
|
||||
RitualRegister ritualRegister = clazz.getAnnotation(RitualRegister.class);
|
||||
String id = ritualRegister.value();
|
||||
if (Ritual.class.isAssignableFrom(clazz))
|
||||
{
|
||||
Ritual ritual = (Ritual) clazz.newInstance();
|
||||
rituals.put(id, ritual);
|
||||
ritualsReverse.put(ritual, id);
|
||||
BMLog.DEBUG.info("Registered ritual {}", id);
|
||||
} else
|
||||
{
|
||||
BMLog.DEFAULT.error("Error creating ritual instance for {}.", id);
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
ModList.get().getAllScanData().forEach(scan -> {
|
||||
scan.getAnnotations().forEach(a -> {
|
||||
if (a.getAnnotationType().getClassName().equals(RitualRegister.Imperfect.class.getName()))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
Class<?> clazz = Class.forName(a.getClassType().getClassName());
|
||||
RitualRegister.Imperfect ritualRegister = clazz.getAnnotation(RitualRegister.Imperfect.class);
|
||||
String id = ritualRegister.value();
|
||||
if (ImperfectRitual.class.isAssignableFrom(clazz))
|
||||
{
|
||||
ImperfectRitual ritual = (ImperfectRitual) clazz.newInstance();
|
||||
imperfectRituals.put(id, ritual);
|
||||
imperfectRitualsReverse.put(ritual, id);
|
||||
BMLog.DEBUG.info("Registered imperfect ritual {}", id);
|
||||
} else
|
||||
{
|
||||
BMLog.DEFAULT.error("Error creating imperfect ritual instance for {}.", id);
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// syncConfig();
|
||||
|
||||
// Sort rituals
|
||||
sortedRituals.addAll(rituals.values());
|
||||
// Oh dear this is probably so slow
|
||||
sortedRituals.sort((o1, o2) -> {
|
||||
Set<RitualComponent> components = Sets.newHashSet();
|
||||
o1.gatherComponents(components::add);
|
||||
int initialSize = components.size();
|
||||
components.clear();
|
||||
o2.gatherComponents(components::add);
|
||||
return Integer.compare(initialSize, components.size());
|
||||
});
|
||||
}
|
||||
|
||||
public Ritual getRitual(String id)
|
||||
{
|
||||
return rituals.get(id);
|
||||
}
|
||||
|
||||
public String getId(Ritual ritual)
|
||||
{
|
||||
return ritualsReverse.get(ritual);
|
||||
}
|
||||
|
||||
public ImperfectRitual getImperfectRitual(BlockState state)
|
||||
{
|
||||
for (ImperfectRitual ritual : imperfectRituals.values()) if (ritual.getBlockRequirement().test(state))
|
||||
return ritual;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getId(ImperfectRitual ritual)
|
||||
{
|
||||
return imperfectRitualsReverse.get(ritual);
|
||||
}
|
||||
|
||||
public Collection<Ritual> getRituals()
|
||||
{
|
||||
return rituals.values();
|
||||
}
|
||||
|
||||
public Collection<ImperfectRitual> getImperfectRituals()
|
||||
{
|
||||
return imperfectRituals.values();
|
||||
}
|
||||
|
||||
public List<Ritual> getSortedRituals()
|
||||
{
|
||||
return sortedRituals;
|
||||
}
|
||||
|
||||
// public void syncConfig()
|
||||
// {
|
||||
// config.addCustomCategoryComment("rituals", "Toggles for all rituals");
|
||||
// rituals.forEach((k, v) -> config.getBoolean(k, "rituals", true, "Enable the " + k + " ritual."));
|
||||
// imperfectRituals.forEach((k, v) -> config.getBoolean(k, "rituals.imperfect", true, "Enable the " + k + " imperfect ritual."));
|
||||
// config.save();
|
||||
// }
|
||||
//
|
||||
public boolean enabled(String id, boolean imperfect)
|
||||
{
|
||||
return id != null;
|
||||
// return id != null && config.getBoolean(id, "rituals" + (imperfect ? ".imperfect" : ""), true, "");
|
||||
}
|
||||
//
|
||||
// public Configuration getConfig()
|
||||
// {
|
||||
// return config;
|
||||
// }
|
||||
|
||||
public static class BadRitualException extends RuntimeException
|
||||
{
|
||||
public BadRitualException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package wayoftime.bloodmagic.ritual;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.function.Function;
|
||||
|
||||
import wayoftime.bloodmagic.ritual.imperfect.ImperfectRitual;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface RitualRegister
|
||||
{
|
||||
String value();
|
||||
|
||||
Class<? extends Function<Class<? extends Ritual>, Ritual>> factory() default DefaultRitualFactory.class;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
@interface Imperfect
|
||||
{
|
||||
|
||||
String value();
|
||||
|
||||
Class<? extends Function<Class<? extends ImperfectRitual>, ImperfectRitual>> factory() default DefaultImperfectRitualFactory.class;
|
||||
}
|
||||
|
||||
class DefaultRitualFactory implements Function<Class<? extends Ritual>, Ritual>
|
||||
{
|
||||
@Override
|
||||
public Ritual apply(Class<? extends Ritual> aClass)
|
||||
{
|
||||
try
|
||||
{
|
||||
return aClass.newInstance();
|
||||
} catch (Exception e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DefaultImperfectRitualFactory implements Function<Class<? extends ImperfectRitual>, ImperfectRitual>
|
||||
{
|
||||
@Override
|
||||
public ImperfectRitual apply(Class<? extends ImperfectRitual> aClass)
|
||||
{
|
||||
try
|
||||
{
|
||||
return aClass.newInstance();
|
||||
} catch (Exception e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package wayoftime.bloodmagic.ritual;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public abstract class RitualRenderer
|
||||
{
|
||||
public abstract void renderAt(IMasterRitualStone masterRitualStone, double x, double y, double z);
|
||||
|
||||
protected void bindTexture(ResourceLocation resourceLocation)
|
||||
{
|
||||
Minecraft.getInstance().getTextureManager().bindTexture(resourceLocation);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package wayoftime.bloodmagic.ritual.imperfect;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
* This interface is for internal implementation only.
|
||||
* <p>
|
||||
* It is provided via the API for easy obtaining of basic data.
|
||||
*/
|
||||
public interface IImperfectRitualStone
|
||||
{
|
||||
|
||||
boolean performRitual(World world, BlockPos pos, ImperfectRitual imperfectRitual, PlayerEntity player);
|
||||
|
||||
World getRitualWorld();
|
||||
|
||||
BlockPos getRitualPos();
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package wayoftime.bloodmagic.ritual.imperfect;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
* Abstract class for creating new imperfect rituals. To register, annotate your
|
||||
* class with {@link WayofTime.bloodmagic.ritual.RitualRegister.Imperfect}
|
||||
*/
|
||||
public abstract class ImperfectRitual
|
||||
{
|
||||
|
||||
private final String name;
|
||||
private final Predicate<BlockState> blockRequirement;
|
||||
private final int activationCost;
|
||||
private final boolean lightShow;
|
||||
private final String unlocalizedName;
|
||||
|
||||
public ImperfectRitual(String name, Predicate<BlockState> blockRequirement, int activationCost, boolean lightShow, String unlocalizedName)
|
||||
{
|
||||
this.name = name;
|
||||
this.blockRequirement = blockRequirement;
|
||||
this.activationCost = activationCost;
|
||||
this.lightShow = lightShow;
|
||||
this.unlocalizedName = unlocalizedName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name The name of the ritual
|
||||
* @param blockRequirement The block required above the ImperfectRitualStone
|
||||
* @param activationCost Base LP cost for activating the ritual
|
||||
*/
|
||||
public ImperfectRitual(String name, Predicate<BlockState> blockRequirement, int activationCost, String unlocalizedName)
|
||||
{
|
||||
this(name, blockRequirement, activationCost, false, unlocalizedName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the player activates the ritual
|
||||
* {@link WayofTime.bloodmagic.tile.TileImperfectRitualStone#performRitual(World, net.minecraft.util.math.BlockPos, ImperfectRitual, PlayerEntity)}
|
||||
*
|
||||
* @param imperfectRitualStone - The {@link IImperfectRitualStone} that the
|
||||
* ritual is bound to
|
||||
* @param player - The player activating the ritual
|
||||
* @return - Whether activation was successful
|
||||
*/
|
||||
public abstract boolean onActivate(IImperfectRitualStone imperfectRitualStone, PlayerEntity player);
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public Predicate<BlockState> getBlockRequirement()
|
||||
{
|
||||
return blockRequirement;
|
||||
}
|
||||
|
||||
public int getActivationCost()
|
||||
{
|
||||
return activationCost;
|
||||
}
|
||||
|
||||
public boolean isLightShow()
|
||||
{
|
||||
return lightShow;
|
||||
}
|
||||
|
||||
public String getTranslationKey()
|
||||
{
|
||||
return unlocalizedName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getName() + "@" + getActivationCost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof ImperfectRitual))
|
||||
return false;
|
||||
|
||||
ImperfectRitual that = (ImperfectRitual) o;
|
||||
|
||||
if (activationCost != that.activationCost)
|
||||
return false;
|
||||
if (name != null ? !name.equals(that.name) : that.name != null)
|
||||
return false;
|
||||
return unlocalizedName != null ? unlocalizedName.equals(that.unlocalizedName) : that.unlocalizedName == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int result = name != null ? name.hashCode() : 0;
|
||||
result = 31 * result + activationCost;
|
||||
result = 31 * result + (unlocalizedName != null ? unlocalizedName.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package wayoftime.bloodmagic.ritual.types;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import wayoftime.bloodmagic.BloodMagic;
|
||||
import wayoftime.bloodmagic.ritual.AreaDescriptor;
|
||||
import wayoftime.bloodmagic.ritual.EnumRuneType;
|
||||
import wayoftime.bloodmagic.ritual.IMasterRitualStone;
|
||||
import wayoftime.bloodmagic.ritual.Ritual;
|
||||
import wayoftime.bloodmagic.ritual.RitualComponent;
|
||||
import wayoftime.bloodmagic.ritual.RitualRegister;
|
||||
|
||||
@RitualRegister("water")
|
||||
public class RitualWater extends Ritual
|
||||
{
|
||||
public static final String WATER_RANGE = "waterRange";
|
||||
|
||||
public RitualWater()
|
||||
{
|
||||
super("ritualWater", 0, 500, "ritual." + BloodMagic.MODID + ".waterRitual");
|
||||
addBlockRange(WATER_RANGE, new AreaDescriptor.Rectangle(new BlockPos(0, 1, 0), 1));
|
||||
setMaximumVolumeAndDistanceOfRange(WATER_RANGE, 9, 3, 3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performRitual(IMasterRitualStone masterRitualStone)
|
||||
{
|
||||
World world = masterRitualStone.getWorldObj();
|
||||
int currentEssence = masterRitualStone.getOwnerNetwork().getCurrentEssence();
|
||||
|
||||
if (currentEssence < getRefreshCost())
|
||||
{
|
||||
masterRitualStone.getOwnerNetwork().causeNausea();
|
||||
return;
|
||||
}
|
||||
|
||||
int maxEffects = currentEssence / getRefreshCost();
|
||||
int totalEffects = 0;
|
||||
|
||||
AreaDescriptor waterRange = masterRitualStone.getBlockRange(WATER_RANGE);
|
||||
|
||||
for (BlockPos newPos : waterRange.getContainedPositions(masterRitualStone.getBlockPos()))
|
||||
{
|
||||
if (world.isAirBlock(newPos))
|
||||
{
|
||||
world.setBlockState(newPos, Blocks.WATER.getDefaultState());
|
||||
totalEffects++;
|
||||
}
|
||||
|
||||
if (totalEffects >= maxEffects)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
masterRitualStone.getOwnerNetwork().syphon(masterRitualStone.ticket(getRefreshCost() * totalEffects));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRefreshTime()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRefreshCost()
|
||||
{
|
||||
return 25;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gatherComponents(Consumer<RitualComponent> components)
|
||||
{
|
||||
addCornerRunes(components, 1, 0, EnumRuneType.WATER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ritual getNewCopy()
|
||||
{
|
||||
return new RitualWater();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,566 @@
|
|||
package wayoftime.bloodmagic.tile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.registries.ObjectHolder;
|
||||
import wayoftime.bloodmagic.BloodMagic;
|
||||
import wayoftime.bloodmagic.common.item.ItemActivationCrystal;
|
||||
import wayoftime.bloodmagic.core.data.Binding;
|
||||
import wayoftime.bloodmagic.core.data.SoulNetwork;
|
||||
import wayoftime.bloodmagic.demonaura.WorldDemonWillHandler;
|
||||
import wayoftime.bloodmagic.event.RitualEvent;
|
||||
import wayoftime.bloodmagic.iface.IBindable;
|
||||
import wayoftime.bloodmagic.ritual.AreaDescriptor;
|
||||
import wayoftime.bloodmagic.ritual.EnumReaderBoundaries;
|
||||
import wayoftime.bloodmagic.ritual.IMasterRitualStone;
|
||||
import wayoftime.bloodmagic.ritual.Ritual;
|
||||
import wayoftime.bloodmagic.tile.base.TileTicking;
|
||||
import wayoftime.bloodmagic.util.ChatUtil;
|
||||
import wayoftime.bloodmagic.util.Constants;
|
||||
import wayoftime.bloodmagic.util.helper.BindableHelper;
|
||||
import wayoftime.bloodmagic.util.helper.NBTHelper;
|
||||
import wayoftime.bloodmagic.util.helper.NetworkHelper;
|
||||
import wayoftime.bloodmagic.util.helper.PlayerHelper;
|
||||
import wayoftime.bloodmagic.util.helper.RitualHelper;
|
||||
import wayoftime.bloodmagic.will.DemonWillHolder;
|
||||
import wayoftime.bloodmagic.will.EnumDemonWillType;
|
||||
|
||||
public class TileMasterRitualStone extends TileTicking implements IMasterRitualStone
|
||||
{
|
||||
@ObjectHolder("bloodmagic:masterritualstone")
|
||||
public static TileEntityType<TileMasterRitualStone> TYPE;
|
||||
protected final Map<String, AreaDescriptor> modableRangeMap = new HashMap<>();
|
||||
private UUID owner;
|
||||
private SoulNetwork cachedNetwork;
|
||||
private boolean active;
|
||||
private boolean redstoned;
|
||||
private int activeTime;
|
||||
private int cooldown;
|
||||
private Ritual currentRitual;
|
||||
private Direction direction = Direction.NORTH;
|
||||
private boolean inverted;
|
||||
private List<EnumDemonWillType> currentActiveWillConfig = new ArrayList<>();
|
||||
|
||||
public TileMasterRitualStone(TileEntityType<?> type)
|
||||
{
|
||||
super(type);
|
||||
}
|
||||
|
||||
public TileMasterRitualStone()
|
||||
{
|
||||
this(TYPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate()
|
||||
{
|
||||
if (getWorld().isRemote)
|
||||
return;
|
||||
|
||||
if (isPowered() && isActive())
|
||||
{
|
||||
active = false;
|
||||
redstoned = true;
|
||||
stopRitual(Ritual.BreakType.REDSTONE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isActive() && !isPowered() && isRedstoned() && getCurrentRitual() != null)
|
||||
{
|
||||
active = true;
|
||||
ItemStack crystalStack = NBTHelper.checkNBT(ItemActivationCrystal.CrystalType.getStack(getCurrentRitual().getCrystalLevel()));
|
||||
BindableHelper.applyBinding(crystalStack, new Binding(owner, PlayerHelper.getUsernameFromUUID(owner)));
|
||||
activateRitual(crystalStack, null, getCurrentRitual());
|
||||
redstoned = false;
|
||||
}
|
||||
|
||||
if (getCurrentRitual() != null && isActive())
|
||||
{
|
||||
if (activeTime % getCurrentRitual().getRefreshTime() == 0)
|
||||
performRitual(getWorld(), getPos());
|
||||
|
||||
activeTime++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(CompoundNBT tag)
|
||||
{
|
||||
owner = tag.hasUniqueId("owner") ? tag.getUniqueId("owner") : null;
|
||||
if (owner != null)
|
||||
cachedNetwork = NetworkHelper.getSoulNetwork(owner);
|
||||
currentRitual = BloodMagic.RITUAL_MANAGER.getRitual(tag.getString(Constants.NBT.CURRENT_RITUAL));
|
||||
if (currentRitual != null)
|
||||
{
|
||||
CompoundNBT ritualTag = tag.getCompound(Constants.NBT.CURRENT_RITUAL_TAG);
|
||||
if (!ritualTag.isEmpty())
|
||||
{
|
||||
currentRitual.readFromNBT(ritualTag);
|
||||
}
|
||||
}
|
||||
active = tag.getBoolean(Constants.NBT.IS_RUNNING);
|
||||
activeTime = tag.getInt(Constants.NBT.RUNTIME);
|
||||
direction = Direction.values()[tag.getInt(Constants.NBT.DIRECTION)];
|
||||
redstoned = tag.getBoolean(Constants.NBT.IS_REDSTONED);
|
||||
|
||||
for (EnumDemonWillType type : EnumDemonWillType.values())
|
||||
{
|
||||
if (tag.getBoolean("EnumWill" + type))
|
||||
{
|
||||
currentActiveWillConfig.add(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT serialize(CompoundNBT tag)
|
||||
{
|
||||
String ritualId = BloodMagic.RITUAL_MANAGER.getId(getCurrentRitual());
|
||||
if (owner != null)
|
||||
tag.putUniqueId("owner", owner);
|
||||
tag.putString(Constants.NBT.CURRENT_RITUAL, Strings.isNullOrEmpty(ritualId) ? "" : ritualId);
|
||||
if (currentRitual != null)
|
||||
{
|
||||
CompoundNBT ritualTag = new CompoundNBT();
|
||||
currentRitual.writeToNBT(ritualTag);
|
||||
tag.put(Constants.NBT.CURRENT_RITUAL_TAG, ritualTag);
|
||||
}
|
||||
tag.putBoolean(Constants.NBT.IS_RUNNING, isActive());
|
||||
tag.putInt(Constants.NBT.RUNTIME, getActiveTime());
|
||||
tag.putInt(Constants.NBT.DIRECTION, direction.getIndex());
|
||||
tag.putBoolean(Constants.NBT.IS_REDSTONED, redstoned);
|
||||
|
||||
for (EnumDemonWillType type : currentActiveWillConfig)
|
||||
{
|
||||
tag.putBoolean("EnumWill" + type, true);
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean activateRitual(ItemStack activationCrystal, @Nullable PlayerEntity activator, Ritual ritual)
|
||||
{
|
||||
if (PlayerHelper.isFakePlayer(activator))
|
||||
return false;
|
||||
|
||||
Binding binding = ((IBindable) activationCrystal.getItem()).getBinding(activationCrystal);
|
||||
if (binding != null && ritual != null)
|
||||
{
|
||||
if (activationCrystal.getItem() instanceof ItemActivationCrystal)
|
||||
{
|
||||
int crystalLevel = ((ItemActivationCrystal) activationCrystal.getItem()).getCrystalLevel(activationCrystal);
|
||||
if (RitualHelper.canCrystalActivate(ritual, crystalLevel))
|
||||
{
|
||||
if (!getWorld().isRemote)
|
||||
{
|
||||
SoulNetwork network = NetworkHelper.getSoulNetwork(binding);
|
||||
|
||||
if (!isRedstoned() && network.getCurrentEssence() < ritual.getActivationCost()
|
||||
&& (activator != null && !activator.isCreative()))
|
||||
{
|
||||
activator.sendStatusMessage(new TranslationTextComponent("chat.bloodmagic.ritual.weak"), true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (currentRitual != null)
|
||||
currentRitual.stopRitual(this, Ritual.BreakType.ACTIVATE);
|
||||
|
||||
RitualEvent.RitualActivatedEvent event = new RitualEvent.RitualActivatedEvent(this, binding.getOwnerId(), ritual, activator, activationCrystal, crystalLevel);
|
||||
|
||||
if (MinecraftForge.EVENT_BUS.post(event))
|
||||
{
|
||||
if (activator != null)
|
||||
activator.sendStatusMessage(new TranslationTextComponent("chat.bloodmagic.ritual.prevent"), true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ritual.activateRitual(this, activator, binding.getOwnerId()))
|
||||
{
|
||||
if (!isRedstoned() && (activator != null && !activator.isCreative()))
|
||||
network.syphon(ticket(ritual.getActivationCost()));
|
||||
|
||||
if (activator != null)
|
||||
activator.sendStatusMessage(new TranslationTextComponent("chat.bloodmagic.ritual.activate"), true);
|
||||
|
||||
this.active = true;
|
||||
this.owner = binding.getOwnerId();
|
||||
this.cachedNetwork = network;
|
||||
this.currentRitual = ritual;
|
||||
|
||||
if (!checkBlockRanges(ritual.getModableRangeMap()))
|
||||
addBlockRanges(ritual.getModableRangeMap());
|
||||
|
||||
notifyUpdate();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
notifyUpdate();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (activator != null)
|
||||
activator.sendStatusMessage(new TranslationTextComponent("chat.bloodmagic.ritual.notValid"), true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performRitual(World world, BlockPos pos)
|
||||
{
|
||||
if (!world.isRemote && getCurrentRitual() != null
|
||||
&& BloodMagic.RITUAL_MANAGER.enabled(BloodMagic.RITUAL_MANAGER.getId(currentRitual), false))
|
||||
{
|
||||
if (RitualHelper.checkValidRitual(getWorld(), getPos(), currentRitual, getDirection()))
|
||||
{
|
||||
Ritual ritual = getCurrentRitual();
|
||||
RitualEvent.RitualRunEvent event = new RitualEvent.RitualRunEvent(this, getOwner(), ritual);
|
||||
|
||||
if (MinecraftForge.EVENT_BUS.post(event))
|
||||
return;
|
||||
|
||||
if (!checkBlockRanges(getCurrentRitual().getModableRangeMap()))
|
||||
addBlockRanges(getCurrentRitual().getModableRangeMap());
|
||||
|
||||
getCurrentRitual().performRitual(this);
|
||||
} else
|
||||
{
|
||||
stopRitual(Ritual.BreakType.BREAK_STONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopRitual(Ritual.BreakType breakType)
|
||||
{
|
||||
if (!getWorld().isRemote && getCurrentRitual() != null)
|
||||
{
|
||||
RitualEvent.RitualStopEvent event = new RitualEvent.RitualStopEvent(this, getOwner(), getCurrentRitual(), breakType);
|
||||
|
||||
if (MinecraftForge.EVENT_BUS.post(event))
|
||||
return;
|
||||
|
||||
getCurrentRitual().stopRitual(this, breakType);
|
||||
if (breakType != Ritual.BreakType.REDSTONE)
|
||||
{
|
||||
this.currentRitual = null;
|
||||
this.active = false;
|
||||
this.activeTime = 0;
|
||||
}
|
||||
notifyUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCooldown()
|
||||
{
|
||||
return cooldown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCooldown(int cooldown)
|
||||
{
|
||||
this.cooldown = cooldown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Direction getDirection()
|
||||
{
|
||||
return direction;
|
||||
}
|
||||
|
||||
public void setDirection(Direction direction)
|
||||
{
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areTanksEmpty()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRunningTime()
|
||||
{
|
||||
return activeTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getOwner()
|
||||
{
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(UUID owner)
|
||||
{
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoulNetwork getOwnerNetwork()
|
||||
{
|
||||
return cachedNetwork;
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld()
|
||||
{
|
||||
return super.getWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getPos()
|
||||
{
|
||||
return super.getPos();
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorldObj()
|
||||
{
|
||||
return getWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getBlockPos()
|
||||
{
|
||||
return getPos();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNextBlockRange(String range)
|
||||
{
|
||||
if (this.currentRitual != null)
|
||||
{
|
||||
return this.currentRitual.getNextBlockRange(range);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void provideInformationOfRitualToPlayer(PlayerEntity player)
|
||||
{
|
||||
if (this.currentRitual != null)
|
||||
{
|
||||
ChatUtil.sendNoSpam(player, this.currentRitual.provideInformationOfRitualToPlayer(player));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void provideInformationOfRangeToPlayer(PlayerEntity player, String range)
|
||||
{
|
||||
if (this.currentRitual != null && this.currentRitual.getListOfRanges().contains(range))
|
||||
{
|
||||
ChatUtil.sendNoSpam(player, this.currentRitual.provideInformationOfRangeToPlayer(player, range));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActiveWillConfig(PlayerEntity player, List<EnumDemonWillType> typeList)
|
||||
{
|
||||
this.currentActiveWillConfig = typeList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumReaderBoundaries setBlockRangeByBounds(PlayerEntity player, String range, BlockPos offset1, BlockPos offset2)
|
||||
{
|
||||
AreaDescriptor descriptor = this.getBlockRange(range);
|
||||
DemonWillHolder holder = WorldDemonWillHandler.getWillHolder(world, getBlockPos());
|
||||
|
||||
EnumReaderBoundaries modificationType = currentRitual.canBlockRangeBeModified(range, descriptor, this, offset1, offset2, holder);
|
||||
if (modificationType == EnumReaderBoundaries.SUCCESS)
|
||||
descriptor.modifyAreaByBlockPositions(offset1, offset2);
|
||||
|
||||
return modificationType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EnumDemonWillType> getActiveWillConfig()
|
||||
{
|
||||
return new ArrayList<>(currentActiveWillConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void provideInformationOfWillConfigToPlayer(PlayerEntity player, List<EnumDemonWillType> typeList)
|
||||
{
|
||||
// There is probably an easier way to make expanded chat messages
|
||||
if (typeList.size() >= 1)
|
||||
{
|
||||
Object[] translations = new TranslationTextComponent[typeList.size()];
|
||||
StringBuilder constructedString = new StringBuilder("%s");
|
||||
|
||||
for (int i = 1; i < typeList.size(); i++)
|
||||
{
|
||||
constructedString.append(", %s");
|
||||
}
|
||||
|
||||
for (int i = 0; i < typeList.size(); i++)
|
||||
{
|
||||
translations[i] = new TranslationTextComponent("tooltip.bloodmagic.currentBaseType." + typeList.get(i).name.toLowerCase());
|
||||
}
|
||||
|
||||
ChatUtil.sendNoSpam(player, new TranslationTextComponent("ritual.bloodmagic.willConfig.set", new TranslationTextComponent(constructedString.toString(), translations)));
|
||||
} else
|
||||
{
|
||||
ChatUtil.sendNoSpam(player, new TranslationTextComponent("ritual.bloodmagic.willConfig.void"));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPowered()
|
||||
{
|
||||
if (inverted)
|
||||
return !getWorld().isBlockPowered(getPos());
|
||||
|
||||
return getWorld().isBlockPowered(getPos());
|
||||
}
|
||||
|
||||
public SoulNetwork getCachedNetwork()
|
||||
{
|
||||
return cachedNetwork;
|
||||
}
|
||||
|
||||
public void setCachedNetwork(SoulNetwork cachedNetwork)
|
||||
{
|
||||
this.cachedNetwork = cachedNetwork;
|
||||
}
|
||||
|
||||
public boolean isActive()
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActive(boolean active)
|
||||
{
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public boolean isRedstoned()
|
||||
{
|
||||
return redstoned;
|
||||
}
|
||||
|
||||
public void setRedstoned(boolean redstoned)
|
||||
{
|
||||
this.redstoned = redstoned;
|
||||
}
|
||||
|
||||
public int getActiveTime()
|
||||
{
|
||||
return activeTime;
|
||||
}
|
||||
|
||||
public void setActiveTime(int activeTime)
|
||||
{
|
||||
this.activeTime = activeTime;
|
||||
}
|
||||
|
||||
public Ritual getCurrentRitual()
|
||||
{
|
||||
return currentRitual;
|
||||
}
|
||||
|
||||
public void setCurrentRitual(Ritual currentRitual)
|
||||
{
|
||||
this.currentRitual = currentRitual;
|
||||
}
|
||||
|
||||
public boolean isInverted()
|
||||
{
|
||||
return inverted;
|
||||
}
|
||||
|
||||
public void setInverted(boolean inverted)
|
||||
{
|
||||
this.inverted = inverted;
|
||||
}
|
||||
|
||||
public List<EnumDemonWillType> getCurrentActiveWillConfig()
|
||||
{
|
||||
return currentActiveWillConfig;
|
||||
}
|
||||
|
||||
public void setCurrentActiveWillConfig(List<EnumDemonWillType> currentActiveWillConfig)
|
||||
{
|
||||
this.currentActiveWillConfig = currentActiveWillConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to grab the range of a ritual for a given effect.
|
||||
*
|
||||
* @param range - Range that needs to be pulled.
|
||||
* @return -
|
||||
*/
|
||||
public AreaDescriptor getBlockRange(String range)
|
||||
{
|
||||
if (modableRangeMap.containsKey(range))
|
||||
{
|
||||
return modableRangeMap.get(range);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBlockRange(String range, AreaDescriptor defaultRange)
|
||||
{
|
||||
modableRangeMap.putIfAbsent(range, defaultRange.copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBlockRanges(Map<String, AreaDescriptor> blockRanges)
|
||||
{
|
||||
for (Map.Entry<String, AreaDescriptor> entry : blockRanges.entrySet())
|
||||
{
|
||||
modableRangeMap.putIfAbsent(entry.getKey(), entry.getValue().copy());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockRange(String range, AreaDescriptor defaultRange)
|
||||
{
|
||||
modableRangeMap.put(range, defaultRange.copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockRanges(Map<String, AreaDescriptor> blockRanges)
|
||||
{
|
||||
for (Map.Entry<String, AreaDescriptor> entry : blockRanges.entrySet())
|
||||
{
|
||||
modableRangeMap.put(entry.getKey(), entry.getValue().copy());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean checkBlockRanges(Map<String, AreaDescriptor> blockRanges)
|
||||
{
|
||||
for (Map.Entry<String, AreaDescriptor> entry : blockRanges.entrySet())
|
||||
{
|
||||
if (modableRangeMap.get(entry.getKey()) == null)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package wayoftime.bloodmagic.tile.base;
|
||||
|
||||
import net.minecraft.client.renderer.texture.ITickable;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
|
||||
/**
|
||||
* Base class for tiles that tick. Allows disabling the ticking
|
||||
* programmatically.
|
||||
*/
|
||||
// TODO - Move implementations that depend on existed ticks to new methods from here.
|
||||
public abstract class TileTicking extends TileBase implements ITickable
|
||||
{
|
||||
private int ticksExisted;
|
||||
private boolean shouldTick = true;
|
||||
|
||||
public TileTicking(TileEntityType<?> type)
|
||||
{
|
||||
super(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void tick()
|
||||
{
|
||||
if (shouldTick())
|
||||
{
|
||||
ticksExisted++;
|
||||
onUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void deserializeBase(CompoundNBT tagCompound)
|
||||
{
|
||||
this.ticksExisted = tagCompound.getInt("ticksExisted");
|
||||
this.shouldTick = tagCompound.getBoolean("shouldTick");
|
||||
}
|
||||
|
||||
@Override
|
||||
CompoundNBT serializeBase(CompoundNBT tagCompound)
|
||||
{
|
||||
tagCompound.putInt("ticksExisted", getTicksExisted());
|
||||
tagCompound.putBoolean("shouldTick", shouldTick());
|
||||
return tagCompound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every tick that {@link #shouldTick()} is true.
|
||||
*/
|
||||
public abstract void onUpdate();
|
||||
|
||||
public int getTicksExisted()
|
||||
{
|
||||
return ticksExisted;
|
||||
}
|
||||
|
||||
public void resetLifetime()
|
||||
{
|
||||
ticksExisted = 0;
|
||||
}
|
||||
|
||||
public boolean shouldTick()
|
||||
{
|
||||
return shouldTick;
|
||||
}
|
||||
|
||||
public void setShouldTick(boolean shouldTick)
|
||||
{
|
||||
this.shouldTick = shouldTick;
|
||||
}
|
||||
}
|
253
src/main/java/wayoftime/bloodmagic/util/helper/RitualHelper.java
Normal file
253
src/main/java/wayoftime/bloodmagic/util/helper/RitualHelper.java
Normal file
|
@ -0,0 +1,253 @@
|
|||
package wayoftime.bloodmagic.util.helper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.CapabilityInject;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import wayoftime.bloodmagic.BloodMagic;
|
||||
import wayoftime.bloodmagic.common.block.BlockRitualStone;
|
||||
import wayoftime.bloodmagic.common.block.BloodMagicBlocks;
|
||||
import wayoftime.bloodmagic.ritual.EnumRuneType;
|
||||
import wayoftime.bloodmagic.ritual.IRitualStone;
|
||||
import wayoftime.bloodmagic.ritual.IRitualStone.Tile;
|
||||
import wayoftime.bloodmagic.ritual.Ritual;
|
||||
import wayoftime.bloodmagic.ritual.RitualComponent;
|
||||
import wayoftime.bloodmagic.tile.TileMasterRitualStone;
|
||||
|
||||
public class RitualHelper
|
||||
{
|
||||
@CapabilityInject(IRitualStone.Tile.class)
|
||||
static Capability<IRitualStone.Tile> RUNE_CAPABILITY = null;
|
||||
|
||||
public static boolean canCrystalActivate(Ritual ritual, int crystalLevel)
|
||||
{
|
||||
return ritual.getCrystalLevel() <= crystalLevel
|
||||
&& BloodMagic.RITUAL_MANAGER.enabled(BloodMagic.RITUAL_MANAGER.getId(ritual), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the RitualRegistry to see if the configuration of the ritual stones in
|
||||
* the world is valid for the given Direction.
|
||||
*
|
||||
* @param world - The world
|
||||
* @param pos - Location of the MasterRitualStone
|
||||
* @return The ID of the valid ritual
|
||||
*/
|
||||
public static String getValidRitual(World world, BlockPos pos)
|
||||
{
|
||||
for (Ritual ritual : BloodMagic.RITUAL_MANAGER.getRituals())
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Direction direction = Direction.byHorizontalIndex(i);
|
||||
|
||||
if (checkValidRitual(world, pos, ritual, direction))
|
||||
return BloodMagic.RITUAL_MANAGER.getId(ritual);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public static Direction getDirectionOfRitual(World world, BlockPos pos, Ritual ritual)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Direction direction = Direction.byHorizontalIndex(i);
|
||||
if (checkValidRitual(world, pos, ritual, direction))
|
||||
return direction;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean checkValidRitual(World world, BlockPos pos, Ritual ritual, Direction direction)
|
||||
{
|
||||
if (ritual == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
List<RitualComponent> components = Lists.newArrayList();
|
||||
ritual.gatherComponents(components::add);
|
||||
|
||||
for (RitualComponent component : components)
|
||||
{
|
||||
BlockPos newPos = pos.add(component.getOffset(direction));
|
||||
if (!isRuneType(world, newPos, component.getRuneType()))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isRuneType(World world, BlockPos pos, EnumRuneType type)
|
||||
{
|
||||
if (world == null)
|
||||
return false;
|
||||
Block block = world.getBlockState(pos).getBlock();
|
||||
TileEntity tile = world.getTileEntity(pos);
|
||||
|
||||
if (block instanceof IRitualStone)
|
||||
return ((IRitualStone) block).isRuneType(world, pos, type);
|
||||
else if (tile instanceof IRitualStone.Tile)
|
||||
return ((IRitualStone.Tile) tile).isRuneType(type);
|
||||
else if (tile != null && tile.getCapability(RUNE_CAPABILITY, null).isPresent())
|
||||
return tile.getCapability(RUNE_CAPABILITY, null).resolve().get().isRuneType(type);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isRune(World world, BlockPos pos)
|
||||
{
|
||||
if (world == null)
|
||||
return false;
|
||||
Block block = world.getBlockState(pos).getBlock();
|
||||
TileEntity tile = world.getTileEntity(pos);
|
||||
|
||||
if (block instanceof IRitualStone)
|
||||
return true;
|
||||
else if (tile instanceof IRitualStone.Tile)
|
||||
return true;
|
||||
else
|
||||
return tile != null && tile.getCapability(RUNE_CAPABILITY, null).isPresent();
|
||||
|
||||
}
|
||||
|
||||
public static void setRuneType(World world, BlockPos pos, EnumRuneType type)
|
||||
{
|
||||
if (world == null)
|
||||
return;
|
||||
BlockState state = world.getBlockState(pos);
|
||||
TileEntity tile = world.getTileEntity(pos);
|
||||
|
||||
if (state.getBlock() instanceof IRitualStone)
|
||||
((IRitualStone) state.getBlock()).setRuneType(world, pos, type);
|
||||
else if (tile instanceof IRitualStone.Tile)
|
||||
((IRitualStone.Tile) tile).setRuneType(type);
|
||||
else
|
||||
{
|
||||
LazyOptional<Tile> cap = tile.getCapability(RUNE_CAPABILITY, null);
|
||||
if (cap.isPresent())
|
||||
{
|
||||
cap.resolve().get().setRuneType(type);
|
||||
world.notifyBlockUpdate(pos, state, state, 3);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean createRitual(World world, BlockPos pos, Direction direction, Ritual ritual, boolean safe)
|
||||
{
|
||||
|
||||
List<RitualComponent> components = Lists.newArrayList();
|
||||
ritual.gatherComponents(components::add);
|
||||
|
||||
if (abortConstruction(world, pos, direction, safe, components))
|
||||
return false;
|
||||
|
||||
BlockState mrs = BloodMagicBlocks.MASTER_RITUAL_STONE.get().getDefaultState();
|
||||
world.setBlockState(pos, mrs);
|
||||
|
||||
setRitualStones(direction, world, pos, components);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean abortConstruction(World world, BlockPos pos, Direction direction, boolean safe, List<RitualComponent> components)
|
||||
{
|
||||
// TODO: can be optimized to check only for the first and last component if
|
||||
// every ritual has those at the highest and lowest y-level respectivly.
|
||||
for (RitualComponent component : components)
|
||||
{
|
||||
BlockPos offset = component.getOffset(direction);
|
||||
BlockPos newPos = pos.add(offset);
|
||||
if (world.isOutsideBuildHeight(newPos) || (safe && !world.isAirBlock(newPos)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean repairRitualFromRuins(TileMasterRitualStone tile, boolean safe)
|
||||
{
|
||||
Ritual ritual = tile.getCurrentRitual();
|
||||
Direction direction;
|
||||
Pair<Ritual, Direction> pair;
|
||||
if (ritual == null)
|
||||
{
|
||||
pair = getRitualFromRuins(tile);
|
||||
ritual = pair.getKey();
|
||||
direction = pair.getValue();
|
||||
} else
|
||||
direction = tile.getDirection();
|
||||
|
||||
World world = tile.getWorld();
|
||||
BlockPos pos = tile.getPos();
|
||||
|
||||
List<RitualComponent> components = Lists.newArrayList();
|
||||
ritual.gatherComponents(components::add);
|
||||
|
||||
if (abortConstruction(world, pos, direction, safe, components))
|
||||
return false;
|
||||
|
||||
setRitualStones(direction, world, pos, components);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void setRitualStones(Direction direction, World world, BlockPos pos, List<RitualComponent> gatheredComponents)
|
||||
{
|
||||
for (RitualComponent component : gatheredComponents)
|
||||
{
|
||||
BlockPos offset = component.getOffset(direction);
|
||||
BlockPos newPos = pos.add(offset);
|
||||
((BlockRitualStone) BloodMagicBlocks.BLANK_RITUAL_STONE.get()).setRuneType(world, newPos, component.getRuneType());
|
||||
}
|
||||
}
|
||||
|
||||
public static Pair<Ritual, Direction> getRitualFromRuins(TileMasterRitualStone tile)
|
||||
{
|
||||
BlockPos pos = tile.getPos();
|
||||
World world = tile.getWorld();
|
||||
Ritual possibleRitual = tile.getCurrentRitual();
|
||||
Direction possibleDirection = tile.getDirection();
|
||||
int highestCount = 0;
|
||||
|
||||
if (possibleRitual == null || possibleDirection == null)
|
||||
for (Ritual ritual : BloodMagic.RITUAL_MANAGER.getRituals())
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Direction direction = Direction.byHorizontalIndex(i);
|
||||
List<RitualComponent> components = Lists.newArrayList();
|
||||
ritual.gatherComponents(components::add);
|
||||
int currentCount = 0;
|
||||
|
||||
for (RitualComponent component : components)
|
||||
{
|
||||
BlockPos newPos = pos.add(component.getOffset(direction));
|
||||
if (isRuneType(world, newPos, component.getRuneType()))
|
||||
currentCount += 1;
|
||||
}
|
||||
if (currentCount > highestCount)
|
||||
{
|
||||
highestCount = currentCount;
|
||||
possibleRitual = ritual;
|
||||
possibleDirection = direction;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return Pair.of(possibleRitual, possibleDirection);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue