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.
This commit is contained in:
Eldrinn Elantey authored and GitHub committed 2026-09-09 09:21:27 +08:00
1 parent 137f651486
commit d829ae466b
1 file changed
+27 -8
@@ -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.
* <p>
* 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(