Keep local version of files

This commit is contained in:
2026-10-08 00:49:10 +05:30
parent 7fa0621ff8
commit 053665c690
7343 changed files with 5470578 additions and 5470528 deletions
+8 -8
View File
@@ -1,8 +1,8 @@
fileFormatVersion: 2
guid: 03e1ec02518fe484bb1f1237dd9c4b53
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 03e1ec02518fe484bb1f1237dd9c4b53
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+78 -78
View File
@@ -1,78 +1,78 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Blue
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 0, g: 0.5745051, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Blue
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 0, g: 0.5745051, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []
+8 -8
View File
@@ -1,8 +1,8 @@
fileFormatVersion: 2
guid: 819b8aa39c8242e44bdac7415e175082
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 819b8aa39c8242e44bdac7415e175082
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
+78 -78
View File
@@ -1,78 +1,78 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Green
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 0.1357857, g: 1, b: 0, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Green
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 0.1357857, g: 1, b: 0, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []
+8 -8
View File
@@ -1,8 +1,8 @@
fileFormatVersion: 2
guid: bc7208520e54fed4bbbf69acfdc80003
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: bc7208520e54fed4bbbf69acfdc80003
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
+78 -78
View File
@@ -1,78 +1,78 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Red
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 0, b: 0, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Red
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 0, b: 0, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []
+8 -8
View File
@@ -1,8 +1,8 @@
fileFormatVersion: 2
guid: 4df5efc85edee454eab2679f682dce72
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 4df5efc85edee454eab2679f682dce72
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
+8 -8
View File
@@ -1,8 +1,8 @@
fileFormatVersion: 2
guid: 89fffa5a103c8cd41bc4b774b4592fb8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 89fffa5a103c8cd41bc4b774b4592fb8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
+7 -7
View File
@@ -1,7 +1,7 @@
fileFormatVersion: 2
guid: 87e33e26aef57244e8d142595c2914f2
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 87e33e26aef57244e8d142595c2914f2
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
@@ -1,7 +1,7 @@
fileFormatVersion: 2
guid: 56b69b75178c27f429ca86afa8e35766
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 56b69b75178c27f429ca86afa8e35766
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+8 -8
View File
@@ -1,8 +1,8 @@
fileFormatVersion: 2
guid: 6ee42fdcca11b724ebcd8b89ed3bf7ab
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 6ee42fdcca11b724ebcd8b89ed3bf7ab
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+167 -167
View File
@@ -1,167 +1,167 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &891853989634538503
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 891853989634538499}
- component: {fileID: 891853989634538496}
- component: {fileID: 891853989634538497}
- component: {fileID: 891853989634538502}
- component: {fileID: 891853989634538509}
- component: {fileID: 891853989634538508}
- component: {fileID: 6360994593908302921}
m_Layer: 0
m_Name: Player
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &891853989634538499
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 891853989634538503}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1.68, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &891853989634538496
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 891853989634538503}
m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &891853989634538497
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 891853989634538503}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 4df5efc85edee454eab2679f682dce72, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!136 &891853989634538502
CapsuleCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 891853989634538503}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
m_Radius: 0.5
m_Height: 2
m_Direction: 1
m_Center: {x: 0, y: 0, z: 0}
--- !u!114 &891853989634538509
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 891853989634538503}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
m_Name:
m_EditorClassIdentifier:
sceneId: 0
serverOnly: 0
visible: 0
m_AssetId: 02d2f5d2e1a355f4f972dc86642216ba
hasSpawned: 0
--- !u!114 &891853989634538508
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 891853989634538503}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2f74aedd71d9a4f55b3ce499326d45fb, type: 3}
m_Name:
m_EditorClassIdentifier:
syncMode: 0
syncInterval: 0.1
clientAuthority: 0
sendInterval: 0.05
syncPosition: 1
syncRotation: 1
syncScale: 0
interpolatePosition: 1
interpolateRotation: 1
interpolateScale: 0
bufferTimeMultiplier: 1
bufferSizeLimit: 64
catchupThreshold: 4
catchupMultiplier: 0.1
onlySyncOnChange: 1
bufferResetMultiplier: 5
positionSensitivity: 0.01
rotationSensitivity: 0.01
scaleSensitivity: 0.01
showGizmos: 0
showOverlay: 0
overlayColor: {r: 0, g: 0, b: 0, a: 0.5}
--- !u!114 &6360994593908302921
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 891853989634538503}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3a7be0347e7dc43449adcbd1121e447e, type: 3}
m_Name:
m_EditorClassIdentifier:
syncMode: 0
syncInterval: 0.1
movingSpeed: 0.05
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &891853989634538503
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 891853989634538499}
- component: {fileID: 891853989634538496}
- component: {fileID: 891853989634538497}
- component: {fileID: 891853989634538502}
- component: {fileID: 891853989634538509}
- component: {fileID: 891853989634538508}
- component: {fileID: 6360994593908302921}
m_Layer: 0
m_Name: Player
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &891853989634538499
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 891853989634538503}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1.68, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &891853989634538496
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 891853989634538503}
m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &891853989634538497
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 891853989634538503}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 4df5efc85edee454eab2679f682dce72, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!136 &891853989634538502
CapsuleCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 891853989634538503}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
m_Radius: 0.5
m_Height: 2
m_Direction: 1
m_Center: {x: 0, y: 0, z: 0}
--- !u!114 &891853989634538509
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 891853989634538503}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
m_Name:
m_EditorClassIdentifier:
sceneId: 0
serverOnly: 0
visible: 0
m_AssetId: 02d2f5d2e1a355f4f972dc86642216ba
hasSpawned: 0
--- !u!114 &891853989634538508
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 891853989634538503}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2f74aedd71d9a4f55b3ce499326d45fb, type: 3}
m_Name:
m_EditorClassIdentifier:
syncMode: 0
syncInterval: 0.1
clientAuthority: 0
sendInterval: 0.05
syncPosition: 1
syncRotation: 1
syncScale: 0
interpolatePosition: 1
interpolateRotation: 1
interpolateScale: 0
bufferTimeMultiplier: 1
bufferSizeLimit: 64
catchupThreshold: 4
catchupMultiplier: 0.1
onlySyncOnChange: 1
bufferResetMultiplier: 5
positionSensitivity: 0.01
rotationSensitivity: 0.01
scaleSensitivity: 0.01
showGizmos: 0
showOverlay: 0
overlayColor: {r: 0, g: 0, b: 0, a: 0.5}
--- !u!114 &6360994593908302921
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 891853989634538503}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3a7be0347e7dc43449adcbd1121e447e, type: 3}
m_Name:
m_EditorClassIdentifier:
syncMode: 0
syncInterval: 0.1
movingSpeed: 0.05
@@ -1,7 +1,7 @@
fileFormatVersion: 2
guid: 02d2f5d2e1a355f4f972dc86642216ba
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 02d2f5d2e1a355f4f972dc86642216ba
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+8 -8
View File
@@ -1,8 +1,8 @@
fileFormatVersion: 2
guid: 2fd0733b17f542948aa425a833bfe227
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 2fd0733b17f542948aa425a833bfe227
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+169 -169
View File
@@ -1,169 +1,169 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Mirror;
using UnityEngine;
public class CupidConnector : MonoBehaviour
{
public kcp2k.KcpTransport transport;
void Start()
{
#if UNITY_SERVER
//Server code
string[] args = Environment.GetCommandLineArgs();
int matchId = 0;
string dedicatedSecret = null;
bool dedicatedSecretFromCli = false;
string internalApiBase = null;
for (int i = 0; i < args.Length; i++)
{
if (args[i].Contains("-port") && i + 1 < args.Length)
{
Cupid.RoomPort = int.Parse(args[i + 1]);
}
if (i + 1 < args.Length)
{
if (string.Equals(args[i], "-matchId", StringComparison.OrdinalIgnoreCase)
|| string.Equals(args[i], "-matchid", StringComparison.OrdinalIgnoreCase))
int.TryParse(args[i + 1], out matchId);
else if (string.Equals(args[i], "-dedicatedSecret", StringComparison.OrdinalIgnoreCase))
{
dedicatedSecret = args[i + 1];
dedicatedSecretFromCli = true;
}
else if (string.Equals(args[i], "-internalApiBase", StringComparison.OrdinalIgnoreCase))
internalApiBase = args[i + 1];
}
}
if (!dedicatedSecretFromCli)
{
string envSecret = Environment.GetEnvironmentVariable("DEDICATED_SERVER_SECRET");
if (!string.IsNullOrEmpty(envSecret))
dedicatedSecret = envSecret;
}
GameManager.ConfigureDedicatedMatchReporting(matchId, dedicatedSecret, internalApiBase);
#if UNITY_EDITOR
Logger.Log("Editor mode, skipping arg check");
Cupid.RoomPort = 7777;
matchId = 228;
#else
if(Cupid.RoomPort < 0){
Logger.Log("Invalid port, Did you pass the -port arguement?");
return;
}
if(matchId <=0){
Logger.Log("Invalid match id, Did you pass the -matchId arguement?");
return;
}
#endif
Logger.SetFileName(matchId.ToString());
// Keep this component alive across server scene loads so timeout coroutine keeps running.
DontDestroyOnLoad(gameObject);
transport.Port = (ushort)Cupid.RoomPort;
Logger.Log($"Starting server at port {Cupid.RoomPort}");
//StartCoroutine(PlayerTimeoutLoop());
NetworkManager.singleton.StartServer();
#else
//Client code
// Practice starts its own localhost host+client on a free port.
if (GameTutorialManager.tutorialModeEnabled)
return;
if (Cupid.RoomPort < 0)
{
Logger.Log("Invalid Room port");
return;
}
transport.Port = (ushort)Cupid.RoomPort;
NetworkManager.singleton.networkAddress = Cupid.ServerAddress;
Logger.Log($"Starting client at ${Cupid.ServerAddress}:{Cupid.RoomPort}");
NetworkManager.singleton.StartClient();
#endif
}
const float NoPlayersTimeoutSeconds = 45f;
float noPlayersTimer = 0f;
bool hasPlayerEverJoined = false;
int lastCountdownLoggedSecond = -1;
int lastObservedPlayerCount = -1;
public static int GetActivePlayerConnectionCount()
{
if (NetworkServer.connections == null || NetworkServer.connections.Count == 0)
return 0;
// Mirror can keep dictionary entries around briefly; count only live/authenticated clients.
return NetworkServer.connections.Values.Count(conn =>
conn != null &&
conn.isAuthenticated &&
conn.identity != null);
}
IEnumerator PlayerTimeoutLoop()
{
Logger.Log("Player timeout loop started");
while (true)
{
int activePlayers = 0;
try{
activePlayers = GetActivePlayerConnectionCount();
if (activePlayers != lastObservedPlayerCount)
{
Logger.Log("Active player connections: " + activePlayers);
lastObservedPlayerCount = activePlayers;
}
}catch(Exception e){
Logger.Log("Error getting active player connection count: " + e.Message);
}
if (activePlayers > 0)
{
hasPlayerEverJoined = true;
noPlayersTimer = 0f;
lastCountdownLoggedSecond = -1;
yield return new WaitForSecondsRealtime(1f);
continue;
}
noPlayersTimer += 1f;
int secondsRemaining = Mathf.CeilToInt(NoPlayersTimeoutSeconds - noPlayersTimer);
if (secondsRemaining > 0 && secondsRemaining % 10 == 0 && secondsRemaining != lastCountdownLoggedSecond)
{
lastCountdownLoggedSecond = secondsRemaining;
Logger.Log("Server will be closed due to no players in, " + secondsRemaining);
}
if (noPlayersTimer >= NoPlayersTimeoutSeconds)
{
if (hasPlayerEverJoined)
Logger.Log("All players left, exiting");
else
Logger.Log("No players joined, exiting");
GameManager.ReportDedicatedMatchRoomClosed();
Application.Quit();
}
yield return new WaitForSecondsRealtime(1f);
}
}
void OnValidate()
{
if (GetComponent<NetworkManager>() != null)
{
GetComponent<NetworkManager>().headlessStartMode = HeadlessStartOptions.DoNothing;
}
if (transport == null)
{
transport = GetComponent<kcp2k.KcpTransport>();
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Mirror;
using UnityEngine;
public class CupidConnector : MonoBehaviour
{
public kcp2k.KcpTransport transport;
void Start()
{
#if UNITY_SERVER
//Server code
string[] args = Environment.GetCommandLineArgs();
int matchId = 0;
string dedicatedSecret = null;
bool dedicatedSecretFromCli = false;
string internalApiBase = null;
for (int i = 0; i < args.Length; i++)
{
if (args[i].Contains("-port") && i + 1 < args.Length)
{
Cupid.RoomPort = int.Parse(args[i + 1]);
}
if (i + 1 < args.Length)
{
if (string.Equals(args[i], "-matchId", StringComparison.OrdinalIgnoreCase)
|| string.Equals(args[i], "-matchid", StringComparison.OrdinalIgnoreCase))
int.TryParse(args[i + 1], out matchId);
else if (string.Equals(args[i], "-dedicatedSecret", StringComparison.OrdinalIgnoreCase))
{
dedicatedSecret = args[i + 1];
dedicatedSecretFromCli = true;
}
else if (string.Equals(args[i], "-internalApiBase", StringComparison.OrdinalIgnoreCase))
internalApiBase = args[i + 1];
}
}
if (!dedicatedSecretFromCli)
{
string envSecret = Environment.GetEnvironmentVariable("DEDICATED_SERVER_SECRET");
if (!string.IsNullOrEmpty(envSecret))
dedicatedSecret = envSecret;
}
GameManager.ConfigureDedicatedMatchReporting(matchId, dedicatedSecret, internalApiBase);
#if UNITY_EDITOR
Logger.Log("Editor mode, skipping arg check");
Cupid.RoomPort = 7777;
matchId = 228;
#else
if(Cupid.RoomPort < 0){
Logger.Log("Invalid port, Did you pass the -port arguement?");
return;
}
if(matchId <=0){
Logger.Log("Invalid match id, Did you pass the -matchId arguement?");
return;
}
#endif
Logger.SetFileName(matchId.ToString());
// Keep this component alive across server scene loads so timeout coroutine keeps running.
DontDestroyOnLoad(gameObject);
transport.Port = (ushort)Cupid.RoomPort;
Logger.Log($"Starting server at port {Cupid.RoomPort}");
//StartCoroutine(PlayerTimeoutLoop());
NetworkManager.singleton.StartServer();
#else
//Client code
// Practice starts its own localhost host+client on a free port.
if (GameTutorialManager.tutorialModeEnabled)
return;
if (Cupid.RoomPort < 0)
{
Logger.Log("Invalid Room port");
return;
}
transport.Port = (ushort)Cupid.RoomPort;
NetworkManager.singleton.networkAddress = Cupid.ServerAddress;
Logger.Log($"Starting client at ${Cupid.ServerAddress}:{Cupid.RoomPort}");
NetworkManager.singleton.StartClient();
#endif
}
const float NoPlayersTimeoutSeconds = 45f;
float noPlayersTimer = 0f;
bool hasPlayerEverJoined = false;
int lastCountdownLoggedSecond = -1;
int lastObservedPlayerCount = -1;
public static int GetActivePlayerConnectionCount()
{
if (NetworkServer.connections == null || NetworkServer.connections.Count == 0)
return 0;
// Mirror can keep dictionary entries around briefly; count only live/authenticated clients.
return NetworkServer.connections.Values.Count(conn =>
conn != null &&
conn.isAuthenticated &&
conn.identity != null);
}
IEnumerator PlayerTimeoutLoop()
{
Logger.Log("Player timeout loop started");
while (true)
{
int activePlayers = 0;
try{
activePlayers = GetActivePlayerConnectionCount();
if (activePlayers != lastObservedPlayerCount)
{
Logger.Log("Active player connections: " + activePlayers);
lastObservedPlayerCount = activePlayers;
}
}catch(Exception e){
Logger.Log("Error getting active player connection count: " + e.Message);
}
if (activePlayers > 0)
{
hasPlayerEverJoined = true;
noPlayersTimer = 0f;
lastCountdownLoggedSecond = -1;
yield return new WaitForSecondsRealtime(1f);
continue;
}
noPlayersTimer += 1f;
int secondsRemaining = Mathf.CeilToInt(NoPlayersTimeoutSeconds - noPlayersTimer);
if (secondsRemaining > 0 && secondsRemaining % 10 == 0 && secondsRemaining != lastCountdownLoggedSecond)
{
lastCountdownLoggedSecond = secondsRemaining;
Logger.Log("Server will be closed due to no players in, " + secondsRemaining);
}
if (noPlayersTimer >= NoPlayersTimeoutSeconds)
{
if (hasPlayerEverJoined)
Logger.Log("All players left, exiting");
else
Logger.Log("No players joined, exiting");
GameManager.ReportDedicatedMatchRoomClosed();
Application.Quit();
}
yield return new WaitForSecondsRealtime(1f);
}
}
void OnValidate()
{
if (GetComponent<NetworkManager>() != null)
{
GetComponent<NetworkManager>().headlessStartMode = HeadlessStartOptions.DoNothing;
}
if (transport == null)
{
transport = GetComponent<kcp2k.KcpTransport>();
}
}
}
+11 -11
View File
@@ -1,11 +1,11 @@
fileFormatVersion: 2
guid: f3c99e609d4d9cd49aa4a36bbaaf539e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: f3c99e609d4d9cd49aa4a36bbaaf539e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+317 -317
View File
@@ -1,318 +1,318 @@
using System;
using System.Collections;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
public static class Cupid
{
private static string serverAddress;
public static string ServerAddress => serverAddress;
private static string cupidBaseUri;
public static string CupidURI => cupidBaseUri;
private static int port;
public static int Port => port;
private static string bearerToken;
public static string BearerToken => bearerToken;
private static string settingsPassword = "";
public static string SettingsPassword => settingsPassword;
private static CupidSettings settings = null;
public static CupidSettings Settings => settings;
public static bool isInitialized => settings != null;
/// <summary>True once <see cref="Init"/> has built a matchmaker base URI and stored a bearer token (required for <c>/settings</c>).</summary>
public static bool IsEndpointReady =>
!string.IsNullOrEmpty(cupidBaseUri) && !string.IsNullOrEmpty(bearerToken);
public static int RoomPort = -1;
/// <summary>Clears auth/matchmaker session fields. Server address is left so the next login can <see cref="Init"/> again.</summary>
public static void ClearSession()
{
bearerToken = "";
RoomPort = -1;
}
public static async Task Init(string _serverAddress, int _port, string _bearerToken, string _settingsPassword)
{
if (!TryBuildEndpoints(_serverAddress, _port, out serverAddress, out cupidBaseUri, out port))
{
Logger.Log("Cupid: invalid or empty server address.");
bearerToken = _bearerToken ?? "";
settings = null;
return;
}
bearerToken = _bearerToken ?? "";
if (string.IsNullOrEmpty(bearerToken))
{
Logger.Log("Cupid: no bearer token; configure auth before matchmaking.");
settings = null;
return;
}
settingsPassword = _settingsPassword ?? "";
string settingsUrl = CupidURI + "/settings?password=" + UnityWebRequest.EscapeURL(settingsPassword);
using (UnityWebRequest www = UnityWebRequest.Get(settingsUrl))
{
www.SetRequestHeader("Authorization", "Bearer " + bearerToken);
var operation = www.SendWebRequest();
while (!operation.isDone)
{
await Task.Yield();
}
try
{
if (www.result != UnityWebRequest.Result.Success)
{
Logger.Log("Cupid settings request failed: " + www.error);
Logger.Log(www.downloadHandler != null ? www.downloadHandler.text : "");
settings = null;
return;
}
string body = www.downloadHandler != null ? www.downloadHandler.text : "";
if (string.IsNullOrWhiteSpace(body))
{
settings = null;
return;
}
ApplySettingsJsonBody(body, logSuccess: true);
}
catch (Exception e)
{
Logger.Log("Error retreiving settings from server " + e.Message);
Logger.Log(www.downloadHandler != null ? www.downloadHandler.text : "");
settings = null;
}
}
}
/// <summary>
/// Re-fetches GET <c>/settings</c> (e.g. each time Main Menu is shown). Safe to call from a coroutine; no-op if not <see cref="IsEndpointReady"/>.
/// </summary>
public static IEnumerator CoRefreshSettings()
{
if (!IsEndpointReady)
yield break;
string settingsUrl = CupidURI + "/settings?password=" + UnityWebRequest.EscapeURL(settingsPassword ?? "");
using (UnityWebRequest www = UnityWebRequest.Get(settingsUrl))
{
www.SetRequestHeader("Authorization", "Bearer " + bearerToken);
yield return www.SendWebRequest();
if (www.result != UnityWebRequest.Result.Success)
{
Logger.Log("Cupid settings refresh failed: " + www.error);
Logger.Log(www.downloadHandler != null ? www.downloadHandler.text : "");
yield break;
}
string body = www.downloadHandler != null ? www.downloadHandler.text : "";
ApplySettingsJsonBody(body, logSuccess: true);
}
}
static void ApplySettingsJsonBody(string body, bool logSuccess)
{
settings = null;
if (string.IsNullOrWhiteSpace(body))
return;
if (body.Trim() == "403 Unauthorized")
{
Logger.Log("Cupid settings: wrong or missing password query (server rejected /settings).");
return;
}
try
{
var parsed = JsonUtility.FromJson<CupidSettings>(body);
if (parsed == null)
throw new NullReferenceException(nameof(CupidSettings));
settings = parsed;
if (logSuccess)
Logger.Log("Cupid settings updated");
}
catch (Exception e)
{
Logger.Log("Cupid settings JSON error: " + e.Message + " body=" + body);
settings = null;
}
}
/// <summary>
/// Plain host/IP + HTTP port, or an absolute URL (https://host with no port uses 443).
/// Sets <paramref name="hostOnly"/> for game client transport; <paramref name="baseUri"/> has no trailing slash.
/// </summary>
static bool TryBuildEndpoints(string input, int fallbackHttpPort, out string hostOnly, out string baseUri, out int resolvedPort)
{
hostOnly = "";
baseUri = "";
resolvedPort = fallbackHttpPort;
input = (input ?? "").Trim();
if (string.IsNullOrEmpty(input))
return false;
if (input.IndexOf("://", StringComparison.Ordinal) >= 0
&& Uri.TryCreate(input, UriKind.Absolute, out Uri uri)
&& (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps))
{
hostOnly = uri.Host;
string authority = uri.GetLeftPart(UriPartial.Authority);
string path = uri.AbsolutePath;
if (!string.IsNullOrEmpty(path) && path != "/")
baseUri = authority.TrimEnd('/') + path.TrimEnd('/');
else
baseUri = authority;
resolvedPort = uri.Port;
return true;
}
hostOnly = input;
baseUri = "http://" + input + ":" + fallbackHttpPort;
resolvedPort = fallbackHttpPort;
return true;
}
public static string RandomUsername{
get{
string pool="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
string output ="";
for(int i=0; i < 5; i++){
output += pool.ToCharArray()[UnityEngine.Random.Range(0,pool.Length)];
}
return output;
}
}
/// <summary>Matchmaker GET / body: <c>"0"</c> while waiting; otherwise a JSON room object.</summary>
public static CupidRoom? ParseRoom(string data) => ParseRoom(data, 0, null);
/// <inheritdoc cref="ParseRoom(string)"/>
/// <param name="currentUserId">Used to pick <c>for_red</c> vs <c>for_blue</c> when both list the same players.</param>
/// <param name="teamDisambiguation">Optional hint (e.g. <see cref="GameManager.MyTeam"/>) when the roster is duplicated on both sides.</param>
public static CupidRoom? ParseRoom(string data, int currentUserId, Team? teamDisambiguation)
{
if (string.IsNullOrWhiteSpace(data))
return null;
string t = data.Trim();
if (t == "0")
return null;
if (t.IndexOf("\"for_red\"", StringComparison.Ordinal) >= 0)
{
MatchmadeResponse env = JsonUtility.FromJson<MatchmadeResponse>(t);
if (env == null || !env.ok || !MatchmadeResponse.IsMatchReady(env))
return null;
MatchmadeTeamPayload branch = MatchmadeResponse.SelectTeamPayload(env, currentUserId, teamDisambiguation);
if (branch == null || branch.Port <= 0)
return null;
return ToCupidRoom(branch);
}
try
{
CupidRoom room = JsonUtility.FromJson<CupidRoom>(t);
if (room.Port <= 0)
return null;
return room;
}
catch
{
return null;
}
}
static CupidRoom ToCupidRoom(MatchmadeTeamPayload p)
{
var room = new CupidRoom
{
GameName = p.GameName ?? "",
Port = p.Port,
InitTime = p.InitTime,
match_id = p.match_id,
your_team = p.your_team ?? ""
};
if (p.Players != null)
{
room.Players = new CupidQueueEntry[p.Players.Length];
for (int i = 0; i < p.Players.Length; i++)
{
room.Players[i] = new CupidQueueEntry
{
Name = p.Players[i].Name,
LastSeen = p.Players[i].LastSeen,
UserId = p.Players[i].UserId
};
}
}
return room;
}
}
[System.Serializable]
public class CupidSettings
{
public int minimum_players;
public int maximum_players;
public int waiting_time;
public int port_range_min;
public int port_range_max;
public CupidGameEntry[] games;
/// <summary>RC stake per player for the default match (<c>/settings</c>), in coin units (same as matchmaker <c>entry_fee</c>).</summary>
public int entry_fee;
/// <summary>Optional side-bet or table minimum from matchmaker settings; same units as <see cref="entry_fee"/>.</summary>
public int bet_fee;
/// <summary>Winner net RC prize from settings, coin units (same as room <c>rc_prize</c>).</summary>
public int rc_prize;
public CupidTableSettings table_settings;
}
[System.Serializable]
public class CupidGameEntry
{
public string name;
public string exe;
}
[System.Serializable]
public class CupidTableSettings
{
public string entry_fee;
public string bet_fee;
/// <summary>Minimum client version (e.g. <c>0.99</c>, <c>1.21</c>). Compared to <see cref="Application.version"/>.</summary>
public string version;
public string error_msg;
public string warning_msg;
}
[System.Serializable]
public struct CupidRoom
{
public CupidQueueEntry[] Players;
public string GameName;
public int Port;
public long InitTime;
public int match_id;
public string your_team;
}
[System.Serializable]
public struct CupidQueueEntry
{
public string Name;
public long LastSeen;
public int UserId;
using System;
using System.Collections;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
public static class Cupid
{
private static string serverAddress;
public static string ServerAddress => serverAddress;
private static string cupidBaseUri;
public static string CupidURI => cupidBaseUri;
private static int port;
public static int Port => port;
private static string bearerToken;
public static string BearerToken => bearerToken;
private static string settingsPassword = "";
public static string SettingsPassword => settingsPassword;
private static CupidSettings settings = null;
public static CupidSettings Settings => settings;
public static bool isInitialized => settings != null;
/// <summary>True once <see cref="Init"/> has built a matchmaker base URI and stored a bearer token (required for <c>/settings</c>).</summary>
public static bool IsEndpointReady =>
!string.IsNullOrEmpty(cupidBaseUri) && !string.IsNullOrEmpty(bearerToken);
public static int RoomPort = -1;
/// <summary>Clears auth/matchmaker session fields. Server address is left so the next login can <see cref="Init"/> again.</summary>
public static void ClearSession()
{
bearerToken = "";
RoomPort = -1;
}
public static async Task Init(string _serverAddress, int _port, string _bearerToken, string _settingsPassword)
{
if (!TryBuildEndpoints(_serverAddress, _port, out serverAddress, out cupidBaseUri, out port))
{
Logger.Log("Cupid: invalid or empty server address.");
bearerToken = _bearerToken ?? "";
settings = null;
return;
}
bearerToken = _bearerToken ?? "";
if (string.IsNullOrEmpty(bearerToken))
{
Logger.Log("Cupid: no bearer token; configure auth before matchmaking.");
settings = null;
return;
}
settingsPassword = _settingsPassword ?? "";
string settingsUrl = CupidURI + "/settings?password=" + UnityWebRequest.EscapeURL(settingsPassword);
using (UnityWebRequest www = UnityWebRequest.Get(settingsUrl))
{
www.SetRequestHeader("Authorization", "Bearer " + bearerToken);
var operation = www.SendWebRequest();
while (!operation.isDone)
{
await Task.Yield();
}
try
{
if (www.result != UnityWebRequest.Result.Success)
{
Logger.Log("Cupid settings request failed: " + www.error);
Logger.Log(www.downloadHandler != null ? www.downloadHandler.text : "");
settings = null;
return;
}
string body = www.downloadHandler != null ? www.downloadHandler.text : "";
if (string.IsNullOrWhiteSpace(body))
{
settings = null;
return;
}
ApplySettingsJsonBody(body, logSuccess: true);
}
catch (Exception e)
{
Logger.Log("Error retreiving settings from server " + e.Message);
Logger.Log(www.downloadHandler != null ? www.downloadHandler.text : "");
settings = null;
}
}
}
/// <summary>
/// Re-fetches GET <c>/settings</c> (e.g. each time Main Menu is shown). Safe to call from a coroutine; no-op if not <see cref="IsEndpointReady"/>.
/// </summary>
public static IEnumerator CoRefreshSettings()
{
if (!IsEndpointReady)
yield break;
string settingsUrl = CupidURI + "/settings?password=" + UnityWebRequest.EscapeURL(settingsPassword ?? "");
using (UnityWebRequest www = UnityWebRequest.Get(settingsUrl))
{
www.SetRequestHeader("Authorization", "Bearer " + bearerToken);
yield return www.SendWebRequest();
if (www.result != UnityWebRequest.Result.Success)
{
Logger.Log("Cupid settings refresh failed: " + www.error);
Logger.Log(www.downloadHandler != null ? www.downloadHandler.text : "");
yield break;
}
string body = www.downloadHandler != null ? www.downloadHandler.text : "";
ApplySettingsJsonBody(body, logSuccess: true);
}
}
static void ApplySettingsJsonBody(string body, bool logSuccess)
{
settings = null;
if (string.IsNullOrWhiteSpace(body))
return;
if (body.Trim() == "403 Unauthorized")
{
Logger.Log("Cupid settings: wrong or missing password query (server rejected /settings).");
return;
}
try
{
var parsed = JsonUtility.FromJson<CupidSettings>(body);
if (parsed == null)
throw new NullReferenceException(nameof(CupidSettings));
settings = parsed;
if (logSuccess)
Logger.Log("Cupid settings updated");
}
catch (Exception e)
{
Logger.Log("Cupid settings JSON error: " + e.Message + " body=" + body);
settings = null;
}
}
/// <summary>
/// Plain host/IP + HTTP port, or an absolute URL (https://host with no port uses 443).
/// Sets <paramref name="hostOnly"/> for game client transport; <paramref name="baseUri"/> has no trailing slash.
/// </summary>
static bool TryBuildEndpoints(string input, int fallbackHttpPort, out string hostOnly, out string baseUri, out int resolvedPort)
{
hostOnly = "";
baseUri = "";
resolvedPort = fallbackHttpPort;
input = (input ?? "").Trim();
if (string.IsNullOrEmpty(input))
return false;
if (input.IndexOf("://", StringComparison.Ordinal) >= 0
&& Uri.TryCreate(input, UriKind.Absolute, out Uri uri)
&& (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps))
{
hostOnly = uri.Host;
string authority = uri.GetLeftPart(UriPartial.Authority);
string path = uri.AbsolutePath;
if (!string.IsNullOrEmpty(path) && path != "/")
baseUri = authority.TrimEnd('/') + path.TrimEnd('/');
else
baseUri = authority;
resolvedPort = uri.Port;
return true;
}
hostOnly = input;
baseUri = "http://" + input + ":" + fallbackHttpPort;
resolvedPort = fallbackHttpPort;
return true;
}
public static string RandomUsername{
get{
string pool="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
string output ="";
for(int i=0; i < 5; i++){
output += pool.ToCharArray()[UnityEngine.Random.Range(0,pool.Length)];
}
return output;
}
}
/// <summary>Matchmaker GET / body: <c>"0"</c> while waiting; otherwise a JSON room object.</summary>
public static CupidRoom? ParseRoom(string data) => ParseRoom(data, 0, null);
/// <inheritdoc cref="ParseRoom(string)"/>
/// <param name="currentUserId">Used to pick <c>for_red</c> vs <c>for_blue</c> when both list the same players.</param>
/// <param name="teamDisambiguation">Optional hint (e.g. <see cref="GameManager.MyTeam"/>) when the roster is duplicated on both sides.</param>
public static CupidRoom? ParseRoom(string data, int currentUserId, Team? teamDisambiguation)
{
if (string.IsNullOrWhiteSpace(data))
return null;
string t = data.Trim();
if (t == "0")
return null;
if (t.IndexOf("\"for_red\"", StringComparison.Ordinal) >= 0)
{
MatchmadeResponse env = JsonUtility.FromJson<MatchmadeResponse>(t);
if (env == null || !env.ok || !MatchmadeResponse.IsMatchReady(env))
return null;
MatchmadeTeamPayload branch = MatchmadeResponse.SelectTeamPayload(env, currentUserId, teamDisambiguation);
if (branch == null || branch.Port <= 0)
return null;
return ToCupidRoom(branch);
}
try
{
CupidRoom room = JsonUtility.FromJson<CupidRoom>(t);
if (room.Port <= 0)
return null;
return room;
}
catch
{
return null;
}
}
static CupidRoom ToCupidRoom(MatchmadeTeamPayload p)
{
var room = new CupidRoom
{
GameName = p.GameName ?? "",
Port = p.Port,
InitTime = p.InitTime,
match_id = p.match_id,
your_team = p.your_team ?? ""
};
if (p.Players != null)
{
room.Players = new CupidQueueEntry[p.Players.Length];
for (int i = 0; i < p.Players.Length; i++)
{
room.Players[i] = new CupidQueueEntry
{
Name = p.Players[i].Name,
LastSeen = p.Players[i].LastSeen,
UserId = p.Players[i].UserId
};
}
}
return room;
}
}
[System.Serializable]
public class CupidSettings
{
public int minimum_players;
public int maximum_players;
public int waiting_time;
public int port_range_min;
public int port_range_max;
public CupidGameEntry[] games;
/// <summary>RC stake per player for the default match (<c>/settings</c>), in coin units (same as matchmaker <c>entry_fee</c>).</summary>
public int entry_fee;
/// <summary>Optional side-bet or table minimum from matchmaker settings; same units as <see cref="entry_fee"/>.</summary>
public int bet_fee;
/// <summary>Winner net RC prize from settings, coin units (same as room <c>rc_prize</c>).</summary>
public int rc_prize;
public CupidTableSettings table_settings;
}
[System.Serializable]
public class CupidGameEntry
{
public string name;
public string exe;
}
[System.Serializable]
public class CupidTableSettings
{
public string entry_fee;
public string bet_fee;
/// <summary>Minimum client version (e.g. <c>0.99</c>, <c>1.21</c>). Compared to <see cref="Application.version"/>.</summary>
public string version;
public string error_msg;
public string warning_msg;
}
[System.Serializable]
public struct CupidRoom
{
public CupidQueueEntry[] Players;
public string GameName;
public int Port;
public long InitTime;
public int match_id;
public string your_team;
}
[System.Serializable]
public struct CupidQueueEntry
{
public string Name;
public long LastSeen;
public int UserId;
}
+11 -11
View File
@@ -1,11 +1,11 @@
fileFormatVersion: 2
guid: c2c877cb30cc2fe44b30ab3681e44604
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: c2c877cb30cc2fe44b30ab3681e44604
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+230 -230
View File
@@ -1,230 +1,230 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
public class CupidLobby : MonoBehaviour
{
public const bool saveUsername = false;
private static string m_username = "";
[SerializeField]private GameObject MatchmakingUI;
[SerializeField]private string GameScene;
[Header("Server info (matchmaker port should match server settings.json)")]
[Tooltip("IP/hostname uses HTTP and cupidPort below. Or full URL: https://match.example.com (default 443, no :port in URL) or http://host/path.")]
[SerializeField]private string serverAddress = "xx.xx.xxx.xx";
[Tooltip("HTTP port when server address is not a full URL. Ignored for https:// or http:// URLs unless the URL includes an explicit port.")]
[SerializeField]private int cupidPort = 2612;
[Tooltip("Sent as the password query param on GET /settings (matchmaker settings.json).")]
[SerializeField]private string cupidPassword = "HelloWorld";
[Tooltip("Used when LoginManager is absent or has no token (e.g. Cupid sample scene).")]
[SerializeField]private string bearerTokenFallback = "";
public static string Username
{
get
{
if(m_username == ""){
m_username = Cupid.RandomUsername;
}
if(saveUsername){
if (PlayerPrefs.HasKey("username"))
{
return PlayerPrefs.GetString("username");
}else{
string username = Cupid.RandomUsername;
PlayerPrefs.SetString("username",username);
PlayerPrefs.Save();
return username;
}
}else{
return m_username;
}
}
}
public static CupidLobby instance;
public static void ClearUsername()
{
m_username = "";
}
void Awake(){
instance=this;
}
void Start()
{
string token = !string.IsNullOrEmpty(LoginManager.AuthToken)
? LoginManager.AuthToken
: bearerTokenFallback;
if (LoginManager.instance != null && LoginManager.CurrentUser != null && !string.IsNullOrEmpty(LoginManager.CurrentUser.username))
m_username = LoginManager.CurrentUser.username;
Cupid.Init(serverAddress, cupidPort, token, cupidPassword);
}
bool matchmaking = false;
public bool isMatchmaking => matchmaking;
public void Matchmake()
{
LoginManager.ClearMatchYourTeam();
Logger.Log("Starting matchmake as " + Username);
StartCoroutine(matchmake());
}
IEnumerator matchmake()
{
matchmaking = true;
if (string.IsNullOrEmpty(Cupid.BearerToken))
{
Logger.Log("Matchmake aborted: no bearer token");
matchmaking = false;
RefreshMatchmakingPanel();
yield break;
}
while (matchmaking)
{
RefreshMatchmakingPanel();
if (Application.internetReachability == NetworkReachability.NotReachable)
{
Logger.Log("Matchmaker unreachable: no internet");
StopMatchmakingNoInternet();
yield break;
}
using (UnityWebRequest req = UnityWebRequest.Get(Cupid.CupidURI + "/"))
{
req.downloadHandler = new DownloadHandlerBuffer();
req.SetRequestHeader("Authorization", "Bearer " + Cupid.BearerToken);
yield return req.SendWebRequest();
string text = req.downloadHandler != null ? req.downloadHandler.text : "";
if (req.result == UnityWebRequest.Result.ConnectionError)
{
Logger.Log("Matchmaker unreachable: " + req.error + " body: " + text);
StopMatchmakingNoInternet();
yield break;
}
if (req.result != UnityWebRequest.Result.Success)
{
Logger.Log("Matchmaker poll failed: " + req.error + " body: " + text);
yield return new WaitForSeconds(1);
continue;
}
Team? teamHint = LoginManager.MatchYourTeam;
if (!teamHint.HasValue && GameManager.instance != null)
teamHint = GameManager.MyTeam;
int userId = LoginManager.CurrentUser != null ? LoginManager.CurrentUser.id : 0;
CupidRoom? room = Cupid.ParseRoom(text, userId, teamHint);
if (room == null)
{
if (text != null && text.Trim() != "0")
Logger.Log("Still waiting: " + text);
}
else
{
CupidRoom _room = (CupidRoom)room;
Logger.Log("Got into a room");
Logger.Log(text);
MatchmadeResponse env = JsonUtility.FromJson<MatchmadeResponse>(text);
MatchmadeTeamPayload branch = MatchmadeResponse.SelectTeamPayload(env, userId, teamHint);
if (branch == null || !MatchmadeResponse.TryResolveMyAndOpponent(env, branch, userId, out MatchmadePlayer myPlayer, out MatchmadePlayer opponentPlayer))
{
Debug.Log("Waiting for the other player to show up (could not resolve roster)");
yield return new WaitForSeconds(1);
continue;
}
string yt = (branch.your_team ?? "").Trim().ToLowerInvariant();
Team myTeam = yt == "blue" ? Team.Blue : Team.Red;
if (myTeam == Team.Red)
{
GameManager.RedPlayer = myPlayer;
GameManager.BluePlayer = opponentPlayer;
}
else
{
GameManager.BluePlayer = myPlayer;
GameManager.RedPlayer = opponentPlayer;
}
GameManager.MyTeam = myTeam;
int rcPrizeCoins = env.rc_prize > 0 ? env.rc_prize : branch.rc_prize;
GameManager.MatchRcPrizeCoins = rcPrizeCoins;
LevelLoadManager.instance.SetupMatchMade(myTeam, myPlayer, opponentPlayer, CoinHelper.FormatString(rcPrizeCoins) + " RC");
GameManager.ConfigureDedicatedMatchReporting(branch.match_id);
Logger.Log("Setting cupid to load game scene");
Cupid.RoomPort = _room.Port;
LoginManager.SetMatchYourTeam(_room.your_team);
matchmaking = false;
Logger.Log("Loading game scene");
LevelLoadManager.LoadLevel(GameScene);
yield break;
}
}
yield return new WaitForSeconds(1);
}
}
IEnumerator CancelMatchmake()
{
if (string.IsNullOrEmpty(Cupid.BearerToken))
{
Logger.Log("Cancel skipped: no bearer token");
yield break;
}
using (UnityWebRequest www = UnityWebRequest.Get(Cupid.CupidURI + "/cancel"))
{
www.downloadHandler = new DownloadHandlerBuffer();
www.SetRequestHeader("Authorization", "Bearer " + Cupid.BearerToken);
yield return www.SendWebRequest();
string text = www.downloadHandler != null ? www.downloadHandler.text : "";
if (www.result != UnityWebRequest.Result.Success)
{
Logger.Log("Cancel request failed: " + www.error + " body: " + text);
yield break;
}
if (text.Trim() == "1")
Logger.Log("Cancelled matchmaking success");
else
Logger.Log("Matchmaking cancellation said " + text);
}
}
public void Cancel()
{
matchmaking = false;
StartCoroutine(CancelMatchmake());
RefreshMatchmakingPanel();
}
void StopMatchmakingNoInternet()
{
matchmaking = false;
RefreshMatchmakingPanel();
if (MainMenuManager.instance != null)
MainMenuManager.instance.ShowMatchmakingNoInternet();
StartCoroutine(CancelMatchmake());
}
void RefreshMatchmakingPanel()
{
MatchmakingUI.SetActive(matchmaking);
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
public class CupidLobby : MonoBehaviour
{
public const bool saveUsername = false;
private static string m_username = "";
[SerializeField]private GameObject MatchmakingUI;
[SerializeField]private string GameScene;
[Header("Server info (matchmaker port should match server settings.json)")]
[Tooltip("IP/hostname uses HTTP and cupidPort below. Or full URL: https://match.example.com (default 443, no :port in URL) or http://host/path.")]
[SerializeField]private string serverAddress = "xx.xx.xxx.xx";
[Tooltip("HTTP port when server address is not a full URL. Ignored for https:// or http:// URLs unless the URL includes an explicit port.")]
[SerializeField]private int cupidPort = 2612;
[Tooltip("Sent as the password query param on GET /settings (matchmaker settings.json).")]
[SerializeField]private string cupidPassword = "HelloWorld";
[Tooltip("Used when LoginManager is absent or has no token (e.g. Cupid sample scene).")]
[SerializeField]private string bearerTokenFallback = "";
public static string Username
{
get
{
if(m_username == ""){
m_username = Cupid.RandomUsername;
}
if(saveUsername){
if (PlayerPrefs.HasKey("username"))
{
return PlayerPrefs.GetString("username");
}else{
string username = Cupid.RandomUsername;
PlayerPrefs.SetString("username",username);
PlayerPrefs.Save();
return username;
}
}else{
return m_username;
}
}
}
public static CupidLobby instance;
public static void ClearUsername()
{
m_username = "";
}
void Awake(){
instance=this;
}
void Start()
{
string token = !string.IsNullOrEmpty(LoginManager.AuthToken)
? LoginManager.AuthToken
: bearerTokenFallback;
if (LoginManager.instance != null && LoginManager.CurrentUser != null && !string.IsNullOrEmpty(LoginManager.CurrentUser.username))
m_username = LoginManager.CurrentUser.username;
Cupid.Init(serverAddress, cupidPort, token, cupidPassword);
}
bool matchmaking = false;
public bool isMatchmaking => matchmaking;
public void Matchmake()
{
LoginManager.ClearMatchYourTeam();
Logger.Log("Starting matchmake as " + Username);
StartCoroutine(matchmake());
}
IEnumerator matchmake()
{
matchmaking = true;
if (string.IsNullOrEmpty(Cupid.BearerToken))
{
Logger.Log("Matchmake aborted: no bearer token");
matchmaking = false;
RefreshMatchmakingPanel();
yield break;
}
while (matchmaking)
{
RefreshMatchmakingPanel();
if (Application.internetReachability == NetworkReachability.NotReachable)
{
Logger.Log("Matchmaker unreachable: no internet");
StopMatchmakingNoInternet();
yield break;
}
using (UnityWebRequest req = UnityWebRequest.Get(Cupid.CupidURI + "/"))
{
req.downloadHandler = new DownloadHandlerBuffer();
req.SetRequestHeader("Authorization", "Bearer " + Cupid.BearerToken);
yield return req.SendWebRequest();
string text = req.downloadHandler != null ? req.downloadHandler.text : "";
if (req.result == UnityWebRequest.Result.ConnectionError)
{
Logger.Log("Matchmaker unreachable: " + req.error + " body: " + text);
StopMatchmakingNoInternet();
yield break;
}
if (req.result != UnityWebRequest.Result.Success)
{
Logger.Log("Matchmaker poll failed: " + req.error + " body: " + text);
yield return new WaitForSeconds(1);
continue;
}
Team? teamHint = LoginManager.MatchYourTeam;
if (!teamHint.HasValue && GameManager.instance != null)
teamHint = GameManager.MyTeam;
int userId = LoginManager.CurrentUser != null ? LoginManager.CurrentUser.id : 0;
CupidRoom? room = Cupid.ParseRoom(text, userId, teamHint);
if (room == null)
{
if (text != null && text.Trim() != "0")
Logger.Log("Still waiting: " + text);
}
else
{
CupidRoom _room = (CupidRoom)room;
Logger.Log("Got into a room");
Logger.Log(text);
MatchmadeResponse env = JsonUtility.FromJson<MatchmadeResponse>(text);
MatchmadeTeamPayload branch = MatchmadeResponse.SelectTeamPayload(env, userId, teamHint);
if (branch == null || !MatchmadeResponse.TryResolveMyAndOpponent(env, branch, userId, out MatchmadePlayer myPlayer, out MatchmadePlayer opponentPlayer))
{
Debug.Log("Waiting for the other player to show up (could not resolve roster)");
yield return new WaitForSeconds(1);
continue;
}
string yt = (branch.your_team ?? "").Trim().ToLowerInvariant();
Team myTeam = yt == "blue" ? Team.Blue : Team.Red;
if (myTeam == Team.Red)
{
GameManager.RedPlayer = myPlayer;
GameManager.BluePlayer = opponentPlayer;
}
else
{
GameManager.BluePlayer = myPlayer;
GameManager.RedPlayer = opponentPlayer;
}
GameManager.MyTeam = myTeam;
int rcPrizeCoins = env.rc_prize > 0 ? env.rc_prize : branch.rc_prize;
GameManager.MatchRcPrizeCoins = rcPrizeCoins;
LevelLoadManager.instance.SetupMatchMade(myTeam, myPlayer, opponentPlayer, CoinHelper.FormatString(rcPrizeCoins) + " RC");
GameManager.ConfigureDedicatedMatchReporting(branch.match_id);
Logger.Log("Setting cupid to load game scene");
Cupid.RoomPort = _room.Port;
LoginManager.SetMatchYourTeam(_room.your_team);
matchmaking = false;
Logger.Log("Loading game scene");
LevelLoadManager.LoadLevel(GameScene);
yield break;
}
}
yield return new WaitForSeconds(1);
}
}
IEnumerator CancelMatchmake()
{
if (string.IsNullOrEmpty(Cupid.BearerToken))
{
Logger.Log("Cancel skipped: no bearer token");
yield break;
}
using (UnityWebRequest www = UnityWebRequest.Get(Cupid.CupidURI + "/cancel"))
{
www.downloadHandler = new DownloadHandlerBuffer();
www.SetRequestHeader("Authorization", "Bearer " + Cupid.BearerToken);
yield return www.SendWebRequest();
string text = www.downloadHandler != null ? www.downloadHandler.text : "";
if (www.result != UnityWebRequest.Result.Success)
{
Logger.Log("Cancel request failed: " + www.error + " body: " + text);
yield break;
}
if (text.Trim() == "1")
Logger.Log("Cancelled matchmaking success");
else
Logger.Log("Matchmaking cancellation said " + text);
}
}
public void Cancel()
{
matchmaking = false;
StartCoroutine(CancelMatchmake());
RefreshMatchmakingPanel();
}
void StopMatchmakingNoInternet()
{
matchmaking = false;
RefreshMatchmakingPanel();
if (MainMenuManager.instance != null)
MainMenuManager.instance.ShowMatchmakingNoInternet();
StartCoroutine(CancelMatchmake());
}
void RefreshMatchmakingPanel()
{
MatchmakingUI.SetActive(matchmaking);
}
}
+11 -11
View File
@@ -1,11 +1,11 @@
fileFormatVersion: 2
guid: 87b7650ffdc115443a13b24670850ce2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 87b7650ffdc115443a13b24670850ce2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+138 -138
View File
@@ -1,138 +1,138 @@
using System;
using System.IO;
using UnityEngine;
public class Logger
{
public static bool Enabled = true;
private static Logger m_instance = null;
private static readonly object FileLock = new object();
private static string ApplicationDirectory
{
get
{
// Android (and iOS): dataPath is inside the package/APK and is not writable.
if (Application.platform == RuntimePlatform.Android ||
Application.platform == RuntimePlatform.IPhonePlayer)
{
return Application.persistentDataPath;
}
string path = Application.dataPath;
#if UNITY_EDITOR
// Never write under Assets/: the Editor importer locks those files, and
// File.AppendAllText then throws Sharing violation. Mirror treats that as a
// fatal RPC error and disconnects the client.
path = Path.GetFullPath(Path.Combine(path, ".."));
#else
if (Application.platform == RuntimePlatform.OSXPlayer)
{
path = Path.Combine(path, "..", "..");
}
else if (Application.platform == RuntimePlatform.WindowsPlayer)
{
path = Path.Combine(path, "..");
}
#endif
return path;
}
}
public string LogFilePath {get; private set;}
public static Logger instance
{
get
{
if (m_instance == null)
{
m_instance = new Logger();
}
return m_instance;
}
}
public Logger()
{
if(!Enabled){return;}
Debug.Log("Starting logger @ " + ApplicationDirectory);
if(LogFilePath == null){
LogFilePath = Path.Combine(ApplicationDirectory, "Log.txt");
}
TryWriteFile(LogFilePath, "Logger initiated at " + DateTime.Now + "\n\n", append: false);
}
public void log(string message){
if(!Enabled){return;}
Debug.Log(message);
TryWriteFile(LogFilePath, $"[{DateTime.Now}] {message}\n", append: true);
}
public static void Log(string message){
instance.log(message);
}
public static void SetFileName(string fileName){
EnsureDirectoryExists(Path.Combine(ApplicationDirectory, "Logs"));
instance.LogFilePath = Path.Combine(ApplicationDirectory, "Logs", fileName + ".txt");
}
public static void EnsureDirectoryExists(string path){
if(!Directory.Exists(path)){
Directory.CreateDirectory(path);
}
}
/// <summary>Writable Logs folder next to match log files (creates if missing).</summary>
public static string GetLogsDirectory()
{
string dir = Path.Combine(ApplicationDirectory, "Logs");
EnsureDirectoryExists(dir);
return dir;
}
public static void SetFilePath(string path){
instance.LogFilePath= path;
}
/// <summary>
/// File I/O must never throw: callers include Mirror RPCs, and an exception there
/// disconnects the client. Sharing violations are expected if another process has
/// the file open; FileShare.ReadWrite plus a swallow keeps gameplay alive.
/// </summary>
static void TryWriteFile(string path, string contents, bool append)
{
if (string.IsNullOrEmpty(path) || contents == null)
return;
try
{
string dir = Path.GetDirectoryName(path);
if (!string.IsNullOrEmpty(dir))
EnsureDirectoryExists(dir);
}
catch (Exception e)
{
Debug.LogWarning("Logger: could not create log directory: " + e.Message);
return;
}
lock (FileLock)
{
try
{
FileMode mode = append ? FileMode.Append : FileMode.Create;
using (var stream = new FileStream(path, mode, FileAccess.Write, FileShare.ReadWrite))
using (var writer = new StreamWriter(stream))
{
writer.Write(contents);
}
}
catch (Exception e)
{
Debug.LogWarning("Logger: file write failed (" + path + "): " + e.Message);
}
}
}
}
using System;
using System.IO;
using UnityEngine;
public class Logger
{
public static bool Enabled = true;
private static Logger m_instance = null;
private static readonly object FileLock = new object();
private static string ApplicationDirectory
{
get
{
// Android (and iOS): dataPath is inside the package/APK and is not writable.
if (Application.platform == RuntimePlatform.Android ||
Application.platform == RuntimePlatform.IPhonePlayer)
{
return Application.persistentDataPath;
}
string path = Application.dataPath;
#if UNITY_EDITOR
// Never write under Assets/: the Editor importer locks those files, and
// File.AppendAllText then throws Sharing violation. Mirror treats that as a
// fatal RPC error and disconnects the client.
path = Path.GetFullPath(Path.Combine(path, ".."));
#else
if (Application.platform == RuntimePlatform.OSXPlayer)
{
path = Path.Combine(path, "..", "..");
}
else if (Application.platform == RuntimePlatform.WindowsPlayer)
{
path = Path.Combine(path, "..");
}
#endif
return path;
}
}
public string LogFilePath {get; private set;}
public static Logger instance
{
get
{
if (m_instance == null)
{
m_instance = new Logger();
}
return m_instance;
}
}
public Logger()
{
if(!Enabled){return;}
Debug.Log("Starting logger @ " + ApplicationDirectory);
if(LogFilePath == null){
LogFilePath = Path.Combine(ApplicationDirectory, "Log.txt");
}
TryWriteFile(LogFilePath, "Logger initiated at " + DateTime.Now + "\n\n", append: false);
}
public void log(string message){
if(!Enabled){return;}
Debug.Log(message);
TryWriteFile(LogFilePath, $"[{DateTime.Now}] {message}\n", append: true);
}
public static void Log(string message){
instance.log(message);
}
public static void SetFileName(string fileName){
EnsureDirectoryExists(Path.Combine(ApplicationDirectory, "Logs"));
instance.LogFilePath = Path.Combine(ApplicationDirectory, "Logs", fileName + ".txt");
}
public static void EnsureDirectoryExists(string path){
if(!Directory.Exists(path)){
Directory.CreateDirectory(path);
}
}
/// <summary>Writable Logs folder next to match log files (creates if missing).</summary>
public static string GetLogsDirectory()
{
string dir = Path.Combine(ApplicationDirectory, "Logs");
EnsureDirectoryExists(dir);
return dir;
}
public static void SetFilePath(string path){
instance.LogFilePath= path;
}
/// <summary>
/// File I/O must never throw: callers include Mirror RPCs, and an exception there
/// disconnects the client. Sharing violations are expected if another process has
/// the file open; FileShare.ReadWrite plus a swallow keeps gameplay alive.
/// </summary>
static void TryWriteFile(string path, string contents, bool append)
{
if (string.IsNullOrEmpty(path) || contents == null)
return;
try
{
string dir = Path.GetDirectoryName(path);
if (!string.IsNullOrEmpty(dir))
EnsureDirectoryExists(dir);
}
catch (Exception e)
{
Debug.LogWarning("Logger: could not create log directory: " + e.Message);
return;
}
lock (FileLock)
{
try
{
FileMode mode = append ? FileMode.Append : FileMode.Create;
using (var stream = new FileStream(path, mode, FileAccess.Write, FileShare.ReadWrite))
using (var writer = new StreamWriter(stream))
{
writer.Write(contents);
}
}
catch (Exception e)
{
Debug.LogWarning("Logger: file write failed (" + path + "): " + e.Message);
}
}
}
}
+11 -11
View File
@@ -1,11 +1,11 @@
fileFormatVersion: 2
guid: 672122f9a9766e549b1df8ea295585a6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 672122f9a9766e549b1df8ea295585a6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+8 -8
View File
@@ -1,8 +1,8 @@
fileFormatVersion: 2
guid: b055694d5c52d6642a9accb5a18af808
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: b055694d5c52d6642a9accb5a18af808
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,22 +1,22 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollower : MonoBehaviour
{
[SerializeField]private Vector3 offset;
[SerializeField]private bool autoOffset = false;
[SerializeField]private Transform target;
[SerializeField]private float smoothness = 0.1f;
void LateUpdate()
{
if(target==null){return;}
transform.position = Vector3.Lerp(transform.position, target.position + offset,smoothness);
}
public void SetTarget(Transform _target){
target = _target;
offset = transform.position - target.position;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollower : MonoBehaviour
{
[SerializeField]private Vector3 offset;
[SerializeField]private bool autoOffset = false;
[SerializeField]private Transform target;
[SerializeField]private float smoothness = 0.1f;
void LateUpdate()
{
if(target==null){return;}
transform.position = Vector3.Lerp(transform.position, target.position + offset,smoothness);
}
public void SetTarget(Transform _target){
target = _target;
offset = transform.position - target.position;
}
}
@@ -1,11 +1,11 @@
fileFormatVersion: 2
guid: 7d2364b6fed7b904bb0ad40b7b79de7c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 7d2364b6fed7b904bb0ad40b7b79de7c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+52 -52
View File
@@ -1,52 +1,52 @@
using System.Collections;
using System.Collections.Generic;
using Mirror;
using UnityEngine;
public class Player : NetworkBehaviour
{
[SerializeField]private float movingSpeed;
[SyncVar]
private Vector2 input;
[SyncVar(hook = nameof(OnColorChanged))]
private Color color;
void Start()
{
if(isServer){
SetPlayer();
}
if(isLocalPlayer){
FindObjectOfType<CameraFollower>().SetTarget(transform);
}
}
void SetPlayer(){
color = new Color(Random.Range(0f,1f),Random.Range(0f,1f),Random.Range(0f,1f));
}
void OnColorChanged(Color oldValue, Color newValue){
GetComponent<MeshRenderer>().material.color = newValue;
}
// Update is called once per frame
void Update()
{
if(isLocalPlayer){
Vector2 m_input = new Vector2(Input.GetAxis("Horizontal"),Input.GetAxis("Vertical"));
if(isServer){
input = m_input;
}else{
CmdSetInput(m_input);
}
}
if(isServer){
transform.Translate(new Vector3(input.x,0,input.y)*movingSpeed);
}
}
[Command]
void CmdSetInput(Vector2 _input){
input = _input;
}
}
using System.Collections;
using System.Collections.Generic;
using Mirror;
using UnityEngine;
public class Player : NetworkBehaviour
{
[SerializeField]private float movingSpeed;
[SyncVar]
private Vector2 input;
[SyncVar(hook = nameof(OnColorChanged))]
private Color color;
void Start()
{
if(isServer){
SetPlayer();
}
if(isLocalPlayer){
FindObjectOfType<CameraFollower>().SetTarget(transform);
}
}
void SetPlayer(){
color = new Color(Random.Range(0f,1f),Random.Range(0f,1f),Random.Range(0f,1f));
}
void OnColorChanged(Color oldValue, Color newValue){
GetComponent<MeshRenderer>().material.color = newValue;
}
// Update is called once per frame
void Update()
{
if(isLocalPlayer){
Vector2 m_input = new Vector2(Input.GetAxis("Horizontal"),Input.GetAxis("Vertical"));
if(isServer){
input = m_input;
}else{
CmdSetInput(m_input);
}
}
if(isServer){
transform.Translate(new Vector3(input.x,0,input.y)*movingSpeed);
}
}
[Command]
void CmdSetInput(Vector2 _input){
input = _input;
}
}
+11 -11
View File
@@ -1,11 +1,11 @@
fileFormatVersion: 2
guid: 3a7be0347e7dc43449adcbd1121e447e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 3a7be0347e7dc43449adcbd1121e447e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: