├── CubesMultiplayerDemoClient ├── .gitignore ├── Assets │ ├── Materials │ │ ├── Floor.mat │ │ └── Player.mat │ ├── Prefabs │ │ ├── Floor.prefab │ │ ├── NetPlayer.prefab │ │ └── Player.prefab │ ├── Scenes │ │ └── SampleScene.unity │ ├── Scripts │ │ ├── LiteNetLib │ │ │ ├── INetEventListener.cs │ │ │ ├── NatPunchModule.cs │ │ │ ├── NetConstants.cs │ │ │ ├── NetDebug.cs │ │ │ ├── NetEndPoint.cs │ │ │ ├── NetManager.cs │ │ │ ├── NetPacket.cs │ │ │ ├── NetPacketPool.cs │ │ │ ├── NetPeer.cs │ │ │ ├── NetPeerCollection.cs │ │ │ ├── NetSocket.cs │ │ │ ├── NetStatistics.cs │ │ │ ├── NetThread.cs │ │ │ ├── NetUtils.cs │ │ │ ├── ReliableChannel.cs │ │ │ ├── SequencedChannel.cs │ │ │ ├── SimpleChannel.cs │ │ │ └── Utils │ │ │ │ ├── FastBitConverter.cs │ │ │ │ ├── NetDataReader.cs │ │ │ │ ├── NetDataWriter.cs │ │ │ │ └── NetSerializer.cs │ │ ├── NetPlayer.cs │ │ ├── Network.cs │ │ └── Player.cs │ └── Shared.dll ├── Packages │ └── manifest.json └── ProjectSettings │ ├── AudioManager.asset │ ├── ClusterInputManager.asset │ ├── DynamicsManager.asset │ ├── EditorBuildSettings.asset │ ├── EditorSettings.asset │ ├── GraphicsSettings.asset │ ├── InputManager.asset │ ├── NavMeshAreas.asset │ ├── NetworkManager.asset │ ├── Physics2DSettings.asset │ ├── PresetManager.asset │ ├── ProjectSettings.asset │ ├── ProjectVersion.txt │ ├── QualitySettings.asset │ ├── TagManager.asset │ ├── TimeManager.asset │ └── UnityConnectSettings.asset ├── CubesMultiplayerDemoServer ├── .gitignore ├── CubesMultiplayerDemoServer.sln └── src │ ├── Server │ ├── NetworkPlayer.cs │ ├── Program.cs │ └── Server.csproj │ └── Shared │ ├── Enums │ └── NetworkTags.cs │ └── Shared.csproj ├── README.md └── example.gif /CubesMultiplayerDemoClient/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | .vs/ 9 | 10 | # Build results 11 | [Dd]ebug/ 12 | [Dd]ebugPublic/ 13 | [Rr]elease/ 14 | [Rr]eleases/ 15 | x64/ 16 | build/ 17 | bld/ 18 | [Bb]in/ 19 | [Oo]bj/ 20 | 21 | # Roslyn cache directories 22 | *.ide/ 23 | 24 | # MSTest test Results 25 | [Tt]est[Rr]esult*/ 26 | [Bb]uild[Ll]og.* 27 | 28 | #NUNIT 29 | *.VisualState.xml 30 | TestResult.xml 31 | 32 | # Build Results of an ATL Project 33 | [Dd]ebugPS/ 34 | [Rr]eleasePS/ 35 | dlldata.c 36 | 37 | *_i.c 38 | *_p.c 39 | *_i.h 40 | *.ilk 41 | *.meta 42 | *.obj 43 | *.pch 44 | *.pdb 45 | *.pgc 46 | *.pgd 47 | *.rsp 48 | *.sbr 49 | *.tlb 50 | *.tli 51 | *.tlh 52 | *.tmp 53 | *.tmp_proj 54 | *.log 55 | *.vspscc 56 | *.vssscc 57 | .builds 58 | *.pidb 59 | *.svclog 60 | *.scc 61 | 62 | # Chutzpah Test files 63 | _Chutzpah* 64 | 65 | # Visual C++ cache files 66 | ipch/ 67 | *.aps 68 | *.ncb 69 | *.opensdf 70 | *.sdf 71 | *.cachefile 72 | 73 | # Visual Studio profiler 74 | *.psess 75 | *.vsp 76 | *.vspx 77 | 78 | # TFS 2012 Local Workspace 79 | $tf/ 80 | 81 | # Guidance Automation Toolkit 82 | *.gpState 83 | 84 | # Visual Studio 2015/2017 cache/options directory 85 | .vs/ 86 | # Uncomment if you have tasks that create the project's static files in wwwroot 87 | #wwwroot/ 88 | 89 | # Visual Studio 2017 auto generated files 90 | Generated\ Files/ 91 | 92 | # ReSharper is a .NET coding add-in 93 | _ReSharper*/ 94 | *.[Rr]e[Ss]harper 95 | *.DotSettings.user 96 | 97 | # JustCode is a .NET coding addin-in 98 | .JustCode 99 | 100 | # TeamCity is a build add-in 101 | _TeamCity* 102 | 103 | # DotCover is a Code Coverage Tool 104 | *.dotCover 105 | 106 | # NCrunch 107 | _NCrunch_* 108 | .*crunch*.local.xml 109 | 110 | # MightyMoose 111 | *.mm.* 112 | AutoTest.Net/ 113 | 114 | # Web workbench (sass) 115 | .sass-cache/ 116 | 117 | # Installshield output folder 118 | [Ee]xpress/ 119 | 120 | # DocProject is a documentation generator add-in 121 | DocProject/buildhelp/ 122 | DocProject/Help/*.HxT 123 | DocProject/Help/*.HxC 124 | DocProject/Help/*.hhc 125 | DocProject/Help/*.hhk 126 | DocProject/Help/*.hhp 127 | DocProject/Help/Html2 128 | DocProject/Help/html 129 | 130 | # Click-Once directory 131 | publish/ 132 | 133 | # Publish Web Output 134 | *.[Pp]ublish.xml 135 | *.azurePubxml 136 | ## TODO: Comment the next line if you want to checkin your 137 | ## web deploy settings but do note that will include unencrypted 138 | ## passwords 139 | *.pubxml 140 | 141 | # NuGet Packages Directory 142 | packages/* 143 | ## TODO: If the tool you use requires repositories.config 144 | ## uncomment the next line 145 | #!packages/repositories.config 146 | 147 | # Enable "build/" folder in the NuGet Packages folder since 148 | # NuGet packages use it for MSBuild targets. 149 | # This line needs to be after the ignore of the build folder 150 | # (and the packages folder if the line above has been uncommented) 151 | !packages/build/ 152 | 153 | # Windows Azure Build Output 154 | csx/ 155 | *.build.csdef 156 | 157 | # Windows Store app package directory 158 | AppPackages/ 159 | 160 | # Others 161 | sql/ 162 | *.Cache 163 | ClientBin/ 164 | [Ss]tyle[Cc]op.* 165 | ~$* 166 | *~ 167 | *.dbmdl 168 | *.dbproj.schemaview 169 | *.pfx 170 | *.publishsettings 171 | node_modules/ 172 | 173 | # RIA/Silverlight projects 174 | Generated_Code/ 175 | 176 | # Backup & report files from converting an old project file 177 | # to a newer Visual Studio version. Backup files are not needed, 178 | # because we have git ;-) 179 | _UpgradeReport_Files/ 180 | Backup*/ 181 | UpgradeLog*.XML 182 | UpgradeLog*.htm 183 | 184 | # SQL Server files 185 | *.mdf 186 | *.ldf 187 | 188 | # Business Intelligence projects 189 | *.rdl.data 190 | *.bim.layout 191 | *.bim_*.settings 192 | 193 | # Microsoft Fakes 194 | FakesAssemblies/ 195 | 196 | git_stats/* 197 | 198 | *.ncrunchproject 199 | StyleCop.Cache 200 | bin 201 | obj 202 | 203 | 204 | # UNITY 205 | 206 | [Ll]ibrary/ 207 | [Tt]emp/ 208 | [Oo]bj/ 209 | [Bb]uild/ 210 | [Bb]uilds/ 211 | Assets/AssetStoreTools* 212 | 213 | # Visual Studio cache directory 214 | .vs/ 215 | 216 | # Autogenerated VS/MD/Consulo solution and project files 217 | ExportedObj/ 218 | .consulo/ 219 | *.csproj 220 | *.unityproj 221 | *.sln 222 | *.suo 223 | *.tmp 224 | *.user 225 | *.userprefs 226 | *.pidb 227 | *.booproj 228 | *.svd 229 | *.pdb 230 | *.opendb 231 | 232 | # Unity3D generated meta files 233 | *.pidb.meta 234 | *.pdb.meta 235 | 236 | # Unity3D Generated File On Crash Reports 237 | sysinfo.txt 238 | 239 | # Builds 240 | *.apk 241 | *.unitypackage -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Materials/Floor.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: Floor 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 0} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 0.5 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _UVSec: 0 73 | - _ZWrite: 1 74 | m_Colors: 75 | - _Color: {r: 0.15419188, g: 0.5188679, b: 0.25857887, a: 1} 76 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 77 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Materials/Player.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: Player 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 0} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 0.5 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _UVSec: 0 73 | - _ZWrite: 1 74 | m_Colors: 75 | - _Color: {r: 0.6886792, g: 0.48402455, b: 0.48402455, a: 1} 76 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 77 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Prefabs/Floor.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1001 &100100000 4 | Prefab: 5 | m_ObjectHideFlags: 1 6 | serializedVersion: 2 7 | m_Modification: 8 | m_TransformParent: {fileID: 0} 9 | m_Modifications: [] 10 | m_RemovedComponents: [] 11 | m_SourcePrefab: {fileID: 0} 12 | m_RootGameObject: {fileID: 1010506836010290} 13 | m_IsPrefabAsset: 1 14 | --- !u!1 &1010340096941446 15 | GameObject: 16 | m_ObjectHideFlags: 0 17 | m_CorrespondingSourceObject: {fileID: 0} 18 | m_PrefabInternal: {fileID: 100100000} 19 | serializedVersion: 6 20 | m_Component: 21 | - component: {fileID: 4573927177739748} 22 | - component: {fileID: 33662256303880736} 23 | - component: {fileID: 23774172063303014} 24 | - component: {fileID: 65787851039163106} 25 | - component: {fileID: 65087800184519950} 26 | m_Layer: 0 27 | m_Name: Bord (2) 28 | m_TagString: Untagged 29 | m_Icon: {fileID: 0} 30 | m_NavMeshLayer: 0 31 | m_StaticEditorFlags: 0 32 | m_IsActive: 1 33 | --- !u!1 &1010506836010290 34 | GameObject: 35 | m_ObjectHideFlags: 0 36 | m_CorrespondingSourceObject: {fileID: 0} 37 | m_PrefabInternal: {fileID: 100100000} 38 | serializedVersion: 6 39 | m_Component: 40 | - component: {fileID: 4284712273699304} 41 | - component: {fileID: 33929017365551490} 42 | - component: {fileID: 23038515933329936} 43 | - component: {fileID: 64689253414403800} 44 | - component: {fileID: 65805571091712842} 45 | m_Layer: 0 46 | m_Name: Floor 47 | m_TagString: Untagged 48 | m_Icon: {fileID: 0} 49 | m_NavMeshLayer: 0 50 | m_StaticEditorFlags: 0 51 | m_IsActive: 1 52 | --- !u!1 &1665137963937560 53 | GameObject: 54 | m_ObjectHideFlags: 0 55 | m_CorrespondingSourceObject: {fileID: 0} 56 | m_PrefabInternal: {fileID: 100100000} 57 | serializedVersion: 6 58 | m_Component: 59 | - component: {fileID: 4615528866575254} 60 | - component: {fileID: 33862078007593612} 61 | - component: {fileID: 23523361689677772} 62 | - component: {fileID: 65803275033776586} 63 | - component: {fileID: 65631375037955232} 64 | m_Layer: 0 65 | m_Name: Bord (3) 66 | m_TagString: Untagged 67 | m_Icon: {fileID: 0} 68 | m_NavMeshLayer: 0 69 | m_StaticEditorFlags: 0 70 | m_IsActive: 1 71 | --- !u!1 &1872367868043456 72 | GameObject: 73 | m_ObjectHideFlags: 0 74 | m_CorrespondingSourceObject: {fileID: 0} 75 | m_PrefabInternal: {fileID: 100100000} 76 | serializedVersion: 6 77 | m_Component: 78 | - component: {fileID: 4738313961880710} 79 | - component: {fileID: 33896680748480580} 80 | - component: {fileID: 23011519681391014} 81 | - component: {fileID: 65059584660200156} 82 | - component: {fileID: 65590949987065842} 83 | - component: {fileID: 65627854145120356} 84 | m_Layer: 0 85 | m_Name: Bord 86 | m_TagString: Untagged 87 | m_Icon: {fileID: 0} 88 | m_NavMeshLayer: 0 89 | m_StaticEditorFlags: 0 90 | m_IsActive: 1 91 | --- !u!1 &1950511125725858 92 | GameObject: 93 | m_ObjectHideFlags: 0 94 | m_CorrespondingSourceObject: {fileID: 0} 95 | m_PrefabInternal: {fileID: 100100000} 96 | serializedVersion: 6 97 | m_Component: 98 | - component: {fileID: 4752335114122484} 99 | - component: {fileID: 33462836363037428} 100 | - component: {fileID: 23458528837225990} 101 | - component: {fileID: 65076807166802294} 102 | - component: {fileID: 65114910231564214} 103 | m_Layer: 0 104 | m_Name: Bord (1) 105 | m_TagString: Untagged 106 | m_Icon: {fileID: 0} 107 | m_NavMeshLayer: 0 108 | m_StaticEditorFlags: 0 109 | m_IsActive: 1 110 | --- !u!4 &4284712273699304 111 | Transform: 112 | m_ObjectHideFlags: 1 113 | m_CorrespondingSourceObject: {fileID: 0} 114 | m_PrefabInternal: {fileID: 100100000} 115 | m_GameObject: {fileID: 1010506836010290} 116 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 117 | m_LocalPosition: {x: 0, y: 0, z: 0} 118 | m_LocalScale: {x: 2, y: 1, z: 2} 119 | m_Children: 120 | - {fileID: 4738313961880710} 121 | - {fileID: 4752335114122484} 122 | - {fileID: 4573927177739748} 123 | - {fileID: 4615528866575254} 124 | m_Father: {fileID: 0} 125 | m_RootOrder: 0 126 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 127 | --- !u!4 &4573927177739748 128 | Transform: 129 | m_ObjectHideFlags: 1 130 | m_CorrespondingSourceObject: {fileID: 0} 131 | m_PrefabInternal: {fileID: 100100000} 132 | m_GameObject: {fileID: 1010340096941446} 133 | m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} 134 | m_LocalPosition: {x: -0.02, y: 0, z: -5.08} 135 | m_LocalScale: {x: 10.4656, y: 1, z: 0.32958338} 136 | m_Children: [] 137 | m_Father: {fileID: 4284712273699304} 138 | m_RootOrder: 2 139 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 140 | --- !u!4 &4615528866575254 141 | Transform: 142 | m_ObjectHideFlags: 1 143 | m_CorrespondingSourceObject: {fileID: 0} 144 | m_PrefabInternal: {fileID: 100100000} 145 | m_GameObject: {fileID: 1665137963937560} 146 | m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} 147 | m_LocalPosition: {x: -0.02, y: 0, z: 4.834} 148 | m_LocalScale: {x: 10.4656, y: 1, z: 0.329585} 149 | m_Children: [] 150 | m_Father: {fileID: 4284712273699304} 151 | m_RootOrder: 3 152 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 153 | --- !u!4 &4738313961880710 154 | Transform: 155 | m_ObjectHideFlags: 1 156 | m_CorrespondingSourceObject: {fileID: 0} 157 | m_PrefabInternal: {fileID: 100100000} 158 | m_GameObject: {fileID: 1872367868043456} 159 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 160 | m_LocalPosition: {x: -5.13, y: 0, z: 0} 161 | m_LocalScale: {x: 0.37416, y: 1, z: 9.9901} 162 | m_Children: [] 163 | m_Father: {fileID: 4284712273699304} 164 | m_RootOrder: 0 165 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 166 | --- !u!4 &4752335114122484 167 | Transform: 168 | m_ObjectHideFlags: 1 169 | m_CorrespondingSourceObject: {fileID: 0} 170 | m_PrefabInternal: {fileID: 100100000} 171 | m_GameObject: {fileID: 1950511125725858} 172 | m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} 173 | m_LocalPosition: {x: 5.07, y: 0, z: 0} 174 | m_LocalScale: {x: 0.37416, y: 1, z: 9.9901} 175 | m_Children: [] 176 | m_Father: {fileID: 4284712273699304} 177 | m_RootOrder: 1 178 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 179 | --- !u!23 &23011519681391014 180 | MeshRenderer: 181 | m_ObjectHideFlags: 1 182 | m_CorrespondingSourceObject: {fileID: 0} 183 | m_PrefabInternal: {fileID: 100100000} 184 | m_GameObject: {fileID: 1872367868043456} 185 | m_Enabled: 1 186 | m_CastShadows: 1 187 | m_ReceiveShadows: 1 188 | m_DynamicOccludee: 1 189 | m_MotionVectors: 1 190 | m_LightProbeUsage: 1 191 | m_ReflectionProbeUsage: 1 192 | m_RenderingLayerMask: 4294967295 193 | m_Materials: 194 | - {fileID: 2100000, guid: ab2a7968eac24a4468126b30e7c9293b, type: 2} 195 | m_StaticBatchInfo: 196 | firstSubMesh: 0 197 | subMeshCount: 0 198 | m_StaticBatchRoot: {fileID: 0} 199 | m_ProbeAnchor: {fileID: 0} 200 | m_LightProbeVolumeOverride: {fileID: 0} 201 | m_ScaleInLightmap: 1 202 | m_PreserveUVs: 0 203 | m_IgnoreNormalsForChartDetection: 0 204 | m_ImportantGI: 0 205 | m_StitchLightmapSeams: 0 206 | m_SelectedEditorRenderState: 3 207 | m_MinimumChartSize: 4 208 | m_AutoUVMaxDistance: 0.5 209 | m_AutoUVMaxAngle: 89 210 | m_LightmapParameters: {fileID: 0} 211 | m_SortingLayerID: 0 212 | m_SortingLayer: 0 213 | m_SortingOrder: 0 214 | --- !u!23 &23038515933329936 215 | MeshRenderer: 216 | m_ObjectHideFlags: 1 217 | m_CorrespondingSourceObject: {fileID: 0} 218 | m_PrefabInternal: {fileID: 100100000} 219 | m_GameObject: {fileID: 1010506836010290} 220 | m_Enabled: 1 221 | m_CastShadows: 1 222 | m_ReceiveShadows: 1 223 | m_DynamicOccludee: 1 224 | m_MotionVectors: 1 225 | m_LightProbeUsage: 1 226 | m_ReflectionProbeUsage: 1 227 | m_RenderingLayerMask: 4294967295 228 | m_Materials: 229 | - {fileID: 2100000, guid: ab2a7968eac24a4468126b30e7c9293b, type: 2} 230 | m_StaticBatchInfo: 231 | firstSubMesh: 0 232 | subMeshCount: 0 233 | m_StaticBatchRoot: {fileID: 0} 234 | m_ProbeAnchor: {fileID: 0} 235 | m_LightProbeVolumeOverride: {fileID: 0} 236 | m_ScaleInLightmap: 1 237 | m_PreserveUVs: 0 238 | m_IgnoreNormalsForChartDetection: 0 239 | m_ImportantGI: 0 240 | m_StitchLightmapSeams: 0 241 | m_SelectedEditorRenderState: 3 242 | m_MinimumChartSize: 4 243 | m_AutoUVMaxDistance: 0.5 244 | m_AutoUVMaxAngle: 89 245 | m_LightmapParameters: {fileID: 0} 246 | m_SortingLayerID: 0 247 | m_SortingLayer: 0 248 | m_SortingOrder: 0 249 | --- !u!23 &23458528837225990 250 | MeshRenderer: 251 | m_ObjectHideFlags: 1 252 | m_CorrespondingSourceObject: {fileID: 0} 253 | m_PrefabInternal: {fileID: 100100000} 254 | m_GameObject: {fileID: 1950511125725858} 255 | m_Enabled: 1 256 | m_CastShadows: 1 257 | m_ReceiveShadows: 1 258 | m_DynamicOccludee: 1 259 | m_MotionVectors: 1 260 | m_LightProbeUsage: 1 261 | m_ReflectionProbeUsage: 1 262 | m_RenderingLayerMask: 4294967295 263 | m_Materials: 264 | - {fileID: 2100000, guid: ab2a7968eac24a4468126b30e7c9293b, type: 2} 265 | m_StaticBatchInfo: 266 | firstSubMesh: 0 267 | subMeshCount: 0 268 | m_StaticBatchRoot: {fileID: 0} 269 | m_ProbeAnchor: {fileID: 0} 270 | m_LightProbeVolumeOverride: {fileID: 0} 271 | m_ScaleInLightmap: 1 272 | m_PreserveUVs: 0 273 | m_IgnoreNormalsForChartDetection: 0 274 | m_ImportantGI: 0 275 | m_StitchLightmapSeams: 0 276 | m_SelectedEditorRenderState: 3 277 | m_MinimumChartSize: 4 278 | m_AutoUVMaxDistance: 0.5 279 | m_AutoUVMaxAngle: 89 280 | m_LightmapParameters: {fileID: 0} 281 | m_SortingLayerID: 0 282 | m_SortingLayer: 0 283 | m_SortingOrder: 0 284 | --- !u!23 &23523361689677772 285 | MeshRenderer: 286 | m_ObjectHideFlags: 1 287 | m_CorrespondingSourceObject: {fileID: 0} 288 | m_PrefabInternal: {fileID: 100100000} 289 | m_GameObject: {fileID: 1665137963937560} 290 | m_Enabled: 1 291 | m_CastShadows: 1 292 | m_ReceiveShadows: 1 293 | m_DynamicOccludee: 1 294 | m_MotionVectors: 1 295 | m_LightProbeUsage: 1 296 | m_ReflectionProbeUsage: 1 297 | m_RenderingLayerMask: 4294967295 298 | m_Materials: 299 | - {fileID: 2100000, guid: ab2a7968eac24a4468126b30e7c9293b, type: 2} 300 | m_StaticBatchInfo: 301 | firstSubMesh: 0 302 | subMeshCount: 0 303 | m_StaticBatchRoot: {fileID: 0} 304 | m_ProbeAnchor: {fileID: 0} 305 | m_LightProbeVolumeOverride: {fileID: 0} 306 | m_ScaleInLightmap: 1 307 | m_PreserveUVs: 0 308 | m_IgnoreNormalsForChartDetection: 0 309 | m_ImportantGI: 0 310 | m_StitchLightmapSeams: 0 311 | m_SelectedEditorRenderState: 3 312 | m_MinimumChartSize: 4 313 | m_AutoUVMaxDistance: 0.5 314 | m_AutoUVMaxAngle: 89 315 | m_LightmapParameters: {fileID: 0} 316 | m_SortingLayerID: 0 317 | m_SortingLayer: 0 318 | m_SortingOrder: 0 319 | --- !u!23 &23774172063303014 320 | MeshRenderer: 321 | m_ObjectHideFlags: 1 322 | m_CorrespondingSourceObject: {fileID: 0} 323 | m_PrefabInternal: {fileID: 100100000} 324 | m_GameObject: {fileID: 1010340096941446} 325 | m_Enabled: 1 326 | m_CastShadows: 1 327 | m_ReceiveShadows: 1 328 | m_DynamicOccludee: 1 329 | m_MotionVectors: 1 330 | m_LightProbeUsage: 1 331 | m_ReflectionProbeUsage: 1 332 | m_RenderingLayerMask: 4294967295 333 | m_Materials: 334 | - {fileID: 2100000, guid: ab2a7968eac24a4468126b30e7c9293b, type: 2} 335 | m_StaticBatchInfo: 336 | firstSubMesh: 0 337 | subMeshCount: 0 338 | m_StaticBatchRoot: {fileID: 0} 339 | m_ProbeAnchor: {fileID: 0} 340 | m_LightProbeVolumeOverride: {fileID: 0} 341 | m_ScaleInLightmap: 1 342 | m_PreserveUVs: 0 343 | m_IgnoreNormalsForChartDetection: 0 344 | m_ImportantGI: 0 345 | m_StitchLightmapSeams: 0 346 | m_SelectedEditorRenderState: 3 347 | m_MinimumChartSize: 4 348 | m_AutoUVMaxDistance: 0.5 349 | m_AutoUVMaxAngle: 89 350 | m_LightmapParameters: {fileID: 0} 351 | m_SortingLayerID: 0 352 | m_SortingLayer: 0 353 | m_SortingOrder: 0 354 | --- !u!33 &33462836363037428 355 | MeshFilter: 356 | m_ObjectHideFlags: 1 357 | m_CorrespondingSourceObject: {fileID: 0} 358 | m_PrefabInternal: {fileID: 100100000} 359 | m_GameObject: {fileID: 1950511125725858} 360 | m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} 361 | --- !u!33 &33662256303880736 362 | MeshFilter: 363 | m_ObjectHideFlags: 1 364 | m_CorrespondingSourceObject: {fileID: 0} 365 | m_PrefabInternal: {fileID: 100100000} 366 | m_GameObject: {fileID: 1010340096941446} 367 | m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} 368 | --- !u!33 &33862078007593612 369 | MeshFilter: 370 | m_ObjectHideFlags: 1 371 | m_CorrespondingSourceObject: {fileID: 0} 372 | m_PrefabInternal: {fileID: 100100000} 373 | m_GameObject: {fileID: 1665137963937560} 374 | m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} 375 | --- !u!33 &33896680748480580 376 | MeshFilter: 377 | m_ObjectHideFlags: 1 378 | m_CorrespondingSourceObject: {fileID: 0} 379 | m_PrefabInternal: {fileID: 100100000} 380 | m_GameObject: {fileID: 1872367868043456} 381 | m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} 382 | --- !u!33 &33929017365551490 383 | MeshFilter: 384 | m_ObjectHideFlags: 1 385 | m_CorrespondingSourceObject: {fileID: 0} 386 | m_PrefabInternal: {fileID: 100100000} 387 | m_GameObject: {fileID: 1010506836010290} 388 | m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} 389 | --- !u!64 &64689253414403800 390 | MeshCollider: 391 | m_ObjectHideFlags: 1 392 | m_CorrespondingSourceObject: {fileID: 0} 393 | m_PrefabInternal: {fileID: 100100000} 394 | m_GameObject: {fileID: 1010506836010290} 395 | m_Material: {fileID: 0} 396 | m_IsTrigger: 0 397 | m_Enabled: 1 398 | serializedVersion: 3 399 | m_Convex: 0 400 | m_CookingOptions: 14 401 | m_SkinWidth: 0.01 402 | m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} 403 | --- !u!65 &65059584660200156 404 | BoxCollider: 405 | m_ObjectHideFlags: 1 406 | m_CorrespondingSourceObject: {fileID: 0} 407 | m_PrefabInternal: {fileID: 100100000} 408 | m_GameObject: {fileID: 1872367868043456} 409 | m_Material: {fileID: 0} 410 | m_IsTrigger: 0 411 | m_Enabled: 1 412 | serializedVersion: 2 413 | m_Size: {x: 1, y: 1, z: 1} 414 | m_Center: {x: 0, y: 0, z: 0} 415 | --- !u!65 &65076807166802294 416 | BoxCollider: 417 | m_ObjectHideFlags: 1 418 | m_CorrespondingSourceObject: {fileID: 0} 419 | m_PrefabInternal: {fileID: 100100000} 420 | m_GameObject: {fileID: 1950511125725858} 421 | m_Material: {fileID: 0} 422 | m_IsTrigger: 0 423 | m_Enabled: 1 424 | serializedVersion: 2 425 | m_Size: {x: 1, y: 1, z: 1} 426 | m_Center: {x: 0, y: 0, z: 0} 427 | --- !u!65 &65087800184519950 428 | BoxCollider: 429 | m_ObjectHideFlags: 1 430 | m_CorrespondingSourceObject: {fileID: 0} 431 | m_PrefabInternal: {fileID: 100100000} 432 | m_GameObject: {fileID: 1010340096941446} 433 | m_Material: {fileID: 0} 434 | m_IsTrigger: 0 435 | m_Enabled: 1 436 | serializedVersion: 2 437 | m_Size: {x: 1, y: 1, z: 1} 438 | m_Center: {x: 0, y: 0, z: 0} 439 | --- !u!65 &65114910231564214 440 | BoxCollider: 441 | m_ObjectHideFlags: 1 442 | m_CorrespondingSourceObject: {fileID: 0} 443 | m_PrefabInternal: {fileID: 100100000} 444 | m_GameObject: {fileID: 1950511125725858} 445 | m_Material: {fileID: 0} 446 | m_IsTrigger: 0 447 | m_Enabled: 1 448 | serializedVersion: 2 449 | m_Size: {x: 1.0000001, y: 1, z: 1} 450 | m_Center: {x: 0, y: 0, z: 0} 451 | --- !u!65 &65590949987065842 452 | BoxCollider: 453 | m_ObjectHideFlags: 1 454 | m_CorrespondingSourceObject: {fileID: 0} 455 | m_PrefabInternal: {fileID: 100100000} 456 | m_GameObject: {fileID: 1872367868043456} 457 | m_Material: {fileID: 0} 458 | m_IsTrigger: 0 459 | m_Enabled: 1 460 | serializedVersion: 2 461 | m_Size: {x: 1.0000001, y: 1, z: 1} 462 | m_Center: {x: 0, y: 0, z: 0} 463 | --- !u!65 &65627854145120356 464 | BoxCollider: 465 | m_ObjectHideFlags: 1 466 | m_CorrespondingSourceObject: {fileID: 0} 467 | m_PrefabInternal: {fileID: 100100000} 468 | m_GameObject: {fileID: 1872367868043456} 469 | m_Material: {fileID: 0} 470 | m_IsTrigger: 0 471 | m_Enabled: 1 472 | serializedVersion: 2 473 | m_Size: {x: 1.0000001, y: 1, z: 1} 474 | m_Center: {x: 0, y: 0, z: 0} 475 | --- !u!65 &65631375037955232 476 | BoxCollider: 477 | m_ObjectHideFlags: 1 478 | m_CorrespondingSourceObject: {fileID: 0} 479 | m_PrefabInternal: {fileID: 100100000} 480 | m_GameObject: {fileID: 1665137963937560} 481 | m_Material: {fileID: 0} 482 | m_IsTrigger: 0 483 | m_Enabled: 1 484 | serializedVersion: 2 485 | m_Size: {x: 1, y: 1, z: 1} 486 | m_Center: {x: 0, y: 0, z: 0} 487 | --- !u!65 &65787851039163106 488 | BoxCollider: 489 | m_ObjectHideFlags: 1 490 | m_CorrespondingSourceObject: {fileID: 0} 491 | m_PrefabInternal: {fileID: 100100000} 492 | m_GameObject: {fileID: 1010340096941446} 493 | m_Material: {fileID: 0} 494 | m_IsTrigger: 0 495 | m_Enabled: 1 496 | serializedVersion: 2 497 | m_Size: {x: 1, y: 1, z: 1} 498 | m_Center: {x: 0, y: 0, z: 0} 499 | --- !u!65 &65803275033776586 500 | BoxCollider: 501 | m_ObjectHideFlags: 1 502 | m_CorrespondingSourceObject: {fileID: 0} 503 | m_PrefabInternal: {fileID: 100100000} 504 | m_GameObject: {fileID: 1665137963937560} 505 | m_Material: {fileID: 0} 506 | m_IsTrigger: 0 507 | m_Enabled: 1 508 | serializedVersion: 2 509 | m_Size: {x: 1, y: 1, z: 1} 510 | m_Center: {x: 0, y: 0, z: 0} 511 | --- !u!65 &65805571091712842 512 | BoxCollider: 513 | m_ObjectHideFlags: 1 514 | m_CorrespondingSourceObject: {fileID: 0} 515 | m_PrefabInternal: {fileID: 100100000} 516 | m_GameObject: {fileID: 1010506836010290} 517 | m_Material: {fileID: 0} 518 | m_IsTrigger: 0 519 | m_Enabled: 1 520 | serializedVersion: 2 521 | m_Size: {x: 10, y: 2.220446e-16, z: 10} 522 | m_Center: {x: 0, y: 0, z: 0} 523 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Prefabs/NetPlayer.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1001 &100100000 4 | Prefab: 5 | m_ObjectHideFlags: 1 6 | serializedVersion: 2 7 | m_Modification: 8 | m_TransformParent: {fileID: 0} 9 | m_Modifications: [] 10 | m_RemovedComponents: [] 11 | m_SourcePrefab: {fileID: 0} 12 | m_RootGameObject: {fileID: 1907576282027438} 13 | m_IsPrefabAsset: 1 14 | --- !u!1 &1907576282027438 15 | GameObject: 16 | m_ObjectHideFlags: 0 17 | m_CorrespondingSourceObject: {fileID: 0} 18 | m_PrefabInternal: {fileID: 100100000} 19 | serializedVersion: 6 20 | m_Component: 21 | - component: {fileID: 4322976432850648} 22 | - component: {fileID: 33329529089019516} 23 | - component: {fileID: 23544497273986068} 24 | - component: {fileID: 65867865545197592} 25 | - component: {fileID: 54098693686471628} 26 | - component: {fileID: 114598850161925216} 27 | m_Layer: 0 28 | m_Name: NetPlayer 29 | m_TagString: Untagged 30 | m_Icon: {fileID: 0} 31 | m_NavMeshLayer: 0 32 | m_StaticEditorFlags: 0 33 | m_IsActive: 1 34 | --- !u!4 &4322976432850648 35 | Transform: 36 | m_ObjectHideFlags: 1 37 | m_CorrespondingSourceObject: {fileID: 0} 38 | m_PrefabInternal: {fileID: 100100000} 39 | m_GameObject: {fileID: 1907576282027438} 40 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 41 | m_LocalPosition: {x: 0.27323237, y: 2.47, z: 1.9536208} 42 | m_LocalScale: {x: 1, y: 1, z: 1} 43 | m_Children: [] 44 | m_Father: {fileID: 0} 45 | m_RootOrder: 0 46 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 47 | --- !u!23 &23544497273986068 48 | MeshRenderer: 49 | m_ObjectHideFlags: 1 50 | m_CorrespondingSourceObject: {fileID: 0} 51 | m_PrefabInternal: {fileID: 100100000} 52 | m_GameObject: {fileID: 1907576282027438} 53 | m_Enabled: 1 54 | m_CastShadows: 1 55 | m_ReceiveShadows: 1 56 | m_DynamicOccludee: 1 57 | m_MotionVectors: 1 58 | m_LightProbeUsage: 1 59 | m_ReflectionProbeUsage: 1 60 | m_RenderingLayerMask: 4294967295 61 | m_Materials: 62 | - {fileID: 2100000, guid: e6bbc5330ae4aa749901f0d8e039adab, type: 2} 63 | m_StaticBatchInfo: 64 | firstSubMesh: 0 65 | subMeshCount: 0 66 | m_StaticBatchRoot: {fileID: 0} 67 | m_ProbeAnchor: {fileID: 0} 68 | m_LightProbeVolumeOverride: {fileID: 0} 69 | m_ScaleInLightmap: 1 70 | m_PreserveUVs: 0 71 | m_IgnoreNormalsForChartDetection: 0 72 | m_ImportantGI: 0 73 | m_StitchLightmapSeams: 0 74 | m_SelectedEditorRenderState: 3 75 | m_MinimumChartSize: 4 76 | m_AutoUVMaxDistance: 0.5 77 | m_AutoUVMaxAngle: 89 78 | m_LightmapParameters: {fileID: 0} 79 | m_SortingLayerID: 0 80 | m_SortingLayer: 0 81 | m_SortingOrder: 0 82 | --- !u!33 &33329529089019516 83 | MeshFilter: 84 | m_ObjectHideFlags: 1 85 | m_CorrespondingSourceObject: {fileID: 0} 86 | m_PrefabInternal: {fileID: 100100000} 87 | m_GameObject: {fileID: 1907576282027438} 88 | m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} 89 | --- !u!54 &54098693686471628 90 | Rigidbody: 91 | m_ObjectHideFlags: 1 92 | m_CorrespondingSourceObject: {fileID: 0} 93 | m_PrefabInternal: {fileID: 100100000} 94 | m_GameObject: {fileID: 1907576282027438} 95 | serializedVersion: 2 96 | m_Mass: 1 97 | m_Drag: 1 98 | m_AngularDrag: 0.05 99 | m_UseGravity: 1 100 | m_IsKinematic: 0 101 | m_Interpolate: 0 102 | m_Constraints: 112 103 | m_CollisionDetection: 0 104 | --- !u!65 &65867865545197592 105 | BoxCollider: 106 | m_ObjectHideFlags: 1 107 | m_CorrespondingSourceObject: {fileID: 0} 108 | m_PrefabInternal: {fileID: 100100000} 109 | m_GameObject: {fileID: 1907576282027438} 110 | m_Material: {fileID: 0} 111 | m_IsTrigger: 0 112 | m_Enabled: 1 113 | serializedVersion: 2 114 | m_Size: {x: 1, y: 1, z: 1} 115 | m_Center: {x: 0, y: 0, z: 0} 116 | --- !u!114 &114598850161925216 117 | MonoBehaviour: 118 | m_ObjectHideFlags: 1 119 | m_CorrespondingSourceObject: {fileID: 0} 120 | m_PrefabInternal: {fileID: 100100000} 121 | m_GameObject: {fileID: 1907576282027438} 122 | m_Enabled: 1 123 | m_EditorHideFlags: 0 124 | m_Script: {fileID: 11500000, guid: f2cc146edb8065b408f3ab3d31f1577b, type: 3} 125 | m_Name: 126 | m_EditorClassIdentifier: 127 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Prefabs/Player.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1001 &100100000 4 | Prefab: 5 | m_ObjectHideFlags: 1 6 | serializedVersion: 2 7 | m_Modification: 8 | m_TransformParent: {fileID: 0} 9 | m_Modifications: [] 10 | m_RemovedComponents: [] 11 | m_SourcePrefab: {fileID: 0} 12 | m_RootGameObject: {fileID: 1414922606614572} 13 | m_IsPrefabAsset: 1 14 | --- !u!1 &1414922606614572 15 | GameObject: 16 | m_ObjectHideFlags: 0 17 | m_CorrespondingSourceObject: {fileID: 0} 18 | m_PrefabInternal: {fileID: 100100000} 19 | serializedVersion: 6 20 | m_Component: 21 | - component: {fileID: 4162407942446692} 22 | - component: {fileID: 33732225074929884} 23 | - component: {fileID: 23026479571434842} 24 | - component: {fileID: 65628339607062204} 25 | - component: {fileID: 114350425359523364} 26 | - component: {fileID: 54463104736367640} 27 | m_Layer: 0 28 | m_Name: Player 29 | m_TagString: Untagged 30 | m_Icon: {fileID: 0} 31 | m_NavMeshLayer: 0 32 | m_StaticEditorFlags: 0 33 | m_IsActive: 1 34 | --- !u!4 &4162407942446692 35 | Transform: 36 | m_ObjectHideFlags: 1 37 | m_CorrespondingSourceObject: {fileID: 0} 38 | m_PrefabInternal: {fileID: 100100000} 39 | m_GameObject: {fileID: 1414922606614572} 40 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 41 | m_LocalPosition: {x: 0.27323237, y: 0.58, z: 1.9536208} 42 | m_LocalScale: {x: 1, y: 1, z: 1} 43 | m_Children: [] 44 | m_Father: {fileID: 0} 45 | m_RootOrder: 0 46 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 47 | --- !u!23 &23026479571434842 48 | MeshRenderer: 49 | m_ObjectHideFlags: 1 50 | m_CorrespondingSourceObject: {fileID: 0} 51 | m_PrefabInternal: {fileID: 100100000} 52 | m_GameObject: {fileID: 1414922606614572} 53 | m_Enabled: 1 54 | m_CastShadows: 1 55 | m_ReceiveShadows: 1 56 | m_DynamicOccludee: 1 57 | m_MotionVectors: 1 58 | m_LightProbeUsage: 1 59 | m_ReflectionProbeUsage: 1 60 | m_RenderingLayerMask: 4294967295 61 | m_Materials: 62 | - {fileID: 2100000, guid: e6bbc5330ae4aa749901f0d8e039adab, type: 2} 63 | m_StaticBatchInfo: 64 | firstSubMesh: 0 65 | subMeshCount: 0 66 | m_StaticBatchRoot: {fileID: 0} 67 | m_ProbeAnchor: {fileID: 0} 68 | m_LightProbeVolumeOverride: {fileID: 0} 69 | m_ScaleInLightmap: 1 70 | m_PreserveUVs: 0 71 | m_IgnoreNormalsForChartDetection: 0 72 | m_ImportantGI: 0 73 | m_StitchLightmapSeams: 0 74 | m_SelectedEditorRenderState: 3 75 | m_MinimumChartSize: 4 76 | m_AutoUVMaxDistance: 0.5 77 | m_AutoUVMaxAngle: 89 78 | m_LightmapParameters: {fileID: 0} 79 | m_SortingLayerID: 0 80 | m_SortingLayer: 0 81 | m_SortingOrder: 0 82 | --- !u!33 &33732225074929884 83 | MeshFilter: 84 | m_ObjectHideFlags: 1 85 | m_CorrespondingSourceObject: {fileID: 0} 86 | m_PrefabInternal: {fileID: 100100000} 87 | m_GameObject: {fileID: 1414922606614572} 88 | m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} 89 | --- !u!54 &54463104736367640 90 | Rigidbody: 91 | m_ObjectHideFlags: 1 92 | m_CorrespondingSourceObject: {fileID: 0} 93 | m_PrefabInternal: {fileID: 100100000} 94 | m_GameObject: {fileID: 1414922606614572} 95 | serializedVersion: 2 96 | m_Mass: 1 97 | m_Drag: 20 98 | m_AngularDrag: 0.05 99 | m_UseGravity: 1 100 | m_IsKinematic: 0 101 | m_Interpolate: 0 102 | m_Constraints: 112 103 | m_CollisionDetection: 0 104 | --- !u!65 &65628339607062204 105 | BoxCollider: 106 | m_ObjectHideFlags: 1 107 | m_CorrespondingSourceObject: {fileID: 0} 108 | m_PrefabInternal: {fileID: 100100000} 109 | m_GameObject: {fileID: 1414922606614572} 110 | m_Material: {fileID: 0} 111 | m_IsTrigger: 0 112 | m_Enabled: 1 113 | serializedVersion: 2 114 | m_Size: {x: 1, y: 1, z: 1} 115 | m_Center: {x: 0, y: 0, z: 0} 116 | --- !u!114 &114350425359523364 117 | MonoBehaviour: 118 | m_ObjectHideFlags: 1 119 | m_CorrespondingSourceObject: {fileID: 0} 120 | m_PrefabInternal: {fileID: 100100000} 121 | m_GameObject: {fileID: 1414922606614572} 122 | m_Enabled: 1 123 | m_EditorHideFlags: 0 124 | m_Script: {fileID: 11500000, guid: f2cc146edb8065b408f3ab3d31f1577b, type: 3} 125 | m_Name: 126 | m_EditorClassIdentifier: 127 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scenes/SampleScene.unity: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!29 &1 4 | OcclusionCullingSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_OcclusionBakeSettings: 8 | smallestOccluder: 5 9 | smallestHole: 0.25 10 | backfaceThreshold: 100 11 | m_SceneGUID: 00000000000000000000000000000000 12 | m_OcclusionCullingData: {fileID: 0} 13 | --- !u!104 &2 14 | RenderSettings: 15 | m_ObjectHideFlags: 0 16 | serializedVersion: 9 17 | m_Fog: 0 18 | m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} 19 | m_FogMode: 3 20 | m_FogDensity: 0.01 21 | m_LinearFogStart: 0 22 | m_LinearFogEnd: 300 23 | m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} 24 | m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} 25 | m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} 26 | m_AmbientIntensity: 1 27 | m_AmbientMode: 0 28 | m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} 29 | m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} 30 | m_HaloStrength: 0.5 31 | m_FlareStrength: 1 32 | m_FlareFadeSpeed: 3 33 | m_HaloTexture: {fileID: 0} 34 | m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} 35 | m_DefaultReflectionMode: 0 36 | m_DefaultReflectionResolution: 128 37 | m_ReflectionBounces: 1 38 | m_ReflectionIntensity: 1 39 | m_CustomReflection: {fileID: 0} 40 | m_Sun: {fileID: 0} 41 | m_IndirectSpecularColor: {r: 0.44657844, g: 0.49641222, b: 0.57481694, a: 1} 42 | m_UseRadianceAmbientProbe: 0 43 | --- !u!157 &3 44 | LightmapSettings: 45 | m_ObjectHideFlags: 0 46 | serializedVersion: 11 47 | m_GIWorkflowMode: 0 48 | m_GISettings: 49 | serializedVersion: 2 50 | m_BounceScale: 1 51 | m_IndirectOutputScale: 1 52 | m_AlbedoBoost: 1 53 | m_TemporalCoherenceThreshold: 1 54 | m_EnvironmentLightingMode: 0 55 | m_EnableBakedLightmaps: 1 56 | m_EnableRealtimeLightmaps: 0 57 | m_LightmapEditorSettings: 58 | serializedVersion: 10 59 | m_Resolution: 2 60 | m_BakeResolution: 10 61 | m_AtlasSize: 512 62 | m_AO: 0 63 | m_AOMaxDistance: 1 64 | m_CompAOExponent: 1 65 | m_CompAOExponentDirect: 0 66 | m_Padding: 2 67 | m_LightmapParameters: {fileID: 0} 68 | m_LightmapsBakeMode: 1 69 | m_TextureCompression: 1 70 | m_FinalGather: 0 71 | m_FinalGatherFiltering: 1 72 | m_FinalGatherRayCount: 256 73 | m_ReflectionCompression: 2 74 | m_MixedBakeMode: 2 75 | m_BakeBackend: 1 76 | m_PVRSampling: 1 77 | m_PVRDirectSampleCount: 32 78 | m_PVRSampleCount: 256 79 | m_PVRBounces: 2 80 | m_PVRFilterTypeDirect: 0 81 | m_PVRFilterTypeIndirect: 0 82 | m_PVRFilterTypeAO: 0 83 | m_PVRFilteringMode: 1 84 | m_PVRCulling: 1 85 | m_PVRFilteringGaussRadiusDirect: 1 86 | m_PVRFilteringGaussRadiusIndirect: 5 87 | m_PVRFilteringGaussRadiusAO: 2 88 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5 89 | m_PVRFilteringAtrousPositionSigmaIndirect: 2 90 | m_PVRFilteringAtrousPositionSigmaAO: 1 91 | m_ShowResolutionOverlay: 1 92 | m_LightingDataAsset: {fileID: 0} 93 | m_UseShadowmask: 1 94 | --- !u!196 &4 95 | NavMeshSettings: 96 | serializedVersion: 2 97 | m_ObjectHideFlags: 0 98 | m_BuildSettings: 99 | serializedVersion: 2 100 | agentTypeID: 0 101 | agentRadius: 0.5 102 | agentHeight: 2 103 | agentSlope: 45 104 | agentClimb: 0.4 105 | ledgeDropHeight: 0 106 | maxJumpAcrossDistance: 0 107 | minRegionArea: 2 108 | manualCellSize: 0 109 | cellSize: 0.16666667 110 | manualTileSize: 0 111 | tileSize: 256 112 | accuratePlacement: 0 113 | debug: 114 | m_Flags: 0 115 | m_NavMeshData: {fileID: 0} 116 | --- !u!1 &170076733 117 | GameObject: 118 | m_ObjectHideFlags: 0 119 | m_CorrespondingSourceObject: {fileID: 0} 120 | m_PrefabInternal: {fileID: 0} 121 | serializedVersion: 6 122 | m_Component: 123 | - component: {fileID: 170076735} 124 | - component: {fileID: 170076734} 125 | m_Layer: 0 126 | m_Name: Directional Light 127 | m_TagString: Untagged 128 | m_Icon: {fileID: 0} 129 | m_NavMeshLayer: 0 130 | m_StaticEditorFlags: 0 131 | m_IsActive: 1 132 | --- !u!108 &170076734 133 | Light: 134 | m_ObjectHideFlags: 0 135 | m_CorrespondingSourceObject: {fileID: 0} 136 | m_PrefabInternal: {fileID: 0} 137 | m_GameObject: {fileID: 170076733} 138 | m_Enabled: 1 139 | serializedVersion: 8 140 | m_Type: 1 141 | m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} 142 | m_Intensity: 1 143 | m_Range: 10 144 | m_SpotAngle: 30 145 | m_CookieSize: 10 146 | m_Shadows: 147 | m_Type: 2 148 | m_Resolution: -1 149 | m_CustomResolution: -1 150 | m_Strength: 1 151 | m_Bias: 0.05 152 | m_NormalBias: 0.4 153 | m_NearPlane: 0.2 154 | m_Cookie: {fileID: 0} 155 | m_DrawHalo: 0 156 | m_Flare: {fileID: 0} 157 | m_RenderMode: 0 158 | m_CullingMask: 159 | serializedVersion: 2 160 | m_Bits: 4294967295 161 | m_Lightmapping: 1 162 | m_LightShadowCasterMode: 0 163 | m_AreaSize: {x: 1, y: 1} 164 | m_BounceIntensity: 1 165 | m_ColorTemperature: 6570 166 | m_UseColorTemperature: 0 167 | m_ShadowRadius: 0 168 | m_ShadowAngle: 0 169 | --- !u!4 &170076735 170 | Transform: 171 | m_ObjectHideFlags: 0 172 | m_CorrespondingSourceObject: {fileID: 0} 173 | m_PrefabInternal: {fileID: 0} 174 | m_GameObject: {fileID: 170076733} 175 | m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} 176 | m_LocalPosition: {x: 0, y: 3, z: 0} 177 | m_LocalScale: {x: 1, y: 1, z: 1} 178 | m_Children: [] 179 | m_Father: {fileID: 0} 180 | m_RootOrder: 1 181 | m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} 182 | --- !u!1 &534669902 183 | GameObject: 184 | m_ObjectHideFlags: 0 185 | m_CorrespondingSourceObject: {fileID: 0} 186 | m_PrefabInternal: {fileID: 0} 187 | serializedVersion: 6 188 | m_Component: 189 | - component: {fileID: 534669905} 190 | - component: {fileID: 534669904} 191 | - component: {fileID: 534669903} 192 | m_Layer: 0 193 | m_Name: Main Camera 194 | m_TagString: Untagged 195 | m_Icon: {fileID: 0} 196 | m_NavMeshLayer: 0 197 | m_StaticEditorFlags: 0 198 | m_IsActive: 1 199 | --- !u!81 &534669903 200 | AudioListener: 201 | m_ObjectHideFlags: 0 202 | m_CorrespondingSourceObject: {fileID: 0} 203 | m_PrefabInternal: {fileID: 0} 204 | m_GameObject: {fileID: 534669902} 205 | m_Enabled: 1 206 | --- !u!20 &534669904 207 | Camera: 208 | m_ObjectHideFlags: 0 209 | m_CorrespondingSourceObject: {fileID: 0} 210 | m_PrefabInternal: {fileID: 0} 211 | m_GameObject: {fileID: 534669902} 212 | m_Enabled: 1 213 | serializedVersion: 2 214 | m_ClearFlags: 1 215 | m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} 216 | m_projectionMatrixMode: 1 217 | m_SensorSize: {x: 36, y: 24} 218 | m_LensShift: {x: 0, y: 0} 219 | m_FocalLength: 50 220 | m_NormalizedViewPortRect: 221 | serializedVersion: 2 222 | x: 0 223 | y: 0 224 | width: 1 225 | height: 1 226 | near clip plane: 0.3 227 | far clip plane: 1000 228 | field of view: 60 229 | orthographic: 0 230 | orthographic size: 5 231 | m_Depth: -1 232 | m_CullingMask: 233 | serializedVersion: 2 234 | m_Bits: 4294967295 235 | m_RenderingPath: -1 236 | m_TargetTexture: {fileID: 0} 237 | m_TargetDisplay: 0 238 | m_TargetEye: 3 239 | m_HDR: 1 240 | m_AllowMSAA: 1 241 | m_AllowDynamicResolution: 0 242 | m_ForceIntoRT: 0 243 | m_OcclusionCulling: 1 244 | m_StereoConvergence: 10 245 | m_StereoSeparation: 0.022 246 | --- !u!4 &534669905 247 | Transform: 248 | m_ObjectHideFlags: 0 249 | m_CorrespondingSourceObject: {fileID: 0} 250 | m_PrefabInternal: {fileID: 0} 251 | m_GameObject: {fileID: 534669902} 252 | m_LocalRotation: {x: -0.31295317, y: 0.007690475, z: -0.0025340617, w: -0.9497341} 253 | m_LocalPosition: {x: -0.55480546, y: 8.812106, z: -14.104752} 254 | m_LocalScale: {x: 1, y: 1, z: 1} 255 | m_Children: [] 256 | m_Father: {fileID: 0} 257 | m_RootOrder: 0 258 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 259 | --- !u!1001 &682273211 260 | Prefab: 261 | m_ObjectHideFlags: 0 262 | serializedVersion: 2 263 | m_Modification: 264 | m_TransformParent: {fileID: 0} 265 | m_Modifications: 266 | - target: {fileID: 4322976432850648, guid: c732c2a27348837429ae048c52fc4ff5, type: 2} 267 | propertyPath: m_LocalPosition.x 268 | value: 0.27323237 269 | objectReference: {fileID: 0} 270 | - target: {fileID: 4322976432850648, guid: c732c2a27348837429ae048c52fc4ff5, type: 2} 271 | propertyPath: m_LocalPosition.y 272 | value: 2.47 273 | objectReference: {fileID: 0} 274 | - target: {fileID: 4322976432850648, guid: c732c2a27348837429ae048c52fc4ff5, type: 2} 275 | propertyPath: m_LocalPosition.z 276 | value: 1.9536208 277 | objectReference: {fileID: 0} 278 | - target: {fileID: 4322976432850648, guid: c732c2a27348837429ae048c52fc4ff5, type: 2} 279 | propertyPath: m_LocalRotation.x 280 | value: 0 281 | objectReference: {fileID: 0} 282 | - target: {fileID: 4322976432850648, guid: c732c2a27348837429ae048c52fc4ff5, type: 2} 283 | propertyPath: m_LocalRotation.y 284 | value: 0 285 | objectReference: {fileID: 0} 286 | - target: {fileID: 4322976432850648, guid: c732c2a27348837429ae048c52fc4ff5, type: 2} 287 | propertyPath: m_LocalRotation.z 288 | value: 0 289 | objectReference: {fileID: 0} 290 | - target: {fileID: 4322976432850648, guid: c732c2a27348837429ae048c52fc4ff5, type: 2} 291 | propertyPath: m_LocalRotation.w 292 | value: 1 293 | objectReference: {fileID: 0} 294 | - target: {fileID: 4322976432850648, guid: c732c2a27348837429ae048c52fc4ff5, type: 2} 295 | propertyPath: m_RootOrder 296 | value: 3 297 | objectReference: {fileID: 0} 298 | - target: {fileID: 1907576282027438, guid: c732c2a27348837429ae048c52fc4ff5, type: 2} 299 | propertyPath: m_Name 300 | value: Player 301 | objectReference: {fileID: 0} 302 | - target: {fileID: 54098693686471628, guid: c732c2a27348837429ae048c52fc4ff5, 303 | type: 2} 304 | propertyPath: m_Mass 305 | value: 1 306 | objectReference: {fileID: 0} 307 | - target: {fileID: 54098693686471628, guid: c732c2a27348837429ae048c52fc4ff5, 308 | type: 2} 309 | propertyPath: m_Drag 310 | value: 1 311 | objectReference: {fileID: 0} 312 | m_RemovedComponents: [] 313 | m_SourcePrefab: {fileID: 100100000, guid: c732c2a27348837429ae048c52fc4ff5, type: 2} 314 | m_IsPrefabAsset: 0 315 | --- !u!1001 &832715669 316 | Prefab: 317 | m_ObjectHideFlags: 0 318 | serializedVersion: 2 319 | m_Modification: 320 | m_TransformParent: {fileID: 0} 321 | m_Modifications: 322 | - target: {fileID: 4284712273699304, guid: 329a3e36b25332c4b9ace67af047f460, type: 2} 323 | propertyPath: m_LocalPosition.x 324 | value: 0 325 | objectReference: {fileID: 0} 326 | - target: {fileID: 4284712273699304, guid: 329a3e36b25332c4b9ace67af047f460, type: 2} 327 | propertyPath: m_LocalPosition.y 328 | value: 0 329 | objectReference: {fileID: 0} 330 | - target: {fileID: 4284712273699304, guid: 329a3e36b25332c4b9ace67af047f460, type: 2} 331 | propertyPath: m_LocalPosition.z 332 | value: 0 333 | objectReference: {fileID: 0} 334 | - target: {fileID: 4284712273699304, guid: 329a3e36b25332c4b9ace67af047f460, type: 2} 335 | propertyPath: m_LocalRotation.x 336 | value: 0 337 | objectReference: {fileID: 0} 338 | - target: {fileID: 4284712273699304, guid: 329a3e36b25332c4b9ace67af047f460, type: 2} 339 | propertyPath: m_LocalRotation.y 340 | value: 0 341 | objectReference: {fileID: 0} 342 | - target: {fileID: 4284712273699304, guid: 329a3e36b25332c4b9ace67af047f460, type: 2} 343 | propertyPath: m_LocalRotation.z 344 | value: 0 345 | objectReference: {fileID: 0} 346 | - target: {fileID: 4284712273699304, guid: 329a3e36b25332c4b9ace67af047f460, type: 2} 347 | propertyPath: m_LocalRotation.w 348 | value: 1 349 | objectReference: {fileID: 0} 350 | - target: {fileID: 4284712273699304, guid: 329a3e36b25332c4b9ace67af047f460, type: 2} 351 | propertyPath: m_RootOrder 352 | value: 2 353 | objectReference: {fileID: 0} 354 | m_RemovedComponents: [] 355 | m_SourcePrefab: {fileID: 100100000, guid: 329a3e36b25332c4b9ace67af047f460, type: 2} 356 | m_IsPrefabAsset: 0 357 | --- !u!1 &1234116709 stripped 358 | GameObject: 359 | m_CorrespondingSourceObject: {fileID: 1907576282027438, guid: c732c2a27348837429ae048c52fc4ff5, 360 | type: 2} 361 | m_PrefabInternal: {fileID: 682273211} 362 | --- !u!114 &1234116710 363 | MonoBehaviour: 364 | m_ObjectHideFlags: 0 365 | m_CorrespondingSourceObject: {fileID: 0} 366 | m_PrefabInternal: {fileID: 0} 367 | m_GameObject: {fileID: 1234116709} 368 | m_Enabled: 1 369 | m_EditorHideFlags: 0 370 | m_Script: {fileID: 11500000, guid: f2cc146edb8065b408f3ab3d31f1577b, type: 3} 371 | m_Name: 372 | m_EditorClassIdentifier: 373 | --- !u!1 &1828230971 374 | GameObject: 375 | m_ObjectHideFlags: 0 376 | m_CorrespondingSourceObject: {fileID: 0} 377 | m_PrefabInternal: {fileID: 0} 378 | serializedVersion: 6 379 | m_Component: 380 | - component: {fileID: 1828230973} 381 | - component: {fileID: 1828230972} 382 | m_Layer: 0 383 | m_Name: Network 384 | m_TagString: Untagged 385 | m_Icon: {fileID: 0} 386 | m_NavMeshLayer: 0 387 | m_StaticEditorFlags: 0 388 | m_IsActive: 1 389 | --- !u!114 &1828230972 390 | MonoBehaviour: 391 | m_ObjectHideFlags: 0 392 | m_CorrespondingSourceObject: {fileID: 0} 393 | m_PrefabInternal: {fileID: 0} 394 | m_GameObject: {fileID: 1828230971} 395 | m_Enabled: 1 396 | m_EditorHideFlags: 0 397 | m_Script: {fileID: 11500000, guid: bed6be86f8dc24d41b4a64911ff1e288, type: 3} 398 | m_Name: 399 | m_EditorClassIdentifier: 400 | player: {fileID: 1234116710} 401 | netPlayerPrefab: {fileID: 1907576282027438, guid: c732c2a27348837429ae048c52fc4ff5, 402 | type: 2} 403 | --- !u!4 &1828230973 404 | Transform: 405 | m_ObjectHideFlags: 0 406 | m_CorrespondingSourceObject: {fileID: 0} 407 | m_PrefabInternal: {fileID: 0} 408 | m_GameObject: {fileID: 1828230971} 409 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 410 | m_LocalPosition: {x: -0.582959, y: 7.234597, z: -11.971174} 411 | m_LocalScale: {x: 1, y: 1, z: 1} 412 | m_Children: [] 413 | m_Father: {fileID: 0} 414 | m_RootOrder: 4 415 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 416 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/LiteNetLib/INetEventListener.cs: -------------------------------------------------------------------------------- 1 | using LiteNetLib.Utils; 2 | 3 | namespace LiteNetLib 4 | { 5 | /// 6 | /// Type of message that you receive in OnNetworkReceiveUnconnected event 7 | /// 8 | public enum UnconnectedMessageType 9 | { 10 | Default, 11 | DiscoveryRequest, 12 | DiscoveryResponse 13 | } 14 | 15 | /// 16 | /// Disconnect reason that you receive in OnPeerDisconnected event 17 | /// 18 | public enum DisconnectReason 19 | { 20 | SocketReceiveError, 21 | ConnectionFailed, 22 | Timeout, 23 | SocketSendError, 24 | RemoteConnectionClose, 25 | DisconnectPeerCalled 26 | } 27 | 28 | /// 29 | /// Additional information about disconnection 30 | /// 31 | public struct DisconnectInfo 32 | { 33 | /// 34 | /// Additional info why peer disconnected 35 | /// 36 | public DisconnectReason Reason; 37 | 38 | /// 39 | /// Error code (if reason is SocketSendError or SocketReceiveError) 40 | /// 41 | public int SocketErrorCode; 42 | 43 | /// 44 | /// Additional data that can be accessed (only if reason is RemoteConnectionClose) 45 | /// 46 | public NetDataReader AdditionalData; 47 | } 48 | 49 | public interface INetEventListener 50 | { 51 | /// 52 | /// New remote peer connected to host, or client connected to remote host 53 | /// 54 | /// Connected peer object 55 | void OnPeerConnected(NetPeer peer); 56 | 57 | /// 58 | /// Peer disconnected 59 | /// 60 | /// disconnected peer 61 | /// additional info about reason, errorCode or data received with disconnect message 62 | void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo); 63 | 64 | /// 65 | /// Network error (on send or receive) 66 | /// 67 | /// From endPoint (can be null) 68 | /// Socket error code 69 | void OnNetworkError(NetEndPoint endPoint, int socketErrorCode); 70 | 71 | /// 72 | /// Received some data 73 | /// 74 | /// From peer 75 | /// DataReader containing all received data 76 | void OnNetworkReceive(NetPeer peer, NetDataReader reader); 77 | 78 | /// 79 | /// Received unconnected message 80 | /// 81 | /// From address (IP and Port) 82 | /// Message data 83 | /// Message type (simple, discovery request or responce) 84 | void OnNetworkReceiveUnconnected(NetEndPoint remoteEndPoint, NetDataReader reader, UnconnectedMessageType messageType); 85 | 86 | /// 87 | /// Latency information updated 88 | /// 89 | /// Peer with updated latency 90 | /// latency value in milliseconds 91 | void OnNetworkLatencyUpdate(NetPeer peer, int latency); 92 | } 93 | 94 | public class EventBasedNetListener : INetEventListener 95 | { 96 | public delegate void OnPeerConnected(NetPeer peer); 97 | public delegate void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo); 98 | public delegate void OnNetworkError(NetEndPoint endPoint, int socketErrorCode); 99 | public delegate void OnNetworkReceive(NetPeer peer, NetDataReader reader); 100 | public delegate void OnNetworkReceiveUnconnected(NetEndPoint remoteEndPoint, NetDataReader reader, UnconnectedMessageType messageType); 101 | public delegate void OnNetworkLatencyUpdate(NetPeer peer, int latency); 102 | 103 | public event OnPeerConnected PeerConnectedEvent; 104 | public event OnPeerDisconnected PeerDisconnectedEvent; 105 | public event OnNetworkError NetworkErrorEvent; 106 | public event OnNetworkReceive NetworkReceiveEvent; 107 | public event OnNetworkReceiveUnconnected NetworkReceiveUnconnectedEvent; 108 | public event OnNetworkLatencyUpdate NetworkLatencyUpdateEvent; 109 | 110 | void INetEventListener.OnPeerConnected(NetPeer peer) 111 | { 112 | if (PeerConnectedEvent != null) 113 | PeerConnectedEvent(peer); 114 | } 115 | 116 | void INetEventListener.OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo) 117 | { 118 | if (PeerDisconnectedEvent != null) 119 | PeerDisconnectedEvent(peer, disconnectInfo); 120 | } 121 | 122 | void INetEventListener.OnNetworkError(NetEndPoint endPoint, int socketErrorCode) 123 | { 124 | if (NetworkErrorEvent != null) 125 | NetworkErrorEvent(endPoint, socketErrorCode); 126 | } 127 | 128 | void INetEventListener.OnNetworkReceive(NetPeer peer, NetDataReader reader) 129 | { 130 | if (NetworkReceiveEvent != null) 131 | NetworkReceiveEvent(peer, reader); 132 | } 133 | 134 | void INetEventListener.OnNetworkReceiveUnconnected(NetEndPoint remoteEndPoint, NetDataReader reader, UnconnectedMessageType messageType) 135 | { 136 | if (NetworkReceiveUnconnectedEvent != null) 137 | NetworkReceiveUnconnectedEvent(remoteEndPoint, reader, messageType); 138 | } 139 | 140 | void INetEventListener.OnNetworkLatencyUpdate(NetPeer peer, int latency) 141 | { 142 | if (NetworkLatencyUpdateEvent != null) 143 | NetworkLatencyUpdateEvent(peer, latency); 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/LiteNetLib/NatPunchModule.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using LiteNetLib.Utils; 4 | 5 | //Some code parts taken from lidgren-network-gen3 6 | namespace LiteNetLib 7 | { 8 | public interface INatPunchListener 9 | { 10 | void OnNatIntroductionRequest(NetEndPoint localEndPoint, NetEndPoint remoteEndPoint, string token); 11 | void OnNatIntroductionSuccess(NetEndPoint targetEndPoint, string token); 12 | } 13 | 14 | public class EventBasedNatPunchListener : INatPunchListener 15 | { 16 | public delegate void OnNatIntroductionRequest(NetEndPoint localEndPoint, NetEndPoint remoteEndPoint, string token); 17 | public delegate void OnNatIntroductionSuccess(NetEndPoint targetEndPoint, string token); 18 | 19 | public event OnNatIntroductionRequest NatIntroductionRequest; 20 | public event OnNatIntroductionSuccess NatIntroductionSuccess; 21 | 22 | void INatPunchListener.OnNatIntroductionRequest(NetEndPoint localEndPoint, NetEndPoint remoteEndPoint, string token) 23 | { 24 | if(NatIntroductionRequest != null) 25 | NatIntroductionRequest(localEndPoint, remoteEndPoint, token); 26 | } 27 | 28 | void INatPunchListener.OnNatIntroductionSuccess(NetEndPoint targetEndPoint, string token) 29 | { 30 | if (NatIntroductionSuccess != null) 31 | NatIntroductionSuccess(targetEndPoint, token); 32 | } 33 | } 34 | 35 | /// 36 | /// Module for UDP NAT Hole punching operations. Can be accessed from NetManager 37 | /// 38 | public sealed class NatPunchModule 39 | { 40 | struct RequestEventData 41 | { 42 | public NetEndPoint LocalEndPoint; 43 | public NetEndPoint RemoteEndPoint; 44 | public string Token; 45 | } 46 | 47 | struct SuccessEventData 48 | { 49 | public NetEndPoint TargetEndPoint; 50 | public string Token; 51 | } 52 | 53 | private readonly NetManager _netBase; 54 | private readonly Queue _requestEvents; 55 | private readonly Queue _successEvents; 56 | private const byte HostByte = 1; 57 | private const byte ClientByte = 0; 58 | public const int MaxTokenLength = 256; 59 | 60 | private INatPunchListener _natPunchListener; 61 | 62 | internal NatPunchModule(NetManager netBase) 63 | { 64 | _netBase = netBase; 65 | _requestEvents = new Queue(); 66 | _successEvents = new Queue(); 67 | } 68 | 69 | public void Init(INatPunchListener listener) 70 | { 71 | _natPunchListener = listener; 72 | } 73 | 74 | public void NatIntroduce( 75 | NetEndPoint hostInternal, 76 | NetEndPoint hostExternal, 77 | NetEndPoint clientInternal, 78 | NetEndPoint clientExternal, 79 | string additionalInfo) 80 | { 81 | NetDataWriter dw = new NetDataWriter(); 82 | 83 | //First packet (server) 84 | //send to client 85 | dw.Put(ClientByte); 86 | dw.Put(hostInternal); 87 | dw.Put(hostExternal); 88 | dw.Put(additionalInfo, MaxTokenLength); 89 | 90 | var packet = _netBase.PacketPool.GetWithData(PacketProperty.NatIntroduction, dw); 91 | _netBase.SendRawAndRecycle(packet, clientExternal); 92 | 93 | //Second packet (client) 94 | //send to server 95 | dw.Reset(); 96 | dw.Put(HostByte); 97 | dw.Put(clientInternal); 98 | dw.Put(clientExternal); 99 | dw.Put(additionalInfo, MaxTokenLength); 100 | 101 | packet = _netBase.PacketPool.GetWithData(PacketProperty.NatIntroduction, dw); 102 | _netBase.SendRawAndRecycle(packet, hostExternal); 103 | } 104 | 105 | public void PollEvents() 106 | { 107 | if (_natPunchListener == null) 108 | return; 109 | lock (_successEvents) 110 | { 111 | while (_successEvents.Count > 0) 112 | { 113 | var evt = _successEvents.Dequeue(); 114 | _natPunchListener.OnNatIntroductionSuccess(evt.TargetEndPoint, evt.Token); 115 | } 116 | } 117 | lock (_requestEvents) 118 | { 119 | while (_requestEvents.Count > 0) 120 | { 121 | var evt = _requestEvents.Dequeue(); 122 | _natPunchListener.OnNatIntroductionRequest(evt.LocalEndPoint, evt.RemoteEndPoint, evt.Token); 123 | } 124 | } 125 | } 126 | 127 | public void SendNatIntroduceRequest(NetEndPoint masterServerEndPoint, string additionalInfo) 128 | { 129 | if (!_netBase.IsRunning) 130 | return; 131 | 132 | //prepare outgoing data 133 | NetDataWriter dw = new NetDataWriter(); 134 | string networkIp = NetUtils.GetLocalIp(LocalAddrType.IPv4); 135 | if (string.IsNullOrEmpty(networkIp)) 136 | { 137 | networkIp = NetUtils.GetLocalIp(LocalAddrType.IPv6); 138 | } 139 | int networkPort = _netBase.LocalPort; 140 | NetEndPoint localEndPoint = new NetEndPoint(networkIp, networkPort); 141 | dw.Put(localEndPoint); 142 | dw.Put(additionalInfo, MaxTokenLength); 143 | 144 | //prepare packet 145 | var packet = _netBase.PacketPool.GetWithData(PacketProperty.NatIntroductionRequest, dw); 146 | _netBase.SendRawAndRecycle(packet, masterServerEndPoint); 147 | } 148 | 149 | private void HandleNatPunch(NetEndPoint senderEndPoint, NetDataReader dr) 150 | { 151 | byte fromHostByte = dr.GetByte(); 152 | if (fromHostByte != HostByte && fromHostByte != ClientByte) 153 | { 154 | //garbage 155 | return; 156 | } 157 | 158 | //Read info 159 | string additionalInfo = dr.GetString(MaxTokenLength); 160 | NetUtils.DebugWrite(ConsoleColor.Green, "[NAT] punch received from {0} - additional info: {1}", senderEndPoint, additionalInfo); 161 | 162 | //Release punch success to client; enabling him to Connect() to msg.Sender if token is ok 163 | lock (_successEvents) 164 | { 165 | _successEvents.Enqueue(new SuccessEventData { TargetEndPoint = senderEndPoint, Token = additionalInfo }); 166 | } 167 | } 168 | 169 | private void HandleNatIntroduction(NetDataReader dr) 170 | { 171 | // read intro 172 | byte hostByte = dr.GetByte(); 173 | NetEndPoint remoteInternal = dr.GetNetEndPoint(); 174 | NetEndPoint remoteExternal = dr.GetNetEndPoint(); 175 | string token = dr.GetString(MaxTokenLength); 176 | 177 | NetUtils.DebugWrite(ConsoleColor.Cyan, "[NAT] introduction received; we are designated " + (hostByte == HostByte ? "host" : "client")); 178 | NetDataWriter writer = new NetDataWriter(); 179 | 180 | // send internal punch 181 | writer.Put(hostByte); 182 | writer.Put(token); 183 | var packet = _netBase.PacketPool.GetWithData(PacketProperty.NatPunchMessage, writer); 184 | _netBase.SendRawAndRecycle(packet, remoteInternal); 185 | NetUtils.DebugWrite(ConsoleColor.Cyan, "[NAT] internal punch sent to " + remoteInternal); 186 | 187 | // send external punch 188 | writer.Reset(); 189 | writer.Put(hostByte); 190 | writer.Put(token); 191 | packet = _netBase.PacketPool.GetWithData(PacketProperty.NatPunchMessage, writer); 192 | _netBase.SendRawAndRecycle(packet, remoteExternal); 193 | NetUtils.DebugWrite(ConsoleColor.Cyan, "[NAT] external punch sent to " + remoteExternal); 194 | } 195 | 196 | private void HandleNatIntroductionRequest(NetEndPoint senderEndPoint, NetDataReader dr) 197 | { 198 | NetEndPoint localEp = dr.GetNetEndPoint(); 199 | string token = dr.GetString(MaxTokenLength); 200 | lock (_requestEvents) 201 | { 202 | _requestEvents.Enqueue(new RequestEventData 203 | { 204 | LocalEndPoint = localEp, 205 | RemoteEndPoint = senderEndPoint, 206 | Token = token 207 | }); 208 | } 209 | } 210 | 211 | internal void ProcessMessage(NetEndPoint senderEndPoint, NetPacket packet) 212 | { 213 | var dr = new NetDataReader(packet.RawData, NetConstants.HeaderSize, packet.Size); 214 | switch (packet.Property) 215 | { 216 | case PacketProperty.NatIntroductionRequest: 217 | //We got request and must introduce 218 | HandleNatIntroductionRequest(senderEndPoint, dr); 219 | break; 220 | case PacketProperty.NatIntroduction: 221 | //We got introduce and must punch 222 | HandleNatIntroduction(dr); 223 | break; 224 | case PacketProperty.NatPunchMessage: 225 | //We got punch and can connect 226 | HandleNatPunch(senderEndPoint, dr); 227 | break; 228 | } 229 | } 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/LiteNetLib/NetConstants.cs: -------------------------------------------------------------------------------- 1 | namespace LiteNetLib 2 | { 3 | /// 4 | /// Sending method type 5 | /// 6 | public enum SendOptions 7 | { 8 | /// 9 | /// Unreliable. Packets can be dropped, duplicated or arrive without order 10 | /// 11 | Unreliable, 12 | 13 | /// 14 | /// Reliable. All packets will be sent and received, but without order 15 | /// 16 | ReliableUnordered, 17 | 18 | /// 19 | /// Unreliable. Packets can be dropped, but never duplicated and arrive in order 20 | /// 21 | Sequenced, 22 | 23 | /// 24 | /// Reliable and ordered. All packets will be sent and received in order 25 | /// 26 | ReliableOrdered 27 | } 28 | 29 | /// 30 | /// Network constants. Can be tuned from sources for your purposes. 31 | /// 32 | public static class NetConstants 33 | { 34 | //can be tuned 35 | public const int DefaultWindowSize = 64; 36 | public const int SocketBufferSize = 1024 * 1024; //1mb 37 | public const int SocketTTL = 255; 38 | 39 | public const int HeaderSize = 1; 40 | public const int SequencedHeaderSize = 3; 41 | public const int FragmentHeaderSize = 6; 42 | public const ushort MaxSequence = 32768; 43 | public const ushort HalfMaxSequence = MaxSequence / 2; 44 | public const int MinPacketSize = 576 - MaxUdpHeaderSize; 45 | public const int MinPacketDataSize = MinPacketSize - HeaderSize; 46 | public const int MinSequencedPacketDataSize = MinPacketSize - SequencedHeaderSize; 47 | 48 | //internal 49 | internal const string MulticastGroupIPv4 = "224.0.0.1"; 50 | internal const string MulticastGroupIPv6 = "FF02:0:0:0:0:0:0:1"; 51 | 52 | //protocol 53 | internal const int ProtocolId = 1; 54 | internal const int MaxUdpHeaderSize = 68; 55 | internal const int PacketSizeLimit = ushort.MaxValue - MaxUdpHeaderSize; 56 | internal const int RequestConnectIdIndex = 5; 57 | internal const int AcceptConnectIdIndex = 1; 58 | 59 | internal static readonly int[] PossibleMtu = 60 | { 61 | 576 - MaxUdpHeaderSize, //Internet Path MTU for X.25 (RFC 879) 62 | 1492 - MaxUdpHeaderSize, //Ethernet with LLC and SNAP, PPPoE (RFC 1042) 63 | 1500 - MaxUdpHeaderSize, //Ethernet II (RFC 1191) 64 | 4352 - MaxUdpHeaderSize, //FDDI 65 | 4464 - MaxUdpHeaderSize, //Token ring 66 | 7981 - MaxUdpHeaderSize //WLAN 67 | }; 68 | 69 | internal static int MaxPacketSize = PossibleMtu[PossibleMtu.Length - 1]; 70 | 71 | //peer specific 72 | public const int FlowUpdateTime = 1000; 73 | public const int FlowIncreaseThreshold = 4; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/LiteNetLib/NetDebug.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace LiteNetLib 4 | { 5 | /// 6 | /// Interface to implement for your own logger 7 | /// 8 | public interface INetLogger 9 | { 10 | void WriteNet(ConsoleColor color, string str, params object[] args); 11 | } 12 | 13 | /// 14 | /// Static class for defining your own LiteNetLib logger instead of Console.WriteLine 15 | /// or Debug.Log if compiled with UNITY flag 16 | /// 17 | public static class NetDebug 18 | { 19 | public static INetLogger Logger = null; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/LiteNetLib/NetEndPoint.cs: -------------------------------------------------------------------------------- 1 | #if !WINRT || UNITY_EDITOR 2 | using System; 3 | using System.Net; 4 | using System.Net.Sockets; 5 | 6 | namespace LiteNetLib 7 | { 8 | /// 9 | /// Network End Point. Contains ip address and port 10 | /// 11 | public sealed class NetEndPoint 12 | { 13 | public string Host { get { return EndPoint.Address.ToString(); } } 14 | public int Port { get { return EndPoint.Port; } } 15 | 16 | internal readonly IPEndPoint EndPoint; 17 | 18 | internal NetEndPoint(IPEndPoint ipEndPoint) 19 | { 20 | EndPoint = ipEndPoint; 21 | } 22 | 23 | public override bool Equals(object obj) 24 | { 25 | if (!(obj is NetEndPoint)) 26 | { 27 | return false; 28 | } 29 | return EndPoint.Equals(((NetEndPoint)obj).EndPoint); 30 | } 31 | 32 | public override string ToString() 33 | { 34 | return EndPoint.ToString(); 35 | } 36 | 37 | public override int GetHashCode() 38 | { 39 | return EndPoint.GetHashCode(); 40 | } 41 | 42 | public NetEndPoint(string hostStr, int port) 43 | { 44 | IPAddress ipAddress; 45 | if (!IPAddress.TryParse(hostStr, out ipAddress)) 46 | { 47 | if (NetSocket.IPv6Support) 48 | { 49 | if (hostStr == "localhost") 50 | { 51 | ipAddress = IPAddress.IPv6Loopback; 52 | } 53 | else 54 | { 55 | ipAddress = ResolveAddress(hostStr, AddressFamily.InterNetworkV6); 56 | } 57 | } 58 | if (ipAddress == null) 59 | { 60 | ipAddress = ResolveAddress(hostStr, AddressFamily.InterNetwork); 61 | } 62 | } 63 | if (ipAddress == null) 64 | { 65 | throw new Exception("Invalid address: " + hostStr); 66 | } 67 | EndPoint = new IPEndPoint(ipAddress, port); 68 | } 69 | 70 | private IPAddress ResolveAddress(string hostStr, AddressFamily addressFamily) 71 | { 72 | #if NETCORE 73 | var hostTask = Dns.GetHostEntryAsync(hostStr); 74 | hostTask.Wait(); 75 | var host = hostTask.Result; 76 | #else 77 | var host = Dns.GetHostEntry(hostStr); 78 | #endif 79 | foreach (IPAddress ip in host.AddressList) 80 | { 81 | if (ip.AddressFamily == addressFamily) 82 | { 83 | return ip; 84 | } 85 | } 86 | return null; 87 | } 88 | 89 | internal long GetId() 90 | { 91 | byte[] addr = EndPoint.Address.GetAddressBytes(); 92 | long id = 0; 93 | 94 | if (addr.Length == 4) //IPv4 95 | { 96 | id = addr[0]; 97 | id |= (long)addr[1] << 8; 98 | id |= (long)addr[2] << 16; 99 | id |= (long)addr[3] << 24; 100 | id |= (long)EndPoint.Port << 32; 101 | } 102 | else if (addr.Length == 16) //IPv6 103 | { 104 | id = addr[0] ^ addr[8]; 105 | id |= (long)(addr[1] ^ addr[9]) << 8; 106 | id |= (long)(addr[2] ^ addr[10]) << 16; 107 | 108 | 109 | id |= (long)(addr[3] ^ addr[11]) << 24; 110 | id |= (long)(addr[4] ^ addr[12]) << 32; 111 | id |= (long)(addr[5] ^ addr[13]) << 40; 112 | id |= (long)(addr[6] ^ addr[14]) << 48; 113 | id |= (long)(Port ^ addr[7] ^ addr[15]) << 56; 114 | } 115 | 116 | return id; 117 | } 118 | } 119 | } 120 | #else 121 | using System; 122 | using Windows.Networking; 123 | using Windows.Networking.Sockets; 124 | 125 | namespace LiteNetLib 126 | { 127 | public sealed class NetEndPoint 128 | { 129 | public string Host { get { return HostName.DisplayName; } } 130 | public int Port { get; private set; } 131 | internal readonly HostName HostName; 132 | internal readonly string PortStr; 133 | 134 | internal NetEndPoint(int port) 135 | { 136 | HostName = null; 137 | PortStr = port.ToString(); 138 | Port = port; 139 | } 140 | 141 | public override bool Equals(object obj) 142 | { 143 | if (!(obj is NetEndPoint)) 144 | { 145 | return false; 146 | } 147 | NetEndPoint other = (NetEndPoint) obj; 148 | return HostName.IsEqual(other.HostName) && PortStr.Equals(other.PortStr); 149 | } 150 | 151 | public override int GetHashCode() 152 | { 153 | return HostName.CanonicalName.GetHashCode() ^ PortStr.GetHashCode(); 154 | } 155 | 156 | internal long GetId() 157 | { 158 | //Check locals 159 | if (HostName == null) 160 | { 161 | return ParseIpToId("0.0.0.0"); 162 | } 163 | 164 | if (HostName.DisplayName == "localhost") 165 | { 166 | return ParseIpToId("127.0.0.1"); 167 | } 168 | 169 | //Check remote 170 | string hostIp = string.Empty; 171 | var task = DatagramSocket.GetEndpointPairsAsync(HostName, "0").AsTask(); 172 | task.Wait(); 173 | 174 | //IPv4 175 | foreach (var endpointPair in task.Result) 176 | { 177 | hostIp = endpointPair.RemoteHostName.CanonicalName; 178 | if (endpointPair.RemoteHostName.Type == HostNameType.Ipv4) 179 | { 180 | return ParseIpToId(hostIp); 181 | } 182 | } 183 | 184 | //Else 185 | return hostIp.GetHashCode() ^ Port; 186 | } 187 | 188 | private long ParseIpToId(string hostIp) 189 | { 190 | long id = 0; 191 | string[] ip = hostIp.Split('.'); 192 | id |= long.Parse(ip[0]); 193 | id |= long.Parse(ip[1]) << 8; 194 | id |= long.Parse(ip[2]) << 16; 195 | id |= long.Parse(ip[3]) << 24; 196 | id |= (long)Port << 32; 197 | return id; 198 | } 199 | 200 | public override string ToString() 201 | { 202 | return HostName.CanonicalName + ":" + PortStr; 203 | } 204 | 205 | public NetEndPoint(string hostName, int port) 206 | { 207 | var task = DatagramSocket.GetEndpointPairsAsync(new HostName(hostName), port.ToString()).AsTask(); 208 | task.Wait(); 209 | HostName = task.Result[0].RemoteHostName; 210 | Port = port; 211 | PortStr = port.ToString(); 212 | } 213 | 214 | internal NetEndPoint(HostName hostName, string port) 215 | { 216 | HostName = hostName; 217 | Port = int.Parse(port); 218 | PortStr = port; 219 | } 220 | } 221 | } 222 | #endif 223 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/LiteNetLib/NetPacket.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using LiteNetLib.Utils; 3 | 4 | namespace LiteNetLib 5 | { 6 | internal enum PacketProperty : byte 7 | { 8 | Unreliable, //0 9 | Reliable, //1 10 | Sequenced, //2 11 | ReliableOrdered, //3 12 | AckReliable, //4 13 | AckReliableOrdered, //5 14 | Ping, //6 15 | Pong, //7 16 | ConnectRequest, //8 17 | ConnectAccept, //9 18 | Disconnect, //10 19 | UnconnectedMessage, //11 20 | NatIntroductionRequest, //12 21 | NatIntroduction, //13 22 | NatPunchMessage, //14 23 | MtuCheck, //15 24 | MtuOk, //16 25 | DiscoveryRequest, //17 26 | DiscoveryResponse, //18 27 | Merged //19 28 | } 29 | 30 | internal sealed class NetPacket 31 | { 32 | private const int LastProperty = 19; 33 | 34 | //Header 35 | public PacketProperty Property 36 | { 37 | get { return (PacketProperty)(RawData[0] & 0x7F); } 38 | set { RawData[0] = (byte)((RawData[0] & 0x80) | ((byte)value & 0x7F)); } 39 | } 40 | 41 | public ushort Sequence 42 | { 43 | get { return BitConverter.ToUInt16(RawData, 1); } 44 | set { FastBitConverter.GetBytes(RawData, 1, value); } 45 | } 46 | 47 | public bool IsFragmented 48 | { 49 | get { return (RawData[0] & 0x80) != 0; } 50 | set 51 | { 52 | if (value) 53 | RawData[0] |= 0x80; //set first bit 54 | else 55 | RawData[0] &= 0x7F; //unset first bit 56 | } 57 | } 58 | 59 | public ushort FragmentId 60 | { 61 | get { return BitConverter.ToUInt16(RawData, 3); } 62 | set { FastBitConverter.GetBytes(RawData, 3, value); } 63 | } 64 | 65 | public ushort FragmentPart 66 | { 67 | get { return BitConverter.ToUInt16(RawData, 5); } 68 | set { FastBitConverter.GetBytes(RawData, 5, value); } 69 | } 70 | 71 | public ushort FragmentsTotal 72 | { 73 | get { return BitConverter.ToUInt16(RawData, 7); } 74 | set { FastBitConverter.GetBytes(RawData, 7, value); } 75 | } 76 | 77 | //Data 78 | public byte[] RawData; 79 | public int Size; 80 | 81 | public NetPacket(int size) 82 | { 83 | RawData = new byte[size]; 84 | Size = 0; 85 | } 86 | 87 | public bool Realloc(int toSize) 88 | { 89 | if (RawData.Length < toSize) 90 | { 91 | RawData = new byte[toSize]; 92 | return true; 93 | } 94 | return false; 95 | } 96 | 97 | public static bool GetPacketProperty(byte[] data, out PacketProperty property) 98 | { 99 | byte properyByte = (byte)(data[0] & 0x7F); 100 | if (properyByte > LastProperty) 101 | { 102 | property = PacketProperty.Unreliable; 103 | return false; 104 | } 105 | property = (PacketProperty)properyByte; 106 | return true; 107 | } 108 | 109 | public static int GetHeaderSize(PacketProperty property) 110 | { 111 | switch (property) 112 | { 113 | case PacketProperty.ReliableOrdered: 114 | case PacketProperty.Reliable: 115 | case PacketProperty.Sequenced: 116 | case PacketProperty.Ping: 117 | case PacketProperty.Pong: 118 | case PacketProperty.AckReliable: 119 | case PacketProperty.AckReliableOrdered: 120 | return NetConstants.SequencedHeaderSize; 121 | default: 122 | return NetConstants.HeaderSize; 123 | } 124 | } 125 | 126 | public int GetHeaderSize() 127 | { 128 | return GetHeaderSize(Property); 129 | } 130 | 131 | public byte[] GetPacketData() 132 | { 133 | int headerSize = GetHeaderSize(Property); 134 | int dataSize = Size - headerSize; 135 | byte[] data = new byte[dataSize]; 136 | Buffer.BlockCopy(RawData, headerSize, data, 0, dataSize); 137 | return data; 138 | } 139 | 140 | public bool IsClientData() 141 | { 142 | var property = Property; 143 | return property == PacketProperty.Reliable || 144 | property == PacketProperty.ReliableOrdered || 145 | property == PacketProperty.Unreliable || 146 | property == PacketProperty.Sequenced; 147 | } 148 | 149 | //Packet contstructor from byte array 150 | public bool FromBytes(byte[] data, int start, int packetSize) 151 | { 152 | //Reading property 153 | byte property = (byte)(data[start] & 0x7F); 154 | bool fragmented = (data[start] & 0x80) != 0; 155 | int headerSize = GetHeaderSize((PacketProperty) property); 156 | 157 | if (property > LastProperty || 158 | packetSize > NetConstants.PacketSizeLimit || 159 | packetSize < headerSize || 160 | (fragmented && packetSize < headerSize + NetConstants.FragmentHeaderSize)) 161 | { 162 | return false; 163 | } 164 | 165 | Buffer.BlockCopy(data, start, RawData, 0, packetSize); 166 | Size = packetSize; 167 | return true; 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/LiteNetLib/NetPacketPool.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using LiteNetLib.Utils; 4 | 5 | namespace LiteNetLib 6 | { 7 | internal class NetPacketPool 8 | { 9 | private const int PoolLimit = 1000; 10 | private readonly Stack _pool; 11 | 12 | public NetPacketPool() 13 | { 14 | _pool = new Stack(); 15 | } 16 | 17 | public NetPacket GetWithData(PacketProperty property, NetDataWriter writer) 18 | { 19 | var packet = Get(property, writer.Length); 20 | Buffer.BlockCopy(writer.Data, 0, packet.RawData, NetPacket.GetHeaderSize(property), writer.Length); 21 | return packet; 22 | } 23 | 24 | public NetPacket GetWithData(PacketProperty property, byte[] data, int start, int length) 25 | { 26 | var packet = Get(property, length); 27 | Buffer.BlockCopy(data, start, packet.RawData, NetPacket.GetHeaderSize(property), length); 28 | return packet; 29 | } 30 | 31 | private NetPacket GetPacket(int size, bool clear) 32 | { 33 | NetPacket packet = null; 34 | if (size <= NetConstants.MaxPacketSize) 35 | { 36 | lock (_pool) 37 | { 38 | if (_pool.Count > 0) 39 | { 40 | packet = _pool.Pop(); 41 | } 42 | } 43 | } 44 | if (packet == null) 45 | { 46 | //allocate new packet 47 | packet = new NetPacket(size); 48 | } 49 | else 50 | { 51 | //reallocate packet data if packet not fits 52 | if (!packet.Realloc(size) && clear) 53 | { 54 | //clear in not reallocated 55 | Array.Clear(packet.RawData, 0, size); 56 | } 57 | } 58 | return packet; 59 | } 60 | 61 | //Get packet just for read 62 | public NetPacket GetAndRead(byte[] data, int start, int count) 63 | { 64 | NetPacket packet = GetPacket(count, false); 65 | if (!packet.FromBytes(data, start, count)) 66 | { 67 | Recycle(packet); 68 | return null; 69 | } 70 | return packet; 71 | } 72 | 73 | //Get packet with size 74 | public NetPacket Get(PacketProperty property, int size) 75 | { 76 | size += NetPacket.GetHeaderSize(property); 77 | NetPacket packet = GetPacket(size, true); 78 | packet.Property = property; 79 | packet.Size = size; 80 | return packet; 81 | } 82 | 83 | public void Recycle(NetPacket packet) 84 | { 85 | if (packet.Size > NetConstants.MaxPacketSize || _pool.Count > PoolLimit) 86 | { 87 | //Dont pool big packets. Save memory 88 | return; 89 | } 90 | 91 | //Clean fragmented flag 92 | packet.IsFragmented = false; 93 | lock (_pool) 94 | { 95 | _pool.Push(packet); 96 | } 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/LiteNetLib/NetPeerCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace LiteNetLib 5 | { 6 | internal sealed class NetPeerCollection 7 | { 8 | private readonly Dictionary _peersDict; 9 | private readonly NetPeer[] _peersArray; 10 | private int _count; 11 | 12 | public int Count 13 | { 14 | get { return _count; } 15 | } 16 | 17 | public NetPeer this[int index] 18 | { 19 | get { return _peersArray[index]; } 20 | } 21 | 22 | public NetPeerCollection(int maxPeers) 23 | { 24 | _peersArray = new NetPeer[maxPeers]; 25 | _peersDict = new Dictionary(); 26 | } 27 | 28 | public bool TryGetValue(NetEndPoint endPoint, out NetPeer peer) 29 | { 30 | return _peersDict.TryGetValue(endPoint, out peer); 31 | } 32 | 33 | public void Clear() 34 | { 35 | Array.Clear(_peersArray, 0, _count); 36 | _peersDict.Clear(); 37 | _count = 0; 38 | } 39 | 40 | public void Add(NetEndPoint endPoint, NetPeer peer) 41 | { 42 | _peersArray[_count] = peer; 43 | _peersDict.Add(endPoint, peer); 44 | _count++; 45 | } 46 | 47 | public bool ContainsAddress(NetEndPoint endPoint) 48 | { 49 | return _peersDict.ContainsKey(endPoint); 50 | } 51 | 52 | public NetPeer[] ToArray() 53 | { 54 | NetPeer[] result = new NetPeer[_count]; 55 | Array.Copy(_peersArray, 0, result, 0, _count); 56 | return result; 57 | } 58 | 59 | public void RemoveAt(int idx) 60 | { 61 | _peersDict.Remove(_peersArray[idx].EndPoint); 62 | _peersArray[idx] = _peersArray[_count - 1]; 63 | _peersArray[_count - 1] = null; 64 | _count--; 65 | } 66 | 67 | public void Remove(NetEndPoint endPoint) 68 | { 69 | for (int i = 0; i < _count; i++) 70 | { 71 | if (_peersArray[i].EndPoint.Equals(endPoint)) 72 | { 73 | RemoveAt(i); 74 | break; 75 | } 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/LiteNetLib/NetSocket.cs: -------------------------------------------------------------------------------- 1 | #if !WINRT || UNITY_EDITOR 2 | using System; 3 | using System.Net; 4 | using System.Net.Sockets; 5 | using System.Threading; 6 | 7 | namespace LiteNetLib 8 | { 9 | internal sealed class NetSocket 10 | { 11 | private Socket _udpSocketv4; 12 | private Socket _udpSocketv6; 13 | private int _port; 14 | private Thread _threadv4; 15 | private Thread _threadv6; 16 | private bool _running; 17 | private readonly NetManager.OnMessageReceived _onMessageReceived; 18 | 19 | private static readonly IPAddress MulticastAddressV6 = IPAddress.Parse (NetConstants.MulticastGroupIPv6); 20 | internal static readonly bool IPv6Support; 21 | private const int SocketReceivePollTime = 100000; 22 | private const int SocketSendPollTime = 5000; 23 | 24 | public int LocalPort 25 | { 26 | get { return _port; } 27 | } 28 | 29 | static NetSocket() 30 | { 31 | #if UNITY 32 | IPv6Support = Socket.SupportsIPv6; 33 | #else 34 | IPv6Support = Socket.OSSupportsIPv6; 35 | #endif 36 | } 37 | 38 | public NetSocket(NetManager.OnMessageReceived onMessageReceived) 39 | { 40 | _onMessageReceived = onMessageReceived; 41 | } 42 | 43 | private void ReceiveLogic(object state) 44 | { 45 | Socket socket = (Socket)state; 46 | EndPoint bufferEndPoint = new IPEndPoint(socket.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, 0); 47 | NetEndPoint bufferNetEndPoint = new NetEndPoint((IPEndPoint)bufferEndPoint); 48 | byte[] receiveBuffer = new byte[NetConstants.PacketSizeLimit]; 49 | 50 | while (_running) 51 | { 52 | //wait for data 53 | if (!socket.Poll(SocketReceivePollTime, SelectMode.SelectRead)) 54 | { 55 | continue; 56 | } 57 | 58 | int result; 59 | 60 | //Reading data 61 | try 62 | { 63 | result = socket.ReceiveFrom(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None, ref bufferEndPoint); 64 | if (!bufferNetEndPoint.EndPoint.Equals(bufferEndPoint)) 65 | { 66 | bufferNetEndPoint = new NetEndPoint((IPEndPoint)bufferEndPoint); 67 | } 68 | } 69 | catch (SocketException ex) 70 | { 71 | if (ex.SocketErrorCode == SocketError.ConnectionReset || 72 | ex.SocketErrorCode == SocketError.MessageSize) 73 | { 74 | //10040 - message too long 75 | //10054 - remote close (not error) 76 | //Just UDP 77 | NetUtils.DebugWrite(ConsoleColor.DarkRed, "[R] Ingored error: {0} - {1}", (int)ex.SocketErrorCode, ex.ToString() ); 78 | continue; 79 | } 80 | NetUtils.DebugWriteError("[R]Error code: {0} - {1}", (int)ex.SocketErrorCode, ex.ToString()); 81 | _onMessageReceived(null, 0, (int)ex.SocketErrorCode, bufferNetEndPoint); 82 | continue; 83 | } 84 | 85 | //All ok! 86 | NetUtils.DebugWrite(ConsoleColor.Blue, "[R]Recieved data from {0}, result: {1}", bufferNetEndPoint.ToString(), result); 87 | _onMessageReceived(receiveBuffer, result, 0, bufferNetEndPoint); 88 | } 89 | } 90 | 91 | public bool Bind(int port, bool reuseAddress) 92 | { 93 | _udpSocketv4 = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 94 | _udpSocketv4.Blocking = false; 95 | _udpSocketv4.ReceiveBufferSize = NetConstants.SocketBufferSize; 96 | _udpSocketv4.SendBufferSize = NetConstants.SocketBufferSize; 97 | _udpSocketv4.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, NetConstants.SocketTTL); 98 | if(reuseAddress) 99 | _udpSocketv4.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 100 | #if !NETCORE 101 | _udpSocketv4.DontFragment = true; 102 | #endif 103 | 104 | try 105 | { 106 | _udpSocketv4.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); 107 | } 108 | catch (SocketException e) 109 | { 110 | NetUtils.DebugWriteError("Broadcast error: {0}", e.ToString()); 111 | } 112 | 113 | if (!BindSocket(_udpSocketv4, new IPEndPoint(IPAddress.Any, port))) 114 | { 115 | return false; 116 | } 117 | _port = ((IPEndPoint) _udpSocketv4.LocalEndPoint).Port; 118 | _running = true; 119 | _threadv4 = new Thread(ReceiveLogic); 120 | _threadv4.Name = "SocketThreadv4(" + _port + ")"; 121 | _threadv4.IsBackground = true; 122 | _threadv4.Start(_udpSocketv4); 123 | 124 | //Check IPv6 support 125 | if (!IPv6Support) 126 | return true; 127 | 128 | _udpSocketv6 = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp); 129 | _udpSocketv6.Blocking = false; 130 | _udpSocketv6.ReceiveBufferSize = NetConstants.SocketBufferSize; 131 | _udpSocketv6.SendBufferSize = NetConstants.SocketBufferSize; 132 | if (reuseAddress) 133 | _udpSocketv6.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 134 | 135 | //Use one port for two sockets 136 | if (BindSocket(_udpSocketv6, new IPEndPoint(IPAddress.IPv6Any, _port))) 137 | { 138 | try 139 | { 140 | #if !ENABLE_IL2CPP 141 | _udpSocketv6.SetSocketOption( 142 | SocketOptionLevel.IPv6, 143 | SocketOptionName.AddMembership, 144 | new IPv6MulticastOption(MulticastAddressV6)); 145 | #endif 146 | } 147 | catch(Exception) 148 | { 149 | // Unity3d throws exception - ignored 150 | } 151 | 152 | _threadv6 = new Thread(ReceiveLogic); 153 | _threadv6.Name = "SocketThreadv6(" + _port + ")"; 154 | _threadv6.IsBackground = true; 155 | _threadv6.Start(_udpSocketv6); 156 | } 157 | 158 | return true; 159 | } 160 | 161 | private bool BindSocket(Socket socket, IPEndPoint ep) 162 | { 163 | try 164 | { 165 | socket.Bind(ep); 166 | NetUtils.DebugWrite(ConsoleColor.Blue, "[B]Succesfully binded to port: {0}", ((IPEndPoint)socket.LocalEndPoint).Port); 167 | } 168 | catch (SocketException ex) 169 | { 170 | NetUtils.DebugWriteError("[B]Bind exception: {0}", ex.ToString()); 171 | //TODO: very temporary hack for iOS (Unity3D) 172 | if (ex.SocketErrorCode == SocketError.AddressFamilyNotSupported) 173 | { 174 | return true; 175 | } 176 | return false; 177 | } 178 | return true; 179 | } 180 | 181 | public bool SendBroadcast(byte[] data, int offset, int size, int port) 182 | { 183 | try 184 | { 185 | int result = _udpSocketv4.SendTo(data, offset, size, SocketFlags.None, new IPEndPoint(IPAddress.Broadcast, port)); 186 | if (result <= 0) 187 | return false; 188 | if (IPv6Support) 189 | { 190 | result = _udpSocketv6.SendTo(data, offset, size, SocketFlags.None, new IPEndPoint(MulticastAddressV6, port)); 191 | if (result <= 0) 192 | return false; 193 | } 194 | } 195 | catch (Exception ex) 196 | { 197 | NetUtils.DebugWriteError("[S][MCAST]" + ex); 198 | return false; 199 | } 200 | return true; 201 | } 202 | 203 | public int SendTo(byte[] data, int offset, int size, NetEndPoint remoteEndPoint, ref int errorCode) 204 | { 205 | try 206 | { 207 | int result = 0; 208 | if (remoteEndPoint.EndPoint.AddressFamily == AddressFamily.InterNetwork) 209 | { 210 | if (!_udpSocketv4.Poll(SocketSendPollTime, SelectMode.SelectWrite)) 211 | return -1; 212 | result = _udpSocketv4.SendTo(data, offset, size, SocketFlags.None, remoteEndPoint.EndPoint); 213 | } 214 | else if(IPv6Support) 215 | { 216 | if (!_udpSocketv6.Poll(SocketSendPollTime, SelectMode.SelectWrite)) 217 | return -1; 218 | result = _udpSocketv6.SendTo(data, offset, size, SocketFlags.None, remoteEndPoint.EndPoint); 219 | } 220 | 221 | NetUtils.DebugWrite(ConsoleColor.Blue, "[S]Send packet to {0}, result: {1}", remoteEndPoint.EndPoint, result); 222 | return result; 223 | } 224 | catch (SocketException ex) 225 | { 226 | if (ex.SocketErrorCode != SocketError.MessageSize) 227 | { 228 | NetUtils.DebugWriteError("[S]" + ex); 229 | } 230 | 231 | errorCode = (int)ex.SocketErrorCode; 232 | return -1; 233 | } 234 | catch (Exception ex) 235 | { 236 | NetUtils.DebugWriteError("[S]" + ex); 237 | return -1; 238 | } 239 | } 240 | 241 | private void CloseSocket(Socket s) 242 | { 243 | #if NETCORE 244 | s.Dispose(); 245 | #else 246 | s.Close(); 247 | #endif 248 | } 249 | 250 | public void Close() 251 | { 252 | _running = false; 253 | 254 | //Close IPv4 255 | if (Thread.CurrentThread != _threadv4) 256 | { 257 | _threadv4.Join(); 258 | } 259 | _threadv4 = null; 260 | if (_udpSocketv4 != null) 261 | { 262 | CloseSocket(_udpSocketv4); 263 | _udpSocketv4 = null; 264 | } 265 | 266 | //No ipv6 267 | if (_udpSocketv6 == null) 268 | return; 269 | 270 | //Close IPv6 271 | if (Thread.CurrentThread != _threadv6) 272 | { 273 | _threadv6.Join(); 274 | } 275 | _threadv6 = null; 276 | if (_udpSocketv6 != null) 277 | { 278 | CloseSocket(_udpSocketv6); 279 | _udpSocketv6 = null; 280 | } 281 | } 282 | } 283 | } 284 | #else 285 | using System; 286 | using System.Collections.Generic; 287 | using System.IO; 288 | using System.Runtime.InteropServices.WindowsRuntime; 289 | using System.Threading; 290 | using System.Threading.Tasks; 291 | using Windows.Networking; 292 | using Windows.Networking.Sockets; 293 | using Windows.Storage.Streams; 294 | 295 | namespace LiteNetLib 296 | { 297 | internal sealed class NetSocket 298 | { 299 | private DatagramSocket _datagramSocket; 300 | private readonly Dictionary _peers = new Dictionary(); 301 | private readonly NetManager.OnMessageReceived _onMessageReceived; 302 | private readonly byte[] _byteBuffer = new byte[NetConstants.PacketSizeLimit]; 303 | private readonly IBuffer _buffer; 304 | private NetEndPoint _bufferEndPoint; 305 | private int _port; 306 | private static readonly HostName BroadcastAddress = new HostName("255.255.255.255"); 307 | private static readonly HostName MulticastAddressV6 = new HostName(NetConstants.MulticastGroupIPv6); 308 | 309 | public int LocalPort 310 | { 311 | get { return _port; } 312 | } 313 | 314 | public NetSocket(NetManager.OnMessageReceived onMessageReceived) 315 | { 316 | _onMessageReceived = onMessageReceived; 317 | _buffer = _byteBuffer.AsBuffer(); 318 | } 319 | 320 | private void OnMessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args) 321 | { 322 | var result = args.GetDataStream().ReadAsync(_buffer, _buffer.Capacity, InputStreamOptions.None).AsTask().Result; 323 | int length = (int)result.Length; 324 | if (length <= 0) 325 | return; 326 | 327 | if (_bufferEndPoint == null || 328 | !_bufferEndPoint.HostName.IsEqual(args.RemoteAddress) || 329 | !_bufferEndPoint.PortStr.Equals(args.RemotePort)) 330 | { 331 | _bufferEndPoint = new NetEndPoint(args.RemoteAddress, args.RemotePort); 332 | } 333 | _onMessageReceived(_byteBuffer, length, 0, _bufferEndPoint); 334 | } 335 | 336 | public bool Bind(int port, bool reuseAddress) 337 | { 338 | _datagramSocket = new DatagramSocket(); 339 | _datagramSocket.Control.InboundBufferSizeInBytes = NetConstants.SocketBufferSize; 340 | _datagramSocket.Control.DontFragment = true; 341 | _datagramSocket.Control.OutboundUnicastHopLimit = NetConstants.SocketTTL; 342 | _datagramSocket.MessageReceived += OnMessageReceived; 343 | 344 | try 345 | { 346 | _datagramSocket.BindServiceNameAsync(port.ToString()).AsTask().Wait(); 347 | _datagramSocket.JoinMulticastGroup(MulticastAddressV6); 348 | _port = int.Parse(_datagramSocket.Information.LocalPort); 349 | } 350 | catch (Exception ex) 351 | { 352 | NetUtils.DebugWriteError("[B]Bind exception: {0}", ex.ToString()); 353 | return false; 354 | } 355 | return true; 356 | } 357 | 358 | public bool SendBroadcast(byte[] data, int offset, int size, int port) 359 | { 360 | var portString = port.ToString(); 361 | try 362 | { 363 | var outputStream = 364 | _datagramSocket.GetOutputStreamAsync(BroadcastAddress, portString) 365 | .AsTask() 366 | .Result; 367 | var writer = outputStream.AsStreamForWrite(); 368 | writer.Write(data, offset, size); 369 | writer.Flush(); 370 | 371 | outputStream = 372 | _datagramSocket.GetOutputStreamAsync(MulticastAddressV6, portString) 373 | .AsTask() 374 | .Result; 375 | writer = outputStream.AsStreamForWrite(); 376 | writer.Write(data, offset, size); 377 | writer.Flush(); 378 | } 379 | catch (Exception ex) 380 | { 381 | NetUtils.DebugWriteError("[S][MCAST]" + ex); 382 | return false; 383 | } 384 | return true; 385 | } 386 | 387 | public int SendTo(byte[] data, int offset, int length, NetEndPoint remoteEndPoint, ref int errorCode) 388 | { 389 | Task task = null; 390 | try 391 | { 392 | IOutputStream writer; 393 | if (!_peers.TryGetValue(remoteEndPoint, out writer)) 394 | { 395 | writer = 396 | _datagramSocket.GetOutputStreamAsync(remoteEndPoint.HostName, remoteEndPoint.PortStr) 397 | .AsTask() 398 | .Result; 399 | _peers.Add(remoteEndPoint, writer); 400 | } 401 | 402 | task = writer.WriteAsync(data.AsBuffer(offset, length)).AsTask(); 403 | return (int)task.Result; 404 | } 405 | catch (Exception ex) 406 | { 407 | if (task?.Exception?.InnerExceptions != null) 408 | { 409 | ex = task.Exception.InnerException; 410 | } 411 | var errorStatus = SocketError.GetStatus(ex.HResult); 412 | switch (errorStatus) 413 | { 414 | case SocketErrorStatus.MessageTooLong: 415 | errorCode = 10040; 416 | break; 417 | default: 418 | errorCode = (int)errorStatus; 419 | NetUtils.DebugWriteError("[S " + errorStatus + "(" + errorCode + ")]" + ex); 420 | break; 421 | } 422 | 423 | return -1; 424 | } 425 | } 426 | 427 | internal void RemovePeer(NetEndPoint ep) 428 | { 429 | _peers.Remove(ep); 430 | } 431 | 432 | public void Close() 433 | { 434 | _datagramSocket.Dispose(); 435 | _datagramSocket = null; 436 | ClearPeers(); 437 | } 438 | 439 | internal void ClearPeers() 440 | { 441 | _peers.Clear(); 442 | } 443 | } 444 | } 445 | #endif 446 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/LiteNetLib/NetStatistics.cs: -------------------------------------------------------------------------------- 1 | namespace LiteNetLib 2 | { 3 | public sealed class NetStatistics 4 | { 5 | public ulong PacketsSent; 6 | public ulong PacketsReceived; 7 | public ulong BytesSent; 8 | public ulong BytesReceived; 9 | public ulong PacketLoss; 10 | public ulong PacketLossPercent 11 | { 12 | get 13 | { 14 | if (PacketsSent == 0) 15 | { 16 | return 0; 17 | } 18 | 19 | return PacketLoss * 100 / PacketsSent; 20 | } 21 | } 22 | 23 | public override string ToString() 24 | { 25 | return 26 | string.Format( 27 | "BytesReceived: {0}\nPacketsReceived: {1}\nBytesSent: {2}\nPacketsSent: {3}\nPacketLoss: {4}\nPacketLossPercent: {5}\n", 28 | BytesReceived, 29 | PacketsReceived, 30 | BytesSent, 31 | PacketsSent, 32 | PacketLoss, 33 | PacketLossPercent); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/LiteNetLib/NetThread.cs: -------------------------------------------------------------------------------- 1 | #if WINRT && !UNITY_EDITOR 2 | #define USE_WINRT 3 | #endif 4 | 5 | using System; 6 | using System.Threading; 7 | 8 | #if USE_WINRT 9 | using Windows.Foundation; 10 | using Windows.System.Threading; 11 | using Windows.System.Threading.Core; 12 | #endif 13 | 14 | namespace LiteNetLib 15 | { 16 | internal sealed class NetThread 17 | { 18 | #if USE_WINRT 19 | private readonly ManualResetEvent _updateWaiter = new ManualResetEvent(false); 20 | private readonly ManualResetEvent _joinWaiter = new ManualResetEvent(false); 21 | #else 22 | private Thread _thread; 23 | #endif 24 | 25 | private readonly Action _callback; 26 | 27 | public int SleepTime; 28 | private volatile bool _running; 29 | private readonly string _name; 30 | 31 | public bool IsRunning 32 | { 33 | get { return _running; } 34 | } 35 | 36 | public NetThread(string name, int sleepTime, Action callback) 37 | { 38 | _callback = callback; 39 | SleepTime = sleepTime; 40 | _name = name; 41 | } 42 | 43 | public void Sleep(int msec) 44 | { 45 | #if USE_WINRT 46 | _updateWaiter.WaitOne(msec); 47 | #else 48 | Thread.Sleep(msec); 49 | #endif 50 | } 51 | 52 | public void Start() 53 | { 54 | if (_running) 55 | return; 56 | _running = true; 57 | #if USE_WINRT 58 | var thread = new PreallocatedWorkItem(ThreadLogic, WorkItemPriority.Normal, WorkItemOptions.TimeSliced); 59 | thread.RunAsync().AsTask(); 60 | #else 61 | _thread = new Thread(ThreadLogic) 62 | { 63 | Name = _name, 64 | IsBackground = true 65 | }; 66 | _thread.Start(); 67 | #endif 68 | } 69 | 70 | public void Stop() 71 | { 72 | if (!_running) 73 | return; 74 | _running = false; 75 | 76 | #if USE_WINRT 77 | _joinWaiter.WaitOne(); 78 | #else 79 | _thread.Join(); 80 | #endif 81 | } 82 | 83 | #if USE_WINRT 84 | private void ThreadLogic(IAsyncAction action) 85 | { 86 | while (_running) 87 | { 88 | _callback(); 89 | _updateWaiter.WaitOne(SleepTime); 90 | } 91 | _joinWaiter.Set(); 92 | } 93 | #else 94 | private void ThreadLogic() 95 | { 96 | while (_running) 97 | { 98 | _callback(); 99 | Thread.Sleep(SleepTime); 100 | } 101 | } 102 | #endif 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/LiteNetLib/NetUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | #if WINRT && !UNITY_EDITOR 5 | using Windows.Networking; 6 | using Windows.Networking.Connectivity; 7 | #else 8 | using System.Net; 9 | using System.Net.Sockets; 10 | using System.Net.NetworkInformation; 11 | #endif 12 | 13 | namespace LiteNetLib 14 | { 15 | #if WINRT && !UNITY_EDITOR 16 | public enum ConsoleColor 17 | { 18 | Gray, 19 | Yellow, 20 | Cyan, 21 | DarkCyan, 22 | DarkGreen, 23 | Blue, 24 | DarkRed, 25 | Red, 26 | Green, 27 | DarkYellow 28 | } 29 | #endif 30 | 31 | /// 32 | /// Address type that you want to receive from NetUtils.GetLocalIp method 33 | /// 34 | [Flags] 35 | public enum LocalAddrType 36 | { 37 | IPv4 = 1, 38 | IPv6 = 2, 39 | All = 3 40 | } 41 | 42 | /// 43 | /// Some specific network utilities 44 | /// 45 | public static class NetUtils 46 | { 47 | /// 48 | /// Request time from NTP server and calls callback (if success) 49 | /// 50 | /// NTP Server address 51 | /// port 52 | /// callback (called from other thread!) 53 | public static void RequestTimeFromNTP(string ntpServerAddress, int port, Action onRequestComplete) 54 | { 55 | NetSocket socket = null; 56 | var ntpEndPoint = new NetEndPoint(ntpServerAddress, port); 57 | 58 | NetManager.OnMessageReceived onReceive = (data, length, code, point) => 59 | { 60 | if (!point.Equals(ntpEndPoint) || length < 48) 61 | { 62 | return; 63 | } 64 | socket.Close(); 65 | 66 | ulong intPart = (ulong)data[40] << 24 | (ulong)data[41] << 16 | (ulong)data[42] << 8 | (ulong)data[43]; 67 | ulong fractPart = (ulong)data[44] << 24 | (ulong)data[45] << 16 | (ulong)data[46] << 8 | (ulong)data[47]; 68 | var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L); 69 | onRequestComplete(new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds((long) milliseconds)); 70 | }; 71 | 72 | //Create and start socket 73 | socket = new NetSocket(onReceive); 74 | socket.Bind(0, false); 75 | 76 | //Send request 77 | int errorCode = 0; 78 | var sendData = new byte[48]; 79 | sendData[0] = 0x1B; 80 | var sendCount = socket.SendTo(sendData, 0, sendData.Length, ntpEndPoint, ref errorCode); 81 | if (errorCode != 0 || sendCount != sendData.Length) 82 | { 83 | onRequestComplete(null); 84 | } 85 | } 86 | 87 | /// 88 | /// Get all local ip addresses 89 | /// 90 | /// type of address (IPv4, IPv6 or both) 91 | /// List with all local ip adresses 92 | public static List GetLocalIpList(LocalAddrType addrType) 93 | { 94 | List targetList = new List(); 95 | GetLocalIpList(targetList, addrType); 96 | return targetList; 97 | } 98 | 99 | /// 100 | /// Get all local ip addresses (non alloc version) 101 | /// 102 | /// result list 103 | /// type of address (IPv4, IPv6 or both) 104 | public static void GetLocalIpList(List targetList, LocalAddrType addrType) 105 | { 106 | bool ipv4 = (addrType & LocalAddrType.IPv4) == LocalAddrType.IPv4; 107 | bool ipv6 = (addrType & LocalAddrType.IPv6) == LocalAddrType.IPv6; 108 | #if WINRT && !UNITY_EDITOR 109 | foreach (HostName localHostName in NetworkInformation.GetHostNames()) 110 | { 111 | if (localHostName.IPInformation != null && 112 | ((ipv4 && localHostName.Type == HostNameType.Ipv4) || 113 | (ipv6 && localHostName.Type == HostNameType.Ipv6))) 114 | { 115 | targetList.Add(localHostName.ToString()); 116 | } 117 | } 118 | #else 119 | try 120 | { 121 | foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces()) 122 | { 123 | //Skip loopback and disabled network interfaces 124 | if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback || 125 | ni.OperationalStatus != OperationalStatus.Up) 126 | continue; 127 | 128 | var ipProps = ni.GetIPProperties(); 129 | 130 | //Skip address without gateway 131 | if (ipProps.GatewayAddresses.Count == 0) 132 | continue; 133 | 134 | foreach (UnicastIPAddressInformation ip in ipProps.UnicastAddresses) 135 | { 136 | var address = ip.Address; 137 | if ((ipv4 && address.AddressFamily == AddressFamily.InterNetwork) || 138 | (ipv6 && address.AddressFamily == AddressFamily.InterNetworkV6)) 139 | targetList.Add(address.ToString()); 140 | } 141 | } 142 | } 143 | catch 144 | { 145 | //ignored 146 | } 147 | 148 | //Fallback mode (unity android) 149 | if (targetList.Count == 0) 150 | { 151 | #if NETCORE 152 | var hostTask = Dns.GetHostEntryAsync(Dns.GetHostName()); 153 | hostTask.Wait(); 154 | var host = hostTask.Result; 155 | #else 156 | var host = Dns.GetHostEntry(Dns.GetHostName()); 157 | #endif 158 | foreach (IPAddress ip in host.AddressList) 159 | { 160 | if((ipv4 && ip.AddressFamily == AddressFamily.InterNetwork) || 161 | (ipv6 && ip.AddressFamily == AddressFamily.InterNetworkV6)) 162 | targetList.Add(ip.ToString()); 163 | } 164 | } 165 | #endif 166 | if (targetList.Count == 0) 167 | { 168 | if(ipv4) 169 | targetList.Add("127.0.0.1"); 170 | if(ipv6) 171 | targetList.Add("::1"); 172 | } 173 | } 174 | 175 | private static readonly List IpList = new List(); 176 | /// 177 | /// Get first detected local ip address 178 | /// 179 | /// type of address (IPv4, IPv6 or both) 180 | /// IP address if available. Else - string.Empty 181 | public static string GetLocalIp(LocalAddrType addrType) 182 | { 183 | lock (IpList) 184 | { 185 | IpList.Clear(); 186 | GetLocalIpList(IpList, addrType); 187 | return IpList.Count == 0 ? string.Empty : IpList[0]; 188 | } 189 | } 190 | 191 | // =========================================== 192 | // Internal and debug log related stuff 193 | // =========================================== 194 | internal static void PrintInterfaceInfos() 195 | { 196 | #if !WINRT || UNITY_EDITOR 197 | DebugWriteForce(ConsoleColor.Green, "IPv6Support: {0}", NetSocket.IPv6Support); 198 | try 199 | { 200 | foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces()) 201 | { 202 | foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses) 203 | { 204 | if (ip.Address.AddressFamily == AddressFamily.InterNetwork || 205 | ip.Address.AddressFamily == AddressFamily.InterNetworkV6) 206 | { 207 | DebugWriteForce( 208 | ConsoleColor.Green, 209 | "Interface: {0}, Type: {1}, Ip: {2}, OpStatus: {3}", 210 | ni.Name, 211 | ni.NetworkInterfaceType.ToString(), 212 | ip.Address.ToString(), 213 | ni.OperationalStatus.ToString()); 214 | } 215 | } 216 | } 217 | } 218 | catch (Exception e) 219 | { 220 | DebugWriteForce(ConsoleColor.Red, "Error while getting interface infos: {0}", e.ToString()); 221 | } 222 | #endif 223 | } 224 | 225 | internal static int RelativeSequenceNumber(int number, int expected) 226 | { 227 | return (number - expected + NetConstants.MaxSequence + NetConstants.HalfMaxSequence) % NetConstants.MaxSequence - NetConstants.HalfMaxSequence; 228 | } 229 | 230 | private static readonly object DebugLogLock = new object(); 231 | private static void DebugWriteLogic(ConsoleColor color, string str, params object[] args) 232 | { 233 | lock (DebugLogLock) 234 | { 235 | 236 | if (NetDebug.Logger == null) 237 | { 238 | #if UNITY 239 | UnityEngine.Debug.Log(string.Format(str, args)); 240 | #elif WINRT 241 | Debug.WriteLine(str, args); 242 | #else 243 | //Console.ForegroundColor = color; 244 | Console.WriteLine(str, args); 245 | //Console.ForegroundColor = ConsoleColor.Gray; 246 | #endif 247 | } 248 | else 249 | { 250 | NetDebug.Logger.WriteNet(color, str, args); 251 | } 252 | } 253 | } 254 | 255 | [Conditional("DEBUG_MESSAGES")] 256 | internal static void DebugWrite(string str, params object[] args) 257 | { 258 | DebugWriteLogic(ConsoleColor.DarkGreen, str, args); 259 | } 260 | 261 | [Conditional("DEBUG_MESSAGES")] 262 | internal static void DebugWrite(ConsoleColor color, string str, params object[] args) 263 | { 264 | DebugWriteLogic(color, str, args); 265 | } 266 | 267 | [Conditional("DEBUG_MESSAGES"), Conditional("DEBUG")] 268 | internal static void DebugWriteForce(ConsoleColor color, string str, params object[] args) 269 | { 270 | DebugWriteLogic(color, str, args); 271 | } 272 | 273 | [Conditional("DEBUG_MESSAGES"), Conditional("DEBUG")] 274 | internal static void DebugWriteError(string str, params object[] args) 275 | { 276 | DebugWriteLogic(ConsoleColor.Red, str, args); 277 | } 278 | } 279 | } 280 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/LiteNetLib/ReliableChannel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | 5 | namespace LiteNetLib 6 | { 7 | internal sealed class ReliableChannel 8 | { 9 | private sealed class PendingPacket 10 | { 11 | public NetPacket Packet; 12 | public DateTime? TimeStamp; 13 | public PendingPacket Next; 14 | public PendingPacket Prev; 15 | 16 | public void Clear() 17 | { 18 | if (Prev != null) 19 | { 20 | Prev.Next = Next; 21 | } 22 | if (Next != null) 23 | { 24 | Next.Prev = Prev; 25 | } 26 | Prev = null; 27 | Next = null; 28 | Packet = null; 29 | TimeStamp = null; 30 | } 31 | } 32 | 33 | private readonly Queue _outgoingPackets; 34 | private readonly bool[] _outgoingAcks; //for send acks 35 | private readonly PendingPacket[] _pendingPackets; //for unacked packets and duplicates 36 | private readonly NetPacket[] _receivedPackets; //for order 37 | private readonly bool[] _earlyReceived; //for unordered 38 | private PendingPacket _headPendingPacket; 39 | 40 | private int _localSeqence; 41 | private int _remoteSequence; 42 | private int _localWindowStart; 43 | private int _remoteWindowStart; 44 | 45 | private readonly NetPeer _peer; 46 | private bool _mustSendAcks; 47 | 48 | private readonly bool _ordered; 49 | private readonly int _windowSize; 50 | private const int BitsInByte = 8; 51 | 52 | public int PacketsInQueue 53 | { 54 | get { return _outgoingPackets.Count; } 55 | } 56 | 57 | public ReliableChannel(NetPeer peer, bool ordered) 58 | { 59 | _windowSize = NetConstants.DefaultWindowSize; 60 | _peer = peer; 61 | _ordered = ordered; 62 | 63 | _outgoingPackets = new Queue(_windowSize); 64 | 65 | _outgoingAcks = new bool[_windowSize]; 66 | _pendingPackets = new PendingPacket[_windowSize]; 67 | for (int i = 0; i < _pendingPackets.Length; i++) 68 | { 69 | _pendingPackets[i] = new PendingPacket(); 70 | } 71 | 72 | if (_ordered) 73 | _receivedPackets = new NetPacket[_windowSize]; 74 | else 75 | _earlyReceived = new bool[_windowSize]; 76 | 77 | _localWindowStart = 0; 78 | _localSeqence = 0; 79 | _remoteSequence = 0; 80 | _remoteWindowStart = 0; 81 | } 82 | 83 | //ProcessAck in packet 84 | public void ProcessAck(NetPacket packet) 85 | { 86 | int validPacketSize = (_windowSize - 1) / BitsInByte + 1 + NetConstants.SequencedHeaderSize; 87 | if (packet.Size != validPacketSize) 88 | { 89 | NetUtils.DebugWrite("[PA]Invalid acks packet size"); 90 | return; 91 | } 92 | 93 | ushort ackWindowStart = packet.Sequence; 94 | if (ackWindowStart > NetConstants.MaxSequence) 95 | { 96 | NetUtils.DebugWrite("[PA]Bad window start"); 97 | return; 98 | } 99 | 100 | //check relevance 101 | if (NetUtils.RelativeSequenceNumber(ackWindowStart, _localWindowStart) <= -_windowSize) 102 | { 103 | NetUtils.DebugWrite("[PA]Old acks"); 104 | return; 105 | } 106 | 107 | byte[] acksData = packet.RawData; 108 | NetUtils.DebugWrite("[PA]AcksStart: {0}", ackWindowStart); 109 | int startByte = NetConstants.SequencedHeaderSize; 110 | 111 | Monitor.Enter(_pendingPackets); 112 | for (int i = 0; i < _windowSize; i++) 113 | { 114 | int ackSequence = (ackWindowStart + i) % NetConstants.MaxSequence; 115 | if (NetUtils.RelativeSequenceNumber(ackSequence, _localWindowStart) < 0) 116 | { 117 | //NetUtils.DebugWrite(ConsoleColor.Cyan, "[PA] SKIP OLD: " + ackSequence); 118 | //Skip old ack 119 | continue; 120 | } 121 | 122 | int currentByte = startByte + i / BitsInByte; 123 | int currentBit = i % BitsInByte; 124 | 125 | if ((acksData[currentByte] & (1 << currentBit)) == 0) 126 | { 127 | #if STATS_ENABLED || DEBUG 128 | if(_pendingPackets[ackSequence % _windowSize].TimeStamp.HasValue) 129 | _peer.Statistics.PacketLoss++; 130 | #endif 131 | //NetUtils.DebugWrite(ConsoleColor.Cyan, "[PA] SKIP FALSE: " + ackSequence); 132 | //Skip false ack 133 | continue; 134 | } 135 | 136 | if (ackSequence == _localWindowStart) 137 | { 138 | //Move window 139 | _localWindowStart = (_localWindowStart + 1) % NetConstants.MaxSequence; 140 | } 141 | 142 | PendingPacket pendingPacket = _pendingPackets[ackSequence % _windowSize]; 143 | if (pendingPacket.Packet != null) 144 | { 145 | if (pendingPacket == _headPendingPacket) 146 | { 147 | _headPendingPacket = _headPendingPacket.Prev; 148 | } 149 | _peer.Recycle(pendingPacket.Packet); 150 | pendingPacket.Clear(); 151 | NetUtils.DebugWrite("[PA]Removing reliableInOrder ack: {0} - true", ackSequence); 152 | } 153 | else 154 | { 155 | NetUtils.DebugWrite("[PA]Removing reliableInOrder ack: {0} - false", ackSequence); 156 | } 157 | } 158 | Monitor.Exit(_pendingPackets); 159 | } 160 | 161 | public void AddToQueue(NetPacket packet) 162 | { 163 | Monitor.Enter(_outgoingPackets); 164 | _outgoingPackets.Enqueue(packet); 165 | Monitor.Exit(_outgoingPackets); 166 | } 167 | 168 | public void SendNextPackets() 169 | { 170 | //check sending acks 171 | DateTime currentTime = DateTime.UtcNow; 172 | Monitor.Enter(_pendingPackets); 173 | //get packets from queue 174 | Monitor.Enter(_outgoingPackets); 175 | while (_outgoingPackets.Count > 0) 176 | { 177 | int relate = NetUtils.RelativeSequenceNumber(_localSeqence, _localWindowStart); 178 | if (relate < _windowSize) 179 | { 180 | PendingPacket pendingPacket = _pendingPackets[_localSeqence % _windowSize]; 181 | pendingPacket.Packet = _outgoingPackets.Dequeue(); 182 | pendingPacket.Packet.Sequence = (ushort) _localSeqence; 183 | if (_headPendingPacket != null) 184 | { 185 | _headPendingPacket.Next = pendingPacket; 186 | pendingPacket.Prev = _headPendingPacket; 187 | } 188 | _headPendingPacket = pendingPacket; 189 | _localSeqence = (_localSeqence + 1) % NetConstants.MaxSequence; 190 | } 191 | else //Queue filled 192 | { 193 | break; 194 | } 195 | } 196 | Monitor.Exit(_outgoingPackets); 197 | 198 | //if no pending packets return 199 | if (_headPendingPacket == null) 200 | { 201 | Monitor.Exit(_pendingPackets); 202 | return; 203 | } 204 | //send 205 | PendingPacket currentPacket = _headPendingPacket; 206 | do 207 | { 208 | if (currentPacket.TimeStamp.HasValue) //check send time 209 | { 210 | double packetHoldTime = (currentTime - currentPacket.TimeStamp.Value).TotalMilliseconds; 211 | if (packetHoldTime < _peer.ResendDelay) 212 | { 213 | continue; 214 | } 215 | NetUtils.DebugWrite("[RC]Resend: {0} > {1}", (int)packetHoldTime, _peer.ResendDelay); 216 | } 217 | 218 | currentPacket.TimeStamp = currentTime; 219 | _peer.SendRawData(currentPacket.Packet); 220 | } while ((currentPacket = currentPacket.Prev) != null); 221 | Monitor.Exit(_pendingPackets); 222 | } 223 | 224 | public void SendAcks() 225 | { 226 | if (!_mustSendAcks) 227 | return; 228 | _mustSendAcks = false; 229 | 230 | NetUtils.DebugWrite("[RR]SendAcks"); 231 | 232 | //Init packet 233 | int bytesCount = (_windowSize - 1) / BitsInByte + 1; 234 | PacketProperty property = _ordered ? PacketProperty.AckReliableOrdered : PacketProperty.AckReliable; 235 | var acksPacket = _peer.GetPacketFromPool(property, bytesCount); 236 | 237 | //For quick access 238 | byte[] data = acksPacket.RawData; //window start + acks size 239 | 240 | //Put window start 241 | Monitor.Enter(_outgoingAcks); 242 | acksPacket.Sequence = (ushort)_remoteWindowStart; 243 | 244 | //Put acks 245 | int startAckIndex = _remoteWindowStart % _windowSize; 246 | int currentAckIndex = startAckIndex; 247 | int currentBit = 0; 248 | int currentByte = NetConstants.SequencedHeaderSize; 249 | do 250 | { 251 | if (_outgoingAcks[currentAckIndex]) 252 | { 253 | data[currentByte] |= (byte)(1 << currentBit); 254 | } 255 | 256 | currentBit++; 257 | if (currentBit == BitsInByte) 258 | { 259 | currentByte++; 260 | currentBit = 0; 261 | } 262 | currentAckIndex = (currentAckIndex + 1) % _windowSize; 263 | } while (currentAckIndex != startAckIndex); 264 | Monitor.Exit(_outgoingAcks); 265 | 266 | _peer.SendRawData(acksPacket); 267 | _peer.Recycle(acksPacket); 268 | } 269 | 270 | //Process incoming packet 271 | public void ProcessPacket(NetPacket packet) 272 | { 273 | if (packet.Sequence >= NetConstants.MaxSequence) 274 | { 275 | NetUtils.DebugWrite("[RR]Bad sequence"); 276 | return; 277 | } 278 | 279 | int relate = NetUtils.RelativeSequenceNumber(packet.Sequence, _remoteWindowStart); 280 | int relateSeq = NetUtils.RelativeSequenceNumber(packet.Sequence, _remoteSequence); 281 | 282 | if (relateSeq > _windowSize) 283 | { 284 | NetUtils.DebugWrite("[RR]Bad sequence"); 285 | return; 286 | } 287 | 288 | //Drop bad packets 289 | if(relate < 0) 290 | { 291 | //Too old packet doesn't ack 292 | NetUtils.DebugWrite("[RR]ReliableInOrder too old"); 293 | return; 294 | } 295 | if (relate >= _windowSize * 2) 296 | { 297 | //Some very new packet 298 | NetUtils.DebugWrite("[RR]ReliableInOrder too new"); 299 | return; 300 | } 301 | 302 | //If very new - move window 303 | Monitor.Enter(_outgoingAcks); 304 | if (relate >= _windowSize) 305 | { 306 | //New window position 307 | int newWindowStart = (_remoteWindowStart + relate - _windowSize + 1) % NetConstants.MaxSequence; 308 | 309 | //Clean old data 310 | while (_remoteWindowStart != newWindowStart) 311 | { 312 | _outgoingAcks[_remoteWindowStart % _windowSize] = false; 313 | _remoteWindowStart = (_remoteWindowStart + 1) % NetConstants.MaxSequence; 314 | } 315 | } 316 | 317 | //Final stage - process valid packet 318 | //trigger acks send 319 | _mustSendAcks = true; 320 | 321 | if (_outgoingAcks[packet.Sequence % _windowSize]) 322 | { 323 | NetUtils.DebugWrite("[RR]ReliableInOrder duplicate"); 324 | Monitor.Exit(_outgoingAcks); 325 | return; 326 | } 327 | 328 | //save ack 329 | _outgoingAcks[packet.Sequence % _windowSize] = true; 330 | Monitor.Exit(_outgoingAcks); 331 | 332 | //detailed check 333 | if (packet.Sequence == _remoteSequence) 334 | { 335 | NetUtils.DebugWrite("[RR]ReliableInOrder packet succes"); 336 | _peer.AddIncomingPacket(packet); 337 | _remoteSequence = (_remoteSequence + 1) % NetConstants.MaxSequence; 338 | 339 | if (_ordered) 340 | { 341 | NetPacket p; 342 | while ( (p = _receivedPackets[_remoteSequence % _windowSize]) != null) 343 | { 344 | //process holded packet 345 | _receivedPackets[_remoteSequence % _windowSize] = null; 346 | _peer.AddIncomingPacket(p); 347 | _remoteSequence = (_remoteSequence + 1) % NetConstants.MaxSequence; 348 | } 349 | } 350 | else 351 | { 352 | while (_earlyReceived[_remoteSequence % _windowSize]) 353 | { 354 | //process early packet 355 | _earlyReceived[_remoteSequence % _windowSize] = false; 356 | _remoteSequence = (_remoteSequence + 1) % NetConstants.MaxSequence; 357 | } 358 | } 359 | 360 | return; 361 | } 362 | 363 | //holded packet 364 | if (_ordered) 365 | { 366 | _receivedPackets[packet.Sequence % _windowSize] = packet; 367 | } 368 | else 369 | { 370 | _earlyReceived[packet.Sequence % _windowSize] = true; 371 | _peer.AddIncomingPacket(packet); 372 | } 373 | } 374 | } 375 | } 376 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/LiteNetLib/SequencedChannel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace LiteNetLib 4 | { 5 | internal sealed class SequencedChannel 6 | { 7 | private int _localSequence; 8 | private int _remoteSequence; 9 | private readonly Queue _outgoingPackets; 10 | private readonly NetPeer _peer; 11 | 12 | public SequencedChannel(NetPeer peer) 13 | { 14 | _outgoingPackets = new Queue(); 15 | _peer = peer; 16 | } 17 | 18 | public void AddToQueue(NetPacket packet) 19 | { 20 | lock (_outgoingPackets) 21 | { 22 | _outgoingPackets.Enqueue(packet); 23 | } 24 | } 25 | 26 | public void SendNextPackets() 27 | { 28 | lock (_outgoingPackets) 29 | { 30 | while (_outgoingPackets.Count > 0) 31 | { 32 | NetPacket packet = _outgoingPackets.Dequeue(); 33 | _localSequence = (_localSequence + 1) % NetConstants.MaxSequence; 34 | packet.Sequence = (ushort)_localSequence; 35 | _peer.SendRawData(packet); 36 | _peer.Recycle(packet); 37 | } 38 | } 39 | } 40 | 41 | public void ProcessPacket(NetPacket packet) 42 | { 43 | if (packet.Sequence < NetConstants.MaxSequence && 44 | NetUtils.RelativeSequenceNumber(packet.Sequence, _remoteSequence) > 0) 45 | { 46 | _remoteSequence = packet.Sequence; 47 | _peer.AddIncomingPacket(packet); 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/LiteNetLib/SimpleChannel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace LiteNetLib 4 | { 5 | internal sealed class SimpleChannel 6 | { 7 | private readonly Queue _outgoingPackets; 8 | private readonly NetPeer _peer; 9 | 10 | public SimpleChannel(NetPeer peer) 11 | { 12 | _outgoingPackets = new Queue(); 13 | _peer = peer; 14 | } 15 | 16 | public void AddToQueue(NetPacket packet) 17 | { 18 | lock (_outgoingPackets) 19 | { 20 | _outgoingPackets.Enqueue(packet); 21 | } 22 | } 23 | 24 | public bool SendNextPackets() 25 | { 26 | NetPacket packet; 27 | lock (_outgoingPackets) 28 | { 29 | while (_outgoingPackets.Count > 0) 30 | { 31 | packet = _outgoingPackets.Dequeue(); 32 | _peer.SendRawData(packet); 33 | _peer.Recycle(packet); 34 | } 35 | } 36 | return true; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/LiteNetLib/Utils/FastBitConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace LiteNetLib.Utils 4 | { 5 | public static class FastBitConverter 6 | { 7 | [StructLayout(LayoutKind.Explicit)] 8 | private struct ConverterHelperDouble 9 | { 10 | [FieldOffset(0)] 11 | public ulong Along; 12 | 13 | [FieldOffset(0)] 14 | public double Adouble; 15 | } 16 | 17 | [StructLayout(LayoutKind.Explicit)] 18 | private struct ConverterHelperFloat 19 | { 20 | [FieldOffset(0)] 21 | public int Aint; 22 | 23 | [FieldOffset(0)] 24 | public float Afloat; 25 | } 26 | 27 | private static void WriteLittleEndian(byte[] buffer, int offset, ulong data) 28 | { 29 | #if BIGENDIAN 30 | buffer[offset + 7] = (byte)(data); 31 | buffer[offset + 6] = (byte)(data >> 8); 32 | buffer[offset + 5] = (byte)(data >> 16); 33 | buffer[offset + 4] = (byte)(data >> 24); 34 | buffer[offset + 3] = (byte)(data >> 32); 35 | buffer[offset + 2] = (byte)(data >> 40); 36 | buffer[offset + 1] = (byte)(data >> 48); 37 | buffer[offset ] = (byte)(data >> 56); 38 | #else 39 | buffer[offset] = (byte)(data); 40 | buffer[offset + 1] = (byte)(data >> 8); 41 | buffer[offset + 2] = (byte)(data >> 16); 42 | buffer[offset + 3] = (byte)(data >> 24); 43 | buffer[offset + 4] = (byte)(data >> 32); 44 | buffer[offset + 5] = (byte)(data >> 40); 45 | buffer[offset + 6] = (byte)(data >> 48); 46 | buffer[offset + 7] = (byte)(data >> 56); 47 | #endif 48 | } 49 | 50 | private static void WriteLittleEndian(byte[] buffer, int offset, int data) 51 | { 52 | #if BIGENDIAN 53 | buffer[offset + 3] = (byte)(data); 54 | buffer[offset + 2] = (byte)(data >> 8); 55 | buffer[offset + 1] = (byte)(data >> 16); 56 | buffer[offset ] = (byte)(data >> 24); 57 | #else 58 | buffer[offset] = (byte)(data); 59 | buffer[offset + 1] = (byte)(data >> 8); 60 | buffer[offset + 2] = (byte)(data >> 16); 61 | buffer[offset + 3] = (byte)(data >> 24); 62 | #endif 63 | } 64 | 65 | public static void WriteLittleEndian(byte[] buffer, int offset, short data) 66 | { 67 | #if BIGENDIAN 68 | buffer[offset + 1] = (byte)(data); 69 | buffer[offset ] = (byte)(data >> 8); 70 | #else 71 | buffer[offset] = (byte)(data); 72 | buffer[offset + 1] = (byte)(data >> 8); 73 | #endif 74 | } 75 | 76 | public static void GetBytes(byte[] bytes, int startIndex, double value) 77 | { 78 | ConverterHelperDouble ch = new ConverterHelperDouble { Adouble = value }; 79 | WriteLittleEndian(bytes, startIndex, ch.Along); 80 | } 81 | 82 | public static void GetBytes(byte[] bytes, int startIndex, float value) 83 | { 84 | ConverterHelperFloat ch = new ConverterHelperFloat { Afloat = value }; 85 | WriteLittleEndian(bytes, startIndex, ch.Aint); 86 | } 87 | 88 | public static void GetBytes(byte[] bytes, int startIndex, short value) 89 | { 90 | WriteLittleEndian(bytes, startIndex, value); 91 | } 92 | 93 | public static void GetBytes(byte[] bytes, int startIndex, ushort value) 94 | { 95 | WriteLittleEndian(bytes, startIndex, (short)value); 96 | } 97 | 98 | public static void GetBytes(byte[] bytes, int startIndex, int value) 99 | { 100 | WriteLittleEndian(bytes, startIndex, value); 101 | } 102 | 103 | public static void GetBytes(byte[] bytes, int startIndex, uint value) 104 | { 105 | WriteLittleEndian(bytes, startIndex, (int)value); 106 | } 107 | 108 | public static void GetBytes(byte[] bytes, int startIndex, long value) 109 | { 110 | WriteLittleEndian(bytes, startIndex, (ulong)value); 111 | } 112 | 113 | public static void GetBytes(byte[] bytes, int startIndex, ulong value) 114 | { 115 | WriteLittleEndian(bytes, startIndex, value); 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/LiteNetLib/Utils/NetDataReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace LiteNetLib.Utils 5 | { 6 | public class NetDataReader 7 | { 8 | protected byte[] _data; 9 | protected int _position; 10 | protected int _dataSize; 11 | 12 | public byte[] Data 13 | { 14 | get { return _data; } 15 | } 16 | 17 | public int Position 18 | { 19 | get { return _position; } 20 | } 21 | 22 | public bool EndOfData 23 | { 24 | get { return _position == _dataSize; } 25 | } 26 | 27 | public int AvailableBytes 28 | { 29 | get { return _dataSize - _position; } 30 | } 31 | 32 | public void SetSource(NetDataWriter dataWriter) 33 | { 34 | _data = dataWriter.Data; 35 | _position = 0; 36 | _dataSize = dataWriter.Length; 37 | } 38 | 39 | public void SetSource(byte[] source) 40 | { 41 | _data = source; 42 | _position = 0; 43 | _dataSize = source.Length; 44 | } 45 | 46 | public void SetSource(byte[] source, int offset) 47 | { 48 | _data = source; 49 | _position = offset; 50 | _dataSize = source.Length; 51 | } 52 | 53 | public void SetSource(byte[] source, int offset, int dataSize) 54 | { 55 | _data = source; 56 | _position = offset; 57 | _dataSize = dataSize; 58 | } 59 | 60 | /// 61 | /// Clone NetDataReader without data copy (usable for OnReceive) 62 | /// 63 | /// new NetDataReader instance 64 | public NetDataReader Clone() 65 | { 66 | return new NetDataReader(_data, _position, _dataSize); 67 | } 68 | 69 | public NetDataReader() 70 | { 71 | 72 | } 73 | 74 | public NetDataReader(byte[] source) 75 | { 76 | SetSource(source); 77 | } 78 | 79 | public NetDataReader(byte[] source, int offset) 80 | { 81 | SetSource(source, offset); 82 | } 83 | 84 | public NetDataReader(byte[] source, int offset, int maxSize) 85 | { 86 | SetSource(source, offset, maxSize); 87 | } 88 | 89 | #region GetMethods 90 | public NetEndPoint GetNetEndPoint() 91 | { 92 | string host = GetString(1000); 93 | int port = GetInt(); 94 | return new NetEndPoint(host, port); 95 | } 96 | 97 | public byte GetByte() 98 | { 99 | byte res = _data[_position]; 100 | _position += 1; 101 | return res; 102 | } 103 | 104 | public sbyte GetSByte() 105 | { 106 | var b = (sbyte)_data[_position]; 107 | _position++; 108 | return b; 109 | } 110 | 111 | public bool[] GetBoolArray() 112 | { 113 | ushort size = BitConverter.ToUInt16(_data, _position); 114 | _position += 2; 115 | var arr = new bool[size]; 116 | for (int i = 0; i < size; i++) 117 | { 118 | arr[i] = GetBool(); 119 | } 120 | return arr; 121 | } 122 | 123 | public ushort[] GetUShortArray() 124 | { 125 | ushort size = BitConverter.ToUInt16(_data, _position); 126 | _position += 2; 127 | var arr = new ushort[size]; 128 | for (int i = 0; i < size; i++) 129 | { 130 | arr[i] = GetUShort(); 131 | } 132 | return arr; 133 | } 134 | 135 | public short[] GetShortArray() 136 | { 137 | ushort size = BitConverter.ToUInt16(_data, _position); 138 | _position += 2; 139 | var arr = new short[size]; 140 | for (int i = 0; i < size; i++) 141 | { 142 | arr[i] = GetShort(); 143 | } 144 | return arr; 145 | } 146 | 147 | public long[] GetLongArray() 148 | { 149 | ushort size = BitConverter.ToUInt16(_data, _position); 150 | _position += 2; 151 | var arr = new long[size]; 152 | for (int i = 0; i < size; i++) 153 | { 154 | arr[i] = GetLong(); 155 | } 156 | return arr; 157 | } 158 | 159 | public ulong[] GetULongArray() 160 | { 161 | ushort size = BitConverter.ToUInt16(_data, _position); 162 | _position += 2; 163 | var arr = new ulong[size]; 164 | for (int i = 0; i < size; i++) 165 | { 166 | arr[i] = GetULong(); 167 | } 168 | return arr; 169 | } 170 | 171 | public int[] GetIntArray() 172 | { 173 | ushort size = BitConverter.ToUInt16(_data, _position); 174 | _position += 2; 175 | var arr = new int[size]; 176 | for (int i = 0; i < size; i++) 177 | { 178 | arr[i] = GetInt(); 179 | } 180 | return arr; 181 | } 182 | 183 | public uint[] GetUIntArray() 184 | { 185 | ushort size = BitConverter.ToUInt16(_data, _position); 186 | _position += 2; 187 | var arr = new uint[size]; 188 | for (int i = 0; i < size; i++) 189 | { 190 | arr[i] = GetUInt(); 191 | } 192 | return arr; 193 | } 194 | 195 | public float[] GetFloatArray() 196 | { 197 | ushort size = BitConverter.ToUInt16(_data, _position); 198 | _position += 2; 199 | var arr = new float[size]; 200 | for (int i = 0; i < size; i++) 201 | { 202 | arr[i] = GetFloat(); 203 | } 204 | return arr; 205 | } 206 | 207 | public double[] GetDoubleArray() 208 | { 209 | ushort size = BitConverter.ToUInt16(_data, _position); 210 | _position += 2; 211 | var arr = new double[size]; 212 | for (int i = 0; i < size; i++) 213 | { 214 | arr[i] = GetDouble(); 215 | } 216 | return arr; 217 | } 218 | 219 | public string[] GetStringArray(int maxLength) 220 | { 221 | ushort size = BitConverter.ToUInt16(_data, _position); 222 | _position += 2; 223 | var arr = new string[size]; 224 | for (int i = 0; i < size; i++) 225 | { 226 | arr[i] = GetString(maxLength); 227 | } 228 | return arr; 229 | } 230 | 231 | public bool GetBool() 232 | { 233 | bool res = _data[_position] > 0; 234 | _position += 1; 235 | return res; 236 | } 237 | 238 | public char GetChar() 239 | { 240 | char result = BitConverter.ToChar(_data, _position); 241 | _position += 2; 242 | return result; 243 | } 244 | 245 | public ushort GetUShort() 246 | { 247 | ushort result = BitConverter.ToUInt16(_data, _position); 248 | _position += 2; 249 | return result; 250 | } 251 | 252 | public short GetShort() 253 | { 254 | short result = BitConverter.ToInt16(_data, _position); 255 | _position += 2; 256 | return result; 257 | } 258 | 259 | public long GetLong() 260 | { 261 | long result = BitConverter.ToInt64(_data, _position); 262 | _position += 8; 263 | return result; 264 | } 265 | 266 | public ulong GetULong() 267 | { 268 | ulong result = BitConverter.ToUInt64(_data, _position); 269 | _position += 8; 270 | return result; 271 | } 272 | 273 | public int GetInt() 274 | { 275 | int result = BitConverter.ToInt32(_data, _position); 276 | _position += 4; 277 | return result; 278 | } 279 | 280 | public uint GetUInt() 281 | { 282 | uint result = BitConverter.ToUInt32(_data, _position); 283 | _position += 4; 284 | return result; 285 | } 286 | 287 | public float GetFloat() 288 | { 289 | float result = BitConverter.ToSingle(_data, _position); 290 | _position += 4; 291 | return result; 292 | } 293 | 294 | public double GetDouble() 295 | { 296 | double result = BitConverter.ToDouble(_data, _position); 297 | _position += 8; 298 | return result; 299 | } 300 | 301 | public string GetString(int maxLength) 302 | { 303 | int bytesCount = GetInt(); 304 | if (bytesCount <= 0 || bytesCount > maxLength*2) 305 | { 306 | return string.Empty; 307 | } 308 | 309 | int charCount = Encoding.UTF8.GetCharCount(_data, _position, bytesCount); 310 | if (charCount > maxLength) 311 | { 312 | return string.Empty; 313 | } 314 | 315 | string result = Encoding.UTF8.GetString(_data, _position, bytesCount); 316 | _position += bytesCount; 317 | return result; 318 | } 319 | 320 | public string GetString() 321 | { 322 | int bytesCount = GetInt(); 323 | if (bytesCount <= 0) 324 | { 325 | return string.Empty; 326 | } 327 | 328 | string result = Encoding.UTF8.GetString(_data, _position, bytesCount); 329 | _position += bytesCount; 330 | return result; 331 | } 332 | 333 | public byte[] GetRemainingBytes() 334 | { 335 | byte[] outgoingData = new byte[AvailableBytes]; 336 | Buffer.BlockCopy(_data, _position, outgoingData, 0, AvailableBytes); 337 | _position = _data.Length; 338 | return outgoingData; 339 | } 340 | 341 | public void GetRemainingBytes(byte[] destination) 342 | { 343 | Buffer.BlockCopy(_data, _position, destination, 0, AvailableBytes); 344 | _position = _data.Length; 345 | } 346 | 347 | public void GetBytes(byte[] destination, int lenght) 348 | { 349 | Buffer.BlockCopy(_data, _position, destination, 0, lenght); 350 | _position += lenght; 351 | } 352 | 353 | public byte[] GetBytesWithLength() 354 | { 355 | int length = GetInt(); 356 | byte[] outgoingData = new byte[length]; 357 | Buffer.BlockCopy(_data, _position, outgoingData, 0, length); 358 | _position += length; 359 | return outgoingData; 360 | } 361 | #endregion 362 | 363 | #region PeekMethods 364 | 365 | public byte PeekByte() 366 | { 367 | return _data[_position]; 368 | } 369 | 370 | public sbyte PeekSByte() 371 | { 372 | return (sbyte)_data[_position]; 373 | } 374 | 375 | public bool PeekBool() 376 | { 377 | return _data[_position] > 0; 378 | } 379 | 380 | public char PeekChar() 381 | { 382 | return BitConverter.ToChar(_data, _position); 383 | } 384 | 385 | public ushort PeekUShort() 386 | { 387 | return BitConverter.ToUInt16(_data, _position); 388 | } 389 | 390 | public short PeekShort() 391 | { 392 | return BitConverter.ToInt16(_data, _position); 393 | } 394 | 395 | public long PeekLong() 396 | { 397 | return BitConverter.ToInt64(_data, _position); 398 | } 399 | 400 | public ulong PeekULong() 401 | { 402 | return BitConverter.ToUInt64(_data, _position); 403 | } 404 | 405 | public int PeekInt() 406 | { 407 | return BitConverter.ToInt32(_data, _position); 408 | } 409 | 410 | public uint PeekUInt() 411 | { 412 | return BitConverter.ToUInt32(_data, _position); 413 | } 414 | 415 | public float PeekFloat() 416 | { 417 | return BitConverter.ToSingle(_data, _position); 418 | } 419 | 420 | public double PeekDouble() 421 | { 422 | return BitConverter.ToDouble(_data, _position); 423 | } 424 | 425 | public string PeekString(int maxLength) 426 | { 427 | int bytesCount = BitConverter.ToInt32(_data, _position); 428 | if (bytesCount <= 0 || bytesCount > maxLength * 2) 429 | { 430 | return string.Empty; 431 | } 432 | 433 | int charCount = Encoding.UTF8.GetCharCount(_data, _position + 4, bytesCount); 434 | if (charCount > maxLength) 435 | { 436 | return string.Empty; 437 | } 438 | 439 | string result = Encoding.UTF8.GetString(_data, _position + 4, bytesCount); 440 | return result; 441 | } 442 | 443 | public string PeekString() 444 | { 445 | int bytesCount = BitConverter.ToInt32(_data, _position); 446 | if (bytesCount <= 0) 447 | { 448 | return string.Empty; 449 | } 450 | 451 | string result = Encoding.UTF8.GetString(_data, _position + 4, bytesCount); 452 | return result; 453 | } 454 | #endregion 455 | 456 | public void Clear() 457 | { 458 | _position = 0; 459 | _dataSize = 0; 460 | _data = null; 461 | } 462 | } 463 | } 464 | 465 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/LiteNetLib/Utils/NetDataWriter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace LiteNetLib.Utils 5 | { 6 | public class NetDataWriter 7 | { 8 | protected byte[] _data; 9 | protected int _position; 10 | 11 | private int _maxLength; 12 | private readonly bool _autoResize; 13 | 14 | public NetDataWriter() 15 | { 16 | _maxLength = 64; 17 | _data = new byte[_maxLength]; 18 | _autoResize = true; 19 | } 20 | 21 | public NetDataWriter(bool autoResize) 22 | { 23 | _maxLength = 64; 24 | _data = new byte[_maxLength]; 25 | _autoResize = autoResize; 26 | } 27 | 28 | public NetDataWriter(bool autoResize, int initialSize) 29 | { 30 | _maxLength = initialSize; 31 | _data = new byte[_maxLength]; 32 | _autoResize = autoResize; 33 | } 34 | 35 | public void ResizeIfNeed(int newSize) 36 | { 37 | if (_maxLength < newSize) 38 | { 39 | while (_maxLength < newSize) 40 | { 41 | _maxLength *= 2; 42 | } 43 | Array.Resize(ref _data, _maxLength); 44 | } 45 | } 46 | 47 | public void Reset(int size) 48 | { 49 | ResizeIfNeed(size); 50 | _position = 0; 51 | } 52 | 53 | public void Reset() 54 | { 55 | _position = 0; 56 | } 57 | 58 | public byte[] CopyData() 59 | { 60 | byte[] resultData = new byte[_position]; 61 | Buffer.BlockCopy(_data, 0, resultData, 0, _position); 62 | return resultData; 63 | } 64 | 65 | public byte[] Data 66 | { 67 | get { return _data; } 68 | } 69 | 70 | public int Length 71 | { 72 | get { return _position; } 73 | } 74 | 75 | public void Put(float value) 76 | { 77 | if (_autoResize) 78 | ResizeIfNeed(_position + 4); 79 | FastBitConverter.GetBytes(_data, _position, value); 80 | _position += 4; 81 | } 82 | 83 | public void Put(double value) 84 | { 85 | if (_autoResize) 86 | ResizeIfNeed(_position + 8); 87 | FastBitConverter.GetBytes(_data, _position, value); 88 | _position += 8; 89 | } 90 | 91 | public void Put(long value) 92 | { 93 | if (_autoResize) 94 | ResizeIfNeed(_position + 8); 95 | FastBitConverter.GetBytes(_data, _position, value); 96 | _position += 8; 97 | } 98 | 99 | public void Put(ulong value) 100 | { 101 | if (_autoResize) 102 | ResizeIfNeed(_position + 8); 103 | FastBitConverter.GetBytes(_data, _position, value); 104 | _position += 8; 105 | } 106 | 107 | public void Put(int value) 108 | { 109 | if (_autoResize) 110 | ResizeIfNeed(_position + 4); 111 | FastBitConverter.GetBytes(_data, _position, value); 112 | _position += 4; 113 | } 114 | 115 | public void Put(uint value) 116 | { 117 | if (_autoResize) 118 | ResizeIfNeed(_position + 4); 119 | FastBitConverter.GetBytes(_data, _position, value); 120 | _position += 4; 121 | } 122 | 123 | public void Put(char value) 124 | { 125 | if (_autoResize) 126 | ResizeIfNeed(_position + 2); 127 | FastBitConverter.GetBytes(_data, _position, value); 128 | _position += 2; 129 | } 130 | 131 | public void Put(ushort value) 132 | { 133 | if (_autoResize) 134 | ResizeIfNeed(_position + 2); 135 | FastBitConverter.GetBytes(_data, _position, value); 136 | _position += 2; 137 | } 138 | 139 | public void Put(short value) 140 | { 141 | if (_autoResize) 142 | ResizeIfNeed(_position + 2); 143 | FastBitConverter.GetBytes(_data, _position, value); 144 | _position += 2; 145 | } 146 | 147 | public void Put(sbyte value) 148 | { 149 | if (_autoResize) 150 | ResizeIfNeed(_position + 1); 151 | _data[_position] = (byte)value; 152 | _position++; 153 | } 154 | 155 | public void Put(byte value) 156 | { 157 | if (_autoResize) 158 | ResizeIfNeed(_position + 1); 159 | _data[_position] = value; 160 | _position++; 161 | } 162 | 163 | public void Put(byte[] data, int offset, int length) 164 | { 165 | if (_autoResize) 166 | ResizeIfNeed(_position + length); 167 | Buffer.BlockCopy(data, offset, _data, _position, length); 168 | _position += length; 169 | } 170 | 171 | public void Put(byte[] data) 172 | { 173 | if (_autoResize) 174 | ResizeIfNeed(_position + data.Length); 175 | Buffer.BlockCopy(data, 0, _data, _position, data.Length); 176 | _position += data.Length; 177 | } 178 | 179 | public void PutBytesWithLength(byte[] data, int offset, int length) 180 | { 181 | if (_autoResize) 182 | ResizeIfNeed(_position + length + 4); 183 | FastBitConverter.GetBytes(_data, _position, length); 184 | Buffer.BlockCopy(data, offset, _data, _position + 4, length); 185 | _position += length + 4; 186 | } 187 | 188 | public void PutBytesWithLength(byte[] data) 189 | { 190 | if (_autoResize) 191 | ResizeIfNeed(_position + data.Length + 4); 192 | FastBitConverter.GetBytes(_data, _position, data.Length); 193 | Buffer.BlockCopy(data, 0, _data, _position + 4, data.Length); 194 | _position += data.Length + 4; 195 | } 196 | 197 | public void Put(bool value) 198 | { 199 | if (_autoResize) 200 | ResizeIfNeed(_position + 1); 201 | _data[_position] = (byte)(value ? 1 : 0); 202 | _position++; 203 | } 204 | 205 | public void PutArray(float[] value) 206 | { 207 | ushort len = value == null ? (ushort)0 : (ushort)value.Length; 208 | if (_autoResize) 209 | ResizeIfNeed(_position + len * 4 + 2); 210 | Put(len); 211 | for (int i = 0; i < len; i++) 212 | { 213 | Put(value[i]); 214 | } 215 | } 216 | 217 | public void PutArray(double[] value) 218 | { 219 | ushort len = value == null ? (ushort)0 : (ushort)value.Length; 220 | if (_autoResize) 221 | ResizeIfNeed(_position + len * 8 + 2); 222 | Put(len); 223 | for (int i = 0; i < len; i++) 224 | { 225 | Put(value[i]); 226 | } 227 | } 228 | 229 | public void PutArray(long[] value) 230 | { 231 | ushort len = value == null ? (ushort)0 : (ushort)value.Length; 232 | if (_autoResize) 233 | ResizeIfNeed(_position + len * 8 + 2); 234 | Put(len); 235 | for (int i = 0; i < len; i++) 236 | { 237 | Put(value[i]); 238 | } 239 | } 240 | 241 | public void PutArray(ulong[] value) 242 | { 243 | ushort len = value == null ? (ushort)0 : (ushort)value.Length; 244 | if (_autoResize) 245 | ResizeIfNeed(_position + len * 8 + 2); 246 | Put(len); 247 | for (int i = 0; i < len; i++) 248 | { 249 | Put(value[i]); 250 | } 251 | } 252 | 253 | public void PutArray(int[] value) 254 | { 255 | ushort len = value == null ? (ushort)0 : (ushort)value.Length; 256 | if (_autoResize) 257 | ResizeIfNeed(_position + len * 4 + 2); 258 | Put(len); 259 | for (int i = 0; i < len; i++) 260 | { 261 | Put(value[i]); 262 | } 263 | } 264 | 265 | public void PutArray(uint[] value) 266 | { 267 | ushort len = value == null ? (ushort)0 : (ushort)value.Length; 268 | if (_autoResize) 269 | ResizeIfNeed(_position + len * 4 + 2); 270 | Put(len); 271 | for (int i = 0; i < len; i++) 272 | { 273 | Put(value[i]); 274 | } 275 | } 276 | 277 | public void PutArray(ushort[] value) 278 | { 279 | ushort len = value == null ? (ushort)0 : (ushort)value.Length; 280 | if (_autoResize) 281 | ResizeIfNeed(_position + len * 2 + 2); 282 | Put(len); 283 | for (int i = 0; i < len; i++) 284 | { 285 | Put(value[i]); 286 | } 287 | } 288 | 289 | public void PutArray(short[] value) 290 | { 291 | ushort len = value == null ? (ushort)0 : (ushort)value.Length; 292 | if (_autoResize) 293 | ResizeIfNeed(_position + len * 2 + 2); 294 | Put(len); 295 | for (int i = 0; i < len; i++) 296 | { 297 | Put(value[i]); 298 | } 299 | } 300 | 301 | public void PutArray(bool[] value) 302 | { 303 | ushort len = value == null ? (ushort)0 : (ushort)value.Length; 304 | if (_autoResize) 305 | ResizeIfNeed(_position + len + 2); 306 | Put(len); 307 | for (int i = 0; i < len; i++) 308 | { 309 | Put(value[i]); 310 | } 311 | } 312 | 313 | public void PutArray(string[] value) 314 | { 315 | ushort len = value == null ? (ushort)0 : (ushort)value.Length; 316 | Put(len); 317 | for (int i = 0; i < len; i++) 318 | { 319 | Put(value[i]); 320 | } 321 | } 322 | 323 | public void PutArray(string[] value, int maxLength) 324 | { 325 | ushort len = value == null ? (ushort)0 : (ushort)value.Length; 326 | Put(len); 327 | for (int i = 0; i < len; i++) 328 | { 329 | Put(value[i], maxLength); 330 | } 331 | } 332 | 333 | public void Put(NetEndPoint endPoint) 334 | { 335 | Put(endPoint.Host); 336 | Put(endPoint.Port); 337 | } 338 | 339 | public void Put(string value) 340 | { 341 | if (string.IsNullOrEmpty(value)) 342 | { 343 | Put(0); 344 | return; 345 | } 346 | 347 | //put bytes count 348 | int bytesCount = Encoding.UTF8.GetByteCount(value); 349 | if (_autoResize) 350 | ResizeIfNeed(_position + bytesCount + 4); 351 | Put(bytesCount); 352 | 353 | //put string 354 | Encoding.UTF8.GetBytes(value, 0, value.Length, _data, _position); 355 | _position += bytesCount; 356 | } 357 | 358 | public void Put(string value, int maxLength) 359 | { 360 | if (string.IsNullOrEmpty(value)) 361 | { 362 | Put(0); 363 | return; 364 | } 365 | 366 | int length = value.Length > maxLength ? maxLength : value.Length; 367 | //calculate max count 368 | int bytesCount = Encoding.UTF8.GetByteCount(value); 369 | if (_autoResize) 370 | ResizeIfNeed(_position + bytesCount + 4); 371 | 372 | //put bytes count 373 | Put(bytesCount); 374 | 375 | //put string 376 | Encoding.UTF8.GetBytes(value, 0, length, _data, _position); 377 | 378 | _position += bytesCount; 379 | } 380 | } 381 | } 382 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/NetPlayer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace Assets.Scripts 4 | { 5 | public class NetPlayer 6 | { 7 | public float X { get; set; } 8 | public float Y { get; set; } 9 | public float Z { get; set; } 10 | 11 | public GameObject GameObject { get; set; } 12 | public bool GameObjectAdded { get; set; } 13 | 14 | public NetPlayer() 15 | { 16 | GameObjectAdded = false; 17 | } 18 | 19 | public Vector3 Position => new Vector3(X, Y, Z); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/Network.cs: -------------------------------------------------------------------------------- 1 | using Assets.Scripts; 2 | using LiteNetLib; 3 | using LiteNetLib.Utils; 4 | using Shared.Enums; 5 | using System.Collections.Generic; 6 | using UnityEngine; 7 | 8 | public class Network : MonoBehaviour, INetEventListener { 9 | 10 | public Player player; 11 | private Vector3 lastNetworkedPosition = Vector3.zero; 12 | 13 | private float lastDistance = 0.0f; 14 | const float MIN_DISTANCE_TO_SEND_POSITION = 0.01f; 15 | 16 | private NetDataWriter dataWriter; 17 | private NetManager clientNetManager; 18 | private NetPeer serverPeer; 19 | 20 | public GameObject netPlayerPrefab; 21 | private Dictionary netPlayersDictionary; 22 | 23 | // Use this for initialization 24 | void Start() 25 | { 26 | netPlayersDictionary = new Dictionary(); 27 | dataWriter = new NetDataWriter(); 28 | clientNetManager = new NetManager(this, "game"); 29 | 30 | if (clientNetManager.Start()) 31 | { 32 | clientNetManager.Connect("localhost", 15000); 33 | Debug.Log("Client net manager started!"); 34 | } 35 | else 36 | Debug.LogError("Could not start client net manager!"); 37 | 38 | } 39 | 40 | private void FixedUpdate() 41 | { 42 | if (clientNetManager != null) 43 | if (clientNetManager.IsRunning) 44 | { 45 | clientNetManager.PollEvents(); 46 | 47 | lastDistance = Vector3.Distance(lastNetworkedPosition, player.transform.position); 48 | if(lastDistance >= MIN_DISTANCE_TO_SEND_POSITION) 49 | { 50 | dataWriter.Reset(); 51 | 52 | dataWriter.Put((int)NetworkTags.PlayerPosition); 53 | dataWriter.Put(player.transform.position.x); 54 | dataWriter.Put(player.transform.position.y); 55 | dataWriter.Put(player.transform.position.z); 56 | 57 | serverPeer.Send(dataWriter, SendOptions.Sequenced); 58 | 59 | lastNetworkedPosition = player.transform.position; 60 | } 61 | } 62 | 63 | foreach (var player in netPlayersDictionary) 64 | { 65 | if (!player.Value.GameObjectAdded) 66 | { 67 | player.Value.GameObjectAdded = true; 68 | player.Value.GameObject = Instantiate(netPlayerPrefab, player.Value.Position, Quaternion.identity); 69 | } 70 | else 71 | player.Value.GameObject.transform.position = player.Value.Position; 72 | } 73 | } 74 | 75 | private void OnApplicationQuit() 76 | { 77 | if (clientNetManager != null) 78 | if (clientNetManager.IsRunning) 79 | clientNetManager.Stop(); 80 | } 81 | 82 | public void OnNetworkLatencyUpdate(NetPeer peer, int latency) { } 83 | 84 | public void OnNetworkReceive(NetPeer peer, NetDataReader reader) 85 | { 86 | if (reader.Data == null) 87 | return; 88 | 89 | Debug.Log($"OnNetworkReceive: {reader.Data.Length}"); 90 | 91 | if (reader.Data.Length >= 4) 92 | { 93 | NetworkTags networkTag = (NetworkTags)reader.GetInt(); 94 | if (networkTag == NetworkTags.PlayerPositionsArray) 95 | { 96 | int lengthArr = (reader.Data.Length - 4) / (sizeof(long) + sizeof(float) * 3); 97 | 98 | Debug.Log("Got positions array data num : " + lengthArr); 99 | 100 | for (int i = 0; i < lengthArr; i++) 101 | { 102 | long playerid = reader.GetLong(); 103 | 104 | if (!netPlayersDictionary.ContainsKey(playerid)) 105 | netPlayersDictionary.Add(playerid, new NetPlayer()); 106 | 107 | netPlayersDictionary[playerid].X = reader.GetFloat(); 108 | netPlayersDictionary[playerid].Y = reader.GetFloat(); 109 | netPlayersDictionary[playerid].Z = reader.GetFloat(); 110 | } 111 | } 112 | } 113 | } 114 | 115 | public void OnPeerConnected(NetPeer peer) 116 | { 117 | serverPeer = peer; 118 | Debug.Log($"OnPeerConnected: {peer.EndPoint.Host} : {peer.EndPoint.Port}"); 119 | } 120 | 121 | public void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo) 122 | { 123 | Debug.Log($"OnPeerConnected: {peer.EndPoint.Host} : {peer.EndPoint.Port} Reason: {disconnectInfo.Reason.ToString()}"); 124 | } 125 | 126 | public void OnNetworkError(NetEndPoint endPoint, int socketErrorCode) 127 | { 128 | Debug.LogError($"OnNetworkError: {socketErrorCode}"); 129 | } 130 | 131 | public void OnNetworkReceiveUnconnected(NetEndPoint remoteEndPoint, NetDataReader reader, UnconnectedMessageType messageType) 132 | { 133 | Debug.Log($"OnNetworkReceive: {reader.Data.Length}"); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Scripts/Player.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public class Player : MonoBehaviour { 4 | 5 | private readonly float moveSpeed = 5f; 6 | 7 | // Use this for initialization 8 | void Start () { 9 | 10 | } 11 | 12 | // Update is called once per frame 13 | void Update () { 14 | float vertical = Input.GetAxis("Vertical"); 15 | float horizontal = Input.GetAxis("Horizontal"); 16 | 17 | transform.Translate(moveSpeed * Input.GetAxis("Horizontal") * Time.deltaTime, 0f, moveSpeed * Input.GetAxis("Vertical") * Time.deltaTime); 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Assets/Shared.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MUN1Z/CubesMultiplayerDemoUnityLiteNetLib/d29387ded18b1353409c03fe7cd53ded6106f789/CubesMultiplayerDemoClient/Assets/Shared.dll -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/Packages/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "com.unity.ads": "2.0.8", 4 | "com.unity.analytics": "2.0.16", 5 | "com.unity.package-manager-ui": "1.9.11", 6 | "com.unity.purchasing": "2.0.3", 7 | "com.unity.textmeshpro": "1.2.4", 8 | "com.unity.modules.ai": "1.0.0", 9 | "com.unity.modules.animation": "1.0.0", 10 | "com.unity.modules.assetbundle": "1.0.0", 11 | "com.unity.modules.audio": "1.0.0", 12 | "com.unity.modules.cloth": "1.0.0", 13 | "com.unity.modules.director": "1.0.0", 14 | "com.unity.modules.imageconversion": "1.0.0", 15 | "com.unity.modules.imgui": "1.0.0", 16 | "com.unity.modules.jsonserialize": "1.0.0", 17 | "com.unity.modules.particlesystem": "1.0.0", 18 | "com.unity.modules.physics": "1.0.0", 19 | "com.unity.modules.physics2d": "1.0.0", 20 | "com.unity.modules.screencapture": "1.0.0", 21 | "com.unity.modules.terrain": "1.0.0", 22 | "com.unity.modules.terrainphysics": "1.0.0", 23 | "com.unity.modules.tilemap": "1.0.0", 24 | "com.unity.modules.ui": "1.0.0", 25 | "com.unity.modules.uielements": "1.0.0", 26 | "com.unity.modules.umbra": "1.0.0", 27 | "com.unity.modules.unityanalytics": "1.0.0", 28 | "com.unity.modules.unitywebrequest": "1.0.0", 29 | "com.unity.modules.unitywebrequestassetbundle": "1.0.0", 30 | "com.unity.modules.unitywebrequestaudio": "1.0.0", 31 | "com.unity.modules.unitywebrequesttexture": "1.0.0", 32 | "com.unity.modules.unitywebrequestwww": "1.0.0", 33 | "com.unity.modules.vehicles": "1.0.0", 34 | "com.unity.modules.video": "1.0.0", 35 | "com.unity.modules.vr": "1.0.0", 36 | "com.unity.modules.wind": "1.0.0", 37 | "com.unity.modules.xr": "1.0.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!11 &1 4 | AudioManager: 5 | m_ObjectHideFlags: 0 6 | m_Volume: 1 7 | Rolloff Scale: 1 8 | Doppler Factor: 1 9 | Default Speaker Mode: 2 10 | m_SampleRate: 0 11 | m_DSPBufferSize: 1024 12 | m_VirtualVoiceCount: 512 13 | m_RealVoiceCount: 32 14 | m_SpatializerPlugin: 15 | m_AmbisonicDecoderPlugin: 16 | m_DisableAudio: 0 17 | m_VirtualizeEffects: 1 18 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!236 &1 4 | ClusterInputManager: 5 | m_ObjectHideFlags: 0 6 | m_Inputs: [] 7 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!55 &1 4 | PhysicsManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 7 7 | m_Gravity: {x: 0, y: -9.81, z: 0} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_BounceThreshold: 2 10 | m_SleepThreshold: 0.005 11 | m_DefaultContactOffset: 0.01 12 | m_DefaultSolverIterations: 6 13 | m_DefaultSolverVelocityIterations: 1 14 | m_QueriesHitBackfaces: 0 15 | m_QueriesHitTriggers: 1 16 | m_EnableAdaptiveForce: 0 17 | m_ClothInterCollisionDistance: 0 18 | m_ClothInterCollisionStiffness: 0 19 | m_ContactsGeneration: 1 20 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 21 | m_AutoSimulation: 1 22 | m_AutoSyncTransforms: 1 23 | m_ClothInterCollisionSettingsToggle: 0 24 | m_ContactPairsMode: 0 25 | m_BroadphaseType: 0 26 | m_WorldBounds: 27 | m_Center: {x: 0, y: 0, z: 0} 28 | m_Extent: {x: 250, y: 250, z: 250} 29 | m_WorldSubdivisions: 8 30 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1045 &1 4 | EditorBuildSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Scenes: 8 | - enabled: 1 9 | path: Assets/Scenes/SampleScene.unity 10 | guid: 99c9720ab356a0642a771bea13969a05 11 | m_configObjects: {} 12 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!159 &1 4 | EditorSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 7 7 | m_ExternalVersionControlSupport: Visible Meta Files 8 | m_SerializationMode: 2 9 | m_LineEndingsForNewScripts: 2 10 | m_DefaultBehaviorMode: 0 11 | m_SpritePackerMode: 0 12 | m_SpritePackerPaddingPower: 1 13 | m_EtcTextureCompressorBehavior: 1 14 | m_EtcTextureFastCompressor: 1 15 | m_EtcTextureNormalCompressor: 2 16 | m_EtcTextureBestCompressor: 4 17 | m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd 18 | m_ProjectGenerationRootNamespace: 19 | m_UserGeneratedProjectSuffix: 20 | m_CollabEditorSettings: 21 | inProgressEnabled: 1 22 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!30 &1 4 | GraphicsSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 12 7 | m_Deferred: 8 | m_Mode: 1 9 | m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} 10 | m_DeferredReflections: 11 | m_Mode: 1 12 | m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} 13 | m_ScreenSpaceShadows: 14 | m_Mode: 1 15 | m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} 16 | m_LegacyDeferred: 17 | m_Mode: 1 18 | m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} 19 | m_DepthNormals: 20 | m_Mode: 1 21 | m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} 22 | m_MotionVectors: 23 | m_Mode: 1 24 | m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} 25 | m_LightHalo: 26 | m_Mode: 1 27 | m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} 28 | m_LensFlare: 29 | m_Mode: 1 30 | m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} 31 | m_AlwaysIncludedShaders: 32 | - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} 33 | - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} 34 | - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} 35 | - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} 36 | - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} 37 | - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} 38 | - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0} 39 | - {fileID: 17000, guid: 0000000000000000f000000000000000, type: 0} 40 | m_PreloadedShaders: [] 41 | m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, 42 | type: 0} 43 | m_CustomRenderPipeline: {fileID: 0} 44 | m_TransparencySortMode: 0 45 | m_TransparencySortAxis: {x: 0, y: 0, z: 1} 46 | m_DefaultRenderingPath: 1 47 | m_DefaultMobileRenderingPath: 1 48 | m_TierSettings: [] 49 | m_LightmapStripping: 0 50 | m_FogStripping: 0 51 | m_InstancingStripping: 0 52 | m_LightmapKeepPlain: 1 53 | m_LightmapKeepDirCombined: 1 54 | m_LightmapKeepDynamicPlain: 1 55 | m_LightmapKeepDynamicDirCombined: 1 56 | m_LightmapKeepShadowMask: 1 57 | m_LightmapKeepSubtractive: 1 58 | m_FogKeepLinear: 1 59 | m_FogKeepExp: 1 60 | m_FogKeepExp2: 1 61 | m_AlbedoSwatchInfos: [] 62 | m_LightsUseLinearIntensity: 0 63 | m_LightsUseColorTemperature: 0 64 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!13 &1 4 | InputManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Axes: 8 | - serializedVersion: 3 9 | m_Name: Horizontal 10 | descriptiveName: 11 | descriptiveNegativeName: 12 | negativeButton: left 13 | positiveButton: right 14 | altNegativeButton: a 15 | altPositiveButton: d 16 | gravity: 3 17 | dead: 0.001 18 | sensitivity: 3 19 | snap: 1 20 | invert: 0 21 | type: 0 22 | axis: 0 23 | joyNum: 0 24 | - serializedVersion: 3 25 | m_Name: Vertical 26 | descriptiveName: 27 | descriptiveNegativeName: 28 | negativeButton: down 29 | positiveButton: up 30 | altNegativeButton: s 31 | altPositiveButton: w 32 | gravity: 3 33 | dead: 0.001 34 | sensitivity: 3 35 | snap: 1 36 | invert: 0 37 | type: 0 38 | axis: 0 39 | joyNum: 0 40 | - serializedVersion: 3 41 | m_Name: Fire1 42 | descriptiveName: 43 | descriptiveNegativeName: 44 | negativeButton: 45 | positiveButton: left ctrl 46 | altNegativeButton: 47 | altPositiveButton: mouse 0 48 | gravity: 1000 49 | dead: 0.001 50 | sensitivity: 1000 51 | snap: 0 52 | invert: 0 53 | type: 0 54 | axis: 0 55 | joyNum: 0 56 | - serializedVersion: 3 57 | m_Name: Fire2 58 | descriptiveName: 59 | descriptiveNegativeName: 60 | negativeButton: 61 | positiveButton: left alt 62 | altNegativeButton: 63 | altPositiveButton: mouse 1 64 | gravity: 1000 65 | dead: 0.001 66 | sensitivity: 1000 67 | snap: 0 68 | invert: 0 69 | type: 0 70 | axis: 0 71 | joyNum: 0 72 | - serializedVersion: 3 73 | m_Name: Fire3 74 | descriptiveName: 75 | descriptiveNegativeName: 76 | negativeButton: 77 | positiveButton: left shift 78 | altNegativeButton: 79 | altPositiveButton: mouse 2 80 | gravity: 1000 81 | dead: 0.001 82 | sensitivity: 1000 83 | snap: 0 84 | invert: 0 85 | type: 0 86 | axis: 0 87 | joyNum: 0 88 | - serializedVersion: 3 89 | m_Name: Jump 90 | descriptiveName: 91 | descriptiveNegativeName: 92 | negativeButton: 93 | positiveButton: space 94 | altNegativeButton: 95 | altPositiveButton: 96 | gravity: 1000 97 | dead: 0.001 98 | sensitivity: 1000 99 | snap: 0 100 | invert: 0 101 | type: 0 102 | axis: 0 103 | joyNum: 0 104 | - serializedVersion: 3 105 | m_Name: Mouse X 106 | descriptiveName: 107 | descriptiveNegativeName: 108 | negativeButton: 109 | positiveButton: 110 | altNegativeButton: 111 | altPositiveButton: 112 | gravity: 0 113 | dead: 0 114 | sensitivity: 0.1 115 | snap: 0 116 | invert: 0 117 | type: 1 118 | axis: 0 119 | joyNum: 0 120 | - serializedVersion: 3 121 | m_Name: Mouse Y 122 | descriptiveName: 123 | descriptiveNegativeName: 124 | negativeButton: 125 | positiveButton: 126 | altNegativeButton: 127 | altPositiveButton: 128 | gravity: 0 129 | dead: 0 130 | sensitivity: 0.1 131 | snap: 0 132 | invert: 0 133 | type: 1 134 | axis: 1 135 | joyNum: 0 136 | - serializedVersion: 3 137 | m_Name: Mouse ScrollWheel 138 | descriptiveName: 139 | descriptiveNegativeName: 140 | negativeButton: 141 | positiveButton: 142 | altNegativeButton: 143 | altPositiveButton: 144 | gravity: 0 145 | dead: 0 146 | sensitivity: 0.1 147 | snap: 0 148 | invert: 0 149 | type: 1 150 | axis: 2 151 | joyNum: 0 152 | - serializedVersion: 3 153 | m_Name: Horizontal 154 | descriptiveName: 155 | descriptiveNegativeName: 156 | negativeButton: 157 | positiveButton: 158 | altNegativeButton: 159 | altPositiveButton: 160 | gravity: 0 161 | dead: 0.19 162 | sensitivity: 1 163 | snap: 0 164 | invert: 0 165 | type: 2 166 | axis: 0 167 | joyNum: 0 168 | - serializedVersion: 3 169 | m_Name: Vertical 170 | descriptiveName: 171 | descriptiveNegativeName: 172 | negativeButton: 173 | positiveButton: 174 | altNegativeButton: 175 | altPositiveButton: 176 | gravity: 0 177 | dead: 0.19 178 | sensitivity: 1 179 | snap: 0 180 | invert: 1 181 | type: 2 182 | axis: 1 183 | joyNum: 0 184 | - serializedVersion: 3 185 | m_Name: Fire1 186 | descriptiveName: 187 | descriptiveNegativeName: 188 | negativeButton: 189 | positiveButton: joystick button 0 190 | altNegativeButton: 191 | altPositiveButton: 192 | gravity: 1000 193 | dead: 0.001 194 | sensitivity: 1000 195 | snap: 0 196 | invert: 0 197 | type: 0 198 | axis: 0 199 | joyNum: 0 200 | - serializedVersion: 3 201 | m_Name: Fire2 202 | descriptiveName: 203 | descriptiveNegativeName: 204 | negativeButton: 205 | positiveButton: joystick button 1 206 | altNegativeButton: 207 | altPositiveButton: 208 | gravity: 1000 209 | dead: 0.001 210 | sensitivity: 1000 211 | snap: 0 212 | invert: 0 213 | type: 0 214 | axis: 0 215 | joyNum: 0 216 | - serializedVersion: 3 217 | m_Name: Fire3 218 | descriptiveName: 219 | descriptiveNegativeName: 220 | negativeButton: 221 | positiveButton: joystick button 2 222 | altNegativeButton: 223 | altPositiveButton: 224 | gravity: 1000 225 | dead: 0.001 226 | sensitivity: 1000 227 | snap: 0 228 | invert: 0 229 | type: 0 230 | axis: 0 231 | joyNum: 0 232 | - serializedVersion: 3 233 | m_Name: Jump 234 | descriptiveName: 235 | descriptiveNegativeName: 236 | negativeButton: 237 | positiveButton: joystick button 3 238 | altNegativeButton: 239 | altPositiveButton: 240 | gravity: 1000 241 | dead: 0.001 242 | sensitivity: 1000 243 | snap: 0 244 | invert: 0 245 | type: 0 246 | axis: 0 247 | joyNum: 0 248 | - serializedVersion: 3 249 | m_Name: Submit 250 | descriptiveName: 251 | descriptiveNegativeName: 252 | negativeButton: 253 | positiveButton: return 254 | altNegativeButton: 255 | altPositiveButton: joystick button 0 256 | gravity: 1000 257 | dead: 0.001 258 | sensitivity: 1000 259 | snap: 0 260 | invert: 0 261 | type: 0 262 | axis: 0 263 | joyNum: 0 264 | - serializedVersion: 3 265 | m_Name: Submit 266 | descriptiveName: 267 | descriptiveNegativeName: 268 | negativeButton: 269 | positiveButton: enter 270 | altNegativeButton: 271 | altPositiveButton: space 272 | gravity: 1000 273 | dead: 0.001 274 | sensitivity: 1000 275 | snap: 0 276 | invert: 0 277 | type: 0 278 | axis: 0 279 | joyNum: 0 280 | - serializedVersion: 3 281 | m_Name: Cancel 282 | descriptiveName: 283 | descriptiveNegativeName: 284 | negativeButton: 285 | positiveButton: escape 286 | altNegativeButton: 287 | altPositiveButton: joystick button 1 288 | gravity: 1000 289 | dead: 0.001 290 | sensitivity: 1000 291 | snap: 0 292 | invert: 0 293 | type: 0 294 | axis: 0 295 | joyNum: 0 296 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!126 &1 4 | NavMeshProjectSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | areas: 8 | - name: Walkable 9 | cost: 1 10 | - name: Not Walkable 11 | cost: 1 12 | - name: Jump 13 | cost: 2 14 | - name: 15 | cost: 1 16 | - name: 17 | cost: 1 18 | - name: 19 | cost: 1 20 | - name: 21 | cost: 1 22 | - name: 23 | cost: 1 24 | - name: 25 | cost: 1 26 | - name: 27 | cost: 1 28 | - name: 29 | cost: 1 30 | - name: 31 | cost: 1 32 | - name: 33 | cost: 1 34 | - name: 35 | cost: 1 36 | - name: 37 | cost: 1 38 | - name: 39 | cost: 1 40 | - name: 41 | cost: 1 42 | - name: 43 | cost: 1 44 | - name: 45 | cost: 1 46 | - name: 47 | cost: 1 48 | - name: 49 | cost: 1 50 | - name: 51 | cost: 1 52 | - name: 53 | cost: 1 54 | - name: 55 | cost: 1 56 | - name: 57 | cost: 1 58 | - name: 59 | cost: 1 60 | - name: 61 | cost: 1 62 | - name: 63 | cost: 1 64 | - name: 65 | cost: 1 66 | - name: 67 | cost: 1 68 | - name: 69 | cost: 1 70 | - name: 71 | cost: 1 72 | m_LastAgentTypeID: -887442657 73 | m_Settings: 74 | - serializedVersion: 2 75 | agentTypeID: 0 76 | agentRadius: 0.5 77 | agentHeight: 2 78 | agentSlope: 45 79 | agentClimb: 0.75 80 | ledgeDropHeight: 0 81 | maxJumpAcrossDistance: 0 82 | minRegionArea: 2 83 | manualCellSize: 0 84 | cellSize: 0.16666667 85 | manualTileSize: 0 86 | tileSize: 256 87 | accuratePlacement: 0 88 | debug: 89 | m_Flags: 0 90 | m_SettingNames: 91 | - Humanoid 92 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!149 &1 4 | NetworkManager: 5 | m_ObjectHideFlags: 0 6 | m_DebugLevel: 0 7 | m_Sendrate: 15 8 | m_AssetToPrefab: {} 9 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!19 &1 4 | Physics2DSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 3 7 | m_Gravity: {x: 0, y: -9.81} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_VelocityIterations: 8 10 | m_PositionIterations: 3 11 | m_VelocityThreshold: 1 12 | m_MaxLinearCorrection: 0.2 13 | m_MaxAngularCorrection: 8 14 | m_MaxTranslationSpeed: 100 15 | m_MaxRotationSpeed: 360 16 | m_BaumgarteScale: 0.2 17 | m_BaumgarteTimeOfImpactScale: 0.75 18 | m_TimeToSleep: 0.5 19 | m_LinearSleepTolerance: 0.01 20 | m_AngularSleepTolerance: 2 21 | m_DefaultContactOffset: 0.01 22 | m_AutoSimulation: 1 23 | m_QueriesHitTriggers: 1 24 | m_QueriesStartInColliders: 1 25 | m_ChangeStopsCallbacks: 0 26 | m_CallbacksOnDisable: 1 27 | m_AutoSyncTransforms: 1 28 | m_AlwaysShowColliders: 0 29 | m_ShowColliderSleep: 1 30 | m_ShowColliderContacts: 0 31 | m_ShowColliderAABB: 0 32 | m_ContactArrowScale: 0.2 33 | m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} 34 | m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} 35 | m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} 36 | m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} 37 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 38 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/ProjectSettings/PresetManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1386491679 &1 4 | PresetManager: 5 | m_ObjectHideFlags: 0 6 | m_DefaultList: 7 | - type: 8 | m_NativeTypeID: 108 9 | m_ManagedTypePPtr: {fileID: 0} 10 | m_ManagedTypeFallback: 11 | defaultPresets: 12 | - m_Preset: {fileID: 2655988077585873504, guid: c1cf8506f04ef2c4a88b64b6c4202eea, 13 | type: 2} 14 | - type: 15 | m_NativeTypeID: 1020 16 | m_ManagedTypePPtr: {fileID: 0} 17 | m_ManagedTypeFallback: 18 | defaultPresets: 19 | - m_Preset: {fileID: 2655988077585873504, guid: 0cd792cc87e492d43b4e95b205fc5cc6, 20 | type: 2} 21 | - type: 22 | m_NativeTypeID: 1006 23 | m_ManagedTypePPtr: {fileID: 0} 24 | m_ManagedTypeFallback: 25 | defaultPresets: 26 | - m_Preset: {fileID: 2655988077585873504, guid: 7a99f8aa944efe94cb9bd74562b7d5f9, 27 | type: 2} 28 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 2018.2.7f1 2 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!47 &1 4 | QualitySettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 5 7 | m_CurrentQuality: 4 8 | m_QualitySettings: 9 | - serializedVersion: 2 10 | name: Very Low 11 | pixelLightCount: 0 12 | shadows: 0 13 | shadowResolution: 0 14 | shadowProjection: 1 15 | shadowCascades: 1 16 | shadowDistance: 15 17 | shadowNearPlaneOffset: 3 18 | shadowCascade2Split: 0.33333334 19 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 20 | shadowmaskMode: 0 21 | blendWeights: 1 22 | textureQuality: 1 23 | anisotropicTextures: 0 24 | antiAliasing: 0 25 | softParticles: 0 26 | softVegetation: 0 27 | realtimeReflectionProbes: 0 28 | billboardsFaceCameraPosition: 0 29 | vSyncCount: 0 30 | lodBias: 0.3 31 | maximumLODLevel: 0 32 | particleRaycastBudget: 4 33 | asyncUploadTimeSlice: 2 34 | asyncUploadBufferSize: 4 35 | resolutionScalingFixedDPIFactor: 1 36 | excludedTargetPlatforms: [] 37 | - serializedVersion: 2 38 | name: Low 39 | pixelLightCount: 0 40 | shadows: 0 41 | shadowResolution: 0 42 | shadowProjection: 1 43 | shadowCascades: 1 44 | shadowDistance: 20 45 | shadowNearPlaneOffset: 3 46 | shadowCascade2Split: 0.33333334 47 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 48 | shadowmaskMode: 0 49 | blendWeights: 2 50 | textureQuality: 0 51 | anisotropicTextures: 0 52 | antiAliasing: 0 53 | softParticles: 0 54 | softVegetation: 0 55 | realtimeReflectionProbes: 0 56 | billboardsFaceCameraPosition: 0 57 | vSyncCount: 0 58 | lodBias: 0.4 59 | maximumLODLevel: 0 60 | particleRaycastBudget: 16 61 | asyncUploadTimeSlice: 2 62 | asyncUploadBufferSize: 4 63 | resolutionScalingFixedDPIFactor: 1 64 | excludedTargetPlatforms: [] 65 | - serializedVersion: 2 66 | name: Medium 67 | pixelLightCount: 1 68 | shadows: 1 69 | shadowResolution: 0 70 | shadowProjection: 1 71 | shadowCascades: 1 72 | shadowDistance: 20 73 | shadowNearPlaneOffset: 3 74 | shadowCascade2Split: 0.33333334 75 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 76 | shadowmaskMode: 0 77 | blendWeights: 2 78 | textureQuality: 0 79 | anisotropicTextures: 1 80 | antiAliasing: 0 81 | softParticles: 0 82 | softVegetation: 0 83 | realtimeReflectionProbes: 0 84 | billboardsFaceCameraPosition: 0 85 | vSyncCount: 1 86 | lodBias: 0.7 87 | maximumLODLevel: 0 88 | particleRaycastBudget: 64 89 | asyncUploadTimeSlice: 2 90 | asyncUploadBufferSize: 4 91 | resolutionScalingFixedDPIFactor: 1 92 | excludedTargetPlatforms: [] 93 | - serializedVersion: 2 94 | name: High 95 | pixelLightCount: 2 96 | shadows: 2 97 | shadowResolution: 1 98 | shadowProjection: 1 99 | shadowCascades: 2 100 | shadowDistance: 40 101 | shadowNearPlaneOffset: 3 102 | shadowCascade2Split: 0.33333334 103 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 104 | shadowmaskMode: 1 105 | blendWeights: 2 106 | textureQuality: 0 107 | anisotropicTextures: 1 108 | antiAliasing: 2 109 | softParticles: 0 110 | softVegetation: 1 111 | realtimeReflectionProbes: 1 112 | billboardsFaceCameraPosition: 1 113 | vSyncCount: 1 114 | lodBias: 1 115 | maximumLODLevel: 0 116 | particleRaycastBudget: 256 117 | asyncUploadTimeSlice: 2 118 | asyncUploadBufferSize: 4 119 | resolutionScalingFixedDPIFactor: 1 120 | excludedTargetPlatforms: [] 121 | - serializedVersion: 2 122 | name: Very High 123 | pixelLightCount: 3 124 | shadows: 2 125 | shadowResolution: 2 126 | shadowProjection: 1 127 | shadowCascades: 2 128 | shadowDistance: 40 129 | shadowNearPlaneOffset: 3 130 | shadowCascade2Split: 0.33333334 131 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 132 | shadowmaskMode: 1 133 | blendWeights: 4 134 | textureQuality: 0 135 | anisotropicTextures: 1 136 | antiAliasing: 4 137 | softParticles: 1 138 | softVegetation: 1 139 | realtimeReflectionProbes: 1 140 | billboardsFaceCameraPosition: 1 141 | vSyncCount: 1 142 | lodBias: 1.5 143 | maximumLODLevel: 0 144 | particleRaycastBudget: 1024 145 | asyncUploadTimeSlice: 2 146 | asyncUploadBufferSize: 4 147 | resolutionScalingFixedDPIFactor: 1 148 | excludedTargetPlatforms: [] 149 | - serializedVersion: 2 150 | name: Ultra 151 | pixelLightCount: 4 152 | shadows: 2 153 | shadowResolution: 2 154 | shadowProjection: 1 155 | shadowCascades: 4 156 | shadowDistance: 150 157 | shadowNearPlaneOffset: 3 158 | shadowCascade2Split: 0.33333334 159 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 160 | shadowmaskMode: 1 161 | blendWeights: 4 162 | textureQuality: 0 163 | anisotropicTextures: 1 164 | antiAliasing: 4 165 | softParticles: 1 166 | softVegetation: 1 167 | realtimeReflectionProbes: 1 168 | billboardsFaceCameraPosition: 1 169 | vSyncCount: 1 170 | lodBias: 2 171 | maximumLODLevel: 0 172 | particleRaycastBudget: 4096 173 | asyncUploadTimeSlice: 2 174 | asyncUploadBufferSize: 4 175 | resolutionScalingFixedDPIFactor: 1 176 | excludedTargetPlatforms: [] 177 | m_PerPlatformDefaultQuality: 178 | Android: 2 179 | Nintendo 3DS: 5 180 | Nintendo Switch: 5 181 | PS4: 5 182 | PSP2: 2 183 | Standalone: 5 184 | Tizen: 2 185 | WebGL: 3 186 | WiiU: 5 187 | Windows Store Apps: 5 188 | XboxOne: 5 189 | iPhone: 2 190 | tvOS: 2 191 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!78 &1 4 | TagManager: 5 | serializedVersion: 2 6 | tags: [] 7 | layers: 8 | - Default 9 | - TransparentFX 10 | - Ignore Raycast 11 | - 12 | - Water 13 | - UI 14 | - 15 | - 16 | - PostProcessing 17 | - 18 | - 19 | - 20 | - 21 | - 22 | - 23 | - 24 | - 25 | - 26 | - 27 | - 28 | - 29 | - 30 | - 31 | - 32 | - 33 | - 34 | - 35 | - 36 | - 37 | - 38 | - 39 | - 40 | m_SortingLayers: 41 | - name: Default 42 | uniqueID: 0 43 | locked: 0 44 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!5 &1 4 | TimeManager: 5 | m_ObjectHideFlags: 0 6 | Fixed Timestep: 0.02 7 | Maximum Allowed Timestep: 0.1 8 | m_TimeScale: 1 9 | Maximum Particle Timestep: 0.03 10 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoClient/ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!310 &1 4 | UnityConnectSettings: 5 | m_ObjectHideFlags: 0 6 | m_Enabled: 1 7 | m_TestMode: 0 8 | m_TestEventUrl: 9 | m_TestConfigUrl: 10 | m_TestInitMode: 0 11 | CrashReportingSettings: 12 | m_EventUrl: https://perf-events.cloud.unity3d.com/api/events/crashes 13 | m_NativeEventUrl: https://perf-events.cloud.unity3d.com/symbolicate 14 | m_Enabled: 0 15 | m_CaptureEditorExceptions: 1 16 | UnityPurchasingSettings: 17 | m_Enabled: 0 18 | m_TestMode: 0 19 | UnityAnalyticsSettings: 20 | m_Enabled: 1 21 | m_InitializeOnStartup: 1 22 | m_TestMode: 0 23 | m_TestEventUrl: 24 | m_TestConfigUrl: 25 | UnityAdsSettings: 26 | m_Enabled: 0 27 | m_InitializeOnStartup: 1 28 | m_TestMode: 0 29 | m_IosGameId: 30 | m_AndroidGameId: 31 | m_GameIds: {} 32 | m_GameId: 33 | PerformanceReportingSettings: 34 | m_Enabled: 0 35 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoServer/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | .vs/ 9 | 10 | # Build results 11 | [Dd]ebug/ 12 | [Dd]ebugPublic/ 13 | [Rr]elease/ 14 | [Rr]eleases/ 15 | x64/ 16 | build/ 17 | bld/ 18 | [Bb]in/ 19 | [Oo]bj/ 20 | 21 | # Roslyn cache directories 22 | *.ide/ 23 | 24 | # MSTest test Results 25 | [Tt]est[Rr]esult*/ 26 | [Bb]uild[Ll]og.* 27 | 28 | #NUNIT 29 | *.VisualState.xml 30 | TestResult.xml 31 | 32 | # Build Results of an ATL Project 33 | [Dd]ebugPS/ 34 | [Rr]eleasePS/ 35 | dlldata.c 36 | 37 | *_i.c 38 | *_p.c 39 | *_i.h 40 | *.ilk 41 | *.meta 42 | *.obj 43 | *.pch 44 | *.pdb 45 | *.pgc 46 | *.pgd 47 | *.rsp 48 | *.sbr 49 | *.tlb 50 | *.tli 51 | *.tlh 52 | *.tmp 53 | *.tmp_proj 54 | *.log 55 | *.vspscc 56 | *.vssscc 57 | .builds 58 | *.pidb 59 | *.svclog 60 | *.scc 61 | 62 | # Chutzpah Test files 63 | _Chutzpah* 64 | 65 | # Visual C++ cache files 66 | ipch/ 67 | *.aps 68 | *.ncb 69 | *.opensdf 70 | *.sdf 71 | *.cachefile 72 | 73 | # Visual Studio profiler 74 | *.psess 75 | *.vsp 76 | *.vspx 77 | 78 | # TFS 2012 Local Workspace 79 | $tf/ 80 | 81 | # Guidance Automation Toolkit 82 | *.gpState 83 | 84 | # Visual Studio 2015/2017 cache/options directory 85 | .vs/ 86 | # Uncomment if you have tasks that create the project's static files in wwwroot 87 | #wwwroot/ 88 | 89 | # Visual Studio 2017 auto generated files 90 | Generated\ Files/ 91 | 92 | # ReSharper is a .NET coding add-in 93 | _ReSharper*/ 94 | *.[Rr]e[Ss]harper 95 | *.DotSettings.user 96 | 97 | # JustCode is a .NET coding addin-in 98 | .JustCode 99 | 100 | # TeamCity is a build add-in 101 | _TeamCity* 102 | 103 | # DotCover is a Code Coverage Tool 104 | *.dotCover 105 | 106 | # NCrunch 107 | _NCrunch_* 108 | .*crunch*.local.xml 109 | 110 | # MightyMoose 111 | *.mm.* 112 | AutoTest.Net/ 113 | 114 | # Web workbench (sass) 115 | .sass-cache/ 116 | 117 | # Installshield output folder 118 | [Ee]xpress/ 119 | 120 | # DocProject is a documentation generator add-in 121 | DocProject/buildhelp/ 122 | DocProject/Help/*.HxT 123 | DocProject/Help/*.HxC 124 | DocProject/Help/*.hhc 125 | DocProject/Help/*.hhk 126 | DocProject/Help/*.hhp 127 | DocProject/Help/Html2 128 | DocProject/Help/html 129 | 130 | # Click-Once directory 131 | publish/ 132 | 133 | # Publish Web Output 134 | *.[Pp]ublish.xml 135 | *.azurePubxml 136 | ## TODO: Comment the next line if you want to checkin your 137 | ## web deploy settings but do note that will include unencrypted 138 | ## passwords 139 | *.pubxml 140 | 141 | # NuGet Packages Directory 142 | packages/* 143 | ## TODO: If the tool you use requires repositories.config 144 | ## uncomment the next line 145 | #!packages/repositories.config 146 | 147 | # Enable "build/" folder in the NuGet Packages folder since 148 | # NuGet packages use it for MSBuild targets. 149 | # This line needs to be after the ignore of the build folder 150 | # (and the packages folder if the line above has been uncommented) 151 | !packages/build/ 152 | 153 | # Windows Azure Build Output 154 | csx/ 155 | *.build.csdef 156 | 157 | # Windows Store app package directory 158 | AppPackages/ 159 | 160 | # Others 161 | sql/ 162 | *.Cache 163 | ClientBin/ 164 | [Ss]tyle[Cc]op.* 165 | ~$* 166 | *~ 167 | *.dbmdl 168 | *.dbproj.schemaview 169 | *.pfx 170 | *.publishsettings 171 | node_modules/ 172 | 173 | # RIA/Silverlight projects 174 | Generated_Code/ 175 | 176 | # Backup & report files from converting an old project file 177 | # to a newer Visual Studio version. Backup files are not needed, 178 | # because we have git ;-) 179 | _UpgradeReport_Files/ 180 | Backup*/ 181 | UpgradeLog*.XML 182 | UpgradeLog*.htm 183 | 184 | # SQL Server files 185 | *.mdf 186 | *.ldf 187 | 188 | # Business Intelligence projects 189 | *.rdl.data 190 | *.bim.layout 191 | *.bim_*.settings 192 | 193 | # Microsoft Fakes 194 | FakesAssemblies/ 195 | 196 | git_stats/* 197 | 198 | *.ncrunchproject 199 | StyleCop.Cache 200 | bin 201 | obj -------------------------------------------------------------------------------- /CubesMultiplayerDemoServer/CubesMultiplayerDemoServer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2041 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "src\Server\Server.csproj", "{B02FC5BC-4A7E-4994-9074-B4D8C54FE907}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared", "src\Shared\Shared.csproj", "{FC144ED3-D224-4FE7-92EB-44013C0A5005}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {B02FC5BC-4A7E-4994-9074-B4D8C54FE907}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {B02FC5BC-4A7E-4994-9074-B4D8C54FE907}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {B02FC5BC-4A7E-4994-9074-B4D8C54FE907}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {B02FC5BC-4A7E-4994-9074-B4D8C54FE907}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {FC144ED3-D224-4FE7-92EB-44013C0A5005}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {FC144ED3-D224-4FE7-92EB-44013C0A5005}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {FC144ED3-D224-4FE7-92EB-44013C0A5005}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {FC144ED3-D224-4FE7-92EB-44013C0A5005}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {3D63F82C-2719-4B5C-AF4C-E60EFCADBAFC} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoServer/src/Server/NetworkPlayer.cs: -------------------------------------------------------------------------------- 1 | using LiteNetLib; 2 | 3 | namespace Server 4 | { 5 | public class NetworkPlayer 6 | { 7 | public float X { get; set; } 8 | public float Y { get; set; } 9 | public float Z { get; set; } 10 | 11 | public NetPeer NetPeer { get; set; } 12 | public bool Moved { get; set; } 13 | 14 | 15 | public NetworkPlayer(NetPeer peer) 16 | { 17 | NetPeer = peer; 18 | 19 | X = 0.0f; 20 | Y = 0.0f; 21 | Z = 0.0f; 22 | 23 | Moved = false; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoServer/src/Server/Program.cs: -------------------------------------------------------------------------------- 1 | using LiteNetLib; 2 | using LiteNetLib.Utils; 3 | using Shared.Enums; 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace Server 8 | { 9 | class Program : INetEventListener 10 | { 11 | NetDataWriter dataWriter; 12 | private NetManager serverNetManager; 13 | 14 | private Dictionary networkPlayersDictionary; 15 | 16 | public void Run() 17 | { 18 | try 19 | { 20 | dataWriter = new NetDataWriter(); 21 | networkPlayersDictionary = new Dictionary(); 22 | 23 | serverNetManager = new NetManager(this, 100, "game"); 24 | if (serverNetManager.Start(15000)) 25 | Console.WriteLine("Server started listening on port 15000"); 26 | else 27 | { 28 | Console.WriteLine("Server cold not start!"); 29 | return; 30 | } 31 | 32 | while (serverNetManager.IsRunning) 33 | { 34 | serverNetManager.PollEvents(); 35 | 36 | SendPlayerPositions(); 37 | 38 | System.Threading.Thread.Sleep(15); 39 | } 40 | } 41 | catch (Exception ex) 42 | { 43 | Console.WriteLine($"Error: {ex.Message}"); 44 | } 45 | } 46 | 47 | static void Main(string[] args) 48 | { 49 | Program program = new Program(); 50 | program.Run(); 51 | 52 | Console.ReadKey(); 53 | } 54 | 55 | public void SendPlayerPositions() 56 | { 57 | try 58 | { 59 | Dictionary sendPosDict = new Dictionary(networkPlayersDictionary); 60 | 61 | foreach (var sendToPlayer in sendPosDict) 62 | { 63 | if (sendToPlayer.Value == null) 64 | continue; 65 | 66 | dataWriter.Reset(); 67 | dataWriter.Put((int)NetworkTags.PlayerPositionsArray); 68 | 69 | int amountPlayersMoved = 0; 70 | 71 | foreach (var posPlayers in sendPosDict) 72 | { 73 | if (sendToPlayer.Key == posPlayers.Key) 74 | continue; 75 | 76 | if (!posPlayers.Value.Moved) 77 | continue; 78 | 79 | dataWriter.Put(posPlayers.Key); 80 | 81 | dataWriter.Put(posPlayers.Value.X); 82 | dataWriter.Put(posPlayers.Value.Y); 83 | dataWriter.Put(posPlayers.Value.Z); 84 | 85 | amountPlayersMoved++; 86 | } 87 | 88 | if (amountPlayersMoved > 0) 89 | sendToPlayer.Value.NetPeer.Send(dataWriter, SendOptions.Sequenced); 90 | } 91 | 92 | foreach (var player in networkPlayersDictionary) 93 | player.Value.Moved = false; 94 | } 95 | catch (Exception ex) 96 | { 97 | Console.WriteLine($"Error: {ex.Message}"); 98 | } 99 | } 100 | 101 | public void OnPeerConnected(NetPeer peer) 102 | { 103 | try 104 | { 105 | Console.WriteLine($"OnPeerConnected: {peer.EndPoint.Host} : {peer.EndPoint.Port}"); 106 | 107 | NetDataWriter netDataWriter = new NetDataWriter(); 108 | netDataWriter.Reset(); 109 | netDataWriter.Put((int)NetworkTags.PlayerPositionsArray); 110 | foreach (var p in networkPlayersDictionary) 111 | { 112 | netDataWriter.Put(p.Key); 113 | 114 | netDataWriter.Put(p.Value.X); 115 | netDataWriter.Put(p.Value.Y); 116 | netDataWriter.Put(p.Value.Z); 117 | } 118 | 119 | peer.Send(netDataWriter, SendOptions.ReliableOrdered); 120 | 121 | if (!networkPlayersDictionary.ContainsKey(peer.ConnectId)) 122 | networkPlayersDictionary.Add(peer.ConnectId, new NetworkPlayer(peer)); 123 | 124 | networkPlayersDictionary[peer.ConnectId].Moved = true; 125 | } 126 | catch (Exception ex) 127 | { 128 | Console.WriteLine($"Error: {ex.Message}"); 129 | } 130 | } 131 | 132 | public void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo) 133 | { 134 | try 135 | { 136 | Console.WriteLine($"OnPeerConnected: {peer.EndPoint.Host} : {peer.EndPoint.Port} Reason: {disconnectInfo.Reason.ToString()}"); 137 | 138 | if (networkPlayersDictionary.ContainsKey(peer.ConnectId)) 139 | networkPlayersDictionary.Remove(peer.ConnectId); 140 | } 141 | catch(Exception ex) 142 | { 143 | Console.WriteLine($"Error: {ex.Message}"); 144 | } 145 | } 146 | 147 | public void OnNetworkError(NetEndPoint endPoint, int socketErrorCode) 148 | { 149 | try 150 | { 151 | Console.WriteLine($"OnNetworkError: {socketErrorCode}"); 152 | } 153 | catch (Exception ex) 154 | { 155 | Console.WriteLine($"Error: {ex.Message}"); 156 | } 157 | } 158 | 159 | public void OnNetworkReceive(NetPeer peer, NetDataReader reader) 160 | { 161 | try 162 | { 163 | if (reader.Data == null) 164 | return; 165 | 166 | NetworkTags networkTag = (NetworkTags)reader.GetInt(); 167 | if (networkTag == NetworkTags.PlayerPosition) 168 | { 169 | float x = reader.GetFloat(); 170 | float y = reader.GetFloat(); 171 | float z = reader.GetFloat(); 172 | 173 | Console.WriteLine($"Got position packet : {x} | {y} | {z}"); 174 | 175 | networkPlayersDictionary[peer.ConnectId].X = x; 176 | networkPlayersDictionary[peer.ConnectId].Y = y; 177 | networkPlayersDictionary[peer.ConnectId].Z = z; 178 | 179 | networkPlayersDictionary[peer.ConnectId].Moved = true; 180 | } 181 | } 182 | catch (Exception ex) 183 | { 184 | Console.WriteLine($"Error: {ex.Message}"); 185 | } 186 | } 187 | 188 | public void OnNetworkReceiveUnconnected(NetEndPoint remoteEndPoint, NetDataReader reader, UnconnectedMessageType messageType) 189 | { 190 | try 191 | { 192 | Console.WriteLine($"OnNetworkReceiveUnconnected"); 193 | } 194 | catch (Exception ex) 195 | { 196 | Console.WriteLine($"Error: {ex.Message}"); 197 | } 198 | } 199 | 200 | public void OnNetworkLatencyUpdate(NetPeer peer, int latency) 201 | { 202 | try { } 203 | catch (Exception ex) 204 | { 205 | Console.WriteLine($"Error: {ex.Message}"); 206 | } 207 | } 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoServer/src/Server/Server.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoServer/src/Shared/Enums/NetworkTags.cs: -------------------------------------------------------------------------------- 1 | namespace Shared.Enums 2 | { 3 | public enum NetworkTags 4 | { 5 | PlayerPosition, 6 | PlayerPositionsArray 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /CubesMultiplayerDemoServer/src/Shared/Shared.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Example](https://github.com/Mun1z/CubesMultiplayerDemoUnityLiteNetLib/blob/master/example.gif) 2 | 3 | Example of multiplayer game using unity 2018, .net core, .net standard and LiteLibNet (https://github.com/RevenantX/LiteNetLib). 4 | 5 | -------------------------------------------------------------------------------- /example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MUN1Z/CubesMultiplayerDemoUnityLiteNetLib/d29387ded18b1353409c03fe7cd53ded6106f789/example.gif --------------------------------------------------------------------------------