from github

This commit is contained in:
jonas
2024-10-29 17:16:17 +01:00
commit 537f1d77fb
1074 changed files with 303521 additions and 0 deletions
+238
View File
@@ -0,0 +1,238 @@
using SimpleFileBrowser;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
//this script implements save logic for a room on any client
public class RoomSaver : MonoBehaviour
{
//culture info for float parsing
private CultureInfo ci = CultureInfo.InvariantCulture;
[SerializeField] private ObjectSync objSyn;
[SerializeField] private OBJLoader objLoader;
private GameObject spawnedObject;
[SerializeField] private Material defaultMat;
private string osPath;
// a class that can store all object data in one place (keep in mind DIFFERENT TO OTHER OBJData structs in other structs !!!)
public class OBJData
{
public string objectName;
public List<Vector3> vertices;
public List<int> triangles;
public Vector3 position;
public Quaternion rotation;
public Vector3 scale;
}
//if a clients requests to create a save file, the server will call this function on the client
[ClientRpc]
public void GetAllRoomDataClientRPC(ulong clientID, ObjectSync.OBJData[] objData)
{
//only the requesting client should save the file
if (clientID != NetworkManager.Singleton.LocalClientId)
{
return;
}
//generate a random string for save (save file can be renamed by user in their system file explorer)
string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
char[] stringChars = new char[8];
System.Random random = new System.Random();
for (int i = 0; i < stringChars.Length; i++)
{
stringChars[i] = chars[random.Next(chars.Length)];
}
//add the current date to the save file
string curDate = new String(DateTime.Today.ToString("d"));
string finalString = new String(stringChars) + "_" + curDate;
//check if the saves directory does already existist -not-> create it
if (!Directory.Exists(osPath + "vrcsaves"))
{
Directory.CreateDirectory(osPath + "vrcsaves");
}
//the final path to the saves destination (please keep os specific file paths in mind "c:" for windows "/ etc." for unix based systems)
string filePath = osPath + "vrcsaves/" + finalString.Replace("/", "_") + ".vrc";
StreamWriter writer = new StreamWriter(filePath);
//enumerate all objects sent by the server and write into the savefile
foreach (ObjectSync.OBJData o in objData)
{
writer.WriteLine("o");
foreach (Vector3 v in o.vertices)
{
writer.WriteLine("v$" + v.x + "$" + v.y + "$" + v.z);
}
foreach (int t in o.triangles)
{
writer.WriteLine("t$" + t);
}
writer.WriteLine("p$" + o.positionVector.x + "$" + o.positionVector.y + "$" + o.positionVector.z);
writer.WriteLine("r$" + o.rotation.x + "$" + o.rotation.y + "$" + o.rotation.z + "$" + o.rotation.w);
writer.WriteLine("s$" + o.scale.x + "$" + o.scale.y + "$" + o.scale.z);
}
//"save file changes"
writer.Flush();
}
//a client requesting to save will call this function with its id
[ServerRpc]
public void GetAllRoomDataServerRPC(ulong clientID)
{
GetAllRoomDataClientRPC(clientID, objSyn.objDataList.ToArray());
}
//this function will be called from the menu bar if a player wants to save
public void SaveScene()
{
//ask the server for the current data in the room
GetAllRoomDataServerRPC(NetworkManager.Singleton.LocalClientId);
}
private void Start()
{
//set default save paths on windows and linux
if (Application.platform == RuntimePlatform.LinuxEditor || Application.platform == RuntimePlatform.LinuxServer || Application.platform == RuntimePlatform.LinuxPlayer)
{
osPath = "/home/" + Environment.UserName + "/";
}
else
{
osPath = "c:/";
}
try
{
//try to get a filepath to load a a save file
//if there is no save file a blank classroom will be created
if (PlayerPrefs.GetString("path") != "")
{
string path = PlayerPrefs.GetString("path");
ReadEvenMoreObjDataFromFile(path);
PlayerPrefs.SetString("path", "");
}
}
catch
{
Debug.Log("Fehler beim Lesen der Datei");
}
}
//This is a meme <-- XD
//this function does read and load a save file
private void ReadEvenMoreObjDataFromFile(string path)
{
List<OBJData> objDataList = new List<OBJData>();
//read the file data and split each line
string[] lines = FileBrowserHelpers.ReadTextFromFile(path).Split("\n");
OBJData dataStruct = new OBJData();
string curString;
foreach (string line in lines)
{
line.Trim();
curString = line.Replace("$", " ");
//if there is a "o" the data block of a new object will begin
if (curString.StartsWith("o"))
{
dataStruct = new OBJData();
dataStruct.vertices = new List<Vector3>();
dataStruct.triangles = new List<int>();
objDataList.Add(dataStruct);
}
//if there is a "v" at the start of the line there is a vertex stored
else if (curString.StartsWith("v"))
{
dataStruct.vertices.Add(ComeBackOfTheObjVector3StringToVector3(curString));
}
//if there is a "t" at the start of the line there is a triangle index stored
else if (curString.StartsWith("t"))
{
int curInt = int.Parse(curString.Trim().Replace("t", ""));
dataStruct.triangles.Add((curInt));
}
//if there is a "p" at the start of the line position of the gameobject is stored here
else if (curString.StartsWith("p"))
{
dataStruct.position = ComeBackOfTheObjVector3StringToVector3(curString);
}
//if there is a "r" at the start of the line rotation of the gameobject is stored here
else if (curString.StartsWith("r"))
{
dataStruct.rotation = ObjQuanternion(curString);
}
//if there is a "s" at the start of the line scale of the gameobject is stored here
else if (curString.StartsWith("s"))
{
dataStruct.scale = ComeBackOfTheObjVector3StringToVector3(curString);
}
}
//create a mesh/gameobject of each loaded object data
for (int i = 0; i < objDataList.Count; i++)
{
GameObject finishedObj = objLoader.CreateMesh(objLoader.buildObjData(objDataList[i].vertices.ToArray(), objDataList[i].triangles.ToArray()), objDataList[i].position);
//apply rotation and scale to the gameobject
finishedObj.transform.rotation = objDataList[i].rotation;
finishedObj.transform.localScale = objDataList[i].scale;
//create info to keep track of the object in servers object list etc.
ObjectSync.OBJData objsyncData = new ObjectSync.OBJData();
objsyncData.vertices = objDataList[i].vertices.ToArray();
objsyncData.triangles = objDataList[i].triangles.ToArray();
objsyncData.positionVector = objDataList[i].position;
objsyncData.rotation = objDataList[i].rotation;
Debug.Log(objDataList[i].scale);
//add the object to the sync
objsyncData.scale = objDataList[i].scale;
objSyn.objDataList.Add(objsyncData);
objSyn.spawnedObjects.Add(finishedObj);
}
}
//This is another meme
//this function creates a vector3 object from a vector stored in vrc file
private Vector3 ComeBackOfTheObjVector3StringToVector3(string vecString)
{
vecString = vecString.Replace(",", ".");
string[] lnSplit = vecString.Trim().Split(" ");
return new Vector3(float.Parse(lnSplit[1], NumberStyles.Float, ci),
float.Parse(lnSplit[2], NumberStyles.Float, ci),
float.Parse(lnSplit[3], NumberStyles.Float, ci));
}
//this function creates a quaternion object from a quaternion stored in vrc file
private Quaternion ObjQuanternion(string quanString)
{
quanString = quanString.Replace(",", ".");
string[] lnSplit = quanString.Trim().Split(" ");
return new Quaternion(float.Parse(lnSplit[1], NumberStyles.Float, ci),
float.Parse(lnSplit[2], NumberStyles.Float, ci),
float.Parse(lnSplit[3], NumberStyles.Float, ci),
float.Parse(lnSplit[4], NumberStyles.Float, ci));
}
}