This commit is contained in:
vis2k 2020-10-30 13:53:13 +01:00 committed by GitHub
parent 88e160a5f7
commit 0c2ad96061
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 2704 additions and 234 deletions

View File

@ -38,7 +38,7 @@ RenderSettings:
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.4366757, g: 0.48427194, b: 0.5645252, a: 1}
m_IndirectSpecularColor: {r: 0.43667564, g: 0.48427147, b: 0.56452364, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
@ -1830,12 +1830,12 @@ MonoBehaviour:
m_EditorClassIdentifier:
dontDestroyOnLoad: 0
runInBackground: 1
startOnHeadless: 1
autoStartServerBuild: 1
showDebugMessages: 0
serverTickRate: 30
offlineScene:
onlineScene:
transport: {fileID: 1661834280}
transport: {fileID: 0}
networkAddress: localhost
maxConnections: 4
disconnectInactiveConnections: 0
@ -1871,7 +1871,7 @@ MonoBehaviour:
m_GameObject: {fileID: 1661834277}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
m_Script: {fileID: 11500000, guid: 6b0fecffa3f624585964b0d0eb21b18e, type: 3}
m_Name:
m_EditorClassIdentifier:
OnClientConnected:
@ -1898,10 +1898,14 @@ MonoBehaviour:
OnServerDisconnected:
m_PersistentCalls:
m_Calls: []
port: 7777
Port: 7777
NoDelay: 1
serverMaxMessageSize: 16384
clientMaxMessageSize: 16384
Interval: 10
FastResend: 0
CongestionWindow: 1
SendWindowSize: 128
ReceiveWindowSize: 128
debugGUI: 0
--- !u!114 &1661834281
MonoBehaviour:
m_ObjectHideFlags: 0

View File

@ -38,7 +38,7 @@ RenderSettings:
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1}
m_IndirectSpecularColor: {r: 0.44657868, g: 0.49641263, b: 0.57481706, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
@ -155,7 +155,7 @@ MonoBehaviour:
m_GameObject: {fileID: 249891953}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
m_Script: {fileID: 11500000, guid: 6b0fecffa3f624585964b0d0eb21b18e, type: 3}
m_Name:
m_EditorClassIdentifier:
OnClientConnected:
@ -182,10 +182,14 @@ MonoBehaviour:
OnServerDisconnected:
m_PersistentCalls:
m_Calls: []
port: 7777
Port: 7777
NoDelay: 1
serverMaxMessageSize: 16384
clientMaxMessageSize: 16384
Interval: 10
FastResend: 0
CongestionWindow: 1
SendWindowSize: 128
ReceiveWindowSize: 128
debugGUI: 0
--- !u!114 &249891956
MonoBehaviour:
m_ObjectHideFlags: 0
@ -200,12 +204,12 @@ MonoBehaviour:
m_EditorClassIdentifier:
dontDestroyOnLoad: 0
runInBackground: 1
startOnHeadless: 1
autoStartServerBuild: 1
showDebugMessages: 0
serverTickRate: 30
offlineScene:
onlineScene:
transport: {fileID: 249891955}
transport: {fileID: 0}
networkAddress: localhost
maxConnections: 16
disconnectInactiveConnections: 0

View File

@ -309,7 +309,7 @@ MonoBehaviour:
- {fileID: 449802645721213856, guid: 30b8f251d03d84284b70601e691d474f, type: 3}
spawnPrefab: {fileID: 449802645721213856, guid: 30b8f251d03d84284b70601e691d474f,
type: 3}
spawnAmount: 4000
spawnAmount: 1000
interleave: 1
--- !u!114 &1282001521
MonoBehaviour:
@ -320,7 +320,7 @@ MonoBehaviour:
m_GameObject: {fileID: 1282001517}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
m_Script: {fileID: 11500000, guid: 6b0fecffa3f624585964b0d0eb21b18e, type: 3}
m_Name:
m_EditorClassIdentifier:
OnClientConnected:
@ -347,12 +347,14 @@ MonoBehaviour:
OnServerDisconnected:
m_PersistentCalls:
m_Calls: []
port: 7777
Port: 7777
NoDelay: 1
serverMaxMessageSize: 16384
serverMaxReceivesPerTick: 10000
clientMaxMessageSize: 16384
clientMaxReceivesPerTick: 1000
Interval: 10
FastResend: 0
CongestionWindow: 0
SendWindowSize: 512
ReceiveWindowSize: 512
debugGUI: 1
--- !u!1 &2054208274
GameObject:
m_ObjectHideFlags: 0

View File

@ -38,7 +38,7 @@ RenderSettings:
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1}
m_IndirectSpecularColor: {r: 0.44657868, g: 0.49641263, b: 0.57481706, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
@ -2895,7 +2895,7 @@ GameObject:
m_Component:
- component: {fileID: 1783103026}
- component: {fileID: 1783103025}
- component: {fileID: 1783103024}
- component: {fileID: 1783103023}
m_Layer: 0
m_Name: NetworkManager
m_TagString: Untagged
@ -2903,7 +2903,7 @@ GameObject:
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1783103024
--- !u!114 &1783103023
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
@ -2912,7 +2912,7 @@ MonoBehaviour:
m_GameObject: {fileID: 1783103022}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
m_Script: {fileID: 11500000, guid: 6b0fecffa3f624585964b0d0eb21b18e, type: 3}
m_Name:
m_EditorClassIdentifier:
OnClientConnected:
@ -2939,10 +2939,14 @@ MonoBehaviour:
OnServerDisconnected:
m_PersistentCalls:
m_Calls: []
port: 7777
Port: 7777
NoDelay: 1
serverMaxMessageSize: 16384
clientMaxMessageSize: 16384
Interval: 10
FastResend: 0
CongestionWindow: 1
SendWindowSize: 128
ReceiveWindowSize: 128
debugGUI: 0
--- !u!114 &1783103025
MonoBehaviour:
m_ObjectHideFlags: 0
@ -2957,12 +2961,12 @@ MonoBehaviour:
m_EditorClassIdentifier:
dontDestroyOnLoad: 1
runInBackground: 1
startOnHeadless: 1
autoStartServerBuild: 1
showDebugMessages: 0
serverTickRate: 30
offlineScene:
onlineScene:
transport: {fileID: 1783103024}
transport: {fileID: 1783103023}
networkAddress: localhost
maxConnections: 4
disconnectInactiveConnections: 0

View File

@ -12,7 +12,7 @@ GameObject:
- component: {fileID: 4798169800353248833}
- component: {fileID: 5399210850297115757}
- component: {fileID: 1442807832621757098}
- component: {fileID: 4798169800353248834}
- component: {fileID: 7877660282335013212}
m_Layer: 0
m_Name: NetworkManagerPong
m_TagString: Untagged
@ -51,8 +51,6 @@ MonoBehaviour:
_onServerListUpdated:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.Cloud.ServerListEvent, Mirror.Cloud, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
--- !u!114 &5399210850297115757
MonoBehaviour:
m_ObjectHideFlags: 0
@ -65,6 +63,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 1f6e5d5acb5879f45a2235ae0f44dc92, type: 3}
m_Name:
m_EditorClassIdentifier:
manager: {fileID: 0}
connector: {fileID: 0}
gameName: Pong Game
--- !u!114 &1442807832621757098
MonoBehaviour:
@ -80,12 +80,12 @@ MonoBehaviour:
m_EditorClassIdentifier:
dontDestroyOnLoad: 1
runInBackground: 1
startOnHeadless: 1
autoStartServerBuild: 1
showDebugMessages: 0
serverTickRate: 30
offlineScene: Assets/Mirror/Examples/Cloud/PongWithListServer/Scenes/ListServerLobbyScenePong.unity
onlineScene: Assets/Mirror/Examples/Cloud/PongWithListServer/Scenes/PongGameScene.unity
transport: {fileID: 4798169800353248834}
transport: {fileID: 7877660282335013212}
networkAddress: localhost
maxConnections: 2
disconnectInactiveConnections: 0
@ -97,7 +97,7 @@ MonoBehaviour:
playerSpawnMethod: 1
spawnPrefabs:
- {fileID: 1080679924113744, guid: a4b57f17790d9634ea5fd0fe80b214fd, type: 3}
--- !u!114 &4798169800353248834
--- !u!114 &7877660282335013212
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
@ -106,50 +106,38 @@ MonoBehaviour:
m_GameObject: {fileID: 4798169800353248846}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
m_Script: {fileID: 11500000, guid: 6b0fecffa3f624585964b0d0eb21b18e, type: 3}
m_Name:
m_EditorClassIdentifier:
OnClientConnected:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
OnClientDataReceived:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.ClientDataReceivedEvent, Mirror, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
OnClientError:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.UnityEventException, Mirror, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
OnClientDisconnected:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
OnServerConnected:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.UnityEventInt, Mirror, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
OnServerDataReceived:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.ServerDataReceivedEvent, Mirror, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
OnServerError:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.UnityEventIntException, Mirror, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
OnServerDisconnected:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.UnityEventInt, Mirror, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
port: 7777
Port: 7777
NoDelay: 1
serverMaxMessageSize: 16384
serverMaxReceivesPerTick: 10000
clientMaxMessageSize: 16384
clientMaxReceivesPerTick: 1000
Interval: 10
FastResend: 0
CongestionWindow: 1
SendWindowSize: 128
ReceiveWindowSize: 128
debugGUI: 0

View File

@ -13,7 +13,6 @@ GameObject:
- component: {fileID: 5399210850297115757}
- component: {fileID: 5256484632236059241}
- component: {fileID: 1442807832621757098}
- component: {fileID: 4798169800353248834}
m_Layer: 0
m_Name: TanksNetworkManager
m_TagString: Untagged
@ -52,8 +51,6 @@ MonoBehaviour:
_onServerListUpdated:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.Cloud.ServerListEvent, Mirror.Cloud, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
--- !u!114 &5399210850297115757
MonoBehaviour:
m_ObjectHideFlags: 0
@ -66,6 +63,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 1f6e5d5acb5879f45a2235ae0f44dc92, type: 3}
m_Name:
m_EditorClassIdentifier:
manager: {fileID: 0}
connector: {fileID: 0}
gameName: Tanks Game
--- !u!114 &5256484632236059241
MonoBehaviour:
@ -93,12 +92,12 @@ MonoBehaviour:
m_EditorClassIdentifier:
dontDestroyOnLoad: 1
runInBackground: 1
startOnHeadless: 1
autoStartServerBuild: 1
showDebugMessages: 0
serverTickRate: 30
offlineScene: Assets/Mirror/Examples/Cloud/TanksWithListServer/Scenes/ListServerLobbySceneTanks.unity
onlineScene: Assets/Mirror/Examples/Tanks/Scenes/Scene.unity
transport: {fileID: 4798169800353248834}
transport: {fileID: 0}
networkAddress: localhost
maxConnections: 4
disconnectInactiveConnections: 0
@ -110,59 +109,3 @@ MonoBehaviour:
playerSpawnMethod: 1
spawnPrefabs:
- {fileID: 5890560936853567077, guid: b7dd46dbf38c643f09e206f9fa4be008, type: 3}
--- !u!114 &4798169800353248834
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4798169800353248846}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
m_Name:
m_EditorClassIdentifier:
OnClientConnected:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
OnClientDataReceived:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.ClientDataReceivedEvent, Mirror, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
OnClientError:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.UnityEventException, Mirror, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
OnClientDisconnected:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
OnServerConnected:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.UnityEventInt, Mirror, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
OnServerDataReceived:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.ServerDataReceivedEvent, Mirror, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
OnServerError:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.UnityEventIntException, Mirror, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
OnServerDisconnected:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.UnityEventInt, Mirror, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
port: 7777
NoDelay: 1
serverMaxMessageSize: 16384
serverMaxReceivesPerTick: 10000
clientMaxMessageSize: 16384
clientMaxReceivesPerTick: 1000

View File

@ -451,6 +451,11 @@ PrefabInstance:
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4971607475644947932, guid: e16e442bbd8d4434cb606afd72bcd08b,
type: 3}
propertyPath: m_AnchoredPosition.y
value: 0.000091552734
objectReference: {fileID: 0}
- target: {fileID: 4971607476029058370, guid: e16e442bbd8d4434cb606afd72bcd08b,
type: 3}
propertyPath: m_AnchorMin.y
@ -521,6 +526,11 @@ PrefabInstance:
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4971607476873278848, guid: e16e442bbd8d4434cb606afd72bcd08b,
type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b,
type: 3}
propertyPath: m_LocalPosition.x

View File

@ -395,7 +395,7 @@ MonoBehaviour:
m_GameObject: {fileID: 1556883243}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
m_Script: {fileID: 11500000, guid: 6b0fecffa3f624585964b0d0eb21b18e, type: 3}
m_Name:
m_EditorClassIdentifier:
OnClientConnected:
@ -422,10 +422,14 @@ MonoBehaviour:
OnServerDisconnected:
m_PersistentCalls:
m_Calls: []
port: 7777
Port: 7777
NoDelay: 1
serverMaxMessageSize: 16384
clientMaxMessageSize: 16384
Interval: 10
FastResend: 0
CongestionWindow: 1
SendWindowSize: 128
ReceiveWindowSize: 128
debugGUI: 0
--- !u!114 &1556883245
MonoBehaviour:
m_ObjectHideFlags: 0
@ -440,7 +444,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
dontDestroyOnLoad: 1
runInBackground: 1
startOnHeadless: 1
autoStartServerBuild: 1
showDebugMessages: 0
serverTickRate: 30
offlineScene:

View File

