public void StoryUpdate(StoryUpdate update) { SetActive(false); SetText(update.text); SetChoices(update.choices); SetActive(true); }
// Keeping this for a bit. If there's multiple clients we need to solve what gets sent where. An update from a client to the server should be forwarded. // Other clients would receive the update first and any server updates on top of that. // But that would mean different messages which we haven't used so far. // Could also be that update messages get forwarded but all updates have sender labels, so the the sender can identify an update as their own and ignore it. // All clients and server would need unique id's. // Could already be implemented in unity. If not, server should pass around unique names. // /* * void onTaskUpdateFromClient(NetworkMessage netMsg) * { * * var taskUpdate = netMsg.ReadMessage<TaskUpdate>(); * * string debug = ""; * * debug += "Incoming task update on connection ID " + netMsg.conn.connectionId; * * // if (GENERAL.ALLTASKS * * applyTaskUpdate(taskUpdate); * * * List<NetworkConnection> connections = new List<NetworkConnection>(NetworkServer.connections); * * int c = 0; * * for (int ci = 0; ci < connections.Count; ci++) * { * * NetworkConnection nc = connections[ci]; * * if (nc != null) * { * * if (nc.connectionId != netMsg.conn.connectionId) * { * * debug += " sending update to connection ID " + nc.connectionId; * * NetworkServer.SendToClient(ci, taskCode, taskUpdate); * c++; * * } * else * { * * debug += " skipping client connection ID " + nc.connectionId; * * } * * } * else * { * * debug += (" skipping null connection "); * * } * * } * * Log.Message(debug); * * } */ // Send bundled story updates void SendStoryUpdateToClients(StoryUpdate message) { // message.MaxMessageSize; // NetworkServer.SendUnreliableToAll(storyCode, message); NetworkServer.SendToAll(storyCode, message); }
// Keeping this for a bit. If there's multiple clients we need to solve what gets sent where. An update from a client to the server should be forwarded. // Other clients would receive the update first and any server updates on top of that. // But that would mean different messages which we haven't used so far. // Could also be that update messages get forwarded but all updates have sender labels, so the the sender can identify an update as their own and ignore it. // All clients and server would need unique id's. // Could already be implemented in unity. If not, server should pass around unique names. // /* * void onTaskUpdateFromClient(NetworkMessage netMsg) * { * * var taskUpdate = netMsg.ReadMessage<TaskUpdate>(); * * string debug = ""; * * debug += "Incoming task update on connection ID " + netMsg.conn.connectionId; * * // if (GENERAL.ALLTASKS * * applyTaskUpdate(taskUpdate); * * * List<NetworkConnection> connections = new List<NetworkConnection>(NetworkServer.connections); * * int c = 0; * * for (int ci = 0; ci < connections.Count; ci++) * { * * NetworkConnection nc = connections[ci]; * * if (nc != null) * { * * if (nc.connectionId != netMsg.conn.connectionId) * { * * debug += " sending update to connection ID " + nc.connectionId; * * NetworkServer.SendToClient(ci, taskCode, taskUpdate); * c++; * * } * else * { * * debug += " skipping client connection ID " + nc.connectionId; * * } * * } * else * { * * debug += (" skipping null connection "); * * } * * } * * Log.Message(debug); * * } */ // Send bundled story updates public void SendStoryUpdateToClients(StoryUpdate message) { // message.MaxMessageSize; // NetworkServer.SendUnreliableToAll(storyCode, message); NetworkServer.SendToAll(storyCode, message); Verbose("Sending: " + message.DebugLog); }
// must async auto-continue, or new messages happen immediately, // in the middle of the old message, leading to out-of-order issues. private IEnumerator AutoContinue(StoryUpdate update) { if (autoContinue && (ink.story.canContinue && update.choices.Count == 0)) { yield return(new WaitForSeconds(0)); ink.Continue(); } if (autoContinue && update.atEnd) { Quit(); } }
void ApplyStoryUpdate(StoryUpdate storyUpdate) { PointerUpdateBundled pointerUpdateBundled; while (storyUpdate.GetPointerUpdate(out pointerUpdateBundled)) { ApplyPointerUpdate(pointerUpdateBundled); } TaskUpdateBundled taskUpdateBundled; while (storyUpdate.GetTaskUpdate(out taskUpdateBundled)) { ApplyTaskUpdate(taskUpdateBundled); } }
//void ApplyStoryUpdate(StoryUpdate storyUpdate) //{ // DataUpdate dataUpdate; // while (storyUpdate.GetDataUpdate(out dataUpdate)) // ApplyDataUpdate(dataUpdate); //} //void ApplyDataUpdate(DataUpdate dataUpdate) //{ // // See if we have an instance of this. // // GENERAL.ALLDATA.Contains //} void ApplyStoryUpdate(StoryUpdate storyUpdate) { // apply all pointerupdates StoryPointerUpdate pointerUpdateBundled; while (storyUpdate.GetPointerUpdate(out pointerUpdateBundled)) { ApplyPointerUpdate(pointerUpdateBundled); } // apply all taskupdates StoryTaskUpdate taskUpdateBundled; while (storyUpdate.GetTaskUpdate(out taskUpdateBundled)) { ApplyTaskUpdate(taskUpdateBundled); } }
public void SendStoryUpdateToClient(StoryUpdate message, string address) { int conn = -1; for (int i = 0; i < NetworkServer.connections.Count; i++) { if (NetworkServer.connections[i].address == address) { conn = i; break; } } if (conn == -1) { Warning("client not found " + address); } ; // NetworkServer.SendUnreliableToAll(storyCode, message); NetworkServer.SendToClient(conn, storyCode, message); // Verbose("Sending: "+message.DebugLog); }
public void StoryUpdate(StoryUpdate update) => choices = update.choices;
//State state; // Start is called before the first frame update void Start() { states = StoryUpdate.update(); UpdateStoryText(); }
private void StoryUpdate(StoryUpdate update) { Debug.Log(update); StartCoroutine(AutoContinue(update)); }
public void StoryUpdate(StoryUpdate u) => speechBubble?.StoryUpdate(u);
void SendStoryUpdateToServer(StoryUpdate message) { networkManager.client.Send(storyCode, message); // sendMessageToServer("ping"); }
void LateUpdate() { StoryUpdate storyUpdate = new StoryUpdate(); // Contains a collection of task and pointer updates. // Check our loadbalance. If we're sending too many updates we'll randomly drop frames. // All changes will be sent but if values are updated in the meantime the previous value will never be sent. // This is ok for running values but not ok for status values etc. int QueueSize = 0; if (GENERAL.AUTHORITY == AUTHORITY.GLOBAL && NetworkServer.active) { // We're an active server. byte error; QueueSize = NetworkTransport.GetOutgoingMessageQueueSize(NetworkServer.serverHostId, out error); // debugValue.text = "queued out server: " + QueueSize; if ((NetworkError)error != NetworkError.Ok) { Error("Networktransport error: " + (NetworkError)error); } } if (GENERAL.AUTHORITY == AUTHORITY.LOCAL && networkManager != null && networkManager.client != null) { // We're an active client. byte error = (byte)NetworkError.Ok; if (networkManager.client.connection != null) { QueueSize = NetworkTransport.GetOutgoingMessageQueueSize(networkManager.client.connection.hostId, out error); } else { Warning("Can't get queue size (yet)"); } // debugValue.text = "queued out client: " + QueueSize; if ((NetworkError)error != NetworkError.Ok) { Error("Networktransport error: " + (NetworkError)error); } } switch (QueueSize) { case 0: BufferStatusOut = 0; break; case 1: case 2: BufferStatusOut = 1; break; default: BufferStatusOut = 2; break; } // forcing always send. // this means that a storyupdate is sent for every frame and they all arrive in order. // they get executed in order as well, but they may be batched together. // so multiple tasks might get executed in a single frame. they will be executed in the correct order. if (QueueSize < 3 || true) { // Iterate over all pointers to see if any were killed. Clients do not kill pointers themselves. // For consistency of network logic, local pointers that were killed are disposed by the director. // Global pointers are disposed here, after updating clients about them. for (int p = GENERAL.ALLPOINTERS.Count - 1; p >= 0; p--) { StoryPointer pointer = GENERAL.ALLPOINTERS[p]; if (GENERAL.AUTHORITY == AUTHORITY.GLOBAL && pointer.scope == SCOPE.GLOBAL && pointer.GetStatus() == POINTERSTATUS.KILLED) //if (GENERAL.AUTHORITY == AUTHORITY.GLOBAL && pointer.scope == SCOPE.GLOBAL && pointer.modified && pointer.GetStatus() == POINTERSTATUS.KILLED) { Log("Sending pointer kill update to clients: " + pointer.currentPoint.StoryLine); storyUpdate.AddStoryPointerUpdate(pointer.GetUpdate()); // bundled //pointer.modified = false; Log("Removing pointer " + pointer.currentPoint.StoryLine); GENERAL.ALLPOINTERS.Remove(pointer); } } // Iterate over all tasks. for (int i = GENERAL.ALLTASKS.Count - 1; i >= 0; i--) { StoryTask task = GENERAL.ALLTASKS[i]; // Cleanup completed tasks. if (task.getStatus() == TASKSTATUS.COMPLETE) { GENERAL.ALLTASKS.RemoveAt(i); Verbose("Task " + task.Instruction + " on storyline " + task.Pointer.currentPoint.StoryLine + " completed, removed from alltasks. "); } if (task.modified) { // Debugging: if a pointer is in the process of being killed, we may want to not send task updates // as they might result in the task being recreated clientside. if (task.Pointer.GetStatus() == POINTERSTATUS.KILLED) { Warning("Supressing sending task update for task with pointer that is dying. " + task.Instruction); } else { // Check if we need to send network updates. switch (GENERAL.AUTHORITY) { case AUTHORITY.LOCAL: if (task.scope == SCOPE.GLOBAL) { Verbose("Global task " + task.Instruction + " changed, adding to update for server."); storyUpdate.AddTaskUpdate(task.GetUpdateBundled()); // bundled } break; case AUTHORITY.GLOBAL: if (task.scope == SCOPE.GLOBAL) { Verbose("Global task " + task.Instruction + " changed, adding to update for clients."); storyUpdate.AddTaskUpdate(task.GetUpdateBundled()); // bundled } break; default: break; } task.modified = false; } } } // If anything to send, send. if (storyUpdate.AnythingToSend()) { switch (GENERAL.AUTHORITY) { case AUTHORITY.LOCAL: SendStoryUpdateToServer(storyUpdate); //Debug.Log("Sending story update to server. \n" + storyUpdate.DebugLog); break; case AUTHORITY.GLOBAL: SendStoryUpdateToClients(storyUpdate); //Debug.Log("Sending story update to clients. \n" + storyUpdate.DebugLog); //Debug.Log(storyUpdate.ToString()); break; default: break; } } } else { Warning("Dropping update."); } }
/* * private async void LoadScript() * { * if (scriptAddressable != null && scriptAddressable != "") * { * theDirector.status = DIRECTORSTATUS.PAUSED; * AsyncOperationHandle<TextAsset> handle = Addressables.LoadAssetAsync<TextAsset>(scriptAddressable); * await handle.Task; * * if (handle.Status==) * if (handle.Result == null) * { * Error("Addressable script asset failed: " + obj.OperationException.Message); * * } * else * { * * theDirector.loadScriptAsset(obj.Result); * Log("Script loaded, from addressable asset."); * * * } * * } * * * * * * // The task is complete. Be sure to check the Status is successful before storing the Result. * * } * */ #region SENDUPDATES void LateUpdate() { // Check if any data changed during this frame, and send updates across network. StoryUpdate storyUpdate = new StoryUpdate(); // Contains a collection of task and pointer updates. // Is there a networkhandler. if (NetworkHandler.Instance != null) { int Queue = NetworkHandler.Instance.GetQueueSize(); if (Queue == -1) { // Verbose("no network active"); } else { switch (Queue) { case 0: BufferStatusOut = 0; break; case 1: case 2: BufferStatusOut = 1; break; default: BufferStatusOut = 2; break; } // forcing always send. // this means that a storyupdate is sent for every frame and they all arrive in order. // they get executed in order as well, but they may be batched together. // so multiple tasks might get executed in a single frame. they will be executed in the correct order. if (Queue < 3 || true) { // Iterate over all pointers to see if any were killed. Clients do not kill pointers themselves. // For consistency of network logic, local pointers that were killed are disposed by the director. // Global pointers are disposed here, after updating clients about them. for (int p = GENERAL.ALLPOINTERS.Count - 1; p >= 0; p--) { StoryPointer pointer = GENERAL.ALLPOINTERS[p]; if (GENERAL.AUTHORITY == AUTHORITY.GLOBAL && pointer.scope == SCOPE.GLOBAL && pointer.GetStatus() == POINTERSTATUS.KILLED) //if (GENERAL.AUTHORITY == AUTHORITY.GLOBAL && pointer.scope == SCOPE.GLOBAL && pointer.modified && pointer.GetStatus() == POINTERSTATUS.KILLED) { Log("Sending pointer kill update to clients: " + pointer.currentPoint.StoryLine); storyUpdate.AddStoryPointerUpdate(pointer.GetUpdate()); // bundled //pointer.modified = false; Log("Removing pointer " + pointer.currentPoint.StoryLine); GENERAL.ALLPOINTERS.Remove(pointer); } } // Iterate over all tasks. for (int i = GENERAL.ALLTASKS.Count - 1; i >= 0; i--) { StoryTask task = GENERAL.ALLTASKS[i]; // Cleanup completed tasks. if (task.getStatus() == TASKSTATUS.COMPLETE) { GENERAL.ALLTASKS.RemoveAt(i); Verbose("Task " + task.Instruction + " on storyline " + task.Pointer.currentPoint.StoryLine + " completed, removed from alltasks. "); } if (task.modified) { // Debugging: if a pointer is in the process of being killed, we may want to not send task updates // as they might result in the task being recreated clientside. if (task.Pointer.GetStatus() == POINTERSTATUS.KILLED) { Warning("Supressing sending task update for task with pointer that is dying. " + task.Instruction); } else { // Check if we need to send network updates. switch (GENERAL.AUTHORITY) { case AUTHORITY.LOCAL: if (task.scope == SCOPE.GLOBAL) { Verbose("Global task " + task.Instruction + " with id " + task.PointID + " changed, adding to update for server."); storyUpdate.AddTaskUpdate(task.GetUpdate()); // bundled } break; case AUTHORITY.GLOBAL: if (task.scope == SCOPE.GLOBAL) { Verbose("Global task " + task.Instruction + " with id " + task.PointID + " changed, adding to update for clients."); storyUpdate.AddTaskUpdate(task.GetUpdate()); // bundled } break; default: break; } task.modified = false; } } } // If anything to send, send. if (storyUpdate.AnythingToSend()) { switch (GENERAL.AUTHORITY) { case AUTHORITY.LOCAL: if (NetworkHandler.Instance != null) { NetworkHandler.Instance.SendStoryUpdateToServer(storyUpdate); } Log("Sending story update to server. \n" + storyUpdate.DebugLog); break; case AUTHORITY.GLOBAL: if (NetworkHandler.Instance != null) { NetworkHandler.Instance.SendStoryUpdateToClients(storyUpdate); } Log("Sending story update to clients. \n" + storyUpdate.DebugLog); //Debug.Log(storyUpdate.ToString()); break; default: break; } } } } /* * * * * if (NetworkHandler.Instance.IsClient()) * { * StoryUpdate storyUpdate = new StoryUpdate(); // Contains a collection of dataupdates. * * // Iterate over all data. * * for (int i = GENERAL.ALLTASKS.Count - 1; i >= 0; i--) * { * StoryTask data = GENERAL.ALLTASKS[i]; * * if (data.modified) * { * // Data was modified locally, if global, compile an update for the server. * * if (data.scope == SCOPE.GLOBAL) * { * Verbose("Data was modified locally as client, creating update for server for " + data.ID); * storyUpdate.AddDataUpdate(data.GetDataUpdate()); // bundled * } * * data.modified = false; * } * } * * // If anything to send, send. * * if (storyUpdate.AnythingToSend()) * * { * * NetworkHandler.Instance.SendStoryUpdateToServer(storyUpdate); * * Verbose("Sending story update to server. \n" + storyUpdate.DebugLog); * * * * } * * * * } * * * * * // If server, messages may differ for clients. * * * if (NetworkHandler.Instance.IsServer()) * { * * string[] clients = NetworkHandler.Instance.TrackedConnectedAddresses().ToArray(); * * for (int c = 0; c < clients.Length; c++) * { * * StoryUpdate storyUpdate = new StoryUpdate(); // Contains a collection of dataupdates. * * // Iterate over all data. * * for (int i = GENERAL.ALLTASKS.Count - 1; i >= 0; i--) * { * StoryTask data = GENERAL.ALLTASKS[i]; * * if (data.modified) * { * // Data was modified locally, if global, compile an update for the server. * * if (data.scope == SCOPE.GLOBAL) * { * Verbose("Data was modified locally as client, creating update for server for " + data.ID); * storyUpdate.AddDataUpdate(data.GetDataUpdateFor(clients[c])); // bundled * } * * data.modified = false; * } * } * * // If anything to send, send. * * if (storyUpdate.AnythingToSend()) * * { * NetworkHandler.Instance.SendStoryUpdateToClient(storyUpdate, clients[c]); * * Verbose("Sending story update to client. \n" + storyUpdate.DebugLog); * * * * } * * * } * * * * * } * * */ } }