//------------------------------------------------------------------------------------------------------- // SnapShot: single-shot save current Player state to World-saves internal void SnapShot() { Debug.Log("SnapShot: " + Player); if (Player.Equals("")) { return; // no active player } // CT snapshot source if (ctsnapshot != null) { ctsnapshot.close(); } ctsnapshot = new CTlib.CThttp(Session + "/" + Inventory + "/_" + Player, blocksPerSegment, true, true, true, Server); ctsnapshot.login(user, password); ctsnapshot.setAsync(AsyncMode); // serverConnect(); // reset Player folder paths string CTstateString = CTserdes.serialize(this, JSON_Format ? CTserdes.Format.JSON : CTserdes.Format.CSV); if (CTstateString == null) { return; // meh } // archive World state ctsnapshot.setTime(ServerTime()); ctsnapshot.putData(CTchannel, CTstateString); ctsnapshot.flush(); }
/// <summary> /// Deserialize a string into a List of one or more CTworld objects. /// This method supports parsing ".txt"/csv and JSON strings. /// </summary> /// <param name="strI">The serialized world objects.</param> /// <returns>A List of CTworlds, parsed from the given string.</returns> public static List <CTworld> deserialize(CTunity ctunityI, string strI) { List <CTworld> worlds = null; if (strI[0] == '#') { worlds = CTserdes.deserialize_csv(strI); } else if (strI[0] == '{') { worlds = CTserdes.deserialize_json(ctunityI, strI); } return(worlds); }
//------------------------------------------------------------------------------------------------------- // OneShot: single-shot save current Player state to GamePlay internal void OneShot() { Debug.Log("OneShot, Player: " + Player); if (Player.Equals("")) { return; // no active player } serverConnect(); // reset Player folder paths string CTstateString = CTserdes.serialize(this, JSON_Format ? CTserdes.Format.JSON : CTserdes.Format.CSV); if (CTstateString == null) { return; // meh } // update GamePlay ctplayer.setTime(ServerTime()); ctplayer.putData(CTchannel, CTstateString); ctplayer.flush(); }
private IEnumerator deployInventoryItem(String deploy, String objID) { if (newSession) { Debug.Log("OOPS can't create new object during newSession setup!"); yield break; } String myPlayer = String.Copy(Player); // Debug.Log("deployInventory: " + deploy+", id: "+objID); WaitForSeconds delay = new WaitForSeconds(pollInterval); while (true) { yield return(delay); yield return(null); // and wait for next full Update // form HTTP GET URL string url1 = Server + "/CT/" + Session + "/" + Inventory + "/" + deploy + "/" + CTchannel + "?f=d"; UnityWebRequest www1 = UnityWebRequest.Get(url1); www1.SetRequestHeader("AUTHORIZATION", CTauthorization()); yield return(www1.SendWebRequest()); // proceed with parsing CTstates.txt if (!string.IsNullOrEmpty(www1.error) || www1.downloadHandler.text.Length < 10) { Debug.Log("Inventory Error: " + www1.error + ": " + url1); yield break; } CTdebug(null); // clear error // parse to class structure... List <CTworld> worlds = CTserdes.deserialize(this, www1.downloadHandler.text); if (worlds == null) { Debug.Log("Null worlds found for: " + url1); yield break; } if (!myPlayer.Equals(Player)) { Debug.Log("Player switch on mid-deploy: " + myPlayer + " -> " + Player); yield break; // player switched on us! } // instantiate World objects here (vs waiting for CT GET loop) foreach (CTworld world in worlds) { foreach (KeyValuePair <String, CTobject> ctpair in world.objects) { CTobject ctobject = ctpair.Value; if (objID != null) { ctobject.id = objID; } if (!ctobject.id.StartsWith(Player + "/")) { ctobject.id = Player + "/" + ctobject.id; // auto-prepend Player name to object } newGameObject(ctobject, true); // require parent in-place } } yield break; } // end while(true) }
public IEnumerator getGameState() { Boolean pendingSession = false; while (true) { if (gamePaused || (replayActive && (replayTime == oldTime))) // no dupes (e.g. paused) { yield return(null); // ease up until next Update() continue; } oldTime = replayTime; double thisTime = ServerTime(); double deltaTime = thisTime - lastTime; double pointTime = 1F / maxPointRate; if (replayActive) { waitTime = pointTime; } // Debug.Log("waitTime: " + waitTime + ", pointTime: " + pointTime + ", pollInterval: " + pollInterval + ", deltaWorldTime: " + deltaWorldTime+", deltaTime: "+deltaTime); // idle-loop until expected amount of time for next update if (deltaTime < waitTime || Session.Equals("")) { yield return(null); continue; } lastTime = thisTime; if (newSession) { pendingSession = true; } // form HTTP GET URL String urlparams = ""; // "?f=d" is no-op for wildcard request if (replayActive) { urlparams = "?t=" + replayTime; // replay at masterTime } else { urlparams = "?c=" + Math.Round(pollInterval * 1000F); // set cache interval } string url1 = Server + "/CT/" + Session + "/GamePlay/*/" + CTchannel + urlparams; // Debug.Log("url1: " + url1); // enclose in "using" to ensure www1 object properly disposed: using (UnityWebRequest www1 = UnityWebRequest.Get(url1)) { www1.SetRequestHeader("AUTHORIZATION", CTauthorization()); yield return(www1.SendWebRequest()); if (newSession && !pendingSession) { continue; } // proceed with parsing CTstates.txt if (!string.IsNullOrEmpty(www1.error) || www1.downloadHandler.text.Length < 10) { Debug.Log("HTTP Error: " + www1.error + ": " + url1); if (isReplayMode()) { clearWorlds(); // presume problem is empty world... } pendingSession = newSession = false; // bail (presume empty all-around) // Debug.Log("newSession OFF"); continue; } CTdebug(null); // clear error double stime = ServerTime(); if (stime > lastReadTime) // block/sec (moving avg) { // BPS = Math.Round((BPS + (1F / (stime - lastReadTime))) / 2F); if (BPS < 1F) { BPS = Math.Ceiling((BPS + (1F / (stime - lastReadTime))) / 2F); // don't round to 0 } else { BPS = Math.Round((BPS + (1F / (stime - lastReadTime))) / 2F); } } lastReadTime = stime; // parse to class structure... List <CTworld> ws = CTserdes.deserialize(this, www1.downloadHandler.text); CTworld CTW = mergeCTworlds(ws); if (CTW == null || CTW.objects == null) { continue; // notta } if (pendingSession) { pendingSession = newSession = false; // (re)enable Update getData } if (!replayActive) // got a new deltaWorldTime... { // if (deltaWorldTime > 0) waitTime = Math.Max(0F, pollInterval-deltaTime); // fast waitTime if active if (deltaWorldTime > 0) { waitTime = pollInterval; // fast waitTime if active } else { waitTime = Math.Min(PaceTime, waitTime * 1.1f); // grow waitTime if idle } } } } // end while(true) }
double BPS = 10, PPS = 10, FPS = 10; // block, point, frame per second info void Update() { nups++; stopWatchF += Time.deltaTime; if (ctplayer == null) { serverConnect(); } if (ctplayer == null || newSession || replayActive || gamePaused || Player.Equals(Observer) /* || CTlist.Count==0 */) { // No writes for you! if (stopWatchF > fpsInterval) { FPS = Math.Round(nups / stopWatchF); fpsText.text = "FPS: " + BPS + "/" + FPS; // info BPS = 0; // reset til next update stopWatchF = stopWatchP = stopWatchB = nups = npts = 0; } activeWrite = false; return; } activeWrite = true; // flag important global state: actively creating files via CTput if (maxPointRate < blockRate) { maxPointRate = blockRate; // firewall } float pointInterval = 1f / maxPointRate; stopWatchP += Time.deltaTime; if (stopWatchP >= pointInterval) { string CTstateString = CTserdes.serialize(this, JSON_Format ? CTserdes.Format.JSON : CTserdes.Format.CSV); if (CTstateString == null) { return; // meh } ctplayer.setTime(ServerTime()); ctplayer.putData(CTchannel, CTstateString); npts++; stopWatchP = 0f; } float blockInterval = 1f / blockRate; pollInterval = blockInterval; // CTget poll at fraction of block interval? stopWatchB += Time.deltaTime; if (stopWatchB >= blockInterval) { // BPS = Math.Round(1F / stopWatchB); // moving average PPS = Math.Round(npts / stopWatchB); stopWatchB = npts = 0; ctplayer.flush(); // flush data to CT } // calc/display metrics if (stopWatchF > fpsInterval) { FPS = Math.Round(nups / stopWatchF); fpsText.text = "FPS: " + BPS + "/" + FPS; BPS = 0; // reset til next update stopWatchF = nups = 0; } }