-
Notifications
You must be signed in to change notification settings - Fork 1
/
NPCTeleport.cs
324 lines (282 loc) · 12.3 KB
/
NPCTeleport.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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
/* This content is licensed under the terms of the Creative Commons Attribution 4.0 International License.
* When using this content, you must:
* • Acknowledge that the content is from the Sansar Knowledge Base.
* • Include our copyright notice: "© 2017 Linden Research, Inc."
* • Indicate that the content is licensed under the Creative Commons Attribution-Share Alike 4.0 International License.
* • Include the URL for, or link to, the license summary at https://creativecommons.org/licenses/by-sa/4.0/deed.hi (and, if possible, to the complete license terms at https://creativecommons.org/licenses/by-sa/4.0/legalcode.
* For example:
* "This work uses content from the Sansar Knowledge Base. © 2017 Linden Research, Inc. Licensed under the Creative Commons Attribution 4.0 International License (license summary available at https://creativecommons.org/licenses/by/4.0/ and complete license terms available at https://creativecommons.org/licenses/by/4.0/legalcode)."
*/
using Sansar.Script;
using Sansar.Simulation;
using Sansar;
using System;
using System.Linq;
public class NPCTeleport : SceneObjectScript
{
#region EditorProperties
// Teleport the person who interacted to somewhere within the scene. Can be a comma separated list of event names.
[DefaultValue("on")]
[DisplayName("-> Local Teleport")]
public readonly string LocalEvent;
// The destination within the scene to teleport to
[DisplayName("Destination")]
[DefaultValue("<0,0,0>")]
public readonly Vector Destination;
// If true the destination position is relative to the object this script is on
// If false the destination is in scene coordinates regardless of this script's object's position
[DefaultValue(true)]
[DisplayName("Relative Position")]
public readonly bool RelativeDestination;
// Teleport the person that interacted to a remote scene. Can be a comma separated list of event names.
[DefaultValue("")]
[DisplayName("-> Remote Teleport")]
public readonly string RemoteEvent;
// The destination scene owner (from the scene url)
[DisplayName("Dest. Owner")]
[DefaultValue("")]
public readonly String DestOwner;
// The destination scene handle (from the scene url)
[DefaultValue("")]
[DisplayName("Dest. Scene")]
public readonly String DestScene;
// Enable responding to events for this script. Can be a comma separated list of event names.
[DefaultValue("tp_enable")]
[DisplayName("-> Enable")]
public readonly string EnableEvent;
// Disable responding to events for this script. Can be a comma separated list of event names.
[DefaultValue("tp_disable")]
[DisplayName("-> Disable")]
public readonly string DisableEvent;
// If StartEnabled is true then the script will respond to events when the scene is loaded
// If StartEnabled is false then the script will not respond to events until an (-> Enable) event is received.
[DefaultValue(true)]
[DisplayName("Start Enabled")]
public readonly bool StartEnabled = true;
#endregion
#region SimpleHelpers v2
// Update the region tag above by incrementing the version when updating anything in the region.
// If a Group is set, will only respond and send to other SimpleScripts with the same Group tag set.
// Does NOT accept CSV lists of groups.
// To send or receive events to/from a specific group from outside that group prepend the group name with a > to the event name
// my_group>on
[DefaultValue("")]
[DisplayName("Group")]
public string Group = "";
public interface ISimpleData
{
AgentInfo AgentInfo { get; }
ObjectId ObjectId { get; }
ObjectId SourceObjectId { get; }
// Extra data
Reflective ExtraData { get; }
}
public class SimpleData : Reflective, ISimpleData
{
public SimpleData(ScriptBase script) { ExtraData = script; }
public AgentInfo AgentInfo { get; set; }
public ObjectId ObjectId { get; set; }
public ObjectId SourceObjectId { get; set; }
public Reflective ExtraData { get; }
}
public interface IDebugger { bool DebugSimple { get; } }
private bool __debugInitialized = false;
private bool __SimpleDebugging = false;
private string __SimpleTag = "";
private string GenerateEventName(string eventName)
{
eventName = eventName.Trim();
if (eventName.EndsWith("@"))
{
// Special case on@ to send the event globally (the null group) by sending w/o the @.
return eventName.Substring(0, eventName.Length - 1);
}
else if (Group == "" || eventName.Contains("@"))
{
// No group was set or already targeting a specific group as is.
return eventName;
}
else
{
// Append the group
return $"{eventName}@{Group}";
}
}
private void SetupSimple()
{
__debugInitialized = true;
__SimpleTag = GetType().Name + " [S:" + Script.ID.ToString() + " O:" + ObjectPrivate.ObjectId.ToString() + "]";
Wait(TimeSpan.FromSeconds(1));
IDebugger debugger = ScenePrivate.FindReflective<IDebugger>("SimpleDebugger").FirstOrDefault();
if (debugger != null) __SimpleDebugging = debugger.DebugSimple;
}
System.Collections.Generic.Dictionary<string, Func<string, Action<ScriptEventData>, Action>> __subscribeActions = new System.Collections.Generic.Dictionary<string, Func<string, Action<ScriptEventData>, Action>>();
private Action SubscribeToAll(string csv, Action<ScriptEventData> callback)
{
if (!__debugInitialized) SetupSimple();
if (string.IsNullOrWhiteSpace(csv)) return null;
Func<string, Action<ScriptEventData>, Action> subscribeAction;
if (__subscribeActions.TryGetValue(csv, out subscribeAction))
{
return subscribeAction(csv, callback);
}
// Simple case.
if (!csv.Contains(">>"))
{
__subscribeActions[csv] = SubscribeToAllInternal;
return SubscribeToAllInternal(csv, callback);
}
// Chaining
__subscribeActions[csv] = (_csv, _callback) =>
{
System.Collections.Generic.List<string> chainedCommands = new System.Collections.Generic.List<string>(csv.Split(new string[] { ">>" }, StringSplitOptions.RemoveEmptyEntries));
string initial = chainedCommands[0];
chainedCommands.RemoveAt(0);
chainedCommands.Add(initial);
Action unsub = null;
Action<ScriptEventData> wrappedCallback = null;
wrappedCallback = (data) =>
{
string first = chainedCommands[0];
chainedCommands.RemoveAt(0);
chainedCommands.Add(first);
if (unsub != null) unsub();
unsub = SubscribeToAllInternal(first, wrappedCallback);
Log.Write(LogLevel.Info, "CHAIN Subscribing to " + first);
_callback(data);
};
unsub = SubscribeToAllInternal(initial, wrappedCallback);
return unsub;
};
return __subscribeActions[csv](csv, callback);
}
private Action SubscribeToAllInternal(string csv, Action<ScriptEventData> callback)
{
Action unsubscribes = null;
string[] events = csv.Trim().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
if (__SimpleDebugging)
{
Log.Write(LogLevel.Info, __SimpleTag, "Subscribing to " + events.Length + " events: " + string.Join(", ", events));
}
Action<ScriptEventData> wrappedCallback = callback;
foreach (string eventName in events)
{
if (__SimpleDebugging)
{
var sub = SubscribeToScriptEvent(GenerateEventName(eventName), (ScriptEventData data) =>
{
Log.Write(LogLevel.Info, __SimpleTag, "Received event " + GenerateEventName(eventName));
wrappedCallback(data);
});
unsubscribes += sub.Unsubscribe;
}
else
{
var sub = SubscribeToScriptEvent(GenerateEventName(eventName), wrappedCallback);
unsubscribes += sub.Unsubscribe;
}
}
return unsubscribes;
}
System.Collections.Generic.Dictionary<string, Action<string, Reflective>> __sendActions = new System.Collections.Generic.Dictionary<string, Action<string, Reflective>>();
private void SendToAll(string csv, Reflective data)
{
if (!__debugInitialized) SetupSimple();
if (string.IsNullOrWhiteSpace(csv)) return;
Action<string, Reflective> sendAction;
if (__sendActions.TryGetValue(csv, out sendAction))
{
sendAction(csv, data);
return;
}
// Simple case.
if (!csv.Contains(">>"))
{
__sendActions[csv] = SendToAllInternal;
SendToAllInternal(csv, data);
return;
}
// Chaining
System.Collections.Generic.List<string> chainedCommands = new System.Collections.Generic.List<string>(csv.Split(new string[] { ">>" }, StringSplitOptions.RemoveEmptyEntries));
__sendActions[csv] = (_csv, _data) =>
{
string first = chainedCommands[0];
chainedCommands.RemoveAt(0);
chainedCommands.Add(first);
Log.Write(LogLevel.Info, "CHAIN Sending to " + first);
SendToAllInternal(first, _data);
};
__sendActions[csv](csv, data);
}
private void SendToAllInternal(string csv, Reflective data)
{
if (string.IsNullOrWhiteSpace(csv)) return;
string[] events = csv.Trim().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
if (__SimpleDebugging) Log.Write(LogLevel.Info, __SimpleTag, "Sending " + events.Length + " events: " + string.Join(", ", events) + (Group != "" ? (" to group " + Group) : ""));
foreach (string eventName in events)
{
PostScriptEvent(GenerateEventName(eventName), data);
}
}
#endregion
Action Unsubscribes = null;
public override void Init()
{
if (StartEnabled) Subscribe(null);
SubscribeToAll(EnableEvent, Subscribe);
SubscribeToAll(DisableEvent, Unsubscribe);
}
private void Subscribe(ScriptEventData sed)
{
if (Unsubscribes == null)
{
Unsubscribes = SubscribeToAll(LocalEvent, LocalTeleport);
Unsubscribes += SubscribeToAll(RemoteEvent, RemoteTeleport);
}
}
private void Unsubscribe(ScriptEventData sed)
{
if (Unsubscribes != null)
{
Unsubscribes();
Unsubscribes = null;
}
}
private void LocalTeleport(ScriptEventData data)
{
Log.Write("A");
foreach (AgentPrivate agent in ScenePrivate.GetAgents())
{
Log.Write(agent.AgentInfo.Name);
if (agent.AgentInfo.Name == "GranddadGotMojo")
{
Log.Write("Camaeraman found");
ObjectPrivate objectPrivate = ScenePrivate.FindObject(agent.AgentInfo.ObjectId);
if (objectPrivate != null)
{
AnimationComponent anim = null;
if (objectPrivate.TryGetFirstComponent(out anim))
{
if (RelativeDestination)
{
anim.SetPosition(Destination + ObjectPrivate.Position);
}
else
{
anim.SetPosition(Destination);
}
}
}
}
}
}
private void RemoteTeleport(ScriptEventData data)
{
ISimpleData idata = data.Data.AsInterface<ISimpleData>();
AgentPrivate agent = ScenePrivate.FindAgent(idata.AgentInfo.SessionId);
if (agent != null)
{
agent.Client.TeleportToLocation(DestOwner, DestScene);
}
}
}