备份CatanBuilding瘦身独立工程

This commit is contained in:
JSD\13999
2026-05-26 16:15:54 +08:00
commit 2d0e6a61b7
12001 changed files with 2431925 additions and 0 deletions

View File

@@ -0,0 +1,112 @@
using System.Collections.Generic;
namespace com.fpnn.rtm
{
internal class DuplicatedMessageFilter
{
private enum MessageCategories
{
P2PMessageType,
GroupMessageType,
RoomMessageType,
BroadcastMessageType,
}
private struct MessageIdUnit
{
public MessageCategories messageType;
public long bizId;
public long uid;
public long mid;
}
private const int expireSeconds = 20 * 60;
private Dictionary<MessageIdUnit, long> midCache;
private object interLocker;
public DuplicatedMessageFilter()
{
midCache = new Dictionary<MessageIdUnit, long>();
interLocker = new object();
}
public bool CheckP2PMessage(long uid, long mid, long to)
{
MessageIdUnit unit;
unit.messageType = MessageCategories.P2PMessageType;
unit.bizId = to;
unit.uid = uid;
unit.mid = mid;
return CheckMessageIdUnit(unit);
}
public bool CheckGroupMessage(long groupId, long uid, long mid)
{
MessageIdUnit unit;
unit.messageType = MessageCategories.GroupMessageType;
unit.bizId = groupId;
unit.uid = uid;
unit.mid = mid;
return CheckMessageIdUnit(unit);
}
public bool CheckRoomMessage(long roomId, long uid, long mid)
{
MessageIdUnit unit;
unit.messageType = MessageCategories.RoomMessageType;
unit.bizId = roomId;
unit.uid = uid;
unit.mid = mid;
return CheckMessageIdUnit(unit);
}
public bool CheckBroadcastMessage(long uid, long mid)
{
MessageIdUnit unit;
unit.messageType = MessageCategories.BroadcastMessageType;
unit.bizId = 0;
unit.uid = uid;
unit.mid = mid;
return CheckMessageIdUnit(unit);
}
private bool CheckMessageIdUnit(MessageIdUnit unit)
{
long now = ClientEngine.GetCurrentSeconds();
lock (interLocker)
{
if (midCache.ContainsKey(unit))
{
midCache[unit] = now;
return false;
}
else
{
midCache.Add(unit, now);
ClearExpired(now);
return true;
}
}
}
private void ClearExpired(long now)
{
now -= expireSeconds;
List<MessageIdUnit> expired = new List<MessageIdUnit>();
foreach (KeyValuePair<MessageIdUnit, long> kvp in midCache)
{
if (kvp.Value <= now)
expired.Add(kvp.Key);
}
foreach (MessageIdUnit unit in expired)
midCache.Remove(unit);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d587adca036a740d1a115f4e4f01f2f7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,62 @@
using System;
namespace com.fpnn.rtm
{
public static class ErrorCode
{
public const int RTM_EC_INVALID_PID_OR_UID = 200001;
public const int RTM_EC_INVALID_PID_OR_SIGN = 200002;
public const int RTM_EC_INVALID_FILE_OR_SIGN_OR_TOKEN = 200003;
public const int RTM_EC_ATTRS_WITHOUT_SIGN_OR_EXT = 200004;
public const int RTM_EC_INVALID_MTYPE = 200005;
public const int RTM_EC_SAME_SIGN = 200006;
public const int RTM_EC_INVALID_FILE_MTYPE = 200007;
public const int RTM_EC_INVALID_SERFVER_TIME = 200008;
public const int RTM_EC_FREQUENCY_LIMITED = 200010;
public const int RTM_EC_REFRESH_SCREEN_LIMITED = 200011;
public const int RTM_EC_KICKOUT_SELF = 200012;
public const int RTM_EC_FORBIDDEN_METHOD = 200020;
public const int RTM_EC_PERMISSION_DENIED = 200021;
public const int RTM_EC_UNAUTHORIZED = 200022;
public const int RTM_EC_DUPLCATED_AUTH = 200023;
public const int RTM_EC_AUTH_DENIED = 200024;
public const int RTM_EC_ADMIN_LOGIN = 200025;
public const int RTM_EC_ADMIN_ONLY = 200026;
public const int RTM_EC_INVALID_AUTH_TOEKN = 200027;
public const int RTM_EC_LARGE_MESSAGE_OR_ATTRS = 200030;
public const int RTM_EC_LARGE_FILE_OR_ATTRS = 200031;
public const int RTM_EC_TOO_MANY_ITEMS_IN_PARAMETERS = 200032;
public const int RTM_EC_EMPTY_PARAMETER = 200033;
public const int RTM_EC_INVALID_PARAMETER = 200034;
public const int RTM_EC_LARGE_DATA = 200035;
public const int RTM_EC_NOT_IN_ROOM = 200040;
public const int RTM_EC_NOT_GROUP_MEMBER = 200041;
public const int RTM_EC_MAX_GROUP_MEMBER_COUNT = 200042;
public const int RTM_EC_NOT_FRIEND = 200043;
public const int RTM_EC_BANNED_IN_GROUP = 200044;
public const int RTM_EC_BANNED_IN_ROOM = 200045;
public const int RTM_EC_EMPTY_GROUP = 200046;
public const int RTM_EC_MAX_ROOM_COUNT = 200047;
public const int RTM_EC_MAX_FRIEND_COUNT = 200048;
public const int RTM_EC_BLOCKED_USER = 200049;
public const int RTM_EC_UNSUPPORTED_LANGUAGE = 200050;
public const int RTM_EC_EMPTY_TRANSLATION = 200051;
public const int RTM_EC_SEND_TO_SELF = 200052;
public const int RTM_EC_DUPLCATED_MID = 200053;
public const int RTM_EC_SENSITIVE_WORDS = 200054;
public const int RTM_EC_NOT_ONLINE = 200055;
public const int RTM_EC_TRANSLATION_ERROR = 200056;
public const int RTM_EC_PROFANITY_STOP = 200057;
public const int RTM_EC_NO_CONFIG_IN_CONSOLE = 200060;
public const int RTM_EC_UNSUPPORTED_TRASNCRIBE_TYPE = 200061;
public const int RTM_EC_BLOCK_USER = 200062;
public const int RTM_EC_MESSAGE_NOT_FOUND = 200070;
public const int RTM_EC_UNKNOWN_ERROR = 200999;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1ba4bcf6a86f2433abd07d015223bda7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
namespace com.fpnn.rtm
{
public class MidGenerator
{
static private ushort order = 0;
static private object interLocker = new object();
static public long Gen()
{
long baseId = ClientEngine.GetCurrentMilliseconds() << 16;
lock (interLocker)
{
return baseId + ++order;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e74c15297ec2642c086cd61b71bc402a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,149 @@
using System;
using System.Collections.Generic;
using com.fpnn.msgpack;
namespace com.fpnn.rtm
{
public class InvalidAudioDataException : Exception
{
public InvalidAudioDataException(string message) : base(message) { }
public InvalidAudioDataException(String message, Exception ex) : base(message, ex) { }
}
public class RTMAudioData
{
public static string DefaultCodec = "amr-wb";
private string codecType;
private string lang;
private readonly byte[] audio; // Current is AMR-WB
private float[] pcmData; // Original PCM data
private long duration; // Duration in ms
private int frequency;
private int lengthSamples;
public RTMAudioData(byte[] audio, float[] pcmData, string codecType, string lang, long duration, int lengthSamples, int frequency)
{
this.audio = audio;
this.pcmData = pcmData;
this.codecType = codecType;
this.lang = lang;
this.duration = duration;
this.lengthSamples = lengthSamples;
this.frequency = frequency;
}
public RTMAudioData(byte[] audio, FileInfo fileInfo)
{
codecType = DefaultCodec;
lang = fileInfo.language;
duration = fileInfo.duration;
this.audio = audio;
frequency = AudioRecorder.RECORD_SAMPLE_RATE;
ParseAudioData();
}
public RTMAudioData(byte[] audio, string language, long duration)
{
codecType = DefaultCodec;
lang = language;
this.duration = duration;
this.audio = audio;
frequency = AudioRecorder.RECORD_SAMPLE_RATE;
ParseAudioData();
}
private void ParseAudioData()
{
byte[] wavBuffer = AudioConvert.ConvertToWav(audio);
if (wavBuffer == null || wavBuffer.Length < 23)
{
throw new InvalidAudioDataException("Invalid audio data, convert failed.");
}
int channelCount = wavBuffer[22];
int pos = 12;
while(! (wavBuffer.Length > pos+3 && wavBuffer[pos] == 100 && wavBuffer[pos+1] == 97 && wavBuffer[pos+2] == 116 && wavBuffer[pos+3] == 97)) {
pos += 4;
int chunkSize = wavBuffer[pos] + wavBuffer[pos + 1] * 256 + wavBuffer[pos + 2] * 65536 + wavBuffer[pos + 3] * 16777216;
pos += 4 + chunkSize;
}
pos += 8;
lengthSamples = (wavBuffer.Length - pos) /2 ;
pcmData = new float[lengthSamples];
int idx = 0;
while (pos < wavBuffer.Length) {
pcmData[idx] = BytesToFloat(wavBuffer[pos], wavBuffer[pos + 1]);
pos += 2;
idx++;
}
}
private static float BytesToFloat(byte firstByte, byte secondByte) {
short s = (short)((secondByte << 8) | firstByte);
return s / 32768.0F;
}
public byte[] Audio
{
get
{
return audio;
}
}
public float[] PcmData
{
get
{
return pcmData;
}
}
public long Duration
{
get
{
return duration;
}
}
public string Language
{
get
{
return lang;
}
}
public string CodecType
{
get
{
return codecType;
}
}
public int LengthSamples
{
get
{
return lengthSamples;
}
}
public int Frequency
{
get
{
return frequency;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b9dbf0784ae094a7d8f9a65e62f1d409
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace com.fpnn.rtm
{
public class RTMCallbackQueue : MonoBehaviour
{
private static Queue<Action> actionQueue = new Queue<Action>();
public void Clear()
{
lock (actionQueue)
{
actionQueue.Clear();
}
}
public void PostAction(Action action)
{
lock (actionQueue)
{
actionQueue.Enqueue(action);
}
}
private Action GetAction()
{
lock (actionQueue)
{
Action action = actionQueue.Dequeue();
return action;
}
}
void Update()
{
while (actionQueue.Count > 0)
{
Action action = GetAction();
action();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 482ae1cf95d6746d8bc2284c1f4c61b2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 51ea35e78aa9447579e1f633b4b7f74e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,522 @@
using System;
using System.Collections.Generic;
using com.fpnn.proto;
namespace com.fpnn.rtm
{
public partial class RTMClient
{
private List<Conversation> BuildP2PConversationList(List<long> conversations, List<int> unreads, List<object> messages)
{
List<Conversation> conversationList = new List<Conversation>();
int i = 0;
foreach (List<object> items in messages)
{
HistoryMessage message = new HistoryMessage();
message.cursorId = (long)Convert.ChangeType(items[0], TypeCode.Int64);
if (message.cursorId != 0)
{
long direction = (long)Convert.ChangeType(items[1], TypeCode.Int64);
if (direction == 1)
{
message.fromUid = Uid;
message.toId = conversations[i];
}
else
{
message.fromUid = conversations[i];
message.toId = Uid;
}
message.messageType = (byte)Convert.ChangeType(items[2], TypeCode.Byte);
message.messageId = (long)Convert.ChangeType(items[3], TypeCode.Int64);
if (!CheckBinaryType(items[5]))
message.stringMessage = (string)Convert.ChangeType(items[5], TypeCode.String);
else
message.binaryMessage = (byte[])items[5];
message.attrs = (string)Convert.ChangeType(items[6], TypeCode.String);
message.modifiedTime = (long)Convert.ChangeType(items[7], TypeCode.Int64);
if (message.messageType >= 40 && message.messageType <= 50)
RTMClient.BuildFileInfo(message, errorRecorder);
}
Conversation conversation = new Conversation();
conversation.id = conversations[i];
conversation.conversationType = ConversationType.P2P;
conversation.unreadCount = unreads[i];
conversation.lastMessage = message;
conversationList.Add(conversation);
i += 1;
}
return conversationList;
}
public bool GetP2PConversationList(Action<List<Conversation>, int> callback, HashSet<byte> mTypes = null, long startTime = 0, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getp2pconversationlist");
if (mTypes != null)
quest.Param("mtypes", mTypes);
if (startTime != 0)
quest.Param("mtime", startTime);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
List<Conversation> conversationList = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
List<long> conversations = WantLongList(answer, "conversations");
List<int> unreads = GetIntList(answer, "unreads");
List<object> messages = (List<object>)answer.Want("msgs");
conversationList = BuildP2PConversationList(conversations, unreads, messages);
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(conversationList, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetP2PConversationList(out List<Conversation> conversationList, HashSet<byte> mTypes = null, long startTime = 0, int timeout = 0)
{
conversationList = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getp2pconversationlist");
if (mTypes != null)
quest.Param("mtypes", mTypes);
if (startTime != 0)
quest.Param("mtime", startTime);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
List<long> conversations = WantLongList(answer, "conversations");
List<int> unreads = GetIntList(answer, "unreads");
List<object> messages = (List<object>)answer.Want("msgs");
conversationList = BuildP2PConversationList(conversations, unreads, messages);
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
public bool GetP2PUnreadConversationList(Action<List<Conversation>, int> callback, HashSet<byte> mTypes = null, long startTime = 0, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getp2punreadconversationlist");
if (mTypes != null)
quest.Param("mtypes", mTypes);
if (startTime != 0)
quest.Param("mtime", startTime);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
List<Conversation> conversationList = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
List<long> conversations = WantLongList(answer, "conversations");
List<int> unreads = GetIntList(answer, "unreads");
List<object> messages = (List<object>)answer.Want("msgs");
conversationList = BuildP2PConversationList(conversations, unreads, messages);
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(conversationList, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetP2PUnreadConversationList(out List<Conversation> conversationList, HashSet<byte> mTypes = null, long startTime = 0, int timeout = 0)
{
conversationList = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getp2punreadconversationlist");
if (mTypes != null)
quest.Param("mtypes", mTypes);
if (startTime != 0)
quest.Param("mtime", startTime);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
List<long> conversations = WantLongList(answer, "conversations");
List<int> unreads = GetIntList(answer, "unreads");
List<object> messages = (List<object>)answer.Want("msgs");
conversationList = BuildP2PConversationList(conversations, unreads, messages);
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
private List<Conversation> BuildGroupConversationList(List<long> conversations, List<int> unreads, List<object> messages)
{
List<Conversation> conversationList = new List<Conversation>();
int i = 0;
foreach (List<object> items in messages)
{
HistoryMessage message = new HistoryMessage();
message.cursorId = (long)Convert.ChangeType(items[0], TypeCode.Int64);
if (message.cursorId != 0)
{
message.fromUid = (long)Convert.ChangeType(items[1], TypeCode.Int64);
message.toId = conversations[i];
message.messageType = (byte)Convert.ChangeType(items[2], TypeCode.Byte);
message.messageId = (long)Convert.ChangeType(items[3], TypeCode.Int64);
if (!CheckBinaryType(items[5]))
message.stringMessage = (string)Convert.ChangeType(items[5], TypeCode.String);
else
message.binaryMessage = (byte[])items[5];
message.attrs = (string)Convert.ChangeType(items[6], TypeCode.String);
message.modifiedTime = (long)Convert.ChangeType(items[7], TypeCode.Int64);
if (message.messageType >= 40 && message.messageType <= 50)
RTMClient.BuildFileInfo(message, errorRecorder);
}
Conversation conversation = new Conversation();
conversation.id = conversations[i];
conversation.conversationType = ConversationType.GROUP;
conversation.unreadCount = unreads[i];
conversation.lastMessage = message;
conversationList.Add(conversation);
i += 1;
}
return conversationList;
}
public bool GetGroupConversationList(Action<List<Conversation>, int> callback, HashSet<byte> mTypes = null, long startTime = 0, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getgroupconversationlist");
if (mTypes != null)
quest.Param("mtypes", mTypes);
if (startTime != 0)
quest.Param("mtime", startTime);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
List<Conversation> conversationList = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
List<long> conversations = WantLongList(answer, "conversations");
List<int> unreads = GetIntList(answer, "unreads");
List<object> messages = (List<object>)answer.Want("msgs");
conversationList = BuildGroupConversationList(conversations, unreads, messages);
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(conversationList, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetGroupConversationList(out List<Conversation> conversationList, HashSet<byte> mTypes = null, long startTime = 0, int timeout = 0)
{
conversationList = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getgroupconversationlist");
if (mTypes != null)
quest.Param("mtypes", mTypes);
if (startTime != 0)
quest.Param("mtime", startTime);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
List<long> conversations = WantLongList(answer, "conversations");
List<int> unreads = GetIntList(answer, "unreads");
List<object> messages = (List<object>)answer.Want("msgs");
conversationList = BuildGroupConversationList(conversations, unreads, messages);
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
public bool GetGroupUnreadConversationList(Action<List<Conversation>, int> callback, HashSet<byte> mTypes = null, long startTime = 0, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getgroupunreadconversationlist");
if (mTypes != null)
quest.Param("mtypes", mTypes);
if (startTime != 0)
quest.Param("mtime", startTime);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
List<Conversation> conversationList = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
List<long> conversations = WantLongList(answer, "conversations");
List<int> unreads = GetIntList(answer, "unreads");
List<object> messages = (List<object>)answer.Want("msgs");
conversationList = BuildGroupConversationList(conversations, unreads, messages);
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(conversationList, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetGroupUnreadConversationList(out List<Conversation> conversationList, HashSet<byte> mTypes = null, long startTime = 0, int timeout = 0)
{
conversationList = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getgroupunreadconversationlist");
if (mTypes != null)
quest.Param("mtypes", mTypes);
if (startTime != 0)
quest.Param("mtime", startTime);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
List<long> conversations = WantLongList(answer, "conversations");
List<int> unreads = GetIntList(answer, "unreads");
List<object> messages = (List<object>)answer.Want("msgs");
conversationList = BuildGroupConversationList(conversations, unreads, messages);
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
public bool GetUnreadConversationList(Action<List<Conversation>, List<Conversation>, int> callback, bool clear = true, HashSet<byte> mTypes = null, long startTime = 0, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getunreadconversationlist");
quest.Param("clear", clear);
if (mTypes != null)
quest.Param("mtypes", mTypes);
if (startTime != 0)
quest.Param("mtime", startTime);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
List<Conversation> groupConversationList = null;
List<Conversation> p2pConversationList = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
List<long> groupConversations = WantLongList(answer, "groupConversations");
List<int> groupUnreads = GetIntList(answer, "groupUnreads");
List<object> groupMsgs = (List<object>)answer.Want("groupMsgs");
List<long> p2pConversations = WantLongList(answer, "p2pConversations");
List<int> p2pUnreads = GetIntList(answer, "p2pUnreads");
List<object> p2pMsgs = (List<object>)answer.Want("p2pMsgs");
groupConversationList = BuildGroupConversationList(groupConversations, groupUnreads, groupMsgs);
p2pConversationList = BuildP2PConversationList(p2pConversations, p2pUnreads, p2pMsgs);
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(groupConversationList, p2pConversationList, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetUnreadConversationList(out List<Conversation> groupConversationList, out List<Conversation> p2pConversationList, bool clear = true, HashSet<byte> mTypes = null, long startTime = 0, int timeout = 0)
{
groupConversationList = null;
p2pConversationList = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getunreadconversationlist");
quest.Param("clear", clear);
if (mTypes != null)
quest.Param("mtypes", mTypes);
if (startTime != 0)
quest.Param("mtime", startTime);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
List<long> groupConversations = WantLongList(answer, "groupConversations");
List<int> groupUnreads = GetIntList(answer, "groupUnreads");
List<object> groupMsgs = (List<object>)answer.Want("groupMsgs");
List<long> p2pConversations = WantLongList(answer, "p2pConversations");
List<int> p2pUnreads = GetIntList(answer, "p2pUnreads");
List<object> p2pMsgs = (List<object>)answer.Want("p2pMsgs");
groupConversationList = BuildGroupConversationList(groupConversations, groupUnreads, groupMsgs);
p2pConversationList = BuildP2PConversationList(p2pConversations, p2pUnreads, p2pMsgs);
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cd4b0e14ac34c400b8d5eb269cc2e8ea
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,851 @@
using System;
using System.Collections.Generic;
using System.Threading;
using com.fpnn.proto;
using UnityEngine;
namespace com.fpnn.rtm
{
public partial class RTMClient
{
public enum ClientStatus
{
Closed,
Connecting,
Connected
}
//-------------[ Private class for Login ]--------------------------//
private class AutoReloginInfo
{
public bool disabled = true;
public bool canRelogin = false;
public int reloginCount = 0;
public int lastErrorCode = 0;
public long lastReloginMS = 0;
public string token;
public long ts;
public Dictionary<string, string> attr;
public string lang;
public void Login()
{
if (disabled)
{
disabled = false;
reloginCount = 0;
lastErrorCode = 0;
}
else if (canRelogin)
{
reloginCount += 1;
}
lastReloginMS = ClientEngine.GetCurrentMilliseconds();
}
public void LoginSuccessful()
{
canRelogin = true;
reloginCount = 0;
lastErrorCode = 0;
}
public void Disable()
{
disabled = true;
canRelogin = false;
}
}
private class AuthStatusInfo
{
public HashSet<AuthDelegate> authDelegates;
public string token;
public long ts;
public Dictionary<string, string> attr;
public string lang;
public int remainedTimeout;
public long lastActionMsecTimeStamp;
}
//-------------[ Static Fields ]--------------------------//
private static readonly HashSet<int> reloginStopCodes = new HashSet<int>
{
fpnn.ErrorCode.FPNN_EC_CORE_FORBIDDEN,
ErrorCode.RTM_EC_INVALID_PID_OR_UID,
ErrorCode.RTM_EC_INVALID_PID_OR_SIGN,
ErrorCode.RTM_EC_PERMISSION_DENIED,
ErrorCode.RTM_EC_AUTH_DENIED,
ErrorCode.RTM_EC_ADMIN_LOGIN,
ErrorCode.RTM_EC_ADMIN_ONLY,
ErrorCode.RTM_EC_INVALID_AUTH_TOEKN,
ErrorCode.RTM_EC_BLOCKED_USER,
};
//-------------[ Fields ]--------------------------//
private object interLocker;
private static object instanceLocker = new object();
private readonly long projectId;
private readonly long uid;
private ClientStatus status;
private volatile bool requireClose;
private ManualResetEvent syncConnectingEvent;
public volatile int ConnectTimeout;
public volatile int QuestTimeout;
private IRTMMasterProcessor processor;
private TCPClient rtmGate;
private Int64 rtmGateConnectionId;
private AuthStatusInfo authStatsInfo;
private AutoReloginInfo autoReloginInfo;
private RegressiveStrategy regressiveStrategy;
private common.ErrorRecorder errorRecorder;
public RTMClient(string endpoint, long projectId, long uid, RTMQuestProcessor serverPushProcessor, bool autoRelogin = true)
{
interLocker = new object();
this.projectId = projectId;
this.uid = uid;
status = ClientStatus.Closed;
requireClose = false;
syncConnectingEvent = new ManualResetEvent(false);
ConnectTimeout = 0;
QuestTimeout = 0;
RTMMasterProcessor processorCurrent = new RTMMasterProcessor();
processorCurrent.SetProcessor(serverPushProcessor);
processor = processorCurrent;
errorRecorder = RTMConfig.errorRecorder;
if (errorRecorder != null)
processor.SetErrorRecorder(errorRecorder);
BuildRtmGateClient(endpoint);
if (autoRelogin)
{
autoReloginInfo = new AutoReloginInfo();
regressiveStrategy = RTMConfig.globalRegressiveStrategy;
}
}
private void reset(RTMQuestProcessor serverPushProcessor, bool autoRelogin)
{
//status = ClientStatus.Closed;
//requireClose = false;
//ConnectTimeout = 0;
//QuestTimeout = 0;
//rtmGateConnectionId = 0;
//RTMMasterProcessor processorCurrent = new RTMMasterProcessor();
//processorCurrent.SetProcessor(serverPushProcessor);
lock (interLocker)
{
(processor as RTMMasterProcessor).SetProcessor(serverPushProcessor);
//processorCurrent.SetConnectionId(rtmGateConnectionId);
//processor = processorCurrent;
if (errorRecorder != null)
processor.SetErrorRecorder(errorRecorder);
if (autoRelogin)
{
autoReloginInfo = new AutoReloginInfo();
regressiveStrategy = RTMConfig.globalRegressiveStrategy;
}
else
{
autoReloginInfo = null;
regressiveStrategy = null;
}
}
//authStatsInfo = null;
//syncConnectingEvent.Reset();
}
public static RTMClient getInstance(string endpoint, long projectId, long uid, RTMQuestProcessor serverPushProcessor, bool autoRelogin = true)
{
RTMClient client = null;
lock (instanceLocker)
{
client = RTMControlCenter.FetchClient(projectId, uid);
if (client != null)
{
client.reset(serverPushProcessor, autoRelogin);
}
else
{
client = new RTMClient(endpoint, projectId, uid, serverPushProcessor, autoRelogin);
RTMControlCenter.AddClient(projectId, uid, client);
}
}
return client;
}
//-------------[ Fack Fields ]--------------------------//
//-- Obsolete in v.2.2.0
[Obsolete("Property Pid is deprecated, please use ProjectId instead.")]
public long Pid
{
get
{
return projectId;
}
}
public long ProjectId
{
get
{
return projectId;
}
}
public long Uid
{
get
{
return uid;
}
}
public ClientStatus Status
{
get
{
lock (interLocker)
return status;
}
}
public common.ErrorRecorder ErrorRecorder
{
set
{
lock (interLocker)
{
errorRecorder = value;
processor.SetErrorRecorder(errorRecorder);
rtmGate.SetErrorRecorder(errorRecorder);
}
}
}
public bool ConnectionIsAlive()
{
return processor.ConnectionIsAlive();
}
public void SetRegressiveStrategy(RegressiveStrategy strategy)
{
regressiveStrategy = strategy;
}
private TCPClient GetCoreClient()
{
lock (interLocker)
{
if (status == ClientStatus.Connected)
return rtmGate;
else
return null;
}
}
//-------------[ Init Functions ]--------------------------//
private string adjustEndpoint(string originalEndpoint)
{
int idx = originalEndpoint.LastIndexOf(':');
if (idx < 1)
{
if (errorRecorder != null)
errorRecorder.RecordError("Invalid RTM client endpoint: " + originalEndpoint);
return originalEndpoint;
}
string portString = originalEndpoint.Substring(idx + 1);
int port = Convert.ToInt32(portString, 10);
if (port == 13321)
return originalEndpoint;
if (port == 13325)
return originalEndpoint.Substring(0, idx) + ":" + 13321;
if (errorRecorder != null)
errorRecorder.RecordError("Invalid RTM client endpoint: " + originalEndpoint + " (invalid port)");
return originalEndpoint;
}
private void BuildRtmGateClient(string originalEndpoint)
{
rtmGate = TCPClient.Create(adjustEndpoint(originalEndpoint), true);
if (errorRecorder != null)
rtmGate.SetErrorRecorder(errorRecorder);
rtmGate.SetQuestProcessor(processor);
rtmGate.SetConnectionConnectedDelegate((Int64 connectionId, string endpoint, bool connected) => {
if (requireClose)
{
AuthFinish(false, fpnn.ErrorCode.FPNN_EC_CORE_CONNECTION_CLOSED);
return;
}
if (connected)
{
rtmGateConnectionId = connectionId;
RTMControlCenter.RegisterSession(rtmGateConnectionId, this);
Auth(true);
}
else
{
AuthFinish(false, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
}
});
rtmGate.SetConnectionCloseDelegate((Int64 connectionId, string endpoint, bool causedByError) => {
bool trigger = false;
bool isConnecting = false;
bool startRelogin = false;
lock (interLocker)
{
trigger = rtmGateConnectionId == connectionId;
if (trigger)
{
if (status == ClientStatus.Connecting)
isConnecting = true;
else
{
status = ClientStatus.Closed;
rtmGateConnectionId = 0;
}
}
if (autoReloginInfo != null)
{
startRelogin = CheckRelogin();
autoReloginInfo.lastErrorCode = (causedByError ? fpnn.ErrorCode.FPNN_EC_CORE_CONNECTION_CLOSED : fpnn.ErrorCode.FPNN_EC_OK);
}
}
if (trigger)
{
if (isConnecting)
AuthFinish(false, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
else
{
if (startRelogin)
StartRelogin();
else
processor.SessionClosed(causedByError ? fpnn.ErrorCode.FPNN_EC_CORE_UNKNOWN_ERROR : fpnn.ErrorCode.FPNN_EC_OK);
}
}
});
}
public bool CheckRelogin()
{
return autoReloginInfo.disabled == false && autoReloginInfo.canRelogin && RTMControlCenter.NetworkStatus != NetworkType.NetworkType_Unreachable;
}
//-------------[ Auth(Login) processing functions ]--------------------------//
private void AuthFinish(bool authStatus, int errorCode)
{
AuthStatusInfo currInfo;
long currUid;
bool isRelogin = false;
Int64 reservedRtmGateConnectionId = 0;
bool needClose = false;
lock (interLocker)
{
if (status != ClientStatus.Connecting)
return;
if (authStatus)
{
status = ClientStatus.Connected;
}
else
{
status = ClientStatus.Closed;
reservedRtmGateConnectionId = rtmGateConnectionId;
rtmGateConnectionId = 0;
needClose = true;
//-- Reserving rtmGate without closing for quick relogin.
}
if (autoReloginInfo != null)
{
isRelogin = autoReloginInfo.canRelogin;
if (authStatsInfo != null)
{
autoReloginInfo.token = authStatsInfo.token;
autoReloginInfo.ts = authStatsInfo.ts;
autoReloginInfo.attr = authStatsInfo.attr;
autoReloginInfo.lang = authStatsInfo.lang;
}
if (authStatus && !autoReloginInfo.canRelogin)
autoReloginInfo.LoginSuccessful();
}
currInfo = authStatsInfo;
authStatsInfo = null;
currUid = uid;
if (needClose)
rtmGate.Close();
syncConnectingEvent.Set();
}
if (reservedRtmGateConnectionId != 0)
RTMControlCenter.UnregisterSession(reservedRtmGateConnectionId);
if (currInfo != null)
foreach (AuthDelegate callback in currInfo.authDelegates)
callback(projectId, currUid, authStatus, errorCode);
if (authStatus)
processor.BeginCheckPingInterval();
}
private bool AdjustAuthRemainedTimeout()
{
if (authStatsInfo == null)
return false;
long curr = ClientEngine.GetCurrentMilliseconds();
int passSeconds = (int)(curr - authStatsInfo.lastActionMsecTimeStamp) / 1000;
authStatsInfo.lastActionMsecTimeStamp = curr;
authStatsInfo.remainedTimeout -= passSeconds;
if (authStatsInfo.remainedTimeout <= 0)
{
AuthFinish(false, fpnn.ErrorCode.FPNN_EC_CORE_TIMEOUT);
return false;
}
return true;
}
private void Auth(bool checkRemainedTimeout)
{
if (checkRemainedTimeout && !AdjustAuthRemainedTimeout())
return;
processor.SetConnectionId(rtmGateConnectionId);
Quest quest = new Quest("auth");
quest.Param("pid", projectId);
quest.Param("uid", uid);
quest.Param("token", authStatsInfo.token);
if (authStatsInfo.ts != 0)
{
quest.Param("ts", authStatsInfo.ts);
quest.Param("authv", 2);
}
#if UNITY_2017_1_OR_NEWER
quest.Param("version", "Unity-" + RTMConfig.SDKVersion);
#else
quest.Param("version", "C#-" + RTMConfig.SDKVersion);
#endif
if (authStatsInfo.lang.Length > 0)
quest.Param("lang", authStatsInfo.lang);
if (authStatsInfo.attr != null && authStatsInfo.attr.Count > 0)
quest.Param("attrs", authStatsInfo.attr);
int timeout = authStatsInfo.remainedTimeout;
bool status = rtmGate.SendQuest(quest, (Answer answer, int errorCode) => {
if (requireClose)
{
AuthFinish(false, fpnn.ErrorCode.FPNN_EC_CORE_CONNECTION_CLOSED);
return;
}
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
bool ok = answer.Get<bool>("ok", false);
AuthFinish(ok, fpnn.ErrorCode.FPNN_EC_OK);
}
else
{
AuthFinish(false, errorCode);
}
}, timeout);
if (!status)
AuthFinish(false, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
}
//-------------[ Login & System interfaces ]--------------------------//
public bool Login(AuthDelegate callback, string token, int timeout = 0)
{
return Login(callback, token, null, 0, "", timeout);
}
public bool Login(AuthDelegate callback, string token, long ts, int timeout = 0)
{
return Login(callback, token, null, ts, "", timeout);
}
public bool Login(AuthDelegate callback, string token, Dictionary<string, string> attr, TranslateLanguage language = TranslateLanguage.None, int timeout = 0)
{
return Login(callback, token, attr, 0, GetTranslatedLanguage(language), timeout);
}
public bool Login(AuthDelegate callback, string token, long ts, Dictionary<string, string> attr, TranslateLanguage language = TranslateLanguage.None, int timeout = 0)
{
return Login(callback, token, attr, ts, GetTranslatedLanguage(language), timeout);
}
private bool Login(AuthDelegate callback, string token, Dictionary<string, string> attr, long ts = 0, string lang = "", int timeout = 0)
{
lock (interLocker)
{
if (status == ClientStatus.Connected)
{
ClientEngine.RunTask(() =>
{
callback(projectId, uid, true, fpnn.ErrorCode.FPNN_EC_OK);
});
return true;
}
if (status == ClientStatus.Connecting)
{
authStatsInfo.authDelegates.Add(callback);
return true;
}
status = ClientStatus.Connecting;
syncConnectingEvent.Reset();
requireClose = false;
if (autoReloginInfo != null)
autoReloginInfo.Login();
authStatsInfo = new AuthStatusInfo
{
authDelegates = new HashSet<AuthDelegate>() { callback },
remainedTimeout = timeout,
};
authStatsInfo.token = token;
authStatsInfo.ts = ts;
authStatsInfo.attr = attr;
authStatsInfo.lang = lang;
authStatsInfo.lastActionMsecTimeStamp = ClientEngine.GetCurrentMilliseconds();
if (authStatsInfo.remainedTimeout == 0)
authStatsInfo.remainedTimeout = ((ConnectTimeout == 0) ? RTMConfig.globalConnectTimeoutSeconds : ConnectTimeout)
+ ((QuestTimeout == 0) ? RTMConfig.globalQuestTimeoutSeconds : QuestTimeout);
}
rtmGate.AsyncConnect();
return true;
}
public int Login(out bool ok, string token, int timeout = 0)
{
return Login(out ok, token, null, 0, "", timeout);
}
public int Login(out bool ok, string token, long ts, int timeout = 0)
{
return Login(out ok, token, null, ts, "", timeout);
}
private class SyncLoginStatus
{
private ManualResetEvent syncWaiter;
public bool ok;
public int errorCode;
public SyncLoginStatus()
{
syncWaiter = new ManualResetEvent(false);
syncWaiter.Reset();
}
public void Set()
{
syncWaiter.Set();
}
public void Wait()
{
syncWaiter.WaitOne();
}
}
public int Login(out bool ok, string token, Dictionary<string, string> attr, TranslateLanguage language = TranslateLanguage.None, int timeout = 0)
{
return Login(out ok, token, attr, 0, GetTranslatedLanguage(language), timeout);
}
public int Login(out bool ok, string token, long ts, Dictionary<string, string> attr, TranslateLanguage language = TranslateLanguage.None, int timeout = 0)
{
return Login(out ok, token, attr, ts, GetTranslatedLanguage(language), timeout);
}
private int Login(out bool ok, string token, Dictionary<string, string> attr, long ts = 0, string lang = "", int timeout = 0)
{
SyncLoginStatus syncLoginStatus = new SyncLoginStatus();
bool actionBegin = Login((long projectId, long uid, bool authStatus, int errorCode) => {
syncLoginStatus.ok = authStatus;
syncLoginStatus.errorCode = errorCode;
syncLoginStatus.Set();
}, token, attr, ts, lang, timeout);
if (!actionBegin)
{
lock (interLocker)
{
if (status == ClientStatus.Connected)
{
ok = true;
return fpnn.ErrorCode.FPNN_EC_OK;
}
if (status == ClientStatus.Closed)
{
ok = false;
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
}
}
}
syncLoginStatus.Wait();
lock (interLocker)
{
ok = syncLoginStatus.ok;
return syncLoginStatus.errorCode;
}
}
//-------------[ Relogin interfaces ]--------------------------//
private void StartNextRelogin()
{
int regressiveCount = autoReloginInfo.reloginCount;
long interval = regressiveStrategy.maxIntervalSeconds * 1000;
if (regressiveCount > regressiveStrategy.maxRegressvieCount)
{
processor.SessionClosed(autoReloginInfo.lastErrorCode);
return;
}
if (regressiveCount < regressiveStrategy.linearRegressiveCount)
{
interval = interval * regressiveCount / regressiveStrategy.linearRegressiveCount;
}
RTMControlCenter.DelayRelogin(this, ClientEngine.GetCurrentMilliseconds() + interval);
}
internal void StartRelogin()
{
bool launch = processor.ReloginWillStart(autoReloginInfo.lastErrorCode, autoReloginInfo.reloginCount);
if (!launch)
{
processor.SessionClosed(autoReloginInfo.lastErrorCode);
return;
}
bool startLogin = Login((long projectId, long uid, bool successful, int errorCode) =>
{
if (successful)
{
processor.ReloginCompleted(true, false, errorCode, autoReloginInfo.reloginCount);
autoReloginInfo.LoginSuccessful();
return;
}
else
{
bool connected = false;
lock (interLocker)
{
if (status == ClientStatus.Connected)
connected = true;
}
if (connected || errorCode == ErrorCode.RTM_EC_DUPLCATED_AUTH)
{
processor.ReloginCompleted(true, false, fpnn.ErrorCode.FPNN_EC_OK, autoReloginInfo.reloginCount);
autoReloginInfo.LoginSuccessful();
return;
}
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
processor.ReloginCompleted(false, false, ErrorCode.RTM_EC_INVALID_AUTH_TOEKN, autoReloginInfo.reloginCount);
autoReloginInfo.Disable();
processor.SessionClosed(ErrorCode.RTM_EC_INVALID_AUTH_TOEKN);
return;
}
bool stopRetry = reloginStopCodes.Contains(errorCode);
processor.ReloginCompleted(false, !stopRetry, errorCode, autoReloginInfo.reloginCount);
if (stopRetry)
{
autoReloginInfo.Disable();
processor.SessionClosed(errorCode);
return;
}
else
autoReloginInfo.lastErrorCode = errorCode;
StartNextRelogin();
}
},
autoReloginInfo.token, autoReloginInfo.attr, autoReloginInfo.ts, autoReloginInfo.lang);
if (!startLogin && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse == false)
{
ClientStatus connStatus;
lock (interLocker)
{
connStatus = status;
}
if (connStatus == ClientStatus.Connected)
{
processor.ReloginCompleted(true, false, fpnn.ErrorCode.FPNN_EC_OK, autoReloginInfo.reloginCount);
autoReloginInfo.LoginSuccessful();
return;
}
else
{
int errorCode = fpnn.ErrorCode.FPNN_EC_CORE_CONNECTION_CLOSED;
if (connStatus == ClientStatus.Connecting)
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_UNKNOWN_ERROR;
processor.ReloginCompleted(false, true, errorCode, autoReloginInfo.reloginCount);
autoReloginInfo.lastErrorCode = errorCode;
StartNextRelogin();
}
}
}
//-------------[ Close interfaces ]--------------------------//
internal void Close(bool disableRelogin, bool waitConnectingCannelled)
{
bool isConnecting = false;
lock (interLocker)
{
if (disableRelogin && autoReloginInfo != null)
autoReloginInfo.Disable();
if (status == ClientStatus.Closed)
return;
requireClose = true;
if (status == ClientStatus.Connecting)
{
isConnecting = true;
}
else
{
status = ClientStatus.Closed;
}
}
rtmGate.Close();
if (isConnecting && waitConnectingCannelled)
syncConnectingEvent.WaitOne();
}
public void Close(bool waitConnectingCannelled = true)
{
Close(true, waitConnectingCannelled);
}
public bool GetServerTime(Action<long, int> callback, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getservertime");
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
long msec = 0;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{ msec = answer.Get<long>("mts", 0); }
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(msec, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetServerTime(out long msec, int timeout = 0)
{
msec = 0;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getservertime");
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
msec = answer.Get<long>("mts", 0);
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3ac63defd7aef4aa98ea19b883c03a01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,162 @@
using System;
using com.fpnn.proto;
namespace com.fpnn.rtm
{
public partial class RTMClient
{
//===========================[ Data Get ]=========================//
//-- Action<value, errorCode>
public bool DataGet(Action<string, int> callback, string key, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("dataget");
quest.Param("key", key);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
string value = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{ value = answer.Get<string>("val", null); }
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(value, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int DataGet(out string value, string key, int timeout = 0)
{
value = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("dataget");
quest.Param("key", key);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
value = answer.Get<string>("val", null);
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
//===========================[ Data Set ]=========================//
public bool DataSet(DoneDelegate callback, string key, string value, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("dataset");
quest.Param("key", key);
quest.Param("val", value);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int DataSet(string key, string value, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("dataset");
quest.Param("key", key);
quest.Param("val", value);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
//===========================[ Data Delete ]=========================//
public bool DataDelete(DoneDelegate callback, string key, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("datadel");
quest.Param("key", key);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int DataDelete(string key, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("datadel");
quest.Param("key", key);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e67729abad0244684936ae1621abb727
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,145 @@
using System.Collections.Generic;
namespace com.fpnn.rtm
{
public delegate void AuthDelegate(long projectId, long uid, bool successful, int errorCode);
public delegate void DoneDelegate(int errorCode);
public delegate void MessageIdDelegate(long messageId, int errorCode);
public delegate void SendMessageDelegate(long messageId, long mtime, int errorCode);
public class CheckResult
{
public int result;
public List<int> tags;
}
public class TextCheckResult : CheckResult
{
public string text;
public List<string> wlist;
public string language;
}
public class FileInfo
{
//-- Common
public string url; //-- File url
public int size = 0; //-- File size
//-- For image type
public string surl; //-- Thumb url, only for image type.
//-- For RTM audio
public bool isRTMAudio = false;
public string language;
public int duration = 0;
}
public class BaseMessage
{
public byte messageType;
public string stringMessage = null;
public byte[] binaryMessage = null;
public string attrs;
public long modifiedTime;
public FileInfo fileInfo = null;
//-- Compatible with version 2.1.4 and before.
[System.Obsolete("Field mtype is deprecated, please use messageType instead.")]
public byte mtype
{
get { return messageType; }
set { messageType = value; }
}
[System.Obsolete("Field mtime is deprecated, please use modifiedTime instead.")]
public long mtime
{
get { return modifiedTime; }
set { modifiedTime = value; }
}
}
public class RetrievedMessage : BaseMessage
{
public long cursorId;
//-- Compatible with version 2.1.4 and before.
[System.Obsolete("Field id is deprecated, please use cursorId instead.")]
public long id
{
get { return cursorId; }
set { cursorId = value; }
}
}
public class TranslatedInfo
{
public string sourceLanguage;
public string targetLanguage;
public string sourceText;
public string targetText;
}
public class RTMMessage : BaseMessage
{
public long fromUid;
public long toId; //-- xid
public long messageId;
public TranslatedInfo translatedInfo = null;
//-- Compatible with version 2.1.4 and before.
[System.Obsolete("Field mid is deprecated, please use messageId instead.")]
public long mid
{
get { return messageId; }
set { messageId = value; }
}
}
public class HistoryMessage : RTMMessage
{
public long cursorId;
//-- Compatible with version 2.1.4 and before.
[System.Obsolete("Field id is deprecated, please use cursorId instead.")]
public long id
{
get { return cursorId; }
set { cursorId = value; }
}
}
public class HistoryMessageResult
{
public int count;
public long lastCursorId;
public long beginMsec;
public long endMsec;
public List<HistoryMessage> messages;
[System.Obsolete("Field lastId is deprecated, please use lastCursorId instead.")]
public long lastId
{
get { return lastCursorId; }
set { lastCursorId = value; }
}
}
public delegate void HistoryMessageDelegate(int count, long lastCursorId, long beginMsec, long endMsec, List<HistoryMessage> messages, int errorCode);
public enum ConversationType
{
INVALID = 0,
P2P = 1,
GROUP = 2,
ROOM = 3,
}
public class Conversation
{
public long id;
public ConversationType conversationType;
public int unreadCount;
public HistoryMessage lastMessage;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5ccf7ede33da94a6fb81508287c08c1d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
namespace com.fpnn.rtm
{
public partial class RTMClient
{
private Dictionary<string, object> BuildAudioMessageAttrs(RTMAudioData audioData)
{
Dictionary<string, object> rtmAttrs = new Dictionary<string, object>();
rtmAttrs.Add("type", "audiomsg");
rtmAttrs.Add("codec", audioData.CodecType);
rtmAttrs.Add("srate", audioData.Frequency);
rtmAttrs.Add("lang", audioData.Language);
rtmAttrs.Add("duration", audioData.Duration);
return rtmAttrs;
}
//===========================[ Send RTM-Audio File ]=========================//
public bool SendFile(MessageIdDelegate callback, long peerUid, RTMAudioData audioData, string attrs = "", int timeout = 120)
{
return RealSendFile(callback, FileTokenType.P2P, peerUid, (byte)MessageType.AudioFile, audioData.Audio, "", "", attrs, BuildAudioMessageAttrs(audioData), 0, timeout);
}
public int SendFile(out long messageId, long peerUid, RTMAudioData audioData, string attrs = "", int timeout = 120)
{
return RealSendFile(out messageId, out _, FileTokenType.P2P, peerUid, (byte)MessageType.AudioFile, audioData.Audio, "", "", attrs, BuildAudioMessageAttrs(audioData), 0, timeout);
}
public bool SendFile(SendMessageDelegate callback, long peerUid, RTMAudioData audioData, string attrs = "", int timeout = 120)
{
return RealSendFile(callback, FileTokenType.P2P, peerUid, (byte)MessageType.AudioFile, audioData.Audio, "", "", attrs, BuildAudioMessageAttrs(audioData), 0, timeout);
}
public int SendFile(out long messageId, out long mtime, long peerUid, RTMAudioData audioData, string attrs = "", int timeout = 120)
{
return RealSendFile(out messageId, out mtime, FileTokenType.P2P, peerUid, (byte)MessageType.AudioFile, audioData.Audio, "", "", attrs, BuildAudioMessageAttrs(audioData), 0, timeout);
}
//===========================[ Send RTM-Audio Group File ]=========================//
public bool SendGroupFile(MessageIdDelegate callback, long groupId, RTMAudioData audioData, string attrs = "", int timeout = 120)
{
return RealSendFile(callback, FileTokenType.Group, groupId, (byte)MessageType.AudioFile, audioData.Audio, "", "", attrs, BuildAudioMessageAttrs(audioData), 0, timeout);
}
public int SendGroupFile(out long messageId, long groupId, RTMAudioData audioData, string attrs = "", int timeout = 120)
{
return RealSendFile(out messageId, out _, FileTokenType.Group, groupId, (byte)MessageType.AudioFile, audioData.Audio, "", "", attrs, BuildAudioMessageAttrs(audioData), 0, timeout);
}
public bool SendGroupFile(SendMessageDelegate callback, long groupId, RTMAudioData audioData, string attrs = "", int timeout = 120)
{
return RealSendFile(callback, FileTokenType.Group, groupId, (byte)MessageType.AudioFile, audioData.Audio, "", "", attrs, BuildAudioMessageAttrs(audioData), 0, timeout);
}
public int SendGroupFile(out long messageId, out long mtime, long groupId, RTMAudioData audioData, string attrs = "", int timeout = 120)
{
return RealSendFile(out messageId, out mtime, FileTokenType.Group, groupId, (byte)MessageType.AudioFile, audioData.Audio, "", "", attrs, BuildAudioMessageAttrs(audioData), 0, timeout);
}
//===========================[ Send RTM-Audio Room File ]=========================//
public bool SendRoomFile(MessageIdDelegate callback, long roomId, RTMAudioData audioData, string attrs = "", int timeout = 120)
{
return RealSendFile(callback, FileTokenType.Room, roomId, (byte)MessageType.AudioFile, audioData.Audio, "", "", attrs, BuildAudioMessageAttrs(audioData), 0, timeout);
}
public int SendRoomFile(out long messageId, long roomId, RTMAudioData audioData, string attrs = "", int timeout = 120)
{
return RealSendFile(out messageId, out _, FileTokenType.Room, roomId, (byte)MessageType.AudioFile, audioData.Audio, "", "", attrs, BuildAudioMessageAttrs(audioData), 0, timeout);
}
public bool SendRoomFile(SendMessageDelegate callback, long roomId, RTMAudioData audioData, string attrs = "", int timeout = 120)
{
return RealSendFile(callback, FileTokenType.Room, roomId, (byte)MessageType.AudioFile, audioData.Audio, "", "", attrs, BuildAudioMessageAttrs(audioData), 0, timeout);
}
public int SendRoomFile(out long messageId, out long mtime, long roomId, RTMAudioData audioData, string attrs = "", int timeout = 120)
{
return RealSendFile(out messageId, out mtime, FileTokenType.Room, roomId, (byte)MessageType.AudioFile, audioData.Audio, "", "", attrs, BuildAudioMessageAttrs(audioData), 0, timeout);
}
//===========================[ Upload RTM-Audio File ]=========================//
public bool UploadFile(Action<string, uint, int> callback, RTMAudioData audioData, string attrs = "", int timeout = 120)
{
return RealUploadFile(callback, FileTokenType.Upload, (byte)MessageType.AudioFile, audioData.Audio, "", "", attrs, BuildAudioMessageAttrs(audioData), timeout);
}
public int UploadFile(out string url, out uint size, RTMAudioData audioData, string attrs = "", int timeout = 120)
{
return RealUploadFile(out url, out size, FileTokenType.Upload, (byte)MessageType.AudioFile, audioData.Audio, "", "", attrs, BuildAudioMessageAttrs(audioData), timeout);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9507cd07a08ed4e7b830c720e6ae6b86
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,996 @@
using System;
using System.Text;
using System.Collections.Generic;
using System.Security.Cryptography;
using com.fpnn.proto;
using com.fpnn.common;
namespace com.fpnn.rtm
{
public partial class RTMClient
{
private enum FileTokenType
{
P2P,
Group,
Room,
Upload,
}
private class SendFileInfo
{
public FileTokenType actionType;
public long xid;
public byte mtype;
public byte[] fileContent;
public string filename;
public string fileExtension;
public string userAttrs;
public long messageId;
public string token;
public string endpoint;
public int remainTimeout;
public long lastActionTimestamp;
public MessageIdDelegate callback;
public SendMessageDelegate callbackMtime;
public Action<string, uint, int> uploadCallback;
public Dictionary<string, object> rtmAttrs;
}
//===========================[ File Token ]=========================//
//-- Action<token, endpoint, errorCode>
private bool FileToken(Action<string, string, int> callback, FileTokenType tokenType, long xid, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
return false;
Quest quest = new Quest("filetoken");
switch (tokenType)
{
case FileTokenType.P2P:
quest.Param("cmd", "sendfile");
quest.Param("to", xid);
break;
case FileTokenType.Group:
quest.Param("cmd", "sendgroupfile");
quest.Param("gid", xid);
break;
case FileTokenType.Room:
quest.Param("cmd", "sendroomfile");
quest.Param("rid", xid);
break;
case FileTokenType.Upload:
quest.Param("cmd", "uploadfile");
break;
}
return client.SendQuest(quest, (Answer answer, int errorCode) => {
string token = "";
string endpoint = "";
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
token = answer.Want<string>("token");
endpoint = answer.Want<string>("endpoint");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(token, endpoint, errorCode);
}, timeout);
}
private int FileToken(out string token, out string endpoint, FileTokenType tokenType, long xid, int timeout = 0)
{
token = "";
endpoint = "";
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("filetoken");
switch (tokenType)
{
case FileTokenType.P2P:
quest.Param("cmd", "sendfile");
quest.Param("to", xid);
break;
case FileTokenType.Group:
quest.Param("cmd", "sendgroupfile");
quest.Param("gid", xid);
break;
case FileTokenType.Room:
quest.Param("cmd", "sendroomfile");
quest.Param("rid", xid);
break;
case FileTokenType.Upload:
quest.Param("cmd", "uploadfile");
break;
}
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
token = answer.Want<string>("token");
endpoint = answer.Want<string>("endpoint");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
//===========================[ IPv4 Convert IPv6 Utilies ]=========================//
private string ConvertIPv4ToIPv6(string ipv4)
{
string[] parts = ipv4.Split(new Char[] { '.' });
if (parts.Length != 4)
return string.Empty;
foreach (string part in parts)
{
int partInt = Int32.Parse(part);
if (partInt > 255 || partInt < 0)
return string.Empty;
}
string part7 = Convert.ToString(Int32.Parse(parts[0]) * 256 + Int32.Parse(parts[1]), 16);
string part8 = Convert.ToString(Int32.Parse(parts[2]) * 256 + Int32.Parse(parts[3]), 16);
return "64:ff9b::" + part7 + ":" + part8;
}
private bool ConvertIPv4EndpointToIPv6IPPort(string ipv4endpoint, out string ipv6, out int port)
{
int idx = ipv4endpoint.LastIndexOf(':');
if (idx == -1)
{
ipv6 = string.Empty;
port = 0;
return false;
}
string ipv4 = ipv4endpoint.Substring(0, idx);
string portString = ipv4endpoint.Substring(idx + 1);
port = Convert.ToInt32(portString, 10);
ipv6 = ConvertIPv4ToIPv6(ipv4);
if (ipv6.Length == 0)
return false;
return true;
}
//===========================[ File Utilies ]=========================//
private void UpdateTimeout(ref int timeout, ref long lastActionTimestamp)
{
long currMsec = ClientEngine.GetCurrentMilliseconds();
timeout -= (int)((currMsec - lastActionTimestamp) / 1000);
lastActionTimestamp = currMsec;
}
private string ExtraFileExtension(string filename)
{
int idx = filename.LastIndexOf('.');
if (idx == -1)
return null;
return filename.Substring(idx + 1);
}
private string GetMD5(string str, bool upper)
{
byte[] inputBytes = Encoding.ASCII.GetBytes(str);
return GetMD5(inputBytes, upper);
}
private string GetMD5(byte[] bytes, bool upper)
{
MD5 md5 = MD5.Create();
byte[] hash = md5.ComputeHash(bytes);
string f = "x2";
if (upper)
{
f = "X2";
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
sb.Append(hash[i].ToString(f));
}
return sb.ToString();
}
private string BuildFileAttrs(SendFileInfo info)
{
string fileMD5 = GetMD5(info.fileContent, false);
string sign = GetMD5(fileMD5 + ":" + info.token, false);
if (info.rtmAttrs == null)
info.rtmAttrs = new Dictionary<string, object>();
Dictionary<string, object> rtmAttrs = info.rtmAttrs;
rtmAttrs.Add("sign", sign);
if (info.filename != null && info.filename.Length > 0)
{
rtmAttrs.Add("filename", info.filename);
if (info.fileExtension == null || info.fileExtension.Length == 0)
info.fileExtension = ExtraFileExtension(info.filename);
}
if (info.fileExtension != null && info.fileExtension.Length > 0)
rtmAttrs.Add("ext", info.fileExtension);
Dictionary<string, object> fileAttrs = new Dictionary<string, object>();
fileAttrs.Add("rtm", rtmAttrs);
if (info.userAttrs == null || info.userAttrs.Length == 0)
fileAttrs.Add("custom", "");
else
{
try
{
Dictionary<string, object> userDict = Json.ParseObject(info.userAttrs);
if (userDict != null)
fileAttrs.Add("custom", userDict);
else
fileAttrs.Add("custom", info.userAttrs);
}
catch (JsonException)
{
fileAttrs.Add("custom", info.userAttrs);
}
}
return Json.ToString(fileAttrs);
}
private Quest BuildSendFileQuest(out long messageId, SendFileInfo info)
{
Quest quest = null;
switch (info.actionType)
{
case FileTokenType.P2P:
quest = new Quest("sendfile");
quest.Param("to", info.xid);
break;
case FileTokenType.Group:
quest = new Quest("sendgroupfile");
quest.Param("gid", info.xid);
break;
case FileTokenType.Room:
quest = new Quest("sendroomfile");
quest.Param("rid", info.xid);
break;
case FileTokenType.Upload:
quest = new Quest("uploadfile");
quest.Param("uid", uid);
break;
}
quest.Param("pid", projectId);
quest.Param("from", uid);
quest.Param("token", info.token);
quest.Param("mtype", info.mtype);
messageId = info.messageId;
if (info.messageId == 0)
messageId = MidGenerator.Gen();
quest.Param("mid", messageId);
quest.Param("file", info.fileContent);
quest.Param("attrs", BuildFileAttrs(info));
return quest;
}
private int SendFileWithClient(SendFileInfo info, TCPClient client)
{
UpdateTimeout(ref info.remainTimeout, ref info.lastActionTimestamp);
if (info.remainTimeout <= 0)
return fpnn.ErrorCode.FPNN_EC_CORE_TIMEOUT;
long messageId = 0;
Quest quest = BuildSendFileQuest(out messageId, info);
bool success = client.SendQuest(quest, (Answer answer, int errorCode) => {
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
if (info.callbackMtime == null)
info.callback(messageId, fpnn.ErrorCode.FPNN_EC_OK);
else
{
long mtime = answer.Want<long>("mtime");
info.callbackMtime(messageId, mtime, fpnn.ErrorCode.FPNN_EC_OK);
}
RTMControlCenter.ActiveFileGateClient(info.endpoint, client);
return;
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
if (info.callbackMtime == null)
info.callback(0, errorCode);
else
info.callbackMtime(0, 0, errorCode);
}, info.remainTimeout);
if (success)
return fpnn.ErrorCode.FPNN_EC_OK;
else
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
}
private int UploadFileWithClient(SendFileInfo info, TCPClient client)
{
UpdateTimeout(ref info.remainTimeout, ref info.lastActionTimestamp);
if (info.remainTimeout <= 0)
return fpnn.ErrorCode.FPNN_EC_CORE_TIMEOUT;
long messageId = 0;
Quest quest = BuildSendFileQuest(out messageId, info);
bool success = client.SendQuest(quest, (Answer answer, int errorCode) => {
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
string url = answer.Want<string>("url");
uint size = answer.Want<uint>("size");
info.uploadCallback(url, size, fpnn.ErrorCode.FPNN_EC_OK);
RTMControlCenter.ActiveFileGateClient(info.endpoint, client);
return;
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
info.uploadCallback(null, 0, errorCode);
}, info.remainTimeout);
if (success)
return fpnn.ErrorCode.FPNN_EC_OK;
else
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
}
private int SendFileWithoutClient(SendFileInfo info, bool originalEndpoint)
{
string fileGateEndpoint;
if (originalEndpoint)
fileGateEndpoint = info.endpoint;
else
{
if (ConvertIPv4EndpointToIPv6IPPort(info.endpoint, out string ipv6, out int port))
{
fileGateEndpoint = ipv6 + ":" + port;
}
else
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
}
}
TCPClient client = TCPClient.Create(fileGateEndpoint, true);
if (errorRecorder != null)
client.SetErrorRecorder(errorRecorder);
client.SetConnectionConnectedDelegate((Int64 connectionId, string endpoint, bool connected) => {
int errorCode = fpnn.ErrorCode.FPNN_EC_OK;
if (connected)
{
RTMControlCenter.ActiveFileGateClient(info.endpoint, client);
errorCode = SendFileWithClient(info, client);
}
else if (originalEndpoint)
{
errorCode = SendFileWithoutClient(info, false);
}
else
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
}
if (errorCode != fpnn.ErrorCode.FPNN_EC_OK)
{
if (info.callbackMtime == null)
info.callback(0, errorCode);
else
info.callbackMtime(0, 0, errorCode);
}
if (connected)
client.SetConnectionConnectedDelegate(null);
});
client.AsyncConnect();
return fpnn.ErrorCode.FPNN_EC_OK;
}
private int UploadFileWithoutClient(SendFileInfo info, bool originalEndpoint)
{
string fileGateEndpoint;
if (originalEndpoint)
fileGateEndpoint = info.endpoint;
else
{
if (ConvertIPv4EndpointToIPv6IPPort(info.endpoint, out string ipv6, out int port))
{
fileGateEndpoint = ipv6 + ":" + port;
}
else
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
}
}
TCPClient client = TCPClient.Create(fileGateEndpoint, true);
if (errorRecorder != null)
client.SetErrorRecorder(errorRecorder);
client.SetConnectionConnectedDelegate((Int64 connectionId, string endpoint, bool connected) => {
int errorCode = fpnn.ErrorCode.FPNN_EC_OK;
if (connected)
{
RTMControlCenter.ActiveFileGateClient(info.endpoint, client);
errorCode = UploadFileWithClient(info, client);
}
else if (originalEndpoint)
{
errorCode = UploadFileWithoutClient(info, false);
}
else
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
}
if (errorCode != fpnn.ErrorCode.FPNN_EC_OK)
info.uploadCallback(null, 0, errorCode);
if (connected)
client.SetConnectionConnectedDelegate(null);
});
client.AsyncConnect();
return fpnn.ErrorCode.FPNN_EC_OK;
}
private void GetFileTokenCallback(SendFileInfo info, string token, string endpoint, int errorCode)
{
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
info.token = token;
info.endpoint = endpoint;
TCPClient fileClient = RTMControlCenter.FecthFileGateClient(info.endpoint);
if (fileClient != null)
errorCode = SendFileWithClient(info, fileClient);
else
errorCode = SendFileWithoutClient(info, true);
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
return;
}
else
{
if (info.callbackMtime == null)
info.callback(0, errorCode);
else
info.callbackMtime(0, 0, errorCode);
}
}
private void GetFileTokenUploadCallback(SendFileInfo info, string token, string endpoint, int errorCode)
{
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
info.token = token;
info.endpoint = endpoint;
TCPClient fileClient = RTMControlCenter.FecthFileGateClient(info.endpoint);
if (fileClient != null)
errorCode = UploadFileWithClient(info, fileClient);
else
errorCode = UploadFileWithoutClient(info, true);
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
return;
}
else
info.uploadCallback(null, 0, errorCode);
}
//===========================[ Real Send File ]=========================//
private bool RealSendFile(MessageIdDelegate callback, FileTokenType tokenType, long targetId, byte mtype,
byte[] fileContent, string filename, string fileExtension, string attrs, Dictionary<string, object> rtmAttrs, long messageId, int timeout)
{
if (mtype < 40 || mtype > 50)
{
if (errorRecorder != null)
errorRecorder.RecordError("Send file require mtype between [40, 50], current mtype is " + mtype);
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, ErrorCode.RTM_EC_INVALID_MTYPE);
});
return false;
}
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
SendFileInfo info = new SendFileInfo
{
actionType = tokenType,
xid = targetId,
mtype = mtype,
fileContent = fileContent,
filename = filename,
fileExtension = fileExtension,
userAttrs = attrs,
messageId = messageId,
remainTimeout = timeout,
lastActionTimestamp = ClientEngine.GetCurrentMilliseconds(),
callback = callback
};
info.rtmAttrs = rtmAttrs;
bool asyncStarted = FileToken((string token, string endpoint, int errorCode) => {
GetFileTokenCallback(info, token, endpoint, errorCode);
}, tokenType, info.xid, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
private bool RealSendFile(SendMessageDelegate callback, FileTokenType tokenType, long targetId, byte mtype,
byte[] fileContent, string filename, string fileExtension, string attrs, Dictionary<string, object> rtmAttrs, long messageId, int timeout)
{
if (mtype < 40 || mtype > 50)
{
if (errorRecorder != null)
errorRecorder.RecordError("Send file require mtype between [40, 50], current mtype is " + mtype);
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, 0, ErrorCode.RTM_EC_INVALID_MTYPE);
});
return false;
}
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, 0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
SendFileInfo info = new SendFileInfo
{
actionType = tokenType,
xid = targetId,
mtype = mtype,
fileContent = fileContent,
filename = filename,
fileExtension = fileExtension,
userAttrs = attrs,
messageId = messageId,
remainTimeout = timeout,
lastActionTimestamp = ClientEngine.GetCurrentMilliseconds(),
callbackMtime = callback
};
info.rtmAttrs = rtmAttrs;
bool asyncStarted = FileToken((string token, string endpoint, int errorCode) => {
GetFileTokenCallback(info, token, endpoint, errorCode);
}, tokenType, info.xid, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, 0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
private int RealSendFile(out long messageId, out long mtime, FileTokenType tokenType, long targetId, byte mtype,
byte[] fileContent, string filename, string fileExtension, string attrs, Dictionary<string, object> rtmAttrs, long mid, int timeout)
{
messageId = mid;
mtime = 0;
//----------[ 1. check mtype ]---------------//
if (mtype < 40 || mtype > 50)
{
if (errorRecorder != null)
errorRecorder.RecordError("Send file require mtype between [40, 50], current mtype is " + mtype);
return ErrorCode.RTM_EC_INVALID_MTYPE;
}
//----------[ 2. Get File Token ]---------------//
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
long lastActionTimestamp = ClientEngine.GetCurrentMilliseconds();
int errorCode = FileToken(out string token, out string endpoint, tokenType, targetId, timeout);
if (errorCode != fpnn.ErrorCode.FPNN_EC_OK)
return errorCode;
//----------[ 2.1 check timeout ]---------------//
UpdateTimeout(ref timeout, ref lastActionTimestamp);
if (timeout <= 0)
return fpnn.ErrorCode.FPNN_EC_CORE_TIMEOUT;
//----------[ 3. fetch file gate client ]---------------//
TCPClient fileClient = RTMControlCenter.FecthFileGateClient(endpoint);
if (fileClient == null)
{
fileClient = TCPClient.Create(endpoint, true);
if (fileClient.SyncConnect())
{
RTMControlCenter.ActiveFileGateClient(endpoint, fileClient);
}
else
{
//----------[ 3.1 check timeout ]---------------//
UpdateTimeout(ref timeout, ref lastActionTimestamp);
if (timeout <= 0)
return fpnn.ErrorCode.FPNN_EC_CORE_TIMEOUT;
if (ConvertIPv4EndpointToIPv6IPPort(endpoint, out string ipv6, out int port))
{
fileClient = TCPClient.Create(ipv6 + ":" + port, true);
if (fileClient.SyncConnect())
{
RTMControlCenter.ActiveFileGateClient(endpoint, fileClient);
}
else
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
}
}
else
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
}
}
}
//----------[ 3.2 check timeout ]---------------//
UpdateTimeout(ref timeout, ref lastActionTimestamp);
if (timeout <= 0)
return fpnn.ErrorCode.FPNN_EC_CORE_TIMEOUT;
//----------[ 4. build quest ]---------------//
SendFileInfo info = new SendFileInfo
{
actionType = tokenType,
xid = targetId,
mtype = mtype,
fileContent = fileContent,
filename = filename,
fileExtension = fileExtension,
userAttrs = attrs,
messageId = mid,
token = token,
};
info.rtmAttrs = rtmAttrs;
Quest quest = BuildSendFileQuest(out messageId, info);
Answer answer = fileClient.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
RTMControlCenter.ActiveFileGateClient(endpoint, fileClient);
mtime = answer.Want<long>("mtime");
return fpnn.ErrorCode.FPNN_EC_OK;
}
private bool RealUploadFile(Action<string, uint, int> callback, FileTokenType tokenType, byte mtype,
byte[] fileContent, string filename, string fileExtension, string attrs, Dictionary<string, object> rtmAttrs, int timeout)
{
if (mtype < 40 || mtype > 50)
{
if (errorRecorder != null)
errorRecorder.RecordError("Send file require mtype between [40, 50], current mtype is " + mtype);
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, 0, ErrorCode.RTM_EC_INVALID_MTYPE);
});
return false;
}
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, 0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
SendFileInfo info = new SendFileInfo
{
actionType = tokenType,
xid = 0,
mtype = mtype,
fileContent = fileContent,
filename = filename,
fileExtension = fileExtension,
userAttrs = attrs,
remainTimeout = timeout,
lastActionTimestamp = ClientEngine.GetCurrentMilliseconds(),
uploadCallback = callback
};
info.rtmAttrs = rtmAttrs;
bool asyncStarted = FileToken((string token, string endpoint, int errorCode) => {
GetFileTokenUploadCallback(info, token, endpoint, errorCode);
}, tokenType, info.xid, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, 0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
private int RealUploadFile(out string url, out uint size, FileTokenType tokenType, byte mtype,
byte[] fileContent, string filename, string fileExtension, string attrs, Dictionary<string, object> rtmAttrs, int timeout)
{
url = null;
size = 0;
//----------[ 1. check mtype ]---------------//
if (mtype < 40 || mtype > 50)
{
if (errorRecorder != null)
errorRecorder.RecordError("Send file require mtype between [40, 50], current mtype is " + mtype);
return ErrorCode.RTM_EC_INVALID_MTYPE;
}
//----------[ 2. Get File Token ]---------------//
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
long lastActionTimestamp = ClientEngine.GetCurrentMilliseconds();
int errorCode = FileToken(out string token, out string endpoint, tokenType, 0, timeout);
if (errorCode != fpnn.ErrorCode.FPNN_EC_OK)
return errorCode;
//----------[ 2.1 check timeout ]---------------//
UpdateTimeout(ref timeout, ref lastActionTimestamp);
if (timeout <= 0)
return fpnn.ErrorCode.FPNN_EC_CORE_TIMEOUT;
//----------[ 3. fetch file gate client ]---------------//
TCPClient fileClient = RTMControlCenter.FecthFileGateClient(endpoint);
if (fileClient == null)
{
fileClient = TCPClient.Create(endpoint, true);
if (fileClient.SyncConnect())
{
RTMControlCenter.ActiveFileGateClient(endpoint, fileClient);
}
else
{
//----------[ 3.1 check timeout ]---------------//
UpdateTimeout(ref timeout, ref lastActionTimestamp);
if (timeout <= 0)
return fpnn.ErrorCode.FPNN_EC_CORE_TIMEOUT;
if (ConvertIPv4EndpointToIPv6IPPort(endpoint, out string ipv6, out int port))
{
fileClient = TCPClient.Create(ipv6 + ":" + port, true);
if (fileClient.SyncConnect())
{
RTMControlCenter.ActiveFileGateClient(endpoint, fileClient);
}
else
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
}
}
else
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
}
}
}
//----------[ 3.2 check timeout ]---------------//
UpdateTimeout(ref timeout, ref lastActionTimestamp);
if (timeout <= 0)
return fpnn.ErrorCode.FPNN_EC_CORE_TIMEOUT;
//----------[ 4. build quest ]---------------//
SendFileInfo info = new SendFileInfo
{
actionType = tokenType,
xid = 0,
mtype = mtype,
fileContent = fileContent,
filename = filename,
fileExtension = fileExtension,
userAttrs = attrs,
token = token,
};
info.rtmAttrs = rtmAttrs;
long messageId = 0;
Quest quest = BuildSendFileQuest(out messageId, info);
Answer answer = fileClient.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
url = answer.Want<string>("url");
size = answer.Want<uint>("size");
RTMControlCenter.ActiveFileGateClient(endpoint, fileClient);
// mtime = answer.Want<long>("mtime");
return fpnn.ErrorCode.FPNN_EC_OK;
}
//===========================[ Send File ]=========================//
public bool SendFile(MessageIdDelegate callback, long peerUid, MessageType type, byte[] fileContent, string filename, string fileExtension = "", string attrs = "", int timeout = 120)
{
return RealSendFile(callback, FileTokenType.P2P, peerUid, (byte)type, fileContent, filename, fileExtension, attrs, null, 0, timeout);
}
public int SendFile(out long messageId, long peerUid, MessageType type, byte[] fileContent, string filename, string fileExtension = "", string attrs = "", int timeout = 120)
{
return RealSendFile(out messageId, out _, FileTokenType.P2P, peerUid, (byte)type, fileContent, filename, fileExtension, attrs, null, 0, timeout);
}
public bool SendFile(SendMessageDelegate callback, long peerUid, MessageType type, byte[] fileContent, string filename, string fileExtension = "", string attrs = "", int timeout = 120)
{
return RealSendFile(callback, FileTokenType.P2P, peerUid, (byte)type, fileContent, filename, fileExtension, attrs, null, 0, timeout);
}
public int SendFile(out long messageId, out long mtime, long peerUid, MessageType type, byte[] fileContent, string filename, string fileExtension = "", string attrs = "", int timeout = 120)
{
return RealSendFile(out messageId, out mtime, FileTokenType.P2P, peerUid, (byte)type, fileContent, filename, fileExtension, attrs, null, 0, timeout);
}
//===========================[ Sned Group File ]=========================//
public bool SendGroupFile(MessageIdDelegate callback, long groupId, MessageType type, byte[] fileContent, string filename, string fileExtension = "", string attrs = "", int timeout = 120)
{
return RealSendFile(callback, FileTokenType.Group, groupId, (byte)type, fileContent, filename, fileExtension, attrs, null, 0, timeout);
}
public int SendGroupFile(out long messageId, long groupId, MessageType type, byte[] fileContent, string filename, string fileExtension = "", string attrs = "", int timeout = 120)
{
return RealSendFile(out messageId, out _, FileTokenType.Group, groupId, (byte)type, fileContent, filename, fileExtension, attrs, null, 0, timeout);
}
public bool SendGroupFile(SendMessageDelegate callback, long groupId, MessageType type, byte[] fileContent, string filename, string fileExtension = "", string attrs = "", int timeout = 120)
{
return RealSendFile(callback, FileTokenType.Group, groupId, (byte)type, fileContent, filename, fileExtension, attrs, null, 0, timeout);
}
public int SendGroupFile(out long messageId, out long mtime, long groupId, MessageType type, byte[] fileContent, string filename, string fileExtension = "", string attrs = "", int timeout = 120)
{
return RealSendFile(out messageId, out mtime, FileTokenType.Group, groupId, (byte)type, fileContent, filename, fileExtension, attrs, null, 0, timeout);
}
//===========================[ Sned Room File ]=========================//
public bool SendRoomFile(MessageIdDelegate callback, long roomId, MessageType type, byte[] fileContent, string filename, string fileExtension = "", string attrs = "", int timeout = 120)
{
return RealSendFile(callback, FileTokenType.Room, roomId, (byte)type, fileContent, filename, fileExtension, attrs, null, 0, timeout);
}
public int SendRoomFile(out long messageId, long roomId, MessageType type, byte[] fileContent, string filename, string fileExtension = "", string attrs = "", int timeout = 120)
{
return RealSendFile(out messageId, out _, FileTokenType.Room, roomId, (byte)type, fileContent, filename, fileExtension, attrs, null, 0, timeout);
}
public bool SendRoomFile(SendMessageDelegate callback, long roomId, MessageType type, byte[] fileContent, string filename, string fileExtension = "", string attrs = "", int timeout = 120)
{
return RealSendFile(callback, FileTokenType.Room, roomId, (byte)type, fileContent, filename, fileExtension, attrs, null, 0, timeout);
}
public int SendRoomFile(out long messageId, out long mtime, long roomId, MessageType type, byte[] fileContent, string filename, string fileExtension = "", string attrs = "", int timeout = 120)
{
return RealSendFile(out messageId, out mtime, FileTokenType.Room, roomId, (byte)type, fileContent, filename, fileExtension, attrs, null, 0, timeout);
}
//===========================[ Upload File ]=========================//
public bool UploadFile(Action<string, uint, int> callback, MessageType type, byte[] fileContent, string filename, string fileExtension = "", string attrs = "", int timeout = 120)
{
return RealUploadFile(callback, FileTokenType.Upload, (byte)type, fileContent, filename, fileExtension, attrs, null, timeout);
}
public int UploadFile(out string url, out uint size, MessageType type, byte[] fileContent, string filename, string fileExtension = "", string attrs = "", int timeout = 120)
{
return RealUploadFile(out url, out size, FileTokenType.Upload, (byte)type, fileContent, filename, fileExtension, attrs, null, timeout);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f33ee6002df954ce3a69f01c981cc58c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,315 @@
using System;
using System.Collections.Generic;
using com.fpnn.proto;
namespace com.fpnn.rtm
{
public partial class RTMClient
{
//===========================[ Add Friends ]=========================//
public bool AddFriends(DoneDelegate callback, HashSet<long> uids, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("addfriends");
quest.Param("friends", uids);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int AddFriends(HashSet<long> uids, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("addfriends");
quest.Param("friends", uids);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
//===========================[ Delete Friends ]=========================//
public bool DeleteFriends(DoneDelegate callback, HashSet<long> uids, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("delfriends");
quest.Param("friends", uids);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int DeleteFriends(HashSet<long> uids, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("delfriends");
quest.Param("friends", uids);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
//===========================[ Get Friends ]=========================//
//-- Action<friend_uids, errorCode>
public bool GetFriends(Action<HashSet<long>, int> callback, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getfriends");
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
HashSet<long> friends = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
friends = WantLongHashSet(answer, "uids");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(friends, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetFriends(out HashSet<long> friends, int timeout = 0)
{
friends = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getfriends");
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
friends = WantLongHashSet(answer, "uids");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
//===========================[ Add Blacklist ]=========================//
public bool AddBlacklist(DoneDelegate callback, HashSet<long> uids, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("addblacks");
quest.Param("blacks", uids);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int AddBlacklist(HashSet<long> uids, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("addblacks");
quest.Param("blacks", uids);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
//===========================[ Delete Blacklist ]=========================//
public bool DeleteBlacklist(DoneDelegate callback, HashSet<long> uids, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("delblacks");
quest.Param("blacks", uids);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int DeleteBlacklist(HashSet<long> uids, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("delblacks");
quest.Param("blacks", uids);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
//===========================[ Get Blacklist ]=========================//
//-- Action<uids, errorCode>
public bool GetBlacklist(Action<HashSet<long>, int> callback, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getblacks");
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
HashSet<long> friends = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
friends = WantLongHashSet(answer, "uids");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(friends, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetBlacklist(out HashSet<long> uids, int timeout = 0)
{
uids = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getblacks");
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
uids = WantLongHashSet(answer, "uids");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b19d83ff9c43b4bc78d49fe3b5c65073
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,807 @@
using System;
using System.Collections.Generic;
using com.fpnn.proto;
namespace com.fpnn.rtm
{
public partial class RTMClient
{
//===========================[ Add Group Members ]=========================//
public bool AddGroupMembers(DoneDelegate callback, long groupId, HashSet<long> uids, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("addgroupmembers");
quest.Param("gid", groupId);
quest.Param("uids", uids);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int AddGroupMembers(long groupId, HashSet<long> uids, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("addgroupmembers");
quest.Param("gid", groupId);
quest.Param("uids", uids);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
//===========================[ Delete Group Members ]=========================//
public bool DeleteGroupMembers(DoneDelegate callback, long groupId, HashSet<long> uids, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("delgroupmembers");
quest.Param("gid", groupId);
quest.Param("uids", uids);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int DeleteGroupMembers(long groupId, HashSet<long> uids, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("delgroupmembers");
quest.Param("gid", groupId);
quest.Param("uids", uids);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
//===========================[ Get Group Members ]=========================//
//-- Action<uids, errorCode>
public bool GetGroupMembers(Action<HashSet<long>, int> callback, long groupId, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getgroupmembers");
quest.Param("gid", groupId);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
HashSet<long> uids = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
uids = WantLongHashSet(answer, "uids");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(uids, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
//-- Action<member_uids, online_uids, errorCode>
public bool GetGroupMembers(Action<HashSet<long>, HashSet<long>, int> callback, long groupId, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getgroupmembers");
quest.Param("gid", groupId);
quest.Param("online", true);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
HashSet<long> allUids = null;
HashSet<long> onlineUids = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
allUids = WantLongHashSet(answer, "uids");
onlineUids = GetLongHashSet(answer, "onlines");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(allUids, onlineUids, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetGroupMembers(out HashSet<long> uids, long groupId, int timeout = 0)
{
uids = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getgroupmembers");
quest.Param("gid", groupId);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
uids = WantLongHashSet(answer, "uids");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
public int GetGroupMembers(out HashSet<long> allUids, out HashSet<long> onlineUids, long groupId, int timeout = 0)
{
allUids = null;
onlineUids = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getgroupmembers");
quest.Param("gid", groupId);
quest.Param("online", true);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
allUids = WantLongHashSet(answer, "uids");
onlineUids = GetLongHashSet(answer, "onlines");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
//===========================[ Get Group Count ]=========================//
//-- Action<member_count, errorCode>
public bool GetGroupCount(Action<int, int> callback, long groupId, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getgroupcount");
quest.Param("gid", groupId);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
int memberCount = 0;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
memberCount = answer.Want<int>("cn");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(memberCount, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
//-- Action<member_count, online_count, errorCode>
public bool GetGroupCount(Action<int, int, int> callback, long groupId, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, 0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getgroupcount");
quest.Param("gid", groupId);
quest.Param("online", true);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
int memberCount = 0;
int onlineCount = 0;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
memberCount = answer.Want<int>("cn");
onlineCount = answer.Want<int>("online");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(memberCount, onlineCount, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, 0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetGroupCount(out int memberCount, long groupId, int timeout = 0)
{
memberCount = 0;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getgroupcount");
quest.Param("gid", groupId);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
memberCount = answer.Want<int>("cn");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
public int GetGroupCount(out int memberCount, out int onlineCount, long groupId, int timeout = 0)
{
memberCount = 0;
onlineCount = 0;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getgroupcount");
quest.Param("gid", groupId);
quest.Param("online", true);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
memberCount = answer.Want<int>("cn");
onlineCount = answer.Want<int>("online");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
//===========================[ Get User Groups ]=========================//
//-- Action<groupIds, errorCode>
public bool GetUserGroups(Action<HashSet<long>, int> callback, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getusergroups");
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
HashSet<long> groupIds = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
groupIds = WantLongHashSet(answer, "gids");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(groupIds, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetUserGroups(out HashSet<long> groupIds, int timeout = 0)
{
groupIds = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getusergroups");
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
groupIds = WantLongHashSet(answer, "gids");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
//===========================[ Set Group Info ]=========================//
public bool SetGroupInfo(DoneDelegate callback, long groupId, string publicInfo = null, string privateInfo = null, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("setgroupinfo");
quest.Param("gid", groupId);
if (publicInfo != null)
quest.Param("oinfo", publicInfo);
if (privateInfo != null)
quest.Param("pinfo", privateInfo);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int SetGroupInfo(long groupId, string publicInfo = null, string privateInfo = null, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("setgroupinfo");
quest.Param("gid", groupId);
if (publicInfo != null)
quest.Param("oinfo", publicInfo);
if (privateInfo != null)
quest.Param("pinfo", privateInfo);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
//===========================[ Get Group Info ]=========================//
//-- Action<publicInfo, privateInfo, errorCode>
public bool GetGroupInfo(Action<string, string, int> callback, long groupId, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getgroupinfo");
quest.Param("gid", groupId);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
string publicInfo = "";
string privateInfo = "";
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
publicInfo = answer.Want<string>("oinfo");
privateInfo = answer.Want<string>("pinfo");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(publicInfo, privateInfo, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetGroupInfo(out string publicInfo, out string privateInfo, long groupId, int timeout = 0)
{
publicInfo = null;
privateInfo = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getgroupinfo");
quest.Param("gid", groupId);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
publicInfo = answer.Want<string>("oinfo");
privateInfo = answer.Want<string>("pinfo");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
//===========================[ Get Group Open Info ]=========================//
//-- Action<public_info, errorCode>
public bool GetGroupPublicInfo(Action<string, int> callback, long groupId, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(string.Empty, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getgroupopeninfo");
quest.Param("gid", groupId);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
string publicInfo = "";
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{ publicInfo = answer.Want<string>("oinfo"); }
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(publicInfo, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(string.Empty, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetGroupPublicInfo(out string publicInfo, long groupId, int timeout = 0)
{
publicInfo = "";
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getgroupopeninfo");
quest.Param("gid", groupId);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
publicInfo = answer.Want<string>("oinfo");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
//===========================[ Get Groups Open Info ]=========================//
//-- Action<Dictionary<string_groupId, public_info>, errorCode>
[System.Obsolete("GetGroupsPublicInfo() with dictionary in string key type is deprecated, please using the overloaded function with dictionary in long key type instead.")]
public bool GetGroupsPublicInfo(Action<Dictionary<string, string>, int> callback, HashSet<long> groupIds, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getgroupsopeninfo");
quest.Param("gids", groupIds);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
Dictionary<string, string> publicInfos = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
publicInfos = WantStringDictionary(answer, "info");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(publicInfos, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
//-- Action<Dictionary<groupId, public_info>, errorCode>
public bool GetGroupsPublicInfo(Action<Dictionary<long, string>, int> callback, HashSet<long> groupIds, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getgroupsopeninfo");
quest.Param("gids", groupIds);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
Dictionary<long, string> publicInfos = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
publicInfos = WantLongStringDictionary(answer, "info");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(publicInfos, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
[System.Obsolete("GetGroupsPublicInfo() with dictionary in string key type is deprecated, please using the overloaded function with dictionary in long key type instead.")]
public int GetGroupsPublicInfo(out Dictionary<string, string> publicInfos, HashSet<long> groupIds, int timeout = 0)
{
publicInfos = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getgroupsopeninfo");
quest.Param("gids", groupIds);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
publicInfos = WantStringDictionary(answer, "info");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
public int GetGroupsPublicInfo(out Dictionary<long, string> publicInfos, HashSet<long> groupIds, int timeout = 0)
{
publicInfos = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getgroupsopeninfo");
quest.Param("gids", groupIds);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
publicInfos = WantLongStringDictionary(answer, "info");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 625503492ea1340aa8dc7d9fd044beb0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,706 @@
using System;
using com.fpnn.proto;
namespace com.fpnn.rtm
{
public partial class RTMClient
{
//======================[ string message version ]================================//
private bool InternalSendMessage(long uid, byte mtype, string message, string attrs, MessageIdDelegate callback, long messageId, int timeout)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
long mid = messageId;
if (messageId == 0)
mid = MidGenerator.Gen();
Quest quest = new Quest("sendmsg");
quest.Param("to", uid);
quest.Param("mid", mid);
quest.Param("mtype", mtype);
quest.Param("msg", message);
quest.Param("attrs", attrs);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
//long mtime = 0;
//if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
// mtime = answer.Want<long>("mtime");
callback(mid, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
private bool InternalSendMessage(long uid, byte mtype, string message, string attrs, SendMessageDelegate callback, long messageId, int timeout)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, 0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
long mid = messageId;
if (messageId == 0)
mid = MidGenerator.Gen();
Quest quest = new Quest("sendmsg");
quest.Param("to", uid);
quest.Param("mid", mid);
quest.Param("mtype", mtype);
quest.Param("msg", message);
quest.Param("attrs", attrs);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
long mtime = 0;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
mtime = answer.Want<long>("mtime");
callback(mid, mtime, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, 0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
private int InternalSendMessage(out long messageId, out long mtime, long uid, byte mtype, string message, string attrs, long mid, int timeout)
{
mtime = 0;
TCPClient client = GetCoreClient();
if (client == null)
{
messageId = mid;
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
}
messageId = mid;
if (mid == 0)
messageId = MidGenerator.Gen();
Quest quest = new Quest("sendmsg");
quest.Param("to", uid);
quest.Param("mid", messageId);
quest.Param("mtype", mtype);
quest.Param("msg", message);
quest.Param("attrs", attrs);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
mtime = answer.Want<long>("mtime");
return fpnn.ErrorCode.FPNN_EC_OK;
}
private bool InternalSendGroupMessage(long groupId, byte mtype, string message, string attrs, MessageIdDelegate callback, long messageId, int timeout)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
long mid = messageId;
if (messageId == 0)
mid = MidGenerator.Gen();
Quest quest = new Quest("sendgroupmsg");
quest.Param("gid", groupId);
quest.Param("mid", mid);
quest.Param("mtype", mtype);
quest.Param("msg", message);
quest.Param("attrs", attrs);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
//long mtime = 0;
//if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
// mtime = answer.Want<long>("mtime");
callback(mid, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
private bool InternalSendGroupMessage(long groupId, byte mtype, string message, string attrs, SendMessageDelegate callback, long messageId, int timeout)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, 0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
long mid = messageId;
if (messageId == 0)
mid = MidGenerator.Gen();
Quest quest = new Quest("sendgroupmsg");
quest.Param("gid", groupId);
quest.Param("mid", mid);
quest.Param("mtype", mtype);
quest.Param("msg", message);
quest.Param("attrs", attrs);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
long mtime = 0;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
mtime = answer.Want<long>("mtime");
callback(mid, mtime, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, 0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
private int InternalSendGroupMessage(out long messageId, out long mtime, long groupId, byte mtype, string message, string attrs, long mid, int timeout)
{
mtime = 0;
TCPClient client = GetCoreClient();
if (client == null)
{
messageId = mid;
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
}
messageId = mid;
if (mid == 0)
messageId = MidGenerator.Gen();
Quest quest = new Quest("sendgroupmsg");
quest.Param("gid", groupId);
quest.Param("mid", messageId);
quest.Param("mtype", mtype);
quest.Param("msg", message);
quest.Param("attrs", attrs);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
mtime = answer.Want<long>("mtime");
return fpnn.ErrorCode.FPNN_EC_OK;
}
private bool InternalSendRoomMessage(long roomId, byte mtype, string message, string attrs, MessageIdDelegate callback, long messageId, int timeout)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
long mid = messageId;
if (messageId == 0)
mid = MidGenerator.Gen();
Quest quest = new Quest("sendroommsg");
quest.Param("rid", roomId);
quest.Param("mid", mid);
quest.Param("mtype", mtype);
quest.Param("msg", message);
quest.Param("attrs", attrs);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
//long mtime = 0;
//if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
// mtime = answer.Want<long>("mtime");
callback(mid, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
private bool InternalSendRoomMessage(long roomId, byte mtype, string message, string attrs, SendMessageDelegate callback, long messageId, int timeout)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, 0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
long mid = messageId;
if (messageId == 0)
mid = MidGenerator.Gen();
Quest quest = new Quest("sendroommsg");
quest.Param("rid", roomId);
quest.Param("mid", mid);
quest.Param("mtype", mtype);
quest.Param("msg", message);
quest.Param("attrs", attrs);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
long mtime = 0;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
mtime = answer.Want<long>("mtime");
callback(mid, mtime, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, 0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
private int InternalSendRoomMessage(out long messageId, out long mtime, long roomId, byte mtype, string message, string attrs, long mid, int timeout)
{
mtime = 0;
TCPClient client = GetCoreClient();
if (client == null)
{
messageId = mid;
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
}
messageId = mid;
if (mid == 0)
messageId = MidGenerator.Gen();
Quest quest = new Quest("sendroommsg");
quest.Param("rid", roomId);
quest.Param("mid", messageId);
quest.Param("mtype", mtype);
quest.Param("msg", message);
quest.Param("attrs", attrs);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
mtime = answer.Want<long>("mtime");
return fpnn.ErrorCode.FPNN_EC_OK;
}
//======================[ binary message version ]================================//
private bool InternalSendMessage(long uid, byte mtype, byte[] message, string attrs, MessageIdDelegate callback, long messageId, int timeout)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
long mid = messageId;
if (messageId == 0)
mid = MidGenerator.Gen();
Quest quest = new Quest("sendmsg");
quest.Param("to", uid);
quest.Param("mid", mid);
quest.Param("mtype", mtype);
quest.Param("msg", message);
quest.Param("attrs", attrs);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
//long mtime = 0;
//if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
// mtime = answer.Want<long>("mtime");
callback(mid, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
private bool InternalSendMessage(long uid, byte mtype, byte[] message, string attrs, SendMessageDelegate callback, long messageId, int timeout)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, 0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
long mid = messageId;
if (messageId == 0)
mid = MidGenerator.Gen();
Quest quest = new Quest("sendmsg");
quest.Param("to", uid);
quest.Param("mid", mid);
quest.Param("mtype", mtype);
quest.Param("msg", message);
quest.Param("attrs", attrs);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
long mtime = 0;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
mtime = answer.Want<long>("mtime");
callback(mid, mtime, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, 0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
private int InternalSendMessage(out long messageId, out long mtime, long uid, byte mtype, byte[] message, string attrs, long mid, int timeout)
{
mtime = 0;
TCPClient client = GetCoreClient();
if (client == null)
{
messageId = mid;
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
}
messageId = mid;
if (mid == 0)
messageId = MidGenerator.Gen();
Quest quest = new Quest("sendmsg");
quest.Param("to", uid);
quest.Param("mid", messageId);
quest.Param("mtype", mtype);
quest.Param("msg", message);
quest.Param("attrs", attrs);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
mtime = answer.Want<long>("mtime");
return fpnn.ErrorCode.FPNN_EC_OK;
}
private bool InternalSendGroupMessage(long groupId, byte mtype, byte[] message, string attrs, MessageIdDelegate callback, long messageId, int timeout)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
long mid = messageId;
if (messageId == 0)
mid = MidGenerator.Gen();
Quest quest = new Quest("sendgroupmsg");
quest.Param("gid", groupId);
quest.Param("mid", mid);
quest.Param("mtype", mtype);
quest.Param("msg", message);
quest.Param("attrs", attrs);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
//long mtime = 0;
//if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
// mtime = answer.Want<long>("mtime");
callback(mid, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
private bool InternalSendGroupMessage(long groupId, byte mtype, byte[] message, string attrs, SendMessageDelegate callback, long messageId, int timeout)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, 0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
long mid = messageId;
if (messageId == 0)
mid = MidGenerator.Gen();
Quest quest = new Quest("sendgroupmsg");
quest.Param("gid", groupId);
quest.Param("mid", mid);
quest.Param("mtype", mtype);
quest.Param("msg", message);
quest.Param("attrs", attrs);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
long mtime = 0;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
mtime = answer.Want<long>("mtime");
callback(mid, mtime, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, 0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
private int InternalSendGroupMessage(out long messageId, out long mtime, long groupId, byte mtype, byte[] message, string attrs, long mid, int timeout)
{
mtime = 0;
TCPClient client = GetCoreClient();
if (client == null)
{
messageId = mid;
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
}
messageId = mid;
if (mid == 0)
messageId = MidGenerator.Gen();
Quest quest = new Quest("sendgroupmsg");
quest.Param("gid", groupId);
quest.Param("mid", messageId);
quest.Param("mtype", mtype);
quest.Param("msg", message);
quest.Param("attrs", attrs);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
mtime = answer.Want<long>("mtime");
return fpnn.ErrorCode.FPNN_EC_OK;
}
private bool InternalSendRoomMessage(long roomId, byte mtype, byte[] message, string attrs, MessageIdDelegate callback, long messageId, int timeout)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
long mid = messageId;
if (messageId == 0)
mid = MidGenerator.Gen();
Quest quest = new Quest("sendroommsg");
quest.Param("rid", roomId);
quest.Param("mid", mid);
quest.Param("mtype", mtype);
quest.Param("msg", message);
quest.Param("attrs", attrs);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
//long mtime = 0;
//if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
// mtime = answer.Want<long>("mtime");
callback(mid, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
private bool InternalSendRoomMessage(long roomId, byte mtype, byte[] message, string attrs, SendMessageDelegate callback, long messageId, int timeout)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, 0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
long mid = messageId;
if (messageId == 0)
mid = MidGenerator.Gen();
Quest quest = new Quest("sendroommsg");
quest.Param("rid", roomId);
quest.Param("mid", mid);
quest.Param("mtype", mtype);
quest.Param("msg", message);
quest.Param("attrs", attrs);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
long mtime = 0;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
mtime = answer.Want<long>("mtime");
callback(mid, mtime, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(0, 0, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
private int InternalSendRoomMessage(out long messageId, out long mtime, long roomId, byte mtype, byte[] message, string attrs, long mid, int timeout)
{
mtime = 0;
TCPClient client = GetCoreClient();
if (client == null)
{
messageId = mid;
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
}
messageId = mid;
if (mid == 0)
messageId = MidGenerator.Gen();
Quest quest = new Quest("sendroommsg");
quest.Param("rid", roomId);
quest.Param("mid", messageId);
quest.Param("mtype", mtype);
quest.Param("msg", message);
quest.Param("attrs", attrs);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
mtime = answer.Want<long>("mtime");
return fpnn.ErrorCode.FPNN_EC_OK;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5e31f3e9ee2b14cd898b34496b5f97da
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2622dc5f09afe4c3fbf6d24dda5e30b9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,794 @@
using System;
using System.Collections.Generic;
using com.fpnn.common;
using com.fpnn.proto;
namespace com.fpnn.rtm
{
public partial class RTMClient
{
//===========================[ Enter Room ]=========================//
public bool EnterRoom(DoneDelegate callback, long roomId, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("enterroom");
quest.Param("rid", roomId);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int EnterRoom(long roomId, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("enterroom");
quest.Param("rid", roomId);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
public bool EnterRooms(DoneDelegate callback, HashSet<long> roomIds, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("enterrooms");
quest.Param("rids", roomIds);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int EnterRooms(HashSet<long> roomIds, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("enterrooms");
quest.Param("rids", roomIds);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
//===========================[ Leave Room ]=========================//
public bool LeaveRoom(DoneDelegate callback, long roomId, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("leaveroom");
quest.Param("rid", roomId);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int LeaveRoom(long roomId, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("leaveroom");
quest.Param("rid", roomId);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
//===========================[ Get User Rooms ]=========================//
//-- Action<roomIds, errorCode>
public bool GetUserRooms(Action<HashSet<long>, int> callback, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getuserrooms");
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
HashSet<long> roomIds = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
roomIds = WantLongHashSet(answer, "rooms");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(roomIds, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetUserRooms(out HashSet<long> roomIds, int timeout = 0)
{
roomIds = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getuserrooms");
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
roomIds = WantLongHashSet(answer, "rooms");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
//===========================[ Set Room Info ]=========================//
public bool SetRoomInfo(DoneDelegate callback, long roomId, string publicInfo = null, string privateInfo = null, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("setroominfo");
quest.Param("rid", roomId);
if (publicInfo != null)
quest.Param("oinfo", publicInfo);
if (privateInfo != null)
quest.Param("pinfo", privateInfo);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int SetRoomInfo(long roomId, string publicInfo = null, string privateInfo = null, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("setroominfo");
quest.Param("rid", roomId);
if (publicInfo != null)
quest.Param("oinfo", publicInfo);
if (privateInfo != null)
quest.Param("pinfo", privateInfo);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
//===========================[ Get Room Info ]=========================//
//-- Action<publicInfo, privateInfo, errorCode>
public bool GetRoomInfo(Action<string, string, int> callback, long roomId, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback("", "", fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getroominfo");
quest.Param("rid", roomId);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
string publicInfo = "";
string privateInfo = "";
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
publicInfo = answer.Want<string>("oinfo");
privateInfo = answer.Want<string>("pinfo");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(publicInfo, privateInfo, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback("", "", fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetRoomInfo(out string publicInfo, out string privateInfo, long roomId, int timeout = 0)
{
publicInfo = null;
privateInfo = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getroominfo");
quest.Param("rid", roomId);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
publicInfo = answer.Want<string>("oinfo");
privateInfo = answer.Want<string>("pinfo");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
//===========================[ Get Room Open Info ]=========================//
//-- Action<public_info, errorCode>
public bool GetRoomPublicInfo(Action<string, int> callback, long roomId, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback("", fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getroomopeninfo");
quest.Param("rid", roomId);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
string publicInfo = "";
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{ publicInfo = answer.Want<string>("oinfo"); }
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(publicInfo, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback("", fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetRoomPublicInfo(out string publicInfo, long roomId, int timeout = 0)
{
publicInfo = "";
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getroomopeninfo");
quest.Param("rid", roomId);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
publicInfo = answer.Want<string>("oinfo");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
//===========================[ Get Rooms Open Info ]=========================//
//-- Action<Dictionary<string_roomId, public_info>, errorCode>
[System.Obsolete("GetRoomsPublicInfo() with dictionary in string key type is deprecated, please using the overloaded function with dictionary in long key type instead.")]
public bool GetRoomsPublicInfo(Action<Dictionary<string, string>, int> callback, HashSet<long> roomIds, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getroomsopeninfo");
quest.Param("rids", roomIds);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
Dictionary<string, string> publicInfos = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
publicInfos = WantStringDictionary(answer, "info");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(publicInfos, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
//-- Action<Dictionary<roomId, public_info>, errorCode>
public bool GetRoomsPublicInfo(Action<Dictionary<long, string>, int> callback, HashSet<long> roomIds, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getroomsopeninfo");
quest.Param("rids", roomIds);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
Dictionary<long, string> publicInfos = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
publicInfos = WantLongStringDictionary(answer, "info");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(publicInfos, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
[System.Obsolete("GetRoomsPublicInfo() with dictionary in string key type is deprecated, please using the overloaded function with dictionary in long key type instead.")]
public int GetRoomsPublicInfo(out Dictionary<string, string> publicInfos, HashSet<long> roomIds, int timeout = 0)
{
publicInfos = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getroomsopeninfo");
quest.Param("rids", roomIds);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
publicInfos = WantStringDictionary(answer, "info");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
public int GetRoomsPublicInfo(out Dictionary<long, string> publicInfos, HashSet<long> roomIds, int timeout = 0)
{
publicInfos = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getroomsopeninfo");
quest.Param("rids", roomIds);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
publicInfos = WantLongStringDictionary(answer, "info");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
//===========================[ Get Room Members ]=========================//
//-- Action<HashSet<uids>, errorCode>
public bool GetRoomMembers(Action<HashSet<long>, int> callback, long roomId, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getroommembers");
quest.Param("rid", roomId);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
HashSet<long> uids = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
uids = WantLongHashSet(answer, "uids");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(uids, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetRoomMembers(out HashSet<long> uids, long roomId, int timeout = 0)
{
uids = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getroommembers");
quest.Param("rid", roomId);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
uids = WantLongHashSet(answer, "uids");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
//===========================[ Get Room Count ]=========================//
//-- Action<Dictionary<roomId, count>, errorCode>
public bool GetRoomMemberCount(Action<Dictionary<long, int>, int> callback, HashSet<long> roomIds, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getroomcount");
quest.Param("rids", roomIds);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
Dictionary<long, int> counts = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
counts = WantLongIntDictionary(answer, "cn");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(counts, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetRoomMemberCount(out Dictionary<long, int> counts, HashSet<long> roomIds, int timeout = 0)
{
counts = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getroomcount");
quest.Param("rids", roomIds);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
counts = WantLongIntDictionary(answer, "cn");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
//===========================[ Get User Room Last Message ]=========================//
void GetRoomLastMessage(ref Dictionary<long, HistoryMessage> roomMessages, Answer answer)
{
Dictionary<object, object> originalDict = (Dictionary<object, object>)answer.Want("rooms");
foreach (KeyValuePair<object, object> kvp in originalDict)
{
long roomId = (long)Convert.ChangeType(kvp.Key, TypeCode.Int64);
List<object> items = (List<object>)kvp.Value;
HistoryMessage message = new HistoryMessage();
message.cursorId = (long)Convert.ChangeType(items[0], TypeCode.Int64);
message.fromUid = (long)Convert.ChangeType(items[1], TypeCode.Int64);
message.toId = roomId;
message.messageType = (byte)Convert.ChangeType(items[2], TypeCode.Byte);
message.messageId = (long)Convert.ChangeType(items[3], TypeCode.Int64);
if (!CheckBinaryType(items[5]))
message.stringMessage = (string)Convert.ChangeType(items[5], TypeCode.String);
else
message.binaryMessage = (byte[])items[5];
message.attrs = (string)Convert.ChangeType(items[6], TypeCode.String);
message.modifiedTime = (long)Convert.ChangeType(items[7], TypeCode.Int64);
if (message.messageType >= 40 && message.messageType <= 50)
RTMClient.BuildFileInfo(message, errorRecorder);
roomMessages.Add(roomId, message);
}
}
public bool GetUserRoomLastMessage(Action<Dictionary<long, HistoryMessage>, int> callback, HashSet<long> mtypes = null, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getuserroomsandlastmsg");
if (mtypes != null)
quest.Param("mtypes", mtypes);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
Dictionary<long, HistoryMessage> roomMessages = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
roomMessages = new Dictionary<long, HistoryMessage>();
GetRoomLastMessage(ref roomMessages, answer);
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(roomMessages, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetUserRoomLastMessage(out Dictionary<long, HistoryMessage> roomMessages, HashSet<long> mtypes = null, int timeout = 0)
{
roomMessages = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getuserroomsandlastmsg");
if (mtypes != null)
quest.Param("mtypes", mtypes);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
roomMessages = new Dictionary<long, HistoryMessage>();
GetRoomLastMessage(ref roomMessages, answer); ;
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d13c3df96419848328a7e475f4c5c273
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,562 @@
using System;
using System.Collections.Generic;
using com.fpnn.proto;
namespace com.fpnn.rtm
{
public partial class RTMClient
{
public void Bye(bool async = true)
{
TCPClient client = GetCoreClient();
if (client == null)
{
Close();
return;
}
lock (interLocker)
{
if (autoReloginInfo != null)
autoReloginInfo.Disable();
}
Quest quest = new Quest("bye");
if (async)
{
bool success = client.SendQuest(quest, (Answer answer, int errorCode) => { Close(); });
if (!success)
Close();
}
else
{
client.SendQuest(quest);
Close();
}
}
//===========================[ Add Attributes ]=========================//
public bool AddAttributes(DoneDelegate callback, Dictionary<string, string> attrs, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("addattrs");
quest.Param("attrs", attrs);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int AddAttributes(Dictionary<string, string> attrs, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("addattrs");
quest.Param("attrs", attrs);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
//===========================[ Get Attributes ]=========================//
//-- Action<attributes, errorCode>
public bool GetAttributes(Action<Dictionary<string, string>, int> callback, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getattrs");
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
Dictionary<string, string> result = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
result = WantStringDictionary(answer, "attrs");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(result, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetAttributes(out Dictionary<string, string> attributes, int timeout = 0)
{
attributes = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getattrs");
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
attributes = WantStringDictionary(answer, "attrs");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
//===========================[ Add Debug Log ]=========================//
public bool AddDebugLog(DoneDelegate callback, string message, string attrs, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("adddebuglog");
quest.Param("msg", message);
quest.Param("attrs", attrs);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int AddDebugLog(string message, string attrs, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("adddebuglog");
quest.Param("msg", message);
quest.Param("attrs", attrs);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
//===========================[ Add Device ]=========================//
public bool AddDevice(DoneDelegate callback, string appType, string deviceToken, string tag = null, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("adddevice");
quest.Param("apptype", appType);
quest.Param("devicetoken", deviceToken);
if (tag != null)
quest.Param("tag", tag);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int AddDevice(string appType, string deviceToken, string tag = null, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("adddevice");
quest.Param("apptype", appType);
quest.Param("devicetoken", deviceToken);
if (tag != null)
quest.Param("tag", tag);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
//===========================[ Remove Device ]=========================//
public bool RemoveDevice(DoneDelegate callback, string deviceToken, string tag = null, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("removedevice");
quest.Param("devicetoken", deviceToken);
if (tag != null)
quest.Param("tag", tag);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int RemoveDevice(string deviceToken, string tag = null, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("removedevice");
quest.Param("devicetoken", deviceToken);
if (tag != null)
quest.Param("tag", tag);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
//===========================[ Add Device Push Option ]=========================//
public bool AddDevicePushOption(DoneDelegate callback, MessageCategory messageCategory, long targetId, HashSet<byte> mTypes = null, int timeout = 0)
{
byte type = 99;
switch (messageCategory)
{
case MessageCategory.P2PMessage:
type = 0; break;
case MessageCategory.GroupMessage:
type = 1; break;
}
return AddDevicePushOption(callback, type, targetId, mTypes, timeout);
}
internal bool AddDevicePushOption(DoneDelegate callback, byte type, long targetId, HashSet<byte> mTypes = null, int timeout = 0)
{
if (type > 1)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(ErrorCode.RTM_EC_INVALID_PARAMETER);
});
return false;
}
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("addoption");
quest.Param("type", type);
quest.Param("xid", targetId);
if (mTypes != null)
quest.Param("mtypes", mTypes);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int AddDevicePushOption(MessageCategory messageCategory, long targetId, HashSet<byte> mTypes = null, int timeout = 0)
{
byte type = 99;
switch (messageCategory)
{
case MessageCategory.P2PMessage:
type = 0; break;
case MessageCategory.GroupMessage:
type = 1; break;
}
return AddDevicePushOption(type, targetId, mTypes, timeout);
}
internal int AddDevicePushOption(byte type, long targetId, HashSet<byte> mTypes = null, int timeout = 0)
{
if (type > 1)
return ErrorCode.RTM_EC_INVALID_PARAMETER;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("addoption");
quest.Param("type", type);
quest.Param("xid", targetId);
if (mTypes != null)
quest.Param("mtypes", mTypes);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
//===========================[ Remove Device Push Option ]=========================//
public bool RemoveDevicePushOption(DoneDelegate callback, MessageCategory messageCategory, long targetId, HashSet<byte> mTypes = null, int timeout = 0)
{
byte type = 99;
switch (messageCategory)
{
case MessageCategory.P2PMessage:
type = 0; break;
case MessageCategory.GroupMessage:
type = 1; break;
}
return RemoveDevicePushOption(callback, type, targetId, mTypes, timeout);
}
internal bool RemoveDevicePushOption(DoneDelegate callback, byte type, long targetId, HashSet<byte> mTypes = null, int timeout = 0)
{
if (type > 1)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(ErrorCode.RTM_EC_INVALID_PARAMETER);
});
return false;
}
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("removeoption");
quest.Param("type", type);
quest.Param("xid", targetId);
if (mTypes != null)
quest.Param("mtypes", mTypes);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int RemoveDevicePushOption(MessageCategory messageCategory, long targetId, HashSet<byte> mTypes = null, int timeout = 0)
{
byte type = 99;
switch (messageCategory)
{
case MessageCategory.P2PMessage:
type = 0; break;
case MessageCategory.GroupMessage:
type = 1; break;
}
return RemoveDevicePushOption(type, targetId, mTypes, timeout);
}
internal int RemoveDevicePushOption(byte type, long targetId, HashSet<byte> mTypes = null, int timeout = 0)
{
if (type > 1)
return ErrorCode.RTM_EC_INVALID_PARAMETER;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("removeoption");
quest.Param("type", type);
quest.Param("xid", targetId);
if (mTypes != null)
quest.Param("mtypes", mTypes);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
//===========================[ Get Device Push Option ]=========================//
//-- Utilities functions
private Dictionary<long, HashSet<byte>> WantLongByteHashSetDictionary(Message message, string key)
{
Dictionary <long, HashSet<byte>> rev = new Dictionary<long, HashSet<byte>>();
Dictionary<object, object> originalDict = (Dictionary<object, object>)message.Want(key);
foreach (KeyValuePair<object, object> kvp in originalDict)
{
List<object> originalList = (List<object>)(kvp.Value);
HashSet<byte> resultSet = new HashSet<byte>();
foreach (object obj in originalList)
{
resultSet.Add((byte)Convert.ChangeType(obj, TypeCode.Byte));
}
rev.Add((long)Convert.ChangeType(kvp.Key, TypeCode.Int64), resultSet);
}
return rev;
}
//-- Action<Dictionary<p2p_uidHashSet<mType>>, Dictionary<groupId, HashSet<mType>>, errorCode>
public bool GetDevicePushOption(Action<Dictionary<long, HashSet<byte>>, Dictionary<long, HashSet<byte>>, int> callback, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getoption");
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
Dictionary<long, HashSet<byte>> p2pDictionary = null;
Dictionary<long, HashSet<byte>> groupDictionary = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
p2pDictionary = WantLongByteHashSetDictionary(answer, "p2p");
groupDictionary = WantLongByteHashSetDictionary(answer, "group");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(p2pDictionary, groupDictionary, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetDevicePushOption(out Dictionary<long, HashSet<byte>> p2pDictionary, out Dictionary<long, HashSet<byte>> groupDictionary, int timeout = 0)
{
p2pDictionary = null;
groupDictionary = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getoption");
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
p2pDictionary = WantLongByteHashSetDictionary(answer, "p2p");
groupDictionary = WantLongByteHashSetDictionary(answer, "group");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3687230688d70456b9134a3bcfabed46
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,305 @@
using System;
using System.Collections.Generic;
using com.fpnn.proto;
using com.fpnn.common;
namespace com.fpnn.rtm
{
public partial class RTMClient
{
public static string GetTranslatedLanguage(TranslateLanguage language)
{
if (language == TranslateLanguage.None)
return "";
if (language == TranslateLanguage.zh_cn)
return "zh-CN";
if (language == TranslateLanguage.zh_tw)
return "zh-TW";
return language.ToString("G");
}
public static HashSet<long> WantLongHashSet(Message message, string key)
{
HashSet<long> rev = new HashSet<long>();
List<object> originalList = (List<object>)message.Want(key);
foreach (object obj in originalList)
rev.Add((long)Convert.ChangeType(obj, TypeCode.Int64));
return rev;
}
private static HashSet<long> GetLongHashSet(Message message, string key)
{
HashSet<long> rev = new HashSet<long>();
List<object> originalList = (List<object>)message.Get(key);
if (originalList != null)
foreach (object obj in originalList)
rev.Add((long)Convert.ChangeType(obj, TypeCode.Int64));
return rev;
}
private static List<long> WantLongList(Message message, string key)
{
List<long> rev = new List<long>();
List<object> originalList = (List<object>)message.Want(key);
foreach (object obj in originalList)
rev.Add((long)Convert.ChangeType(obj, TypeCode.Int64));
return rev;
}
private static List<long> GetLongList(Message message, string key)
{
List<long> rev = new List<long>();
List<object> originalList = (List<object>)message.Get(key);
if (originalList == null)
return null;
foreach (object obj in originalList)
rev.Add((long)Convert.ChangeType(obj, TypeCode.Int64));
return rev;
}
private static List<List<long>> GetLongListList(Message message, string key)
{
List<List<long>> rev = new List<List<long>>();
List<object> originalList = (List<object>)message.Get(key);
if (originalList == null)
return null;
foreach (object obj in originalList)
{
if (obj == null)
continue;
List<long> list = new List<long>();
List<object> listObject = (List<object>)obj;
foreach (var val in listObject)
list.Add((long)Convert.ChangeType(val, TypeCode.Int64));
rev.Add(list);
}
return rev;
}
private static List<int> GetIntList(Message message, string key)
{
List<int> rev = new List<int>();
List<object> originalList = (List<object>)message.Get(key);
if (originalList == null)
return null;
foreach (object obj in originalList)
rev.Add((int)Convert.ChangeType(obj, TypeCode.Int32));
return rev;
}
private static List<bool> GetBoolList(Message message, string key)
{
List<bool> rev = new List<bool>();
List<object> originalList = (List<object>)message.Get(key);
if (originalList == null)
return null;
foreach (object obj in originalList)
rev.Add((bool)Convert.ChangeType(obj, TypeCode.Boolean));
return rev;
}
private List<string> GetStringList(Message message, string key)
{
List<string> rev = new List<string>();
List<object> originalList = (List<object>)message.Get(key);
if (originalList == null)
return null;
foreach (object obj in originalList)
rev.Add((string)Convert.ChangeType(obj, TypeCode.String));
return rev;
}
private Dictionary<string, Dictionary<string, string>> GetStringStringDictionary(Message message, string key)
{
Dictionary<string, Dictionary<string, string>> rev = new Dictionary<string, Dictionary<string, string>>();
Dictionary<object, Dictionary<object, object>> originalDict = (Dictionary<object, Dictionary<object, object>>)message.Want(key);
foreach (var kvp in originalDict)
{
Dictionary<string, string> subDict = new Dictionary<string, string>();
foreach(var kvp2 in kvp.Value)
subDict.Add((string)Convert.ChangeType(kvp2.Key, TypeCode.String), (string)Convert.ChangeType(kvp2.Value, TypeCode.String));
rev.Add((string)Convert.ChangeType(kvp.Key, TypeCode.String), subDict);
}
return rev;
}
private Dictionary<string, string> WantStringDictionary(Message message, string key)
{
Dictionary<string, string> rev = new Dictionary<string, string>();
Dictionary<object, object> originalDict = (Dictionary<object, object>)message.Want(key);
foreach (KeyValuePair<object, object> kvp in originalDict)
rev.Add((string)Convert.ChangeType(kvp.Key, TypeCode.String), (string)Convert.ChangeType(kvp.Value, TypeCode.String));
return rev;
}
private Dictionary<long, string> WantLongStringDictionary(Message message, string key)
{
Dictionary<long, string> rev = new Dictionary<long, string>();
Dictionary<object, object> originalDict = (Dictionary<object, object>)message.Want(key);
foreach (KeyValuePair<object, object> kvp in originalDict)
rev.Add((long)Convert.ChangeType(kvp.Key, TypeCode.Int64), (string)Convert.ChangeType(kvp.Value, TypeCode.String));
return rev;
}
private Dictionary<long, int> WantLongIntDictionary(Message message, string key)
{
Dictionary<long, int> rev = new Dictionary<long, int>();
Dictionary<object, object> originalDict = (Dictionary<object, object>)message.Want(key);
foreach (KeyValuePair<object, object> kvp in originalDict)
rev.Add((long)Convert.ChangeType(kvp.Key, TypeCode.Int64), (int)Convert.ChangeType(kvp.Value, TypeCode.Int32));
return rev;
}
private Dictionary<long, long> WantLongLongDictionary(Message message, string key)
{
Dictionary<long, long> rev = new Dictionary<long, long>();
Dictionary<object, object> originalDict = (Dictionary<object, object>)message.Want(key);
foreach (KeyValuePair<object, object> kvp in originalDict)
rev.Add((long)Convert.ChangeType(kvp.Key, TypeCode.Int64), (long)Convert.ChangeType(kvp.Value, TypeCode.Int64));
return rev;
}
private List<Dictionary<string, string>> GetListStringDictionary(Message message, string key)
{
List<Dictionary<string, string>> rev = new List<Dictionary<string, string>>();
List<Dictionary<object, object>> originalList = (List<Dictionary<object, object>>)message.Get(key);
foreach (var value in originalList)
{
Dictionary<string, string> dict = new Dictionary<string, string>();
foreach (var kv in value)
dict.Add((string)Convert.ChangeType(kv.Key, TypeCode.String), (string)Convert.ChangeType(kv.Value, TypeCode.String));
rev.Add(dict);
}
return rev;
}
internal static void ParseFileMessage(BaseMessage baseMessage, ErrorRecorder errorRecorder)
{
try
{
Dictionary<string, object> infoDict = Json.ParseObject(baseMessage.stringMessage);
if (infoDict != null)
{
if (infoDict.TryGetValue("url", out object urlText))
baseMessage.fileInfo.url = (string)urlText;
if (infoDict.TryGetValue("size", out object sizeInt))
baseMessage.fileInfo.size = (Int32)Convert.ChangeType(sizeInt, TypeCode.Int32);
if (baseMessage.messageType == (byte)MessageType.ImageFile)
{
if (infoDict.TryGetValue("surl", out object surlText))
baseMessage.fileInfo.surl = (string)surlText;
}
baseMessage.stringMessage = null;
}
}
catch (JsonException e)
{
if (errorRecorder != null)
errorRecorder.RecordError("Parse file msg error. Full msg: " + baseMessage.stringMessage, e);
}
}
internal static void ParseFileAttrs(BaseMessage baseMessage, ErrorRecorder errorRecorder)
{
try
{
Dictionary<string, object> attrsDict = Json.ParseObject(baseMessage.attrs);
if (attrsDict != null)
{
if (attrsDict.TryGetValue("rtm", out object rtmAttrs))
{
Dictionary<string, object> rtmAttrsDict = (Dictionary<string, object>)rtmAttrs;
if (rtmAttrsDict.TryGetValue("type", out object typeText))
{
string typeStr = (string)typeText;
if (typeStr.Equals("audiomsg"))
baseMessage.fileInfo.isRTMAudio = true;
}
if (baseMessage.fileInfo.isRTMAudio)
{
if (rtmAttrsDict.TryGetValue("lang", out object languageText))
baseMessage.fileInfo.language = (string)languageText;
if (rtmAttrsDict.TryGetValue("duration", out object durationInt))
baseMessage.fileInfo.duration = (Int32)Convert.ChangeType(durationInt, TypeCode.Int32);
}
}
if (attrsDict.TryGetValue("custom", out object attrsInfo))
{
try
{
Dictionary<string, object> userAttrsDict = (Dictionary<string, object>)attrsInfo;
baseMessage.attrs = Json.ToString(userAttrsDict);
return;
}
catch (Exception)
{
try
{
string userAttrs = (string)attrsInfo;
baseMessage.attrs = userAttrs;
return;
}
catch (Exception ex)
{
if (errorRecorder != null)
errorRecorder.RecordError("Convert user attrs to string type for file attrs error. Full attrs: " + baseMessage.attrs, ex);
}
}
}
}
}
catch (JsonException e)
{
if (errorRecorder != null)
errorRecorder.RecordError("Parse file attrs error. Full attrs: " + baseMessage.attrs, e);
}
}
internal static void BuildFileInfo(BaseMessage baseMessage, ErrorRecorder errorRecorder)
{
baseMessage.fileInfo = new FileInfo();
ParseFileMessage(baseMessage, errorRecorder);
ParseFileAttrs(baseMessage, errorRecorder);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 31055209098fa4d01a29a37a2ba0e6f8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,347 @@
using System;
using System.Collections.Generic;
using com.fpnn.proto;
namespace com.fpnn.rtm
{
public partial class RTMClient
{
//===========================[ Get Online Users ]=========================//
//-- Action<online_uids, errorCode>
public bool GetOnlineUsers(Action<HashSet<long>, int> callback, HashSet<long> uids, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getonlineusers");
quest.Param("uids", uids);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
HashSet<long> onlineUids = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
onlineUids = WantLongHashSet(answer, "uids");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(onlineUids, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetOnlineUsers(out HashSet<long> onlineUids, HashSet<long> uids, int timeout = 0)
{
onlineUids = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getonlineusers");
quest.Param("uids", uids);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
onlineUids = WantLongHashSet(answer, "uids");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
//===========================[ Set User Info ]=========================//
public bool SetUserInfo(DoneDelegate callback, string publicInfo = null, string privateInfo = null, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("setuserinfo");
if (publicInfo != null)
quest.Param("oinfo", publicInfo);
if (privateInfo != null)
quest.Param("pinfo", privateInfo);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => { callback(errorCode); }, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int SetUserInfo(string publicInfo = null, string privateInfo = null, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("setuserinfo");
if (publicInfo != null)
quest.Param("oinfo", publicInfo);
if (privateInfo != null)
quest.Param("pinfo", privateInfo);
Answer answer = client.SendQuest(quest, timeout);
return answer.ErrorCode();
}
//===========================[ Get User Info ]=========================//
//-- Action<publicInfo, privateInfo, errorCode>
public bool GetUserInfo(Action<string, string, int> callback, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getuserinfo");
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
string publicInfo = null;
string privateInfo = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
publicInfo = answer.Want<string>("oinfo");
privateInfo = answer.Want<string> ("pinfo");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(publicInfo, privateInfo, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
public int GetUserInfo(out string publicInfo, out string privateInfo, int timeout = 0)
{
publicInfo = null;
privateInfo = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getuserinfo");
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
publicInfo = answer.Want<string>("oinfo");
privateInfo = answer.Want<string>("pinfo");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
//===========================[ Get User Open Info ]=========================//
//-- Action<Dictionary<string_uid, public_info>, errorCode>
[System.Obsolete("GetUserPublicInfo() with dictionary in string key type is deprecated, please using the overloaded function with dictionary in long key type instead.")]
public bool GetUserPublicInfo(Action<Dictionary<string, string>, int> callback, HashSet<long> uids, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getuseropeninfo");
quest.Param("uids", uids);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
Dictionary<string, string> publicInfos = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
publicInfos = WantStringDictionary(answer, "info");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(publicInfos, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
//-- Action<Dictionary<uid, public_info>, errorCode>
public bool GetUserPublicInfo(Action<Dictionary<long, string>, int> callback, HashSet<long> uids, int timeout = 0)
{
TCPClient client = GetCoreClient();
if (client == null)
{
if (RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return false;
}
Quest quest = new Quest("getuseropeninfo");
quest.Param("uids", uids);
bool asyncStarted = client.SendQuest(quest, (Answer answer, int errorCode) => {
Dictionary<long, string> publicInfos = null;
if (errorCode == fpnn.ErrorCode.FPNN_EC_OK)
{
try
{
publicInfos = WantLongStringDictionary(answer, "info");
}
catch (Exception)
{
errorCode = fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
callback(publicInfos, errorCode);
}, timeout);
if (!asyncStarted && RTMConfig.triggerCallbackIfAsyncMethodReturnFalse)
ClientEngine.RunTask(() =>
{
callback(null, fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);
});
return asyncStarted;
}
[System.Obsolete("GetUserPublicInfo() with dictionary in string key type is deprecated, please using the overloaded function with dictionary in long key type instead.")]
public int GetUserPublicInfo(out Dictionary<string, string> publicInfos, HashSet<long> uids, int timeout = 0)
{
publicInfos = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getuseropeninfo");
quest.Param("uids", uids);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
publicInfos = WantStringDictionary(answer, "info");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
public int GetUserPublicInfo(out Dictionary<long, string> publicInfos, HashSet<long> uids, int timeout = 0)
{
publicInfos = null;
TCPClient client = GetCoreClient();
if (client == null)
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION;
Quest quest = new Quest("getuseropeninfo");
quest.Param("uids", uids);
Answer answer = client.SendQuest(quest, timeout);
if (answer.IsException())
return answer.ErrorCode();
try
{
publicInfos = WantLongStringDictionary(answer, "info");
return fpnn.ErrorCode.FPNN_EC_OK;
}
catch (Exception)
{
return fpnn.ErrorCode.FPNN_EC_CORE_INVALID_PACKAGE;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7562b11f9e2a64037a65479e77af641e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,133 @@
using System;
namespace com.fpnn.rtm
{
public class RegressiveStrategy
{
public int maxIntervalSeconds = 8; //-- 退行性重连最大时间间隔
public int linearRegressiveCount = 4; //-- 从第一次退行性连接开始,到最大链接时间,允许尝试几次连接,每次时间间隔都会增大
public int maxRegressvieCount = 10; //-- 退行性重连最大次数,超出该次数则不再进行重连
}
public class RTMConfig
{
public static readonly string SDKVersion = "2.7.20";
public static readonly string InterfaceVersion = "2.7.3";
public static readonly string RTMGameObjectName = "RTM_GAMEOBJECT";
internal static int lostConnectionAfterLastPingInSeconds = 60;
internal static int globalConnectTimeoutSeconds = 30;
internal static int globalQuestTimeoutSeconds = 30;
internal static int fileGateClientHoldingSeconds = 150;
internal static common.ErrorRecorder errorRecorder = null;
internal static bool triggerCallbackIfAsyncMethodReturnFalse = false;
internal static RegressiveStrategy globalRegressiveStrategy = new RegressiveStrategy();
public int maxPingInterval;
public int globalConnectTimeout;
public int globalQuestTimeout;
public int fileClientHoldingSeconds;
public common.ErrorRecorder defaultErrorRecorder;
public bool forceTriggerCallbackWhenAsyncMethodReturnFalse;
public long adminID;
public RegressiveStrategy regressiveStrategy;
public RTMConfig()
{
maxPingInterval = 60;
globalConnectTimeout = 30;
globalQuestTimeout = 30;
fileClientHoldingSeconds = 150;
forceTriggerCallbackWhenAsyncMethodReturnFalse = false;
adminID = 111;
regressiveStrategy = new RegressiveStrategy();
}
internal static void Config(RTMConfig config)
{
lostConnectionAfterLastPingInSeconds = config.maxPingInterval;
globalConnectTimeoutSeconds = config.globalConnectTimeout;
globalQuestTimeoutSeconds = config.globalQuestTimeout;
fileGateClientHoldingSeconds = config.fileClientHoldingSeconds;
errorRecorder = config.defaultErrorRecorder;
triggerCallbackIfAsyncMethodReturnFalse = config.forceTriggerCallbackWhenAsyncMethodReturnFalse;
globalRegressiveStrategy = config.regressiveStrategy;
}
}
public enum TranslateLanguage
{
ar, //阿拉伯语
nl, //荷兰语
en, //英语
fr, //法语
de, //德语
el, //希腊语
id, //印度尼西亚语
it, //意大利语
ja, //日语
ko, //韩语
no, //挪威语
pl, //波兰语
pt, //葡萄牙语
ru, //俄语
es, //西班牙语
sv, //瑞典语
tl, //塔加路语(菲律宾语)
th, //泰语
tr, //土耳其语
vi, //越南语
zh_cn, //中文(简体)
zh_tw, //中文(繁体)
None
}
public enum MessageType : byte
{
Withdraw = 1,
GEO = 2,
SystemNotification = 6,
MultiLogin = 7,
Chat = 30,
Cmd = 32,
RealAudio = 35,
RealVideo = 36,
ImageFile = 40,
AudioFile = 41,
VideoFile = 42,
VoiceFile = 43,
NormalFile = 50
}
public enum MessageCategory : byte
{
P2PMessage = 1,
GroupMessage = 2,
RoomMessage = 3,
BroadcastMessage = 4
}
public enum IMLIB_MessageType
{
AddFriendApply = 1,
RefuseFriendApply = 2,
EnterGroupApply = 3,
RefuseEnterGroupApply = 4,
InvitedIntoGroup = 5,
RefuseInvitedIntoGroup = 7,
FriendChanged = 15,
GroupChanged = 17,
GroupMemberChanged = 19,
RoomMemberChanged = 20,
AcceptFriendApply = 21,
AcceptEnterGroupApply = 22,
AcceptInvitedIntoGroup = 24,
AddGroupManagers = 26,
RemoveGroupManagers = 27,
GroupOwnerChanged = 28,
AddRoomManagers = 29,
RemoveRoomManagers = 30,
RoomOwnerChanged = 31,
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8421e6d8001b9435797cf8212505374d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,471 @@
using System;
using System.Collections.Generic;
using System.Threading;
using static com.fpnn.rtm.RTMClient;
#if UNITY_2017_1_OR_NEWER
using UnityEngine;
#endif
namespace com.fpnn.rtm
{
public static class RTMControlCenter
{
private static object interLocker = new object();
//private static volatile bool networkReachable = true;
private static volatile NetworkType networkType = NetworkType.NetworkType_Uninited;
private static Dictionary<Int64, RTMClient> rtmClients = new Dictionary<long, RTMClient>();
private static Dictionary<Int64, Dictionary<Int64, RTMClient>> pidUidClients = new Dictionary<Int64, Dictionary<Int64, RTMClient>>();
private static Dictionary<RTMClient, Int64> reloginClients = new Dictionary<RTMClient, Int64>();
private static Dictionary<string, Dictionary<TCPClient, long>> fileClients = new Dictionary<string, Dictionary<TCPClient, long>>();
private static volatile bool routineInited;
private static volatile bool routineRunning;
private static Thread routineThread;
private static GameObject rtmGameObject;
public static RTMCallbackQueue callbackQueue;
static RTMControlCenter()
{
routineInited = false;
}
public static NetworkType NetworkStatus
{
get { return networkType; }
}
//===========================[ Session Functions ]=========================//
internal static void RegisterSession(Int64 connectionId, RTMClient client)
{
CheckRoutineInit();
lock (interLocker)
{
rtmClients.Add(connectionId, client);
}
}
internal static void UnregisterSession(Int64 connectionId)
{
lock (interLocker)
{
rtmClients.Remove(connectionId);
}
}
internal static void CloseSession(Int64 connectionId)
{
RTMClient client = null;
lock (interLocker)
{
rtmClients.TryGetValue(connectionId, out client);
}
if (client != null)
client.Close();
}
internal static ClientStatus GetClientStatus(Int64 connectionId)
{
RTMClient client = null;
lock (interLocker)
{
rtmClients.TryGetValue(connectionId, out client);
}
if (client != null)
return client.Status;
else
return ClientStatus.Closed;
}
internal static void AddClient(Int64 projectId, Int64 uid, RTMClient client)
{
lock (interLocker)
{
pidUidClients.TryGetValue(projectId, out Dictionary<Int64, RTMClient> clients);
if (clients == null)
{
clients = new Dictionary<long, RTMClient>{ { uid, client } };
pidUidClients.Add(projectId, clients);
}
else
{
clients.TryGetValue(uid, out RTMClient rtmClient);
if (rtmClient == null)
clients.Add(uid, client);
else
throw new Exception("duplicated RTMClient pid = " + projectId.ToString() + ", uid = " + uid.ToString());
}
}
}
internal static RTMClient FetchClient(Int64 projectId, Int64 uid)
{
RTMClient client = null;
lock (interLocker)
{
pidUidClients.TryGetValue(projectId, out Dictionary<Int64, RTMClient> clients);
if (clients == null)
return null;
clients.TryGetValue(uid, out client);
}
return client;
}
//===========================[ Relogin Functions ]=========================//
internal static void DelayRelogin(RTMClient client, long triggeredMs)
{
CheckRoutineInit();
lock (interLocker)
{
try
{
reloginClients.Add(client, triggeredMs);
}
catch (ArgumentException)
{
//-- Do nothing.
}
}
}
private static void ReloginCheck()
{
//if (!networkReachable)
//return;
if (networkType != NetworkType.NetworkType_4G && networkType != NetworkType.NetworkType_Wifi)
return;
HashSet<RTMClient> clients = new HashSet<RTMClient>();
long now = ClientEngine.GetCurrentMilliseconds();
lock (interLocker)
{
foreach (KeyValuePair<RTMClient, Int64> kvp in reloginClients)
{
if (kvp.Value <= now)
clients.Add(kvp.Key);
}
foreach (RTMClient client in clients)
reloginClients.Remove(client);
}
foreach (RTMClient client in clients)
{
ClientEngine.RunTask(() => {
if (client.CheckRelogin())
client.StartRelogin();
else
{
lock (interLocker)
{
reloginClients.Add(client, now);
}
}
});
}
}
//internal static void NetworkReachableChanged(bool reachable)
//{
// if (reachable != networkReachable)
// {
// networkReachable = reachable;
// long now = ClientEngine.GetCurrentMilliseconds();
// if (reachable)
// {
// Dictionary<RTMClient, Int64> clients = new Dictionary<RTMClient, Int64>();
// lock (interLocker)
// {
// foreach (KeyValuePair<RTMClient, Int64> kvp in reloginClients)
// clients.Add(kvp.Key, now);
// reloginClients = clients;
// }
// }
// else
// {
// lock (interLocker)
// {
// foreach (KeyValuePair<UInt64, RTMClient> kvp in rtmClients)
// {
// kvp.Value.Close();
// reloginClients.Add(kvp.Value, now);
// }
// }
// }
// }
//}
internal static void NetworkChanged(NetworkType type)
{
if (networkType == NetworkType.NetworkType_Uninited)
networkType = type;
if (type == NetworkType.NetworkType_Unknown)
type = NetworkType.NetworkType_Unreachable;
if (networkType == type)
return;
long now = ClientEngine.GetCurrentMilliseconds();
NetworkType oldType = networkType;
networkType = type;
ClientEngine.RunTask(()=>
{
if (oldType == NetworkType.NetworkType_Unreachable && (type == NetworkType.NetworkType_4G || type == NetworkType.NetworkType_Wifi))
{//之前没有网络,现在有网络
Dictionary<RTMClient, Int64> clients = new Dictionary<RTMClient, Int64>();
List<RTMClient> activeClients = new List<RTMClient>();
lock (interLocker)
{
foreach (KeyValuePair<RTMClient, Int64> kvp in reloginClients)
clients.Add(kvp.Key, now);
foreach (KeyValuePair<Int64, RTMClient> kvp in rtmClients)
{
if (!clients.ContainsKey(kvp.Value))
{
if (kvp.Value.Status != ClientStatus.Connecting)
{
activeClients.Add(kvp.Value);
clients.Add(kvp.Value, now);
}
}
}
foreach (RTMClient client in activeClients)
client.Close(false, false);
reloginClients = clients;
}
}
else if ((type == NetworkType.NetworkType_4G && oldType == NetworkType.NetworkType_Wifi) || (oldType == NetworkType.NetworkType_4G && type == NetworkType.NetworkType_Wifi))
{
lock (interLocker)
{
List<RTMClient> clients = new List<RTMClient>();
foreach (KeyValuePair<Int64, RTMClient> kvp in rtmClients)
{
if (kvp.Value.Status != ClientStatus.Connecting)
{
clients.Add(kvp.Value);
}
}
foreach (RTMClient client in clients)
client.Close(false, false);
}
}
else
{
lock (interLocker)
{
List<RTMClient> clients = new List<RTMClient>();
foreach (KeyValuePair<Int64, RTMClient> kvp in rtmClients)
{
if (kvp.Value.Status != ClientStatus.Connecting)
{
clients.Add(kvp.Value);
reloginClients.Add(kvp.Value, now);
}
}
foreach (RTMClient client in clients)
client.Close(false, false);
}
}
});
}
//===========================[ File Gate Client Functions ]=========================//
internal static void ActiveFileGateClient(string endpoint, TCPClient client)
{
lock (interLocker)
{
if (fileClients.TryGetValue(endpoint, out Dictionary<TCPClient, long> clients))
{
if (clients.ContainsKey(client))
clients[client] = ClientEngine.GetCurrentSeconds();
else
clients.Add(client, ClientEngine.GetCurrentSeconds());
}
else
{
clients = new Dictionary<TCPClient, long>
{
{ client, ClientEngine.GetCurrentSeconds() }
};
fileClients.Add(endpoint, clients);
}
}
}
internal static TCPClient FecthFileGateClient(string endpoint)
{
lock (interLocker)
{
if (fileClients.TryGetValue(endpoint, out Dictionary<TCPClient, long> clients))
{
foreach (KeyValuePair<TCPClient, long> kvp in clients)
return kvp.Key;
}
}
return null;
}
private static void CheckFileGateClients()
{
HashSet<string> emptyEndpoints = new HashSet<string>();
lock (interLocker)
{
long threshold = ClientEngine.GetCurrentSeconds() - RTMConfig.fileGateClientHoldingSeconds;
foreach (KeyValuePair<string, Dictionary<TCPClient, long>> kvp in fileClients)
{
HashSet<TCPClient> unactivedClients = new HashSet<TCPClient>();
foreach (KeyValuePair<TCPClient, long> subKvp in kvp.Value)
{
if (subKvp.Value <= threshold)
unactivedClients.Add(subKvp.Key);
}
foreach (TCPClient client in unactivedClients)
{
kvp.Value.Remove(client);
}
if (kvp.Value.Count == 0)
emptyEndpoints.Add(kvp.Key);
}
foreach (string endpoint in emptyEndpoints)
fileClients.Remove(endpoint);
}
}
//===========================[ Init & Routine Functions ]=========================//
public static void Init()
{
Init(null);
}
public static void Init(RTMConfig config)
{
#if UNITY_2017_1_OR_NEWER
StatusMonitor.Instance.Init();
#endif
InitCallbackQueue();
if (config == null)
return;
RTMConfig.Config(config);
}
private static void InitCallbackQueue()
{
rtmGameObject = new GameObject(RTMConfig.RTMGameObjectName);
callbackQueue = rtmGameObject.AddComponent<RTMCallbackQueue>();
GameObject.DontDestroyOnLoad(rtmGameObject);
rtmGameObject.hideFlags = HideFlags.HideInHierarchy;
}
private static void CheckRoutineInit()
{
if (routineInited)
return;
lock (interLocker)
{
if (routineInited)
return;
routineRunning = true;
routineThread = new Thread(RoutineFunc)
{
Name = "RTM.ControlCenter.RoutineThread",
#if UNITY_2017_1_OR_NEWER
#else
IsBackground = true
#endif
};
routineThread.Start();
routineInited = true;
}
}
private static void RoutineFunc()
{
while (routineRunning)
{
Thread.Sleep(1000);
HashSet<RTMClient> clients;
try
{
clients = new HashSet<RTMClient>();
}
catch (Exception e)
{
RTMConfig.errorRecorder?.RecordError(e);
continue;
}
lock (interLocker)
{
foreach (KeyValuePair<Int64, RTMClient> kvp in rtmClients)
clients.Add(kvp.Value);
}
foreach (RTMClient client in clients)
if (client.ConnectionIsAlive() == false)
client.Close(false, true);
CheckFileGateClients();
ReloginCheck();
}
}
public static void Close()
{
#if (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN)
AudioRecorderNative.destroy();
#endif
StatusMonitor.Instance.Close();
lock (interLocker)
{
if (!routineInited)
return;
if (!routineRunning)
return;
routineRunning = false;
}
#if UNITY_2017_1_OR_NEWER
routineThread.Join();
#endif
HashSet<RTMClient> clients = new HashSet<RTMClient>();
lock (interLocker)
{
foreach (KeyValuePair<Int64, RTMClient> kvp in rtmClients)
clients.Add(kvp.Value);
}
foreach (RTMClient client in clients)
client.Close(true, true);
rtmClients.Clear();
pidUidClients.Clear();
reloginClients.Clear();
fileClients.Clear();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dadf9429ba622491882482f8801503c0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
using System;
using com.fpnn.common;
namespace com.fpnn.rtm
{
public interface IRTMMasterProcessor: IQuestProcessor
{
void SetErrorRecorder(ErrorRecorder recorder);
void SetConnectionId(Int64 connId);
void BeginCheckPingInterval();
bool ConnectionIsAlive();
void SessionClosed(int ClosedByErrorCode);
bool ReloginWillStart(int lastErrorCode, int retriedCount);
void ReloginCompleted(bool successful, bool retryAgain, int errorCode, int retriedCount);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 61fa0a40c29974b65b1b6548d0db902f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,582 @@
using System;
using System.Collections.Generic;
using System.Threading;
using com.fpnn.common;
using com.fpnn.proto;
namespace com.fpnn.rtm
{
public delegate void SessionClosedDelegate(int ClosedByErrorCode);
public delegate bool ReloginWillStartDelegate(int lastErrorCode, int retriedCount);
public delegate void ReloginCompletedDelegate(bool successful, bool retryAgain, int errorCode, int retriedCount);
public delegate void KickOutDelegate();
public delegate void KickoutRoomDelegate(long roomId);
public delegate void PushMessageDelegate(RTMMessage message);
public class RTMQuestProcessor
{
//----------------[ System Events ]-----------------//
public virtual void SessionClosed(int ClosedByErrorCode) { } //-- ErrorCode: com.fpnn.ErrorCode & com.fpnn.rtm.ErrorCode
public SessionClosedDelegate SessionClosedCallback;
//-- Return true for starting relogin, false for stopping relogin.
public virtual bool ReloginWillStart(int lastErrorCode, int retriedCount) { return true; }
public ReloginWillStartDelegate ReloginWillStartCallback;
public virtual void ReloginCompleted(bool successful, bool retryAgain, int errorCode, int retriedCount) { }
public ReloginCompletedDelegate ReloginCompletedCallback;
public virtual void Kickout() { }
public KickOutDelegate KickoutCallback;
public virtual void KickoutRoom(long roomId) { }
public KickoutRoomDelegate KickoutRoomCallback;
//----------------[ Message Interfaces ]-----------------//
//-- Messages
public virtual void PushMessage(RTMMessage message) { }
public PushMessageDelegate PushMessageCallback;
public virtual void PushGroupMessage(RTMMessage message) { }
public PushMessageDelegate PushGroupMessageCallback;
public virtual void PushRoomMessage(RTMMessage message) { }
public PushMessageDelegate PushRoomMessageCallback;
public virtual void PushBroadcastMessage(RTMMessage message) { }
public PushMessageDelegate PushBroadcastMessageCallback;
//-- Chat
public virtual void PushChat(RTMMessage message) { }
public PushMessageDelegate PushChatCallback;
public virtual void PushGroupChat(RTMMessage message) { }
public PushMessageDelegate PushGroupChatCallback;
public virtual void PushRoomChat(RTMMessage message) { }
public PushMessageDelegate PushRoomChatCallback;
public virtual void PushBroadcastChat(RTMMessage message) { }
public PushMessageDelegate PushBroadcastChatCallback;
//-- Cmd
public virtual void PushCmd(RTMMessage message) { }
public PushMessageDelegate PushCmdCallback;
public virtual void PushGroupCmd(RTMMessage message) { }
public PushMessageDelegate PushGroupCmdCallback;
public virtual void PushRoomCmd(RTMMessage message) { }
public PushMessageDelegate PushRoomCmdCallback;
public virtual void PushBroadcastCmd(RTMMessage message) { }
public PushMessageDelegate PushBroadcastCmdCallback;
//-- Files
public virtual void PushFile(RTMMessage message) { }
public PushMessageDelegate PushFileCallback;
public virtual void PushGroupFile(RTMMessage message) { }
public PushMessageDelegate PushGroupFileCallback;
public virtual void PushRoomFile(RTMMessage message) { }
public PushMessageDelegate PushRoomFileCallback;
public virtual void PushBroadcastFile(RTMMessage message) { }
public PushMessageDelegate PushBroadcastFileCallback;
}
public class RTMMasterProcessor: IRTMMasterProcessor
{
private RTMQuestProcessor questProcessor;
private DuplicatedMessageFilter duplicatedFilter;
private ErrorRecorder errorRecorder;
private Int64 connectionId;
private Int64 lastPingTime;
private readonly Dictionary<string, QuestProcessDelegate> methodMap;
public RTMMasterProcessor()
{
duplicatedFilter = new DuplicatedMessageFilter();
lastPingTime = 0;
methodMap = new Dictionary<string, QuestProcessDelegate> {
{ "ping", Ping },
{ "kickout", Kickout },
{ "kickoutroom", KickoutRoom },
{ "pushmsg", PushMessage },
{ "pushgroupmsg", PushGroupMessage },
{ "pushroommsg", PushRoomMessage },
{ "pushbroadcastmsg", PushBroadcastMessage },
};
}
public void SetProcessor(RTMQuestProcessor processor)
{
questProcessor = processor;
}
public void SetErrorRecorder(ErrorRecorder recorder)
{
errorRecorder = recorder;
}
public void SetConnectionId(Int64 connId)
{
connectionId = connId;
Interlocked.Exchange(ref lastPingTime, 0);
}
public void BeginCheckPingInterval()
{
Int64 now = ClientEngine.GetCurrentSeconds();
Interlocked.Exchange(ref lastPingTime, now);
}
public bool ConnectionIsAlive()
{
Int64 lastPingSec = Interlocked.Read(ref lastPingTime);
if (lastPingSec == 0 || ClientEngine.GetCurrentSeconds() - lastPingSec < RTMConfig.lostConnectionAfterLastPingInSeconds)
return true;
else
return false;
}
public QuestProcessDelegate GetQuestProcessDelegate(string method)
{
if (methodMap.TryGetValue(method, out QuestProcessDelegate process))
{
return process;
}
return null;
}
public void SessionClosed(int ClosedByErrorCode)
{
if (questProcessor != null)
{
questProcessor.SessionClosed(ClosedByErrorCode);
RTMControlCenter.callbackQueue.PostAction(() => {
questProcessor.SessionClosedCallback?.Invoke(ClosedByErrorCode);
});
}
RTMControlCenter.UnregisterSession(connectionId);
}
public bool ReloginWillStart(int lastErrorCode, int retriedCount)
{
bool startRelogin = true;
if (questProcessor != null)
{
if (questProcessor.ReloginWillStartCallback == null)
startRelogin = questProcessor.ReloginWillStart(lastErrorCode, retriedCount);
else
{
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.ReloginWillStartCallback?.Invoke(lastErrorCode, retriedCount);
});
}
}
if (startRelogin) //-- if startRelogin == false, will call SessionClosed(), the UnregisterSession() will be called in SessionClosed().
RTMControlCenter.UnregisterSession(connectionId);
return startRelogin;
}
public void ReloginCompleted(bool successful, bool retryAgain, int errorCode, int retriedCount)
{
if (questProcessor != null)
{
questProcessor.ReloginCompleted(successful, retryAgain, errorCode, retriedCount);
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.ReloginCompletedCallback?.Invoke(successful, retryAgain, errorCode, retriedCount);
});
}
}
//----------------------[ RTM Operations ]-------------------//
public Answer Ping(Int64 connectionId, string endpoint, Quest quest)
{
AdvanceAnswer.SendAnswer(new Answer(quest));
Int64 now = ClientEngine.GetCurrentSeconds();
Interlocked.Exchange(ref lastPingTime, now);
return null;
}
public Answer Kickout(Int64 connectionId, string endpoint, Quest quest)
{
bool closed = RTMControlCenter.GetClientStatus(connectionId) == RTMClient.ClientStatus.Closed;
RTMControlCenter.CloseSession(connectionId);
if (questProcessor != null && closed == false)
{
questProcessor.Kickout();
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.KickoutCallback?.Invoke();
});
}
return null;
}
public Answer KickoutRoom(Int64 connectionId, string endpoint, Quest quest)
{
if (questProcessor != null)
{
long roomId = quest.Want<Int64>("rid");
questProcessor.KickoutRoom(roomId);
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.KickoutRoomCallback?.Invoke(roomId);
});
}
return null;
}
//----------------------[ RTM Messagess Utilities ]-------------------//
private TranslatedInfo ProcessChatMessage(Quest quest)
{
TranslatedInfo tm = new TranslatedInfo();
try
{
Dictionary<object, object> msg = quest.Want<Dictionary<object, object>>("msg");
if (msg.TryGetValue("source", out object source))
{
tm.sourceLanguage = (string)source;
}
else
tm.sourceLanguage = string.Empty;
if (msg.TryGetValue("target", out object target))
{
tm.targetLanguage = (string)target;
}
else
tm.targetLanguage = string.Empty;
if (msg.TryGetValue("sourceText", out object sourceText))
{
tm.sourceText = (string)sourceText;
}
else
tm.sourceText = string.Empty;
if (msg.TryGetValue("targetText", out object targetText))
{
tm.targetText = (string)targetText;
}
else
tm.targetText = string.Empty;
return tm;
}
catch (InvalidCastException e)
{
if (errorRecorder != null)
errorRecorder.RecordError("ProcessChatMessage failed.", e);
return null;
}
}
private class MessageInfo
{
public bool isBinary;
public byte[] binaryData;
public string message;
}
private MessageInfo BuildMessageInfo(Quest quest)
{
MessageInfo info = new MessageInfo();
object message = quest.Want("msg");
info.isBinary = RTMClient.CheckBinaryType(message);
if (info.isBinary)
info.binaryData = (byte[])message;
else
info.message = (string)message;
return info;
}
private RTMMessage BuildRTMMessage(Quest quest, long from, long to, long mid)
{
RTMMessage rtmMessage = new RTMMessage
{
fromUid = from,
toId = to,
messageId = mid,
messageType = quest.Want<byte>("mtype"),
attrs = quest.Want<string>("attrs"),
modifiedTime = quest.Want<long>("mtime")
};
if (rtmMessage.messageType == (byte)MessageType.Chat)
{
rtmMessage.translatedInfo = ProcessChatMessage(quest);
if (rtmMessage.translatedInfo != null)
{
if (rtmMessage.translatedInfo.targetText.Length > 0)
rtmMessage.stringMessage = rtmMessage.translatedInfo.targetText;
else
rtmMessage.stringMessage = rtmMessage.translatedInfo.sourceText;
}
}
else if (rtmMessage.messageType == (byte)MessageType.Cmd)
{
rtmMessage.stringMessage = quest.Want<string>("msg");
}
else if (rtmMessage.messageType >= 40 && rtmMessage.messageType <= 50)
{
rtmMessage.stringMessage = quest.Want<string>("msg");
RTMClient.BuildFileInfo(rtmMessage, errorRecorder);
}
else
{
MessageInfo messageInfo = BuildMessageInfo(quest);
if (messageInfo.isBinary)
{
rtmMessage.binaryMessage = messageInfo.binaryData;
}
else
rtmMessage.stringMessage = messageInfo.message;
}
return rtmMessage;
}
//----------------------[ RTM Messagess ]-------------------//
public Answer PushMessage(Int64 connectionId, string endpoint, Quest quest)
{
AdvanceAnswer.SendAnswer(new Answer(quest));
if (questProcessor == null)
return null;
long from = quest.Want<long>("from");
long to = quest.Want<long>("to");
long mid = quest.Want<long>("mid");
if (duplicatedFilter.CheckP2PMessage(from, mid, to) == false)
return null;
RTMMessage rtmMessage = BuildRTMMessage(quest, from, to, mid);
if (rtmMessage.messageType == (byte)MessageType.Chat)
{
if (rtmMessage.translatedInfo != null)
{
questProcessor.PushChat(rtmMessage);
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.PushChatCallback?.Invoke(rtmMessage);
});
}
}
else if (rtmMessage.messageType == (byte)MessageType.Cmd)
{
questProcessor.PushCmd(rtmMessage);
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.PushCmdCallback?.Invoke(rtmMessage);
});
}
else if (rtmMessage.messageType >= 40 && rtmMessage.messageType <= 50)
{
questProcessor.PushFile(rtmMessage);
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.PushFileCallback?.Invoke(rtmMessage);
});
}
else
{
questProcessor.PushMessage(rtmMessage);
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.PushMessageCallback?.Invoke(rtmMessage);
});
}
return null;
}
public Answer PushGroupMessage(Int64 connectionId, string endpoint, Quest quest)
{
AdvanceAnswer.SendAnswer(new Answer(quest));
if (questProcessor == null)
return null;
long groupId = quest.Want<long>("gid");
long from = quest.Want<long>("from");
long mid = quest.Want<long>("mid");
if (duplicatedFilter.CheckGroupMessage(groupId, from, mid) == false)
return null;
RTMMessage rtmMessage = BuildRTMMessage(quest, from, groupId, mid);
if (rtmMessage.messageType == (byte)MessageType.Chat)
{
if (rtmMessage.translatedInfo != null)
{
questProcessor.PushGroupChat(rtmMessage);
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.PushGroupChatCallback?.Invoke(rtmMessage);
});
}
}
else if (rtmMessage.messageType == (byte)MessageType.Cmd)
{
questProcessor.PushGroupCmd(rtmMessage);
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.PushGroupCmdCallback?.Invoke(rtmMessage);
});
}
else if (rtmMessage.messageType >= 40 && rtmMessage.messageType <= 50)
{
questProcessor.PushGroupFile(rtmMessage);
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.PushGroupFileCallback?.Invoke(rtmMessage);
});
}
else
{
questProcessor.PushGroupMessage(rtmMessage);
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.PushGroupMessageCallback?.Invoke(rtmMessage);
});
}
return null;
}
public Answer PushRoomMessage(Int64 connectionId, string endpoint, Quest quest)
{
AdvanceAnswer.SendAnswer(new Answer(quest));
if (questProcessor == null)
return null;
long from = quest.Want<long>("from");
long roomId = quest.Want<long>("rid");
long mid = quest.Want<long>("mid");
if (duplicatedFilter.CheckRoomMessage(roomId, from, mid) == false)
return null;
RTMMessage rtmMessage = BuildRTMMessage(quest, from, roomId, mid);
if (rtmMessage.messageType == (byte)MessageType.Chat)
{
if (rtmMessage.translatedInfo != null)
{
questProcessor.PushRoomChat(rtmMessage);
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.PushRoomChatCallback?.Invoke(rtmMessage);
});
}
}
else if (rtmMessage.messageType == (byte)MessageType.Cmd)
{
questProcessor.PushRoomCmd(rtmMessage);
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.PushRoomCmdCallback?.Invoke(rtmMessage);
});
}
else if (rtmMessage.messageType >= 40 && rtmMessage.messageType <= 50)
{
questProcessor.PushRoomFile(rtmMessage);
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.PushRoomFileCallback?.Invoke(rtmMessage);
});
}
else
{
questProcessor.PushRoomMessage(rtmMessage);
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.PushRoomMessageCallback?.Invoke(rtmMessage);
});
}
return null;
}
public Answer PushBroadcastMessage(Int64 connectionId, string endpoint, Quest quest)
{
AdvanceAnswer.SendAnswer(new Answer(quest));
if (questProcessor == null)
return null;
long from = quest.Want<long>("from");
long mid = quest.Want<long>("mid");
if (duplicatedFilter.CheckBroadcastMessage(from, mid) == false)
return null;
RTMMessage rtmMessage = BuildRTMMessage(quest, from, 0, mid);
if (rtmMessage.messageType == (byte)MessageType.Chat)
{
if (rtmMessage.translatedInfo != null)
{
questProcessor.PushBroadcastChat(rtmMessage);
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.PushBroadcastChatCallback?.Invoke(rtmMessage);
});
}
}
else if (rtmMessage.messageType == (byte)MessageType.Cmd)
{
questProcessor.PushBroadcastCmd(rtmMessage);
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.PushBroadcastCmdCallback?.Invoke(rtmMessage);
});
}
else if (rtmMessage.messageType >= 40 && rtmMessage.messageType <= 50)
{
questProcessor.PushBroadcastFile(rtmMessage);
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.PushBroadcastFileCallback?.Invoke(rtmMessage);
});
}
else
{
questProcessor.PushBroadcastMessage(rtmMessage);
RTMControlCenter.callbackQueue.PostAction(() =>
{
questProcessor.PushBroadcastMessageCallback?.Invoke(rtmMessage);
});
}
return null;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3baaa308ec0214907890eaae1e90cbc5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 47ff5e9cc3e4d47faa5766841754abc2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,86 @@
#if UNITY_2017_1_OR_NEWER
using System;
using System.Runtime.InteropServices;
namespace com.fpnn.rtm
{
internal static class AudioConvert
{
#if (UNITY_ANDROID || UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN || UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
[DllImport("audio-convert")]
public static extern IntPtr convert_wav_to_amrwb(IntPtr wavSrc, int wavSrcSize, ref int status, ref int amrSize);
[DllImport("audio-convert")]
public static extern IntPtr convert_amrwb_to_wav(IntPtr amrSrc, int amrSrcSize, ref int status, ref int wavSize);
[DllImport("audio-convert")]
public static extern void free_memory(IntPtr ptr);
#elif UNITY_IOS
[DllImport("__Internal")]
public static extern IntPtr convert_wav_to_amrwb(IntPtr wavSrc, int wavSrcSize, ref int status, ref int amrSize);
[DllImport("__Internal")]
public static extern IntPtr convert_amrwb_to_wav(IntPtr amrSrc, int amrSrcSize, ref int status, ref int wavSize);
[DllImport("__Internal")]
public static extern void free_memory(IntPtr ptr);
#endif
public static byte[] ConvertToAmrwb(byte[] wavBuffer)
{
int status = 0;
int amrSize = 0;
IntPtr wavSrcPtr = Marshal.AllocHGlobal(wavBuffer.Length);
Marshal.Copy(wavBuffer, 0, wavSrcPtr, wavBuffer.Length);
IntPtr amrPtr = AudioConvert.convert_wav_to_amrwb(wavSrcPtr, wavBuffer.Length, ref status, ref amrSize);
Marshal.FreeHGlobal(wavSrcPtr);
if (amrPtr != null && status == 0) {
byte[] amrBuffer = new byte[amrSize];
Marshal.Copy(amrPtr, amrBuffer, 0, amrSize);
AudioConvert.free_memory(amrPtr);
return amrBuffer;
}
if (amrPtr != null)
AudioConvert.free_memory(amrPtr);
return null;
}
public static byte[] ConvertToWav(byte[] amrBuffer)
{
int status = 0;
int wavSize = 0;
IntPtr amrSrcPtr = Marshal.AllocHGlobal(amrBuffer.Length);
Marshal.Copy(amrBuffer, 0, amrSrcPtr, amrBuffer.Length);
IntPtr wavPtr = AudioConvert.convert_amrwb_to_wav(amrSrcPtr, amrBuffer.Length, ref status, ref wavSize);
Marshal.FreeHGlobal(amrSrcPtr);
if (wavPtr != null && status == 0) {
byte[] wavBuffer = new byte[wavSize];
Marshal.Copy(wavPtr, wavBuffer, 0, wavSize);
AudioConvert.free_memory(wavPtr);
return wavBuffer;
}
if (wavPtr != null)
AudioConvert.free_memory(wavPtr);
return null;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bfaf510d97fd04302bf3d50f2486b91d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,324 @@
using System.Collections;
using System;
using System.IO;
using System.Runtime.InteropServices;
using UnityEngine;
using AOT;
namespace com.fpnn.rtm
{
static public class AudioRecorderNative
{
public enum AudioDeviceType
{
Microphone = 0,
Speaker = 1,
}
public interface IAudioRecorderListener
{
void RecordStart(bool success);
void RecordEnd();
void OnRecord(RTMAudioData audioData);
void OnVolumn(double db);
void PlayStart(bool success);
void PlayEnd();
}
static internal IAudioRecorderListener audioRecorderListener;
static internal string language;
static volatile bool cancelRecord = false;
static volatile bool recording = false;
delegate void VolumnCallbackDelegate(float volumn);
[MonoPInvokeCallback(typeof(VolumnCallbackDelegate))]
private static void VolumnCallback(float volumn)
{
if (audioRecorderListener != null)
{
float minValue = -60;
float range = 60;
float outRange = 100;
if (volumn < minValue)
volumn = minValue;
volumn = (volumn + range) / range * outRange;
audioRecorderListener.OnVolumn(volumn);
}
}
delegate void StartRecordCallbackDelegate(bool success);
[MonoPInvokeCallback(typeof(StartRecordCallbackDelegate))]
private static void StartRecordCallback(bool success)
{
if (success == false)
recording = false;
if (audioRecorderListener != null)
audioRecorderListener.RecordStart(success);
}
delegate void StopRecordCallbackDelegate(IntPtr data, int length, long time);
[MonoPInvokeCallback(typeof(StopRecordCallbackDelegate))]
private static void StopRecordCallback(IntPtr data, int length, long time)
{
recording = false;
if (audioRecorderListener != null)
{
audioRecorderListener.RecordEnd();
if (cancelRecord)
{
cancelRecord = false;
return;
}
if (data == IntPtr.Zero)
return;
byte[] payload = new byte[length];
Marshal.Copy(data, payload, 0, length);
#if (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN)
RTMAudioData audioData = new RTMAudioData(AudioConvert.ConvertToAmrwb(payload), language, time);
#else
RTMAudioData audioData = new RTMAudioData(payload, language, time);
#endif
audioRecorderListener.OnRecord(audioData);
}
}
delegate void PlayFinishCallbackDelegate();
[MonoPInvokeCallback(typeof(PlayFinishCallbackDelegate))]
private static void PlayFinishCallback()
{
if (audioRecorderListener != null)
audioRecorderListener.PlayEnd();
}
delegate void PlayStartCallbackDelegate(bool success);
[MonoPInvokeCallback(typeof(PlayStartCallbackDelegate))]
private static void PlayStartCallback(bool success)
{
audioRecorderListener?.PlayStart(success);
}
#if (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN)
delegate void AudioDeviceChangedDelegate(int type);
static bool microphoneChanged = false;
static bool speakerChanged = false;
[MonoPInvokeCallback(typeof(AudioDeviceChangedDelegate))]
private static void AudioDeviceChangedCallback(int type)
{
AudioDeviceType deviceType = (AudioDeviceType)type;
if (deviceType == AudioDeviceType.Microphone)
microphoneChanged = true;
if (deviceType == AudioDeviceType.Speaker)
speakerChanged = true;
}
[DllImport("RTMNative")]
private static extern void initAudioDeviceChecker(AudioDeviceChangedDelegate callback);
[DllImport("RTMNative")]
private static extern void startRecord(VolumnCallbackDelegate callback, StartRecordCallbackDelegate startCallback, bool update);
[DllImport("RTMNative")]
private static extern void stopRecord(StopRecordCallbackDelegate callback);
[DllImport("RTMNative")]
private static extern void startPlay(byte[] data, int length, PlayFinishCallbackDelegate callback, PlayStartCallbackDelegate playStartCallback, bool update);
[DllImport("RTMNative")]
private static extern void stopPlay();
[DllImport("RTMNative")]
private static extern void playWithPath(byte[] data, int length, PlayFinishCallbackDelegate callback);
#elif (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
[DllImport("RTMNative")]
private static extern void startRecord(VolumnCallbackDelegate callback, StartRecordCallbackDelegate startCallback);
[DllImport("RTMNative")]
private static extern void stopRecord(StopRecordCallbackDelegate callback);
[DllImport("RTMNative")]
private static extern void startPlay(byte[] data, int length, PlayFinishCallbackDelegate callback, PlayStartCallbackDelegate playStartCallback);
[DllImport("RTMNative")]
private static extern void stopPlay();
[DllImport("RTMNative")]
private static extern void playWithPath(byte[] data, int length, PlayFinishCallbackDelegate callback);
#elif UNITY_IOS
[DllImport("__Internal")]
private static extern void startRecord(VolumnCallbackDelegate callback, StartRecordCallbackDelegate startCallback);
[DllImport("__Internal")]
private static extern void stopRecord(StopRecordCallbackDelegate callback);
[DllImport("__Internal")]
private static extern void startPlay(byte[] data, int length, PlayFinishCallbackDelegate callback, PlayStartCallbackDelegate playStartCallback);
[DllImport("__Internal")]
private static extern void stopPlay();
#elif UNITY_ANDROID
class AudioRecordAndroidProxy : AndroidJavaProxy
{
public AudioRecordAndroidProxy() : base("com.NetForUnity.IAudioAction")
{
}
public void startRecord(bool success, string errorMsg)
{
if (success == false)
recording = false;
if (AudioRecorderNative.audioRecorderListener != null)
AudioRecorderNative.audioRecorderListener.RecordStart(success);
}
public void stopRecord()
{
recording = false;
if (AudioRecorderNative.audioRecorderListener != null)
AudioRecorderNative.audioRecorderListener.RecordEnd();
}
public void startBroad(bool success)
{
if (AudioRecorderNative.audioRecorderListener != null)
AudioRecorderNative.audioRecorderListener.PlayStart(success);
}
public void broadFinish()
{
if (AudioRecorderNative.audioRecorderListener != null)
AudioRecorderNative.audioRecorderListener.PlayEnd();
}
public void listenVolume(double db)
{
if (AudioRecorderNative.audioRecorderListener != null)
{
float minValue = -60;
float range = 60;
float outRange = 100;
if (db < minValue)
db = minValue;
db = (db + range) / range * outRange;
AudioRecorderNative.audioRecorderListener.OnVolumn(db);
}
}
}
static AndroidJavaObject AudioRecord = null;
#endif
#if (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN)
[DllImport("RTMNative")]
internal static extern void destroy();
#endif
static public void Init(string language, IAudioRecorderListener listener)
{
AudioRecorderNative.language = language;
audioRecorderListener = listener;
#if (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN)
initAudioDeviceChecker(AudioDeviceChangedCallback);
#elif (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
#elif UNITY_ANDROID
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject appconatext = jc.GetStatic<AndroidJavaObject>("currentActivity");
if (AudioRecord == null)
{
AndroidJavaClass playerClass = new AndroidJavaClass("com.NetForUnity.RTMAudio");
AudioRecord = playerClass.CallStatic<AndroidJavaObject>("getInstance");
}
AudioRecord.Call("init", appconatext, language, new AudioRecordAndroidProxy());
#else
#endif
}
static public bool IsRecording()
{
return recording;
}
static public void StartRecord()
{
recording = true;
#if (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN)
startRecord(VolumnCallback, StartRecordCallback, microphoneChanged);
microphoneChanged = false;
#elif (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
startRecord(VolumnCallback, StartRecordCallback);
#elif UNITY_ANDROID
if (AudioRecord != null)
AudioRecord.Call("startRecord");
#else
startRecord(VolumnCallback, StartRecordCallback);
#endif
}
static public void StopRecord()
{
#if (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN || UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
stopRecord(StopRecordCallback);
#elif UNITY_ANDROID
AndroidJavaObject audio = AudioRecord.Call<AndroidJavaObject>("stopRecord");
if (audio == null)
{
if (audioRecorderListener != null)
audioRecorderListener.OnRecord(null);
return;
}
int duration = audio.Get<int>("duration");
byte[] audioData = audio.Get<byte[]>("audioData");
//byte[] audioData = (byte[])(Array)audio.Get<sbyte[]>("audioData");
if (cancelRecord)
{
cancelRecord = false;
return;
}
if (audioRecorderListener != null)
{
RTMAudioData data = new RTMAudioData(audioData, language, duration);
audioRecorderListener.OnRecord(data);
}
#else
stopRecord(StopRecordCallback);
#endif
}
static public void CancelRecord()
{
cancelRecord = true;
StopRecord();
}
static public void Play(RTMAudioData data)
{
#if (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN)
byte[] wavBuffer = AudioConvert.ConvertToWav(data.Audio);
startPlay(wavBuffer, wavBuffer.Length, PlayFinishCallback, PlayStartCallback, speakerChanged);
speakerChanged = false;
#elif (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
startPlay(data.Audio, data.Audio.Length, PlayFinishCallback, PlayStartCallback);
#elif UNITY_ANDROID
if (AudioRecord != null)
AudioRecord.Call("broadAudio", AudioConvert.ConvertToWav(data.Audio));
#else
startPlay(data.Audio, data.Audio.Length, PlayFinishCallback, PlayStartCallback);
#endif
}
static public void StopPlay()
{
#if (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN || UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
stopPlay();
#elif UNITY_ANDROID
if (AudioRecord != null)
AudioRecord.Call("stopAudio");
#else
stopPlay();
#endif
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 297ecbe86374440b18db4b398678923e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,337 @@
#if UNITY_2017_1_OR_NEWER
using System.Collections;
using System;
using System.IO;
using System.Runtime.InteropServices;
using UnityEngine;
namespace com.fpnn.rtm
{
public class AudioRecorder : Singleton<AudioRecorder>
{
public interface IMicrophone {
void Start();
void End();
void OnRecord(RTMAudioData audioData);
}
public static int RECORD_SAMPLE_RATE = 16000;
private int LOUDNESS_SAMPLE_WINDOW = 128;
private int UPDATE_LOUDNESS_MS = 50;
private int maxRecordSeconds = 60;
private bool isPause;
private bool isFocus;
private string lang;
private string device;
private bool isRecording;
private float loudness;
private long lastUpdateLoudnessTime = 0;
private int position;
private AudioClip clipRecord;
private IMicrophone micPhone;
private object selfLocker = new object();
void OnEnable() {
this.isPause = false;
this.isFocus = false;
}
void OnDisable() {
StopAllCoroutines();
CancelInput();
}
void OnApplicationPause() {
if (!this.isPause) {
CancelInput();
} else {
this.isFocus = true;
}
this.isPause = true;
}
void OnApplicationFocus() {
if (isFocus) {
isPause = false;
isFocus = false;
}
if (isPause) {
isFocus = true;
}
}
void Update() {
lock (selfLocker) {
if (!isRecording)
return;
long now = ClientEngine.GetCurrentMilliseconds();
if (now - lastUpdateLoudnessTime > UPDATE_LOUDNESS_MS) {
lastUpdateLoudnessTime = now;
UpdateLoudness();
}
}
}
void UpdateLoudness() {
#if RTM_BUILD_NO_AUDIO
throw new Exception("Audio is disabled, please remove the RTM_BUILD_NO_AUDIO define in \"Scripting Define Symbols\"");
#else
if (micPhone == null) {
return;
}
float levelMax = 0;
float[] data = new float[LOUDNESS_SAMPLE_WINDOW];
int pos = Microphone.GetPosition(device) - (LOUDNESS_SAMPLE_WINDOW + 1);
if (pos < 0) {
return;
}
clipRecord.GetData(data, pos);
for (int i = 0; i < LOUDNESS_SAMPLE_WINDOW; i++) {
float wavePeak = data[i] * data[i];
if (levelMax < wavePeak) {
levelMax = wavePeak;
}
}
loudness = levelMax;
#endif
}
private IEnumerator TimeDown() {
int time = 0;
while (++time <= this.maxRecordSeconds) {
lock (selfLocker) {
if (!isRecording) {
yield return 0;
}
}
yield return new WaitForSeconds(1);
}
FinishInput();
}
public void Init(string lang, string device, IMicrophone micPhone) {
position = 0;
isRecording = false;
this.lang = lang;
#if RTM_BUILD_NO_AUDIO
throw new Exception("Audio is disabled, please remove the RTM_BUILD_NO_AUDIO define in \"Scripting Define Symbols\"");
#else
if (micPhone != null) {
this.micPhone = micPhone;
}
lock (selfLocker) {
this.device = device;
}
#endif
}
public void SetLanguage(string lang) {
this.lang = lang;
}
public int GetRelativeLoudness(float maxLoudness) {
float loudnessNormalized = loudness;
if (loudnessNormalized > maxLoudness)
loudnessNormalized = maxLoudness;
return (int)(loudnessNormalized / maxLoudness * 100);
}
public float GetAbsoluteLoudness() {
return loudness;
}
public void StartInput(int maxRecordSeconds = 60) {
#if RTM_BUILD_NO_AUDIO
throw new Exception("Audio is disabled, please remove the RTM_BUILD_NO_AUDIO define in \"Scripting Define Symbols\"");
#else
if (micPhone == null) {
return;
}
if (Microphone.devices.Length == 0) {
return;
}
lock (selfLocker) {
if (device == null) {
device = Microphone.devices[0];
}
if (isRecording) {
return;
}
this.maxRecordSeconds = maxRecordSeconds;
isRecording = true;
clipRecord = Microphone.Start(device, false, this.maxRecordSeconds, RECORD_SAMPLE_RATE);
micPhone.Start();
}
StartCoroutine("TimeDown");
#endif
}
public void FinishInput() {
#if RTM_BUILD_NO_AUDIO
throw new Exception("Audio is disabled, please remove the RTM_BUILD_NO_AUDIO define in \"Scripting Define Symbols\"");
#else
if (micPhone == null) {
return;
}
bool timeDown = false;
lock (selfLocker) {
if (isRecording) {
timeDown = true;
isRecording = false;
position = Microphone.GetPosition(device);
Microphone.End(device);
micPhone.End();
}
}
if (timeDown) {
StopCoroutine("TimeDown");
if (micPhone != null && clipRecord != null) {
GetAudioData(clipRecord);
}
}
#endif
loudness = 0;
}
public void CancelInput() {
#if RTM_BUILD_NO_AUDIO
throw new Exception("Audio is disabled, please remove the RTM_BUILD_NO_AUDIO define in \"Scripting Define Symbols\"");
#else
if (micPhone == null) {
return;
}
bool timeDown = false;
lock (selfLocker) {
if (isRecording) {
timeDown = true;
isRecording = false;
Microphone.End(device);
micPhone.End();
}
}
if (timeDown) {
StopCoroutine("TimeDown");
}
#endif
loudness = 0;
}
private void GetAudioData(AudioClip clip) {
var soundData = new float[clip.samples * clip.channels];
clip.GetData(soundData, 0);
var newData = new float[position * clip.channels];
for (int i = 0; i < newData.Length; i++) {
newData[i] = soundData[i];
}
var newClip = AudioClip.Create (clip.name,
position,
clip.channels,
clip.frequency,
false);
newClip.SetData(newData, 0);
long duration = (long)(newClip.length * 1000);
MemoryStream amrStream = new MemoryStream();
ConvertAndWriteWav(amrStream, newClip);
WriteWavHeader(amrStream, newClip);
int lengthSamples = newClip.samples;
ClientEngine.RunTask(() => {
micPhone.OnRecord(new RTMAudioData(AudioConvert.ConvertToAmrwb(amrStream.ToArray()), newData, RTMAudioData.DefaultCodec, lang, duration, lengthSamples, RECORD_SAMPLE_RATE));
});
}
private void ConvertAndWriteWav(MemoryStream stream, AudioClip clip) {
float[] samples = new float[clip.samples];
clip.GetData(samples, 0);
Int16[] intData = new Int16[samples.Length];
Byte[] bytesData = new Byte[samples.Length * 2];
int rescaleFactor = 32767;
for (int i = 0; i < samples.Length; i++)
{
intData[i] = (short)(samples[i] * rescaleFactor);
Byte[] byteArr = new Byte[2];
byteArr = BitConverter.GetBytes(intData[i]);
byteArr.CopyTo(bytesData, i * 2);
}
stream.Write(bytesData, 0, bytesData.Length);
}
public static void WriteWavHeader(MemoryStream stream, AudioClip clip)
{
int hz = clip.frequency;
int channels = clip.channels;
int samples = clip.samples;
stream.Seek(0, SeekOrigin.Begin);
Byte[] riff = System.Text.Encoding.UTF8.GetBytes("RIFF");
stream.Write(riff, 0, 4);
Byte[] chunkSize = BitConverter.GetBytes(stream.Length - 8);
stream.Write(chunkSize, 0, 4);
Byte[] wave = System.Text.Encoding.UTF8.GetBytes("WAVE");
stream.Write(wave, 0, 4);
Byte[] fmt = System.Text.Encoding.UTF8.GetBytes("fmt ");
stream.Write(fmt, 0, 4);
Byte[] subChunk1 = BitConverter.GetBytes(16);
stream.Write(subChunk1, 0, 4);
UInt16 one = 1;
Byte[] audioFormat = BitConverter.GetBytes(one);
stream.Write(audioFormat, 0, 2);
Byte[] numChannels = BitConverter.GetBytes(channels);
stream.Write(numChannels, 0, 2);
Byte[] sampleRate = BitConverter.GetBytes(hz);
stream.Write(sampleRate, 0, 4);
Byte[] byteRate = BitConverter.GetBytes(hz * channels * 2);
stream.Write(byteRate, 0, 4);
UInt16 blockAlign = (ushort)(channels * 2);
stream.Write(BitConverter.GetBytes(blockAlign), 0, 2);
UInt16 bps = 16;
Byte[] bitsPerSample = BitConverter.GetBytes(bps);
stream.Write(bitsPerSample, 0, 2);
Byte[] datastring = System.Text.Encoding.UTF8.GetBytes("data");
stream.Write(datastring, 0, 4);
Byte[] subChunk2 = BitConverter.GetBytes(samples * channels * 2);
stream.Write(subChunk2, 0, 4);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f568454c4f1fc45d4acea6416df9086e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,182 @@
#if UNITY_2017_1_OR_NEWER
using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.Threading;
using AOT;
using UnityEngine;
namespace com.fpnn.rtm
{
public enum NetworkType
{
NetworkType_Uninited = -2,
NetworkType_Unknown = -1,
NetworkType_Unreachable = 0,
NetworkType_4G = 1,
NetworkType_Wifi = 2,
}
public class StatusMonitor : Singleton<StatusMonitor>
{
#if (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN)
[DllImport("RTMNative")]
private static extern void initNetworkStatusChecker(NetworkStatusDelegate callback);
[DllImport("RTMNative")]
private static extern void closeNetworkStatusChecker();
#elif (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
[DllImport("RTMNative")]
private static extern void initNetworkStatusChecker(NetworkStatusDelegate callback);
#elif UNITY_IOS
[DllImport("__Internal")]
private static extern void initNetworkStatusChecker(NetworkStatusDelegate callback);
#elif UNITY_ANDROID
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void HeadsetStatusDelegate(int networkStatus);
[MonoPInvokeCallback(typeof(HeadsetStatusDelegate))]
public static void HeadsetStatusCallback(int headsetType)
{
}
static AndroidJavaObject AndroidNativeManager= null;
class NetChangeListener : AndroidJavaProxy
{
Action<int> msgCallback;
public NetChangeListener(Action<int> callback) : base("com.NetForUnity.INetChange") { msgCallback = callback; }
public void netChangeNotify(int type)
{
msgCallback(type);
}
}
class HeadsetListener: AndroidJavaProxy
{
Action<int> headsetCallback;
public HeadsetListener(Action<int> callback) : base("com.NetForUnity.IHeadsetChange") { headsetCallback = callback; }
public void headsetChange(int type) // //0-无网 1-移动网络 2-wifi
{
headsetCallback(type);
}
}
private static void initNetworkStatusChecker(Action<int> netChangeCallback, Action<int> headersetCallback)
{
if (AndroidNativeManager == null)
{
AndroidJavaClass playerClass = new AndroidJavaClass("com.NetForUnity.ListenUnity");
AndroidNativeManager = playerClass.CallStatic<AndroidJavaObject>("getInstance");
}
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
var context = jc.GetStatic<AndroidJavaObject>("currentActivity");
AndroidNativeManager.Call("registerNetChange", context, new NetChangeListener(netChangeCallback));
AndroidNativeManager.Call("registerHeadsetChange", context, new HeadsetListener(headersetCallback));
}
#else
#endif
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void NetworkStatusDelegate(int networkStatus);
[MonoPInvokeCallback(typeof(NetworkStatusDelegate))]
static void NetworkStatusCallback(int networkStatus)
{
RTMControlCenter.NetworkChanged((NetworkType)networkStatus);
}
static private bool _isPause;
static private bool _isFocus;
static private bool _isBackground;
internal static bool IsBackground() { return _isBackground; }
void OnEnable()
{
_isPause = false;
_isFocus = true;
_isBackground = false;
}
public void Init()
{
#if (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN)
initNetworkStatusChecker(NetworkStatusCallback);
#elif (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
initNetworkStatusChecker(NetworkStatusCallback);
#elif UNITY_IOS
initNetworkStatusChecker(NetworkStatusCallback);
#elif UNITY_ANDROID
initNetworkStatusChecker(NetworkStatusCallback, HeadsetStatusCallback);
#endif
}
public void Close()
{
#if (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN)
closeNetworkStatusChecker();
#endif
}
//#if (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN)
// public void Start()
// {
// StartCoroutine(PerSecondCoroutine());
// }
//
// public void OnDestroy()
// {
// StopAllCoroutines();
// }
//
// private IEnumerator PerSecondCoroutine()
// {
// yield return new WaitForSeconds(1.0f);
//
// while (true)
// {
// CheckNetworkChange();
//
// yield return new WaitForSeconds(1.0f);
// }
// }
//
// private void CheckNetworkChange()
// {
// int networkStatus = (int)Application.internetReachability;
// RTMControlCenter.NetworkChanged((NetworkType)networkStatus);
// }
//#endif
private void CheckInBackground()
{
if (_isPause && !_isFocus)
{
if (_isBackground == false)
{
_isBackground = true;
}
}
else
{
if (_isBackground)
{
_isBackground = false;
}
}
}
void OnApplicationPause(bool pauseStatus)
{
_isPause = pauseStatus;
CheckInBackground();
}
void OnApplicationFocus(bool hasFocus)
{
_isFocus = hasFocus;
CheckInBackground();
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d55621c6e649e4542952aed2bc0f5cf4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: