void DownloadUserAvatar(int clientnum, int guid)
{
	if (avatarinfo[clientnum].guid != guid)
	{
		Com_Printf(0, "Starting for client %d (guid %d)\n", clientnum, guid);
		NPAsync<NPGetUserAvatarResult>* async = NP_GetUserAvatar(guid, avatarinfo[clientnum].buffer, 1024 * 100);
		async->SetCallback(RecieveUserAvatarCB, (void*)clientnum);
		avatarinfo[clientnum].guid = guid;
	}
}
bool CSteamGameServer010::SendUserConnectAndAuthenticate( uint32 unIPClient, const void *pvAuthBlob, uint32 cubAuthBlobSize, CSteamID *pSteamIDUser ) {
	
	#ifdef KEY_DISABLED
	NPAuthenticateTicket* ticket = (NPAuthenticateTicket*)pvAuthBlob;

	GSClientApprove_t* retvals = (GSClientApprove_t*)malloc(sizeof(GSClientApprove_t));
	retvals->m_SteamID = CSteamID(ticket->clientID);
	CSteamBase::ReturnCall(retvals, sizeof(GSClientApprove_t), GSClientApprove_t::k_iCallback, 0);
	return true;
#endif

	NPAsync<NPValidateUserTicketResult>* async = NP_ValidateUserTicket(pvAuthBlob, cubAuthBlobSize, unIPClient, pSteamIDUser->ConvertToUint64());
	async->SetCallback(SteamGS_OnValidateTicket, NULL);
	return true;
}
    __declspec(dllexport) bool __cdecl SteamAPI_Init()
    {
#if USE_MANAGED_CODE
		IW4::AdminPluginCode::Initialize();
#endif
		//HideCode_FindCreateFile();

#ifdef PRE_RELEASE_DEMO
		DisableOldVersions();
#endif

		NP_SetLogCallback(NP_LogCB);
		NP_Init();

		NP_RegisterEACallback(NPA_StateSet);

#ifdef KEY_DISABLED
		if (!GAME_FLAG(GAME_FLAG_DEDICATED))
		{
#endif
		if (!NP_Connect(NP_SERVER, 3025))
		{
			// TODO: offer offline mode in this case/with an offline gameflag
			Com_Error(1, "Could not connect to NP server at " NP_SERVER);
			return false;
		}
#ifdef KEY_DISABLED
		}
#endif

		NPAuthenticateResult* result;

		if (!GAME_FLAG(GAME_FLAG_DEDICATED))
		{
			NPAsync<NPAuthenticateResult>* async = NP_AuthenticateWithToken(Auth_GetSessionID());
			result = async->Wait();
		}
		else
		{
			//NPAsync<NPAuthenticateResult>* async = NP_AuthenticateWithLicenseKey("123456789012345678901234");
#ifndef KEY_DISABLED
			/*const char* licenseKey = GetLicenseKey();

			if (!licenseKey)
			{
				Com_Error(1, "No license key set. Pass a license key in the command line of the application (like iw4.exe #123456789012345678901234).");
			}*/

			dvar_t* licenseKey = Dvar_RegisterString("np_licenseKey", "", DVAR_FLAG_DEDISAVED, "NP dedicated server license key");
			dvar_t* licenseID = Dvar_RegisterString("np_licenseID", "", DVAR_FLAG_DEDISAVED, "NP dedicated server ID");
			InitializeDediConfig();

			if (!licenseKey->current.string[0])
			{
				NPAsync<NPRegisterServerResult>* regAsync = NP_RegisterServer("iw4m ftw! hey guys, it's me, the cake hero! cake is lovely and tasty! eat many cakes in your life! bye!");
				NPRegisterServerResult* regResult = regAsync->Wait();

				if (regResult->result != AuthenticateResultOK)
				{
					switch (result->result)
					{
					case AuthenticateResultBadDetails:
						Com_Error(1, "Could not register to NP server at " NP_SERVER " -- bad details.");
						break;
					case AuthenticateResultServiceUnavailable:
						Com_Error(1, "Could not register to NP server at " NP_SERVER " -- service unavailable.");
						break;
					case AuthenticateResultBanned:
						Com_Error(1, "Could not register to NP server at " NP_SERVER " -- banned.");
						break;
					case AuthenticateResultUnknown:
						Com_Error(1, "Could not register to NP server at " NP_SERVER " -- unknown error.");
						break;
					}
				}

				Dvar_SetCommand("np_licenseKey", regResult->licenseKey);
				Dvar_SetCommand("np_licenseID", va("%i", regResult->serverID));
			}

			NPAsync<NPAuthenticateResult>* async = NP_AuthenticateWithLicenseKey(licenseKey->current.string);
			result = async->Wait();

			//dvar_t* net_port = Dvar_FindVar("net_port");
			//NP_SendRandomString(va("port %i", net_port->current.integer));
#endif
		}
#ifndef KEY_DISABLED
		if (result->result != AuthenticateResultOK)
		{
			switch (result->result)
			{
			case AuthenticateResultBadDetails:
				Dvar_SetCommand("np_licenseKey", "");

				if (GAME_FLAG(GAME_FLAG_DEDICATED))
				{
					Com_SaveDediConfig();
				}

				Com_Error(1, "Could not authenticate to NP server at " NP_SERVER " -- bad details.");
				break;
			case AuthenticateResultAlreadyLoggedIn:
				Com_Error(1, "Could not authenticate to NP server at " NP_SERVER " -- already logged in.");
				break;
			case AuthenticateResultServiceUnavailable:
				Com_Error(1, "Could not authenticate to NP server at " NP_SERVER " -- service unavailable.");
				break;
			case AuthenticateResultBanned:
				Com_Error(1, "Could not authenticate to NP server at " NP_SERVER " -- banned.");
				break;
			case AuthenticateResultUnknown:
				Com_Error(1, "Could not authenticate to NP server at " NP_SERVER " -- unknown error.");
				break;
			}
		}
#endif

		g_extDLL = (IExtDLL*)NP_LoadGameModule(BUILDNUMBER);

		if (!g_extDLL) Com_Error(1, "Could not load the extension DLL for revision number " BUILDNUMBER_STR);

		g_extDLL->Initialize(_gameFlags, new ClientDLLAPI());

		ignoreThisFx = g_extDLL->AssetRestrict_Trade1(&useEntryNames);
		g_nuiDraw = g_extDLL->GetNUIDraw();
		g_scriptability = g_extDLL->GetScriptability();

		g_scriptability->cbExceptionFilter = CustomUnhandledExceptionFilter;

#ifdef WE_DO_WANT_NUI
		g_scriptability->cbInitNUI();
#endif

		NP_RegisterKickCallback(NPA_KickClient);

		SteamProxy_Init();

		// perform Steam validation
		SteamProxy_DoThatTwinklyStuff();

		NPID npID;
		NP_GetNPID(&npID);

		return true;

		// private build?
		int id = npID & 0xFFFFFFFF;

		if (id != 2 && id != 1052 && id != 2337 && id != 5428 && id != 233 && id != 337 && id != 341138 && id != 228 && id != 165422 && id != 1304 && id != 1126 && id != 348 && id != 1330 && id != 826 && id != 24140 && id != 66 && id != 8206 && id != 1546 && id != 172 && id != 677 && id != 406 && id != 217 && id != 111 && id != 561 && id != 39566 && id != 669 && id != 788 && id != 616 && id != 161 && id != 303 && id != 40974 && id != 208 && id != 351 && id != 264 && id != 699 && id != 1710)
		{
			ExitProcess(1);
		}

        return true;
    }
bool ExtDLL_CheckSafety()
{
	// check #1: NP validity
	NPAsync<NPGetPublisherFileResult>* async = NP_GetPublisherFile("hello_world.txt", (uint8_t*)helloWorld, sizeof(helloWorld));
	NPGetPublisherFileResult* result = async->Wait();

	if (result->result != GetFileResultOK)
	{
		MessageBoxA(NULL, "The IW4M extension DLL failed to load due to the master server lacking support for the functionality provided by this DLL.", "IW4M", MB_OK);
		return false;
	}

	// check #2: DLL signature
	if (!GAME_FLAG(GAME_FLAG_DEDICATED))
	{
		HMODULE iw4m = GetModuleHandleA("iw4m.dll");

		if (!iw4m)
		{
			return false;
		}

		wchar_t filename[MAX_PATH];
		GetModuleFileNameW(iw4m, filename, sizeof(filename) / 2);

		WINTRUST_FILE_INFO info;
		memset(&info, 0, sizeof(info));

		info.cbStruct = sizeof(info);
		info.pcwszFilePath = filename;
		info.hFile = NULL;
		info.pgKnownSubject = NULL;

		GUID WVTPolicyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2;

		WINTRUST_DATA data;
		memset(&data, 0, sizeof(data));

		data.cbStruct = sizeof(data);
		data.pPolicyCallbackData = NULL;
		data.pSIPClientData = NULL;
		data.dwUIChoice = WTD_UI_NONE;
		data.fdwRevocationChecks = WTD_REVOKE_NONE;
		data.dwUnionChoice = WTD_CHOICE_FILE;
		data.dwStateAction = 0;
		data.hWVTStateData = NULL;
		data.pwszURLReference = NULL;
		data.dwUIContext = 0;
		data.pFile = &info;

		LONG status = WinVerifyTrust(NULL, &WVTPolicyGUID, &data);

		if (status != ERROR_SUCCESS)
		{
			MessageBoxA(NULL, va("The IW4M extension DLL failed to load due to a trust chain error. The specific error was 0x%x.", status), "IW4M", MB_OK);
			return false;
		}
	}

	return true;
}
	__declspec(dllexport) bool __cdecl SteamAPI_Init()
	{
	    NP_SetLogCallback(NP_LogCB);
		NP_Init();

#ifdef KEY_DISABLED
		if (!GAME_FLAG(GAME_FLAG_DEDICATED))
		{
#endif
		if (!NP_Connect(MASTER_SERVER, 3025))
		{
			// TODO: offer offline mode in this case/with an offline gameflag
			Com_Error(1, "Could not connect to NP server at " MASTER_SERVER);
			return false;
		}
#ifdef KEY_DISABLED
		}
#endif

		NPAuthenticateResult* result;

		if (!GAME_FLAG(GAME_FLAG_DEDICATED))
		{
			//NPAsync<NPAuthenticateResult>* async = NP_AuthenticateWithToken(Auth_GetSessionID());
			NPAsync<NPAuthenticateResult>* async = NP_AuthenticateWithLicenseKey("123456789012345678901234");
			result = async->Wait();
		}
		else
		{
			//NPAsync<NPAuthenticateResult>* async = NP_AuthenticateWithLicenseKey("123456789012345678901234");
#ifndef KEY_DISABLED
			//const char* licenseKey = GetLicenseKey();

			Dvar_RegisterString("dw_licensefile", "dwkey.dat", 16, "");

			char licenseKey[26];
			if (!DW_ReadLicenseKey(licenseKey, sizeof(licenseKey)))
			{
				return false;
			}

			licenseKey[24] = '\0';

			NPAsync<NPAuthenticateResult>* async = NP_AuthenticateWithLicenseKey(licenseKey);
			result = async->Wait();
#endif
		}
#ifndef KEY_DISABLED
		if (result->result != AuthenticateResultOK)
		{
			switch (result->result)
			{
			case AuthenticateResultBadDetails:
				Com_Error(1, "Could not authenticate to NP server at " MASTER_SERVER " -- bad details.");
				break;
			case AuthenticateResultAlreadyLoggedIn:
				Com_Error(1, "Could not authenticate to NP server at " MASTER_SERVER " -- already logged in.");
				break;
			case AuthenticateResultServiceUnavailable:
				Com_Error(1, "Could not authenticate to NP server at " MASTER_SERVER " -- service unavailable.");
				break;
			case AuthenticateResultBanned:
				Com_Error(1, "Could not authenticate to NP server at " MASTER_SERVER " -- banned.");
				break;
			case AuthenticateResultUnknown:
				Com_Error(1, "Could not authenticate to NP server at " MASTER_SERVER " -- unknown error.");
				break;
			}
		}
#endif
		NP_RegisterKickCallback(NPA_KickClient);

        return true;
	}