From d829ae466b7e8e1a5bb33d0b9719b79f3b4eacec Mon Sep 17 00:00:00 2001 From: Eldrinn Elantey <46845681+Eldrinn-Elantey@users.noreply.github.com> Date: Wed, 9 Sep 2026 05:21:27 +0400 Subject: [PATCH] Localize and unify missing block messages in autoplace (#70) StructureLib built the missing block name on the server, where only en_US is loaded, so players on dedicated servers saw English names in chat. Send the item's lang key and let the client translate it. Stacks whose name is not a plain key, GT meta items among them, keep the old server side name. Players also saw two shapes of the same message: a bracketed name with rarity color and an item tooltip from two of the survivalPlaceBlocks branches, a bare yellow name from the stack list branch. All three now build the name the same way. --- .../structure/StructureUtility.java | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/gtnewhorizon/structurelib/structure/StructureUtility.java b/src/main/java/com/gtnewhorizon/structurelib/structure/StructureUtility.java index 8abde125..a1ac478e 100644 --- a/src/main/java/com/gtnewhorizon/structurelib/structure/StructureUtility.java +++ b/src/main/java/com/gtnewhorizon/structurelib/structure/StructureUtility.java @@ -30,6 +30,7 @@ import javax.annotation.Nullable; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.event.HoverEvent; import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; @@ -38,10 +39,9 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ChatComponentText; import net.minecraft.util.ChatComponentTranslation; -import net.minecraft.util.ChatStyle; -import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IChatComponent; import net.minecraft.util.IIcon; +import net.minecraft.util.StatCollector; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; @@ -317,6 +317,25 @@ public class StructureUtility { return survivalPlaceBlock(block, meta, world, x, y, z, s, (EntityPlayer) actor, chatter); } + /** + * Build a chat component naming the given stack, so that the receiving client localizes it. + *

+ * Falls back to the server side display name for stacks whose name is not a plain translation key, e.g. items that + * assemble their name in {@link Item#getItemStackDisplayName(ItemStack)}. + */ + private static IChatComponent getStackChatName(ItemStack stack) { + String key = stack.getUnlocalizedName() + ".name"; + if (!StatCollector.canTranslate(key)) return stack.func_151000_E(); + IChatComponent name = new ChatComponentText("[").appendSibling(new ChatComponentTranslation(key)) + .appendText("]"); + NBTTagCompound tag = new NBTTagCompound(); + stack.writeToNBT(tag); + name.getChatStyle() + .setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ITEM, new ChatComponentText(tag.toString()))) + .setColor(stack.getRarity().rarityColor); + return name; + } + /** * This is a helper method for implementing * {@link IStructureElement#survivalPlaceBlock(Object, World, int, int, int, ItemStack, IItemSource, EntityPlayerMP, Consumer)} @@ -341,7 +360,7 @@ public class StructureUtility { ItemStack stack = new ItemStack(itemBlock, 1, itemMeta); if (!s.takeOne(stack, true)) { if (chatter != null) chatter.accept( - new ChatComponentTranslation("structurelib.autoplace.missing_block", stack.func_151000_E())); + new ChatComponentTranslation("structurelib.autoplace.missing_block", getStackChatName(stack))); return PlaceResult.REJECT; } if (block instanceof ICustomBlockSetting blockCustom) { @@ -447,7 +466,7 @@ public class StructureUtility { if (!StructureLibAPI.isBlockTriviallyReplaceable(world, x, y, z, actor)) return PlaceResult.REJECT; if (!assumeStackPresent && !s.takeOne(stack, true)) { if (chatter != null) chatter.accept( - new ChatComponentTranslation("structurelib.autoplace.missing_block", stack.func_151000_E())); + new ChatComponentTranslation("structurelib.autoplace.missing_block", getStackChatName(stack))); return PlaceResult.REJECT; } if (!stack.copy().tryPlaceItemIntoWorld(actor, world, x, y, z, ForgeDirection.UP.ordinal(), 0.5f, 0.5f, 0.5f)) @@ -1484,10 +1503,10 @@ public class StructureUtility { } for (ItemStack stack : e.getStacks()) { if (!source.takeOne(stack, true)) { - IChatComponent name = new ChatComponentText(stack.getDisplayName()); - name.setChatStyle(new ChatStyle().setColor(EnumChatFormatting.YELLOW)); - env.getChatter() - .accept(new ChatComponentTranslation("structurelib.autoplace.missing_block", name)); + env.getChatter().accept( + new ChatComponentTranslation( + "structurelib.autoplace.missing_block", + getStackChatName(stack))); continue; } return StructureUtility.survivalPlaceBlock(