const char *CSizzPluginContext::GetPlayerIPPortString( int ent_index )
{
	INetChannelInfo *pNetInfo = m_pEngine->GetPlayerNetInfo(ent_index);
	if (pNetInfo)
	{
		return pNetInfo->GetAddress();
	}
	return "";
}
void Firehose_Send(uint16_t port, size_t len, const uint8_t *src)
{
//	auto t_begin = std::chrono::high_resolution_clock::now();
	
//	for (int i = 1; i <= gpGlobals->maxClients; ++i) {
	for (int i = 1; i <= 1; ++i) {
		INetChannelInfo *info = engine->GetPlayerNetInfo(i);
		if (info == nullptr) continue;
		
		netadr_t c_addr(info->GetAddress());
		if (!c_addr.IsValid()) continue;
		
		c_addr.SetPort(port);
		
	//	DevMsg("Sending %u bytes to player %d: %s\n", len, i, c_addr.ToString());
		
		int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
		if (s < 0) {
			Warning("Firehose_Send: socket creation failed: %s\n", strerror(errno));
			continue;
		}
		
		sockaddr_in addr;
		c_addr.ToSockadr((sockaddr *)&addr);
		
//		bool retry;
//		do {
//			retry = false;
//			
			if (sendto(s, (const char *)src, len, 0, (const sockaddr *)&addr, sizeof(addr)) < 0) {
//				if (errno == ENOBUFS) {
//					retry = true;
//				} else {
					Warning("Firehose_Send: sendto failed: %s\n", strerror(errno));
//				}
			}
//		} while (retry);
		
#if defined _WINDOWS
		closesocket(s);
#else
		close(s);
#endif
	}
	
//	auto t_end = std::chrono::high_resolution_clock::now();
	
//	auto dt = t_end - t_begin;
//	DevMsg("Firehose_Send: %lld ns\n", std::chrono::duration_cast<std::chrono::nanoseconds>(dt).count());
}
//-----------------------------------------------------------------------------
// Returns an address from the given PlayerInfo instance.
//-----------------------------------------------------------------------------
bool AddressFromPlayerInfo2( IPlayerInfo* pInfo, const char*& output )
{
	if (!pInfo)
		return false;

	if (pInfo->IsFakeClient() || V_strstr(pInfo->GetNetworkIDString(), "BOT"))
	{
		output = "";
		return true;
	}

	unsigned int index;
	if (!IndexFromPlayerInfo(pInfo, index))
		return false;

	INetChannelInfo* netinfo = engine->GetPlayerNetInfo(index);
	if (!netinfo)
		return false;

	output = netinfo->GetAddress();
	return true;
}
//---------------------------------------------------------------------------------
// Purpose: Builds up a list of players that are 'kickable'
//---------------------------------------------------------------------------------
void ManiReservedSlot::BuildPlayerKickList( player_t *player_ptr, int *players_on_server )
{
	player_t	temp_player;
	active_player_t active_player;

	FreeList((void **) &active_player_list, &active_player_list_size);

	for (int i = 1; i <= max_players; i ++)
	{
#if defined ( GAME_CSGO )
		edict_t *pEntity = PEntityOfEntIndex(i);
#else
		edict_t *pEntity = engine->PEntityOfEntIndex(i);
#endif
		if( pEntity && !pEntity->IsFree())
		{
			if ( player_ptr && ( pEntity == player_ptr->entity ) )
				continue;

			IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity );
			if (playerinfo && playerinfo->IsConnected())
			{
				Q_strcpy(active_player.steam_id, playerinfo->GetNetworkIDString());
				if (FStrEq("BOT", active_player.steam_id))
				{
					continue;
				}

				INetChannelInfo *nci = engine->GetPlayerNetInfo(i);
				if (!nci)
				{
					continue;
				}

				active_player.entity = pEntity;

				active_player.ping = nci->GetAvgLatency(0);
				const char * szCmdRate = engine->GetClientConVarValue( i, "cl_cmdrate" );
				int nCmdRate = (20 > Q_atoi( szCmdRate )) ? 20 : Q_atoi(szCmdRate);
				active_player.ping -= (0.5f/nCmdRate) + TICKS_TO_TIME( 1.0f ); // correct latency

				// in GoldSrc we had a different, not fixed tickrate. so we have to adjust
				// Source pings by half a tick to match the old GoldSrc pings.
				active_player.ping -= TICKS_TO_TIME( 0.5f );
				active_player.ping = active_player.ping * 1000.0f; // as msecs
				active_player.ping = ((5 > active_player.ping) ? 5:active_player.ping); // set bounds, dont show pings under 5 msecs

				active_player.time_connected = nci->GetTimeConnected();
				Q_strcpy(active_player.ip_address, nci->GetAddress());
				if (gpManiGameType->IsSpectatorAllowed() &&
					playerinfo->GetTeamIndex () == gpManiGameType->GetSpectatorIndex())
				{
					active_player.is_spectator = true;
				}
				else
				{
					active_player.is_spectator = false;
				}
				active_player.user_id = playerinfo->GetUserID();
				Q_strcpy(active_player.name, playerinfo->GetName());

				if ( players_on_server )
					*players_on_server = *players_on_server + 1;

				active_player.kills = playerinfo->GetFragCount();
				active_player.deaths = playerinfo->GetDeathCount();
				Q_strcpy(temp_player.steam_id, active_player.steam_id);
				Q_strcpy(temp_player.ip_address, active_player.ip_address);
				Q_strcpy(temp_player.name, active_player.name);
				temp_player.is_bot = false;

				if (IsPlayerInReserveList(&temp_player))
				{
					continue;
				}

				active_player.index = i;

				if (mani_reserve_slots_include_admin.GetInt() == 1 &&
					gpManiClient->HasAccess(active_player.index, ADMIN, ADMIN_BASIC_ADMIN))
				{
					continue;
				}

				if (gpManiClient->HasAccess(active_player.index, IMMUNITY, IMMUNITY_RESERVE))
				{
					continue;
				}

				AddToList((void **) &active_player_list, sizeof(active_player_t), &active_player_list_size);
				active_player_list[active_player_list_size - 1] = active_player;
			}
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: restarts the game
//-----------------------------------------------------------------------------
void CTFOptionsVideoPanel::OnApplyChanges()
{
	BaseClass::OnApplyChanges();

	if ( RequiresRestart() )
	{
		INetChannelInfo *nci = engine->GetNetChannelInfo();
		if ( nci )
		{
			// Only retry if we're not running the server
			const char *pAddr = nci->GetAddress();
			if ( pAddr )
			{
				if ( Q_strncmp(pAddr,"127.0.0.1",9) && Q_strncmp(pAddr,"localhost",9) )
				{
					engine->ClientCmd_Unrestricted( "retry\n" );
				}
				else
				{
					engine->ClientCmd_Unrestricted( "disconnect\n" );
				}
			}
		}
	}


	// resolution
	char sz[256];
	//if ( m_nSelectedMode == -1 )
	//{
	//	m_pMode->GetText(sz, 256);
	//}
	//else
	//{
		m_pMode->GetItemText( m_nSelectedMode, sz, 256 );
	//}
	
	int width = 0, height = 0;
	sscanf(sz, "%i x %i", &width, &height);
	Msg("VIDEO %s\n", sz);
	// windowed
	bool windowed = (m_pWindowed->GetActiveItem() > 0) ? true : false;

	// make sure there is a change
	const MaterialSystem_Config_t &config = materials->GetCurrentConfigForVideoCard();
	if ( config.m_VideoMode.m_Width != width 
		|| config.m_VideoMode.m_Height != height
		|| config.Windowed() != windowed)
	{
		// set mode
		char szCmd[ 256 ];
		Q_snprintf( szCmd, sizeof( szCmd ), "mat_setvideomode %i %i %i\n", width, height, windowed ? 1 : 0 );
		Msg(szCmd);
		engine->ClientCmd_Unrestricted( szCmd );
	}

	if (config.m_VideoMode.m_Width != width || config.m_VideoMode.m_Height != height || config.Windowed() != windowed)
	{
		MAINMENU_ROOT->LaunchInvalidatePanelsLayout();
	}

	m_pGammaSlider->ApplyChanges();

	// apply changes
	engine->ClientCmd_Unrestricted( "mat_savechanges\n" );


	//VIDEOADV
	//if (!m_bUseChanges)
	//	return;

	ApplyChangesToConVar("mat_dxlevel", m_pDXLevel->GetActiveItemUserData()->GetInt("dxlevel"));
	ApplyChangesToConVar("r_rootlod", 2 - m_pModelDetail->GetActiveItem());
	ApplyChangesToConVar("mat_picmip", 2 - m_pTextureDetail->GetActiveItem());

	// reset everything tied to the filtering mode, then the switch sets the appropriate one
	ApplyChangesToConVar("mat_trilinear", false);
	ApplyChangesToConVar("mat_forceaniso", 1);
	switch (m_pFilteringMode->GetActiveItem())
	{
	case 0:
		break;
	case 1:
		ApplyChangesToConVar("mat_trilinear", true);
		break;
	case 2:
		ApplyChangesToConVar("mat_forceaniso", 2);
		break;
	case 3:
		ApplyChangesToConVar("mat_forceaniso", 4);
		break;
	case 4:
		ApplyChangesToConVar("mat_forceaniso", 8);
		break;
	case 5:
		ApplyChangesToConVar("mat_forceaniso", 16);
		break;
	}

	// Set the AA convars according to the menu item chosen
	int nActiveAAItem = m_pAntialiasingMode->GetActiveItem();
	ApplyChangesToConVar("mat_antialias", m_nAAModes[nActiveAAItem].m_nNumSamples);
	ApplyChangesToConVar("mat_aaquality", m_nAAModes[nActiveAAItem].m_nQualityLevel);

	if (m_pHDR->IsEnabled())
	{
		ConVarRef mat_hdr_level("mat_hdr_level");
		Assert(mat_hdr_level.IsValid());
		mat_hdr_level.SetValue(m_pHDR->GetActiveItem());
	}

	if (m_pShadowDetail->GetActiveItem() == 0)						// Blobby shadows
	{
		ApplyChangesToConVar("r_shadowrendertotexture", 0);			// Turn off RTT shadows
		ApplyChangesToConVar("r_flashlightdepthtexture", 0);			// Turn off shadow depth textures
	}
	else if (m_pShadowDetail->GetActiveItem() == 1)					// RTT shadows only
	{
		ApplyChangesToConVar("r_shadowrendertotexture", 1);			// Turn on RTT shadows
		ApplyChangesToConVar("r_flashlightdepthtexture", 0);			// Turn off shadow depth textures
	}
	else if (m_pShadowDetail->GetActiveItem() == 2)					// Shadow depth textures
	{
		ApplyChangesToConVar("r_shadowrendertotexture", 1);			// Turn on RTT shadows
		ApplyChangesToConVar("r_flashlightdepthtexture", 1);			// Turn on shadow depth textures
	}

	ApplyChangesToConVar("mat_reducefillrate", (m_pShaderDetail->GetActiveItem() > 0) ? 0 : 1);

	switch (m_pWaterDetail->GetActiveItem())
	{
	default:
	case 0:
#ifndef _X360
		ApplyChangesToConVar("r_waterforceexpensive", false);
#endif
		ApplyChangesToConVar("r_waterforcereflectentities", false);
		break;
	case 1:
#ifndef _X360
		ApplyChangesToConVar("r_waterforceexpensive", true);
#endif
		ApplyChangesToConVar("r_waterforcereflectentities", false);
		break;
	case 2:
#ifndef _X360
		ApplyChangesToConVar("r_waterforceexpensive", true);
#endif
		ApplyChangesToConVar("r_waterforcereflectentities", true);
		break;
	}

	m_pFOVSlider->ApplyChanges();

	ApplyChangesToConVar("mat_vsync", m_pVSync->GetActiveItem());

	ApplyChangesToConVar("mat_colorcorrection", m_pColorCorrection->GetActiveItem());

	ApplyChangesToConVar("mat_queue_mode", m_pQueuedMode->GetActiveItem() * -1);

	ApplyChangesToConVar("mat_motion_blur_enabled", m_pMotionBlur->GetActiveItem());
}