MANGOS的程序架构没有考虑多语种支持,给我们带来了不少麻烦~
----------------------------------------
目前的做法:
汉化源码->记事本转存UTF-8->字符串首尾加空格(UTF-8格式保存)->VS2003编译->中文完美显示
此方法只适用于VS2003 (VS2005中文无法完整显示),操作繁琐,转化后的源码不直观不便修改...
----------------------------------------
本人对C++不太熟,经过一段时间摸索,找到了一个解决此问题的方法,而且对已完成的汉化内容不用做任何修改即可生效,暂且叫最懒解决方案吧 --__--|||
我发现MANGOS向客户端发送文本的都是UTF-8编码的,经过调试发现VS2005编译后的源码在发送前就已经存在问题了,也就是说用VS2005编译的含有外部工具转换后的UTF-8编码的中文字符的源码并不能保证中文部分的完整性,具体内在原因我没有再深入查下去...就算查下去也不太可能修改VS2005的编译方式~~~
验证此问题可用如下代码:
cpp 代码
-
#include "stdafx.h"
-
#include <iostream>
#include <string>
#include <windows.h>
using namespace std;
-
-
void UTF_8ToUnicode(wchar_t* pOut,char *pText)
-
{
-
char* uchar = (char *)pOut;
-
-
uchar[1] = ((pText[0] & 0x0F) << 4) + ((pText[1] >> 2) & 0x0F);
-
uchar[0] = ((pText[1] & 0x03) << 6) + (pText[2] & 0x3F);
-
-
return;
-
}
-
-
void UnicodeToUTF_8(char* pOut,wchar_t* pText)
-
{
-
char* pchar = (char *)pText;
-
-
pOut[0] = (0xE0 | ((pchar[1] & 0xF0) >> 4));
-
pOut[1] = (0x80 | ((pchar[1] & 0x0F) << 2)) + ((pchar[0] & 0xC0) >> 6);
-
pOut[2] = (0x80 | (pchar[0] & 0x3F));
-
-
return;
-
}
-
-
void UnicodeToGB2312(char* pOut,wchar_t uData)
-
{
-
WideCharToMultiByte(CP_ACP,NULL,&uData,1,pOut,sizeof(wchar_t),NULL,NULL);
-
return;
-
}
-
-
void Gb2312ToUnicode(wchar_t* pOut,char *gbBuffer)
-
{
-
MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,gbBuffer,2,pOut,1);
-
return ;
-
}
-
-
void GB2312ToUTF_8(string& pOut,char *pText, int pLen)
-
{
-
char buf[4];
-
int nLength = pLen* 3;
-
char* rst = new char[nLength];
-
-
memset(buf,0,4);
-
memset(rst,0,nLength);
-
-
int i = 0;
-
int j = 0;
-
while(i < pLen)
-
{
-
if( *(pText + i) >= 0)
-
{
-
rst[j++] = pText[i++];
-
}
-
else
-
{
-
wchar_t pbuffer;
-
Gb2312ToUnicode(&pbuffer,pText+i);
-
-
UnicodeToUTF_8(buf,&pbuffer);
-
-
unsigned short int tmp = 0;
-
tmp = rst[j] = buf[0];
-
tmp = rst[j+1] = buf[1];
-
tmp = rst[j+2] = buf[2];
-
-
j += 3;
-
i += 2;
-
}
-
}
-
rst[j] = '\0';
-
-
pOut = rst;
-
delete []rst;
-
-
return;
-
}
-
-
void UTF_8ToGB2312(string &pOut, char *pText, int pLen)
-
{
-
char * newBuf = new char[pLen];
-
char Ctemp[4];
-
memset(Ctemp,0,4);
-
-
int i =0;
-
int j = 0;
-
-
while(i < pLen)
-
{
-
if(pText[i] > 0)
-
{
-
newBuf[j++] = pText[i++];
-
}
-
else
-
{
-
WCHAR Wtemp;
-
UTF_8ToUnicode(&Wtemp,pText + i);
-
-
UnicodeToGB2312(Ctemp,Wtemp);
-
-
newBuf[j] = Ctemp[0];
-
newBuf[j + 1] = Ctemp[1];
-
-
i += 3;
-
j += 2;
-
}
-
}
-
newBuf[j] = '\0';
-
-
pOut = newBuf;
-
delete []newBuf;
-
-
return;
-
}
-
-
int _tmain(int argc, _TCHAR* argv[])
-
{
-
string strIN = " 管理员 ";
-
cout << "init 0 : " << strIN << endl;
-
string strOUT;
-
cout << ". GB2312 -> UTF-8 ." << endl;
-
char *chr1 = (char *)strIN.c_str();
-
GB2312ToUTF_8(strOUT, chr1, strlen(chr1));
-
cout << strOUT << endl;
-
cout << ". UTF-8 -> GB2312 ." << endl;
-
-
char *chr2 = (char *)strOUT.c_str();
-
UTF_8ToGB2312(strOUT, chr2, strlen(chr2));
-
cout << "test 1 : " << strOUT << endl;
-
-
char *chr3 = " 绠$悊鍛 ";
-
UTF_8ToGB2312(strOUT, chr3, strlen(chr3));
-
cout << "test 2 : " << strOUT << endl;
-
return 0;
-
}
VS2005编译后 test 2 的输出结果并不是“管理员” --__--|||
----------------------------------------
问题找到了,接下来就是解决问题,既然VS2005不能完美编译预先转换后的中文源码,那就改写这部分的处理方式即可。
顺着这条思路我找到了GossipDef.cpp的void PlayerMenu::SendGossipMenu( uint32 TitleTextId, uint64 npcGUID)方法,这是MANGOS服务端向客户端输出对话界面的最终出口,在这里做一些改写即可达到目的,改写后的代码如下:
----------------------------------------
cpp 代码
-
...
-
-
void PlayerMenu::SendGossipMenu( uint32 TitleTextId, uint64 npcGUID )
-
{
-
WorldPacket data( SMSG_GOSSIP_MESSAGE, (100) );
-
data << npcGUID;
-
data << uint32( TitleTextId );
-
data << uint32( pGossipMenu->MenuItemCount() );
-
-
for ( unsigned int iI = 0; iI < pGossipMenu->MenuItemCount(); iI++ )
-
{
-
data << uint32( iI );
-
data << uint8( pGossipMenu->GetItem(iI).m_gIcon );
-
data << uint8( pGossipMenu->GetItem(iI).m_gCoded );
-
data << uint32(0);
-
-
-
-
std::string str = pGossipMenu->GetItem(iI).m_gMessage;
-
if(str[0] == ' '){
-
char *chr = (char *)str.c_str();
-
TyreCodeTransformer::GB2312ToUTF_8(str, chr, strlen(chr));
-
}
-
data << str;
-
-
-
-
data << uint8(0);
-
}
-
-
data << uint32( pQuestMenu->MenuItemCount() );
-
-
for ( uint16 iI = 0; iI < pQuestMenu->MenuItemCount(); iI++ )
-
{
-
uint32 questID = pQuestMenu->GetItem(iI).m_qId;
-
Quest const* pQuest = objmgr.GetQuestTemplate(questID);
-
-
data << questID;
-
data << uint32( pQuestMenu->GetItem(iI).m_qIcon );
-
data << uint32( pQuest ? pQuest->GetQuestLevel() : 0 );
-
std::string Title = pQuest->GetTitle();
-
if (pSession->GetSessionLanguage()>0)
-
{
-
QuestLocale const *ql = objmgr.GetQuestLocale(questID);
-
if (ql)
-
{
-
if (ql->Title[pSession->GetSessionLanguage()]!="")
-
Title=ql->Title[pSession->GetSessionLanguage()];
-
}
-
}
-
data << Title;
-
}
-
-
pSession->SendPacket( &data );
-
}
-
-
...
----------------------------------------
大家可能注意到了
if(str[0] == ' '){ // 根据首字符是否为空格来判断是否需要转换
因为PlayerMenu::SendGossipMenu是处理源码与数据库中数据的统一出口,对于原本就是UTF-8编码的数据不能进行再次转换,不然会产生乱码。为了便于区分加上根据之前的习惯,汉化后的字符串前后都已经加上了空格,根据这一特点决定了用此方式来区分是否需要转换,也可以换种方式加上字符串编码分析然后再做区分判断(可扩展为多语种支持),暂时不搞了,以后再说吧~
此方式通过扩展是可以支持多语种的,但是将内容文本HardCode进源码的味道很不好~,还是等待MANGOS团队对代码做整体更新吧,另外MANGOS的文本输出接口可能不只这一个PlayerMenu::SendGossipMenu,等发现了其它接口用同样方法修改即可。。。
呵呵!不求最好!只求最懒!如果有更好的方法请大家和我联系 QQ 15149077 泛开源技术研究群 40635510 !
----------------------------------------
总结最懒解决方案:
汉化源码->字符串首加空格(GB2312/UTF-8格式保存)->VS2003/2005编译->中文完美显示
----------------------------------------
不知道MANGOS是什么? 去这里看看就知道了 http://www.mangosproject.org
----------------------------------------
分享到:
相关推荐
总之,Linux MaNGOS-0.14.tar.gz 是一个为魔兽世界爱好者准备的开源游戏服务器解决方案。它基于Linux系统,提供了一套完整的模拟环境,允许用户自行搭建和管理游戏服务器,享受高度定制化的游戏体验。尽管安装和配置...
6. **社区支持**:mangos项目有一个活跃的开发者和用户社区,他们共享资源、解决问题,并持续改进项目,为用户提供帮助和指导。 7. **可扩展性**:由于是开源项目,mangos 0.16允许开发者根据自己的需求进行定制,...
《Mangos 0.13 9506:构建你的魔兽世界模拟服务器》 "Mangos_0.13_9506_MangOS9506_" 是一个针对魔兽世界模拟服务器的软件版本,这个版本是Mangos项目的一个重要里程碑。Mangos是一个开源的、免费的、基于Linux的...
此外,调试工具和日志分析也是关键技能,帮助解决问题并优化服务器性能。 7. **社区支持**: 作为一个开源项目,Mangos拥有活跃的开发者和用户社区,他们通过论坛、邮件列表和IRC频道分享经验、解决遇到的问题。...
2. **编译错误**:检查VS2010的错误列表,根据错误信息解决问题。可能是缺少头文件、链接错误或其他编译设置不正确。 3. **数据库连接问题**:确认MySQL服务运行正常,数据库配置无误,且Mangos有权限访问。 总的来...
mangos项目始于2005年,旨在为魔兽世界提供一个免费、可定制的服务器解决方案。它的核心目标是模拟原版游戏服务器的行为,包括玩家交互、地图数据处理、战斗逻辑、任务系统等多个方面。这个项目不仅吸引了众多的...
《mangos分析笔记》是关于开源游戏服务器端软件Mangos的一系列研究记录,旨在与读者分享作者在深入理解Mangos过程中所积累的知识和经验。Mangos是一款用于模拟暴雪公司大型多人在线角色扮演游戏(MMORPG)《魔兽世界...
mangos支持多种数据库系统,最常用的是MySQL。通过MySQL存储游戏数据,如角色信息、物品属性等,确保数据的一致性和安全性。 **3. 扩展脚本** 游戏内容、任务脚本等是由扩展脚本实现的,这些脚本可以使用Lua等脚本...
mangos 项目背后有一个活跃的开发者和用户社区,他们共享资源,解决问题,并推动项目的更新。用户可以通过参与社区讨论,获得技术支持,甚至参与到项目的开发中,贡献自己的代码。此外,基于 mangos 的二次开发也...
魔兽世界MANGOS数据库分析
mangos不是一个魔兽私服模拟器,它是一个开源的自由软件项目,是用c++和C#编程语言,实现的一个支持大型多人在线角色扮演游戏服务器的程序框架,在这个框架下,它理论上应该支持任何客户端的网络游戏,由于现在很多...
总结来说,MangOS 0.13 9183版是针对魔兽世界3.0.3客户端的一个强大私人服务器解决方案,它提供了一套完整的框架,让开发者可以构建自己的游戏环境。通过深入了解其核心升级和使用方法,我们可以更好地利用这个工具...
mangos服务器架构.pdf Mangos服务器架构是一种游戏服务器架构,主要用于游戏服务器的设计和实现。该架构的核心组件包括登录服、游戏服和数据库等。登录服是游戏服务器的入口,负责验证用户的账号和密码,并提供...
### 从零开始编译MaNGOS芒果服务端——魔兽世界的自建服务器之旅 #### 一、准备工作 在开始之前,我们需要确保所有的前置工作已经准备就绪,这包括必要的开发工具和环境搭建。 ##### 1.1 .NET Framework 3.5 的...
主数据库:trinitydatabase ============================================= achievement_reward 巫妖王的奖励成就 areatrigger_involvedrelation 传送(区域触发)_包含的任务关系 areatrigger_scripts 区域触发脚本 ...
MaNGOS是“Many Gates to Nowhere”的缩写,它是一个由社区驱动的项目,旨在提供一个高效、稳定的游戏服务器解决方案。MaNGOS的目标是使非专业开发者也能搭建和管理自己的魔兽世界服务器,从而为玩家提供一个自定义...
mangos不是一个魔兽私服模拟器,它是一个开源的自由软件项目,是用c++和C#编程语言,实现的一个支持大型多人在线角色扮演游戏服务器的程序框架,在这个框架下,它理论上应该支持任何客户端的网络游戏,由于现在很多...
《MangOS 0.13与客户端3.0.9升级详解》 MangOS 0.13是一款开放源代码的大型多人在线角色扮演游戏(MMORPG)服务器软件,其核心设计目标是为游戏开发者提供一个高效、可扩展且易于维护的平台。此次发布的"MangOS_...
通过深入学习Go-mangos,你将能够构建出高效、可靠且可扩展的分布式系统,充分利用Go语言的特性来解决复杂的消息传递问题。在实际项目中,Go-mangos可以用于构建微服务架构、事件驱动系统或者作为异步任务队列的基础...
总的来说,Mangos Zero Server x64 Release是一个为魔兽世界怀旧服爱好者量身定制的解决方案,它将经典游戏体验与现代技术相结合,提供了一个可高度自定义的平台,使玩家可以在自己的服务器上重温那些难忘的冒险时光...