Недавно решил написать мод с кастомным шрифтом и нашел данную тему: https://forum.mcmodding.ru/resources/kastomnyj-shrift.281/
Сначала всё было отлично, позже при попытке отрендерить русские буквы они не отобразились, но решение этого я нашел в данной теме: https://forum.mcmodding.ru/threads/ne-otobrazhaetsja-russkaja-kirillica-v-shrifte.31845/#post-215415
Попробовав советы в данной теме, я сменил CharData[256] на CharData[2048], после этого гуи начал отображать что-то, но это "что-то" явно не русские буквы (на изображении показан вывод "Тест 1 test")
Сначала всё было отлично, позже при попытке отрендерить русские буквы они не отобразились, но решение этого я нашел в данной теме: https://forum.mcmodding.ru/threads/ne-otobrazhaetsja-russkaja-kirillica-v-shrifte.31845/#post-215415
Попробовав советы в данной теме, я сменил CharData[256] на CharData[2048], после этого гуи начал отображать что-то, но это "что-то" явно не русские буквы (на изображении показан вывод "Тест 1 test")
Gui:
package ua.thespiker.SpikeServer.client.gui;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import ua.thespiker.SpikeServer.client.Font.CustomFontUtil;
import java.awt.*;
public class GuiOverlay {
public static int White = new Color(255, 255, 255).getRGB();
public static int LightBlue = new Color(9, 110, 183).getRGB();
public static int DarkBlue = new Color(0, 88, 152).getRGB();
public static long startTimeToolTip = 0;
@SubscribeEvent
public void RenderOverlay(RenderGameOverlayEvent e) {
CustomFontUtil.NewZelek.drawString("Тест 1 test", 100, 100, White);
}
}
CustomFont:
package ua.thespiker.SpikeServer.client.Font;
import net.minecraft.client.renderer.texture.DynamicTexture;
import org.lwjgl.opengl.GL11;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
public class CustomFont {
float imgSize = 512;
CharData[] charData = new CharData[2048];
Font font;
boolean antiAlias, fractionalMetrics;
int fontHeight = -1, charOffset = 0;
DynamicTexture tex;
public CustomFont(Font font, boolean antiAlias, boolean fractionalMetrics) {
this.font = font;
this.antiAlias = antiAlias;
this.fractionalMetrics = fractionalMetrics;
this.tex = this.setupTexture(font, antiAlias, fractionalMetrics, this.charData);
}
protected DynamicTexture setupTexture(Font font, boolean antiAlias, boolean fractionalMetrics, CharData[] chars) {
BufferedImage img = this.generateFontImage(font, antiAlias, fractionalMetrics, chars);
try {
return new DynamicTexture(img);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
protected BufferedImage generateFontImage(Font font, boolean antiAlias, boolean fractionalMetrics, CharData[] chars) {
int imgSize = (int) this.imgSize;
BufferedImage bufferedImage = new BufferedImage(imgSize, imgSize, 2);
Graphics2D graphics = (Graphics2D) bufferedImage.getGraphics();
graphics.setFont(font);
graphics.setColor(new Color(255, 255, 255, 0));
graphics.fillRect(0, 0, imgSize, imgSize);
graphics.setColor(Color.WHITE);
graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, fractionalMetrics ? RenderingHints.VALUE_FRACTIONALMETRICS_ON : RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, antiAlias ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antiAlias ? RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF);
FontMetrics fontMetrics = graphics.getFontMetrics();
int charHeight = 0;
int positionX = 0;
int positionY = 1;
int index = 0;
while (index < chars.length) {
char c = (char) index;
CharData charData = new CharData();
Rectangle2D dimensions = fontMetrics.getStringBounds(String.valueOf(c), graphics);
charData.width = dimensions.getBounds().width + 8;
charData.height = dimensions.getBounds().height;
if (positionX + charData.width >= imgSize) {
positionX = 0;
positionY += charHeight;
charHeight = 0;
}
if (charData.height > charHeight) {
charHeight = charData.height;
}
charData.storedX = positionX;
charData.storedY = positionY;
if (charData.height > this.fontHeight) {
this.fontHeight = charData.height;
}
chars[index] = charData;
graphics.drawString(String.valueOf(c), positionX + 2, positionY + fontMetrics.getAscent());
positionX += charData.width;
++index;
}
return bufferedImage;
}
public void drawChar(CharData[] chars, char c, float x, float y) throws ArrayIndexOutOfBoundsException {
try {
this.drawQuad(x, y, chars[c].width, chars[c].height, chars[c].storedX, chars[c].storedY, chars[c].width, chars[c].height);
} catch (Exception e) {
e.printStackTrace();
}
}
protected void drawQuad(float x2, float y2, float width, float height, float srcX, float srcY, float srcWidth, float srcHeight) {
float renderSRCX = srcX / this.imgSize;
float renderSRCY = srcY / this.imgSize;
float renderSRCWidth = srcWidth / this.imgSize;
float renderSRCHeight = srcHeight / this.imgSize;
GL11.glTexCoord2f(renderSRCX + renderSRCWidth, renderSRCY);
GL11.glVertex2d(x2 + width, y2);
GL11.glTexCoord2f(renderSRCX, renderSRCY);
GL11.glVertex2d(x2, y2);
GL11.glTexCoord2f(renderSRCX, renderSRCY + renderSRCHeight);
GL11.glVertex2d(x2, y2 + height);
GL11.glTexCoord2f(renderSRCX, renderSRCY + renderSRCHeight);
GL11.glVertex2d(x2, y2 + height);
GL11.glTexCoord2f(renderSRCX + renderSRCWidth, renderSRCY + renderSRCHeight);
GL11.glVertex2d(x2 + width, y2 + height);
GL11.glTexCoord2f(renderSRCX + renderSRCWidth, renderSRCY);
GL11.glVertex2d(x2 + width, y2);
}
public void setAntiAlias(boolean antiAlias) {
if (this.antiAlias != antiAlias) {
this.antiAlias = antiAlias;
this.tex = this.setupTexture(this.font, antiAlias, this.fractionalMetrics, this.charData);
}
}
public boolean isFractionalMetrics() {
return this.fractionalMetrics;
}
public void setFractionalMetrics(boolean fractionalMetrics) {
if (this.fractionalMetrics != fractionalMetrics) {
this.fractionalMetrics = fractionalMetrics;
this.tex = this.setupTexture(this.font, this.antiAlias, fractionalMetrics, this.charData);
}
}
public void setFont(Font font) {
this.font = font;
this.tex = this.setupTexture(font, this.antiAlias, this.fractionalMetrics, this.charData);
}
protected static class CharData {
public int width, height,
storedX, storedY;
protected CharData() {
}
}
}
CustomFontRenderer:
package ua.thespiker.SpikeServer.client.Font;
import net.minecraft.client.renderer.texture.DynamicTexture;
import org.lwjgl.opengl.GL11;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public class CustomFontRenderer extends CustomFont {
CustomFont.CharData[] boldChars = new CustomFont.CharData[2048],
italicChars = new CustomFont.CharData[2048],
boldItalicChars = new CustomFont.CharData[2048];
int[] colorCode = new int[32];
String colorcodeIdentifiers = "0123456789abcdefklmnor";
DynamicTexture texBold, texItalic, texItalicBold;
public CustomFontRenderer(Font font, boolean antiAlias, boolean fractionalMetrics) {
super(font, antiAlias, fractionalMetrics);
this.setupMinecraftColorcodes();
this.setupBoldItalicIDs();
}
public int drawStringWithShadow(String text, double x2, float y2, int color) {
float shadowWidth = this.drawString(text, x2 + 0.9f, (double) y2 + 0.5f, color, true, 8.3f);
return (int) Math.max(shadowWidth, this.drawString(text, x2, y2, color, false, 8.3f));
}
public int drawString(String text, double x2, float y2, int color) {
return (int) this.drawString(text, x2, y2, color, false, 8.3f);
}
public int drawPassword(String text, double x2, float y2, int color) {
return (int) this.drawString(text.replaceAll(".", "."), x2, y2, color, false, 8f);
}
public int drawNoBSString(String text, double x2, float y2, int color) {
return (int) this.drawNoBSString(text, x2, y2, color, false);
}
public int drawSmoothString(String text, double x2, float y2, int color) {
return (int) this.drawSmoothString(text, x2, y2, color, false);
}
public double getPasswordWidth(String text) {
return this.getStringWidth(text.replaceAll(".", "."), 8);
}
public float drawCenteredString(String text, float x2, float y2, int color) {
return this.drawString(text, x2 - (float) (this.getStringWidth(text) / 2), y2, color);
}
public float drawNoBSCenteredString(String text, float x2, float y2, int color) {
return this.drawNoBSString(text, x2 - (float) (this.getStringWidth(text) / 2), y2, color);
}
public float drawCenteredStringWithShadow(String text, float x2, float y2, int color) {
return this.drawStringWithShadow(text, x2 - (float) (this.getStringWidth(text) / 2), y2, color);
}
public float drawString(String text, double x, double y, int color, boolean shadow, float kerning) {
x -= 1.0;
if (text == null) {
return 0;
}
if (color == 0x20FFFFFF) {
color = 0xFFFFFF;
}
if ((color & 0xFC000000) == 0) {
color |= 0xFF000000;
}
if (shadow) {
color = (color & 0xFCFCFC) >> 2 | color & 0xFF000000;
}
CustomFont.CharData[] currentData = this.charData;
float alpha = (float) (color >> 24 & 255) / 255f;
boolean randomCase = false,
bold = false,
italic = false,
strikethrough = false,
underline = false,
render = true;
x *= 2;
y = (y - 3) * 2;
GL11.glPushMatrix();
GL11.glScalef(0.5F, 0.5F, 0.5F);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glColor4f((float) (color >> 16 & 255) / 255f, (float) (color >> 8 & 255) / 255f, (float) (color & 255) / 255f, alpha);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.tex.getGlTextureId());
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.tex.getGlTextureId());
for (int index = 0; index < text.length(); index++) {
char character = text.charAt(index);
if (character == '\u00a7') {
int colorIndex = 21;
try {
colorIndex = "0123456789abcdefklmnor".indexOf(text.charAt(index + 1));
} catch (Exception e) {
e.printStackTrace();
}
if (colorIndex < 16) {
bold = false;
italic = false;
randomCase = false;
underline = false;
strikethrough = false;
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.tex.getGlTextureId());
currentData = this.charData;
if (colorIndex < 0) {
colorIndex = 15;
}
if (shadow) {
colorIndex += 16;
}
int colorcode = this.colorCode[colorIndex];
GL11.glColor4f((float) (colorcode >> 16 & 255) / 255f, (float) (colorcode >> 8 & 255) / 255f, (float) (colorcode & 255) / 255f, alpha);
} else if (colorIndex == 16) {
randomCase = true;
} else if (colorIndex == 17) {
bold = true;
if (italic) {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texItalicBold.getGlTextureId());
currentData = this.boldItalicChars;
} else {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texBold.getGlTextureId());
currentData = this.boldChars;
}
} else if (colorIndex == 18) {
strikethrough = true;
} else if (colorIndex == 19) {
underline = true;
} else if (colorIndex == 20) {
italic = true;
if (bold) {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texItalicBold.getGlTextureId());
currentData = this.boldItalicChars;
} else {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texItalic.getGlTextureId());
currentData = this.italicChars;
}
} else {
bold = false;
italic = false;
randomCase = false;
underline = false;
strikethrough = false;
GL11.glColor4f((float) (color >> 16 & 255) / 255f, (float) (color >> 8 & 255) / 255f, (float) (color & 255) / 255f, alpha);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.tex.getGlTextureId());
currentData = this.charData;
}
++index;
} else if (character < currentData.length) {
GL11.glBegin(GL11.GL_TRIANGLES);
this.drawChar(currentData, character, (float) x, (float) y);
GL11.glEnd();
if (strikethrough) {
this.drawLine(x, y + (double) (currentData[character].height / 2), x + (double) currentData[character].width - 8, y + (double) (currentData[character].height / 2), 1);
}
if (underline) {
this.drawLine(x, y + (double) currentData[character].height - 2, x + (double) currentData[character].width - 8, y + (double) currentData[character].height - 2, 1);
}
x += currentData[character].width - kerning + this.charOffset;
}
}
GL11.glHint(GL11.GL_POLYGON_SMOOTH_HINT, GL11.GL_DONT_CARE);
GL11.glPopMatrix();
GL11.glColor4f(1, 1, 1, 1);
return (float) x / 2f;
}
public float drawSmoothString(String text, double x, double y, int color, boolean shadow) {
x -= 1;
if (text == null) {
return 0;
}
CustomFont.CharData[] currentData = this.charData;
float alpha = (float) (color >> 24 & 255) / 255f;
boolean randomCase = false,
bold = false,
italic = false,
strikethrough = false,
underline = false,
render = true;
x *= 2;
y = (y - 3) * 2;
GL11.glPushMatrix();
GL11.glScalef(0.5F, 0.5F, 0.5F);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glColor4f((float) (color >> 16 & 255) / 255f, (float) (color >> 8 & 255) / 255f, (float) (color & 255) / 255f, alpha);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.tex.getGlTextureId());
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.tex.getGlTextureId());
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
for (int index = 0; index < text.length(); index++) {
char character = text.charAt(index);
if (character == '\u00a7') {
int colorIndex = 21;
try {
colorIndex = "0123456789abcdefklmnor".indexOf(text.charAt(index + 1));
} catch (Exception e) {
e.printStackTrace();
}
if (colorIndex < 16) {
bold = false;
italic = false;
randomCase = false;
underline = false;
strikethrough = false;
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.tex.getGlTextureId());
currentData = this.charData;
if (colorIndex < 0) {
colorIndex = 15;
}
if (shadow) {
colorIndex += 16;
}
int colorcode = this.colorCode[colorIndex];
GL11.glColor4f((float) (colorcode >> 16 & 255) / 255f, (float) (colorcode >> 8 & 255) / 255f, (float) (colorcode & 255) / 255f, alpha);
} else if (colorIndex == 16) {
randomCase = true;
} else if (colorIndex == 17) {
bold = true;
if (italic) {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texItalicBold.getGlTextureId());
currentData = this.boldItalicChars;
} else {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texBold.getGlTextureId());
currentData = this.boldChars;
}
} else if (colorIndex == 18) {
strikethrough = true;
} else if (colorIndex == 19) {
underline = true;
} else if (colorIndex == 20) {
italic = true;
if (bold) {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texItalicBold.getGlTextureId());
currentData = this.boldItalicChars;
} else {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texItalic.getGlTextureId());
currentData = this.italicChars;
}
} else {
bold = false;
italic = false;
randomCase = false;
underline = false;
strikethrough = false;
GL11.glColor4f((float) (color >> 16 & 255) / 255f, (float) (color >> 8 & 255) / 255f, (float) (color & 255) / 255f, alpha);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.tex.getGlTextureId());
currentData = this.charData;
}
++index;
} else if (character < currentData.length) {
GL11.glBegin(GL11.GL_TRIANGLES);
this.drawChar(currentData, character, (float) x, (float) y);
GL11.glEnd();
if (strikethrough) {
this.drawLine(x, y + (double) (currentData[character].height / 2), x + (double) currentData[character].width - 8, y + (double) (currentData[character].height / 2), 1);
}
if (underline) {
this.drawLine(x, y + (double) currentData[character].height - 2, x + (double) currentData[character].width - 8, y + (double) currentData[character].height - 2, 1);
}
x += currentData[character].width - 8.3f + this.charOffset;
}
}
GL11.glHint(GL11.GL_POLYGON_SMOOTH_HINT, GL11.GL_DONT_CARE);
GL11.glPopMatrix();
GL11.glColor4f(1, 1, 1, 1);
return (float) x / 2f;
}
public float drawNoBSString(String text, double x, double y, int color, boolean shadow) {
x -= 1;
if (text == null) {
return 0;
}
CustomFont.CharData[] currentData = this.charData;
float alpha = (float) (color >> 24 & 0xFF) / 255f;
boolean randomCase = false,
bold = false,
italic = false,
strikethrough = false,
underline = false,
render = true;
x *= 2;
y = (y - 3) * 2;
GL11.glPushMatrix();
GL11.glScalef(0.5F, 0.5F, 0.5F);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glColor4f((float) (color >> 16 & 255) / 255f, (float) (color >> 8 & 255) / 255f, (float) (color & 255) / 255f, alpha);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.tex.getGlTextureId());
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.tex.getGlTextureId());
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
for (int index = 0; index < text.length(); index++) {
char character = text.charAt(index);
if (character == '\u00a7') {
int colorIndex = 21;
try {
colorIndex = "0123456789abcdefklmnor".indexOf(text.charAt(index + 1));
} catch (Exception e) {
e.printStackTrace();
}
if (colorIndex < 16) {
bold = false;
italic = false;
randomCase = false;
underline = false;
strikethrough = false;
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.tex.getGlTextureId());
currentData = this.charData;
if (colorIndex < 0) {
colorIndex = 15;
}
if (shadow) {
colorIndex += 16;
}
int colorcode = this.colorCode[colorIndex];
GL11.glColor4f((float) (colorcode >> 16 & 255) / 255f, (float) (colorcode >> 8 & 255) / 255f, (float) (colorcode & 255) / 255f, alpha);
} else if (colorIndex == 16) {
randomCase = true;
} else if (colorIndex == 17) {
bold = true;
if (italic) {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texItalicBold.getGlTextureId());
currentData = this.boldItalicChars;
} else {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texBold.getGlTextureId());
currentData = this.boldChars;
}
} else if (colorIndex == 18) {
strikethrough = true;
} else if (colorIndex == 19) {
underline = true;
} else if (colorIndex == 20) {
italic = true;
if (bold) {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texItalicBold.getGlTextureId());
currentData = this.boldItalicChars;
} else {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texItalic.getGlTextureId());
currentData = this.italicChars;
}
} else {
bold = false;
italic = false;
randomCase = false;
underline = false;
strikethrough = false;
GL11.glColor4f((float) (color >> 16 & 255) / 255f, (float) (color >> 8 & 255) / 255f, (float) (color & 255) / 255f, alpha);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.tex.getGlTextureId());
currentData = this.charData;
}
++index;
} else if (character < currentData.length) {
GL11.glBegin(GL11.GL_TRIANGLES);
this.drawChar(currentData, character, (float) x, (float) y);
GL11.glEnd();
if (strikethrough) {
this.drawLine(x, y + (double) (currentData[character].height / 2), x + (double) currentData[character].width - 8, y + (double) (currentData[character].height / 2), 1);
}
if (underline) {
this.drawLine(x, y + (double) currentData[character].height - 2, x + (double) currentData[character].width - 8, y + (double) currentData[character].height - 2, 1);
}
x += currentData[character].width - 8.3f + this.charOffset;
}
}
GL11.glHint(GL11.GL_POLYGON_SMOOTH_HINT, GL11.GL_DONT_CARE);
GL11.glPopMatrix();
GL11.glColor4f(1, 1, 1, 1);
return (float) x / 2f;
}
public double getStringWidth(String text) {
if (text == null) {
return 0;
}
float width = 0;
CustomFont.CharData[] currentData = charData;
boolean bold = false, italic = false;
for (int index = 0; index < text.length(); index++) {
char character = text.charAt(index);
if (character == '\u00a7') {
int colorIndex = "0123456789abcdefklmnor".indexOf(character);
bold = false;
italic = false;
++index;
} else if (character < currentData.length) {
width += currentData[character].width - 8.3f + charOffset;
}
}
return width / 2;
}
public double getStringWidth(String text, float kerning) {
if (text == null) {
return 0;
}
float width = 0;
CustomFont.CharData[] currentData = charData;
boolean bold = false, italic = false;
for (int index = 0; index < text.length(); index++) {
char c = text.charAt(index);
if (c == '\u00a7') {
int colorIndex = "0123456789abcdefklmnor".indexOf(c);
bold = false;
italic = false;
++index;
} else if (c < currentData.length) {
width += currentData[c].width - kerning + charOffset;
}
}
return width / 2;
}
public int getHeight() {
return (this.fontHeight - 8) / 2;
}
@Override
public void setFont(Font font) {
super.setFont(font);
this.setupBoldItalicIDs();
}
@Override
public void setAntiAlias(boolean antiAlias) {
super.setAntiAlias(antiAlias);
this.setupBoldItalicIDs();
}
@Override
public void setFractionalMetrics(boolean fractionalMetrics) {
super.setFractionalMetrics(fractionalMetrics);
this.setupBoldItalicIDs();
}
private void setupBoldItalicIDs() {
this.texBold = this.setupTexture(this.font.deriveFont(Font.BOLD), this.antiAlias, this.fractionalMetrics, this.boldChars);
this.texItalic = this.setupTexture(this.font.deriveFont(Font.ITALIC), this.antiAlias, this.fractionalMetrics, this.italicChars);
this.texItalicBold = this.setupTexture(this.font.deriveFont(Font.BOLD | Font.ITALIC), this.antiAlias, this.fractionalMetrics, this.boldItalicChars);
}
private void drawLine(double x2, double y2, double x1, double y1, float width) {
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glLineWidth(width);
GL11.glBegin(GL11.GL_LINES);
GL11.glVertex2d(x2, y2);
GL11.glVertex2d(x1, y1);
GL11.glEnd();
GL11.glEnable(GL11.GL_TEXTURE_2D);
}
public List<String> wrapWords(String text, double width) {
ArrayList<String> finalWords = new ArrayList<String>();
if (getStringWidth(text) > width) {
String[] words = text.split(" ");
StringBuilder currentWord = new StringBuilder();
char lastColorCode = 65535;
for (String word : words) {
for (int innerIndex = 0; innerIndex < word.toCharArray().length; innerIndex++) {
char c = word.toCharArray()[innerIndex];
if (c == '\u00a7' && innerIndex < word.toCharArray().length - 1) {
lastColorCode = word.toCharArray()[innerIndex + 1];
}
}
if (getStringWidth(currentWord + word + " ") < width) {
currentWord.append(word).append(" ");
} else {
finalWords.add(currentWord.toString());
currentWord = new StringBuilder("\u00a7" + lastColorCode + word + " ");
}
}
if (currentWord.length() > 0) {
if (getStringWidth(currentWord.toString()) < width) {
finalWords.add("\u00a7" + lastColorCode + currentWord + " ");
currentWord = new StringBuilder();
} else {
finalWords.addAll(formatString(currentWord.toString(), width));
}
}
} else {
finalWords.add(text);
}
return finalWords;
}
public List<String> formatString(String string, double width) {
ArrayList<String> finalWords = new ArrayList<String>();
StringBuilder currentWord = new StringBuilder();
char lastColorCode = 65535;
char[] chars = string.toCharArray();
for (int index = 0; index < chars.length; index++) {
char c = chars[index];
if (c == '\u00a7' && index < chars.length - 1) {
lastColorCode = chars[index + 1];
}
if (getStringWidth(currentWord.toString() + c) < width) {
currentWord.append(c);
} else {
finalWords.add(currentWord.toString());
currentWord = new StringBuilder("\u00a7" + lastColorCode + c);
}
}
if (currentWord.length() > 0) {
finalWords.add(currentWord.toString());
}
return finalWords;
}
private void setupMinecraftColorcodes() {
int index = 0;
while (index < 32) {
int noClue = (index >> 3 & 1) * 85;
int red = (index >> 2 & 1) * 170 + noClue;
int green = (index >> 1 & 1) * 170 + noClue;
int blue = (index & 1) * 170 + noClue;
if (index == 6) {
red += 85;
}
if (index >= 16) {
red /= 4;
green /= 4;
blue /= 4;
}
this.colorCode[index] = (red & 255) << 16 | (green & 255) << 8 | blue & 255;
++index;
}
}
public String trimStringToWidth(String text, int width) {
return this.trimStringToWidth(text, width, false);
}
public String trimStringToWidthPassword(String text, int width, boolean custom) {
text = text.replaceAll(".", ".");
return this.trimStringToWidth(text, width, custom);
}
private float getCharWidthFloat(char c) {
if (c == 167) {
return -1;
} else if (c == 32) {
return 2;
} else {
int var2 = "\u00c0\u00c1\u00c2\u00c8\u00ca\u00cb\u00cd\u00d3\u00d4\u00d5\u00da\u00df\u00e3\u00f5\u011f\u0130\u0131\u0152\u0153\u015e\u015f\u0174\u0175\u017e\u0207\u0000\u0000\u0000\u0000\u0000\u0000\u0000 !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0000\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00f8\u00a3\u00d8\u00d7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u00ae\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u03b2\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u2205\u2208\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u0000"
.indexOf(c);
if (c > 0 && var2 != -1) {
return ((charData[var2].width / 2.f) - 4.f);
} else if (((charData[c].width / 2.f) - 4.f) != 0) {
int var3 = ((int) ((charData[c].width / 2.f) - 4.f)) >>> 4;
int var4 = ((int) ((charData[c].width / 2.f) - 4.f)) & 15;
var3 &= 15;
++var4;
return (float) ((var4 - var3) / 2 + 1);
} else {
return 0;
}
}
}
public String trimStringToWidth(String text, int width, boolean custom) {
StringBuilder buffer = new StringBuilder();
float lineWidth = 0.0F;
int offset = custom ? text.length() - 1 : 0;
int increment = custom ? -1 : 1;
boolean var8 = false;
boolean var9 = false;
for (int index = offset; index >= 0 && index < text.length() && lineWidth < (float) width; index += increment) {
char character = text.charAt(index);
float charWidth = this.getCharWidthFloat(character);
if (var8) {
var8 = false;
if (character != 108 && character != 76) {
if (character == 114 || character == 82) {
var9 = false;
}
} else {
var9 = true;
}
} else if (charWidth < 0) {
var8 = true;
} else {
lineWidth += charWidth;
if (var9) {
++lineWidth;
}
}
if (lineWidth > (float) width) {
break;
}
if (custom) {
buffer.insert(0, character);
} else {
buffer.append(character);
}
}
return buffer.toString();
}
}
CustomFontRenderer:
package ua.thespiker.SpikeServer.client.Font;
import net.minecraft.client.Minecraft;
import net.minecraft.util.ResourceLocation;
import ua.thespiker.SpikeServer.common.SpikeServer;
import java.awt.*;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
public class CustomFontUtil {
public static volatile int completed;
public static CustomFontRenderer NewZelek;
public static Font bahnschrift;
private static Font getFont(Map<String, Font> locationMap, String location, int size) {
Font font = null;
try {
if (locationMap.containsKey(location)) {
font = locationMap.get(location).deriveFont(Font.PLAIN, size);
} else {
InputStream is = Minecraft.getMinecraft().getResourceManager()
.getResource(new ResourceLocation(SpikeServer.MODID, "fonts/" + location)).getInputStream();
font = Font.createFont(0, is);
locationMap.put(location, font);
font = font.deriveFont(Font.PLAIN, size);
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("Error! Font can't be loaded.");
font = new Font("default", Font.PLAIN, +10);
}
return font;
}
public static boolean hasLoaded() {
return completed >= 3;
}
public static void bootstrap() {
new Thread(() ->
{
Map<String, Font> locationMap = new HashMap<String, Font>();
bahnschrift = getFont(locationMap, "NewZelek.ttf", 20);
completed++;
}).start();
new Thread(() ->
{
Map<String, Font> locationMap = new HashMap<>();
completed++;
}).start();
new Thread(() ->
{
Map<String, Font> locationMap = new HashMap<>();
completed++;
}).start();
while (!hasLoaded()) {
try {
//noinspection BusyWait
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
loadFont();
}
public static void loadFont() {
NewZelek = new CustomFontRenderer(bahnschrift, true, true);
}
}