@xmobitea/gn-typescript-client 2.6.12 → 2.6.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/dist/gearn.js.client.js +183 -57
  2. package/dist/gearn.js.client.min.js +1 -1
  3. package/dist/index.d.ts +2 -2
  4. package/dist/index.js +183 -57
  5. package/dist/runtime/GNNetwork.d.ts +1 -1
  6. package/dist/runtime/helper/GNSupport.d.ts +20 -0
  7. package/dist/runtime/{entity → helper}/OperationHelper.d.ts +1 -1
  8. package/dist/runtime/helper/StorageService.d.ts +18 -0
  9. package/dist/runtime/networking/NetworkingPeer.d.ts +1 -1
  10. package/dist/runtime/typescript/ServiceUpdate.d.ts +2 -0
  11. package/docs/COCOS_CREATOR_INTEGRATION.md +116 -0
  12. package/examples/cocos-creator/GearNExample.ts.txt +176 -0
  13. package/package.json +3 -2
  14. package/srcSwift/Package.swift +32 -0
  15. package/srcSwift/Sources/GearN/runtime/GNNetwork.swift +530 -0
  16. package/srcSwift/Sources/GearN/runtime/GNNetworkAuthenticateApi.swift +178 -0
  17. package/srcSwift/Sources/GearN/runtime/GNNetworkCharacterPlayerApi.swift +1162 -0
  18. package/srcSwift/Sources/GearN/runtime/GNNetworkCloudScriptApi.swift +154 -0
  19. package/srcSwift/Sources/GearN/runtime/GNNetworkContentApi.swift +208 -0
  20. package/srcSwift/Sources/GearN/runtime/GNNetworkDashboardApi.swift +240 -0
  21. package/srcSwift/Sources/GearN/runtime/GNNetworkGamePlayerApi.swift +1369 -0
  22. package/srcSwift/Sources/GearN/runtime/GNNetworkGroupApi.swift +1100 -0
  23. package/srcSwift/Sources/GearN/runtime/GNNetworkInventoryApi.swift +937 -0
  24. package/srcSwift/Sources/GearN/runtime/GNNetworkMasterPlayerApi.swift +2323 -0
  25. package/srcSwift/Sources/GearN/runtime/GNNetworkMultiplayerApi.swift +298 -0
  26. package/srcSwift/Sources/GearN/runtime/GNNetworkStoreInventoryApi.swift +397 -0
  27. package/srcSwift/Sources/GearN/runtime/common/Action0.swift +3 -0
  28. package/srcSwift/Sources/GearN/runtime/common/Action1.swift +3 -0
  29. package/srcSwift/Sources/GearN/runtime/common/Action2.swift +3 -0
  30. package/srcSwift/Sources/GearN/runtime/common/Action3.swift +3 -0
  31. package/srcSwift/Sources/GearN/runtime/common/Action4.swift +3 -0
  32. package/srcSwift/Sources/GearN/runtime/common/GNArray.swift +204 -0
  33. package/srcSwift/Sources/GearN/runtime/common/GNData.swift +108 -0
  34. package/srcSwift/Sources/GearN/runtime/common/GNHashtable.swift +200 -0
  35. package/srcSwift/Sources/GearN/runtime/config/GNServerSettings.swift +95 -0
  36. package/srcSwift/Sources/GearN/runtime/constant/Commands.swift +28 -0
  37. package/srcSwift/Sources/GearN/runtime/constant/EventCode.swift +10 -0
  38. package/srcSwift/Sources/GearN/runtime/constant/OperationCode.swift +252 -0
  39. package/srcSwift/Sources/GearN/runtime/constant/ReturnCode.swift +19 -0
  40. package/srcSwift/Sources/GearN/runtime/constant/enumType/ExecuteResponseStatus.swift +9 -0
  41. package/srcSwift/Sources/GearN/runtime/constant/enumType/FriendStatus.swift +8 -0
  42. package/srcSwift/Sources/GearN/runtime/constant/enumType/GoogleLoginType.swift +6 -0
  43. package/srcSwift/Sources/GearN/runtime/constant/enumType/GroupStatus.swift +8 -0
  44. package/srcSwift/Sources/GearN/runtime/constant/enumType/InvalidMemberType.swift +19 -0
  45. package/srcSwift/Sources/GearN/runtime/constant/enumType/ItemType.swift +6 -0
  46. package/srcSwift/Sources/GearN/runtime/constant/enumType/MatchmakingMemberStatus.swift +7 -0
  47. package/srcSwift/Sources/GearN/runtime/constant/enumType/MatchmakingTicketStatus.swift +9 -0
  48. package/srcSwift/Sources/GearN/runtime/constant/enumType/OwnerType.swift +10 -0
  49. package/srcSwift/Sources/GearN/runtime/constant/enumType/PermissionDataItem.swift +6 -0
  50. package/srcSwift/Sources/GearN/runtime/constant/enumType/PushPlatformType.swift +6 -0
  51. package/srcSwift/Sources/GearN/runtime/constant/enumType/RequestRole.swift +7 -0
  52. package/srcSwift/Sources/GearN/runtime/constant/enumType/RequestType.swift +16 -0
  53. package/srcSwift/Sources/GearN/runtime/constant/enumType/StoreItemType.swift +6 -0
  54. package/srcSwift/Sources/GearN/runtime/constant/enumType/StoreReceiveType.swift +9 -0
  55. package/srcSwift/Sources/GearN/runtime/constant/errorCode/ErrorCode.swift +58 -0
  56. package/srcSwift/Sources/GearN/runtime/constant/parameterCode/ParameterCode.swift +672 -0
  57. package/srcSwift/Sources/GearN/runtime/entity/DataMember.swift +196 -0
  58. package/srcSwift/Sources/GearN/runtime/entity/GNMetadata.swift +9 -0
  59. package/srcSwift/Sources/GearN/runtime/entity/InvalidMember.swift +11 -0
  60. package/srcSwift/Sources/GearN/runtime/entity/OperationEvent.swift +38 -0
  61. package/srcSwift/Sources/GearN/runtime/entity/OperationHelper.swift +28 -0
  62. package/srcSwift/Sources/GearN/runtime/entity/OperationRequest.swift +62 -0
  63. package/srcSwift/Sources/GearN/runtime/entity/OperationResponse.swift +98 -0
  64. package/srcSwift/Sources/GearN/runtime/entity/models/AuthenticateModels.swift +351 -0
  65. package/srcSwift/Sources/GearN/runtime/entity/models/AuthenticateRequestModels.swift +81 -0
  66. package/srcSwift/Sources/GearN/runtime/entity/models/AuthenticateResponseModels.swift +108 -0
  67. package/srcSwift/Sources/GearN/runtime/entity/models/CharacterPlayerModels.swift +1045 -0
  68. package/srcSwift/Sources/GearN/runtime/entity/models/CharacterPlayerRequestModels.swift +821 -0
  69. package/srcSwift/Sources/GearN/runtime/entity/models/CharacterPlayerResponseModels.swift +588 -0
  70. package/srcSwift/Sources/GearN/runtime/entity/models/CloudScriptModels.swift +187 -0
  71. package/srcSwift/Sources/GearN/runtime/entity/models/CloudScriptRequestModels.swift +84 -0
  72. package/srcSwift/Sources/GearN/runtime/entity/models/CloudScriptResponseModels.swift +59 -0
  73. package/srcSwift/Sources/GearN/runtime/entity/models/ContentModels.swift +195 -0
  74. package/srcSwift/Sources/GearN/runtime/entity/models/ContentRequestModels.swift +116 -0
  75. package/srcSwift/Sources/GearN/runtime/entity/models/ContentResponseModels.swift +81 -0
  76. package/srcSwift/Sources/GearN/runtime/entity/models/DashboardModels.swift +426 -0
  77. package/srcSwift/Sources/GearN/runtime/entity/models/DashboardRequestModels.swift +160 -0
  78. package/srcSwift/Sources/GearN/runtime/entity/models/DashboardResponseModels.swift +82 -0
  79. package/srcSwift/Sources/GearN/runtime/entity/models/GamePlayerModels.swift +1334 -0
  80. package/srcSwift/Sources/GearN/runtime/entity/models/GamePlayerRequestModels.swift +643 -0
  81. package/srcSwift/Sources/GearN/runtime/entity/models/GamePlayerResponseModels.swift +213 -0
  82. package/srcSwift/Sources/GearN/runtime/entity/models/GenericModels.swift +171 -0
  83. package/srcSwift/Sources/GearN/runtime/entity/models/GroupModels.swift +850 -0
  84. package/srcSwift/Sources/GearN/runtime/entity/models/GroupRequestModels.swift +485 -0
  85. package/srcSwift/Sources/GearN/runtime/entity/models/GroupResponseModels.swift +165 -0
  86. package/srcSwift/Sources/GearN/runtime/entity/models/InventoryModels.swift +679 -0
  87. package/srcSwift/Sources/GearN/runtime/entity/models/InventoryRequestModels.swift +413 -0
  88. package/srcSwift/Sources/GearN/runtime/entity/models/InventoryResponseModels.swift +141 -0
  89. package/srcSwift/Sources/GearN/runtime/entity/models/MasterPlayerModels.swift +378 -0
  90. package/srcSwift/Sources/GearN/runtime/entity/models/MasterPlayerRequestModels.swift +147 -0
  91. package/srcSwift/Sources/GearN/runtime/entity/models/MasterPlayerResponseModels.swift +318 -0
  92. package/srcSwift/Sources/GearN/runtime/entity/models/MultiplayerModels.swift +319 -0
  93. package/srcSwift/Sources/GearN/runtime/entity/models/MultiplayerRequestModels.swift +125 -0
  94. package/srcSwift/Sources/GearN/runtime/entity/models/MultiplayerResponseModels.swift +45 -0
  95. package/srcSwift/Sources/GearN/runtime/entity/models/StoreInventoryModels.swift +633 -0
  96. package/srcSwift/Sources/GearN/runtime/entity/models/StoreInventoryRequestModels.swift +173 -0
  97. package/srcSwift/Sources/GearN/runtime/entity/models/StoreInventoryResponseModels.swift +61 -0
  98. package/srcSwift/Sources/GearN/runtime/entity/request/CustomOperationRequest.swift +42 -0
  99. package/srcSwift/Sources/GearN/runtime/entity/response/CustomOperationResponse.swift +49 -0
  100. package/srcSwift/Sources/GearN/runtime/entity/response/GetAuthInfoResponse.swift +43 -0
  101. package/srcSwift/Sources/GearN/runtime/entity/response/HealthCheckResponse.swift +86 -0
  102. package/srcSwift/Sources/GearN/runtime/entity/response/UploadFileResponse.swift +15 -0
  103. package/srcSwift/Sources/GearN/runtime/helper/CodeHelper.swift +107 -0
  104. package/srcSwift/Sources/GearN/runtime/helper/ConverterService.swift +98 -0
  105. package/srcSwift/Sources/GearN/runtime/helper/EnumUtility.swift +34 -0
  106. package/srcSwift/Sources/GearN/runtime/helper/GNSupport.swift +41 -0
  107. package/srcSwift/Sources/GearN/runtime/helper/GNUtils.swift +66 -0
  108. package/srcSwift/Sources/GearN/runtime/helper/MessagePackConverterService.swift +21 -0
  109. package/srcSwift/Sources/GearN/runtime/helper/StorageService.swift +29 -0
  110. package/srcSwift/Sources/GearN/runtime/logger/GNDebug.swift +33 -0
  111. package/srcSwift/Sources/GearN/runtime/networking/AuthenticateStatus.swift +24 -0
  112. package/srcSwift/Sources/GearN/runtime/networking/IPeer.swift +8 -0
  113. package/srcSwift/Sources/GearN/runtime/networking/NetworkingPeer.swift +368 -0
  114. package/srcSwift/Sources/GearN/runtime/networking/OperationPending.swift +81 -0
  115. package/srcSwift/Sources/GearN/runtime/networking/PeerBase.swift +228 -0
  116. package/srcSwift/Sources/GearN/runtime/networking/handler/IServerEventHandler.swift +20 -0
  117. package/srcSwift/Sources/GearN/runtime/networking/http/HttpPeer.swift +226 -0
  118. package/srcSwift/Sources/GearN/runtime/networking/http/HttpTypes.swift +24 -0
  119. package/srcSwift/Sources/GearN/runtime/networking/http/NetworkingHttpPeerBase.swift +13 -0
  120. package/srcSwift/Sources/GearN/runtime/networking/http/NetworkingPeerUrlSession.swift +125 -0
  121. package/srcSwift/Sources/GearN/runtime/networking/request/NetRequest.swift +19 -0
  122. package/srcSwift/Sources/GearN/runtime/networking/response/NetResponse.swift +13 -0
  123. package/srcSwift/Sources/GearN/runtime/networking/socket/NetworkingPeerSocketIOClient.swift +244 -0
  124. package/srcSwift/Sources/GearN/runtime/networking/socket/NetworkingSocketPeerBase.swift +59 -0
  125. package/srcSwift/Sources/GearN/runtime/networking/socket/SocketPeer.swift +136 -0
  126. package/tsconfig-build.cocos.json +31 -0
  127. package/webpack.config.cocos.mjs +78 -0
@@ -0,0 +1,34 @@
1
+ import Foundation
2
+
3
+ public class EnumUtility {
4
+ // Swift has native RawRepresentable support, simplified logic.
5
+
6
+ public static func parse<T: RawRepresentable>(enumType: T.Type, value: String, ignoreCase: Bool = false) -> T? where T.RawValue == String {
7
+ // This assumes String raw value. But most enums here are Int.
8
+ // If generic T has RawValue == String, this works.
9
+ // For Int enums, parsing from String requires name matching, which equates to "custom parsing".
10
+ // Since CaseIterable exists, we can iterate.
11
+ return nil
12
+ }
13
+
14
+ // Helper for Int enums if name is passed
15
+ public static func parseGameLoop<T: CaseIterable>(enumType: T.Type, value: String, ignoreCase: Bool = true) -> T? {
16
+ for caseVal in enumType.allCases {
17
+ let label = String(describing: caseVal)
18
+ if ignoreCase {
19
+ if label.caseInsensitiveCompare(value) == .orderedSame {
20
+ return caseVal
21
+ }
22
+ } else {
23
+ if label == value {
24
+ return caseVal
25
+ }
26
+ }
27
+ }
28
+ return nil
29
+ }
30
+
31
+ public static func toString<T>(enumType: T, value: Any) -> String {
32
+ return String(describing: value)
33
+ }
34
+ }
@@ -0,0 +1,41 @@
1
+ import Foundation
2
+
3
+ public enum PlatformType: String {
4
+ case Cocos = "cocos"
5
+ case Browser = "browser"
6
+ case NodeJS = "nodejs"
7
+ case iOS = "ios"
8
+ case Windows = "windows" // Adding local context
9
+ }
10
+
11
+ public class GNSupport {
12
+ private static var isBrowserVar: Bool = false
13
+ private static var isCocosCreatorVar: Bool = false
14
+ private static var platformTypeVar: PlatformType = .Windows // Defaulting to native
15
+
16
+ public static func initSupport() {
17
+ // Detection logic in pure Swift is less relevant for "Browser/Node/Cocos" unless using those bridges.
18
+ // We will assume native.
19
+ #if canImport(UIKit)
20
+ self.platformTypeVar = .iOS
21
+ #else
22
+ self.platformTypeVar = .Windows // or Generic
23
+ #endif
24
+ }
25
+
26
+ public static func initialize() {
27
+ initSupport()
28
+ }
29
+
30
+ public static func isBrowser() -> Bool {
31
+ return self.isBrowserVar
32
+ }
33
+
34
+ public static func isCocosCreator() -> Bool {
35
+ return self.isCocosCreatorVar
36
+ }
37
+
38
+ public static func getPlatformType() -> PlatformType {
39
+ return self.platformTypeVar
40
+ }
41
+ }
@@ -0,0 +1,66 @@
1
+ import Foundation
2
+
3
+ public class GNUtils {
4
+ public static func toDatasDictionary(datas: [GenericModels.DataItem]?) -> [String: GenericModels.DataItem]? {
5
+ guard let datas = datas else { return nil }
6
+ var answer = [String: GenericModels.DataItem]()
7
+ for data in datas {
8
+ answer[data.key] = data
9
+ }
10
+ return answer
11
+ }
12
+
13
+ public static func toTagsDictionary(tags: [GenericModels.TagItem]?) -> [String: GenericModels.TagItem]? {
14
+ guard let tags = tags else { return nil }
15
+ var answer = [String: GenericModels.TagItem]()
16
+ for tag in tags {
17
+ answer[tag.key] = tag
18
+ }
19
+ return answer
20
+ }
21
+
22
+ public static func toCurrenciesDictionary(currencies: [GenericModels.CurrencyItem]?) -> [String: GenericModels.CurrencyItem]? {
23
+ guard let currencies = currencies else { return nil }
24
+ var answer = [String: GenericModels.CurrencyItem]()
25
+ for currency in currencies {
26
+ answer[currency.key] = currency
27
+ }
28
+ return answer
29
+ }
30
+
31
+ public static func toStatisticsDictionary(statistics: [GenericModels.StatisticsItem]?) -> [String: GenericModels.StatisticsItem]? {
32
+ guard let statistics = statistics else { return nil }
33
+ var answer = [String: GenericModels.StatisticsItem]()
34
+ for statistic in statistics {
35
+ answer[statistic.key] = statistic
36
+ }
37
+ return answer
38
+ }
39
+
40
+ public static func toInventoriesDictionary(inventories: [GenericModels.InventoryItem]?) -> [String: GenericModels.InventoryItem]? {
41
+ guard let inventories = inventories else { return nil }
42
+ var answer = [String: GenericModels.InventoryItem]()
43
+ for inventory in inventories {
44
+ answer[inventory.itemId] = inventory
45
+ }
46
+ return answer
47
+ }
48
+
49
+ public static func toGroupDictionary(groups: [GenericModels.GroupItem]?) -> [String: GenericModels.GroupItem]? {
50
+ guard let groups = groups else { return nil }
51
+ var answer = [String: GenericModels.GroupItem]()
52
+ for group in groups {
53
+ answer[group.groupId] = group
54
+ }
55
+ return answer
56
+ }
57
+
58
+ public static func toFriendDictionary(friends: [GenericModels.FriendItem]?) -> [String: GenericModels.FriendItem]? {
59
+ guard let friends = friends else { return nil }
60
+ var answer = [String: GenericModels.FriendItem]()
61
+ for friend in friends {
62
+ answer[friend.friendId] = friend
63
+ }
64
+ return answer
65
+ }
66
+ }
@@ -0,0 +1,21 @@
1
+ import Foundation
2
+ // Assuming a MsgPack library is available or will be implemented.
3
+ // TS used @msgpack/msgpack. Unity likely uses a C# MsgPack lib.
4
+ // Swift has MessagePack libraries. For now we will stub or assume basic Data if logic allows.
5
+ // But the service signature requires ser/deser.
6
+
7
+ public class MessagePackConverterService {
8
+ public static func serialize<T>(_ tObj: T) -> Data? {
9
+ // Placeholder: Implementation requires external MsgPack library
10
+ // For now returning nil to satisfy compilation, or use JSON as fallback?
11
+ // No, must follow MsgPack.
12
+ // Assuming user will provide MsgPack dependency or we create a wrapper later.
13
+ print("Warning: MessagePack serialization not fully implemented without dependency.")
14
+ return nil
15
+ }
16
+
17
+ public static func deserialize<T>(_ data: Data) -> T? {
18
+ // Placeholder
19
+ return nil
20
+ }
21
+ }
@@ -0,0 +1,29 @@
1
+ import Foundation
2
+
3
+ public class StorageService {
4
+ private static var _storage: [String: Any] = [:]
5
+
6
+ // In a real Swift SDK (iOS/macOS), we would use UserDefaults
7
+ // For now, mirroring the "NodeJS" in-memory approach or UserDefaults if available
8
+
9
+ public static func get(key: String, defaultValue: Any = "") -> Any {
10
+ if let val = UserDefaults.standard.object(forKey: key) {
11
+ return val
12
+ }
13
+ return defaultValue
14
+ }
15
+
16
+ public static func set(key: String, value: Any) {
17
+ UserDefaults.standard.set(value, forKey: key)
18
+ }
19
+
20
+ public static func remove(key: String) {
21
+ UserDefaults.standard.removeObject(forKey: key)
22
+ }
23
+
24
+ public static func clear() {
25
+ if let bundleID = Bundle.main.bundleIdentifier {
26
+ UserDefaults.standard.removePersistentDomain(forName: bundleID)
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,33 @@
1
+ import Foundation
2
+
3
+ public class GNDebug {
4
+ private static var _logType: LogType = .All
5
+
6
+ public static func setLogType(logType: LogType) {
7
+ self._logType = logType
8
+ }
9
+
10
+ public static func log(_ message: Any) {
11
+ if self._logType.rawValue >= LogType.All.rawValue {
12
+ print(message)
13
+ }
14
+ }
15
+
16
+ public static func logException(_ exception: Error) {
17
+ if self._logType.rawValue >= LogType.Exception.rawValue {
18
+ print("Exception: \(exception)")
19
+ }
20
+ }
21
+
22
+ public static func logWarning(_ message: Any) {
23
+ if self._logType.rawValue >= LogType.Warning.rawValue {
24
+ print("Warning: \(message)")
25
+ }
26
+ }
27
+
28
+ public static func logError(_ message: Any) {
29
+ if self._logType.rawValue >= LogType.Error.rawValue {
30
+ print("Error: \(message)")
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,24 @@
1
+ import Foundation
2
+
3
+ public class AuthenticateStatus {
4
+ private var authToken: String = ""
5
+ private var userId: String = ""
6
+
7
+ public init() {}
8
+
9
+ public func getAuthToken() -> String {
10
+ return authToken
11
+ }
12
+
13
+ public func setAuthToken(authToken: String) {
14
+ self.authToken = authToken
15
+ }
16
+
17
+ public func getUserId() -> String {
18
+ return userId
19
+ }
20
+
21
+ public func setUserId(userId: String) {
22
+ self.userId = userId
23
+ }
24
+ }
@@ -0,0 +1,8 @@
1
+ import Foundation
2
+
3
+ public protocol IPeer {
4
+ func initPeer()
5
+ func enqueue(requestType: RequestType, role: RequestRole, operationRequest: OperationRequest, onOperationResponse: Action1<OperationResponse>?, authToken: String?, secretKey: String?, customTags: GNHashtable?, gameId: String?)
6
+ func isUsing() -> Bool
7
+ func service()
8
+ }
@@ -0,0 +1,368 @@
1
+ import Foundation
2
+
3
+ public class NetworkingPeer {
4
+
5
+ // MARK: - Constants
6
+ internal static let SYNC_TS: String = "ts"
7
+ internal static let GET_AUTH_INFO: String = "getAuthInfo"
8
+ internal static let HEALTH_CHECK: String = "healthcheck"
9
+ internal static let API_JSON: String = "api/json"
10
+ internal static let API_MSG_PACK: String = "api/msgpack"
11
+ internal static let UPLOAD_FILE: String = "upload"
12
+ internal static let DOWNLOAD_FILE: String = "download"
13
+
14
+ // MARK: - Properties
15
+ private var socketPeer: SocketPeer!
16
+ private var httpPeer: HttpPeer!
17
+
18
+ public var authenticateStatus: AuthenticateStatus = AuthenticateStatus()
19
+ public var gameId: String = ""
20
+
21
+ private var onEventHandler: Action1<OperationEvent>?
22
+ private var onConnectHandlers: [Action0] = []
23
+ private var onDisconnectHandlers: [Action0] = []
24
+ private var serverEventHandlers: [IServerEventHandler] = []
25
+
26
+ // MARK: - Initialization
27
+ public init() {
28
+ self.socketPeer = SocketPeer()
29
+ self.httpPeer = HttpPeer()
30
+ }
31
+
32
+ public func initPeer() {
33
+ self.socketPeer.initPeer()
34
+ self.httpPeer.initPeer()
35
+ }
36
+
37
+ // MARK: - Getters
38
+ public func getPing() -> Int {
39
+ return socketPeer?.getPing() ?? -1
40
+ }
41
+
42
+ public func getClientId() -> String {
43
+ return socketPeer?.getClientId() ?? ""
44
+ }
45
+
46
+ public func getServerTimestamp() -> Int64 {
47
+ let currentTime = Int64(Date().timeIntervalSince1970 * 1000)
48
+ return currentTime + Int64(GNNetwork.serverTimeOffset)
49
+ }
50
+
51
+ public func getSocketPeer() -> SocketPeer {
52
+ return self.socketPeer
53
+ }
54
+
55
+ public func getHttpPeer() -> HttpPeer {
56
+ return self.httpPeer
57
+ }
58
+
59
+ // MARK: - Time Sync
60
+ public func setServerTimeMilliseconds(currentServerMilliseconds: Double) {
61
+ let timeOffset = currentServerMilliseconds - Double(Date().timeIntervalSince1970 * 1000)
62
+ GNNetwork.serverTimeOffset = timeOffset
63
+ }
64
+
65
+ // MARK: - Service Loop
66
+ public func service() {
67
+ self.socketPeer?.service()
68
+ self.httpPeer?.service()
69
+ }
70
+
71
+ // MARK: - Socket Connection
72
+ public func connectSocket(onSocketConnect: Action0? = nil) {
73
+ socketPeer?.connect(onConnect: onSocketConnect)
74
+ }
75
+
76
+ public func disconnectSocket(onSocketDisconnect: Action0? = nil) {
77
+ socketPeer?.disconnect(onDisconnect: onSocketDisconnect)
78
+ }
79
+
80
+ public func sendRequestAuthSocket() {
81
+ socketPeer?.sendRequestAuth()
82
+ }
83
+
84
+ // MARK: - Event Handlers
85
+ public func setOnEventHandler(onEventHandler: Action1<OperationEvent>?) {
86
+ self.onEventHandler = onEventHandler
87
+ }
88
+
89
+ public func setOnConnectHandler(onConnectHandler: @escaping Action0) {
90
+ onConnectHandlers.append(onConnectHandler)
91
+ }
92
+
93
+ public func setOnDisconnectHandler(onDisconnectHandler: @escaping Action0) {
94
+ onDisconnectHandlers.append(onDisconnectHandler)
95
+ }
96
+
97
+ public func removeOnConnectHandler(onConnectHandler: @escaping Action0) {
98
+ // Note: Swift closures are not directly comparable, so this is a simplified implementation
99
+ // In production, consider using identifiable handlers
100
+ }
101
+
102
+ public func removeOnDisconnectHandler(onDisconnectHandler: @escaping Action0) {
103
+ // Note: Swift closures are not directly comparable, so this is a simplified implementation
104
+ }
105
+
106
+ public func subscribeServerEventHandler(serverEventHandler: IServerEventHandler) {
107
+ serverEventHandlers.append(serverEventHandler)
108
+ }
109
+
110
+ internal func notifyOnConnect() {
111
+ for handler in onConnectHandlers {
112
+ handler()
113
+ }
114
+ }
115
+
116
+ internal func notifyOnDisconnect() {
117
+ for handler in onDisconnectHandlers {
118
+ handler()
119
+ }
120
+ }
121
+
122
+ internal func notifyOnEvent(event: OperationEvent) {
123
+ onEventHandler?(event)
124
+ for handler in serverEventHandlers {
125
+ handler.onEvent(event: event)
126
+ }
127
+ }
128
+
129
+ // MARK: - Send Methods
130
+ public func sendViaSocket(
131
+ requestType: RequestType,
132
+ role: RequestRole,
133
+ request: OperationRequest,
134
+ onResponse: Action1<OperationResponse>?,
135
+ overrideAuthToken: String = "",
136
+ overrideSecretKey: String = "",
137
+ customTags: GNHashtable? = nil
138
+ ) {
139
+ guard let settings = GNNetwork.getGNServerSettings() else { return }
140
+
141
+ let auth = overrideAuthToken.isEmpty ? authenticateStatus.getAuthToken() : overrideAuthToken
142
+
143
+ // Determine secret key based on role if not overridden
144
+ var secret = overrideSecretKey
145
+ if secret.isEmpty {
146
+ switch role {
147
+ case .Admin:
148
+ secret = settings.getAdminSecretKey() ?? ""
149
+ case .Server:
150
+ secret = settings.getServerSecretKey() ?? ""
151
+ case .Client:
152
+ secret = settings.getClientSecretKey() ?? ""
153
+ default:
154
+ break
155
+ }
156
+ }
157
+
158
+ let game = gameId.isEmpty ? settings.getGameId() : gameId
159
+
160
+ socketPeer.enqueue(
161
+ requestType: requestType,
162
+ role: role,
163
+ operationRequest: request,
164
+ onOperationResponse: onResponse,
165
+ authToken: auth,
166
+ secretKey: secret,
167
+ customTags: customTags,
168
+ gameId: game
169
+ )
170
+ }
171
+
172
+ public func sendViaHttp(
173
+ requestType: RequestType,
174
+ role: RequestRole,
175
+ request: OperationRequest,
176
+ onResponse: Action1<OperationResponse>?,
177
+ overrideAuthToken: String = "",
178
+ overrideSecretKey: String = "",
179
+ customTags: GNHashtable? = nil
180
+ ) {
181
+ guard let settings = GNNetwork.getGNServerSettings() else { return }
182
+
183
+ let auth = overrideAuthToken.isEmpty ? authenticateStatus.getAuthToken() : overrideAuthToken
184
+
185
+ // Determine secret key based on role if not overridden
186
+ var secret = overrideSecretKey
187
+ if secret.isEmpty {
188
+ switch role {
189
+ case .Admin:
190
+ secret = settings.getAdminSecretKey() ?? ""
191
+ case .Server:
192
+ secret = settings.getServerSecretKey() ?? ""
193
+ case .Client:
194
+ secret = settings.getClientSecretKey() ?? ""
195
+ default:
196
+ break
197
+ }
198
+ }
199
+
200
+ let game = gameId.isEmpty ? settings.getGameId() : gameId
201
+
202
+ httpPeer.enqueue(
203
+ requestType: requestType,
204
+ role: role,
205
+ operationRequest: request,
206
+ onOperationResponse: onResponse,
207
+ authToken: auth,
208
+ secretKey: secret,
209
+ customTags: customTags,
210
+ gameId: game
211
+ )
212
+ }
213
+
214
+ public func request(
215
+ requestType: RequestType,
216
+ role: RequestRole,
217
+ operationRequest: OperationRequest,
218
+ onOperationResponse: Action1<OperationResponse>?,
219
+ authToken: String = "",
220
+ secretKey: String = "",
221
+ customTags: GNHashtable? = nil,
222
+ gameId: String = ""
223
+ ) {
224
+ guard let settings = GNNetwork.getGNServerSettings() else { return }
225
+
226
+ let auth = authToken.isEmpty ? authenticateStatus.getAuthToken() : authToken
227
+ let game = gameId.isEmpty ? settings.getGameId() : gameId
228
+
229
+ if settings.isUseSocket() && socketPeer.isConnected() {
230
+ socketPeer.enqueue(
231
+ requestType: requestType,
232
+ role: role,
233
+ operationRequest: operationRequest,
234
+ onOperationResponse: onOperationResponse,
235
+ authToken: auth,
236
+ secretKey: secretKey,
237
+ customTags: customTags,
238
+ gameId: game
239
+ )
240
+ } else if settings.isUseHttp() {
241
+ httpPeer.enqueue(
242
+ requestType: requestType,
243
+ role: role,
244
+ operationRequest: operationRequest,
245
+ onOperationResponse: onOperationResponse,
246
+ authToken: auth,
247
+ secretKey: secretKey,
248
+ customTags: customTags,
249
+ gameId: game
250
+ )
251
+ } else {
252
+ GNDebug.logError("Cannot send request, no active peer connection or configuration.")
253
+ }
254
+ }
255
+
256
+ // MARK: - Utility Methods
257
+ public func syncTs(onResponse: Action1<Int64>? = nil) {
258
+ guard let settings = GNNetwork.getGNServerSettings() else {
259
+ onResponse?(Int64(Date().timeIntervalSince1970 * 1000))
260
+ return
261
+ }
262
+
263
+ let url = "\(settings.getHttpUrl())/\(NetworkingPeer.API_JSON)/sync"
264
+
265
+ httpPeer.sendRawRequest(url: url, method: "GET", body: nil) { [weak self] data, response, error in
266
+ guard let data = data,
267
+ let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
268
+ let serverTs = json["ts"] as? Int64 else {
269
+ onResponse?(Int64(Date().timeIntervalSince1970 * 1000))
270
+ return
271
+ }
272
+
273
+ self?.setServerTimeMilliseconds(currentServerMilliseconds: Double(serverTs))
274
+ onResponse?(serverTs)
275
+ }
276
+ }
277
+
278
+ public func getAuthInfo(authToken: String, onResponse: Action1<GetAuthInfoResponse>? = nil) {
279
+ guard let settings = GNNetwork.getGNServerSettings() else {
280
+ let response = GetAuthInfoResponse()
281
+ onResponse?(response)
282
+ return
283
+ }
284
+
285
+ let url = "\(settings.getHttpUrl())/\(NetworkingPeer.API_JSON)/auth/info"
286
+ var headers: [String: String] = [:]
287
+ headers["Authorization"] = "Bearer \(authToken)"
288
+
289
+ httpPeer.sendRawRequest(url: url, method: "GET", headers: headers, body: nil) { data, response, error in
290
+ let authInfoResponse = GetAuthInfoResponse()
291
+
292
+ if let data = data,
293
+ let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {
294
+ authInfoResponse.parseFromJson(json: json)
295
+ }
296
+
297
+ onResponse?(authInfoResponse)
298
+ }
299
+ }
300
+
301
+ public func healthCheck(onResponse: Action1<HealthCheckResponse>? = nil) {
302
+ guard let settings = GNNetwork.getGNServerSettings() else {
303
+ let response = HealthCheckResponse()
304
+ onResponse?(response)
305
+ return
306
+ }
307
+
308
+ let url = "\(settings.getHttpUrl())/health"
309
+
310
+ httpPeer.sendRawRequest(url: url, method: "GET", body: nil) { data, response, error in
311
+ let healthResponse = HealthCheckResponse()
312
+
313
+ if let data = data,
314
+ let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {
315
+ healthResponse.parseFromJson(json: json)
316
+ }
317
+
318
+ onResponse?(healthResponse)
319
+ }
320
+ }
321
+
322
+ public func uploadFile(
323
+ fileId: String,
324
+ content: Data,
325
+ filename: String,
326
+ mimetype: String,
327
+ onResponse: Action1<UploadFileResponse>? = nil
328
+ ) {
329
+ guard let settings = GNNetwork.getGNServerSettings() else {
330
+ let response = UploadFileResponse()
331
+ onResponse?(response)
332
+ return
333
+ }
334
+
335
+ let url = "\(settings.getHttpUrl())/\(NetworkingPeer.UPLOAD_FILE)"
336
+ let boundary = UUID().uuidString
337
+
338
+ var body = Data()
339
+
340
+ // Add file id field
341
+ body.append("--\(boundary)\r\n".data(using: .utf8)!)
342
+ body.append("Content-Disposition: form-data; name=\"fileId\"\r\n\r\n".data(using: .utf8)!)
343
+ body.append("\(fileId)\r\n".data(using: .utf8)!)
344
+
345
+ // Add file content
346
+ body.append("--\(boundary)\r\n".data(using: .utf8)!)
347
+ body.append("Content-Disposition: form-data; name=\"file\"; filename=\"\(filename)\"\r\n".data(using: .utf8)!)
348
+ body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: .utf8)!)
349
+ body.append(content)
350
+ body.append("\r\n".data(using: .utf8)!)
351
+ body.append("--\(boundary)--\r\n".data(using: .utf8)!)
352
+
353
+ var headers: [String: String] = [:]
354
+ headers["Content-Type"] = "multipart/form-data; boundary=\(boundary)"
355
+ headers["Authorization"] = "Bearer \(authenticateStatus.getAuthToken())"
356
+
357
+ httpPeer.sendRawRequest(url: url, method: "POST", headers: headers, body: body) { data, response, error in
358
+ let uploadResponse = UploadFileResponse()
359
+
360
+ if let data = data,
361
+ let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {
362
+ uploadResponse.parseFromJson(json: json)
363
+ }
364
+
365
+ onResponse?(uploadResponse)
366
+ }
367
+ }
368
+ }