customer support WiP

This commit is contained in:
2026-10-16 14:00:52 +05:30
parent 053665c690
commit a1b2b41912
35 changed files with 14855 additions and 349 deletions
@@ -15,7 +15,7 @@ MonoBehaviour:
m_DefaultGroup: af10c9716f97a20469b8fc257eec4a13 m_DefaultGroup: af10c9716f97a20469b8fc257eec4a13
m_currentHash: m_currentHash:
serializedVersion: 2 serializedVersion: 2
Hash: 00000000000000000000000000000000 Hash: ea94b3f7985f7214a5719239922767ff
m_OptimizeCatalogSize: 0 m_OptimizeCatalogSize: 0
m_BuildRemoteCatalog: 1 m_BuildRemoteCatalog: 1
m_CatalogRequestsTimeout: 0 m_CatalogRequestsTimeout: 0
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+11 -3
View File
@@ -1,23 +1,31 @@
{ {
"packages": { "packages": {
"com.IvanMurzak.McpPlugin": { "com.IvanMurzak.McpPlugin": {
"version": "8.6.0", "version": "8.8.0",
"dlls": [ "dlls": [
"McpPlugin.dll" "McpPlugin.dll"
] ]
}, },
"com.IvanMurzak.McpPlugin.Common": { "com.IvanMurzak.McpPlugin.Common": {
"version": "8.6.0", "version": "8.8.0",
"dlls": [ "dlls": [
"McpPlugin.Common.dll" "McpPlugin.Common.dll"
] ]
}, },
"com.IvanMurzak.ReflectorNet": { "com.IvanMurzak.ReflectorNet": {
"version": "5.4.1", "version": "5.4.2",
"dlls": [ "dlls": [
"ReflectorNet.dll" "ReflectorNet.dll"
] ]
}, },
"com.IvanMurzak.Rql": {
"version": "0.1.0",
"dlls": [
"Rql.Contracts.dll",
"Rql.Execution.dll",
"Rql.Parser.dll"
]
},
"Microsoft.AspNetCore.Connections.Abstractions": { "Microsoft.AspNetCore.Connections.Abstractions": {
"version": "8.0.15", "version": "8.0.15",
"dlls": [ "dlls": [
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,27 @@
fileFormatVersion: 2
guid: db548aeaf1152963881b554eba410161
PluginImporter:
externalObjects: {}
serializedVersion: 3
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
Any:
enabled: 0
settings: {}
Editor:
enabled: 1
settings:
DefaultValueInitialized: true
WindowsStoreApps:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.
@@ -0,0 +1,27 @@
fileFormatVersion: 2
guid: 97e397af08297ce51a3b5571c6846718
PluginImporter:
externalObjects: {}
serializedVersion: 3
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
Any:
enabled: 0
settings: {}
Editor:
enabled: 1
settings:
DefaultValueInitialized: true
WindowsStoreApps:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.
+27
View File
@@ -0,0 +1,27 @@
fileFormatVersion: 2
guid: dc42fc2b683fef0d38c9a8a665c8c895
PluginImporter:
externalObjects: {}
serializedVersion: 3
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
Any:
enabled: 0
settings: {}
Editor:
enabled: 1
settings:
DefaultValueInitialized: true
WindowsStoreApps:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: eba0163e0bd8ecb51a5771802f3ba7c1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+214
View File
@@ -0,0 +1,214 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1462090972661197787
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1341831250786711559}
- component: {fileID: 917088490488454432}
- component: {fileID: 7853747512264009880}
m_Layer: 5
m_Name: ticketButton
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1341831250786711559
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1462090972661197787}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7548297246373829554}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 264.971, y: 100}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &917088490488454432
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1462090972661197787}
m_CullTransparentMesh: 1
--- !u!114 &7853747512264009880
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1462090972661197787}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 0d64f6174c0ee48ac82b9113016322ad, type: 3}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &4451237980070011678
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7548297246373829554}
- component: {fileID: 5708029325541978246}
- component: {fileID: 3736942545593823984}
m_Layer: 5
m_Name: Text (TMP)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7548297246373829554
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4451237980070011678}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1341831250786711559}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: -1.0713, y: 7.4987}
m_SizeDelta: {x: 238.5647, y: 64.9974}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &5708029325541978246
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4451237980070011678}
m_CullTransparentMesh: 1
--- !u!114 &3736942545593823984
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4451237980070011678}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Ticket #001
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 893d86ab7286e5d4383d1c3f2ecdb510, type: 2}
m_sharedMaterial: {fileID: -5214663084478877120, guid: 893d86ab7286e5d4383d1c3f2ecdb510, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 43.85
m_fontSizeBase: 36
m_fontWeight: 400
m_enableAutoSizing: 1
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 0a51b9d7b411ceb929e32a35f5e66e30
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,375 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &707051342981123557
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7224778997419466767}
- component: {fileID: 5711083483119391043}
- component: {fileID: 3297791151943284155}
m_Layer: 5
m_Name: Checkmark
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7224778997419466767
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 707051342981123557}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7977828951142855133}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 40, y: 40}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &5711083483119391043
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 707051342981123557}
m_CullTransparentMesh: 1
--- !u!114 &3297791151943284155
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 707051342981123557}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0, g: 0.5, b: 0.153054, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 15e725f67e31b4b14b47715b50244dc0, type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &1024608873468362559
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7977828951142855133}
- component: {fileID: 7523232256770333524}
- component: {fileID: 7703631144606004140}
m_Layer: 5
m_Name: Background
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7977828951142855133
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1024608873468362559}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7224778997419466767}
m_Father: {fileID: 2189137325404022664}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 31.392, y: -31.092}
m_SizeDelta: {x: 40, y: 40}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7523232256770333524
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1024608873468362559}
m_CullTransparentMesh: 1
--- !u!114 &7703631144606004140
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1024608873468362559}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &2735457255991415772
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2189137325404022664}
- component: {fileID: 1368985993873080562}
m_Layer: 5
m_Name: ticketReasonToggle
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &2189137325404022664
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2735457255991415772}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7977828951142855133}
- {fileID: 7390458379522290553}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 567.0859, y: 63.2413}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1368985993873080562
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2735457255991415772}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 7703631144606004140}
toggleTransition: 1
graphic: {fileID: 3297791151943284155}
m_Group: {fileID: 0}
onValueChanged:
m_PersistentCalls:
m_Calls: []
m_IsOn: 1
--- !u!1 &5350386791310786802
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7390458379522290553}
- component: {fileID: 3429130727295528746}
- component: {fileID: 1103805545102531619}
m_Layer: 5
m_Name: Text (TMP)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7390458379522290553
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5350386791310786802}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2189137325404022664}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 19.9, y: 2.3}
m_SizeDelta: {x: 453.3022, y: 50}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &3429130727295528746
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5350386791310786802}
m_CullTransparentMesh: 1
--- !u!114 &1103805545102531619
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5350386791310786802}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Withdraw
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 893d86ab7286e5d4383d1c3f2ecdb510, type: 2}
m_sharedMaterial: {fileID: -5214663084478877120, guid: 893d86ab7286e5d4383d1c3f2ecdb510, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 36
m_fontSizeBase: 36
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 1
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 6372e540e43168cf0ab947b5ea4a95d5
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,796 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1318490843304738885
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4872065421449220216}
- component: {fileID: 868351031018468229}
- component: {fileID: 6046286292233998668}
- component: {fileID: 5046166766175730094}
- component: {fileID: 3566127904265910461}
m_Layer: 5
m_Name: Image (1)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4872065421449220216
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1318490843304738885}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 219784365551460667}
m_Father: {fileID: 2636528318417055051}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 458.40002, y: -92.6}
m_SizeDelta: {x: 547.48, y: 158}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &868351031018468229
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1318490843304738885}
m_CullTransparentMesh: 1
--- !u!114 &6046286292233998668
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1318490843304738885}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 74114cc50585c4f6785798e3d7f07fc8, type: 3}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &5046166766175730094
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1318490843304738885}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
m_Name:
m_EditorClassIdentifier:
m_HorizontalFit: 2
m_VerticalFit: 2
--- !u!114 &3566127904265910461
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1318490843304738885}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Padding:
m_Left: 28
m_Right: 55
m_Top: 0
m_Bottom: 0
m_ChildAlignment: 5
m_Spacing: 0
m_ChildForceExpandWidth: 1
m_ChildForceExpandHeight: 0
m_ChildControlWidth: 1
m_ChildControlHeight: 1
m_ChildScaleWidth: 0
m_ChildScaleHeight: 0
m_ReverseArrangement: 1
--- !u!1 &1405380894901176747
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7850979786460832269}
- component: {fileID: 7674930453967139263}
- component: {fileID: 6266541463831949275}
- component: {fileID: 9056709216080557839}
- component: {fileID: 5023480786529098034}
m_Layer: 5
m_Name: Image
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7850979786460832269
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1405380894901176747}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 6066549005503560976}
m_Father: {fileID: 9176780049885004140}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 355.085, y: -92.6}
m_SizeDelta: {x: 710.17, y: 154}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7674930453967139263
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1405380894901176747}
m_CullTransparentMesh: 1
--- !u!114 &6266541463831949275
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1405380894901176747}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 0.7372549}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 6a84fe7d00c0247719b41d0998c03ab0, type: 3}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &9056709216080557839
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1405380894901176747}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
m_Name:
m_EditorClassIdentifier:
m_HorizontalFit: 2
m_VerticalFit: 2
--- !u!114 &5023480786529098034
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1405380894901176747}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Padding:
m_Left: 45
m_Right: 30
m_Top: 0
m_Bottom: 0
m_ChildAlignment: 3
m_Spacing: 0
m_ChildForceExpandWidth: 1
m_ChildForceExpandHeight: 0
m_ChildControlWidth: 1
m_ChildControlHeight: 1
m_ChildScaleWidth: 0
m_ChildScaleHeight: 0
m_ReverseArrangement: 0
--- !u!1 &3977255666687989749
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 219784365551460667}
- component: {fileID: 7823826910691705863}
- component: {fileID: 1596261778508815527}
m_Layer: 5
m_Name: Text (TMP)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &219784365551460667
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3977255666687989749}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4872065421449220216}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 28, y: -79}
m_SizeDelta: {x: 464.48, y: 45.15}
m_Pivot: {x: 0, y: 0.5}
--- !u!222 &7823826910691705863
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3977255666687989749}
m_CullTransparentMesh: 1
--- !u!114 &1596261778508815527
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3977255666687989749}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Hi, sssssssssssssssssssssss
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: c1482dbce654844b9ba1c753cbea5d80, type: 2}
m_sharedMaterial: {fileID: 7374927986402738804, guid: c1482dbce654844b9ba1c753cbea5d80, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4282097920
m_fontColor: {r: 0, g: 0.6320754, b: 0.230302, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 39.5
m_fontSizeBase: 39.5
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 1
m_VerticalAlignment: 256
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &5544518929901409163
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6805552789421676139}
- component: {fileID: 4413301573786862017}
- component: {fileID: 6913463568644443495}
m_Layer: 5
m_Name: tkt_messageRow
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6805552789421676139
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5544518929901409163}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 9176780049885004140}
- {fileID: 2636528318417055051}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 185.2}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4413301573786862017
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5544518929901409163}
m_CullTransparentMesh: 1
--- !u!114 &6913463568644443495
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5544518929901409163}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 0}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &6071047006490169686
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 9176780049885004140}
- component: {fileID: 9101877728799453743}
- component: {fileID: 2454813564430485537}
- component: {fileID: 4463332525355654355}
m_Layer: 5
m_Name: left
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &9176780049885004140
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6071047006490169686}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7850979786460832269}
m_Father: {fileID: 6805552789421676139}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 369.7437, y: -92.6}
m_SizeDelta: {x: 725.4874, y: 185.2}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &9101877728799453743
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6071047006490169686}
m_CullTransparentMesh: 1
--- !u!114 &2454813564430485537
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6071047006490169686}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 0}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &4463332525355654355
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6071047006490169686}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Padding:
m_Left: 0
m_Right: 0
m_Top: 0
m_Bottom: 0
m_ChildAlignment: 3
m_Spacing: 0
m_ChildForceExpandWidth: 1
m_ChildForceExpandHeight: 1
m_ChildControlWidth: 0
m_ChildControlHeight: 0
m_ChildScaleWidth: 0
m_ChildScaleHeight: 0
m_ReverseArrangement: 0
--- !u!1 &7715799318579200123
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6066549005503560976}
- component: {fileID: 9106847951458700505}
- component: {fileID: 7196986866946262397}
m_Layer: 5
m_Name: Text (TMP)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6066549005503560976
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7715799318579200123}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7850979786460832269}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 45, y: -77}
m_SizeDelta: {x: 635.17, y: 135.45}
m_Pivot: {x: 0, y: 0.5}
--- !u!222 &9106847951458700505
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7715799318579200123}
m_CullTransparentMesh: 1
--- !u!114 &7196986866946262397
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7715799318579200123}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: 'Hello, Im Sew from customer support,
How may i assit you today?'
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: c1482dbce654844b9ba1c753cbea5d80, type: 2}
m_sharedMaterial: {fileID: 7374927986402738804, guid: c1482dbce654844b9ba1c753cbea5d80, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 39.5
m_fontSizeBase: 39.5
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 1
m_VerticalAlignment: 256
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &8599674140115870311
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2636528318417055051}
- component: {fileID: 6169702296448177218}
- component: {fileID: 5121754827664209597}
- component: {fileID: 422950567891508529}
m_Layer: 5
m_Name: right
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!224 &2636528318417055051
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8599674140115870311}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 4872065421449220216}
m_Father: {fileID: 6805552789421676139}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 366.07, y: -92.6}
m_SizeDelta: {x: 732.14, y: 185.2}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &6169702296448177218
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8599674140115870311}
m_CullTransparentMesh: 1
--- !u!114 &5121754827664209597
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8599674140115870311}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 0}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &422950567891508529
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8599674140115870311}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Padding:
m_Left: 0
m_Right: 0
m_Top: 0
m_Bottom: 0
m_ChildAlignment: 5
m_Spacing: 0
m_ChildForceExpandWidth: 1
m_ChildForceExpandHeight: 1
m_ChildControlWidth: 0
m_ChildControlHeight: 0
m_ChildScaleWidth: 0
m_ChildScaleHeight: 0
m_ReverseArrangement: 1
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: bc147480c77b541cb8b6d87f47604deb
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+1 -1
View File
@@ -39,7 +39,7 @@ RectTransform:
m_AnchorMin: {x: 0, y: 1} m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 98.775, y: -50} m_AnchoredPosition: {x: 98.775, y: -50}
m_SizeDelta: {x: 157.55, y: 0} m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5} m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &1951170700571642783 --- !u!222 &1951170700571642783
CanvasRenderer: CanvasRenderer:
File diff suppressed because it is too large Load Diff
+655
View File
@@ -0,0 +1,655 @@
using System;
using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class CustomerSupportCanvas : MonoBehaviour
{
const float ScreenFadeSeconds = 0.5f;
const float PollIntervalSeconds = 5f;
static readonly (string slug, string label)[] Categories =
{
(SupportClient.Category.Bug, "Report Bug"),
(SupportClient.Category.Cheating, "Report cheating"),
(SupportClient.Category.Withdrawal, "Request withdrawal"),
(SupportClient.Category.Crypto, "Pay with crypto"),
(SupportClient.Category.Other, "Other"),
};
public CanvasGroup helpScreen;
public Button btnCloseHelp;
public Button btnFaq, btnTickets;
public string faqUrl = "https://kickkings.app/faq";
public CanvasGroup ticketScreen;
public Button btnCloseTicket;
/// <summary>
/// If 0 open tickets, "No open tickets", otherwise "X Open Tickets"
/// </summary>
public TMP_Text txtTicketTitle;
public RectTransform ticketListParent;
/// <summary>
/// Item for the ticket list, single TMP_Text inside. Which should be like "Ticket #001", Once clicked, Show the necessary chat.
/// </summary>
public GameObject ticketListItemPrefab;
public Sprite spriteTicketOpen, spriteTicketClosed;
/// <summary>
/// If no chat is selected, show this text, Also dont show the input field if this is shown.
/// </summary>
public GameObject noChatSelectedTxt;
public RectTransform ticketChatParent;
/// <summary>
/// Two children, first is left, second is right, only 1 TMP_Text inside each, which should be the message. enable left for customer support agent, enable right for player.
/// </summary>
public GameObject ticketChatItemPrefab;
public TMP_InputField inputField;
public Button btnSend;
public Button newTicketBtn;
public GameObject newTicketPanel;
public RectTransform ticketReasonListParent;
/// <summary>
/// Item for the ticket reason list, a Toggle with a TMP_Text inside, which should be like "Reason 1", "Reason 2", "Reason 3", etc. Only 1 can be on. By default it will be all off, If all off, create Button should be interactable=false;
/// </summary>
public GameObject ticketReasonItemPrefab;
public Button btnCreateTicket;
public Button btnCancelTicket;
readonly List<SupportTicket> _tickets = new List<SupportTicket>();
readonly List<Toggle> _reasonToggles = new List<Toggle>();
readonly List<string> _reasonSlugs = new List<string>();
string _selectedTicketId;
string _selectedCategorySlug;
string _selectedCategoryLabel;
Coroutine _pollRoutine;
Coroutine _busyRoutine;
bool _requestInFlight;
bool _reasonsBuilt;
ToggleGroup _reasonToggleGroup;
void Start()
{
if (btnFaq != null)
btnFaq.onClick.AddListener(LaunchFAQ);
if (btnTickets != null)
btnTickets.onClick.AddListener(ShowTicketScreen);
if (btnCloseHelp != null)
btnCloseHelp.onClick.AddListener(CloseHelp);
if (btnCloseTicket != null)
btnCloseTicket.onClick.AddListener(ShowHelpScreen);
if (btnSend != null)
btnSend.onClick.AddListener(OnSendClicked);
if (newTicketBtn != null)
newTicketBtn.onClick.AddListener(OpenNewTicketPanel);
if (btnCreateTicket != null)
btnCreateTicket.onClick.AddListener(OnCreateTicketClicked);
if (btnCancelTicket != null)
btnCancelTicket.onClick.AddListener(CloseNewTicketPanel);
SetCanvasGroupVisible(helpScreen, true, false);
SetCanvasGroupVisible(ticketScreen, false, false);
ClearChatSelection();
HideNewTicketPanel();
EnsureReasonToggles();
}
void OnDisable()
{
StopPoll();
if (_busyRoutine != null)
{
StopCoroutine(_busyRoutine);
_busyRoutine = null;
}
_requestInFlight = false;
}
public void ShowHelpScreen()
{
StopPoll();
ClearChatSelection();
HideNewTicketPanel();
SetCanvasGroupVisible(helpScreen, true, true);
SetCanvasGroupVisible(ticketScreen, false, true);
}
public void ShowTicketScreen()
{
HideNewTicketPanel();
ClearChatSelection();
SetCanvasGroupVisible(helpScreen, false, true);
SetCanvasGroupVisible(ticketScreen, true, true);
RunExclusive(RefreshTicketsFlow());
}
void CloseHelp()
{
StopPoll();
ClearChatSelection();
HideNewTicketPanel();
SetCanvasGroupVisible(helpScreen, false, true);
SetCanvasGroupVisible(ticketScreen, false, true);
gameObject.SetActive(false);
}
void LaunchFAQ()
{
Application.OpenURL(faqUrl);
}
void OpenNewTicketPanel()
{
EnsureReasonToggles();
ResetReasonToggles();
if (newTicketPanel != null)
newTicketPanel.SetActive(true);
UpdateCreateButtonInteractable();
}
void CloseNewTicketPanel()
{
HideNewTicketPanel();
}
void HideNewTicketPanel()
{
if (newTicketPanel != null)
newTicketPanel.SetActive(false);
ResetReasonToggles();
}
void OnSendClicked()
{
if (_requestInFlight || string.IsNullOrEmpty(_selectedTicketId))
return;
string body = inputField != null ? inputField.text.Trim() : "";
if (string.IsNullOrEmpty(body))
return;
RunExclusive(SendMessageFlow(body));
}
void OnCreateTicketClicked()
{
if (_requestInFlight || string.IsNullOrEmpty(_selectedCategorySlug))
return;
string body = _selectedCategorySlug == SupportClient.Category.Other
? "Hi I need assistance"
: "Hi, I need assistance with " + _selectedCategoryLabel;
RunExclusive(CreateTicketFlow(_selectedCategorySlug, body));
}
IEnumerator RefreshTicketsFlow()
{
bool ok = false;
yield return EnsureSupportAuth(r => ok = r);
if (!ok)
yield break;
SupportCallResult<SupportTicketListResponse> result = null;
yield return SupportClient.ListTickets(r => result = r);
if (result == null || !result.ok)
{
ShowError(result != null ? result.error : "Could not load tickets.");
yield break;
}
RebuildTicketList(result.data != null ? result.data.tickets : null);
}
IEnumerator SendMessageFlow(string body)
{
bool ok = false;
yield return EnsureSupportAuth(r => ok = r);
if (!ok)
yield break;
string ticketId = _selectedTicketId;
SupportCallResult<SupportThread> result = null;
yield return SupportClient.SendMessage(ticketId, body, r => result = r);
if (result == null || !result.ok)
{
ShowError(result != null ? result.error : "Could not send message.");
yield break;
}
if (inputField != null)
inputField.text = "";
ApplyThread(result.data);
RefreshTicketPreviewFromThread(result.data);
RebuildTicketListFromCache();
}
IEnumerator CreateTicketFlow(string category, string body)
{
bool ok = false;
yield return EnsureSupportAuth(r => ok = r);
if (!ok)
yield break;
SupportCallResult<SupportThread> result = null;
yield return SupportClient.CreateTicket(category, body, r => result = r);
if (result == null || !result.ok)
{
ShowError(result != null ? result.error : "Could not create ticket.");
yield break;
}
HideNewTicketPanel();
SupportCallResult<SupportTicketListResponse> list = null;
yield return SupportClient.ListTickets(r => list = r);
if (list != null && list.ok)
RebuildTicketList(list.data != null ? list.data.tickets : null);
else if (result.data != null && result.data.ticket != null)
{
_tickets.Clear();
_tickets.Add(result.data.ticket);
RebuildTicketListFromCache();
}
if (result.data != null && result.data.ticket != null)
SelectTicket(result.data.ticket.id, result.data);
}
IEnumerator EnsureSupportAuth(Action<bool> done)
{
if (SupportClient.IsSignedIn)
{
done?.Invoke(true);
yield break;
}
string username = !string.IsNullOrEmpty(LoginManager.SessionUsername)
? LoginManager.SessionUsername
: (LoginManager.CurrentUser != null ? LoginManager.CurrentUser.username : null);
string password = LoginManager.SessionPassword;
Debug.Log("[CustomerSupport] support login as user='" + (username ?? "") +
"' passwordLength=" + (password != null ? password.Length : 0));
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
{
ShowError("Please sign in again to use customer support.");
done?.Invoke(false);
yield break;
}
SupportCallResult<SupportLoginResponse> result = null;
yield return SupportClient.Login(username, password, r => result = r);
if (result == null || !result.ok)
{
ShowError(result != null ? result.error : "Support login failed.");
done?.Invoke(false);
yield break;
}
done?.Invoke(true);
}
IEnumerator PollSelectedTicket()
{
string ticketId = _selectedTicketId;
if (string.IsNullOrEmpty(ticketId))
yield break;
yield return SupportClient.PollThread(ticketId, PollIntervalSeconds, result =>
{
if (result == null || !result.ok)
return;
if (_selectedTicketId != ticketId)
return;
ApplyThread(result.data);
RefreshTicketPreviewFromThread(result.data);
});
}
void SelectTicket(string ticketId, SupportThread initialThread = null)
{
if (string.IsNullOrEmpty(ticketId))
return;
_selectedTicketId = ticketId;
if (noChatSelectedTxt != null)
noChatSelectedTxt.SetActive(false);
SetChatInputVisible(true);
if (initialThread != null)
ApplyThread(initialThread);
else
ClearChatMessages();
StopPoll();
_pollRoutine = StartCoroutine(PollSelectedTicket());
}
void ClearChatSelection()
{
StopPoll();
_selectedTicketId = null;
ClearChatMessages();
if (noChatSelectedTxt != null)
noChatSelectedTxt.SetActive(true);
SetChatInputVisible(false);
if (inputField != null)
inputField.text = "";
}
void SetChatInputVisible(bool visible)
{
if (inputField != null)
inputField.gameObject.SetActive(visible);
if (btnSend != null)
btnSend.gameObject.SetActive(visible);
}
void RebuildTicketList(SupportTicket[] tickets)
{
_tickets.Clear();
if (tickets != null)
{
for (int i = 0; i < tickets.Length; i++)
{
if (tickets[i] != null)
_tickets.Add(tickets[i]);
}
}
RebuildTicketListFromCache();
}
void RebuildTicketListFromCache()
{
ClearChildren(ticketListParent);
UpdateOpenTicketTitle();
if (ticketListItemPrefab == null || ticketListParent == null)
return;
for (int i = 0; i < _tickets.Count; i++)
{
SupportTicket ticket = _tickets[i];
if (ticket == null)
continue;
GameObject item = Instantiate(ticketListItemPrefab, ticketListParent);
item.SetActive(true);
TMP_Text label = item.GetComponentInChildren<TMP_Text>(true);
if (label != null)
label.text = "Ticket #" + (i + 1).ToString("000");
Image image = item.GetComponent<Image>();
if (image == null)
image = item.GetComponentInChildren<Image>(true);
if (image != null)
{
bool isOpen = ticket.status == SupportClient.Status.Open;
Sprite sprite = isOpen ? spriteTicketOpen : spriteTicketClosed;
if (sprite != null)
image.sprite = sprite;
}
Button button = item.GetComponent<Button>();
if (button == null)
button = item.GetComponentInChildren<Button>(true);
if (button == null)
{
button = item.AddComponent<Button>();
if (image != null)
button.targetGraphic = image;
}
string ticketId = ticket.id;
button.onClick.RemoveAllListeners();
button.onClick.AddListener(() => SelectTicket(ticketId));
}
}
void ApplyThread(SupportThread thread)
{
if (thread == null)
return;
ClearChatMessages();
if (ticketChatItemPrefab == null || ticketChatParent == null || thread.messages == null)
return;
for (int i = 0; i < thread.messages.Length; i++)
{
SupportMessage message = thread.messages[i];
if (message == null)
continue;
GameObject item = Instantiate(ticketChatItemPrefab, ticketChatParent);
item.SetActive(true);
bool isStaff = string.Equals(message.authorKind, SupportClient.AuthorKind.Staff, StringComparison.OrdinalIgnoreCase);
Transform left = item.transform.childCount > 0 ? item.transform.GetChild(0) : null;
Transform right = item.transform.childCount > 1 ? item.transform.GetChild(1) : null;
if (left != null)
left.gameObject.SetActive(isStaff);
if (right != null)
right.gameObject.SetActive(!isStaff);
Transform activeSide = isStaff ? left : right;
if (activeSide != null)
{
TMP_Text text = activeSide.GetComponentInChildren<TMP_Text>(true);
if (text != null)
text.text = message.body ?? "";
}
}
}
void ClearChatMessages()
{
ClearChildren(ticketChatParent);
}
void RefreshTicketPreviewFromThread(SupportThread thread)
{
if (thread == null || thread.ticket == null || string.IsNullOrEmpty(thread.ticket.id))
return;
bool found = false;
for (int i = 0; i < _tickets.Count; i++)
{
if (_tickets[i] != null && _tickets[i].id == thread.ticket.id)
{
_tickets[i] = thread.ticket;
found = true;
break;
}
}
if (!found)
_tickets.Insert(0, thread.ticket);
UpdateOpenTicketTitle();
}
void UpdateOpenTicketTitle()
{
if (txtTicketTitle == null)
return;
int openCount = 0;
for (int i = 0; i < _tickets.Count; i++)
{
if (_tickets[i] != null && _tickets[i].status == SupportClient.Status.Open)
openCount++;
}
txtTicketTitle.text = openCount == 0
? "No open tickets"
: openCount + (openCount == 1 ? " Open Ticket" : " Open Tickets");
}
void EnsureReasonToggles()
{
if (_reasonsBuilt || ticketReasonListParent == null || ticketReasonItemPrefab == null)
return;
_reasonsBuilt = true;
ClearChildren(ticketReasonListParent);
_reasonToggles.Clear();
_reasonSlugs.Clear();
_reasonToggleGroup = ticketReasonListParent.GetComponent<ToggleGroup>();
if (_reasonToggleGroup == null)
_reasonToggleGroup = ticketReasonListParent.gameObject.AddComponent<ToggleGroup>();
_reasonToggleGroup.allowSwitchOff = true;
for (int i = 0; i < Categories.Length; i++)
{
string slug = Categories[i].slug;
string label = Categories[i].label;
GameObject item = Instantiate(ticketReasonItemPrefab, ticketReasonListParent);
item.SetActive(true);
Toggle toggle = item.GetComponent<Toggle>();
if (toggle == null)
toggle = item.GetComponentInChildren<Toggle>(true);
if (toggle == null)
continue;
toggle.group = _reasonToggleGroup;
toggle.isOn = false;
toggle.onValueChanged.RemoveAllListeners();
TMP_Text text = item.GetComponentInChildren<TMP_Text>(true);
if (text != null)
text.text = label;
string capturedSlug = slug;
string capturedLabel = label;
toggle.onValueChanged.AddListener(isOn =>
{
if (isOn)
{
_selectedCategorySlug = capturedSlug;
_selectedCategoryLabel = capturedLabel;
}
else if (_selectedCategorySlug == capturedSlug)
{
_selectedCategorySlug = null;
_selectedCategoryLabel = null;
}
UpdateCreateButtonInteractable();
});
_reasonToggles.Add(toggle);
_reasonSlugs.Add(slug);
}
UpdateCreateButtonInteractable();
}
void ResetReasonToggles()
{
_selectedCategorySlug = null;
_selectedCategoryLabel = null;
for (int i = 0; i < _reasonToggles.Count; i++)
{
if (_reasonToggles[i] != null)
_reasonToggles[i].SetIsOnWithoutNotify(false);
}
UpdateCreateButtonInteractable();
}
void UpdateCreateButtonInteractable()
{
if (btnCreateTicket != null)
btnCreateTicket.interactable = !_requestInFlight && !string.IsNullOrEmpty(_selectedCategorySlug);
}
void RunExclusive(IEnumerator routine)
{
if (_requestInFlight)
return;
if (_busyRoutine != null)
StopCoroutine(_busyRoutine);
_busyRoutine = StartCoroutine(RunExclusiveCoroutine(routine));
}
IEnumerator RunExclusiveCoroutine(IEnumerator routine)
{
_requestInFlight = true;
SetBusyUi(true);
try
{
yield return routine;
}
finally
{
_requestInFlight = false;
_busyRoutine = null;
SetBusyUi(false);
}
}
void SetBusyUi(bool busy)
{
if (btnSend != null)
btnSend.interactable = !busy && !string.IsNullOrEmpty(_selectedTicketId);
if (newTicketBtn != null)
newTicketBtn.interactable = !busy;
if (btnTickets != null)
btnTickets.interactable = !busy;
UpdateCreateButtonInteractable();
if (busy && btnCreateTicket != null)
btnCreateTicket.interactable = false;
}
void StopPoll()
{
if (_pollRoutine != null)
{
StopCoroutine(_pollRoutine);
_pollRoutine = null;
}
}
static void SetCanvasGroupVisible(CanvasGroup group, bool visible, bool animate)
{
if (group == null)
return;
group.DOKill();
group.blocksRaycasts = visible;
group.interactable = visible;
if (animate)
group.DOFade(visible ? 1f : 0f, ScreenFadeSeconds);
else
group.alpha = visible ? 1f : 0f;
}
static void ClearChildren(Transform parent)
{
if (parent == null)
return;
for (int i = parent.childCount - 1; i >= 0; i--)
Destroy(parent.GetChild(i).gameObject);
}
static void ShowError(string message)
{
if (string.IsNullOrEmpty(message))
message = "Something went wrong. Please try again.";
if (MessageBoxDialog.IsAvailable)
MessageBoxDialog.ShowBasic(message);
else
Debug.LogWarning(message);
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 3eb20b333998c3513aee8b47c7ebc472
+27
View File
@@ -64,9 +64,16 @@ public class LoginManager : MonoBehaviour
bool _appFocused = true; bool _appFocused = true;
bool _handlingKeepaliveUnauthorized; bool _handlingKeepaliveUnauthorized;
string _pendingAuthMessage; string _pendingAuthMessage;
string _pendingSessionPassword;
public static string AuthToken { get; private set; } public static string AuthToken { get; private set; }
/// <summary>Username from the last successful login/register (memory only).</summary>
public static string SessionUsername { get; private set; }
/// <summary>Game password kept in memory only after a successful login/register. Cleared on logout.</summary>
public static string SessionPassword { get; private set; }
/// <summary>Assigned side from the matchmaker <c>your_team</c> field. <c>null</c> until a room is found or after clear.</summary> /// <summary>Assigned side from the matchmaker <c>your_team</c> field. <c>null</c> until a room is found or after clear.</summary>
public static Team? MatchYourTeam { get; private set; } public static Team? MatchYourTeam { get; private set; }
@@ -175,6 +182,8 @@ public class LoginManager : MonoBehaviour
// Dev: log in with clone-aware credentials instead of resuming a saved session. // Dev: log in with clone-aware credentials instead of resuming a saved session.
StopKeepalive(); StopKeepalive();
AuthToken = ""; AuthToken = "";
SessionUsername = "";
SessionPassword = "";
PlayerPrefs.DeleteKey(PlayerPrefsAuthKey); PlayerPrefs.DeleteKey(PlayerPrefsAuthKey);
PlayerPrefs.Save(); PlayerPrefs.Save();
@@ -185,6 +194,7 @@ public class LoginManager : MonoBehaviour
if (passwordInputLogin != null) passwordInputLogin.text = devPass; if (passwordInputLogin != null) passwordInputLogin.text = devPass;
string loginJson = BuildLoginBody(devUser, devPass); string loginJson = BuildLoginBody(devUser, devPass);
// _pendingSessionPassword = devPass;
// StartCoroutine(AuthPostCoroutine(AuthBaseUrl + "/auth/login", loginJson, "Signed in.")); // StartCoroutine(AuthPostCoroutine(AuthBaseUrl + "/auth/login", loginJson, "Signed in."));
SetBusy(false); SetBusy(false);
#else #else
@@ -250,6 +260,8 @@ public class LoginManager : MonoBehaviour
if (instance != null) if (instance != null)
instance.StopKeepalive(); instance.StopKeepalive();
AuthToken = ""; AuthToken = "";
SessionUsername = "";
SessionPassword = "";
ClearLocalUserProfile(); ClearLocalUserProfile();
ClearMatchYourTeam(); ClearMatchYourTeam();
PlayerPrefs.DeleteKey(PlayerPrefsAuthKey); PlayerPrefs.DeleteKey(PlayerPrefsAuthKey);
@@ -274,10 +286,13 @@ public class LoginManager : MonoBehaviour
} }
AuthToken = ""; AuthToken = "";
SessionUsername = "";
SessionPassword = "";
ClearLocalUserProfile(); ClearLocalUserProfile();
MainMenuManager.ClearCachedSettingsProfile(); MainMenuManager.ClearCachedSettingsProfile();
ClearMatchYourTeam(); ClearMatchYourTeam();
OnUserDataUpdated = null; OnUserDataUpdated = null;
SupportClient.ClearSession();
Cupid.ClearSession(); Cupid.ClearSession();
CupidLobby.ClearUsername(); CupidLobby.ClearUsername();
GameManager.ClearMatchSession(); GameManager.ClearMatchSession();
@@ -390,6 +405,7 @@ public class LoginManager : MonoBehaviour
return; return;
} }
_pendingSessionPassword = password;
StartCoroutine(AuthPostCoroutine(AuthBaseUrl + "/auth/login", BuildLoginBody(username, password), "Signed in.")); StartCoroutine(AuthPostCoroutine(AuthBaseUrl + "/auth/login", BuildLoginBody(username, password), "Signed in."));
} }
@@ -427,6 +443,7 @@ public class LoginManager : MonoBehaviour
return; return;
} }
_pendingSessionPassword = password;
StartCoroutine(AuthPostCoroutine(AuthBaseUrl + "/auth/register", BuildRegisterBody(username, email, password), "Account created.")); StartCoroutine(AuthPostCoroutine(AuthBaseUrl + "/auth/register", BuildRegisterBody(username, email, password), "Account created."));
} }
@@ -713,12 +730,16 @@ public class LoginManager : MonoBehaviour
if (profileOk) if (profileOk)
{ {
SessionUsername = _currentUser != null ? _currentUser.username : "";
SessionPassword = _pendingSessionPassword ?? "";
_pendingSessionPassword = null;
enteredMenu = true; enteredMenu = true;
StartKeepalive(); StartKeepalive();
ProceedToMainMenu(); ProceedToMainMenu();
} }
else else
{ {
_pendingSessionPassword = null;
InvalidateStoredSession(); InvalidateStoredSession();
ShowAuthMessage(string.IsNullOrEmpty(profileErr) ShowAuthMessage(string.IsNullOrEmpty(profileErr)
? PlayerConnectionError ? PlayerConnectionError
@@ -727,6 +748,7 @@ public class LoginManager : MonoBehaviour
} }
else else
{ {
_pendingSessionPassword = null;
string serverError = resp != null ? resp.error : null; string serverError = resp != null ? resp.error : null;
if (string.IsNullOrEmpty(serverError) && resp != null && resp.code == AlreadyLoggedInCode) if (string.IsNullOrEmpty(serverError) && resp != null && resp.code == AlreadyLoggedInCode)
serverError = "Already logged in on another device"; serverError = "Already logged in on another device";
@@ -739,7 +761,10 @@ public class LoginManager : MonoBehaviour
finally finally
{ {
if (!enteredMenu) if (!enteredMenu)
{
_pendingSessionPassword = null;
SetBusy(false); SetBusy(false);
}
} }
} }
@@ -905,6 +930,8 @@ public class LoginManager : MonoBehaviour
static void ApplyUserData(UserData u) static void ApplyUserData(UserData u)
{ {
_currentUser = u; _currentUser = u;
if (u != null)
SupportClient.ClearSessionIfDifferentUser(u.username);
OnUserDataUpdated?.Invoke(u); OnUserDataUpdated?.Invoke(u);
} }
+546
View File
@@ -0,0 +1,546 @@
using System;
using System.Collections;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
/// <summary>
/// Player customer-support client for the admin server.
/// Staff routes are not included.
/// Call from any behaviour with <c>StartCoroutine</c>. Staff replies arrive when the game polls an open thread.
/// </summary>
public static class SupportClient
{
public const string DefaultBaseUrl = "https://kkadmin.playpoolstudios.com";
public const int MaxMessageLength = 4000;
const string TokenPrefsKey = "WalkInvest.SupportPlayerToken";
const string UserIdPrefsKey = "WalkInvest.SupportPlayerUserId";
const string UsernamePrefsKey = "WalkInvest.SupportPlayerUsername";
const string MessageLengthError = "Message must be between 1 and 4000 characters";
const string PlayerConnectionError = "Please check your internet connection and try again.";
const int RequestTimeoutSeconds = 20;
static readonly string[] CategorySlugs =
{
Category.Bug,
Category.Cheating,
Category.Withdrawal,
Category.Crypto,
Category.Other
};
/// <summary>Admin server origin, with no trailing slash.</summary>
public static string BaseUrl = DefaultBaseUrl;
static string _token;
static int _userId;
static string _username;
static bool _loaded;
public static bool IsSignedIn
{
get
{
EnsureLoaded();
return !string.IsNullOrEmpty(_token);
}
}
public static string Token
{
get
{
EnsureLoaded();
return _token;
}
}
public static int UserId
{
get
{
EnsureLoaded();
return _userId;
}
}
public static string Username
{
get
{
EnsureLoaded();
return _username;
}
}
public static class Category
{
public const string Bug = "bug";
public const string Cheating = "cheating";
public const string Withdrawal = "withdrawal";
public const string Crypto = "crypto";
public const string Other = "other";
}
public static class Status
{
public const string Open = "open";
public const string Closed = "closed";
}
public static class AuthorKind
{
public const string Player = "player";
public const string Staff = "staff";
}
public static bool IsCategory(string slug)
{
if (string.IsNullOrEmpty(slug))
return false;
for (int i = 0; i < CategorySlugs.Length; i++)
{
if (CategorySlugs[i] == slug)
return true;
}
return false;
}
public static void ClearSession()
{
_loaded = true;
_token = "";
_userId = 0;
_username = "";
PlayerPrefs.DeleteKey(TokenPrefsKey);
PlayerPrefs.DeleteKey(UserIdPrefsKey);
PlayerPrefs.DeleteKey(UsernamePrefsKey);
PlayerPrefs.Save();
}
/// <summary>
/// Drops a stored support session that belongs to a different game username.
/// </summary>
public static void ClearSessionIfDifferentUser(string gameUsername)
{
EnsureLoaded();
if (string.IsNullOrEmpty(_token) || string.IsNullOrEmpty(gameUsername))
return;
if (string.Equals(_username, gameUsername.Trim(), StringComparison.Ordinal))
return;
ClearSession();
}
/// <summary>POST /api/support/player/login. Stores the bearer token for later calls.</summary>
public static IEnumerator Login(string username, string password, Action<SupportCallResult<SupportLoginResponse>> onComplete)
{
var body = new LoginRequest
{
username = username != null ? username.Trim() : "",
password = password ?? ""
};
string json = JsonUtility.ToJson(body);
Debug.Log("[SupportClient] login user='" + body.username +
"' passwordLength=" + body.password.Length);
HttpOutcome http = null;
yield return Request("POST", "/api/support/player/login", json, false, r => http = r);
SupportCallResult<SupportLoginResponse> result = ParseOk<SupportLoginResponse>(http);
if (result.ok && (result.data == null || string.IsNullOrEmpty(result.data.token)))
result = Fail<SupportLoginResponse>(http.statusCode, "Invalid response from server");
if (result.ok)
StoreSession(result.data);
LogFailure("/api/support/player/login", result);
onComplete?.Invoke(result);
}
/// <summary>GET /api/support/player/tickets. Open tickets first, then newest message.</summary>
public static IEnumerator ListTickets(Action<SupportCallResult<SupportTicketListResponse>> onComplete)
{
yield return SendAuthorized("/api/support/player/tickets", "GET", null, onComplete, NormalizeTickets);
}
/// <summary>POST /api/support/player/tickets. Each call creates a new open ticket.</summary>
public static IEnumerator CreateTicket(string category, string body, Action<SupportCallResult<SupportThread>> onComplete)
{
category = category != null ? category.Trim() : "";
if (!IsCategory(category))
{
var invalid = Fail<SupportThread>(400, "Invalid category");
LogFailure("/api/support/player/tickets", invalid);
onComplete?.Invoke(invalid);
yield break;
}
body = body != null ? body.Trim() : "";
if (!IsMessageLengthValid(body))
{
var invalid = Fail<SupportThread>(400, MessageLengthError);
LogFailure("/api/support/player/tickets", invalid);
onComplete?.Invoke(invalid);
yield break;
}
string json = JsonUtility.ToJson(new CreateTicketRequest { category = category, body = body });
yield return SendAuthorized("/api/support/player/tickets", "POST", json, onComplete, NormalizeThread);
}
/// <summary>GET /api/support/player/tickets/{ticketId}. Messages are oldest first.</summary>
public static IEnumerator GetThread(string ticketId, Action<SupportCallResult<SupportThread>> onComplete)
{
if (!TryTicketPath(ticketId, "", out string path, out SupportCallResult<SupportThread> invalid))
{
LogFailure("/api/support/player/tickets/{ticketId}", invalid);
onComplete?.Invoke(invalid);
yield break;
}
yield return SendAuthorized(path, "GET", null, onComplete, NormalizeThread);
}
/// <summary>
/// POST /api/support/player/tickets/{ticketId}/messages.
/// A player message on a closed ticket reopens it.
/// </summary>
public static IEnumerator SendMessage(string ticketId, string body, Action<SupportCallResult<SupportThread>> onComplete)
{
if (!TryTicketPath(ticketId, "/messages", out string path, out SupportCallResult<SupportThread> invalid))
{
LogFailure("/api/support/player/tickets/{ticketId}/messages", invalid);
onComplete?.Invoke(invalid);
yield break;
}
body = body != null ? body.Trim() : "";
if (!IsMessageLengthValid(body))
{
invalid = Fail<SupportThread>(400, MessageLengthError);
LogFailure(path, invalid);
onComplete?.Invoke(invalid);
yield break;
}
string json = JsonUtility.ToJson(new MessageRequest { body = body });
yield return SendAuthorized(path, "POST", json, onComplete, NormalizeThread);
}
/// <summary>
/// Reads a thread immediately, then again after each interval, until the coroutine is stopped or the token is rejected.
/// </summary>
public static IEnumerator PollThread(string ticketId, float intervalSeconds, Action<SupportCallResult<SupportThread>> onResult)
{
if (intervalSeconds <= 0f)
intervalSeconds = 5f;
while (true)
{
SupportCallResult<SupportThread> result = null;
yield return GetThread(ticketId, r => result = r);
onResult?.Invoke(result);
if (result != null && (result.statusCode == 400 || result.statusCode == 401 || result.statusCode == 404))
yield break;
yield return new WaitForSecondsRealtime(intervalSeconds);
}
}
static IEnumerator SendAuthorized<T>(
string path,
string method,
string json,
Action<SupportCallResult<T>> onComplete,
Action<T> normalize) where T : class
{
HttpOutcome http = null;
yield return Request(method, path, json, true, r => http = r);
if (http != null && http.statusCode == 401 && IsSignedIn)
ClearSession();
SupportCallResult<T> result = ParseOk<T>(http);
if (result.ok && result.data != null)
normalize?.Invoke(result.data);
LogFailure(path, result);
onComplete?.Invoke(result);
}
static IEnumerator Request(string method, string path, string json, bool authorize, Action<HttpOutcome> done)
{
if (authorize && string.IsNullOrEmpty(Token))
{
done?.Invoke(new HttpOutcome
{
statusCode = 401,
body = "{\"error\":\"Unauthorized\"}"
});
yield break;
}
string url = RootUrl() + path;
Debug.Log("[SupportClient] " + method + " " + url);
using (var request = new UnityWebRequest(url, method))
{
request.downloadHandler = new DownloadHandlerBuffer();
request.timeout = RequestTimeoutSeconds;
if (method == UnityWebRequest.kHttpVerbPOST)
{
byte[] raw = Encoding.UTF8.GetBytes(json ?? "{}");
request.uploadHandler = new UploadHandlerRaw(raw);
request.SetRequestHeader("Content-Type", "application/json");
}
if (authorize)
request.SetRequestHeader("Authorization", "Bearer " + Token);
yield return request.SendWebRequest();
string text = "";
try
{
text = request.downloadHandler != null ? request.downloadHandler.text ?? "" : "";
}
catch (Exception e)
{
Logger.Log("Support response unreadable: " + e.Message);
}
if (request.responseCode == 0)
{
Debug.LogWarning("[SupportClient] failed " + method + " " + url + " — " +
(string.IsNullOrEmpty(request.error) ? "network error" : request.error));
done?.Invoke(new HttpOutcome { statusCode = 0, transportError = PlayerConnectionError });
yield break;
}
done?.Invoke(new HttpOutcome { statusCode = request.responseCode, body = text });
}
}
static SupportCallResult<T> ParseOk<T>(HttpOutcome http) where T : class
{
if (http == null)
return Fail<T>(0, PlayerConnectionError);
if (!string.IsNullOrEmpty(http.transportError))
return Fail<T>(http.statusCode, http.transportError);
if (http.statusCode < 200 || http.statusCode >= 300)
{
SupportErrorBody err = TryParse<SupportErrorBody>(http.body);
int retry = http.statusCode == 429 && err != null ? err.retryAfterSeconds : 0;
string message = err != null && !string.IsNullOrEmpty(err.error)
? err.error
: FallbackError(http.statusCode);
return Fail<T>(http.statusCode, message, retry);
}
T data = TryParse<T>(http.body);
if (data == null)
return Fail<T>(http.statusCode, "Invalid response from server");
return new SupportCallResult<T>
{
ok = true,
statusCode = http.statusCode,
data = data
};
}
static SupportCallResult<T> Fail<T>(long statusCode, string error, int retryAfterSeconds = 0)
{
return new SupportCallResult<T>
{
ok = false,
statusCode = statusCode,
error = error,
retryAfterSeconds = retryAfterSeconds
};
}
static T TryParse<T>(string json) where T : class
{
if (string.IsNullOrEmpty(json))
return null;
try
{
return JsonUtility.FromJson<T>(json);
}
catch (Exception e)
{
Logger.Log("Support JSON error: " + e.Message);
return null;
}
}
static string FallbackError(long statusCode)
{
if (statusCode == 401)
return "Unauthorized";
if (statusCode == 503)
return "Support is unavailable. Please try again later.";
return "Something went wrong. Please try again.";
}
static bool IsMessageLengthValid(string body)
{
return body != null && body.Length >= 1 && body.Length <= MaxMessageLength;
}
static bool TryTicketPath(string ticketId, string suffix, out string path, out SupportCallResult<SupportThread> error)
{
if (string.IsNullOrWhiteSpace(ticketId))
{
path = null;
error = Fail<SupportThread>(400, "Invalid ticket id");
return false;
}
path = "/api/support/player/tickets/" + UnityWebRequest.EscapeURL(ticketId.Trim()) + suffix;
error = null;
return true;
}
static void NormalizeTickets(SupportTicketListResponse list)
{
if (list != null && list.tickets == null)
list.tickets = Array.Empty<SupportTicket>();
}
static void NormalizeThread(SupportThread thread)
{
if (thread != null && thread.messages == null)
thread.messages = Array.Empty<SupportMessage>();
}
static void StoreSession(SupportLoginResponse login)
{
_loaded = true;
_token = login.token;
_userId = login.user != null ? login.user.id : 0;
_username = login.user != null ? login.user.username : "";
PlayerPrefs.SetString(TokenPrefsKey, _token);
PlayerPrefs.SetInt(UserIdPrefsKey, _userId);
PlayerPrefs.SetString(UsernamePrefsKey, _username ?? "");
PlayerPrefs.Save();
}
static void EnsureLoaded()
{
if (_loaded)
return;
_loaded = true;
_token = PlayerPrefs.GetString(TokenPrefsKey, "");
_userId = PlayerPrefs.GetInt(UserIdPrefsKey, 0);
_username = PlayerPrefs.GetString(UsernamePrefsKey, "");
}
static string RootUrl()
{
string root = string.IsNullOrWhiteSpace(BaseUrl) ? DefaultBaseUrl : BaseUrl.Trim();
return root.TrimEnd('/');
}
static void LogFailure<T>(string path, SupportCallResult<T> result)
{
if (result == null || result.ok)
return;
Logger.Log("Support " + path + " failed (" + result.statusCode + "): " + result.error);
}
class HttpOutcome
{
public long statusCode;
public string body;
public string transportError;
}
[Serializable]
public class LoginRequest
{
public string username;
public string password;
}
[Serializable]
public class CreateTicketRequest
{
public string category;
public string body;
}
[Serializable]
public class MessageRequest
{
public string body;
}
[Serializable]
public class SupportErrorBody
{
public string error;
public int retryAfterSeconds;
}
}
public class SupportCallResult<T>
{
public bool ok;
public long statusCode;
public string error;
public int retryAfterSeconds;
public T data;
}
[Serializable]
public class SupportLoginResponse
{
public string token;
public SupportPlayer user;
}
[Serializable]
public class SupportPlayer
{
public int id;
public string username;
}
[Serializable]
public class SupportTicket
{
public string id;
public int userId;
public string username;
public string category;
public string categoryLabel;
public string status;
public string createdAt;
public string updatedAt;
public string lastMessageAt;
public string lastMessagePreview;
}
[Serializable]
public class SupportMessage
{
public string id;
public string ticketId;
public string authorKind;
public string authorName;
public string body;
public string createdAt;
}
[Serializable]
public class SupportThread
{
public SupportTicket ticket;
public SupportMessage[] messages;
}
[Serializable]
public class SupportTicketListResponse
{
public SupportTicket[] tickets;
}
+2
View File
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: dbf9a007712b0ed92bb464442dd7f8b3
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

+182
View File
@@ -0,0 +1,182 @@
fileFormatVersion: 2
guid: f6a23a8d0f872b9bfbf4c720cc5ab6f1
TextureImporter:
internalIDToNameTable:
- first:
213: 1249877939505449902
second: cust_sup_0
- first:
213: -155184681247666284
second: cust_sup_1
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: cust_sup_0
rect:
serializedVersion: 2
x: 76
y: 24
width: 360
height: 418
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: eabc1d42d55785110800000000000000
internalID: 1249877939505449902
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: cust_sup_1
rect:
serializedVersion: 2
x: 96
y: 226
width: 320
height: 262
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 49f86a7ca5ca8ddf0800000000000000
internalID: -155184681247666284
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
cust_sup_0: 1249877939505449902
cust_sup_1: -155184681247666284
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
+3 -28
View File
@@ -1,29 +1,4 @@
Logger initiated at 10/8/2026 12:25:24 AM Logger initiated at 10/16/2026 1:51:15 PM
[10/8/2026 12:25:24 AM] Cupid settings updated [10/16/2026 1:51:15 PM] Cupid settings updated
[10/8/2026 12:25:24 AM] Cupid settings updated [10/16/2026 1:51:16 PM] Cupid settings updated
[10/8/2026 12:25:35 AM] Starting matchmake as warlock
[10/8/2026 12:25:37 AM] Got into a room
[10/8/2026 12:25:37 AM] {"ok":true,"entry_fee":21,"rc_prize":34,"for_red":{"Players":[{"Name":"warlock3","LastSeen":1791399336307,"UserId":6,"l10_wins":6,"l10_losses":3},{"Name":"warlock","LastSeen":1791399337205,"UserId":2,"l10_wins":4,"l10_losses":6}],"GameName":"soccar","Port":26738,"InitTime":1791399336307,"entry_fee":21,"match_id":689,"instance_started":true,"rc_prize":34,"your_team":"red"},"for_blue":{"Players":[{"Name":"warlock3","LastSeen":1791399336307,"UserId":6,"l10_wins":6,"l10_losses":3},{"Name":"warlock","LastSeen":1791399337205,"UserId":2,"l10_wins":4,"l10_losses":6}],"GameName":"soccar","Port":26738,"InitTime":1791399336307,"entry_fee":21,"match_id":689,"instance_started":true,"rc_prize":34,"your_team":"blue"}}
[10/8/2026 12:25:37 AM] Configured dedicated match reporting for match id 689 with secret 38516e39d3406225b7c3015a66e5d25c54e9b2024c0755212122bdcea3e3a328 and internal api base https://kkapi.playpoolstudios.com
[10/8/2026 12:25:37 AM] Setting cupid to load game scene
[10/8/2026 12:25:37 AM] Loading game scene
[10/8/2026 12:25:43 AM] Starting client at $kkapi.playpoolstudios.com:26738
[10/8/2026 12:25:43 AM] Client connected
[10/8/2026 12:25:43 AM] Dedicated join: team assigned Blue isServer=False matchId=689 secretEmpty=False redJoin=False blueJoin=False collected=False
[10/8/2026 12:25:58 AM] Selected team changed from Red to Blue
[10/8/2026 12:26:03 AM] Selected team changed from Blue to Red
[10/8/2026 12:26:03 AM] Score changed from 0 to 1
[10/8/2026 12:26:06 AM] Selected team changed from Red to Blue
[10/8/2026 12:26:12 AM] Selected team changed from Blue to Red
[10/8/2026 12:26:20 AM] Selected team changed from Red to Blue
[10/8/2026 12:26:24 AM] Selected team changed from Blue to Red
[10/8/2026 12:26:29 AM] Selected team changed from Red to Blue
[10/8/2026 12:26:32 AM] Selected team changed from Blue to Red
[10/8/2026 12:26:34 AM] Score changed from 1 to 2
[10/8/2026 12:26:37 AM] Selected team changed from Red to Blue
[10/8/2026 12:26:44 AM] Selected team changed from Blue to Red
[10/8/2026 12:26:47 AM] Score changed from 2 to 3
[10/8/2026 12:27:00 AM] Client disconnected
[10/8/2026 12:27:05 AM] Cupid settings updated
[10/8/2026 12:27:05 AM] Cupid settings updated
+1 -1
View File
@@ -2,7 +2,7 @@
"dependencies": { "dependencies": {
"com.boxqkrtm.ide.cursor": "https://github.com/boxqkrtm/com.unity.ide.cursor.git", "com.boxqkrtm.ide.cursor": "https://github.com/boxqkrtm/com.unity.ide.cursor.git",
"com.hwaet.projectcloner": "https://github.com/hwaet/UnityProjectCloner.git", "com.hwaet.projectcloner": "https://github.com/hwaet/UnityProjectCloner.git",
"com.ivanmurzak.unity.mcp": "0.93.0", "com.ivanmurzak.unity.mcp": "1.0.0",
"com.unity.addressables": "2.4.1", "com.unity.addressables": "2.4.1",
"com.unity.collab-proxy": "2.11.3", "com.unity.collab-proxy": "2.11.3",
"com.unity.feature.2d": "2.0.1", "com.unity.feature.2d": "2.0.1",
+1 -1
View File
@@ -17,7 +17,7 @@
"hash": "f8c8347af3a144069dffd6120f1c4142f8120891" "hash": "f8c8347af3a144069dffd6120f1c4142f8120891"
}, },
"com.ivanmurzak.unity.mcp": { "com.ivanmurzak.unity.mcp": {
"version": "0.93.0", "version": "1.0.0",
"depth": 0, "depth": 0,
"source": "registry", "source": "registry",
"dependencies": { "dependencies": {
+19 -19
View File
@@ -693,25 +693,25 @@ PlayerSettings:
webGLCloseOnQuit: 0 webGLCloseOnQuit: 0
webWasm2023: 0 webWasm2023: 0
scriptingDefineSymbols: scriptingDefineSymbols:
Android: MIRROR;MIRROR_89_OR_NEWER;MIRROR_90_OR_NEWER;MIRROR_93_OR_NEWER;MIRROR_96_OR_NEWER;EDGEGAP_PLUGIN_SERVERS;DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_6 Android: MIRROR;MIRROR_89_OR_NEWER;MIRROR_90_OR_NEWER;MIRROR_93_OR_NEWER;MIRROR_96_OR_NEWER;EDGEGAP_PLUGIN_SERVERS;DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_10
EmbeddedLinux: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_6 EmbeddedLinux: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_10
GameCoreScarlett: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_6 GameCoreScarlett: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_10
GameCoreXboxOne: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_6 GameCoreXboxOne: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_10
Kepler: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_6 Kepler: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_10
LinuxHeadlessSimulation: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_6 LinuxHeadlessSimulation: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_10
Nintendo Switch: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_6 Nintendo Switch: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_10
Nintendo Switch 2: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_6 Nintendo Switch 2: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_10
PS4: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_6 PS4: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_10
PS5: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_6 PS5: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_10
QNX: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_6 QNX: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_10
Server: EDGEGAP_PLUGIN_SERVERS;UNITY_MCP_READY;UNITY_MCP_DEPS_6 Server: EDGEGAP_PLUGIN_SERVERS;UNITY_MCP_READY;UNITY_MCP_DEPS_10
Standalone: DOTWEEN;MIRROR;MIRROR_89_OR_NEWER;MIRROR_90_OR_NEWER;MIRROR_93_OR_NEWER;MIRROR_96_OR_NEWER;EDGEGAP_PLUGIN_SERVERS;UNITY_MCP_READY;UNITY_MCP_DEPS_6 Standalone: DOTWEEN;MIRROR;MIRROR_89_OR_NEWER;MIRROR_90_OR_NEWER;MIRROR_93_OR_NEWER;MIRROR_96_OR_NEWER;EDGEGAP_PLUGIN_SERVERS;UNITY_MCP_READY;UNITY_MCP_DEPS_10
VisionOS: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_6 VisionOS: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_10
WebGL: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_6 WebGL: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_10
Windows Store Apps: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_6 Windows Store Apps: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_10
XboxOne: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_6 XboxOne: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_10
iPhone: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_6 iPhone: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_10
tvOS: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_6 tvOS: DOTWEEN;UNITY_MCP_READY;UNITY_MCP_DEPS_10
additionalCompilerArguments: {} additionalCompilerArguments: {}
platformArchitecture: {} platformArchitecture: {}
scriptingBackend: scriptingBackend: