Exemplo n.º 1
0
    //-------------------------------------------------------------------------------------------------------
    // disable objects that are in CTlist but go missing from CTworld list

    public void clearMissing(CTworld ctworld)
    {
        if (newSession)
        {
            return;
        }

        List <String> destroyList = new List <String>();            // make copy; avoid sync error

        foreach (KeyValuePair <string, GameObject> entry in CTlist) // cycle through objects in world
        {
            GameObject go     = entry.Value;
            String     goName = entry.Key;

            if ((go == null) || !go.activeSelf)         // prune inactive objects
            {
                destroyList.Add(goName);
            }
            else
            {
                //  don't deactivate locally owned Player objects (might be instantiated but not yet seen in ctworld)
                if (!activeWrite || !goName.StartsWith(Player))
                {
                    if (!ctworld.objects.ContainsKey(goName))
                    {
                        CTclient ctc = go.GetComponent <CTclient>();
                        if (!(ctc != null && ctc.isRogue))   // let Rogue objects persist
                        {
                            destroyList.Add(goName);
                        }
                    }
                }
            }
        }

        // clear out destroylist
        foreach (String t in destroyList)
        {
//            Debug.Log("clearMissing: " + t);
            clearObject(t);  // destroy while iterating wrecks list
        }
    }
Exemplo n.º 2
0
    //-------------------------------------------------------------------------------------------------------
    void printCTworld(CTworld ctworld)
    {
        String p = "CTworld:\n";

        p += ("name: " + ctworld.player + "\n");      // redundant Key, name?
//        p += ("mode: " + ctworld.mode + "\n");
        p += ("time: " + ctworld.time + "\n");
        p += ("Objects:" + "\n");
        if (ctworld.objects == null)
        {
            p += "<null>";
        }
        else
        {
            foreach (CTobject ctobject in ctworld.objects.Values)
            {
                p += ("\tkey: " + ctobject.id + "\n");                          // redundant Key, id?
                p += ("\tprefab: " + ctobject.model + "\n");                    // object class
//				p += ("\tstate: " + ctobject.state + "\n");
                p += ("\tpos: " + ctobject.pos + "\n");
            }
        }
        UnityEngine.Debug.Log(p);
    }
Exemplo n.º 3
0
    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)
    }
Exemplo n.º 4
0
    //-------------------------------------------------------------------------------------------------------
    // mergeCTworlds:  consolidate CTworlds from each player into local world-state

    CTworld mergeCTworlds(List <CTworld> worlds)
    {
        if (worlds == null)
        {
//			CTdebug("Warning: null CTworlds!");
            return(null);                                // nobody home
        }

        double masterTime = ServerTime();
        double updateTime = 0F;

        // build CTWorld structure from consolidated objects as owned (prefix) by each world

        CTworld CTW = new CTworld();

        CTW.player = masterWorldName;                         // nominal CTW header values (not actually used)
        CTW.time   = masterTime;

        CTW.objects = new Dictionary <String, CTobject>();
        List <CTworld> tworldList = new List <CTworld>();

        // second pass, screen masterTime, consolidate masterWorld
        foreach (CTworld world in worlds)
        {
            if (world.time > updateTime && !world.player.Equals(Player))
            {
                updateTime = world.time;                      // keep track of most-recent CTW time
            }
            double delta = Math.Abs(world.time - masterTime); // masterTime NG on Remote... ???
            if ((SyncTime > 0) && (delta > SyncTime))         // reject stale times
            {
                if (!world.player.Equals(Player) /* || observerFlag */)
                {
                    clearWorld(world.player);                                                        // inefficient?
                }
                continue;
            }

            //           if (world.objects.Count > 0)                    // skip empty place-holder worlds
            {
                world.active = (delta < LinkDeadTime);
                tworldList.Add(world);                      // build list of active worlds
            }

//            Debug.Log("mergeWorlds player: " + world.player+", objects: "+world.objects.Count);
            foreach (KeyValuePair <String, CTobject> ctpair in world.objects)
            {
                CTobject ctobject = ctpair.Value;
                //               if (!ctobject.id.StartsWith(world.player + "/"))
                ctobject.id = world.player + "/" + ctobject.id;          // auto-prepend world name to object

                // accumulate objects owned by each world
                try
                {
                    CTW.objects.Add(ctobject.id, ctobject);
                }
                catch (Exception e)
                {
                    Debug.Log("CTW exception on object: " + ctobject.id + ", e: " + e);
                }

                // set object state with CTclient
                GameObject mygo;
                Boolean    isOnList = CTlist.TryGetValue(ctobject.id, out mygo);

                if (isOnList && mygo != null)                             // object exists
                {
                    if ((isReplayMode() || !world.player.Equals(Player))) // check for change of prefab
                    {
                        string pf = mygo.transform.GetComponent <CTclient>().prefab;
                        if (!pf.Equals(ctobject.model))   // recheck showMenu for async newPlayer
                        {
                            // Debug.Log("change prefab: " + ctobject.model + " --> " + pf);
                            newGameObject(ctobject);
                        }
                    }
                    setState(ctobject.id, ctobject, mygo);                            // use pre-fetched mygo if possible
                }
                else                                                                  // instantiate new players and objects
                {
                    if ((newSession || replayActive || !world.player.Equals(Player))) // mjm 12/3/18
                    {
                        newGameObject(ctobject);
                    }
                    setState(ctobject.id, ctobject);
                }
            }
        }

        // scan for missing objects
        clearMissing(CTW);

        deltaWorldTime  = updateTime - latestWorldTime;
        latestWorldTime = updateTime;               // for replay reference
        WorldList       = tworldList;               // update set of worlds

//        Debug.Log("new Worldlist!");  foreach(CTworld ctw in WorldList) Debug.Log("ctw: " + ctw.player+", time: "+ctw.time+", nobjects: "+ctw.objects.Count);
        return(CTW);                                        // consolidated CTworld
    }
