最近用多開,注意到一個現象
直接關Garena會順便把一個War3關掉 (不知道哪版開始改的)
似乎很方便?
實際上,GGC直接暴力關掉War3 (不使用正常方式結束程式)
這樣做的結果就是,程式結束應該做的釋放資源等動作不會被執行
(驗證方式請用message sniffer,看war3不會收到WM_DESTROY就結束
印象中clean up的動作是在WM_DESTROY中做的)
會不會有memory leak,這要看war3是怎麼寫的
其實改成送WM_DESTROY來結束war3就解決了,怎麼會犯這種錯誤?
我有聽過更誇張的內幕,這邊就不方便透露了 (認識管理員的應該都有機會聽到)
像我就很偷懶,MSDN說程式結束會自動釋放的,我就沒手動寫
如果你沒正常結束koala's WC3 helper,我可以告訴你
基本上會有memory leak,某些系統資源會沒機會釋放
Showing posts with label war3. Show all posts
Showing posts with label war3. Show all posts
Sunday, October 25, 2009
Sunday, September 6, 2009
Ghost++ 開遊戲機器人
BBS版本請到PTT(telnet://ptt.cc) WarcraftChat板觀看
我不發Warcraft板,發文沒被m過,浪費力氣
http://forum.codelain.com/index.php?board=22.0
GHost++ stands for Game Host.
簡單說就是開game用的 (目前只支援War3)
為什麼要使用GHost++?
Open Source!! 可額外選用patch增加需要的功能,或自己改
可以分離主機和玩家端,開遊戲不一定要用自己的電腦開,可節省資源減少lag
可同時進行多個遊戲,只要遊戲開始了,bot就可以繼續開一下個遊戲
可自動開遊戲,人滿就自動開始 (!autohost)
內建無訊息自動刷房 (不會出現誰加入離開)
內建反延遲及遊戲管理功能 (ex: 查ping, 國家, 黑名單...等)
可自動踢掉網路太差的玩家
可自動過濾國家 (目前custom build才有,官方版沒採用)
支援多平台,不需要安裝遊戲主程式 (Windows, Linux, Mac皆可使用)
ghost.cfg 設定檔
motd.txt 進入遊戲大廳的公告 (沒有請自己建立)
gameloaded.txt 地圖讀取完的訊息
gameover.txt 遊戲結束的訊息
ghost.cfg需要改的地方
bot_war3path = D:\Warcraft III\
war3路徑
沒有war3的電腦,要有下面的檔案 (請從有安裝的電腦copy過來)
game.dll
Storm.dll
war3.exe
blizzard.j
common.j
bot_mappath = maps\
war3地圖檔路徑,請把要用的圖都copy一份進去
或是使用 link shell extension 做連結
bot_spoofchecks = 0
bot_requirespoofchecks = 0
改名檢查,最好關掉 (不關應該沒幾個人會通過,就被踢光光)
bot_latency = 150
反延遲設定
admingame_create = 1
開啟Lan game管理介面
admingame_password = ranranru
Lan game管理介面密碼
bnet_cdkeyroc =
bnet_cdkeytft =
遊戲序號
bnet_server = uswest.battle.net
bnet_serveralias = USWest
bnet_username = IamBot
bnet_password = ******
帳號 密碼
bnet_firstchannel = test
進哪個頻道
bnet_rootadmin = ranranru
你老大是誰
bnet_bnlsserver = bnls.hikato.com
bnet_bnlsport = 19283
Warden相關的東西,直接用老外提供的就可以了
不想用老外的,自己跑server也可以
設定錯誤會一直跟Battlenet斷線
常用指令
!map load a map file (".w3m" and ".w3x" files),
!load load a map config file (".cfg" files), leave
blank to see current map
!priv host private game
!pub host public game
!close ... close slot
!open ... open slot
!closeall close all open slots
!openall open all closed slots
!from display the country each player is from
!ping [number] ping players, optionally add [number] to kick
players with ping above [number]
!unhost unhost game
!start [force] start game, optionally add [force] to skip
checks
使用方式
先用 !map 或 !load 選一張圖
!map指令只能開非正規圖,只能用預設選項開,不能在遊戲開始時打指令
!map ImbaWar592b.w3x
請確定 bot_mappath 路徑內有 ImbaWar592b.w3x,否則會錯誤
以正規圖為例,介紹!load的用法
!load tw-ref.cfg
請確定 bot_mapcfgpath 路徑內有 tw-ref.cfg,否則會錯誤
tw-ref.cfg的內容
map_path = Maps\FrozenThrone\(4)TwistedMeadows.w3x
給replay看的,(4)TwistedMeadows.w3x改成你用的地圖,其他不要動
map_localpath = FrozenThrone\(4)TwistedMeadows.w3x
看你圖放在哪就設哪嘍
map_speed = 3
map_visibility = 4
map_flags = 3
map_gametype = 2
# map observers
# 1 = none
# 2 = on defeat
# 3 = allowed
# 4 = referees
map_observers = 4
選完圖後
公開遊戲 !pub 正規隨便打
私人遊戲 !priv 1234
公開遊戲開了bot就會從頻道消失,私人遊戲不會
有沒有開成功,bot會告訴你
進入遊戲後,記得先用/w 密一下bot,做完id檢查 (bot跟war3同一台的不用檢查)
否則bot怕你是假冒的,不會聽你的話
開始遊戲打 !start
關掉遊戲打 !unhost
遊戲開始後bot就會回到聊天頻道了,可再開下一個遊戲
頻道中的對話,bot也可轉送給你
只有一套cdkey要怎麼使用?
在ghost.cfg中 admingame_create = 1
進lan game,加入admingame
加入後打 !password ranranru (你的密碼)
接著就跟前面提到的一樣了 (!map/!load 然後 !pub/!priv)
開好後,離開admingame
會在lan game看到你剛開的遊戲,加入即可
有Visual C++的,建議調一下設定,自己編最佳化版本
檔案比較小,執行效率也比較好
較少用的功能懶得寫,某些功能/用法是不能寫
未提及的部份,請自己看文件
我編的15.0以後版本需配合官方版本使用
Ghost++ 15.0 SSE2 build
Ghost++ 14.7 SSE2 build
我不發Warcraft板,發文沒被m過,浪費力氣
http://forum.codelain.com/index.php?board=22.0
GHost++ stands for Game Host.
簡單說就是開game用的 (目前只支援War3)
為什麼要使用GHost++?
Open Source!! 可額外選用patch增加需要的功能,或自己改
可以分離主機和玩家端,開遊戲不一定要用自己的電腦開,可節省資源減少lag
可同時進行多個遊戲,只要遊戲開始了,bot就可以繼續開一下個遊戲
可自動開遊戲,人滿就自動開始 (!autohost)
內建無訊息自動刷房 (不會出現誰加入離開)
內建反延遲及遊戲管理功能 (ex: 查ping, 國家, 黑名單...等)
可自動踢掉網路太差的玩家
可自動過濾國家 (目前custom build才有,官方版沒採用)
支援多平台,不需要安裝遊戲主程式 (Windows, Linux, Mac皆可使用)
ghost.cfg 設定檔
motd.txt 進入遊戲大廳的公告 (沒有請自己建立)
gameloaded.txt 地圖讀取完的訊息
gameover.txt 遊戲結束的訊息
ghost.cfg需要改的地方
bot_war3path = D:\Warcraft III\
war3路徑
沒有war3的電腦,要有下面的檔案 (請從有安裝的電腦copy過來)
game.dll
Storm.dll
war3.exe
blizzard.j
common.j
bot_mappath = maps\
war3地圖檔路徑,請把要用的圖都copy一份進去
或是使用 link shell extension 做連結
bot_spoofchecks = 0
bot_requirespoofchecks = 0
改名檢查,最好關掉 (不關應該沒幾個人會通過,就被踢光光)
bot_latency = 150
反延遲設定
admingame_create = 1
開啟Lan game管理介面
admingame_password = ranranru
Lan game管理介面密碼
bnet_cdkeyroc =
bnet_cdkeytft =
遊戲序號
bnet_server = uswest.battle.net
bnet_serveralias = USWest
bnet_username = IamBot
bnet_password = ******
帳號 密碼
bnet_firstchannel = test
進哪個頻道
bnet_rootadmin = ranranru
你老大是誰
bnet_bnlsserver = bnls.hikato.com
bnet_bnlsport = 19283
Warden相關的東西,直接用老外提供的就可以了
不想用老外的,自己跑server也可以
設定錯誤會一直跟Battlenet斷線
常用指令
!map
!load
blank to see current map
!priv
!pub
!close
!open
!closeall close all open slots
!openall open all closed slots
!from display the country each player is from
!ping [number] ping players, optionally add [number] to kick
players with ping above [number]
!unhost unhost game
!start [force] start game, optionally add [force] to skip
checks
使用方式
先用 !map 或 !load 選一張圖
!map指令只能開非正規圖,只能用預設選項開,不能在遊戲開始時打指令
!map ImbaWar592b.w3x
請確定 bot_mappath 路徑內有 ImbaWar592b.w3x,否則會錯誤
以正規圖為例,介紹!load的用法
!load tw-ref.cfg
請確定 bot_mapcfgpath 路徑內有 tw-ref.cfg,否則會錯誤
tw-ref.cfg的內容
map_path = Maps\FrozenThrone\(4)TwistedMeadows.w3x
給replay看的,(4)TwistedMeadows.w3x改成你用的地圖,其他不要動
map_localpath = FrozenThrone\(4)TwistedMeadows.w3x
看你圖放在哪就設哪嘍
map_speed = 3
map_visibility = 4
map_flags = 3
map_gametype = 2
# map observers
# 1 = none
# 2 = on defeat
# 3 = allowed
# 4 = referees
map_observers = 4
選完圖後
公開遊戲 !pub 正規隨便打
私人遊戲 !priv 1234
公開遊戲開了bot就會從頻道消失,私人遊戲不會
有沒有開成功,bot會告訴你
進入遊戲後,記得先用/w 密一下bot,做完id檢查 (bot跟war3同一台的不用檢查)
否則bot怕你是假冒的,不會聽你的話
開始遊戲打 !start
關掉遊戲打 !unhost
遊戲開始後bot就會回到聊天頻道了,可再開下一個遊戲
頻道中的對話,bot也可轉送給你
只有一套cdkey要怎麼使用?
在ghost.cfg中 admingame_create = 1
進lan game,加入admingame
加入後打 !password ranranru (你的密碼)
接著就跟前面提到的一樣了 (!map/!load 然後 !pub/!priv)
開好後,離開admingame
會在lan game看到你剛開的遊戲,加入即可
有Visual C++的,建議調一下設定,自己編最佳化版本
檔案比較小,執行效率也比較好
較少用的功能懶得寫,某些功能/用法是不能寫
未提及的部份,請自己看文件
Ghost++ 15.0 SSE2 build
Ghost++ 14.7 SSE2 build
Saturday, September 5, 2009
War3多開 1.24b
Allows multiple warcraft 3 instances and joining your own LAN game.
The file must be placed within your Warcraft 3 folder or it will fail. Must
be run as administrator.
1.24b
The file must be placed within your Warcraft 3 folder or it will fail. Must
be run as administrator.
1.24b
Saturday, August 29, 2009
[1.23]Opensource Hack with Many offsets! by sd333221
現在差不多都1.24了,留個備份
僅提供研究,使用後果自行負責
作者是sd333221
//SimpleWc3Hack for Warcraft 3 Patch 1.23...
#include
#include
#include
using namespace std;
DWORD GetPIDForProcess (char* process);
void EnableDebugPriv();
DWORD GetDLLBase(char* DllName, DWORD tPid);
#define PATCH(i,w,l) WriteProcessMemory(hProc,reinterpret_cast(gameBase+i),w,l,&dSize)
#define NPATCH(i,w,l) WriteProcessMemory(hProc,reinterpret_cast(i),w,l,&dSize)
int main()
{
cout << "SimpleWc3Hack v2.1 by sd333221 loaded (for WC3 v1.23)!" << endl << endl; cout << "Searching Wc3..." << endl; if(GetPIDForProcess("WAR3.EXE") == 0) { cout << "Warcraft 3 was not found..." << endl; system("Pause"); exit(0); } else { cout << "Getting debug privileges..." << endl; EnableDebugPriv(); cout << "Opening Warcraft 3 Process..." << endl; HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, false, GetPIDForProcess("WAR3.EXE")); if(hProc) { cout << "Process opened... Patching" << endl; DWORD gameBase = GetDLLBase("Game.dll",GetPIDForProcess("WAR3.EXE")); DWORD dSize = 0; PATCH(0x3A1E9B,"\x90\x90",2); //Patch 6F3A1E9B to nop nop :-) if(dSize == 0) { cout << "Failed to patch showunitsingame" << endl; } PATCH(0x361DFC,"\x00",1); if(dSize == 0) { cout << "Failed to patch showunitsmap" << endl; } PATCH(0x285B8C,"\x90\x90",2); if(dSize == 0) { cout << "Failed to patch clickableunits" << endl; } PATCH(0x285BA2,"\xEB\x29",2); if(dSize == 0) { cout << "Failed to patch clickableunits (2nd patch)" << endl; } PATCH(0x28345C,"\x40\xc3",2); if(dSize == 0) { cout << "Failed to patch revealillu" << endl; } PATCH(0x73DEC9,"\xB2\x00\x90\x90\x90\x90",6); if(dSize == 0) { cout << "Failed to patch removefogingame" << endl; } PATCH(0x431556,"\x3B\xC0\x0F\x85\xC0\x00\x00\x00\x8D\x8B\xF0\x00\x00\x00\xE8\x07\x3D\x03\x00\x3B\xC0\x0F\x85\xAD\x00\x00\x00",27); if(dSize == 0) { cout << "Failed to patch pingsignal" << endl; } PATCH(0x362211,"\x3B\xC0\x0F\x85\x30\x04\x00\x00",8); if(dSize == 0) { cout << "Failed to patch showinvisiblemap" << endl; } PATCH(0x356E7E,"\x90\x90\x90",3); if(dSize == 0) { cout << "Failed to patch showinvisiblemap" << endl; } PATCH(0x3C5C22,"\xEB",1); PATCH(0x3C135C,"\xB8\xFF\x00\x00\x00\xEB",6); if(dSize == 0) { cout << "Failed to bypass DotA -ah command" << endl; } PATCH(0x3F92CA,"\x90\x90",2); PATCH(0x3A1DDB,"\xEB",1); if(dSize == 0) { cout << "Failed to enable viewable items" << endl; } NPATCH(0x4559EC,"\x60\x0B\xC0\x75\x2F\x8A\x8E\xD0\x02\x00\x00\x80\xF9\x01\x74\x51\xC6\x86\xD0\x02\x00\x00\x01\xC6\x86\xD1\x02\x00\x00\x01\xC6\x86\xD2\x02\x00\x00\xFF\x8B\xCE\xB8\xFF\x01\x01\xFF\xFF\x15\x60\x5A\x45\x00\xEB\x2D\x8A\x8E\xD0\x02\x00\x00\x80\xF9\xFF\x74\x22\xC6\x86\xD0\x02\x00\x00\xFF\xC6\x86\xD1\x02\x00\x00\xFF\xC6\x86\xD2\x02\x00\x00\xFF\x8B\xCE\xB8\xFF\xFF\xFF\xFF\xFF\x15\x60\x5A\x45\x00\x61\xB8\x01\x00\x00\x00\x23\xD8\x89\x44\x24\xE4\xFF\x35\x65\x5A\x45\x00\xC3",116); DWORD addr[3]; addr[0] = gameBase + 0x29E270; //References to the Game.dll addr[1] = gameBase + 0x39A3BF; // addr[2] = 0x4559EC; //Detour NPATCH(0x455A60,&addr[0],sizeof(DWORD)); NPATCH(0x455A65,&addr[1],sizeof(DWORD)); NPATCH(0x455A6A,&addr[2],sizeof(DWORD)); PATCH(0x39A3B9,"\xFF\x25\x6A\x5A\x45\x00",6); //Plant detour if(dSize == 0) { cout << "Failed to enable colored invisibles" << endl; } PATCH(0x2030DC,"\x90\x90\x90\x90\x90\x90",6); PATCH(0x34FC68,"\x90\x90",2); if(dSize == 0) { cout << "Failed to enable view skills" << endl; } PATCH(0x28EBCE,"\xEB",1); PATCH(0x34FCA6,"\x90\x90\x90\x90",4); if(dSize == 0) { cout << "Failed to enable view cooldowns" << endl; } PATCH(0x285BA2,"\xEB",1); if(dSize == 0) { cout << "Failed to enable click invisible units" << endl; } //Tradeamount disabled /*PATCH(0x34E762,"\xB8\x00\x00\x00\x00\x90",6); DWORD highTradeAmount = 200; PATCH(0x34E763,&highTradeAmount,sizeof(DWORD)); PATCH(0x34E76A,"\xB8\x00\x00\x00\x00\x90",6); DWORD lowTradeAmount = 100; PATCH(0x34E76B,&lowTradeAmount,sizeof(DWORD)); if(dSize == 0) { cout << "Failed to patch tradeamount" << endl; }*/ cout << "Show hero icons: " << endl; cout << "Press F1 to view all hero icons, F2 for enemy icons, F3 for ally icons, any key for nothing!" << endl; system("Pause"); if(GetAsyncKeyState(VK_F1)) { PATCH(0x371581, "\x5B\x26",2); PATCH(0x371587, "\x90\x90\x90\x90\x90\x90",6); if(dSize == 0) { cout << "Failed to patch view all icons" << endl; } } else if(GetAsyncKeyState(VK_F2)) { PATCH(0x371581, "\x5B\x26",2); PATCH(0x371587, "\x0F\x85\x8F\x02\x00\x00",6); if(dSize == 0) { cout << "Failed to patch view enemy icons" << endl; } } else if(GetAsyncKeyState(VK_F3)) { PATCH(0x371581, "\x5B\x26",2); PATCH(0x371587, "\x0F\x84\x8F\x02\x00\x00",6); if(dSize == 0) { cout << "Failed to patch view ally icons" << endl; } } else { cout << "View hero icons not enabled!" << endl; } Sleep(1000); cout << "Unlimited camera zoom" << endl; cout << "Press F1 to enable camera zoom" << endl; system("Pause"); if(GetAsyncKeyState(VK_F1)) { float zoom = 0; cout << "Please enter zoom: "; cin >> zoom;
PATCH(0x285B68, "\xE9\x04\xA3\x5E\x00",5);
PATCH(0x86FE71, "\xE8\xDA\x13\xCC\xFF\x6A\x01\x6A\x00\x68\xCC\xCC\xCC\xCC\x6A\x00\x8B\x0D\xD8\xA7\xAB\x6F\x8B\x89\x54\x02\x00\x00\xE8\x8E\x65\xA9\xFF\xE9\xD6\x5C\xA1\xFF",38);
PATCH(0x86FE7B,&zoom,sizeof(DWORD));
}
cout << "Done, goodbye!" << endl;
system("Pause");
exit(1);
}
else
{
cout << "Warcraft 3 could not be opened..." << endl;
system("Pause");
exit(0);
}
}
return 0;
}
//Queries the ProcessId of a certain process
DWORD GetPIDForProcess (char* process)
{
BOOL working=0;
PROCESSENTRY32 lppe= {0};
DWORD targetPid=0;
HANDLE hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS ,0);
if (hSnapshot)
{
lppe.dwSize=sizeof(lppe);
working=Process32First(hSnapshot,&lppe);
while (working)
{
if(_stricmp(lppe.szExeFile,process)==0)
{
targetPid=lppe.th32ProcessID;
break;
}
working=Process32Next(hSnapshot,&lppe);
}
}
CloseHandle( hSnapshot );
return targetPid;
}
//Enables to open other processes
void EnableDebugPriv()
{
HANDLE hToken;
LUID sedebugnameValue;
TOKEN_PRIVILEGES tkp;
if ( ! OpenProcessToken( GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
return;
if ( ! LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) ){
CloseHandle( hToken );
return;
}
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = sedebugnameValue;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if ( ! AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, NULL, NULL ) )
CloseHandle( hToken );
}
//Gets the base of our dll
DWORD GetDLLBase(char* DllName, DWORD tPid)
{
HANDLE snapMod;
MODULEENTRY32 me32;
if (tPid == 0) return 0;
snapMod = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, tPid);
me32.dwSize = sizeof(MODULEENTRY32);
if (Module32First(snapMod, &me32)){
do{
if (strcmp(DllName,me32.szModule) == 0){
CloseHandle(snapMod);
return (DWORD) me32.modBaseAddr;
}
}while(Module32Next(snapMod,&me32));
}
CloseHandle(snapMod);
return 0;
}
僅提供研究,使用後果自行負責
作者是sd333221
//SimpleWc3Hack for Warcraft 3 Patch 1.23...
#include
#include
#include
using namespace std;
DWORD GetPIDForProcess (char* process);
void EnableDebugPriv();
DWORD GetDLLBase(char* DllName, DWORD tPid);
#define PATCH(i,w,l) WriteProcessMemory(hProc,reinterpret_cast
#define NPATCH(i,w,l) WriteProcessMemory(hProc,reinterpret_cast
int main()
{
cout << "SimpleWc3Hack v2.1 by sd333221 loaded (for WC3 v1.23)!" << endl << endl; cout << "Searching Wc3..." << endl; if(GetPIDForProcess("WAR3.EXE") == 0) { cout << "Warcraft 3 was not found..." << endl; system("Pause"); exit(0); } else { cout << "Getting debug privileges..." << endl; EnableDebugPriv(); cout << "Opening Warcraft 3 Process..." << endl; HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, false, GetPIDForProcess("WAR3.EXE")); if(hProc) { cout << "Process opened... Patching" << endl; DWORD gameBase = GetDLLBase("Game.dll",GetPIDForProcess("WAR3.EXE")); DWORD dSize = 0; PATCH(0x3A1E9B,"\x90\x90",2); //Patch 6F3A1E9B to nop nop :-) if(dSize == 0) { cout << "Failed to patch showunitsingame" << endl; } PATCH(0x361DFC,"\x00",1); if(dSize == 0) { cout << "Failed to patch showunitsmap" << endl; } PATCH(0x285B8C,"\x90\x90",2); if(dSize == 0) { cout << "Failed to patch clickableunits" << endl; } PATCH(0x285BA2,"\xEB\x29",2); if(dSize == 0) { cout << "Failed to patch clickableunits (2nd patch)" << endl; } PATCH(0x28345C,"\x40\xc3",2); if(dSize == 0) { cout << "Failed to patch revealillu" << endl; } PATCH(0x73DEC9,"\xB2\x00\x90\x90\x90\x90",6); if(dSize == 0) { cout << "Failed to patch removefogingame" << endl; } PATCH(0x431556,"\x3B\xC0\x0F\x85\xC0\x00\x00\x00\x8D\x8B\xF0\x00\x00\x00\xE8\x07\x3D\x03\x00\x3B\xC0\x0F\x85\xAD\x00\x00\x00",27); if(dSize == 0) { cout << "Failed to patch pingsignal" << endl; } PATCH(0x362211,"\x3B\xC0\x0F\x85\x30\x04\x00\x00",8); if(dSize == 0) { cout << "Failed to patch showinvisiblemap" << endl; } PATCH(0x356E7E,"\x90\x90\x90",3); if(dSize == 0) { cout << "Failed to patch showinvisiblemap" << endl; } PATCH(0x3C5C22,"\xEB",1); PATCH(0x3C135C,"\xB8\xFF\x00\x00\x00\xEB",6); if(dSize == 0) { cout << "Failed to bypass DotA -ah command" << endl; } PATCH(0x3F92CA,"\x90\x90",2); PATCH(0x3A1DDB,"\xEB",1); if(dSize == 0) { cout << "Failed to enable viewable items" << endl; } NPATCH(0x4559EC,"\x60\x0B\xC0\x75\x2F\x8A\x8E\xD0\x02\x00\x00\x80\xF9\x01\x74\x51\xC6\x86\xD0\x02\x00\x00\x01\xC6\x86\xD1\x02\x00\x00\x01\xC6\x86\xD2\x02\x00\x00\xFF\x8B\xCE\xB8\xFF\x01\x01\xFF\xFF\x15\x60\x5A\x45\x00\xEB\x2D\x8A\x8E\xD0\x02\x00\x00\x80\xF9\xFF\x74\x22\xC6\x86\xD0\x02\x00\x00\xFF\xC6\x86\xD1\x02\x00\x00\xFF\xC6\x86\xD2\x02\x00\x00\xFF\x8B\xCE\xB8\xFF\xFF\xFF\xFF\xFF\x15\x60\x5A\x45\x00\x61\xB8\x01\x00\x00\x00\x23\xD8\x89\x44\x24\xE4\xFF\x35\x65\x5A\x45\x00\xC3",116); DWORD addr[3]; addr[0] = gameBase + 0x29E270; //References to the Game.dll addr[1] = gameBase + 0x39A3BF; // addr[2] = 0x4559EC; //Detour NPATCH(0x455A60,&addr[0],sizeof(DWORD)); NPATCH(0x455A65,&addr[1],sizeof(DWORD)); NPATCH(0x455A6A,&addr[2],sizeof(DWORD)); PATCH(0x39A3B9,"\xFF\x25\x6A\x5A\x45\x00",6); //Plant detour if(dSize == 0) { cout << "Failed to enable colored invisibles" << endl; } PATCH(0x2030DC,"\x90\x90\x90\x90\x90\x90",6); PATCH(0x34FC68,"\x90\x90",2); if(dSize == 0) { cout << "Failed to enable view skills" << endl; } PATCH(0x28EBCE,"\xEB",1); PATCH(0x34FCA6,"\x90\x90\x90\x90",4); if(dSize == 0) { cout << "Failed to enable view cooldowns" << endl; } PATCH(0x285BA2,"\xEB",1); if(dSize == 0) { cout << "Failed to enable click invisible units" << endl; } //Tradeamount disabled /*PATCH(0x34E762,"\xB8\x00\x00\x00\x00\x90",6); DWORD highTradeAmount = 200; PATCH(0x34E763,&highTradeAmount,sizeof(DWORD)); PATCH(0x34E76A,"\xB8\x00\x00\x00\x00\x90",6); DWORD lowTradeAmount = 100; PATCH(0x34E76B,&lowTradeAmount,sizeof(DWORD)); if(dSize == 0) { cout << "Failed to patch tradeamount" << endl; }*/ cout << "Show hero icons: " << endl; cout << "Press F1 to view all hero icons, F2 for enemy icons, F3 for ally icons, any key for nothing!" << endl; system("Pause"); if(GetAsyncKeyState(VK_F1)) { PATCH(0x371581, "\x5B\x26",2); PATCH(0x371587, "\x90\x90\x90\x90\x90\x90",6); if(dSize == 0) { cout << "Failed to patch view all icons" << endl; } } else if(GetAsyncKeyState(VK_F2)) { PATCH(0x371581, "\x5B\x26",2); PATCH(0x371587, "\x0F\x85\x8F\x02\x00\x00",6); if(dSize == 0) { cout << "Failed to patch view enemy icons" << endl; } } else if(GetAsyncKeyState(VK_F3)) { PATCH(0x371581, "\x5B\x26",2); PATCH(0x371587, "\x0F\x84\x8F\x02\x00\x00",6); if(dSize == 0) { cout << "Failed to patch view ally icons" << endl; } } else { cout << "View hero icons not enabled!" << endl; } Sleep(1000); cout << "Unlimited camera zoom" << endl; cout << "Press F1 to enable camera zoom" << endl; system("Pause"); if(GetAsyncKeyState(VK_F1)) { float zoom = 0; cout << "Please enter zoom: "; cin >> zoom;
PATCH(0x285B68, "\xE9\x04\xA3\x5E\x00",5);
PATCH(0x86FE71, "\xE8\xDA\x13\xCC\xFF\x6A\x01\x6A\x00\x68\xCC\xCC\xCC\xCC\x6A\x00\x8B\x0D\xD8\xA7\xAB\x6F\x8B\x89\x54\x02\x00\x00\xE8\x8E\x65\xA9\xFF\xE9\xD6\x5C\xA1\xFF",38);
PATCH(0x86FE7B,&zoom,sizeof(DWORD));
}
cout << "Done, goodbye!" << endl;
system("Pause");
exit(1);
}
else
{
cout << "Warcraft 3 could not be opened..." << endl;
system("Pause");
exit(0);
}
}
return 0;
}
//Queries the ProcessId of a certain process
DWORD GetPIDForProcess (char* process)
{
BOOL working=0;
PROCESSENTRY32 lppe= {0};
DWORD targetPid=0;
HANDLE hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS ,0);
if (hSnapshot)
{
lppe.dwSize=sizeof(lppe);
working=Process32First(hSnapshot,&lppe);
while (working)
{
if(_stricmp(lppe.szExeFile,process)==0)
{
targetPid=lppe.th32ProcessID;
break;
}
working=Process32Next(hSnapshot,&lppe);
}
}
CloseHandle( hSnapshot );
return targetPid;
}
//Enables to open other processes
void EnableDebugPriv()
{
HANDLE hToken;
LUID sedebugnameValue;
TOKEN_PRIVILEGES tkp;
if ( ! OpenProcessToken( GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
return;
if ( ! LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) ){
CloseHandle( hToken );
return;
}
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = sedebugnameValue;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if ( ! AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, NULL, NULL ) )
CloseHandle( hToken );
}
//Gets the base of our dll
DWORD GetDLLBase(char* DllName, DWORD tPid)
{
HANDLE snapMod;
MODULEENTRY32 me32;
if (tPid == 0) return 0;
snapMod = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, tPid);
me32.dwSize = sizeof(MODULEENTRY32);
if (Module32First(snapMod, &me32)){
do{
if (strcmp(DllName,me32.szModule) == 0){
CloseHandle(snapMod);
return (DWORD) me32.modBaseAddr;
}
}while(Module32Next(snapMod,&me32));
}
CloseHandle(snapMod);
return 0;
}
Wednesday, July 22, 2009
Tuesday, July 21, 2009
Friday, June 5, 2009
Saturday, September 13, 2008
koala's WC3 helper 和 koala's WC3 tool比較
後來寫的koala's WC3 helper,在memory使用上約少了7MB
用Sysinternals測出的結果
功能上
自動偵測輸入法切換,自動開關熱鍵,不影響中文輸入
這個功能有些限制
ex : 簡體輸入法使用者應該是無法使用


下載
用Sysinternals測出的結果
功能上
自動偵測輸入法切換,自動開關熱鍵,不影響中文輸入
這個功能有些限制
ex : 簡體輸入法使用者應該是無法使用
下載
Labels:
war3
Saturday, September 6, 2008
英文版和中文版的差別
好友上下線訊息語系不同
英文版沒改過字型
/profile 裡面看不到中文,game name也看不到中文
chat改成traditional chinese也沒用,一定要改字型
英文版沒改過字型
/profile 裡面看不到中文,game name也看不到中文
chat改成traditional chinese也沒用,一定要改字型
Labels:
war3
Thursday, August 28, 2008
hinet非固定adsl ladder黃金時段
據我測試是4:00~8:00 ping可以穩定維持在18x~22x
最早的記錄是3:00左右,最晚可以到8:30~9:00
超過就隨時會爆炸了
最早的記錄是3:00左右,最晚可以到8:30~9:00
超過就隨時會爆炸了
Labels:
war3
Wednesday, August 6, 2008
Battle.net 測ping
不要再用bot來ping了
直接用程式吧
BNGatewayEditor 是編輯Battle.net server的工具,可測試server的連線狀態
選定要測試的server後,按下Detect Gateway就可以測試了
測試時,多按幾次會比較準一點 (用bot測似乎要一直重新登入,超麻煩)
測出來的ping太大,就別打ladder吧
Custom Game不受本方法影響
要看是誰開的,參照Custom Game latency

