示例#1
0
    //-------------------------------------------------------------------------------------------------------
    // CTsetstate wrapper

    private void setState(String objectID, CTobject ctobject)
    {
        if (!CTlist.TryGetValue(objectID, out GameObject ct))
        {
            return;
        }
        if (ct != null)
        {
            setState(objectID, ctobject, ct);
        }
    }
示例#2
0
    //----------------------------------------------------------------------------------------------------------------
    // setState called from CTunity, works on active/inactive

    public void setState(CTobject cto, Boolean ireplay, Boolean iplayPaused)
    {
        if (ctunity == null)
        {
            return;                                     // async
        }
        if (isLocalControl())
        {
            return;                      // no updates for local player
        }
        ctobject = cto;                  // for public ref

        // set baseline for Lerp going forward to next step
        oldPos   = transform.localPosition;
        oldRot   = transform.localRotation;
        oldScale = transform.localScale;

        // following TrackSpeed tries to estimate average update-interval, but it varies too much to be smooth (mjm 1/18/19)
//        if (stopWatch > 0F) TrackSpeed = (3F * TrackSpeed + (1F / stopWatch)) / 4F;  // weighted moving average

        // update targets
        stopWatch = 0F;
        myPos     = cto.pos;
        myRot     = cto.rot;
        myScale   = cto.scale;
        //		Debug.Log("myScale: " + myScale);
        myColor = cto.color;

        replayMode = ireplay;
        playPaused = iplayPaused;           // playPaused used by smooth replay logic
        newCustom(cto.custom);

        // locals for immediate action:
        if (replayMode || !isLocalObject())
        {
//            gameObject.SetActive(cto.state);            // need to activate here (vs Update callback)
//            setColor(cto.color);                        // set color for non-local objects
        }

        if (rb == null)
        {
            rb = GetComponent <Rigidbody>();               // try again; async issue?
        }
        setGravity();

        //		Debug.Log(name+", ilc: "+isLocalControl());
        startup = false;
    }
示例#3
0
    private void setState(String objectID, CTobject ctobject, GameObject ct)
    {
        if (ct == null || !ct.activeSelf)
        {
            return;
        }
        CTclient ctp = ct.GetComponent <CTclient>();

        if (ctp != null)
        {
            ctp.setState(ctobject, replayActive, playPaused);
            if (newSession)
            {
                ctp.jumpState();                                            // do it now (don't wait for next ctclient.Update cycle)
            }
        }
    }
示例#4
0
    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)
    }
示例#5
0
    private GameObject newGameObject(CTobject ctobject, Boolean requireParent)
    {
        // define parameters
        String     objID    = ctobject.id;
        String     prefab   = ctobject.model;
        Vector3    position = ctobject.pos;
        Quaternion rotation = ctobject.rot;
        Vector3    scale    = ctobject.scale;
        Color      color    = ctobject.color;

//		Debug.Log("newGameObject: " + objID+", prefab: "+prefab+", custom: "+ctobject.custom+", prefab: "+prefab+", color: "+color);
        if (prefab.Equals(""))
        {
            return(null);                                   // in-game player without prefab
        }
        // already exists?
        if (CTlist.ContainsKey(objID))
        {
            GameObject go = CTlist[objID];
            if (go != null)
            {
                go.SetActive(true);     // let setState activate?
                CTclient ctc  = go.gameObject.transform.GetComponent <CTclient>();
                string   ctpf = (ctc == null) ? "" : CTlist[objID].gameObject.transform.GetComponent <CTclient>().prefab;
                if (!ctpf.Equals(prefab) || scale == Vector3.zero)        // prefab changed!
                {
                    //	Debug.Log(objID+": new prefab: " + prefab +", old pf: "+ctpf);
                    position = go.transform.localPosition;   // rebuild to new prefab (in-place)
                    rotation = go.transform.localRotation;
                    clearObject(objID);
                }
                else
                {
                    //	Debug.Log("newGameObject, replacing existing object: " + objID);
                    clearObject(objID, true);           // replace vs:
                    //  return CTlist[objID];             // maintain if already there
                }
            }
        }

        GameObject tgo = GameObject.Find(objID);

        if (tgo != null)
        {
            Debug.Log("Warning, existing object: " + objID);                  // unregistered prefabs hit this check
//            clearObject(tgo);  // clear vs leave in place?
            return(tgo);
        }

        // load prefab
        GameObject pfgo = ((GameObject)getPrefab(prefab));

        if (pfgo == null)
        {
            Debug.Log("NULL prefab: " + prefab);
            return(null);
        }
//		pfgo.SetActive(isactive);

        // build hierarchical path to new object: Players/<Player>/object-path
        String parent   = "Players";
        String fullpath = parent + "/" + objID;

        char[]   delims    = { '/', ':' };
        String[] pathparts = fullpath.Split(delims);

        GameObject pgo = GameObject.Find(parent);           // "Players" at this point

//        Debug.Log("create objID: " + objID+", fullpath: "+fullpath);

        for (int i = 1; i < pathparts.Length - 1; i++)
        {
            parent = parent + "/" + pathparts[i];
            GameObject cgo = GameObject.Find(parent);

            if (cgo == null)
            {
                if (requireParent && i > 1)             // sorry clugey.  can happen with async deployInventory (e.g. Launcher)
                {
                    Debug.Log("Null parent! " + objID); // this can strand empty grandparent (benign)
                    return(null);
                }
                //            Debug.Log("Create empty parent: " + pathparts[i]);
                cgo      = new GameObject(); // empty gameObject; trunk-node in hierarchy
                cgo.name = pathparts[i];
                cgo.transform.SetParent(pgo.transform, true);
            }
            pgo = cgo;
        }


        pgo = GameObject.Find(parent);
        if (pgo == null)                                                  // parent missing
        {
            Debug.Log("Missing parent: " + parent + ", child: " + objID); // init issue, catch it next update...
            return(null);
        }
        Transform tparent = pgo.transform;
        Transform pf      = pfgo.transform;

        // Instantiate!
//		Transform newp = Instantiate(pf, position, rotation * pf.rotation, tparent);    // rez prefab with set parent
        Transform newp = Instantiate(pf, tparent, false);            // rez prefab with set parent

        newp.localPosition = position /* + pf.position */;           // offset by prefab built-in position?
        newp.localRotation = rotation * pf.rotation;
//		Debug.Log(objID + ": instantiate child at: " + position+", parent: "+tparent.name);

        if (scale.Equals(Vector3.zero))
        {
            newp.localScale = pf.localScale;
        }
        else
        {
            newp.localScale = scale;                                         // zero scale means use initial prefab scale
        }
        newp.name = pathparts[pathparts.Length - 1];

        CTclient myctc = newp.GetComponent <CTclient>();

        if (myctc != null)
        {
            myctc.newCustom(ctobject.custom);  // set this now vs waiting for setState
            myctc.prefab = prefab;
            myctc.setColor(color);
        }

        // make sure in CTlist (inactive objects won't call CTregister...)
        CTregister(newp.gameObject);

        return(newp.gameObject);
    }
示例#6
0
    //-------------------------------------------------------------------------------------------------------
    // newGameObject:  create and instantiate new CTobject

    private GameObject newGameObject(CTobject ctobject)
    {
        return(newGameObject(ctobject, false));
    }
示例#7
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
    }
示例#8
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);
    }
示例#9
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);
    }