@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.
- package/dist/gearn.js.client.js +183 -57
- package/dist/gearn.js.client.min.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +183 -57
- package/dist/runtime/GNNetwork.d.ts +1 -1
- package/dist/runtime/helper/GNSupport.d.ts +20 -0
- package/dist/runtime/{entity → helper}/OperationHelper.d.ts +1 -1
- package/dist/runtime/helper/StorageService.d.ts +18 -0
- package/dist/runtime/networking/NetworkingPeer.d.ts +1 -1
- package/dist/runtime/typescript/ServiceUpdate.d.ts +2 -0
- package/docs/COCOS_CREATOR_INTEGRATION.md +116 -0
- package/examples/cocos-creator/GearNExample.ts.txt +176 -0
- package/package.json +3 -2
- package/srcSwift/Package.swift +32 -0
- package/srcSwift/Sources/GearN/runtime/GNNetwork.swift +530 -0
- package/srcSwift/Sources/GearN/runtime/GNNetworkAuthenticateApi.swift +178 -0
- package/srcSwift/Sources/GearN/runtime/GNNetworkCharacterPlayerApi.swift +1162 -0
- package/srcSwift/Sources/GearN/runtime/GNNetworkCloudScriptApi.swift +154 -0
- package/srcSwift/Sources/GearN/runtime/GNNetworkContentApi.swift +208 -0
- package/srcSwift/Sources/GearN/runtime/GNNetworkDashboardApi.swift +240 -0
- package/srcSwift/Sources/GearN/runtime/GNNetworkGamePlayerApi.swift +1369 -0
- package/srcSwift/Sources/GearN/runtime/GNNetworkGroupApi.swift +1100 -0
- package/srcSwift/Sources/GearN/runtime/GNNetworkInventoryApi.swift +937 -0
- package/srcSwift/Sources/GearN/runtime/GNNetworkMasterPlayerApi.swift +2323 -0
- package/srcSwift/Sources/GearN/runtime/GNNetworkMultiplayerApi.swift +298 -0
- package/srcSwift/Sources/GearN/runtime/GNNetworkStoreInventoryApi.swift +397 -0
- package/srcSwift/Sources/GearN/runtime/common/Action0.swift +3 -0
- package/srcSwift/Sources/GearN/runtime/common/Action1.swift +3 -0
- package/srcSwift/Sources/GearN/runtime/common/Action2.swift +3 -0
- package/srcSwift/Sources/GearN/runtime/common/Action3.swift +3 -0
- package/srcSwift/Sources/GearN/runtime/common/Action4.swift +3 -0
- package/srcSwift/Sources/GearN/runtime/common/GNArray.swift +204 -0
- package/srcSwift/Sources/GearN/runtime/common/GNData.swift +108 -0
- package/srcSwift/Sources/GearN/runtime/common/GNHashtable.swift +200 -0
- package/srcSwift/Sources/GearN/runtime/config/GNServerSettings.swift +95 -0
- package/srcSwift/Sources/GearN/runtime/constant/Commands.swift +28 -0
- package/srcSwift/Sources/GearN/runtime/constant/EventCode.swift +10 -0
- package/srcSwift/Sources/GearN/runtime/constant/OperationCode.swift +252 -0
- package/srcSwift/Sources/GearN/runtime/constant/ReturnCode.swift +19 -0
- package/srcSwift/Sources/GearN/runtime/constant/enumType/ExecuteResponseStatus.swift +9 -0
- package/srcSwift/Sources/GearN/runtime/constant/enumType/FriendStatus.swift +8 -0
- package/srcSwift/Sources/GearN/runtime/constant/enumType/GoogleLoginType.swift +6 -0
- package/srcSwift/Sources/GearN/runtime/constant/enumType/GroupStatus.swift +8 -0
- package/srcSwift/Sources/GearN/runtime/constant/enumType/InvalidMemberType.swift +19 -0
- package/srcSwift/Sources/GearN/runtime/constant/enumType/ItemType.swift +6 -0
- package/srcSwift/Sources/GearN/runtime/constant/enumType/MatchmakingMemberStatus.swift +7 -0
- package/srcSwift/Sources/GearN/runtime/constant/enumType/MatchmakingTicketStatus.swift +9 -0
- package/srcSwift/Sources/GearN/runtime/constant/enumType/OwnerType.swift +10 -0
- package/srcSwift/Sources/GearN/runtime/constant/enumType/PermissionDataItem.swift +6 -0
- package/srcSwift/Sources/GearN/runtime/constant/enumType/PushPlatformType.swift +6 -0
- package/srcSwift/Sources/GearN/runtime/constant/enumType/RequestRole.swift +7 -0
- package/srcSwift/Sources/GearN/runtime/constant/enumType/RequestType.swift +16 -0
- package/srcSwift/Sources/GearN/runtime/constant/enumType/StoreItemType.swift +6 -0
- package/srcSwift/Sources/GearN/runtime/constant/enumType/StoreReceiveType.swift +9 -0
- package/srcSwift/Sources/GearN/runtime/constant/errorCode/ErrorCode.swift +58 -0
- package/srcSwift/Sources/GearN/runtime/constant/parameterCode/ParameterCode.swift +672 -0
- package/srcSwift/Sources/GearN/runtime/entity/DataMember.swift +196 -0
- package/srcSwift/Sources/GearN/runtime/entity/GNMetadata.swift +9 -0
- package/srcSwift/Sources/GearN/runtime/entity/InvalidMember.swift +11 -0
- package/srcSwift/Sources/GearN/runtime/entity/OperationEvent.swift +38 -0
- package/srcSwift/Sources/GearN/runtime/entity/OperationHelper.swift +28 -0
- package/srcSwift/Sources/GearN/runtime/entity/OperationRequest.swift +62 -0
- package/srcSwift/Sources/GearN/runtime/entity/OperationResponse.swift +98 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/AuthenticateModels.swift +351 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/AuthenticateRequestModels.swift +81 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/AuthenticateResponseModels.swift +108 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/CharacterPlayerModels.swift +1045 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/CharacterPlayerRequestModels.swift +821 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/CharacterPlayerResponseModels.swift +588 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/CloudScriptModels.swift +187 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/CloudScriptRequestModels.swift +84 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/CloudScriptResponseModels.swift +59 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/ContentModels.swift +195 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/ContentRequestModels.swift +116 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/ContentResponseModels.swift +81 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/DashboardModels.swift +426 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/DashboardRequestModels.swift +160 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/DashboardResponseModels.swift +82 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/GamePlayerModels.swift +1334 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/GamePlayerRequestModels.swift +643 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/GamePlayerResponseModels.swift +213 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/GenericModels.swift +171 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/GroupModels.swift +850 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/GroupRequestModels.swift +485 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/GroupResponseModels.swift +165 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/InventoryModels.swift +679 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/InventoryRequestModels.swift +413 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/InventoryResponseModels.swift +141 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/MasterPlayerModels.swift +378 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/MasterPlayerRequestModels.swift +147 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/MasterPlayerResponseModels.swift +318 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/MultiplayerModels.swift +319 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/MultiplayerRequestModels.swift +125 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/MultiplayerResponseModels.swift +45 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/StoreInventoryModels.swift +633 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/StoreInventoryRequestModels.swift +173 -0
- package/srcSwift/Sources/GearN/runtime/entity/models/StoreInventoryResponseModels.swift +61 -0
- package/srcSwift/Sources/GearN/runtime/entity/request/CustomOperationRequest.swift +42 -0
- package/srcSwift/Sources/GearN/runtime/entity/response/CustomOperationResponse.swift +49 -0
- package/srcSwift/Sources/GearN/runtime/entity/response/GetAuthInfoResponse.swift +43 -0
- package/srcSwift/Sources/GearN/runtime/entity/response/HealthCheckResponse.swift +86 -0
- package/srcSwift/Sources/GearN/runtime/entity/response/UploadFileResponse.swift +15 -0
- package/srcSwift/Sources/GearN/runtime/helper/CodeHelper.swift +107 -0
- package/srcSwift/Sources/GearN/runtime/helper/ConverterService.swift +98 -0
- package/srcSwift/Sources/GearN/runtime/helper/EnumUtility.swift +34 -0
- package/srcSwift/Sources/GearN/runtime/helper/GNSupport.swift +41 -0
- package/srcSwift/Sources/GearN/runtime/helper/GNUtils.swift +66 -0
- package/srcSwift/Sources/GearN/runtime/helper/MessagePackConverterService.swift +21 -0
- package/srcSwift/Sources/GearN/runtime/helper/StorageService.swift +29 -0
- package/srcSwift/Sources/GearN/runtime/logger/GNDebug.swift +33 -0
- package/srcSwift/Sources/GearN/runtime/networking/AuthenticateStatus.swift +24 -0
- package/srcSwift/Sources/GearN/runtime/networking/IPeer.swift +8 -0
- package/srcSwift/Sources/GearN/runtime/networking/NetworkingPeer.swift +368 -0
- package/srcSwift/Sources/GearN/runtime/networking/OperationPending.swift +81 -0
- package/srcSwift/Sources/GearN/runtime/networking/PeerBase.swift +228 -0
- package/srcSwift/Sources/GearN/runtime/networking/handler/IServerEventHandler.swift +20 -0
- package/srcSwift/Sources/GearN/runtime/networking/http/HttpPeer.swift +226 -0
- package/srcSwift/Sources/GearN/runtime/networking/http/HttpTypes.swift +24 -0
- package/srcSwift/Sources/GearN/runtime/networking/http/NetworkingHttpPeerBase.swift +13 -0
- package/srcSwift/Sources/GearN/runtime/networking/http/NetworkingPeerUrlSession.swift +125 -0
- package/srcSwift/Sources/GearN/runtime/networking/request/NetRequest.swift +19 -0
- package/srcSwift/Sources/GearN/runtime/networking/response/NetResponse.swift +13 -0
- package/srcSwift/Sources/GearN/runtime/networking/socket/NetworkingPeerSocketIOClient.swift +244 -0
- package/srcSwift/Sources/GearN/runtime/networking/socket/NetworkingSocketPeerBase.swift +59 -0
- package/srcSwift/Sources/GearN/runtime/networking/socket/SocketPeer.swift +136 -0
- package/tsconfig-build.cocos.json +31 -0
- 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
|
+
}
|