下載
RS
google page (3.0.1.702)
war3.tw
直接用程式吧
BNGatewayEditor 是編輯Battle.net server的工具,可測試server的連線狀態
選定要測試的server後,按下Detect Gateway就可以測試了
測試時,多按幾次會比較準一點 (用bot測似乎要一直重新登入,超麻煩)
測出來的ping太大,就別打ladder吧
Custom Game不受本方法影響
要看是誰開的,參照Custom Game latency
下載
RS
google page (3.0.1.702)
war3.tw
Sunday, August 3, 2008
使用UPnP解決War3不能開game或AT邀請
這方法是好處是不需要密碼,不用任何技巧,電腦麻瓜都可以使用
想知道UPnP是什麼的點我
這個UPnP相關軟體是在在wikipedia上發現的,只有command line介面
UPnP Port Works
以War3為例簡介使用方式
UPnPPW.exe -remvoe TCP 6112
UPnPPW.exe -add TCP 6112 6112
這樣就完成了,遊戲中有改過port的,把6112改掉
如果不止一台電腦想開,記得在遊戲中改用不同port
會設定NAT, DHCP server保留ip address的就別用UPnP了吧
懶人包下載(直接執行war3.bat就可以用了)
RS
ESM
google page
PS.
電腦的防火牆可能會影響UPnP Port Works運作 (防毒有些有包含防火牆)
要先關掉
或是打開UPnP會使用到的port
outgoing UDP port 1900 (ssdp, UPnP Simple Service Discovery Protocol)
incoming TCP port 2869
M$內建防火牆可以把內建的例外規則UPnP framework打勾
詳細資訊可以看kb886257
最後用UPnP設定的port forwarding不見得會在分享器管理介面裡出現
想知道UPnP是什麼的點我
這個UPnP相關軟體是在在wikipedia上發現的,只有command line介面
UPnP Port Works
以War3為例簡介使用方式
UPnPPW.exe -remvoe TCP 6112
UPnPPW.exe -add TCP 6112 6112
這樣就完成了,遊戲中有改過port的,把6112改掉
如果不止一台電腦想開,記得在遊戲中改用不同port
會設定NAT, DHCP server保留ip address的就別用UPnP了吧
懶人包下載(直接執行war3.bat就可以用了)
RS
ESM
google page
PS.
電腦的防火牆可能會影響UPnP Port Works運作 (防毒有些有包含防火牆)
要先關掉
或是打開UPnP會使用到的port
outgoing UDP port 1900 (ssdp, UPnP Simple Service Discovery Protocol)
incoming TCP port 2869
M$內建防火牆可以把內建的例外規則UPnP framework打勾
詳細資訊可以看kb886257
最後用UPnP設定的port forwarding不見得會在分享器管理介面裡出現
解決War3 不能開game/invite AT (AP/分享器)
解法只有兩種
1) port forwarding (可用UPnP設定,不需密碼)
2) 設DMZ
port forwarding的設定通常在NAT或virtual server可以找到 (請參考分享器說明書)
分享器的預設密碼不知道?google it
找朋友幫忙設定
1) 分享器設定中開遠端管理功能
2) 遠端連線 ex: TeamViewer直接連到你的電腦再進入分享器管理介面 (連線可能透過中介server安全性自行斟酌)
某些分享器設port forwarding沒用,一定要設DMZ
如果設port forwarding有效,就不要設DMZ (影響安全性)
現在的分享器應該都會支援UPnP (至少我用過的都有)
參考使用UPnP解決不能開遊戲或邀請
ogc有使用UPnP,也許這是傳聞中,在Bnet不能開,ogc能開的原因吧 (未測試)
分享器解決後
還是不能,那就是電腦上防火牆的問題了
設War3.exe為允許或是只設TCP port 6112都可以
1) port forwarding (可用UPnP設定,不需密碼)
2) 設DMZ
port forwarding的設定通常在NAT或virtual server可以找到 (請參考分享器說明書)
分享器的預設密碼不知道?google it
找朋友幫忙設定
1) 分享器設定中開遠端管理功能
2) 遠端連線 ex: TeamViewer直接連到你的電腦再進入分享器管理介面 (連線可能透過中介server安全性自行斟酌)
某些分享器設port forwarding沒用,一定要設DMZ
如果設port forwarding有效,就不要設DMZ (影響安全性)
現在的分享器應該都會支援UPnP (至少我用過的都有)
參考使用UPnP解決不能開遊戲或邀請
ogc有使用UPnP,也許這是傳聞中,在Bnet不能開,ogc能開的原因吧 (未測試)
分享器解決後
還是不能,那就是電腦上防火牆的問題了
設War3.exe為允許或是只設TCP port 6112都可以
Sunday, July 27, 2008
ggc make war3 crash....
在ogc打一場,後來忘了關掉重開war3 (清掉War3Hook.dll)
後來join一個game,war3就當掉了,這是以前從沒發生過的事
我只玩了正規的圖,所以原因非常有可能就是ogc的問題!!
後來join一個game,war3就當掉了,這是以前從沒發生過的事
我只玩了正規的圖,所以原因非常有可能就是ogc的問題!!
Thursday, July 24, 2008
Tuesday, June 24, 2008
Saturday, June 21, 2008
reduce custom game latency(二)
對原理沒興趣直接看reduce custom game latency(一)
以下轉錄自sitos在PTT魔獸爭霸所回應文章
文章代碼(AID): #18NFFRON (WarCraft) [ptt.cc]
以下我先翻譯 Dota-Client 首頁的一段文字。
Warcraft III 的區域網路連線在遊戲中並不是透過 UDP 封包來傳輸的,
Warcraft III 的區域網路遊戲和在 Battle.net 的遊戲,
是用一模一樣的方式在進行。唯一的不同只有在尋找遊戲與加入遊戲的機制。
WC3 的區域網路,透過 UDP 廣播來找尋區域網路當中的遊戲,
並取得由主機所送出的遊戲資訊。一旦收到這些資訊,用戶端將會建立 TCP 連線,
連接到主機,並加入遊戲。這個加入遊戲的動作和在 Battle.net 是相同的。
唯一的不同是,在區域網路遊戲中,每個遊戲會有一個獨一無二的代碼,
這個 32-bit 的值會由主機透過描述遊戲的 UDP 封包送給用戶端。
但在 Battle.net 當中,這個值會被設成 0 。
(譯註: Battle.net 的遊戲列表由 Battle.net Server 直接送出,
在顯示遊戲時也有某種機制避免重覆顯示已經出現的遊戲。)
唯一不同的地方很簡單: WC3 在區域網路當中的同步時間間隔是 100ms ,
而在 Battle.net 遊戲中的時間間隔是 250ms 。 Listchecker (另一個軟體)
用了某些小技巧讓在使用 B.net 的 WC3 自以為在區域網路中,
使它會以每 100ms 的時間單位作同步的動作,而非 250ms 。
(譯註: 這件事譯者在本版 #169j3p-2 也已經提過, Listchecker 的構想我也想過,
不過沒有動手去實行,因為有更有趣的目標。 Dota-Client 的做法,
應該和 Listchecker 是類似的,或許是強迫修改某個紀錄同步時間的記憶體值。)
中略三段,主要是在講為啥 100ms 比 250ms 快。基本上這很直覺,
如果有興趣可以參考 #169j3p-2 ,我認為意思是差不多的。
當你將同步時間從 250ms 降到 100ms ,你將會看到重大的改變,
主機優勢只剩 100ms (譯註: 本來是 250ms),而不可避免的延遲也減到 100ms 。
但是,要在不影響用戶的情況底下掉封包或封包變慢可容忍的時間,
也只剩下 100ms (譯註: 這裡應該是講 TCP 的 retransmittion)。
這會使得主機在要送 2.5 倍的封包情況下,變得更糟,
使得封包更有可能在傳送當中遺失。這個方法的確有它的好處。
但是否值得,可以參考論壇當中的討論。
http://forums.dota-allstars.com/index.php?showtopic=154464&st=0&p=1918905
譯文到此為止。
其實 Dota-Client 的首頁已經給這個方法作了很清楚的說明,
不管你要調怎樣的 latency ,你必須要承擔它的後果,而且是正回饋的後果。
把 latency 從 250ms 調到 100ms ,封包量就要變 2.5 倍。
如果進一步調到 50ms 封包量是原本的五倍。封包量變大,但延遲容忍度降低。
原本一個封包要超過 250ms 沒送到,才會有感覺,但現在只要 100ms 就有感覺了。
更慘的是,封包量變大,直接導致 queuing latency 增高,增加封包延遲的情況,
另一方面也使得封包會掉的機會更大。
在這種情況底下,如果隨意調短 latency 卻沒有足夠的網路頻寬,
特別是主機的上傳頻寬(他要傳給遊戲中的其它人),就會出現嚴重的延遲。
以先前 GGC 給的建議值為參考基準的話, 100ms * 10 人的遊戲,
上傳所需是 640kbps ,如果降到 50ms 則會成為 1280kbps 。
而且依據 queuing theory ,頻寬使用量與延遲的關係是指數成長,
因此在網路情況不良的狀況下,縮短同步時間反而可能是一件不好的事。
如果離開理論,回到現實當中,高橋名人的極速是一秒 16 連打,
也就是每個動作之間是 62.5ms ,而一般人能作到 10 連打就已經很強了。
但 WC3 當中的 action 有時不是單純的一次按鍵,因此可達到的 apm 就更低了。
如果每秒都可以送出 10 個 action , apm 就是 600 。
但 apm 到達三百事實上就已經不常出現了。對 apm 300 的人而言,
平均每一個動作是 200ms ,sample frequency 只要是它的兩倍就很夠了,
也就是 100ms 正是 LAN game 的設定值,因此目前 LAN game 的效果大部份人都很滿意。
因此我們要問,真的有必要追求 100ms 以下的同步時間嗎?
為了效益並不明顯的延遲改善,而犧牲網路的頻寬與穩定性,
在不斷追求速度的同時,不要忘記 B 社在製作的時候,
為何選用這兩種數值,考量現實的網路狀況並作出合理的設定,
是相當重要的。上傳 > 2m 的人也許可以開個遊戲來造福大家,
但至少以我而言,連在 LAN game 我都不想作主機了。
反正我的手眼協調和神經傳導根本沒那麼快。
這篇是我寫的
文章代碼(AID): #18NIsiKP (WarCraft) [ptt.cc]
當初在ESM上發表3套reduce latency的軟體
dota client無法測試 (後來才知道1.8要用eesti)
令外兩套使用方式真的很麻煩,即使寫了詳細的說明
我也不覺得會有人願意使用,丟下一句有興趣的自己看說明吧 (我真的很懶是吧)
只提sitos沒講到的部份
對網路了解不多,以下是從網路上看來來 (本人不對內容真實性背書)
參考資料
sitos寫的文 #169j3p-2
TDA Community討論
http://forums.dota-allstars.com/index.php?showtopic=154464&st=0&p=1918905
從玩家的角度來看,影響遊戲有兩個因素 delay, spike
delay是玩家下一個指令後多久會生效,減少latency可以減少delay
spike發生時,玩家會感覺到畫面跳動,或是人物突然動作變很快
這是因為server(host)送給client的封包,有一部份沒在latency的時間內收到
client在收到封包後,要想辦法跟server同步,就得想辦法趕上
1) 直接跳畫面 2)加速跑完
TCP time-out最小是3秒 (遠大於250ms or 100ms)
如果這個封包沒辦法在latency時間內送到client,就會發生spike
如果spike不多,玩家是感覺不太出來的
一個spike畫面只會往前跳個250ms or 100ms
只有在server和client間連線狀況不穩定,連續spike出現才有明顯影響
連線的穩定程度指的不是ping值
在選latency時,必須要比玩家和host之間的ping值還大,否則就會有一堆spike發生
為了避免spike,猜想server會多送幾個同樣的封包出去
ogc anti-spike開了會耗用更大頻寬的原因所在?
ping怎麼看? 可以用這兩個程式
WC3Banlist
DotaRank
如果你在ogc開game能進行的很順,那麼使用dota client在Bnet上也可以辦到
也可能會有更好的結果,因為系統負擔比較小
至於我不提Dota Client Anti-Cheat的原因
作用原理跟Hollywood一樣,必需每個玩家都要開
你覺得這可行性有多大? 辦比賽再考慮吧
號稱可以減少delay是確定無誤的
只是為了宣傳,沒有提到可能增加spike的副作用
調整latency就是在delay和spike的trade-off,怎麼調自己斟酌吧
以下轉錄自sitos在PTT魔獸爭霸所回應文章
文章代碼(AID): #18NFFRON (WarCraft) [ptt.cc]
以下我先翻譯 Dota-Client 首頁的一段文字。
Warcraft III 的區域網路連線在遊戲中並不是透過 UDP 封包來傳輸的,
Warcraft III 的區域網路遊戲和在 Battle.net 的遊戲,
是用一模一樣的方式在進行。唯一的不同只有在尋找遊戲與加入遊戲的機制。
WC3 的區域網路,透過 UDP 廣播來找尋區域網路當中的遊戲,
並取得由主機所送出的遊戲資訊。一旦收到這些資訊,用戶端將會建立 TCP 連線,
連接到主機,並加入遊戲。這個加入遊戲的動作和在 Battle.net 是相同的。
唯一的不同是,在區域網路遊戲中,每個遊戲會有一個獨一無二的代碼,
這個 32-bit 的值會由主機透過描述遊戲的 UDP 封包送給用戶端。
但在 Battle.net 當中,這個值會被設成 0 。
(譯註: Battle.net 的遊戲列表由 Battle.net Server 直接送出,
在顯示遊戲時也有某種機制避免重覆顯示已經出現的遊戲。)
唯一不同的地方很簡單: WC3 在區域網路當中的同步時間間隔是 100ms ,
而在 Battle.net 遊戲中的時間間隔是 250ms 。 Listchecker (另一個軟體)
用了某些小技巧讓在使用 B.net 的 WC3 自以為在區域網路中,
使它會以每 100ms 的時間單位作同步的動作,而非 250ms 。
(譯註: 這件事譯者在本版 #169j3p-2 也已經提過, Listchecker 的構想我也想過,
不過沒有動手去實行,因為有更有趣的目標。 Dota-Client 的做法,
應該和 Listchecker 是類似的,或許是強迫修改某個紀錄同步時間的記憶體值。)
中略三段,主要是在講為啥 100ms 比 250ms 快。基本上這很直覺,
如果有興趣可以參考 #169j3p-2 ,我認為意思是差不多的。
當你將同步時間從 250ms 降到 100ms ,你將會看到重大的改變,
主機優勢只剩 100ms (譯註: 本來是 250ms),而不可避免的延遲也減到 100ms 。
但是,要在不影響用戶的情況底下掉封包或封包變慢可容忍的時間,
也只剩下 100ms (譯註: 這裡應該是講 TCP 的 retransmittion)。
這會使得主機在要送 2.5 倍的封包情況下,變得更糟,
使得封包更有可能在傳送當中遺失。這個方法的確有它的好處。
但是否值得,可以參考論壇當中的討論。
http://forums.dota-allstars.com/index.php?showtopic=154464&st=0&p=1918905
譯文到此為止。
其實 Dota-Client 的首頁已經給這個方法作了很清楚的說明,
不管你要調怎樣的 latency ,你必須要承擔它的後果,而且是正回饋的後果。
把 latency 從 250ms 調到 100ms ,封包量就要變 2.5 倍。
如果進一步調到 50ms 封包量是原本的五倍。封包量變大,但延遲容忍度降低。
原本一個封包要超過 250ms 沒送到,才會有感覺,但現在只要 100ms 就有感覺了。
更慘的是,封包量變大,直接導致 queuing latency 增高,增加封包延遲的情況,
另一方面也使得封包會掉的機會更大。
在這種情況底下,如果隨意調短 latency 卻沒有足夠的網路頻寬,
特別是主機的上傳頻寬(他要傳給遊戲中的其它人),就會出現嚴重的延遲。
以先前 GGC 給的建議值為參考基準的話, 100ms * 10 人的遊戲,
上傳所需是 640kbps ,如果降到 50ms 則會成為 1280kbps 。
而且依據 queuing theory ,頻寬使用量與延遲的關係是指數成長,
因此在網路情況不良的狀況下,縮短同步時間反而可能是一件不好的事。
如果離開理論,回到現實當中,高橋名人的極速是一秒 16 連打,
也就是每個動作之間是 62.5ms ,而一般人能作到 10 連打就已經很強了。
但 WC3 當中的 action 有時不是單純的一次按鍵,因此可達到的 apm 就更低了。
如果每秒都可以送出 10 個 action , apm 就是 600 。
但 apm 到達三百事實上就已經不常出現了。對 apm 300 的人而言,
平均每一個動作是 200ms ,sample frequency 只要是它的兩倍就很夠了,
也就是 100ms 正是 LAN game 的設定值,因此目前 LAN game 的效果大部份人都很滿意。
因此我們要問,真的有必要追求 100ms 以下的同步時間嗎?
為了效益並不明顯的延遲改善,而犧牲網路的頻寬與穩定性,
在不斷追求速度的同時,不要忘記 B 社在製作的時候,
為何選用這兩種數值,考量現實的網路狀況並作出合理的設定,
是相當重要的。上傳 > 2m 的人也許可以開個遊戲來造福大家,
但至少以我而言,連在 LAN game 我都不想作主機了。
反正我的手眼協調和神經傳導根本沒那麼快。
這篇是我寫的
文章代碼(AID): #18NIsiKP (WarCraft) [ptt.cc]
當初在ESM上發表3套reduce latency的軟體
dota client無法測試 (後來才知道1.8要用eesti)
令外兩套使用方式真的很麻煩,即使寫了詳細的說明
我也不覺得會有人願意使用,丟下一句有興趣的自己看說明吧 (我真的很懶是吧)
只提sitos沒講到的部份
對網路了解不多,以下是從網路上看來來 (本人不對內容真實性背書)
參考資料
sitos寫的文 #169j3p-2
TDA Community討論
http://forums.dota-allstars.com/index.php?showtopic=154464&st=0&p=1918905
從玩家的角度來看,影響遊戲有兩個因素 delay, spike
delay是玩家下一個指令後多久會生效,減少latency可以減少delay
spike發生時,玩家會感覺到畫面跳動,或是人物突然動作變很快
這是因為server(host)送給client的封包,有一部份沒在latency的時間內收到
client在收到封包後,要想辦法跟server同步,就得想辦法趕上
1) 直接跳畫面 2)加速跑完
TCP time-out最小是3秒 (遠大於250ms or 100ms)
如果這個封包沒辦法在latency時間內送到client,就會發生spike
如果spike不多,玩家是感覺不太出來的
一個spike畫面只會往前跳個250ms or 100ms
只有在server和client間連線狀況不穩定,連續spike出現才有明顯影響
連線的穩定程度指的不是ping值
在選latency時,必須要比玩家和host之間的ping值還大,否則就會有一堆spike發生
為了避免spike,猜想server會多送幾個同樣的封包出去
ogc anti-spike開了會耗用更大頻寬的原因所在?
ping怎麼看? 可以用這兩個程式
WC3Banlist
DotaRank
如果你在ogc開game能進行的很順,那麼使用dota client在Bnet上也可以辦到
也可能會有更好的結果,因為系統負擔比較小
至於我不提Dota Client Anti-Cheat的原因
作用原理跟Hollywood一樣,必需每個玩家都要開
你覺得這可行性有多大? 辦比賽再考慮吧
號稱可以減少delay是確定無誤的
只是為了宣傳,沒有提到可能增加spike的副作用
調整latency就是在delay和spike的trade-off,怎麼調自己斟酌吧
Labels:
war3
Sunday, June 15, 2008
Custom Game查國家
第一選擇我會建議用WC3Banlist
第二個方法可用custom kick (多半都有查國家的功能),載點自己找吧
W3DR也可以使用/drc 查國家
WC3Banlist據說是去查線上的database(來源是哪邊我就沒研究了)
看到太多noob hosting不會過濾老外了...
開game時註明國家也可以避免一些老外
第二個方法可用custom kick (多半都有查國家的功能),載點自己找吧
W3DR也可以使用/drc 查國家
WC3Banlist據說是去查線上的database(來源是哪邊我就沒研究了)
看到太多noob hosting不會過濾老外了...
開game時註明國家也可以避免一些老外
Labels:
war3
Friday, June 6, 2008
IME切換會送WM_DESTROY
怪不得會有神秘bug出現
更神奇的是沒有使用者認為這是個bug (我沒收到任何相關的回報)
基本上沒人回報的bug,或是使用上的問題
如果對我沒影響,通常我都裝死,當做沒發現過
更神奇的是沒有使用者認為這是個bug (我沒收到任何相關的回報)
基本上沒人回報的bug,或是使用上的問題
如果對我沒影響,通常我都裝死,當做沒發現過
Subscribe to:
Posts (Atom)
