/// <summary> /// Create a JSON serialized version of the player information. /// </summary> /// <param name="ctunityI">Source of the information to be serialized.</param> /// <returns>Serialized player information.</returns> private static string serialize_json(CTunity ctunityI) { CTworldJson world = new CTworldJson(); world.player = ctunityI.Player; world.time = ctunityI.ServerTime(); // world.mode = ctunityI.replayText; world.objects = new List <CTobjectJson>(); int objectCount = 0; foreach (GameObject ct in ctunityI.CTlist.Values) { if (!ctunityI.localPlayer(ct)) { continue; // only save locally owned objects } // Debug.Log("CTserdes ct.name: " + fullName); if (ct == null) { continue; } CTclient ctp = ct.GetComponent <CTclient>(); if (ctp == null) { continue; } String prefab = ctp.prefab; if (prefab.Equals("Ghost")) { continue; // no save ghosts } // if (!ctunityI.replayActive && !ct.name.StartsWith(ctunityI.Player)) continue; // only save locally owned objects // if (!ctunityI.doCTwrite(fullName)) continue; // only save locally owned objects CTobjectJson obj = new CTobjectJson(); // obj.id = ct.name; // strip leading world-name from embedded object name String fullName = CTunity.fullName(ct); if (fullName.StartsWith(world.player + "/")) { fullName = fullName.Remove(0, world.player.Length + 1); } // Debug.Log("CTserdes obj.id: " + obj.id + ", world.player: " + world.player+", fullName: "+fullName); obj.id = fullName; obj.model = prefab; // obj.state = (ct.activeSelf ? true : false); // NOTE: limit floating point values to 4 decimal places obj.pos = new List <Double>(); obj.pos.Add(LimitPrecision(ct.transform.localPosition.x, 4)); // was .position obj.pos.Add(LimitPrecision(ct.transform.localPosition.y, 4)); obj.pos.Add(LimitPrecision(ct.transform.localPosition.z, 4)); obj.rot = new List <Double>(); obj.rot.Add(LimitPrecision(ct.transform.localRotation.eulerAngles.x, 4)); // was .rotation obj.rot.Add(LimitPrecision(ct.transform.localRotation.eulerAngles.y, 4)); obj.rot.Add(LimitPrecision(ct.transform.localRotation.eulerAngles.z, 4)); obj.scale = new List <Double>(); obj.scale.Add(LimitPrecision(ct.transform.localScale.x, 4)); obj.scale.Add(LimitPrecision(ct.transform.localScale.y, 4)); obj.scale.Add(LimitPrecision(ct.transform.localScale.z, 4)); Renderer renderer = ct.transform.gameObject.GetComponent <Renderer>(); if (renderer != null) { // Color mycolor = renderer.material.color; // this NG for multi-part prefabs (e.g. biplane) Color mycolor = ctp.myColor; // NG? obj.color = new List <Double>(); obj.color.Add(LimitPrecision(mycolor.r, 4)); obj.color.Add(LimitPrecision(mycolor.g, 4)); obj.color.Add(LimitPrecision(mycolor.b, 4)); obj.color.Add(LimitPrecision(mycolor.a, 4)); } // if (ctp.link != null && ctp.link.Length > 0) obj.link = ctp.link; if (ctp.custom != null && ctp.custom.Length > 0) { obj.custom = ctp.custom; } world.objects.Add(obj); objectCount++; } // Debug.Log("serialize: "+ world.player+", count: "+ objectCount); // if (objectCount == 0) return null; // notta. (returning no-object string writes header-only) string jsonData = null; try { jsonData = JsonUtility.ToJson(world); } catch (Exception e) { UnityEngine.Debug.Log("Exception serializing JSON: " + e.Message); return(null); } // jsonData = jsonData.Replace("},", "},\n"); // for readability jsonData = jsonData.Replace("{\"id", "\n{\"id"); // for readability return(jsonData); }
/// <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); }