#pragma semicolon 1 #include #include int server_ports[2] = {27015, 27075}; //server ports: ze server, simulated server. int g_iServerPort; int g_iClientIndexUserIDMapping[MAXPLAYERS + 1]; //---------------------------------------------------------------------------------------------------- // Purpose: //---------------------------------------------------------------------------------------------------- public Plugin myinfo = { name = "info from the ze server", author = "jenz", description = "just copies maps, hostname and client names info from the ze server", version = "1.0.0" }; public void OnPluginEnd() { for(int i = 1; i <= MaxClients; i++) { if(IsValidClient(i) && IsFakeClient(i)) { KickClient(i, "Disconnect by user."); } } } public void OnPluginStart() { g_iServerPort = GetConVarInt(FindConVar("hostport")); if (g_iServerPort == server_ports[0]) { CreateTimer(15.0, update_info_over_txt, _, TIMER_REPEAT); } else if (g_iServerPort == server_ports[1]) { CreateTimer(GetRandomFloat(5.0, 25.0), read_info_over_txt); } } public Action read_info_over_txt(Handle timer, any data) { new Handle:fileHandle = OpenFile("/addons/sourcemod/logs/simulate.txt", "r"); char lineBuffer[2048]; int count = 0; int current_ClientUserID_iteration[MAXPLAYERS + 1]; bool already_created_fakeClient = false; while(!IsEndOfFile(fileHandle) && ReadFileLine(fileHandle, lineBuffer, sizeof(lineBuffer))) { TrimString(lineBuffer); if (count == 0) //mapname { char mapname[256]; GetCurrentMap(mapname, sizeof(mapname)); if (!StrEqual(mapname, lineBuffer)) { ForceChangeLevel(lineBuffer, ""); break; } } else if (count == 1) //hostname { static Handle hHostName; if((hHostName = FindConVar("hostname")) == INVALID_HANDLE) return Plugin_Handled; SetConVarString(hHostName, lineBuffer, false, false); } else //reading clientUserID, client frag and playername { //index 0 = ClientUserID, index 1 = client frags, index 2 = client user name. char[][] sPart = new char[3][256]; ExplodeString(lineBuffer, " ", sPart, 3, 256); int ClientUserID = StringToInt(sPart[0]); bool does_client_user_id_exist = false; for (int i = 0; i <= MaxClients; i++) { //the clients on the simulate server will always first exist after CreateFakeClient so this approach should be safe. if (IsValidClient(i) && !IsClientSourceTV(i) && g_iClientIndexUserIDMapping[i] == ClientUserID) { does_client_user_id_exist = true; break; } } if (!does_client_user_id_exist && !already_created_fakeClient) { //User ID is new, so lets create the FakeClient. int iIndex = CreateFakeClient(sPart[2]); if(iIndex < 1 || iIndex > MaxClients) break; SetEntityFlags(iIndex, FL_CLIENT); DispatchKeyValue(iIndex, "classname", "player"); DispatchSpawn(iIndex); AdminId FakeAdmin = CreateAdmin(); SetAdminFlag(FakeAdmin, Admin_Custom6, true); SetUserAdmin(iIndex, FakeAdmin, true); g_iClientIndexUserIDMapping[iIndex] = ClientUserID; already_created_fakeClient = true; } //updating the clients frags and username based on the ClientUserID. for (int i = 0; i <= MaxClients; i++) { if (IsValidClient(i) && !IsClientSourceTV(i) && g_iClientIndexUserIDMapping[i] == ClientUserID) { int clientFrag = StringToInt(sPart[1]); SetEntProp(i, Prop_Data, "m_iFrags", clientFrag); SetClientName(i, sPart[2]); //indicating that the client still exists right now. current_ClientUserID_iteration[i] = ClientUserID; break; } } } count++; } CloseHandle(fileHandle); //kicking clients whos UserID is not connected on ze anymore. for (int i = 0; i <= MaxClients; i++) { if (IsValidClient(i) && !IsClientSourceTV(i)) { bool does_UserID_still_exist = false; for (int j = 0; j <= MaxClients; j++) { //for every user in g_iClientIndexUserIDMapping does the userID exist in the current iteration still. if (IsValidClient(j) && !IsClientSourceTV(j) && g_iClientIndexUserIDMapping[i] == current_ClientUserID_iteration[j]) { does_UserID_still_exist = true; break; } } if (!does_UserID_still_exist) { g_iClientIndexUserIDMapping[i] = -1; KickClient(i, "Disconnect by user."); } } } CreateTimer(GetRandomFloat(5.0, 25.0), read_info_over_txt); return Plugin_Handled; } public Action update_info_over_txt(Handle timer, any data) { //sending map name, hostname and player names to the simulate server from ze server. char g_cMapname[256]; GetCurrentMap(g_cMapname, sizeof(g_cMapname)); static Handle hHostName; if((hHostName = FindConVar("hostname")) == INVALID_HANDLE) return Plugin_Handled; char hostname[256]; GetConVarString(hHostName, hostname, sizeof(hostname)); char msg[2048]; Format(msg, sizeof(msg), "%s\n%s\n", g_cMapname, hostname); //cleaning the file so it only contains mapname and hostname new Handle:testFile = OpenFile("/addons/sourcemod/logs/simulate.txt", "w"); WriteFileLine(testFile, msg); CloseHandle(testFile); Format(msg, sizeof(msg), ""); for (int i = 0; i < MaxClients; i++) { if (IsValidClient(i) && !IsClientSourceTV(i)) { int frags = GetClientFrags(i); //GetClientUserId is the only consistent thing for fakeclients. Format(msg, sizeof(msg), "%d %i %N\n", GetClientUserId(i), frags, i); new Handle:testFile_l = OpenFile("/addons/sourcemod/logs/simulate.txt", "a"); WriteFileLine(testFile_l, msg); CloseHandle(testFile_l); } } return Plugin_Handled; } //sending players over to the actual ze server if its the simulated server. public void OnClientPostAdminCheck(int client) { if (g_iServerPort != server_ports[1]) { return; } if (!IsFakeClient(client) && (!IsClientSourceTV(client))) { ClientCommand(client, "redirect ze.unloze.com:27015"); } } stock bool IsValidClient(int client) { if (client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client)) return true; return false; }