I haven’t noticed any rename oddities, but I am also using a patched version of the 1.5.5 rename.
The two major changes I made were to save the character before the rename and to use flnew instead of new to allocate memory for the character names (this fixes FLServer crashing upon shutdown).
For those interested:
HK_ERROR HkRename(wstring wscCharname, wstring wscNewCharname, bool bOnlyDelete)
{
HkSaveChar(wscCharname); //Fixes weird rename behavior
HK_GET_CLIENTID(iClientID, wscCharname);
if((iClientID == -1) && !HkGetAccountByCharname(wscCharname))
return HKE_CHAR_DOES_NOT_EXIST;
if(!bOnlyDelete && HkGetAccountByCharname(wscNewCharname))
return HKE_CHARNAME_ALREADY_EXISTS;
if(!bOnlyDelete && (wscNewCharname.length() > 23))
return HKE_CHARNAME_TOO_LONG;
if(!bOnlyDelete && !wscNewCharname.length())
return HKE_CHARNAME_TOO_SHORT;
CAccount *acc;
wstring wscOldCharname;
if(iClientID != -1) {
acc = Players.FindAccountFromClientID(iClientID);
wscOldCharname = Players.GetActiveCharacterName(iClientID);
} else {
wscOldCharname = wscCharname;
acc = HkGetAccountByCharname(wscCharname);
}
wstring wscAccountDirname;
if(!HKHKSUCCESS(HkGetAccountDirName(acc, wscAccountDirname)) || !wscAccountDirname.length())//Could not get account dir name
return HKE_COULD_NOT_GET_PATH;
wstring wscNewFilename;
if(!bOnlyDelete && (!HKHKSUCCESS(HkGetCharFileName(wscNewCharname, wscNewFilename)) || !wscNewFilename.length()))//Could not get filename of new char
return HKE_COULD_NOT_GET_PATH;
wstring wscOldFilename;
if(!HKHKSUCCESS(HkGetCharFileName(wscOldCharname, wscOldFilename)) || !wscOldFilename.length())
return HKE_COULD_NOT_GET_PATH;
string scNewCharfilePath = scAcctPath + wstos(wscAccountDirname) + "\\" + wstos(wscNewFilename) + ".fl";
string scOldCharfilePath = scAcctPath + wstos(wscAccountDirname) + "\\" + wstos(wscOldFilename) + ".fl";
if(!bOnlyDelete)
{
if(!flc_decode(scOldCharfilePath.c_str(), scNewCharfilePath.c_str()))
{ // file wasn't encoded, thus simply rename it
DeleteFile(scNewCharfilePath.c_str()); // just to get sure...
CopyFile(scOldCharfilePath.c_str(), scNewCharfilePath.c_str(), FALSE);
}
}
// delete old character
flstr *str = CreateWString(wscOldCharname.c_str());
HkLockAccountAccess(acc, true); // also kicks player on this account
bool bRet = Players.DeleteCharacterFromName(*str);
HkUnlockAccountAccess(acc);
FreeWString(str);
DeleteFile(scOldCharfilePath.c_str()); // doesn't delete when previously renamed, dunno why
if(bOnlyDelete)
return HKE_OK; // only delete char, thus we're finished
wstring wscNewNameString = L"";
for(uint i = 0; (i < wscNewCharname.length()); i++)
{
char cHiByte = wscNewCharname[i] >> 8;
char cLoByte = wscNewCharname[i] & 0xFF;
wchar_t wszBuf[8];
swprintf(wszBuf, L"%02X%02X", ((uint)cHiByte) & 0xFF, ((uint)cLoByte) & 0xFF);
wscNewNameString += wszBuf;
}
IniWrite(scNewCharfilePath, "Player", "Name", wstos(wscNewNameString));
// we'll also need to add the new character into the flname searchtree in memory(which is usually build when
// flserver starts). methods like FindAccountByCharacterName won't work else
// insert into flname search tree
struct TREENODE
{
TREENODE *pLeft;
TREENODE *pParent;
TREENODE *pRight;
ulong l1;
char *szFLName;
uint lLength;
ulong l2; // ??
CAccount *acc;
};
char *pEBP;
pEBP = (char*)&Players + 0x30;
char *pEDI;
memcpy(&pEDI, pEBP + 4, 4);
TREENODE *leaf;
memcpy(&leaf, pEBP + 8, 4);
// edi+4 is where the root node is
TREENODE *node;
memcpy(&node, pEDI + 4, 4);
bool bLeft = true;
TREENODE *lastparent = (TREENODE*)(pEDI + 4);
while(node != leaf)
{
lastparent = node;
int iRet = strcmp(node->szFLName, wstos(wscNewFilename + L".fl").c_str());
if(iRet >= 0) { // leftnode?
node = node->pLeft;
bLeft = true;
} else { // rightnode?
node = node->pRight;
bLeft = false;
}
}
// we need to use fl's new operator, else free might fail later when char gets deleted
typedef void* (*_flnew)(unsigned int);
_flnew flnew = (_flnew) SRV_ADDR(ADDR_FLNEW);
TREENODE *tn = (TREENODE *)flnew(sizeof(TREENODE));
memset(tn, 0, sizeof(TREENODE));
tn->pLeft = leaf;
tn->pParent = lastparent;
tn->pRight = leaf;
tn->szFLName = (char*)flnew(32);
strcpy(tn->szFLName, wstos(wscNewFilename + L".fl").c_str());
tn->lLength = (uint)strlen(tn->szFLName);
tn->l2 = 0x1F; // seems to be always 0x1F
tn->acc = acc;
if(bLeft)
lastparent->pLeft = tn;
else
lastparent->pRight = tn;
// increment character counter
uint iNumberOfChars;
memcpy(&iNumberOfChars, (char*)acc + 0x2C, 4);
iNumberOfChars++;
memcpy((char*)acc + 0x2C, &iNumberOfChars, 4);
// finally we need to add the new char to the CAccount character list
// else it will not be shown in the accounts list in the flserver window
struct LISTNODE
{
LISTNODE *next;
LISTNODE *prev;
u_long l1;
wchar_t *wszCharname;
ulong lArray[32];
};
LISTNODE *lnHead;
memcpy(&lnHead, (char*)acc + 0x28, 4);
LISTNODE *lnCur = lnHead->next;
while(lnCur->next != lnHead)
lnCur = lnCur->next;
LISTNODE *ln = (LISTNODE *)flnew(sizeof(LISTNODE));
ln->next = lnHead;
ln->prev = lnCur;
ln->wszCharname = (wchar_t*)flnew(sizeof(wchar_t) * 32);
wcscpy(ln->wszCharname, wscNewCharname.c_str());
lnCur->next = ln;
return HKE_OK;
}[/i][/i]