Keep local version of files
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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: []
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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: []
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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: []
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
+559
-559
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 87e33e26aef57244e8d142595c2914f2
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
fileFormatVersion: 2
|
||||
guid: 87e33e26aef57244e8d142595c2914f2
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
+1512
-1512
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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user