I allready posted my solution to solve this problem. Check few post before, im using it on my own server. On same solution i posted code for golden archer, there was query cross execution problem equal to warehouse. My solution is using single thread (antihacktick) with much lower refresh rate than normal second tick thread for better protection, but it can take about 3-5% additional CPU usage (deppend on CPU type), but its stable, after i released i had no server crashes.
Alternative - modified solution posted apyrupa_master (doesnt using low frequency antihacktick for performance reason).
Disabling features is not bug solution
///////////////////////////////////////////////////////////
//// REPOSTING MY VAULT ANTIHACK SOLUTION ////
//////////////////////////////////////////////////////////
OK Guys, i used brain and solved it for myself. This will give the delay between /ware change and will reset counter everytime the vault is closed (reseting counter will cause the DATASERVER query will have enought time to save vault content and will block user to change vault untill the counter doesnt time out).
Here is my solution:
1. Edit
Lite.cpp and add this after last include and before DWORD MainTick (I changed it to make single thread with much higher reload time - 1x for 100ms, because in MainTick thread is refreshing only 1x for 1000ms, and that was not enough):
PHP Code:
#include "Socket.h"
#include "TradeSystem.h"
DWORD AntiHackTick()
{
while(true)
{
for(int i=OBJECT_MIN; i<=OBJECT_MAX; i++)
{
OBJECTSTRUCT *gObj = (OBJECTSTRUCT*)OBJECT_POINTER(i);
if(gObj->Connected < PLAYER_LOGGED)
continue;
if(gObj->Connected < PLAYER_PLAYING)
continue;
if((AddTab[gObj->m_Index].WARE_Delay > 0) && (gObj->WarehouseSave == 0))
AddTab[gObj->m_Index].WARE_Delay--;
else if (gObj->WarehouseSave != 0)
AddTab[gObj->m_Index].WARE_Delay = Configs.Commands.WareDelay;
}
Sleep(100);
}
return 1;
}
DWORD MainTick()
{
2. Edit
Lite.cpp and add this after maintick thread:
PHP Code:
DWORD ThreadID;
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MainTick, NULL, 0, &ThreadID);//False 2 1173 V513 Use _beginthreadex/_endthreadex functions instead of CreateThread/ExitThread functions. IA Julia 1.x.x lite.cpp 148 False
if ( hThread == 0 )
{
Log.ConsoleOutPut(1, c_Red, t_Error, "CreateThread() failed with error %d", GetLastError());
return;
}
CloseHandle(hThread);
// ANTIHACK
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)AntiHackTick, NULL, 0, &ThreadID);
if ( hThread == 0 )
{
Log.ConsoleOutPut(1, c_Red, t_Error, "CreateThread() failed with error %d", GetLastError());
return;
}
CloseHandle(hThread);
// END ANTIHACK
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)NewsSystem, NULL, 0, &ThreadID);//False 2 1175 V513 Use _beginthreadex/_endthreadex functions instead of CreateThread/ExitThread functions. IA Julia 1.x.x lite.cpp 159 False
if ( hThread == 0 )
3. Edit
Config.h (add in struct sCommands):
4. Edit
Config.cpp (add in // ware // section)
PHP Code:
Commands.WareDelay = GetInt(0, 6000, 10, "MultyVault", "WareDelay", IAJuliaCmd);
5. Edit
User.h (add in typedef struct sAddTab section):
PHP Code:
//WARE Delay
int WARE_Delay;
6. Edit
ChatCommands.cpp and replace original warecommand with this code:
PHP Code:
bool cChat::WareCommand(LPOBJ gObj, char *Msg)
{
if(CheckCommand(gObj, Configs.Commands.IsMultyVault, GmSystem.NONE, Configs.Commands.ZenForChange, Configs.Commands.PcPointForChange, Configs.Commands.WCoinForChange, Configs.Commands.WebPointsForChange, 0, 1, 0, "Ware", "/ware <num>", Msg))
return true;
if(gObj->WarehouseSave != 0)
{
MessageLog(1, c_Red, t_COMMANDS, gObj, "[Ware] Close your vault first!");
return true;
}
if(AddTab[gObj->m_Index].WARE_Delay > 0)
{
MessageLog(1, c_Red, t_COMMANDS, gObj, "[ANTI-HACK] Vault bude mozne zmenit az o %d sekund!", (AddTab[gObj->m_Index].WARE_Delay/10));
return true;
}
int WantSlot;
sscanf(Msg, "%d", &WantSlot);
MuOnlineQuery.ExecQuery("SELECT UsedSlot FROM warehouse WHERE AccountID = '%s'", gObj->AccountID);
MuOnlineQuery.Fetch();
int UsedSlot = MuOnlineQuery.GetAsInteger("UsedSlot");
MuOnlineQuery.Close();
if(UsedSlot == NULL )
{
MuOnlineQuery.ExecQuery("UPDATE warehouse SET Items01 = Items, UsedSlot = 1 WHERE AccountID = '%s'", gObj->AccountID);
MuOnlineQuery.Fetch();
MuOnlineQuery.Close();
}
if(UsedSlot == -1 || UsedSlot == 0)
{
MessageLog(1, c_Red, t_COMMANDS, gObj, "[Ware] Command is broken, relog and try again!");
return true;
}
if(WantSlot < 1 || WantSlot > Configs.Commands.NumberOfVaults)
{
MessageLog(1, c_Red, t_COMMANDS, gObj, "[Ware] You can use from 1 to %d vaults!", Configs.Commands.NumberOfVaults);
return true;
}
if(UsedSlot == WantSlot)
{
MessageLog(1, c_Red, t_COMMANDS, gObj, "[Ware] You need to chose other vault number!");
return true;
}
TakeCommand(gObj, Configs.Commands.ZenForChange, Configs.Commands.PcPointForChange, Configs.Commands.WCoinForChange, Configs.Commands.WebPointsForChange, "Ware");
MuOnlineQuery.ExecQuery("UPDATE warehouse SET Items%02d = Items, Items = Items%02d, UsedSlot = %d WHERE AccountID = '%s'", UsedSlot, WantSlot, WantSlot, gObj->AccountID);
MuOnlineQuery.Fetch();
MuOnlineQuery.Close();
AddTab[gObj->m_Index].WARE_Delay = Configs.Commands.WareDelay;
MessageLog(1, c_Red, t_COMMANDS, gObj, "[Ware] You successfully change vault from %d to %d!", UsedSlot, WantSlot);
return true;
}
7. Edit in IA Julia folder commands.ini and add in:
[MultyVault]
IsMultyVault = 1 // /ware 1; /ware 2
NumberOfVaults = 5 // [1-99]
ZenForChange = 10000
PcPointForChange = 0
WCoinForChange = 0
WebPointsForChange = 0
WareDelay = 100 // Antihack delay for warehouse change in seconds / 10 (100 = 10 seconds)
Yes, im sorry if skilled coder will see i did it like idiot, i have only PHP skills. I allready tested. Enjoy