cukunity 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitmodules +0 -0
- data/.rspec +1 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +60 -0
- data/LICENSE.txt +20 -0
- data/README.md +214 -0
- data/Rakefile +51 -0
- data/Unity/Assets/Demo/Art/Buttons/down.png +0 -0
- data/Unity/Assets/Demo/Art/Buttons/down.png.meta +28 -0
- data/Unity/Assets/Demo/Art/Buttons/left.png +0 -0
- data/Unity/Assets/Demo/Art/Buttons/left.png.meta +28 -0
- data/Unity/Assets/Demo/Art/Buttons/ok.png +0 -0
- data/Unity/Assets/Demo/Art/Buttons/ok.png.meta +28 -0
- data/Unity/Assets/Demo/Art/Buttons/options.png +0 -0
- data/Unity/Assets/Demo/Art/Buttons/options.png.meta +28 -0
- data/Unity/Assets/Demo/Art/Buttons/play.png +0 -0
- data/Unity/Assets/Demo/Art/Buttons/play.png.meta +28 -0
- data/Unity/Assets/Demo/Art/Buttons/quit.png +0 -0
- data/Unity/Assets/Demo/Art/Buttons/quit.png.meta +28 -0
- data/Unity/Assets/Demo/Art/Buttons/retry.png +0 -0
- data/Unity/Assets/Demo/Art/Buttons/retry.png.meta +28 -0
- data/Unity/Assets/Demo/Art/Buttons/right.png +0 -0
- data/Unity/Assets/Demo/Art/Buttons/right.png.meta +28 -0
- data/Unity/Assets/Demo/Art/Buttons/up.png +0 -0
- data/Unity/Assets/Demo/Art/Buttons/up.png.meta +28 -0
- data/Unity/Assets/Demo/Art/Buttons.meta +2 -0
- data/Unity/Assets/Demo/Art/clear.png +0 -0
- data/Unity/Assets/Demo/Art/clear.png.meta +28 -0
- data/Unity/Assets/Demo/Art/options.png +0 -0
- data/Unity/Assets/Demo/Art/options.png.meta +28 -0
- data/Unity/Assets/Demo/Art/sokoban.png +0 -0
- data/Unity/Assets/Demo/Art/sokoban.png.meta +28 -0
- data/Unity/Assets/Demo/Art.meta +2 -0
- data/Unity/Assets/Demo/Cubes/CrateCube.mat +0 -0
- data/Unity/Assets/Demo/Cubes/CrateCube.mat.meta +2 -0
- data/Unity/Assets/Demo/Cubes/CrateCube.prefab +0 -0
- data/Unity/Assets/Demo/Cubes/CrateCube.prefab.meta +2 -0
- data/Unity/Assets/Demo/Cubes/FloorCube.mat +0 -0
- data/Unity/Assets/Demo/Cubes/FloorCube.mat.meta +2 -0
- data/Unity/Assets/Demo/Cubes/FloorCube.prefab +0 -0
- data/Unity/Assets/Demo/Cubes/FloorCube.prefab.meta +2 -0
- data/Unity/Assets/Demo/Cubes/GoalCube.mat +0 -0
- data/Unity/Assets/Demo/Cubes/GoalCube.mat.meta +2 -0
- data/Unity/Assets/Demo/Cubes/GoalCube.prefab +0 -0
- data/Unity/Assets/Demo/Cubes/GoalCube.prefab.meta +2 -0
- data/Unity/Assets/Demo/Cubes/PlayerCube.mat +0 -0
- data/Unity/Assets/Demo/Cubes/PlayerCube.mat.meta +2 -0
- data/Unity/Assets/Demo/Cubes/PlayerCube.prefab +0 -0
- data/Unity/Assets/Demo/Cubes/PlayerCube.prefab.meta +2 -0
- data/Unity/Assets/Demo/Cubes/WallCube.mat +0 -0
- data/Unity/Assets/Demo/Cubes/WallCube.mat.meta +2 -0
- data/Unity/Assets/Demo/Cubes/WallCube.prefab +0 -0
- data/Unity/Assets/Demo/Cubes/WallCube.prefab.meta +2 -0
- data/Unity/Assets/Demo/Cubes.meta +2 -0
- data/Unity/Assets/Demo/Resources/MainMenu.prefab +0 -0
- data/Unity/Assets/Demo/Resources/MainMenu.prefab.meta +2 -0
- data/Unity/Assets/Demo/Resources/OptionsMenu.prefab +0 -0
- data/Unity/Assets/Demo/Resources/OptionsMenu.prefab.meta +2 -0
- data/Unity/Assets/Demo/Resources.meta +2 -0
- data/Unity/Assets/Demo/Scripts/CameraController.js +18 -0
- data/Unity/Assets/Demo/Scripts/CameraController.js.meta +2 -0
- data/Unity/Assets/Demo/Scripts/EnterPlayerName.js +21 -0
- data/Unity/Assets/Demo/Scripts/EnterPlayerName.js.meta +2 -0
- data/Unity/Assets/Demo/Scripts/GameLeftButton.js +18 -0
- data/Unity/Assets/Demo/Scripts/GameLeftButton.js.meta +2 -0
- data/Unity/Assets/Demo/Scripts/GameQuitButton.js +6 -0
- data/Unity/Assets/Demo/Scripts/GameQuitButton.js.meta +2 -0
- data/Unity/Assets/Demo/Scripts/GameRetryButton.js +7 -0
- data/Unity/Assets/Demo/Scripts/GameRetryButton.js.meta +2 -0
- data/Unity/Assets/Demo/Scripts/GameRightButton.js +18 -0
- data/Unity/Assets/Demo/Scripts/GameRightButton.js.meta +2 -0
- data/Unity/Assets/Demo/Scripts/GameUpButton.js +18 -0
- data/Unity/Assets/Demo/Scripts/GameUpButton.js.meta +2 -0
- data/Unity/Assets/Demo/Scripts/OnTouchGUIElementDown.js +34 -0
- data/Unity/Assets/Demo/Scripts/OnTouchGUIElementDown.js.meta +2 -0
- data/Unity/Assets/Demo/Scripts/PlayerData.js +3 -0
- data/Unity/Assets/Demo/Scripts/PlayerData.js.meta +2 -0
- data/Unity/Assets/Demo/Scripts/SokobanController.js +240 -0
- data/Unity/Assets/Demo/Scripts/SokobanController.js.meta +2 -0
- data/Unity/Assets/Demo/Scripts/TakeScreenShot.js +26 -0
- data/Unity/Assets/Demo/Scripts/TakeScreenShot.js.meta +2 -0
- data/Unity/Assets/Demo/Scripts/TitleOptionsButton.js +8 -0
- data/Unity/Assets/Demo/Scripts/TitleOptionsButton.js.meta +2 -0
- data/Unity/Assets/Demo/Scripts/TitleOptionsOkButton.js +8 -0
- data/Unity/Assets/Demo/Scripts/TitleOptionsOkButton.js.meta +2 -0
- data/Unity/Assets/Demo/Scripts/TitlePlayButton.js +6 -0
- data/Unity/Assets/Demo/Scripts/TitlePlayButton.js.meta +2 -0
- data/Unity/Assets/Demo/Scripts/TitleQuitButton.js +7 -0
- data/Unity/Assets/Demo/Scripts/TitleQuitButton.js.meta +2 -0
- data/Unity/Assets/Demo/Scripts/UpdateMovesLabel.js +26 -0
- data/Unity/Assets/Demo/Scripts/UpdateMovesLabel.js.meta +2 -0
- data/Unity/Assets/Demo/Scripts/UpdatePlayerName.js +14 -0
- data/Unity/Assets/Demo/Scripts/UpdatePlayerName.js.meta +2 -0
- data/Unity/Assets/Demo/Scripts.meta +2 -0
- data/Unity/Assets/Demo/demo_game.unity +0 -0
- data/Unity/Assets/Demo/demo_game.unity.meta +2 -0
- data/Unity/Assets/Demo/demo_title.unity +0 -0
- data/Unity/Assets/Demo/demo_title.unity.meta +2 -0
- data/Unity/Assets/Demo.meta +2 -0
- data/Unity/Assets/Plugins/CukunityInstance.prefab +0 -0
- data/Unity/Assets/Plugins/CukunityInstance.prefab.meta +2 -0
- data/Unity/Assets/Plugins/CukunityServer.cs +871 -0
- data/Unity/Assets/Plugins/CukunityServer.cs.meta +2 -0
- data/Unity/Assets/Plugins/JsonFx.Json.dll +0 -0
- data/Unity/Assets/Plugins/JsonFx.Json.dll.meta +2 -0
- data/Unity/Assets/Plugins/iOS/CukunityServer.mm +242 -0
- data/Unity/Assets/Plugins/iOS/CukunityServer.mm.meta +2 -0
- data/Unity/Assets/Plugins/iOS.meta +2 -0
- data/Unity/Assets/Plugins.meta +2 -0
- data/Unity/Library/AudioManager.asset +0 -0
- data/Unity/Library/BuildSettings.asset +0 -0
- data/Unity/Library/DynamicsManager.asset +0 -0
- data/Unity/Library/EditorBuildSettings.asset +0 -0
- data/Unity/Library/EditorSettings.asset +0 -0
- data/Unity/Library/EditorUserBuildSettings.asset +0 -0
- data/Unity/Library/EditorUserSettings.asset +0 -0
- data/Unity/Library/InputManager.asset +0 -0
- data/Unity/Library/InspectorExpandedItems.asset +0 -0
- data/Unity/Library/MonoManager.asset +0 -0
- data/Unity/Library/NetworkManager.asset +0 -0
- data/Unity/Library/ProjectSettings.asset +0 -0
- data/Unity/Library/QualitySettings.asset +0 -0
- data/Unity/Library/TagManager.asset +0 -0
- data/Unity/Library/TimeManager.asset +0 -0
- data/Unity/ProjectSettings/AudioManager.asset +0 -0
- data/Unity/ProjectSettings/DynamicsManager.asset +0 -0
- data/Unity/ProjectSettings/EditorBuildSettings.asset +0 -0
- data/Unity/ProjectSettings/EditorSettings.asset +0 -0
- data/Unity/ProjectSettings/InputManager.asset +0 -0
- data/Unity/ProjectSettings/NavMeshLayers.asset +0 -0
- data/Unity/ProjectSettings/NetworkManager.asset +0 -0
- data/Unity/ProjectSettings/ProjectSettings.asset +0 -0
- data/Unity/ProjectSettings/QualitySettings.asset +0 -0
- data/Unity/ProjectSettings/TagManager.asset +0 -0
- data/Unity/ProjectSettings/TimeManager.asset +0 -0
- data/VERSION +1 -0
- data/bin/cukunity +7 -0
- data/cukunity.gemspec +298 -0
- data/features/get_scene_command.feature +39 -0
- data/features/i18n/ja/sokoban_clear.feature +109 -0
- data/features/install.feature +23 -0
- data/features/keyboard_input.feature +26 -0
- data/features/load_level_command.feature +36 -0
- data/features/run.feature +33 -0
- data/features/select_visible.feature +29 -0
- data/features/support/env.rb +11 -0
- data/features/touch_input.feature +96 -0
- data/lib/cukunity/cli/argument_parser.rb +103 -0
- data/lib/cukunity/cli/bootstrap_command.rb +39 -0
- data/lib/cukunity/cli/doctor_command.rb +150 -0
- data/lib/cukunity/cli/features_command.rb +35 -0
- data/lib/cukunity/cli/main.rb +18 -0
- data/lib/cukunity/cli/options.rb +8 -0
- data/lib/cukunity/cli.rb +11 -0
- data/lib/cukunity/cucumber/step_definitions/get_scene_command_steps.rb +37 -0
- data/lib/cukunity/cucumber/step_definitions/i18n/ja/get_scene_command_steps.rb +37 -0
- data/lib/cukunity/cucumber/step_definitions/i18n/ja/install_steps.rb +25 -0
- data/lib/cukunity/cucumber/step_definitions/i18n/ja/keyboard_input_steps.rb +17 -0
- data/lib/cukunity/cucumber/step_definitions/i18n/ja/load_level_command_steps.rb +17 -0
- data/lib/cukunity/cucumber/step_definitions/i18n/ja/run_steps.rb +25 -0
- data/lib/cukunity/cucumber/step_definitions/i18n/ja/select_visible_steps.rb +9 -0
- data/lib/cukunity/cucumber/step_definitions/i18n/ja/touch_input_steps.rb +19 -0
- data/lib/cukunity/cucumber/step_definitions/i18n/ja.rb +9 -0
- data/lib/cukunity/cucumber/step_definitions/install_steps.rb +33 -0
- data/lib/cukunity/cucumber/step_definitions/keyboard_input_steps.rb +13 -0
- data/lib/cukunity/cucumber/step_definitions/load_level_command_steps.rb +17 -0
- data/lib/cukunity/cucumber/step_definitions/run_steps.rb +32 -0
- data/lib/cukunity/cucumber/step_definitions/select_visible_steps.rb +15 -0
- data/lib/cukunity/cucumber/step_definitions/touch_input_steps.rb +18 -0
- data/lib/cukunity/cucumber/support/platform_helpers.rb +105 -0
- data/lib/cukunity/cucumber/support/spec_helpers.rb +21 -0
- data/lib/cukunity/cucumber/support/transforms.rb +5 -0
- data/lib/cukunity/cucumber/support/unity_helpers.rb +35 -0
- data/lib/cukunity/cucumber.rb +28 -0
- data/lib/cukunity/drivers/android/app.rb +43 -0
- data/lib/cukunity/drivers/android/appkiller/.gitignore +9 -0
- data/lib/cukunity/drivers/android/appkiller/AndroidManifest.xml +17 -0
- data/lib/cukunity/drivers/android/appkiller/ant.properties +17 -0
- data/lib/cukunity/drivers/android/appkiller/build.xml +85 -0
- data/lib/cukunity/drivers/android/appkiller/proguard.cfg +40 -0
- data/lib/cukunity/drivers/android/appkiller/project.properties +11 -0
- data/lib/cukunity/drivers/android/appkiller/res/layout/main.xml +13 -0
- data/lib/cukunity/drivers/android/appkiller/res/values/strings.xml +4 -0
- data/lib/cukunity/drivers/android/appkiller/src/cukunity/appkiller/AppKiller.java +29 -0
- data/lib/cukunity/drivers/android/keyboard_input.rb +149 -0
- data/lib/cukunity/drivers/android/keycodes.rb +531 -0
- data/lib/cukunity/drivers/android/monkey_client.rb +65 -0
- data/lib/cukunity/drivers/android/process.rb +103 -0
- data/lib/cukunity/drivers/android/touch_input.rb +24 -0
- data/lib/cukunity/drivers/android/tunnel_client_methods.rb +22 -0
- data/lib/cukunity/drivers/android/unity_client.rb +27 -0
- data/lib/cukunity/drivers/android/utils.rb +50 -0
- data/lib/cukunity/drivers/android.rb +9 -0
- data/lib/cukunity/drivers/iOS/app.rb +32 -0
- data/lib/cukunity/drivers/iOS/keyboard_input.rb +104 -0
- data/lib/cukunity/drivers/iOS/process.rb +42 -0
- data/lib/cukunity/drivers/iOS/touch_input.rb +18 -0
- data/lib/cukunity/drivers/iOS/tunnel_client_methods.rb +27 -0
- data/lib/cukunity/drivers/iOS/uiautomation.rb +97 -0
- data/lib/cukunity/drivers/iOS/uiautomation_master.rb +152 -0
- data/lib/cukunity/drivers/iOS/uiautomation_slave.js +238 -0
- data/lib/cukunity/drivers/iOS/uiautomation_slave.rb +41 -0
- data/lib/cukunity/drivers/iOS/unity_client.rb +27 -0
- data/lib/cukunity/drivers/iOS/utils.rb +46 -0
- data/lib/cukunity/drivers/iOS.rb +9 -0
- data/lib/cukunity/exceptions.rb +24 -0
- data/lib/cukunity/keyboard_input_methods.rb +35 -0
- data/lib/cukunity/request_line_response_client_methods.rb +80 -0
- data/lib/cukunity/tasks/cucumber.rake +22 -0
- data/lib/cukunity/touch_input_methods.rb +19 -0
- data/lib/cukunity/unity/client_methods.rb +46 -0
- data/lib/cukunity/unity/command_facade.rb +67 -0
- data/lib/cukunity/unity/component.rb +39 -0
- data/lib/cukunity/unity/gameobject.rb +53 -0
- data/lib/cukunity/unity/hint.rb +27 -0
- data/lib/cukunity/unity/json_container.rb +48 -0
- data/lib/cukunity/unity/level.rb +6 -0
- data/lib/cukunity/unity/scene.rb +18 -0
- data/lib/cukunity/unity/screen.rb +45 -0
- data/lib/cukunity/unity/screen_hint_methods.rb +61 -0
- data/lib/cukunity/unity/text_hint_methods.rb +17 -0
- data/lib/cukunity/unity.rb +11 -0
- data/lib/cukunity/utils.rb +56 -0
- data/lib/cukunity.rb +19 -0
- metadata +411 -0
|
@@ -0,0 +1,871 @@
|
|
|
1
|
+
using UnityEngine;
|
|
2
|
+
using System.Collections;
|
|
3
|
+
|
|
4
|
+
using System;
|
|
5
|
+
using System.Net;
|
|
6
|
+
using System.Net.Sockets;
|
|
7
|
+
using System.Text;
|
|
8
|
+
using System.Threading;
|
|
9
|
+
using System.Collections.Generic;
|
|
10
|
+
|
|
11
|
+
using JsonFx.Json;
|
|
12
|
+
|
|
13
|
+
using System.Runtime.InteropServices;
|
|
14
|
+
|
|
15
|
+
public class CukunityServer : MonoBehaviour
|
|
16
|
+
{
|
|
17
|
+
public string ip = "127.0.0.1";
|
|
18
|
+
public int port = 9921;
|
|
19
|
+
public bool excludeSelfFromScene = true;
|
|
20
|
+
|
|
21
|
+
private TcpListener listener = null;
|
|
22
|
+
private List<CukunityRequest> requests;
|
|
23
|
+
|
|
24
|
+
public static CukunityServer instance = null;
|
|
25
|
+
|
|
26
|
+
void Awake()
|
|
27
|
+
{
|
|
28
|
+
if (instance != null)
|
|
29
|
+
{
|
|
30
|
+
Destroy(gameObject);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
instance = this;
|
|
34
|
+
// prevent ourselves being removed from the scene when loading new levels
|
|
35
|
+
DontDestroyOnLoad(gameObject);
|
|
36
|
+
// start server
|
|
37
|
+
requests = new List<CukunityRequest>();
|
|
38
|
+
StartCoroutine(Listen());
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private IEnumerator Listen()
|
|
42
|
+
{
|
|
43
|
+
yield return new WaitForEndOfFrame();
|
|
44
|
+
|
|
45
|
+
Debug.LogWarning("Cukunity: Listening on " + ip + ":" + port.ToString());
|
|
46
|
+
|
|
47
|
+
IPAddress localAddr = IPAddress.Parse(ip);
|
|
48
|
+
listener = new TcpListener(localAddr, port);
|
|
49
|
+
|
|
50
|
+
// start listening
|
|
51
|
+
listener.Start();
|
|
52
|
+
|
|
53
|
+
// wait for our first client
|
|
54
|
+
listener.BeginAcceptTcpClient(OnAcceptTcpClientComplete, this);
|
|
55
|
+
StartCoroutine(MainLoop());
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private IEnumerator MainLoop()
|
|
59
|
+
{
|
|
60
|
+
List<CukunityRequest> pendingRequests;
|
|
61
|
+
|
|
62
|
+
while (true)
|
|
63
|
+
{
|
|
64
|
+
pendingRequests = null;
|
|
65
|
+
lock(requests)
|
|
66
|
+
{
|
|
67
|
+
if (requests.Count > 0)
|
|
68
|
+
{
|
|
69
|
+
pendingRequests = new List<CukunityRequest>(requests);
|
|
70
|
+
requests.Clear();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (pendingRequests != null)
|
|
74
|
+
{
|
|
75
|
+
pendingRequests.ForEach(ProcessRequest);
|
|
76
|
+
yield return new WaitForEndOfFrame();
|
|
77
|
+
}
|
|
78
|
+
else
|
|
79
|
+
{
|
|
80
|
+
yield return new WaitForSeconds(0.1f);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private void ProcessRequest(CukunityRequest req)
|
|
86
|
+
{
|
|
87
|
+
Hashtable res = new Hashtable();
|
|
88
|
+
try
|
|
89
|
+
{
|
|
90
|
+
// read data from client as a JSON dictionary
|
|
91
|
+
Hashtable jsonReq = JsonReader.Deserialize<Hashtable>(req.Request);
|
|
92
|
+
|
|
93
|
+
string cmdName = GetJsonString(jsonReq, "command");
|
|
94
|
+
|
|
95
|
+
if ((cmdName == null) || (cmdName.Length == 0))
|
|
96
|
+
{
|
|
97
|
+
Debug.LogError("Cukunity: missing command in client's request (" + req.Request + ")");
|
|
98
|
+
res["error"] = "MissingCommandError";
|
|
99
|
+
req.OnProcessed(JsonWriter.Serialize(res));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
CukunityCommand cmd;
|
|
104
|
+
|
|
105
|
+
switch (cmdName)
|
|
106
|
+
{
|
|
107
|
+
case "get_screen":
|
|
108
|
+
cmd = new CukunityGetScreenCommand();
|
|
109
|
+
break;
|
|
110
|
+
|
|
111
|
+
case "get_scene":
|
|
112
|
+
cmd = new CukunityGetSceneCommand();
|
|
113
|
+
break;
|
|
114
|
+
|
|
115
|
+
case "get_level":
|
|
116
|
+
cmd = new CukunityGetLevelCommand();
|
|
117
|
+
break;
|
|
118
|
+
|
|
119
|
+
case "load_level":
|
|
120
|
+
cmd = new CukunityLoadLevelCommand();
|
|
121
|
+
break;
|
|
122
|
+
|
|
123
|
+
#if UNITY_IPHONE
|
|
124
|
+
case "touch_screen":
|
|
125
|
+
cmd = new CukunityTouchScreenCommand();
|
|
126
|
+
break;
|
|
127
|
+
#endif
|
|
128
|
+
|
|
129
|
+
default:
|
|
130
|
+
Debug.LogError("Cukunity: unknown command in client's request (" + req.Request + ")");
|
|
131
|
+
res["error"] = "UnknownCommandError";
|
|
132
|
+
req.OnProcessed(JsonWriter.Serialize(res));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
cmd.Process(jsonReq, res);
|
|
137
|
+
}
|
|
138
|
+
catch (Exception e)
|
|
139
|
+
{
|
|
140
|
+
Debug.LogError("Cukunity: exception while processing client's request (" + e + ")");
|
|
141
|
+
res["error"] = "ServerError";
|
|
142
|
+
}
|
|
143
|
+
// reply to client
|
|
144
|
+
req.OnProcessed(JsonWriter.Serialize(res));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
private static string GetJsonString(Hashtable data, string key)
|
|
148
|
+
{
|
|
149
|
+
if ((data == null) ||
|
|
150
|
+
(!data.Contains(key)) ||
|
|
151
|
+
(data[key].GetType() != typeof(string)))
|
|
152
|
+
{
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
return data[key] as string;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
private static bool GetJsonInt(Hashtable data, string key, ref int value)
|
|
159
|
+
{
|
|
160
|
+
if ((data == null) ||
|
|
161
|
+
(!data.Contains(key)) ||
|
|
162
|
+
(data[key].GetType() != typeof(int)))
|
|
163
|
+
{
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
value = (int)data[key];
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
void OnDestroy()
|
|
171
|
+
{
|
|
172
|
+
try
|
|
173
|
+
{
|
|
174
|
+
if (listener != null)
|
|
175
|
+
{
|
|
176
|
+
listener.Stop();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
catch (SocketException)
|
|
180
|
+
{
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
public void EnqueueRequest(CukunityRequest req)
|
|
185
|
+
{
|
|
186
|
+
lock(requests)
|
|
187
|
+
{
|
|
188
|
+
requests.Add(req);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
static private void OnAcceptTcpClientComplete(IAsyncResult result)
|
|
193
|
+
{
|
|
194
|
+
CukunityServer server = result.AsyncState as CukunityServer;
|
|
195
|
+
TcpClient client = server.listener.EndAcceptTcpClient(result);
|
|
196
|
+
|
|
197
|
+
Debug.LogWarning("Cukunity: client connected");
|
|
198
|
+
|
|
199
|
+
CukunityClient cukieClient = new CukunityClient(client, server);
|
|
200
|
+
|
|
201
|
+
// ready for a new client
|
|
202
|
+
server.listener.BeginAcceptTcpClient(OnAcceptTcpClientComplete, server);
|
|
203
|
+
|
|
204
|
+
// start client
|
|
205
|
+
cukieClient.SendAck();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
public class CukunityCommand
|
|
209
|
+
{
|
|
210
|
+
public delegate object GameObjectVisitor(GameObject obj, object context);
|
|
211
|
+
|
|
212
|
+
public virtual void Process(Hashtable req, Hashtable res)
|
|
213
|
+
{
|
|
214
|
+
throw new System.Exception("Not implemented");
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
protected void Traverse(GameObject obj, GameObjectVisitor visitor, object context)
|
|
218
|
+
{
|
|
219
|
+
context = visitor(obj, context);
|
|
220
|
+
foreach (Transform child in obj.transform)
|
|
221
|
+
{
|
|
222
|
+
Traverse(child.gameObject, visitor, context);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
public class CukunityGetSceneCommand : CukunityCommand
|
|
228
|
+
{
|
|
229
|
+
public delegate void SerializerMethod(Component c, Hashtable h);
|
|
230
|
+
|
|
231
|
+
public override void Process(Hashtable req, Hashtable res)
|
|
232
|
+
{
|
|
233
|
+
List<GameObject> objs = new List<GameObject>();
|
|
234
|
+
|
|
235
|
+
// get all objects on the root
|
|
236
|
+
foreach (GameObject obj in UnityEngine.Object.FindObjectsOfType(typeof(GameObject)))
|
|
237
|
+
{
|
|
238
|
+
if ((obj.transform.parent == null) &&
|
|
239
|
+
// exclude this game object?
|
|
240
|
+
((!CukunityServer.instance.excludeSelfFromScene) ||
|
|
241
|
+
((CukunityServer.instance.excludeSelfFromScene) &&
|
|
242
|
+
(obj != CukunityServer.instance.gameObject))))
|
|
243
|
+
{
|
|
244
|
+
objs.Add(obj);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// traverse all objects recursively
|
|
249
|
+
List<Hashtable> rootObjects = new List<Hashtable>();
|
|
250
|
+
res["gameObjects"] = rootObjects;
|
|
251
|
+
foreach (GameObject obj in objs)
|
|
252
|
+
{
|
|
253
|
+
Traverse(obj, SerializeGameObject, rootObjects);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
private object SerializeGameObject(GameObject obj, object context)
|
|
258
|
+
{
|
|
259
|
+
Hashtable objHash = new Hashtable();
|
|
260
|
+
objHash["instanceID"] = obj.GetInstanceID();
|
|
261
|
+
objHash["name"] = obj.name;
|
|
262
|
+
objHash["tag"] = obj.tag;
|
|
263
|
+
objHash["active"] = obj.active;
|
|
264
|
+
|
|
265
|
+
Hashtable layerHash = new Hashtable();
|
|
266
|
+
layerHash["name"] = LayerMask.LayerToName(obj.layer);
|
|
267
|
+
layerHash["value"] = obj.layer;
|
|
268
|
+
objHash["layer"] = layerHash;
|
|
269
|
+
|
|
270
|
+
objHash["children"] = new List<Hashtable>();
|
|
271
|
+
objHash["components"] = SerializeComponents(obj);
|
|
272
|
+
|
|
273
|
+
List<Hashtable> objs = context as List<Hashtable>;
|
|
274
|
+
if (objs != null)
|
|
275
|
+
{
|
|
276
|
+
objs.Add(objHash);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return objHash["children"];
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
private List<Hashtable> SerializeComponents(GameObject obj)
|
|
283
|
+
{
|
|
284
|
+
List<Hashtable> components = new List<Hashtable>();
|
|
285
|
+
Component[] comps = obj.GetComponents<Component>();
|
|
286
|
+
|
|
287
|
+
foreach (Component comp in comps)
|
|
288
|
+
{
|
|
289
|
+
Hashtable compHash = new Hashtable();
|
|
290
|
+
|
|
291
|
+
compHash["instanceID"] = comp.GetInstanceID();
|
|
292
|
+
compHash["type"] = GetComponentTypeString(comp);
|
|
293
|
+
|
|
294
|
+
Behaviour behaviour = null;
|
|
295
|
+
// is this Component a Behaviour?
|
|
296
|
+
if (typeof(Behaviour).IsAssignableFrom(comp.GetType()))
|
|
297
|
+
{
|
|
298
|
+
behaviour = comp as Behaviour;
|
|
299
|
+
compHash["enabled"] = behaviour.enabled;
|
|
300
|
+
}
|
|
301
|
+
// serialize component
|
|
302
|
+
SerializeComponent(comp, compHash);
|
|
303
|
+
|
|
304
|
+
// add it to the list of components
|
|
305
|
+
components.Add(compHash);
|
|
306
|
+
}
|
|
307
|
+
return components;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
public static string GetComponentTypeString(Component comp, Type t = null)
|
|
311
|
+
{
|
|
312
|
+
if (t == null)
|
|
313
|
+
{
|
|
314
|
+
t = comp.GetType();
|
|
315
|
+
}
|
|
316
|
+
string compType = t.ToString();
|
|
317
|
+
|
|
318
|
+
// I have seen this happen for a Camera's FlareLayer
|
|
319
|
+
if (compType == "UnityEngine.Behaviour")
|
|
320
|
+
{
|
|
321
|
+
// extract type while aavoiding reflection
|
|
322
|
+
int pos = comp.ToString().LastIndexOf("(UnityEngine.");
|
|
323
|
+
if (pos >= 0)
|
|
324
|
+
{
|
|
325
|
+
string compType2 = comp.ToString().Substring(pos);
|
|
326
|
+
if ((compType2.Length >= "(UnityEngine.x)".Length) &&
|
|
327
|
+
(compType2.EndsWith(")")))
|
|
328
|
+
{
|
|
329
|
+
// fix type
|
|
330
|
+
compType = compType2.Substring(1, compType2.Length - 2);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (compType.StartsWith("UnityEngine."))
|
|
336
|
+
{
|
|
337
|
+
compType = compType.Remove(0, "UnityEngine.".Length);
|
|
338
|
+
}
|
|
339
|
+
return compType;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
public static void SerializeComponent(Component comp, Hashtable compHash)
|
|
343
|
+
{
|
|
344
|
+
Type compType = comp.GetType();
|
|
345
|
+
Dictionary<Type, SerializerMethod> methods = new Dictionary<Type, SerializerMethod>()
|
|
346
|
+
{
|
|
347
|
+
{ typeof(Transform), SerializeTransform },
|
|
348
|
+
{ typeof(Camera), SerializeCamera },
|
|
349
|
+
{ typeof(GUIElement), SerializeGUIElement },
|
|
350
|
+
{ typeof(GUITexture), SerializeGUITexture },
|
|
351
|
+
{ typeof(GUIText), SerializeGUIText }
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
// serialize subclasses first
|
|
355
|
+
foreach (KeyValuePair<Type, SerializerMethod> pair in methods)
|
|
356
|
+
{
|
|
357
|
+
if (compType.IsSubclassOf(pair.Key))
|
|
358
|
+
{
|
|
359
|
+
pair.Value(comp, compHash);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
// serialize main classes after
|
|
363
|
+
foreach (KeyValuePair<Type, SerializerMethod> pair in methods)
|
|
364
|
+
{
|
|
365
|
+
if (compType == pair.Key)
|
|
366
|
+
{
|
|
367
|
+
pair.Value(comp, compHash);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
public static void SerializeTransform(Component comp, Hashtable h)
|
|
373
|
+
{
|
|
374
|
+
Transform t = comp as Transform;
|
|
375
|
+
h["position"] = SerializeVector3(t.position);
|
|
376
|
+
h["rotation"] = SerializeQuaternion(t.rotation);
|
|
377
|
+
h["localScale"] = SerializeVector3(t.localScale);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
public static void SerializeCamera(Component comp, Hashtable h)
|
|
381
|
+
{
|
|
382
|
+
Camera c = comp as Camera;
|
|
383
|
+
h["fieldOfView"] = c.fieldOfView;
|
|
384
|
+
h["nearClipPlane"] = c.nearClipPlane;
|
|
385
|
+
h["farClipPlane"] = c.farClipPlane;
|
|
386
|
+
h["renderingPath"] = c.renderingPath.ToString();
|
|
387
|
+
h["actualRenderingPath"] = c.actualRenderingPath.ToString();
|
|
388
|
+
h["orthographicSize"] = c.orthographicSize;
|
|
389
|
+
h["orthographic"] = c.orthographic;
|
|
390
|
+
h["depth"] = c.depth;
|
|
391
|
+
h["aspect"] = c.aspect;
|
|
392
|
+
h["cullingMask"] = c.cullingMask;
|
|
393
|
+
h["backgroundColor"] = SerializeColor(c.backgroundColor);
|
|
394
|
+
h["rect"] = SerializeRect(c.rect);
|
|
395
|
+
h["pixelRect"] = SerializeRect(c.pixelRect);
|
|
396
|
+
// FIXME: render texture
|
|
397
|
+
//h["targetTexture"] = SerializeTexture(c.targetTexture);
|
|
398
|
+
h["pixelWidth"] = c.pixelWidth;
|
|
399
|
+
h["pixelHeight"] = c.pixelHeight;
|
|
400
|
+
h["cameraToWorldMatrix"] = SerializeMatrix4x4(c.cameraToWorldMatrix);
|
|
401
|
+
h["worldToCameraMatrix"] = SerializeMatrix4x4(c.worldToCameraMatrix);
|
|
402
|
+
h["projectionMatrix"] = SerializeMatrix4x4(c.projectionMatrix);
|
|
403
|
+
h["velocity"] = SerializeVector3(c.velocity);
|
|
404
|
+
h["clearFlags"] = c.clearFlags.ToString();
|
|
405
|
+
h["layerCullDistances"] = c.layerCullDistances;
|
|
406
|
+
h["depthTextureMode"] = c.depthTextureMode.ToString();
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
public static void SerializeGUIElement(Component comp, Hashtable h)
|
|
410
|
+
{
|
|
411
|
+
GUIElement e = comp as GUIElement;
|
|
412
|
+
AppendHint<Hashtable>(h, "screen", SerializeRect(e.GetScreenRect()));
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
public static void SerializeGUITexture(Component comp, Hashtable h)
|
|
416
|
+
{
|
|
417
|
+
GUITexture t = comp as GUITexture;
|
|
418
|
+
h["color"] = SerializeColor(t.color);
|
|
419
|
+
h["pixelInset"] = SerializeRect(t.pixelInset);
|
|
420
|
+
// FIXME: render texture
|
|
421
|
+
//h["texture"] = SerializeTexture(t.texture);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
public static void SerializeGUIText(Component comp, Hashtable h)
|
|
425
|
+
{
|
|
426
|
+
GUIText t = comp as GUIText;
|
|
427
|
+
h["text"] = t.text;
|
|
428
|
+
// FIXME: serialize Material
|
|
429
|
+
//h["material"] = ...
|
|
430
|
+
h["pixelOffset"] = SerializeVector2(t.pixelOffset);
|
|
431
|
+
// FIXME: serialize Material
|
|
432
|
+
//h["font"] = ...
|
|
433
|
+
h["alignment"] = t.alignment.ToString();
|
|
434
|
+
h["anchor"] = t.anchor.ToString();
|
|
435
|
+
h["lineSpacing"] = t.lineSpacing;
|
|
436
|
+
h["tabSize"] = t.tabSize;
|
|
437
|
+
h["fontSize"] = t.fontSize;
|
|
438
|
+
h["fontStyle"] = t.fontStyle.ToString();
|
|
439
|
+
AppendHint<string>(h, "text", t.text);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
public static Hashtable AppendHint<T>(Hashtable h, string name, T hint)
|
|
443
|
+
{
|
|
444
|
+
Hashtable hints = h[".hints"] as Hashtable;
|
|
445
|
+
if (hints == null)
|
|
446
|
+
{
|
|
447
|
+
hints = new Hashtable();
|
|
448
|
+
h[".hints"] = hints;
|
|
449
|
+
}
|
|
450
|
+
List<T> hintsList;
|
|
451
|
+
if (hints.Contains(name))
|
|
452
|
+
{
|
|
453
|
+
hintsList = hints[name] as List<T>;
|
|
454
|
+
}
|
|
455
|
+
else
|
|
456
|
+
{
|
|
457
|
+
hintsList = new List<T>();
|
|
458
|
+
hints[name] = hintsList;
|
|
459
|
+
}
|
|
460
|
+
hintsList.Add(hint);
|
|
461
|
+
return hints;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
public static Hashtable SerializeColor(Color c)
|
|
465
|
+
{
|
|
466
|
+
Hashtable h = new Hashtable();
|
|
467
|
+
h["r"] = c.r;
|
|
468
|
+
h["g"] = c.g;
|
|
469
|
+
h["b"] = c.b;
|
|
470
|
+
h["a"] = c.a;
|
|
471
|
+
h["grayscale"] = c.grayscale;
|
|
472
|
+
return h;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
public static Hashtable SerializeRect(Rect r)
|
|
476
|
+
{
|
|
477
|
+
Hashtable h = new Hashtable();
|
|
478
|
+
h["x"] = r.x;
|
|
479
|
+
h["y"] = r.y;
|
|
480
|
+
h["width"] = r.width;
|
|
481
|
+
h["height"] = r.height;
|
|
482
|
+
return h;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
public static Hashtable SerializeVector3(Vector3 v)
|
|
486
|
+
{
|
|
487
|
+
Hashtable h = new Hashtable();
|
|
488
|
+
h["x"] = v.x;
|
|
489
|
+
h["y"] = v.y;
|
|
490
|
+
h["z"] = v.z;
|
|
491
|
+
return h;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
public static Hashtable SerializeVector2(Vector2 v)
|
|
495
|
+
{
|
|
496
|
+
Hashtable h = new Hashtable();
|
|
497
|
+
h["x"] = v.x;
|
|
498
|
+
h["y"] = v.y;
|
|
499
|
+
return h;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
public static Hashtable SerializeQuaternion(Quaternion q)
|
|
503
|
+
{
|
|
504
|
+
Hashtable h = new Hashtable();
|
|
505
|
+
h["x"] = q.x;
|
|
506
|
+
h["y"] = q.y;
|
|
507
|
+
h["z"] = q.z;
|
|
508
|
+
h["w"] = q.w;
|
|
509
|
+
return h;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
public static float[] SerializeMatrix4x4(Matrix4x4 m)
|
|
513
|
+
{
|
|
514
|
+
float[] matrix = new float[16];
|
|
515
|
+
for (int index = 0; index < matrix.Length; ++index)
|
|
516
|
+
{
|
|
517
|
+
matrix[index] = m[index];
|
|
518
|
+
}
|
|
519
|
+
return matrix;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
public class CukunityGetScreenCommand : CukunityCommand
|
|
524
|
+
{
|
|
525
|
+
public override void Process(Hashtable req, Hashtable res)
|
|
526
|
+
{
|
|
527
|
+
res["width"] = Screen.width;
|
|
528
|
+
res["height"] = Screen.height;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
public class CukunityGetLevelCommand : CukunityCommand
|
|
533
|
+
{
|
|
534
|
+
public override void Process(Hashtable req, Hashtable res)
|
|
535
|
+
{
|
|
536
|
+
res["number"] = Application.loadedLevel;
|
|
537
|
+
res["name"] = Application.loadedLevelName;
|
|
538
|
+
res["count"] = Application.levelCount;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
public class CukunityLoadLevelCommand : CukunityCommand
|
|
543
|
+
{
|
|
544
|
+
public override void Process(Hashtable req, Hashtable res)
|
|
545
|
+
{
|
|
546
|
+
int levelNumber = -1;
|
|
547
|
+
string levelName = GetJsonString(req, "name");
|
|
548
|
+
string methodName = GetJsonString(req, "method");
|
|
549
|
+
bool hasLevelNumber = GetJsonInt(req, "number", ref levelNumber);
|
|
550
|
+
|
|
551
|
+
if ((hasLevelNumber) && (levelName != null))
|
|
552
|
+
{
|
|
553
|
+
Debug.LogError("Cukunity: cannot specify both level name and number");
|
|
554
|
+
res["error"] = "BothLevelNameOrNumberError";
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
if (((levelNumber < 0) || (levelNumber >= Application.levelCount)) &&
|
|
559
|
+
((levelName == null) || (levelName.Length == 0)))
|
|
560
|
+
{
|
|
561
|
+
Debug.LogError("Cukunity: missing level name/number");
|
|
562
|
+
res["error"] = "MissingLevelNameOrNumberError";
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
if (methodName == null)
|
|
567
|
+
{
|
|
568
|
+
methodName = "sync";
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
switch (methodName.ToLower())
|
|
572
|
+
{
|
|
573
|
+
case "sync":
|
|
574
|
+
try
|
|
575
|
+
{
|
|
576
|
+
if (hasLevelNumber)
|
|
577
|
+
{
|
|
578
|
+
Application.LoadLevel(levelNumber);
|
|
579
|
+
}
|
|
580
|
+
else
|
|
581
|
+
{
|
|
582
|
+
Application.LoadLevel(levelName);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
catch (Exception)
|
|
586
|
+
{
|
|
587
|
+
throw new System.Exception("Load level failed");
|
|
588
|
+
}
|
|
589
|
+
break;
|
|
590
|
+
|
|
591
|
+
case "async":
|
|
592
|
+
try
|
|
593
|
+
{
|
|
594
|
+
if (hasLevelNumber)
|
|
595
|
+
{
|
|
596
|
+
Application.LoadLevelAsync(levelNumber);
|
|
597
|
+
}
|
|
598
|
+
else
|
|
599
|
+
{
|
|
600
|
+
Application.LoadLevelAsync(levelName);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
catch (Exception)
|
|
604
|
+
{
|
|
605
|
+
throw new System.Exception("Load level failed");
|
|
606
|
+
}
|
|
607
|
+
break;
|
|
608
|
+
|
|
609
|
+
case "additive":
|
|
610
|
+
try
|
|
611
|
+
{
|
|
612
|
+
if (hasLevelNumber)
|
|
613
|
+
{
|
|
614
|
+
Application.LoadLevelAdditive(levelNumber);
|
|
615
|
+
}
|
|
616
|
+
else
|
|
617
|
+
{
|
|
618
|
+
Application.LoadLevelAdditive(levelName);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
catch (Exception)
|
|
622
|
+
{
|
|
623
|
+
throw new System.Exception("Load level failed");
|
|
624
|
+
}
|
|
625
|
+
break;
|
|
626
|
+
|
|
627
|
+
case "additiveasync":
|
|
628
|
+
try
|
|
629
|
+
{
|
|
630
|
+
if (hasLevelNumber)
|
|
631
|
+
{
|
|
632
|
+
Application.LoadLevelAdditiveAsync(levelNumber);
|
|
633
|
+
}
|
|
634
|
+
else
|
|
635
|
+
{
|
|
636
|
+
Application.LoadLevelAdditiveAsync(levelName);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
catch (Exception)
|
|
640
|
+
{
|
|
641
|
+
throw new System.Exception("Load level failed");
|
|
642
|
+
}
|
|
643
|
+
break;
|
|
644
|
+
|
|
645
|
+
default:
|
|
646
|
+
Debug.LogError("Cukunity: unknown load level method in client's request");
|
|
647
|
+
res["error"] = "UnknownLoadLevelMethodError";
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
#if UNITY_IPHONE
|
|
654
|
+
public class CukunityIOS
|
|
655
|
+
{
|
|
656
|
+
[DllImport("__Internal")]
|
|
657
|
+
extern static public int CukunityScreenInstantTap(int x, int y, int tapCount);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
public class CukunityTouchScreenCommand : CukunityCommand
|
|
661
|
+
{
|
|
662
|
+
public override void Process(Hashtable req, Hashtable res)
|
|
663
|
+
{
|
|
664
|
+
int x = 0, y = 0, tapCount = 1;
|
|
665
|
+
string methodName = GetJsonString(req, "method");
|
|
666
|
+
|
|
667
|
+
if ((!GetJsonInt(req, "x", ref x)) ||
|
|
668
|
+
(!GetJsonInt(req, "y", ref y)))
|
|
669
|
+
{
|
|
670
|
+
Debug.LogError("Cukunity: must specify x and y for position to touch");
|
|
671
|
+
res["error"] = "MissingCoordinateError";
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
GetJsonInt(req, "tapCount", ref tapCount);
|
|
676
|
+
if (tapCount <= 0)
|
|
677
|
+
{
|
|
678
|
+
Debug.LogError("Cukunity: must specify a tap count greater than 0");
|
|
679
|
+
res["error"] = "InvalidTapCountError";
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
if (methodName == null)
|
|
684
|
+
{
|
|
685
|
+
methodName = "tap";
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
switch (methodName.ToLower())
|
|
689
|
+
{
|
|
690
|
+
case "tap":
|
|
691
|
+
CukunityIOS.CukunityScreenInstantTap(x, y, tapCount);
|
|
692
|
+
break;
|
|
693
|
+
|
|
694
|
+
default:
|
|
695
|
+
Debug.LogError("Cukunity: unknown touch method in client's request");
|
|
696
|
+
res["error"] = "UnknownTouchMethodError";
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
#endif
|
|
702
|
+
|
|
703
|
+
public class CukunityRequest
|
|
704
|
+
{
|
|
705
|
+
private string request;
|
|
706
|
+
private ManualResetEvent signal;
|
|
707
|
+
private string response;
|
|
708
|
+
|
|
709
|
+
public CukunityRequest(string request, ManualResetEvent signal)
|
|
710
|
+
{
|
|
711
|
+
this.request = request;
|
|
712
|
+
this.signal = signal;
|
|
713
|
+
response = "";
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
public string Request
|
|
717
|
+
{
|
|
718
|
+
get
|
|
719
|
+
{
|
|
720
|
+
return request;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
public string Response
|
|
725
|
+
{
|
|
726
|
+
get
|
|
727
|
+
{
|
|
728
|
+
return response;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
public void OnProcessed(string response)
|
|
733
|
+
{
|
|
734
|
+
this.response = response;
|
|
735
|
+
// fire signal
|
|
736
|
+
signal.Set();
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
public class CukunityClient
|
|
741
|
+
{
|
|
742
|
+
private TcpClient client;
|
|
743
|
+
private NetworkStream stream;
|
|
744
|
+
private byte[] buffer;
|
|
745
|
+
private int bufferUsedCount;
|
|
746
|
+
private string bufferedString;
|
|
747
|
+
private CukunityServer server;
|
|
748
|
+
public ManualResetEvent signal;
|
|
749
|
+
|
|
750
|
+
private static readonly int BufferIncrease = 1024;
|
|
751
|
+
private static readonly Encoding enc = Encoding.UTF8;
|
|
752
|
+
|
|
753
|
+
public CukunityClient(TcpClient client, CukunityServer server)
|
|
754
|
+
{
|
|
755
|
+
this.client = client;
|
|
756
|
+
this.server = server;
|
|
757
|
+
stream = client.GetStream();
|
|
758
|
+
buffer = new byte[BufferIncrease];
|
|
759
|
+
bufferUsedCount = 0;
|
|
760
|
+
bufferedString = "";
|
|
761
|
+
signal = new ManualResetEvent(false);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
public void SendAck()
|
|
765
|
+
{
|
|
766
|
+
Hashtable ack = new Hashtable();
|
|
767
|
+
byte[] ackBytes = enc.GetBytes(JsonWriter.Serialize(ack) + "\n");
|
|
768
|
+
stream.BeginWrite(ackBytes, 0, ackBytes.Length, OnSendAckComplete, this);
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
static private void OnSendAckComplete(IAsyncResult result)
|
|
772
|
+
{
|
|
773
|
+
CukunityClient cukieClient = result.AsyncState as CukunityClient;
|
|
774
|
+
cukieClient.stream.EndWrite(result);
|
|
775
|
+
cukieClient.BeginRead();
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
private void BeginRead()
|
|
779
|
+
{
|
|
780
|
+
// resize required?
|
|
781
|
+
if (bufferUsedCount >= buffer.Length)
|
|
782
|
+
{
|
|
783
|
+
byte[] newBuffer = new byte[bufferUsedCount + BufferIncrease];
|
|
784
|
+
Array.Copy(buffer, newBuffer, buffer.Length);
|
|
785
|
+
buffer = newBuffer;
|
|
786
|
+
}
|
|
787
|
+
stream.BeginRead(buffer, bufferUsedCount, buffer.Length - bufferUsedCount, OnReadComplete, this);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
public void Close()
|
|
791
|
+
{
|
|
792
|
+
Debug.LogWarning("Cukunity: client disconnected");
|
|
793
|
+
try
|
|
794
|
+
{
|
|
795
|
+
stream.Close();
|
|
796
|
+
client.Close();
|
|
797
|
+
}
|
|
798
|
+
catch (Exception)
|
|
799
|
+
{
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
static private void OnReadComplete(IAsyncResult result)
|
|
804
|
+
{
|
|
805
|
+
CukunityClient cukieClient = result.AsyncState as CukunityClient;
|
|
806
|
+
int byteCount = cukieClient.stream.EndRead(result);
|
|
807
|
+
string line;
|
|
808
|
+
|
|
809
|
+
// nothing received?
|
|
810
|
+
if (byteCount <= 0)
|
|
811
|
+
{
|
|
812
|
+
cukieClient.Close();
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
// append read data to internal buffer
|
|
817
|
+
cukieClient.bufferedString += enc.GetString(cukieClient.buffer, cukieClient.bufferUsedCount, byteCount);
|
|
818
|
+
cukieClient.bufferUsedCount += byteCount;
|
|
819
|
+
|
|
820
|
+
// can we extract a line from this buffer?
|
|
821
|
+
while ((line = cukieClient.ExtractLine(cukieClient.bufferedString)) != null)
|
|
822
|
+
{
|
|
823
|
+
int lineByteCount = enc.GetByteCount(line);
|
|
824
|
+
cukieClient.bufferedString = cukieClient.bufferedString.Remove(0, lineByteCount);
|
|
825
|
+
cukieClient.bufferUsedCount -= lineByteCount;
|
|
826
|
+
|
|
827
|
+
// process received line
|
|
828
|
+
string response = cukieClient.ProcessLineRequest(line);
|
|
829
|
+
if (response.Length > 0)
|
|
830
|
+
{
|
|
831
|
+
// respond to client
|
|
832
|
+
byte[] responseBytes = enc.GetBytes(response + "\n");
|
|
833
|
+
cukieClient.stream.BeginWrite(responseBytes, 0, responseBytes.Length, null, null);
|
|
834
|
+
}
|
|
835
|
+
else
|
|
836
|
+
{
|
|
837
|
+
cukieClient.Close();
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
// next read
|
|
843
|
+
cukieClient.BeginRead();
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
private string ExtractLine(string data)
|
|
847
|
+
{
|
|
848
|
+
int newLine = data.IndexOf("\n");
|
|
849
|
+
|
|
850
|
+
if (newLine < 0)
|
|
851
|
+
{
|
|
852
|
+
return null;
|
|
853
|
+
}
|
|
854
|
+
return data.Substring(0, newLine + 1);
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
private string ProcessLineRequest(string line)
|
|
858
|
+
{
|
|
859
|
+
string request = line.TrimEnd('\r', '\n');
|
|
860
|
+
CukunityRequest req = new CukunityRequest(request, signal);
|
|
861
|
+
|
|
862
|
+
// reset signal
|
|
863
|
+
signal.Reset();
|
|
864
|
+
// add request to que
|
|
865
|
+
server.EnqueueRequest(req);
|
|
866
|
+
// wait for completion
|
|
867
|
+
signal.WaitOne();
|
|
868
|
+
return req.Response;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|