forked from Unity-Technologies/Megacity-2019
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNetcodeBootstrap.cs
170 lines (149 loc) · 6.92 KB
/
NetcodeBootstrap.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
using Gameplay;
using JetBrains.Annotations;
using Unity.Entities;
using Unity.NetCode;
using Unity.Networking.Transport;
using UnityEngine;
using Unity.Megacity.UI;
using Unity.Services.Samples.GameServerHosting;
using UnityEngine.SceneManagement;
using Unity.Megacity.Gameplay;
using Unity.Megacity.CameraManagement;
namespace Unity.Megacity
{
/// <summary>
/// The bootstrap needs to extend `ClientServerBootstrap`, there can only be one class extending it in the project
/// </summary>
[UnityEngine.Scripting.Preserve]
public class NetCodeBootstrap : ClientServerBootstrap
{
const string k_ServicesDataResourceLocation = "GameServiceData";
const string k_MultiplayerDataResourceLocation = "MultiplayerServerSettings";
public static NetworkEndpoint MegacityServerIp => NetworkEndpoint.Parse("128.14.159.58", 7979);
/// <summary>
/// Limitation imposed to ensure UTP send/receiveQueueSize's are set appropriately.
/// <see cref="MegacityDriverConstructor"/>.
/// </summary>
public const int MaxPlayerCount = 200;
// The initialize method is what entities calls to create the default worlds
public override bool Initialize(string defaultWorldName)
{
// Handle max player count globally.
NetworkStreamReceiveSystem.DriverConstructor = new MegacityDriverConstructor();
#if UNITY_SERVER && !UNITY_EDITOR
var isFrontEnd = SceneController.IsFrontEnd;
if(isFrontEnd)
{
SceneController.LoadGame();
}
Application.targetFrameRate = 60;
CreateDefaultClientServerWorlds();
TryStartUgs();
// Niki.Walker: Disabled as UNITY_SERVER does not support creating thin client worlds.
// // On the server, also create thin clients (if requested).
// TryCreateThinClientsIfRequested();
return true;
#else
// Try and auto-connect.
#if UNITY_EDITOR
if (IsConnectedFromTheMainScene(defaultWorldName))
{
return true;
}
if (RequestedPlayType == PlayType.Client)
{
if (MultiplayerPlayModePreferences.IsEditorInputtedAddressValidForConnect(out var editorSpecifiedEndpoint))
{
AutoConnectPort = editorSpecifiedEndpoint.Port;
DefaultConnectAddress = editorSpecifiedEndpoint;
UnityEngine.Debug.Log($"Detected auto-connection preference in 'Multiplayer PlayMode Tool' targeting '{editorSpecifiedEndpoint}' (Port: '{AutoConnectPort}')!");
}
}
#else
// We always set the DefaultConnectAddress in a player, because it's unlikely you'll want to test locally here.
DefaultConnectAddress = ModeBootstrap.Options.UserSpecifiedEndpoint;
if (TryCreateThinClientsIfRequested())
return true;
#endif
ServerConnectionUtils.CreateDefaultWorld();
return true;
#endif
}
private bool IsConnectedFromTheMainScene(string defaultWorldName)
{
var isMainScene = SceneController.IsGameScene;
#if UNITY_EDITOR
var gameInfo = Resources.Load<MultiplayerServerSettings>(k_MultiplayerDataResourceLocation);
if (!gameInfo)
{
Debug.LogError($"[EditorSettings] No Game Info Object at 'Assets/Resources/{k_MultiplayerDataResourceLocation}'");
return false;
}
gameInfo.IsAutoloading = isMainScene;
if (isMainScene)
{
var isMultiplayerMode = gameInfo.AutoRunGameModeInEditorMain == GameMode.Multiplayer || gameInfo.AutoRunGameModeInEditorMain == GameMode.None;
if (isMultiplayerMode)
{
Debug.Log("Auto creating server and client worlds");
AutoConnectPort = 7979;
CreateDefaultClientServerWorlds();
return true;
}
else
{
Debug.Log("Auto creating Local world");
CreateLocalWorld(defaultWorldName);
}
}
#endif
return isMainScene;
}
[UsedImplicitly]
private static bool TryCreateThinClientsIfRequested()
{
if (ModeBootstrap.Options.IsThinClient)
{
var requestedNumThinClients = ModeBootstrap.Options.TargetThinClientWorldCount;
if (requestedNumThinClients > 0)
{
// Hardcoded DefaultConnectAddress for the Megacity demo.
AutoConnectPort = ModeBootstrap.Options.UserSpecifiedEndpoint.Port;
for (var i = 0; i < requestedNumThinClients; i++)
{
Debug.Log($"Creating a Thin Client World! {(i + 1)} of {requestedNumThinClients}...");
var world = CreateThinClientWorld();
if (i == 0 || World.DefaultGameObjectInjectionWorld == null || !World.DefaultGameObjectInjectionWorld.IsCreated)
{
World.DefaultGameObjectInjectionWorld = world;
Debug.Log($"Setting DefaultGameObjectInjectionWorld to world '{world.Name}'.");
}
}
Debug.Log($"Detected headless client! Automatically creating {requestedNumThinClients} ThinClients, and connecting them to the hardcoded endpoint '{DefaultConnectAddress}' (Port: '{AutoConnectPort}')!");
return true;
}
Debug.LogError($"Detected headless client, but TargetThinClientWorldCount is {requestedNumThinClients}! Cannot initialize!");
}
return false;
}
/// <summary>
/// Runs parallel to the initialization thread from here.
/// </summary>
private async void TryStartUgs()
{
var gameInfo = Resources.Load<GameServerInfo_Data>(k_ServicesDataResourceLocation);
if (!gameInfo)
{
Debug.LogError($"[GSH] No Game Server Info Object at 'Assets/Resources/{k_ServicesDataResourceLocation}'");
return;
}
var multiplayGameServerManager = new GameObject("MultiplayServer").AddComponent<GameServerManager>();
multiplayGameServerManager.Init(gameInfo);
Debug.LogError($"[GSH] Multiplay GameServer Manager {gameInfo.Data}'");
if (!await multiplayGameServerManager.InitServices())
return;
Debug.LogError($"[GSH] Try Start Server {ModeBootstrap.Options.UserSpecifiedEndpoint.Address}");
await multiplayGameServerManager.TryStartServer(ModeBootstrap.Options.UserSpecifiedEndpoint.Address);
}
}
}