Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Basis/Packages/com.basis.eventdriver/BasisEventDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ public partial class BasisEventDriver : MonoBehaviour

public static bool StateOfOnRenderBefore = false;

public static Action OnUpdate;


// ── Lifecycle ───────────────────────────────────────────────

Expand Down Expand Up @@ -213,6 +215,7 @@ public void Update()
OSCAcquisitionServer.Simulate();
SMModuleAvatarPerformanceLimits.SimulateDebounce();
timeSinceLastUpdate += DeltaTime;
OnUpdate?.Invoke();
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,31 @@ public partial class EventBasedNetListener
public event OnNetworkError NetworkErrorEvent;
public event OnPeerConnected PeerConnectedEvent;
public event OnNetworkReceiveUnconnected NetworkReceiveUnconnectedEvent;

public void RaiseConnectionRequest(ConnectionRequest request)
{
ConnectionRequestEvent?.Invoke(request);
}

public void RaisePeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo)
{
PeerDisconnectedEvent?.Invoke(peer, disconnectInfo);
}

public void RaiseNetworkReceive(NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod)
{
NetworkReceiveEvent?.Invoke(peer, reader, channel, deliveryMethod);
}

public void RaisePeerConnected(NetPeer peer)
{
PeerConnectedEvent?.Invoke(peer);
}

public void RaiseNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader)
{
NetworkReceiveUnconnectedEvent?.Invoke(remoteEndPoint, reader);
}
}

public interface ConnectionRequest
Expand Down Expand Up @@ -99,6 +124,10 @@ public void Start(int SetPort)

