using Game.Model;
using GameServices;
using Unity.Netcode;
using Unity.Netcode.Transports.UTP;
using UnityEngine;
using UnityEngine.SceneManagement;
using Steamworks;
using System;
using System.Threading.Tasks;
public class ClientNetworkManager : NetworkManager
{
[SerializeField] private string mainMenuSceneName = "MainMenu";
[SerializeField] private string defaultServerIP = "owo";
[SerializeField] private ushort defaultServerPort = 7777;
private bool isConnecting = false;
private CSteamID targetSteamID;
private Callback<P2PSessionRequest_t> p2pSessionRequestCallback;
private bool usingSteamNetworking = false;
async void Start()
{
if (SteamAPI.IsSteamRunning())
{
p2pSessionRequestCallback = Callback<P2PSessionRequest_t>.Create(OnP2PSessionRequest);
await ProcessSteamPlayerInfo();
}
else
{
Debug.LogWarning("Steam is not running. Using PlayerPrefs data if available.");
ProcessPlayerPrefs();
}
LoadMainMenu();
Debug.Log("Client Ready");
}
private void OnP2PSessionRequest(P2PSessionRequest_t request)
{
Debug.Log($"Accepting P2P session with: {request.m_steamIDRemote}");
SteamNetworking.AcceptP2PSessionWithUser(request.m_steamIDRemote);
}
public bool ConnectToServerViaSteam(string steamIdString)
{
if (isConnecting || IsClient)
{
Debug.LogWarning("Already connecting or connected to server");
return false;
}
if (!SteamAPI.IsSteamRunning())
{
Debug.LogError("Steam is not running. Cannot connect via Steam.");
return false;
}
ulong steamIdValue;
if (!ulong.TryParse(steamIdString, out steamIdValue))
{
Debug.LogError($"Invalid Steam ID format: {steamIdString}");
return false;
}
CSteamID serverId = new CSteamID(steamIdValue);
return ConnectToServerViaSteam(serverId);
}
public bool ConnectToServerViaSteam(CSteamID serverId)
{
if (isConnecting || IsClient)
{
Debug.LogWarning("Already connecting or connected to server");
return false;
}
if (!SteamAPI.IsSteamRunning())
{
Debug.LogError("Steam is not running. Cannot connect via Steam.");
return false;
}
Debug.Log($"Connecting to Steam server ID: {serverId}");
targetSteamID = serverId;
SteamNetworking.AllowP2PPacketRelay(true);
byte[] connectData = System.Text.Encoding.UTF8.GetBytes("CONNECT_REQUEST");
bool success = SteamNetworking.SendP2PPacket(
serverId,
connectData,
(uint)connectData.Length,
EP2PSend.k_EP2PSendReliable);
if (success)
{
Debug.Log("Initial Steam P2P connection packet sent");
isConnecting = true;
usingSteamNetworking = true;
SetupNetcodeForSteamConnection(serverId);
return true;
}
else
{
Debug.LogError("Failed to send initial Steam P2P connection packet");
return false;
}
}
private void SetupNetcodeForSteamConnection(CSteamID serverId)
{
UnityTransport existingTransport = GetComponent<UnityTransport>();
if (existingTransport != null)
{
DestroyImmediate(existingTransport);
}
// Add fresh transport
UnityTransport transport = gameObject.AddComponent<UnityTransport>();
transport.ConnectionData.Address = "127.0.0.1";
transport.ConnectionData.Port = defaultServerPort;
transport.MaxConnectAttempts = 3;
transport.ConnectTimeoutMS = 15000;
NetworkConfig.NetworkTransport = transport;
// Attach connection callbacks
OnClientConnectedCallback += OnClientConnected;
OnClientDisconnectCallback += OnClientDisconnect;
// Start client
bool result = StartClient();
if (!result)
{
Debug.LogError("Failed to start client connection");
isConnecting = false;
usingSteamNetworking = false;
}
}
public bool ConnectToServer(string serverIP = null, ushort? serverPort = null)
{
if (isConnecting || IsClient)
{
Debug.LogWarning("Already connecting or connected to server");
return false;
}
string targetIP = serverIP ?? defaultServerIP;
ushort targetPort = serverPort ?? defaultServerPort;
UnityTransport existingTransport = GetComponent<UnityTransport>();
if (existingTransport != null)
{
DestroyImmediate(existingTransport);
}
UnityTransport transport = gameObject.AddComponent<UnityTransport>();
transport.ConnectionData.Address = targetIP;
transport.ConnectionData.Port = targetPort;
transport.MaxConnectAttempts = 2;
transport.ConnectTimeoutMS = 10000;
NetworkConfig.NetworkTransport = transport;
Debug.Log($"Attempting to connect to server at {targetIP}:{targetPort}");
isConnecting = true;
usingSteamNetworking = false;
OnClientConnectedCallback += OnClientConnected;
OnClientDisconnectCallback += OnClientDisconnect;
bool result = StartClient();
if (!result)
{
Debug.LogError("Failed to start client connection");
isConnecting = false;
}
return result;
}
private void OnClientConnected(ulong clientId)
{
Debug.Log($"Successfully connected to server! Client ID: {clientId}");
isConnecting = false;
if (usingSteamNetworking)
{
Debug.Log("Connection established using Steam networking");
}
}
private void OnClientDisconnect(ulong clientId)
{
Debug.Log($"Disconnected from server. Client ID: {clientId}");
isConnecting = false;
usingSteamNetworking = false;
}
private async Task ProcessSteamPlayerInfo()
{
try {
CSteamID steamID = SteamUser.GetSteamID();
string steamIdString = steamID.ToString();
Debug.Log($"Steam ID retrieved: {steamIdString}");
Player player = await PlayerService.GetPlayer(steamIdString);
PlayerPrefs.SetString("Gamertag", player.Gamertag);
PlayerPrefs.SetString("SteamID", steamIdString);
PlayerPrefs.Save();
Debug.Log($"Player retrieved/created: {player.Gamertag}");
}
catch (System.Exception e) {
Debug.LogError($"Error retrieving Steam ID or player data: {e.Message}");
ProcessPlayerPrefs();
}
}
private void ProcessPlayerPrefs()
{
if (PlayerPrefs.HasKey("Gamertag")) {
string gamertag = PlayerPrefs.GetString("Gamertag");
Debug.Log($"Using cached player data: {gamertag}");
}
}
private void LoadMainMenu()
{
Debug.Log($"Scene name to load: '{mainMenuSceneName}'");
if (Application.CanStreamedLevelBeLoaded(mainMenuSceneName))
{
string sceneName = mainMenuSceneName;
Debug.Log($"Loading main menu scene: {sceneName}");
SceneManager.LoadScene(sceneName, LoadSceneMode.Single);
}
else
{
Debug.LogError($"Scene '{mainMenuSceneName}' is nOT in build settings or misspelled.");
}
}
public async void TestBasicConnection(string ip = null, int? port = null)
{
string targetIP = ip ?? defaultServerIP;
int targetPort = port ?? defaultServerPort;
try
{
Debug.Log($"Testing basic TCP connection to {targetIP}:{targetPort}...");
using (var client = new System.Net.Sockets.TcpClient())
{
var connectTask = client.ConnectAsync(targetIP, targetPort);
var timeoutTask = System.Threading.Tasks.Task.Delay(5000);
if (await System.Threading.Tasks.Task.WhenAny(connectTask, timeoutTask) == timeoutTask)
{
Debug.Log($"TCP connection to {targetIP}:{targetPort} timed out");
return;
}
if (client.Connected)
{
Debug.Log($"TCP connection to {targetIP}:{targetPort} successful!");
}
else
{
Debug.Log($"TCP connection to {targetIP}:{targetPort} failed (client reports not connected)");
}
}
}
catch (System.Exception ex)
{
Debug.LogError($"TCP connection test error: {ex.Message}");
}
}
}