From dc0161b6defe38537e076c18484d6f96d6ae02e6 Mon Sep 17 00:00:00 2001 From: itsmeow Date: Sun, 22 Nov 2020 04:17:13 -0500 Subject: [PATCH] Finish up HG summoning for HoF and add tooltip --- .../whisperwoods/block/BlockHandOfFate.java | 38 ++++++++++++ .../renderer/tile/RenderTileHandOfFate.java | 21 ++++--- .../whisperwoods/network/HOFEffectPacket.java | 42 +++++++++++-- .../tileentity/TileEntityHandOfFate.java | 59 +++++++++++++++---- .../whisperwoods/util/MutablePair.java | 27 +++++++++ .../whisperwoods/util/WWClientTaskQueue.java | 36 +++++++++++ .../whisperwoods/util/WWServerTaskQueue.java | 35 +++++++++++ .../assets/whisperwoods/lang/en_us.json | 6 ++ 8 files changed, 243 insertions(+), 21 deletions(-) create mode 100644 src/main/java/dev/itsmeow/whisperwoods/util/MutablePair.java create mode 100644 src/main/java/dev/itsmeow/whisperwoods/util/WWClientTaskQueue.java create mode 100644 src/main/java/dev/itsmeow/whisperwoods/util/WWServerTaskQueue.java diff --git a/src/main/java/dev/itsmeow/whisperwoods/block/BlockHandOfFate.java b/src/main/java/dev/itsmeow/whisperwoods/block/BlockHandOfFate.java index ec5f275..16d1eff 100644 --- a/src/main/java/dev/itsmeow/whisperwoods/block/BlockHandOfFate.java +++ b/src/main/java/dev/itsmeow/whisperwoods/block/BlockHandOfFate.java @@ -1,11 +1,17 @@ package dev.itsmeow.whisperwoods.block; +import java.util.List; + import javax.annotation.Nullable; import dev.itsmeow.whisperwoods.tileentity.TileEntityHandOfFate; +import dev.itsmeow.whisperwoods.tileentity.TileEntityHandOfFate.HOFRecipe; import net.minecraft.block.Block; import net.minecraft.block.BlockRenderType; import net.minecraft.block.BlockState; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.fluid.FluidState; import net.minecraft.fluid.Fluids; @@ -27,9 +33,16 @@ import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShapes; +import net.minecraft.util.text.IFormattableTextComponent; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.Style; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorldReader; import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; public class BlockHandOfFate extends Block { @@ -117,6 +130,31 @@ public TileEntity createTileEntity(BlockState state, IBlockReader worldIn) { return new TileEntityHandOfFate(); } + @OnlyIn(Dist.CLIENT) + @Override + public void addInformation(ItemStack stack, IBlockReader worldIn, List tooltip, ITooltipFlag flagIn) { + super.addInformation(stack, worldIn, tooltip, flagIn); + Style gIS = Style.EMPTY.applyFormatting(TextFormatting.GRAY).setItalic(true); + String tooltipPrefix = "block.whisperwoods.hand_of_fate.tooltip."; + String recipePrefix = tooltipPrefix + "recipe."; + if(Screen.hasShiftDown()) { + tooltip.add(new TranslationTextComponent(tooltipPrefix + "recipehint").setStyle(gIS)); + for(String recipeKey : TileEntityHandOfFate.RECIPES.keySet()) { + HOFRecipe recipe = TileEntityHandOfFate.RECIPES.get(recipeKey); + IFormattableTextComponent t = new TranslationTextComponent(recipePrefix + recipeKey) + .setStyle(Style.EMPTY.applyFormatting(recipe.getColor()).setBold(recipe.isBold())) + .appendString(": ") + .append(new TranslationTextComponent(recipe.getFirst().getTranslationKey()).setStyle(Style.EMPTY.applyFormatting(TextFormatting.WHITE).setBold(false))); + if(I18n.hasKey(recipePrefix + recipeKey + ".hint")) { + t.appendString(" ").append(new TranslationTextComponent(recipePrefix + recipeKey + ".hint").setStyle(Style.EMPTY.applyFormatting(TextFormatting.GRAY).setBold(false))); + } + tooltip.add(t); + } + } else { + tooltip.add(new TranslationTextComponent(tooltipPrefix + "shiftdown").setStyle(gIS)); + } + } + public enum Orientation implements IStringSerializable { SOUTH(Direction.SOUTH), SOUTHWEST(Direction.SOUTH, Direction.WEST), diff --git a/src/main/java/dev/itsmeow/whisperwoods/client/renderer/tile/RenderTileHandOfFate.java b/src/main/java/dev/itsmeow/whisperwoods/client/renderer/tile/RenderTileHandOfFate.java index 071e72a..30f2f8a 100644 --- a/src/main/java/dev/itsmeow/whisperwoods/client/renderer/tile/RenderTileHandOfFate.java +++ b/src/main/java/dev/itsmeow/whisperwoods/client/renderer/tile/RenderTileHandOfFate.java @@ -21,6 +21,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.particles.ParticleTypes; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3f; public class RenderTileHandOfFate extends TileEntityRenderer { @@ -55,16 +56,22 @@ public void render(TileEntityHandOfFate te, float partialTicks, MatrixStack stac } } stack.pop(); - Item display = te.getRecipeContainer().getDisplayItem(); + Item display = te.getDisplayItem(); if(display != null) { stack.push(); - stack.translate(0.5F, 2F, 0.5F); - stack.rotate(Vector3f.YP.rotationDegrees(rotation + (rot.getHorizontalAngle() % 90F == 0 ? 0F : 90F))); - stack.scale(0.25F, 0.25F, 0.25F); - if(istack == null || istack.getItem() != display) { - istack = new ItemStack(display); + { + stack.translate(0.5F, 1.5F, 0.5F); + @SuppressWarnings("resource") + float y = MathHelper.sin((float) Minecraft.getInstance().world.getGameTime() * 0.05F) / 8F; + stack.translate(0F, MathHelper.lerp(partialTicks, te.lastAnimationY, y), 0F); + te.lastAnimationY = y; + stack.rotate(Vector3f.YP.rotationDegrees(rotation + (rot.getHorizontalAngle() % 90F == 0 ? 0F : 90F))); + stack.scale(0.25F, 0.25F, 0.25F); + if(istack == null || istack.getItem() != display) { + istack = new ItemStack(display); + } + Minecraft.getInstance().getItemRenderer().renderItem(istack, TransformType.NONE, combinedLightIn, combinedOverlayIn, stack, bufferIn); } - Minecraft.getInstance().getItemRenderer().renderItem(istack, TransformType.NONE, combinedLightIn, combinedOverlayIn, stack, bufferIn); stack.pop(); } } diff --git a/src/main/java/dev/itsmeow/whisperwoods/network/HOFEffectPacket.java b/src/main/java/dev/itsmeow/whisperwoods/network/HOFEffectPacket.java index c17596d..898aa2a 100644 --- a/src/main/java/dev/itsmeow/whisperwoods/network/HOFEffectPacket.java +++ b/src/main/java/dev/itsmeow/whisperwoods/network/HOFEffectPacket.java @@ -3,23 +3,29 @@ import java.util.function.Supplier; import dev.itsmeow.whisperwoods.particle.WispParticleData; +import dev.itsmeow.whisperwoods.util.WWClientTaskQueue; import net.minecraft.client.Minecraft; import net.minecraft.network.PacketBuffer; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvents; import net.minecraft.util.math.vector.Vector3f; import net.minecraftforge.fml.network.NetworkDirection; import net.minecraftforge.fml.network.NetworkEvent; public class HOFEffectPacket { + public HOFEffectType type; public Vector3f pos; public int color; - public HOFEffectPacket(Vector3f pos, int color) { + public HOFEffectPacket(HOFEffectType type, Vector3f pos, int color) { + this.type = type; this.pos = pos; this.color = color; } public static void encode(HOFEffectPacket pkt, PacketBuffer buf) { + buf.writeInt(pkt.type.ordinal()); buf.writeFloat(pkt.pos.getX()); buf.writeFloat(pkt.pos.getY()); buf.writeFloat(pkt.pos.getZ()); @@ -27,7 +33,11 @@ public static void encode(HOFEffectPacket pkt, PacketBuffer buf) { } public static HOFEffectPacket decode(PacketBuffer buf) { - return new HOFEffectPacket(new Vector3f(buf.readFloat(), buf.readFloat(), buf.readFloat()), buf.readInt()); + int i = buf.readInt(); + if(i < 0 || i >= HOFEffectType.values().length) { + return null; + } + return new HOFEffectPacket(HOFEffectType.values()[i], new Vector3f(buf.readFloat(), buf.readFloat(), buf.readFloat()), buf.readInt()); } @SuppressWarnings("resource") @@ -35,7 +45,8 @@ public static void handle(HOFEffectPacket msg, Supplier ct if(ctx.get().getDirection() != NetworkDirection.PLAY_TO_CLIENT) return; ctx.get().enqueueWork(() -> { - if(Minecraft.getInstance().world != null) { + if(Minecraft.getInstance().world != null && msg != null) { + HOFEffectType type = msg.type; Vector3f pos = msg.pos; int color = msg.color; float r = (color >> 16) & 0xFF; @@ -45,13 +56,36 @@ public static void handle(HOFEffectPacket msg, Supplier ct final int amt = 90; final float angle = 360F / (float) amt; final float speed = 0.5F; + final WispParticleData data = new WispParticleData(r, g, b, 1); for(int i = 0; i < amt; i++) { float pAngle = (float) Math.toRadians(angle * (float) i); - Minecraft.getInstance().world.addParticle(new WispParticleData(r, g, b, 1), pos.getX(), pos.getY(), pos.getZ(), speed * Math.cos(pAngle), 0F, speed * Math.sin(pAngle)); + Minecraft.getInstance().world.addParticle(data, pos.getX(), pos.getY(), pos.getZ(), speed * Math.cos(pAngle), 0F, speed * Math.sin(pAngle)); + } + if(type == HOFEffectType.HIRSCHGEIST) { + WWClientTaskQueue.schedule(21, () -> { + for(int i = 0; i < amt; i++) { + float pAngle = (float) Math.toRadians(angle * (float) i); + Minecraft.getInstance().world.addParticle(data, pos.getX() + 16 * speed * Math.cos(pAngle), pos.getY(), pos.getZ() + 16 * speed * Math.sin(pAngle), -speed * Math.cos(pAngle), 0F, -speed * Math.sin(pAngle)); + } + WWClientTaskQueue.schedule(25, () -> { + Minecraft.getInstance().world.playSound(pos.getX(), pos.getY(), pos.getZ(), SoundEvents.ENTITY_RAVAGER_ROAR, SoundCategory.BLOCKS, 1F, 0.25F, false); + final WispParticleData data2 = new WispParticleData(r, g, b, 0.25F); + for(int i = 0; i < 500; i++) { + float xOff = (float) ((Math.random() - 0.5F) * 5F); + float yOff = (float) (Math.random() * 2.5F); + float zOff = (float) ((Math.random() - 0.5F) * 5F); + Minecraft.getInstance().world.addParticle(data2, pos.getX() + xOff, Math.floor(pos.getY()) - 1F + yOff, pos.getZ() + zOff, xOff / 16F, yOff / 16F, zOff / 16F); + } + }); + }); } } }); ctx.get().setPacketHandled(true); } + public static enum HOFEffectType { + CIRCLE, + HIRSCHGEIST + } } diff --git a/src/main/java/dev/itsmeow/whisperwoods/tileentity/TileEntityHandOfFate.java b/src/main/java/dev/itsmeow/whisperwoods/tileentity/TileEntityHandOfFate.java index ec97752..59d38e9 100644 --- a/src/main/java/dev/itsmeow/whisperwoods/tileentity/TileEntityHandOfFate.java +++ b/src/main/java/dev/itsmeow/whisperwoods/tileentity/TileEntityHandOfFate.java @@ -17,7 +17,9 @@ import dev.itsmeow.whisperwoods.init.ModEntities; import dev.itsmeow.whisperwoods.init.ModTileEntities; import dev.itsmeow.whisperwoods.network.HOFEffectPacket; +import dev.itsmeow.whisperwoods.network.HOFEffectPacket.HOFEffectType; import dev.itsmeow.whisperwoods.network.WWNetwork; +import dev.itsmeow.whisperwoods.util.WWServerTaskQueue; import dev.itsmeow.whisperwoods.util.WispColors; import dev.itsmeow.whisperwoods.util.WispColors.WispColor; import net.minecraft.block.Block; @@ -38,6 +40,7 @@ import net.minecraft.util.Hand; import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvent; import net.minecraft.util.SoundEvents; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; @@ -46,9 +49,12 @@ import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShapes; import net.minecraft.util.math.vector.Vector3f; +import net.minecraft.util.text.TextFormatting; import net.minecraft.world.IWorldReader; import net.minecraft.world.World; import net.minecraft.world.server.ServerWorld; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.util.Constants; import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.fml.network.PacketDistributor; @@ -57,14 +63,26 @@ public class TileEntityHandOfFate extends TileEntity { public static final ImmutableBiMap RECIPES = ImmutableBiMap.of( - "hirschgeist", new HOFRecipe(Items.BONE, Items.DIAMOND, Items.SOUL_SAND), - "wisp", new HOFRecipe(Items.BLAZE_POWDER, Items.GLOWSTONE_DUST, Items.SOUL_SAND)); + "hirschgeist", new HOFRecipe(TextFormatting.AQUA, true, Items.BONE, Items.DIAMOND, Items.SOUL_SAND), + "wisp", new HOFRecipe(TextFormatting.GOLD, false, Items.BLAZE_POWDER, Items.GLOWSTONE_DUST, Items.SOUL_SAND)); private final CurrentRecipeContainer recipeContainer = new CurrentRecipeContainer(); + private Item toDisplay = null; + private boolean displayDirty = true; + @OnlyIn(Dist.CLIENT) + public float lastAnimationY = 0F; public TileEntityHandOfFate() { super(ModTileEntities.HAND_OF_FATE.get()); } + public Item getDisplayItem() { + if(displayDirty) { + this.toDisplay = this.getRecipeContainer().getDisplayItem(); + this.displayDirty = false; + } + return this.toDisplay; + } + public boolean isLit() { Block b = this.getBlockState().getBlock(); if(b instanceof BlockHandOfFate) { @@ -95,6 +113,7 @@ public ActionResultType onBlockActivated(BlockState state, World worldIn, BlockP held.shrink(1); } player.playSound(SoundEvents.BLOCK_END_PORTAL_FRAME_FILL, 1F, 1F); + this.displayDirty = true; return ActionResultType.CONSUME; } } @@ -107,6 +126,7 @@ public ActionResultType onBlockActivated(BlockState state, World worldIn, BlockP this.onRecipeComplete(this.getRecipeContainer().getCurrentRecipe(), state, worldIn, pos, player, hand, hit); } player.playSound(SoundEvents.BLOCK_END_PORTAL_FRAME_FILL, 1F, 1F); + this.displayDirty = true; return ActionResultType.CONSUME; } } @@ -116,9 +136,17 @@ public ActionResultType onBlockActivated(BlockState state, World worldIn, BlockP public void onRecipeComplete(HOFRecipe recipe, BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult hit) { if(!world.isRemote && worldIn instanceof ServerWorld) { ServerWorld world = (ServerWorld) worldIn; + Consumer sender = p -> WWNetwork.HANDLER.send(PacketDistributor.TRACKING_CHUNK.with(() -> world.getChunkAt(pos)), p); + Consumer soundPlayer = s -> world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), s, SoundCategory.BLOCKS, 1F, 1F); switch(recipe.getName()) { case "hirschgeist": - + HOFEffectPacket hgpk = new HOFEffectPacket(HOFEffectType.HIRSCHGEIST, new Vector3f(pos.getX() + 0.5F, pos.getY() + 1F, pos.getZ() + 0.5F), WispColors.BLUE.getColor()); + sender.accept(hgpk); + soundPlayer.accept(SoundEvents.ENTITY_EVOKER_CAST_SPELL); + soundPlayer.accept(SoundEvents.BLOCK_BELL_RESONATE); + WWServerTaskQueue.schedule(50, () -> { + ModEntities.HIRSCHGEIST.entityType.spawn((ServerWorld) worldIn, null, null, pos.up(), SpawnReason.EVENT, false, false); + }); break; case "wisp": EntityWisp wisp = ModEntities.WISP.entityType.create(world); @@ -141,15 +169,14 @@ public void onRecipeComplete(HOFRecipe recipe, BlockState state, World worldIn, } int color = wisp.getWispColor().getColor(); - HOFEffectPacket packet = new HOFEffectPacket(new Vector3f(pos.getX() + 0.5F, pos.getY() + 1F, pos.getZ() + 0.5F), color); - Consumer sender = p -> WWNetwork.HANDLER.send(PacketDistributor.TRACKING_CHUNK.with(() -> world.getChunkAt(pos)), p); + HOFEffectPacket packet = new HOFEffectPacket(HOFEffectType.CIRCLE, new Vector3f(pos.getX() + 0.5F, pos.getY() + 1F, pos.getZ() + 0.5F), color); sender.accept(packet); if(wisp.isHostile) { - HOFEffectPacket packet2 = new HOFEffectPacket(new Vector3f(pos.getX() + 0.5F, pos.getY() + 1F, pos.getZ() + 0.5F), 0xFF0000); + HOFEffectPacket packet2 = new HOFEffectPacket(HOFEffectType.CIRCLE, new Vector3f(pos.getX() + 0.5F, pos.getY() + 1F, pos.getZ() + 0.5F), 0xFF0000); sender.accept(packet2); } - world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), wisp.isHostile ? SoundEvents.ENTITY_ELDER_GUARDIAN_CURSE : SoundEvents.ENTITY_EVOKER_CAST_SPELL, SoundCategory.BLOCKS, 1F, 1F); + soundPlayer.accept(wisp.isHostile ? SoundEvents.ENTITY_ELDER_GUARDIAN_CURSE : SoundEvents.ENTITY_EVOKER_CAST_SPELL); break; default: break; @@ -170,13 +197,13 @@ private static double bbOffset(IWorldReader world, BlockPos pos, boolean down, A @Override public void read(BlockState state, CompoundNBT nbt) { super.read(state, nbt); - + this.getRecipeContainer().read(state, nbt); } @Override public CompoundNBT write(CompoundNBT compound) { CompoundNBT c = super.write(compound); - + this.getRecipeContainer().write(compound); return c; } @@ -352,16 +379,28 @@ public Map getItemData() { public static class HOFRecipe { + private TextFormatting color; + private boolean bold; private String name = null; public final ImmutableList items; - public HOFRecipe(Item... items) { + public HOFRecipe(TextFormatting color, boolean bold, Item... items) { if(items.length < 1) { throw new IllegalArgumentException("HOFRecipe constructor: \"items\" must have at least one item!"); } + this.color = color; + this.bold = bold; this.items = ImmutableList.copyOf(items); } + public TextFormatting getColor() { + return color; + } + + public boolean isBold() { + return bold; + } + public String getName() { if(name == null) { this.name = TileEntityHandOfFate.RECIPES.inverse().get(this); diff --git a/src/main/java/dev/itsmeow/whisperwoods/util/MutablePair.java b/src/main/java/dev/itsmeow/whisperwoods/util/MutablePair.java new file mode 100644 index 0000000..840e78b --- /dev/null +++ b/src/main/java/dev/itsmeow/whisperwoods/util/MutablePair.java @@ -0,0 +1,27 @@ +package dev.itsmeow.whisperwoods.util; + +public class MutablePair { + private A a; + private B b; + + public MutablePair(A aIn, B bIn) { + this.a = aIn; + this.b = bIn; + } + + public A getLeft() { + return this.a; + } + + public B getRight() { + return this.b; + } + + public void setLeft(A aIn) { + this.a = aIn; + } + + public void setRight(B bIn) { + this.b = bIn; + } +} diff --git a/src/main/java/dev/itsmeow/whisperwoods/util/WWClientTaskQueue.java b/src/main/java/dev/itsmeow/whisperwoods/util/WWClientTaskQueue.java new file mode 100644 index 0000000..8f444d8 --- /dev/null +++ b/src/main/java/dev/itsmeow/whisperwoods/util/WWClientTaskQueue.java @@ -0,0 +1,36 @@ +package dev.itsmeow.whisperwoods.util; + +import java.util.HashSet; +import java.util.Set; + +import dev.itsmeow.whisperwoods.WhisperwoodsMod; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.event.TickEvent.ClientTickEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber(modid = WhisperwoodsMod.MODID, value = Dist.CLIENT) +public class WWClientTaskQueue { + + private static final Set> TASK_QUEUE = new HashSet>(); + private static final Set> REMOVE_NEXT = new HashSet>(); + + public static void schedule(int ticks, Runnable run) { + TASK_QUEUE.add(new MutablePair<>(ticks, run)); + } + + @SubscribeEvent + public static void clientTick(ClientTickEvent event) { + TASK_QUEUE.forEach(p -> { + int ticksLeft = p.getLeft(); + if(ticksLeft <= 0) { + REMOVE_NEXT.add(p); + p.getRight().run(); + } + p.setLeft(ticksLeft - 1); + }); + TASK_QUEUE.removeIf(p -> REMOVE_NEXT.contains(p)); + REMOVE_NEXT.clear(); + } + +} diff --git a/src/main/java/dev/itsmeow/whisperwoods/util/WWServerTaskQueue.java b/src/main/java/dev/itsmeow/whisperwoods/util/WWServerTaskQueue.java new file mode 100644 index 0000000..a392f97 --- /dev/null +++ b/src/main/java/dev/itsmeow/whisperwoods/util/WWServerTaskQueue.java @@ -0,0 +1,35 @@ +package dev.itsmeow.whisperwoods.util; + +import java.util.HashSet; +import java.util.Set; + +import dev.itsmeow.whisperwoods.WhisperwoodsMod; +import net.minecraftforge.event.TickEvent.ServerTickEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber(modid = WhisperwoodsMod.MODID) +public class WWServerTaskQueue { + + private static final Set> TASK_QUEUE = new HashSet>(); + private static final Set> REMOVE_NEXT = new HashSet>(); + + public static void schedule(int ticks, Runnable run) { + TASK_QUEUE.add(new MutablePair<>(ticks, run)); + } + + @SubscribeEvent + public static void serverTick(ServerTickEvent event) { + TASK_QUEUE.forEach(p -> { + int ticksLeft = p.getLeft(); + if(ticksLeft <= 0) { + REMOVE_NEXT.add(p); + p.getRight().run(); + } + p.setLeft(ticksLeft - 1); + }); + TASK_QUEUE.removeIf(p -> REMOVE_NEXT.contains(p)); + REMOVE_NEXT.clear(); + } + +} diff --git a/src/main/resources/assets/whisperwoods/lang/en_us.json b/src/main/resources/assets/whisperwoods/lang/en_us.json index 9fc9728..870319a 100644 --- a/src/main/resources/assets/whisperwoods/lang/en_us.json +++ b/src/main/resources/assets/whisperwoods/lang/en_us.json @@ -29,6 +29,12 @@ "block.whisperwoods.wisp_lantern_green": "Toxic Green Wisp Lantern", "block.whisperwoods.wisp_lantern_purple": "Magic Purple Wisp Lantern", "block.whisperwoods.hand_of_fate": "Hand of Fate", + "block.whisperwoods.hand_of_fate.tooltip.shiftdown": "Hold SHIFT to show recipes", + "block.whisperwoods.hand_of_fate.tooltip.recipehint": "Right-click the Hand with one of the following.", + "block.whisperwoods.hand_of_fate.tooltip.recipe.wisp": "Wisp Summoning", + "block.whisperwoods.hand_of_fate.tooltip.recipe.wisp.hint": "(when used with a Ghost Light inserted, it will create wisps of matching color)", + "block.whisperwoods.hand_of_fate.tooltip.recipe.hirschgeist": "Hirschgeist Summoning", + "block.whisperwoods.hand_of_fate.tooltip.recipe.hirschgeist.hint": "(requires any Ghost Light to be inserted)", "item.whisperwoods.bottled_moth": "Bottled Moth",