// Initialize SteamGameServer client and interface objects, and set server properties which may not be changed.
        //
        // After calling this function, you should set any additional server parameters, and then
        // call ISteamGameServer::LogOnAnonymous() or ISteamGameServer::LogOn()
        //
        // - unIP will usually be zero.  If you are on a machine with multiple IP addresses, you can pass a non-zero
        //   value here and the relevant sockets will be bound to that IP.  This can be used to ensure that
        //   the IP you desire is the one used in the server browser.
        // - usGamePort is the port that clients will connect to for gameplay.  You will usually open up your
        //   own socket bound to this port.
        // - usQueryPort is the port that will manage server browser related duties and info
        //		pings from clients.  If you pass STEAMGAMESERVER_QUERY_PORT_SHARED for usQueryPort, then it
        //		will use "GameSocketShare" mode, which means that the game is responsible for sending and receiving
        //		UDP packets for the master  server updater.  (See ISteamGameServer::HandleIncomingPacket and
        //		ISteamGameServer::GetNextOutgoingPacket.)
        // - The version string should be in the form x.x.x.x, and is used by the master server to detect when the
        //		server is out of date.  (Only servers with the latest version will be listed.)
        public static bool Init(uint unIP, ushort usGamePort, ushort usQueryPort, EServerMode eServerMode, string pchVersionString)
        {
            InteropHelp.TestIfPlatformSupported();

            bool ret;

            using (var pchVersionString2 = new InteropHelp.UTF8StringHandle(pchVersionString)) {
                ret = NativeMethods.SteamInternal_GameServer_Init(unIP, 0, usGamePort, usQueryPort, eServerMode, pchVersionString2);
            }

            // Steamworks.NET specific: We initialize the SteamAPI Context like this for now, but we need to do it
            // every time that Unity reloads binaries, so we also check if the pointers are available and initialized
            // before each call to any interface functions. That is in InteropHelp.cs
            if (ret)
            {
                ret = CSteamGameServerAPIContext.Init();
            }

            if (ret)
            {
                CallbackDispatcher.Initialize();
            }

            return(ret);
        }
        //----------------------------------------------------------------------------------------------------------------------------------------------------------//
        //	Steam API setup & shutdown
        //
        //	These functions manage loading, initializing and shutdown of the steamclient.dll
        //
        //----------------------------------------------------------------------------------------------------------------------------------------------------------//


        // SteamAPI_Init must be called before using any other API functions. If it fails, an
        // error message will be output to the debugger (or stderr) with further information.
        public static FailureReason Init()
        {
            InteropHelp.TestIfPlatformSupported();

            var  reason = FailureReason.None;
            bool ret    = NativeMethods.SteamAPI_Init();

            if (!ret)
            {
                reason |= FailureReason.SteamAPI_Init;
            }
            // Steamworks.NET specific: We initialize the SteamAPI Context like this for now, but we need to do it
            // every time that Unity reloads binaries, so we also check if the pointers are available and initialized
            // before each call to any interface functions. That is in InteropHelp.cs
            if (reason == FailureReason.None)
            {
                reason |= CSteamAPIContext.Init();
            }

            if (reason == FailureReason.None)
            {
                CallbackDispatcher.Initialize();
            }

            return(reason);
        }