Exemplo n.º 5
0
    /// <summary>
    /// Deserialize the given JSON string into a List of CTworld objects.
    /// The given string may contain one or a concatenation of several "world" objects.
    ///
    /// JSON example:
    /// {"mode":"Live","time":1.536844452785E9,"name":"Blue","objects":[{"id":"Blue","prefab":"Ball","state":true,"pos":[-8.380356788635254,0.25,3.8628578186035156],"rot":[0.0,0.0,0.0],"custom":""}]}
    ///
    /// </summary>
    /// <param name="strI">The JSON serialized world objects.</param>
    /// <returns>A List of CTworlds, parsed from the given string.</returns>
    private static List <CTworld> deserialize_json(CTunity ctunityI, string strI)
    {
        if ((strI == null) || (strI.Length < 10))
        {
            return(null);
        }

        List <CTworld> worlds = new List <CTworld>();

        // Break up the given string into different "world" objects
        // NOTE: This assumes that "player" is the first field in the JSON string
        List <int> indexes = AllIndexesOf(strI, @"{""player"":""");

        if (indexes.Count == 0)
        {
            return(null);
        }
        for (int i = 0; i < indexes.Count; ++i)
        {
            int startIdx = indexes[i];
            int endIdx   = strI.Length - 1;
            if (i < (indexes.Count - 1))
            {
                endIdx = indexes[i + 1];
            }
            string      nextWorldStr = strI.Substring(startIdx, endIdx - startIdx);
            CTworldJson dataFromJson = null;
            try
            {
                dataFromJson = JsonUtility.FromJson <CTworldJson>(nextWorldStr);
            }
            catch (Exception e)
            {
                UnityEngine.Debug.Log("Exception deserializing JSON: " + e.Message);
                continue;
            }
            if (dataFromJson == null || dataFromJson.objects == null)
            {
                continue;
            }

            // skip active local player ( save the effort here and in MergeWorlds() )
            // ??  seems to have issues PB <--> RT ??
            //           if(ctunityI.activePlayer(dataFromJson.player)) continue;

            // Create CTworld object from CTworldJson (these classes are very similar but there are differences, see definitions above)
            CTworld jCTW = new CTworld();
            jCTW.player = dataFromJson.player;
            jCTW.time   = dataFromJson.time;
//			jCTW.mode = dataFromJson.mode;
            jCTW.objects = new Dictionary <String, CTobject>();
            foreach (CTobjectJson ctobject in dataFromJson.objects)
            {
                CTobject cto = new CTobject();
                cto.id = ctobject.id;

                // legacy format conversion:
                //				if (cto.id.Equals(jCTW.player)) cto.id = cto.id + "/" + cto.id;  // convert old top-level player
                //				else if (cto.id.StartsWith(jCTW.player + ".")) cto.id = cto.id.Remove(0, jCTW.player.Length + 1);
//                Debug.Log("deserialize id: " + cto.id);
                cto.model = ctobject.model;
//				cto.state = ctobject.state;
//				cto.link = ctobject.link;
                cto.pos    = new Vector3((float)ctobject.pos[0], (float)ctobject.pos[1], (float)ctobject.pos[2]);
                cto.rot    = Quaternion.Euler((float)ctobject.rot[0], (float)ctobject.rot[1], (float)ctobject.rot[2]);
                cto.scale  = new Vector3((float)ctobject.scale[0], (float)ctobject.scale[1], (float)ctobject.scale[2]);
                cto.color  = new Color((float)ctobject.color[0], (float)ctobject.color[1], (float)ctobject.color[2], (float)ctobject.color[3]);
                cto.custom = ctobject.custom;
                jCTW.objects.Add(cto.id, cto);
            }
            worlds.Add(jCTW);
        }

        if (worlds.Count == 0)
        {
            return(null);
        }

        return(worlds);
    }
Exemplo n.º 6
0
    /// <summary>
    /// Deserialize the given txt/csv string into a List of CTworld objects.
    ///
    /// CSV example:
    /// #Live:1536843969.4578:Red
    /// Red;Ball;1;(2.5764, 0.2600, 8.5905);(0.0277, 60.7938, -0.0043)
    /// Red.Ground;Ground;1;(0.0000, 0.0000, 20.0000);(0.0000, 0.0000, 0.0000)
    /// Red.Pickup0;Pickup;1;(0.2000, 0.4000, 23.0000);(45.0800, 20.8186, 21.9459)
    /// Red.Pickup1;Pickup;1;(8.1000, 0.4000, 27.4000);(45.0800, 20.8186, 21.9459)
    /// Red.Pickup2;Pickup;1;(-1.3000, 0.4000, 13.3000);(45.0800, 20.8186, 21.9459)
    /// Red.Pickup3;Pickup;1;(2.0000, 0.4000, 23.6000);(45.0800, 20.8186, 21.9459)
    /// Red.Pickup4;Pickup;1;(0.9000, 0.4000, 22.7000);(45.0800, 20.8186, 21.9459)
    ///
    /// </summary>
    /// <param name="strI">The csv serialized world objects.</param>
    /// <returns>A List of CTworlds, parsed from the given string.</returns>
    private static List <CTworld> deserialize_csv(string strI)
    {
        List <CTworld> worlds = new List <CTworld>();

        String[] sworlds = strI.Split('#');                                     // parse world-by-world

        // consolidate objects for each world
        foreach (String world in sworlds)
        {
//			Debug.Log("world: " + world);
            if (world.Length < 2)
            {
                continue;
            }
            String[] lines  = world.Split('\n');
            String[] header = lines[0].Split(':');
            if (header.Length != 3)
            {
                continue;
            }

            CTworld CTW = new CTworld();
            CTW.objects = new Dictionary <String, CTobject>();

//			CTW.mode = header[0];
            CTW.time   = Double.Parse(header[1]);
            CTW.player = header[2];

            foreach (String line in lines)
            {
                // sanity checks:
                if (line.Length < 2 || line.StartsWith("<"))
                {
                    continue;                                                           // skip empty & html lines
                }
                String[] parts = line.Split(';');
                if (parts.Length < 3)
                {
                    continue;
                }

                CTobject ctobject = new CTobject();
                ctobject.id    = parts[0];
                ctobject.model = parts[1];
//				ctobject.state = !parts[2].Equals("0");

                // parse ctobject.pos
                string   pstate = parts[3].Substring(1, parts[3].Length - 2);                   // drop parens
                string[] pvec   = pstate.Split(',');
                ctobject.pos = new Vector3(float.Parse(pvec[0]), float.Parse(pvec[1]), float.Parse(pvec[2]));

                // parse ctobject.rot
                pstate       = parts[4].Substring(1, parts[4].Length - 2);               // drop parens
                pvec         = pstate.Split(',');
                ctobject.rot = Quaternion.Euler(float.Parse(pvec[0]), float.Parse(pvec[1]), float.Parse(pvec[2]));

                // custom field (used for indirect URL):
//				if (parts.Length > 5) ctobject.link = parts[5];

                CTW.objects.Add(ctobject.id, ctobject);
            }

            worlds.Add(CTW);
        }

        return(worlds);
    }