Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added text of signs placed on all blocks that provide tabs to the tab tooltips #52

Draft
wants to merge 2 commits into
base: 1.19.3
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ public void renderHoverTooltips(MatrixStack matrices, double mouseX, double mous
Rectangle itemRec = new Rectangle(tabRenderInfo.itemX, tabRenderInfo.itemY, 16, 16);

if (itemRec.contains(mouseX, mouseY)) {
tabManager.getCurrentScreen().renderTooltip(matrices, tabRenderInfo.tabReference.getHoverText(),
tabManager.getCurrentScreen().renderTooltip(matrices, tabRenderInfo.tabReference.getFullHoverText(),
(int) mouseX, (int) mouseY);
}
}
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/kqp/inventorytabs/tabs/tab/SimpleBlockTab.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.kqp.inventorytabs.tabs.tab;

import java.util.List;
import java.util.Objects;

import com.kqp.inventorytabs.init.InventoryTabs;
import com.kqp.inventorytabs.tabs.provider.BlockTabProvider;
import com.kqp.inventorytabs.util.BlockUtil;

import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.ChestBlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.command.argument.EntityAnchorArgumentType;
Expand Down Expand Up @@ -98,6 +100,16 @@ public Text getHoverText() {

}

@Override
public List<Text> getFullHoverText() {
List<Text> hoverTexts = super.getFullHoverText();
World world = MinecraftClient.getInstance().player.world;
BlockEntity blockEntity = world.getBlockEntity(blockPos);
boolean isChest = blockEntity instanceof ChestBlockEntity;
hoverTexts.addAll(BlockUtil.getSignText(blockPos, isChest));
return hoverTexts;
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand Down
17 changes: 16 additions & 1 deletion src/main/java/com/kqp/inventorytabs/tabs/tab/Tab.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;

import java.util.ArrayList;
import java.util.List;

/**
* Base interface for tabs.
*/
Expand All @@ -37,12 +40,24 @@ protected Tab(ItemStack renderItemStack) {
public abstract boolean shouldBeRemoved();

/**
* Returns the text that's displayed when hovering over the tab.
* Returns the first line of text that's displayed when hovering over the tab.
*
* @return
*/
public abstract Text getHoverText();

/**
* Returns the full text that's displayed when hovering over the tab,
* this includes the text of a sign that is attached to the container.
*
* @return
*/
public List<Text> getFullHoverText() {
ArrayList<Text> firstHoverText = new ArrayList<>(1);
firstHoverText.add(getHoverText());
return firstHoverText;
}

/**
* Called when the screen associated with the tab is closed.
*/
Expand Down
122 changes: 122 additions & 0 deletions src/main/java/com/kqp/inventorytabs/util/BlockUtil.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
package com.kqp.inventorytabs.util;

import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.state.property.Properties;
import net.minecraft.text.MutableText;
import net.minecraft.text.Style;
import net.minecraft.text.Text;
import net.minecraft.util.DyeColor;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.RaycastContext;
import net.minecraft.world.World;

import java.util.ArrayList;
import java.util.List;

import static com.kqp.inventorytabs.util.ChestUtil.getOtherChestBlockPos;

public class BlockUtil {
public static boolean inRange(BlockPos pos, PlayerEntity player, double distance) {
double distanceSquared = distance * distance;
Expand Down Expand Up @@ -65,6 +79,114 @@ private static BlockHitResult getBlockHitResult(Vec3d playerHead, Vec3d blockVec
return null;
}

public static List<Text> getSignText(BlockPos blockPos) {
return getSignText(blockPos, false);
}

public static List<Text> getSignText(BlockPos blockPos, boolean isChest) {
World world = MinecraftClient.getInstance().player.world;
ArrayList<Text> signTextLines = new ArrayList<>();

// If the dye color of the sign should be used to format the label
// True by default unless the sign has custom formatting applied to it (via commands)
// If false, the sign's custom formatting is used instead
boolean applySignDyeColor = true;

// Check if this is a double chest
boolean isDoubleChest = isChest && ChestUtil.isDouble(world, blockPos);
BlockPos doubleChestPos = isDoubleChest ? getOtherChestBlockPos(world, blockPos) : blockPos;

// Positions to check around the container
ArrayList<BlockPos> positionsToCheck = new ArrayList<>();
positionsToCheck.add(blockPos.add(1, 0, 0));
positionsToCheck.add(blockPos.add(0, 0, 1));
positionsToCheck.add(blockPos.add(-1, 0, 0));
positionsToCheck.add(blockPos.add(0, 0, -1));

// If this is a double chest, also check positions around the other side of the chest
// (and don't check positions inside the chests)
if(isDoubleChest) {
positionsToCheck.add(doubleChestPos.add(1, 0, 0));
positionsToCheck.add(doubleChestPos.add(0, 0, 1));
positionsToCheck.add(doubleChestPos.add(-1, 0, 0));
positionsToCheck.add(doubleChestPos.add(0, 0, -1));
positionsToCheck.remove(doubleChestPos);
positionsToCheck.remove(blockPos);
}

// Check each position needed
BlockEntity blockEntity = null;
int positionToCheckIndex = -1;
for(BlockPos positionToCheck : positionsToCheck) {
blockEntity = world.getBlockEntity(positionToCheck);

// Keep track of which position is being checked
// if this is a double chest, the other chest position needs to be used for the comparison
// after all three sides of the first chest were checked
positionToCheckIndex++;

// If a sign was found around the container
if(blockEntity instanceof SignBlockEntity) {

// Check if it is a sign that could be attached to the container
BlockState blockState = world.getBlockState(positionToCheck);
if (blockState.contains(Properties.HORIZONTAL_FACING)) {
Direction direction = blockState.get(Properties.HORIZONTAL_FACING);

// If the block this sign is attached to sign is the container, then use it as the label for this container
if(positionToCheck.add(direction.getOpposite().getVector()).equals(positionToCheckIndex < 3 ? blockPos : doubleChestPos)) {
break;
}
}
}
}

// If a suitable sign was found, read the NBT data from it
if (blockEntity != null) {
NbtCompound tag = new NbtCompound();
blockEntity.writeNbt(tag);

// Check all 4 lines of text
for (int lineNumber = 1; lineNumber <= 4; lineNumber++) {

// If the current line is not empty
if(!tag.getString("Text" + lineNumber).equals("{\"text\":\"\"}")) {

// Get the text on this line and add it to the list of texts to be processed
MutableText currentLineText = Text.Serializer.fromJson(tag.getString("Text" + lineNumber));
if(currentLineText == null) { continue; }
signTextLines.add(currentLineText);

// Check if this line contains any custom formatting (determine if the dye color should be used or not)
// For some reason Text.getStyle().isEmpty() always seems to return false
// even on simple un-formatted signs so this had to be done instead
if (currentLineText.getStyle() != null) {
if (currentLineText.getStyle().isBold() ||
currentLineText.getStyle().isItalic() ||
currentLineText.getStyle().isObfuscated() ||
currentLineText.getStyle().isStrikethrough() ||
currentLineText.getStyle().isUnderlined() ||
currentLineText.getStyle().getColor() != null) {
applySignDyeColor = false;
}
}
}
}

// Apply the dye color if need be, replacing the default text on signs with a gray so the tooltip is visible
if(applySignDyeColor) {
String signDyeColorToUse = tag.getString("Color").equals("black") ? "gray" : tag.getString("Color");
for (int currentLineInxed = 0; currentLineInxed < signTextLines.size(); currentLineInxed++) {
MutableText currentText = ((MutableText) signTextLines.get(currentLineInxed));
signTextLines.set(currentLineInxed, currentText.setStyle(Style.EMPTY.withColor(DyeColor.byName(signDyeColorToUse, DyeColor.GRAY).getSignColor())));
}
}

}

return signTextLines;
}

private static final Vec3d[] SIGHT_OFFSETS = {
// Center
new Vec3d(0.5D, 0.5D, 0.5D),
Expand Down