public sealed partial class NetStatistics
{
public NetStatistics()
{
}

public long PacketsSent;
public long PacketsReceived;
public long BytesSent;
Expand All @@ -115,6 +144,20 @@ public partial class NetPacketReader : NetDataReader
internal DeliveryMethod method;
#endif

public NetPacketReader()
{
}

public NetPacketReader(byte[] source, int offset, int maxSize, Action recycle) : base(source, offset, maxSize)
{
RecycleInternal = recycle;
}

public static NetPacketReader Create(byte[] source, int offset, int maxSize, Action recycle)
{
return new NetPacketReader(source, offset, maxSize, recycle);
}

public void Recycle(bool IsOkTOHaveEmptyData = false)
{
#if UNITY_EDITOR || DEVELOPMENT_BUILD
Expand Down
23 changes: 23 additions & 0 deletions Basis/Packages/com.basis.steamtransport/BasisSteamTransport.asmdef
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "BasisSteamTransport",
"rootNamespace": "",
"references": [
"BasisCommon",
"BasisDebug",
"BasisNetworkCore",
"BasisSteamTransportCore",
"BasisBundleManagement",
"Basis Framework",
"BasisEventDriver",
"BasisSDK"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Basis/Packages/com.basis.steamtransport/Runtime.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
using Steamworks;
using Basis.EventDriver;
using UnityEngine;

namespace Basis.Scripts.Networking.Steam
{
[DefaultExecutionOrder(-14950)]
public class BasisSteamBootstrap : MonoBehaviour
{
public BasisSteamSettings Settings;

public static BasisSteamBootstrap Instance;
public static BasisSteamSettings ActiveSettings { get; private set; }
public static bool IsInitialized => SteamClient.IsValid;
public static bool HasTriedInitialization { get; private set; }
public static bool HasRequestedRelayWarmup { get; private set; }

[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void EnsureRuntimeInstance()
{
if (Instance != null)
{
return;
}

GameObject bootstrapObject = new GameObject(nameof(BasisSteamBootstrap));
DontDestroyOnLoad(bootstrapObject);
bootstrapObject.hideFlags = HideFlags.DontSave;
bootstrapObject.AddComponent<BasisSteamBootstrap>();
}

private void OnEnable()
{
if (Instance != null && Instance != this)
{
enabled = false;
return;
}

Instance = this;
ActiveSettings = ResolveSettings(Settings);
BasisSteamTransportMetrics.Reset();
BasisSteamTransportTrace.Configure(ActiveSettings != null && ActiveSettings.EnableTransportTrace);
BasisSteamTransportTrace.Clear();

if (SteamClient.IsValid)
{
EnsureRelayWarmup();
}

if (ActiveSettings != null && ActiveSettings.AutoInitialize)
{
EnsureInitialized(ActiveSettings);
}

BasisEventDriver.OnUpdate -= Tick;
BasisEventDriver.OnUpdate += Tick;
}

private static void Tick()
{
if (SteamClient.IsValid && ActiveSettings != null && ActiveSettings.RunCallbacksManually)
{
SteamClient.RunCallbacks();
}

BasisSteamTransportTrace.FlushPending();
SteamNetManager.PollActiveManagers();
}

private void OnDisable()
{
if (Instance == this)
{
Instance = null;
}

BasisEventDriver.OnUpdate -= Tick;
}

private void OnApplicationQuit()
{
BasisSteamTransportTrace.FlushPending(force: true);
Shutdown();
}

public static bool EnsureInitialized(BasisSteamSettings settings)
{
HasTriedInitialization = true;
settings = ResolveSettings(settings);

if (settings == null)
{
BasisDebug.LogError("Missing BasisSteamSettings asset. Cannot initialize Steam.", BasisDebug.LogTag.Networking);
return false;
}

ActiveSettings = settings;
BasisSteamTransportTrace.Configure(ActiveSettings != null && ActiveSettings.EnableTransportTrace);

if (SteamClient.IsValid)
{
return true;
}

try
{
if (settings.RestartAppIfNecessary && SteamClient.RestartAppIfNecessary(settings.AppId))
{
return false;
}

SteamClient.Init(settings.AppId, asyncCallbacks: !settings.RunCallbacksManually);
EnsureRelayWarmup();
return SteamClient.IsValid;
}
catch (System.Exception ex)
{
BasisDebug.LogError($"Steam init failed: {ex.Message}", BasisDebug.LogTag.Networking);
return false;
}
}

public static void Shutdown()
{
BasisSteamLobbyService.HandleSteamShutdown();

if (SteamClient.IsValid)
{
SteamClient.Shutdown();
}

HasRequestedRelayWarmup = false;
}

public static BasisSteamSettings ResolveSettings(BasisSteamSettings settings = null)
{
if (settings != null)
{
ActiveSettings = settings;
return ActiveSettings;
}

if (ActiveSettings != null)
{
return ActiveSettings;
}

ActiveSettings = ScriptableObject.CreateInstance<BasisSteamSettings>();
ActiveSettings.hideFlags = HideFlags.DontSave;
return ActiveSettings;
}

private static void EnsureRelayWarmup()
{
if (HasRequestedRelayWarmup || !SteamClient.IsValid)
{
return;
}

SteamNetworkingUtils.InitRelayNetworkAccess();
HasRequestedRelayWarmup = true;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
using Basis.BasisUI;
using System;
using System.Threading;
using System.Threading.Tasks;
using static Basis.Scripts.UI.UI_Panels.BasisDataStoreItemKeys;

namespace Basis.Scripts.Networking.Steam
{
public static class BasisSteamBeeValidation
{
public static async Task<BasisSteamBeeValidationResult> ValidateWorldAsync(string url, string password, CancellationToken cancellationToken = default)
{
BasisSteamBeeValidationResult result = new BasisSteamBeeValidationResult
{
WorldUrl = url ?? string.Empty,
WorldPassword = password ?? string.Empty,
};

InputValidation.EntryValidationResponse validationResponse = InputValidation.ValidateEntry(url, password, Array.Empty<ItemKey>());
if (validationResponse.Result != InputValidation.EntryValidationResult.Success)
{
result.ErrorMessage = validationResponse.Result switch
{
InputValidation.EntryValidationResult.EmptyUrl => "URL cannot be empty.",
InputValidation.EntryValidationResult.InvalidUrlFormat => "URL format is invalid.",
InputValidation.EntryValidationResult.InvalidUrlScheme => "URL must start with http:// or https://",
InputValidation.EntryValidationResult.EmptyPassword => "Password cannot be empty.",
_ => "BEE validation input failed."
};
return result;
}

ItemKey tempItem = new ItemKey
{
Pass = validationResponse.Password,
Url = validationResponse.ProcessedUrl,
Mode = 0
};

var tempWrapper = LibraryProvider.CreateNewWrapperFromItem(tempItem);
BasisProgressReport report = new BasisProgressReport();

bool isValid = await BasisBeeManagement.HandleMetaOnlyLoad(tempWrapper.basisTrackedBundleWrapper, report, cancellationToken);
if (!isValid)
{
result.ErrorMessage = "The provided BEE file could not be validated.";
return result;
}

var loaded = await LibraryProvider.LoadWrapperFromDisc(tempItem, tempWrapper);
if (loaded?.BasisLoadableBundle?.BasisBundleConnector == null)
{
result.ErrorMessage = "Validated BEE file did not provide bundle connector metadata.";
return result;
}

BasisBundleConnector connector = loaded.BasisLoadableBundle.BasisBundleConnector;
result.WorldName = connector.BasisBundleDescription?.AssetBundleName ?? validationResponse.ProcessedUrl;

bool isWorld = false;
if (connector.MetaData.ComponentNames != null)
{
foreach (BasisBundleConnector.BasisComponentName component in connector.MetaData.ComponentNames)
{
if (string.Equals(component.Name, "BasisScene", StringComparison.OrdinalIgnoreCase))
{
isWorld = true;
break;
}
}
}

if (!isWorld)
{
result.ErrorMessage = "The provided BEE file is valid, but it is not a world scene bundle.";
return result;
}

result.WorldUrl = validationResponse.ProcessedUrl;
result.WorldPassword = validationResponse.Password;
result.IsValid = true;
return result;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading