292 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			SourcePawn
		
	
	
	
	
	
			
		
		
	
	
			292 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			SourcePawn
		
	
	
	
	
	
| #pragma semicolon 1
 | |
| 
 | |
| #include <sourcemod>
 | |
| #include <sdktools>
 | |
| 
 | |
| int server_ports[2] = {27015, 27078}; //server ports: ze server, simulated server.
 | |
| int g_iServerPort;
 | |
| int g_iClientIndexUserIDMapping[MAXPLAYERS + 1];
 | |
| bool g_bCooldownMapChange = false;
 | |
| 
 | |
| 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_bCooldownMapChange = false;
 | |
|     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(2.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))
 | |
|     {
 | |
|         char letters[26] = "abcdefghijklmnopqrstuvwxyz\0";
 | |
|         int iRandom = GetRandomInt(0, 25);
 | |
|         char random_char_begin = letters[iRandom];
 | |
|         int iRandom_end = GetRandomInt(0, 25);
 | |
|         char random_char_end = letters[iRandom_end];
 | |
|         char final_name[MAX_NAME_LENGTH * 2];
 | |
|         Format(final_name, sizeof(final_name), "%s%s%s", random_char_begin, g_cClientNewName[client], random_char_end);
 | |
|         SetClientName(client, final_name);
 | |
|         Format(g_cClientNewName[client], sizeof(g_cClientNewName[]), final_name);
 | |
|     }
 | |
|     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
 | |
|         {
 | |
|             //its prefered instead to just fake the mapname since the fakeclients wont have to be kicked on mapchange then.
 | |
|             /*
 | |
|             char mapname[256];
 | |
|             GetCurrentMap(mapname, sizeof(mapname));
 | |
|             if (!StrEqual(mapname, lineBuffer))
 | |
|             {
 | |
|                 //ForceChangeLevel(lineBuffer, "");
 | |
|                 break;
 | |
|             }
 | |
|             */
 | |
|             char cmd[256];
 | |
|             Format(cmd, sizeof(cmd), "sv_mapname_override %s", lineBuffer);
 | |
|             ServerCommand(cmd);
 | |
|             //handled server hibernation with https://forums.alliedmods.net/showthread.php?t=331283
 | |
|         }
 | |
|         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];
 | |
|             char final_name[MAX_NAME_LENGTH * 2];
 | |
|             //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)
 | |
|             {
 | |
|                 char letters[26] = "abcdefghijklmnopqrstuvwxyz\0";
 | |
|                 int iRandom = GetRandomInt(0, 25);
 | |
|                 char random_char_begin = letters[iRandom];
 | |
|                 int iRandom_end = GetRandomInt(0, 25);
 | |
|                 char random_char_end = letters[iRandom_end];
 | |
|                 Format(final_name, sizeof(final_name), "%s%s%s", random_char_begin, fixedName, random_char_end);
 | |
| 
 | |
|                 //User ID is new, so lets create the FakeClient.
 | |
|                 int iIndex = CreateFakeClient(final_name);
 | |
| 
 | |
|                 if(iIndex < 1 || iIndex > MaxClients)
 | |
|                     continue;
 | |
| 
 | |
|                 Format(g_cClientNewName[iIndex], sizeof(g_cClientNewName[]), final_name);
 | |
| 
 | |
|                 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, 5.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(2.0, 5.0), read_info_over_txt);
 | |
|     return Plugin_Handled;
 | |
| }
 | |
| 
 | |
| 
 | |
| public void OnMapEnd()
 | |
| {
 | |
|     g_bCooldownMapChange = true;
 | |
|     CreateTimer(20.0, allow_updating_again);
 | |
| }
 | |
| 
 | |
| public Action allow_updating_again(Handle timer, any data)
 | |
| {
 | |
|     g_bCooldownMapChange = false;
 | |
|     return Plugin_Handled;
 | |
| }
 | |
| 
 | |
| public Action update_info_over_txt(Handle timer, any data)
 | |
| {
 | |
|     if (g_bCooldownMapChange)
 | |
|     {
 | |
|         return Plugin_Handled;
 | |
|     }
 | |
|     //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;
 | |
| }
 |