@ -38,7 +38,7 @@ RenderSettings:
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 690741348}
m_IndirectSpecularColor: {r: 0.4366757, g: 0.48427194, b: 0.5645252, a: 1}
m_IndirectSpecularColor: {r: 0.43667564, g: 0.48427147, b: 0.56452364, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
@ -54,7 +54,7 @@ LightmapSettings:
m_EnableBakedLightmaps: 0
m_EnableRealtimeLightmaps: 0
m_LightmapEditorSettings:
serializedVersion: 12
serializedVersion: 10
m_Resolution: 2
m_BakeResolution: 40
m_AtlasSize: 1024
@ -62,7 +62,6 @@ LightmapSettings:
m_AOMaxDistance: 1
m_CompAOExponent: 1
m_CompAOExponentDirect: 0
m_ExtractAmbientOcclusion: 0
m_Padding: 2
m_LightmapParameters: {fileID: 0}
m_LightmapsBakeMode: 1
@ -77,16 +76,10 @@ LightmapSettings:
m_PVRDirectSampleCount: 32
m_PVRSampleCount: 500
m_PVRBounces: 2
m_PVREnvironmentSampleCount: 500
m_PVREnvironmentReferencePointCount: 2048
m_PVRFilteringMode: 2
m_PVRDenoiserTypeDirect: 0
m_PVRDenoiserTypeIndirect: 0
m_PVRDenoiserTypeAO: 0
m_PVRFilterTypeDirect: 0
m_PVRFilterTypeIndirect: 0
m_PVRFilterTypeAO: 0
m_PVREnvironmentMIS: 0
m_PVRFilteringMode: 2
m_PVRCulling: 1
m_PVRFilteringGaussRadiusDirect: 1
m_PVRFilteringGaussRadiusIndirect: 5
@ -94,8 +87,7 @@ LightmapSettings:
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
m_PVRFilteringAtrousPositionSigmaIndirect: 2
m_PVRFilteringAtrousPositionSigmaAO: 1
m_ExportTrainingData: 0
m_TrainingDataDestination: TrainingData
m_ShowResolutionOverlay: 1
m_LightingDataAsset: {fileID: 0}
m_UseShadowmask: 1
--- !u!196 &4
@ -158,10 +150,9 @@ Camera:
m_ClearFlags: 1
m_BackGroundColor: {r: 0, g: 0, b: 0, a: 0}
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_GateFitMode: 2
m_FocalLength: 50
m_NormalizedViewPortRect:
serializedVersion: 2
@ -213,8 +204,8 @@ GameObject:
m_Component:
- component: {fileID: 69965670}
- component: {fileID: 69965669}
- component: {fileID: 69965668}
- component: {fileID: 69965667}
- component: {fileID: 69965668}
m_Layer: 0
m_Name: Network
m_TagString: Untagged
@ -246,7 +237,7 @@ MonoBehaviour:
m_GameObject: {fileID: 69965666}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
m_Script: {fileID: 11500000, guid: 6b0fecffa3f624585964b0d0eb21b18e, type: 3}
m_Name:
m_EditorClassIdentifier:
OnClientConnected:
@ -273,12 +264,14 @@ MonoBehaviour:
OnServerDisconnected:
m_PersistentCalls:
m_Calls: []
port: 7777
Port: 7777
NoDelay: 1
serverMaxMessageSize: 16384
serverMaxReceivesPerTick: 10000
clientMaxMessageSize: 16384
clientMaxReceivesPerTick: 1000
Interval: 10
FastResend: 0
CongestionWindow: 1
SendWindowSize: 128
ReceiveWindowSize: 128
debugGUI: 0
--- !u!114 &69965669
MonoBehaviour:
m_ObjectHideFlags: 0
@ -293,7 +286,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
dontDestroyOnLoad: 0
runInBackground: 1
startOnHeadless: 1
autoStartServerBuild: 1
showDebugMessages: 0
serverTickRate: 30
offlineScene:
@ -480,13 +473,12 @@ Light:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 690741347}
m_Enabled: 1
serializedVersion: 9
serializedVersion: 8
m_Type: 1
m_Color: {r: 0.990566, g: 0.9496818, b: 0.82702917, a: 1}
m_Intensity: 1
m_Range: 10
m_SpotAngle: 30
m_InnerSpotAngle: 21.80208
m_CookieSize: 10
m_Shadows:
m_Type: 2
@ -496,24 +488,6 @@ Light:
m_Bias: 0.05
m_NormalBias: 0.4
m_NearPlane: 0.2
m_CullingMatrixOverride:
e00: 1
e01: 0
e02: 0
e03: 0
e10: 0
e11: 1
e12: 0
e13: 0
e20: 0
e21: 0
e22: 1
e23: 0
e30: 0
e31: 0
e32: 0
e33: 1
m_UseCullingMatrixOverride: 0
m_Cookie: {fileID: 0}
m_DrawHalo: 0
m_Flare: {fileID: 0}
@ -521,15 +495,12 @@ Light:
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingLayerMask: 1
m_Lightmapping: 4
m_LightShadowCasterMode: 0
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
m_UseBoundingSphereOverride: 0
m_ShadowRadius: 0
m_ShadowAngle: 0
--- !u!4 &690741349

View File

@ -872,7 +872,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
dontDestroyOnLoad: 1
runInBackground: 1
startOnHeadless: 1
autoStartServerBuild: 1
showDebugMessages: 0
serverTickRate: 30
offlineScene:
@ -900,7 +900,7 @@ MonoBehaviour:
m_GameObject: {fileID: 1886246549}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
m_Script: {fileID: 11500000, guid: 6b0fecffa3f624585964b0d0eb21b18e, type: 3}
m_Name:
m_EditorClassIdentifier:
OnClientConnected:
@ -927,7 +927,11 @@ MonoBehaviour:
OnServerDisconnected:
m_PersistentCalls:
m_Calls: []
port: 7777
Port: 7777
NoDelay: 1
serverMaxMessageSize: 16384
clientMaxMessageSize: 16384
Interval: 10
FastResend: 0
CongestionWindow: 1
SendWindowSize: 128
ReceiveWindowSize: 128
debugGUI: 0

View File

@ -38,7 +38,7 @@ RenderSettings:
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1}
m_IndirectSpecularColor: {r: 0.44657868, g: 0.49641263, b: 0.57481706, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
@ -214,8 +214,8 @@ GameObject:
m_Component:
- component: {fileID: 492096636}
- component: {fileID: 492096635}
- component: {fileID: 492096634}
- component: {fileID: 492096637}
- component: {fileID: 492096634}
m_Layer: 0
m_Name: NetworkManager
m_TagString: Untagged
@ -232,53 +232,41 @@ MonoBehaviour:
m_GameObject: {fileID: 492096633}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
m_Script: {fileID: 11500000, guid: 6b0fecffa3f624585964b0d0eb21b18e, type: 3}
m_Name:
m_EditorClassIdentifier:
OnClientConnected:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
OnClientDataReceived:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.ClientDataReceivedEvent, Mirror, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
OnClientError:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.UnityEventException, Mirror, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
OnClientDisconnected:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
OnServerConnected:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.UnityEventInt, Mirror, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
OnServerDataReceived:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.ServerDataReceivedEvent, Mirror, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
OnServerError:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.UnityEventIntException, Mirror, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
OnServerDisconnected:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.UnityEventInt, Mirror, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
port: 7777
Port: 7777
NoDelay: 1
serverMaxMessageSize: 16384
serverMaxReceivesPerTick: 10000
clientMaxMessageSize: 16384
clientMaxReceivesPerTick: 1000
Interval: 10
FastResend: 0
CongestionWindow: 1
SendWindowSize: 128
ReceiveWindowSize: 128
debugGUI: 0
--- !u!114 &492096635
MonoBehaviour:
m_ObjectHideFlags: 0
@ -293,7 +281,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
dontDestroyOnLoad: 1
runInBackground: 1
startOnHeadless: 1
autoStartServerBuild: 1
showDebugMessages: 0
serverTickRate: 30
offlineScene:
@ -394,8 +382,6 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
@ -881,8 +867,6 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
@ -955,8 +939,6 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 24
@ -1034,8 +1016,6 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 24
@ -1296,8 +1276,6 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 24
@ -1378,8 +1356,6 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0

View File

@ -222,7 +222,7 @@ MonoBehaviour:
m_GameObject: {fileID: 2008127829}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
m_Script: {fileID: 11500000, guid: 6b0fecffa3f624585964b0d0eb21b18e, type: 3}
m_Name:
m_EditorClassIdentifier:
OnClientConnected:
@ -249,10 +249,14 @@ MonoBehaviour:
OnServerDisconnected:
m_PersistentCalls:
m_Calls: []
port: 7777
Port: 7777
NoDelay: 1
serverMaxMessageSize: 16384
clientMaxMessageSize: 16384
Interval: 10
FastResend: 0
CongestionWindow: 1
SendWindowSize: 128
ReceiveWindowSize: 128
debugGUI: 0
--- !u!114 &2008127831
MonoBehaviour:
m_ObjectHideFlags: 0
@ -267,7 +271,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
dontDestroyOnLoad: 1
runInBackground: 1
startOnHeadless: 1
autoStartServerBuild: 1
showDebugMessages: 0
serverTickRate: 30
offlineScene: Assets/Mirror/Examples/Room/Scenes/OfflineScene.unity
@ -290,7 +294,7 @@ MonoBehaviour:
type: 3}
RoomScene: Assets/Mirror/Examples/Room/Scenes/RoomScene.unity
GameplayScene: Assets/Mirror/Examples/Room/Scenes/OnlineScene.unity
allPlayersReady: 0
_allPlayersReady: 0
roomSlots: []
--- !u!4 &2008127832
Transform:

