Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
MPAI-MMM
mmm-tec-unity
Commits
f6ed3c6f
Commit
f6ed3c6f
authored
Feb 21, 2025
by
cann-alberto
Browse files
first project commit
parent
4487b14f
Changes
1000
Hide whitespace changes
Inline
Side-by-side
Too many changes to show.
To preserve performance only
20 of 1000+
files are displayed.
Plain diff
Email patch
Assets/Mirror/Authenticators/Mirror.Authenticators.asmdef.meta
0 → 100644
View file @
f6ed3c6f
fileFormatVersion: 2
guid: e720aa64e3f58fb4880566a322584340
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Assets/Mirror/Authenticators/TimeoutAuthenticator.cs
0 → 100644
View file @
f6ed3c6f
using
System.Collections
;
using
UnityEngine
;
namespace
Mirror.Authenticators
{
/// <summary>
/// An authenticator that disconnects connections if they don't
/// authenticate within a specified time limit.
/// </summary>
[
AddComponentMenu
(
"Network/ Authenticators/Timeout Authenticator"
)]
public
class
TimeoutAuthenticator
:
NetworkAuthenticator
{
public
NetworkAuthenticator
authenticator
;
[
Range
(
0
,
600
),
Tooltip
(
"Timeout to auto-disconnect in seconds. Set to 0 for no timeout."
)]
public
float
timeout
=
60
;
public
void
Awake
()
{
authenticator
.
OnServerAuthenticated
.
AddListener
(
connection
=>
OnServerAuthenticated
.
Invoke
(
connection
));
authenticator
.
OnClientAuthenticated
.
AddListener
(
OnClientAuthenticated
.
Invoke
);
}
public
override
void
OnStartServer
()
{
authenticator
.
OnStartServer
();
}
public
override
void
OnStopServer
()
{
authenticator
.
OnStopServer
();
}
public
override
void
OnStartClient
()
{
authenticator
.
OnStartClient
();
}
public
override
void
OnStopClient
()
{
authenticator
.
OnStopClient
();
}
public
override
void
OnServerAuthenticate
(
NetworkConnectionToClient
conn
)
{
authenticator
.
OnServerAuthenticate
(
conn
);
if
(
timeout
>
0
)
StartCoroutine
(
BeginAuthentication
(
conn
));
}
public
override
void
OnClientAuthenticate
()
{
authenticator
.
OnClientAuthenticate
();
if
(
timeout
>
0
)
StartCoroutine
(
BeginAuthentication
(
NetworkClient
.
connection
));
}
IEnumerator
BeginAuthentication
(
NetworkConnection
conn
)
{
//Debug.Log($"Authentication countdown started {conn} {timeout}");
yield
return
new
WaitForSecondsRealtime
(
timeout
);
if
(!
conn
.
isAuthenticated
)
{
Debug
.
LogError
(
$"Authentication Timeout - Disconnecting
{
conn
}
"
);
conn
.
Disconnect
();
}
}
}
}
Assets/Mirror/Authenticators/TimeoutAuthenticator.cs.meta
0 → 100644
View file @
f6ed3c6f
fileFormatVersion: 2
guid: 24d8269a07b8e4edfa374753a91c946e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
Assets/Mirror/CompilerSymbols.meta
0 → 100644
View file @
f6ed3c6f
fileFormatVersion: 2
guid: 1f8b918bcd89f5c488b06f5574f34760
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Assets/Mirror/CompilerSymbols/Mirror.CompilerSymbols.asmdef
0 → 100644
View file @
f6ed3c6f
{
"name": "Mirror.CompilerSymbols",
"references": [],
"optionalUnityReferences": [],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": []
}
\ No newline at end of file
Assets/Mirror/CompilerSymbols/Mirror.CompilerSymbols.asmdef.meta
0 → 100644
View file @
f6ed3c6f
fileFormatVersion: 2
guid: 325984b52e4128546bc7558552f8b1d2
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Assets/Mirror/CompilerSymbols/PreprocessorDefine.cs
0 → 100644
View file @
f6ed3c6f
using
System.Collections.Generic
;
using
UnityEditor
;
namespace
Mirror
{
static
class
PreprocessorDefine
{
/// <summary>
/// Add define symbols as soon as Unity gets done compiling.
/// </summary>
[
InitializeOnLoadMethod
]
public
static
void
AddDefineSymbols
()
{
#if UNITY_2021_2_OR_NEWER
string
currentDefines
=
PlayerSettings
.
GetScriptingDefineSymbols
(
UnityEditor
.
Build
.
NamedBuildTarget
.
FromBuildTargetGroup
(
EditorUserBuildSettings
.
selectedBuildTargetGroup
));
#else
// Deprecated in Unity 2023.1
string
currentDefines
=
PlayerSettings
.
GetScriptingDefineSymbolsForGroup
(
EditorUserBuildSettings
.
selectedBuildTargetGroup
);
#endif
// Remove oldest when adding next month's symbol.
// Keep a rolling 12 months of symbols.
HashSet
<
string
>
defines
=
new
HashSet
<
string
>(
currentDefines
.
Split
(
';'
))
{
"MIRROR"
,
"MIRROR_79_OR_NEWER"
,
"MIRROR_81_OR_NEWER"
,
"MIRROR_82_OR_NEWER"
,
"MIRROR_83_OR_NEWER"
,
"MIRROR_84_OR_NEWER"
,
"MIRROR_85_OR_NEWER"
,
"MIRROR_86_OR_NEWER"
,
"MIRROR_89_OR_NEWER"
};
// only touch PlayerSettings if we actually modified it,
// otherwise it shows up as changed in git each time.
string
newDefines
=
string
.
Join
(
";"
,
defines
);
if
(
newDefines
!=
currentDefines
)
{
#if UNITY_2021_2_OR_NEWER
PlayerSettings
.
SetScriptingDefineSymbols
(
UnityEditor
.
Build
.
NamedBuildTarget
.
FromBuildTargetGroup
(
EditorUserBuildSettings
.
selectedBuildTargetGroup
),
newDefines
);
#else
// Deprecated in Unity 2023.1
PlayerSettings
.
SetScriptingDefineSymbolsForGroup
(
EditorUserBuildSettings
.
selectedBuildTargetGroup
,
newDefines
);
#endif
}
}
}
}
Assets/Mirror/CompilerSymbols/PreprocessorDefine.cs.meta
0 → 100644
View file @
f6ed3c6f
fileFormatVersion: 2
guid: f1d66fe74ec6f42dd974cba37d25d453
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
Assets/Mirror/Components.meta
0 → 100644
View file @
f6ed3c6f
fileFormatVersion: 2
guid: 9bee879fbc8ef4b1a9a9f7088bfbf726
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Assets/Mirror/Components/AssemblyInfo.cs
0 → 100644
View file @
f6ed3c6f
using
System.Runtime.CompilerServices
;
[
assembly
:
InternalsVisibleTo
(
"Mirror.Tests.Common"
)]
[
assembly
:
InternalsVisibleTo
(
"Mirror.Tests"
)]
// need to use Unity.*.CodeGen assembly name to import Unity.CompilationPipeline
// for ILPostProcessor tests.
[
assembly
:
InternalsVisibleTo
(
"Unity.Mirror.Tests.CodeGen"
)]
[
assembly
:
InternalsVisibleTo
(
"Mirror.Tests.Generated"
)]
[
assembly
:
InternalsVisibleTo
(
"Mirror.Tests.Runtime"
)]
[
assembly
:
InternalsVisibleTo
(
"Mirror.Tests.Performance.Editor"
)]
[
assembly
:
InternalsVisibleTo
(
"Mirror.Tests.Performance.Runtime"
)]
[
assembly
:
InternalsVisibleTo
(
"Mirror.Editor"
)]
Assets/Mirror/Components/AssemblyInfo.cs.meta
0 → 100644
View file @
f6ed3c6f
fileFormatVersion: 2
guid: a65b9283f7a724e70b8e17cb277f4c1e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
Assets/Mirror/Components/Discovery.meta
0 → 100644
View file @
f6ed3c6f
fileFormatVersion: 2
guid: b5dcf9618f5e14a4eb60bff5480284a6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Assets/Mirror/Components/Discovery/NetworkDiscovery.cs
0 → 100644
View file @
f6ed3c6f
using
System
;
using
System.Net
;
using
UnityEngine
;
using
UnityEngine.Events
;
namespace
Mirror.Discovery
{
[
Serializable
]
public
class
ServerFoundUnityEvent
<
TResponseType
>
:
UnityEvent
<
TResponseType
>
{};
[
DisallowMultipleComponent
]
[
AddComponentMenu
(
"Network/Network Discovery"
)]
public
class
NetworkDiscovery
:
NetworkDiscoveryBase
<
ServerRequest
,
ServerResponse
>
{
#
region
Server
/// <summary>
/// Process the request from a client
/// </summary>
/// <remarks>
/// Override if you wish to provide more information to the clients
/// such as the name of the host player
/// </remarks>
/// <param name="request">Request coming from client</param>
/// <param name="endpoint">Address of the client that sent the request</param>
/// <returns>The message to be sent back to the client or null</returns>
protected
override
ServerResponse
ProcessRequest
(
ServerRequest
request
,
IPEndPoint
endpoint
)
{
// In this case we don't do anything with the request
// but other discovery implementations might want to use the data
// in there, This way the client can ask for
// specific game mode or something
try
{
// this is an example reply message, return your own
// to include whatever is relevant for your game
return
new
ServerResponse
{
serverId
=
ServerId
,
uri
=
transport
.
ServerUri
()
};
}
catch
(
NotImplementedException
)
{
Debug
.
LogError
(
$"Transport
{
transport
}
does not support network discovery"
);
throw
;
}
}
#
endregion
#
region
Client
/// <summary>
/// Create a message that will be broadcasted on the network to discover servers
/// </summary>
/// <remarks>
/// Override if you wish to include additional data in the discovery message
/// such as desired game mode, language, difficulty, etc... </remarks>
/// <returns>An instance of ServerRequest with data to be broadcasted</returns>
protected
override
ServerRequest
GetRequest
()
=>
new
ServerRequest
();
/// <summary>
/// Process the answer from a server
/// </summary>
/// <remarks>
/// A client receives a reply from a server, this method processes the
/// reply and raises an event
/// </remarks>
/// <param name="response">Response that came from the server</param>
/// <param name="endpoint">Address of the server that replied</param>
protected
override
void
ProcessResponse
(
ServerResponse
response
,
IPEndPoint
endpoint
)
{
// we received a message from the remote endpoint
response
.
EndPoint
=
endpoint
;
// although we got a supposedly valid url, we may not be able to resolve
// the provided host
// However we know the real ip address of the server because we just
// received a packet from it, so use that as host.
UriBuilder
realUri
=
new
UriBuilder
(
response
.
uri
)
{
Host
=
response
.
EndPoint
.
Address
.
ToString
()
};
response
.
uri
=
realUri
.
Uri
;
OnServerFound
.
Invoke
(
response
);
}
#
endregion
}
}
Assets/Mirror/Components/Discovery/NetworkDiscovery.cs.meta
0 → 100644
View file @
f6ed3c6f
fileFormatVersion: 2
guid: c761308e733c51245b2e8bb4201f46dc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
Assets/Mirror/Components/Discovery/NetworkDiscoveryBase.cs
0 → 100644
View file @
f6ed3c6f
using
System
;
using
System.Net
;
using
System.Net.Sockets
;
using
System.Threading.Tasks
;
using
UnityEngine
;
// Based on https://github.com/EnlightenedOne/MirrorNetworkDiscovery
// forked from https://github.com/in0finite/MirrorNetworkDiscovery
// Both are MIT Licensed
namespace
Mirror.Discovery
{
/// <summary>
/// Base implementation for Network Discovery. Extend this component
/// to provide custom discovery with game specific data
/// <see cref="NetworkDiscovery">NetworkDiscovery</see> for a sample implementation
/// </summary>
[
DisallowMultipleComponent
]
[
HelpURL
(
"https://mirror-networking.gitbook.io/docs/components/network-discovery"
)]
public
abstract
class
NetworkDiscoveryBase
<
Request
,
Response
>
:
MonoBehaviour
where
Request
:
NetworkMessage
where
Response
:
NetworkMessage
{
public
static
bool
SupportedOnThisPlatform
{
get
{
return
Application
.
platform
!=
RuntimePlatform
.
WebGLPlayer
;
}
}
[
SerializeField
]
[
Tooltip
(
"If true, broadcasts a discovery request every ActiveDiscoveryInterval seconds"
)]
public
bool
enableActiveDiscovery
=
true
;
// broadcast address needs to be configurable on iOS:
// https://github.com/vis2k/Mirror/pull/3255
[
Tooltip
(
"iOS may require LAN IP address here (e.g. 192.168.x.x), otherwise leave blank."
)]
public
string
BroadcastAddress
=
""
;
[
SerializeField
]
[
Tooltip
(
"The UDP port the server will listen for multi-cast messages"
)]
protected
int
serverBroadcastListenPort
=
47777
;
[
SerializeField
]
[
Tooltip
(
"Time in seconds between multi-cast messages"
)]
[
Range
(
1
,
60
)]
float
ActiveDiscoveryInterval
=
3
;
[
Tooltip
(
"Transport to be advertised during discovery"
)]
public
Transport
transport
;
[
Tooltip
(
"Invoked when a server is found"
)]
public
ServerFoundUnityEvent
<
Response
>
OnServerFound
;
// Each game should have a random unique handshake,
// this way you can tell if this is the same game or not
[
HideInInspector
]
public
long
secretHandshake
;
public
long
ServerId
{
get
;
private
set
;
}
protected
UdpClient
serverUdpClient
;
protected
UdpClient
clientUdpClient
;
#if UNITY_EDITOR
public
virtual
void
OnValidate
()
{
if
(
transport
==
null
)
transport
=
GetComponent
<
Transport
>();
if
(
secretHandshake
==
0
)
{
secretHandshake
=
RandomLong
();
UnityEditor
.
Undo
.
RecordObject
(
this
,
"Set secret handshake"
);
}
}
#endif
/// <summary>
/// virtual so that inheriting classes' Start() can call base.Start() too
/// </summary>
public
virtual
void
Start
()
{
ServerId
=
RandomLong
();
// active transport gets initialized in Awake
// so make sure we set it here in Start() after Awake
// Or just let the user assign it in the inspector
if
(
transport
==
null
)
transport
=
Transport
.
active
;
// Server mode? then start advertising
if
(
Utils
.
IsHeadless
())
{
AdvertiseServer
();
}
}
public
static
long
RandomLong
()
{
int
value1
=
UnityEngine
.
Random
.
Range
(
int
.
MinValue
,
int
.
MaxValue
);
int
value2
=
UnityEngine
.
Random
.
Range
(
int
.
MinValue
,
int
.
MaxValue
);
return
value1
+
((
long
)
value2
<<
32
);
}
// Ensure the ports are cleared no matter when Game/Unity UI exits
void
OnApplicationQuit
()
{
//Debug.Log("NetworkDiscoveryBase OnApplicationQuit");
Shutdown
();
}
void
OnDisable
()
{
//Debug.Log("NetworkDiscoveryBase OnDisable");
Shutdown
();
}
void
OnDestroy
()
{
//Debug.Log("NetworkDiscoveryBase OnDestroy");
Shutdown
();
}
void
Shutdown
()
{
EndpMulticastLock
();
if
(
serverUdpClient
!=
null
)
{
try
{
serverUdpClient
.
Close
();
}
catch
(
Exception
)
{
// it is just close, swallow the error
}
serverUdpClient
=
null
;
}
if
(
clientUdpClient
!=
null
)
{
try
{
clientUdpClient
.
Close
();
}
catch
(
Exception
)
{
// it is just close, swallow the error
}
clientUdpClient
=
null
;
}
CancelInvoke
();
}
#
region
Server
/// <summary>
/// Advertise this server in the local network
/// </summary>
public
void
AdvertiseServer
()
{
if
(!
SupportedOnThisPlatform
)
throw
new
PlatformNotSupportedException
(
"Network discovery not supported in this platform"
);
StopDiscovery
();
// Setup port -- may throw exception
serverUdpClient
=
new
UdpClient
(
serverBroadcastListenPort
)
{
EnableBroadcast
=
true
,
MulticastLoopback
=
false
};
// listen for client pings
_
=
ServerListenAsync
();
}
public
async
Task
ServerListenAsync
()
{
BeginMulticastLock
();
while
(
true
)
{
try
{
await
ReceiveRequestAsync
(
serverUdpClient
);
}
catch
(
ObjectDisposedException
)
{
// socket has been closed
break
;
}
catch
(
Exception
)
{}
}
}
async
Task
ReceiveRequestAsync
(
UdpClient
udpClient
)
{
// only proceed if there is available data in network buffer, or otherwise Receive() will block
// average time for UdpClient.Available : 10 us
UdpReceiveResult
udpReceiveResult
=
await
udpClient
.
ReceiveAsync
();
using
(
NetworkReaderPooled
networkReader
=
NetworkReaderPool
.
Get
(
udpReceiveResult
.
Buffer
))
{
long
handshake
=
networkReader
.
ReadLong
();
if
(
handshake
!=
secretHandshake
)
{
// message is not for us
throw
new
ProtocolViolationException
(
"Invalid handshake"
);
}
Request
request
=
networkReader
.
Read
<
Request
>();
ProcessClientRequest
(
request
,
udpReceiveResult
.
RemoteEndPoint
);
}
}
/// <summary>
/// Reply to the client to inform it of this server
/// </summary>
/// <remarks>
/// Override if you wish to ignore server requests based on
/// custom criteria such as language, full server game mode or difficulty
/// </remarks>
/// <param name="request">Request coming from client</param>
/// <param name="endpoint">Address of the client that sent the request</param>
protected
virtual
void
ProcessClientRequest
(
Request
request
,
IPEndPoint
endpoint
)
{
Response
info
=
ProcessRequest
(
request
,
endpoint
);
if
(
info
==
null
)
return
;
using
(
NetworkWriterPooled
writer
=
NetworkWriterPool
.
Get
())
{
try
{
writer
.
WriteLong
(
secretHandshake
);
writer
.
Write
(
info
);
ArraySegment
<
byte
>
data
=
writer
.
ToArraySegment
();
// signature matches
// send response
serverUdpClient
.
Send
(
data
.
Array
,
data
.
Count
,
endpoint
);
}
catch
(
Exception
ex
)
{
Debug
.
LogException
(
ex
,
this
);
}
}
}
/// <summary>
/// Process the request from a client
/// </summary>
/// <remarks>
/// Override if you wish to provide more information to the clients
/// such as the name of the host player
/// </remarks>
/// <param name="request">Request coming from client</param>
/// <param name="endpoint">Address of the client that sent the request</param>
/// <returns>The message to be sent back to the client or null</returns>
protected
abstract
Response
ProcessRequest
(
Request
request
,
IPEndPoint
endpoint
);
// Android Multicast fix: https://github.com/vis2k/Mirror/pull/2887
#if UNITY_ANDROID
AndroidJavaObject
multicastLock
;
bool
hasMulticastLock
;
#endif
void
BeginMulticastLock
()
{
#if UNITY_ANDROID
if
(
hasMulticastLock
)
return
;
if
(
Application
.
platform
==
RuntimePlatform
.
Android
)
{
using
(
AndroidJavaObject
activity
=
new
AndroidJavaClass
(
"com.unity3d.player.UnityPlayer"
).
GetStatic
<
AndroidJavaObject
>(
"currentActivity"
))
{
using
(
var
wifiManager
=
activity
.
Call
<
AndroidJavaObject
>(
"getSystemService"
,
"wifi"
))
{
multicastLock
=
wifiManager
.
Call
<
AndroidJavaObject
>(
"createMulticastLock"
,
"lock"
);
multicastLock
.
Call
(
"acquire"
);
hasMulticastLock
=
true
;
}
}
}
#endif
}
void
EndpMulticastLock
()
{
#if UNITY_ANDROID
if
(!
hasMulticastLock
)
return
;
multicastLock
?.
Call
(
"release"
);
hasMulticastLock
=
false
;
#endif
}
#endregion
#
region
Client
/// <summary>
/// Start Active Discovery
/// </summary>
public
void
StartDiscovery
()
{
if
(!
SupportedOnThisPlatform
)
throw
new
PlatformNotSupportedException
(
"Network discovery not supported in this platform"
);
StopDiscovery
();
try
{
// Setup port
clientUdpClient
=
new
UdpClient
(
0
)
{
EnableBroadcast
=
true
,
MulticastLoopback
=
false
};
}
catch
(
Exception
)
{
// Free the port if we took it
//Debug.LogError("NetworkDiscoveryBase StartDiscovery Exception");
Shutdown
();
throw
;
}
_
=
ClientListenAsync
();
if
(
enableActiveDiscovery
)
InvokeRepeating
(
nameof
(
BroadcastDiscoveryRequest
),
0
,
ActiveDiscoveryInterval
);
}
/// <summary>
/// Stop Active Discovery
/// </summary>
public
void
StopDiscovery
()
{
//Debug.Log("NetworkDiscoveryBase StopDiscovery");
Shutdown
();
}
/// <summary>
/// Awaits for server response
/// </summary>
/// <returns>ClientListenAsync Task</returns>
public
async
Task
ClientListenAsync
()
{
// while clientUpdClient to fix:
// https://github.com/vis2k/Mirror/pull/2908
//
// If, you cancel discovery the clientUdpClient is set to null.
// However, nothing cancels ClientListenAsync. If we change the if(true)
// to check if the client is null. You can properly cancel the discovery,
// and kill the listen thread.
//
// Prior to this fix, if you cancel the discovery search. It crashes the
// thread, and is super noisy in the output. As well as causes issues on
// the quest.
while
(
clientUdpClient
!=
null
)
{
try
{
await
ReceiveGameBroadcastAsync
(
clientUdpClient
);
}
catch
(
ObjectDisposedException
)
{
// socket was closed, no problem
return
;
}
catch
(
Exception
ex
)
{
Debug
.
LogException
(
ex
);
}
}
}
/// <summary>
/// Sends discovery request from client
/// </summary>
public
void
BroadcastDiscoveryRequest
()
{
if
(
clientUdpClient
==
null
)
return
;
if
(
NetworkClient
.
isConnected
)
{
StopDiscovery
();
return
;
}
IPEndPoint
endPoint
=
new
IPEndPoint
(
IPAddress
.
Broadcast
,
serverBroadcastListenPort
);
if
(!
string
.
IsNullOrWhiteSpace
(
BroadcastAddress
))
{
try
{
endPoint
=
new
IPEndPoint
(
IPAddress
.
Parse
(
BroadcastAddress
),
serverBroadcastListenPort
);
}
catch
(
Exception
ex
)
{
Debug
.
LogException
(
ex
);
}
}
using
(
NetworkWriterPooled
writer
=
NetworkWriterPool
.
Get
())
{
writer
.
WriteLong
(
secretHandshake
);
try
{
Request
request
=
GetRequest
();
writer
.
Write
(
request
);
ArraySegment
<
byte
>
data
=
writer
.
ToArraySegment
();
clientUdpClient
.
SendAsync
(
data
.
Array
,
data
.
Count
,
endPoint
);
}
catch
(
Exception
)
{
// It is ok if we can't broadcast to one of the addresses
}
}
}
/// <summary>
/// Create a message that will be broadcasted on the network to discover servers
/// </summary>
/// <remarks>
/// Override if you wish to include additional data in the discovery message
/// such as desired game mode, language, difficulty, etc... </remarks>
/// <returns>An instance of ServerRequest with data to be broadcasted</returns>
protected
virtual
Request
GetRequest
()
=>
default
;
async
Task
ReceiveGameBroadcastAsync
(
UdpClient
udpClient
)
{
// only proceed if there is available data in network buffer, or otherwise Receive() will block
// average time for UdpClient.Available : 10 us
UdpReceiveResult
udpReceiveResult
=
await
udpClient
.
ReceiveAsync
();
using
(
NetworkReaderPooled
networkReader
=
NetworkReaderPool
.
Get
(
udpReceiveResult
.
Buffer
))
{
if
(
networkReader
.
ReadLong
()
!=
secretHandshake
)
return
;
Response
response
=
networkReader
.
Read
<
Response
>();
ProcessResponse
(
response
,
udpReceiveResult
.
RemoteEndPoint
);
}
}
/// <summary>
/// Process the answer from a server
/// </summary>
/// <remarks>
/// A client receives a reply from a server, this method processes the
/// reply and raises an event
/// </remarks>
/// <param name="response">Response that came from the server</param>
/// <param name="endpoint">Address of the server that replied</param>
protected
abstract
void
ProcessResponse
(
Response
response
,
IPEndPoint
endpoint
);
#
endregion
}
}
Assets/Mirror/Components/Discovery/NetworkDiscoveryBase.cs.meta
0 → 100644
View file @
f6ed3c6f
fileFormatVersion: 2
guid: b9971d60ce61f4e39b07cd9e7e0c68fa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
Assets/Mirror/Components/Discovery/NetworkDiscoveryHUD.cs
0 → 100644
View file @
f6ed3c6f
using System.Collections.Generic;
using UnityEngine;
namespace Mirror.Discovery
{
[DisallowMultipleComponent]
[AddComponentMenu("Network/Network Discovery HUD")]
[HelpURL("https://mirror-networking.gitbook.io/docs/components/network-discovery")]
[RequireComponent(typeof(NetworkDiscovery))]
public class NetworkDiscoveryHUD : MonoBehaviour
{
readonly Dictionary<long, ServerResponse> discoveredServers = new Dictionary<long, ServerResponse>();
Vector2 scrollViewPos = Vector2.zero;
public NetworkDiscovery networkDiscovery;
#if UNITY_EDITOR
void OnValidate()
{
if (networkDiscovery == null)
{
networkDiscovery = GetComponent<NetworkDiscovery>();
UnityEditor.Events.UnityEventTools.AddPersistentListener(networkDiscovery.OnServerFound, OnDiscoveredServer);
UnityEditor.Undo.RecordObjects(new Object[] { this, networkDiscovery }, "Set NetworkDiscovery");
}
}
#endif
void OnGUI()
{
if (NetworkManager.singleton == null)
return;
if (!NetworkClient.isConnected && !NetworkServer.active && !NetworkClient.active)
DrawGUI();
if (NetworkServer.active || NetworkClient.active)
StopButtons();
}
void DrawGUI()
{
GUILayout.BeginArea(new Rect(10, 10, 300, 500));
GUILayout.BeginHorizontal();
if (GUILayout.Button("Find Servers"))
{
discoveredServers.Clear();
networkDiscovery.StartDiscovery();
}
// LAN Host
if (GUILayout.Button("Start Host"))
{
discoveredServers.Clear();
NetworkManager.singleton.StartHost();
networkDiscovery.AdvertiseServer();
}
// Dedicated server
if (GUILayout.Button("Start Server"))
{
discoveredServers.Clear();
NetworkManager.singleton.StartServer();
networkDiscovery.AdvertiseServer();
}
GUILayout.EndHorizontal();
// show list of found server
GUILayout.Label($"Discovered Servers [{discoveredServers.Count}]:");
// servers
scrollViewPos = GUILayout.BeginScrollView(scrollViewPos);
foreach (ServerResponse info in discoveredServers.Values)
if (GUILayout.Button(info.EndPoint.Address.ToString()))
Connect(info);
GUILayout.EndScrollView();
GUILayout.EndArea();
}
void StopButtons()
{
GUILayout.BeginArea(new Rect(10, 40, 100, 25));
// stop host if host mode
if (NetworkServer.active && NetworkClient.isConnected)
{
if (GUILayout.Button("Stop Host"))
{
NetworkManager.singleton.StopHost();
networkDiscovery.StopDiscovery();
}
}
// stop client if client-only
else if (NetworkClient.isConnected)
{
if (GUILayout.Button("Stop Client"))
{
NetworkManager.singleton.StopClient();
networkDiscovery.StopDiscovery();
}
}
// stop server if server-only
else if (NetworkServer.active)
{
if (GUILayout.Button("Stop Server"))
{
NetworkManager.singleton.StopServer();
networkDiscovery.StopDiscovery();
}
}
GUILayout.EndArea();
}
void Connect(ServerResponse info)
{
networkDiscovery.StopDiscovery();
NetworkManager.singleton.StartClient(info.uri);
}
public void OnDiscoveredServer(ServerResponse info)
{
// Note that you can check the versioning to decide if you can connect to the server or not using this method
discoveredServers[info.serverId] = info;
}
}
}
Assets/Mirror/Components/Discovery/NetworkDiscoveryHUD.cs.meta
0 → 100644
View file @
f6ed3c6f
fileFormatVersion: 2
guid: 88c37d3deca7a834d80cfd8d3cfcc510
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
Assets/Mirror/Components/Discovery/ServerRequest.cs
0 → 100644
View file @
f6ed3c6f
namespace
Mirror.Discovery
{
public
struct
ServerRequest
:
NetworkMessage
{}
}
Assets/Mirror/Components/Discovery/ServerRequest.cs.meta
0 → 100644
View file @
f6ed3c6f
fileFormatVersion: 2
guid: ea7254bf7b9454da4adad881d94cd141
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:
Prev
1
2
3
4
5
6
…
50
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment