Кастомный шрифт на кастомной табличке

Версия Minecraft
1.12.2
5,018
47
783
Здравствуйте!
В общем появилась идея сделать в ванильке свои таблички, но со своим шрифтом.
Но при этом мне например не нужны какие то монструозные либы, моды по типу SmoothFonts и подобном.
Хотелось бы для начала изучить как это все работает в ванили и может, сделать по аналогии.
Каким образом в ванили работают шрифты? ttf ? или там свой формат? Если да, как его делать, чем редактировать? Каким образом можно подгружать свой шрифт конкретно для моей таблички?
 
5,018
47
783
Е мое. Так это че обычная текстура?)

Я так понял мне надо кастомный FontRenderer сделать с расширением от ванильного?
 
5,018
47
783
5,018
47
783
И еще вопрос. Может есть какие то автоматические конвертаторы? Или мне сидеть вручную эту картинку с буквами делать?:cry:
 

timaxa007

Модератор
5,831
409
672
TrueType — Википедия
Можно написать код своего генератора атласа текстуры, со своим принципом хранения к определённым координатам как в glyph_sizes.bin, для определённого TTF'а с нужным набором символов.
 
5,018
47
783
Да понятное дело что можно все это самому сделать. Хотелось бы без запары.

Тут кстати еще один вопрос возникает - каким образом правильно сделать атлас, чтобы каждый символ попал так как надо? В ванилле там много всяких, очень много.
 

timaxa007

Модератор
5,831
409
672
Хотелось бы без запары.
http://www.java-gaming.org/topics/rendering-text-in-lwjgl-without-slick/35535/view.html
чтобы каждый символ попал так как надо?
Можно по простому, типа первая строчка цифры, вторая маленькие буквы, третья для больших, последняя строчка для всяких знаков.
В TTF вроде как храниться их ширина и высота и типа их смещение (типа в сполере есть видео, где типа это объяснялось.).
 
5,018
47
783
timaxa007, а ты сам пробовал делать похожие таблички? Не помнишь, нужно как то свой кастомный FontRenderer регистрировать?
 
5,018
47
783
Да, уже нашел. P.S Тут внезапно оказалось что табличка вовсе Json модели не имеет.
 

timaxa007

Модератор
5,831
409
672
timaxa007, а ты сам пробовал делать похожие таблички?
Таблички нет.
Не помнишь, нужно как то свой кастомный FontRenderer регистрировать?
Вроде как регистрировать не надо было. Просто создать объект или константу к классу, который-бы хранил атлас и размеры и смещения для символов.
 
5,018
47
783
Так, этот способ регистрации не работает. Там крашится на стадии преинита
попробуем без этого пока.
 
5,018
47
783
Хм, вроде сделал, ошибок нет, но почему то при установке не открывается окошко ввода. Странно, блок ведь копия ванильного:(
 
5,018
47
783
Выяснил что style почему то равен нулю. По совершенно непонятной причине..
Ввиду этого кликэвент и не срабатывает. Это не зависит кстати от моего шрифта который я там делал.
Java:
public class TileEntitySovietSign extends TileEntity
{
    public final ITextComponent[] signText = new ITextComponent[] {new TextComponentString(""), new TextComponentString(""), new TextComponentString(""), new TextComponentString("")};
    /**
     * The index of the line currently being edited. Only used on client side, but defined on both. Note this is only
     * really used when the > < are going to be visible.
     */
    public int lineBeingEdited = -1;
    private boolean isEditable = true;
    private EntityPlayer player;
    private final CommandResultStats stats = new CommandResultStats();

    public NBTTagCompound writeToNBT(NBTTagCompound compound)
    {
        super.writeToNBT(compound);

        for (int i = 0; i < 4; ++i)
        {
            String s = ITextComponent.Serializer.componentToJson(this.signText[i]);
            compound.setString("Text" + (i + 1), s);
        }

        this.stats.writeStatsToNBT(compound);
        return compound;
    }

    protected void setWorldCreate(World worldIn)
    {
        this.setWorld(worldIn);
    }

    public void readFromNBT(NBTTagCompound compound)
    {
        this.isEditable = false;
        super.readFromNBT(compound);
        ICommandSender icommandsender = new ICommandSender()
        {
            /**
             * Get the name of this object. For players this returns their username
             */
            public String getName()
            {
                return "Sign";
            }
            /**
             * Returns {@code true} if the CommandSender is allowed to execute the command, {@code false} if not
             */
            public boolean canUseCommand(int permLevel, String commandName)
            {
                return permLevel <= 2; //Forge: Fixes  MC-75630 - Exploit with signs and command blocks
            }
            /**
             * Get the position in the world. <b>{@code null} is not allowed!</b> If you are not an entity in the world,
             * return the coordinates 0, 0, 0
             */
            public BlockPos getPosition()
            {
                return TileEntitySovietSign.this.pos;
            }
            /**
             * Get the position vector. <b>{@code null} is not allowed!</b> If you are not an entity in the world,
             * return 0.0D, 0.0D, 0.0D
             */
            public Vec3d getPositionVector()
            {
                return new Vec3d((double)TileEntitySovietSign.this.pos.getX() + 0.5D, (double)TileEntitySovietSign.this.pos.getY() + 0.5D, (double)TileEntitySovietSign.this.pos.getZ() + 0.5D);
            }
            /**
             * Get the world, if available. <b>{@code null} is not allowed!</b> If you are not an entity in the world,
             * return the overworld
             */
            public World getEntityWorld()
            {
                return TileEntitySovietSign.this.world;
            }
            /**
             * Get the Minecraft server instance
             */
            public MinecraftServer getServer()
            {
                return TileEntitySovietSign.this.world.getMinecraftServer();
            }
        };

        for (int i = 0; i < 4; ++i)
        {
            String s = compound.getString("Text" + (i + 1));
            ITextComponent itextcomponent = ITextComponent.Serializer.jsonToComponent(s);

            try
            {
                this.signText[i] = TextComponentUtils.processComponent(icommandsender, itextcomponent, (Entity)null);
            }
            catch (CommandException var7)
            {
                this.signText[i] = itextcomponent;
            }
        }

        this.stats.readStatsFromNBT(compound);
    }

    @Nullable
    public SPacketUpdateTileEntity getUpdatePacket()
    {
        return new SPacketUpdateTileEntity(this.pos, 9, this.getUpdateTag());
    }

    public NBTTagCompound getUpdateTag()
    {
        return this.writeToNBT(new NBTTagCompound());
    }

    public boolean onlyOpsCanSetNbt()
    {
        return true;
    }

    public boolean getIsEditable()
    {
        return this.isEditable;
    }

    /**
     * Sets the sign's isEditable flag to the specified parameter.
     */
    @SideOnly(Side.CLIENT)
    public void setEditable(boolean isEditableIn)
    {
        this.isEditable = isEditableIn;

        if (!isEditableIn)
        {
            this.player = null;
        }
    }

    public void setPlayer(EntityPlayer playerIn)
    {
        this.player = playerIn;
    }

    public EntityPlayer getPlayer()
    {
        return this.player;
    }

    public boolean executeCommand(final EntityPlayer playerIn)
    {
        ICommandSender icommandsender = new ICommandSender()
        {
            /**
             * Get the name of this object. For players this returns their username
             */
            public String getName()
            {
                return playerIn.getName();
            }
            /**
             * Get the formatted ChatComponent that will be used for the sender's username in chat
             */
            public ITextComponent getDisplayName()
            {
                return playerIn.getDisplayName();
            }
            /**
             * Send a chat message to the CommandSender
             */
            public void sendMessage(ITextComponent component)
            {
            }
            /**
             * Returns {@code true} if the CommandSender is allowed to execute the command, {@code false} if not
             */
            public boolean canUseCommand(int permLevel, String commandName)
            {
                return permLevel <= 2;
            }
            /**
             * Get the position in the world. <b>{@code null} is not allowed!</b> If you are not an entity in the world,
             * return the coordinates 0, 0, 0
             */
            public BlockPos getPosition()
            {
                return TileEntitySovietSign.this.pos;
            }
            /**
             * Get the position vector. <b>{@code null} is not allowed!</b> If you are not an entity in the world,
             * return 0.0D, 0.0D, 0.0D
             */
            public Vec3d getPositionVector()
            {
                return new Vec3d((double)TileEntitySovietSign.this.pos.getX() + 0.5D, (double)TileEntitySovietSign.this.pos.getY() + 0.5D, (double)TileEntitySovietSign.this.pos.getZ() + 0.5D);
            }
            /**
             * Get the world, if available. <b>{@code null} is not allowed!</b> If you are not an entity in the world,
             * return the overworld
             */
            public World getEntityWorld()
            {
                return playerIn.getEntityWorld();
            }
            /**
             * Returns the entity associated with the command sender. MAY BE NULL!
             */
            public Entity getCommandSenderEntity()
            {
                return playerIn;
            }
            /**
             * Returns true if the command sender should be sent feedback about executed commands
             */
            public boolean sendCommandFeedback()
            {
                return false;
            }
            public void setCommandStat(CommandResultStats.Type type, int amount)
            {
                if (TileEntitySovietSign.this.world != null && !TileEntitySovietSign.this.world.isRemote)
                {
                    TileEntitySovietSign.this.stats.setCommandStatForSender(TileEntitySovietSign.this.world.getMinecraftServer(), this, type, amount);
                }
            }
            /**
             * Get the Minecraft server instance
             */
            public MinecraftServer getServer()
            {
                return playerIn.getServer();
            }
        };

        for (ITextComponent itextcomponent : this.signText)
        {
            Style style = itextcomponent == null ? null : itextcomponent.getStyle();
         
            if (style != null && style.getClickEvent() != null)
            {
                ClickEvent clickevent = style.getClickEvent();
               
                if (clickevent.getAction() == ClickEvent.Action.RUN_COMMAND)
                {
                    System.out.println("true" );
                    playerIn.getServer().getCommandManager().executeCommand(icommandsender, clickevent.getValue());
                }
            }
        }

        return true;
    }

    public CommandResultStats getStats()
    {
        return this.stats;
    }
}
 
5,018
47
783
Ну вот еще, деньги за эту херню платить. Я лучше два дня угрохаю и сам разберусь, нежели отдавать кому то деньги. тема кстати не для предложения своих услуг. И кстати мод который поддерживает ttf существует уже давно
 
Сверху