diff --git a/Assets/GameData/Action/Abilities/Vector Fence.asset b/Assets/GameData/Action/Abilities/Vector Fence.asset index 979f185..46ed761 100644 --- a/Assets/GameData/Action/Abilities/Vector Fence.asset +++ b/Assets/GameData/Action/Abilities/Vector Fence.asset @@ -20,6 +20,6 @@ MonoBehaviour: abilityCooldownTime: 3 prefab: {fileID: 9694722736535169, guid: 9b94ed8895919e84aa669628b0761eaf, type: 3} wallLength: 8 - wallWidth: 0.5 + wallWidth: 0.01 wallHeight: 2 scaleUpDuration: 1 diff --git a/Assets/GameData/Transforms.meta b/Assets/GameData/Transforms.meta new file mode 100644 index 0000000..b3c4fca --- /dev/null +++ b/Assets/GameData/Transforms.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: de41b38403a001448a6a730af84d72c8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameData/Transforms/NetworkGameState.asset b/Assets/GameData/Transforms/NetworkGameState.asset new file mode 100644 index 0000000..5714fb2 --- /dev/null +++ b/Assets/GameData/Transforms/NetworkGameState.asset @@ -0,0 +1,15 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5cccef3cfcbccdb4aa4b407a003237b7, type: 3} + m_Name: NetworkGameState + m_EditorClassIdentifier: + Value: {fileID: 0} diff --git a/Assets/GameData/Transforms/NetworkGameState.asset.meta b/Assets/GameData/Transforms/NetworkGameState.asset.meta new file mode 100644 index 0000000..42d592b --- /dev/null +++ b/Assets/GameData/Transforms/NetworkGameState.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f90b09725fdc466489abf3df1697fccc +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/Abilities/VectorFencePrefab.prefab b/Assets/Prefabs/Abilities/VectorFencePrefab.prefab index 5ad556b..c161609 100644 --- a/Assets/Prefabs/Abilities/VectorFencePrefab.prefab +++ b/Assets/Prefabs/Abilities/VectorFencePrefab.prefab @@ -11,7 +11,6 @@ GameObject: - component: {fileID: 1756252046645169901} - component: {fileID: 7200474853122004856} - component: {fileID: 5290524345172392442} - - component: {fileID: 550742182908126467} - component: {fileID: 8921202503349013827} - component: {fileID: 5807442085122568602} - component: {fileID: -7009867759405921325} @@ -33,7 +32,7 @@ Transform: serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 8, y: 1, z: 0.5} + m_LocalScale: {x: 8, y: 1, z: 0.01} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} @@ -88,27 +87,6 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!65 &550742182908126467 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 9694722736535169} - m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 - m_IsTrigger: 0 - m_ProvidesContacts: 0 - m_Enabled: 0 - serializedVersion: 3 - m_Size: {x: 1, y: 1, z: 1} - m_Center: {x: 0, y: 0, z: 0} --- !u!208 &8921202503349013827 NavMeshObstacle: m_ObjectHideFlags: 0 @@ -119,7 +97,7 @@ NavMeshObstacle: m_Enabled: 1 serializedVersion: 3 m_Shape: 1 - m_Extents: {x: 0.5, y: 0.5, z: 0.5} + m_Extents: {x: 0.5, y: 0.5, z: 0.005} m_MoveThreshold: 0.01 m_Carve: 1 m_CarveOnlyStationary: 0 @@ -137,7 +115,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} m_Name: m_EditorClassIdentifier: - GlobalObjectIdHash: 3892629208 + GlobalObjectIdHash: 1554870052 InScenePlacedSourceGlobalObjectIdHash: 0 AlwaysReplicateAsRoot: 0 SynchronizeTransform: 1 diff --git a/Assets/Prefabs/Game/NetworkGameState.prefab b/Assets/Prefabs/Game/NetworkGameState.prefab new file mode 100644 index 0000000..476ac40 --- /dev/null +++ b/Assets/Prefabs/Game/NetworkGameState.prefab @@ -0,0 +1,99 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &3487892320786813612 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4251412275105530415} + - component: {fileID: 8671395340743330634} + - component: {fileID: 3758027155353090712} + - component: {fileID: 4390463078158709668} + - component: {fileID: 6970145845986941762} + m_Layer: 0 + m_Name: NetworkGameState + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4251412275105530415 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3487892320786813612} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -0.2769791, y: 1.2954404, z: 0.23972915} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &8671395340743330634 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3487892320786813612} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} + m_Name: + m_EditorClassIdentifier: + GlobalObjectIdHash: 1396645719 + InScenePlacedSourceGlobalObjectIdHash: 0 + AlwaysReplicateAsRoot: 0 + SynchronizeTransform: 1 + ActiveSceneSynchronization: 0 + SceneMigrationSynchronization: 1 + SpawnWithObservers: 1 + DontDestroyWithOwner: 0 + AutoObjectParentSync: 1 +--- !u!114 &3758027155353090712 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3487892320786813612} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9fb009f05b6b84d35af38930cac98d9a, type: 3} + m_Name: + m_EditorClassIdentifier: + m_GameStateTransformVariable: {fileID: 11400000, guid: f90b09725fdc466489abf3df1697fccc, type: 2} + m_NetworkWinState: {fileID: 4390463078158709668} +--- !u!114 &4390463078158709668 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3487892320786813612} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 69eb1bedacf698e4bada2f8d55dabdd8, type: 3} + m_Name: + m_EditorClassIdentifier: + winState: + m_InternalValue: 0 +--- !u!114 &6970145845986941762 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3487892320786813612} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b280145480d7594419baed09a111184b, type: 3} + m_Name: + m_EditorClassIdentifier: + m_TransformVariable: {fileID: 11400000, guid: f90b09725fdc466489abf3df1697fccc, type: 2} diff --git a/Assets/Prefabs/Game/NetworkGameState.prefab.meta b/Assets/Prefabs/Game/NetworkGameState.prefab.meta new file mode 100644 index 0000000..22181e1 --- /dev/null +++ b/Assets/Prefabs/Game/NetworkGameState.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2200a7c8099eb8b4a8a43beb96097cef +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/State/DSLobbyManagementState.prefab b/Assets/Prefabs/State/DSLobbyManagementState.prefab new file mode 100644 index 0000000..5b2bd03 --- /dev/null +++ b/Assets/Prefabs/State/DSLobbyManagementState.prefab @@ -0,0 +1,50 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &483784040165852385 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8317007143651163113} + - component: {fileID: 1988754947503560336} + m_Layer: 0 + m_Name: DSLobbyManagementState + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8317007143651163113 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 483784040165852385} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 27.0119, y: -29.155869, z: 13.674866} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1988754947503560336 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 483784040165852385} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a35fe42cd86928c4d9dd52f2136ba795, type: 3} + m_Name: + m_EditorClassIdentifier: + parentReference: + TypeName: Unity.BossRoom.ApplicationLifecycle.ApplicationController + autoRun: 1 + autoInjectGameObjects: [] diff --git a/Assets/Prefabs/State/DSLobbyManagementState.prefab.meta b/Assets/Prefabs/State/DSLobbyManagementState.prefab.meta new file mode 100644 index 0000000..3f65c8b --- /dev/null +++ b/Assets/Prefabs/State/DSLobbyManagementState.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 85008d44a844548c083b38cda8083ef7 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/DedicatedServerLobbyManagement.unity b/Assets/Scenes/DedicatedServerLobbyManagement.unity new file mode 100644 index 0000000..8fdd0ea --- /dev/null +++ b/Assets/Scenes/DedicatedServerLobbyManagement.unity @@ -0,0 +1,187 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1001 &8885455575253120869 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 483784040165852385, guid: 85008d44a844548c083b38cda8083ef7, type: 3} + propertyPath: m_Name + value: DSLobbyManagementState + objectReference: {fileID: 0} + - target: {fileID: 8317007143651163113, guid: 85008d44a844548c083b38cda8083ef7, type: 3} + propertyPath: m_LocalPosition.x + value: 27.0119 + objectReference: {fileID: 0} + - target: {fileID: 8317007143651163113, guid: 85008d44a844548c083b38cda8083ef7, type: 3} + propertyPath: m_LocalPosition.y + value: -29.155869 + objectReference: {fileID: 0} + - target: {fileID: 8317007143651163113, guid: 85008d44a844548c083b38cda8083ef7, type: 3} + propertyPath: m_LocalPosition.z + value: 13.674866 + objectReference: {fileID: 0} + - target: {fileID: 8317007143651163113, guid: 85008d44a844548c083b38cda8083ef7, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 8317007143651163113, guid: 85008d44a844548c083b38cda8083ef7, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 8317007143651163113, guid: 85008d44a844548c083b38cda8083ef7, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 8317007143651163113, guid: 85008d44a844548c083b38cda8083ef7, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 8317007143651163113, guid: 85008d44a844548c083b38cda8083ef7, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 8317007143651163113, guid: 85008d44a844548c083b38cda8083ef7, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 8317007143651163113, guid: 85008d44a844548c083b38cda8083ef7, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 85008d44a844548c083b38cda8083ef7, type: 3} +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 8885455575253120869} diff --git a/Assets/Scenes/DedicatedServerLobbyManagement.unity.meta b/Assets/Scenes/DedicatedServerLobbyManagement.unity.meta new file mode 100644 index 0000000..0825401 --- /dev/null +++ b/Assets/Scenes/DedicatedServerLobbyManagement.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c415c55354f6743faa63ac4c8b181a65 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/Startup.unity b/Assets/Scenes/Startup.unity index 59bbdc5..f17021c 100644 --- a/Assets/Scenes/Startup.unity +++ b/Assets/Scenes/Startup.unity @@ -38,7 +38,7 @@ RenderSettings: m_ReflectionIntensity: 1 m_CustomReflection: {fileID: 0} m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 0.12731749, g: 0.13414757, b: 0.1210787, a: 1} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} m_UseRadianceAmbientProbe: 0 --- !u!157 &3 LightmapSettings: @@ -1348,6 +1348,10 @@ PrefabInstance: serializedVersion: 3 m_TransformParent: {fileID: 0} m_Modifications: + - target: {fileID: 1984353324962460586, guid: c16e5c84955e2124b819f83a4e5078db, type: 3} + propertyPath: m_GameState + value: + objectReference: {fileID: 8671395340743330634, guid: 2200a7c8099eb8b4a8a43beb96097cef, type: 3} - target: {fileID: 1984353324962460586, guid: c16e5c84955e2124b819f83a4e5078db, type: 3} propertyPath: m_NetworkManager value: @@ -1516,6 +1520,71 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 593a2fe42fa9d37498c96f9a383b6521, type: 3} m_Name: m_EditorClassIdentifier: +--- !u!1001 &6826832879089252232 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 3487892320786813612, guid: 2200a7c8099eb8b4a8a43beb96097cef, type: 3} + propertyPath: m_Name + value: NetworkGameState + objectReference: {fileID: 0} + - target: {fileID: 4251412275105530415, guid: 2200a7c8099eb8b4a8a43beb96097cef, type: 3} + propertyPath: m_LocalPosition.x + value: -0.2769791 + objectReference: {fileID: 0} + - target: {fileID: 4251412275105530415, guid: 2200a7c8099eb8b4a8a43beb96097cef, type: 3} + propertyPath: m_LocalPosition.y + value: 1.2954404 + objectReference: {fileID: 0} + - target: {fileID: 4251412275105530415, guid: 2200a7c8099eb8b4a8a43beb96097cef, type: 3} + propertyPath: m_LocalPosition.z + value: 0.23972915 + objectReference: {fileID: 0} + - target: {fileID: 4251412275105530415, guid: 2200a7c8099eb8b4a8a43beb96097cef, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4251412275105530415, guid: 2200a7c8099eb8b4a8a43beb96097cef, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4251412275105530415, guid: 2200a7c8099eb8b4a8a43beb96097cef, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4251412275105530415, guid: 2200a7c8099eb8b4a8a43beb96097cef, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4251412275105530415, guid: 2200a7c8099eb8b4a8a43beb96097cef, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4251412275105530415, guid: 2200a7c8099eb8b4a8a43beb96097cef, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4251412275105530415, guid: 2200a7c8099eb8b4a8a43beb96097cef, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 8671395340743330634, guid: 2200a7c8099eb8b4a8a43beb96097cef, type: 3} + propertyPath: GlobalObjectIdHash + value: 2423675111 + objectReference: {fileID: 0} + - target: {fileID: 8671395340743330634, guid: 2200a7c8099eb8b4a8a43beb96097cef, type: 3} + propertyPath: InScenePlacedSourceGlobalObjectIdHash + value: 1399236880 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 2200a7c8099eb8b4a8a43beb96097cef, type: 3} --- !u!1001 &7200250264107179103 PrefabInstance: m_ObjectHideFlags: 0 @@ -1721,3 +1790,4 @@ SceneRoots: - {fileID: 2133349239} - {fileID: 1965079830} - {fileID: 1232034916} + - {fileID: 6826832879089252232} diff --git a/Assets/Scripts/ApplicationLifecycle/ApplicationController.cs b/Assets/Scripts/ApplicationLifecycle/ApplicationController.cs index 499701f..f420996 100644 --- a/Assets/Scripts/ApplicationLifecycle/ApplicationController.cs +++ b/Assets/Scripts/ApplicationLifecycle/ApplicationController.cs @@ -9,6 +9,7 @@ using Unity.BossRoom.UnityServices; using Unity.BossRoom.UnityServices.Auth; using Unity.BossRoom.UnityServices.Lobbies; using Unity.BossRoom.Utils; +using Unity.Multiplayer.Samples; using Unity.Netcode; using UnityEngine; using UnityEngine.SceneManagement; @@ -61,6 +62,8 @@ namespace Unity.BossRoom.ApplicationLifecycle //they are networked so that the clients can subscribe to those messages that are published by the server builder.RegisterComponent(new NetworkedMessageChannel()).AsImplementedInterfaces(); builder.RegisterComponent(new NetworkedMessageChannel()).AsImplementedInterfaces(); + Debug.Log("Registered NetworkedMessageChannel."); + #if UNITY_EDITOR || DEVELOPMENT_BUILD builder.RegisterComponent(new NetworkedMessageChannel()).AsImplementedInterfaces(); #endif @@ -93,7 +96,15 @@ namespace Unity.BossRoom.ApplicationLifecycle DontDestroyOnLoad(gameObject); DontDestroyOnLoad(m_UpdateRunner.gameObject); Application.targetFrameRate = 120; - SceneManager.LoadScene("MainMenu"); + if (DedicatedServerUtilities.IsServerBuildTarget) + { + // skip main menu and start IP server directly + SceneManager.LoadScene("DedicatedServerLobbyManagement"); + } + else + { + SceneManager.LoadScene("MainMenu"); + } } protected override void OnDestroy() diff --git a/Assets/Scripts/ConnectionManagement/ConnectionManager.cs b/Assets/Scripts/ConnectionManagement/ConnectionManager.cs index 22068b3..b941c8e 100644 --- a/Assets/Scripts/ConnectionManagement/ConnectionManager.cs +++ b/Assets/Scripts/ConnectionManagement/ConnectionManager.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using Unity.BossRoom.Utils; +using Unity.Collections; +using Unity.Multiplayer.Samples.BossRoom; using Unity.Netcode; using UnityEngine; using UUnity.BossRoom.ConnectionManagement; @@ -69,6 +71,10 @@ namespace Unity.BossRoom.ConnectionManagement [Inject] IObjectResolver m_Resolver; + [SerializeField] + NetworkObject m_GameState; + public NetworkObject GameState => m_GameState; + public int MaxConnectedPlayers = 8; internal readonly OfflineState m_Offline = new OfflineState(); @@ -77,6 +83,9 @@ namespace Unity.BossRoom.ConnectionManagement internal readonly ClientReconnectingState m_ClientReconnecting = new ClientReconnectingState(); internal readonly StartingHostState m_StartingHost = new StartingHostState(); internal readonly HostingState m_Hosting = new HostingState(); + internal readonly ServerStartingState m_ServerStarting = new ServerStartingState(); + internal readonly ServerListeningState m_ServerListening = new ServerListeningState(); + internal readonly DisconnectingWithReasonState m_DisconnectingWithReason = new DisconnectingWithReasonState(); void Awake() { @@ -85,7 +94,7 @@ namespace Unity.BossRoom.ConnectionManagement void Start() { - List states = new() { m_Offline, m_ClientConnecting, m_ClientConnected, m_ClientReconnecting, m_StartingHost, m_Hosting }; + List states = new() { m_Offline, m_ClientConnecting, m_ClientConnected, m_ClientReconnecting, m_StartingHost, m_Hosting, m_ServerStarting, m_ServerListening, m_DisconnectingWithReason }; foreach (var connectionState in states) { m_Resolver.Inject(connectionState); @@ -172,10 +181,45 @@ namespace Unity.BossRoom.ConnectionManagement { m_CurrentState.StartHostIP(playerName, ipaddress, port); } - + public void StartServerIP(string ipaddress, int port) + { + m_CurrentState.StartServerIP(ipaddress, port); + } + public void RequestShutdown() { m_CurrentState.OnUserRequestedShutdown(); } + internal void ReceiveServertoClientSuccessPayload_CustomMessage(ulong clientID, FastBufferReader reader) + { + reader.ReadValueSafe(out ServerType isHost); + IsConnectedToHost = isHost; + } + public ServerType IsConnectedToHost { get; set; } + internal static void SendServertoClientSuccessPayload(ulong clientID, ServerType isHost) + { + var writer = new FastBufferWriter(sizeof(bool), Allocator.Temp); + writer.WriteValueSafe(isHost); + NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage(nameof(ReceiveServertoClientSuccessPayload_CustomMessage), clientID, writer); + } + public enum ServerType : byte + { + Undefined = 0, + DedicatedServer, + ClientHostedServer + } + + public static void SendServerToClientSetDisconnectReason(ulong clientID, ConnectStatus status) + { + var writer = new FastBufferWriter(sizeof(ConnectStatus), Allocator.Temp); + writer.WriteValueSafe(status); + NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage(nameof(ReceiveServerToClientSetDisconnectReason_CustomMessage), clientID, writer); + } + + void ReceiveServerToClientSetDisconnectReason_CustomMessage(ulong clientID, FastBufferReader reader) + { + reader.ReadValueSafe(out ConnectStatus status); + m_CurrentState.OnDisconnectReasonReceived(status); + } } } diff --git a/Assets/Scripts/ConnectionManagement/ConnectionState/ClientConnectedState.cs b/Assets/Scripts/ConnectionManagement/ConnectionState/ClientConnectedState.cs index 9d4e0e0..b5f37a7 100644 --- a/Assets/Scripts/ConnectionManagement/ConnectionState/ClientConnectedState.cs +++ b/Assets/Scripts/ConnectionManagement/ConnectionState/ClientConnectedState.cs @@ -23,6 +23,12 @@ namespace Unity.BossRoom.ConnectionManagement public override void Exit() { } + public override void OnDisconnectReasonReceived(ConnectStatus disconnectReason) + { + m_ConnectStatusPublisher.Publish(disconnectReason); + m_ConnectionManager.ChangeState(m_ConnectionManager.m_DisconnectingWithReason); + } + public override void OnClientDisconnect(ulong _) { var disconnectReason = m_ConnectionManager.NetworkManager.DisconnectReason; diff --git a/Assets/Scripts/ConnectionManagement/ConnectionState/ClientConnectingState.cs b/Assets/Scripts/ConnectionManagement/ConnectionState/ClientConnectingState.cs index fc2fd12..1ead01a 100644 --- a/Assets/Scripts/ConnectionManagement/ConnectionState/ClientConnectingState.cs +++ b/Assets/Scripts/ConnectionManagement/ConnectionState/ClientConnectingState.cs @@ -54,7 +54,12 @@ namespace Unity.BossRoom.ConnectionManagement m_ConnectionManager.ChangeState(m_ConnectionManager.m_Offline); } - + public override void OnDisconnectReasonReceived(ConnectStatus disconnectReason) + { + m_ConnectStatusPublisher.Publish(disconnectReason); + m_ConnectionManager.ChangeState(m_ConnectionManager.m_DisconnectingWithReason); + } + internal async Task ConnectClientAsync() { try diff --git a/Assets/Scripts/ConnectionManagement/ConnectionState/ClientReconnectingState.cs b/Assets/Scripts/ConnectionManagement/ConnectionState/ClientReconnectingState.cs index 3b7d039..528742a 100644 --- a/Assets/Scripts/ConnectionManagement/ConnectionState/ClientReconnectingState.cs +++ b/Assets/Scripts/ConnectionManagement/ConnectionState/ClientReconnectingState.cs @@ -45,6 +45,19 @@ namespace Unity.BossRoom.ConnectionManagement m_ConnectionManager.ChangeState(m_ConnectionManager.m_ClientConnected); } + public override void OnDisconnectReasonReceived(ConnectStatus disconnectReason) + { + m_ConnectStatusPublisher.Publish(disconnectReason); + switch (disconnectReason) + { + case ConnectStatus.UserRequestedDisconnect: + case ConnectStatus.HostEndedSession: + case ConnectStatus.ServerFull: + m_ConnectionManager.ChangeState(m_ConnectionManager.m_DisconnectingWithReason); + break; + } + } + public override void OnClientDisconnect(ulong _) { var disconnectReason = m_ConnectionManager.NetworkManager.DisconnectReason; diff --git a/Assets/Scripts/ConnectionManagement/ConnectionState/ConnectionState.cs b/Assets/Scripts/ConnectionManagement/ConnectionState/ConnectionState.cs index eed9a87..28d56aa 100644 --- a/Assets/Scripts/ConnectionManagement/ConnectionState/ConnectionState.cs +++ b/Assets/Scripts/ConnectionManagement/ConnectionState/ConnectionState.cs @@ -28,6 +28,8 @@ namespace Unity.BossRoom.ConnectionManagement public virtual void StartClientIP(string playerName, string ipaddress, int port) { } + public virtual void StartServerIP(string ipaddress, int port) { } + public virtual void StartClientLobby(string playerName) { } public virtual void StartHostIP(string playerName, string ipaddress, int port) { } @@ -41,5 +43,7 @@ namespace Unity.BossRoom.ConnectionManagement public virtual void OnTransportFailure() { } public virtual void OnServerStopped() { } + + public virtual void OnDisconnectReasonReceived(ConnectStatus disconnectReason) { } } } diff --git a/Assets/Scripts/ConnectionManagement/ConnectionState/DisconnectingWithReasonState.cs b/Assets/Scripts/ConnectionManagement/ConnectionState/DisconnectingWithReasonState.cs new file mode 100644 index 0000000..f9f6562 --- /dev/null +++ b/Assets/Scripts/ConnectionManagement/ConnectionState/DisconnectingWithReasonState.cs @@ -0,0 +1,24 @@ +namespace Unity.BossRoom.ConnectionManagement +{ + /// + /// Connection state corresponding to a client who received a message from the server with a disconnect reason. + /// Since our disconnect process runs in multiple steps host side, this state is the first step client side. This + /// state simply waits for the actual disconnect, then transitions to the offline state. + /// + class DisconnectingWithReasonState : ConnectionState + { + public override void Enter() { } + + public override void Exit() { } + + public override void OnClientDisconnect(ulong _) + { + m_ConnectionManager.ChangeState(m_ConnectionManager.m_Offline); + } + + public override void OnUserRequestedShutdown() + { + m_ConnectionManager.ChangeState(m_ConnectionManager.m_Offline); + } + } +} diff --git a/Assets/Scripts/ConnectionManagement/ConnectionState/DisconnectingWithReasonState.cs.meta b/Assets/Scripts/ConnectionManagement/ConnectionState/DisconnectingWithReasonState.cs.meta new file mode 100644 index 0000000..96cbc0b --- /dev/null +++ b/Assets/Scripts/ConnectionManagement/ConnectionState/DisconnectingWithReasonState.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8cdbdfce07de4da48006d8e16b95da48 +timeCreated: 1654886224 \ No newline at end of file diff --git a/Assets/Scripts/ConnectionManagement/ConnectionState/OfflineState.cs b/Assets/Scripts/ConnectionManagement/ConnectionState/OfflineState.cs index 34dc047..bf8f196 100644 --- a/Assets/Scripts/ConnectionManagement/ConnectionState/OfflineState.cs +++ b/Assets/Scripts/ConnectionManagement/ConnectionState/OfflineState.cs @@ -3,6 +3,8 @@ using Unity.BossRoom.ConnectionManagement; using Unity.BossRoom.UnityServices.Lobbies; using Unity.BossRoom.Utils; using Unity.Multiplayer.Samples.Utilities; +using Unity.Netcode; +using Unity.Netcode.Transports.UTP; using UnityEngine; using UnityEngine.SceneManagement; using VContainer; @@ -61,5 +63,61 @@ namespace UUnity.BossRoom.ConnectionManagement var connectionMethod = new ConnectionMethodRelay(m_LobbyServiceFacade, m_LocalLobby, m_ConnectionManager, m_ProfileManager, playerName); m_ConnectionManager.ChangeState(m_ConnectionManager.m_StartingHost.Configure(connectionMethod)); } + + public override void StartServerIP(string ip, int port) + { + // Log input parameters to ensure they are correct + Debug.Log($"StartServerIP called with IP: {ip}, Port: {port}"); + + // Check if NetworkManager.Singleton is null + if (NetworkManager.Singleton == null) + { + Debug.Log("NetworkManager.Singleton is null. Ensure a NetworkManager exists in the scene."); + return; + } + + // Check if NetworkConfig or NetworkTransport is null + if (NetworkManager.Singleton.NetworkConfig == null) + { + Debug.Log("NetworkManager.Singleton.NetworkConfig is null. Ensure NetworkConfig is properly configured."); + return; + } + + if (NetworkManager.Singleton.NetworkConfig.NetworkTransport == null) + { + Debug.Log("NetworkManager.Singleton.NetworkConfig.NetworkTransport is null. Ensure NetworkTransport is properly configured."); + return; + } + + // Attempt to cast the transport to UnityTransport + var utp = NetworkManager.Singleton.NetworkConfig.NetworkTransport as UnityTransport; + if (utp == null) + { + Debug.Log("Failed to cast NetworkTransport to UnityTransport. Ensure UnityTransport is set up as the transport."); + return; + } + + // Log before setting connection data + Debug.Log($"Setting UnityTransport connection data with IP: {ip}, Port: {port}"); + utp.SetConnectionData(ip, (ushort)port); + + // Check if ConnectionManager or m_ServerStarting is null + if (m_ConnectionManager == null) + { + Debug.Log("m_ConnectionManager is null. Ensure it is properly assigned."); + return; + } + + if (m_ConnectionManager.m_ServerStarting == null) + { + Debug.Log("m_ServerStarting is null. Ensure all states are properly initialized in ConnectionManager."); + return; + } + + // Log state change + Debug.Log("Changing state to m_ServerStarting."); + m_ConnectionManager.ChangeState(m_ConnectionManager.m_ServerStarting); + } + } } diff --git a/Assets/Scripts/ConnectionManagement/ConnectionState/ServerListeningState.cs b/Assets/Scripts/ConnectionManagement/ConnectionState/ServerListeningState.cs new file mode 100644 index 0000000..281a13a --- /dev/null +++ b/Assets/Scripts/ConnectionManagement/ConnectionState/ServerListeningState.cs @@ -0,0 +1,171 @@ +using System; +using System.Collections; +using Unity.BossRoom.Infrastructure; +using Unity.BossRoom.UnityServices.Lobbies; +using Unity.Multiplayer.Samples.BossRoom; +using Unity.Netcode; +using UnityEngine; +using VContainer; + +namespace Unity.BossRoom.ConnectionManagement +{ + class ServerListeningState : ConnectionState + { + [Inject] + protected LobbyServiceFacade m_LobbyServiceFacade; + + [Inject] + protected IPublisher m_ConnectionEventPublisher; + + // used in ApprovalCheck. This is intended as a bit of light protection against DOS attacks that rely on sending silly big buffers of garbage. + const int k_MaxConnectPayload = 1024; + + public override void Enter() + { + var gameState = UnityEngine.Object.Instantiate(m_ConnectionManager.GameState); + + gameState.Spawn(); + // TODO Phil is refactoring the above, leaving this here for now + } + + public override void Exit() + { + SessionManager.Instance.OnServerEnded(); + } + + public override void OnClientConnected(ulong clientId) + { + m_ConnectionEventPublisher.Publish(new ConnectionEventMessage() { ConnectStatus = ConnectStatus.Success, PlayerName = SessionManager.Instance.GetPlayerData(clientId)?.PlayerName }); + } + + public override void OnClientDisconnect(ulong clientId) + { + var playerId = SessionManager.Instance.GetPlayerId(clientId); + if (playerId != null) + { + if (m_LobbyServiceFacade.CurrentUnityLobby != null) + { + m_LobbyServiceFacade.RemovePlayerFromLobbyAsync(playerId); + } + + var sessionData = SessionManager.Instance.GetPlayerData(playerId); + if (sessionData.HasValue) + { + m_ConnectionEventPublisher.Publish(new ConnectionEventMessage() { ConnectStatus = ConnectStatus.GenericDisconnect, PlayerName = sessionData.Value.PlayerName }); + } + + SessionManager.Instance.DisconnectClient(clientId); + } + } + + /// + /// This logic plugs into the "ConnectionApprovalResponse" exposed by Netcode.NetworkManager. It is run every time a client connects to us. + /// The complementary logic that runs when the client starts its connection can be found in ClientConnectingState. + /// + /// + /// Multiple things can be done here, some asynchronously. For example, it could authenticate your user against an auth service like UGS' auth service. It can + /// also send custom messages to connecting users before they receive their connection result (this is useful to set status messages client side + /// when connection is refused, for example). + /// + /// The initial request contains, among other things, binary data passed into StartClient. In our case, this is the client's GUID, + /// which is a unique identifier for their install of the game that persists across app restarts. + /// Our response to the approval process. In case of connection refusal with custom return message, we delay using the Pending field. + public override void ApprovalCheck(NetworkManager.ConnectionApprovalRequest request, NetworkManager.ConnectionApprovalResponse response) + { + Debug.Log($"ApprovalCheck called for clientId: {request.ClientNetworkId}"); + + var connectionData = request.Payload; + var clientId = request.ClientNetworkId; + + // Check if the connection data size exceeds the maximum payload size + if (connectionData.Length > k_MaxConnectPayload) + { + Debug.LogWarning($"Connection data from clientId: {clientId} exceeds the maximum allowed size of {k_MaxConnectPayload}. Denying connection."); + response.Approved = false; + return; + } + + // Decode and parse the connection payload + var payload = System.Text.Encoding.UTF8.GetString(connectionData); + Debug.Log($"Received connection payload from clientId: {clientId}: {payload}"); + + ConnectionPayload connectionPayload; + try + { + connectionPayload = JsonUtility.FromJson(payload); + } + catch (Exception ex) + { + Debug.LogError($"Failed to deserialize connection payload from clientId: {clientId}. Error: {ex.Message}"); + response.Approved = false; + return; + } + + // Determine the connection status + var gameReturnStatus = GetConnectStatus(connectionPayload); + Debug.Log($"Connect status for clientId: {clientId}: {gameReturnStatus}"); + + if (gameReturnStatus == ConnectStatus.Success) + { + Debug.Log($"Connection approved for clientId: {clientId}. Setting up session data."); + + SessionManager.Instance.SetupConnectingPlayerSessionData(clientId, connectionPayload.playerId, + new SessionPlayerData(clientId, connectionPayload.playerName, new NetworkGuid(), 0, true)); + + response.Approved = true; + response.CreatePlayerObject = true; + response.Position = Vector3.zero; + response.Rotation = Quaternion.identity; + + Debug.Log($"Sending success payload to clientId: {clientId}"); + ConnectionManager.SendServertoClientSuccessPayload(clientId, NetworkManager.Singleton.IsHost ? ConnectionManager.ServerType.ClientHostedServer : ConnectionManager.ServerType.DedicatedServer); + + return; + } + + // Log denial reason and handle feedback + Debug.LogWarning($"Connection denied for clientId: {clientId}. Reason: {gameReturnStatus}"); + + IEnumerator WaitToDenyApproval() + { + Debug.Log($"Sending denial reason to clientId: {clientId}"); + response.Pending = true; // Delay the approval response + response.Approved = false; + ConnectionManager.SendServerToClientSetDisconnectReason(clientId, gameReturnStatus); + yield return null; // Wait for one frame + response.Pending = false; // Finish the approval process + Debug.Log($"Denied connection finalized for clientId: {clientId}"); + } + + // Start coroutine to handle denial + ConnectionManager.SendServerToClientSetDisconnectReason(clientId, gameReturnStatus); + Debug.Log($"Starting denial process for clientId: {clientId}"); + m_ConnectionManager.StartCoroutine(WaitToDenyApproval()); + + if (m_LobbyServiceFacade.CurrentUnityLobby != null) + { + Debug.Log($"Removing clientId: {clientId} from lobby."); + m_LobbyServiceFacade.RemovePlayerFromLobbyAsync(connectionPayload.playerId); + } + } + + + ConnectStatus GetConnectStatus(ConnectionPayload connectionPayload) + { + if (m_ConnectionManager.NetworkManager.ConnectedClientsIds.Count >= m_ConnectionManager.MaxConnectedPlayers) + { + return ConnectStatus.ServerFull; + } + + if (connectionPayload.isDebug != Debug.isDebugBuild) + { + return ConnectStatus.IncompatibleBuildType; + } + + return SessionManager.Instance.IsDuplicateConnection(connectionPayload.playerId) ? + ConnectStatus.LoggedInAgain : ConnectStatus.Success; + } + + // TODO handle server shutdown by itself (clean shutdown) and tells clients to disconnect? connection draining? MTT-4069 + } +} diff --git a/Assets/Scripts/ConnectionManagement/ConnectionState/ServerListeningState.cs.meta b/Assets/Scripts/ConnectionManagement/ConnectionState/ServerListeningState.cs.meta new file mode 100644 index 0000000..5ac2a30 --- /dev/null +++ b/Assets/Scripts/ConnectionManagement/ConnectionState/ServerListeningState.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 70a54926786e4e92a304a22c43bacb25 +timeCreated: 1657574627 \ No newline at end of file diff --git a/Assets/Scripts/ConnectionManagement/ConnectionState/ServerStartingState.cs b/Assets/Scripts/ConnectionManagement/ConnectionState/ServerStartingState.cs new file mode 100644 index 0000000..acf0c37 --- /dev/null +++ b/Assets/Scripts/ConnectionManagement/ConnectionState/ServerStartingState.cs @@ -0,0 +1,25 @@ +using Unity.Multiplayer.Samples; +using Unity.Netcode; +using UnityEngine; + +namespace Unity.BossRoom.ConnectionManagement +{ + class ServerStartingState : ConnectionState + { + public override void Enter() + { + var success = NetworkManager.Singleton.StartServer(); + if (!success) + { + Debug.Log("StartServer returned false and failed starting. Killing process."); + Application.Quit(1); + return; + } + + m_ConnectionManager.ChangeState(m_ConnectionManager.m_ServerListening); + } + + + public override void Exit() { } + } +} diff --git a/Assets/Scripts/ConnectionManagement/ConnectionState/ServerStartingState.cs.meta b/Assets/Scripts/ConnectionManagement/ConnectionState/ServerStartingState.cs.meta new file mode 100644 index 0000000..015268c --- /dev/null +++ b/Assets/Scripts/ConnectionManagement/ConnectionState/ServerStartingState.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3340424e374042ab977d9f1dfced6811 +timeCreated: 1657574995 \ No newline at end of file diff --git a/Assets/Scripts/Gameplay/GameState/DSLobbyManagementState.cs b/Assets/Scripts/Gameplay/GameState/DSLobbyManagementState.cs new file mode 100644 index 0000000..86cf015 --- /dev/null +++ b/Assets/Scripts/Gameplay/GameState/DSLobbyManagementState.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using BossRoom.Scripts.Shared.Utilities; +using Unity.BossRoom.ConnectionManagement; +using Unity.BossRoom.Gameplay.GameState; +using Unity.Multiplayer.Samples.Utilities; +using UnityEngine; +using VContainer; + +namespace Unity.Multiplayer.Samples.BossRoom.Server +{ + public class DSLobbyManagementState : GameStateBehaviour + { + [Inject] + ConnectionManager m_ConnectionManager; + public override GameState ActiveState => GameState.DedicatedServerLobbyManagement; + + protected override void Start() + { + base.Start(); + + // TODO create DGS lobby here, register to matchmaking, etc. This state bypasses the main menu setup users would normally do get in a game + // and does its own game setup MTT-4035 + var address = "0.0.0.0"; // Change this for fancier infrastructure hosting setup where you can listen on different IP addresses. Right now listening on all. + var port = 9998; + + // Some quick command line processing. + Dictionary args = new(); + foreach (var oneArg in Environment.GetCommandLineArgs()) + { + var keyValue = oneArg.Split('='); + args.Add(keyValue[0], keyValue.Length > 1 ? keyValue[1] : null); + } + + var portArg = "-port"; + if (args.ContainsKey(portArg) && !int.TryParse(args[portArg], out port)) + { + DedicatedServerUtilities.Log("failed to parse -port arg: " + args[portArg]); + } + var ipArg = "-ip"; + if (args.TryGetValue(ipArg, out var arg)) + { + address = arg; + DedicatedServerUtilities.Log("Got IP: " + args[portArg]); + } + + + IEnumerator StartServerCoroutine() + { + DedicatedServerUtilities.Log($"Starting Headless Server, listening on address {address}:{port}"); + m_ConnectionManager.StartServerIP(address, port); // This will switch to the char select scene once the server started callback has been called + + yield return new WaitForServerStarted(); // Less performant than just the callback, but way more readable than a callback hell. + + // TODO change scene to char select here and do other init. why is it handled by connection manager right now? + SceneLoaderWrapper.Instance.AddOnSceneEventCallback(); + SceneLoaderWrapper.Instance.LoadScene("CharSelect", useNetworkSceneManager: true); + } + StartCoroutine(StartServerCoroutine()); + } + } +} diff --git a/Assets/Scripts/Gameplay/GameState/DSLobbyManagementState.cs.meta b/Assets/Scripts/Gameplay/GameState/DSLobbyManagementState.cs.meta new file mode 100644 index 0000000..3931245 --- /dev/null +++ b/Assets/Scripts/Gameplay/GameState/DSLobbyManagementState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a35fe42cd86928c4d9dd52f2136ba795 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Gameplay/GameState/GameStateBehaviour.cs b/Assets/Scripts/Gameplay/GameState/GameStateBehaviour.cs index c371fbe..22b28aa 100644 --- a/Assets/Scripts/Gameplay/GameState/GameStateBehaviour.cs +++ b/Assets/Scripts/Gameplay/GameState/GameStateBehaviour.cs @@ -7,6 +7,7 @@ namespace Unity.BossRoom.Gameplay.GameState public enum GameState { MainMenu, + DedicatedServerLobbyManagement, CharSelect, BossRoom, PostGame diff --git a/Assets/Scripts/Gameplay/GameState/NetworkGameState.cs b/Assets/Scripts/Gameplay/GameState/NetworkGameState.cs new file mode 100644 index 0000000..a81a38b --- /dev/null +++ b/Assets/Scripts/Gameplay/GameState/NetworkGameState.cs @@ -0,0 +1,34 @@ +using System; +using Unity.Netcode; +using UnityEngine; + +namespace Unity.Multiplayer.Samples.BossRoom +{ + public class NetworkGameState : NetworkBehaviour + { + [SerializeField] + TransformVariable m_GameStateTransformVariable; + + [SerializeField] + NetworkWinState m_NetworkWinState; + + public NetworkWinState NetworkWinState => m_NetworkWinState; + + void Awake() + { + DontDestroyOnLoad(this); + } + + public override void OnNetworkSpawn() + { + gameObject.name = "NetworkGameState"; + + m_GameStateTransformVariable.Value = transform; + } + + public override void OnNetworkDespawn() + { + m_GameStateTransformVariable.Value = null; + } + } +} diff --git a/Assets/Scripts/Gameplay/GameState/NetworkGameState.cs.meta b/Assets/Scripts/Gameplay/GameState/NetworkGameState.cs.meta new file mode 100644 index 0000000..072e6b0 --- /dev/null +++ b/Assets/Scripts/Gameplay/GameState/NetworkGameState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9fb009f05b6b84d35af38930cac98d9a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Gameplay/GameState/NetworkWinState.cs b/Assets/Scripts/Gameplay/GameState/NetworkWinState.cs new file mode 100644 index 0000000..adc127c --- /dev/null +++ b/Assets/Scripts/Gameplay/GameState/NetworkWinState.cs @@ -0,0 +1,21 @@ +using System; +using Unity.Netcode; +using UnityEngine; + +namespace Unity.Multiplayer.Samples.BossRoom +{ + public enum WinState + { + Invalid, + Win, + Loss + } + + /// + /// MonoBehaviour containing only one NetworkVariableBool to represent the game session's win state. + /// + public class NetworkWinState : NetworkBehaviour + { + public NetworkVariable winState = new NetworkVariable(WinState.Invalid); + } +} diff --git a/Assets/Scripts/Gameplay/GameState/NetworkWinState.cs.meta b/Assets/Scripts/Gameplay/GameState/NetworkWinState.cs.meta new file mode 100644 index 0000000..4053feb --- /dev/null +++ b/Assets/Scripts/Gameplay/GameState/NetworkWinState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 69eb1bedacf698e4bada2f8d55dabdd8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Gameplay/GameState/ServerCharSelectState.cs b/Assets/Scripts/Gameplay/GameState/ServerCharSelectState.cs index cd3eea0..48ccee3 100644 --- a/Assets/Scripts/Gameplay/GameState/ServerCharSelectState.cs +++ b/Assets/Scripts/Gameplay/GameState/ServerCharSelectState.cs @@ -3,6 +3,7 @@ using System.Collections; using Unity.BossRoom.ConnectionManagement; using Unity.BossRoom.Gameplay.GameplayObjects; using Unity.BossRoom.Infrastructure; +using Unity.Multiplayer.Samples; using Unity.Multiplayer.Samples.BossRoom; using Unity.Multiplayer.Samples.Utilities; using Unity.Netcode; @@ -48,6 +49,31 @@ namespace Unity.BossRoom.Gameplay.GameState } } + // void OnClientChangedSeat(ulong clientId, int newSeatIdx, bool lockedIn) + // { + // int idx = FindLobbyPlayerIdx(clientId); + // if (idx == -1) + // { + // throw new Exception($"OnClientChangedSeat: client ID {clientId} is not a lobby player and cannot change seats! Shouldn't be here!"); + // } + // + // if (networkCharSelection.IsLobbyClosed.Value) + // { + // // The user tried to change their class after everything was locked in... too late! Discard this choice + // return; + // } + // + // // Allow multiple players to select the same character without restrictions + // networkCharSelection.LobbyPlayers[idx] = new NetworkCharSelection.LobbyPlayerState(clientId, + // networkCharSelection.LobbyPlayers[idx].PlayerName, + // networkCharSelection.LobbyPlayers[idx].PlayerNumber, + // lockedIn ? NetworkCharSelection.SeatState.LockedIn : NetworkCharSelection.SeatState.Active, + // newSeatIdx, + // Time.time); + // Debug.Log("CloseLobbyIfReady"); + // CloseLobbyIfReady(); + // } + void OnClientChangedSeat(ulong clientId, int newSeatIdx, bool lockedIn) { int idx = FindLobbyPlayerIdx(clientId); @@ -55,24 +81,66 @@ namespace Unity.BossRoom.Gameplay.GameState { throw new Exception($"OnClientChangedSeat: client ID {clientId} is not a lobby player and cannot change seats! Shouldn't be here!"); } - + if (networkCharSelection.IsLobbyClosed.Value) { // The user tried to change their class after everything was locked in... too late! Discard this choice return; } - - // Allow multiple players to select the same character without restrictions + + if (newSeatIdx == -1) + { + // we can't lock in with no seat + lockedIn = false; + } + else + { + // see if someone has already locked-in that seat! If so, too late... discard this choice + foreach (NetworkCharSelection.LobbyPlayerState playerInfo in networkCharSelection.LobbyPlayers) + { + if (playerInfo.ClientId != clientId && playerInfo.SeatIdx == newSeatIdx && playerInfo.SeatState == NetworkCharSelection.SeatState.LockedIn) + { + // somebody already locked this choice in. Stop! + // Instead of granting lock request, change this player to Inactive state. + networkCharSelection.LobbyPlayers[idx] = new NetworkCharSelection.LobbyPlayerState(clientId, + networkCharSelection.LobbyPlayers[idx].PlayerName, + networkCharSelection.LobbyPlayers[idx].PlayerNumber, + NetworkCharSelection.SeatState.Inactive); + + // then early out + return; + } + } + } + networkCharSelection.LobbyPlayers[idx] = new NetworkCharSelection.LobbyPlayerState(clientId, networkCharSelection.LobbyPlayers[idx].PlayerName, networkCharSelection.LobbyPlayers[idx].PlayerNumber, lockedIn ? NetworkCharSelection.SeatState.LockedIn : NetworkCharSelection.SeatState.Active, newSeatIdx, Time.time); - Debug.Log("CloseLobbyIfReady"); + + if (lockedIn) + { + // to help the clients visually keep track of who's in what seat, we'll "kick out" any other players + // who were also in that seat. (Those players didn't click "Ready!" fast enough, somebody else took their seat!) + for (int i = 0; i < networkCharSelection.LobbyPlayers.Count; ++i) + { + if (networkCharSelection.LobbyPlayers[i].SeatIdx == newSeatIdx && i != idx) + { + // change this player to Inactive state. + networkCharSelection.LobbyPlayers[i] = new NetworkCharSelection.LobbyPlayerState( + networkCharSelection.LobbyPlayers[i].ClientId, + networkCharSelection.LobbyPlayers[i].PlayerName, + networkCharSelection.LobbyPlayers[i].PlayerNumber, + NetworkCharSelection.SeatState.Inactive); + } + } + } + CloseLobbyIfReady(); } - + /// /// Returns the index of a client in the master LobbyPlayer list, or -1 if not found /// @@ -93,14 +161,50 @@ namespace Unity.BossRoom.Gameplay.GameState } void CloseLobbyIfReady() { - startButtonScipt.InteractableTruer(false); + // If dedicated server, leave char select open if there's no one left + if (DedicatedServerUtilities.IsServerBuildTarget && networkCharSelection.LobbyPlayers.Count == 0) + { + return; + } + foreach (NetworkCharSelection.LobbyPlayerState playerInfo in networkCharSelection.LobbyPlayers) { if (playerInfo.SeatState != NetworkCharSelection.SeatState.LockedIn) - return; // at least one player isn't locked in yet! + return; // nope, at least one player isn't locked in yet! } - startButtonScipt.InteractableTruer(true); + + // everybody's ready at the same time! Lock it down! + networkCharSelection.IsLobbyClosed.Value = true; + + // remember our choices so the next scene can use the info + SaveLobbyResults(); + + // Delay a few seconds to give the UI time to react, then switch scenes + IEnumerator WaitToEndLobby() + { + yield return new WaitForSeconds(3); + SceneLoaderWrapper.Instance.LoadScene("BossRoom", useNetworkSceneManager: true); + } + m_WaitToEndLobbyCoroutine = StartCoroutine(WaitToEndLobby()); } + + + // void CloseLobbyIfReady() + // { + // // If dedicated server, leave char select open if there's no one left + // if (DedicatedServerUtilities.IsServerBuildTarget && networkCharSelection.LobbyPlayers.Count == 0) + // { + // return; + // } + // + // startButtonScipt.InteractableTruer(false); + // foreach (NetworkCharSelection.LobbyPlayerState playerInfo in networkCharSelection.LobbyPlayers) + // { + // if (playerInfo.SeatState != NetworkCharSelection.SeatState.LockedIn) + // return; // at least one player isn't locked in yet! + // } + // startButtonScipt.InteractableTruer(true); + // } public StartButtonScipt startButtonScipt; void CancelCloseLobby() { diff --git a/Assets/Scripts/Gameplay/GameplayObjects/RuntimeDataContainers/TransformRegister.cs b/Assets/Scripts/Gameplay/GameplayObjects/RuntimeDataContainers/TransformRegister.cs new file mode 100644 index 0000000..d416a8e --- /dev/null +++ b/Assets/Scripts/Gameplay/GameplayObjects/RuntimeDataContainers/TransformRegister.cs @@ -0,0 +1,23 @@ +using UnityEngine; + +namespace Unity.Multiplayer.Samples.BossRoom +{ + /// + /// Class which registers a transform to an associated TransformVariable ScriptableObject. + /// + public class TransformRegister : MonoBehaviour + { + [SerializeField] + TransformVariable m_TransformVariable; + + void OnEnable() + { + m_TransformVariable.Value = transform; + } + + void OnDisable() + { + m_TransformVariable.Value = null; + } + } +} diff --git a/Assets/Scripts/Gameplay/GameplayObjects/RuntimeDataContainers/TransformRegister.cs.meta b/Assets/Scripts/Gameplay/GameplayObjects/RuntimeDataContainers/TransformRegister.cs.meta new file mode 100644 index 0000000..f48803e --- /dev/null +++ b/Assets/Scripts/Gameplay/GameplayObjects/RuntimeDataContainers/TransformRegister.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b280145480d7594419baed09a111184b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Infrastructure/ScriptableObjectArchitecture/TransformVariable.cs b/Assets/Scripts/Infrastructure/ScriptableObjectArchitecture/TransformVariable.cs new file mode 100644 index 0000000..d3ae2fd --- /dev/null +++ b/Assets/Scripts/Infrastructure/ScriptableObjectArchitecture/TransformVariable.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +namespace Unity.Multiplayer.Samples.BossRoom +{ + /// + /// A ScriptableObject which contains a reference to a Transform component. This can be used to remove dependencies + /// between scene objects. + /// + [CreateAssetMenu] + public class TransformVariable : ScriptableObject + { + public Transform Value; + } +} diff --git a/Assets/Scripts/Infrastructure/ScriptableObjectArchitecture/TransformVariable.cs.meta b/Assets/Scripts/Infrastructure/ScriptableObjectArchitecture/TransformVariable.cs.meta new file mode 100644 index 0000000..3a77a93 --- /dev/null +++ b/Assets/Scripts/Infrastructure/ScriptableObjectArchitecture/TransformVariable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5cccef3cfcbccdb4aa4b407a003237b7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/DedicatedServer.meta b/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/DedicatedServer.meta new file mode 100644 index 0000000..cd117d5 --- /dev/null +++ b/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/DedicatedServer.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b4e4a262f7414bc40b42ff2b75a1610c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/DedicatedServer/DedicatedServerUtilities.cs b/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/DedicatedServer/DedicatedServerUtilities.cs new file mode 100644 index 0000000..a2a1211 --- /dev/null +++ b/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/DedicatedServer/DedicatedServerUtilities.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using UnityEngine; +using UnityEngine.SceneManagement; +using Debug = UnityEngine.Debug; + +namespace Unity.Multiplayer.Samples +{ + public static class DedicatedServerUtilities + { + public static bool IsServerBuildTarget + { + get + { +#if UNITY_SERVER + return true; +#else + return false; +#endif + } + } + + /// + /// Some notes on logging and dedicated servers: + /// + /// With dedicated server, you don't have a view into your game like you'd have with other types of platforms. You'll rely a lot on logging to get + /// insights into what's happening on your servers, even more with your live fleets of thousands of servers. + /// Unity's default logging isn't usable for dedicated server use cases. The following requirements are missing: + /// - Structured logging: with 1000+ server fleets, you don't want to look at log files individually. You'll need log ingestion/analysis tools to be able + /// to parse all that data (think tools like elasticsearch for example). Making your logs structured so they are machine friendly (for example + /// having each log entry be a json object) makes this easier to integrate with those tools and easier to analyze. + /// - Log levels: most of the time, you won't want to receive info or debug logs, only warnings and errors (so you don't spam your analysis tools and so they don't + /// cost your a fortune). However, you'll also want to enable info and debug logs for specific servers when debugging them. Having a logger that + /// manages this for you is better than wrapping your logs yourself and managing this yourself. + /// - Log file rotation: Dedicated servers can run for days and days, while games on user devices will run for a few play sessions before being closed. This means your + /// log file will grow and grow. Rotation is an automated way to swap log files each x hours or days. This allows deleting and easier managing + /// of older log files. + /// - Performance: logging can be a performance costly operation, which contributes to your CPU perf costs, which in turn are translated to hosting monetary costs. + /// Having a logging library that's optimized for these scenarios is essential (burstable, threaded, etc). + /// This also includes not having to print full stack traces (not needed for most devops operations, but could be enabled for debugging) + /// + /// A few solutions exists for this. ZLogger https://github.com/Cysharp/ZLogger and serilog https://www.nuget.org/packages/serilog/ for example. + /// Unity also has an experimental package com.unity.logging that answers the above needs as well. Once this is out of experimental, this will be + /// integrated in boss room. TODO for this first pass at DGS, we're using the default logger. TODO replace me - MTT-4038 + /// + /// + public static void Log(string message) + { + // IMPORTANT FOR LOGGING READ ABOVE. The following isn't recommended for production use with dedicated game servers. + Debug.Log($"[{DateTime.UtcNow}] {Time.realtimeSinceStartup} {Time.time} pid[{Process.GetCurrentProcess().Id}] - {message}"); + } + + /// + /// Quick tool to get insights in your current scene, to be able to debug client and server hierarchies. + /// + public static void PrintSceneHierarchy() + { + List rootObjects = new List(); + Scene scene = SceneManager.GetActiveScene(); + scene.GetRootGameObjects(rootObjects); + string toPrint = "\n"; + foreach (var rootObject in rootObjects) + { + toPrint += $"{GetInfoForObject(rootObject)}\n"; + PrintChildObjectsRecursive(rootObject, depth: 0, ref toPrint); + } + + Log(toPrint); + } + + private static void PrintChildObjectsRecursive(GameObject parentObject, int depth, ref string toPrint) + { + if (parentObject.transform.childCount == 0) + { + return; + } + + string tabs = new string(' ', ++depth * 4); + foreach (Transform child in parentObject.transform) + { + toPrint += $"{tabs}{GetInfoForObject(child.gameObject)}\n"; + PrintChildObjectsRecursive(child.gameObject, depth, ref toPrint); // asdf + } + } + + private static string GetInfoForObject(GameObject obj) + { + List allComponents = new(); + obj.GetComponents(allComponents); + var nullCount = allComponents.FindAll(component => component == null).Count; + return $"{obj.name}\tnb null {nullCount}/{allComponents.Count}"; + } + } +} diff --git a/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/DedicatedServer/DedicatedServerUtilities.cs.meta b/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/DedicatedServer/DedicatedServerUtilities.cs.meta new file mode 100644 index 0000000..22adcd4 --- /dev/null +++ b/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/DedicatedServer/DedicatedServerUtilities.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 035a4d94ff413464f85c30a5cc56cf91 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/WaitForNetworkManagerEvents.cs b/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/WaitForNetworkManagerEvents.cs new file mode 100644 index 0000000..105222a --- /dev/null +++ b/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/WaitForNetworkManagerEvents.cs @@ -0,0 +1,23 @@ +using Unity.Netcode; +using UnityEngine; + +namespace BossRoom.Scripts.Shared.Utilities +{ + public class WaitForServerStarted : CustomYieldInstruction + { + bool m_IsDone; + + public override bool keepWaiting => m_IsDone; + + public WaitForServerStarted() + { + void SetDone() + { + NetworkManager.Singleton.OnServerStarted -= SetDone; + m_IsDone = true; + } + + NetworkManager.Singleton.OnServerStarted += SetDone; + } + } +} diff --git a/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/WaitForNetworkManagerEvents.cs.meta b/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/WaitForNetworkManagerEvents.cs.meta new file mode 100644 index 0000000..620f0fd --- /dev/null +++ b/Packages/com.unity.multiplayer.samples.coop/Utilities/Net/WaitForNetworkManagerEvents.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8a86c80ed82a60747a073c9940723d4d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.multiplayer.samples.coop/Utilities/SceneManagement/SceneLoaderWrapper.cs b/Packages/com.unity.multiplayer.samples.coop/Utilities/SceneManagement/SceneLoaderWrapper.cs index 8104ecb..b78e1c8 100644 --- a/Packages/com.unity.multiplayer.samples.coop/Utilities/SceneManagement/SceneLoaderWrapper.cs +++ b/Packages/com.unity.multiplayer.samples.coop/Utilities/SceneManagement/SceneLoaderWrapper.cs @@ -127,6 +127,18 @@ namespace Unity.Multiplayer.Samples.Utilities } } + /// + /// Initializes the callback on scene events. This needs to be called right after initializing NetworkManager + /// (after StartHost, StartClient or StartServer) + /// + public void AddOnSceneEventCallback() + { + if (IsNetworkSceneManagementEnabled) + { + NetworkManager.SceneManager.OnSceneEvent += OnSceneEvent; + } + } + void OnSceneEvent(SceneEvent sceneEvent) { switch (sceneEvent.SceneEventType) diff --git a/ProjectSettings/BurstAotSettings_StandaloneLinux64.json b/ProjectSettings/BurstAotSettings_StandaloneLinux64.json new file mode 100644 index 0000000..ca7cf1a --- /dev/null +++ b/ProjectSettings/BurstAotSettings_StandaloneLinux64.json @@ -0,0 +1,17 @@ +{ + "MonoBehaviour": { + "Version": 4, + "EnableBurstCompilation": true, + "EnableOptimisations": true, + "EnableSafetyChecks": false, + "EnableDebugInAllBuilds": false, + "DebugDataKind": 1, + "EnableArmv9SecurityFeatures": false, + "CpuMinTargetX32": 0, + "CpuMaxTargetX32": 0, + "CpuMinTargetX64": 0, + "CpuMaxTargetX64": 0, + "CpuTargetsX64": 72, + "OptimizeFor": 0 + } +} diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset index 14a0e49..e8dd81f 100644 --- a/ProjectSettings/EditorBuildSettings.asset +++ b/ProjectSettings/EditorBuildSettings.asset @@ -11,6 +11,9 @@ EditorBuildSettings: - enabled: 1 path: Assets/Scenes/MainMenu.unity guid: e676e10fba50b4172a2b5146af0b3c12 + - enabled: 1 + path: Assets/Scenes/DedicatedServerLobbyManagement.unity + guid: c415c55354f6743faa63ac4c8b181a65 - enabled: 1 path: Assets/Scenes/CharSelect.unity guid: 69ca9af1235ffe340a45770dd5771f03