diff --git a/src/main/java/at/petrak/hexcasting/api/client/ScryingLensOverlayRegistry.java b/src/main/java/at/petrak/hexcasting/api/client/ScryingLensOverlayRegistry.java index b042bee2..85a5e58c 100644 --- a/src/main/java/at/petrak/hexcasting/api/client/ScryingLensOverlayRegistry.java +++ b/src/main/java/at/petrak/hexcasting/api/client/ScryingLensOverlayRegistry.java @@ -1,6 +1,7 @@ package at.petrak.hexcasting.api.client; import com.mojang.datafixers.util.Pair; +import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; @@ -11,8 +12,8 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; import java.util.List; +import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -22,7 +23,9 @@ import java.util.concurrent.ConcurrentMap; * Client-side only. */ public class ScryingLensOverlayRegistry { - private static final ConcurrentMap BLOCK_LOOKUP = new ConcurrentHashMap<>(); + private static final ConcurrentMap ID_LOOKUP = new ConcurrentHashMap<>(); + // vectors are thread-safe! + private static final List> PREDICATE_LOOKUP = new Vector<>(); /** * Add the block to display things when the player is holding a lens and looking at it. @@ -39,37 +42,40 @@ public class ScryingLensOverlayRegistry { * @throws IllegalArgumentException if the block ID is already registered. */ public static void addDisplayer(ResourceLocation blockID, Displayer displayer) { - if (BLOCK_LOOKUP.containsKey(blockID)) { + if (ID_LOOKUP.containsKey(blockID)) { throw new IllegalArgumentException("Already have a displayer for " + blockID); } - BLOCK_LOOKUP.put(blockID, displayer); + ID_LOOKUP.put(blockID, displayer); } /** - * Add the block to display things when the player is holding a lens and looking at it. + * Display things when the player is holding a lens and looking at some block via a predicate. *

- * If the block ID is already registered, append this {@link Displayer}'s output after whatever - * was previously there. - *

- * Returns if there was already something in the map (and this is appending). + * These have a lower priority than the standard ID-based displays, so if an ID and predicate both match, + * this won't be displayed. */ - public static boolean appendDisplayer(ResourceLocation blockID, Displayer displayer) { - var extant = BLOCK_LOOKUP.getOrDefault(blockID, null); - if (extant == null) { - BLOCK_LOOKUP.put(blockID, displayer); - return false; - } else { - var andThen = new AndThen(extant, displayer); - BLOCK_LOOKUP.put(blockID, andThen); - return true; - } + public static void addPredicateDisplayer(Predicate predicate, Displayer displayer) { + PREDICATE_LOOKUP.add(new Pair<>(predicate, displayer)); } /** * Internal use only. */ - public static @Nullable Displayer getDisplayer(Block block) { - return BLOCK_LOOKUP.getOrDefault(block.getRegistryName(), null); + public static @Nullable List> getLines(BlockState state, BlockPos pos, + LocalPlayer observer, ClientLevel world, + InteractionHand lensHand) { + var idLookedup = ID_LOOKUP.get(state.getBlock().getRegistryName()); + if (idLookedup != null) { + return idLookedup.getLines(state, pos, observer, world, lensHand); + } + + for (var pair : PREDICATE_LOOKUP) { + if (pair.getFirst().test(state, pos, observer, world, lensHand)) { + return pair.getSecond().getLines(state, pos, observer, world, lensHand); + } + } + + return null; } /** @@ -80,17 +86,15 @@ public class ScryingLensOverlayRegistry { @FunctionalInterface public interface Displayer { List> getLines(BlockState state, BlockPos pos, LocalPlayer observer, + ClientLevel world, InteractionHand lensHand); } - private record AndThen(Displayer first, Displayer then) implements Displayer { - @Override - public List> getLines(BlockState state, BlockPos pos, - LocalPlayer observer, InteractionHand lensHand) { - var lines = this.first.getLines(state, pos, observer, lensHand); - var mutableLines = new ArrayList<>(lines); - mutableLines.addAll(this.then.getLines(state, pos, observer, lensHand)); - return mutableLines; - } + /** + * Predicate for matching on a block state. + */ + @FunctionalInterface + public interface Predicate { + boolean test(BlockState state, BlockPos pos, LocalPlayer observer, ClientLevel world, InteractionHand lensHand); } } diff --git a/src/main/java/at/petrak/hexcasting/client/HexAdditionalRenderers.java b/src/main/java/at/petrak/hexcasting/client/HexAdditionalRenderers.java index 66adfe16..befdc015 100644 --- a/src/main/java/at/petrak/hexcasting/client/HexAdditionalRenderers.java +++ b/src/main/java/at/petrak/hexcasting/client/HexAdditionalRenderers.java @@ -175,10 +175,8 @@ public class HexAdditionalRenderers { var pos = bhr.getBlockPos(); var bs = mc.level.getBlockState(pos); - var displayer = ScryingLensOverlayRegistry.getDisplayer(bs.getBlock()); - if (displayer != null) { - var lines = displayer.getLines(bs, pos, mc.player, lensHand); - + var lines = ScryingLensOverlayRegistry.getLines(bs, pos, mc.player, mc.level, lensHand); + if (lines != null) { var window = mc.getWindow(); var lineSpacing = 15f; var totalHeight = lineSpacing * lines.size(); diff --git a/src/main/java/at/petrak/hexcasting/client/RegisterClientStuff.java b/src/main/java/at/petrak/hexcasting/client/RegisterClientStuff.java index 91a63a16..cf29b971 100644 --- a/src/main/java/at/petrak/hexcasting/client/RegisterClientStuff.java +++ b/src/main/java/at/petrak/hexcasting/client/RegisterClientStuff.java @@ -6,6 +6,8 @@ import at.petrak.hexcasting.api.spell.SpellDatum; import at.petrak.hexcasting.client.particles.ConjureParticle; import at.petrak.hexcasting.common.blocks.HexBlocks; import at.petrak.hexcasting.common.blocks.circles.BlockEntitySlate; +import at.petrak.hexcasting.common.blocks.circles.impetuses.BlockAbstractImpetus; +import at.petrak.hexcasting.common.blocks.circles.impetuses.BlockEntityAbstractImpetus; import at.petrak.hexcasting.common.items.HexItems; import at.petrak.hexcasting.common.items.ItemFocus; import at.petrak.hexcasting.common.items.ItemScroll; @@ -20,6 +22,7 @@ import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.item.ItemProperties; import net.minecraft.network.chat.TextComponent; +import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; @@ -104,16 +107,25 @@ public class RegisterClientStuff { } private static void addScryingLensStuff() { - ScryingLensOverlayRegistry.addDisplayer(Blocks.GRASS_BLOCK, (state, pos, observer, lensHand) -> List.of( - new Pair<>(new ItemStack(Blocks.GRASS_BLOCK), new TextComponent("Holy hell that's grass")), - new Pair<>(new ItemStack(Items.COMPASS), new TextComponent("Position: " + pos.toShortString())) - )); - ScryingLensOverlayRegistry.addDisplayer(Blocks.REDSTONE_WIRE, (state, pos, observer, lensHand) -> List.of( - new Pair<>( - new ItemStack(Items.REDSTONE), - new TextComponent(String.valueOf(state.getValue(BlockStateProperties.POWER))) - .withStyle(ChatFormatting.RED)) - )); + ScryingLensOverlayRegistry.addPredicateDisplayer( + (state, pos, observer, world, lensHand) -> state.getBlock() instanceof BlockAbstractImpetus, + (state, pos, observer, world, lensHand) -> { + if (world.getBlockEntity(pos) instanceof BlockEntityAbstractImpetus beai) { + var dustCount = (float) beai.getMana() / (float) HexConfig.dustManaAmount.get(); + var tc = new TranslatableComponent("hexcasting.tooltip.lens.impetus.mana", + String.format("%.2f", dustCount)); + return List.of(new Pair<>(new ItemStack(HexItems.AMETHYST_DUST.get()), tc)); + } else { + return List.of(); + } + }); + ScryingLensOverlayRegistry.addDisplayer(Blocks.REDSTONE_WIRE, + (state, pos, observer, world, lensHand) -> List.of( + new Pair<>( + new ItemStack(Items.REDSTONE), + new TextComponent(String.valueOf(state.getValue(BlockStateProperties.POWER))) + .withStyle(ChatFormatting.RED)) + )); } @SubscribeEvent(priority = EventPriority.LOWEST) diff --git a/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockSlate.java b/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockSlate.java index 6cc28269..b9416cbc 100644 --- a/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockSlate.java +++ b/src/main/java/at/petrak/hexcasting/common/blocks/circles/BlockSlate.java @@ -107,6 +107,4 @@ public class BlockSlate extends BlockCircleComponent implements EntityBlock { pCurrentPos) ? Blocks.AIR.defaultBlockState() : super.updateShape(pState, pFacing, pFacingState, pLevel, pCurrentPos, pFacingPos); } - - } diff --git a/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityAbstractImpetus.java b/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityAbstractImpetus.java index 9d31c2ed..87e81e3a 100644 --- a/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityAbstractImpetus.java +++ b/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityAbstractImpetus.java @@ -25,6 +25,7 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; @@ -70,6 +71,10 @@ public abstract class BlockEntityAbstractImpetus extends ModBlockEntity implemen abstract public boolean playerAlwaysInRange(); + public int getMana() { + return this.mana; + } + protected void activateSpellCircle(ServerPlayer activator) { if (this.nextBlock != null) { return; @@ -84,6 +89,7 @@ public abstract class BlockEntityAbstractImpetus extends ModBlockEntity implemen this.level.setBlockAndUpdate(this.getBlockPos(), this.getBlockState().setValue(BlockAbstractImpetus.ENERGIZED, true)); + this.setChanged(); } protected void stepCircle() { @@ -369,6 +375,8 @@ public abstract class BlockEntityAbstractImpetus extends ModBlockEntity implemen if (manamount != null) { if (!simulate) { BlockEntityAbstractImpetus.this.mana += manamount; + BlockEntityAbstractImpetus.this.setChanged(); + level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), Block.UPDATE_CLIENTS); } return ItemStack.EMPTY.copy(); } diff --git a/src/main/java/at/petrak/hexcasting/common/items/ItemSlate.java b/src/main/java/at/petrak/hexcasting/common/items/ItemSlate.java index 1da50238..383c9ddb 100644 --- a/src/main/java/at/petrak/hexcasting/common/items/ItemSlate.java +++ b/src/main/java/at/petrak/hexcasting/common/items/ItemSlate.java @@ -18,7 +18,7 @@ public class ItemSlate extends BlockItem { @Override public Component getName(ItemStack pStack) { - var key = HexMod.MOD_ID + ".block.slate." + (hasPattern(pStack) ? "written" : "blank"); + var key = "block." + HexMod.MOD_ID + ".slate." + (hasPattern(pStack) ? "written" : "blank"); return new TranslatableComponent(key); } diff --git a/src/main/resources/assets/hexcasting/lang/en_us.json b/src/main/resources/assets/hexcasting/lang/en_us.json index fc3fd615..ed36fb7b 100644 --- a/src/main/resources/assets/hexcasting/lang/en_us.json +++ b/src/main/resources/assets/hexcasting/lang/en_us.json @@ -48,14 +48,16 @@ "item.hexcasting.pride_colorizer_13": "Aroace Pigment", "item.hexcasting.uuid_colorizer": "Soulglimmer Pigment", "block.hexcasting.conjured": "Conjured Block", - "hexcasting.block.slate.blank": "Blank Slate", - "hexcasting.block.slate.written": "Patterned Slate", + "block.hexcasting.slate.blank": "Blank Slate", + "block.hexcasting.slate.written": "Patterned Slate", "itemGroup.hexcasting": "Hexcasting", "hexcasting.tooltip.spellbook.page": "§7Selected Page §a§l%d§7/§a§l%d§r", "hexcasting.tooltip.abacus": "§a§l%d§r", "hexcasting.tooltip.abacus.reset": "Reset to 0", "hexcasting.tooltip.abacus.reset.nice": "nice", + "hexcasting.tooltip.lens.impetus.mana": "%s Dusts", + "hexcasting.tooltip.lens.pattern.invalid": "Invalid Pattern", "hexcasting.spelldata.onitem": "§7Contains: §r%s", "hexcasting.spelldata.entity.whoknows": "An Entity (this should only show up if this was stored before the 0.5.0 update, use Scribe's Reflection, Scribe's Gambit to fix)",