mirror of
https://github.com/neoStudiosLCE/neoLegacy.git
synced 2026-06-09 02:13:09 +00:00
Enable multi-language font rendering and Unicode text input
Goal: Allow players to type and display text in any language supported by Unicode, including Chinese, Japanese, Korean, Thai, Arabic, Korean, Hindi, and more. This covers all text surfaces: chat editor, chat messages, signs (in-world and editor), world name/seed, server address/port fields, and all Iggy Flash UI text fields. Multi-language support: Two complementary rendering systems were added to handle Unicode text across the entire client: 1. Iggy UI (Flash-based text fields): A new UIUnicodeBitmapFont class serves Java Minecraft's glyph page PNGs (glyph_00.png-glyph_FF.png) through Iggy's bitmap font provider API. Registered as the global fallback font with metrics matching the Mojangles bitmap font for correct baseline alignment. When the primary bitmap font lacks a glyph, it returns IGGY_GLYPH_INVALID and Iggy seamlessly falls back to the unicode bitmap font. 2. Legacy C++ Font renderer (chat editor, in-world signs): Revived the commented-out unicode glyph page system in Font.cpp. Characters not in the bitmap font texture are rendered from glyph page PNGs loaded on demand, with proper texture switching mid-string. 3. ChatScreen input: Removed the restrictive acceptableLetters filter so all printable Unicode characters are accepted in chat. Languages now supported for text input and rendering: - Japanese (Hiragana, Katakana, Kanji) - Chinese (Simplified and Traditional) - Korean (Hangul) - Thai - Arabic - Hindi (Devanagari) - Russian (Cyrillic) - already worked via bitmap font - Greek - already worked via bitmap font - Polish, Czech, Turkish (Extended Latin) - already worked via bitmap font - Armenian, Georgian, and other scripts covered by glyph pages Security fixes: - Fixed memset under-initialization of Font::charWidths (zeroed 460 bytes instead of 460*sizeof(int)=1840 bytes, leaving entries 115+ uninitialized) - pre-existing bug - Added bounds checks to all UIUnicodeBitmapFont callbacks to reject glyph IDs outside [0, 65535], preventing OOB array access - Added bounds check in Font::width() section-sign fallback path to prevent OOB read on charWidths[] with high codepoints - Blocked Unicode bidirectional override characters (U+202A-202E, U+2066-2069) in chat input to prevent message spoofing Memory leak fix: - Fixed SignTileEntity::load allocating wchar_t[256] with new[] on every sign load without freeing. Replaced with stack allocation. Debug logging: - Added [SIGN] prefixed logging for sign save/update operations - Added [CHAT] prefixed logging for chat send/receive operations Files changed: - UIUnicodeBitmapFont.h/.cpp (new) - Iggy bitmap font for glyph pages - UIBitmapFont.cpp - Return IGGY_GLYPH_INVALID for unknown chars - UIFontData.h/.cpp - Added hasGlyph() method - UIController.h/.cpp - Load and register unicode bitmap fallback font - UITTFFont.h/.cpp - Added registerAsDefaultFonts parameter - Font.h/.cpp - Revived unicode glyph page rendering system - ChatScreen.cpp - Accept all Unicode input, block bidi overrides - Gui.cpp - Chat display debug logging - ClientConnection.cpp - Sign update debug logging - SignTileEntity.cpp - Sign save logging, memory leak fix
This commit is contained in:
parent
a3395329e5
commit
d7822ac81e
|
|
@ -14,7 +14,12 @@ wstring ChatScreen::s_historyDraft;
|
|||
|
||||
bool ChatScreen::isAllowedChatChar(wchar_t c)
|
||||
{
|
||||
return c >= 0x20 && (c == L'\u00A7' || allowedChars.empty() || allowedChars.find(c) != wstring::npos);
|
||||
if (c < 0x20) return false;
|
||||
// Block Unicode bidirectional override characters that can be used to
|
||||
// spoof chat messages or impersonate players.
|
||||
if (c >= 0x202A && c <= 0x202E) return false; // LRE, RLE, PDF, LRO, RLO
|
||||
if (c >= 0x2066 && c <= 0x2069) return false; // LRI, RLI, FSI, PDI
|
||||
return true;
|
||||
}
|
||||
|
||||
ChatScreen::ChatScreen()
|
||||
|
|
@ -93,6 +98,9 @@ void ChatScreen::keyPressed(wchar_t ch, int eventKey)
|
|||
if (eventKey == Keyboard::KEY_RETURN)
|
||||
{
|
||||
wstring trim = trimString(message);
|
||||
{ char buf[64]; sprintf_s(buf, "[CHAT] Sending (%d chars): ", (int)trim.length()); OutputDebugStringA(buf); }
|
||||
OutputDebugStringW(trim.c_str());
|
||||
OutputDebugStringA("\n");
|
||||
if (trim.length() > 0)
|
||||
{
|
||||
if (!minecraft->handleClientSideCommand(trim))
|
||||
|
|
@ -135,6 +143,7 @@ void ChatScreen::keyPressed(wchar_t ch, int eventKey)
|
|||
{
|
||||
message.insert(cursorIndex, 1, ch);
|
||||
cursorIndex++;
|
||||
{ char buf[64]; sprintf_s(buf, "[CHAT] Char U+%04X accepted (%d chars)\n", (unsigned)ch, (int)message.length()); OutputDebugStringA(buf); }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3315,7 +3315,9 @@ void ClientConnection::handleTileEditorOpen(shared_ptr<TileEditorOpenPacket> pac
|
|||
|
||||
void ClientConnection::handleSignUpdate(shared_ptr<SignUpdatePacket> packet)
|
||||
{
|
||||
app.DebugPrintf("ClientConnection::handleSignUpdate - ");
|
||||
app.DebugPrintf("[SIGN] handleSignUpdate at (%d, %d, %d):\n", packet->x, packet->y, packet->z);
|
||||
for (int i = 0; i < MAX_SIGN_LINES; i++)
|
||||
app.DebugPrintf("[SIGN] Line%d: \"%ls\"\n", i+1, packet->lines[i].c_str());
|
||||
if (minecraft->level->hasChunkAt(packet->x, packet->y, packet->z))
|
||||
{
|
||||
shared_ptr<TileEntity> te = minecraft->level->getTileEntity(packet->x, packet->y, packet->z);
|
||||
|
|
@ -3329,7 +3331,7 @@ void ClientConnection::handleSignUpdate(shared_ptr<SignUpdatePacket> packet)
|
|||
ste->SetMessage(i,packet->lines[i]);
|
||||
}
|
||||
|
||||
app.DebugPrintf("verified = %d\tCensored = %d\n",packet->m_bVerified,packet->m_bCensored);
|
||||
app.DebugPrintf("[SIGN] verified=%d censored=%d\n", packet->m_bVerified, packet->m_bCensored);
|
||||
ste->SetVerified(packet->m_bVerified);
|
||||
ste->SetCensored(packet->m_bCensored);
|
||||
|
||||
|
|
@ -3337,12 +3339,12 @@ void ClientConnection::handleSignUpdate(shared_ptr<SignUpdatePacket> packet)
|
|||
}
|
||||
else
|
||||
{
|
||||
app.DebugPrintf("dynamic_pointer_cast<SignTileEntity>(te) == nullptr\n");
|
||||
app.DebugPrintf("[SIGN] ERROR: tile entity is not a SignTileEntity\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
app.DebugPrintf("hasChunkAt failed\n");
|
||||
app.DebugPrintf("[SIGN] ERROR: chunk not loaded at position\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -141,6 +141,9 @@ S32 UIBitmapFont::GetCodepointGlyph(U32 codepoint)
|
|||
// 4J-JEV: Change "right single quotation marks" to apostrophies.
|
||||
if (codepoint == 0x2019) codepoint = 0x27;
|
||||
|
||||
if (!m_cFontData->hasGlyph(codepoint))
|
||||
return IGGY_GLYPH_INVALID;
|
||||
|
||||
return m_cFontData->getGlyphId(codepoint);
|
||||
}
|
||||
|
||||
|
|
@ -253,19 +256,6 @@ rrbool UIBitmapFont::GetGlyphBitmap(S32 glyph,F32 pixel_scale,IggyBitmapCharacte
|
|||
while ( (0.5f + glyphScale) * truePixelScale < pixel_scale)
|
||||
glyphScale++;
|
||||
|
||||
// Debug: log each unique (font, pixel_scale) pair
|
||||
{
|
||||
static std::unordered_set<int> s_loggedScaleKeys;
|
||||
// Encode font pointer + quantized scale into a key to log each combo once
|
||||
int scaleKey = (int)(pixel_scale * 100.0f) ^ (int)(uintptr_t)m_cFontData;
|
||||
if (s_loggedScaleKeys.find(scaleKey) == s_loggedScaleKeys.end() && s_loggedScaleKeys.size() < 50) {
|
||||
s_loggedScaleKeys.insert(scaleKey);
|
||||
float tps = truePixelScale;
|
||||
app.DebugPrintf("[FONT-DBG] GetGlyphBitmap: font=%s glyph=%d pixel_scale=%.3f truePixelScale=%.1f glyphScale=%.0f\n",
|
||||
m_cFontData->getFontName().c_str(), glyph, pixel_scale, tps, glyphScale);
|
||||
}
|
||||
}
|
||||
|
||||
// 4J-JEV: Debug code to check which font sizes are being used.
|
||||
#if (!defined _CONTENT_PACKAGE) && (VERBOSE_FONT_OUTPUT > 0)
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include "..\..\EnderDragonRenderer.h"
|
||||
#include "..\..\MultiPlayerLocalPlayer.h"
|
||||
#include "UIFontData.h"
|
||||
#include "UIUnicodeBitmapFont.h"
|
||||
#include "UISplitScreenHelpers.h"
|
||||
#ifdef _WINDOWS64
|
||||
#include "..\..\Windows64\KeyboardMouseInput.h"
|
||||
|
|
@ -193,6 +194,7 @@ UIController::UIController()
|
|||
m_mcTTFFont = nullptr;
|
||||
m_moj7 = nullptr;
|
||||
m_moj11 = nullptr;
|
||||
m_unicodeBitmapFont = nullptr;
|
||||
|
||||
// 4J-JEV: It's important that these remain the same, unless updateCurrentLanguage is going to be called.
|
||||
m_eCurrentFont = m_eTargetFont = eFont_NotLoaded;
|
||||
|
|
@ -307,6 +309,14 @@ void UIController::postInit()
|
|||
IggySetAS3ExternalFunctionCallbackUTF16 ( &UIController::ExternalFunctionCallback, this );
|
||||
IggySetTextureSubstitutionCallbacks ( &UIController::TextureSubstitutionCreateCallback , &UIController::TextureSubstitutionDestroyCallback, this );
|
||||
|
||||
// Load a unicode bitmap font as Iggy's global fallback for characters not
|
||||
// covered by the Mojangles bitmap font (CJK, Thai, Arabic, Korean, etc.).
|
||||
// Uses the same glyph page PNGs as the legacy Font class, with matching
|
||||
// Mojangles metrics for correct vertical alignment.
|
||||
m_unicodeBitmapFont = new UIUnicodeBitmapFont("Mojangles_Unicode_Bitmap", SFontData::Mojangles_7);
|
||||
m_unicodeBitmapFont->registerFont();
|
||||
IggyFontSetFallbackFontUTF8("Mojangles_Unicode_Bitmap", -1, IGGY_FONTFLAG_none);
|
||||
|
||||
SetupFont();
|
||||
//
|
||||
loadSkins();
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using namespace std;
|
|||
|
||||
class UIAbstractBitmapFont;
|
||||
class UIBitmapFont;
|
||||
class UIUnicodeBitmapFont;
|
||||
class UITTFFont;
|
||||
class UIComponent_DebugUIConsole;
|
||||
class UIComponent_DebugUIMarketingGuide;
|
||||
|
|
@ -63,6 +64,7 @@ private:
|
|||
UIAbstractBitmapFont *m_mcBitmapFont;
|
||||
UITTFFont *m_mcTTFFont;
|
||||
UIBitmapFont *m_moj7, *m_moj11;
|
||||
UIUnicodeBitmapFont *m_unicodeBitmapFont;
|
||||
|
||||
std::mt19937 m_randomGenerator;
|
||||
std::uniform_real_distribution<float> m_randomDistribution;
|
||||
|
|
|
|||
|
|
@ -335,6 +335,11 @@ bool CFontData::unicodeIsWhitespace(unsigned int unicode)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool CFontData::hasGlyph(unsigned int unicodepoint)
|
||||
{
|
||||
return m_unicodeMap.find(unicodepoint) != m_unicodeMap.end();
|
||||
}
|
||||
|
||||
void CFontData::moveCursor(unsigned char *&cursor, unsigned int dx, unsigned int dy)
|
||||
{
|
||||
cursor += (dy * m_sFontData->m_uiGlyphMapX) + dx;
|
||||
|
|
|
|||
|
|
@ -125,6 +125,9 @@ public:
|
|||
// Returns true if this unicodepoint is whitespace
|
||||
bool unicodeIsWhitespace(unsigned int unicodepoint);
|
||||
|
||||
// Returns true if this unicodepoint exists in the font's glyph map.
|
||||
bool hasGlyph(unsigned int unicodepoint);
|
||||
|
||||
private:
|
||||
|
||||
// Move a pointer in an image dx pixels right and dy pixels down, wrap around in either dimension leads to unknown behaviour.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include "..\..\..\Minecraft.World\File.h"
|
||||
#include "UITTFFont.h"
|
||||
|
||||
UITTFFont::UITTFFont(const string &name, const string &path, S32 fallbackCharacter)
|
||||
UITTFFont::UITTFFont(const string &name, const string &path, S32 fallbackCharacter, bool registerAsDefaultFonts)
|
||||
: m_strFontName(name)
|
||||
{
|
||||
app.DebugPrintf("UITTFFont opening %s\n",path.c_str());
|
||||
|
|
@ -41,9 +41,12 @@ UITTFFont::UITTFFont(const string &name, const string &path, S32 fallbackCharact
|
|||
|
||||
IggyFontInstallTruetypeFallbackCodepointUTF8( m_strFontName.c_str(), -1, IGGY_FONTFLAG_none, fallbackCharacter );
|
||||
|
||||
// 4J Stu - These are so we can use the default flash controls
|
||||
IggyFontInstallTruetypeUTF8 ( (void *)pbData, IGGY_TTC_INDEX_none, "Times New Roman", -1, IGGY_FONTFLAG_none );
|
||||
IggyFontInstallTruetypeUTF8 ( (void *)pbData, IGGY_TTC_INDEX_none, "Arial", -1, IGGY_FONTFLAG_none );
|
||||
if (registerAsDefaultFonts)
|
||||
{
|
||||
// 4J Stu - These are so we can use the default flash controls
|
||||
IggyFontInstallTruetypeUTF8 ( (void *)pbData, IGGY_TTC_INDEX_none, "Times New Roman", -1, IGGY_FONTFLAG_none );
|
||||
IggyFontInstallTruetypeUTF8 ( (void *)pbData, IGGY_TTC_INDEX_none, "Arial", -1, IGGY_FONTFLAG_none );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ private:
|
|||
//DWORD dwDataSize;
|
||||
|
||||
public:
|
||||
UITTFFont(const string &name, const string &path, S32 fallbackCharacter);
|
||||
UITTFFont(const string &name, const string &path, S32 fallbackCharacter, bool registerAsDefaultFonts = true);
|
||||
~UITTFFont();
|
||||
|
||||
string getFontName();
|
||||
|
|
|
|||
164
Minecraft.Client/Common/UI/UIUnicodeBitmapFont.cpp
Normal file
164
Minecraft.Client/Common/UI/UIUnicodeBitmapFont.cpp
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
#include "stdafx.h"
|
||||
#include "BufferedImage.h"
|
||||
#include "UIFontData.h"
|
||||
#include "UIUnicodeBitmapFont.h"
|
||||
|
||||
UIUnicodeBitmapFont::UIUnicodeBitmapFont(const string &fontname, SFontData &referenceFontData)
|
||||
: UIAbstractBitmapFont(fontname)
|
||||
{
|
||||
m_numGlyphs = 65536;
|
||||
m_referenceFontData = &referenceFontData;
|
||||
memset(m_glyphPages, 0, sizeof(m_glyphPages));
|
||||
memset(m_unicodeWidth, 0, sizeof(m_unicodeWidth));
|
||||
|
||||
FILE *f = nullptr;
|
||||
fopen_s(&f, "Common/res/1_2_2/font/glyph_sizes.bin", "rb");
|
||||
if (f)
|
||||
{
|
||||
fread(m_unicodeWidth, 1, 65536, f);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
UIUnicodeBitmapFont::~UIUnicodeBitmapFont()
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
delete[] m_glyphPages[i];
|
||||
}
|
||||
|
||||
void UIUnicodeBitmapFont::loadGlyphPage(int page)
|
||||
{
|
||||
wchar_t fileName[64];
|
||||
swprintf(fileName, 64, L"/1_2_2/font/glyph_%02X.png", page);
|
||||
BufferedImage bimg(fileName);
|
||||
int *rawData = bimg.getData();
|
||||
if (!rawData) return;
|
||||
|
||||
int size = 256 * 256;
|
||||
m_glyphPages[page] = new unsigned char[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
m_glyphPages[page][i] = (rawData[i] & 0xFF000000) >> 24;
|
||||
}
|
||||
|
||||
IggyFontMetrics *UIUnicodeBitmapFont::GetFontMetrics(IggyFontMetrics *metrics)
|
||||
{
|
||||
metrics->ascent = m_referenceFontData->m_fAscent;
|
||||
metrics->descent = m_referenceFontData->m_fDescent;
|
||||
metrics->average_glyph_width_for_tab_stops = 8.0f;
|
||||
metrics->largest_glyph_bbox_y1 = metrics->descent;
|
||||
return metrics;
|
||||
}
|
||||
|
||||
S32 UIUnicodeBitmapFont::GetCodepointGlyph(U32 codepoint)
|
||||
{
|
||||
if (codepoint < 65536 && m_unicodeWidth[codepoint] != 0)
|
||||
return (S32)codepoint;
|
||||
return IGGY_GLYPH_INVALID;
|
||||
}
|
||||
|
||||
IggyGlyphMetrics *UIUnicodeBitmapFont::GetGlyphMetrics(S32 glyph, IggyGlyphMetrics *metrics)
|
||||
{
|
||||
if (glyph < 0 || glyph >= 65536) { metrics->x0 = metrics->x1 = metrics->advance = metrics->y0 = metrics->y1 = 0; return metrics; }
|
||||
int left = m_unicodeWidth[glyph] >> 4;
|
||||
int right = (m_unicodeWidth[glyph] & 0xF) + 1;
|
||||
float pixelWidth = (right - left) / 2.0f + 1.0f;
|
||||
float advance = pixelWidth * m_referenceFontData->m_fAdvPerPixel;
|
||||
|
||||
metrics->x0 = 0.0f;
|
||||
metrics->x1 = advance;
|
||||
metrics->advance = advance;
|
||||
metrics->y0 = 0.0f;
|
||||
metrics->y1 = 1.0f;
|
||||
return metrics;
|
||||
}
|
||||
|
||||
rrbool UIUnicodeBitmapFont::IsGlyphEmpty(S32 glyph)
|
||||
{
|
||||
if (glyph < 0 || glyph >= 65536) return true;
|
||||
return m_unicodeWidth[glyph] == 0;
|
||||
}
|
||||
|
||||
F32 UIUnicodeBitmapFont::GetKerningForGlyphPair(S32 first_glyph, S32 second_glyph)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
rrbool UIUnicodeBitmapFont::CanProvideBitmap(S32 glyph, F32 pixel_scale)
|
||||
{
|
||||
return glyph >= 0 && glyph < 65536;
|
||||
}
|
||||
|
||||
rrbool UIUnicodeBitmapFont::GetGlyphBitmap(S32 glyph, F32 pixel_scale, IggyBitmapCharacter *bitmap)
|
||||
{
|
||||
if (glyph < 0 || glyph >= 65536) return false;
|
||||
int page = glyph / 256;
|
||||
if (!m_glyphPages[page])
|
||||
{
|
||||
loadGlyphPage(page);
|
||||
if (!m_glyphPages[page]) return false;
|
||||
}
|
||||
|
||||
int cx = (glyph % 16) * 16;
|
||||
int cy = ((glyph & 0xFF) / 16) * 16;
|
||||
|
||||
bitmap->pixels_one_per_byte = m_glyphPages[page] + (cy * 256) + cx;
|
||||
bitmap->width_in_pixels = 16;
|
||||
bitmap->height_in_pixels = 16;
|
||||
bitmap->stride_in_bytes = 256;
|
||||
|
||||
bitmap->top_left_x = 0;
|
||||
bitmap->top_left_y = -static_cast<S32>(16) * m_referenceFontData->m_fAscent;
|
||||
|
||||
bitmap->oversample = 0;
|
||||
|
||||
// Scale parameters: match UIBitmapFont's approach.
|
||||
// truePixelScale = the pixel_scale at which 1 glyph pixel = 1 screen pixel.
|
||||
// For 16px glyphs displayed at the same visual size as Mojangles_7 (8px glyphs with advPerPixel 1/10):
|
||||
// The reference truePixelScale for Mojangles_7 is 1.0f/m_fAdvPerPixel = 10.0f
|
||||
// Since our glyphs are 16px (2x the Mojangles 8px), our truePixelScale is 20.0f
|
||||
float truePixelScale = 2.0f / m_referenceFontData->m_fAdvPerPixel;
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
bitmap->pixel_scale_correct = truePixelScale;
|
||||
if (pixel_scale < truePixelScale)
|
||||
{
|
||||
bitmap->pixel_scale_min = 0.0f;
|
||||
bitmap->pixel_scale_max = truePixelScale;
|
||||
bitmap->point_sample = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmap->pixel_scale_min = truePixelScale;
|
||||
bitmap->pixel_scale_max = 99.0f;
|
||||
bitmap->point_sample = true;
|
||||
}
|
||||
#else
|
||||
float glyphScale = 1.0f;
|
||||
while ((0.5f + glyphScale) * truePixelScale < pixel_scale)
|
||||
glyphScale++;
|
||||
|
||||
if (glyphScale <= 1 && pixel_scale < truePixelScale)
|
||||
{
|
||||
bitmap->pixel_scale_correct = truePixelScale;
|
||||
bitmap->pixel_scale_min = 0.0f;
|
||||
bitmap->pixel_scale_max = truePixelScale * 1.001f;
|
||||
bitmap->point_sample = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
float actualScale = pixel_scale / glyphScale;
|
||||
bitmap->pixel_scale_correct = actualScale;
|
||||
bitmap->pixel_scale_min = truePixelScale;
|
||||
bitmap->pixel_scale_max = 99.0f;
|
||||
bitmap->point_sample = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bitmap->user_context_for_free = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIUnicodeBitmapFont::FreeGlyphBitmap(S32 glyph, F32 pixel_scale, IggyBitmapCharacter *bitmap)
|
||||
{
|
||||
// Pixel data lives in m_glyphPages -- nothing to free.
|
||||
}
|
||||
27
Minecraft.Client/Common/UI/UIUnicodeBitmapFont.h
Normal file
27
Minecraft.Client/Common/UI/UIUnicodeBitmapFont.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#pragma once
|
||||
#include "UIBitmapFont.h"
|
||||
|
||||
struct SFontData;
|
||||
|
||||
class UIUnicodeBitmapFont : public UIAbstractBitmapFont
|
||||
{
|
||||
private:
|
||||
unsigned char m_unicodeWidth[65536];
|
||||
unsigned char* m_glyphPages[256];
|
||||
SFontData* m_referenceFontData;
|
||||
|
||||
void loadGlyphPage(int page);
|
||||
|
||||
public:
|
||||
UIUnicodeBitmapFont(const string &fontname, SFontData &referenceFontData);
|
||||
~UIUnicodeBitmapFont();
|
||||
|
||||
virtual IggyFontMetrics *GetFontMetrics(IggyFontMetrics *metrics);
|
||||
virtual S32 GetCodepointGlyph(U32 codepoint);
|
||||
virtual IggyGlyphMetrics *GetGlyphMetrics(S32 glyph, IggyGlyphMetrics *metrics);
|
||||
virtual rrbool IsGlyphEmpty(S32 glyph);
|
||||
virtual F32 GetKerningForGlyphPair(S32 first_glyph, S32 second_glyph);
|
||||
virtual rrbool CanProvideBitmap(S32 glyph, F32 pixel_scale);
|
||||
virtual rrbool GetGlyphBitmap(S32 glyph, F32 pixel_scale, IggyBitmapCharacter *bitmap);
|
||||
virtual void FreeGlyphBitmap(S32 glyph, F32 pixel_scale, IggyBitmapCharacter *bitmap);
|
||||
};
|
||||
|
|
@ -16,7 +16,7 @@ Font::Font(Options *options, const wstring& name, Textures* textures, bool enfor
|
|||
charWidths = new int[charC];
|
||||
|
||||
// 4J - added initialisers
|
||||
memset(charWidths, 0, charC);
|
||||
memset(charWidths, 0, charC * sizeof(int));
|
||||
|
||||
enforceUnicodeSheet = false;
|
||||
bidirectional = false;
|
||||
|
|
@ -26,6 +26,19 @@ Font::Font(Options *options, const wstring& name, Textures* textures, bool enfor
|
|||
m_underline = false;
|
||||
m_strikethrough = false;
|
||||
|
||||
memset(unicodeTexID, 0, sizeof(unicodeTexID));
|
||||
memset(unicodeWidth, 0, sizeof(unicodeWidth));
|
||||
lastBoundTexture = 0;
|
||||
|
||||
// Load unicode glyph sizes
|
||||
FILE *glyphFile = nullptr;
|
||||
fopen_s(&glyphFile, "Common/res/1_2_2/font/glyph_sizes.bin", "rb");
|
||||
if (glyphFile)
|
||||
{
|
||||
fread(unicodeWidth, 1, 65536, glyphFile);
|
||||
fclose(glyphFile);
|
||||
}
|
||||
|
||||
// Set up member variables
|
||||
m_cols = cols;
|
||||
m_rows = rows;
|
||||
|
|
@ -261,7 +274,19 @@ void Font::drawLiteral(const wstring& str, int x, int y, int color)
|
|||
yPos = static_cast<float>(y);
|
||||
wstring cleanStr = sanitize(str);
|
||||
for (size_t i = 0; i < cleanStr.length(); ++i)
|
||||
renderCharacter(cleanStr.at(i));
|
||||
{
|
||||
wchar_t c = cleanStr.at(i);
|
||||
if (isUnicodeGlyphChar(c))
|
||||
{
|
||||
renderUnicodeCharacter(c);
|
||||
textures->bindTexture(m_textureLocation);
|
||||
lastBoundTexture = fontTexture;
|
||||
}
|
||||
else
|
||||
{
|
||||
renderCharacter(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Font::drawShadowWordWrap(const wstring &str, int x, int y, int w, int color, int h)
|
||||
|
|
@ -345,7 +370,7 @@ void Font::draw(const wstring &str, bool dropShadow)
|
|||
}
|
||||
|
||||
// "noise" for crazy splash screen message
|
||||
if (noise)
|
||||
if (noise && !isUnicodeGlyphChar(c))
|
||||
{
|
||||
int newc;
|
||||
do
|
||||
|
|
@ -355,7 +380,18 @@ void Font::draw(const wstring &str, bool dropShadow)
|
|||
c = newc;
|
||||
}
|
||||
|
||||
addCharacterQuad(c);
|
||||
if (isUnicodeGlyphChar(c))
|
||||
{
|
||||
t->end();
|
||||
renderUnicodeCharacter(c);
|
||||
textures->bindTexture(m_textureLocation);
|
||||
lastBoundTexture = fontTexture;
|
||||
t->begin();
|
||||
}
|
||||
else
|
||||
{
|
||||
addCharacterQuad(c);
|
||||
}
|
||||
}
|
||||
|
||||
t->end();
|
||||
|
|
@ -396,11 +432,22 @@ int Font::width(const wstring& str)
|
|||
++i;
|
||||
else
|
||||
{
|
||||
len += charWidths[167];
|
||||
if (isUnicodeGlyphChar(167))
|
||||
len += (int)unicodeCharWidth(167);
|
||||
else
|
||||
len += charWidths[167];
|
||||
if (i + 1 < cleanStr.length())
|
||||
len += charWidths[static_cast<unsigned>(cleanStr[++i])];
|
||||
{
|
||||
wchar_t nextC = cleanStr[++i];
|
||||
if (isUnicodeGlyphChar(nextC))
|
||||
len += (int)unicodeCharWidth(nextC);
|
||||
else if (static_cast<unsigned>(nextC) < static_cast<unsigned>(m_cols * m_rows))
|
||||
len += charWidths[static_cast<unsigned>(nextC)];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isUnicodeGlyphChar(c))
|
||||
len += (int)unicodeCharWidth(c);
|
||||
else
|
||||
len += charWidths[c];
|
||||
}
|
||||
|
|
@ -414,7 +461,13 @@ int Font::widthLiteral(const wstring& str)
|
|||
if (cleanStr == L"") return 0;
|
||||
int len = 0;
|
||||
for (size_t i = 0; i < cleanStr.length(); ++i)
|
||||
len += charWidths[static_cast<unsigned>(cleanStr.at(i))];
|
||||
{
|
||||
wchar_t wc = cleanStr.at(i);
|
||||
if (isUnicodeGlyphChar(wc))
|
||||
len += (int)unicodeCharWidth(wc);
|
||||
else
|
||||
len += charWidths[static_cast<unsigned>(wc)];
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
@ -428,6 +481,10 @@ wstring Font::sanitize(const wstring& str)
|
|||
{
|
||||
sb[i] = MapCharacter(sb[i]);
|
||||
}
|
||||
else if (unicodeWidth[sb[i]] != 0)
|
||||
{
|
||||
// Leave as-is: raw codepoint for glyph page rendering
|
||||
}
|
||||
else
|
||||
{
|
||||
// If this character isn't supported, just show the first character (empty square box character)
|
||||
|
|
@ -671,33 +728,22 @@ void Font::renderFakeCB(IntBuffer *ib)
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void Font::loadUnicodePage(int page)
|
||||
{
|
||||
wchar_t fileName[25];
|
||||
//String fileName = String.format("/1_2_2/font/glyph_%02X.png", page);
|
||||
swprintf(fileName,25,L"/1_2_2/font/glyph_%02X.png",page);
|
||||
wchar_t fileName[40];
|
||||
swprintf(fileName, 40, L"/1_2_2/font/glyph_%02X.png", page);
|
||||
BufferedImage *image = new BufferedImage(fileName);
|
||||
//try
|
||||
//{
|
||||
// image = ImageIO.read(Textures.class.getResourceAsStream(fileName.toString()));
|
||||
//}
|
||||
//catch (IOException e)
|
||||
//{
|
||||
// throw new RuntimeException(e);
|
||||
//}
|
||||
|
||||
unicodeTexID[page] = textures->getTexture(image);
|
||||
lastBoundTexture = unicodeTexID[page];
|
||||
delete image;
|
||||
}
|
||||
|
||||
void Font::renderUnicodeCharacter(wchar_t c)
|
||||
{
|
||||
if (unicodeWidth[c] == 0)
|
||||
{
|
||||
// System.out.println("no-width char " + c);
|
||||
return;
|
||||
}
|
||||
|
||||
int page = c / 256;
|
||||
|
||||
|
|
@ -709,19 +755,17 @@ void Font::renderUnicodeCharacter(wchar_t c)
|
|||
lastBoundTexture = unicodeTexID[page];
|
||||
}
|
||||
|
||||
// first column with non-trans pixels
|
||||
int firstLeft = unicodeWidth[c] >> 4;
|
||||
// last column with non-trans pixels
|
||||
int firstRight = unicodeWidth[c] & 0xF;
|
||||
|
||||
float left = firstLeft;
|
||||
float right = firstRight + 1;
|
||||
float left = (float)firstLeft;
|
||||
float right = (float)(firstRight + 1);
|
||||
|
||||
float xOff = c % 16 * 16 + left;
|
||||
float yOff = (c & 0xFF) / 16 * 16;
|
||||
float xOff = (c % 16) * 16 + left;
|
||||
float yOff = ((c & 0xFF) / 16) * 16;
|
||||
float width = right - left - .02f;
|
||||
|
||||
Tesselator *t = Tesselator::getInstance();
|
||||
Tesselator *t = Tesselator::getInstance();
|
||||
t->begin(GL_TRIANGLE_STRIP);
|
||||
t->tex(xOff / 256.0F, yOff / 256.0F);
|
||||
t->vertex(xPos, yPos, 0.0f);
|
||||
|
|
@ -735,5 +779,17 @@ void Font::renderUnicodeCharacter(wchar_t c)
|
|||
|
||||
xPos += (right - left) / 2 + 1;
|
||||
}
|
||||
*/
|
||||
|
||||
float Font::unicodeCharWidth(wchar_t c)
|
||||
{
|
||||
if (unicodeWidth[c] == 0) return 0;
|
||||
int firstLeft = unicodeWidth[c] >> 4;
|
||||
int firstRight = unicodeWidth[c] & 0xF;
|
||||
return (firstRight + 1 - firstLeft) / 2.0f + 1;
|
||||
}
|
||||
|
||||
bool Font::isUnicodeGlyphChar(wchar_t c)
|
||||
{
|
||||
return c >= m_cols * m_rows && unicodeWidth[c] != 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@ private:
|
|||
|
||||
Textures *textures;
|
||||
|
||||
int unicodeTexID[256];
|
||||
unsigned char unicodeWidth[65536];
|
||||
int lastBoundTexture;
|
||||
|
||||
float xPos;
|
||||
float yPos;
|
||||
|
||||
|
|
@ -70,6 +74,10 @@ private:
|
|||
void drawLiteral(const wstring& str, int x, int y, int color); // no § parsing
|
||||
int MapCharacter(wchar_t c); // 4J added
|
||||
bool CharacterExists(wchar_t c); // 4J added
|
||||
void loadUnicodePage(int page);
|
||||
void renderUnicodeCharacter(wchar_t c);
|
||||
float unicodeCharWidth(wchar_t c);
|
||||
bool isUnicodeGlyphChar(wchar_t c);
|
||||
|
||||
public:
|
||||
int width(const wstring& str);
|
||||
|
|
|
|||
|
|
@ -1386,6 +1386,9 @@ void Gui::clearMessages(int iPad)
|
|||
|
||||
void Gui::addMessage(const wstring& _string,int iPad,bool bIsDeathMessage)
|
||||
{
|
||||
{ char buf[32]; sprintf_s(buf, "[CHAT] Display (pad=%d): ", iPad); OutputDebugStringA(buf); }
|
||||
OutputDebugStringW(_string.c_str());
|
||||
OutputDebugStringA("\n");
|
||||
wstring string = _string; // 4J - Take copy of input as it is const
|
||||
//int iScale=1;
|
||||
|
||||
|
|
|
|||
|
|
@ -6894,6 +6894,22 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
|
|||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|PSVita'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|PSVita'">false</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common\UI\UIUnicodeBitmapFont.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|Xbox 360'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Xbox 360'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|Xbox 360'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|Xbox 360'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Xbox 360'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Xbox 360'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Xbox 360'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|PSVita'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|PSVita'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|PSVita'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|PSVita'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|PSVita'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|PSVita'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|PSVita'">false</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common\UI\UIComponent_Chat.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Xbox 360'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Xbox 360'">true</ExcludedFromBuild>
|
||||
|
|
@ -29623,6 +29639,22 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
|
|||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|PSVita'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|PSVita'">false</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Common\UI\UIUnicodeBitmapFont.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|Xbox 360'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Xbox 360'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|Xbox 360'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|Xbox 360'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Xbox 360'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Xbox 360'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Xbox 360'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|PSVita'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|PSVita'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|PSVita'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|PSVita'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|PSVita'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|PSVita'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|PSVita'">false</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Common\UI\UIComponent_Chat.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Xbox 360'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Xbox 360'">true</ExcludedFromBuild>
|
||||
|
|
|
|||
|
|
@ -2953,6 +2953,9 @@
|
|||
<ClInclude Include="Common\UI\UIBitmapFont.h">
|
||||
<Filter>Common\Source Files\UI</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common\UI\UIUnicodeBitmapFont.h">
|
||||
<Filter>Common\Source Files\UI</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common\UI\UITTFFont.h">
|
||||
<Filter>Common\Source Files\UI</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -5199,6 +5202,9 @@
|
|||
<ClCompile Include="Common\UI\UIBitmapFont.cpp">
|
||||
<Filter>Common\Source Files\UI</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Common\UI\UIUnicodeBitmapFont.cpp">
|
||||
<Filter>Common\Source Files\UI</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Common\UI\UITTFFont.cpp">
|
||||
<Filter>Common\Source Files\UI</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -506,7 +506,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
break;
|
||||
|
||||
default:
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
return DefWindowProcW(hWnd, message, wParam, lParam);
|
||||
}
|
||||
break;
|
||||
case WM_PAINT:
|
||||
|
|
@ -563,7 +563,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
else if (vk == VK_MENU)
|
||||
vk = (lParam & (1 << 24)) ? VK_RMENU : VK_LMENU;
|
||||
g_KBMInput.OnKeyDown(vk);
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
return DefWindowProcW(hWnd, message, wParam, lParam);
|
||||
}
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYUP:
|
||||
|
|
@ -661,7 +661,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
break;
|
||||
default:
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
return DefWindowProcW(hWnd, message, wParam, lParam);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -673,23 +673,23 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
//
|
||||
ATOM MyRegisterClass(HINSTANCE hInstance)
|
||||
{
|
||||
WNDCLASSEX wcex;
|
||||
WNDCLASSEXW wcex;
|
||||
|
||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||
wcex.cbSize = sizeof(WNDCLASSEXW);
|
||||
|
||||
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wcex.lpfnWndProc = WndProc;
|
||||
wcex.cbClsExtra = 0;
|
||||
wcex.cbWndExtra = 0;
|
||||
wcex.hInstance = hInstance;
|
||||
wcex.hIcon = LoadIcon(hInstance, "Minecraft");
|
||||
wcex.hIcon = LoadIconW(hInstance, L"Minecraft");
|
||||
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
|
||||
wcex.lpszMenuName = "Minecraft";
|
||||
wcex.lpszClassName = "MinecraftClass";
|
||||
wcex.lpszMenuName = L"Minecraft";
|
||||
wcex.lpszClassName = L"MinecraftClass";
|
||||
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_MINECRAFTWINDOWS));
|
||||
|
||||
return RegisterClassEx(&wcex);
|
||||
return RegisterClassExW(&wcex);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -709,8 +709,8 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
|
|||
RECT wr = {0, 0, g_rScreenWidth, g_rScreenHeight}; // set the size, but not the position
|
||||
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); // adjust the size
|
||||
|
||||
g_hWnd = CreateWindow( "MinecraftClass",
|
||||
"Minecraft",
|
||||
g_hWnd = CreateWindowW( L"MinecraftClass",
|
||||
L"Minecraft",
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT,
|
||||
0,
|
||||
|
|
|
|||
|
|
@ -260,6 +260,7 @@
|
|||
<ClCompile Include="..\Minecraft.Client\Common\UI\IUIScene_StartGame.cpp" />
|
||||
<ClCompile Include="..\Minecraft.Client\Common\UI\IUIScene_TradingMenu.cpp" />
|
||||
<ClCompile Include="..\Minecraft.Client\Common\UI\UIBitmapFont.cpp" />
|
||||
<ClCompile Include="..\Minecraft.Client\Common\UI\UIUnicodeBitmapFont.cpp" />
|
||||
<ClCompile Include="..\Minecraft.Client\Common\UI\UIComponent_Chat.cpp" />
|
||||
<ClCompile Include="..\Minecraft.Client\Common\UI\UIComponent_DebugUIConsole.cpp" />
|
||||
<ClCompile Include="..\Minecraft.Client\Common\UI\UIComponent_DebugUIMarketingGuide.cpp" />
|
||||
|
|
|
|||
|
|
@ -50,11 +50,10 @@ void SignTileEntity::save(CompoundTag *tag)
|
|||
tag->putString(L"Text3", m_wsmessages[2] );
|
||||
tag->putString(L"Text4", m_wsmessages[3] );
|
||||
#ifndef _CONTENT_PACKAGE
|
||||
OutputDebugStringW(L"### - Saving a sign with text - \n");
|
||||
app.DebugPrintf("[SIGN] Saving sign at (%d, %d, %d):\n", x, y, z);
|
||||
for(int i=0;i<4;i++)
|
||||
{
|
||||
OutputDebugStringW(m_wsmessages[i].c_str());
|
||||
OutputDebugStringW(L"\n");
|
||||
app.DebugPrintf("[SIGN] Line%d: \"%ls\"\n", i+1, m_wsmessages[i].c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -65,8 +64,8 @@ void SignTileEntity::load(CompoundTag *tag)
|
|||
TileEntity::load(tag);
|
||||
for (int i = 0; i < MAX_SIGN_LINES; i++)
|
||||
{
|
||||
wchar_t *buf = new wchar_t[256];
|
||||
swprintf(buf, 256, L"Text%d", (i+1) );
|
||||
wchar_t buf[16];
|
||||
swprintf(buf, 16, L"Text%d", (i+1) );
|
||||
m_wsmessages[i] = tag->getString( buf );
|
||||
if (m_wsmessages[i].length() > MAX_LINE_LENGTH) m_wsmessages[i] = m_wsmessages[i].substr(0, MAX_LINE_LENGTH);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue