From 1d03696ceb50138644f047c04aa9068a189cac34 Mon Sep 17 00:00:00 2001 From: cheaterpaul Date: Tue, 31 Oct 2023 18:31:36 +0100 Subject: [PATCH] add beacon for hunters add blood infused iron storage blocks as base --- .../blood_infused_enhanced_iron_block.json | 7 + .../blockstates/blood_infused_iron_block.json | 7 + .../vampirism/blockstates/vampire_beacon.json | 7 + .../blood_infused_enhanced_iron_block.json | 6 + .../block/blood_infused_iron_block.json | 6 + .../models/block/vampire_beacon.json | 7 + .../blood_infused_enhanced_iron_block.json | 3 + .../models/item/blood_infused_iron_block.json | 3 + .../models/item/cursed_hanging_roots.json | 5 +- .../vampirism/models/item/vampire_beacon.json | 3 + .../forge/tags/blocks/storage_blocks.json | 6 + .../blood_infused_enhanced_iron_block.json | 35 ++ .../blood_infused_enhanced_iron_ingot.json | 35 ++ .../blood_infused_iron_block.json | 35 ++ .../blood_infused_iron_ingot.json | 35 ++ .../blood_infused_enhanced_iron_block.json | 18 + .../blood_infused_enhanced_iron_ingot.json | 13 + .../recipes/blood_infused_iron_block.json | 18 + .../recipes/blood_infused_iron_ingot.json | 13 + ...enhanced_iron_ingot_from_pure_blood_4.json | 22 ++ ..._infused_iron_ingot_from_pure_blood_0.json | 22 ++ ..._infused_iron_ingot_from_pure_blood_1.json | 22 ++ ..._infused_iron_ingot_from_pure_blood_2.json | 22 ++ ..._infused_iron_ingot_from_pure_blood_3.json | 22 ++ .../recipes/misc/vampire_beacon.json | 59 ++++ .../blood_infused_enhanced_iron_block.json | 21 ++ .../blocks/blood_infused_iron_block.json | 21 ++ .../loot_tables/blocks/vampire_beacon.json | 27 ++ ...enhanced_iron_ingot_from_pure_blood_4.json | 18 + ..._infused_iron_ingot_from_pure_blood_0.json | 18 + ..._infused_iron_ingot_from_pure_blood_1.json | 18 + ..._infused_iron_ingot_from_pure_blood_2.json | 18 + ..._infused_iron_ingot_from_pure_blood_3.json | 18 + .../vampirism/recipes/vampire_beacon.json | 24 ++ .../blocks/vampire_beacon_base_blocks.json | 6 + .../vampire_beacon_base_enhanced_blocks.json | 5 + .../items/vampire_beacon_payment_item.json | 7 + .../blockentity/VampireBeaconBlockEntity.java | 329 ++++++++++++++++++ .../vampirism/blocks/VampireBeaconBlock.java | 77 ++++ .../client/core/ModBlocksRender.java | 1 + .../vampirism/client/core/ModScreens.java | 1 + .../gui/screens/VampireBeaconScreen.java | 278 +++++++++++++++ .../blockentity/VampireBeaconBESR.java | 55 +++ .../teamlapen/vampirism/core/ModBlocks.java | 4 + .../vampirism/core/ModContainer.java | 1 + .../teamlapen/vampirism/core/ModRecipes.java | 6 +- .../de/teamlapen/vampirism/core/ModTags.java | 4 +- .../de/teamlapen/vampirism/core/ModTiles.java | 1 + .../vampirism/data/BlockStateGenerator.java | 3 + .../vampirism/data/ItemModelGenerator.java | 4 + .../vampirism/data/LootTablesGenerator.java | 3 + .../vampirism/data/RecipesGenerator.java | 9 + .../vampirism/data/TagGenerator.java | 5 + .../entity/player/vampire/VampirePlayer.java | 17 +- .../inventory/VampireBeaconMenu.java | 124 +++++++ .../inventory/VampirismContainerMenu.java | 74 ++++ .../vampirism/misc/VampirismCreativeTab.java | 4 + .../mixin/BeaconBeamSectionyMixin.java | 12 + .../mixin/BeaconBlockEntityMixin.java | 19 + .../network/ModPacketDispatcher.java | 1 + .../ServerboundSetVampireBeaconPacket.java | 44 +++ .../assets/vampirism/lang/en_us.json | 4 + .../blood_infused_enhanced_iron_block.png | Bin 0 -> 1311 bytes .../block/blood_infused_iron_block.png | Bin 0 -> 385 bytes .../textures/block/vampire_beacon.png | Bin 0 -> 4411 bytes .../textures/gui/container/vampire_beacon.png | Bin 0 -> 6054 bytes src/main/resources/vampirism.mixins.json | 2 + 67 files changed, 1708 insertions(+), 6 deletions(-) create mode 100644 src/generated/resources/assets/vampirism/blockstates/blood_infused_enhanced_iron_block.json create mode 100644 src/generated/resources/assets/vampirism/blockstates/blood_infused_iron_block.json create mode 100644 src/generated/resources/assets/vampirism/blockstates/vampire_beacon.json create mode 100644 src/generated/resources/assets/vampirism/models/block/blood_infused_enhanced_iron_block.json create mode 100644 src/generated/resources/assets/vampirism/models/block/blood_infused_iron_block.json create mode 100644 src/generated/resources/assets/vampirism/models/block/vampire_beacon.json create mode 100644 src/generated/resources/assets/vampirism/models/item/blood_infused_enhanced_iron_block.json create mode 100644 src/generated/resources/assets/vampirism/models/item/blood_infused_iron_block.json create mode 100644 src/generated/resources/assets/vampirism/models/item/vampire_beacon.json create mode 100644 src/generated/resources/data/forge/tags/blocks/storage_blocks.json create mode 100644 src/generated/resources/data/minecraft/advancements/recipes/building_blocks/blood_infused_enhanced_iron_block.json create mode 100644 src/generated/resources/data/minecraft/advancements/recipes/building_blocks/blood_infused_enhanced_iron_ingot.json create mode 100644 src/generated/resources/data/minecraft/advancements/recipes/building_blocks/blood_infused_iron_block.json create mode 100644 src/generated/resources/data/minecraft/advancements/recipes/building_blocks/blood_infused_iron_ingot.json create mode 100644 src/generated/resources/data/minecraft/recipes/blood_infused_enhanced_iron_block.json create mode 100644 src/generated/resources/data/minecraft/recipes/blood_infused_enhanced_iron_ingot.json create mode 100644 src/generated/resources/data/minecraft/recipes/blood_infused_iron_block.json create mode 100644 src/generated/resources/data/minecraft/recipes/blood_infused_iron_ingot.json create mode 100644 src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_enhanced_iron_ingot_from_pure_blood_4.json create mode 100644 src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_0.json create mode 100644 src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_1.json create mode 100644 src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_2.json create mode 100644 src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_3.json create mode 100644 src/generated/resources/data/vampirism/advancements/recipes/misc/vampire_beacon.json create mode 100644 src/generated/resources/data/vampirism/loot_tables/blocks/blood_infused_enhanced_iron_block.json create mode 100644 src/generated/resources/data/vampirism/loot_tables/blocks/blood_infused_iron_block.json create mode 100644 src/generated/resources/data/vampirism/loot_tables/blocks/vampire_beacon.json create mode 100644 src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_enhanced_iron_ingot_from_pure_blood_4.json create mode 100644 src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_0.json create mode 100644 src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_1.json create mode 100644 src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_2.json create mode 100644 src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_3.json create mode 100644 src/generated/resources/data/vampirism/recipes/vampire_beacon.json create mode 100644 src/generated/resources/data/vampirism/tags/blocks/vampire_beacon_base_blocks.json create mode 100644 src/generated/resources/data/vampirism/tags/blocks/vampire_beacon_base_enhanced_blocks.json create mode 100644 src/generated/resources/data/vampirism/tags/items/vampire_beacon_payment_item.json create mode 100644 src/main/java/de/teamlapen/vampirism/blockentity/VampireBeaconBlockEntity.java create mode 100644 src/main/java/de/teamlapen/vampirism/blocks/VampireBeaconBlock.java create mode 100644 src/main/java/de/teamlapen/vampirism/client/gui/screens/VampireBeaconScreen.java create mode 100644 src/main/java/de/teamlapen/vampirism/client/renderer/blockentity/VampireBeaconBESR.java create mode 100644 src/main/java/de/teamlapen/vampirism/inventory/VampireBeaconMenu.java create mode 100644 src/main/java/de/teamlapen/vampirism/inventory/VampirismContainerMenu.java create mode 100644 src/main/java/de/teamlapen/vampirism/mixin/BeaconBeamSectionyMixin.java create mode 100644 src/main/java/de/teamlapen/vampirism/mixin/BeaconBlockEntityMixin.java create mode 100644 src/main/java/de/teamlapen/vampirism/network/ServerboundSetVampireBeaconPacket.java create mode 100755 src/main/resources/assets/vampirism/textures/block/blood_infused_enhanced_iron_block.png create mode 100755 src/main/resources/assets/vampirism/textures/block/blood_infused_iron_block.png create mode 100644 src/main/resources/assets/vampirism/textures/block/vampire_beacon.png create mode 100644 src/main/resources/assets/vampirism/textures/gui/container/vampire_beacon.png diff --git a/src/generated/resources/assets/vampirism/blockstates/blood_infused_enhanced_iron_block.json b/src/generated/resources/assets/vampirism/blockstates/blood_infused_enhanced_iron_block.json new file mode 100644 index 0000000000..6ce37cf4a5 --- /dev/null +++ b/src/generated/resources/assets/vampirism/blockstates/blood_infused_enhanced_iron_block.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "vampirism:block/blood_infused_enhanced_iron_block" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/vampirism/blockstates/blood_infused_iron_block.json b/src/generated/resources/assets/vampirism/blockstates/blood_infused_iron_block.json new file mode 100644 index 0000000000..c1b4bc834e --- /dev/null +++ b/src/generated/resources/assets/vampirism/blockstates/blood_infused_iron_block.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "vampirism:block/blood_infused_iron_block" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/vampirism/blockstates/vampire_beacon.json b/src/generated/resources/assets/vampirism/blockstates/vampire_beacon.json new file mode 100644 index 0000000000..1e9db0cd38 --- /dev/null +++ b/src/generated/resources/assets/vampirism/blockstates/vampire_beacon.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "vampirism:block/vampire_beacon" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/vampirism/models/block/blood_infused_enhanced_iron_block.json b/src/generated/resources/assets/vampirism/models/block/blood_infused_enhanced_iron_block.json new file mode 100644 index 0000000000..2abbf67d25 --- /dev/null +++ b/src/generated/resources/assets/vampirism/models/block/blood_infused_enhanced_iron_block.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "vampirism:block/blood_infused_enhanced_iron_block" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/vampirism/models/block/blood_infused_iron_block.json b/src/generated/resources/assets/vampirism/models/block/blood_infused_iron_block.json new file mode 100644 index 0000000000..7c14805bbd --- /dev/null +++ b/src/generated/resources/assets/vampirism/models/block/blood_infused_iron_block.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "vampirism:block/blood_infused_iron_block" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/vampirism/models/block/vampire_beacon.json b/src/generated/resources/assets/vampirism/models/block/vampire_beacon.json new file mode 100644 index 0000000000..fbc4149bf6 --- /dev/null +++ b/src/generated/resources/assets/vampirism/models/block/vampire_beacon.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/beacon", + "render_type": "minecraft:cutout", + "textures": { + "beacon": "vampirism:block/vampire_beacon" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/vampirism/models/item/blood_infused_enhanced_iron_block.json b/src/generated/resources/assets/vampirism/models/item/blood_infused_enhanced_iron_block.json new file mode 100644 index 0000000000..d131cfd06a --- /dev/null +++ b/src/generated/resources/assets/vampirism/models/item/blood_infused_enhanced_iron_block.json @@ -0,0 +1,3 @@ +{ + "parent": "vampirism:block/blood_infused_enhanced_iron_block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/vampirism/models/item/blood_infused_iron_block.json b/src/generated/resources/assets/vampirism/models/item/blood_infused_iron_block.json new file mode 100644 index 0000000000..f551f2ac81 --- /dev/null +++ b/src/generated/resources/assets/vampirism/models/item/blood_infused_iron_block.json @@ -0,0 +1,3 @@ +{ + "parent": "vampirism:block/blood_infused_iron_block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/vampirism/models/item/cursed_hanging_roots.json b/src/generated/resources/assets/vampirism/models/item/cursed_hanging_roots.json index 0a9d488de6..477ef1cbfe 100644 --- a/src/generated/resources/assets/vampirism/models/item/cursed_hanging_roots.json +++ b/src/generated/resources/assets/vampirism/models/item/cursed_hanging_roots.json @@ -1,3 +1,6 @@ { - "parent": "vampirism:block/cursed_hanging_roots" + "parent": "minecraft:item/generated", + "textures": { + "layer0": "vampirism:block/cursed_hanging_roots" + } } \ No newline at end of file diff --git a/src/generated/resources/assets/vampirism/models/item/vampire_beacon.json b/src/generated/resources/assets/vampirism/models/item/vampire_beacon.json new file mode 100644 index 0000000000..dc489f8dfb --- /dev/null +++ b/src/generated/resources/assets/vampirism/models/item/vampire_beacon.json @@ -0,0 +1,3 @@ +{ + "parent": "vampirism:block/vampire_beacon" +} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/blocks/storage_blocks.json b/src/generated/resources/data/forge/tags/blocks/storage_blocks.json new file mode 100644 index 0000000000..f6926ca0b2 --- /dev/null +++ b/src/generated/resources/data/forge/tags/blocks/storage_blocks.json @@ -0,0 +1,6 @@ +{ + "values": [ + "vampirism:blood_infused_iron_block", + "vampirism:blood_infused_enhanced_iron_block" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/advancements/recipes/building_blocks/blood_infused_enhanced_iron_block.json b/src/generated/resources/data/minecraft/advancements/recipes/building_blocks/blood_infused_enhanced_iron_block.json new file mode 100644 index 0000000000..8c98dc0977 --- /dev/null +++ b/src/generated/resources/data/minecraft/advancements/recipes/building_blocks/blood_infused_enhanced_iron_block.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_blood_infused_enhanced_iron_ingot": { + "conditions": { + "items": [ + { + "items": [ + "vampirism:blood_infused_enhanced_iron_ingot" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "minecraft:blood_infused_enhanced_iron_block" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_blood_infused_enhanced_iron_ingot", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "minecraft:blood_infused_enhanced_iron_block" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/advancements/recipes/building_blocks/blood_infused_enhanced_iron_ingot.json b/src/generated/resources/data/minecraft/advancements/recipes/building_blocks/blood_infused_enhanced_iron_ingot.json new file mode 100644 index 0000000000..205721be64 --- /dev/null +++ b/src/generated/resources/data/minecraft/advancements/recipes/building_blocks/blood_infused_enhanced_iron_ingot.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_blood_infused_enhanced_iron_block": { + "conditions": { + "items": [ + { + "items": [ + "vampirism:blood_infused_enhanced_iron_block" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "minecraft:blood_infused_enhanced_iron_ingot" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_blood_infused_enhanced_iron_block", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "minecraft:blood_infused_enhanced_iron_ingot" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/advancements/recipes/building_blocks/blood_infused_iron_block.json b/src/generated/resources/data/minecraft/advancements/recipes/building_blocks/blood_infused_iron_block.json new file mode 100644 index 0000000000..19e00ea153 --- /dev/null +++ b/src/generated/resources/data/minecraft/advancements/recipes/building_blocks/blood_infused_iron_block.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_blood_infused_iron_ingot": { + "conditions": { + "items": [ + { + "items": [ + "vampirism:blood_infused_iron_ingot" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "minecraft:blood_infused_iron_block" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_blood_infused_iron_ingot", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "minecraft:blood_infused_iron_block" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/advancements/recipes/building_blocks/blood_infused_iron_ingot.json b/src/generated/resources/data/minecraft/advancements/recipes/building_blocks/blood_infused_iron_ingot.json new file mode 100644 index 0000000000..d35c36a017 --- /dev/null +++ b/src/generated/resources/data/minecraft/advancements/recipes/building_blocks/blood_infused_iron_ingot.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_blood_infused_iron_block": { + "conditions": { + "items": [ + { + "items": [ + "vampirism:blood_infused_iron_block" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "minecraft:blood_infused_iron_ingot" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_blood_infused_iron_block", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "minecraft:blood_infused_iron_ingot" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/recipes/blood_infused_enhanced_iron_block.json b/src/generated/resources/data/minecraft/recipes/blood_infused_enhanced_iron_block.json new file mode 100644 index 0000000000..b63954b271 --- /dev/null +++ b/src/generated/resources/data/minecraft/recipes/blood_infused_enhanced_iron_block.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "#": { + "item": "vampirism:blood_infused_enhanced_iron_ingot" + } + }, + "pattern": [ + "###", + "###", + "###" + ], + "result": { + "item": "vampirism:blood_infused_enhanced_iron_block" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/recipes/blood_infused_enhanced_iron_ingot.json b/src/generated/resources/data/minecraft/recipes/blood_infused_enhanced_iron_ingot.json new file mode 100644 index 0000000000..b5e43606f7 --- /dev/null +++ b/src/generated/resources/data/minecraft/recipes/blood_infused_enhanced_iron_ingot.json @@ -0,0 +1,13 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "item": "vampirism:blood_infused_enhanced_iron_block" + } + ], + "result": { + "count": 9, + "item": "vampirism:blood_infused_enhanced_iron_ingot" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/recipes/blood_infused_iron_block.json b/src/generated/resources/data/minecraft/recipes/blood_infused_iron_block.json new file mode 100644 index 0000000000..fa8773de78 --- /dev/null +++ b/src/generated/resources/data/minecraft/recipes/blood_infused_iron_block.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "#": { + "item": "vampirism:blood_infused_iron_ingot" + } + }, + "pattern": [ + "###", + "###", + "###" + ], + "result": { + "item": "vampirism:blood_infused_iron_block" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/recipes/blood_infused_iron_ingot.json b/src/generated/resources/data/minecraft/recipes/blood_infused_iron_ingot.json new file mode 100644 index 0000000000..c54398ec4b --- /dev/null +++ b/src/generated/resources/data/minecraft/recipes/blood_infused_iron_ingot.json @@ -0,0 +1,13 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "building", + "ingredients": [ + { + "item": "vampirism:blood_infused_iron_block" + } + ], + "result": { + "count": 9, + "item": "vampirism:blood_infused_iron_ingot" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_enhanced_iron_ingot_from_pure_blood_4.json b/src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_enhanced_iron_ingot_from_pure_blood_4.json new file mode 100644 index 0000000000..5596c0186f --- /dev/null +++ b/src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_enhanced_iron_ingot_from_pure_blood_4.json @@ -0,0 +1,22 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "vampirism:alchemical_cauldron/blood_infused_enhanced_iron_ingot_from_pure_blood_4" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "vampirism:alchemical_cauldron/blood_infused_enhanced_iron_ingot_from_pure_blood_4" + ] + }, + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_0.json b/src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_0.json new file mode 100644 index 0000000000..12fa6507e3 --- /dev/null +++ b/src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_0.json @@ -0,0 +1,22 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "vampirism:alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_0" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "vampirism:alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_0" + ] + }, + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_1.json b/src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_1.json new file mode 100644 index 0000000000..3a79604afd --- /dev/null +++ b/src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_1.json @@ -0,0 +1,22 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "vampirism:alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_1" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "vampirism:alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_1" + ] + }, + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_2.json b/src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_2.json new file mode 100644 index 0000000000..a9e43018b6 --- /dev/null +++ b/src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_2.json @@ -0,0 +1,22 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "vampirism:alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_2" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "vampirism:alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_2" + ] + }, + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_3.json b/src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_3.json new file mode 100644 index 0000000000..8b6743a161 --- /dev/null +++ b/src/generated/resources/data/vampirism/advancements/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_3.json @@ -0,0 +1,22 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "vampirism:alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_3" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "vampirism:alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_3" + ] + }, + "sends_telemetry_event": true +} \ No newline at end of file diff --git a/src/generated/resources/data/vampirism/advancements/recipes/misc/vampire_beacon.json b/src/generated/resources/data/vampirism/advancements/recipes/misc/vampire_beacon.json new file mode 100644 index 0000000000..ba55e2e3f8 --- /dev/null +++ b/src/generated/resources/data/vampirism/advancements/recipes/misc/vampire_beacon.json @@ -0,0 +1,59 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_glass": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:glass" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_mother_core": { + "conditions": { + "items": [ + { + "items": [ + "vampirism:mother_core" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_obsidian": { + "conditions": { + "items": [ + { + "tag": "forge:obsidian" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "vampirism:vampire_beacon" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_mother_core", + "has_obsidian", + "has_glass", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "vampirism:vampire_beacon" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/src/generated/resources/data/vampirism/loot_tables/blocks/blood_infused_enhanced_iron_block.json b/src/generated/resources/data/vampirism/loot_tables/blocks/blood_infused_enhanced_iron_block.json new file mode 100644 index 0000000000..b07d2df6b4 --- /dev/null +++ b/src/generated/resources/data/vampirism/loot_tables/blocks/blood_infused_enhanced_iron_block.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "vampirism:blood_infused_enhanced_iron_block" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "vampirism:blocks/blood_infused_enhanced_iron_block" +} \ No newline at end of file diff --git a/src/generated/resources/data/vampirism/loot_tables/blocks/blood_infused_iron_block.json b/src/generated/resources/data/vampirism/loot_tables/blocks/blood_infused_iron_block.json new file mode 100644 index 0000000000..dacd5f4d03 --- /dev/null +++ b/src/generated/resources/data/vampirism/loot_tables/blocks/blood_infused_iron_block.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "vampirism:blood_infused_iron_block" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "vampirism:blocks/blood_infused_iron_block" +} \ No newline at end of file diff --git a/src/generated/resources/data/vampirism/loot_tables/blocks/vampire_beacon.json b/src/generated/resources/data/vampirism/loot_tables/blocks/vampire_beacon.json new file mode 100644 index 0000000000..be84d2d9df --- /dev/null +++ b/src/generated/resources/data/vampirism/loot_tables/blocks/vampire_beacon.json @@ -0,0 +1,27 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + } + ], + "name": "vampirism:vampire_beacon" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "vampirism:blocks/vampire_beacon" +} \ No newline at end of file diff --git a/src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_enhanced_iron_ingot_from_pure_blood_4.json b/src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_enhanced_iron_ingot_from_pure_blood_4.json new file mode 100644 index 0000000000..f3067b45eb --- /dev/null +++ b/src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_enhanced_iron_ingot_from_pure_blood_4.json @@ -0,0 +1,18 @@ +{ + "type": "vampirism:alchemical_cauldron", + "cookTime": 300, + "experience": 0.3, + "fluidItem": { + "item": "vampirism:pure_blood_4" + }, + "ingredient": { + "item": "minecraft:iron_block" + }, + "reqLevel": 1, + "result": { + "item": "vampirism:blood_infused_enhanced_iron_block" + }, + "skill": [ + "vampirism:basic_alchemy" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_0.json b/src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_0.json new file mode 100644 index 0000000000..b94da5ec84 --- /dev/null +++ b/src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_0.json @@ -0,0 +1,18 @@ +{ + "type": "vampirism:alchemical_cauldron", + "cookTime": 200, + "experience": 0.1, + "fluidItem": { + "item": "vampirism:pure_blood_0" + }, + "ingredient": { + "item": "minecraft:iron_block" + }, + "reqLevel": 1, + "result": { + "item": "vampirism:blood_infused_iron_block" + }, + "skill": [ + "vampirism:basic_alchemy" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_1.json b/src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_1.json new file mode 100644 index 0000000000..a16c04e0ae --- /dev/null +++ b/src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_1.json @@ -0,0 +1,18 @@ +{ + "type": "vampirism:alchemical_cauldron", + "cookTime": 180, + "experience": 0.15, + "fluidItem": { + "item": "vampirism:pure_blood_1" + }, + "ingredient": { + "item": "minecraft:iron_block" + }, + "reqLevel": 1, + "result": { + "item": "vampirism:blood_infused_iron_block" + }, + "skill": [ + "vampirism:basic_alchemy" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_2.json b/src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_2.json new file mode 100644 index 0000000000..bc361b7951 --- /dev/null +++ b/src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_2.json @@ -0,0 +1,18 @@ +{ + "type": "vampirism:alchemical_cauldron", + "cookTime": 160, + "experience": 0.2, + "fluidItem": { + "item": "vampirism:pure_blood_2" + }, + "ingredient": { + "item": "minecraft:iron_block" + }, + "reqLevel": 1, + "result": { + "item": "vampirism:blood_infused_iron_block" + }, + "skill": [ + "vampirism:basic_alchemy" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_3.json b/src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_3.json new file mode 100644 index 0000000000..c26aac1c2b --- /dev/null +++ b/src/generated/resources/data/vampirism/recipes/alchemical_cauldron/blood_infused_iron_ingot_from_pure_blood_3.json @@ -0,0 +1,18 @@ +{ + "type": "vampirism:alchemical_cauldron", + "cookTime": 140, + "experience": 0.25, + "fluidItem": { + "item": "vampirism:pure_blood_3" + }, + "ingredient": { + "item": "minecraft:iron_block" + }, + "reqLevel": 1, + "result": { + "item": "vampirism:blood_infused_iron_block" + }, + "skill": [ + "vampirism:basic_alchemy" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/vampirism/recipes/vampire_beacon.json b/src/generated/resources/data/vampirism/recipes/vampire_beacon.json new file mode 100644 index 0000000000..87639221a8 --- /dev/null +++ b/src/generated/resources/data/vampirism/recipes/vampire_beacon.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "C": { + "item": "vampirism:mother_core" + }, + "G": { + "item": "minecraft:glass" + }, + "O": { + "tag": "forge:obsidian" + } + }, + "pattern": [ + "GGG", + "GCG", + "OOO" + ], + "result": { + "item": "vampirism:vampire_beacon" + }, + "show_notification": true +} \ No newline at end of file diff --git a/src/generated/resources/data/vampirism/tags/blocks/vampire_beacon_base_blocks.json b/src/generated/resources/data/vampirism/tags/blocks/vampire_beacon_base_blocks.json new file mode 100644 index 0000000000..f6926ca0b2 --- /dev/null +++ b/src/generated/resources/data/vampirism/tags/blocks/vampire_beacon_base_blocks.json @@ -0,0 +1,6 @@ +{ + "values": [ + "vampirism:blood_infused_iron_block", + "vampirism:blood_infused_enhanced_iron_block" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/vampirism/tags/blocks/vampire_beacon_base_enhanced_blocks.json b/src/generated/resources/data/vampirism/tags/blocks/vampire_beacon_base_enhanced_blocks.json new file mode 100644 index 0000000000..10ff4c104b --- /dev/null +++ b/src/generated/resources/data/vampirism/tags/blocks/vampire_beacon_base_enhanced_blocks.json @@ -0,0 +1,5 @@ +{ + "values": [ + "vampirism:blood_infused_enhanced_iron_block" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/vampirism/tags/items/vampire_beacon_payment_item.json b/src/generated/resources/data/vampirism/tags/items/vampire_beacon_payment_item.json new file mode 100644 index 0000000000..b9ccaf11b9 --- /dev/null +++ b/src/generated/resources/data/vampirism/tags/items/vampire_beacon_payment_item.json @@ -0,0 +1,7 @@ +{ + "values": [ + "#vampirism:pure_blood", + "#vampirism:heart", + "vampirism:soul_orb_vampire" + ] +} \ No newline at end of file diff --git a/src/main/java/de/teamlapen/vampirism/blockentity/VampireBeaconBlockEntity.java b/src/main/java/de/teamlapen/vampirism/blockentity/VampireBeaconBlockEntity.java new file mode 100644 index 0000000000..c2461f8c9f --- /dev/null +++ b/src/main/java/de/teamlapen/vampirism/blockentity/VampireBeaconBlockEntity.java @@ -0,0 +1,329 @@ +package de.teamlapen.vampirism.blockentity; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import de.teamlapen.vampirism.core.ModTags; +import de.teamlapen.vampirism.core.ModTiles; +import de.teamlapen.vampirism.inventory.VampireBeaconMenu; +import de.teamlapen.vampirism.mixin.BeaconBeamSectionyMixin; +import de.teamlapen.vampirism.util.Helper; +import net.minecraft.advancements.CriteriaTriggers; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.LockCode; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.Nameable; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerData; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; +import net.minecraft.world.level.block.entity.BeaconBlockEntity; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.phys.AABB; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import static net.minecraft.world.level.block.entity.BeaconBlockEntity.playSound; + +public class VampireBeaconBlockEntity extends BlockEntity implements MenuProvider, Nameable { + private static final int MAX_LEVELS = 3; + public static final MobEffect[][] BEACON_EFFECTS = new MobEffect[][] {{MobEffects.MOVEMENT_SPEED, MobEffects.SATURATION}, {MobEffects.NIGHT_VISION, MobEffects.WATER_BREATHING}, {MobEffects.REGENERATION}}; + public static final int[][] BEACON_EFFECTS_AMPLIFIER = new int[][] {{0, 0}, {0, 0}, {0, 1}}; + public static final Set NO_AMPLIFIER_EFFECTS = Set.of(MobEffects.NIGHT_VISION, MobEffects.WATER_BREATHING); + private static final Set VALID_EFFECTS = Arrays.stream(BEACON_EFFECTS).flatMap(Arrays::stream).collect(Collectors.toSet()); + public static final int DATA_LEVELS = 0; + public static final int DATA_PRIMARY = 1; + public static final int DATA_AMPLIFIER = 2; + public static final int DATA_UPGRADED = 3; + public static final int NUM_DATA_VALUES = 4; + private static final int BLOCKS_CHECK_PER_TICK = 10; + private static final Component DEFAULT_NAME = Component.translatable("container.beacon"); + private List beamSections = Lists.newArrayList(); + private List checkingBeamSections = Lists.newArrayList(); + private int levels; + private int lastCheckY; + @Nullable + private MobEffect primaryPower; + private int effectAmplifier; + private boolean isUpgraded; + @Nullable + private Component name; + private LockCode lockKey = LockCode.NO_LOCK; + private final ContainerData dataAccess = new ContainerData() { + public int get(int slot) { + return switch (slot) { + case DATA_LEVELS -> VampireBeaconBlockEntity.this.levels; + case DATA_PRIMARY -> MobEffect.getIdFromNullable(VampireBeaconBlockEntity.this.primaryPower); + case DATA_AMPLIFIER -> VampireBeaconBlockEntity.this.effectAmplifier; + case DATA_UPGRADED -> VampireBeaconBlockEntity.this.isUpgraded ? 1 : 0; + default -> 0; + }; + } + + public void set(int slot, int value) { + switch (slot) { + case DATA_LEVELS: + VampireBeaconBlockEntity.this.levels = value; + break; + case DATA_PRIMARY: + if (!VampireBeaconBlockEntity.this.level.isClientSide && !VampireBeaconBlockEntity.this.beamSections.isEmpty()) { + playSound(VampireBeaconBlockEntity.this.level, VampireBeaconBlockEntity.this.worldPosition, SoundEvents.BEACON_POWER_SELECT); + } + VampireBeaconBlockEntity.this.primaryPower = VampireBeaconBlockEntity.getValidEffectById(value); + break; + case DATA_AMPLIFIER: + VampireBeaconBlockEntity.this.effectAmplifier = value; + break; + case DATA_UPGRADED: + VampireBeaconBlockEntity.this.isUpgraded = value != 0; + break; + } + + } + + public int getCount() { + return NUM_DATA_VALUES; + } + }; + + public VampireBeaconBlockEntity(BlockPos pPos, BlockState pBlockState) { + super(ModTiles.VAMPIRE_BEACON.get(), pPos, pBlockState); + } + + public static void tick(Level pLevel, BlockPos pPos, BlockState pState, VampireBeaconBlockEntity pBlockEntity) { + int i = pPos.getX(); + int j = pPos.getY(); + int k = pPos.getZ(); + BlockPos blockpos; + if (pBlockEntity.lastCheckY < j) { + blockpos = pPos; + pBlockEntity.checkingBeamSections = Lists.newArrayList(); + pBlockEntity.lastCheckY = pPos.getY() - 1; + } else { + blockpos = new BlockPos(i, pBlockEntity.lastCheckY + 1, k); + } + + BeaconBlockEntity.BeaconBeamSection beaconblockentity$beaconbeamsection = pBlockEntity.checkingBeamSections.isEmpty() ? null : pBlockEntity.checkingBeamSections.get(pBlockEntity.checkingBeamSections.size() - 1); + int l = pLevel.getHeight(Heightmap.Types.WORLD_SURFACE, i, k); + + for(int i1 = 0; i1 < BLOCKS_CHECK_PER_TICK && blockpos.getY() <= l; ++i1) { + BlockState blockstate = pLevel.getBlockState(blockpos); + Block block = blockstate.getBlock(); + float[] afloat = blockstate.getBeaconColorMultiplier(pLevel, blockpos, pPos); + if (afloat != null) { + if (pBlockEntity.checkingBeamSections.size() <= 1) { + beaconblockentity$beaconbeamsection = new BeaconBlockEntity.BeaconBeamSection(afloat); + pBlockEntity.checkingBeamSections.add(beaconblockentity$beaconbeamsection); + } else if (beaconblockentity$beaconbeamsection != null) { + if (Arrays.equals(afloat, beaconblockentity$beaconbeamsection.getColor())) { + ((BeaconBeamSectionyMixin)beaconblockentity$beaconbeamsection).invokeIncreaseHeight(); + } else { + beaconblockentity$beaconbeamsection = new BeaconBlockEntity.BeaconBeamSection(new float[]{(beaconblockentity$beaconbeamsection.getColor()[0] + afloat[0]) / 2.0F, (beaconblockentity$beaconbeamsection.getColor()[1] + afloat[1]) / 2.0F, (beaconblockentity$beaconbeamsection.getColor()[2] + afloat[2]) / 2.0F}); + pBlockEntity.checkingBeamSections.add(beaconblockentity$beaconbeamsection); + } + } + } else { + if (beaconblockentity$beaconbeamsection == null || blockstate.getLightBlock(pLevel, blockpos) >= 15 && !blockstate.is(Blocks.BEDROCK)) { + pBlockEntity.checkingBeamSections.clear(); + pBlockEntity.lastCheckY = l; + break; + } + + ((BeaconBeamSectionyMixin)beaconblockentity$beaconbeamsection).invokeIncreaseHeight(); + } + + blockpos = blockpos.above(); + ++pBlockEntity.lastCheckY; + } + + int j1 = pBlockEntity.levels; + if (pLevel.getGameTime() % 80L == 0L) { + if (!pBlockEntity.beamSections.isEmpty()) { + Pair integerBooleanPair = updateBase(pLevel, i, j, k); + pBlockEntity.levels = integerBooleanPair.getLeft(); + pBlockEntity.isUpgraded = integerBooleanPair.getRight(); + } + + if (pBlockEntity.levels > 0 && !pBlockEntity.beamSections.isEmpty()) { + pBlockEntity.applyEffects(pLevel, pPos, pBlockEntity.levels, pBlockEntity.primaryPower, pBlockEntity.isUpgraded ? pBlockEntity.effectAmplifier + 1 : pBlockEntity.effectAmplifier); + playSound(pLevel, pPos, SoundEvents.BEACON_AMBIENT); + } + } + + if (pBlockEntity.lastCheckY >= l) { + pBlockEntity.lastCheckY = pLevel.getMinBuildHeight() - 1; + boolean flag = j1 > 0; + pBlockEntity.beamSections = pBlockEntity.checkingBeamSections; + if (!pLevel.isClientSide) { + boolean flag1 = pBlockEntity.levels > 0; + if (!flag && flag1) { + playSound(pLevel, pPos, SoundEvents.BEACON_ACTIVATE); + + for(ServerPlayer serverplayer : pLevel.getEntitiesOfClass(ServerPlayer.class, (new AABB((double)i, (double)j, (double)k, (double)i, (double)(j - MAX_LEVELS), (double)k)).inflate(10.0D, 5.0D, 10.0D))) { + CriteriaTriggers.CONSTRUCT_BEACON.trigger(serverplayer, pBlockEntity.levels); + } + } else if (flag && !flag1) { + playSound(pLevel, pPos, SoundEvents.BEACON_DEACTIVATE); + } + } + } + + } + + protected void applyEffects(Level level, BlockPos pos, int levels, @Nullable MobEffect power, int effectAmplifier) { + if (!level.isClientSide && power != null) { + if (NO_AMPLIFIER_EFFECTS.contains(power)) { + effectAmplifier = 0; + } + AABB aabb = (new AABB(pos)).inflate(levels * 10 + 10).expandTowards(0.0D, (double) level.getHeight(), 0.0D); + int effectDuration = (9 + levels * 2) * 20; + List list = level.getEntitiesOfClass(Player.class, aabb, Helper::isHunter); + int finalEffectAmplifier = effectAmplifier; + list.forEach((player) -> player.addEffect(new MobEffectInstance(power, effectDuration, finalEffectAmplifier, true, true))); + } + } + + @Override + public AABB getRenderBoundingBox() { + return INFINITE_EXTENT_AABB; + } + + private static Pair updateBase(Level pLevel, int pX, int pY, int pZ) { + int i = 0; + boolean upgradeFlag = true; + + for(int j = 1; j <= MAX_LEVELS; i = j++) { + int k = pY - j; + if (k < pLevel.getMinBuildHeight()) { + break; + } + + boolean flag = true; + boolean upgradeFlagLevel = upgradeFlag; + + for(int l = pX - j; l <= pX + j && flag; ++l) { + for(int i1 = pZ - j; i1 <= pZ + j; ++i1) { + BlockState blockState = pLevel.getBlockState(new BlockPos(l, k, i1)); + if (!blockState.is(ModTags.Blocks.VAMPIRE_BEACON_BASE_BLOCKS)) { + flag = false; + break; + } else if (upgradeFlagLevel) { + upgradeFlagLevel = blockState.is(ModTags.Blocks.VAMPIRE_BEACON_BASE_ENHANCED_BLOCKS); + } + } + } + + if (!flag) { + break; + } + upgradeFlag = upgradeFlag && upgradeFlagLevel; + } + + return Pair.of(i, upgradeFlag); + } + + @Override + public void setRemoved() { + playSound(this.level, this.worldPosition, SoundEvents.BEACON_DEACTIVATE); + super.setRemoved(); + } + + public List getBeamSections() { + return this.levels == 0 ? ImmutableList.of() : this.beamSections; + } + + @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + @Override + public @NotNull CompoundTag getUpdateTag() { + return this.saveWithoutMetadata(); + } + + @Nullable + static MobEffect getValidEffectById(int pEffectId) { + MobEffect mobeffect = MobEffect.byId(pEffectId); + return VALID_EFFECTS.contains(mobeffect) ? mobeffect : null; + } + + @Override + public void load(@NotNull CompoundTag pTag) { + super.load(pTag); + this.primaryPower = getValidEffectById(pTag.getInt("Primary")); + if (pTag.contains("CustomName", 8)) { + this.name = Component.Serializer.fromJson(pTag.getString("CustomName")); + } + this.effectAmplifier = pTag.getInt("Amplifier"); + + this.lockKey = LockCode.fromTag(pTag); + this.isUpgraded = pTag.getBoolean("Upgraded"); + } + + @Override + protected void saveAdditional(@NotNull CompoundTag pTag) { + super.saveAdditional(pTag); + pTag.putInt("Primary", MobEffect.getIdFromNullable(this.primaryPower)); + pTag.putInt("Levels", this.levels); + if (this.name != null) { + pTag.putString("CustomName", Component.Serializer.toJson(this.name)); + } + pTag.putInt("Amplifier", this.effectAmplifier); + + this.lockKey.addToTag(pTag); + pTag.putBoolean("Upgraded", this.isUpgraded); + } + + public void setCustomName(@Nullable Component pName) { + this.name = pName; + } + + @Override + @Nullable + public Component getCustomName() { + return this.name; + } + + @Override + @Nullable + public AbstractContainerMenu createMenu(int pContainerId, @NotNull Inventory pPlayerInventory, @NotNull Player pPlayer) { + return BaseContainerBlockEntity.canUnlock(pPlayer, this.lockKey, this.getDisplayName()) ? new VampireBeaconMenu(pContainerId, pPlayerInventory, this.dataAccess, ContainerLevelAccess.create(this.level, this.getBlockPos())) : null; + } + + @Override + public @NotNull Component getDisplayName() { + return this.getName(); + } + + @Override + public @NotNull Component getName() { + return this.name != null ? this.name : DEFAULT_NAME; + } + + @Override + public void setLevel(@NotNull Level pLevel) { + super.setLevel(pLevel); + this.lastCheckY = pLevel.getMinBuildHeight() - 1; + } +} diff --git a/src/main/java/de/teamlapen/vampirism/blocks/VampireBeaconBlock.java b/src/main/java/de/teamlapen/vampirism/blocks/VampireBeaconBlock.java new file mode 100644 index 0000000000..18a19842f8 --- /dev/null +++ b/src/main/java/de/teamlapen/vampirism/blocks/VampireBeaconBlock.java @@ -0,0 +1,77 @@ +package de.teamlapen.vampirism.blocks; + +import de.teamlapen.vampirism.blockentity.VampireBeaconBlockEntity; +import de.teamlapen.vampirism.core.ModTiles; +import de.teamlapen.vampirism.util.Helper; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.BeaconBeamBlock; +import net.minecraft.world.level.block.RenderShape; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class VampireBeaconBlock extends VampirismBlockContainer implements BeaconBeamBlock { + + public VampireBeaconBlock(@NotNull Properties properties) { + super(properties); + } + + @Override + public @NotNull DyeColor getColor() { + return DyeColor.RED; + } + + @Nullable + @Override + public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) { + return new VampireBeaconBlockEntity(pPos, pState); + } + + @Nullable + @Override + public BlockEntityTicker getTicker(@NotNull Level pLevel, @NotNull BlockState pState, @NotNull BlockEntityType pBlockEntityType) { + return createTickerHelper(pBlockEntityType, ModTiles.VAMPIRE_BEACON.get(), VampireBeaconBlockEntity::tick); + } + + @Override + public @NotNull InteractionResult use(@NotNull BlockState pState, @NotNull Level pLevel, @NotNull BlockPos pPos, @NotNull Player pPlayer, @NotNull InteractionHand pHand, @NotNull BlockHitResult pHit) { + if (!pLevel.isClientSide) { + if (pPlayer instanceof ServerPlayer serverPlayer) { + if (Helper.isHunter(serverPlayer)) { + if (pLevel.getBlockEntity(pPos) instanceof VampireBeaconBlockEntity blockentity) { + pPlayer.openMenu(blockentity); + } + } else { + pPlayer.displayClientMessage(Component.translatable("text.vampirism.unfamiliar"), true); + } + return InteractionResult.CONSUME; + } + } + return InteractionResult.SUCCESS; + } + + @Override + public @NotNull RenderShape getRenderShape(@NotNull BlockState pState) { + return RenderShape.MODEL; + } + + @Override + public void setPlacedBy(@NotNull Level pLevel, @NotNull BlockPos pPos, @NotNull BlockState pState, @Nullable LivingEntity pPlacer, ItemStack pStack) { + if (pStack.hasCustomHoverName() && pLevel.getBlockEntity(pPos) instanceof VampireBeaconBlockEntity blockEntity) { + blockEntity.setCustomName(pStack.getHoverName()); + } + } +} diff --git a/src/main/java/de/teamlapen/vampirism/client/core/ModBlocksRender.java b/src/main/java/de/teamlapen/vampirism/client/core/ModBlocksRender.java index ee20007525..b2f342e3d1 100755 --- a/src/main/java/de/teamlapen/vampirism/client/core/ModBlocksRender.java +++ b/src/main/java/de/teamlapen/vampirism/client/core/ModBlocksRender.java @@ -78,6 +78,7 @@ static void registerBlockEntityRenderers(EntityRenderersEvent.@NotNull RegisterR event.registerBlockEntityRenderer(ModTiles.BAT_CAGE.get(), BatCageBESR::new); event.registerBlockEntityRenderer(ModTiles.MOTHER_TROPHY.get(), MotherTrophyBESR::new); event.registerBlockEntityRenderer(ModTiles.FOG_DIFFUSER.get(), FogDiffuserBESR::new); + event.registerBlockEntityRenderer(ModTiles.VAMPIRE_BEACON.get(), VampireBeaconBESR::new); } private static void registerRenderType() { diff --git a/src/main/java/de/teamlapen/vampirism/client/core/ModScreens.java b/src/main/java/de/teamlapen/vampirism/client/core/ModScreens.java index 008dc8ce44..538ac8d044 100644 --- a/src/main/java/de/teamlapen/vampirism/client/core/ModScreens.java +++ b/src/main/java/de/teamlapen/vampirism/client/core/ModScreens.java @@ -29,6 +29,7 @@ public static void registerScreensUnsafe() { MenuScreens.register(ModContainer.EXTENDED_POTION_TABLE.get(), PotionTableScreen::new); MenuScreens.register(ModContainer.VAMPIRISM.get(), VampirismContainerScreen::new); MenuScreens.register(ModContainer.ALCHEMICAL_TABLE.get(), AlchemyTableScreen::new); + MenuScreens.register(ModContainer.VAMPIRE_BEACON.get(), VampireBeaconScreen::new); } static void registerScreenOverlays(@NotNull RegisterGuiOverlaysEvent event) { diff --git a/src/main/java/de/teamlapen/vampirism/client/gui/screens/VampireBeaconScreen.java b/src/main/java/de/teamlapen/vampirism/client/gui/screens/VampireBeaconScreen.java new file mode 100644 index 0000000000..467c22ec2d --- /dev/null +++ b/src/main/java/de/teamlapen/vampirism/client/gui/screens/VampireBeaconScreen.java @@ -0,0 +1,278 @@ +package de.teamlapen.vampirism.client.gui.screens; + +import de.teamlapen.vampirism.REFERENCE; +import de.teamlapen.vampirism.VampirismMod; +import de.teamlapen.vampirism.blockentity.VampireBeaconBlockEntity; +import de.teamlapen.vampirism.core.ModItems; +import de.teamlapen.vampirism.inventory.VampireBeaconMenu; +import de.teamlapen.vampirism.network.ServerboundSetVampireBeaconPacket; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.AbstractButton; +import net.minecraft.client.gui.components.AbstractWidget; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.client.gui.narration.NarrationElementOutput; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.network.chat.CommonComponents; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerListener; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class VampireBeaconScreen extends AbstractContainerScreen { + private static final ResourceLocation BEACON_LOCATION = new ResourceLocation(REFERENCE.MODID, "textures/gui/container/vampire_beacon.png"); + private static final Component EFFECT_LABEL = Component.translatable("container.vampirism.vampire_beacon.power"); + private final List beaconButtons = new ArrayList<>(); + @Nullable + private MobEffect primary; + private int amplifier; + private boolean isUpgraded; + + public VampireBeaconScreen(VampireBeaconMenu pMenu, Inventory pPlayerInventory, Component pTitle) { + super(pMenu, pPlayerInventory, pTitle); + this.imageWidth = 230; + this.imageHeight = 219; + pMenu.addSlotListener(new ContainerListener() { + @Override + public void slotChanged(@NotNull AbstractContainerMenu pContainerToSend, int pDataSlotIndex, @NotNull ItemStack pStack) { + } + + @Override + public void dataChanged(@NotNull AbstractContainerMenu pContainerMenu, int pDataSlotIndex, int pValue) { + VampireBeaconScreen.this.primary = menu.getPrimaryEffect(); + VampireBeaconScreen.this.amplifier = menu.getAmplifier(); + VampireBeaconScreen.this.isUpgraded = menu.isUpgraded(); + VampireBeaconScreen.this.children().forEach(pWidget -> { + if (pWidget instanceof BeaconPowerButton button) { + button.updateTooltip(); + } + }); + } + }); + } + + private void addBeaconButton(T button) { + this.addRenderableWidget(button); + this.beaconButtons.add(button); + } + + @Override + protected void init() { + super.init(); + this.beaconButtons.clear(); + this.addBeaconButton(new BeaconConfirmButton(this.leftPos + 164, this.topPos + 107)); + this.addBeaconButton(new BeaconCancelButton(this.leftPos + 190, this.topPos + 107)); + + for(int i = 0; i <= 2; ++i) { + int j = VampireBeaconBlockEntity.BEACON_EFFECTS[i].length; + int k = j * 22 + (j - 1) * 2; + + for(int l = 0; l < j; ++l) { + MobEffect mobeffect = VampireBeaconBlockEntity.BEACON_EFFECTS[i][l]; + int amplifier = VampireBeaconBlockEntity.BEACON_EFFECTS_AMPLIFIER[i][l]; + BeaconPowerButton beaconscreen$beaconpowerbutton = new BeaconPowerButton(this.leftPos + 76 + 62 + l * 24 - k / 2, this.topPos + 22 + i * 25, mobeffect, amplifier, i); + beaconscreen$beaconpowerbutton.active = false; + this.addBeaconButton(beaconscreen$beaconpowerbutton); + } + } + } + + public void containerTick() { + super.containerTick(); + this.updateButtons(); + } + + void updateButtons() { + int i = this.menu.getLevels(); + this.beaconButtons.forEach((p_169615_) -> { + p_169615_.updateStatus(i); + }); + } + + protected void renderLabels(GuiGraphics pGuiGraphics, int pMouseX, int pMouseY) { + pGuiGraphics.drawCenteredString(this.font, EFFECT_LABEL, 62 + 55, 10, 14737632); + } + + protected void renderBg(GuiGraphics pGuiGraphics, float pPartialTick, int pMouseX, int pMouseY) { + int i = (this.width - this.imageWidth) / 2; + int j = (this.height - this.imageHeight) / 2; + pGuiGraphics.blit(BEACON_LOCATION, i, j, 0, 0, this.imageWidth, this.imageHeight); + pGuiGraphics.pose().pushPose(); + pGuiGraphics.pose().translate(0.0F, 0.0F, 100.0F); + pGuiGraphics.renderItem(new ItemStack(ModItems.PURE_BLOOD_0.get()), i + 41, j + 109); + pGuiGraphics.renderItem(new ItemStack(ModItems.SOUL_ORB_VAMPIRE.get()), i + 41 + 22, j + 109); + pGuiGraphics.renderItem(new ItemStack(ModItems.HUMAN_HEART.get()), i + 42 + 44, j + 109); + pGuiGraphics.renderItem(new ItemStack(ModItems.WEAK_HUMAN_HEART.get()), i + 42 + 66, j + 109); + pGuiGraphics.pose().popPose(); + } + + public void render(@NotNull GuiGraphics pGuiGraphics, int pMouseX, int pMouseY, float pPartialTick) { + this.renderBackground(pGuiGraphics); + super.render(pGuiGraphics, pMouseX, pMouseY, pPartialTick); + this.renderTooltip(pGuiGraphics, pMouseX, pMouseY); + } + + interface BeaconButton { + void updateStatus(int beaconTier); + } + + class BeaconCancelButton extends BeaconSpriteScreenButton { + public BeaconCancelButton(int pX, int pY) { + super(pX, pY, 112, 220, CommonComponents.GUI_CANCEL); + } + + public void onPress() { + VampireBeaconScreen.this.minecraft.player.closeContainer(); + } + + public void updateStatus(int pBeaconTier) { + } + } + + @OnlyIn(Dist.CLIENT) + class BeaconConfirmButton extends BeaconSpriteScreenButton { + public BeaconConfirmButton(int pX, int pY) { + super(pX, pY, 90, 220, CommonComponents.GUI_DONE); + } + + public void onPress() { + VampirismMod.dispatcher.sendToServer(new ServerboundSetVampireBeaconPacket(Optional.ofNullable(VampireBeaconScreen.this.primary), Optional.of(VampireBeaconScreen.this.amplifier))); + VampireBeaconScreen.this.minecraft.player.closeContainer(); + } + + public void updateStatus(int pBeaconTier) { + this.active = VampireBeaconScreen.this.menu.hasPayment() && VampireBeaconScreen.this.primary != null; + } + } + + @OnlyIn(Dist.CLIENT) + class BeaconPowerButton extends BeaconScreenButton { + protected final int tier; + private MobEffect effect; + private int effectAmplifier; + private TextureAtlasSprite sprite; + + public BeaconPowerButton(int pX, int pY, MobEffect pEffect, int effectAmplifier, int pTier) { + super(pX, pY); + this.effectAmplifier = effectAmplifier; + this.tier = pTier; + this.setEffect(pEffect, effectAmplifier); + } + + protected void setEffect(MobEffect pEffect, int effectAmplifier) { + this.effect = pEffect; + this.effectAmplifier = effectAmplifier; + this.sprite = Minecraft.getInstance().getMobEffectTextures().get(pEffect); + this.updateTooltip(); + } + + public void updateTooltip() { + this.setTooltip(Tooltip.create(this.createEffectDescription(this.effect, this.effectAmplifier), null)); + } + + protected MutableComponent createEffectDescription(MobEffect pEffect, int amplifier) { + MutableComponent component = Component.translatable(pEffect.getDescriptionId()); + if (!VampireBeaconBlockEntity.NO_AMPLIFIER_EFFECTS.contains(pEffect)) { + amplifier += VampireBeaconScreen.this.menu.isUpgraded() ? 1 : 0; + } + if (amplifier <= 0) { + return component; + } + return Component.translatable("potion.withAmplifier", component, Component.translatable("potion.potency." + amplifier)); + } + + public void onPress() { + if (!this.isSelected()) { + VampireBeaconScreen.this.primary = this.effect; + VampireBeaconScreen.this.amplifier = this.effectAmplifier; + + VampireBeaconScreen.this.updateButtons(); + } + } + + protected void renderIcon(GuiGraphics pGuiGraphics) { + pGuiGraphics.blit(this.getX() + 2, this.getY() + 2, 0, 18, 18, this.sprite); + } + + public void updateStatus(int pBeaconTier) { + this.active = this.tier < pBeaconTier; + this.setSelected(this.effect == VampireBeaconScreen.this.primary); + } + + protected @NotNull MutableComponent createNarrationMessage() { + return this.createEffectDescription(this.effect, this.effectAmplifier); + } + } + + @OnlyIn(Dist.CLIENT) + abstract static class BeaconScreenButton extends AbstractButton implements BeaconButton { + private boolean selected; + + protected BeaconScreenButton(int pX, int pY) { + super(pX, pY, 22, 22, CommonComponents.EMPTY); + } + + protected BeaconScreenButton(int pX, int pY, Component pMessage) { + super(pX, pY, 22, 22, pMessage); + } + + public void renderWidget(@NotNull GuiGraphics pGuiGraphics, int pMouseX, int pMouseY, float pPartialTick) { + int i = 219; + int j = 0; + if (!this.active) { + j += this.width * 2; + } else if (this.selected) { + j += this.width; + } else if (this.isHoveredOrFocused()) { + j += this.width * 3; + } + + pGuiGraphics.blit(BEACON_LOCATION, this.getX(), this.getY(), j, 219, this.width, this.height); + this.renderIcon(pGuiGraphics); + } + + protected abstract void renderIcon(GuiGraphics pGuiGraphics); + + public boolean isSelected() { + return this.selected; + } + + public void setSelected(boolean pSelected) { + this.selected = pSelected; + } + + public void updateWidgetNarration(@NotNull NarrationElementOutput pNarrationElementOutput) { + this.defaultButtonNarrationText(pNarrationElementOutput); + } + } + + @OnlyIn(Dist.CLIENT) + abstract static class BeaconSpriteScreenButton extends BeaconScreenButton { + private final int iconX; + private final int iconY; + + protected BeaconSpriteScreenButton(int p_169663_, int p_169664_, int p_169665_, int p_169666_, Component p_169667_) { + super(p_169663_, p_169664_, p_169667_); + this.iconX = p_169665_; + this.iconY = p_169666_; + } + + protected void renderIcon(GuiGraphics p_283624_) { + p_283624_.blit(BEACON_LOCATION, this.getX() + 2, this.getY() + 2, this.iconX, this.iconY, 18, 18); + } + } + +} diff --git a/src/main/java/de/teamlapen/vampirism/client/renderer/blockentity/VampireBeaconBESR.java b/src/main/java/de/teamlapen/vampirism/client/renderer/blockentity/VampireBeaconBESR.java new file mode 100644 index 0000000000..9afc8e01d9 --- /dev/null +++ b/src/main/java/de/teamlapen/vampirism/client/renderer/blockentity/VampireBeaconBESR.java @@ -0,0 +1,55 @@ +package de.teamlapen.vampirism.client.renderer.blockentity; + +import com.mojang.blaze3d.vertex.PoseStack; +import de.teamlapen.vampirism.blockentity.VampireBeaconBlockEntity; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.blockentity.BeaconRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.entity.BeaconBlockEntity; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class VampireBeaconBESR extends VampirismBESR { + public static final ResourceLocation BEAM_LOCATION = new ResourceLocation("textures/entity/beacon_beam.png"); + public static final int MAX_RENDER_Y = 1024; + + public VampireBeaconBESR(BlockEntityRendererProvider.Context pContext) { + } + + @Override + public void render(VampireBeaconBlockEntity pBlockEntity, float pPartialTick, @NotNull PoseStack pPoseStack, @NotNull MultiBufferSource pBuffer, int pPackedLight, int pPackedOverlay) { + //noinspection DataFlowIssue + long i = pBlockEntity.getLevel().getGameTime(); + List list = pBlockEntity.getBeamSections(); + int j = 0; + + for(int k = 0; k < list.size(); ++k) { + BeaconBlockEntity.BeaconBeamSection beaconblockentity$beaconbeamsection = list.get(k); + renderBeaconBeam(pPoseStack, pBuffer, pPartialTick, i, j, k == list.size() - 1 ? MAX_RENDER_Y : beaconblockentity$beaconbeamsection.getHeight(), beaconblockentity$beaconbeamsection.getColor()); + j += beaconblockentity$beaconbeamsection.getHeight(); + } + + } + + private static void renderBeaconBeam(PoseStack pPoseStack, MultiBufferSource pBufferSource, float pPartialTick, long pGameTime, int pYOffset, int pHeight, float[] pColors) { + BeaconRenderer.renderBeaconBeam(pPoseStack, pBufferSource, BEAM_LOCATION, pPartialTick, 1.0F, pGameTime, pYOffset, pHeight, pColors, 0.2F, 0.25F); + } + + @Override + public boolean shouldRenderOffScreen(@NotNull VampireBeaconBlockEntity pBlockEntity) { + return true; + } + + @Override + public int getViewDistance() { + return 256; + } + + @Override + public boolean shouldRender(VampireBeaconBlockEntity pBlockEntity, Vec3 pCameraPos) { + return Vec3.atCenterOf(pBlockEntity.getBlockPos()).multiply(1.0D, 0.0D, 1.0D).closerThan(pCameraPos.multiply(1.0D, 0.0D, 1.0D), this.getViewDistance()); + } +} diff --git a/src/main/java/de/teamlapen/vampirism/core/ModBlocks.java b/src/main/java/de/teamlapen/vampirism/core/ModBlocks.java index 3f7c56bb1e..4de7f52607 100755 --- a/src/main/java/de/teamlapen/vampirism/core/ModBlocks.java +++ b/src/main/java/de/teamlapen/vampirism/core/ModBlocks.java @@ -19,6 +19,7 @@ import net.minecraft.world.level.block.*; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.properties.BlockSetType; +import net.minecraft.world.level.block.state.properties.NoteBlockInstrument; import net.minecraft.world.level.material.MapColor; import net.minecraft.world.level.material.PushReaction; import net.minecraftforge.eventbus.api.IEventBus; @@ -191,6 +192,9 @@ public class ModBlocks { public static final RegistryObject FOG_DIFFUSER = registerWithItem("fog_diffuser", () -> new FogDiffuserBlock(BlockBehaviour.Properties.of().noOcclusion().mapColor(MapColor.STONE).strength(40.0F, 1200.0F).sound(SoundType.STONE))); public static final RegistryObject POTTED_DARK_SPRUCE_SAPLING = BLOCKS.register("potted_dark_spruce_sapling", () -> potted(new FlowerPotBlock(() -> (FlowerPotBlock) Blocks.FLOWER_POT, DARK_SPRUCE_SAPLING, Block.Properties.of().noCollission().isViewBlocking(UtilLib::never).pushReaction(PushReaction.DESTROY).instabreak()), DARK_SPRUCE_SAPLING.getId())); public static final RegistryObject POTTED_CURSED_SPRUCE_SAPLING = BLOCKS.register("potted_cursed_spruce_sapling", () -> potted(new FlowerPotBlock(() -> (FlowerPotBlock) Blocks.FLOWER_POT, CURSED_SPRUCE_SAPLING, Block.Properties.of().noCollission().isViewBlocking(UtilLib::never).pushReaction(PushReaction.DESTROY).instabreak()), CURSED_SPRUCE_SAPLING.getId())); + public static final RegistryObject BLOOD_INFUSED_IRON_BLOCK = registerWithItem("blood_infused_iron_block", () -> new Block(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).requiresCorrectToolForDrops().strength(5.0F, 6.0F).sound(SoundType.METAL))); + public static final RegistryObject BLOOD_INFUSED_ENHANCED_IRON_BLOCK = registerWithItem("blood_infused_enhanced_iron_block", () -> new Block(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).requiresCorrectToolForDrops().strength(5.0F, 6.0F).sound(SoundType.METAL))); + public static final RegistryObject VAMPIRE_BEACON = registerWithItem("vampire_beacon", () -> new VampireBeaconBlock(BlockBehaviour.Properties.of().mapColor(MapColor.DIAMOND).instrument(NoteBlockInstrument.HAT).strength(3.0F).lightLevel((p_50828_) -> 15).noOcclusion().isRedstoneConductor(UtilLib::never)), new Item.Properties().rarity(Rarity.RARE)); /** diff --git a/src/main/java/de/teamlapen/vampirism/core/ModContainer.java b/src/main/java/de/teamlapen/vampirism/core/ModContainer.java index 1b6f460831..ac26854b89 100644 --- a/src/main/java/de/teamlapen/vampirism/core/ModContainer.java +++ b/src/main/java/de/teamlapen/vampirism/core/ModContainer.java @@ -26,6 +26,7 @@ public class ModContainer { public static final RegistryObject> EXTENDED_POTION_TABLE = MENUS.register("extended_potion_table", () -> create(new PotionTableMenu.Factory())); public static final RegistryObject> VAMPIRISM = MENUS.register("vampirism", () -> create(VampirismMenu::new)); public static final RegistryObject> ALCHEMICAL_TABLE = MENUS.register("alchemical_table", () -> create(AlchemyTableMenu::new)); + public static final RegistryObject> VAMPIRE_BEACON = MENUS.register("vampire_beacon", () -> create(VampireBeaconMenu::new)); private static MenuType create(MenuType.MenuSupplier supplier) { return new MenuType<>(supplier, FeatureFlags.DEFAULT_FLAGS); diff --git a/src/main/java/de/teamlapen/vampirism/core/ModRecipes.java b/src/main/java/de/teamlapen/vampirism/core/ModRecipes.java index f7800813ec..78d4a85ec1 100644 --- a/src/main/java/de/teamlapen/vampirism/core/ModRecipes.java +++ b/src/main/java/de/teamlapen/vampirism/core/ModRecipes.java @@ -5,7 +5,6 @@ import de.teamlapen.vampirism.api.items.IWeaponTableRecipe; import de.teamlapen.vampirism.recipes.*; import de.teamlapen.vampirism.util.NBTIngredient; -import net.minecraft.core.Registry; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; @@ -66,6 +65,11 @@ static void registerDefaultLiquidColors() { registerLiquidColor(ModItems.HOLY_WATER_BOTTLE_NORMAL.get(), 0x6666FF); registerLiquidColor(ModItems.HOLY_WATER_BOTTLE_ENHANCED.get(), 0x6666FF); registerLiquidColor(ModItems.HOLY_WATER_BOTTLE_ULTIMATE.get(), 0x6666FF); + registerLiquidColor(ModItems.PURE_BLOOD_0.get(), 0x7c0805); + registerLiquidColor(ModItems.PURE_BLOOD_1.get(), 0x7d0503); + registerLiquidColor(ModItems.PURE_BLOOD_2.get(), 0x830000); + registerLiquidColor(ModItems.PURE_BLOOD_3.get(), 0x7e0e0e); + registerLiquidColor(ModItems.PURE_BLOOD_4.get(), 0x8e0000); registerLiquidColor(ModTags.Items.GARLIC, 0xBBBBBB); diff --git a/src/main/java/de/teamlapen/vampirism/core/ModTags.java b/src/main/java/de/teamlapen/vampirism/core/ModTags.java index b64859fe16..7f51014d7f 100644 --- a/src/main/java/de/teamlapen/vampirism/core/ModTags.java +++ b/src/main/java/de/teamlapen/vampirism/core/ModTags.java @@ -49,11 +49,12 @@ public static class Blocks { public static final TagKey DARK_STONE_TILES = tag("dark_brick_tiles"); public static final TagKey NO_SPAWN = tag("no_spawn"); public static final TagKey VAMPIRE_SPAWN = tag("vampire_spawn"); - public static final TagKey REMAINS = tag("remains"); public static final TagKey ACTIVE_REMAINS = tag("active_remains"); public static final TagKey VULNERABLE_REMAINS = tag("vulnerable_remains"); public static final TagKey MOTHER_GROWS_ON = tag("mother_grows_on"); + public static final TagKey VAMPIRE_BEACON_BASE_BLOCKS = tag("vampire_beacon_base_blocks"); + public static final TagKey VAMPIRE_BEACON_BASE_ENHANCED_BLOCKS = tag("vampire_beacon_base_enhanced_blocks"); private static @NotNull TagKey tag(@NotNull ResourceLocation resourceLocation) { return BlockTags.create(resourceLocation); @@ -90,6 +91,7 @@ public static class Items { public static final TagKey DARK_STONE_TILES = tag("dark_brick_tiles"); public static final TagKey NO_SPAWN = tag("no_spawn"); public static final TagKey VAMPIRE_SPAWN = tag("vampire_spawn"); + public static final TagKey VAMPIRE_BEACON_PAYMENT_ITEM = tag("vampire_beacon_payment_item"); private static @NotNull TagKey tag(@NotNull ResourceLocation resourceLocation) { return ItemTags.create(resourceLocation); diff --git a/src/main/java/de/teamlapen/vampirism/core/ModTiles.java b/src/main/java/de/teamlapen/vampirism/core/ModTiles.java index 80d16e2cf9..6f293f6008 100644 --- a/src/main/java/de/teamlapen/vampirism/core/ModTiles.java +++ b/src/main/java/de/teamlapen/vampirism/core/ModTiles.java @@ -41,6 +41,7 @@ public class ModTiles { public static final RegistryObject> VULNERABLE_CURSED_ROOTED_DIRT = BLOCK_ENTITY_TYPES.register("vulnerable_cursed_rooted_dirt", () -> create(VulnerableRemainsBlockEntity::new, ModBlocks.ACTIVE_VULNERABLE_REMAINS.get())); public static final RegistryObject> MOTHER_TROPHY = BLOCK_ENTITY_TYPES.register("mother_trophy", () -> create(MotherTrophyBlockEntity::new, ModBlocks.MOTHER_TROPHY.get())); public static final RegistryObject> FOG_DIFFUSER = BLOCK_ENTITY_TYPES.register("fog_diffuser", () -> create(FogDiffuserBlockEntity::new, ModBlocks.FOG_DIFFUSER.get())); + public static final RegistryObject> VAMPIRE_BEACON = BLOCK_ENTITY_TYPES.register("vampire_beacon", () -> create(VampireBeaconBlockEntity::new, ModBlocks.VAMPIRE_BEACON.get())); static void register(IEventBus bus) { BLOCK_ENTITY_TYPES.register(bus); diff --git a/src/main/java/de/teamlapen/vampirism/data/BlockStateGenerator.java b/src/main/java/de/teamlapen/vampirism/data/BlockStateGenerator.java index 2676fbdf63..9a2880430c 100644 --- a/src/main/java/de/teamlapen/vampirism/data/BlockStateGenerator.java +++ b/src/main/java/de/teamlapen/vampirism/data/BlockStateGenerator.java @@ -285,6 +285,9 @@ protected void registerStatesAndModels() { simpleBlock(ModBlocks.FOG_DIFFUSER.get(), models().withExistingParent("fog_diffuser_normal", modLoc("block/fog_diffuser")).renderType(cutout)); simpleBlock(ModBlocks.POTTED_DARK_SPRUCE_SAPLING.get(), models().withExistingParent("vampirism:block/potted_dark_spruce_sapling", "minecraft:block/flower_pot_cross").texture("plant", "vampirism:block/dark_spruce_sapling").renderType(cutout)); simpleBlock(ModBlocks.POTTED_CURSED_SPRUCE_SAPLING.get(), models().withExistingParent("vampirism:block/potted_cursed_spruce_sapling", "minecraft:block/flower_pot_cross").texture("plant", "vampirism:block/cursed_spruce_sapling").renderType(cutout)); + simpleBlock(ModBlocks.BLOOD_INFUSED_IRON_BLOCK.get()); + simpleBlock(ModBlocks.BLOOD_INFUSED_ENHANCED_IRON_BLOCK.get()); + simpleBlock(ModBlocks.VAMPIRE_BEACON.get(), models().withExistingParent("vampire_beacon", mcLoc("block/beacon")).texture("beacon", modLoc("block/vampire_beacon")).renderType(cutout)); } private void createWoodStates() { diff --git a/src/main/java/de/teamlapen/vampirism/data/ItemModelGenerator.java b/src/main/java/de/teamlapen/vampirism/data/ItemModelGenerator.java index 13e7b84b0e..46d38afe5d 100644 --- a/src/main/java/de/teamlapen/vampirism/data/ItemModelGenerator.java +++ b/src/main/java/de/teamlapen/vampirism/data/ItemModelGenerator.java @@ -101,6 +101,9 @@ protected void registerModels() { add(ModBlocks.INCAPACITATED_VULNERABLE_REMAINS.get()); add(ModBlocks.CURSED_HANGING_ROOTS.get()); add(ModBlocks.MOTHER.get()); + add(ModBlocks.BLOOD_INFUSED_ENHANCED_IRON_BLOCK.get()); + add(ModBlocks.BLOOD_INFUSED_IRON_BLOCK.get()); + add(ModBlocks.VAMPIRE_BEACON.get()); }}; Set items = new HashSet<>() {{ add(ModItems.HUNTER_COAT_CHEST_NORMAL.get()); @@ -331,6 +334,7 @@ protected void registerModels() { withExistingParent(ModBlocks.POLISHED_DARK_STONE_WALL.get(), mcLoc("block/wall_inventory")).texture("wall", modLoc("block/polished_dark_stone")); withExistingParent(ModBlocks.INFESTED_DARK_STONE.get(), modLoc("block/dark_stone")); block(ModBlocks.FOG_DIFFUSER.get(), "fog_diffuser"); + withExistingParent(ModBlocks.CURSED_HANGING_ROOTS.get().asItem(), mcLoc("item/generated")).texture("layer0", REFERENCE.MODID + ":block/cursed_hanging_roots"); } } diff --git a/src/main/java/de/teamlapen/vampirism/data/LootTablesGenerator.java b/src/main/java/de/teamlapen/vampirism/data/LootTablesGenerator.java index 098e399d3e..ab5fe8b427 100644 --- a/src/main/java/de/teamlapen/vampirism/data/LootTablesGenerator.java +++ b/src/main/java/de/teamlapen/vampirism/data/LootTablesGenerator.java @@ -431,6 +431,9 @@ protected void generate() { this.dropSelf(ModBlocks.FOG_DIFFUSER.get()); this.dropPottedContents(ModBlocks.POTTED_DARK_SPRUCE_SAPLING.get()); this.dropPottedContents(ModBlocks.POTTED_CURSED_SPRUCE_SAPLING.get()); + this.dropSelf(ModBlocks.BLOOD_INFUSED_IRON_BLOCK.get()); + this.dropSelf(ModBlocks.BLOOD_INFUSED_ENHANCED_IRON_BLOCK.get()); + this.add(ModBlocks.VAMPIRE_BEACON.get(), this::createNameableBlockEntityTable); } @NotNull diff --git a/src/main/java/de/teamlapen/vampirism/data/RecipesGenerator.java b/src/main/java/de/teamlapen/vampirism/data/RecipesGenerator.java index 9ea533d67a..4fcc3a8265 100644 --- a/src/main/java/de/teamlapen/vampirism/data/RecipesGenerator.java +++ b/src/main/java/de/teamlapen/vampirism/data/RecipesGenerator.java @@ -434,6 +434,15 @@ protected void buildRecipes(@NotNull Consumer consumer) { SimpleCookingRecipeBuilder.blasting(Ingredient.of(ModBlocks.COBBLED_DARK_STONE.get()), RecipeCategory.BUILDING_BLOCKS, ModBlocks.DARK_STONE.get(),0.1f, 100).unlockedBy("has_cobbled_dark_stone", has(ModBlocks.COBBLED_DARK_STONE.get())).save(consumer, new ResourceLocation(REFERENCE.MODID, "dark_stone_from_cobbled_dark_stone_blasting")); ShapedRecipeBuilder.shaped(RecipeCategory.DECORATIONS, ModBlocks.BAT_CAGE.get()).pattern("GGG").pattern("GPG").pattern("PPP").define('G', gold_ingot).define('P', planks).unlockedBy("has_gold", has(gold_ingot)).unlockedBy("has_planks", has(planks)).save(consumer); ShapedRecipeBuilder.shaped(RecipeCategory.DECORATIONS, ModBlocks.FOG_DIFFUSER.get()).pattern("XYX").pattern("YZY").pattern("OOO").define('X', cursed_spruce_planks).define('Y', diamond).define('O', obsidian).define('Z', mother_core).unlockedBy("has_diamond", has(diamond)).unlockedBy("has_cursed_plank", has(cursed_spruce_planks)).unlockedBy("has_mother_core", has(mother_core)).save(consumer, vampire("fog_diffuser")); + nineBlockStorageRecipes(consumer, RecipeCategory.BUILDING_BLOCKS, ModItems.BLOOD_INFUSED_IRON_INGOT.get(), RecipeCategory.BUILDING_BLOCKS, ModBlocks.BLOOD_INFUSED_IRON_BLOCK.get()); + nineBlockStorageRecipes(consumer, RecipeCategory.BUILDING_BLOCKS, ModItems.BLOOD_INFUSED_ENHANCED_IRON_INGOT.get(), RecipeCategory.BUILDING_BLOCKS, ModBlocks.BLOOD_INFUSED_ENHANCED_IRON_BLOCK.get()); + ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ModBlocks.VAMPIRE_BEACON.get()).pattern("GGG").pattern("GCG").pattern("OOO").define('G', Items.GLASS).define('C', mother_core).define('O', obsidian).unlockedBy("has_mother_core", has(mother_core)).unlockedBy("has_obsidian", has(obsidian)).unlockedBy("has_glass", has(Items.GLASS)).save(consumer); + AlchemicalCauldronRecipeBuilder.cauldronRecipe(ModBlocks.BLOOD_INFUSED_IRON_BLOCK.get().asItem()).withFluid(ModItems.PURE_BLOOD_0.get()).withIngredient(new ItemStack(Items.IRON_BLOCK)).cookTime(200).experience(0.1f).build(consumer, new ResourceLocation(REFERENCE.MODID, "blood_infused_iron_ingot_from_pure_blood_0")); + AlchemicalCauldronRecipeBuilder.cauldronRecipe(ModBlocks.BLOOD_INFUSED_IRON_BLOCK.get().asItem()).withFluid(ModItems.PURE_BLOOD_1.get()).withIngredient(new ItemStack(Items.IRON_BLOCK)).cookTime(180).experience(0.15f).build(consumer, new ResourceLocation(REFERENCE.MODID, "blood_infused_iron_ingot_from_pure_blood_1")); + AlchemicalCauldronRecipeBuilder.cauldronRecipe(ModBlocks.BLOOD_INFUSED_IRON_BLOCK.get().asItem()).withFluid(ModItems.PURE_BLOOD_2.get()).withIngredient(new ItemStack(Items.IRON_BLOCK)).cookTime(160).experience(0.2f).build(consumer, new ResourceLocation(REFERENCE.MODID, "blood_infused_iron_ingot_from_pure_blood_2")); + AlchemicalCauldronRecipeBuilder.cauldronRecipe(ModBlocks.BLOOD_INFUSED_IRON_BLOCK.get().asItem()).withFluid(ModItems.PURE_BLOOD_3.get()).withIngredient(new ItemStack(Items.IRON_BLOCK)).cookTime(140).experience(0.25f).build(consumer, new ResourceLocation(REFERENCE.MODID, "blood_infused_iron_ingot_from_pure_blood_3")); + AlchemicalCauldronRecipeBuilder.cauldronRecipe(ModBlocks.BLOOD_INFUSED_ENHANCED_IRON_BLOCK.get().asItem()).withFluid(ModItems.PURE_BLOOD_4.get()).withIngredient(new ItemStack(Items.IRON_BLOCK)).cookTime(300).experience(0.3f).build(consumer, new ResourceLocation(REFERENCE.MODID, "blood_infused_enhanced_iron_ingot_from_pure_blood_4")); + } private @NotNull JsonObject enchantment(int level, Enchantment enchantment) { diff --git a/src/main/java/de/teamlapen/vampirism/data/TagGenerator.java b/src/main/java/de/teamlapen/vampirism/data/TagGenerator.java index e9909a0a82..5a0e2bb7f4 100644 --- a/src/main/java/de/teamlapen/vampirism/data/TagGenerator.java +++ b/src/main/java/de/teamlapen/vampirism/data/TagGenerator.java @@ -191,6 +191,9 @@ protected void addTags(HolderLookup.Provider holderLookup) { tag(BlockTags.STAIRS).add(ModBlocks.DARK_STONE_BRICK_STAIRS.get(), ModBlocks.POLISHED_DARK_STONE_STAIRS.get(), ModBlocks.COBBLED_DARK_STONE_STAIRS.get(), ModBlocks.DARK_STONE_STAIRS.get(), ModBlocks.DARK_STONE_TILES_STAIRS.get(), ModBlocks.CASTLE_STAIRS_PURPLE_BRICK.get()); tag(BlockTags.SLABS).add(ModBlocks.DARK_STONE_BRICK_SLAB.get(), ModBlocks.POLISHED_DARK_STONE_SLAB.get(), ModBlocks.COBBLED_DARK_STONE_SLAB.get(), ModBlocks.DARK_STONE_SLAB.get(), ModBlocks.DARK_STONE_TILES_SLAB.get(), ModBlocks.CASTLE_SLAB_PURPLE_BRICK.get()); tag(ModTags.Blocks.MOTHER_GROWS_ON).addTag(BlockTags.DIRT); + tag(Tags.Blocks.STORAGE_BLOCKS).add(ModBlocks.BLOOD_INFUSED_IRON_BLOCK.get(), ModBlocks.BLOOD_INFUSED_ENHANCED_IRON_BLOCK.get()); + tag(ModTags.Blocks.VAMPIRE_BEACON_BASE_BLOCKS).add(ModBlocks.BLOOD_INFUSED_IRON_BLOCK.get(), ModBlocks.BLOOD_INFUSED_ENHANCED_IRON_BLOCK.get()); + tag(ModTags.Blocks.VAMPIRE_BEACON_BASE_ENHANCED_BLOCKS).add(ModBlocks.BLOOD_INFUSED_ENHANCED_IRON_BLOCK.get()); } } @@ -205,6 +208,7 @@ public String getName() { return REFERENCE.MODID + " " + super.getName(); } + @SuppressWarnings("unchecked") @Override protected void addTags(HolderLookup.@NotNull Provider holderProvider) { copy(ModTags.Blocks.CASTLE_BLOCK, ModTags.Items.CASTLE_BLOCK); @@ -256,6 +260,7 @@ protected void addTags(HolderLookup.@NotNull Provider holderProvider) { tag(ItemTags.HANGING_SIGNS).add(ModItems.DARK_SPRUCE_HANGING_SIGN.get(), ModItems.CURSED_SPRUCE_HANGING_SIGN.get()); tag(ModTags.Items.HUNTER_COAT).add(ModItems.HUNTER_COAT_HEAD_NORMAL.get(),ModItems.HUNTER_COAT_HEAD_ENHANCED.get(),ModItems.HUNTER_COAT_HEAD_ULTIMATE.get(), ModItems.HUNTER_COAT_CHEST_NORMAL.get(),ModItems.HUNTER_COAT_CHEST_ENHANCED.get(),ModItems.HUNTER_COAT_CHEST_ULTIMATE.get(), ModItems.HUNTER_COAT_LEGS_NORMAL.get(),ModItems.HUNTER_COAT_LEGS_ENHANCED.get(),ModItems.HUNTER_COAT_LEGS_ULTIMATE.get(), ModItems.HUNTER_COAT_FEET_NORMAL.get(),ModItems.HUNTER_COAT_FEET_ENHANCED.get(),ModItems.HUNTER_COAT_FEET_ULTIMATE.get()); tag(ItemTags.FREEZE_IMMUNE_WEARABLES).addTag(ModTags.Items.HUNTER_COAT); + tag(ModTags.Items.VAMPIRE_BEACON_PAYMENT_ITEM).addTags(ModTags.Items.PURE_BLOOD, ModTags.Items.HEART).add(ModItems.SOUL_ORB_VAMPIRE.get()); } } diff --git a/src/main/java/de/teamlapen/vampirism/entity/player/vampire/VampirePlayer.java b/src/main/java/de/teamlapen/vampirism/entity/player/vampire/VampirePlayer.java index 1bef966ebd..783169c88e 100644 --- a/src/main/java/de/teamlapen/vampirism/entity/player/vampire/VampirePlayer.java +++ b/src/main/java/de/teamlapen/vampirism/entity/player/vampire/VampirePlayer.java @@ -82,12 +82,14 @@ import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.ForgeMod; -import net.minecraftforge.common.capabilities.*; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.common.capabilities.ICapabilitySerializable; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.event.TickEvent; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.server.permission.PermissionAPI; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; @@ -739,7 +741,11 @@ public void onJoinWorld() { @Override public void onLevelChanged(int newLevel, int oldLevel) { super.onLevelChanged(newLevel, oldLevel); - this.applyEntityAttributes(); + if (newLevel > 0) { + this.applyEntityAttributes(); + } else { + this.removeEntityAttributes(); + } if (!isRemote()) { ScoreboardUtil.updateScoreboard(player, ScoreboardUtil.VAMPIRE_LEVEL_CRITERIA, newLevel); applyLevelModifiersA(newLevel); @@ -1214,6 +1220,11 @@ private void applyEntityAttributes() { player.getAttribute(ModAttributes.BLOOD_EXHAUSTION.get()).setBaseValue(VampirismConfig.BALANCE.vpBloodExhaustionFactor.get()); } + private void removeEntityAttributes() { + player.getAttribute(ModAttributes.SUNDAMAGE.get()).setBaseValue(0); + player.getAttribute(ModAttributes.BLOOD_EXHAUSTION.get()).setBaseValue(0); + } + /** * Apply the armor unaffected level scaled entity attribute modifiers */ diff --git a/src/main/java/de/teamlapen/vampirism/inventory/VampireBeaconMenu.java b/src/main/java/de/teamlapen/vampirism/inventory/VampireBeaconMenu.java new file mode 100644 index 0000000000..e7bf6e6351 --- /dev/null +++ b/src/main/java/de/teamlapen/vampirism/inventory/VampireBeaconMenu.java @@ -0,0 +1,124 @@ +package de.teamlapen.vampirism.inventory; + +import de.teamlapen.vampirism.blockentity.VampireBeaconBlockEntity; +import de.teamlapen.vampirism.core.ModBlocks; +import de.teamlapen.vampirism.core.ModContainer; +import de.teamlapen.vampirism.core.ModTags; +import net.minecraft.world.Container; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.ContainerData; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.world.inventory.SimpleContainerData; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nullable; +import java.util.Optional; + +public class VampireBeaconMenu extends VampirismContainerMenu { + + private final Container beacon = new SimpleContainer(1) { + + @Override + public boolean canPlaceItem(int pIndex, ItemStack pStack) { + return pStack.is(ModTags.Items.VAMPIRE_BEACON_PAYMENT_ITEM); + } + + @Override + public int getMaxStackSize() { + return 1; + } + }; + private final PaymentSlot paymentSlot; + private final ContainerData beaconData; + private final ContainerLevelAccess access; + + public VampireBeaconMenu(int pContainerId, Container container) { + this(pContainerId, container, new SimpleContainerData(VampireBeaconBlockEntity.NUM_DATA_VALUES), ContainerLevelAccess.NULL); + } + + public VampireBeaconMenu(int pContainerId, Container container, ContainerData beaconData, ContainerLevelAccess pLevelAccess) { + super(ModContainer.VAMPIRE_BEACON.get(), pContainerId, 1); + this.beaconData = beaconData; + this.access = pLevelAccess; + this.paymentSlot = new PaymentSlot(this.beacon, 0, 136, 110); + this.addSlot(this.paymentSlot); + this.addDataSlots(beaconData); + addPlayerSlots(container, 36, 137); + } + + + + @Override + public void removed(@NotNull Player pPlayer) { + super.removed(pPlayer); + if (pPlayer.level().isClientSide) { + ItemStack itemStack = this.paymentSlot.remove(this.paymentSlot.getMaxStackSize()); + if (!itemStack.isEmpty()) { + pPlayer.drop(itemStack, false); + } + } + } + + @Override + public boolean stillValid(@NotNull Player pPlayer) { + return stillValid(this.access, pPlayer, ModBlocks.VAMPIRE_BEACON.get()); + } + + @Override + public void setData(int pId, int pData) { + super.setData(pId, pData); + this.broadcastChanges(); + } + + public int getLevels() { + return this.beaconData.get(0); + } + + @Nullable + public MobEffect getPrimaryEffect() { + return MobEffect.byId(this.beaconData.get(VampireBeaconBlockEntity.DATA_PRIMARY)); + } + + public int getAmplifier() { + return this.beaconData.get(VampireBeaconBlockEntity.DATA_AMPLIFIER); + } + + public boolean isUpgraded() { + return this.beaconData.get(VampireBeaconBlockEntity.DATA_UPGRADED) > 0; + } + + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + public void updateEffects(Optional primaryEffect, Optional amplifier) { + if (this.paymentSlot.hasItem()) { + this.beaconData.set(VampireBeaconBlockEntity.DATA_PRIMARY, primaryEffect.map(MobEffect::getId).orElse(-1)); + this.beaconData.set(VampireBeaconBlockEntity.DATA_AMPLIFIER, amplifier.orElse(0)); + this.paymentSlot.remove(1); + this.access.execute(Level::blockEntityChanged); + } + } + + public boolean hasPayment() { + return !this.beacon.getItem(0).isEmpty(); + } + + public static class PaymentSlot extends Slot { + public PaymentSlot(Container pContainer, int pIndex, int pX, int pY) { + super(pContainer, pIndex, pX, pY); + } + + @Override + public boolean mayPlace(ItemStack pStack) { + return pStack.is(ModTags.Items.VAMPIRE_BEACON_PAYMENT_ITEM); + } + + @Override + public int getMaxStackSize() { + return 1; + } + } +} diff --git a/src/main/java/de/teamlapen/vampirism/inventory/VampirismContainerMenu.java b/src/main/java/de/teamlapen/vampirism/inventory/VampirismContainerMenu.java new file mode 100644 index 0000000000..c2b9d81deb --- /dev/null +++ b/src/main/java/de/teamlapen/vampirism/inventory/VampirismContainerMenu.java @@ -0,0 +1,74 @@ +package de.teamlapen.vampirism.inventory; + +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public abstract class VampirismContainerMenu extends AbstractContainerMenu { + + private final int size; + + protected VampirismContainerMenu(@Nullable MenuType pMenuType, int pContainerId, int size) { + super(pMenuType, pContainerId); + this.size = size; + } + + protected void addPlayerSlots(@NotNull Container playerInventory, int baseX, int baseY) { + int i; + for (i = 0; i < 3; ++i) { + for (int j = 0; j < 9; ++j) { + this.addSlot(new Slot(playerInventory, j + i * 9 + 9, baseX + j * 18, baseY + i * 18)); + } + } + for (i = 0; i < 9; ++i) { + this.addSlot(new Slot(playerInventory, i, baseX + i * 18, baseY + 58)); + } + } + + @Override + public @NotNull ItemStack quickMoveStack(@NotNull Player pPlayer, int index) { + ItemStack result = ItemStack.EMPTY; + Slot slot = this.slots.get(index); + if (slot != null && slot.hasItem()) { + ItemStack slotStack = slot.getItem(); + result = slotStack.copy(); + if (index < size) { + if (!this.moveItemStackTo(slotStack, size, 36 + size, false)) { + return ItemStack.EMPTY; + } + } else if (index >= size && index < 27 + size) { + if (!this.moveItemStackTo(slotStack, 0, size, false)) { + if (slotStack.isEmpty()) { + return ItemStack.EMPTY; + } + } + if (!this.moveItemStackTo(slotStack, 27 + size, 36 + size, false)) { + return ItemStack.EMPTY; + } + } else if (index >= 27 + size && index < 36 + size) { + if (!this.moveItemStackTo(slotStack, 0, 27 + size, false)) { + return ItemStack.EMPTY; + } + } + + if (slotStack.isEmpty()) { + slot.set(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + + if (slotStack.getCount() == result.getCount()) { + return ItemStack.EMPTY; + } + + slot.onTake(pPlayer, slotStack); + } + + return result; + } +} diff --git a/src/main/java/de/teamlapen/vampirism/misc/VampirismCreativeTab.java b/src/main/java/de/teamlapen/vampirism/misc/VampirismCreativeTab.java index 929d969fb7..596361920f 100644 --- a/src/main/java/de/teamlapen/vampirism/misc/VampirismCreativeTab.java +++ b/src/main/java/de/teamlapen/vampirism/misc/VampirismCreativeTab.java @@ -141,6 +141,7 @@ private void addBlocks() { addBlock(FOG_DIFFUSER); addBlock(HUNTER_TABLE); addBlock(SUNSCREEN_BEACON); + addBlock(VAMPIRE_BEACON); addBlock(TOTEM_BASE); addBlock(TOTEM_TOP); addBlock(TOTEM_TOP_CRAFTED); @@ -148,6 +149,7 @@ private void addBlocks() { addBlock(POTION_TABLE); addBlock(MED_CHAIR); addBlock(ALCHEMY_TABLE); + addBlock(VAMPIRE_BEACON); addBuildingBlocks(); addPlantBlocks(); @@ -232,6 +234,8 @@ private void addBuildingBlocks() { addBlock(CASTLE_STAIRS_PURPLE_BRICK); addBlock(CASTLE_SLAB_PURPLE_BRICK); addBlock(CASTLE_BLOCK_PURPLE_BRICK_WALL); + addBlock(BLOOD_INFUSED_IRON_BLOCK); + addBlock(BLOOD_INFUSED_ENHANCED_IRON_BLOCK); } private void addDecorativeBlocks() { diff --git a/src/main/java/de/teamlapen/vampirism/mixin/BeaconBeamSectionyMixin.java b/src/main/java/de/teamlapen/vampirism/mixin/BeaconBeamSectionyMixin.java new file mode 100644 index 0000000000..2710f4008e --- /dev/null +++ b/src/main/java/de/teamlapen/vampirism/mixin/BeaconBeamSectionyMixin.java @@ -0,0 +1,12 @@ +package de.teamlapen.vampirism.mixin; + +import net.minecraft.world.level.block.entity.BeaconBlockEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(BeaconBlockEntity.BeaconBeamSection.class) +public interface BeaconBeamSectionyMixin { + + @Invoker("increaseHeight") + void invokeIncreaseHeight(); +} diff --git a/src/main/java/de/teamlapen/vampirism/mixin/BeaconBlockEntityMixin.java b/src/main/java/de/teamlapen/vampirism/mixin/BeaconBlockEntityMixin.java new file mode 100644 index 0000000000..8ba0f278a1 --- /dev/null +++ b/src/main/java/de/teamlapen/vampirism/mixin/BeaconBlockEntityMixin.java @@ -0,0 +1,19 @@ +package de.teamlapen.vampirism.mixin; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BeaconBlockEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import javax.annotation.Nullable; + +@Mixin(BeaconBlockEntity.class) +public interface BeaconBlockEntityMixin { + + @Invoker("applyEffects") + static void applyEffects(Level pLevel, BlockPos pPos, int pLevels, @Nullable MobEffect pPrimary, @Nullable MobEffect pSecondary) { + throw new IllegalStateException("Mixin was not applied"); + } +} diff --git a/src/main/java/de/teamlapen/vampirism/network/ModPacketDispatcher.java b/src/main/java/de/teamlapen/vampirism/network/ModPacketDispatcher.java index 16c3745c20..41b7de3812 100755 --- a/src/main/java/de/teamlapen/vampirism/network/ModPacketDispatcher.java +++ b/src/main/java/de/teamlapen/vampirism/network/ModPacketDispatcher.java @@ -41,5 +41,6 @@ public void registerPackets() { registerServerBound(ServerboundSelectAmmoTypePacket.class, ServerboundSelectAmmoTypePacket::encode, ServerboundSelectAmmoTypePacket::decode, ServerboundSelectAmmoTypePacket::handle); registerClientBound(ClientboundSundamagePacket.class, ClientboundSundamagePacket::encode, ClientboundSundamagePacket::decode, ClientboundSundamagePacket::handle); registerClientBound(ClientboundBossEventSoundPacket.class, ClientboundBossEventSoundPacket::encode, ClientboundBossEventSoundPacket::decode, ClientboundBossEventSoundPacket::handle); + registerServerBound(ServerboundSetVampireBeaconPacket.class, ServerboundSetVampireBeaconPacket::encode, ServerboundSetVampireBeaconPacket::decode, ServerboundSetVampireBeaconPacket::handle); } } diff --git a/src/main/java/de/teamlapen/vampirism/network/ServerboundSetVampireBeaconPacket.java b/src/main/java/de/teamlapen/vampirism/network/ServerboundSetVampireBeaconPacket.java new file mode 100644 index 0000000000..ebc813864c --- /dev/null +++ b/src/main/java/de/teamlapen/vampirism/network/ServerboundSetVampireBeaconPacket.java @@ -0,0 +1,44 @@ +package de.teamlapen.vampirism.network; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import de.teamlapen.lib.network.IMessage; +import de.teamlapen.vampirism.inventory.VampireBeaconMenu; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.effect.MobEffect; +import net.minecraftforge.network.NetworkEvent; +import net.minecraftforge.registries.ForgeRegistries; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; +import java.util.function.Supplier; + +public record ServerboundSetVampireBeaconPacket(Optional effect, Optional amplifier) implements IMessage.IServerBoundMessage { + + public static final Codec CODEC = RecordCodecBuilder.create(builder -> { + return builder.group( + ForgeRegistries.MOB_EFFECTS.getCodec().optionalFieldOf("effect").forGetter(l -> l.effect), + Codec.INT.optionalFieldOf("amplifier").forGetter(l -> l.amplifier) + ).apply(builder, ServerboundSetVampireBeaconPacket::new); + }); + + static void encode(@NotNull ServerboundSetVampireBeaconPacket msg, @NotNull FriendlyByteBuf buf) { + buf.writeJsonWithCodec(CODEC, msg); + } + + static @NotNull ServerboundSetVampireBeaconPacket decode(@NotNull FriendlyByteBuf buf) { + return buf.readJsonWithCodec(CODEC); + } + + public static void handle(final ServerboundSetVampireBeaconPacket msg, @NotNull Supplier contextSupplier) { + final NetworkEvent.Context ctx = contextSupplier.get(); + ctx.enqueueWork(() -> { + ServerPlayer sender = ctx.getSender(); + if (sender.containerMenu instanceof VampireBeaconMenu beaconMenu && beaconMenu.stillValid(sender)) { + beaconMenu.updateEffects(msg.effect, msg.amplifier); + } + }); + ctx.setPacketHandled(true); + } +} diff --git a/src/main/resources/assets/vampirism/lang/en_us.json b/src/main/resources/assets/vampirism/lang/en_us.json index 70dcfa2209..77e355e869 100644 --- a/src/main/resources/assets/vampirism/lang/en_us.json +++ b/src/main/resources/assets/vampirism/lang/en_us.json @@ -618,6 +618,7 @@ "text.vampirism.taskmaster.no_tasks": "No tasks available at the moment", "text.vampirism.taskmaster.no_tasks_unique": "There are no task left", "text.vampirism.oblivion_potion.resets_skills": "Resets skills on consume", + "container.vampirism.vampire_beacon.power": "Power", "__comment": "biome", "biome.vampirism.vampire_forest": "Vampire Forest", "biome.vampirism.vampire_forest_hills": "Vampire Forest Hills", @@ -783,6 +784,9 @@ "block.vampirism.mother": "Ancient Remains", "block.vampirism.mother_trophy": "Ancient Trophy", "block.vampirism.fog_diffuser": "Fog Diffuser", + "block.vampirism.blood_infused_iron_block": "Blood-Infused Iron Block", + "block.vampirism.blood_infused_enhanced_iron_block": "Enhanced Blood-Infused Iron Block", + "block.vampirism.vampire_beacon": "Ancient Beacon", "__comment": "items", "item.vampirism.hunter_intel": "Hunter Intel", "item.vampirism.pure_blood": "Pure Blood", diff --git a/src/main/resources/assets/vampirism/textures/block/blood_infused_enhanced_iron_block.png b/src/main/resources/assets/vampirism/textures/block/blood_infused_enhanced_iron_block.png new file mode 100755 index 0000000000000000000000000000000000000000..662c0a99daa9d910826c3f8c03030c3f9ea50459 GIT binary patch literal 1311 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBDAAG{;hE;^%b*2hb1<+n z3NbJPS&Tr)z$nE4G7ZRL@M4sPvx68lplX;H7}_%#SfFa6fHVkr05M1pgl1mAh%j*h z6I`{x0%imor0saV%ts)_S>O>_%)r1c48n{Iv*t)JFfg6S42dX-@b$4u&d=3LOvz75 z)vL%Y0O?||sjvbvb5lza6)JLb@`|l0Y?Z(&tblBgu)dN4SV>8?tx|+H?jfSfFg)+ zA4CH}eP~{0i5*M}nlQSq2!uSs8e~Cq4gN)$slb2)yUP&jEMzex^&sC_1!PvF=0vz; z=BDNqgZyG>W}}Z)0$rnXeolT-a6w{nsvXcCuofgCbk$&MB5_%RBmvcEqYsK}q_~G9 zEU+jrW!Z7r=)+T~9hY78;(5RvV(97O7-Au~bh4p0v!g)k{g($78M#dtBpf+*%4tzT z`tpDLe^viEd#Y-5Em$Dnlelo{x$Vz)uaQ<{S$@OZ+DuXvzk|0KYm)7 zGbvhlkB$As+do2I|Mh)zvc6{D<#*ra9XNOFQdIn`KMyoEJQL}fo3VuB{z-+fq^*iZ8o_&k*y;~9__f9?P<<=?o_BDG_ zgKoXgIe+X-piJNWR!_Z_EFxc(WR)=mHEluMo_l*boFyt=akR{ E0Ezde4FCWD literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/vampirism/textures/block/blood_infused_iron_block.png b/src/main/resources/assets/vampirism/textures/block/blood_infused_iron_block.png new file mode 100755 index 0000000000000000000000000000000000000000..959f19e4d9b90271d891f368f00a928db5788005 GIT binary patch literal 385 zcmV-{0e=38P)Tk}*reP!xr~U~rN^gMj?G)TxCym(QwU z46n~U#;(g@yA8nDb#VfZvttV<@C1rY%k1DsSsjdQ)TUk%fE9uhc*U?E*#K)*xl>6E ztzPyfOcPKqj^OE`R~**K&tH@+?3}>Msctg-cxU%JEl5M>jmF*qeq=LWPKt~2e!iTL zeEo+7Ln~8o0*~vP?#fa{3*s_!3rgQ2y}i6&^D7S5A&mcEVVZ!UWfi0p5iq+$x2r3kQ+xM~Gk6lB|ChQ`cF3B3gkPf_k@9yTA>_^^v z$!_8Z;iEu`d^pe%X{02iG6N%(nsy>eF``mSDi{i-h(Zx-wG^s!B1J7d@9k!jjLvj2 zQ~%5E+`Z?Wd(Q8k`#a~J)H1@rCdm@*lD3$NYeU^;}yrb=;xP(dH*Xo}HGrfqZY;CJSU*pQX!# zxf2Eh@^qN@!VuS`_WCWz>Sv1f^?;-z56|70E5P}YcLWqxm285WmfA+Zs`Lgy1txjaYa-ucGTCFS?cD4pY(I^ciy zayNc4u+P87&{b1^s{hg;SwFa?r_XNKpOafsuS9p>-TNg+Pz`h^}{_U z@Hba~u>6&mKks`y_xkJ^&+Yh8)7(=J7CpOQ%Ae2eJ#pZ9ui z*KPh~g5LSz6IYJEv*(g;^7ZVC_LF%VlB<(#CkGu@^Vco*R;@qYaWwBB_G!_d(9`Gb zGw&L@Ht@nz-sAb}I({6?J$Bc?{I&C)<##?B*!bC3i=UqH_L9z1^Edwb%3Dik{l4LW zV|9BRPZk#($ex-d{Lx>LQxNQZtY^FD0@_WJ{#O@&|Hwmi{L zaQ8judi+^`TYlgln-}g1&#XTk`QnQ+zxmlcb1!_aZ}9AY9-FlN-^GXCKixfV?oDgF z>AlmJToMLJ)L>E!)GD>U1uP$n7&##pM8;$!t|m<9EJ?;Wz5yv% z5QW943%~mEVH^_$7rw~iqkQo)R4;nkBvjp28Q|L*c!z+OJY;YtSpbM2g~O7O#;D9D zUATtJf~=}Z9Mepc1{YonbyOCU5N0--jTBLy6k8blAp_==gb-Whu1G_`lMAm`lsHS0 ziA2JfFd1V~n4}#J2T3s`!w_IW$gNR@OA=AJNQFpYxRK0DVq6hpQB1|;g0W`Bh2yY} z4aXOW`+OPrsGMd2_#l&9oTQBu8HtdiJ!GZ41whgPeWQmQXpJMX3dyl%iAUuvD5?~V zh7kCSf4o_0)Q%(YBx*zvFqL6fdd!yUjmvnb6okb{T=N35$5<+2XoRdWv8gNCaYhFM z?it)M*28DljKRw1W8E>nSq;zYcH!#&tPtZxfz?El&4hR%#1IZHWF^cD$buMakf4~5gD@i$Bpd>=5JApj<`{;zS*`X_ z5I>Yes7kJJbW|#o08mH>nnE-}gkU!Z2{UaM2nS<!QX0?*h9)aq73`DYO2(Yszyzzr_^Jk zs9hxt(=G+e@u?%oTniGkH~}lQ#Mg7tFoN!pF4tkb_zk5%(+m>~G8Ex3*&u&b&Ornj znkJBq6M~ExSrL^gg$%kJ3n>XsLZxBg5x9c#)c!(Y_iBl{Z)_}ydZcCn2qS2UFww(= znbU-k=>wB$&loMVZ zH9^<77#NrFM0HKjH7*9mWjs+`|2Mh}Bd=2^3jYNq;AJVxxxNBkv?d21ndjEsRKL3p z?b!;NTjHL@vQGD%e0At`J3429GFS2X%5y(56i#EU@hca<3#v0-cWJ=#=bZhZ~A zeN9*_dj9?H@V|O?zR}ye@Mz%+&0W1aJP+SE^VQn-^q1N`eZ6pZPW!tbymU(^_UN+y z@S(1zh0AXH>|;5!lP^CzZKz^*eku0i3X?oFk^T4T^N~$VV%D|1er;gie0N36DMuMQow^{yIlH!oV9-!XH`AKu!wf6hV+U3^3r zx_eV-<;IT3@!k6QN$+#)yPI82E9<)a+g8-B^!;<%U!GZNtZwxx;RkEqT(ojdM^{rx e-MJeDhxIk};*0HPw+_G=b>8wy_x^{Mt@ zA1`-ZovAty1nIIpT$ex)28b94rv-)p=|KS)>XGGa0h|3TgaZ%25`$G6pXLj@=s zgf1>VY!?^2L@E{tLlFpy&Wca7_c-fgw9$L1+q}uzw9PodL9fU|gdK%CZU^;OZ}k7h zb5)-)S!Sf;(qS$_Z%9udAoo@Us&Sck}slf;;}mcIyi;+ zXNcaM!?YZ|ET>LKWQUiuS}ZV0@|e6d!*7rBkx^Vzlf6b<`PQ!asSxSd(obv ze0i~Jcs6{3ql1oJGz$QPA#xZW9TqB*v7+q>YFrkOQ8kHxSDVP!*b|n6I&u+95j@?J zZb>G(MGGUT1P2|wos=(NEpc5q0s)@v2_bU1ghe7nMMYUg(JaN%U=qc~#)d?ulBiT7 zupr7}L~=NqD3Z-UA%-zr5gAV^l*ol*5gx^ax#9@9J%Iq`@uTsDNjRJ_c#&*`1;7U> z8kUeKmSj>`7-_tROzsv5Kt=-kOAncEj07PqL1f|xDGzarL`3o#<01IGF@H&fG*q1q zpGQJMkuYE?1FKR#SQ72HF%Oi2U}2a_ zxI7wj928q5lfxn&fYeT2NR4!4#gULiXOht$`Gy#)H;W5cPgfAe&e6kvf&tokV zOT%EWox(6U7$HeS!RiT=aF(+V+nzwR95z*Jd_rNl065qaJcXi&==Y|+!Z2j197frs zFl?-u)(n~rnaN<1t%hS(d;23&8K^`QQ+;---O+7ffn)%&Fj}VoK&=P4uw0}FEEh|C z#o|zV0t%r%b;qVTpq==z9Cn4}2ml>BhkZxSVGA;aMIH_xh2x0%LP5;`vPPQ+ZwKtb zmU{?gVEq`iYPh48BH_bN!;hgtbt~cV>ZV}9yx|mNa3sQ4#|f~8r+6W-C>Q~!$4I%3 z>VQ#< zXCZ0qFdX3w#QRTPBYW{rE`i5?UgVSb{Y=+qx;}}4Pcr^oU7zXtBnCdo_;Ypr-{{hL z|2l<;z<)te;AN@fRR4VNqNT-M?CuJw&`(Zjz7l9AN<3D`AZXH8=#7CgvrK?eTh8XV zX}9Z`Pu7}7Yo7&P@3mdnuFk&E&CgpXApvhO=U=tnOi}7Qt&eOlEFlv2<$jScl^UUw ztmVba+2A#6>sEi$XFkpAk0r;3*zzwJZffwsZCv0Ku2pKv_5Nnj)_;{OPMUOj`oz`b zSxwVfZ{sdpToF~=-*Km1vntCV@u#Sv#8y?QQuXg$st)ap{Of1R;PO_c3NAQa-k2GK z^~xCVNiHr3E;AHw*UGu|Ja$gdmkcITIdiX9u)t#7{(HvWnFD@)F;PLW!M)u1@h!%_ ze!JehiRd)*boTRebGy5tTJQMrva(gzQevM7%ii@ozjepiIT2z}hv4yc$$+l5wuNGLbmvyvn2y1s zuD;Y&bsO7P)vOJ?%`S^zRVSL6VS@~gWZ5cbo*uYZ*Hs-{`r9*yn!rSr*U;-%r1VEi zSKN%x*d=SdTzbc``&m+%W->HC)4TlkElTp=Y7? zx^~@q-a~P6M`Oz~8OuoJ>1X7#dmkqhv<~uC#rGFxm41uGRdBO=NzeB72C}-}t+Bvh zgTl9UdyrFcF3{H*YK%vfcr#-ME$p9mWHwmmeJCR_9ksSI*^quipPvk3!Gu`rX;sd0 zIvY*K`9r$xz}`u-Zs4r4HOX0DF+0209@t3QiVU5gtllG7eTCcW?#?3R%wT2Q4}on- zrH)p?)Mxzrs>lhI5p$StTFb~f|3oW?@fikqq%S%U_DS;rUeJ8G<( z4Aq~2toxHDD^xhF%a5LMU#ZvtmBC=t7-Dj^0QAtddmnegjxE0==!dLK{iV6NnYttV zOM5S6!a(tf0Df_0UU46x2y&j21FwTBh#8?UOYl{qX~$*)XlHo#?uPP5ej zoW4c(dFuXydlZoq7+w<})T~){w@N$crIzO(1w~aq$<0bMG{=|!NBQC)AE-pb^t`pM zU|G=I4d1WBppc3xqAECS9{X_P>Ng$5`)&nlWOVA}`1$S1#mE?!Ocnj{xn)IA+pks) z;-1H}ih0G6&zpUxT_yk8A_`u+cJ0##J+Y+&JyAsm99~@B)7jQk-p9UFE?iVd&p6sZ z&lpfTbAa^%T)7i%IYpwDF48t$xE@G3Cww<#mMH$BrJ^*vVtZa? zQw#g*-dDPFu!``2X?^szr|*=n&#x_SW%u=SUNF;#>YEgc6@)p7yX^WRhMqWP#?z{M z(^BP|<~ZVfnsusdh=mxXJ+E- zeGsm~E`VdPtY>yiVO^ohz;kFZK>-=%?eQ;OJKbcJ?lq;}U|z`}(Csu?Z_!Zl!trsg zgMkyYXor)13;ed^UQ~U)CVjUzX3^$~owZfFlV|r2wLU$Z{gtHNK+#1Yr%+esFv;KHX#IZyM