#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]; char g_cClientNewName[MAXPLAYERS + 1][128]; //---------------------------------------------------------------------------------------------------- // 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(5.0, update_info_over_txt, _, TIMER_REPEAT); } else if (g_iServerPort == server_ports[1]) { CreateTimer(GetRandomFloat(1.0, 5.0), read_info_over_txt); } } public Action update_client_name(Handle hTimer, int Serial) { int client; if ((client = GetClientFromSerial(Serial)) == 0) { return Plugin_Handled; } if (IsValidClient(client)) { SetClientName(client, g_cClientNewName[client]); } return Plugin_Handled; } 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 (strlen(lineBuffer) == 0) { continue; } 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]); char fixedName[128]; //take everything after the frag. thats a white space + the entire name. int index_after_frag = StrContains(lineBuffer, sPart[1], false) + 1 + strlen(sPart[1]); //skipping the whitespace after frag strcopy(fixedName, sizeof(fixedName), lineBuffer[index_after_frag]); 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; } } //create one new fakeclient if not existing already if (!does_client_user_id_exist && !already_created_fakeClient) { //User ID is new, so lets create the FakeClient. int iIndex = CreateFakeClient(fixedName); if(iIndex < 1 || iIndex > MaxClients) continue; Format(g_cClientNewName[iIndex], sizeof(g_cClientNewName[]), fixedName); 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); if (!StrEqual(g_cClientNewName[i], fixedName)) { Format(g_cClientNewName[i], sizeof(g_cClientNewName[]), fixedName); CreateTimer(GetRandomFloat(1.0, 25.0), update_client_name, GetClientSerial(i)); } //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(1.0, 5.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; }