public void Poll(double timeout) { int timeoutMs = (int)timeout * 1000; HashSet <string> newEntityIds = new HashSet <string>(); HashSet <string> lostEntityIds = new HashSet <string>(); unsafe { // 1. Run network to send and get world changes _AlloClient.alloclient_poll(client, timeoutMs); // 2. Parse through all the C entities and create C# equivalents HashSet <string> incomingEntityIds = new HashSet <string>(); _AlloEntity *entry = client->state.entityHead; while (entry != null) { string entityId = Marshal.PtrToStringAnsi(entry->id); AlloEntity entity; bool exists = entities.TryGetValue(entityId, out entity); if (!exists) { entity = new AlloEntity(); entity.id = entityId; entities[entityId] = entity; newEntityIds.Add(entityId); } incomingEntityIds.Add(entityId); IntPtr componentsJsonPtr = _AlloClient.cJSON_Print(entry->components); string componentsJson = Marshal.PtrToStringAnsi(componentsJsonPtr); entity.components = Deserialize <AlloComponents>(componentsJson); _AlloClient.allo_free(componentsJsonPtr); entry = entry->le_next; } HashSet <String> existingEntityIds = new HashSet <string>(entities.Keys); lostEntityIds = new HashSet <string>(existingEntityIds); lostEntityIds.ExceptWith(incomingEntityIds); } if (onAdded != null) { foreach (string addedId in newEntityIds) { onAdded(entities[addedId]); } } foreach (string removedId in lostEntityIds) { if (onRemoved != null) { onRemoved(entities[removedId]); } entities.Remove(removedId); } }
static unsafe private void _interaction(_AlloClient *_client, _AlloInteraction *inter) { string type = Marshal.PtrToStringAnsi(inter->type); string from = Marshal.PtrToStringAnsi(inter->senderEntityId); string to = Marshal.PtrToStringAnsi(inter->receiverEntityId); string cmd = Marshal.PtrToStringAnsi(inter->body); string requestId = Marshal.PtrToStringAnsi(inter->requestId); GCHandle backref = (GCHandle)_client->_backref; AlloClient self = backref.Target as AlloClient; List <object> data = Deserialize <List <object> >(cmd); if (from == "place" && data[0].ToString() == "announce") { self.avatarId = data[1].ToString(); self.placeName = data[2].ToString(); self.connected = true; self.onConnected?.Invoke(); } AlloEntity fromEntity = null; if (!string.IsNullOrEmpty(from)) { self.entities.TryGetValue(from, out fromEntity); } AlloEntity toEntity = null; if (!string.IsNullOrEmpty(to)) { self.entities.TryGetValue(to, out toEntity); } ResponseCallback callback = null; if (type == "response" && !string.IsNullOrEmpty(requestId)) { self.responseCallbacks.TryGetValue(requestId, out callback); } if (callback != null) { callback(cmd); self.responseCallbacks.Remove(requestId); } else { self.onInteraction?.Invoke(type, fromEntity, toEntity, data); } }
void checkForAddedViewEntity(AlloEntity entity) { if (entity.components.ui == null) { return; } View matchingView = FindView(entity.components.ui.view_id); if (matchingView != null) { matchingView.Entity = entity; matchingView.Awake(); } }
void routeInteraction(string type, AlloEntity sender, AlloEntity receiver, List <object> body) { if (receiver == null) { return; } if (receiver.components.ui == null) { return; } string vid = receiver.components.ui.view_id; View view = this.FindView(vid); if (view != null) { view.OnInteraction(type, body, sender); } else { Debug.WriteLine($"Warning: Got interaction {body[0].ToString()} for nonexistent vid {vid} receiver {receiver.id} sender {sender.id}"); } }
public void Activate(AlloEntity sender) { Action?.Invoke(this, new ActionArgs { Sender = sender }); }