├── ProjectSettings ├── ProjectVersion.txt ├── NavMeshLayers.asset ├── ClusterInputManager.asset ├── NetworkManager.asset ├── TimeManager.asset ├── EditorBuildSettings.asset ├── AudioManager.asset ├── EditorSettings.asset ├── TagManager.asset ├── DynamicsManager.asset ├── UnityConnectSettings.asset ├── Physics2DSettings.asset ├── NavMeshAreas.asset ├── GraphicsSettings.asset ├── QualitySettings.asset ├── InputManager.asset └── ProjectSettings.asset ├── .gitmodules ├── Assets ├── scenes.meta ├── scripts.meta ├── scenes │ └── chat.unity.meta ├── scripts │ ├── pomelo.meta │ └── pomelo │ │ ├── LitJson.meta │ │ ├── pomelo-dotnetclient.meta │ │ ├── pomelo-dotnetclient │ │ ├── client.meta │ │ ├── protobuf.meta │ │ ├── protocol.meta │ │ ├── protobuf │ │ │ ├── util.meta │ │ │ ├── Decoder.cs.meta │ │ │ ├── Encoder.cs.meta │ │ │ ├── MsgDecoder.cs.meta │ │ │ ├── MsgEncoder.cs.meta │ │ │ ├── Protobuf.cs.meta │ │ │ ├── util │ │ │ │ ├── Util.cs.meta │ │ │ │ └── Util.cs │ │ │ ├── Protobuf.cs │ │ │ ├── Decoder.cs │ │ │ ├── Encoder.cs │ │ │ ├── MsgDecoder.cs │ │ │ └── MsgEncoder.cs │ │ ├── transport.meta │ │ ├── protocol │ │ │ ├── PackageTypes.cs │ │ │ ├── MessageType.cs │ │ │ ├── Message.cs.meta │ │ │ ├── Package.cs.meta │ │ │ ├── Protocol.cs.meta │ │ │ ├── MessageProtocol.cs.meta │ │ │ ├── MessageType.cs.meta │ │ │ ├── PackageProtocol.cs.meta │ │ │ ├── PackageTypes.cs.meta │ │ │ ├── ProtocolState.cs.meta │ │ │ ├── HandShakeService.cs.meta │ │ │ ├── HeartBeatService.cs.meta │ │ │ ├── Package.cs │ │ │ ├── Message.cs │ │ │ ├── ProtocolState.cs │ │ │ ├── PackageProtocol.cs │ │ │ ├── HeartBeatService.cs │ │ │ ├── HandShakeService.cs │ │ │ ├── MessageProtocol.cs │ │ │ └── Protocol.cs │ │ ├── client │ │ │ ├── EventManager.cs.meta │ │ │ ├── PomeloClient.cs.meta │ │ │ ├── EventManager.cs │ │ │ └── PomeloClient.cs │ │ └── transport │ │ │ ├── ITransporter.cs.meta │ │ │ ├── TransportState.cs.meta │ │ │ ├── TransporterSSL.cs.meta │ │ │ ├── TransporterTCP.cs.meta │ │ │ ├── ITransporter.cs │ │ │ ├── TransportState.cs │ │ │ ├── TransporterSSL.cs │ │ │ └── TransporterTCP.cs │ │ ├── LitJson │ │ ├── Lexer.cs.meta │ │ ├── JsonData.cs.meta │ │ ├── JsonMapper.cs.meta │ │ ├── JsonReader.cs.meta │ │ ├── JsonWriter.cs.meta │ │ ├── ParserToken.cs.meta │ │ ├── IJsonWrapper.cs.meta │ │ ├── JsonException.cs.meta │ │ ├── JsonMockWrapper.cs.meta │ │ ├── ParserToken.cs │ │ ├── JsonException.cs │ │ ├── IJsonWrapper.cs │ │ ├── JsonMockWrapper.cs │ │ ├── JsonWriter.cs │ │ └── JsonReader.cs │ │ ├── clientProtos.cs.meta │ │ ├── pomeloBehaviour.cs.meta │ │ ├── pomeloBehaviour.cs │ │ └── clientProtos.cs ├── chatofpomelo.cs.meta ├── logicclient.cs.meta ├── chatofpomelo.cs └── logicclient.cs ├── .gitignore ├── chatofpomelo-proto-patch ├── clientProtos.json └── serverProtos.json ├── LICENSE └── README.md /ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 5.6.0f3 2 | -------------------------------------------------------------------------------- /ProjectSettings/NavMeshLayers.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flamefox/pomelo-unitychat/HEAD/ProjectSettings/NavMeshLayers.asset -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "chatofpomelo-websocket"] 2 | path = chatofpomelo-websocket 3 | url = https://github.com/NetEase/chatofpomelo-websocket 4 | -------------------------------------------------------------------------------- /ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!236 &1 4 | ClusterInputManager: 5 | m_ObjectHideFlags: 0 6 | m_Inputs: [] 7 | -------------------------------------------------------------------------------- /Assets/scenes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1901d1beeccd7884a87efa25189b3366 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Assets/scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: de0cc7ee43804c140ac0ad26ec77c6ba 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!149 &1 4 | NetworkManager: 5 | m_ObjectHideFlags: 0 6 | m_DebugLevel: 0 7 | m_Sendrate: 15 8 | m_AssetToPrefab: {} 9 | -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!5 &1 4 | TimeManager: 5 | m_ObjectHideFlags: 0 6 | Fixed Timestep: 0.02 7 | Maximum Allowed Timestep: 0.33333334 8 | m_TimeScale: 1 9 | -------------------------------------------------------------------------------- /Assets/scenes/chat.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1985175677e82e1468ba6eb65ecb0478 3 | timeCreated: 1462854540 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a26bd4f5c67119c4d88caa4fb384cb1d 3 | folderAsset: yes 4 | timeCreated: 1464161552 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/LitJson.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bf46c37708c082841b45e81e90f693b0 3 | folderAsset: yes 4 | timeCreated: 1462854600 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1045 &1 4 | EditorBuildSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Scenes: 8 | - enabled: 0 9 | path: Assets/scenes/chat.unity 10 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 553310ee716a3914fa59b4728eb06419 3 | folderAsset: yes 4 | timeCreated: 1462854654 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/client.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d38744056f359fd42b04cc05951a4df0 3 | folderAsset: yes 4 | timeCreated: 1462854654 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protobuf.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 943789edc0080ce41b6de660df21530c 3 | folderAsset: yes 4 | timeCreated: 1462854654 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: aac621877d764a04588ad55c6f28c52d 3 | folderAsset: yes 4 | timeCreated: 1462854654 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protobuf/util.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 39b093c15892dd1418910e5c8a0de7fb 3 | folderAsset: yes 4 | timeCreated: 1462854654 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/transport.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c5c7a87d7b88c5e4f9e1fa524557140b 3 | folderAsset: yes 4 | timeCreated: 1462854654 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | player_win_x64.pdb 2 | player_win_x64_s.pdb 3 | Temp 4 | Library 5 | /pomelo-unitychat_Data 6 | /pomelo-unitychat.exe 7 | /player_win_x64.pdb 8 | /player_win_x64_s.pdb 9 | /.vs 10 | /pomelo-unitychat.CSharp.csproj 11 | /pomelo-unitychat.CSharp.csproj.user 12 | /pomelo-unitychat.sln 13 | -------------------------------------------------------------------------------- /Assets/chatofpomelo.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2c4a93b8eca5103488a9b0475065bd4b 3 | timeCreated: 1464157426 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/logicclient.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b5dd7fb9c0f72134486dff19aa4c5c48 3 | timeCreated: 1464346460 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/LitJson/Lexer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bf23bec0fd4a4d743846fa2cc7951a68 3 | timeCreated: 1462854600 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/clientProtos.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1c100346b60962a448c9e8c4432e752d 3 | timeCreated: 1464142004 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/LitJson/JsonData.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 73c01bce1537cc3419d374b2a2fd8ff5 3 | timeCreated: 1462854600 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/LitJson/JsonMapper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cd44d9aec75d43c4da58b238dbca19b1 3 | timeCreated: 1462854600 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/LitJson/JsonReader.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7715ee80c56ff2642b5f165c41461601 3 | timeCreated: 1462854600 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/LitJson/JsonWriter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8a18cdfcab209b34890299bd56c1a5f1 3 | timeCreated: 1462854600 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/LitJson/ParserToken.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3e423943575c62a4fb2dd9c4d96bd322 3 | timeCreated: 1462854600 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/PackageTypes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Pomelo.DotNetClient 4 | { 5 | public enum PackageType 6 | { 7 | PKG_HANDSHAKE = 1, 8 | PKG_HANDSHAKE_ACK = 2, 9 | PKG_HEARTBEAT = 3, 10 | PKG_DATA = 4, 11 | PKG_KICK = 5 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomeloBehaviour.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a25f4e11c54f9834d9e3a8668fc3dd4e 3 | timeCreated: 1464155602 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/LitJson/IJsonWrapper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e33786ad43e6a704c866adafd8f8b8ef 3 | timeCreated: 1462854602 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/LitJson/JsonException.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d3ed5d4e49665894cbaaeb7843be31ac 3 | timeCreated: 1462854600 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/LitJson/JsonMockWrapper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: af2920652cd459f4e8eac9ea32b09b80 3 | timeCreated: 1462854600 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/MessageType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Pomelo.DotNetClient 4 | { 5 | public enum MessageType 6 | { 7 | MSG_REQUEST = 0, 8 | MSG_NOTIFY = 1, 9 | MSG_RESPONSE = 2, 10 | MSG_PUSH = 3, 11 | 12 | MSG_LOCAL_CALLBACK = 999, 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/client/EventManager.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 220a7efed0418ce4d8270c4cd8764b64 3 | timeCreated: 1462854654 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/client/PomeloClient.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6675e88424fa0ed4287761950345486c 3 | timeCreated: 1465374469 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protobuf/Decoder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8d65499ea0220594e8a7966c967cde8a 3 | timeCreated: 1462854654 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protobuf/Encoder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 43ce470ba42d595438951a0dd1ab4541 3 | timeCreated: 1462854654 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protobuf/MsgDecoder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 932790a9dde02cf4f9ff2eed98ec9fcb 3 | timeCreated: 1462854654 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protobuf/MsgEncoder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 14f2dd712b7d1294a9bb7776e12247d6 3 | timeCreated: 1462854654 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protobuf/Protobuf.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e607e21738d9f944691871097ef24954 3 | timeCreated: 1462854654 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protobuf/util/Util.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: afb337f0860645d4e9f361d325f54125 3 | timeCreated: 1462854654 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/Message.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0d77ed8da9291bf4bbea16385d732b73 3 | timeCreated: 1462854654 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/Package.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ff0eb600f52970d428e7298727e2e030 3 | timeCreated: 1462854656 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/Protocol.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1c4c6289075b979499ad846b9856d350 3 | timeCreated: 1465374469 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/MessageProtocol.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d90a9a9293fd4db4da32ccb67869877f 3 | timeCreated: 1462854654 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/MessageType.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 77ee11c2f92974f41be0ffd40994ae5b 3 | timeCreated: 1462854654 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/PackageProtocol.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7f0090b39122231478801f62b231e80e 3 | timeCreated: 1462854654 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/PackageTypes.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c9a6ba5d7dc107247a6e065661d77c40 3 | timeCreated: 1462854654 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/ProtocolState.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e6ee9fa6f1101244ab276dea1094a113 3 | timeCreated: 1462854654 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/transport/ITransporter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d1f1072bb3518754e8cf69ccc2569b90 3 | timeCreated: 1464142004 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/transport/TransportState.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: df733a8cd0355d64c8e4ff3bd24d0c25 3 | timeCreated: 1462854654 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/transport/TransporterSSL.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0c3f5e70eb36bfc40b47a8dac855de51 3 | timeCreated: 1465374469 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/transport/TransporterTCP.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a032a8d5dd6f82f42bb6ad4dec9e6c06 3 | timeCreated: 1465374469 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/HandShakeService.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a4406f74e545d1a43b6d7ccff4600708 3 | timeCreated: 1462854654 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/HeartBeatService.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5b33eb63b05ab8242a8927e5a914f126 3 | timeCreated: 1462854654 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!11 &1 4 | AudioManager: 5 | m_ObjectHideFlags: 0 6 | m_Volume: 1 7 | Rolloff Scale: 1 8 | Doppler Factor: 1 9 | Default Speaker Mode: 2 10 | m_SampleRate: 0 11 | m_DSPBufferSize: 0 12 | m_VirtualVoiceCount: 512 13 | m_RealVoiceCount: 32 14 | m_SpatializerPlugin: 15 | m_DisableAudio: 0 16 | -------------------------------------------------------------------------------- /chatofpomelo-proto-patch/clientProtos.json: -------------------------------------------------------------------------------- 1 | { 2 | "chat.chatHandler.send": { 3 | "required string rid": 1, 4 | "required string content": 2, 5 | "required string from": 3, 6 | "required string target": 4 7 | }, 8 | 9 | "connector.entryHandler.enter": { 10 | "required string username": 1, 11 | "required string rid": 2 12 | }, 13 | 14 | "gate.gateHandler.queryEntry": { 15 | "required string uid": 1 16 | } 17 | } 18 | 19 | 20 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/Package.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Pomelo.DotNetClient 4 | { 5 | public class Package 6 | { 7 | public PackageType type; 8 | public int length; 9 | public byte[] body; 10 | 11 | public Package(PackageType type, byte[] body) 12 | { 13 | this.type = type; 14 | this.length = body.Length; 15 | this.body = body; 16 | } 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/transport/ITransporter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | 4 | namespace Pomelo.DotNetClient 5 | { 6 | public interface ITransporter 7 | { 8 | void receive(); 9 | void send(byte[] buffer); 10 | void onReceive(Action messageProcessor); 11 | void close(); 12 | void Connect(System.Net.IPEndPoint ep, int nTimeout = 5000); 13 | void setOnStateChanged(Action cb); 14 | NetWorkState NetworkState(); 15 | } 16 | } -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/transport/TransportState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Pomelo.DotNetClient 4 | { 5 | class StateObject 6 | { 7 | public const int BufferSize = 1024; 8 | internal byte[] buffer = new byte[BufferSize]; 9 | } 10 | 11 | public enum TransportState 12 | { 13 | readHead = 1, // on read head 14 | readBody = 2, // on read body 15 | closed = 3 // connection closed, will ignore all the message and wait for clean up 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /chatofpomelo-proto-patch/serverProtos.json: -------------------------------------------------------------------------------- 1 | { 2 | "onChat": { 3 | "required string msg": 1, 4 | "required string from": 2, 5 | "required string target": 3 6 | }, 7 | "onLeave": { 8 | "required string user": 1 9 | }, 10 | "onAdd": { 11 | "required string user": 1 12 | }, 13 | "gate.gateHandler.queryEntry": { 14 | "required int32 code": 1, 15 | "required string host": 2, 16 | "required int32 port": 3 17 | }, 18 | 19 | "connector.entryHandler.enter": { 20 | "repeated string users": 1 21 | } 22 | } -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!159 &1 4 | EditorSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 3 7 | m_ExternalVersionControlSupport: Hidden Meta Files 8 | m_SerializationMode: 2 9 | m_WebSecurityEmulationEnabled: 0 10 | m_WebSecurityEmulationHostUrl: http://www.mydomain.com/mygame.unity3d 11 | m_DefaultBehaviorMode: 0 12 | m_SpritePackerMode: 2 13 | m_SpritePackerPaddingPower: 1 14 | m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd 15 | m_ProjectGenerationRootNamespace: 16 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/Message.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using LitJson; 3 | 4 | namespace Pomelo.DotNetClient 5 | { 6 | public class Message 7 | { 8 | public MessageType type; 9 | public string route; 10 | public uint id; 11 | public JsonData data; 12 | 13 | public Message (MessageType type, uint id, string route, JsonData data) 14 | { 15 | this.type = type; 16 | this.id = id; 17 | this.route = route; 18 | this.data = data; 19 | } 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!78 &1 4 | TagManager: 5 | serializedVersion: 2 6 | tags: [] 7 | layers: 8 | - Default 9 | - TransparentFX 10 | - Ignore Raycast 11 | - 12 | - Water 13 | - UI 14 | - 15 | - 16 | - 17 | - 18 | - 19 | - 20 | - 21 | - 22 | - 23 | - 24 | - 25 | - 26 | - 27 | - 28 | - 29 | - 30 | - 31 | - 32 | - 33 | - 34 | - 35 | - 36 | - 37 | - 38 | - 39 | - 40 | m_SortingLayers: 41 | - name: Default 42 | uniqueID: 0 43 | locked: 0 44 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/ProtocolState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | 4 | namespace Pomelo.DotNetClient 5 | { 6 | public enum ClientProtocolType 7 | { 8 | [Description("normal")] 9 | NORMAL, 10 | 11 | [Description("TLS")] 12 | TLS 13 | } 14 | 15 | public enum ProtocolState 16 | { 17 | ready = 1, // Just open, need to send handshaking 18 | handshaking = 2, // on handshaking process 19 | working = 3, // can receive and send data 20 | closed = 4, // on read body 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!55 &1 4 | PhysicsManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Gravity: {x: 0, y: -9.81, z: 0} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_BounceThreshold: 2 10 | m_SleepThreshold: 0.005 11 | m_DefaultContactOffset: 0.01 12 | m_SolverIterationCount: 6 13 | m_QueriesHitTriggers: 1 14 | m_EnableAdaptiveForce: 0 15 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 16 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protobuf/Protobuf.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using LitJson; 3 | 4 | namespace Pomelo.Protobuf 5 | { 6 | public class Protobuf 7 | { 8 | private MsgDecoder decoder; 9 | private MsgEncoder encoder; 10 | 11 | public Protobuf (JsonData encodeProtos, JsonData decodeProtos) 12 | { 13 | this.encoder = new MsgEncoder(encodeProtos); 14 | this.decoder = new MsgDecoder(decodeProtos); 15 | } 16 | 17 | public byte[] encode(string route, JsonData msg){ 18 | return encoder.encode(route, msg); 19 | } 20 | 21 | public JsonData decode(string route, byte[] buffer){ 22 | return decoder.decode(route, buffer); 23 | } 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!310 &1 4 | UnityConnectSettings: 5 | m_ObjectHideFlags: 0 6 | m_Enabled: 0 7 | m_TestMode: 0 8 | m_TestEventUrl: 9 | m_TestConfigUrl: 10 | m_TestInitMode: 0 11 | CrashReportingSettings: 12 | m_EventUrl: https://perf-events.cloud.unity3d.com/api/events/crashes 13 | m_Enabled: 0 14 | m_CaptureEditorExceptions: 1 15 | UnityPurchasingSettings: 16 | m_Enabled: 0 17 | m_TestMode: 0 18 | UnityAnalyticsSettings: 19 | m_Enabled: 0 20 | m_InitializeOnStartup: 1 21 | m_TestMode: 0 22 | m_TestEventUrl: 23 | m_TestConfigUrl: 24 | UnityAdsSettings: 25 | m_Enabled: 0 26 | m_InitializeOnStartup: 1 27 | m_TestMode: 0 28 | m_EnabledPlatforms: 4294967295 29 | m_IosGameId: 30 | m_AndroidGameId: 31 | PerformanceReportingSettings: 32 | m_Enabled: 0 33 | -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!19 &1 4 | Physics2DSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Gravity: {x: 0, y: -9.81} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_VelocityIterations: 8 10 | m_PositionIterations: 3 11 | m_VelocityThreshold: 1 12 | m_MaxLinearCorrection: 0.2 13 | m_MaxAngularCorrection: 8 14 | m_MaxTranslationSpeed: 100 15 | m_MaxRotationSpeed: 360 16 | m_MinPenetrationForPenalty: 0.01 17 | m_BaumgarteScale: 0.2 18 | m_BaumgarteTimeOfImpactScale: 0.75 19 | m_TimeToSleep: 0.5 20 | m_LinearSleepTolerance: 0.01 21 | m_AngularSleepTolerance: 2 22 | m_QueriesHitTriggers: 1 23 | m_QueriesStartInColliders: 1 24 | m_ChangeStopsCallbacks: 0 25 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 26 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/LitJson/ParserToken.cs: -------------------------------------------------------------------------------- 1 | #region Header 2 | /** 3 | * ParserToken.cs 4 | * Internal representation of the tokens used by the lexer and the parser. 5 | * 6 | * The authors disclaim copyright to this source code. For more details, see 7 | * the COPYING file included with this distribution. 8 | **/ 9 | #endregion 10 | 11 | 12 | namespace LitJson 13 | { 14 | internal enum ParserToken 15 | { 16 | // Lexer tokens (see section A.1.1. of the manual) 17 | None = System.Char.MaxValue + 1, 18 | Number, 19 | True, 20 | False, 21 | Null, 22 | CharSeq, 23 | // Single char 24 | Char, 25 | 26 | // Parser Rules (see section A.2.1 of the manual) 27 | Text, 28 | Object, 29 | ObjectPrime, 30 | Pair, 31 | PairRest, 32 | Array, 33 | ArrayPrime, 34 | Value, 35 | ValueRest, 36 | String, 37 | 38 | // End of input 39 | End, 40 | 41 | // The empty rule 42 | Epsilon 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 2012-2016 NetDragon Websoft Inc. flamefox and other contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!126 &1 4 | NavMeshAreas: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | areas: 8 | - name: Walkable 9 | cost: 1 10 | - name: Not Walkable 11 | cost: 1 12 | - name: Jump 13 | cost: 2 14 | - name: 15 | cost: 1 16 | - name: 17 | cost: 1 18 | - name: 19 | cost: 1 20 | - name: 21 | cost: 1 22 | - name: 23 | cost: 1 24 | - name: 25 | cost: 1 26 | - name: 27 | cost: 1 28 | - name: 29 | cost: 1 30 | - name: 31 | cost: 1 32 | - name: 33 | cost: 1 34 | - name: 35 | cost: 1 36 | - name: 37 | cost: 1 38 | - name: 39 | cost: 1 40 | - name: 41 | cost: 1 42 | - name: 43 | cost: 1 44 | - name: 45 | cost: 1 46 | - name: 47 | cost: 1 48 | - name: 49 | cost: 1 50 | - name: 51 | cost: 1 52 | - name: 53 | cost: 1 54 | - name: 55 | cost: 1 56 | - name: 57 | cost: 1 58 | - name: 59 | cost: 1 60 | - name: 61 | cost: 1 62 | - name: 63 | cost: 1 64 | - name: 65 | cost: 1 66 | - name: 67 | cost: 1 68 | - name: 69 | cost: 1 70 | - name: 71 | cost: 1 72 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protobuf/Decoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Pomelo.Protobuf 4 | { 5 | public class Decoder 6 | { 7 | /// 8 | /// Decodes the UInt32. 9 | /// 10 | public static uint decodeUInt32(int offset, byte[] bytes, out int length){ 11 | uint n = 0; 12 | length = 0; 13 | 14 | for(int i = offset; i < bytes.Length; i++) { 15 | length++; 16 | uint m = Convert.ToUInt32(bytes[i]); 17 | n = n + Convert.ToUInt32((m & 0x7f) * Math.Pow(2, (7 * (i - offset)))); 18 | if(m < 128) { 19 | break; 20 | } 21 | } 22 | 23 | return n; 24 | } 25 | 26 | public static uint decodeUInt32(byte[] bytes){ 27 | int length; 28 | return decodeUInt32(0, bytes, out length); 29 | } 30 | 31 | /// 32 | /// Decodes the SInt32. 33 | /// 34 | public static int decodeSInt32(byte[] bytes){ 35 | uint n = decodeUInt32(bytes); 36 | int flag = ((n % 2) == 1) ? -1 : 1; 37 | 38 | int result = Convert.ToInt32(((n % 2 + n) / 2) * flag); 39 | return result; 40 | } 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/PackageProtocol.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Pomelo.DotNetClient 4 | { 5 | public class PackageProtocol 6 | { 7 | public const int HEADER_LENGTH = 4; 8 | 9 | public static byte[] encode(PackageType type){ 10 | return new byte[] { Convert.ToByte(type), 0, 0, 0 }; 11 | } 12 | 13 | public static byte[] encode(PackageType type, byte[] body){ 14 | int length = HEADER_LENGTH; 15 | 16 | if (body != null) length += body.Length; 17 | 18 | byte[] buf = new byte[length]; 19 | 20 | int index = 0; 21 | 22 | buf[index++] = Convert.ToByte(type); 23 | buf[index++] = Convert.ToByte(body.Length >> 16 & 0xFF); 24 | buf[index++] = Convert.ToByte(body.Length >> 8 & 0xFF); 25 | buf[index++] = Convert.ToByte(body.Length & 0xFF); 26 | 27 | while(index < length) { 28 | buf[index] = body[index - HEADER_LENGTH]; 29 | index++; 30 | } 31 | 32 | return buf; 33 | } 34 | 35 | public static Package decode(byte[] buf){ 36 | PackageType type = (PackageType)buf[0]; 37 | 38 | byte[] body = new byte[buf.Length - HEADER_LENGTH]; 39 | 40 | for(int i = 0; i < body.Length; i++) { 41 | body[i] = buf[i + HEADER_LENGTH]; 42 | } 43 | 44 | return new Package(type, body); 45 | } 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/LitJson/JsonException.cs: -------------------------------------------------------------------------------- 1 | #region Header 2 | /** 3 | * JsonException.cs 4 | * Base class throwed by LitJSON when a parsing error occurs. 5 | * 6 | * The authors disclaim copyright to this source code. For more details, see 7 | * the COPYING file included with this distribution. 8 | **/ 9 | #endregion 10 | 11 | 12 | using System; 13 | 14 | 15 | namespace LitJson 16 | { 17 | public class JsonException : ApplicationException 18 | { 19 | public JsonException () : base () 20 | { 21 | } 22 | 23 | internal JsonException (ParserToken token) : 24 | base (String.Format ( 25 | "Invalid token '{0}' in input string", token)) 26 | { 27 | } 28 | 29 | internal JsonException (ParserToken token, 30 | Exception inner_exception) : 31 | base (String.Format ( 32 | "Invalid token '{0}' in input string", token), 33 | inner_exception) 34 | { 35 | } 36 | 37 | internal JsonException (int c) : 38 | base (String.Format ( 39 | "Invalid character '{0}' in input string", (char) c)) 40 | { 41 | } 42 | 43 | internal JsonException (int c, Exception inner_exception) : 44 | base (String.Format ( 45 | "Invalid character '{0}' in input string", (char) c), 46 | inner_exception) 47 | { 48 | } 49 | 50 | 51 | public JsonException (string message) : base (message) 52 | { 53 | } 54 | 55 | public JsonException (string message, Exception inner_exception) : 56 | base (message, inner_exception) 57 | { 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pomelo-unitychat 2 | 3 | a pomelo unity chat sample 4 | 5 | * pure c# code 6 | * support proto,dict cache 7 | * poll mode only and all delegate at main thread 8 | * support tls 9 | * use LitJson 10 | 11 | you can use [pomelo's proto generator](https://github.com/flamefox/pomeloc) to generate the stub msg 12 | 13 | ## TestServer 14 | 15 | Use the sample server at this link [https://github.com/NetEase/chatofpomelo-websocket]. 16 | or use submodule just 17 | ``` 18 | cd game-server 19 | npm install -d 20 | node app 21 | ``` 22 | 23 | 24 | ## TLS/SSL EASY USE 25 | 26 | client: 27 | ```C# 28 | pomeloBehaviour client; 29 | client.ConnectServer(host, port, Pomelo.DotNetClient.ClientProtocolType.TLS); 30 | ``` 31 | 32 | server: 33 | ```javascript 34 | //app.js 35 | app.set('connectorConfig',{ 36 | connector: pomelo.connectors.hybridconnector, 37 | useDict: true, 38 | 39 | // enable useProto 40 | useProtobuf: true 41 | 42 | ,ssl: { 43 | ca: [fs.readFileSync('./keys/out/CA/ca.crt')], 44 | pfx: fs.readFileSync('./keys/out/newcert/server.pfx'), 45 | // This is necessary only if using the client certificate authentication. 46 | //requestCert: true, 47 | //rejectUnauthorized: true 48 | } 49 | }); 50 | ``` 51 | 52 | if you want change the verify of the server, change the code of 53 | ``` 54 | TransporterSSL.ValidateServerCertificate 55 | ``` 56 | 57 | 58 | ## Test with 59 | 60 | unity 5.6.0 61 | pomelo 2.2.x 62 | Windows 63 | 64 | ## install 65 | 66 | just run the newest chatofpomelo-websocket game-server, and open the project with untiy3d and play it. 67 | 68 | ## known issue 69 | 70 | ~~sometime unity socket BeginConnect will not return(maybe Unity Editor's bug[[TCP Socket Async BeginSend never happens](http://answers.unity3d.com/questions/892371/tcp-socket-async-beginsend-never-happens.html)]), re-compile script or restart will fix this~~ 71 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/LitJson/IJsonWrapper.cs: -------------------------------------------------------------------------------- 1 | #region Header 2 | /** 3 | * IJsonWrapper.cs 4 | * Interface that represents a type capable of handling all kinds of JSON 5 | * data. This is mainly used when mapping objects through JsonMapper, and 6 | * it's implemented by JsonData. 7 | * 8 | * The authors disclaim copyright to this source code. For more details, see 9 | * the COPYING file included with this distribution. 10 | **/ 11 | #endregion 12 | 13 | 14 | using System.Collections; 15 | using System.Collections.Specialized; 16 | 17 | 18 | namespace LitJson 19 | { 20 | public enum JsonType 21 | { 22 | None, 23 | 24 | Object, 25 | Array, 26 | String, 27 | Int, 28 | Long, 29 | Double, 30 | Boolean, 31 | Float 32 | } 33 | 34 | public interface IJsonWrapper : IList, IOrderedDictionary 35 | { 36 | bool IsArray { get; } 37 | bool IsBoolean { get; } 38 | bool IsDouble { get; } 39 | bool IsInt { get; } 40 | bool IsLong { get; } 41 | bool IsObject { get; } 42 | bool IsString { get; } 43 | bool IsFloat { get; } 44 | 45 | bool GetBoolean (); 46 | float GetFloat(); 47 | double GetDouble (); 48 | int GetInt (); 49 | JsonType GetJsonType (); 50 | long GetLong (); 51 | string GetString (); 52 | 53 | void SetBoolean (bool val); 54 | void SetDouble (double val); 55 | void SetFloat (float val); 56 | void SetInt (int val); 57 | void SetJsonType (JsonType type); 58 | void SetLong (long val); 59 | void SetString (string val); 60 | 61 | string ToJson (); 62 | void ToJson (JsonWriter writer); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/HeartBeatService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Timers; 3 | 4 | namespace Pomelo.DotNetClient 5 | { 6 | public class HeartBeatService 7 | { 8 | int interval; 9 | public int timeout; 10 | Timer timer; 11 | DateTime lastTime; 12 | 13 | Protocol protocol; 14 | 15 | public HeartBeatService(int interval, Protocol protocol){ 16 | this.interval = interval * 1000; 17 | this.protocol = protocol; 18 | } 19 | 20 | public void resetTimeout(){ 21 | this.timeout = 0; 22 | lastTime = DateTime.Now; 23 | } 24 | 25 | public void sendHeartBeat(object source, ElapsedEventArgs e) { 26 | TimeSpan span = DateTime.Now - lastTime; 27 | timeout = (int)span.TotalMilliseconds; 28 | 29 | //check timeout 30 | if (timeout > interval * 2) 31 | { 32 | //protocol.getPomeloClient().disconnect(); 33 | protocol.close(); 34 | //stop(); 35 | return; 36 | } 37 | 38 | //Send heart beat 39 | protocol.send(PackageType.PKG_HEARTBEAT); 40 | } 41 | 42 | public void start(){ 43 | if (interval < 1000) return; 44 | 45 | //start hearbeat 46 | this.timer = new Timer(); 47 | timer.Interval = interval; 48 | timer.Elapsed += new ElapsedEventHandler(sendHeartBeat); 49 | timer.Enabled = true; 50 | 51 | //Set timeout 52 | timeout = 0; 53 | lastTime = DateTime.Now; 54 | } 55 | 56 | public void stop(){ 57 | if(this.timer != null) { 58 | this.timer.Enabled = false; 59 | this.timer.Dispose(); 60 | } 61 | } 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/HandShakeService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using LitJson; 4 | using System.Net; 5 | using System.Net.Sockets; 6 | 7 | namespace Pomelo.DotNetClient 8 | { 9 | public class HandShakeService 10 | { 11 | private Protocol protocol; 12 | private Action callback; 13 | 14 | public const string Version = "0.3.0"; 15 | public const string Type = "unity-socket"; 16 | //private ProtocolNew protocolNew; 17 | 18 | //public HandShakeService(Protocol protocol) 19 | //{ 20 | // this.protocol = protocol; 21 | //} 22 | 23 | public HandShakeService(Protocol protocolNew) 24 | { 25 | this.protocol = protocolNew; 26 | } 27 | 28 | public void request(JsonData user, Action callback){ 29 | byte[] body = Encoding.UTF8.GetBytes(JsonMapper.ToJson(buildMsg(user))); 30 | 31 | protocol.send(PackageType.PKG_HANDSHAKE, body); 32 | 33 | this.callback = callback; 34 | } 35 | 36 | internal void invokeCallback(JsonData data){ 37 | //Invoke the handshake callback 38 | if (callback != null) callback.Invoke(data); 39 | } 40 | 41 | public void ack(){ 42 | protocol.send(PackageType.PKG_HANDSHAKE_ACK, new byte[0]); 43 | } 44 | 45 | private JsonData buildMsg(JsonData user) { 46 | if (user == null) user = new JsonData(); 47 | 48 | JsonData msg = new JsonData(); 49 | 50 | //Build sys option 51 | JsonData sys = new JsonData(); 52 | sys["version"] = Version; 53 | sys["type"] = Type; 54 | sys["dictVersion"] = protocol.getDictVersion(); 55 | sys["protoVersion"] = protocol.getProtoVersion(); 56 | //sys["handshakeVersion"] = protocol.HandShakeVersion; 57 | 58 | //Build handshake message 59 | msg["sys"] = sys; 60 | msg["user"] = user; 61 | 62 | return msg; 63 | } 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!30 &1 4 | GraphicsSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 12 7 | m_Deferred: 8 | m_Mode: 1 9 | m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} 10 | m_DeferredReflections: 11 | m_Mode: 1 12 | m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} 13 | m_ScreenSpaceShadows: 14 | m_Mode: 1 15 | m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} 16 | m_LegacyDeferred: 17 | m_Mode: 1 18 | m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} 19 | m_DepthNormals: 20 | m_Mode: 1 21 | m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} 22 | m_MotionVectors: 23 | m_Mode: 1 24 | m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} 25 | m_LightHalo: 26 | m_Mode: 1 27 | m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} 28 | m_LensFlare: 29 | m_Mode: 1 30 | m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} 31 | m_AlwaysIncludedShaders: 32 | - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} 33 | - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} 34 | - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} 35 | - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} 36 | - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} 37 | - {fileID: 10782, guid: 0000000000000000f000000000000000, type: 0} 38 | - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0} 39 | m_PreloadedShaders: [] 40 | m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, 41 | type: 0} 42 | m_CustomRenderPipeline: {fileID: 0} 43 | m_TransparencySortMode: 0 44 | m_TransparencySortAxis: {x: 0, y: 0, z: 1} 45 | m_DefaultRenderingPath: 1 46 | m_DefaultMobileRenderingPath: 1 47 | m_TierSettings: [] 48 | m_LightmapStripping: 0 49 | m_FogStripping: 0 50 | m_InstancingStripping: 0 51 | m_LightmapKeepPlain: 1 52 | m_LightmapKeepDirCombined: 1 53 | m_LightmapKeepDynamicPlain: 1 54 | m_LightmapKeepDynamicDirCombined: 1 55 | m_LightmapKeepShadowMask: 1 56 | m_LightmapKeepSubtractive: 1 57 | m_FogKeepLinear: 1 58 | m_FogKeepExp: 1 59 | m_FogKeepExp2: 1 60 | m_AlbedoSwatchInfos: [] 61 | m_LightsUseLinearIntensity: 0 62 | m_LightsUseColorTemperature: 0 63 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protobuf/Encoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace Pomelo.Protobuf 6 | { 7 | public class Encoder 8 | { 9 | 10 | //Encode the UInt32. 11 | public static byte[] encodeUInt32(string n) { 12 | return encodeUInt32(Convert.ToUInt32(n)); 13 | } 14 | 15 | /// 16 | /// Encode the UInt32. 17 | /// 18 | /// 19 | /// byte[] 20 | /// 21 | /// 22 | /// int 23 | /// 24 | public static byte [] encodeUInt32(uint n){ 25 | List byteList = new List(); 26 | do{ 27 | uint tmp = n % 128; 28 | uint next = n >> 7; 29 | if (next != 0) { 30 | tmp = tmp + 128; 31 | } 32 | byteList.Add(Convert.ToByte(tmp)); 33 | n = next; 34 | } while (n != 0); 35 | 36 | return byteList.ToArray(); 37 | } 38 | 39 | //Encode SInt32 40 | public static byte [] encodeSInt32(string n){ 41 | return encodeSInt32(Convert.ToInt32(n)); 42 | } 43 | 44 | /// 45 | /// Encodes the SInt32. 46 | /// 47 | /// 48 | /// byte [] 49 | /// 50 | /// 51 | /// int 52 | /// 53 | public static byte [] encodeSInt32(int n){ 54 | UInt32 num = (uint)(n < 0 ? (Math.Abs(n) * 2 - 1) : n * 2); 55 | return encodeUInt32(num); 56 | } 57 | 58 | /// 59 | /// Encodes the float. 60 | /// 61 | /// 62 | /// byte [] 63 | /// 64 | /// 65 | /// float. 66 | /// 67 | public static byte [] encodeFloat(float n){ 68 | byte[] bytes = BitConverter.GetBytes(n); 69 | if (!BitConverter.IsLittleEndian) { 70 | Util.Reverse(bytes); 71 | } 72 | return bytes; 73 | } 74 | 75 | //Get the byte length of message. 76 | public static int byteLength(string msg){ 77 | return System.Text.Encoding.UTF8.GetBytes(msg).Length; 78 | } 79 | 80 | 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protobuf/util/Util.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace Pomelo.Protobuf 6 | { 7 | public class Util 8 | { 9 | //Simple type 10 | private string[] types; 11 | private Dictionary typeMap; 12 | 13 | public Util() 14 | { 15 | this.initTypeMap(); 16 | this.types = new string[] { "uInt32", "sInt32", "int32", "uInt64", "sInt64", "float", "double" }; 17 | } 18 | 19 | /// 20 | /// Check out the given type. If it is simple, return ture. 21 | /// 22 | /// 23 | /// The simple type. 24 | /// 25 | /// 26 | /// If set to true type. 27 | /// 28 | public bool isSimpleType(string type){ 29 | int length = types.Length; 30 | bool flag = false; 31 | for( int i = 0; i < length; i++) { 32 | if (type == types[i]) { 33 | flag = true; 34 | break; 35 | } 36 | } 37 | return flag; 38 | } 39 | 40 | /// 41 | /// Check out the given type. If the type exist in typeMap, return true. 42 | /// 43 | /// 44 | /// The type. 45 | /// 46 | /// 47 | /// Type. 48 | /// 49 | public int containType(string type){ 50 | int value, returnInt = 2; 51 | if(this.typeMap.TryGetValue(type, out value)) { 52 | returnInt = value; 53 | } 54 | return returnInt; 55 | } 56 | 57 | //Init the typeMap 58 | private void initTypeMap(){ 59 | Dictionary dic = new Dictionary(); 60 | dic.Add("uInt32", 0); 61 | dic.Add("sInt32", 0); 62 | dic.Add("int32", 0); 63 | dic.Add("double", 1); 64 | dic.Add("string", 2); 65 | dic.Add("float", 5); 66 | dic.Add("message", 2); 67 | 68 | this.typeMap = dic; 69 | } 70 | 71 | /// 72 | /// Reverses the order of bytes in the array 73 | /// 74 | public static void Reverse(byte[] bytes) 75 | { 76 | byte temp; 77 | for (int first = 0, last = bytes.Length - 1; first < last; first++, last--) 78 | { 79 | temp = bytes[first]; 80 | bytes[first] = bytes[last]; 81 | bytes[last] = temp; 82 | } 83 | } 84 | } 85 | } 86 | 87 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/client/EventManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using LitJson; 5 | 6 | namespace Pomelo.DotNetClient 7 | { 8 | public class EventManager : IDisposable 9 | { 10 | private Dictionary> callBackMap; 11 | private Dictionary>> eventMap; 12 | 13 | public EventManager() 14 | { 15 | this.callBackMap = new Dictionary>(); 16 | this.eventMap = new Dictionary>>(); 17 | } 18 | 19 | //Adds callback to callBackMap by id. 20 | public void AddCallBack(uint id, Action callback) 21 | { 22 | if (id > 0 && callback != null) { 23 | this.callBackMap.Add(id, callback); 24 | } 25 | } 26 | 27 | /// 28 | /// Invoke the callback when the server return messge . 29 | /// 30 | /// 31 | /// Pomelo message. 32 | /// 33 | public void InvokeCallBack(uint id, JsonData data) 34 | { 35 | if (!callBackMap.ContainsKey(id)) return; 36 | callBackMap[id].Invoke(data); 37 | } 38 | 39 | //Adds the event to eventMap by name. 40 | public void AddOnEvent(string eventName, Action callback) 41 | { 42 | List> list = null; 43 | if (this.eventMap.TryGetValue(eventName, out list)) { 44 | list.Add(callback); 45 | } else { 46 | list = new List>(); 47 | list.Add(callback); 48 | this.eventMap.Add(eventName, list); 49 | } 50 | } 51 | 52 | /// 53 | /// If the event exists,invoke the event when server return messge. 54 | /// 55 | /// 56 | /// 57 | /// 58 | /// 59 | public void InvokeOnEvent (string route, JsonData msg) { 60 | if (!this.eventMap.ContainsKey(route)) return; 61 | 62 | List> list = eventMap[route]; 63 | foreach(Action action in list) action.Invoke(msg); 64 | } 65 | 66 | // Dispose() calls Dispose(true) 67 | public void Dispose() 68 | { 69 | Dispose(true); 70 | GC.SuppressFinalize(this); 71 | } 72 | 73 | // The bulk of the clean-up code is implemented in Dispose(bool) 74 | protected void Dispose(bool disposing) 75 | { 76 | this.callBackMap.Clear(); 77 | this.eventMap.Clear(); 78 | } 79 | } 80 | } 81 | 82 | -------------------------------------------------------------------------------- /Assets/chatofpomelo.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using Proto.chat; 4 | using Proto.connector; 5 | using System; 6 | using Proto; 7 | using Proto.gate; 8 | 9 | [RequireComponent(typeof(pomeloBehaviour))] 10 | public class chatofpomelo : MonoBehaviour 11 | { 12 | 13 | 14 | [TextArea(3, 10)] 15 | public string HandShakeCache; 16 | 17 | public string host = "127.0.0.1"; 18 | public int port = 3014; 19 | pomeloBehaviour client; 20 | public string uid = "1"; 21 | 22 | 23 | public Action connectToConnector; 24 | public Action disconnectConnector; 25 | public Action connectGateFailed; 26 | 27 | void Awake() 28 | { 29 | 30 | client = GetComponent(); 31 | client.updateClientEvent += OnUpdateClient; 32 | } 33 | // Use this for initialization 34 | 35 | 36 | public void ConnectToGate() 37 | { 38 | client.connectEvent += OnConnectToGate; 39 | client.closeEvent += OnGateServerDisconnect; 40 | client.ConnectServer(host, port, Pomelo.DotNetClient.ClientProtocolType.NORMAL, HandShakeCache); 41 | } 42 | 43 | public void OnConnectToConnector() 44 | { 45 | client.closeEvent += OnServerDisconnect; 46 | 47 | 48 | this.HandShakeCache = client.GetHandShakeCache(); 49 | 50 | if(connectToConnector != null) 51 | { 52 | connectToConnector.Invoke(); 53 | } 54 | 55 | 56 | Debug.Log("Connector Connected"); 57 | 58 | } 59 | public void OnConnectToGate() 60 | { 61 | this.HandShakeCache = client.GetHandShakeCache(); 62 | //gate logic can moveto logicclient 63 | gateHandler.queryEntry(uid, delegate (gateHandler.queryEntry_result result) 64 | { 65 | client.connectEvent -= OnConnectToGate; 66 | client.closeEvent -= OnGateServerDisconnect; 67 | 68 | client.CloseClient(); 69 | 70 | if (result.code == 500) 71 | { 72 | //TODO 73 | } 74 | 75 | if (result.code == 200) 76 | { 77 | client.connectEvent += OnConnectToConnector; 78 | client.ConnectServer(result.host, result.port, Pomelo.DotNetClient.ClientProtocolType.NORMAL, HandShakeCache); 79 | } 80 | 81 | //TODO other event 82 | }); 83 | Debug.Log("Gate Connected"); 84 | } 85 | 86 | 87 | private void OnUpdateClient() 88 | { 89 | Proto.Version.resetClient(client.pc); 90 | } 91 | 92 | private void OnServerDisconnect() 93 | { 94 | client.connectEvent -= OnConnectToConnector; 95 | client.closeEvent -= OnServerDisconnect; 96 | 97 | if (disconnectConnector != null) disconnectConnector.Invoke(); 98 | 99 | } 100 | 101 | private void OnGateServerDisconnect() 102 | { 103 | client.connectEvent -= OnConnectToGate; 104 | client.closeEvent -= OnGateServerDisconnect; 105 | 106 | if (connectGateFailed != null) connectGateFailed.Invoke(); 107 | 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomeloBehaviour.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | using Pomelo.DotNetClient; 5 | using LitJson; 6 | using System; 7 | using System.Threading; 8 | using System.Collections.Generic; 9 | using System.IO; 10 | 11 | using Proto; 12 | using Proto.gate; 13 | using Proto.connector; 14 | using Proto.chat; 15 | 16 | 17 | public class pomeloBehaviour : MonoBehaviour 18 | { 19 | 20 | [HideInInspector] 21 | public PomeloClient pc; 22 | 23 | public event Action connectEvent; 24 | public event Action closeEvent; 25 | public event Action updateClientEvent; 26 | 27 | // Use this for initialization 28 | void Start() 29 | { 30 | 31 | } 32 | 33 | [ExecuteInEditMode] 34 | void OnDestroy() 35 | { 36 | CloseClient(); 37 | } 38 | 39 | // Update is called once per frame 40 | void Update() 41 | { 42 | if (pc != null) 43 | { 44 | pc.poll(); 45 | } 46 | } 47 | 48 | public void CloseClient() 49 | { 50 | if (pc != null) 51 | { 52 | pc.close(); 53 | //pc.poll(); 54 | if (this.closeEvent != null) 55 | { 56 | this.closeEvent(); 57 | } 58 | pc = null; 59 | 60 | this.UpdateClient(); 61 | } 62 | } 63 | 64 | public string GetHandShakeCache() 65 | { 66 | if(pc != null) 67 | { 68 | return pc.HandShakeCache; 69 | } 70 | return ""; 71 | } 72 | 73 | //TODO TLS "C7773B9D1BF0C5C956C88C60440FA23C3889A403" 74 | public bool ConnectServer(string host, int port, 75 | ClientProtocolType eProtoType = ClientProtocolType.NORMAL, 76 | string HandShakeCache = "", 77 | byte[] clientcert = null, string clientpwd = "", string cathumbprint = null) 78 | { 79 | //if (eProtoType == ClientProtocolType.TLS) 80 | //{ 81 | // if (clientcert == null || cathumbprint == null) 82 | // { 83 | // return false; 84 | // } 85 | //} 86 | 87 | //this.CloseClient(); 88 | pc = new PomeloClient(eProtoType, clientcert, "", cathumbprint); 89 | pc.Connect(host, port, HandShakeCache, delegate () 90 | { 91 | if (pc.IsConnected) 92 | { 93 | this.UpdateClient(); 94 | pc.HandShake(null, delegate (JsonData data) 95 | { 96 | if (this.connectEvent != null) 97 | { 98 | this.connectEvent(); 99 | } 100 | }); 101 | } 102 | }, 103 | delegate () 104 | { 105 | if (this.closeEvent != null) 106 | { 107 | this.closeEvent(); 108 | } 109 | 110 | } 111 | ); 112 | 113 | return true; 114 | } 115 | 116 | 117 | private void UpdateClient() 118 | { 119 | if (this.updateClientEvent != null) 120 | { 121 | this.updateClientEvent(); 122 | } 123 | } 124 | 125 | 126 | } 127 | -------------------------------------------------------------------------------- /Assets/logicclient.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using Proto; 4 | using Proto.connector; 5 | using Proto.chat; 6 | using System; 7 | 8 | public class logicclient : MonoBehaviour 9 | { 10 | public UnityEngine.UI.Text text; 11 | public UnityEngine.UI.InputField input; 12 | public UnityEngine.UI.Button loginBtn; 13 | public UnityEngine.UI.Button sendBtn; 14 | 15 | public string uid; 16 | 17 | string user; 18 | 19 | 20 | chatofpomelo baseClient; 21 | void Awake() 22 | { 23 | baseClient = GetComponent(); 24 | baseClient.connectToConnector += onConnectToConnector; 25 | baseClient.disconnectConnector += onDisconnectConnector; 26 | baseClient.connectGateFailed += onConnectGateFailed; 27 | } 28 | 29 | // Use this for initialization 30 | void Start() 31 | { 32 | if (sendBtn) { sendBtn.interactable = true; } 33 | baseClient.uid = uid; 34 | baseClient.ConnectToGate(); 35 | } 36 | 37 | 38 | public void send() 39 | { 40 | this.send(input.text); 41 | } 42 | 43 | public void send(string message) 44 | { 45 | chatHandler.send( 46 | "pomelo", 47 | message, 48 | user, 49 | "*" 50 | ); 51 | } 52 | 53 | public void login() 54 | { 55 | user = "pomelo" + DateTime.Now.Millisecond; 56 | 57 | entryHandler.enter(user, "pomelo", delegate (entryHandler.enter_result result) 58 | { 59 | if (sendBtn) { sendBtn.interactable = true; } 60 | }); 61 | } 62 | 63 | void onConnectToConnector() 64 | { 65 | ServerEvent.onChat(delegate (ServerEvent.onChat_event ret) 66 | { 67 | string strMsg = string.Format("{0} : {1}.", ret.from, ret.msg); 68 | if (text) 69 | { 70 | text.text = text.text.Insert(text.text.Length, strMsg); 71 | text.text = text.text.Insert(text.text.Length, "\n"); 72 | } 73 | }); 74 | 75 | ServerEvent.onAdd(delegate (ServerEvent.onAdd_event msg) 76 | { 77 | string strMsg = string.Format("{0} Joined.", msg.user); 78 | if (text) 79 | { 80 | text.text = text.text.Insert(text.text.Length, strMsg); 81 | text.text = text.text.Insert(text.text.Length, "\n"); 82 | } 83 | }); 84 | 85 | ServerEvent.onLeave(delegate (ServerEvent.onLeave_event msg) 86 | { 87 | string strMsg = string.Format("{0} Leaved.", msg.user); 88 | if (text) 89 | { 90 | text.text = text.text.Insert(text.text.Length, strMsg); 91 | text.text = text.text.Insert(text.text.Length, "\n"); 92 | } 93 | }); 94 | 95 | 96 | login(); 97 | } 98 | 99 | void onDisconnectConnector() 100 | { 101 | if (loginBtn) { loginBtn.gameObject.SetActive(true); } 102 | if (sendBtn) { sendBtn.interactable = false; } 103 | } 104 | 105 | void onConnectGateFailed() 106 | { 107 | if (loginBtn) { loginBtn.gameObject.SetActive(true); } 108 | if (sendBtn) { sendBtn.interactable = false; } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/LitJson/JsonMockWrapper.cs: -------------------------------------------------------------------------------- 1 | #region Header 2 | /** 3 | * JsonMockWrapper.cs 4 | * Mock object implementing IJsonWrapper, to facilitate actions like 5 | * skipping data more efficiently. 6 | * 7 | * The authors disclaim copyright to this source code. For more details, see 8 | * the COPYING file included with this distribution. 9 | **/ 10 | #endregion 11 | 12 | 13 | using System; 14 | using System.Collections; 15 | using System.Collections.Specialized; 16 | 17 | 18 | namespace LitJson 19 | { 20 | public class JsonMockWrapper : IJsonWrapper 21 | { 22 | public bool IsArray { get { return false; } } 23 | public bool IsBoolean { get { return false; } } 24 | public bool IsDouble { get { return false; } } 25 | public bool IsInt { get { return false; } } 26 | public bool IsLong { get { return false; } } 27 | public bool IsObject { get { return false; } } 28 | public bool IsString { get { return false; } } 29 | public bool IsFloat { get { return false; } } 30 | 31 | public bool GetBoolean () { return false; } 32 | public double GetDouble () { return 0.0; } 33 | public float GetFloat() { return 0.0f; } 34 | public int GetInt () { return 0; } 35 | public JsonType GetJsonType () { return JsonType.None; } 36 | public long GetLong () { return 0L; } 37 | public string GetString () { return ""; } 38 | 39 | public void SetBoolean (bool val) {} 40 | public void SetDouble (double val) {} 41 | public void SetFloat (float val) {} 42 | public void SetInt (int val) {} 43 | public void SetJsonType (JsonType type) {} 44 | public void SetLong (long val) {} 45 | public void SetString (string val) {} 46 | 47 | public string ToJson () { return ""; } 48 | public void ToJson (JsonWriter writer) {} 49 | 50 | 51 | bool IList.IsFixedSize { get { return true; } } 52 | bool IList.IsReadOnly { get { return true; } } 53 | 54 | object IList.this[int index] { 55 | get { return null; } 56 | set {} 57 | } 58 | 59 | int IList.Add (object value) { return 0; } 60 | void IList.Clear () {} 61 | bool IList.Contains (object value) { return false; } 62 | int IList.IndexOf (object value) { return -1; } 63 | void IList.Insert (int i, object v) {} 64 | void IList.Remove (object value) {} 65 | void IList.RemoveAt (int index) {} 66 | 67 | 68 | int ICollection.Count { get { return 0; } } 69 | bool ICollection.IsSynchronized { get { return false; } } 70 | object ICollection.SyncRoot { get { return null; } } 71 | 72 | void ICollection.CopyTo (Array array, int index) {} 73 | 74 | 75 | IEnumerator IEnumerable.GetEnumerator () { return null; } 76 | 77 | 78 | bool IDictionary.IsFixedSize { get { return true; } } 79 | bool IDictionary.IsReadOnly { get { return true; } } 80 | 81 | ICollection IDictionary.Keys { get { return null; } } 82 | ICollection IDictionary.Values { get { return null; } } 83 | 84 | object IDictionary.this[object key] { 85 | get { return null; } 86 | set {} 87 | } 88 | 89 | void IDictionary.Add (object k, object v) {} 90 | void IDictionary.Clear () {} 91 | bool IDictionary.Contains (object key) { return false; } 92 | void IDictionary.Remove (object key) {} 93 | 94 | IDictionaryEnumerator IDictionary.GetEnumerator () { return null; } 95 | 96 | 97 | object IOrderedDictionary.this[int idx] { 98 | get { return null; } 99 | set {} 100 | } 101 | 102 | IDictionaryEnumerator IOrderedDictionary.GetEnumerator () { 103 | return null; 104 | } 105 | void IOrderedDictionary.Insert (int i, object k, object v) {} 106 | void IOrderedDictionary.RemoveAt (int i) {} 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!47 &1 4 | QualitySettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 5 7 | m_CurrentQuality: 3 8 | m_QualitySettings: 9 | - serializedVersion: 2 10 | name: Fastest 11 | pixelLightCount: 0 12 | shadows: 0 13 | shadowResolution: 0 14 | shadowProjection: 1 15 | shadowCascades: 1 16 | shadowDistance: 15 17 | shadowNearPlaneOffset: 2 18 | shadowCascade2Split: 0.33333334 19 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 20 | blendWeights: 1 21 | textureQuality: 1 22 | anisotropicTextures: 0 23 | antiAliasing: 0 24 | softParticles: 0 25 | softVegetation: 0 26 | realtimeReflectionProbes: 0 27 | billboardsFaceCameraPosition: 0 28 | vSyncCount: 0 29 | lodBias: 0.3 30 | maximumLODLevel: 0 31 | particleRaycastBudget: 4 32 | asyncUploadTimeSlice: 2 33 | asyncUploadBufferSize: 4 34 | excludedTargetPlatforms: [] 35 | - serializedVersion: 2 36 | name: Fast 37 | pixelLightCount: 0 38 | shadows: 0 39 | shadowResolution: 0 40 | shadowProjection: 1 41 | shadowCascades: 1 42 | shadowDistance: 20 43 | shadowNearPlaneOffset: 2 44 | shadowCascade2Split: 0.33333334 45 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 46 | blendWeights: 2 47 | textureQuality: 0 48 | anisotropicTextures: 0 49 | antiAliasing: 0 50 | softParticles: 0 51 | softVegetation: 0 52 | realtimeReflectionProbes: 0 53 | billboardsFaceCameraPosition: 0 54 | vSyncCount: 0 55 | lodBias: 0.4 56 | maximumLODLevel: 0 57 | particleRaycastBudget: 16 58 | asyncUploadTimeSlice: 2 59 | asyncUploadBufferSize: 4 60 | excludedTargetPlatforms: [] 61 | - serializedVersion: 2 62 | name: Simple 63 | pixelLightCount: 1 64 | shadows: 1 65 | shadowResolution: 0 66 | shadowProjection: 1 67 | shadowCascades: 1 68 | shadowDistance: 20 69 | shadowNearPlaneOffset: 2 70 | shadowCascade2Split: 0.33333334 71 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 72 | blendWeights: 2 73 | textureQuality: 0 74 | anisotropicTextures: 1 75 | antiAliasing: 0 76 | softParticles: 0 77 | softVegetation: 0 78 | realtimeReflectionProbes: 0 79 | billboardsFaceCameraPosition: 0 80 | vSyncCount: 0 81 | lodBias: 0.7 82 | maximumLODLevel: 0 83 | particleRaycastBudget: 64 84 | asyncUploadTimeSlice: 2 85 | asyncUploadBufferSize: 4 86 | excludedTargetPlatforms: [] 87 | - serializedVersion: 2 88 | name: Good 89 | pixelLightCount: 2 90 | shadows: 2 91 | shadowResolution: 1 92 | shadowProjection: 1 93 | shadowCascades: 2 94 | shadowDistance: 40 95 | shadowNearPlaneOffset: 2 96 | shadowCascade2Split: 0.33333334 97 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 98 | blendWeights: 2 99 | textureQuality: 0 100 | anisotropicTextures: 1 101 | antiAliasing: 0 102 | softParticles: 0 103 | softVegetation: 1 104 | realtimeReflectionProbes: 1 105 | billboardsFaceCameraPosition: 1 106 | vSyncCount: 1 107 | lodBias: 1 108 | maximumLODLevel: 0 109 | particleRaycastBudget: 256 110 | asyncUploadTimeSlice: 2 111 | asyncUploadBufferSize: 4 112 | excludedTargetPlatforms: [] 113 | - serializedVersion: 2 114 | name: Beautiful 115 | pixelLightCount: 3 116 | shadows: 2 117 | shadowResolution: 2 118 | shadowProjection: 1 119 | shadowCascades: 2 120 | shadowDistance: 70 121 | shadowNearPlaneOffset: 2 122 | shadowCascade2Split: 0.33333334 123 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 124 | blendWeights: 4 125 | textureQuality: 0 126 | anisotropicTextures: 2 127 | antiAliasing: 2 128 | softParticles: 1 129 | softVegetation: 1 130 | realtimeReflectionProbes: 1 131 | billboardsFaceCameraPosition: 1 132 | vSyncCount: 1 133 | lodBias: 1.5 134 | maximumLODLevel: 0 135 | particleRaycastBudget: 1024 136 | asyncUploadTimeSlice: 2 137 | asyncUploadBufferSize: 4 138 | excludedTargetPlatforms: [] 139 | - serializedVersion: 2 140 | name: Fantastic 141 | pixelLightCount: 4 142 | shadows: 2 143 | shadowResolution: 2 144 | shadowProjection: 1 145 | shadowCascades: 4 146 | shadowDistance: 150 147 | shadowNearPlaneOffset: 2 148 | shadowCascade2Split: 0.33333334 149 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 150 | blendWeights: 4 151 | textureQuality: 0 152 | anisotropicTextures: 2 153 | antiAliasing: 2 154 | softParticles: 1 155 | softVegetation: 1 156 | realtimeReflectionProbes: 1 157 | billboardsFaceCameraPosition: 1 158 | vSyncCount: 1 159 | lodBias: 2 160 | maximumLODLevel: 0 161 | particleRaycastBudget: 4096 162 | asyncUploadTimeSlice: 2 163 | asyncUploadBufferSize: 4 164 | excludedTargetPlatforms: [] 165 | m_PerPlatformDefaultQuality: {} 166 | -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!13 &1 4 | InputManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Axes: 8 | - serializedVersion: 3 9 | m_Name: Horizontal 10 | descriptiveName: 11 | descriptiveNegativeName: 12 | negativeButton: left 13 | positiveButton: right 14 | altNegativeButton: a 15 | altPositiveButton: d 16 | gravity: 3 17 | dead: 0.001 18 | sensitivity: 3 19 | snap: 1 20 | invert: 0 21 | type: 0 22 | axis: 0 23 | joyNum: 0 24 | - serializedVersion: 3 25 | m_Name: Vertical 26 | descriptiveName: 27 | descriptiveNegativeName: 28 | negativeButton: down 29 | positiveButton: up 30 | altNegativeButton: s 31 | altPositiveButton: w 32 | gravity: 3 33 | dead: 0.001 34 | sensitivity: 3 35 | snap: 1 36 | invert: 0 37 | type: 0 38 | axis: 0 39 | joyNum: 0 40 | - serializedVersion: 3 41 | m_Name: Fire1 42 | descriptiveName: 43 | descriptiveNegativeName: 44 | negativeButton: 45 | positiveButton: left ctrl 46 | altNegativeButton: 47 | altPositiveButton: mouse 0 48 | gravity: 1000 49 | dead: 0.001 50 | sensitivity: 1000 51 | snap: 0 52 | invert: 0 53 | type: 0 54 | axis: 0 55 | joyNum: 0 56 | - serializedVersion: 3 57 | m_Name: Fire2 58 | descriptiveName: 59 | descriptiveNegativeName: 60 | negativeButton: 61 | positiveButton: left alt 62 | altNegativeButton: 63 | altPositiveButton: mouse 1 64 | gravity: 1000 65 | dead: 0.001 66 | sensitivity: 1000 67 | snap: 0 68 | invert: 0 69 | type: 0 70 | axis: 0 71 | joyNum: 0 72 | - serializedVersion: 3 73 | m_Name: Fire3 74 | descriptiveName: 75 | descriptiveNegativeName: 76 | negativeButton: 77 | positiveButton: left cmd 78 | altNegativeButton: 79 | altPositiveButton: mouse 2 80 | gravity: 1000 81 | dead: 0.001 82 | sensitivity: 1000 83 | snap: 0 84 | invert: 0 85 | type: 0 86 | axis: 0 87 | joyNum: 0 88 | - serializedVersion: 3 89 | m_Name: Jump 90 | descriptiveName: 91 | descriptiveNegativeName: 92 | negativeButton: 93 | positiveButton: space 94 | altNegativeButton: 95 | altPositiveButton: 96 | gravity: 1000 97 | dead: 0.001 98 | sensitivity: 1000 99 | snap: 0 100 | invert: 0 101 | type: 0 102 | axis: 0 103 | joyNum: 0 104 | - serializedVersion: 3 105 | m_Name: Mouse X 106 | descriptiveName: 107 | descriptiveNegativeName: 108 | negativeButton: 109 | positiveButton: 110 | altNegativeButton: 111 | altPositiveButton: 112 | gravity: 0 113 | dead: 0 114 | sensitivity: 0.1 115 | snap: 0 116 | invert: 0 117 | type: 1 118 | axis: 0 119 | joyNum: 0 120 | - serializedVersion: 3 121 | m_Name: Mouse Y 122 | descriptiveName: 123 | descriptiveNegativeName: 124 | negativeButton: 125 | positiveButton: 126 | altNegativeButton: 127 | altPositiveButton: 128 | gravity: 0 129 | dead: 0 130 | sensitivity: 0.1 131 | snap: 0 132 | invert: 0 133 | type: 1 134 | axis: 1 135 | joyNum: 0 136 | - serializedVersion: 3 137 | m_Name: Mouse ScrollWheel 138 | descriptiveName: 139 | descriptiveNegativeName: 140 | negativeButton: 141 | positiveButton: 142 | altNegativeButton: 143 | altPositiveButton: 144 | gravity: 0 145 | dead: 0 146 | sensitivity: 0.1 147 | snap: 0 148 | invert: 0 149 | type: 1 150 | axis: 2 151 | joyNum: 0 152 | - serializedVersion: 3 153 | m_Name: Horizontal 154 | descriptiveName: 155 | descriptiveNegativeName: 156 | negativeButton: 157 | positiveButton: 158 | altNegativeButton: 159 | altPositiveButton: 160 | gravity: 0 161 | dead: 0.19 162 | sensitivity: 1 163 | snap: 0 164 | invert: 0 165 | type: 2 166 | axis: 0 167 | joyNum: 0 168 | - serializedVersion: 3 169 | m_Name: Vertical 170 | descriptiveName: 171 | descriptiveNegativeName: 172 | negativeButton: 173 | positiveButton: 174 | altNegativeButton: 175 | altPositiveButton: 176 | gravity: 0 177 | dead: 0.19 178 | sensitivity: 1 179 | snap: 0 180 | invert: 1 181 | type: 2 182 | axis: 1 183 | joyNum: 0 184 | - serializedVersion: 3 185 | m_Name: Fire1 186 | descriptiveName: 187 | descriptiveNegativeName: 188 | negativeButton: 189 | positiveButton: joystick button 0 190 | altNegativeButton: 191 | altPositiveButton: 192 | gravity: 1000 193 | dead: 0.001 194 | sensitivity: 1000 195 | snap: 0 196 | invert: 0 197 | type: 0 198 | axis: 0 199 | joyNum: 0 200 | - serializedVersion: 3 201 | m_Name: Fire2 202 | descriptiveName: 203 | descriptiveNegativeName: 204 | negativeButton: 205 | positiveButton: joystick button 1 206 | altNegativeButton: 207 | altPositiveButton: 208 | gravity: 1000 209 | dead: 0.001 210 | sensitivity: 1000 211 | snap: 0 212 | invert: 0 213 | type: 0 214 | axis: 0 215 | joyNum: 0 216 | - serializedVersion: 3 217 | m_Name: Fire3 218 | descriptiveName: 219 | descriptiveNegativeName: 220 | negativeButton: 221 | positiveButton: joystick button 2 222 | altNegativeButton: 223 | altPositiveButton: 224 | gravity: 1000 225 | dead: 0.001 226 | sensitivity: 1000 227 | snap: 0 228 | invert: 0 229 | type: 0 230 | axis: 0 231 | joyNum: 0 232 | - serializedVersion: 3 233 | m_Name: Jump 234 | descriptiveName: 235 | descriptiveNegativeName: 236 | negativeButton: 237 | positiveButton: joystick button 3 238 | altNegativeButton: 239 | altPositiveButton: 240 | gravity: 1000 241 | dead: 0.001 242 | sensitivity: 1000 243 | snap: 0 244 | invert: 0 245 | type: 0 246 | axis: 0 247 | joyNum: 0 248 | - serializedVersion: 3 249 | m_Name: Submit 250 | descriptiveName: 251 | descriptiveNegativeName: 252 | negativeButton: 253 | positiveButton: return 254 | altNegativeButton: 255 | altPositiveButton: joystick button 0 256 | gravity: 1000 257 | dead: 0.001 258 | sensitivity: 1000 259 | snap: 0 260 | invert: 0 261 | type: 0 262 | axis: 0 263 | joyNum: 0 264 | - serializedVersion: 3 265 | m_Name: Submit 266 | descriptiveName: 267 | descriptiveNegativeName: 268 | negativeButton: 269 | positiveButton: enter 270 | altNegativeButton: 271 | altPositiveButton: space 272 | gravity: 1000 273 | dead: 0.001 274 | sensitivity: 1000 275 | snap: 0 276 | invert: 0 277 | type: 0 278 | axis: 0 279 | joyNum: 0 280 | - serializedVersion: 3 281 | m_Name: Cancel 282 | descriptiveName: 283 | descriptiveNegativeName: 284 | negativeButton: 285 | positiveButton: escape 286 | altNegativeButton: 287 | altPositiveButton: joystick button 1 288 | gravity: 1000 289 | dead: 0.001 290 | sensitivity: 1000 291 | snap: 0 292 | invert: 0 293 | type: 0 294 | axis: 0 295 | joyNum: 0 296 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/MessageProtocol.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Collections.Generic; 4 | using LitJson; 5 | using Pomelo.Protobuf; 6 | using UnityEngine; 7 | 8 | namespace Pomelo.DotNetClient 9 | { 10 | public class MessageProtocol 11 | { 12 | public Dictionary dict = new Dictionary(); 13 | public Dictionary abbrs = new Dictionary(); 14 | public JsonData encodeProtos = new JsonData(); 15 | public JsonData decodeProtos = new JsonData(); 16 | private Dictionary reqMap; 17 | private Protobuf.Protobuf protobuf; 18 | public string protoVersion = ""; 19 | public string dictVersion = ""; 20 | 21 | public const int MSG_Route_Limit = 255; 22 | public const int MSG_Route_Mask = 0x01; 23 | public const int MSG_Type_Mask = 0x07; 24 | 25 | public MessageProtocol(JsonData dict, JsonData serverProtos, JsonData clientProtos, string dictVersion, string protoVersion) 26 | { 27 | ICollection keys = dict.Keys; 28 | 29 | foreach(string key in keys){ 30 | ushort value = Convert.ToUInt16(dict[key].ToString()); 31 | this.dict[key] = value; 32 | this.abbrs[value] = key; 33 | } 34 | 35 | protobuf = new Protobuf.Protobuf(clientProtos, serverProtos); 36 | this.encodeProtos = clientProtos; 37 | this.decodeProtos = serverProtos; 38 | 39 | this.protoVersion = protoVersion; 40 | this.dictVersion = dictVersion; 41 | 42 | this.reqMap = new Dictionary(); 43 | } 44 | 45 | public byte[] encode(string route, JsonData msg){ 46 | return encode(route, 0, msg); 47 | } 48 | 49 | public byte[] encode(string route, uint id, JsonData msg){ 50 | int routeLength = byteLength(route); 51 | if (routeLength > MSG_Route_Limit) { 52 | throw new Exception("Route is too long!"); 53 | } 54 | 55 | //Encode head 56 | //The maximus length of head is 1 byte flag + 4 bytes message id + route string length + 1byte 57 | byte[] head = new byte[routeLength + 6]; 58 | int offset = 1; 59 | byte flag = 0; 60 | 61 | if (id > 0) { 62 | byte[] bytes = Protobuf.Encoder.encodeUInt32(id); 63 | 64 | writeBytes(bytes, offset, head); 65 | flag |= ((byte)MessageType.MSG_REQUEST) << 1; 66 | offset += bytes.Length; 67 | } else { 68 | flag |= ((byte)MessageType.MSG_NOTIFY) << 1; 69 | } 70 | 71 | //Compress head 72 | if (dict.ContainsKey(route)) { 73 | ushort cmpRoute = dict[route]; 74 | writeShort(offset, cmpRoute, head); 75 | flag |= MSG_Route_Mask; 76 | offset += 2; 77 | } else { 78 | //Write route length 79 | head[offset++] = (byte)routeLength; 80 | 81 | //Write route 82 | writeBytes(Encoding.UTF8.GetBytes(route), offset, head); 83 | offset += routeLength; 84 | } 85 | 86 | head[0] = flag; 87 | 88 | //Encode body 89 | byte[] body; 90 | if (encodeProtos.ContainsKey (route)) { 91 | body = protobuf.encode(route, msg); 92 | } else { 93 | body = Encoding.UTF8.GetBytes(JsonMapper.ToJson(msg)); 94 | } 95 | 96 | //Construct the result 97 | byte[] result = new byte[offset + body.Length]; 98 | for (int i = 0; i < offset; i++) { 99 | result[i] = head[i]; 100 | } 101 | 102 | for (int i = 0; i < body.Length; i++) { 103 | result[offset + i] = body[i]; 104 | } 105 | 106 | //Add id to route map 107 | if (id > 0) reqMap.Add(id, route); 108 | 109 | return result; 110 | } 111 | 112 | public Message decode(byte[] buffer){ 113 | //Decode head 114 | //Get flag 115 | byte flag = buffer[0]; 116 | //Set offset to 1, for the 1st byte will always be the flag 117 | int offset = 1; 118 | 119 | //Get type from flag; 120 | MessageType type = (MessageType)((flag >> 1) & MSG_Type_Mask); 121 | uint id = 0; 122 | string route; 123 | 124 | if (type == MessageType.MSG_RESPONSE) { 125 | int length; 126 | id = (uint)Protobuf.Decoder.decodeUInt32(offset, buffer, out length); 127 | if(id <= 0 || !reqMap.ContainsKey(id)){ 128 | return null; 129 | }else{ 130 | route = reqMap[id]; 131 | reqMap.Remove(id); 132 | } 133 | 134 | offset += length; 135 | } else if (type == MessageType.MSG_PUSH) { 136 | //Get route 137 | if((flag & 0x01) == 1){ 138 | ushort routeId = readShort(offset, buffer); 139 | if(!abbrs.ContainsKey(routeId)) 140 | { 141 | offset += 2; 142 | Debug.LogError("error route id " + routeId); 143 | return null; 144 | //throw new System.Exception("error router id " + routeId); 145 | } 146 | route = abbrs[routeId]; 147 | 148 | offset += 2; 149 | }else{ 150 | byte length = buffer[offset]; 151 | offset += 1; 152 | 153 | route = Encoding.UTF8.GetString(buffer, offset, length); 154 | offset += length; 155 | } 156 | } else { 157 | return null; 158 | } 159 | 160 | //Decode body 161 | byte[] body = new byte[buffer.Length - offset]; 162 | for (int i = 0; i < body.Length; i++) { 163 | body[i] = buffer[i + offset]; 164 | } 165 | 166 | JsonData msg; 167 | if (decodeProtos.ContainsKey(route)) { 168 | msg = protobuf.decode(route, body); 169 | } else { 170 | msg = LitJson.JsonMapper.ToObject(Encoding.UTF8.GetString(body)); 171 | //msg = (JsonData)SimpleJson.SimpleJson.DeserializeObject(Encoding.UTF8.GetString(body)); 172 | } 173 | 174 | //Construct the message 175 | return new Message(type, id, route, msg); 176 | } 177 | 178 | private void writeInt(int offset, uint value, byte[] bytes){ 179 | bytes[offset] = (byte)(value >> 24 & 0xff); 180 | bytes[offset + 1] = (byte)(value >> 16 & 0xff); 181 | bytes[offset + 2] = (byte)(value >> 8 & 0xff); 182 | bytes[offset + 3] = (byte)(value & 0xff); 183 | } 184 | 185 | private void writeShort(int offset, ushort value, byte[] bytes){ 186 | bytes[offset] = (byte)(value >> 8 & 0xff); 187 | bytes[offset + 1] = (byte)(value & 0xff); 188 | } 189 | 190 | private ushort readShort(int offset, byte[] bytes){ 191 | ushort result = 0; 192 | 193 | result += (ushort)(bytes[offset] << 8); 194 | result += (ushort)(bytes[offset + 1]); 195 | 196 | return result; 197 | } 198 | 199 | private int byteLength(string msg){ 200 | return Encoding.UTF8.GetBytes(msg).Length; 201 | } 202 | 203 | private void writeBytes(byte [] source, int offset, byte [] target){ 204 | for(int i = 0; i < source.Length; i++){ 205 | target[offset + i] = source[i]; 206 | } 207 | } 208 | } 209 | } 210 | 211 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/clientProtos.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using LitJson; 3 | using Pomelo.DotNetClient; 4 | namespace Proto 5 | { 6 | public static class Version 7 | { 8 | public static void resetClient(PomeloClient pc) 9 | { 10 | gate.gateHandler.pc = pc; 11 | connector.entryHandler.pc = pc; 12 | chat.chatHandler.pc = pc; 13 | ServerEvent.pc = pc; 14 | } 15 | } 16 | namespace chat 17 | { 18 | public class chatHandler 19 | { 20 | public static PomeloClient pc = null; 21 | public static bool send(string rid,string content,string from,string target) 22 | { 23 | JsonData data = new JsonData(); 24 | data["rid"] = rid; 25 | data["content"] = content; 26 | data["from"] = from; 27 | data["target"] = target; 28 | pc.notify("chat.chatHandler.send", data); 29 | return true; 30 | } 31 | } 32 | } 33 | namespace connector 34 | { 35 | public class entryHandler 36 | { 37 | public static PomeloClient pc = null; 38 | public class enter_result 39 | { 40 | public string[] users; 41 | public JsonData ToJson() 42 | { 43 | JsonData data = new JsonData(); 44 | for(int i=0; 45 | i 0) 55 | { 56 | this.users = new string[ret["users"].Count]; 57 | for(int i=0; 58 | i cb) 67 | { 68 | JsonData data = new JsonData(); 69 | data["username"] = username; 70 | data["rid"] = rid; 71 | pc.request("connector.entryHandler.enter", data, delegate (JsonData ret) 72 | { 73 | enter_result result = new enter_result(); 74 | if(ret.ContainsKey("users") && ret["users"].IsArray && ret["users"].Count > 0) 75 | { 76 | result.users = new string[ret["users"].Count]; 77 | for(int i=0; 78 | i cb) 117 | { 118 | JsonData data = new JsonData(); 119 | data["uid"] = uid; 120 | pc.request("gate.gateHandler.queryEntry", data, delegate (JsonData ret) 121 | { 122 | queryEntry_result result = new queryEntry_result(); 123 | result.code= ret.ContainsKey("code")?(int)ret["code"]:0; 124 | result.host= ret.ContainsKey("host")?(string)ret["host"]:""; 125 | result.port= ret.ContainsKey("port")?(int)ret["port"]:0; 126 | cb(result); 127 | } 128 | ); 129 | return true; 130 | } 131 | } 132 | } 133 | public class ServerEvent 134 | { 135 | public static PomeloClient pc = null; 136 | public class onAdd_event 137 | { 138 | public string user; 139 | public JsonData ToJson() 140 | { 141 | JsonData data = new JsonData(); 142 | data["user"] = user; 143 | return data; 144 | } 145 | public void FromJson(JsonData ret) 146 | { 147 | this.user= ret.ContainsKey("user")?(string)ret["user"]:""; 148 | } 149 | } 150 | public static bool onAdd(System.Action cb) 151 | { 152 | pc.on("onAdd", delegate (JsonData ret) 153 | { 154 | onAdd_event result = new onAdd_event(); 155 | if(ret.ContainsKey("user")) 156 | { 157 | result.user = (string)ret["user"]; 158 | } 159 | cb(result); 160 | } 161 | ); 162 | return true; 163 | } 164 | public class onChat_event 165 | { 166 | public string msg; 167 | public string from; 168 | public string target; 169 | public JsonData ToJson() 170 | { 171 | JsonData data = new JsonData(); 172 | data["msg"] = msg; 173 | data["from"] = from; 174 | data["target"] = target; 175 | return data; 176 | } 177 | public void FromJson(JsonData ret) 178 | { 179 | this.msg= ret.ContainsKey("msg")?(string)ret["msg"]:""; 180 | this.from= ret.ContainsKey("from")?(string)ret["from"]:""; 181 | this.target= ret.ContainsKey("target")?(string)ret["target"]:""; 182 | } 183 | } 184 | public static bool onChat(System.Action cb) 185 | { 186 | pc.on("onChat", delegate (JsonData ret) 187 | { 188 | onChat_event result = new onChat_event(); 189 | if(ret.ContainsKey("msg")) 190 | { 191 | result.msg = (string)ret["msg"]; 192 | } 193 | if(ret.ContainsKey("from")) 194 | { 195 | result.from = (string)ret["from"]; 196 | } 197 | if(ret.ContainsKey("target")) 198 | { 199 | result.target = (string)ret["target"]; 200 | } 201 | cb(result); 202 | } 203 | ); 204 | return true; 205 | } 206 | public class onLeave_event 207 | { 208 | public string user; 209 | public JsonData ToJson() 210 | { 211 | JsonData data = new JsonData(); 212 | data["user"] = user; 213 | return data; 214 | } 215 | public void FromJson(JsonData ret) 216 | { 217 | this.user= ret.ContainsKey("user")?(string)ret["user"]:""; 218 | } 219 | } 220 | public static bool onLeave(System.Action cb) 221 | { 222 | pc.on("onLeave", delegate (JsonData ret) 223 | { 224 | onLeave_event result = new onLeave_event(); 225 | if(ret.ContainsKey("user")) 226 | { 227 | result.user = (string)ret["user"]; 228 | } 229 | cb(result); 230 | } 231 | ); 232 | return true; 233 | } 234 | } 235 | } 236 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/client/PomeloClient.cs: -------------------------------------------------------------------------------- 1 | using LitJson; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Net.Sockets; 8 | using System.Text; 9 | using System.Threading; 10 | using UnityEngine; 11 | 12 | namespace Pomelo.DotNetClient 13 | { 14 | public enum NetWorkState 15 | { 16 | [Description("initial state")] 17 | CLOSED, 18 | 19 | [Description("connecting server")] 20 | CONNECTING, 21 | 22 | [Description("server connected")] 23 | CONNECTED, 24 | 25 | [Description("disconnected with server")] 26 | DISCONNECTED, 27 | 28 | [Description("connect timeout")] 29 | TIMEOUT, 30 | 31 | [Description("network error")] 32 | ERROR 33 | } 34 | public class PomeloClient 35 | { 36 | private ITransporter transport; 37 | private Protocol protocol; 38 | 39 | EventManager eventManager; 40 | 41 | private List msgQueue = new List(); 42 | 43 | private ClientProtocolType client_type; 44 | 45 | private event Action connectCB; 46 | private event Action disconnectCB; 47 | private event Action handShakeCallBack; 48 | 49 | private object guard = new object(); 50 | private JsonData handShakeCallBackData; 51 | 52 | private bool handShakeCallBackCanCall; 53 | private bool bDisconnCallBack; 54 | private bool bConnectCallBack; 55 | 56 | public PomeloClient(ClientProtocolType type = ClientProtocolType.NORMAL, 57 | byte[] clientcert = null, string clientpwd = "", string cathumbprint = null) 58 | { 59 | this.client_type = type; 60 | 61 | switch (this.client_type) 62 | { 63 | case ClientProtocolType.TLS: 64 | { 65 | transport = new TransporterSSL(clientcert, clientpwd, cathumbprint); 66 | } 67 | break; 68 | case ClientProtocolType.NORMAL: 69 | { 70 | transport = new TransporterTCP(); 71 | } 72 | break; 73 | default: 74 | break; 75 | } 76 | 77 | this.protocol = new Protocol(transport, processMessage, OnProtocolClose); 78 | this.transport.setOnStateChanged(OnTransportStateChange); 79 | 80 | eventManager = new EventManager(); 81 | } 82 | 83 | void OnTransportStateChange() 84 | { 85 | NetWorkState state = this.transport.NetworkState(); 86 | switch (state) 87 | { 88 | case NetWorkState.CLOSED: 89 | bDisconnCallBack = true; 90 | break; 91 | case NetWorkState.CONNECTING: 92 | break; 93 | case NetWorkState.CONNECTED: 94 | bConnectCallBack = true; 95 | break; 96 | case NetWorkState.DISCONNECTED: 97 | bDisconnCallBack = true; 98 | break; 99 | case NetWorkState.TIMEOUT: 100 | bDisconnCallBack = true; 101 | break; 102 | case NetWorkState.ERROR: 103 | bDisconnCallBack = true; 104 | break; 105 | default: 106 | break; 107 | } 108 | } 109 | 110 | void OnProtocolClose() 111 | { 112 | if(this.IsConnected) 113 | { 114 | this.transport.close(); 115 | } 116 | } 117 | 118 | void processMessage(Message msg) 119 | { 120 | lock (guard) 121 | { 122 | msgQueue.Add(msg); 123 | } 124 | } 125 | 126 | public void poll() 127 | { 128 | lock (guard) 129 | { 130 | foreach (var msg in msgQueue) 131 | { 132 | if (msg.type == MessageType.MSG_RESPONSE) 133 | { 134 | eventManager.InvokeCallBack(msg.id, msg.data); 135 | } 136 | else if (msg.type == MessageType.MSG_PUSH) 137 | { 138 | eventManager.InvokeOnEvent(msg.route, msg.data); 139 | } 140 | } 141 | msgQueue.Clear(); 142 | 143 | if (this.bConnectCallBack == true) 144 | { 145 | if (connectCB != null) connectCB(); 146 | this.bConnectCallBack = false; 147 | 148 | } 149 | 150 | if (this.handShakeCallBackCanCall == true) 151 | { 152 | this.handShakeCallBack(this.handShakeCallBackData); 153 | this.handShakeCallBackCanCall = false; 154 | } 155 | 156 | if (this.bDisconnCallBack == true) 157 | { 158 | if (disconnectCB != null) disconnectCB(); 159 | this.bDisconnCallBack = false; 160 | } 161 | } 162 | } 163 | 164 | public void close() 165 | { 166 | //cycle call 167 | this.protocol.close(); 168 | this.transport.close(); 169 | } 170 | 171 | public bool IsConnected 172 | { 173 | get { return this.transport.NetworkState() == NetWorkState.CONNECTED; } 174 | } 175 | 176 | public string HandShakeCache 177 | { 178 | get { return this.protocol.HandShakeCache; } 179 | } 180 | 181 | public bool Connect( 182 | string host, int port, string handshake = "", 183 | Action callback = null, Action disconnCallBack = null, int nTimeoutMS = 5000 184 | ) 185 | { 186 | this.protocol.HandShakeCache = handshake; 187 | this.connectCB = callback; 188 | this.disconnectCB = disconnCallBack; 189 | 190 | IPAddress ipAddress = new IPAddress(0); 191 | if (!IPAddress.TryParse(host, out ipAddress)) 192 | { 193 | ipAddress = null; 194 | } 195 | 196 | if (ipAddress == null) 197 | { 198 | try 199 | { 200 | IPAddress[] addresses = Dns.GetHostEntry(host).AddressList; 201 | foreach (var item in addresses) 202 | { 203 | if (item.AddressFamily == AddressFamily.InterNetwork) 204 | { 205 | ipAddress = item; 206 | break; 207 | } 208 | } 209 | } 210 | catch (Exception e) 211 | { 212 | Debug.Log(e); 213 | return false; 214 | } 215 | } 216 | 217 | if (ipAddress == null) 218 | { 219 | throw new Exception("can not parse host : " + host); 220 | } 221 | 222 | IPEndPoint ie = new IPEndPoint(ipAddress, port); 223 | 224 | this.transport.Connect(ie, nTimeoutMS); 225 | 226 | return true; 227 | 228 | } 229 | 230 | public bool HandShake(JsonData user, Action handshakeCallback) 231 | { 232 | try 233 | { 234 | this.handShakeCallBack = handshakeCallback; 235 | protocol.start(user, delegate (JsonData data) 236 | { 237 | lock (guard) 238 | { 239 | this.handShakeCallBackData = new JsonData(); 240 | this.handShakeCallBackData = data; 241 | this.handShakeCallBackCanCall = true; 242 | } 243 | }); 244 | return true; 245 | } 246 | catch (Exception e) 247 | { 248 | Debug.Log(e); 249 | return false; 250 | } 251 | } 252 | 253 | private JsonData emptyMsg = new JsonData(); 254 | private uint reqId = 1; 255 | 256 | public void request(string route, Action action) 257 | { 258 | this.request(route, emptyMsg, action); 259 | } 260 | 261 | public void request(string route, JsonData msg, Action action) 262 | { 263 | this.eventManager.AddCallBack(reqId, action); 264 | protocol.send(route, reqId, msg); 265 | 266 | reqId++; 267 | } 268 | 269 | public void notify(string route, JsonData msg) 270 | { 271 | protocol.send(route, msg); 272 | } 273 | 274 | public void on(string eventName, Action action) 275 | { 276 | eventManager.AddOnEvent(eventName, action); 277 | } 278 | } 279 | } -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protobuf/MsgDecoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using LitJson; 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | 7 | namespace Pomelo.Protobuf 8 | { 9 | public class MsgDecoder 10 | { 11 | private JsonData protos{set; get;}//The message format(like .proto file) 12 | private int offset { set; get; } 13 | private byte[] buffer { set; get; }//The binary message from server. 14 | private Util util { set; get; } 15 | 16 | public MsgDecoder (JsonData protos) 17 | { 18 | if(protos == null) protos = new JsonData(); 19 | 20 | this.protos = protos; 21 | this.util = new Util(); 22 | } 23 | 24 | /// 25 | /// Decode message from server. 26 | /// 27 | /// 28 | /// Route. 29 | /// 30 | /// 31 | /// JsonData. 32 | /// 33 | public JsonData decode(string route, byte [] buf){ 34 | this.buffer = buf; 35 | this.offset = 0; 36 | object proto = null; 37 | if (this.protos.TryGetValue(route, out proto)){ 38 | JsonData msg = new JsonData(); 39 | return this.decodeMsg(msg, (JsonData)proto, this.buffer.Length); 40 | } 41 | return null; 42 | } 43 | 44 | 45 | /// 46 | /// Decode the message. 47 | /// 48 | /// 49 | /// The message. 50 | /// 51 | /// 52 | /// JsonData. 53 | /// 54 | /// 55 | /// JsonData. 56 | /// 57 | /// 58 | /// int. 59 | /// 60 | private JsonData decodeMsg(JsonData msg, JsonData proto, int length){ 61 | while(this.offset < length) { 62 | Dictionary head = this.getHead(); 63 | int tag; 64 | if (head.TryGetValue("tag", out tag)) { 65 | object _tags = null; 66 | if (proto.TryGetValue("__tags", out _tags)){ 67 | object name; 68 | if(((JsonData)_tags).TryGetValue(tag.ToString(), out name)) { 69 | object value; 70 | if(proto.TryGetValue(name.ToString(), out value)) { 71 | object option; 72 | if (((JsonData)(value)).TryGetValue("option", out option)) { 73 | switch(option.ToString()){ 74 | case "optional": 75 | case "required": 76 | object type; 77 | if (((JsonData)(value)).TryGetValue("type", out type)) { 78 | msg[name.ToString()] = new JsonData(this.decodeProp(type.ToString(), proto)); 79 | //msg.Add(name.ToString(), this.decodeProp(type.ToString(), proto)); 80 | } 81 | break; 82 | case "repeated": 83 | object _name; 84 | if (!msg.TryGetValue(name.ToString(), out _name)) { 85 | msg[name.ToString()] = new JsonData(); 86 | //msg[name.ToString()] = new JsonData(new List()); 87 | //msg.Add(name.ToString(), new List()); 88 | } 89 | object value_type; 90 | if (msg.TryGetValue(name.ToString(), out _name) && ((JsonData)(value)).TryGetValue("type", out value_type)) { 91 | //decodeArray((List)_name, value_type.ToString(), proto); 92 | decodeArray((JsonData)_name, value_type.ToString(), proto); 93 | } 94 | break; 95 | } 96 | } 97 | } 98 | } 99 | } 100 | } 101 | } 102 | return msg; 103 | } 104 | 105 | /// 106 | /// Decode array in message. 107 | /// 108 | private void decodeArray(JsonData list, string type, JsonData proto) 109 | { 110 | if (this.util.isSimpleType(type)) 111 | { 112 | int length = (int)Decoder.decodeUInt32(this.getBytes()); 113 | for (int i = 0; i < length; i++) 114 | { 115 | list.Add(this.decodeProp(type, null)); 116 | } 117 | } 118 | else { 119 | list.Add(this.decodeProp(type, proto)); 120 | } 121 | } 122 | 123 | /// 124 | /// Decode array in message. 125 | /// 126 | //private void decodeArray(List list, string type, JsonData proto){ 127 | // if (this.util.isSimpleType(type)) { 128 | // int length = (int)Decoder.decodeUInt32(this.getBytes()); 129 | // for(int i = 0; i < length; i++) { 130 | // list.Add(this.decodeProp(type, null)); 131 | // } 132 | // } else { 133 | // list.Add(this.decodeProp(type, proto)); 134 | // } 135 | // } 136 | 137 | /// 138 | /// Decode each simple type in message. 139 | /// 140 | private object decodeProp(string type, JsonData proto){ 141 | switch(type) { 142 | case "uInt32": 143 | return Decoder.decodeUInt32(this.getBytes()); 144 | case "int32": 145 | case "sInt32": 146 | return Decoder.decodeSInt32(this.getBytes()); 147 | case "float": 148 | //object xx = this.decodeFloat(); 149 | //return System.Convert.ToDouble(xx); 150 | return this.decodeFloat(); 151 | case "double": 152 | return this.decodeDouble(); 153 | case "string": 154 | return this.decodeString(); 155 | default: 156 | return this.decodeObject(type, proto); 157 | } 158 | } 159 | 160 | //Decode the user-defined object type in message. 161 | private JsonData decodeObject(string type, JsonData proto){ 162 | if (proto != null) { 163 | object __messages; 164 | if (proto.TryGetValue("__messages", out __messages)) { 165 | object _type; 166 | if (((JsonData)__messages).TryGetValue(type, out _type) || protos.TryGetValue("message " + type, out _type)) { 167 | int l = (int)Decoder.decodeUInt32(this.getBytes()); 168 | JsonData msg = new JsonData(); 169 | return this.decodeMsg(msg, (JsonData)_type, this.offset + l); 170 | } 171 | } 172 | } 173 | return new JsonData(); 174 | } 175 | 176 | //Decode string type. 177 | private string decodeString(){ 178 | int length = (int)Decoder.decodeUInt32(this.getBytes()); 179 | string msg_string = Encoding.UTF8.GetString(this.buffer, this.offset, length); 180 | this.offset += length; 181 | return msg_string; 182 | } 183 | 184 | //Decode double type. 185 | private double decodeDouble(){ 186 | double msg_double = BitConverter.Int64BitsToDouble((long)this.ReadRawLittleEndian64()); 187 | this.offset += 8; 188 | return msg_double; 189 | } 190 | 191 | //Decode float type 192 | private float decodeFloat(){ 193 | float msg_float = BitConverter.ToSingle(this.buffer, this.offset); 194 | this.offset += 4; 195 | return msg_float; 196 | } 197 | 198 | //Read long in littleEndian 199 | private ulong ReadRawLittleEndian64() { 200 | ulong b1 = buffer[this.offset]; 201 | ulong b2 = buffer[this.offset + 1]; 202 | ulong b3 = buffer[this.offset + 2]; 203 | ulong b4 = buffer[this.offset + 3]; 204 | ulong b5 = buffer[this.offset + 4]; 205 | ulong b6 = buffer[this.offset + 5]; 206 | ulong b7 = buffer[this.offset + 6]; 207 | ulong b8 = buffer[this.offset + 7]; 208 | return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24) 209 | | (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56); 210 | } 211 | 212 | //Get the type and tag. 213 | private Dictionary getHead(){ 214 | int tag = (int)Decoder.decodeUInt32(this.getBytes()); 215 | Dictionary head = new Dictionary(); 216 | head.Add("type", tag & 0x7); 217 | head.Add("tag", tag >> 3); 218 | return head; 219 | } 220 | 221 | //Get bytes. 222 | private byte[] getBytes(){ 223 | List arrayList = new List(); 224 | int pos = this.offset; 225 | byte b; 226 | do{ 227 | b = this.buffer[pos]; 228 | arrayList.Add(b); 229 | pos++; 230 | } while (b >= 128); 231 | this.offset = pos; 232 | int length = arrayList.Count; 233 | byte[] bytes = new byte[length]; 234 | for (int i = 0; i < length; i++) { 235 | bytes[i] = arrayList[i]; 236 | } 237 | return bytes; 238 | } 239 | } 240 | } 241 | 242 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/transport/TransporterSSL.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.Security; 6 | using System.Net.Sockets; 7 | using System.Security.Authentication; 8 | using System.Security.Cryptography.X509Certificates; 9 | using System.Text; 10 | using UnityEngine; 11 | 12 | namespace Pomelo.DotNetClient 13 | { 14 | class TransporterSSL : TransporterTCP 15 | { 16 | private SslStream sslstream; 17 | private byte[] clientcert = null; 18 | private string clientpwd = ""; 19 | private static List ca_thumbprints = new List(); 20 | private static List target_hosts = new List(); 21 | private string target_host; 22 | 23 | private bool tryAuthed = false; 24 | private bool authed = false; 25 | private NetworkStream tcpStream; 26 | 27 | public static void clearCAThumbprintList() 28 | { 29 | ca_thumbprints.Clear(); 30 | } 31 | 32 | public bool ValidateServerCertificate( 33 | object sender, 34 | X509Certificate certificate, 35 | X509Chain chain, 36 | SslPolicyErrors sslPolicyErrors) 37 | { 38 | if (sslPolicyErrors == SslPolicyErrors.None) 39 | { 40 | authed = true; 41 | return true; 42 | } 43 | 44 | if (chain.ChainElements.Count < 1) 45 | { 46 | Debug.LogError("certificate failed. empty chain!"); 47 | authed = false; 48 | return false; 49 | } 50 | 51 | //check cert validity 52 | bool cert_is_ok = false; 53 | X509Certificate2 root = chain.ChainElements[chain.ChainElements.Count - 1].Certificate; 54 | for (int i = 0; i < ca_thumbprints.Count; ++i) 55 | { 56 | if (root.Thumbprint == ca_thumbprints[i]) 57 | { 58 | cert_is_ok = true; 59 | break; 60 | } 61 | } 62 | if (!cert_is_ok) 63 | { 64 | Debug.LogError("certificate failed. unknown cert printer: " + root.Thumbprint); 65 | authed = false; 66 | return false; 67 | } 68 | 69 | cert_is_ok = false; 70 | //check host 71 | for (int i = 0; i < target_hosts.Count; ++i) 72 | { 73 | if (root.Subject.Contains("CN=" + target_hosts[i])) 74 | { 75 | cert_is_ok = true; 76 | break; 77 | } 78 | } 79 | if (!cert_is_ok) 80 | { 81 | Debug.LogError("certificate failed. mismatch host: " + root.Subject); 82 | authed = false; 83 | return false; 84 | } 85 | authed = true; 86 | return true; 87 | //Console.WriteLine("{0}", root.Thumbprint); 88 | //// Do not allow this client to communicate with unauthenticated servers. 89 | //X509Chain customChain = new X509Chain 90 | //{ 91 | // ChainPolicy = { 92 | // VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority 93 | // } 94 | //}; 95 | //Boolean retValue = customChain.Build(chain.ChainElements[0].Certificate); 96 | //chain.Reset(); 97 | //return retValue; 98 | } 99 | public TransporterSSL(byte[] clientcert = null, string clientpwd = "", string cathumbprint = null) 100 | { 101 | this.sslstream = null; 102 | 103 | 104 | ca_thumbprints.Add(cathumbprint); 105 | this.clientcert = clientcert; 106 | this.clientpwd = clientpwd; 107 | } 108 | 109 | public override void Connect(IPEndPoint ep, int nTimeout = 8000) 110 | { 111 | target_hosts.Add(ep.Address.ToString()); 112 | this.target_host = ep.Address.ToString(); 113 | base.Connect(ep, nTimeout); 114 | } 115 | 116 | protected override void OnConnected(IAsyncResult result) 117 | { 118 | try 119 | { 120 | this.socket.EndConnect(result); 121 | tcpStream = new NetworkStream(socket); 122 | 123 | 124 | this.sslstream = new SslStream( 125 | tcpStream, 126 | false, 127 | new RemoteCertificateValidationCallback(ValidateServerCertificate), 128 | null 129 | ); 130 | 131 | 132 | NetWorkChanged(NetWorkState.CONNECTED); 133 | } 134 | catch (SocketException e) 135 | { 136 | if (netWorkState != NetWorkState.TIMEOUT) 137 | { 138 | NetWorkChanged(NetWorkState.ERROR); 139 | } 140 | 141 | Debug.Log(e); 142 | } 143 | finally 144 | { 145 | this.CheckTimeOutEvent(); 146 | } 147 | 148 | } 149 | 150 | bool authorized() 151 | { 152 | if (null == sslstream) 153 | { 154 | return false; 155 | } 156 | 157 | if (tryAuthed == false) 158 | { 159 | try 160 | { 161 | if (this.clientcert != null) 162 | { 163 | X509CertificateCollection certs = new X509CertificateCollection(); 164 | X509Certificate2 cert = new X509Certificate2(this.clientcert, this.clientpwd); 165 | certs.Add(cert); 166 | sslstream.AuthenticateAsClient(this.target_host, certs, SslProtocols.Tls, true); 167 | } 168 | else 169 | { 170 | sslstream.AuthenticateAsClient(this.target_host); 171 | } 172 | 173 | // return true; 174 | } 175 | catch (AuthenticationException e) 176 | { 177 | Console.WriteLine("Exception: {0}", e.Message); 178 | if (e.InnerException != null) 179 | { 180 | Console.WriteLine("Inner exception: {0}", e.InnerException.Message); 181 | } 182 | Console.WriteLine("Authentication failed - closing the connection."); 183 | sslstream.Close(); 184 | this.close(); 185 | } 186 | finally 187 | { 188 | tryAuthed = true; 189 | } 190 | } 191 | 192 | 193 | 194 | return authed; 195 | } 196 | 197 | public override void receive() 198 | { 199 | if (!this.authorized()) 200 | { 201 | return; 202 | } 203 | this._receive(); 204 | } 205 | 206 | private void _receive() 207 | { 208 | //Console.WriteLine("receive state : {0}, {1}", this.transportState, socket.Available); 209 | try 210 | { 211 | this.asyncReceive = sslstream.BeginRead(stateObject.buffer, 0, stateObject.buffer.Length, new AsyncCallback(endReceive), stateObject); 212 | } 213 | catch (Exception e) 214 | { 215 | 216 | Debug.Log(e); 217 | 218 | this.close(); 219 | } 220 | } 221 | 222 | protected override void endReceive(IAsyncResult asyncReceive) 223 | { 224 | StateObject state = (StateObject)asyncReceive.AsyncState; 225 | 226 | 227 | try 228 | { 229 | int length = sslstream.EndRead(asyncReceive); 230 | if (length > 0) 231 | { 232 | processBytes(state.buffer, 0, length); 233 | 234 | //Receive next message 235 | if (this.transportState != TransportState.closed) receive(); 236 | } 237 | else 238 | { 239 | this.close(); 240 | } 241 | 242 | } 243 | catch (SocketException e) 244 | { 245 | Debug.Log(e); 246 | 247 | this.close(); 248 | } 249 | } 250 | 251 | public override void send(byte[] buffer) 252 | { 253 | if (this.transportState != TransportState.closed) 254 | { 255 | try 256 | { 257 | this.asyncSend = sslstream.BeginWrite(buffer, 0, buffer.Length, new AsyncCallback(sendCallback), stateObject); 258 | } 259 | catch (Exception e) 260 | { 261 | Debug.Log(e); 262 | this.close(); 263 | } 264 | } 265 | } 266 | 267 | protected override void sendCallback(IAsyncResult asyncSend) 268 | { 269 | try 270 | { 271 | sslstream.EndWrite(asyncSend); 272 | } 273 | catch (Exception e) 274 | { 275 | Debug.Log(e); 276 | } 277 | } 278 | 279 | public override void close() 280 | { 281 | if (this.sslstream != null) 282 | { 283 | this.sslstream.Close(); 284 | this.sslstream = null; 285 | } 286 | 287 | if(this.tcpStream != null) 288 | { 289 | this.tcpStream.Close(); 290 | this.tcpStream = null; 291 | } 292 | 293 | base.close(); 294 | } 295 | 296 | } 297 | } 298 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protocol/Protocol.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using LitJson; 3 | using System.Text; 4 | using UnityEngine; 5 | using System.Net.Sockets; 6 | 7 | namespace Pomelo.DotNetClient 8 | { 9 | public class Protocol 10 | { 11 | private ITransporter transporter; 12 | private MessageProtocol messageProtocol; 13 | private ProtocolState state; 14 | 15 | private HandShakeService handshake; 16 | private HeartBeatService heartBeatService = null; 17 | 18 | private event Action messageProcessor; 19 | private event Action onProtocolClose; 20 | 21 | 22 | public string HandShakeCache{ get; set; } 23 | 24 | public string getDictVersion() 25 | { 26 | if(messageProtocol != null) 27 | { 28 | return messageProtocol.dictVersion; 29 | } 30 | 31 | return ""; 32 | } 33 | 34 | public string getProtoVersion() 35 | { 36 | if (messageProtocol != null) 37 | { 38 | return messageProtocol.protoVersion; 39 | } 40 | 41 | return ""; 42 | } 43 | 44 | 45 | 46 | public Protocol(ITransporter transproter, Action messageProcessor, Action onProtoClose) 47 | { 48 | 49 | this.transporter = transproter; 50 | this.transporter.onReceive(this.processMessage); 51 | this.onProtocolClose += onProtoClose; 52 | this.messageProcessor += messageProcessor; 53 | 54 | this.handshake = new HandShakeService(this); 55 | this.state = ProtocolState.ready; 56 | 57 | } 58 | 59 | public void start(JsonData user, Action callback){ 60 | this.transporter.receive(); 61 | this.handshake.request(user, callback); 62 | 63 | this.state = ProtocolState.handshaking; 64 | } 65 | 66 | //Send notify, do not need id 67 | public void send(string route, JsonData msg){ 68 | send(route, 0, msg); 69 | } 70 | 71 | //Send request, user request id 72 | public void send(string route, uint id, JsonData msg){ 73 | if (this.state != ProtocolState.working) return; 74 | 75 | byte[] body = messageProtocol.encode(route, id, msg); 76 | 77 | send(PackageType.PKG_DATA, body); 78 | } 79 | 80 | public void send(PackageType type){ 81 | if (this.state == ProtocolState.closed) return; 82 | transporter.send(PackageProtocol.encode(type)); 83 | } 84 | 85 | //Send system message, these message do not use messageProtocol 86 | public void send(PackageType type, JsonData msg){ 87 | //This method only used to send system package 88 | if (type == PackageType.PKG_DATA) return; 89 | 90 | byte[] body = Encoding.UTF8.GetBytes(msg.ToString()); 91 | 92 | send(type, body); 93 | } 94 | 95 | //Send message use the transporter 96 | public void send(PackageType type, byte[] body){ 97 | if (this.state == ProtocolState.closed) return; 98 | 99 | byte[] pkg = PackageProtocol.encode(type, body); 100 | 101 | transporter.send(pkg); 102 | } 103 | 104 | //Invoke by Transporter, process the message 105 | void processMessage(byte[] bytes){ 106 | Package pkg = PackageProtocol.decode(bytes); 107 | 108 | //Ignore all the message except handshading at handshake stage 109 | if (pkg.type == PackageType.PKG_HANDSHAKE && this.state == ProtocolState.handshaking) { 110 | 111 | //Ignore all the message except handshading 112 | JsonData data = LitJson.JsonMapper.ToObject(Encoding.UTF8.GetString(pkg.body)); 113 | 114 | processHandshakeData(data); 115 | 116 | this.state = ProtocolState.working; 117 | 118 | } 119 | else if (pkg.type == PackageType.PKG_HEARTBEAT && this.state == ProtocolState.working){ 120 | this.heartBeatService.resetTimeout(); 121 | } 122 | else if (pkg.type == PackageType.PKG_DATA && this.state == ProtocolState.working) { 123 | this.heartBeatService.resetTimeout(); 124 | if(messageProcessor != null) 125 | { 126 | messageProcessor(messageProtocol.decode(pkg.body)); 127 | } 128 | } 129 | else if (pkg.type == PackageType.PKG_KICK) { 130 | this.close(); 131 | } 132 | } 133 | 134 | public void InitProtoCache(string data) 135 | { 136 | JsonData handshake = JsonMapper.ToObject(data); 137 | this.InitProtoCache(handshake); 138 | } 139 | 140 | private void InitProtoCache(JsonData sys) 141 | { 142 | JsonData dict = new JsonData(); 143 | //JsonData routeToCode = new JsonData(); 144 | //JsonData codeToRoute = new JsonData(); 145 | if (sys.ContainsKey("dict")) dict = (JsonData)sys["dict"]; 146 | //if (sys.ContainsKey("routeToCode")) routeToCode = (JsonData)sys["routeToCode"]; 147 | //if (sys.ContainsKey("codeToRoute")) codeToRoute = (JsonData)sys["codeToRoute"]; 148 | 149 | 150 | string dictVersion = ""; 151 | if (sys.ContainsKey("dictVersion")) dictVersion = sys["dictVersion"].ToString(); 152 | 153 | JsonData protos = new JsonData(); 154 | JsonData serverProtos = new JsonData(); 155 | JsonData clientProtos = new JsonData(); 156 | 157 | string protoVersion = ""; 158 | 159 | if (sys.ContainsKey("protos")) 160 | { 161 | protos = (JsonData)sys["protos"]; 162 | serverProtos = (JsonData)protos["server"]; 163 | clientProtos = (JsonData)protos["client"]; 164 | if (protos.ContainsKey("version")) protoVersion = protos["version"].ToString(); 165 | } 166 | 167 | if(messageProtocol != null) 168 | { 169 | if ((dictVersion != "" && messageProtocol.dictVersion != dictVersion) 170 | || (protoVersion != "" && messageProtocol.protoVersion != protoVersion)) 171 | { 172 | //update cache 173 | JsonData sysNew = JsonMapper.ToObject(this.HandShakeCache); 174 | if(sys.ContainsKey("dict")) 175 | { 176 | sysNew["dict"] = new JsonData(); 177 | sysNew["dict"] = sys["dict"]; 178 | } 179 | if (sys.ContainsKey("dictVersion")) 180 | { 181 | sysNew["dictVersion"] = sys["dictVersion"]; 182 | } 183 | if (sys.ContainsKey("protos")) 184 | { 185 | sysNew["protos"] = new JsonData(); 186 | sysNew["protos"] = sys["protos"]; 187 | } 188 | this.HandShakeCache = sysNew.ToJson(); 189 | this.messageProtocol = null; 190 | this.InitProtoCache(this.HandShakeCache); 191 | 192 | //MessageProtocol messageProtocolNew = new MessageProtocol(dict, serverProtos, clientProtos, dictVersion, protoVersion); 193 | 194 | //if (dictVersion == "" && !sys.ContainsKey("dict")) 195 | //{ 196 | // messageProtocolNew.dict = messageProtocol.dict; 197 | // messageProtocolNew.abbrs = messageProtocol.abbrs; 198 | // messageProtocolNew.dictVersion = messageProtocol.dictVersion; 199 | //} 200 | 201 | //if(protoVersion == "" && !sys.ContainsKey("protos")) 202 | //{ 203 | // messageProtocolNew.encodeProtos = messageProtocol.encodeProtos; 204 | // messageProtocolNew.decodeProtos = messageProtocol.decodeProtos; 205 | 206 | // messageProtocolNew.protoVersion = messageProtocol.protoVersion; 207 | //} 208 | 209 | //messageProtocol = messageProtocolNew; 210 | } 211 | } 212 | else 213 | { 214 | messageProtocol = new MessageProtocol(dict, serverProtos, clientProtos, dictVersion, protoVersion); 215 | this.HandShakeCache = sys.ToJson(); 216 | } 217 | 218 | } 219 | 220 | 221 | 222 | private void processHandshakeData(JsonData msg){ 223 | //Handshake error 224 | if(!msg.ContainsKey("code") || !msg.ContainsKey("sys") || Convert.ToInt32(msg["code"].ToString()) != 200){ 225 | throw new Exception("Handshake error! Please check your handshake config."); 226 | } 227 | //Debug.Log(msg.ToJson()); 228 | 229 | //Set compress data 230 | JsonData sys = (JsonData)msg["sys"]; 231 | 232 | 233 | //Init heartbeat service 234 | int interval = 0; 235 | if (sys.ContainsKey("heartbeat")) interval = Convert.ToInt32(sys["heartbeat"].ToString()); 236 | heartBeatService = new HeartBeatService(interval, this); 237 | 238 | if (interval > 0) 239 | { 240 | heartBeatService.start(); 241 | } 242 | 243 | this.InitProtoCache(sys); 244 | 245 | //send ack and change protocol state 246 | handshake.ack(); 247 | this.state = ProtocolState.working; 248 | 249 | //Invoke handshake callback 250 | JsonData user = new JsonData(); 251 | if(msg.ContainsKey("user")) user = (JsonData)msg["user"]; 252 | handshake.invokeCallback(user); 253 | } 254 | 255 | public void close(){ 256 | 257 | if (heartBeatService != null) heartBeatService.stop(); 258 | 259 | this.state = ProtocolState.closed; 260 | 261 | if(onProtocolClose != null) 262 | { 263 | onProtocolClose(); 264 | } 265 | } 266 | } 267 | } 268 | 269 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/transport/TransporterTCP.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.Sockets; 6 | using System.Text; 7 | using System.Threading; 8 | using System.Timers; 9 | using UnityEngine; 10 | 11 | namespace Pomelo.DotNetClient 12 | { 13 | class TransporterTCP : ITransporter 14 | { 15 | public const int HeadLength = 4; 16 | 17 | protected NetWorkState netWorkState = NetWorkState.CLOSED; //current network state 18 | protected Socket socket; 19 | protected event Action networkEventCB; 20 | protected event Action messageProcesserCB; 21 | 22 | 23 | protected int timeoutMSec = 8000; 24 | 25 | 26 | protected StateObject stateObject = new StateObject(); 27 | protected IAsyncResult asyncReceive; 28 | protected IAsyncResult asyncSend; 29 | protected IAsyncResult asyncConnect; 30 | 31 | protected TransportState transportState; 32 | protected byte[] headBuffer = new byte[4]; 33 | protected byte[] buffer; 34 | protected int bufferOffset = 0; 35 | protected int pkgLength = 0; 36 | 37 | private System.Timers.Timer timer; 38 | 39 | public TransporterTCP() 40 | { 41 | this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 42 | this.transportState = TransportState.readHead; 43 | } 44 | 45 | protected void NetWorkChanged(NetWorkState state) 46 | { 47 | if (netWorkState != state) 48 | { 49 | netWorkState = state; 50 | 51 | if (networkEventCB != null) 52 | { 53 | networkEventCB(); 54 | } 55 | } 56 | } 57 | public virtual void close() 58 | { 59 | this.transportState = TransportState.closed; 60 | 61 | if (this.socket != null) 62 | { 63 | if (this.socket.Connected) 64 | { 65 | this.socket.Shutdown(SocketShutdown.Both); 66 | } 67 | 68 | this.socket.Close(); 69 | this.socket = null; 70 | } 71 | 72 | NetWorkChanged(NetWorkState.CLOSED); 73 | } 74 | 75 | protected void CheckTimeOutEvent() 76 | { 77 | timer.Stop(); 78 | timer.Enabled = false; 79 | timer.Dispose(); 80 | timer = null; 81 | 82 | if (netWorkState != NetWorkState.CONNECTED && netWorkState != NetWorkState.ERROR) 83 | { 84 | NetWorkChanged(NetWorkState.TIMEOUT); 85 | } 86 | 87 | if (netWorkState == NetWorkState.ERROR) 88 | { 89 | 90 | } 91 | } 92 | 93 | public virtual void Connect(IPEndPoint ep, int nTimeout) 94 | { 95 | Debug.Log("Transport connect " + ep.Address.ToString() + " with timeout:"+nTimeout); 96 | if (nTimeout != 0) 97 | { 98 | timeoutMSec = nTimeout; 99 | } 100 | 101 | this.timer = new System.Timers.Timer(); 102 | timer.Interval = timeoutMSec; 103 | timer.Elapsed += new ElapsedEventHandler(ConnectTimeout); 104 | timer.Enabled = true; 105 | 106 | asyncConnect = socket.BeginConnect(ep, new AsyncCallback(OnConnected), this.socket); 107 | 108 | } 109 | 110 | virtual protected void OnConnected(IAsyncResult result) 111 | { 112 | try 113 | { 114 | this.socket.EndConnect(result); 115 | NetWorkChanged(NetWorkState.CONNECTED); 116 | } 117 | catch (SocketException e) 118 | { 119 | if (netWorkState != NetWorkState.TIMEOUT) 120 | { 121 | NetWorkChanged(NetWorkState.ERROR); 122 | } 123 | 124 | Debug.Log(e); 125 | } 126 | finally 127 | { 128 | this.CheckTimeOutEvent(); 129 | } 130 | } 131 | 132 | public void ConnectTimeout(object source, ElapsedEventArgs e) 133 | { 134 | Debug.Log("ConnectTimeout"); 135 | this.CheckTimeOutEvent(); 136 | } 137 | 138 | public NetWorkState NetworkState() 139 | { 140 | return netWorkState; 141 | } 142 | protected bool readHead(byte[] bytes, int offset, int limit) 143 | { 144 | int length = limit - offset; 145 | int headNum = HeadLength - bufferOffset; 146 | 147 | if (length >= headNum) 148 | { 149 | //Write head buffer 150 | writeBytes(bytes, offset, headNum, bufferOffset, headBuffer); 151 | //Get package length 152 | pkgLength = (headBuffer[1] << 16) + (headBuffer[2] << 8) + headBuffer[3]; 153 | 154 | //Init message buffer 155 | buffer = new byte[HeadLength + pkgLength]; 156 | writeBytes(headBuffer, 0, HeadLength, buffer); 157 | offset += headNum; 158 | bufferOffset = HeadLength; 159 | this.transportState = TransportState.readBody; 160 | 161 | if (offset <= limit) processBytes(bytes, offset, limit); 162 | return true; 163 | } 164 | else 165 | { 166 | writeBytes(bytes, offset, length, bufferOffset, headBuffer); 167 | bufferOffset += length; 168 | return false; 169 | } 170 | } 171 | protected void readBody(byte[] bytes, int offset, int limit) 172 | { 173 | int length = pkgLength + HeadLength - bufferOffset; 174 | if ((offset + length) <= limit) 175 | { 176 | writeBytes(bytes, offset, length, bufferOffset, buffer); 177 | offset += length; 178 | 179 | //Invoke the protocol api to handle the message 180 | this.messageProcesserCB.Invoke(buffer); 181 | this.bufferOffset = 0; 182 | this.pkgLength = 0; 183 | 184 | if (this.transportState != TransportState.closed) 185 | this.transportState = TransportState.readHead; 186 | if (offset < limit) 187 | processBytes(bytes, offset, limit); 188 | } 189 | else 190 | { 191 | writeBytes(bytes, offset, limit - offset, bufferOffset, buffer); 192 | bufferOffset += limit - offset; 193 | this.transportState = TransportState.readBody; 194 | } 195 | } 196 | protected void writeBytes(byte[] source, int start, int length, byte[] target) 197 | { 198 | writeBytes(source, start, length, 0, target); 199 | } 200 | protected void writeBytes(byte[] source, int start, int length, int offset, byte[] target) 201 | { 202 | for (int i = 0; i < length; i++) 203 | { 204 | target[offset + i] = source[start + i]; 205 | } 206 | } 207 | protected void processBytes(byte[] bytes, int offset, int limit) 208 | { 209 | if (this.transportState == TransportState.readHead) 210 | { 211 | readHead(bytes, offset, limit); 212 | } 213 | else if (this.transportState == TransportState.readBody) 214 | { 215 | readBody(bytes, offset, limit); 216 | } 217 | } 218 | protected virtual void endReceive(IAsyncResult asyncReceive) 219 | { 220 | StateObject state = (StateObject)asyncReceive.AsyncState; 221 | Socket socket = this.socket; 222 | 223 | try 224 | { 225 | int length = socket.EndReceive(asyncReceive); 226 | if (length > 0) 227 | { 228 | processBytes(state.buffer, 0, length); 229 | 230 | //Receive next message 231 | if (this.transportState != TransportState.closed) receive(); 232 | } 233 | else 234 | { 235 | this.close(); 236 | } 237 | 238 | } 239 | catch (SocketException e) 240 | { 241 | Debug.Log(e); 242 | 243 | this.close(); 244 | } 245 | } 246 | public virtual void receive() 247 | { 248 | try 249 | { 250 | this.asyncReceive = socket.BeginReceive(stateObject.buffer, 0, stateObject.buffer.Length, SocketFlags.None, new AsyncCallback(endReceive), stateObject); 251 | } 252 | catch (Exception e) 253 | { 254 | Debug.Log(e); 255 | this.close(); 256 | } 257 | } 258 | public virtual void send(byte[] buffer) 259 | { 260 | if (this.transportState != TransportState.closed) 261 | { 262 | try 263 | { 264 | this.asyncSend = socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(sendCallback), socket); 265 | } 266 | catch (Exception e) 267 | { 268 | Debug.Log(e); 269 | this.close(); 270 | } 271 | } 272 | } 273 | protected virtual void sendCallback(IAsyncResult asyncSend) 274 | { 275 | try 276 | { 277 | socket.EndSend(asyncSend); 278 | } 279 | catch (Exception e) 280 | { 281 | Debug.Log(e); 282 | } 283 | } 284 | 285 | public void setOnStateChanged(Action cb) 286 | { 287 | networkEventCB += cb; 288 | } 289 | public void onReceive(Action messageProcessor) 290 | { 291 | this.messageProcesserCB += messageProcessor; 292 | } 293 | } 294 | } 295 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/LitJson/JsonWriter.cs: -------------------------------------------------------------------------------- 1 | #region Header 2 | /** 3 | * JsonWriter.cs 4 | * Stream-like facility to output JSON text. 5 | * 6 | * The authors disclaim copyright to this source code. For more details, see 7 | * the COPYING file included with this distribution. 8 | **/ 9 | #endregion 10 | 11 | 12 | using System; 13 | using System.Collections.Generic; 14 | using System.Globalization; 15 | using System.IO; 16 | using System.Text; 17 | 18 | 19 | namespace LitJson 20 | { 21 | internal enum Condition 22 | { 23 | InArray, 24 | InObject, 25 | NotAProperty, 26 | Property, 27 | Value 28 | } 29 | 30 | internal class WriterContext 31 | { 32 | public int Count; 33 | public bool InArray; 34 | public bool InObject; 35 | public bool ExpectingValue; 36 | public int Padding; 37 | } 38 | 39 | public class JsonWriter 40 | { 41 | #region Fields 42 | private static NumberFormatInfo number_format; 43 | 44 | private WriterContext context; 45 | private Stack ctx_stack; 46 | private bool has_reached_end; 47 | private char[] hex_seq; 48 | private int indentation; 49 | private int indent_value; 50 | private StringBuilder inst_string_builder; 51 | private bool pretty_print; 52 | private bool validate; 53 | private TextWriter writer; 54 | #endregion 55 | 56 | 57 | #region Properties 58 | public int IndentValue { 59 | get { return indent_value; } 60 | set { 61 | indentation = (indentation / indent_value) * value; 62 | indent_value = value; 63 | } 64 | } 65 | 66 | public bool PrettyPrint { 67 | get { return pretty_print; } 68 | set { pretty_print = value; } 69 | } 70 | 71 | public TextWriter TextWriter { 72 | get { return writer; } 73 | } 74 | 75 | public bool Validate { 76 | get { return validate; } 77 | set { validate = value; } 78 | } 79 | #endregion 80 | 81 | 82 | #region Constructors 83 | static JsonWriter () 84 | { 85 | number_format = NumberFormatInfo.InvariantInfo; 86 | } 87 | 88 | public JsonWriter () 89 | { 90 | inst_string_builder = new StringBuilder (); 91 | writer = new StringWriter (inst_string_builder); 92 | 93 | Init (); 94 | } 95 | 96 | public JsonWriter (StringBuilder sb) : 97 | this (new StringWriter (sb)) 98 | { 99 | } 100 | 101 | public JsonWriter (TextWriter writer) 102 | { 103 | if (writer == null) 104 | throw new ArgumentNullException ("writer"); 105 | 106 | this.writer = writer; 107 | 108 | Init (); 109 | } 110 | #endregion 111 | 112 | 113 | #region Private Methods 114 | private void DoValidation (Condition cond) 115 | { 116 | if (! context.ExpectingValue) 117 | context.Count++; 118 | 119 | if (! validate) 120 | return; 121 | 122 | if (has_reached_end) 123 | throw new JsonException ( 124 | "A complete JSON symbol has already been written"); 125 | 126 | switch (cond) { 127 | case Condition.InArray: 128 | if (! context.InArray) 129 | throw new JsonException ( 130 | "Can't close an array here"); 131 | break; 132 | 133 | case Condition.InObject: 134 | if (! context.InObject || context.ExpectingValue) 135 | throw new JsonException ( 136 | "Can't close an object here"); 137 | break; 138 | 139 | case Condition.NotAProperty: 140 | if (context.InObject && ! context.ExpectingValue) 141 | throw new JsonException ( 142 | "Expected a property"); 143 | break; 144 | 145 | case Condition.Property: 146 | if (! context.InObject || context.ExpectingValue) 147 | throw new JsonException ( 148 | "Can't add a property here"); 149 | break; 150 | 151 | case Condition.Value: 152 | if (! context.InArray && 153 | (! context.InObject || ! context.ExpectingValue)) 154 | throw new JsonException ( 155 | "Can't add a value here"); 156 | 157 | break; 158 | } 159 | } 160 | 161 | private void Init () 162 | { 163 | has_reached_end = false; 164 | hex_seq = new char[4]; 165 | indentation = 0; 166 | indent_value = 4; 167 | pretty_print = false; 168 | validate = true; 169 | 170 | ctx_stack = new Stack (); 171 | context = new WriterContext (); 172 | ctx_stack.Push (context); 173 | } 174 | 175 | private static void IntToHex (int n, char[] hex) 176 | { 177 | int num; 178 | 179 | for (int i = 0; i < 4; i++) { 180 | num = n % 16; 181 | 182 | if (num < 10) 183 | hex[3 - i] = (char) ('0' + num); 184 | else 185 | hex[3 - i] = (char) ('A' + (num - 10)); 186 | 187 | n >>= 4; 188 | } 189 | } 190 | 191 | private void Indent () 192 | { 193 | if (pretty_print) 194 | indentation += indent_value; 195 | } 196 | 197 | 198 | private void Put (string str) 199 | { 200 | if (pretty_print && ! context.ExpectingValue) 201 | for (int i = 0; i < indentation; i++) 202 | writer.Write (' '); 203 | 204 | writer.Write (str); 205 | } 206 | 207 | private void PutNewline () 208 | { 209 | PutNewline (true); 210 | } 211 | 212 | private void PutNewline (bool add_comma) 213 | { 214 | if (add_comma && ! context.ExpectingValue && 215 | context.Count > 1) 216 | writer.Write (','); 217 | 218 | if (pretty_print && ! context.ExpectingValue) 219 | writer.Write ('\n'); 220 | } 221 | 222 | private void PutString (string str) 223 | { 224 | Put (String.Empty); 225 | 226 | writer.Write ('"'); 227 | 228 | int n = str.Length; 229 | for (int i = 0; i < n; i++) { 230 | switch (str[i]) { 231 | case '\n': 232 | writer.Write ("\\n"); 233 | continue; 234 | 235 | case '\r': 236 | writer.Write ("\\r"); 237 | continue; 238 | 239 | case '\t': 240 | writer.Write ("\\t"); 241 | continue; 242 | 243 | case '"': 244 | case '\\': 245 | writer.Write ('\\'); 246 | writer.Write (str[i]); 247 | continue; 248 | 249 | case '\f': 250 | writer.Write ("\\f"); 251 | continue; 252 | 253 | case '\b': 254 | writer.Write ("\\b"); 255 | continue; 256 | } 257 | 258 | if ((int) str[i] >= 32 && (int) str[i] <= 126) { 259 | writer.Write (str[i]); 260 | continue; 261 | } 262 | 263 | // Default, turn into a \uXXXX sequence 264 | IntToHex ((int) str[i], hex_seq); 265 | writer.Write ("\\u"); 266 | writer.Write (hex_seq); 267 | } 268 | 269 | writer.Write ('"'); 270 | } 271 | 272 | private void Unindent () 273 | { 274 | if (pretty_print) 275 | indentation -= indent_value; 276 | } 277 | #endregion 278 | 279 | 280 | public override string ToString () 281 | { 282 | if (inst_string_builder == null) 283 | return String.Empty; 284 | 285 | return inst_string_builder.ToString (); 286 | } 287 | 288 | public void Reset () 289 | { 290 | has_reached_end = false; 291 | 292 | ctx_stack.Clear (); 293 | context = new WriterContext (); 294 | ctx_stack.Push (context); 295 | 296 | if (inst_string_builder != null) 297 | inst_string_builder.Remove (0, inst_string_builder.Length); 298 | } 299 | 300 | public void Write (bool boolean) 301 | { 302 | DoValidation (Condition.Value); 303 | PutNewline (); 304 | 305 | Put (boolean ? "true" : "false"); 306 | 307 | context.ExpectingValue = false; 308 | } 309 | 310 | public void Write (decimal number) 311 | { 312 | DoValidation (Condition.Value); 313 | PutNewline (); 314 | 315 | Put (Convert.ToString (number, number_format)); 316 | 317 | context.ExpectingValue = false; 318 | } 319 | 320 | public void Write (double number) 321 | { 322 | DoValidation (Condition.Value); 323 | PutNewline (); 324 | 325 | string str = Convert.ToString (number, number_format); 326 | Put (str); 327 | 328 | if (str.IndexOf ('.') == -1 && 329 | str.IndexOf ('E') == -1) 330 | writer.Write (".0"); 331 | 332 | context.ExpectingValue = false; 333 | } 334 | 335 | public void Write (int number) 336 | { 337 | DoValidation (Condition.Value); 338 | PutNewline (); 339 | 340 | Put (Convert.ToString (number, number_format)); 341 | 342 | context.ExpectingValue = false; 343 | } 344 | 345 | public void Write (long number) 346 | { 347 | DoValidation (Condition.Value); 348 | PutNewline (); 349 | 350 | Put (Convert.ToString (number, number_format)); 351 | 352 | context.ExpectingValue = false; 353 | } 354 | 355 | public void Write (string str) 356 | { 357 | DoValidation (Condition.Value); 358 | PutNewline (); 359 | 360 | if (str == null) 361 | Put ("null"); 362 | else 363 | PutString (str); 364 | 365 | context.ExpectingValue = false; 366 | } 367 | 368 | //[CLSCompliant(false)] 369 | public void Write (ulong number) 370 | { 371 | DoValidation (Condition.Value); 372 | PutNewline (); 373 | 374 | Put (Convert.ToString (number, number_format)); 375 | 376 | context.ExpectingValue = false; 377 | } 378 | 379 | public void WriteArrayEnd () 380 | { 381 | DoValidation (Condition.InArray); 382 | PutNewline (false); 383 | 384 | ctx_stack.Pop (); 385 | if (ctx_stack.Count == 1) 386 | has_reached_end = true; 387 | else { 388 | context = ctx_stack.Peek (); 389 | context.ExpectingValue = false; 390 | } 391 | 392 | Unindent (); 393 | Put ("]"); 394 | } 395 | 396 | public void WriteArrayStart () 397 | { 398 | DoValidation (Condition.NotAProperty); 399 | PutNewline (); 400 | 401 | Put ("["); 402 | 403 | context = new WriterContext (); 404 | context.InArray = true; 405 | ctx_stack.Push (context); 406 | 407 | Indent (); 408 | } 409 | 410 | public void WriteObjectEnd () 411 | { 412 | DoValidation (Condition.InObject); 413 | PutNewline (false); 414 | 415 | ctx_stack.Pop (); 416 | if (ctx_stack.Count == 1) 417 | has_reached_end = true; 418 | else { 419 | context = ctx_stack.Peek (); 420 | context.ExpectingValue = false; 421 | } 422 | 423 | Unindent (); 424 | Put ("}"); 425 | } 426 | 427 | public void WriteObjectStart () 428 | { 429 | DoValidation (Condition.NotAProperty); 430 | PutNewline (); 431 | 432 | Put ("{"); 433 | 434 | context = new WriterContext (); 435 | context.InObject = true; 436 | ctx_stack.Push (context); 437 | 438 | Indent (); 439 | } 440 | 441 | public void WritePropertyName (string property_name) 442 | { 443 | DoValidation (Condition.Property); 444 | PutNewline (); 445 | 446 | PutString (property_name); 447 | 448 | if (pretty_print) { 449 | if (property_name.Length > context.Padding) 450 | context.Padding = property_name.Length; 451 | 452 | for (int i = context.Padding - property_name.Length; 453 | i >= 0; i--) 454 | writer.Write (' '); 455 | 456 | writer.Write (": "); 457 | } else 458 | writer.Write (':'); 459 | 460 | context.ExpectingValue = true; 461 | } 462 | } 463 | } 464 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/pomelo-dotnetclient/protobuf/MsgEncoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using LitJson; 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | 7 | namespace Pomelo.Protobuf 8 | { 9 | public class MsgEncoder 10 | { 11 | private JsonData protos{set; get;}//The message format(like .proto file) 12 | private Encoder encoder { set; get; } 13 | private Util util { set; get; } 14 | 15 | public MsgEncoder (JsonData protos) 16 | { 17 | if(protos == null) protos = new JsonData(); 18 | 19 | this.protos = protos; 20 | this.util = new Util(); 21 | } 22 | 23 | /// 24 | /// Encode the message from server. 25 | /// 26 | /// 27 | /// Route. 28 | /// 29 | /// 30 | /// Message. 31 | /// 32 | public byte [] encode(string route, JsonData msg){ 33 | byte[] returnByte = null; 34 | object proto; 35 | if (this.protos.TryGetValue(route, out proto)) 36 | { 37 | if (!checkMsg(msg, (JsonData)proto)) { 38 | return null; 39 | } 40 | int length = Encoder.byteLength(msg.ToJson()) * 2; 41 | int offset = 0; 42 | byte[] buff = new byte[length]; 43 | offset = encodeMsg(buff, offset, (JsonData)proto, msg); 44 | returnByte = new byte[offset]; 45 | for (int i = 0; i < offset; i++) { 46 | returnByte[i] = buff[i]; 47 | } 48 | } 49 | return returnByte; 50 | } 51 | 52 | /// 53 | /// Check the message. 54 | /// 55 | private bool checkMsg(JsonData msg, JsonData proto){ 56 | ICollection protoKeys = proto.Keys; 57 | foreach(string key in protoKeys) { 58 | JsonData value = (JsonData)proto[key]; 59 | object proto_option; 60 | if (value.TryGetValue("option", out proto_option)) { 61 | switch(proto_option.ToString()) { 62 | case "required": 63 | if(!msg.Keys.Contains(key)) { 64 | return false; 65 | }else{ 66 | 67 | } 68 | break; 69 | case "optional": 70 | object value_type; 71 | 72 | JsonData messages = (JsonData)proto["__messages"]; 73 | 74 | value_type = value["type"]; 75 | 76 | if(msg.Keys.Contains(key)){ 77 | Object value_proto; 78 | 79 | if(messages.TryGetValue(value_type.ToString(), out value_proto) || protos.TryGetValue("message " + value_type.ToString(), out value_proto)){ 80 | checkMsg ((JsonData)msg[key], (JsonData)value_proto); 81 | } 82 | } 83 | break; 84 | case "repeated": 85 | object msg_name; 86 | object msg_type; 87 | if (msg.Keys.Contains(key)) 88 | { 89 | if(value.TryGetValue("type", out value_type) && msg.TryGetValue(key, out msg_name)) 90 | { 91 | if (((JsonData)proto["__messages"]).TryGetValue(value_type.ToString(), out msg_type) || protos.TryGetValue("message " + value_type.ToString(), out msg_type)) 92 | { 93 | JsonData msg_arr = (JsonData)msg_name; 94 | if (!msg_arr.IsArray) 95 | { 96 | return false; 97 | } 98 | for (int i = 0; i < msg_arr.Count; ++i) 99 | { 100 | if (!checkMsg(msg_arr[i], (JsonData)msg_type)) 101 | { 102 | return false; 103 | } 104 | } 105 | } 106 | } 107 | } 108 | //if (value.TryGetValue("type", out value_type) && msg.TryGetValue(key, out msg_name)) { 109 | //if(((JsonData)proto["__messages"]).TryGetValue(value_type.ToString(), out msg_type) || protos.TryGetValue("message " + value_type.ToString(), out msg_type)){ 110 | 111 | // List o = (List)msg_name; 112 | // foreach (object item in o) 113 | // { 114 | // if (!checkMsg((JsonData)item, (JsonData)msg_type)) 115 | // { 116 | // return false; 117 | // } 118 | // } 119 | // } 120 | // } 121 | break; 122 | } 123 | } 124 | } 125 | return true; 126 | } 127 | 128 | /// 129 | /// Encode the message. 130 | /// 131 | private int encodeMsg(byte [] buffer, int offset, JsonData proto, JsonData msg){ 132 | ICollection msgKeys = msg.Keys; 133 | foreach(string key in msgKeys) { 134 | object value; 135 | if (proto.TryGetValue(key, out value)) { 136 | object value_option; 137 | if (((JsonData)value).TryGetValue("option", out value_option)) { 138 | switch(value_option.ToString()){ 139 | case "required": 140 | case "optional": 141 | object value_type, value_tag; 142 | if (((JsonData)value).TryGetValue("type", out value_type) && ((JsonData)value).TryGetValue("tag", out value_tag)) { 143 | offset = this.writeBytes(buffer, offset, this.encodeTag(value_type.ToString(), Convert.ToInt32(value_tag.ToString()))); 144 | offset = this.encodeProp(msg[key], value_type.ToString(), offset, buffer, proto); 145 | } 146 | break; 147 | case "repeated": 148 | object msg_key; 149 | if (msg.TryGetValue(key, out msg_key)) { 150 | JsonData msg_arr = (JsonData)msg_key; 151 | if(msg_arr.IsArray && msg_arr.Count > 0) 152 | { 153 | offset = encodeArray(msg_arr, (JsonData)value, offset, buffer, proto); 154 | } 155 | //if (((List)msg_key).Count > 0) { 156 | // offset = encodeArray((List)msg_key, (JsonData)value, offset, buffer, proto); 157 | // } 158 | } 159 | break; 160 | } 161 | } 162 | 163 | } 164 | } 165 | return offset; 166 | } 167 | 168 | /// 169 | /// Encode the array type. 170 | /// 171 | private int encodeArray(JsonData msg, JsonData value, int offset, byte[] buffer, JsonData proto) 172 | { 173 | object value_type, value_tag; 174 | if (value.TryGetValue("type", out value_type) && value.TryGetValue("tag", out value_tag)) 175 | { 176 | if (this.util.isSimpleType(value_type.ToString())) 177 | { 178 | offset = this.writeBytes(buffer, offset, this.encodeTag(value_type.ToString(), Convert.ToInt32(value_tag.ToString()))); 179 | offset = this.writeBytes(buffer, offset, Encoder.encodeUInt32((uint)msg.Count)); 180 | //foreach (object item in msg) 181 | for(int i=0;i 200 | /// Encode the array type. 201 | /// 202 | //private int encodeArray(List msg, JsonData value, int offset, byte[] buffer, JsonData proto){ 203 | // object value_type, value_tag; 204 | // if (value.TryGetValue("type", out value_type) && value.TryGetValue("tag", out value_tag)) { 205 | // if (this.util.isSimpleType(value_type.ToString())) { 206 | // offset = this.writeBytes(buffer, offset, this.encodeTag(value_type.ToString(), Convert.ToInt32(value_tag))); 207 | // offset = this.writeBytes(buffer, offset, Encoder.encodeUInt32((uint)msg.Count)); 208 | // foreach(object item in msg) { 209 | // offset = this.encodeProp(item, value_type.ToString(), offset, buffer, null); 210 | // } 211 | // } else { 212 | // foreach(object item in msg) { 213 | // offset = this.writeBytes(buffer, offset, this.encodeTag(value_type.ToString(), Convert.ToInt32(value_tag))); 214 | // offset = this.encodeProp(item, value_type.ToString(), offset, buffer, proto); 215 | // } 216 | // } 217 | // } 218 | // return offset; 219 | // } 220 | 221 | /// 222 | /// Encode each item in message. 223 | /// 224 | private int encodeProp(object value, string type, int offset, byte [] buffer, JsonData proto){ 225 | switch(type) { 226 | case "uInt32": 227 | this.writeUInt32(buffer, ref offset, value); 228 | break; 229 | case "int32": 230 | case "sInt32": 231 | this.writeInt32(buffer, ref offset, value); 232 | break; 233 | case "float": 234 | this.writeFloat(buffer, ref offset, value); 235 | break; 236 | case "double": 237 | this.writeDouble(buffer, ref offset, value); 238 | break; 239 | case "string": 240 | this.writeString(buffer, ref offset, value); 241 | break; 242 | default: 243 | object __messages; 244 | object __message_type; 245 | 246 | if (proto.TryGetValue("__messages", out __messages)) { 247 | if (((JsonData)__messages).TryGetValue(type, out __message_type) || protos.TryGetValue("message " + type, out __message_type)) { 248 | byte[] tembuff = new byte[Encoder.byteLength(value.ToString()) * 3]; 249 | int length = 0; 250 | length = this.encodeMsg(tembuff, length, (JsonData)__message_type, (JsonData)value); 251 | offset = writeBytes(buffer, offset, Encoder.encodeUInt32((uint)length)); 252 | for (int i = 0; i < length; i++) { 253 | buffer[offset] = tembuff[i]; 254 | offset++; 255 | } 256 | } 257 | } 258 | break; 259 | } 260 | return offset; 261 | } 262 | 263 | //Encode string. 264 | private void writeString(byte [] buffer, ref int offset, object value) { 265 | int le = Encoding.UTF8.GetByteCount(value.ToString()); 266 | offset = writeBytes(buffer, offset, Encoder.encodeUInt32((uint)le)); 267 | byte[] bytes = Encoding.UTF8.GetBytes(value.ToString()); 268 | this.writeBytes(buffer, offset, bytes); 269 | offset += le; 270 | } 271 | 272 | //Encode double. 273 | private void writeDouble(byte [] buffer, ref int offset, object value) { 274 | WriteRawLittleEndian64(buffer, offset, (ulong)BitConverter.DoubleToInt64Bits(double.Parse(value.ToString()))); 275 | offset += 8; 276 | } 277 | 278 | //Encode float. 279 | private void writeFloat(byte [] buffer, ref int offset, object value) { 280 | this.writeBytes(buffer, offset, Encoder.encodeFloat(float.Parse(value.ToString()))); 281 | offset += 4; 282 | } 283 | 284 | ////Encode UInt32. 285 | private void writeUInt32(byte [] buffer, ref int offset, object value){ 286 | offset = writeBytes(buffer, offset, Encoder.encodeUInt32(value.ToString())); 287 | } 288 | 289 | //Encode Int32 290 | private void writeInt32(byte [] buffer, ref int offset, object value) { 291 | offset = writeBytes(buffer, offset, Encoder.encodeSInt32(value.ToString())); 292 | } 293 | 294 | //Write bytes to buffer. 295 | private int writeBytes(byte [] buffer, int offset, byte [] bytes){ 296 | for(int i = 0; i < bytes.Length; i++){ 297 | buffer[offset] = bytes[i]; 298 | offset++; 299 | } 300 | return offset; 301 | } 302 | 303 | //Encode tag. 304 | private byte[] encodeTag(string type, int tag) { 305 | int flag = this.util.containType(type); 306 | return Encoder.encodeUInt32((uint)(tag << 3 | flag)); 307 | } 308 | 309 | 310 | private void WriteRawLittleEndian64(byte[] buffer, int offset, ulong value) { 311 | buffer[offset++] = ((byte)value); 312 | buffer[offset++] = ((byte)(value >> 8)); 313 | buffer[offset++] = ((byte)(value >> 16)); 314 | buffer[offset++] = ((byte)(value >> 24)); 315 | buffer[offset++] = ((byte)(value >> 32)); 316 | buffer[offset++] = ((byte)(value >> 40)); 317 | buffer[offset++] = ((byte)(value >> 48)); 318 | buffer[offset++] = ((byte)(value >> 56)); 319 | } 320 | } 321 | } 322 | 323 | -------------------------------------------------------------------------------- /Assets/scripts/pomelo/LitJson/JsonReader.cs: -------------------------------------------------------------------------------- 1 | #region Header 2 | /** 3 | * JsonReader.cs 4 | * Stream-like access to JSON text. 5 | * 6 | * The authors disclaim copyright to this source code. For more details, see 7 | * the COPYING file included with this distribution. 8 | **/ 9 | #endregion 10 | 11 | 12 | using System; 13 | using System.Collections.Generic; 14 | using System.IO; 15 | using System.Text; 16 | 17 | 18 | namespace LitJson 19 | { 20 | public enum JsonToken 21 | { 22 | None, 23 | 24 | ObjectStart, 25 | PropertyName, 26 | ObjectEnd, 27 | 28 | ArrayStart, 29 | ArrayEnd, 30 | 31 | Int, 32 | Long, 33 | Double, 34 | 35 | String, 36 | 37 | Boolean, 38 | Null 39 | } 40 | 41 | 42 | public class JsonReader 43 | { 44 | #region Fields 45 | private static IDictionary> parse_table; 46 | 47 | private Stack automaton_stack; 48 | private int current_input; 49 | private int current_symbol; 50 | private bool end_of_json; 51 | private bool end_of_input; 52 | private Lexer lexer; 53 | private bool parser_in_string; 54 | private bool parser_return; 55 | private bool read_started; 56 | private TextReader reader; 57 | private bool reader_is_owned; 58 | private bool skip_non_members; 59 | private object token_value; 60 | private JsonToken token; 61 | #endregion 62 | 63 | 64 | #region Public Properties 65 | public bool AllowComments { 66 | get { return lexer.AllowComments; } 67 | set { lexer.AllowComments = value; } 68 | } 69 | 70 | public bool AllowSingleQuotedStrings { 71 | get { return lexer.AllowSingleQuotedStrings; } 72 | set { lexer.AllowSingleQuotedStrings = value; } 73 | } 74 | 75 | public bool SkipNonMembers { 76 | get { return skip_non_members; } 77 | set { skip_non_members = value; } 78 | } 79 | 80 | public bool EndOfInput { 81 | get { return end_of_input; } 82 | } 83 | 84 | public bool EndOfJson { 85 | get { return end_of_json; } 86 | } 87 | 88 | public JsonToken Token { 89 | get { return token; } 90 | } 91 | 92 | public object Value { 93 | get { return token_value; } 94 | } 95 | #endregion 96 | 97 | 98 | #region Constructors 99 | static JsonReader () 100 | { 101 | PopulateParseTable (); 102 | } 103 | 104 | public JsonReader (string json_text) : 105 | this (new StringReader (json_text), true) 106 | { 107 | } 108 | 109 | public JsonReader (TextReader reader) : 110 | this (reader, false) 111 | { 112 | } 113 | 114 | private JsonReader (TextReader reader, bool owned) 115 | { 116 | if (reader == null) 117 | throw new ArgumentNullException ("reader"); 118 | 119 | parser_in_string = false; 120 | parser_return = false; 121 | 122 | read_started = false; 123 | automaton_stack = new Stack (); 124 | automaton_stack.Push ((int) ParserToken.End); 125 | automaton_stack.Push ((int) ParserToken.Text); 126 | 127 | lexer = new Lexer (reader); 128 | 129 | end_of_input = false; 130 | end_of_json = false; 131 | 132 | skip_non_members = true; 133 | 134 | this.reader = reader; 135 | reader_is_owned = owned; 136 | } 137 | #endregion 138 | 139 | 140 | #region Static Methods 141 | private static void PopulateParseTable () 142 | { 143 | // See section A.2. of the manual for details 144 | parse_table = new Dictionary> (); 145 | 146 | TableAddRow (ParserToken.Array); 147 | TableAddCol (ParserToken.Array, '[', 148 | '[', 149 | (int) ParserToken.ArrayPrime); 150 | 151 | TableAddRow (ParserToken.ArrayPrime); 152 | TableAddCol (ParserToken.ArrayPrime, '"', 153 | (int) ParserToken.Value, 154 | 155 | (int) ParserToken.ValueRest, 156 | ']'); 157 | TableAddCol (ParserToken.ArrayPrime, '[', 158 | (int) ParserToken.Value, 159 | (int) ParserToken.ValueRest, 160 | ']'); 161 | TableAddCol (ParserToken.ArrayPrime, ']', 162 | ']'); 163 | TableAddCol (ParserToken.ArrayPrime, '{', 164 | (int) ParserToken.Value, 165 | (int) ParserToken.ValueRest, 166 | ']'); 167 | TableAddCol (ParserToken.ArrayPrime, (int) ParserToken.Number, 168 | (int) ParserToken.Value, 169 | (int) ParserToken.ValueRest, 170 | ']'); 171 | TableAddCol (ParserToken.ArrayPrime, (int) ParserToken.True, 172 | (int) ParserToken.Value, 173 | (int) ParserToken.ValueRest, 174 | ']'); 175 | TableAddCol (ParserToken.ArrayPrime, (int) ParserToken.False, 176 | (int) ParserToken.Value, 177 | (int) ParserToken.ValueRest, 178 | ']'); 179 | TableAddCol (ParserToken.ArrayPrime, (int) ParserToken.Null, 180 | (int) ParserToken.Value, 181 | (int) ParserToken.ValueRest, 182 | ']'); 183 | 184 | TableAddRow (ParserToken.Object); 185 | TableAddCol (ParserToken.Object, '{', 186 | '{', 187 | (int) ParserToken.ObjectPrime); 188 | 189 | TableAddRow (ParserToken.ObjectPrime); 190 | TableAddCol (ParserToken.ObjectPrime, '"', 191 | (int) ParserToken.Pair, 192 | (int) ParserToken.PairRest, 193 | '}'); 194 | TableAddCol (ParserToken.ObjectPrime, '}', 195 | '}'); 196 | 197 | TableAddRow (ParserToken.Pair); 198 | TableAddCol (ParserToken.Pair, '"', 199 | (int) ParserToken.String, 200 | ':', 201 | (int) ParserToken.Value); 202 | 203 | TableAddRow (ParserToken.PairRest); 204 | TableAddCol (ParserToken.PairRest, ',', 205 | ',', 206 | (int) ParserToken.Pair, 207 | (int) ParserToken.PairRest); 208 | TableAddCol (ParserToken.PairRest, '}', 209 | (int) ParserToken.Epsilon); 210 | 211 | TableAddRow (ParserToken.String); 212 | TableAddCol (ParserToken.String, '"', 213 | '"', 214 | (int) ParserToken.CharSeq, 215 | '"'); 216 | 217 | TableAddRow (ParserToken.Text); 218 | TableAddCol (ParserToken.Text, '[', 219 | (int) ParserToken.Array); 220 | TableAddCol (ParserToken.Text, '{', 221 | (int) ParserToken.Object); 222 | 223 | TableAddRow (ParserToken.Value); 224 | TableAddCol (ParserToken.Value, '"', 225 | (int) ParserToken.String); 226 | TableAddCol (ParserToken.Value, '[', 227 | (int) ParserToken.Array); 228 | TableAddCol (ParserToken.Value, '{', 229 | (int) ParserToken.Object); 230 | TableAddCol (ParserToken.Value, (int) ParserToken.Number, 231 | (int) ParserToken.Number); 232 | TableAddCol (ParserToken.Value, (int) ParserToken.True, 233 | (int) ParserToken.True); 234 | TableAddCol (ParserToken.Value, (int) ParserToken.False, 235 | (int) ParserToken.False); 236 | TableAddCol (ParserToken.Value, (int) ParserToken.Null, 237 | (int) ParserToken.Null); 238 | 239 | TableAddRow (ParserToken.ValueRest); 240 | TableAddCol (ParserToken.ValueRest, ',', 241 | ',', 242 | (int) ParserToken.Value, 243 | (int) ParserToken.ValueRest); 244 | TableAddCol (ParserToken.ValueRest, ']', 245 | (int) ParserToken.Epsilon); 246 | } 247 | 248 | private static void TableAddCol (ParserToken row, int col, 249 | params int[] symbols) 250 | { 251 | parse_table[(int) row].Add (col, symbols); 252 | } 253 | 254 | private static void TableAddRow (ParserToken rule) 255 | { 256 | parse_table.Add ((int) rule, new Dictionary ()); 257 | } 258 | #endregion 259 | 260 | 261 | #region Private Methods 262 | private void ProcessNumber (string number) 263 | { 264 | if (number.IndexOf ('.') != -1 || 265 | number.IndexOf ('e') != -1 || 266 | number.IndexOf ('E') != -1) { 267 | 268 | double n_double; 269 | if (Double.TryParse (number, out n_double)) { 270 | token = JsonToken.Double; 271 | token_value = n_double; 272 | 273 | return; 274 | } 275 | } 276 | 277 | int n_int32; 278 | if (Int32.TryParse (number, out n_int32)) { 279 | token = JsonToken.Int; 280 | token_value = n_int32; 281 | 282 | return; 283 | } 284 | 285 | long n_int64; 286 | if (Int64.TryParse (number, out n_int64)) { 287 | token = JsonToken.Long; 288 | token_value = n_int64; 289 | 290 | return; 291 | } 292 | 293 | ulong n_uint64; 294 | if (UInt64.TryParse(number, out n_uint64)) 295 | { 296 | token = JsonToken.Long; 297 | token_value = n_uint64; 298 | 299 | return; 300 | } 301 | 302 | // Shouldn't happen, but just in case, return something 303 | token = JsonToken.Int; 304 | token_value = 0; 305 | } 306 | 307 | private void ProcessSymbol () 308 | { 309 | if (current_symbol == '[') { 310 | token = JsonToken.ArrayStart; 311 | parser_return = true; 312 | 313 | } else if (current_symbol == ']') { 314 | token = JsonToken.ArrayEnd; 315 | parser_return = true; 316 | 317 | } else if (current_symbol == '{') { 318 | token = JsonToken.ObjectStart; 319 | parser_return = true; 320 | 321 | } else if (current_symbol == '}') { 322 | token = JsonToken.ObjectEnd; 323 | parser_return = true; 324 | 325 | } else if (current_symbol == '"') { 326 | if (parser_in_string) { 327 | parser_in_string = false; 328 | 329 | parser_return = true; 330 | 331 | } else { 332 | if (token == JsonToken.None) 333 | token = JsonToken.String; 334 | 335 | parser_in_string = true; 336 | } 337 | 338 | } else if (current_symbol == (int) ParserToken.CharSeq) { 339 | token_value = lexer.StringValue; 340 | 341 | } else if (current_symbol == (int) ParserToken.False) { 342 | token = JsonToken.Boolean; 343 | token_value = false; 344 | parser_return = true; 345 | 346 | } else if (current_symbol == (int) ParserToken.Null) { 347 | token = JsonToken.Null; 348 | parser_return = true; 349 | 350 | } else if (current_symbol == (int) ParserToken.Number) { 351 | ProcessNumber (lexer.StringValue); 352 | 353 | parser_return = true; 354 | 355 | } else if (current_symbol == (int) ParserToken.Pair) { 356 | token = JsonToken.PropertyName; 357 | 358 | } else if (current_symbol == (int) ParserToken.True) { 359 | token = JsonToken.Boolean; 360 | token_value = true; 361 | parser_return = true; 362 | 363 | } 364 | } 365 | 366 | private bool ReadToken () 367 | { 368 | if (end_of_input) 369 | return false; 370 | 371 | lexer.NextToken (); 372 | 373 | if (lexer.EndOfInput) { 374 | Close (); 375 | 376 | return false; 377 | } 378 | 379 | current_input = lexer.Token; 380 | 381 | return true; 382 | } 383 | #endregion 384 | 385 | 386 | public void Close () 387 | { 388 | if (end_of_input) 389 | return; 390 | 391 | end_of_input = true; 392 | end_of_json = true; 393 | 394 | if (reader_is_owned) 395 | reader.Close (); 396 | 397 | reader = null; 398 | } 399 | 400 | public bool Read () 401 | { 402 | if (end_of_input) 403 | return false; 404 | 405 | if (end_of_json) { 406 | end_of_json = false; 407 | automaton_stack.Clear (); 408 | automaton_stack.Push ((int) ParserToken.End); 409 | automaton_stack.Push ((int) ParserToken.Text); 410 | } 411 | 412 | parser_in_string = false; 413 | parser_return = false; 414 | 415 | token = JsonToken.None; 416 | token_value = null; 417 | 418 | if (! read_started) { 419 | read_started = true; 420 | 421 | if (! ReadToken ()) 422 | return false; 423 | } 424 | 425 | 426 | int[] entry_symbols; 427 | 428 | while (true) { 429 | if (parser_return) { 430 | if (automaton_stack.Peek () == (int) ParserToken.End) 431 | end_of_json = true; 432 | 433 | return true; 434 | } 435 | 436 | current_symbol = automaton_stack.Pop (); 437 | 438 | ProcessSymbol (); 439 | 440 | if (current_symbol == current_input) { 441 | if (! ReadToken ()) { 442 | if (automaton_stack.Peek () != (int) ParserToken.End) 443 | throw new JsonException ( 444 | "Input doesn't evaluate to proper JSON text"); 445 | 446 | if (parser_return) 447 | return true; 448 | 449 | return false; 450 | } 451 | 452 | continue; 453 | } 454 | 455 | try { 456 | 457 | entry_symbols = 458 | parse_table[current_symbol][current_input]; 459 | 460 | } catch (KeyNotFoundException e) { 461 | throw new JsonException ((ParserToken) current_input, e); 462 | } 463 | 464 | if (entry_symbols[0] == (int) ParserToken.Epsilon) 465 | continue; 466 | 467 | for (int i = entry_symbols.Length - 1; i >= 0; i--) 468 | automaton_stack.Push (entry_symbols[i]); 469 | } 470 | } 471 | 472 | } 473 | } 474 | -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!129 &1 4 | PlayerSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 11 7 | productGUID: 10f1342a16ca74d41ad1447bc4daaade 8 | AndroidProfiler: 0 9 | defaultScreenOrientation: 0 10 | targetDevice: 2 11 | useOnDemandResources: 0 12 | accelerometerFrequency: 60 13 | companyName: DefaultCompany 14 | productName: Chat 15 | defaultCursor: {fileID: 0} 16 | cursorHotspot: {x: 0, y: 0} 17 | m_SplashScreenBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21176471, a: 1} 18 | m_ShowUnitySplashScreen: 1 19 | m_ShowUnitySplashLogo: 1 20 | m_SplashScreenOverlayOpacity: 1 21 | m_SplashScreenAnimation: 1 22 | m_SplashScreenLogoStyle: 1 23 | m_SplashScreenDrawMode: 0 24 | m_SplashScreenBackgroundAnimationZoom: 1 25 | m_SplashScreenLogoAnimationZoom: 1 26 | m_SplashScreenBackgroundLandscapeAspect: 1 27 | m_SplashScreenBackgroundPortraitAspect: 1 28 | m_SplashScreenBackgroundLandscapeUvs: 29 | serializedVersion: 2 30 | x: 0 31 | y: 0 32 | width: 1 33 | height: 1 34 | m_SplashScreenBackgroundPortraitUvs: 35 | serializedVersion: 2 36 | x: 0 37 | y: 0 38 | width: 1 39 | height: 1 40 | m_SplashScreenLogos: [] 41 | m_SplashScreenBackgroundLandscape: {fileID: 0} 42 | m_SplashScreenBackgroundPortrait: {fileID: 0} 43 | m_VirtualRealitySplashScreen: {fileID: 0} 44 | m_HolographicTrackingLossScreen: {fileID: 0} 45 | defaultScreenWidth: 600 46 | defaultScreenHeight: 400 47 | defaultScreenWidthWeb: 960 48 | defaultScreenHeightWeb: 600 49 | m_StereoRenderingPath: 0 50 | m_ActiveColorSpace: 0 51 | m_MTRendering: 1 52 | m_MobileMTRendering: 0 53 | m_StackTraceTypes: 010000000100000001000000010000000100000001000000 54 | iosShowActivityIndicatorOnLoading: -1 55 | androidShowActivityIndicatorOnLoading: -1 56 | tizenShowActivityIndicatorOnLoading: -1 57 | iosAppInBackgroundBehavior: 0 58 | displayResolutionDialog: 0 59 | iosAllowHTTPDownload: 1 60 | allowedAutorotateToPortrait: 1 61 | allowedAutorotateToPortraitUpsideDown: 1 62 | allowedAutorotateToLandscapeRight: 1 63 | allowedAutorotateToLandscapeLeft: 1 64 | useOSAutorotation: 1 65 | use32BitDisplayBuffer: 1 66 | disableDepthAndStencilBuffers: 0 67 | defaultIsFullScreen: 0 68 | defaultIsNativeResolution: 1 69 | runInBackground: 1 70 | captureSingleScreen: 0 71 | muteOtherAudioSources: 0 72 | Prepare IOS For Recording: 0 73 | submitAnalytics: 1 74 | usePlayerLog: 0 75 | bakeCollisionMeshes: 0 76 | forceSingleInstance: 0 77 | resizableWindow: 0 78 | useMacAppStoreValidation: 0 79 | gpuSkinning: 0 80 | graphicsJobs: 0 81 | xboxPIXTextureCapture: 0 82 | xboxEnableAvatar: 0 83 | xboxEnableKinect: 0 84 | xboxEnableKinectAutoTracking: 0 85 | xboxEnableFitness: 0 86 | visibleInBackground: 1 87 | allowFullscreenSwitch: 1 88 | graphicsJobMode: 0 89 | macFullscreenMode: 2 90 | d3d9FullscreenMode: 1 91 | d3d11FullscreenMode: 1 92 | xboxSpeechDB: 0 93 | xboxEnableHeadOrientation: 0 94 | xboxEnableGuest: 0 95 | xboxEnablePIXSampling: 0 96 | n3dsDisableStereoscopicView: 0 97 | n3dsEnableSharedListOpt: 1 98 | n3dsEnableVSync: 0 99 | ignoreAlphaClear: 0 100 | xboxOneResolution: 0 101 | xboxOneMonoLoggingLevel: 0 102 | xboxOneLoggingLevel: 1 103 | videoMemoryForVertexBuffers: 0 104 | psp2PowerMode: 0 105 | psp2AcquireBGM: 1 106 | wiiUTVResolution: 0 107 | wiiUGamePadMSAA: 1 108 | wiiUSupportsNunchuk: 0 109 | wiiUSupportsClassicController: 0 110 | wiiUSupportsBalanceBoard: 0 111 | wiiUSupportsMotionPlus: 0 112 | wiiUSupportsProController: 0 113 | wiiUAllowScreenCapture: 1 114 | wiiUControllerCount: 0 115 | m_SupportedAspectRatios: 116 | 4:3: 1 117 | 5:4: 1 118 | 16:10: 1 119 | 16:9: 1 120 | Others: 1 121 | bundleVersion: 1.0 122 | preloadedAssets: [] 123 | metroInputSource: 0 124 | m_HolographicPauseOnTrackingLoss: 1 125 | xboxOneDisableKinectGpuReservation: 0 126 | xboxOneEnable7thCore: 0 127 | vrSettings: 128 | cardboard: 129 | depthFormat: 0 130 | enableTransitionView: 0 131 | daydream: 132 | depthFormat: 0 133 | useSustainedPerformanceMode: 0 134 | hololens: 135 | depthFormat: 1 136 | protectGraphicsMemory: 0 137 | useHDRDisplay: 0 138 | applicationIdentifier: 139 | Android: com.pomelo.chat 140 | Standalone: unity.DefaultCompany.Chat 141 | Tizen: com.pomelo.chat 142 | iOS: com.pomelo.chat 143 | tvOS: com.pomelo.chat 144 | buildNumber: 145 | iOS: 0 146 | AndroidBundleVersionCode: 1 147 | AndroidMinSdkVersion: 16 148 | AndroidTargetSdkVersion: 0 149 | AndroidPreferredInstallLocation: 1 150 | aotOptions: 151 | stripEngineCode: 1 152 | iPhoneStrippingLevel: 0 153 | iPhoneScriptCallOptimization: 0 154 | ForceInternetPermission: 0 155 | ForceSDCardPermission: 0 156 | CreateWallpaper: 0 157 | APKExpansionFiles: 0 158 | keepLoadedShadersAlive: 0 159 | StripUnusedMeshComponents: 0 160 | VertexChannelCompressionMask: 161 | serializedVersion: 2 162 | m_Bits: 238 163 | iPhoneSdkVersion: 988 164 | iOSTargetOSVersionString: 6.0 165 | tvOSSdkVersion: 0 166 | tvOSRequireExtendedGameController: 0 167 | tvOSTargetOSVersionString: 9.0 168 | uIPrerenderedIcon: 0 169 | uIRequiresPersistentWiFi: 0 170 | uIRequiresFullScreen: 1 171 | uIStatusBarHidden: 1 172 | uIExitOnSuspend: 0 173 | uIStatusBarStyle: 0 174 | iPhoneSplashScreen: {fileID: 0} 175 | iPhoneHighResSplashScreen: {fileID: 0} 176 | iPhoneTallHighResSplashScreen: {fileID: 0} 177 | iPhone47inSplashScreen: {fileID: 0} 178 | iPhone55inPortraitSplashScreen: {fileID: 0} 179 | iPhone55inLandscapeSplashScreen: {fileID: 0} 180 | iPadPortraitSplashScreen: {fileID: 0} 181 | iPadHighResPortraitSplashScreen: {fileID: 0} 182 | iPadLandscapeSplashScreen: {fileID: 0} 183 | iPadHighResLandscapeSplashScreen: {fileID: 0} 184 | appleTVSplashScreen: {fileID: 0} 185 | tvOSSmallIconLayers: [] 186 | tvOSLargeIconLayers: [] 187 | tvOSTopShelfImageLayers: [] 188 | tvOSTopShelfImageWideLayers: [] 189 | iOSLaunchScreenType: 0 190 | iOSLaunchScreenPortrait: {fileID: 0} 191 | iOSLaunchScreenLandscape: {fileID: 0} 192 | iOSLaunchScreenBackgroundColor: 193 | serializedVersion: 2 194 | rgba: 0 195 | iOSLaunchScreenFillPct: 100 196 | iOSLaunchScreenSize: 100 197 | iOSLaunchScreenCustomXibPath: 198 | iOSLaunchScreeniPadType: 0 199 | iOSLaunchScreeniPadImage: {fileID: 0} 200 | iOSLaunchScreeniPadBackgroundColor: 201 | serializedVersion: 2 202 | rgba: 0 203 | iOSLaunchScreeniPadFillPct: 100 204 | iOSLaunchScreeniPadSize: 100 205 | iOSLaunchScreeniPadCustomXibPath: 206 | iOSDeviceRequirements: [] 207 | iOSURLSchemes: [] 208 | iOSBackgroundModes: 0 209 | iOSMetalForceHardShadows: 0 210 | metalEditorSupport: 1 211 | metalAPIValidation: 1 212 | appleDeveloperTeamID: 213 | iOSManualSigningProvisioningProfileID: 214 | tvOSManualSigningProvisioningProfileID: 215 | appleEnableAutomaticSigning: 0 216 | AndroidTargetDevice: 3 217 | AndroidSplashScreenScale: 0 218 | androidSplashScreen: {fileID: 0} 219 | AndroidKeystoreName: 220 | AndroidKeyaliasName: 221 | AndroidTVCompatibility: 1 222 | AndroidIsGame: 1 223 | androidEnableBanner: 1 224 | m_AndroidBanners: 225 | - width: 320 226 | height: 180 227 | banner: {fileID: 0} 228 | androidGamepadSupportLevel: 0 229 | resolutionDialogBanner: {fileID: 0} 230 | m_BuildTargetIcons: 231 | - m_BuildTarget: 232 | m_Icons: 233 | - serializedVersion: 2 234 | m_Icon: {fileID: 0} 235 | m_Width: 128 236 | m_Height: 128 237 | m_BuildTargetBatching: [] 238 | m_BuildTargetGraphicsAPIs: 239 | - m_BuildTarget: WindowsStandaloneSupport 240 | m_APIs: 01000000 241 | m_Automatic: 0 242 | - m_BuildTarget: AndroidPlayer 243 | m_APIs: 08000000 244 | m_Automatic: 0 245 | m_BuildTargetVRSettings: [] 246 | openGLRequireES31: 0 247 | openGLRequireES31AEP: 0 248 | webPlayerTemplate: APPLICATION:Default 249 | m_TemplateCustomTags: {} 250 | wiiUTitleID: 0005000011000000 251 | wiiUGroupID: 00010000 252 | wiiUCommonSaveSize: 4096 253 | wiiUAccountSaveSize: 2048 254 | wiiUOlvAccessKey: 0 255 | wiiUTinCode: 0 256 | wiiUJoinGameId: 0 257 | wiiUJoinGameModeMask: 0000000000000000 258 | wiiUCommonBossSize: 0 259 | wiiUAccountBossSize: 0 260 | wiiUAddOnUniqueIDs: [] 261 | wiiUMainThreadStackSize: 3072 262 | wiiULoaderThreadStackSize: 1024 263 | wiiUSystemHeapSize: 128 264 | wiiUTVStartupScreen: {fileID: 0} 265 | wiiUGamePadStartupScreen: {fileID: 0} 266 | wiiUDrcBufferDisabled: 0 267 | wiiUProfilerLibPath: 268 | actionOnDotNetUnhandledException: 1 269 | enableInternalProfiler: 0 270 | logObjCUncaughtExceptions: 1 271 | enableCrashReportAPI: 0 272 | cameraUsageDescription: 273 | locationUsageDescription: 274 | microphoneUsageDescription: 275 | switchNetLibKey: 276 | switchSocketMemoryPoolSize: 6144 277 | switchSocketAllocatorPoolSize: 128 278 | switchSocketConcurrencyLimit: 14 279 | switchUseCPUProfiler: 0 280 | switchApplicationID: 0x0005000C10000001 281 | switchNSODependencies: 282 | switchTitleNames_0: 283 | switchTitleNames_1: 284 | switchTitleNames_2: 285 | switchTitleNames_3: 286 | switchTitleNames_4: 287 | switchTitleNames_5: 288 | switchTitleNames_6: 289 | switchTitleNames_7: 290 | switchTitleNames_8: 291 | switchTitleNames_9: 292 | switchTitleNames_10: 293 | switchTitleNames_11: 294 | switchTitleNames_12: 295 | switchTitleNames_13: 296 | switchTitleNames_14: 297 | switchPublisherNames_0: 298 | switchPublisherNames_1: 299 | switchPublisherNames_2: 300 | switchPublisherNames_3: 301 | switchPublisherNames_4: 302 | switchPublisherNames_5: 303 | switchPublisherNames_6: 304 | switchPublisherNames_7: 305 | switchPublisherNames_8: 306 | switchPublisherNames_9: 307 | switchPublisherNames_10: 308 | switchPublisherNames_11: 309 | switchPublisherNames_12: 310 | switchPublisherNames_13: 311 | switchPublisherNames_14: 312 | switchIcons_0: {fileID: 0} 313 | switchIcons_1: {fileID: 0} 314 | switchIcons_2: {fileID: 0} 315 | switchIcons_3: {fileID: 0} 316 | switchIcons_4: {fileID: 0} 317 | switchIcons_5: {fileID: 0} 318 | switchIcons_6: {fileID: 0} 319 | switchIcons_7: {fileID: 0} 320 | switchIcons_8: {fileID: 0} 321 | switchIcons_9: {fileID: 0} 322 | switchIcons_10: {fileID: 0} 323 | switchIcons_11: {fileID: 0} 324 | switchIcons_12: {fileID: 0} 325 | switchIcons_13: {fileID: 0} 326 | switchIcons_14: {fileID: 0} 327 | switchSmallIcons_0: {fileID: 0} 328 | switchSmallIcons_1: {fileID: 0} 329 | switchSmallIcons_2: {fileID: 0} 330 | switchSmallIcons_3: {fileID: 0} 331 | switchSmallIcons_4: {fileID: 0} 332 | switchSmallIcons_5: {fileID: 0} 333 | switchSmallIcons_6: {fileID: 0} 334 | switchSmallIcons_7: {fileID: 0} 335 | switchSmallIcons_8: {fileID: 0} 336 | switchSmallIcons_9: {fileID: 0} 337 | switchSmallIcons_10: {fileID: 0} 338 | switchSmallIcons_11: {fileID: 0} 339 | switchSmallIcons_12: {fileID: 0} 340 | switchSmallIcons_13: {fileID: 0} 341 | switchSmallIcons_14: {fileID: 0} 342 | switchManualHTML: 343 | switchAccessibleURLs: 344 | switchLegalInformation: 345 | switchMainThreadStackSize: 1048576 346 | switchPresenceGroupId: 0x0005000C10000001 347 | switchLogoHandling: 0 348 | switchReleaseVersion: 0 349 | switchDisplayVersion: 1.0.0 350 | switchStartupUserAccount: 0 351 | switchTouchScreenUsage: 0 352 | switchSupportedLanguagesMask: 0 353 | switchLogoType: 0 354 | switchApplicationErrorCodeCategory: 355 | switchUserAccountSaveDataSize: 0 356 | switchUserAccountSaveDataJournalSize: 0 357 | switchAttribute: 0 358 | switchCardSpecSize: 4 359 | switchCardSpecClock: 25 360 | switchRatingsMask: 0 361 | switchRatingsInt_0: 0 362 | switchRatingsInt_1: 0 363 | switchRatingsInt_2: 0 364 | switchRatingsInt_3: 0 365 | switchRatingsInt_4: 0 366 | switchRatingsInt_5: 0 367 | switchRatingsInt_6: 0 368 | switchRatingsInt_7: 0 369 | switchRatingsInt_8: 0 370 | switchRatingsInt_9: 0 371 | switchRatingsInt_10: 0 372 | switchRatingsInt_11: 0 373 | switchLocalCommunicationIds_0: 0x0005000C10000001 374 | switchLocalCommunicationIds_1: 375 | switchLocalCommunicationIds_2: 376 | switchLocalCommunicationIds_3: 377 | switchLocalCommunicationIds_4: 378 | switchLocalCommunicationIds_5: 379 | switchLocalCommunicationIds_6: 380 | switchLocalCommunicationIds_7: 381 | switchParentalControl: 0 382 | switchAllowsScreenshot: 1 383 | switchDataLossConfirmation: 0 384 | ps4NPAgeRating: 12 385 | ps4NPTitleSecret: 386 | ps4NPTrophyPackPath: 387 | ps4ParentalLevel: 1 388 | ps4ContentID: ED1633-NPXX51362_00-0000000000000000 389 | ps4Category: 0 390 | ps4MasterVersion: 01.00 391 | ps4AppVersion: 01.00 392 | ps4AppType: 0 393 | ps4ParamSfxPath: 394 | ps4VideoOutPixelFormat: 0 395 | ps4VideoOutInitialWidth: 1920 396 | ps4VideoOutBaseModeInitialWidth: 1920 397 | ps4VideoOutReprojectionRate: 120 398 | ps4PronunciationXMLPath: 399 | ps4PronunciationSIGPath: 400 | ps4BackgroundImagePath: 401 | ps4StartupImagePath: 402 | ps4SaveDataImagePath: 403 | ps4SdkOverride: 404 | ps4BGMPath: 405 | ps4ShareFilePath: 406 | ps4ShareOverlayImagePath: 407 | ps4PrivacyGuardImagePath: 408 | ps4NPtitleDatPath: 409 | ps4RemotePlayKeyAssignment: -1 410 | ps4RemotePlayKeyMappingDir: 411 | ps4PlayTogetherPlayerCount: 0 412 | ps4EnterButtonAssignment: 1 413 | ps4ApplicationParam1: 0 414 | ps4ApplicationParam2: 0 415 | ps4ApplicationParam3: 0 416 | ps4ApplicationParam4: 0 417 | ps4DownloadDataSize: 0 418 | ps4GarlicHeapSize: 2048 419 | ps4ProGarlicHeapSize: 2560 420 | ps4Passcode: eaoEiIgxIX4a2dREbbSqWy6yhKIDCdJO 421 | ps4UseDebugIl2cppLibs: 0 422 | ps4pnSessions: 1 423 | ps4pnPresence: 1 424 | ps4pnFriends: 1 425 | ps4pnGameCustomData: 1 426 | playerPrefsSupport: 0 427 | restrictedAudioUsageRights: 0 428 | ps4UseResolutionFallback: 0 429 | ps4ReprojectionSupport: 0 430 | ps4UseAudio3dBackend: 0 431 | ps4SocialScreenEnabled: 0 432 | ps4ScriptOptimizationLevel: 3 433 | ps4Audio3dVirtualSpeakerCount: 14 434 | ps4attribCpuUsage: 0 435 | ps4PatchPkgPath: 436 | ps4PatchLatestPkgPath: 437 | ps4PatchChangeinfoPath: 438 | ps4PatchDayOne: 0 439 | ps4attribUserManagement: 0 440 | ps4attribMoveSupport: 0 441 | ps4attrib3DSupport: 0 442 | ps4attribShareSupport: 0 443 | ps4attribExclusiveVR: 0 444 | ps4disableAutoHideSplash: 0 445 | ps4videoRecordingFeaturesUsed: 0 446 | ps4contentSearchFeaturesUsed: 0 447 | ps4attribEyeToEyeDistanceSettingVR: 0 448 | ps4IncludedModules: [] 449 | monoEnv: 450 | psp2Splashimage: {fileID: 0} 451 | psp2NPTrophyPackPath: 452 | psp2NPSupportGBMorGJP: 0 453 | psp2NPAgeRating: 12 454 | psp2NPTitleDatPath: 455 | psp2NPCommsID: 456 | psp2NPCommunicationsID: 457 | psp2NPCommsPassphrase: 458 | psp2NPCommsSig: 459 | psp2ParamSfxPath: 460 | psp2ManualPath: 461 | psp2LiveAreaGatePath: 462 | psp2LiveAreaBackroundPath: 463 | psp2LiveAreaPath: 464 | psp2LiveAreaTrialPath: 465 | psp2PatchChangeInfoPath: 466 | psp2PatchOriginalPackage: 467 | psp2PackagePassword: yapnxrpMCARCr4zdGc81tBDKsMlaZTXC 468 | psp2KeystoneFile: 469 | psp2MemoryExpansionMode: 0 470 | psp2DRMType: 0 471 | psp2StorageType: 0 472 | psp2MediaCapacity: 0 473 | psp2DLCConfigPath: 474 | psp2ThumbnailPath: 475 | psp2BackgroundPath: 476 | psp2SoundPath: 477 | psp2TrophyCommId: 478 | psp2TrophyPackagePath: 479 | psp2PackagedResourcesPath: 480 | psp2SaveDataQuota: 10240 481 | psp2ParentalLevel: 1 482 | psp2ShortTitle: Not Set 483 | psp2ContentID: IV0000-ABCD12345_00-0123456789ABCDEF 484 | psp2Category: 0 485 | psp2MasterVersion: 01.00 486 | psp2AppVersion: 01.00 487 | psp2TVBootMode: 0 488 | psp2EnterButtonAssignment: 2 489 | psp2TVDisableEmu: 0 490 | psp2AllowTwitterDialog: 1 491 | psp2Upgradable: 0 492 | psp2HealthWarning: 0 493 | psp2UseLibLocation: 0 494 | psp2InfoBarOnStartup: 0 495 | psp2InfoBarColor: 0 496 | psp2UseDebugIl2cppLibs: 0 497 | psmSplashimage: {fileID: 0} 498 | splashScreenBackgroundSourceLandscape: {fileID: 0} 499 | splashScreenBackgroundSourcePortrait: {fileID: 0} 500 | spritePackerPolicy: 501 | webGLMemorySize: 256 502 | webGLExceptionSupport: 1 503 | webGLNameFilesAsHashes: 0 504 | webGLDataCaching: 0 505 | webGLDebugSymbols: 0 506 | webGLEmscriptenArgs: 507 | webGLModulesDirectory: 508 | webGLTemplate: APPLICATION:Default 509 | webGLAnalyzeBuildSize: 0 510 | webGLUseEmbeddedResources: 0 511 | webGLUseWasm: 0 512 | webGLCompressionFormat: 1 513 | scriptingDefineSymbols: {} 514 | platformArchitecture: {} 515 | scriptingBackend: 516 | Android: 1 517 | Standalone: 0 518 | incrementalIl2cppBuild: {} 519 | additionalIl2CppArgs: 520 | apiCompatibilityLevelPerPlatform: {} 521 | m_RenderingPath: 1 522 | m_MobileRenderingPath: 1 523 | metroPackageName: 524 | metroPackageVersion: 525 | metroCertificatePath: 526 | metroCertificatePassword: 527 | metroCertificateSubject: 528 | metroCertificateIssuer: 529 | metroCertificateNotAfter: 0000000000000000 530 | metroApplicationDescription: 531 | wsaImages: {} 532 | metroTileShortName: 533 | metroCommandLineArgsFile: 534 | metroTileShowName: 0 535 | metroMediumTileShowName: 0 536 | metroLargeTileShowName: 0 537 | metroWideTileShowName: 0 538 | metroDefaultTileSize: 1 539 | metroTileForegroundText: 1 540 | metroTileBackgroundColor: {r: 0, g: 0, b: 0, a: 1} 541 | metroSplashScreenBackgroundColor: {r: 0, g: 0, b: 0, a: 1} 542 | metroSplashScreenUseBackgroundColor: 0 543 | platformCapabilities: {} 544 | metroFTAName: 545 | metroFTAFileTypes: [] 546 | metroProtocolName: 547 | metroCompilationOverrides: 1 548 | tizenProductDescription: 549 | tizenProductURL: 550 | tizenSigningProfileName: 551 | tizenGPSPermissions: 0 552 | tizenMicrophonePermissions: 0 553 | tizenDeploymentTarget: 554 | tizenDeploymentTargetType: -1 555 | tizenMinOSVersion: 1 556 | n3dsUseExtSaveData: 0 557 | n3dsCompressStaticMem: 1 558 | n3dsExtSaveDataNumber: 0x12345 559 | n3dsStackSize: 131072 560 | n3dsTargetPlatform: 2 561 | n3dsRegion: 7 562 | n3dsMediaSize: 0 563 | n3dsLogoStyle: 3 564 | n3dsTitle: GameName 565 | n3dsProductCode: 566 | n3dsApplicationId: 0xFF3FF 567 | stvDeviceAddress: 568 | stvProductDescription: 569 | stvProductAuthor: 570 | stvProductAuthorEmail: 571 | stvProductLink: 572 | stvProductCategory: 0 573 | XboxOneProductId: 574 | XboxOneUpdateKey: 575 | XboxOneSandboxId: 576 | XboxOneContentId: 577 | XboxOneTitleId: 578 | XboxOneSCId: 579 | XboxOneGameOsOverridePath: 580 | XboxOnePackagingOverridePath: 581 | XboxOneAppManifestOverridePath: 582 | XboxOnePackageEncryption: 0 583 | XboxOnePackageUpdateGranularity: 2 584 | XboxOneDescription: 585 | XboxOneLanguage: 586 | - enus 587 | XboxOneCapability: [] 588 | XboxOneGameRating: {} 589 | XboxOneIsContentPackage: 0 590 | XboxOneEnableGPUVariability: 0 591 | XboxOneSockets: {} 592 | XboxOneSplashScreen: {fileID: 0} 593 | XboxOneAllowedProductIds: [] 594 | XboxOnePersistentLocalStorageSize: 0 595 | xboxOneScriptCompiler: 0 596 | vrEditorSettings: 597 | daydream: 598 | daydreamIconForeground: {fileID: 0} 599 | daydreamIconBackground: {fileID: 0} 600 | cloudServicesEnabled: {} 601 | facebookSdkVersion: 7.9.1 602 | apiCompatibilityLevel: 1 603 | cloudProjectId: 604 | projectName: 605 | organizationId: 606 | cloudEnabled: 0 607 | enableNewInputSystem: 0 608 | --------------------------------------------------------------------------------