-
Notifications
You must be signed in to change notification settings - Fork 0
/
RPC.cs
156 lines (133 loc) · 4.72 KB
/
RPC.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Text;
using Newtonsoft.Json;
public class RPC
{
private static RPC instance = null;
public static RPC Instance
{
get
{
if(instance == null)
{
instance = new RPC();
}
return instance;
}
}
private TcpClient client;
private StreamReader stream;
private long id = 0;
public RPC()
{
Debug.Log("Connecting...");
client = new TcpClient("localhost", 4444);
Debug.Log("Connected!");
stream = new StreamReader(client.GetStream(), Encoding.UTF8);
}
public void Close()
{
stream.Close();
client.Close();
}
public T ExecuteMethodOnStaticObject<T>(string className, string objectName, string methodName)
{
return ExecuteMethodOnStaticObject<T>(className, objectName, methodName, new string[] { }, new object[] { });
}
public T ExecuteMethodOnStaticObject<T>(string className, string objectName, string methodName, string[] argClassNames, object[] args)
{
return SendRPCRequest<T>(false, className, objectName, methodName, argClassNames, args);
}
public T ExecuteStaticMethod<T>(string className, string methodName)
{
return ExecuteStaticMethod<T>(className, methodName, new string[] { }, new object[] { });
}
public T ExecuteStaticMethod<T>(string className, string methodName, string[] argClassNames, object[] args)
{
return SendRPCRequest<T>(false, className, "", methodName, argClassNames, args);
}
public T ExecuteMethod<T>(string objectName, string methodName)
{
return ExecuteMethod<T>(objectName, methodName, new string[] { }, new object[] { });
}
public T ExecuteMethod<T>(string objectName, string methodName, string[] argClassNames, object[] args)
{
return SendRPCRequest<T>(false, "", objectName, methodName, argClassNames, args);
}
public T InstantiateObject<T>(string className, string objectName)
{
return InstantiateObject<T>(className, objectName, new string[] { }, new object[] { });
}
public T InstantiateObject<T>(string className, string objectName, string[] argClassNames, object[] args)
{
return SendRPCRequest<T>(true, className, objectName, "", argClassNames, args);
}
private T SendRPCRequest<T>(bool instantiate, string className, string objectName, string methodName, string[] argClassNames, object[] args)
{
if (argClassNames.Length != args.Length)
{
throw new Exception("argClassNames and args must have same length!");
}
RPCRequest request = new RPCRequest
{
id = id++,
instantiate = instantiate,
className = className,
objectName = objectName,
methodName = methodName,
argClassNames = new List<string>(argClassNames),
args = new List<object>(args)
};
string jsonRequest = JsonConvert.SerializeObject(request);
//Debug.Log("Sending request: " + jsonRequest);
WriteLine(jsonRequest);
string jsonResponse = stream.ReadLine();
//Debug.Log("Received response: " + jsonResponse);
RPCResponse<object> tempResponse = JsonConvert.DeserializeObject<RPCResponse<object>>(jsonResponse);
if(tempResponse.isException)
{
RPCResponse<string> exceptionResponse = JsonConvert.DeserializeObject<RPCResponse<string>>(jsonResponse);
throw new Exception(exceptionResponse.value);
}
RPCResponse<T> response = JsonConvert.DeserializeObject<RPCResponse<T>>(jsonResponse);
if (request.id == response.id)
{
return response.value;
}
throw new RPCException("Somehow the calls are out of sync! Are you using multithreading?");
}
private void WriteLine(string message)
{
byte[] msg = Encoding.UTF8.GetBytes(message + "\n");
stream.BaseStream.Write(msg, 0, msg.Length);
stream.BaseStream.Flush();
}
private class RPCException : Exception
{
public RPCException(string message) : base(message) {}
}
[Serializable]
private class RPCRequest
{
public long id;
public bool instantiate;
public string className;
public string objectName;
public string methodName;
public List<string> argClassNames;
public List<object> args;
}
[Serializable]
private class RPCResponse<T>
{
public long id;
public bool isException;
public T value;
}
}