View File

@ -443,14 +443,17 @@ MonoBehaviour:
m_EditorClassIdentifier:
dontDestroyOnLoad: 1
runInBackground: 1
startOnHeadless: 1
serverTickRate: 30
autoStartServerBuild: 1
showDebugMessages: 0
serverTickRate: 30
offlineScene:
onlineScene:
transport: {fileID: 1282001521}
networkAddress: localhost
maxConnections: 4
disconnectInactiveConnections: 0
disconnectInactiveTimeout: 60
authenticator: {fileID: 0}
playerPrefab: {fileID: 1916082411674582, guid: 6f43bf5488a7443d19ab2a83c6b91f35,
type: 3}
autoCreatePlayer: 1
@ -466,49 +469,41 @@ MonoBehaviour:
m_GameObject: {fileID: 1282001517}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3}
m_Script: {fileID: 11500000, guid: 6b0fecffa3f624585964b0d0eb21b18e, type: 3}
m_Name:
m_EditorClassIdentifier:
OnClientConnected:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
OnClientDataReceived:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.UnityEventByteArray, Mirror, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
OnClientError:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.UnityEventException, Mirror, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
OnClientDisconnected:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
OnServerConnected:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.UnityEventInt, Mirror, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
OnServerDataReceived:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.UnityEventIntByteArray, Mirror, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
OnServerError:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.UnityEventIntException, Mirror, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
OnServerDisconnected:
m_PersistentCalls:
m_Calls: []
m_TypeName: Mirror.UnityEventInt, Mirror, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
port: 7777
Port: 7777
NoDelay: 1
Interval: 10
FastResend: 0
CongestionWindow: 1
SendWindowSize: 128
ReceiveWindowSize: 128
debugGUI: 0
--- !u!1 &1458789072
GameObject:
m_ObjectHideFlags: 0

View File

@ -7,7 +7,7 @@
"optionalUnityReferences": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"allowUnsafeCode": true,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,

View File

@ -4,6 +4,7 @@
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.Serialization;
using kcp2k;
namespace Mirror
{
@ -44,7 +45,7 @@ public class NetworkManager : MonoBehaviour
/// <summary>
/// Automatically invoke StartServer()
/// <para>If the application is a Server Build, StartServer is automatically invoked.</para>
/// <para>Server build is true when "Server build" is checked in build menu, or BuildOptions.EnableHeadlessMode flag is in BuildOptions</para>
/// <para>Server build is true when "Server build" is checked in build menu, or BuildOptions.EnableHeadlessMode flag is in BuildOptions</para>
/// </summary>
[Tooltip("Should the server auto-start when 'Server Build' is checked in build settings")]
[FormerlySerializedAs("startOnHeadless")]
@ -204,7 +205,7 @@ public virtual void OnValidate()
transport = GetComponent<Transport>();
if (transport == null)
{
transport = gameObject.AddComponent<TelepathyTransport>();
transport = gameObject.AddComponent<KcpTransport>();
logger.Log("NetworkManager: added default Transport because there was none yet.");
}
#if UNITY_EDITOR

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 953bb5ec5ab2346a092f58061e01ba65
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7bdb797750d0a490684410110bf48192
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,172 @@
#if MIRROR
using System;
using System.Linq;
using System.Net;
using UnityEngine;
using Mirror;
namespace kcp2k
{
public class KcpTransport : Transport
{
// scheme used by this transport
public const string Scheme = "kcp";
// common
[Header("Transport Configuration")]
public ushort Port = 7777;
[Tooltip("NoDelay is recommended to reduce latency. This also scales better without buffers getting full.")]
public bool NoDelay = true;
[Tooltip("KCP internal update interval. 100ms is KCP default, but a lower interval is recommended to minimize latency and to scale to more networked entities.")]
public uint Interval = 10;
[Header("Advanced")]
[Tooltip("KCP fastresend parameter. Faster resend for the cost of higher bandwidth.")]
public int FastResend = 0;
[Tooltip("KCP congestion window can be disabled. This is necessary to Mirror 10k Benchmark. Disable this for high scale games if connections get chocked regularly.")]
public bool CongestionWindow = true; // KCP 'NoCongestionWindow' is false by default. here we negate it for ease of use.
[Tooltip("KCP window size can be modified to support higher loads. For example, Mirror Benchmark requires 128 for 4k monsters, 256 for 10k monsters (if CongestionWindow is disabled.)")]
public uint SendWindowSize = 128; //Kcp.WND_SND; 32 by default. 128 is better for 4k Benchmark etc.
[Tooltip("KCP window size can be modified to support higher loads. For example, Mirror Benchmark requires 128 for 4k monsters, 256 for 10k monsters (if CongestionWindow is disabled.)")]
public uint ReceiveWindowSize = Kcp.WND_RCV;
// server & client
KcpServer server;
KcpClient client;
// debugging
[Header("Debug")]
public bool debugGUI;
void Awake()
{
// TODO simplify after converting Mirror Transport events to Action
client = new KcpClient(
() => OnClientConnected.Invoke(),
(message) => OnClientDataReceived.Invoke(message, Channels.DefaultReliable),
() => OnClientDisconnected.Invoke()
);
// TODO simplify after converting Mirror Transport events to Action
server = new KcpServer(
(connectionId) => OnServerConnected.Invoke(connectionId),
(connectionId, message) => OnServerDataReceived.Invoke(connectionId, message, Channels.DefaultReliable),
(connectionId) => OnServerDisconnected.Invoke(connectionId),
NoDelay,
Interval,
FastResend,
CongestionWindow,
SendWindowSize,
ReceiveWindowSize
);
Debug.Log("KcpTransport initialized!");
}
// all except WebGL
public override bool Available() =>
Application.platform != RuntimePlatform.WebGLPlayer;
// client
public override bool ClientConnected() => client.connected;
public override void ClientConnect(string address)
{
client.Connect(address, Port, NoDelay, Interval, FastResend, CongestionWindow, SendWindowSize, ReceiveWindowSize);
}
public override void ClientSend(int channelId, ArraySegment<byte> segment)
{
client.Send(segment);
}
public override void ClientDisconnect() => client.Disconnect();
// IMPORTANT: set script execution order to >1000 to call Transport's
// LateUpdate after all others. Fixes race condition where
// e.g. in uSurvival Transport would apply Cmds before
// ShoulderRotation.LateUpdate, resulting in projectile
// spawns at the point before shoulder rotation.
public void LateUpdate()
{
// note: we need to check enabled in case we set it to false
// when LateUpdate already started.
// (https://github.com/vis2k/Mirror/pull/379)
if (!enabled)
return;
server.Tick();
client.Tick();
}
// server
public override Uri ServerUri()
{
UriBuilder builder = new UriBuilder();
builder.Scheme = Scheme;
builder.Host = Dns.GetHostName();
builder.Port = Port;
return builder.Uri;
}
public override bool ServerActive() => server.IsActive();
public override void ServerStart() => server.Start(Port);
public override void ServerSend(int connectionId, int channelId, ArraySegment<byte> segment)
{
server.Send(connectionId, segment);
}
public override bool ServerDisconnect(int connectionId)
{
server.Disconnect(connectionId);
return true;
}
public override string ServerGetClientAddress(int connectionId) => server.GetClientAddress(connectionId);
public override void ServerStop() => server.Stop();
// common
public override void Shutdown() {}
// MTU
public override int GetMaxPacketSize(int channelId = Channels.DefaultReliable) => Kcp.MTU_DEF;
public override string ToString()
{
return "KCP";
}
int GetTotalSendQueue() =>
server.connections.Values.Sum(conn => conn.kcp.snd_queue.Count);
int GetTotalReceiveQueue() =>
server.connections.Values.Sum(conn => conn.kcp.rcv_queue.Count);
int GetTotalSendBuffer() =>
server.connections.Values.Sum(conn => conn.kcp.snd_buf.Count);
int GetTotalReceiveBuffer() =>
server.connections.Values.Sum(conn => conn.kcp.rcv_buf.Count);
void OnGUI()
{
if (!debugGUI) return;
GUILayout.BeginArea(new Rect(5, 100, 300, 300));
if (ServerActive())
{
GUILayout.BeginVertical("Box");
GUILayout.Label("SERVER");
GUILayout.Label(" connections: " + server.connections.Count);
GUILayout.Label(" SendQueue: " + GetTotalSendQueue());
GUILayout.Label(" ReceiveQueue: " + GetTotalReceiveQueue());
GUILayout.Label(" SendBuffer: " + GetTotalSendBuffer());
GUILayout.Label(" ReceiveBuffer: " + GetTotalReceiveBuffer());
GUILayout.EndVertical();
}
if (ClientConnected())
{
GUILayout.BeginVertical("Box");
GUILayout.Label("CLIENT");
GUILayout.Label(" SendQueue: " + client.connection.kcp.snd_queue.Count);
GUILayout.Label(" ReceiveQueue: " + client.connection.kcp.rcv_queue.Count);
GUILayout.Label(" SendBuffer: " + client.connection.kcp.snd_buf.Count);
GUILayout.Label(" ReceiveBuffer: " + client.connection.kcp.rcv_buf.Count);
GUILayout.EndVertical();
}
GUILayout.EndArea();
}
}
}
#endif

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6b0fecffa3f624585964b0d0eb21b18e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 71a1c8e8c022d4731a481c1808f37e5d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,24 @@
MIT License
Copyright (c) 2016 limpo1989
Copyright (c) 2020 Paul Pacheco
Copyright (c) 2020 Lymdun
Copyright (c) 2020 vis2k
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9a3e8369060cf4e94ac117603de47aa6
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
V1.1
- high level cleanup, fixes, improvements
V1.0
- Kcp.cs now mirrors original Kcp.c behaviour
(this fixes dozens of bugs)
V0.1
- initial kcp-csharp based version

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ed3f2cf1bbf1b4d53a6f2c103d311f71
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5a54d18b954cb4407a28b633fc32ea6d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,95 @@
// kcp client logic abstracted into a class.
// for use in Mirror, DOTSNET, testing, etc.
using System;
using UnityEngine;
namespace kcp2k
{
public class KcpClient
{
// events
public Action OnConnected;
public Action<ArraySegment<byte>> OnData;
public Action OnDisconnected;
// state
public KcpClientConnection connection;
public bool connected;
public KcpClient(Action OnConnected, Action<ArraySegment<byte>> OnData, Action OnDisconnected)
{
this.OnConnected = OnConnected;
this.OnData = OnData;
this.OnDisconnected = OnDisconnected;
}
public void Connect(string address, ushort port, bool noDelay, uint interval, int fastResend = 0, bool congestionWindow = true, uint sendWindowSize = Kcp.WND_SND, uint receiveWindowSize = Kcp.WND_RCV)
{
if (connected)
{
Debug.LogWarning("KCP: client already connected!");
return;
}
connection = new KcpClientConnection();
// setup events
connection.OnAuthenticated = () =>
{
Debug.Log($"KCP: OnClientConnected");
connected = true;
OnConnected.Invoke();
};
connection.OnData = (message) =>
{
//Debug.Log($"KCP: OnClientData({BitConverter.ToString(message.Array, message.Offset, message.Count)})");
OnData.Invoke(message);
};
connection.OnDisconnected = () =>
{
Debug.Log($"KCP: OnClientDisconnected");
connected = false;
connection = null;
OnDisconnected.Invoke();
};
// connect
connection.Connect(address, port, noDelay, interval, fastResend, congestionWindow, sendWindowSize, receiveWindowSize);
}
public void Send(ArraySegment<byte> segment)
{
if (connected)
{
connection.Send(segment);
}
else Debug.LogWarning("KCP: can't send because client not connected!");
}
public void Disconnect()
{
// only if connected
// otherwise we end up in a deadlock because of an open Mirror bug:
// https://github.com/vis2k/Mirror/issues/2353
if (connected)
{
// call Disconnect and let the connection handle it.
// DO NOT set it to null yet. it needs to be updated a few more
// times first. let the connection handle it!
connection?.Disconnect();
}
}
public void Tick()
{
// tick client connection
if (connection != null)
{
// recv on socket first
connection.RawReceive();
// then update
connection.Tick();
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6aa069a28ed24fedb533c102d9742b36
timeCreated: 1603786960

View File

@ -0,0 +1,59 @@
using UnityEngine;
using System.Net;
using System.Net.Sockets;
namespace kcp2k
{
public class KcpClientConnection : KcpConnection
{
readonly byte[] buffer = new byte[1500];
public void Connect(string host, ushort port, bool noDelay, uint interval = Kcp.INTERVAL, int fastResend = 0, bool congestionWindow = true, uint sendWindowSize = Kcp.WND_SND, uint receiveWindowSize = Kcp.WND_RCV)
{
Debug.Log($"KcpClient: connect to {host}:{port}");
IPAddress[] ipAddress = Dns.GetHostAddresses(host);
if (ipAddress.Length < 1)
throw new SocketException((int)SocketError.HostNotFound);
remoteEndpoint = new IPEndPoint(ipAddress[0], port);
socket = new Socket(remoteEndpoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
socket.Connect(remoteEndpoint);
SetupKcp(noDelay, interval, fastResend, congestionWindow, sendWindowSize, receiveWindowSize);
// client should send handshake to server as very first message
SendHandshake();
RawReceive();
}
// call from transport update
public void RawReceive()
{
try
{
if (socket != null)
{
while (socket.Poll(0, SelectMode.SelectRead))
{
int msgLength = socket.ReceiveFrom(buffer, ref remoteEndpoint);
//Debug.Log($"KCP: client raw recv {msgLength} bytes = {BitConverter.ToString(buffer, 0, msgLength)}");
RawInput(buffer, msgLength);
}
}
}
// this is fine, the socket might have been closed in the other end
catch (SocketException) {}
}
protected override void Dispose()
{
socket.Close();
socket = null;
}
protected override void RawSend(byte[] data, int length)
{
socket.Send(data, length, SocketFlags.None);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 96512e74aa8214a6faa8a412a7a07877
timeCreated: 1602601237

View File

@ -0,0 +1,360 @@
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using Debug = UnityEngine.Debug;
namespace kcp2k
{
enum KcpState { Connected, Authenticated, Disconnected }
public abstract class KcpConnection
{
protected Socket socket;
protected EndPoint remoteEndpoint;
internal Kcp kcp;
// kcp can have several different states, let's use a state machine
KcpState state = KcpState.Disconnected;
public Action OnAuthenticated;
public Action<ArraySegment<byte>> OnData;
public Action OnDisconnected;
// If we don't receive anything these many milliseconds
// then consider us disconnected
public const int TIMEOUT = 10000;
uint lastReceiveTime;
// internal time.
// StopWatch offers ElapsedMilliSeconds and should be more precise than
// Unity's time.deltaTime over long periods.
readonly Stopwatch refTime = new Stopwatch();
// recv buffer to avoid allocations
byte[] buffer = new byte[Kcp.MTU_DEF];
internal static readonly ArraySegment<byte> Hello = new ArraySegment<byte>(new byte[] { 0 });
static readonly ArraySegment<byte> Goodbye = new ArraySegment<byte>(new byte[] { 1 });
static readonly ArraySegment<byte> Ping = new ArraySegment<byte>(new byte[] { 2 });
// send a ping occasionally so we don't time out on the other end.
// for example, creating a character in an MMO could easily take a
// minute of no data being sent. which doesn't mean we want to time out.
// same goes for slow paced card games etc.
public const int PING_INTERVAL = 1000;
uint lastPingTime;
// if we send more than kcp can handle, we will get ever growing
// send/recv buffers and queues and minutes of latency.
// => if a connection can't keep up, it should be disconnected instead
// to protect the server under heavy load, and because there is no
// point in growing to gigabytes of memory or minutes of latency!
// => 2k isn't enough. we reach 2k when spawning 4k monsters at once
// easily, but it does recover over time.
// => 10k seems safe.
//
// note: we have a ChokeConnectionAutoDisconnects test for this too!
internal const int QueueDisconnectThreshold = 10000;
// NoDelay, interval, window size are the most important configurations.
// let's force require the parameters so we don't forget it anywhere.
protected void SetupKcp(bool noDelay, uint interval = Kcp.INTERVAL, int fastResend = 0, bool congestionWindow = true, uint sendWindowSize = Kcp.WND_SND, uint receiveWindowSize = Kcp.WND_RCV)
{
kcp = new Kcp(0, RawSend);
// set nodelay.
// note that kcp uses 'nocwnd' internally so we negate the parameter
kcp.SetNoDelay(noDelay ? 1u : 0u, interval, fastResend, !congestionWindow);
kcp.SetWindowSize(sendWindowSize, receiveWindowSize);
refTime.Start();
state = KcpState.Connected;
Tick();
}
void HandleTimeout(uint time)
{
// note: we are also sending a ping regularly, so timeout should
// only ever happen if the connection is truly gone.
if (time >= lastReceiveTime + TIMEOUT)
{
Debug.LogWarning($"KCP: Connection timed out after {TIMEOUT}ms. Disconnecting.");
Disconnect();
}
}
void HandleDeadLink()
{
// kcp has 'dead_link' detection. might as well use it.
if (kcp.state == -1)
{
Debug.LogWarning("KCP Connection dead_link detected. Disconnecting.");
Disconnect();
}
}
// send a ping occasionally in order to not time out on the other end.
void HandlePing(uint time)
{
// enough time elapsed since last ping?
if (time >= lastPingTime + PING_INTERVAL)
{
// ping again and reset time
//Debug.Log("KCP: sending ping...");
Send(Ping);
lastPingTime = time;
}
}
void HandleChoked()
{
// disconnect connections that can't process the load.
// see QueueSizeDisconnect comments.
int total = kcp.rcv_queue.Count + kcp.snd_queue.Count +
kcp.rcv_buf.Count + kcp.snd_buf.Count;
if (total >= QueueDisconnectThreshold)
{
Debug.LogWarning($"KCP: disconnecting connection because it can't process data fast enough.\n" +
$"Queue total {total}>{QueueDisconnectThreshold}. rcv_queue={kcp.rcv_queue.Count} snd_queue={kcp.snd_queue.Count} rcv_buf={kcp.rcv_buf.Count} snd_buf={kcp.snd_buf.Count}\n" +
$"* Try to Enable NoDelay, decrease INTERVAL, disable Congestion Window (= enable NOCWND!), increase SEND/RECV WINDOW or compress data.\n" +
$"* Or perhaps the network is simply too slow on our end, or on the other end.\n");
// let's clear all pending sends before disconnting with 'Bye'.
// otherwise a single Flush in Disconnect() won't be enough to
// flush thousands of messages to finally deliver 'Bye'.
// this is just faster and more robust.
kcp.snd_queue.Clear();
Disconnect();
}
}
// reads the next message from connection.
bool ReceiveNext(out ArraySegment<byte> message)
{
// read only one message
int msgSize = kcp.PeekSize();
if (msgSize > 0)
{
// only allow receiving up to MaxMessageSize sized messages.
// otherwise we would get BlockCopy ArgumentException anyway.
if (msgSize <= Kcp.MTU_DEF)
{
int received = kcp.Receive(buffer, msgSize);
if (received >= 0)
{
message = new ArraySegment<byte>(buffer, 0, msgSize);
lastReceiveTime = (uint)refTime.ElapsedMilliseconds;
// return false if it was a ping message. true otherwise.
if (Utils.SegmentsEqual(message, Ping))
{
//Debug.Log("KCP: received ping.");
return false;
}
return true;
}
else
{
// if receive failed, close everything
Debug.LogWarning($"Receive failed with error={received}. closing connection.");
Disconnect();
}
}
// we don't allow sending messages > Max, so this must be an
// attacker. let's disconnect to avoid allocation attacks etc.
else
{
Debug.LogWarning($"KCP: possible allocation attack for msgSize {msgSize} > max {Kcp.MTU_DEF}. Disconnecting the connection.");
Disconnect();
}
}
return false;
}
void TickConnected(uint time)
{
// detect common events & ping
HandleTimeout(time);
HandleDeadLink();
HandlePing(time);
HandleChoked();
kcp.Update(time);
// any message received?
if (ReceiveNext(out ArraySegment<byte> message))
{
// handshake message?
if (Utils.SegmentsEqual(message, Hello))
{
Debug.Log("KCP: received handshake");
state = KcpState.Authenticated;
OnAuthenticated?.Invoke();
}
// otherwise it's random data from the internet, not
// from a legitimate player. disconnect.
else
{
Debug.LogWarning("KCP: received random data before handshake. Disconnecting the connection.");
Disconnect();
}
}
}
void TickAuthenticated(uint time)
{
// detect common events & ping
HandleTimeout(time);
HandleDeadLink();
HandlePing(time);
HandleChoked();
kcp.Update(time);
// process all received messages
while (ReceiveNext(out ArraySegment<byte> message))
{
// disconnect message?
if (Utils.SegmentsEqual(message, Goodbye))
{
Debug.Log("KCP: received disconnect message");
Disconnect();
break;
}
// otherwise regular message
else
{
// only accept regular messages
//Debug.LogWarning($"Kcp recv msg: {BitConverter.ToString(buffer, 0, msgSize)}");
OnData?.Invoke(message);
}
}
}
public void Tick()
{
uint time = (uint)refTime.ElapsedMilliseconds;
try
{
switch (state)
{
case KcpState.Connected:
{
TickConnected(time);
break;
}
case KcpState.Authenticated:
{
TickAuthenticated(time);
break;
}
case KcpState.Disconnected:
{
// do nothing while disconnected
break;
}
}
}
catch (SocketException exception)
{
// this is ok, the connection was closed
Debug.Log($"KCP Connection: Disconnecting because {exception}. This is fine.");
Disconnect();
}
catch (ObjectDisposedException exception)
{
// fine, socket was closed
Debug.Log($"KCP Connection: Disconnecting because {exception}. This is fine.");
Disconnect();
}
catch (Exception ex)
{
// unexpected
Debug.LogException(ex);
Disconnect();
}
}
public void RawInput(byte[] buffer, int msgLength)
{
int input = kcp.Input(buffer, msgLength);
if (input != 0)
{
Debug.LogWarning($"Input failed with error={input} for buffer with length={msgLength}");
}
}
protected abstract void RawSend(byte[] data, int length);
public void Send(ArraySegment<byte> data)
{
// only allow sending up to MaxMessageSize sized messages.
// other end won't process bigger messages anyway.
if (data.Count <= Kcp.MTU_DEF)
{
int sent = kcp.Send(data.Array, data.Offset, data.Count);
if (sent < 0)
{
Debug.LogWarning($"Send failed with error={sent} for segment with length={data.Count}");
}
}
else Debug.LogError($"Failed to send message of size {data.Count} because it's larger than MaxMessageSize={Kcp.MTU_DEF}");
}
// server & client need to send handshake at different times, so we need
// to expose the function.
// * client should send it immediately.
// * server should send it as reply to client's handshake, not before
// (server should not reply to random internet messages with handshake)
public void SendHandshake()
{
Debug.Log("KcpConnection: sending Handshake to other end!");
Send(Hello);
}
protected virtual void Dispose()
{
}
// disconnect this connection
public void Disconnect()
{
// only if not disconnected yet
if (state == KcpState.Disconnected)
return;
// send a disconnect message
if (socket.Connected)
{
try
{
Send(Goodbye);
kcp.Flush();
}
catch (SocketException)
{
// this is ok, the connection was already closed
}
catch (ObjectDisposedException)
{
// this is normal when we stop the server
// the socket is stopped so we can't send anything anymore
// to the clients
// the clients will eventually timeout and realize they
// were disconnected
}
}
// set as Disconnected, call event
Debug.Log("KCP Connection: Disconnected.");
state = KcpState.Disconnected;
OnDisconnected?.Invoke();
}
// get remote endpoint
public EndPoint GetRemoteEndPoint() => remoteEndpoint;
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3915c7c62b72d4dc2a9e4e76c94fc484
timeCreated: 1602600432

View File

@ -0,0 +1,229 @@
// kcp server logic abstracted into a class.
// for use in Mirror, DOTSNET, testing, etc.
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using UnityEngine;
namespace kcp2k
{
public class KcpServer
{
// events
public Action<int> OnConnected;
public Action<int, ArraySegment<byte>> OnData;
public Action<int> OnDisconnected;
// configuration
// NoDelay is recommended to reduce latency. This also scales better
// without buffers getting full.
public bool NoDelay;
// KCP internal update interval. 100ms is KCP default, but a lower
// interval is recommended to minimize latency and to scale to more
// networked entities.
public uint Interval;
// KCP fastresend parameter. Faster resend for the cost of higher
// bandwidth.
public int FastResend;
// KCP 'NoCongestionWindow' is false by default. here we negate it for
// ease of use. This can be disabled for high scale games if connections
// choke regularly.
public bool CongestionWindow;
// KCP window size can be modified to support higher loads.
// for example, Mirror Benchmark requires:
// 128, 128 for 4k monsters
// 512, 512 for 10k monsters
// 8192, 8192 for 20k monsters
public uint SendWindowSize;
public uint ReceiveWindowSize;
// state
Socket socket;
EndPoint newClientEP = new IPEndPoint(IPAddress.IPv6Any, 0);
readonly byte[] buffer = new byte[Kcp.MTU_DEF];
// connections <connectionId, connection> where connectionId is EndPoint.GetHashCode
public Dictionary<int, KcpServerConnection> connections = new Dictionary<int, KcpServerConnection>();
public KcpServer(Action<int> OnConnected,
Action<int, ArraySegment<byte>> OnData,
Action<int> OnDisconnected,
bool NoDelay,
uint Interval,
int FastResend = 0,
bool CongestionWindow = true,
uint SendWindowSize = Kcp.WND_SND,
uint ReceiveWindowSize = Kcp.WND_RCV)
{
this.OnConnected = OnConnected;
this.OnData = OnData;
this.OnDisconnected = OnDisconnected;
this.NoDelay = NoDelay;
this.Interval = Interval;
this.FastResend = FastResend;
this.CongestionWindow = CongestionWindow;
this.SendWindowSize = SendWindowSize;
this.ReceiveWindowSize = ReceiveWindowSize;
}
public bool IsActive() => socket != null;
public void Start(ushort port)
{
// only start once
if (socket != null)
{
Debug.LogWarning("KCP: server already started!");
}
// listen
socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp);
socket.DualMode = true;
socket.Bind(new IPEndPoint(IPAddress.IPv6Any, port));
}
public void Send(int connectionId, ArraySegment<byte> segment)
{
if (connections.TryGetValue(connectionId, out KcpServerConnection connection))
{
connection.Send(segment);
}
}
public void Disconnect(int connectionId)
{
if (connections.TryGetValue(connectionId, out KcpServerConnection connection))
{
connection.Disconnect();
}
}
public string GetClientAddress(int connectionId)
{
if (connections.TryGetValue(connectionId, out KcpServerConnection connection))
{
return (connection.GetRemoteEndPoint() as IPEndPoint).Address.ToString();
}
return "";
}
HashSet<int> connectionsToRemove = new HashSet<int>();
public void Tick()
{
while (socket != null && socket.Poll(0, SelectMode.SelectRead))
{
int msgLength = socket.ReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP);
//Debug.Log($"KCP: server raw recv {msgLength} bytes = {BitConverter.ToString(buffer, 0, msgLength)}");
// calculate connectionId from endpoint
int connectionId = newClientEP.GetHashCode();
// is this a new connection?
if (!connections.TryGetValue(connectionId, out KcpServerConnection connection))
{
// create a new KcpConnection
connection = new KcpServerConnection(socket, newClientEP, NoDelay, Interval, FastResend, CongestionWindow, SendWindowSize, ReceiveWindowSize);
// DO NOT add to connections yet. only if the first message
// is actually the kcp handshake. otherwise it's either:
// * random data from the internet
// * or from a client connection that we just disconnected
// but that hasn't realized it yet, still sending data
// from last session that we should absolutely ignore.
//
//
// TODO this allocates a new KcpConnection for each new
// internet connection. not ideal, but C# UDP Receive
// already allocated anyway.
//
// expecting a MAGIC byte[] would work, but sending the raw
// UDP message without kcp's reliability will have low
// probability of being received.
//
// for now, this is fine.
// setup authenticated event that also adds to connections
connection.OnAuthenticated = () =>
{
// only send handshake to client AFTER we received his
// handshake in OnAuthenticated.
// we don't want to reply to random internet messages
// with handshakes each time.
connection.SendHandshake();
// add to connections dict after being authenticated.
connections.Add(connectionId, connection);
Debug.Log($"KCP: server added connection({connectionId}): {newClientEP}");
// setup Data + Disconnected events only AFTER the
// handshake. we don't want to fire OnServerDisconnected
// every time we receive invalid random data from the
// internet.
// setup data event
connection.OnData = (message) =>
{
// call mirror event
//Debug.Log($"KCP: OnServerDataReceived({connectionId}, {BitConverter.ToString(message.Array, message.Offset, message.Count)})");
OnData.Invoke(connectionId, message);
};
// setup disconnected event
connection.OnDisconnected = () =>
{
// flag for removal
// (can't remove directly because connection is updated
// and event is called while iterating all connections)
connectionsToRemove.Add(connectionId);
// call mirror event
Debug.Log($"KCP: OnServerDisconnected({connectionId})");
OnDisconnected.Invoke(connectionId);
};
// finally, call mirror OnConnected event
Debug.Log($"KCP: OnServerConnected({connectionId})");
OnConnected.Invoke(connectionId);
};
// now input the message & tick
// connected event was set up.
// tick will process the first message and adds the
// connection if it was the handshake.
connection.RawInput(buffer, msgLength);
connection.Tick();
// again, do not add to connections.
// if the first message wasn't the kcp handshake then
// connection will simply be garbage collected.
}
// existing connection: simply input the message into kcp
else
{
connection.RawInput(buffer, msgLength);
}
}
// tick all server connections
foreach (KcpServerConnection connection in connections.Values)
{
connection.Tick();
}
// remove disconnected connections
// (can't do it in connection.OnDisconnected because Tick is called
// while iterating connections)
foreach (int connectionId in connectionsToRemove)
{
connections.Remove(connectionId);
}
connectionsToRemove.Clear();
}
public void Stop()
{
socket?.Close();
socket = null;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9759159c6589494a9037f5e130a867ed
timeCreated: 1603787747

View File

@ -0,0 +1,20 @@
using System.Net;
using System.Net.Sockets;
namespace kcp2k
{
public class KcpServerConnection : KcpConnection
{
public KcpServerConnection(Socket socket, EndPoint remoteEndpoint, bool noDelay, uint interval = Kcp.INTERVAL, int fastResend = 0, bool congestionWindow = true, uint sendWindowSize = Kcp.WND_SND, uint receiveWindowSize = Kcp.WND_RCV)
{
this.socket = socket;
this.remoteEndpoint = remoteEndpoint;
SetupKcp(noDelay, interval, fastResend, congestionWindow, sendWindowSize, receiveWindowSize);
}
protected override void RawSend(byte[] data, int length)
{
socket.SendTo(data, 0, length, SocketFlags.None, remoteEndpoint);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 80a9b1ce9a6f14abeb32bfa9921d097b
timeCreated: 1602601483

View File

@ -0,0 +1,23 @@
using System;
using Unity.Collections.LowLevel.Unsafe;
namespace kcp2k
{
public static partial class Utils
{
// ArraySegment content comparison without Linq
public static unsafe bool SegmentsEqual(ArraySegment<byte> a, ArraySegment<byte> b)
{
if (a.Count == b.Count)
{
fixed (byte* aPtr = &a.Array[a.Offset],
bPtr = &b.Array[b.Offset])
{
return UnsafeUtility.MemCmp(aPtr, bPtr, a.Count) == 0;
}
}
return false;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f3a2f1efc7864cb2b01af9d99470613a
timeCreated: 1603833478

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5cafb8851a0084f3e94a580c207b3923
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,3 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("kcp2k.Tests")]

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: aec6a15ac7bd43129317ea1f01f19782
timeCreated: 1602665988

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a59b1cae10a334faf807432ab472f212
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,81 @@
using System.Collections.Generic;
using System.IO;
namespace kcp2k
{
// KCP Segment Definition
internal class Segment
{
internal uint conv; // conversation
internal uint cmd; // command, e.g. Kcp.CMD_ACK etc.
internal uint frg; // fragment
internal uint wnd; // window
internal uint ts; // timestamp
internal uint sn; // serial number
internal uint una;
internal uint resendts; // resend timestamp
internal int rto;
internal uint fastack;
internal uint xmit;
// we need a auto scaling byte[] with a WriteBytes function.
// MemoryStream does that perfectly, no need to reinvent the wheel.
// note: no need to pool it, because Segment is already pooled.
internal MemoryStream data = new MemoryStream();
// pool ////////////////////////////////////////////////////////////////
internal static readonly Stack<Segment> Pool = new Stack<Segment>(32);
public static Segment Take()
{
if (Pool.Count > 0)
{
Segment seg = Pool.Pop();
return seg;
}
return new Segment();
}
public static void Return(Segment seg)
{
seg.Reset();
Pool.Push(seg);
}
////////////////////////////////////////////////////////////////////////
// ikcp_encode_seg
// encode a segment into buffer
internal int Encode(byte[] ptr, int offset)
{
int offset_ = offset;
offset += Utils.Encode32U(ptr, offset, conv);
offset += Utils.Encode8u(ptr, offset, (byte)cmd);
offset += Utils.Encode8u(ptr, offset, (byte)frg);
offset += Utils.Encode16U(ptr, offset, (ushort)wnd);
offset += Utils.Encode32U(ptr, offset, ts);
offset += Utils.Encode32U(ptr, offset, sn);
offset += Utils.Encode32U(ptr, offset, una);
offset += Utils.Encode32U(ptr, offset, (uint)data.Position);
return offset - offset_;
}
// reset to return a fresh segment to the pool
internal void Reset()
{
conv = 0;
cmd = 0;
frg = 0;
wnd = 0;
ts = 0;
sn = 0;
una = 0;
rto = 0;
xmit = 0;
resendts = 0;
fastack = 0;
// keep buffer for next pool usage, but reset length (= bytes written)
data.SetLength(0);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fc58706a05dd3442c8fde858d5266855
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,68 @@
using System.Runtime.CompilerServices;
namespace kcp2k
{
public static partial class Utils
{
// encode 8 bits unsigned int
public static int Encode8u(byte[] p, int offset, byte c)
{
p[0 + offset] = c;
return 1;
}
// decode 8 bits unsigned int
public static int Decode8u(byte[] p, int offset, ref byte c)
{
c = p[0 + offset];
return 1;
}
// encode 16 bits unsigned int (lsb)
public static int Encode16U(byte[] p, int offset, ushort w)
{
p[0 + offset] = (byte)(w >> 0);
p[1 + offset] = (byte)(w >> 8);
return 2;
}
// decode 16 bits unsigned int (lsb)
public static int Decode16U(byte[] p, int offset, ref ushort c)
{
ushort result = 0;
result |= p[0 + offset];
result |= (ushort)(p[1 + offset] << 8);
c = result;
return 2;
}
// encode 32 bits unsigned int (lsb)
public static int Encode32U(byte[] p, int offset, uint l)
{
p[0 + offset] = (byte)(l >> 0);
p[1 + offset] = (byte)(l >> 8);
p[2 + offset] = (byte)(l >> 16);
p[3 + offset] = (byte)(l >> 24);
return 4;
}
// decode 32 bits unsigned int (lsb)
public static int Decode32U(byte[] p, int offset, ref uint c)
{
uint result = 0;
result |= p[0 + offset];
result |= (uint)(p[1 + offset] << 8);
result |= (uint)(p[2 + offset] << 16);
result |= (uint)(p[3 + offset] << 24);
c = result;
return 4;
}
// timediff was a macro in original Kcp. let's inline it if possible.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int TimeDiff(uint later, uint earlier)
{
return (int)(later - earlier);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ef959eb716205bd48b050f010a9a35ae
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

273
Packages/packages-lock.json Normal file
View File

@ -0,0 +1,273 @@
{
"dependencies": {
"com.unity.package-manager-ui": {
"version": "2.0.13",
"depth": 0,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.test-framework.performance": {
"version": "0.1.50-preview",
"depth": 0,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.textmeshpro": {
"version": "1.4.1",
"depth": 0,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.modules.ai": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.animation": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.assetbundle": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.audio": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.cloth": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics": "1.0.0"
}
},
"com.unity.modules.director": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.animation": "1.0.0"
}
},
"com.unity.modules.imageconversion": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.imgui": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.jsonserialize": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.particlesystem": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.physics": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.physics2d": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.screencapture": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.imageconversion": "1.0.0"
}
},
"com.unity.modules.subsystems": {
"version": "1.0.0",
"depth": 1,
"source": "builtin",
"dependencies": {
"com.unity.modules.jsonserialize": "1.0.0"
}
},
"com.unity.modules.terrain": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.terrainphysics": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.terrain": "1.0.0"
}
},
"com.unity.modules.tilemap": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics2d": "1.0.0"
}
},
"com.unity.modules.ui": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.uielements": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.uielementsnative": "1.0.0"
}
},
"com.unity.modules.uielementsnative": {
"version": "1.0.0",
"depth": 1,
"source": "builtin",
"dependencies": {
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0"
}
},
"com.unity.modules.umbra": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.unityanalytics": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0"
}
},
"com.unity.modules.unitywebrequest": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.unitywebrequestassetbundle": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.assetbundle": "1.0.0",
"com.unity.modules.unitywebrequest": "1.0.0"
}
},
"com.unity.modules.unitywebrequestaudio": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.audio": "1.0.0"
}
},
"com.unity.modules.unitywebrequesttexture": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.imageconversion": "1.0.0"
}
},
"com.unity.modules.unitywebrequestwww": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.unitywebrequestassetbundle": "1.0.0",
"com.unity.modules.unitywebrequestaudio": "1.0.0",
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.assetbundle": "1.0.0",
"com.unity.modules.imageconversion": "1.0.0"
}
},
"com.unity.modules.vehicles": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics": "1.0.0"
}
},
"com.unity.modules.video": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.unitywebrequest": "1.0.0"
}
},
"com.unity.modules.vr": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.xr": "1.0.0"
}
},
"com.unity.modules.wind": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.xr": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.subsystems": "1.0.0"
}
}
}
}

Binary file not shown.