diff --git a/.gitignore b/.gitignore index eb83a8f..b4371e5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,10 @@ -/[Ll]ibrary/ -/[Tt]emp/ -/[Oo]bj/ -/[Bb]uild/ -/[Bb]uilds/ -/Assets/AssetStoreTools* +/Close Enough!/[Ll]ibrary/ +/Close Enough!/Library/ +/Close Enough!/[Tt]emp/ +/Close Enough!/[Oo]bj/ +/Close Enough!/[Bb]uild/ +/Close Enough!/[Bb]uilds/ +/Close Enough!/Assets/AssetStoreTools* # Visual Studio 2015 cache directory /.vs/ @@ -12,6 +13,7 @@ ExportedObj/ .consulo/ *.csproj +*metadata* *.unityproj *.sln *.suo @@ -22,6 +24,7 @@ ExportedObj/ *.booproj *.svd *.pdb +*UnityTempFile* # Unity3D generated meta files *.pidb.meta diff --git a/Close Enough!/Assets/Photon Unity Networking.meta b/Close Enough!/Assets/Photon Unity Networking.meta new file mode 100644 index 0000000..910275a --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 3143422ca40fa404bb24888f6a03eab4 +folderAsset: yes +timeCreated: 1525372511 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor.meta b/Close Enough!/Assets/Photon Unity Networking/Editor.meta new file mode 100644 index 0000000..150b6ad --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: a911635029db24d0c9929e47a5616ccf +folderAsset: yes +timeCreated: 1525372511 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork.meta new file mode 100644 index 0000000..9c85a17 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 4a016803b974e45e286ac6dd362eb7eb +folderAsset: yes +timeCreated: 1525372512 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/AccountService.cs b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/AccountService.cs new file mode 100644 index 0000000..b9be1ae --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/AccountService.cs @@ -0,0 +1,235 @@ +// ---------------------------------------------------------------------------- +// +// Photon Cloud Account Service - Copyright (C) 2012 Exit Games GmbH +// +// +// Provides methods to register a new user-account for the Photon Cloud and +// get the resulting appId. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +#if UNITY_EDITOR + +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; + +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using ExitGames.Client.Photon; +using Newtonsoft.Json; + + +public class AccountService +{ + private const string ServiceUrl = "https://service.exitgames.com/AccountExt/AccountServiceExt.aspx"; + + private Action registrationCallback; // optional (when using async reg) + + public string Message { get; private set; } // msg from server (in case of success, this is the appid) + + protected internal Exception Exception { get; set; } // exceptions in account-server communication + + public string AppId { get; private set; } + + public string AppId2 { get; private set; } + + public int ReturnCode { get; private set; } // 0 = OK. anything else is a error with Message + + public enum Origin : byte { ServerWeb = 1, CloudWeb = 2, Pun = 3, Playmaker = 4 }; + + /// + /// Creates a instance of the Account Service to register Photon Cloud accounts. + /// + public AccountService() + { + WebRequest.DefaultWebProxy = null; + ServicePointManager.ServerCertificateValidationCallback = Validator; + } + + public static bool Validator(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors) + { + return true; // any certificate is ok in this case + } + + /// + /// Attempts to create a Photon Cloud Account. + /// Check ReturnCode, Message and AppId to get the result of this attempt. + /// + /// Email of the account. + /// Marks which channel created the new account (if it's new). + /// Defines which type of Photon-service is being requested. + public void RegisterByEmail(string email, Origin origin, string serviceType = null) + { + this.registrationCallback = null; + this.AppId = string.Empty; + this.AppId2 = string.Empty; + this.Message = string.Empty; + this.ReturnCode = -1; + + string result; + try + { + WebRequest req = HttpWebRequest.Create(this.RegistrationUri(email, (byte)origin, serviceType)); + HttpWebResponse resp = req.GetResponse() as HttpWebResponse; + + // now read result + StreamReader reader = new StreamReader(resp.GetResponseStream()); + result = reader.ReadToEnd(); + } + catch (Exception ex) + { + this.Message = "Failed to connect to Cloud Account Service. Please register via account website."; + this.Exception = ex; + return; + } + + this.ParseResult(result); + } + + /// + /// Attempts to create a Photon Cloud Account asynchronously. + /// Once your callback is called, check ReturnCode, Message and AppId to get the result of this attempt. + /// + /// Email of the account. + /// Marks which channel created the new account (if it's new). + /// Defines which type of Photon-service is being requested. + /// Called when the result is available. + public void RegisterByEmailAsync(string email, Origin origin, string serviceType, Action callback = null) + { + this.registrationCallback = callback; + this.AppId = string.Empty; + this.AppId2 = string.Empty; + this.Message = string.Empty; + this.ReturnCode = -1; + + try + { + HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(this.RegistrationUri(email, (byte)origin, serviceType)); + req.Timeout = 5000; // TODO: The Timeout property has no effect on asynchronous requests made with the BeginGetResponse + req.BeginGetResponse(this.OnRegisterByEmailCompleted, req); + } + catch (Exception ex) + { + this.Message = "Failed to connect to Cloud Account Service. Please register via account website."; + this.Exception = ex; + if (this.registrationCallback != null) + { + this.registrationCallback(this); + } + } + } + + /// + /// Internal callback with result of async HttpWebRequest (in RegisterByEmailAsync). + /// + /// + private void OnRegisterByEmailCompleted(IAsyncResult ar) + { + try + { + HttpWebRequest request = (HttpWebRequest)ar.AsyncState; + HttpWebResponse response = request.EndGetResponse(ar) as HttpWebResponse; + + if (response != null && response.StatusCode == HttpStatusCode.OK) + { + // no error. use the result + StreamReader reader = new StreamReader(response.GetResponseStream()); + string result = reader.ReadToEnd(); + + this.ParseResult(result); + } + else + { + // a response but some error on server. show message + this.Message = "Failed to connect to Cloud Account Service. Please register via account website."; + } + } + catch (Exception ex) + { + // not even a response. show message + this.Message = "Failed to connect to Cloud Account Service. Please register via account website."; + this.Exception = ex; + } + + if (this.registrationCallback != null) + { + this.registrationCallback(this); + } + } + + /// + /// Creates the service-call Uri, escaping the email for security reasons. + /// + /// Email of the account. + /// 1 = server-web, 2 = cloud-web, 3 = PUN, 4 = playmaker + /// Defines which type of Photon-service is being requested. Options: "", "voice", "chat" + /// Uri to call. + private Uri RegistrationUri(string email, byte origin, string serviceType) + { + if (serviceType == null) + { + serviceType = string.Empty; + } + + string emailEncoded = Uri.EscapeDataString(email); + string uriString = string.Format("{0}?email={1}&origin={2}&serviceType={3}", ServiceUrl, emailEncoded, origin, serviceType); + + return new Uri(uriString); + } + + /// + /// Reads the Json response and applies it to local properties. + /// + /// + private void ParseResult(string result) + { + if (string.IsNullOrEmpty(result)) + { + this.Message = "Server's response was empty. Please register through account website during this service interruption."; + return; + } + + Dictionary values = JsonConvert.DeserializeObject>(result); + if (values == null) + { + this.Message = "Service temporarily unavailable. Please register through account website."; + return; + } + + int returnCodeInt = -1; + string returnCodeString = string.Empty; + string message; + string messageDetailed; + + values.TryGetValue("ReturnCode", out returnCodeString); + values.TryGetValue("Message", out message); + values.TryGetValue("MessageDetailed", out messageDetailed); + + int.TryParse(returnCodeString, out returnCodeInt); + + this.ReturnCode = returnCodeInt; + if (returnCodeInt == 0) + { + // returnCode == 0 means: all ok. message is new AppId + this.AppId = message; + if (PhotonEditorUtils.HasVoice) + { + this.AppId2 = messageDetailed; + } + } + else + { + // any error gives returnCode != 0 + this.AppId = string.Empty; + if (PhotonEditorUtils.HasVoice) + { + this.AppId2 = string.Empty; + } + this.Message = message; + } + } +} +#endif \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/AccountService.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/AccountService.cs.meta new file mode 100644 index 0000000..a070b17 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/AccountService.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 166dfe22956ef0341b28e18d0499e363 +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/CullAreaEditor.cs b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/CullAreaEditor.cs new file mode 100644 index 0000000..202aa7d --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/CullAreaEditor.cs @@ -0,0 +1,252 @@ +using UnityEditor; +using UnityEngine; + +[CanEditMultipleObjects] +[CustomEditor(typeof(CullArea))] +public class CullAreaEditor : Editor +{ + private bool alignEditorCamera, showHelpEntries; + + private CullArea cullArea; + + private enum UP_AXIS_OPTIONS + { + SideScrollerMode = 0, + TopDownOr3DMode = 1 + } + + private UP_AXIS_OPTIONS upAxisOptions; + + public void OnEnable() + { + cullArea = (CullArea) target; + + // Destroying the newly created cull area if there is already one existing + if (FindObjectsOfType().Length > 1) + { + Debug.LogWarning("Destroying newly created cull area because there is already one existing in the scene."); + + DestroyImmediate(cullArea); + + return; + } + + // Prevents the dropdown from resetting + if (cullArea != null) + { + upAxisOptions = cullArea.YIsUpAxis ? UP_AXIS_OPTIONS.SideScrollerMode : UP_AXIS_OPTIONS.TopDownOr3DMode; + } + } + + public override void OnInspectorGUI() + { + EditorGUILayout.BeginVertical(); + + if (Application.isEditor && !Application.isPlaying) + { + OnInspectorGUIEditMode(); + } + else + { + OnInspectorGUIPlayMode(); + } + + EditorGUILayout.EndVertical(); + } + + /// + /// Represents the inspector GUI when edit mode is active. + /// + private void OnInspectorGUIEditMode() + { + EditorGUI.BeginChangeCheck(); + + #region DEFINE_UP_AXIS + + { + EditorGUILayout.BeginVertical(); + EditorGUILayout.LabelField("Select game type", EditorStyles.boldLabel); + upAxisOptions = (UP_AXIS_OPTIONS) EditorGUILayout.EnumPopup("Game type", upAxisOptions); + cullArea.YIsUpAxis = (upAxisOptions == UP_AXIS_OPTIONS.SideScrollerMode); + EditorGUILayout.EndVertical(); + } + + #endregion + + EditorGUILayout.Space(); + + #region SUBDIVISION + + { + EditorGUILayout.BeginVertical(); + EditorGUILayout.LabelField("Set the number of subdivisions", EditorStyles.boldLabel); + cullArea.NumberOfSubdivisions = EditorGUILayout.IntSlider("Number of subdivisions", cullArea.NumberOfSubdivisions, 0, CullArea.MAX_NUMBER_OF_SUBDIVISIONS); + EditorGUILayout.EndVertical(); + + EditorGUILayout.Space(); + + if (cullArea.NumberOfSubdivisions != 0) + { + for (int index = 0; index < cullArea.Subdivisions.Length; ++index) + { + if ((index + 1) <= cullArea.NumberOfSubdivisions) + { + string countMessage = (index + 1) + ". Subdivision: row / column count"; + + EditorGUILayout.BeginVertical(); + cullArea.Subdivisions[index] = EditorGUILayout.Vector2Field(countMessage, cullArea.Subdivisions[index]); + EditorGUILayout.EndVertical(); + + EditorGUILayout.Space(); + } + else + { + cullArea.Subdivisions[index] = new UnityEngine.Vector2(1, 1); + } + } + } + } + + #endregion + + EditorGUILayout.Space(); + + #region UPDATING_MAIN_CAMERA + + { + EditorGUILayout.BeginVertical(); + + EditorGUILayout.LabelField("View and camera options", EditorStyles.boldLabel); + alignEditorCamera = EditorGUILayout.Toggle("Automatically align editor view with grid", alignEditorCamera); + + if (Camera.main != null) + { + if (GUILayout.Button("Align main camera with grid")) + { + Undo.RecordObject(Camera.main.transform, "Align main camera with grid."); + + float yCoord = cullArea.YIsUpAxis ? cullArea.Center.y : Mathf.Max(cullArea.Size.x, cullArea.Size.y); + float zCoord = cullArea.YIsUpAxis ? -Mathf.Max(cullArea.Size.x, cullArea.Size.y) : cullArea.Center.y; + + Camera.main.transform.position = new Vector3(cullArea.Center.x, yCoord, zCoord); + Camera.main.transform.LookAt(cullArea.transform.position); + } + + EditorGUILayout.LabelField("Current main camera position is " + Camera.main.transform.position.ToString()); + } + + EditorGUILayout.EndVertical(); + } + + #endregion + + if (EditorGUI.EndChangeCheck()) + { + cullArea.RecreateCellHierarchy = true; + + AlignEditorView(); + } + + EditorGUILayout.Space(); + EditorGUILayout.Space(); + EditorGUILayout.Space(); + + showHelpEntries = EditorGUILayout.Foldout(showHelpEntries, "Need help with this component?"); + if (showHelpEntries) + { + EditorGUILayout.HelpBox("To find help you can either follow the tutorial or have a look at the forums by clicking on the buttons below.", MessageType.Info); + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Open the tutorial")) + { + Application.OpenURL("https://doc.photonengine.com/en-us/pun/current/demos-and-tutorials/package-demos/culling-demo"); + } + if (GUILayout.Button("Take me to the forums")) + { + Application.OpenURL("https://forum.photonengine.com/categories/unity-networking-plugin-pun"); + } + EditorGUILayout.EndHorizontal(); + } + } + + /// + /// Represents the inspector GUI when play mode is active. + /// + private void OnInspectorGUIPlayMode() + { + EditorGUILayout.LabelField("No changes allowed when game is running. Please exit play mode first.", EditorStyles.boldLabel); + } + + public void OnSceneGUI() + { + Handles.BeginGUI(); + GUILayout.BeginArea(new Rect(Screen.width - 110, Screen.height - 90, 100, 60)); + + if (GUILayout.Button("Reset position")) + { + cullArea.transform.position = Vector3.zero; + } + + if (GUILayout.Button("Reset scaling")) + { + cullArea.transform.localScale = new Vector3(25.0f, 25.0f, 25.0f); + } + + GUILayout.EndArea(); + Handles.EndGUI(); + + // Checking for changes of the transform + if (cullArea.transform.hasChanged) + { + // Resetting position + float posX = cullArea.transform.position.x; + float posY = cullArea.YIsUpAxis ? cullArea.transform.position.y : 0.0f; + float posZ = !cullArea.YIsUpAxis ? cullArea.transform.position.z : 0.0f; + + cullArea.transform.position = new Vector3(posX, posY, posZ); + + // Resetting scaling + if (cullArea.Size.x < 1.0f || cullArea.Size.y < 1.0f) + { + float scaleX = (cullArea.transform.localScale.x < 1.0f) ? 1.0f : cullArea.transform.localScale.x; + float scaleY = (cullArea.transform.localScale.y < 1.0f) ? 1.0f : cullArea.transform.localScale.y; + float scaleZ = (cullArea.transform.localScale.z < 1.0f) ? 1.0f : cullArea.transform.localScale.z; + + cullArea.transform.localScale = new Vector3(scaleX, scaleY, scaleZ); + + Debug.LogWarning("Scaling on a single axis can not be lower than 1. Resetting..."); + } + + cullArea.RecreateCellHierarchy = true; + + AlignEditorView(); + } + } + + /// + /// Aligns the editor view with the created grid. + /// + private void AlignEditorView() + { + if (!alignEditorCamera) + { + return; + } + + // This creates a temporary game object in order to align the editor view. + // The created game object is destroyed afterwards. + GameObject tmpGo = new GameObject(); + + float yCoord = cullArea.YIsUpAxis ? cullArea.Center.y : Mathf.Max(cullArea.Size.x, cullArea.Size.y); + float zCoord = cullArea.YIsUpAxis ? -Mathf.Max(cullArea.Size.x, cullArea.Size.y) : cullArea.Center.y; + + tmpGo.transform.position = new Vector3(cullArea.Center.x, yCoord, zCoord); + tmpGo.transform.LookAt(cullArea.transform.position); + + if (SceneView.lastActiveSceneView != null) + { + SceneView.lastActiveSceneView.AlignViewToObject(tmpGo.transform); + } + + DestroyImmediate(tmpGo); + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/CullAreaEditor.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/CullAreaEditor.cs.meta new file mode 100644 index 0000000..7d72143 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/CullAreaEditor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: abadaa451a7bff0489078ed9eec61133 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Newtonsoft.Json.dll b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Newtonsoft.Json.dll new file mode 100644 index 0000000..664b5b5 Binary files /dev/null and b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Newtonsoft.Json.dll differ diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Newtonsoft.Json.dll.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Newtonsoft.Json.dll.meta new file mode 100644 index 0000000..735d8de --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Newtonsoft.Json.dll.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0268f98d7c649564a818b0768fc68d4b +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoAssemblyImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonConverter.cs b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonConverter.cs new file mode 100644 index 0000000..9e16815 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonConverter.cs @@ -0,0 +1,68 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2011 Exit Games GmbH +// +// +// Script to convert old RPC attributes into new RPC attributes. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +#if UNITY_5 && !UNITY_5_0 && !UNITY_5_1 && !UNITY_5_2 || UNITY_5_4_OR_NEWER +#define UNITY_MIN_5_3 +#endif + + +using UnityEngine; +using System.Collections.Generic; +using System.IO; + +public class PhotonConverter : Photon.MonoBehaviour +{ + public static List GetScriptsInFolder(string folder) + { + List scripts = new List(); + + try + { + scripts.AddRange(Directory.GetFiles(folder, "*.cs", SearchOption.AllDirectories)); + scripts.AddRange(Directory.GetFiles(folder, "*.js", SearchOption.AllDirectories)); + scripts.AddRange(Directory.GetFiles(folder, "*.boo", SearchOption.AllDirectories)); + } + catch (System.Exception ex) + { + Debug.Log("Getting script list from folder " + folder + " failed. Exception:\n" + ex.ToString()); + } + + return scripts; + } + + /// default path: "Assets" + public static void ConvertRpcAttribute(string path) + { + if (string.IsNullOrEmpty(path)) + { + path = "Assets"; + } + + List scripts = GetScriptsInFolder(path); + foreach (string file in scripts) + { + string text = File.ReadAllText(file); + string textCopy = text; + if (file.EndsWith("PhotonConverter.cs")) + { + continue; + } + + text = text.Replace("[RPC]", "[PunRPC]"); + text = text.Replace("@RPC", "@PunRPC"); + + if (!text.Equals(textCopy)) + { + File.WriteAllText(file, text); + Debug.Log("Converted RPC to PunRPC in: " + file); + } + } + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonConverter.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonConverter.cs.meta new file mode 100644 index 0000000..615c386 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonConverter.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 15757b26cd9b53247be86da9e8da19dd +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonEditor.cs b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonEditor.cs new file mode 100644 index 0000000..e1609ca --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonEditor.cs @@ -0,0 +1,773 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2011 Exit Games GmbH +// +// +// MenuItems and in-Editor scripts for PhotonNetwork. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using ExitGames.Client.Photon; +using UnityEditor; +using UnityEditorInternal; +using UnityEngine; + + +public class PunWizardText +{ + public string WindowTitle = "PUN Wizard"; + public string SetupWizardWarningTitle = "Warning"; + public string SetupWizardWarningMessage = "You have not yet run the Photon setup wizard! Your game won't be able to connect. See Windows -> Photon Unity Networking."; + public string MainMenuButton = "Main Menu"; + public string SetupWizardTitle = "PUN Setup"; + public string SetupWizardInfo = "Thanks for importing Photon Unity Networking.\nThis window should set you up.\n\n- To use an existing Photon Cloud App, enter your AppId.\n- To register an account or access an existing one, enter the account's mail address.\n- To use Photon OnPremise, skip this step."; + public string EmailOrAppIdLabel = "AppId or Email"; + public string AlreadyRegisteredInfo = "The email is registered so we can't fetch your AppId (without password).\n\nPlease login online to get your AppId and paste it above."; + public string SkipRegistrationInfo = "Skipping? No problem:\nEdit your server settings in the PhotonServerSettings file."; + public string RegisteredNewAccountInfo = "We created a (free) account and fetched you an AppId.\nWelcome. Your PUN project is setup."; + public string AppliedToSettingsInfo = "Your AppId is now applied to this project."; + public string SetupCompleteInfo = "Done!\nAll connection settings can be edited in the PhotonServerSettings now.\nHave a look."; + public string CloseWindowButton = "Close"; + public string SkipButton = "Skip"; + public string SetupButton = "Setup Project"; + public string MobileExportNoteLabel = "Build for mobiles impossible. Get PUN+ or Unity 4 Pro for mobile or use Unity 5 or newer."; + public string MobilePunPlusExportNoteLabel = "PUN+ available. Using native sockets for iOS/Android."; + public string CancelButton = "Cancel"; + public string PUNWizardLabel = "PUN Wizard"; + public string SettingsButton = "Settings"; + public string SetupServerCloudLabel = "Setup wizard for setting up your own server or the cloud."; + public string WarningPhotonDisconnect = ""; + public string StartButton = "Start"; + public string LocateSettingsButton = "Locate PhotonServerSettings"; + public string SettingsHighlightLabel = "Highlights the used photon settings file in the project."; + public string DocumentationLabel = "Documentation"; + public string OpenPDFText = "Reference PDF"; + public string OpenPDFTooltip = "Opens the local documentation pdf."; + public string OpenDevNetText = "DevNet / Manual"; + public string OpenDevNetTooltip = "Online documentation for Photon."; + public string OpenCloudDashboardText = "Cloud Dashboard Login"; + public string OpenCloudDashboardTooltip = "Review Cloud App information and statistics."; + public string OpenForumText = "Open Forum"; + public string OpenForumTooltip = "Online support for Photon."; + public string OkButton = "Ok"; + public string OwnHostCloudCompareLabel = "I am not quite sure how 'my own host' compares to 'cloud'."; + public string ComparisonPageButton = "Cloud versus OnPremise"; + public string ConnectionTitle = "Connecting"; + public string ConnectionInfo = "Connecting to the account service..."; + public string ErrorTextTitle = "Error"; + public string IncorrectRPCListTitle = "Warning: RPC-list becoming incompatible!"; + public string IncorrectRPCListLabel = "Your project's RPC-list is full, so we can't add some RPCs just compiled.\n\nBy removing outdated RPCs, the list will be long enough but incompatible with older client builds!\n\nMake sure you change the game version where you use PhotonNetwork.ConnectUsingSettings()."; + public string RemoveOutdatedRPCsLabel = "Remove outdated RPCs"; + public string FullRPCListTitle = "Warning: RPC-list is full!"; + public string FullRPCListLabel = "Your project's RPC-list is too long for PUN.\n\nYou can change PUN's source to use short-typed RPC index. Look for comments 'LIMITS RPC COUNT'\n\nAlternatively, remove some RPC methods (use more parameters per RPC maybe).\n\nAfter a RPC-list refresh, make sure you change the game version where you use PhotonNetwork.ConnectUsingSettings()."; + public string SkipRPCListUpdateLabel = "Skip RPC-list update"; + public string PUNNameReplaceTitle = "Warning: RPC-list Compatibility"; + public string PUNNameReplaceLabel = "PUN replaces RPC names with numbers by using the RPC-list. All clients must use the same list for that.\n\nClearing it most likely makes your client incompatible with previous versions! Change your game version or make sure the RPC-list matches other clients."; + public string RPCListCleared = "Clear RPC-list"; + public string ServerSettingsCleanedWarning = "Cleared the PhotonServerSettings.RpcList! This makes new builds incompatible with older ones. Better change game version in PhotonNetwork.ConnectUsingSettings()."; + public string RpcFoundMessage = "Some code uses the obsolete RPC attribute. PUN now requires the PunRPC attribute to mark remote-callable methods.\nThe Editor can search and replace that code which will modify your source."; + public string RpcFoundDialogTitle = "RPC Attribute Outdated"; + public string RpcReplaceButton = "Replace. I got a backup."; + public string RpcSkipReplace = "Not now."; + public string WizardMainWindowInfo = "This window should help you find important settings for PUN, as well as documentation."; +} + + +[InitializeOnLoad] +public class PhotonEditor : EditorWindow +{ + protected static Type WindowType = typeof (PhotonEditor); + + protected Vector2 scrollPos = Vector2.zero; + + private readonly Vector2 preferredSize = new Vector2(350, 400); + + private static Texture2D BackgroundImage; + + public static PunWizardText CurrentLang = new PunWizardText(); + + + protected static AccountService.Origin RegisterOrigin = AccountService.Origin.Pun; + + protected static string DocumentationLocation = "Assets/Photon Unity Networking/PhotonNetwork-Documentation.pdf"; + + protected static string UrlFreeLicense = "https://www.photonengine.com/en-us/onpremise/dashboard"; + + protected static string UrlDevNet = "https://doc.photonengine.com/en-us/pun/current"; + + protected static string UrlForum = "https://forum.photonengine.com"; + + protected static string UrlCompare = "https://doc.photonengine.com/en-us/realtime/current/getting-started/onpremise-or-saas"; + + protected static string UrlHowToSetup = "https://doc.photonengine.com/en-us/onpremise/current/getting-started/photon-server-in-5min"; + + protected static string UrlAppIDExplained = "https://doc.photonengine.com/en-us/realtime/current/getting-started/obtain-your-app-id"; + + protected static string UrlAccountPage = "https://www.photonengine.com/Account/SignIn?email="; // opened in browser + + protected static string UrlCloudDashboard = "https://www.photonengine.com/dashboard?email="; + + + private enum PhotonSetupStates + { + MainUi, + + RegisterForPhotonCloud, + + EmailAlreadyRegistered, + + GoEditPhotonServerSettings + } + + private bool isSetupWizard = false; + + private PhotonSetupStates photonSetupState = PhotonSetupStates.RegisterForPhotonCloud; + + + private bool minimumInput = false; + private bool useMail = false; + private bool useAppId = false; + private bool useSkip = false; + private bool highlightedSettings = false; + private bool close = false; + private string mailOrAppId = string.Empty; + + + private static double lastWarning = 0; + private static bool postCompileActionsDone; + + private static bool isPunPlus; + private static bool androidLibExists; + private static bool iphoneLibExists; + + + // setup once on load + static PhotonEditor() + { + #if UNITY_2017_2_OR_NEWER + EditorApplication.playModeStateChanged += PlaymodeStateChanged; + #else + EditorApplication.playmodeStateChanged += PlaymodeStateChanged; + #endif + + #if UNITY_2018 + EditorApplication.projectChanged += EditorUpdate; + EditorApplication.hierarchyChanged += EditorUpdate; + #else + EditorApplication.projectWindowChanged += EditorUpdate; + EditorApplication.hierarchyWindowChanged += EditorUpdate; + #endif + EditorApplication.update += OnUpdate; + + // detect optional packages + PhotonEditor.CheckPunPlus(); + } + + // setup per window + public PhotonEditor() + { + minSize = this.preferredSize; + } + + [MenuItem("Window/Photon Unity Networking/PUN Wizard &p", false, 0)] + protected static void MenuItemOpenWizard() + { + PhotonEditor win = GetWindow(WindowType, false, CurrentLang.WindowTitle, true) as PhotonEditor; + win.photonSetupState = PhotonSetupStates.MainUi; + win.isSetupWizard = false; + } + + [MenuItem("Window/Photon Unity Networking/Highlight Server Settings %#&p", false, 1)] + protected static void MenuItemHighlightSettings() + { + HighlightSettings(); + } + + /// Creates an Editor window, showing the cloud-registration wizard for Photon (entry point to setup PUN). + protected static void ShowRegistrationWizard() + { + PhotonEditor win = GetWindow(WindowType, false, CurrentLang.WindowTitle, true) as PhotonEditor; + win.photonSetupState = PhotonSetupStates.RegisterForPhotonCloud; + win.isSetupWizard = true; + } + + + // called 100 times / sec + private static void OnUpdate() + { + // after a compile, check RPCs to create a cache-list + if (!postCompileActionsDone && !EditorApplication.isCompiling && !EditorApplication.isPlayingOrWillChangePlaymode && PhotonNetwork.PhotonServerSettings != null) + { + #if UNITY_4_2 || UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5 || UNITY_5_0 || UNITY_5_3_AND_NEWER + if (EditorApplication.isUpdating) + { + return; + } + #endif + + PhotonEditor.UpdateRpcList(); + postCompileActionsDone = true; // on compile, this falls back to false (without actively doing anything) + + #if UNITY_4_2 || UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5 || UNITY_5_0 || UNITY_5_3_AND_NEWER + PhotonEditor.ImportWin8Support(); + #endif + } + } + + + // called in editor, opens wizard for initial setup, keeps scene PhotonViews up to date and closes connections when compiling (to avoid issues) + private static void EditorUpdate() + { + if (PhotonNetwork.PhotonServerSettings == null) + { + PhotonNetwork.CreateSettings(); + } + if (PhotonNetwork.PhotonServerSettings == null) + { + return; + } + + // serverSetting is null when the file gets deleted. otherwise, the wizard should only run once and only if hosting option is not (yet) set + if (!PhotonNetwork.PhotonServerSettings.DisableAutoOpenWizard && PhotonNetwork.PhotonServerSettings.HostType == ServerSettings.HostingOption.NotSet) + { + ShowRegistrationWizard(); + PhotonNetwork.PhotonServerSettings.DisableAutoOpenWizard = true; + PhotonEditor.SaveSettings(); + } + + // Workaround for TCP crash. Plus this surpresses any other recompile errors. + if (EditorApplication.isCompiling) + { + if (PhotonNetwork.connected) + { + if (lastWarning > EditorApplication.timeSinceStartup - 3) + { + // Prevent error spam + Debug.LogWarning(CurrentLang.WarningPhotonDisconnect); + lastWarning = EditorApplication.timeSinceStartup; + } + + PhotonNetwork.Disconnect(); + } + } + } + + + // called in editor on change of play-mode (used to show a message popup that connection settings are incomplete) + #if UNITY_2017_2_OR_NEWER + private static void PlaymodeStateChanged(PlayModeStateChange state) + #else + private static void PlaymodeStateChanged() + #endif + { + if (EditorApplication.isPlaying || !EditorApplication.isPlayingOrWillChangePlaymode) + { + return; + } + + if (PhotonNetwork.PhotonServerSettings.HostType == ServerSettings.HostingOption.NotSet) + { + EditorUtility.DisplayDialog(CurrentLang.SetupWizardWarningTitle, CurrentLang.SetupWizardWarningMessage, CurrentLang.OkButton); + } + } + + + #region GUI and Wizard + + // Window Update() callback. On-demand, when Window is open + protected void Update() + { + if (this.close) + { + Close(); + } + } + + protected virtual void OnGUI() + { + if (BackgroundImage == null) + { + BackgroundImage = AssetDatabase.LoadAssetAtPath("Assets/Photon Unity Networking/Editor/PhotonNetwork/background.jpg", typeof(Texture2D)) as Texture2D; + } + + PhotonSetupStates oldGuiState = this.photonSetupState; // used to fix an annoying Editor input field issue: wont refresh until focus is changed. + + GUI.SetNextControlName(""); + this.scrollPos = GUILayout.BeginScrollView(this.scrollPos); + + + if (this.photonSetupState == PhotonSetupStates.MainUi) + { + UiMainWizard(); + } + else + { + UiSetupApp(); + } + + + GUILayout.EndScrollView(); + + if (oldGuiState != this.photonSetupState) + { + GUI.FocusControl(""); + } + } + + + protected virtual void UiSetupApp() + { + GUI.skin.label.wordWrap = true; + if (!this.isSetupWizard) + { + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if (GUILayout.Button(CurrentLang.MainMenuButton, GUILayout.ExpandWidth(false))) + { + this.photonSetupState = PhotonSetupStates.MainUi; + } + + GUILayout.EndHorizontal(); + } + + + // setup header + UiTitleBox(CurrentLang.SetupWizardTitle, BackgroundImage); + + // setup info text + GUI.skin.label.richText = true; + GUILayout.Label(CurrentLang.SetupWizardInfo); + + // input of appid or mail + EditorGUILayout.Separator(); + GUILayout.Label(CurrentLang.EmailOrAppIdLabel); + this.mailOrAppId = EditorGUILayout.TextField(this.mailOrAppId).Trim(); // note: we trim all input + + if (this.mailOrAppId.Contains("@")) + { + // this should be a mail address + this.minimumInput = (this.mailOrAppId.Length >= 5 && this.mailOrAppId.Contains(".")); + this.useMail = this.minimumInput; + this.useAppId = false; + } + else + { + // this should be an appId + this.minimumInput = ServerSettings.IsAppId(this.mailOrAppId); + this.useMail = false; + this.useAppId = this.minimumInput; + } + + // button to skip setup + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if (GUILayout.Button(CurrentLang.SkipButton, GUILayout.Width(100))) + { + this.photonSetupState = PhotonSetupStates.GoEditPhotonServerSettings; + this.useSkip = true; + this.useMail = false; + this.useAppId = false; + } + + // SETUP button + EditorGUI.BeginDisabledGroup(!this.minimumInput); + if (GUILayout.Button(CurrentLang.SetupButton, GUILayout.Width(100))) + { + this.useSkip = false; + GUIUtility.keyboardControl = 0; + if (this.useMail) + { + RegisterWithEmail(this.mailOrAppId); // sets state + } + if (this.useAppId) + { + this.photonSetupState = PhotonSetupStates.GoEditPhotonServerSettings; + Undo.RecordObject(PhotonNetwork.PhotonServerSettings, "Update PhotonServerSettings for PUN"); + PhotonNetwork.PhotonServerSettings.UseCloud(this.mailOrAppId); + PhotonEditor.SaveSettings(); + } + } + EditorGUI.EndDisabledGroup(); + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + + + // existing account needs to fetch AppId online + if (this.photonSetupState == PhotonSetupStates.EmailAlreadyRegistered) + { + // button to open dashboard and get the AppId + GUILayout.Space(15); + GUILayout.Label(CurrentLang.AlreadyRegisteredInfo); + + + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if (GUILayout.Button(new GUIContent(CurrentLang.OpenCloudDashboardText, CurrentLang.OpenCloudDashboardTooltip), GUILayout.Width(205))) + { + Application.OpenURL(UrlCloudDashboard + Uri.EscapeUriString(this.mailOrAppId)); + this.mailOrAppId = ""; + } + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + } + + + if (this.photonSetupState == PhotonSetupStates.GoEditPhotonServerSettings) + { + if (!this.highlightedSettings) + { + this.highlightedSettings = true; + HighlightSettings(); + } + + GUILayout.Space(15); + if (this.useSkip) + { + GUILayout.Label(CurrentLang.SkipRegistrationInfo); + } + else if (this.useMail) + { + GUILayout.Label(CurrentLang.RegisteredNewAccountInfo); + } + else if (this.useAppId) + { + GUILayout.Label(CurrentLang.AppliedToSettingsInfo); + } + + + // setup-complete info + GUILayout.Space(15); + GUILayout.Label(CurrentLang.SetupCompleteInfo); + + + // close window (done) + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if (GUILayout.Button(CurrentLang.CloseWindowButton, GUILayout.Width(205))) + { + this.close = true; + } + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + } + GUI.skin.label.richText = false; + } + + private void UiTitleBox(string title, Texture2D bgIcon) + { + GUIStyle bgStyle = new GUIStyle(GUI.skin.GetStyle("Label")); + bgStyle.normal.background = bgIcon; + bgStyle.fontSize = 22; + bgStyle.fontStyle = FontStyle.Bold; + + EditorGUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + EditorGUILayout.EndHorizontal(); + Rect scale = GUILayoutUtility.GetLastRect(); + scale.height = 30; + + GUI.Label(scale, title, bgStyle); + GUILayout.Space(scale.height+5); + } + + protected virtual void UiMainWizard() + { + GUILayout.Space(15); + + // title + UiTitleBox(CurrentLang.PUNWizardLabel, BackgroundImage); + + // wizard info text + GUILayout.Label(CurrentLang.WizardMainWindowInfo); + GUILayout.Space(15); + + + // pun+ info + if (isPunPlus) + { + GUILayout.Label(CurrentLang.MobilePunPlusExportNoteLabel); + GUILayout.Space(15); + } +#if !(UNITY_5_0 || UNITY_5 || UNITY_5_3_AND_NEWER) + else if (!InternalEditorUtility.HasAdvancedLicenseOnBuildTarget(BuildTarget.Android) || !InternalEditorUtility.HasAdvancedLicenseOnBuildTarget(BuildTarget.iOS)) + { + GUILayout.Label(CurrentLang.MobileExportNoteLabel); + GUILayout.Space(15); + } +#endif + + // settings button + GUILayout.BeginHorizontal(); + GUILayout.Label(CurrentLang.SettingsButton, EditorStyles.boldLabel, GUILayout.Width(100)); + GUILayout.BeginVertical(); + if (GUILayout.Button(new GUIContent(CurrentLang.LocateSettingsButton, CurrentLang.SettingsHighlightLabel))) + { + HighlightSettings(); + } + if (GUILayout.Button(new GUIContent(CurrentLang.OpenCloudDashboardText, CurrentLang.OpenCloudDashboardTooltip))) + { + Application.OpenURL(UrlCloudDashboard + Uri.EscapeUriString(this.mailOrAppId)); + } + if (GUILayout.Button(new GUIContent(CurrentLang.SetupButton, CurrentLang.SetupServerCloudLabel))) + { + this.photonSetupState = PhotonSetupStates.RegisterForPhotonCloud; + } + GUILayout.EndVertical(); + GUILayout.EndHorizontal(); + GUILayout.Space(15); + + + EditorGUILayout.Separator(); + + + // documentation + GUILayout.BeginHorizontal(); + GUILayout.Label(CurrentLang.DocumentationLabel, EditorStyles.boldLabel, GUILayout.Width(100)); + GUILayout.BeginVertical(); + if (GUILayout.Button(new GUIContent(CurrentLang.OpenPDFText, CurrentLang.OpenPDFTooltip))) + { + EditorUtility.OpenWithDefaultApp(DocumentationLocation); + } + + if (GUILayout.Button(new GUIContent(CurrentLang.OpenDevNetText, CurrentLang.OpenDevNetTooltip))) + { + Application.OpenURL(UrlDevNet); + } + + GUI.skin.label.wordWrap = true; + GUILayout.Label(CurrentLang.OwnHostCloudCompareLabel); + if (GUILayout.Button(CurrentLang.ComparisonPageButton)) + { + Application.OpenURL(UrlCompare); + } + + + if (GUILayout.Button(new GUIContent(CurrentLang.OpenForumText, CurrentLang.OpenForumTooltip))) + { + Application.OpenURL(UrlForum); + } + + GUILayout.EndVertical(); + GUILayout.EndHorizontal(); + } + + #endregion + + + protected virtual void RegisterWithEmail(string email) + { + EditorUtility.DisplayProgressBar(CurrentLang.ConnectionTitle, CurrentLang.ConnectionInfo, 0.5f); + + string accountServiceType = string.Empty; + if (PhotonEditorUtils.HasVoice) + { + accountServiceType = "voice"; + } + + + AccountService client = new AccountService(); + client.RegisterByEmail(email, RegisterOrigin, accountServiceType); // this is the synchronous variant using the static RegisterOrigin. "result" is in the client + + EditorUtility.ClearProgressBar(); + if (client.ReturnCode == 0) + { + this.mailOrAppId = client.AppId; + PhotonNetwork.PhotonServerSettings.UseCloud(this.mailOrAppId, 0); + if (PhotonEditorUtils.HasVoice) + { + PhotonNetwork.PhotonServerSettings.VoiceAppID = client.AppId2; + } + PhotonEditor.SaveSettings(); + + this.photonSetupState = PhotonSetupStates.GoEditPhotonServerSettings; + } + else + { + PhotonNetwork.PhotonServerSettings.HostType = ServerSettings.HostingOption.PhotonCloud; + PhotonEditor.SaveSettings(); + + Debug.LogWarning(client.Message + " ReturnCode: " + client.ReturnCode); + if (client.Message.Contains("registered")) + { + this.photonSetupState = PhotonSetupStates.EmailAlreadyRegistered; + } + else + { + EditorUtility.DisplayDialog(CurrentLang.ErrorTextTitle, client.Message, CurrentLang.OkButton); + this.photonSetupState = PhotonSetupStates.RegisterForPhotonCloud; + } + } + } + + + protected internal static bool CheckPunPlus() + { + androidLibExists = File.Exists("Assets/Plugins/Android/armeabi-v7a/libPhotonSocketPlugin.so") && + File.Exists("Assets/Plugins/Android/x86/libPhotonSocketPlugin.so"); + + + iphoneLibExists = File.Exists("Assets/Plugins/IOS/libPhotonSocketPlugin.a"); + + isPunPlus = androidLibExists || iphoneLibExists; + return isPunPlus; + } + + + private static void ImportWin8Support() + { + if (EditorApplication.isCompiling || EditorApplication.isPlayingOrWillChangePlaymode) + { + return; // don't import while compiling + } + + #if UNITY_4_2 || UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5 || UNITY_5_0 || UNITY_5_3_AND_NEWER + const string win8Package = "Assets/Plugins/Photon3Unity3D-Win8.unitypackage"; + + bool win8LibsExist = File.Exists("Assets/Plugins/WP8/Photon3Unity3D.dll") && File.Exists("Assets/Plugins/Metro/Photon3Unity3D.dll"); + if (!win8LibsExist && File.Exists(win8Package)) + { + AssetDatabase.ImportPackage(win8Package, false); + } + #endif + } + + + // Pings PhotonServerSettings and makes it selected (show in Inspector) + private static void HighlightSettings() + { + Selection.objects = new UnityEngine.Object[] { PhotonNetwork.PhotonServerSettings }; + EditorGUIUtility.PingObject(PhotonNetwork.PhotonServerSettings); + } + + + // Marks settings object as dirty, so it gets saved. + // unity 5.3 changes the usecase for SetDirty(). but here we don't modify a scene object! so it's ok to use + private static void SaveSettings() + { + EditorUtility.SetDirty(PhotonNetwork.PhotonServerSettings); + } + + + #region RPC List Handling + + public static void UpdateRpcList() + { + List additionalRpcs = new List(); + HashSet currentRpcs = new HashSet(); + + var types = GetAllSubTypesInScripts(typeof(MonoBehaviour)); + + int countOldRpcs = 0; + foreach (var mono in types) + { + MethodInfo[] methods = mono.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + + foreach (MethodInfo method in methods) + { + bool isOldRpc = false; + #pragma warning disable 618 + // we let the Editor check for outdated RPC attributes in code. that should not cause a compile warning + if (method.IsDefined(typeof (RPC), false)) + { + countOldRpcs++; + isOldRpc = true; + } + #pragma warning restore 618 + + if (isOldRpc || method.IsDefined(typeof(PunRPC), false)) + { + currentRpcs.Add(method.Name); + + if (!additionalRpcs.Contains(method.Name) && !PhotonNetwork.PhotonServerSettings.RpcList.Contains(method.Name)) + { + additionalRpcs.Add(method.Name); + } + } + } + } + + if (additionalRpcs.Count > 0) + { + // LIMITS RPC COUNT + if (additionalRpcs.Count + PhotonNetwork.PhotonServerSettings.RpcList.Count >= byte.MaxValue) + { + if (currentRpcs.Count <= byte.MaxValue) + { + bool clearList = EditorUtility.DisplayDialog(CurrentLang.IncorrectRPCListTitle, CurrentLang.IncorrectRPCListLabel, CurrentLang.RemoveOutdatedRPCsLabel, CurrentLang.CancelButton); + if (clearList) + { + PhotonNetwork.PhotonServerSettings.RpcList.Clear(); + PhotonNetwork.PhotonServerSettings.RpcList.AddRange(currentRpcs); + } + else + { + return; + } + } + else + { + EditorUtility.DisplayDialog(CurrentLang.FullRPCListTitle, CurrentLang.FullRPCListLabel, CurrentLang.SkipRPCListUpdateLabel); + return; + } + } + + additionalRpcs.Sort(); + Undo.RecordObject(PhotonNetwork.PhotonServerSettings, "Update PUN RPC-list"); + PhotonNetwork.PhotonServerSettings.RpcList.AddRange(additionalRpcs); + PhotonEditor.SaveSettings(); + } + + if (countOldRpcs > 0) + { + bool convertRPCs = EditorUtility.DisplayDialog(CurrentLang.RpcFoundDialogTitle, CurrentLang.RpcFoundMessage, CurrentLang.RpcReplaceButton, CurrentLang.RpcSkipReplace); + if (convertRPCs) + { + PhotonConverter.ConvertRpcAttribute(""); + } + } + } + + public static void ClearRpcList() + { + bool clearList = EditorUtility.DisplayDialog(CurrentLang.PUNNameReplaceTitle, CurrentLang.PUNNameReplaceLabel, CurrentLang.RPCListCleared, CurrentLang.CancelButton); + if (clearList) + { + PhotonNetwork.PhotonServerSettings.RpcList.Clear(); + Debug.LogWarning(CurrentLang.ServerSettingsCleanedWarning); + } + } + + public static System.Type[] GetAllSubTypesInScripts(System.Type aBaseClass) + { + var result = new System.Collections.Generic.List(); + System.Reflection.Assembly[] AS = System.AppDomain.CurrentDomain.GetAssemblies(); + foreach (var A in AS) + { + // this skips all but the Unity-scripted assemblies for RPC-list creation. You could remove this to search all assemblies in project + if (!A.FullName.StartsWith("Assembly-")) + { + // Debug.Log("Skipping Assembly: " + A); + continue; + } + + //Debug.Log("Assembly: " + A.FullName); + System.Type[] types = A.GetTypes(); + foreach (var T in types) + { + if (T.IsSubclassOf(aBaseClass)) + { + result.Add(T); + } + } + } + return result.ToArray(); + } + + #endregion + +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonEditor.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonEditor.cs.meta new file mode 100644 index 0000000..beda65a --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: dabbbed2a74eac44dac281f20d706ba8 +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonEditorUtils.cs b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonEditorUtils.cs new file mode 100644 index 0000000..c05d9ce --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonEditorUtils.cs @@ -0,0 +1,99 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2011 Exit Games GmbH +// +// +// Unity Editor Utils +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Linq; +using System.IO; +using UnityEditor; + + +namespace ExitGames.Client.Photon +{ + [InitializeOnLoad] + public class PhotonEditorUtils + { + /// True if the ChatClient of the Photon Chat API is available. If so, the editor may (e.g.) show additional options in settings. + public static bool HasChat; + /// True if the VoiceClient of the Photon Voice API is available. If so, the editor may (e.g.) show additional options in settings. + public static bool HasVoice; + /// True if the PhotonEditorUtils checked the available products / APIs. If so, the editor may (e.g.) show additional options in settings. + public static bool HasCheckedProducts; + + static PhotonEditorUtils() + { + HasVoice = Type.GetType("ExitGames.Client.Photon.Voice.VoiceClient, Assembly-CSharp") != null || Type.GetType("ExitGames.Client.Photon.Voice.VoiceClient, Assembly-CSharp-firstpass") != null; + HasChat = Type.GetType("ExitGames.Client.Photon.Chat.ChatClient, Assembly-CSharp") != null || Type.GetType("ExitGames.Client.Photon.Chat.ChatClient, Assembly-CSharp-firstpass") != null; + PhotonEditorUtils.HasCheckedProducts = true; + } + + + public static void MountScriptingDefineSymbolToAllTargets(string defineSymbol) + { + foreach (BuildTargetGroup _group in Enum.GetValues(typeof(BuildTargetGroup))) + { + if (_group == BuildTargetGroup.Unknown) continue; + + List _defineSymbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(_group).Split(';').Select(d => d.Trim()).ToList(); + + if (!_defineSymbols.Contains(defineSymbol)) + { + _defineSymbols.Add(defineSymbol); + PlayerSettings.SetScriptingDefineSymbolsForGroup(_group, string.Join(";", _defineSymbols.ToArray())); + } + } + } + + public static void UnMountScriptingDefineSymbolToAllTargets(string defineSymbol) + { + foreach (BuildTargetGroup _group in Enum.GetValues(typeof(BuildTargetGroup))) + { + if (_group == BuildTargetGroup.Unknown) continue; + + List _defineSymbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(_group).Split(';').Select(d => d.Trim()).ToList(); + + if (_defineSymbols.Contains(defineSymbol)) + { + _defineSymbols.Remove(defineSymbol); + PlayerSettings.SetScriptingDefineSymbolsForGroup(_group, string.Join(";", _defineSymbols.ToArray())); + } + } + } + + + /// + /// Gets the parent directory of a path. Recursive Function, will return null if parentName not found + /// + /// The parent directory + /// Path. + /// Parent name. + public static string GetParent(string path, string parentName) + { + var dir = new DirectoryInfo(path); + + if (dir.Parent == null) + { + return null; + } + + if (string.IsNullOrEmpty(parentName)) + { + return dir.Parent.FullName; + } + + if (dir.Parent.Name == parentName) + { + return dir.Parent.FullName; + } + + return GetParent(dir.Parent.FullName, parentName); + } + } +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonEditorUtils.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonEditorUtils.cs.meta new file mode 100644 index 0000000..0f4cd26 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonEditorUtils.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 42183086715e14a19a573546af09b321 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonGUI.cs b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonGUI.cs new file mode 100644 index 0000000..e236915 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonGUI.cs @@ -0,0 +1,281 @@ +using UnityEngine; +using UnityEditor; +using System.Collections; + +using Photon.Pun; + +public class PhotonGUI +{ + #region Styles + static GUIStyle m_DefaultTitleStyle; + public static GUIStyle DefaultTitleStyle + { + get + { + if( m_DefaultTitleStyle == null ) + { + m_DefaultTitleStyle = new GUIStyle(); + m_DefaultTitleStyle.border = new RectOffset( 2, 2, 2, 1 ); + m_DefaultTitleStyle.margin = new RectOffset( 5, 5, 5, 0 ); + m_DefaultTitleStyle.padding = new RectOffset( 5, 5, 0, 0 ); + m_DefaultTitleStyle.alignment = TextAnchor.MiddleLeft; + m_DefaultTitleStyle.normal.background = ReorderableListResources.texTitleBackground; + m_DefaultTitleStyle.normal.textColor = EditorGUIUtility.isProSkin + ? new Color( 0.8f, 0.8f, 0.8f ) + : new Color( 0.2f, 0.2f, 0.2f ); + } + + return m_DefaultTitleStyle; + } + } + + static GUIStyle m_DefaultContainerStyle; + public static GUIStyle DefaultContainerStyle + { + get + { + if( m_DefaultContainerStyle == null ) + { + m_DefaultContainerStyle = new GUIStyle(); + m_DefaultContainerStyle.border = new RectOffset( 2, 2, 1, 2 ); + m_DefaultContainerStyle.margin = new RectOffset( 5, 5, 5, 5 ); + m_DefaultContainerStyle.padding = new RectOffset( 1, 1, 2, 2 ); + m_DefaultContainerStyle.normal.background = ReorderableListResources.texContainerBackground; + } + + return m_DefaultContainerStyle; + } + } + + static GUIStyle m_DefaultAddButtonStyle; + public static GUIStyle DefaultAddButtonStyle + { + get + { + if( m_DefaultAddButtonStyle == null ) + { + m_DefaultAddButtonStyle = new GUIStyle(); + m_DefaultAddButtonStyle.fixedWidth = 30; + m_DefaultAddButtonStyle.fixedHeight = 16; + m_DefaultAddButtonStyle.normal.background = ReorderableListResources.texAddButton; + m_DefaultAddButtonStyle.active.background = ReorderableListResources.texAddButtonActive; + } + + return m_DefaultAddButtonStyle; + } + } + + static GUIStyle m_DefaultRemoveButtonStyle; + public static GUIStyle DefaultRemoveButtonStyle + { + get + { + if( m_DefaultRemoveButtonStyle == null ) + { + m_DefaultRemoveButtonStyle = new GUIStyle(); + m_DefaultRemoveButtonStyle.fixedWidth = 30; + m_DefaultRemoveButtonStyle.fixedHeight = 20; + m_DefaultRemoveButtonStyle.active.background = ReorderableListResources.CreatePixelTexture( "Dark Pixel (List GUI)", new Color32( 18, 18, 18, 255 ) ); + m_DefaultRemoveButtonStyle.imagePosition = ImagePosition.ImageOnly; + m_DefaultRemoveButtonStyle.alignment = TextAnchor.MiddleCenter; + } + + return m_DefaultRemoveButtonStyle; + } + } + + static GUIStyle m_DefaultContainerRowStyle; + public static GUIStyle DefaultContainerRowStyle + { + get + { + if( m_DefaultContainerRowStyle == null ) + { + m_DefaultContainerRowStyle = new GUIStyle(); + m_DefaultContainerRowStyle.border = new RectOffset( 2, 2, 2, 2 ); + + m_DefaultContainerRowStyle.margin = new RectOffset( 5, 5, 5, 5 ); + m_DefaultContainerRowStyle.padding = new RectOffset( 1, 1, 2, 2 ); + m_DefaultContainerRowStyle.normal.background = ReorderableListResources.texContainerBackground; + } + + return m_DefaultContainerRowStyle; + } + } + + static GUIStyle m_FoldoutBold; + public static GUIStyle FoldoutBold + { + get + { + if( m_FoldoutBold == null ) + { + m_FoldoutBold = new GUIStyle( EditorStyles.foldout ); + m_FoldoutBold.fontStyle = FontStyle.Bold; + } + + return m_FoldoutBold; + } + } + + static GUIStyle m_RichLabel; + public static GUIStyle RichLabel + { + get + { + if( m_RichLabel == null ) + { + m_RichLabel = new GUIStyle( GUI.skin.label ); + m_RichLabel.richText = true; + m_RichLabel.wordWrap = true; + } + + return m_RichLabel; + } + } + #endregion + + static Texture2D m_HelpIcon; + public static Texture2D HelpIcon + { + get + { + if( m_HelpIcon == null ) + { + m_HelpIcon = AssetDatabase.LoadAssetAtPath( "Assets/Photon Unity Networking/Editor/PhotonNetwork/help.png", typeof( Texture2D ) ) as Texture2D; + } + + return m_HelpIcon; + } + } + + #region Interface + public static void ContainerHeader( string headline ) + { + DoContainerHeader( headline, 27, 0 ); + } + + public static bool ContainerHeaderToggle( string headline, bool toggle ) + { + return DoContainerHeaderToggle( headline, toggle ); + } + + public static bool ContainerHeaderFoldout( string headline, bool foldout ) + { + return DoContainerHeaderFoldout( headline, foldout ); + } + + public static Rect ContainerBody( float height ) + { + return DoContainerBody( height ); + } + + public static bool AddButton() + { + Rect controlRect = EditorGUILayout.GetControlRect( false, DefaultAddButtonStyle.fixedHeight - 5 ); + controlRect.yMin -= 5; + controlRect.yMax -= 5; + + Rect addButtonRect = new Rect( controlRect.xMax - DefaultAddButtonStyle.fixedWidth, + controlRect.yMin, + DefaultAddButtonStyle.fixedWidth, + DefaultAddButtonStyle.fixedHeight ); + + return GUI.Button( addButtonRect, "", DefaultAddButtonStyle ); + } + + public static void DrawSplitter( Rect position ) + { + ReorderableListResources.DrawTexture( position, ReorderableListResources.texItemSplitter ); + } + + public static void DrawGizmoOptions( + Rect position, + string label, + SerializedProperty gizmoEnabledProperty, + SerializedProperty gizmoColorProperty, + SerializedProperty gizmoTypeProperty, + SerializedProperty gizmoSizeProperty ) + { + float height = EditorGUIUtility.singleLineHeight; + float flexibleWidth = Mathf.Max( 40, position.width - EditorGUIUtility.labelWidth - 20 - 75 - 5 - 40 - 5 ); + + Rect labelRect = new Rect( position.xMin, position.yMin, EditorGUIUtility.labelWidth, height ); + GUI.Label( labelRect, label ); + + Rect enabledRect = new Rect( labelRect.xMax, labelRect.yMin, 20, height ); + EditorGUI.PropertyField( enabledRect, gizmoEnabledProperty, GUIContent.none ); + + bool oldGUIEnabled = GUI.enabled; + GUI.enabled = gizmoEnabledProperty.boolValue; + + Rect colorRect = new Rect( enabledRect.xMax + 5, labelRect.yMin, 70, height ); + EditorGUI.PropertyField( colorRect, gizmoColorProperty, GUIContent.none ); + + Rect typeRect = new Rect( colorRect.xMax + 5, labelRect.yMin, flexibleWidth * 0.7f, height ); + EditorGUI.PropertyField( typeRect, gizmoTypeProperty, GUIContent.none ); + + Rect sizeLabelRect = new Rect( typeRect.xMax + 10, labelRect.yMin, 30, height ); + GUI.Label( sizeLabelRect, "Size" ); + + Rect sizeRect = new Rect( sizeLabelRect.xMax + 5, labelRect.yMin, flexibleWidth * 0.3f, height ); + EditorGUI.PropertyField( sizeRect, gizmoSizeProperty, GUIContent.none ); + + GUI.enabled = oldGUIEnabled; + } + + #endregion + + #region Implementation + static Rect DoContainerBody( float height ) + { + Rect controlRect = EditorGUILayout.GetControlRect( false, height ); + controlRect.yMin -= 3; + controlRect.yMax -= 2; + + int controlID = GUIUtility.GetControlID( FocusType.Passive, controlRect ); + + if( Event.current.type == EventType.Repaint ) + { + PhotonGUI.DefaultContainerStyle.Draw( controlRect, GUIContent.none, controlID ); + } + + return controlRect; + } + + static bool DoContainerHeaderToggle( string headline, bool toggle ) + { + Rect rect = DoContainerHeader( headline, 27, 15 ); + Rect toggleRect = new Rect( rect.xMin + 5, rect.yMin + 5, EditorGUIUtility.labelWidth, rect.height ); + + return EditorGUI.Toggle( toggleRect, toggle ); + } + + + static bool DoContainerHeaderFoldout( string headline, bool foldout ) + { + Rect rect = DoContainerHeader( "", 27, 0f ); + Rect foldoutRect = new Rect( rect.xMin + 15, rect.yMin + 5, rect.width, rect.height ); + + return EditorGUI.Foldout( foldoutRect, foldout, headline, FoldoutBold ); + } + + static Rect DoContainerHeader( string headline, float height, float contentOffset ) + { + GUILayout.Space( 5 ); + Rect controlRect = EditorGUILayout.GetControlRect( false, height ); + + int controlID = GUIUtility.GetControlID( FocusType.Passive, controlRect ); + + if( Event.current.type == EventType.Repaint ) + { + PhotonGUI.DefaultTitleStyle.Draw( controlRect, GUIContent.none, controlID ); + + Rect labelRect = new Rect( controlRect.xMin + 5 + contentOffset, controlRect.yMin + 5, controlRect.width, controlRect.height ); + GUI.Label( labelRect, headline, EditorStyles.boldLabel ); + } + + return controlRect; + } + #endregion +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonGUI.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonGUI.cs.meta new file mode 100644 index 0000000..247a4eb --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonGUI.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3d2cadb1ccf05074e8ce96b1393846cf +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonViewHandler.cs b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonViewHandler.cs new file mode 100644 index 0000000..a4bb887 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonViewHandler.cs @@ -0,0 +1,197 @@ +#if UNITY_5 && !UNITY_5_0 && !UNITY_5_1 && !UNITY_5_2 || UNITY_5_4_OR_NEWER +#define UNITY_MIN_5_3 +#endif + +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using UnityEditor; +using UnityEngine; +using System.Collections; +using Debug = UnityEngine.Debug; +using UnityEditor.SceneManagement; + +[InitializeOnLoad] +public class PhotonViewHandler : EditorWindow +{ + private static bool CheckSceneForStuckHandlers = true; + + static PhotonViewHandler() + { + // hierarchyWindowChanged is called on hierarchy changed and on save. It's even called when hierarchy-window is closed and if a prefab with instances is changed. + // this is not called when you edit a instance's value but: on save + #if UNITY_2018 + EditorApplication.hierarchyChanged += HierarchyChange; + #else + EditorApplication.hierarchyWindowChanged += HierarchyChange; + #endif + } + + // this method corrects the IDs for photonviews in the scene and in prefabs + // make sure prefabs always use viewID 0 + // make sure instances never use a owner + // this is a editor class that should only run if not playing + internal static void HierarchyChange() + { + if (Application.isPlaying) + { + //Debug.Log("HierarchyChange ignored, while running."); + CheckSceneForStuckHandlers = true; // done once AFTER play mode. + return; + } + + if (CheckSceneForStuckHandlers) + { + CheckSceneForStuckHandlers = false; + PhotonNetwork.InternalCleanPhotonMonoFromSceneIfStuck(); + } + + HashSet pvInstances = new HashSet(); + HashSet usedInstanceViewNumbers = new HashSet(); + bool fixedSomeId = false; + + //// the following code would be an option if we only checked scene objects (but we can check all PVs) + //PhotonView[] pvObjects = GameObject.FindSceneObjectsOfType(typeof(PhotonView)) as PhotonView[]; + //Debug.Log("HierarchyChange. PV Count: " + pvObjects.Length); + + string levelName = SceneManagerHelper.ActiveSceneName; + #if UNITY_EDITOR + levelName = SceneManagerHelper.EditorActiveSceneName; + #endif + int minViewIdInThisScene = PunSceneSettings.MinViewIdForScene(levelName); + //Debug.Log("Level '" + Application.loadedLevelName + "' has a minimum ViewId of: " + minViewIdInThisScene); + + PhotonView[] pvObjects = Resources.FindObjectsOfTypeAll(typeof(PhotonView)) as PhotonView[]; + + foreach (PhotonView view in pvObjects) + { + // first pass: fix prefabs to viewID 0 if they got a view number assigned (cause they should not have one!) + if (EditorUtility.IsPersistent(view.gameObject)) + { + if (view.viewID != 0 || view.prefixBackup != -1 || view.instantiationId != -1) + { + Debug.LogWarning("PhotonView on persistent object being fixed (id and prefix must be 0). Was: " + view); + view.viewID = 0; + view.prefixBackup = -1; + view.instantiationId = -1; + EditorUtility.SetDirty(view); // even in Unity 5.3+ it's OK to SetDirty() for non-scene objects. + fixedSomeId = true; + } + } + else + { + // keep all scene-instanced PVs for later re-check + pvInstances.Add(view); + } + } + + Dictionary idPerObject = new Dictionary(); + + // second pass: check all used-in-scene viewIDs for duplicate viewIDs (only checking anything non-prefab) + // scene-PVs must have user == 0 (scene/room) and a subId != 0 + foreach (PhotonView view in pvInstances) + { + if (view.ownerId > 0) + { + Debug.Log("Re-Setting Owner ID of: " + view); + } + view.ownerId = 0; // simply make sure no owner is set (cause room always uses 0) + view.prefix = -1; // TODO: prefix could be settable via inspector per scene?! + + if (view.viewID != 0) + { + if (view.viewID < minViewIdInThisScene || usedInstanceViewNumbers.Contains(view.viewID)) + { + view.viewID = 0; // avoid duplicates and negative values by assigning 0 as (temporary) number to be fixed in next pass + } + else + { + usedInstanceViewNumbers.Add(view.viewID); // builds a list of currently used viewIDs + + int instId = 0; + if (idPerObject.TryGetValue(view.gameObject, out instId)) + { + view.instantiationId = instId; + } + else + { + view.instantiationId = view.viewID; + idPerObject[view.gameObject] = view.instantiationId; + } + } + } + + } + + // third pass: anything that's now 0 must get a new (not yet used) ID (starting at 0) + int lastUsedId = (minViewIdInThisScene > 0) ? minViewIdInThisScene - 1 : 0; + + foreach (PhotonView view in pvInstances) + { + if (view.viewID == 0) + { + Undo.RecordObject(view, "Automatic viewID change for: "+view.gameObject.name); + + // Debug.LogWarning("setting scene ID: " + view.gameObject.name + " ID: " + view.subId.ID + " scene ID: " + view.GetSceneID() + " IsPersistent: " + EditorUtility.IsPersistent(view.gameObject) + " IsSceneViewIDFree: " + IsSceneViewIDFree(view.subId.ID, view)); + int nextViewId = PhotonViewHandler.GetID(lastUsedId, usedInstanceViewNumbers); + + view.viewID = nextViewId; + + int instId = 0; + if (idPerObject.TryGetValue(view.gameObject, out instId)) + { + view.instantiationId = instId; + } + else + { + view.instantiationId = view.viewID; + idPerObject[view.gameObject] = nextViewId; + } + + lastUsedId = nextViewId; + fixedSomeId = true; + + #if !UNITY_MIN_5_3 + EditorUtility.SetDirty(view); + #endif + } + } + + + if (fixedSomeId) + { + //Debug.LogWarning("Some subId was adjusted."); // this log is only interesting for Exit Games + } + } + + // TODO fail if no ID was available anymore + // TODO look up lower numbers if offset hits max?! + public static int GetID(int idOffset, HashSet usedInstanceViewNumbers) + { + while (idOffset < PhotonNetwork.MAX_VIEW_IDS) + { + idOffset++; + if (!usedInstanceViewNumbers.Contains(idOffset)) + { + break; + } + } + + return idOffset; + } + + //TODO: check if this can be internal protected (as source in editor AND as dll) + public static void LoadAllScenesToFix() + { + string[] scenes = System.IO.Directory.GetFiles(".", "*.unity", SearchOption.AllDirectories); + + foreach (string scene in scenes) + { + EditorSceneManager.OpenScene(scene); + PhotonViewHandler.HierarchyChange();//NOTE: most likely on load also triggers a hierarchy change + EditorSceneManager.SaveOpenScenes(); + } + + Debug.Log("Corrected scene views where needed."); + } +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonViewHandler.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonViewHandler.cs.meta new file mode 100644 index 0000000..74dfe3f --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonViewHandler.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 57b538e62a0ca6248bfd354def935e57 +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonViewInspector.cs b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonViewInspector.cs new file mode 100644 index 0000000..4c1ec90 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonViewInspector.cs @@ -0,0 +1,276 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2011 Exit Games GmbH +// +// +// Custom inspector for the PhotonView component. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +#if UNITY_5 && !UNITY_5_0 && !UNITY_5_1 && !UNITY_5_2 || UNITY_5_4_OR_NEWER +#define UNITY_MIN_5_3 +#endif + + +using System; +using UnityEditor; +using UnityEngine; + +using Photon.Pun; + + +[CustomEditor(typeof (PhotonView))] +public class PhotonViewInspector : Editor +{ + private PhotonView m_Target; + + public override void OnInspectorGUI() + { + this.m_Target = (PhotonView)target; + bool isProjectPrefab = EditorUtility.IsPersistent(this.m_Target.gameObject); + + if (this.m_Target.ObservedComponents == null) + { + this.m_Target.ObservedComponents = new System.Collections.Generic.List(); + } + + if (this.m_Target.ObservedComponents.Count == 0) + { + this.m_Target.ObservedComponents.Add(null); + } + + EditorGUILayout.BeginHorizontal(); + // Owner + if (isProjectPrefab) + { + EditorGUILayout.LabelField("Owner:", "Set at runtime"); + } + else if (!this.m_Target.isOwnerActive) + { + EditorGUILayout.LabelField("Owner", "Scene"); + } + else + { + PhotonPlayer owner = this.m_Target.owner; + string ownerInfo = (owner != null) ? owner.NickName : ""; + + if (string.IsNullOrEmpty(ownerInfo)) + { + ownerInfo = ""; + } + + EditorGUILayout.LabelField("Owner", "[" + this.m_Target.ownerId + "] " + ownerInfo); + } + + // ownership requests + EditorGUI.BeginDisabledGroup(Application.isPlaying); + OwnershipOption own = (OwnershipOption)EditorGUILayout.EnumPopup(this.m_Target.ownershipTransfer, GUILayout.Width(100)); + if (own != this.m_Target.ownershipTransfer) + { + // jf: fixed 5 and up prefab not accepting changes if you quit Unity straight after change. + // not touching the define nor the rest of the code to avoid bringing more problem than solving. + EditorUtility.SetDirty(this.m_Target); + + Undo.RecordObject(this.m_Target, "Change PhotonView Ownership Transfer"); + this.m_Target.ownershipTransfer = own; + } + EditorGUI.EndDisabledGroup(); + + EditorGUILayout.EndHorizontal(); + + + // View ID + if (isProjectPrefab) + { + EditorGUILayout.LabelField("View ID", "Set at runtime"); + } + else if (EditorApplication.isPlaying) + { + EditorGUILayout.LabelField("View ID", this.m_Target.viewID.ToString()); + } + else + { + int idValue = EditorGUILayout.IntField("View ID [1.." + (PhotonNetwork.MAX_VIEW_IDS - 1) + "]", this.m_Target.viewID); + if (this.m_Target.viewID != idValue) + { + Undo.RecordObject(this.m_Target, "Change PhotonView viewID"); + this.m_Target.viewID = idValue; + } + } + + // Locally Controlled + if (EditorApplication.isPlaying) + { + string masterClientHint = PhotonNetwork.isMasterClient ? "(master)" : ""; + EditorGUILayout.Toggle("Controlled locally: " + masterClientHint, this.m_Target.isMine); + } + + // ViewSynchronization (reliability) + if (this.m_Target.synchronization == ViewSynchronization.Off) + { + GUI.color = Color.grey; + } + + EditorGUILayout.PropertyField(serializedObject.FindProperty("synchronization"), new GUIContent("Observe option:")); + + if (this.m_Target.synchronization != ViewSynchronization.Off && this.m_Target.ObservedComponents.FindAll(item => item != null).Count == 0) + { + GUILayout.BeginVertical(GUI.skin.box); + GUILayout.Label("Warning", EditorStyles.boldLabel); + GUILayout.Label("Setting the synchronization option only makes sense if you observe something."); + GUILayout.EndVertical(); + } + + DrawSpecificTypeSerializationOptions(); + + GUI.color = Color.white; + DrawObservedComponentsList(); + + // Cleanup: save and fix look + if (GUI.changed) + { + #if !UNITY_MIN_5_3 + EditorUtility.SetDirty(this.m_Target); + #endif + PhotonViewHandler.HierarchyChange(); // TODO: check if needed + } + + GUI.color = Color.white; + #if !UNITY_MIN_5_3 + EditorGUIUtility.LookLikeControls(); + #endif + } + + private void DrawSpecificTypeSerializationOptions() + { + if (this.m_Target.ObservedComponents.FindAll(item => item != null && item.GetType() == typeof (Transform)).Count > 0) + { + this.m_Target.onSerializeTransformOption = (OnSerializeTransform)EditorGUILayout.EnumPopup("Transform Serialization:", this.m_Target.onSerializeTransformOption); + } + else if (this.m_Target.ObservedComponents.FindAll(item => item != null && item.GetType() == typeof (Rigidbody)).Count > 0 || + this.m_Target.ObservedComponents.FindAll(item => item != null && item.GetType() == typeof (Rigidbody2D)).Count > 0) + { + this.m_Target.onSerializeRigidBodyOption = (OnSerializeRigidBody)EditorGUILayout.EnumPopup("Rigidbody Serialization:", this.m_Target.onSerializeRigidBodyOption); + } + } + + + private int GetObservedComponentsCount() + { + int count = 0; + + for (int i = 0; i < this.m_Target.ObservedComponents.Count; ++i) + { + if (this.m_Target.ObservedComponents[i] != null) + { + count++; + } + } + + return count; + } + + private void DrawObservedComponentsList() + { + GUILayout.Space(5); + SerializedProperty listProperty = serializedObject.FindProperty("ObservedComponents"); + + if (listProperty == null) + { + return; + } + + float containerElementHeight = 22; + float containerHeight = listProperty.arraySize*containerElementHeight; + + bool isOpen = PhotonGUI.ContainerHeaderFoldout("Observed Components (" + GetObservedComponentsCount() + ")", serializedObject.FindProperty("ObservedComponentsFoldoutOpen").boolValue); + serializedObject.FindProperty("ObservedComponentsFoldoutOpen").boolValue = isOpen; + + if (isOpen == false) + { + containerHeight = 0; + } + + //Texture2D statsIcon = AssetDatabase.LoadAssetAtPath( "Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonViewStats.png", typeof( Texture2D ) ) as Texture2D; + + Rect containerRect = PhotonGUI.ContainerBody(containerHeight); + bool wasObservedComponentsEmpty = this.m_Target.ObservedComponents.FindAll(item => item != null).Count == 0; + if (isOpen == true) + { + for (int i = 0; i < listProperty.arraySize; ++i) + { + Rect elementRect = new Rect(containerRect.xMin, containerRect.yMin + containerElementHeight*i, containerRect.width, containerElementHeight); + { + Rect texturePosition = new Rect(elementRect.xMin + 6, elementRect.yMin + elementRect.height/2f - 1, 9, 5); + ReorderableListResources.DrawTexture(texturePosition, ReorderableListResources.texGrabHandle); + + Rect propertyPosition = new Rect(elementRect.xMin + 20, elementRect.yMin + 3, elementRect.width - 45, 16); + EditorGUI.PropertyField(propertyPosition, listProperty.GetArrayElementAtIndex(i), new GUIContent()); + + //Debug.Log( listProperty.GetArrayElementAtIndex( i ).objectReferenceValue.GetType() ); + //Rect statsPosition = new Rect( propertyPosition.xMax + 7, propertyPosition.yMin, statsIcon.width, statsIcon.height ); + //ReorderableListResources.DrawTexture( statsPosition, statsIcon ); + + Rect removeButtonRect = new Rect(elementRect.xMax - PhotonGUI.DefaultRemoveButtonStyle.fixedWidth, + elementRect.yMin + 2, + PhotonGUI.DefaultRemoveButtonStyle.fixedWidth, + PhotonGUI.DefaultRemoveButtonStyle.fixedHeight); + + GUI.enabled = listProperty.arraySize > 1; + if (GUI.Button(removeButtonRect, new GUIContent(ReorderableListResources.texRemoveButton), PhotonGUI.DefaultRemoveButtonStyle)) + { + listProperty.DeleteArrayElementAtIndex(i); + } + GUI.enabled = true; + + if (i < listProperty.arraySize - 1) + { + texturePosition = new Rect(elementRect.xMin + 2, elementRect.yMax, elementRect.width - 4, 1); + PhotonGUI.DrawSplitter(texturePosition); + } + } + } + } + + if (PhotonGUI.AddButton()) + { + listProperty.InsertArrayElementAtIndex(Mathf.Max(0, listProperty.arraySize - 1)); + } + + serializedObject.ApplyModifiedProperties(); + + bool isObservedComponentsEmpty = this.m_Target.ObservedComponents.FindAll(item => item != null).Count == 0; + + if (wasObservedComponentsEmpty == true && isObservedComponentsEmpty == false && this.m_Target.synchronization == ViewSynchronization.Off) + { + Undo.RecordObject(this.m_Target, "Change PhotonView"); + this.m_Target.synchronization = ViewSynchronization.UnreliableOnChange; + #if !UNITY_MIN_5_3 + EditorUtility.SetDirty(this.m_Target); + #endif + serializedObject.Update(); + } + + if (wasObservedComponentsEmpty == false && isObservedComponentsEmpty == true) + { + Undo.RecordObject(this.m_Target, "Change PhotonView"); + this.m_Target.synchronization = ViewSynchronization.Off; + #if !UNITY_MIN_5_3 + EditorUtility.SetDirty(this.m_Target); + #endif + serializedObject.Update(); + } + } + + private static GameObject GetPrefabParent(GameObject mp) + { + #if UNITY_2_6_1 || UNITY_2_6 || UNITY_3_0 || UNITY_3_0_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 + // Unity 3.4 and older use EditorUtility + return (EditorUtility.GetPrefabParent(mp) as GameObject); + #else + // Unity 3.5 uses PrefabUtility + return PrefabUtility.GetPrefabParent(mp) as GameObject; + #endif + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonViewInspector.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonViewInspector.cs.meta new file mode 100644 index 0000000..200b1ee --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonViewInspector.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e73a30c46df19194f873ea7a9ce12753 +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PunSceneSettings.cs b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PunSceneSettings.cs new file mode 100644 index 0000000..4a67fae --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PunSceneSettings.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.IO; +using UnityEditor; +using UnityEngine; + +[Serializable] +public class SceneSetting +{ + public string sceneName; + public int minViewId; +} + +public class PunSceneSettings : ScriptableObject +{ + [SerializeField] public List MinViewIdPerScene = new List(); + + private const string SceneSettingsFileName = "PunSceneSettingsFile.asset"; + + // we use the path to PunSceneSettings.cs as path to create a scene settings file + private static string punSceneSettingsCsPath; + public static string PunSceneSettingsCsPath + { + get + { + if (!string.IsNullOrEmpty(punSceneSettingsCsPath)) + { + return punSceneSettingsCsPath; + } + + // Unity 4.3.4 does not yet have AssetDatabase.FindAssets(). Would be easier. + var result = Directory.GetFiles(Application.dataPath, "PunSceneSettings.cs", SearchOption.AllDirectories); + if (result.Length >= 1) + { + punSceneSettingsCsPath = Path.GetDirectoryName(result[0]); + punSceneSettingsCsPath = punSceneSettingsCsPath.Replace('\\', '/'); + punSceneSettingsCsPath = punSceneSettingsCsPath.Replace(Application.dataPath, "Assets"); + + // AssetDatabase paths have to use '/' and are relative to the project's folder. Always. + punSceneSettingsCsPath = punSceneSettingsCsPath + "/" + SceneSettingsFileName; + } + + return punSceneSettingsCsPath; + } + } + + + private static PunSceneSettings instanceField; + public static PunSceneSettings Instance + { + get + { + if (instanceField != null) + { + return instanceField; + } + + instanceField = (PunSceneSettings)AssetDatabase.LoadAssetAtPath(PunSceneSettingsCsPath, typeof(PunSceneSettings)); + if (instanceField == null) + { + instanceField = ScriptableObject.CreateInstance(); + AssetDatabase.CreateAsset(instanceField, PunSceneSettingsCsPath); + } + + return instanceField; + } + } + + + public static int MinViewIdForScene(string scene) + { + if (string.IsNullOrEmpty(scene)) + { + return 0; + } + + PunSceneSettings pss = Instance; + if (pss == null) + { + Debug.LogError("pss cant be null"); + return 0; + } + + foreach (SceneSetting setting in pss.MinViewIdPerScene) + { + if (setting.sceneName.Equals(scene)) + { + return setting.minViewId; + } + } + return 0; + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PunSceneSettings.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PunSceneSettings.cs.meta new file mode 100644 index 0000000..065e2d8 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PunSceneSettings.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: fc3284eace5a64d4bb516df7d7effdb9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PunSceneSettingsFile.asset b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PunSceneSettingsFile.asset new file mode 100644 index 0000000..8954fa8 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PunSceneSettingsFile.asset @@ -0,0 +1,14 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fc3284eace5a64d4bb516df7d7effdb9, type: 3} + m_Name: PunSceneSettingsFile + m_EditorClassIdentifier: + MinViewIdPerScene: [] diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PunSceneSettingsFile.asset.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PunSceneSettingsFile.asset.meta new file mode 100644 index 0000000..5125fa9 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/PunSceneSettingsFile.asset.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: d0aacb83307022d449e90a09d28222ae diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/ReorderableListResources.cs b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/ReorderableListResources.cs new file mode 100644 index 0000000..72b9d7d --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/ReorderableListResources.cs @@ -0,0 +1,237 @@ +// Copyright (c) 2012-2013 Rotorz Limited. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +using UnityEngine; +using UnityEditor; + +using System; + +namespace Photon.Pun +{ + + /// + /// Resources to assist with reorderable list control. + /// + internal static class ReorderableListResources + { + + static ReorderableListResources() + { + GenerateSpecialTextures(); + LoadResourceAssets(); + } + + #region Texture Resources + + private enum ResourceName + { + add_button = 0, + add_button_active, + container_background, + grab_handle, + remove_button, + remove_button_active, + title_background, + } + + /// + /// Resource assets for light skin. + /// + /// + /// Resource assets are PNG images which have been encoded using a base-64 + /// string so that actual asset files are not necessary. + /// + private static string[] s_LightSkin = { + "iVBORw0KGgoAAAANSUhEUgAAAB4AAAAQCAYAAAABOs/SAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAAW0lEQVRIS+3NywnAQAhF0anI4mzVCmzBBl7QEBgGE5JFhBAXd+OHM5gZZgYRKcktNxu+HRFF2e6qhtOjtQM7K/tZ+xY89wSbazg9eqOfw6oag4rcChjY8coAjA2l1RxFDY8IFAAAAABJRU5ErkJggg==", + "iVBORw0KGgoAAAANSUhEUgAAAB4AAAAQCAYAAAABOs/SAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAGlJREFUeNpiFBER+f/jxw8GNjY2BnqAX79+MXBwcDAwMQwQGHoWnzp1CoxHjo8pBSykBi8+MTMzs2HmY2QfwXxKii9HExdZgNwgHuFB/efPH7pZCLOL8f///wyioqL/6enbL1++MAIEGABvGSLA+9GPZwAAAABJRU5ErkJggg==", + "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAECAYAAABGM/VAAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAAMElEQVQYV2P4//8/Q1FR0X8YBvHBAp8+ffp/+fJlMA3igwUfPnwIFgDRYEFM7f8ZAG1EOYL9INrfAAAAAElFTkSuQmCC", + "iVBORw0KGgoAAAANSUhEUgAAAAkAAAAFCAYAAACXU8ZrAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAAIElEQVQYV2P49OnTf0KYobCw8D8hzPD/P2FMLesK/wMAs5yJpK+6aN4AAAAASUVORK5CYII=", + "iVBORw0KGgoAAAANSUhEUgAAAAgAAAACCAIAAADq9gq6AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABVJREFUeNpiVFZWZsAGmBhwAIAAAwAURgBt4C03ZwAAAABJRU5ErkJggg==", + "iVBORw0KGgoAAAANSUhEUgAAAAgAAAACCAIAAADq9gq6AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABVJREFUeNpivHPnDgM2wMSAAwAEGAB8VgKYlvqkBwAAAABJRU5ErkJggg==", + "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAECAYAAABGM/VAAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEFJREFUeNpi/P//P0NxcfF/BgRgZP78+fN/VVVVhpCQEAZjY2OGs2fPNrCApBwdHRkePHgAVwoWnDVrFgMyAAgwAAt4E1dCq1obAAAAAElFTkSuQmCC" + }; + /// + /// Resource assets for dark skin. + /// + /// + /// Resource assets are PNG images which have been encoded using a base-64 + /// string so that actual asset files are not necessary. + /// + private static string[] s_DarkSkin = { + "iVBORw0KGgoAAAANSUhEUgAAAB4AAAAQCAYAAAABOs/SAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIBJREFUeNpiVFZW/u/i4sLw4sULBnoACQkJhj179jAwMQwQGHoWl5aWgvHI8TGlgIXU4MUn1t3dPcx8HB8fD2cvXLgQQ0xHR4c2FmMzmBTLhl5QYwt2cn1MtsXkWjg4gvrt27fgWoMeAGQXCDD+//+fQUVF5T89fXvnzh1GgAADAFmSI1Ed3FqgAAAAAElFTkSuQmCC", + "iVBORw0KGgoAAAANSUhEUgAAAB4AAAAQCAYAAAABOs/SAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHlJREFUeNpiFBER+f/jxw8GNjY2BnqAX79+MXBwcDAwMQwQGHoWv3nzBoxHjo8pBSykBi8+MWAOGWY+5uLigrO/ffuGIYbMppnF5Fg2tFM1yKfk+pbkoKZGEA+OVP3nzx+6WQizi/H///8MoqKi/+np2y9fvjACBBgAoTYjgvihfz0AAAAASUVORK5CYII=", + "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAECAYAAABGM/VAAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD1JREFUeNpi/P//P4OKisp/Bii4c+cOIwtIwMXFheHFixcMEhISYAVMINm3b9+CBUA0CDCiazc0NGQECDAAdH0YelA27kgAAAAASUVORK5CYII=", + "iVBORw0KGgoAAAANSUhEUgAAAAkAAAAFCAYAAACXU8ZrAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACRJREFUeNpizM3N/c9AADAqKysTVMTi5eXFSFAREFPHOoAAAwBCfwcAO8g48QAAAABJRU5ErkJggg==", + "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAECAYAAACzzX7wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi/P//PwM+wHL06FG8KpgYCABGZWVlvCYABBgA7/sHvGw+cz8AAAAASUVORK5CYII=", + "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAECAYAAACzzX7wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi/P//PwM+wPKfgAomBgKAhYuLC68CgAADAAxjByOjCHIRAAAAAElFTkSuQmCC", + "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAECAYAAABGM/VAAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADtJREFUeNpi/P//P4OKisp/Bii4c+cOIwtIQE9Pj+HLly9gQRCfBcQACbx69QqmmAEseO/ePQZkABBgAD04FXsmmijSAAAAAElFTkSuQmCC" + }; + + /// + /// Gets light or dark texture "add_button.png". + /// + public static Texture2D texAddButton + { + get { return s_Cached[ (int)ResourceName.add_button ]; } + } + /// + /// Gets light or dark texture "add_button_active.png". + /// + public static Texture2D texAddButtonActive + { + get { return s_Cached[ (int)ResourceName.add_button_active ]; } + } + /// + /// Gets light or dark texture "container_background.png". + /// + public static Texture2D texContainerBackground + { + get { return s_Cached[ (int)ResourceName.container_background ]; } + } + /// + /// Gets light or dark texture "grab_handle.png". + /// + public static Texture2D texGrabHandle + { + get { return s_Cached[ (int)ResourceName.grab_handle ]; } + } + /// + /// Gets light or dark texture "remove_button.png". + /// + public static Texture2D texRemoveButton + { + get { return s_Cached[ (int)ResourceName.remove_button ]; } + } + /// + /// Gets light or dark texture "remove_button_active.png". + /// + public static Texture2D texRemoveButtonActive + { + get { return s_Cached[ (int)ResourceName.remove_button_active ]; } + } + /// + /// Gets light or dark texture "title_background.png". + /// + public static Texture2D texTitleBackground + { + get { return s_Cached[ (int)ResourceName.title_background ]; } + } + + #endregion + + #region Generated Resources + + public static Texture2D texItemSplitter { get; private set; } + + /// + /// Generate special textures. + /// + private static void GenerateSpecialTextures() + { + var splitterColor = EditorGUIUtility.isProSkin + ? new Color( 1f, 1f, 1f, 0.14f ) + : new Color( 0.59f, 0.59f, 0.59f, 0.55f ) + ; + texItemSplitter = CreatePixelTexture( "(Generated) Item Splitter", splitterColor ); + } + + /// + /// Create 1x1 pixel texture of specified color. + /// + /// Name for texture object. + /// Pixel color. + /// + /// The new Texture2D instance. + /// + public static Texture2D CreatePixelTexture( string name, Color color ) + { + var tex = new Texture2D( 1, 1, TextureFormat.ARGB32, false, true ); + tex.name = name; + tex.hideFlags = HideFlags.HideAndDontSave; + tex.filterMode = FilterMode.Point; + tex.SetPixel( 0, 0, color ); + tex.Apply(); + return tex; + } + + #endregion + + #region Load PNG from Base-64 Encoded String + + private static Texture2D[] s_Cached; + + /// + /// Read textures from base-64 encoded strings. Automatically selects assets based + /// upon whether the light or dark (pro) skin is active. + /// + private static void LoadResourceAssets() + { + var skin = EditorGUIUtility.isProSkin ? s_DarkSkin : s_LightSkin; + s_Cached = new Texture2D[ skin.Length ]; + + for( int i = 0; i < s_Cached.Length; ++i ) + { + // Get image data (PNG) from base64 encoded strings. + byte[] imageData = Convert.FromBase64String( skin[ i ] ); + + // Gather image size from image data. + int texWidth, texHeight; + GetImageSize( imageData, out texWidth, out texHeight ); + + // Generate texture asset. + var tex = new Texture2D( texWidth, texHeight, TextureFormat.ARGB32, false, true ); + tex.hideFlags = HideFlags.HideAndDontSave; + tex.name = "(Generated) ReorderableList:" + i; + tex.filterMode = FilterMode.Point; + tex.LoadImage( imageData ); + + s_Cached[ i ] = tex; + } + + s_LightSkin = null; + s_DarkSkin = null; + } + + /// + /// Read width and height if PNG file in pixels. + /// + /// PNG image data. + /// Width of image in pixels. + /// Height of image in pixels. + private static void GetImageSize( byte[] imageData, out int width, out int height ) + { + width = ReadInt( imageData, 3 + 15 ); + height = ReadInt( imageData, 3 + 15 + 2 + 2 ); + } + + private static int ReadInt( byte[] imageData, int offset ) + { + return ( imageData[ offset ] << 8 ) | imageData[ offset + 1 ]; + } + + #endregion + + #region GUI Helper + private static GUIStyle s_TempStyle = new GUIStyle(); + + /// + /// Draw texture using to workaround bug in Unity where + /// flickers when embedded inside a property drawer. + /// + /// Position of which to draw texture in space of GUI. + /// Texture. + public static void DrawTexture( Rect position, Texture2D texture ) + { + if( Event.current.type != EventType.Repaint ) + return; + + s_TempStyle.normal.background = texture; + + s_TempStyle.Draw( position, GUIContent.none, false, false, false, false ); + } + #endregion + + } + +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/ReorderableListResources.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/ReorderableListResources.cs.meta new file mode 100644 index 0000000..7f43a21 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/ReorderableListResources.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 60c609ded101b0a468fb5cf27b31cf27 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/ServerSettingsInspector.cs b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/ServerSettingsInspector.cs new file mode 100644 index 0000000..4a6b48c --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/ServerSettingsInspector.cs @@ -0,0 +1,378 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2016 Exit Games GmbH +// +// +// This is a custom editor for the ServerSettings scriptable object. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +using System; +using ExitGames.Client.Photon; +using UnityEditor; +using UnityEngine; + + +[CustomEditor(typeof (ServerSettings))] +public class ServerSettingsInspector : Editor +{ + private bool showMustHaveRegion; + private CloudRegionCode lastUsedRegion; + private ServerConnection lastServer; + + + public void OnEnable() + { + this.lastUsedRegion = ServerSettings.BestRegionCodeInPreferences; + EditorApplication.update += this.OnUpdate; + } + + + public void OnDisable() + { + EditorApplication.update -= this.OnUpdate; + } + + + private void OnUpdate() + { + if (this.lastUsedRegion != ServerSettings.BestRegionCodeInPreferences) + { + this.lastUsedRegion = ServerSettings.BestRegionCodeInPreferences; + Repaint(); + } + // this won't repaint when we disconnect but it's "good enough" to update when we connect and switch servers. + if (Application.isPlaying && this.lastServer != PhotonNetwork.Server) + { + this.lastServer = PhotonNetwork.Server; + Repaint(); + } + } + + + public override void OnInspectorGUI() + { + ServerSettings settings = (ServerSettings) target; + Undo.RecordObject(settings, "Edit PhotonServerSettings"); + settings.HostType = (ServerSettings.HostingOption) EditorGUILayout.EnumPopup("Hosting", settings.HostType); + EditorGUI.indentLevel = 1; + + switch (settings.HostType) + { + case ServerSettings.HostingOption.BestRegion: + case ServerSettings.HostingOption.PhotonCloud: + // region selection + if (settings.HostType == ServerSettings.HostingOption.PhotonCloud) + { + settings.PreferredRegion = (CloudRegionCode)EditorGUILayout.EnumPopup("Region", settings.PreferredRegion); + } + else // Bestregion + { + string _regionFeedback = "Prefs:"+ServerSettings.BestRegionCodeInPreferences.ToString(); + + // the NameServer does not have a region itself. it's global (although it has regional instances) + if (PhotonNetwork.connected && PhotonNetwork.Server != ServerConnection.NameServer) + { + _regionFeedback = "Current:" + PhotonNetwork.CloudRegion + " " + _regionFeedback; + } + + EditorGUILayout.BeginHorizontal (); + EditorGUILayout.PrefixLabel (" "); + Rect rect = GUILayoutUtility.GetRect(new GUIContent(_regionFeedback),"Label"); + int indentLevel = EditorGUI.indentLevel; + EditorGUI.indentLevel = 0; + EditorGUI.LabelField (rect, _regionFeedback); + EditorGUI.indentLevel = indentLevel; + + rect.x += rect.width-39; + rect.width = 39; + + rect.height -=2; + if (GUI.Button(rect,"Reset",EditorStyles.miniButton)) + { + ServerSettings.ResetBestRegionCodeInPreferences(); + } + EditorGUILayout.EndHorizontal (); + + + // Dashboard region settings + EditorGUILayout.BeginHorizontal (); + EditorGUILayout.PrefixLabel ("Regions"); + Rect rect2 = GUILayoutUtility.GetRect(new GUIContent("Online WhiteList"),"Label"); + if (!string.IsNullOrEmpty(settings.AppID)) + { + int indentLevel2 = EditorGUI.indentLevel; + EditorGUI.indentLevel = 0; + EditorGUI.LabelField (rect2, "Online WhiteList"); + EditorGUI.indentLevel = indentLevel2; + + rect2.x += rect2.width-80; + rect2.width = 80; + + rect2.height -=2; + if (GUI.Button(rect2,"Dashboard",EditorStyles.miniButton)) + { + Application.OpenURL("https://www.photonengine.com/en-US/Dashboard/Manage/"+settings.AppID); + } + }else{ + GUI.Label(rect2,"n/a"); + } + + EditorGUILayout.EndHorizontal (); + + + EditorGUI.indentLevel ++; + #if UNITY_2017_3_OR_NEWER + CloudRegionFlag valRegions = (CloudRegionFlag)EditorGUILayout.EnumFlagsField(" ", settings.EnabledRegions); + #else + CloudRegionFlag valRegions = (CloudRegionFlag)EditorGUILayout.EnumMaskField(" ", settings.EnabledRegions); + #endif + + if (valRegions != settings.EnabledRegions) + { + settings.EnabledRegions = valRegions; + this.showMustHaveRegion = valRegions == 0; + } + if (this.showMustHaveRegion) + { + EditorGUILayout.HelpBox("You should enable at least two regions for 'Best Region' hosting.", MessageType.Warning); + } + + EditorGUI.indentLevel --; + + } + + // appid + string valAppId = EditorGUILayout.TextField("AppId", settings.AppID); + if (valAppId != settings.AppID) + { + settings.AppID = valAppId.Trim(); + } + if (!ServerSettings.IsAppId(settings.AppID)) + { + EditorGUILayout.HelpBox("PUN needs an AppId (GUID).\nFind it online in the Dashboard.", MessageType.Warning); + } + + // protocol + ConnectionProtocol valProtocol = settings.Protocol; + valProtocol = (ConnectionProtocol) EditorGUILayout.EnumPopup("Protocol", valProtocol); + settings.Protocol = (ConnectionProtocol) valProtocol; + #if UNITY_WEBGL + EditorGUILayout.HelpBox("WebGL always use Secure WebSockets as protocol.\nThis setting gets ignored in current export.", MessageType.Warning); + #endif + break; + + case ServerSettings.HostingOption.SelfHosted: + // address and port (depends on protocol below) + bool hidePort = false; + if (settings.Protocol == ConnectionProtocol.Udp && (settings.ServerPort == 4530 || settings.ServerPort == 0)) + { + settings.ServerPort = 5055; + } + else if (settings.Protocol == ConnectionProtocol.Tcp && (settings.ServerPort == 5055 || settings.ServerPort == 0)) + { + settings.ServerPort = 4530; + } + #if RHTTP + if (settings.Protocol == ConnectionProtocol.RHttp) + { + settings.ServerPort = 0; + hidePort = true; + } + #endif + settings.ServerAddress = EditorGUILayout.TextField("Server Address", settings.ServerAddress); + settings.ServerAddress = settings.ServerAddress.Trim(); + if (!hidePort) + { + settings.ServerPort = EditorGUILayout.IntField("Server Port", settings.ServerPort); + } + // protocol + valProtocol = settings.Protocol; + valProtocol = (ConnectionProtocol)EditorGUILayout.EnumPopup("Protocol", valProtocol); + settings.Protocol = (ConnectionProtocol)valProtocol; + #if UNITY_WEBGL + EditorGUILayout.HelpBox("WebGL always use Secure WebSockets as protocol.\nThis setting gets ignored in current export.", MessageType.Warning); + #endif + + // appid + settings.AppID = EditorGUILayout.TextField("AppId", settings.AppID); + settings.AppID = settings.AppID.Trim(); + break; + + case ServerSettings.HostingOption.OfflineMode: + EditorGUI.indentLevel = 0; + EditorGUILayout.HelpBox("In 'Offline Mode', the client does not communicate with a server.\nAll settings are hidden currently.", MessageType.Info); + break; + + case ServerSettings.HostingOption.NotSet: + EditorGUI.indentLevel = 0; + EditorGUILayout.HelpBox("Hosting is 'Not Set'.\nConnectUsingSettings() will not be able to connect.\nSelect another option or run the PUN Wizard.", MessageType.Info); + break; + + default: + DrawDefaultInspector(); + break; + } + + if (PhotonEditor.CheckPunPlus()) + { + settings.Protocol = ConnectionProtocol.Udp; + EditorGUILayout.HelpBox("You seem to use PUN+.\nPUN+ only supports reliable UDP so the protocol is locked.", MessageType.Info); + } + + + + // CHAT SETTINGS + if (PhotonEditorUtils.HasChat) + { + GUILayout.Space(5); + EditorGUI.indentLevel = 0; + EditorGUILayout.LabelField("Photon Chat Settings"); + EditorGUI.indentLevel = 1; + string valChatAppid = EditorGUILayout.TextField("Chat AppId", settings.ChatAppID); + if (valChatAppid != settings.ChatAppID) + { + settings.ChatAppID = valChatAppid.Trim(); + } + if (!ServerSettings.IsAppId(settings.ChatAppID)) + { + EditorGUILayout.HelpBox("Photon Chat needs an AppId (GUID).\nFind it online in the Dashboard.", MessageType.Warning); + } + + EditorGUI.indentLevel = 0; + } + + + + // VOICE SETTINGS + if (PhotonEditorUtils.HasVoice) + { + GUILayout.Space(5); + EditorGUI.indentLevel = 0; + EditorGUILayout.LabelField("Photon Voice Settings"); + EditorGUI.indentLevel = 1; + switch (settings.HostType) + { + case ServerSettings.HostingOption.BestRegion: + case ServerSettings.HostingOption.PhotonCloud: + // voice appid + string valVoiceAppId = EditorGUILayout.TextField("Voice AppId", settings.VoiceAppID); + if (valVoiceAppId != settings.VoiceAppID) + { + settings.VoiceAppID = valVoiceAppId.Trim(); + } + if (!ServerSettings.IsAppId(settings.VoiceAppID)) + { + EditorGUILayout.HelpBox("Photon Voice needs an AppId (GUID).\nFind it online in the Dashboard.", MessageType.Warning); + } + break; + case ServerSettings.HostingOption.SelfHosted: + if (settings.VoiceServerPort == 0) + { + settings.VoiceServerPort = 5055; + } + settings.VoiceServerPort = EditorGUILayout.IntField("Server Port UDP", settings.VoiceServerPort); + break; + case ServerSettings.HostingOption.OfflineMode: + case ServerSettings.HostingOption.NotSet: + break; + } + EditorGUI.indentLevel = 0; + } + + + + // PUN Client Settings + GUILayout.Space(5); + EditorGUI.indentLevel = 0; + EditorGUILayout.LabelField("Client Settings"); + EditorGUI.indentLevel = 1; + //EditorGUILayout.LabelField("game version"); + settings.JoinLobby = EditorGUILayout.Toggle("Auto-Join Lobby", settings.JoinLobby); + settings.EnableLobbyStatistics = EditorGUILayout.Toggle("Enable Lobby Stats", settings.EnableLobbyStatistics); + + // Pun Logging Level + PhotonLogLevel _PunLogging = (PhotonLogLevel)EditorGUILayout.EnumPopup("Pun Logging", settings.PunLogging); + if (EditorApplication.isPlaying && PhotonNetwork.logLevel!=_PunLogging) + { + PhotonNetwork.logLevel = _PunLogging; + } + settings.PunLogging = _PunLogging; + + // Network Logging Level + DebugLevel _DebugLevel = (DebugLevel)EditorGUILayout.EnumPopup("Network Logging", settings.NetworkLogging); + if (EditorApplication.isPlaying && settings.NetworkLogging!=_DebugLevel) + { + settings.NetworkLogging = _DebugLevel; + } + settings.NetworkLogging = _DebugLevel; + + + //EditorGUILayout.LabelField("automaticallySyncScene"); + //EditorGUILayout.LabelField("autoCleanUpPlayerObjects"); + //EditorGUILayout.LabelField("lobby stats"); + //EditorGUILayout.LabelField("sendrate / serialize rate"); + //EditorGUILayout.LabelField("quick resends"); + //EditorGUILayout.LabelField("max resends"); + //EditorGUILayout.LabelField("enable crc checking"); + + + // Application settings + GUILayout.Space(5); + EditorGUI.indentLevel = 0; + EditorGUILayout.LabelField("Build Settings"); + EditorGUI.indentLevel = 1; + + settings.RunInBackground = EditorGUILayout.Toggle("Run In Background", settings.RunInBackground); + + + // RPC-shortcut list + GUILayout.Space(5); + EditorGUI.indentLevel = 0; + SerializedObject sObj = new SerializedObject(target); + SerializedProperty sRpcs = sObj.FindProperty("RpcList"); + EditorGUILayout.PropertyField(sRpcs, true); + sObj.ApplyModifiedProperties(); + + GUILayout.BeginHorizontal(); + GUILayout.Space(20); + if (GUILayout.Button("Refresh RPCs")) + { + PhotonEditor.UpdateRpcList(); + Repaint(); + } + if (GUILayout.Button("Clear RPCs")) + { + PhotonEditor.ClearRpcList(); + } + if (GUILayout.Button("Log HashCode")) + { + Debug.Log("RPC-List HashCode: " + RpcListHashCode() + ". Make sure clients that send each other RPCs have the same RPC-List."); + } + GUILayout.Space(20); + GUILayout.EndHorizontal(); + + + //SerializedProperty sp = serializedObject.FindProperty("RpcList"); + //EditorGUILayout.PropertyField(sp, true); + + if (GUI.changed) + { + EditorUtility.SetDirty(target); // even in Unity 5.3+ it's OK to SetDirty() for non-scene objects. + } + } + + private int RpcListHashCode() + { + // this is a hashcode generated to (more) easily compare this Editor's RPC List with some other + int hashCode = PhotonNetwork.PhotonServerSettings.RpcList.Count + 1; + foreach (string s in PhotonNetwork.PhotonServerSettings.RpcList) + { + int h1 = s.GetHashCode(); + hashCode = ((h1 << 5) + h1) ^ hashCode; + } + + return hashCode; + } +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/ServerSettingsInspector.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/ServerSettingsInspector.cs.meta new file mode 100644 index 0000000..d9f769d --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/ServerSettingsInspector.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 21239ba77ac4b534f958e8617ef13ede +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views.meta new file mode 100644 index 0000000..c6b3350 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 782d1ef1fe2574274b61fcba47a72317 +folderAsset: yes +timeCreated: 1525372512 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonAnimatorViewEditor.cs b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonAnimatorViewEditor.cs new file mode 100644 index 0000000..5a6afda --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonAnimatorViewEditor.cs @@ -0,0 +1,343 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2016 Exit Games GmbH +// +// +// This is a custom editor for the AnimatorView component. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + + +#if UNITY_5 && !UNITY_5_0 && !UNITY_5_1 && !UNITY_5_2 || UNITY_5_4_OR_NEWER +#define UNITY_MIN_5_3 +#endif + + +using UnityEditor; +using UnityEngine; +using System.Collections.Generic; + +#if UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7 +using UnityEditorInternal; +#elif UNITY_5 || UNITY_5_0 || UNITY_5_3_OR_NEWER +using UnityEditor.Animations; +#endif + +[CustomEditor(typeof (PhotonAnimatorView))] +public class PhotonAnimatorViewEditor : Editor +{ + private Animator m_Animator; + private PhotonAnimatorView m_Target; + + #if UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5 || UNITY_5_0 || UNITY_5_3_OR_NEWER + private AnimatorController m_Controller; +#endif + + public override void OnInspectorGUI() + { + //base.OnInspectorGUI(); + + if (this.m_Animator == null) + { + GUILayout.BeginVertical(GUI.skin.box); + GUILayout.Label("GameObject doesn't have an Animator component to synchronize"); + GUILayout.EndVertical(); + return; + } + + DrawWeightInspector(); + + if (GetLayerCount() == 0) + { + GUILayout.BeginVertical(GUI.skin.box); + GUILayout.Label("Animator doesn't have any layers setup to synchronize"); + GUILayout.EndVertical(); + } + + DrawParameterInspector(); + + if (GetParameterCount() == 0) + { + GUILayout.BeginVertical(GUI.skin.box); + GUILayout.Label("Animator doesn't have any parameters setup to synchronize"); + GUILayout.EndVertical(); + } + + serializedObject.ApplyModifiedProperties(); + + //GUILayout.Label( "m_SynchronizeLayers " + serializedObject.FindProperty( "m_SynchronizeLayers" ).arraySize ); + //GUILayout.Label( "m_SynchronizeParameters " + serializedObject.FindProperty( "m_SynchronizeParameters" ).arraySize ); + } + + + private int GetLayerCount() + { + #if UNITY_5 || UNITY_5_0 || UNITY_5_3_OR_NEWER + return (this.m_Controller == null) ? 0 : this.m_Controller.layers.Length; + #else + return (this.m_Controller == null) ? 0 : this.m_Controller.layerCount; + #endif + } + + + #if UNITY_5 || UNITY_5_0 || UNITY_5_3_OR_NEWER + private RuntimeAnimatorController GetEffectiveController(Animator animator) + { + RuntimeAnimatorController controller = animator.runtimeAnimatorController; + + AnimatorOverrideController overrideController = controller as AnimatorOverrideController; + while (overrideController != null) + { + controller = overrideController.runtimeAnimatorController; + overrideController = controller as AnimatorOverrideController; + } + + return controller; + } +#endif + + + private void OnEnable() + { + this.m_Target = (PhotonAnimatorView) target; + this.m_Animator = this.m_Target.GetComponent(); + +#if UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7 + this.m_Controller = AnimatorController.GetEffectiveAnimatorController(this.m_Animator); + #elif UNITY_5 || UNITY_5_0 || UNITY_5_3_OR_NEWER + this.m_Controller = this.GetEffectiveController(this.m_Animator) as AnimatorController; +#endif + + CheckIfStoredParametersExist(); + } + + private void DrawWeightInspector() + { + SerializedProperty foldoutProperty = serializedObject.FindProperty("ShowLayerWeightsInspector"); + foldoutProperty.boolValue = PhotonGUI.ContainerHeaderFoldout("Synchronize Layer Weights", foldoutProperty.boolValue); + + if (foldoutProperty.boolValue == false) + { + return; + } + + float lineHeight = 20; + Rect containerRect = PhotonGUI.ContainerBody(this.GetLayerCount()*lineHeight); + + for (int i = 0; i < this.GetLayerCount(); ++i) + { + if (this.m_Target.DoesLayerSynchronizeTypeExist(i) == false) + { + this.m_Target.SetLayerSynchronized(i, PhotonAnimatorView.SynchronizeType.Disabled); + + #if !UNITY_MIN_5_3 + EditorUtility.SetDirty(this.m_Target); + #endif + } + + PhotonAnimatorView.SynchronizeType syncType = this.m_Target.GetLayerSynchronizeType(i); + + Rect elementRect = new Rect(containerRect.xMin, containerRect.yMin + i*lineHeight, containerRect.width, lineHeight); + + Rect labelRect = new Rect(elementRect.xMin + 5, elementRect.yMin + 2, EditorGUIUtility.labelWidth - 5, elementRect.height); + GUI.Label(labelRect, "Layer " + i); + + Rect popupRect = new Rect(elementRect.xMin + EditorGUIUtility.labelWidth, elementRect.yMin + 2, elementRect.width - EditorGUIUtility.labelWidth - 5, EditorGUIUtility.singleLineHeight); + syncType = (PhotonAnimatorView.SynchronizeType) EditorGUI.EnumPopup(popupRect, syncType); + + if (i < this.GetLayerCount() - 1) + { + Rect splitterRect = new Rect(elementRect.xMin + 2, elementRect.yMax, elementRect.width - 4, 1); + PhotonGUI.DrawSplitter(splitterRect); + } + + if (syncType != this.m_Target.GetLayerSynchronizeType(i)) + { + Undo.RecordObject(target, "Modify Synchronize Layer Weights"); + this.m_Target.SetLayerSynchronized(i, syncType); + + #if !UNITY_MIN_5_3 + EditorUtility.SetDirty(this.m_Target); + #endif + } + } + } + + private int GetParameterCount() + { + #if UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7 + return (this.m_Controller == null) ? 0 : this.m_Controller.parameterCount; + #elif UNITY_5 || UNITY_5_0 || UNITY_5_3_OR_NEWER + return (this.m_Controller == null) ? 0 : this.m_Controller.parameters.Length; + #else + return (m_Animator == null) ? 0 : m_Animator.parameters.Length; + #endif + } + + private AnimatorControllerParameter GetAnimatorControllerParameter(int i) + { + #if UNITY_4_0 || UNITY_4_0_1 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7 + return this.m_Controller.GetParameter(i); + #elif UNITY_5 || UNITY_5_0 || UNITY_5_3_OR_NEWER + return this.m_Controller.parameters[i]; + #else + return m_Animator.parameters[i]; + #endif + } + + private bool DoesParameterExist(string name) + { + for (int i = 0; i < this.GetParameterCount(); ++i) + { + if (GetAnimatorControllerParameter(i).name == name) + { + return true; + } + } + + return false; + } + + private void CheckIfStoredParametersExist() + { + var syncedParams = this.m_Target.GetSynchronizedParameters(); + List paramsToRemove = new List(); + + for (int i = 0; i < syncedParams.Count; ++i) + { + string parameterName = syncedParams[i].Name; + if (DoesParameterExist(parameterName) == false) + { + Debug.LogWarning("Parameter '" + this.m_Target.GetSynchronizedParameters()[i].Name + "' doesn't exist anymore. Removing it from the list of synchronized parameters"); + paramsToRemove.Add(parameterName); + } + } + if (paramsToRemove.Count > 0) + { + foreach (string param in paramsToRemove) + { + this.m_Target.GetSynchronizedParameters().RemoveAll(item => item.Name == param); + } + + #if !UNITY_MIN_5_3 + EditorUtility.SetDirty(this.m_Target); + #endif + } + } + + + private void DrawParameterInspector() + { + // flag to expose a note in Interface if one or more trigger(s) are synchronized + bool isUsingTriggers = false; + + SerializedProperty foldoutProperty = serializedObject.FindProperty("ShowParameterInspector"); + foldoutProperty.boolValue = PhotonGUI.ContainerHeaderFoldout("Synchronize Parameters", foldoutProperty.boolValue); + + if (foldoutProperty.boolValue == false) + { + return; + } + + float lineHeight = 20; + Rect containerRect = PhotonGUI.ContainerBody(GetParameterCount()*lineHeight); + + for (int i = 0; i < GetParameterCount(); i++) + { + AnimatorControllerParameter parameter = null; + parameter = GetAnimatorControllerParameter(i); + + string defaultValue = ""; + + if (parameter.type == AnimatorControllerParameterType.Bool) + { + if (Application.isPlaying && m_Animator.gameObject.activeInHierarchy) + { + defaultValue += m_Animator.GetBool(parameter.name); + }else{ + defaultValue += parameter.defaultBool.ToString(); + } + } + else if (parameter.type == AnimatorControllerParameterType.Float) + { + if (Application.isPlaying && m_Animator.gameObject.activeInHierarchy) + { + defaultValue += m_Animator.GetFloat(parameter.name).ToString("0.00"); + }else{ + defaultValue += parameter.defaultFloat.ToString(); + } + } + else if (parameter.type == AnimatorControllerParameterType.Int) + { + if (Application.isPlaying && m_Animator.gameObject.activeInHierarchy) + { + defaultValue += m_Animator.GetInteger(parameter.name); + }else{ + defaultValue += parameter.defaultInt.ToString(); + } + } + else if (parameter.type == AnimatorControllerParameterType.Trigger) + { + if (Application.isPlaying && m_Animator.gameObject.activeInHierarchy) + { + defaultValue += m_Animator.GetBool(parameter.name); + }else{ + defaultValue += parameter.defaultBool.ToString(); + } + } + + if (this.m_Target.DoesParameterSynchronizeTypeExist(parameter.name) == false) + { + this.m_Target.SetParameterSynchronized(parameter.name, (PhotonAnimatorView.ParameterType) parameter.type, PhotonAnimatorView.SynchronizeType.Disabled); + + #if !UNITY_MIN_5_3 + EditorUtility.SetDirty(this.m_Target); + #endif + } + + PhotonAnimatorView.SynchronizeType value = this.m_Target.GetParameterSynchronizeType(parameter.name); + + // check if using trigger and actually synchronizing it + if (value!=PhotonAnimatorView.SynchronizeType.Disabled &¶meter.type == AnimatorControllerParameterType.Trigger) + { + isUsingTriggers = true; + } + + Rect elementRect = new Rect(containerRect.xMin, containerRect.yMin + i*lineHeight, containerRect.width, lineHeight); + + Rect labelRect = new Rect(elementRect.xMin + 5, elementRect.yMin + 2, EditorGUIUtility.labelWidth - 5, elementRect.height); + GUI.Label(labelRect, parameter.name + " (" + defaultValue + ")"); + + Rect popupRect = new Rect(elementRect.xMin + EditorGUIUtility.labelWidth, elementRect.yMin + 2, elementRect.width - EditorGUIUtility.labelWidth - 5, EditorGUIUtility.singleLineHeight); + value = (PhotonAnimatorView.SynchronizeType) EditorGUI.EnumPopup(popupRect, value); + + if (i < GetParameterCount() - 1) + { + Rect splitterRect = new Rect(elementRect.xMin + 2, elementRect.yMax, elementRect.width - 4, 1); + PhotonGUI.DrawSplitter(splitterRect); + } + + + + if (value != this.m_Target.GetParameterSynchronizeType(parameter.name)) + { + Undo.RecordObject(target, "Modify Synchronize Parameter " + parameter.name); + this.m_Target.SetParameterSynchronized(parameter.name, (PhotonAnimatorView.ParameterType) parameter.type, value); + + #if !UNITY_MIN_5_3 + EditorUtility.SetDirty(this.m_Target); + #endif + } + } + + // display note when synchronized triggers are detected. + if (isUsingTriggers) + { + GUILayout.BeginHorizontal(GUI.skin.box); + GUILayout.Label("When using triggers, make sure this component is last in the stack"); + GUILayout.EndHorizontal(); + } + + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonAnimatorViewEditor.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonAnimatorViewEditor.cs.meta new file mode 100644 index 0000000..c6e48af --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonAnimatorViewEditor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a3f61bade114730459f7ad45f5f292c1 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonRigidbody2DViewEditor.cs b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonRigidbody2DViewEditor.cs new file mode 100644 index 0000000..d323121 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonRigidbody2DViewEditor.cs @@ -0,0 +1,21 @@ +using UnityEditor; +using UnityEngine; + +[CustomEditor(typeof (PhotonRigidbody2DView))] +public class PhotonRigidbody2DViewEditor : Editor +{ + public override void OnInspectorGUI() + { + PhotonGUI.ContainerHeader("Options"); + + Rect containerRect = PhotonGUI.ContainerBody(EditorGUIUtility.singleLineHeight*2 + 10); + + Rect propertyRect = new Rect(containerRect.xMin + 5, containerRect.yMin + 5, containerRect.width, EditorGUIUtility.singleLineHeight); + EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_SynchronizeVelocity"), new GUIContent("Synchronize Velocity")); + + propertyRect.y += EditorGUIUtility.singleLineHeight; + EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_SynchronizeAngularVelocity"), new GUIContent("Synchronize Angular Velocity")); + + serializedObject.ApplyModifiedProperties(); + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonRigidbody2DViewEditor.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonRigidbody2DViewEditor.cs.meta new file mode 100644 index 0000000..9e50961 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonRigidbody2DViewEditor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3a82e8e86b9eecb40ac3f6ebc949f6ef +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonRigidbodyViewEditor.cs b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonRigidbodyViewEditor.cs new file mode 100644 index 0000000..4beb8e5 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonRigidbodyViewEditor.cs @@ -0,0 +1,21 @@ +using UnityEditor; +using UnityEngine; + +[CustomEditor(typeof (PhotonRigidbodyView))] +public class PhotonRigidbodyViewEditor : Editor +{ + public override void OnInspectorGUI() + { + PhotonGUI.ContainerHeader("Options"); + + Rect containerRect = PhotonGUI.ContainerBody(EditorGUIUtility.singleLineHeight*2 + 10); + + Rect propertyRect = new Rect(containerRect.xMin + 5, containerRect.yMin + 5, containerRect.width, EditorGUIUtility.singleLineHeight); + EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_SynchronizeVelocity"), new GUIContent("Synchronize Velocity")); + + propertyRect.y += EditorGUIUtility.singleLineHeight; + EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_SynchronizeAngularVelocity"), new GUIContent("Synchronize Angular Velocity")); + + serializedObject.ApplyModifiedProperties(); + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonRigidbodyViewEditor.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonRigidbodyViewEditor.cs.meta new file mode 100644 index 0000000..b4fa5b9 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonRigidbodyViewEditor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4bcfebc9a2f1074488adedd1fe84e6c9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonTransformViewEditor.cs b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonTransformViewEditor.cs new file mode 100644 index 0000000..f2589d2 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonTransformViewEditor.cs @@ -0,0 +1,434 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2016 Exit Games GmbH +// +// +// This is a custom editor for the TransformView component. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + + +#if UNITY_5 && !UNITY_5_0 && !UNITY_5_1 && !UNITY_5_2 || UNITY_5_4_OR_NEWER +#define UNITY_MIN_5_3 +#endif + + +using UnityEditor; +using UnityEngine; + +[CustomEditor(typeof (PhotonTransformView))] +public class PhotonTransformViewEditor : Editor +{ + //private PhotonTransformView m_Target; + + private SerializedProperty m_SynchronizePositionProperty; + private SerializedProperty m_SynchronizeRotationProperty; + private SerializedProperty m_SynchronizeScaleProperty; + + private bool m_InterpolateHelpOpen; + private bool m_ExtrapolateHelpOpen; + private bool m_InterpolateRotationHelpOpen; + private bool m_InterpolateScaleHelpOpen; + + private const int EDITOR_LINE_HEIGHT = 20; + + private const string INTERPOLATE_TOOLTIP = + "Choose between synchronizing the value directly (by disabling interpolation) or smoothly move it towards the newest update."; + + private const string INTERPOLATE_HELP = + "You can use interpolation to smoothly move your GameObject towards a new position that is received via the network. " + + "This helps to reduce the stuttering movement that results because the network updates only arrive 10 times per second.\n" + + "As a side effect, the GameObject is always lagging behind the actual position a little bit. This can be addressed with extrapolation."; + + private const string EXTRAPOLATE_TOOLTIP = "Extrapolation is used to predict where the GameObject actually is"; + + private const string EXTRAPOLATE_HELP = + "Whenever you deal with network values, all values you receive will be a little bit out of date since that data needs " + + "to reach you first. You can use extrapolation to try to predict where the player actually is, based on the movement data you have received.\n" + + + "This has to be tweaked carefully for each specific game in order to insure the optimal prediction. Sometimes it is very easy to extrapolate states, because " + + + "the GameObject behaves very predictable (for example for vehicles). Other times it can be very hard because the user input is translated directly to the game " + + "and you cannot really predict what the user is going to do (for example in fighting games)"; + + private const string INTERPOLATE_HELP_URL = "https://doc.photonengine.com/en-us/pun/current/demos-and-tutorials/package-demos/rpg-movement#interpolate_options"; + private const string EXTRAPOLATE_HELP_URL = "https://doc.photonengine.com/en-us/pun/current/demos-and-tutorials/package-demos/rpg-movement#extrapolate_options"; + + public void OnEnable() + { + SetupSerializedProperties(); + } + + public override void OnInspectorGUI() + { + serializedObject.Update (); + + //this.m_Target = (PhotonTransformView) target; + + DrawIsPlayingWarning(); + GUI.enabled = !Application.isPlaying; + + DrawSynchronizePositionHeader(); + DrawSynchronizePositionData(); + + GUI.enabled = !Application.isPlaying; + DrawSynchronizeRotationHeader(); + DrawSynchronizeRotationData(); + + GUI.enabled = !Application.isPlaying; + DrawSynchronizeScaleHeader(); + DrawSynchronizeScaleData(); + + serializedObject.ApplyModifiedProperties(); + + GUI.enabled = true; + } + + private void DrawIsPlayingWarning() + { + if (Application.isPlaying == false) + { + return; + } + + GUILayout.BeginVertical(GUI.skin.box); + { + GUILayout.Label("Editing is disabled in play mode so the two objects don't go out of sync"); + } + GUILayout.EndVertical(); + } + + private void SetupSerializedProperties() + { + this.m_SynchronizePositionProperty = serializedObject.FindProperty("m_PositionModel.SynchronizeEnabled"); + this.m_SynchronizeRotationProperty = serializedObject.FindProperty("m_RotationModel.SynchronizeEnabled"); + this.m_SynchronizeScaleProperty = serializedObject.FindProperty("m_ScaleModel.SynchronizeEnabled"); + } + + private void DrawSynchronizePositionHeader() + { + DrawHeader("Synchronize Position", this.m_SynchronizePositionProperty); + } + + private void DrawSynchronizePositionData() + { + if (this.m_SynchronizePositionProperty == null || this.m_SynchronizePositionProperty.boolValue == false) + { + return; + } + + SerializedProperty interpolatePositionProperty = serializedObject.FindProperty("m_PositionModel.InterpolateOption"); + PhotonTransformViewPositionModel.InterpolateOptions interpolateOption = (PhotonTransformViewPositionModel.InterpolateOptions)interpolatePositionProperty.enumValueIndex; + + SerializedProperty extrapolatePositionProperty = serializedObject.FindProperty("m_PositionModel.ExtrapolateOption"); + PhotonTransformViewPositionModel.ExtrapolateOptions extrapolateOption = (PhotonTransformViewPositionModel.ExtrapolateOptions)extrapolatePositionProperty.enumValueIndex; + + float containerHeight = 155; + + switch (interpolateOption) + { + case PhotonTransformViewPositionModel.InterpolateOptions.FixedSpeed: + case PhotonTransformViewPositionModel.InterpolateOptions.Lerp: + containerHeight += EDITOR_LINE_HEIGHT; + break; + /*case PhotonTransformViewPositionModel.InterpolateOptions.MoveTowardsComplex: + containerHeight += EDITOR_LINE_HEIGHT*3; + break;*/ + } + + if (extrapolateOption != PhotonTransformViewPositionModel.ExtrapolateOptions.Disabled) + { + containerHeight += EDITOR_LINE_HEIGHT; + } + + switch (extrapolateOption) + { + case PhotonTransformViewPositionModel.ExtrapolateOptions.FixedSpeed: + containerHeight += EDITOR_LINE_HEIGHT; + break; + } + + if (this.m_InterpolateHelpOpen == true) + { + containerHeight += GetInterpolateHelpBoxHeight(); + } + + if (this.m_ExtrapolateHelpOpen == true) + { + containerHeight += GetExtrapolateHelpBoxHeight(); + } + + // removed Gizmo Options. -3 lines, -1 splitter + containerHeight -= EDITOR_LINE_HEIGHT * 2; + + Rect rect = PhotonGUI.ContainerBody(containerHeight); + + Rect propertyRect = new Rect(rect.xMin + 5, rect.yMin + 2, rect.width - 10, EditorGUIUtility.singleLineHeight); + + DrawTeleport(ref propertyRect); + DrawSplitter(ref propertyRect); + + DrawSynchronizePositionDataInterpolation(ref propertyRect, interpolatePositionProperty, interpolateOption); + DrawSplitter(ref propertyRect); + + DrawSynchronizePositionDataExtrapolation(ref propertyRect, extrapolatePositionProperty, extrapolateOption); + DrawSplitter(ref propertyRect); + + DrawSynchronizePositionDataGizmos(ref propertyRect); + } + + private float GetInterpolateHelpBoxHeight() + { + return PhotonGUI.RichLabel.CalcHeight(new GUIContent(INTERPOLATE_HELP), Screen.width - 54) + 35; + } + + private float GetExtrapolateHelpBoxHeight() + { + return PhotonGUI.RichLabel.CalcHeight(new GUIContent(EXTRAPOLATE_HELP), Screen.width - 54) + 35; + } + + private void DrawSplitter(ref Rect propertyRect) + { + Rect splitterRect = new Rect(propertyRect.xMin - 3, propertyRect.yMin, propertyRect.width + 6, 1); + PhotonGUI.DrawSplitter(splitterRect); + + propertyRect.y += 5; + } + + private void DrawSynchronizePositionDataGizmos(ref Rect propertyRect) + { + GUI.enabled = true; + /*PhotonGUI.DrawGizmoOptions(propertyRect, "Synchronized Position Gizmo", + serializedObject.FindProperty("m_PositionModel.DrawNetworkGizmo"), + serializedObject.FindProperty("m_PositionModel.NetworkGizmoColor"), + serializedObject.FindProperty("m_PositionModel.NetworkGizmoType"), + serializedObject.FindProperty("m_PositionModel.NetworkGizmoSize")); + propertyRect.y += EDITOR_LINE_HEIGHT; + + PhotonGUI.DrawGizmoOptions(propertyRect, "Extrapolated Position Gizmo", + serializedObject.FindProperty("m_PositionModel.DrawExtrapolatedGizmo"), + serializedObject.FindProperty("m_PositionModel.ExtrapolatedGizmoColor"), + serializedObject.FindProperty("m_PositionModel.ExtrapolatedGizmoType"), + serializedObject.FindProperty("m_PositionModel.ExtrapolatedGizmoSize")); + propertyRect.y += EDITOR_LINE_HEIGHT;*/ + + EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_PositionModel.DrawErrorGizmo"), + new GUIContent("Draw synchronized position error")); + propertyRect.y += EDITOR_LINE_HEIGHT; + } + + private void DrawHelpBox(ref Rect propertyRect, bool isOpen, float height, string helpText, string url) + { + if (isOpen == true) + { + Rect helpRect = new Rect(propertyRect.xMin, propertyRect.yMin, propertyRect.width, height - 5); + GUI.BeginGroup(helpRect, GUI.skin.box); + GUI.Label(new Rect(5, 5, propertyRect.width - 10, height - 30), helpText, PhotonGUI.RichLabel); + if (GUI.Button(new Rect(5, height - 30, propertyRect.width - 10, 20), "Read more in our documentation")) + { + Application.OpenURL(url); + } + GUI.EndGroup(); + + propertyRect.y += height; + } + } + + private void DrawPropertyWithHelpIcon(ref Rect propertyRect, ref bool isHelpOpen, SerializedProperty property, string tooltip) + { + Rect propertyFieldRect = new Rect(propertyRect.xMin, propertyRect.yMin, propertyRect.width - 20, propertyRect.height); + string propertyName = ObjectNames.NicifyVariableName(property.name); + EditorGUI.PropertyField(propertyFieldRect, property, new GUIContent(propertyName, tooltip)); + + Rect helpIconRect = new Rect(propertyFieldRect.xMax + 5, propertyFieldRect.yMin, 20, propertyFieldRect.height); + isHelpOpen = GUI.Toggle(helpIconRect, isHelpOpen, PhotonGUI.HelpIcon, GUIStyle.none); + + propertyRect.y += EDITOR_LINE_HEIGHT; + } + + private void DrawSynchronizePositionDataExtrapolation(ref Rect propertyRect, SerializedProperty extrapolatePositionProperty, PhotonTransformViewPositionModel.ExtrapolateOptions extrapolateOption) + { + DrawPropertyWithHelpIcon(ref propertyRect, ref this.m_ExtrapolateHelpOpen, extrapolatePositionProperty, EXTRAPOLATE_TOOLTIP); + DrawHelpBox(ref propertyRect, this.m_ExtrapolateHelpOpen, GetExtrapolateHelpBoxHeight(), EXTRAPOLATE_HELP, EXTRAPOLATE_HELP_URL); + + if (extrapolateOption != PhotonTransformViewPositionModel.ExtrapolateOptions.Disabled) + { + EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_PositionModel.ExtrapolateIncludingRoundTripTime")); + propertyRect.y += EDITOR_LINE_HEIGHT; + } + + switch (extrapolateOption) + { + case PhotonTransformViewPositionModel.ExtrapolateOptions.FixedSpeed: + EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_PositionModel.ExtrapolateSpeed")); + propertyRect.y += EDITOR_LINE_HEIGHT; + break; + } + } + + private void DrawTeleport(ref Rect propertyRect) + { + EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_PositionModel.TeleportEnabled"), + new GUIContent("Enable teleport for great distances")); + propertyRect.y += EDITOR_LINE_HEIGHT; + + EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_PositionModel.TeleportIfDistanceGreaterThan"), + new GUIContent("Teleport if distance greater than")); + propertyRect.y += EDITOR_LINE_HEIGHT; + } + + private void DrawSynchronizePositionDataInterpolation(ref Rect propertyRect, SerializedProperty interpolatePositionProperty, + PhotonTransformViewPositionModel.InterpolateOptions interpolateOption) + { + DrawPropertyWithHelpIcon(ref propertyRect, ref this.m_InterpolateHelpOpen, interpolatePositionProperty, INTERPOLATE_TOOLTIP); + DrawHelpBox(ref propertyRect, this.m_InterpolateHelpOpen, GetInterpolateHelpBoxHeight(), INTERPOLATE_HELP, INTERPOLATE_HELP_URL); + + switch (interpolateOption) + { + case PhotonTransformViewPositionModel.InterpolateOptions.FixedSpeed: + EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_PositionModel.InterpolateMoveTowardsSpeed"), + new GUIContent("MoveTowards Speed")); + propertyRect.y += EDITOR_LINE_HEIGHT; + break; + + case PhotonTransformViewPositionModel.InterpolateOptions.Lerp: + EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_PositionModel.InterpolateLerpSpeed"), new GUIContent("Lerp Speed")); + propertyRect.y += EDITOR_LINE_HEIGHT; + break; + + /*case PhotonTransformViewPositionModel.InterpolateOptions.MoveTowardsComplex: + Rect curveRect = new Rect(propertyRect.xMin, propertyRect.yMin, propertyRect.width - 100, propertyRect.height); + EditorGUI.PropertyField(curveRect, serializedObject.FindProperty("m_PositionModel.InterpolateSpeedCurve"), new GUIContent("MoveTowards Speed Curve")); + + Rect labelRect = new Rect(propertyRect.xMax - 95, propertyRect.yMin, 10, propertyRect.height); + GUI.Label(labelRect, "x"); + + Rect multiplierRect = new Rect(propertyRect.xMax - 80, propertyRect.yMin, 80, propertyRect.height); + EditorGUI.PropertyField(multiplierRect, serializedObject.FindProperty("m_PositionModel.InterpolateMoveTowardsSpeed"), GUIContent.none); + propertyRect.y += EDITOR_LINE_HEIGHT; + + EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_PositionModel.InterpolateMoveTowardsAcceleration"), + new GUIContent("Acceleration")); + propertyRect.y += EDITOR_LINE_HEIGHT; + + EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_PositionModel.InterpolateMoveTowardsDeceleration"), + new GUIContent("Deceleration")); + propertyRect.y += EDITOR_LINE_HEIGHT; + break;*/ + } + } + + private void DrawSynchronizeRotationHeader() + { + DrawHeader("Synchronize Rotation", this.m_SynchronizeRotationProperty); + } + + private void DrawSynchronizeRotationData() + { + if (this.m_SynchronizeRotationProperty == null || this.m_SynchronizeRotationProperty.boolValue == false) + { + return; + } + + SerializedProperty interpolateRotationProperty = serializedObject.FindProperty("m_RotationModel.InterpolateOption"); + PhotonTransformViewRotationModel.InterpolateOptions interpolateOption = + (PhotonTransformViewRotationModel.InterpolateOptions) interpolateRotationProperty.enumValueIndex; + + float containerHeight = 20; + + switch (interpolateOption) + { + case PhotonTransformViewRotationModel.InterpolateOptions.RotateTowards: + case PhotonTransformViewRotationModel.InterpolateOptions.Lerp: + containerHeight += EDITOR_LINE_HEIGHT; + break; + } + + if (this.m_InterpolateRotationHelpOpen == true) + { + containerHeight += GetInterpolateHelpBoxHeight(); + } + + Rect rect = PhotonGUI.ContainerBody(containerHeight); + Rect propertyRect = new Rect(rect.xMin + 5, rect.yMin + 2, rect.width - 10, EditorGUIUtility.singleLineHeight); + + DrawPropertyWithHelpIcon(ref propertyRect, ref this.m_InterpolateRotationHelpOpen, interpolateRotationProperty, INTERPOLATE_TOOLTIP); + DrawHelpBox(ref propertyRect, this.m_InterpolateRotationHelpOpen, GetInterpolateHelpBoxHeight(), INTERPOLATE_HELP, INTERPOLATE_HELP_URL); + + switch (interpolateOption) + { + case PhotonTransformViewRotationModel.InterpolateOptions.RotateTowards: + EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_RotationModel.InterpolateRotateTowardsSpeed"), + new GUIContent("RotateTowards Speed")); + break; + case PhotonTransformViewRotationModel.InterpolateOptions.Lerp: + EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_RotationModel.InterpolateLerpSpeed"), new GUIContent("Lerp Speed")); + break; + } + } + + private void DrawSynchronizeScaleHeader() + { + DrawHeader("Synchronize Scale", this.m_SynchronizeScaleProperty); + } + + private void DrawSynchronizeScaleData() + { + if (this.m_SynchronizeScaleProperty == null || this.m_SynchronizeScaleProperty.boolValue == false) + { + return; + } + + SerializedProperty interpolateScaleProperty = serializedObject.FindProperty("m_ScaleModel.InterpolateOption"); + PhotonTransformViewScaleModel.InterpolateOptions interpolateOption = (PhotonTransformViewScaleModel.InterpolateOptions) interpolateScaleProperty.enumValueIndex; + + float containerHeight = EDITOR_LINE_HEIGHT; + + switch (interpolateOption) + { + case PhotonTransformViewScaleModel.InterpolateOptions.MoveTowards: + case PhotonTransformViewScaleModel.InterpolateOptions.Lerp: + containerHeight += EDITOR_LINE_HEIGHT; + break; + } + + if (this.m_InterpolateScaleHelpOpen == true) + { + containerHeight += GetInterpolateHelpBoxHeight(); + } + + Rect rect = PhotonGUI.ContainerBody(containerHeight); + Rect propertyRect = new Rect(rect.xMin + 5, rect.yMin + 2, rect.width - 10, EditorGUIUtility.singleLineHeight); + + DrawPropertyWithHelpIcon(ref propertyRect, ref this.m_InterpolateScaleHelpOpen, interpolateScaleProperty, INTERPOLATE_TOOLTIP); + DrawHelpBox(ref propertyRect, this.m_InterpolateScaleHelpOpen, GetInterpolateHelpBoxHeight(), INTERPOLATE_HELP, INTERPOLATE_HELP_URL); + + switch (interpolateOption) + { + case PhotonTransformViewScaleModel.InterpolateOptions.MoveTowards: + EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_ScaleModel.InterpolateMoveTowardsSpeed"), + new GUIContent("MoveTowards Speed")); + break; + case PhotonTransformViewScaleModel.InterpolateOptions.Lerp: + EditorGUI.PropertyField(propertyRect, serializedObject.FindProperty("m_ScaleModel.InterpolateLerpSpeed"), new GUIContent("Lerp Speed")); + break; + } + } + + private void DrawHeader(string label, SerializedProperty property) + { + if (property == null) + { + return; + } + + bool newValue = PhotonGUI.ContainerHeaderToggle(label, property.boolValue); + + if (newValue != property.boolValue) + { + property.boolValue = newValue; + property.serializedObject.ApplyModifiedProperties(); + } + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonTransformViewEditor.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonTransformViewEditor.cs.meta new file mode 100644 index 0000000..58d59ef --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/Views/PhotonTransformViewEditor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 22292ca8ffb574945bedfaf49266672e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/background.jpg b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/background.jpg new file mode 100644 index 0000000..74d3ce8 Binary files /dev/null and b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/background.jpg differ diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/background.jpg.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/background.jpg.meta new file mode 100644 index 0000000..48f073e --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/background.jpg.meta @@ -0,0 +1,45 @@ +fileFormatVersion: 2 +guid: 1faa1cf0448470c4ebbb23b97759ab50 +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 256 + textureSettings: + filterMode: 0 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/help.png b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/help.png new file mode 100644 index 0000000..a421667 Binary files /dev/null and b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/help.png differ diff --git a/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/help.png.meta b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/help.png.meta new file mode 100644 index 0000000..cb312ac --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Editor/PhotonNetwork/help.png.meta @@ -0,0 +1,45 @@ +fileFormatVersion: 2 +guid: 9f1212502533cb34188dd6ef094188cb +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 1024 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/PhotonCloud-icon.png b/Close Enough!/Assets/Photon Unity Networking/PhotonCloud-icon.png new file mode 100644 index 0000000..aff02a4 Binary files /dev/null and b/Close Enough!/Assets/Photon Unity Networking/PhotonCloud-icon.png differ diff --git a/Close Enough!/Assets/Photon Unity Networking/PhotonCloud-icon.png.meta b/Close Enough!/Assets/Photon Unity Networking/PhotonCloud-icon.png.meta new file mode 100644 index 0000000..230f109 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/PhotonCloud-icon.png.meta @@ -0,0 +1,38 @@ +fileFormatVersion: 2 +guid: 8425b95fef16c3f4194e3a20e245cb67 +labels: +- ExitGames +- PUN +- Photon +- Networking +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + textureFormat: -1 + maxTextureSize: 128 + textureSettings: + filterMode: 0 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + textureType: 2 + buildTargetSettings: [] diff --git a/Close Enough!/Assets/Photon Unity Networking/PhotonNetwork-Documentation.chm b/Close Enough!/Assets/Photon Unity Networking/PhotonNetwork-Documentation.chm new file mode 100644 index 0000000..16113d8 Binary files /dev/null and b/Close Enough!/Assets/Photon Unity Networking/PhotonNetwork-Documentation.chm differ diff --git a/Close Enough!/Assets/Photon Unity Networking/PhotonNetwork-Documentation.chm.meta b/Close Enough!/Assets/Photon Unity Networking/PhotonNetwork-Documentation.chm.meta new file mode 100644 index 0000000..1e4153f --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/PhotonNetwork-Documentation.chm.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: d93cfd57d52f80543b09a3f2ce724f84 diff --git a/Close Enough!/Assets/Photon Unity Networking/PhotonNetwork-Documentation.pdf b/Close Enough!/Assets/Photon Unity Networking/PhotonNetwork-Documentation.pdf new file mode 100644 index 0000000..dcc6b6e Binary files /dev/null and b/Close Enough!/Assets/Photon Unity Networking/PhotonNetwork-Documentation.pdf differ diff --git a/Close Enough!/Assets/Photon Unity Networking/PhotonNetwork-Documentation.pdf.meta b/Close Enough!/Assets/Photon Unity Networking/PhotonNetwork-Documentation.pdf.meta new file mode 100644 index 0000000..187227e --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/PhotonNetwork-Documentation.pdf.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f226ce9e7a33bc24c95f34dd9f583516 +labels: +- ExitGames +- PUN +- Photon +- Networking diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins.meta new file mode 100644 index 0000000..dc9f1ec --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 5560882d95bc746dcb7540862e1a7507 +folderAsset: yes +timeCreated: 1525372511 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork.meta new file mode 100644 index 0000000..826a704 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: c9ae73e8371f046b3be4d69c0908ee7f +folderAsset: yes +timeCreated: 1525372512 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/CustomTypes.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/CustomTypes.cs new file mode 100644 index 0000000..077a6b4 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/CustomTypes.cs @@ -0,0 +1,177 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2011 Exit Games GmbH +// +// +// +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +#pragma warning disable 1587 +/// \file +/// Sets up support for Unity-specific types. Can be a blueprint how to register your own Custom Types for sending. +#pragma warning restore 1587 + + +using ExitGames.Client.Photon; +using UnityEngine; + + +/// +/// Internally used class, containing de/serialization methods for various Unity-specific classes. +/// Adding those to the Photon serialization protocol allows you to send them in events, etc. +/// +internal static class CustomTypes +{ + /// Register + internal static void Register() + { + PhotonPeer.RegisterType(typeof(Vector2), (byte)'W', SerializeVector2, DeserializeVector2); + PhotonPeer.RegisterType(typeof(Vector3), (byte)'V', SerializeVector3, DeserializeVector3); + PhotonPeer.RegisterType(typeof(Quaternion), (byte)'Q', SerializeQuaternion, DeserializeQuaternion); + PhotonPeer.RegisterType(typeof(PhotonPlayer), (byte)'P', SerializePhotonPlayer, DeserializePhotonPlayer); + } + + + #region Custom De/Serializer Methods + + + public static readonly byte[] memVector3 = new byte[3 * 4]; + private static short SerializeVector3(StreamBuffer outStream, object customobject) + { + Vector3 vo = (Vector3)customobject; + + int index = 0; + lock (memVector3) + { + byte[] bytes = memVector3; + Protocol.Serialize(vo.x, bytes, ref index); + Protocol.Serialize(vo.y, bytes, ref index); + Protocol.Serialize(vo.z, bytes, ref index); + outStream.Write(bytes, 0, 3 * 4); + } + + return 3 * 4; + } + + private static object DeserializeVector3(StreamBuffer inStream, short length) + { + Vector3 vo = new Vector3(); + lock (memVector3) + { + inStream.Read(memVector3, 0, 3 * 4); + int index = 0; + Protocol.Deserialize(out vo.x, memVector3, ref index); + Protocol.Deserialize(out vo.y, memVector3, ref index); + Protocol.Deserialize(out vo.z, memVector3, ref index); + } + + return vo; + } + + + public static readonly byte[] memVector2 = new byte[2 * 4]; + private static short SerializeVector2(StreamBuffer outStream, object customobject) + { + Vector2 vo = (Vector2)customobject; + lock (memVector2) + { + byte[] bytes = memVector2; + int index = 0; + Protocol.Serialize(vo.x, bytes, ref index); + Protocol.Serialize(vo.y, bytes, ref index); + outStream.Write(bytes, 0, 2 * 4); + } + + return 2 * 4; + } + + private static object DeserializeVector2(StreamBuffer inStream, short length) + { + Vector2 vo = new Vector2(); + lock (memVector2) + { + inStream.Read(memVector2, 0, 2 * 4); + int index = 0; + Protocol.Deserialize(out vo.x, memVector2, ref index); + Protocol.Deserialize(out vo.y, memVector2, ref index); + } + + return vo; + } + + + public static readonly byte[] memQuarternion = new byte[4 * 4]; + private static short SerializeQuaternion(StreamBuffer outStream, object customobject) + { + Quaternion o = (Quaternion)customobject; + + lock (memQuarternion) + { + byte[] bytes = memQuarternion; + int index = 0; + Protocol.Serialize(o.w, bytes, ref index); + Protocol.Serialize(o.x, bytes, ref index); + Protocol.Serialize(o.y, bytes, ref index); + Protocol.Serialize(o.z, bytes, ref index); + outStream.Write(bytes, 0, 4 * 4); + } + + return 4 * 4; + } + + private static object DeserializeQuaternion(StreamBuffer inStream, short length) + { + Quaternion o = new Quaternion(); + + lock (memQuarternion) + { + inStream.Read(memQuarternion, 0, 4 * 4); + int index = 0; + Protocol.Deserialize(out o.w, memQuarternion, ref index); + Protocol.Deserialize(out o.x, memQuarternion, ref index); + Protocol.Deserialize(out o.y, memQuarternion, ref index); + Protocol.Deserialize(out o.z, memQuarternion, ref index); + } + + return o; + } + + public static readonly byte[] memPlayer = new byte[4]; + private static short SerializePhotonPlayer(StreamBuffer outStream, object customobject) + { + int ID = ((PhotonPlayer)customobject).ID; + + lock (memPlayer) + { + byte[] bytes = memPlayer; + int off = 0; + Protocol.Serialize(ID, bytes, ref off); + outStream.Write(bytes, 0, 4); + return 4; + } + } + + private static object DeserializePhotonPlayer(StreamBuffer inStream, short length) + { + int ID; + lock (memPlayer) + { + inStream.Read(memPlayer, 0, length); + int off = 0; + Protocol.Deserialize(out ID, memPlayer, ref off); + } + + if (PhotonNetwork.networkingPeer.mActors.ContainsKey(ID)) + { + return PhotonNetwork.networkingPeer.mActors[ID]; + } + else + { + return null; + } + } + + #endregion +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/CustomTypes.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/CustomTypes.cs.meta new file mode 100644 index 0000000..82e3a5c --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/CustomTypes.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ab517bd36a2b2504b83979fcad45d4a2 +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Enums.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Enums.cs new file mode 100644 index 0000000..b724768 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Enums.cs @@ -0,0 +1,598 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2011 Exit Games GmbH +// +// +// +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +#pragma warning disable 1587 +/// \file +/// Wraps up several of the commonly used enumerations. +#pragma warning restore 1587 + + +using System; +using ExitGames.Client.Photon; + + +/// +/// This enum defines the set of MonoMessages Photon Unity Networking is using as callbacks. Implemented by PunBehaviour. +/// +/// +/// Much like "Update()" in Unity, PUN will call methods in specific situations. +/// Often, these methods are triggered when network operations complete (example: when joining a room). +/// +/// All those methods are defined and described in this enum and implemented by PunBehaviour +/// (which makes it easy to implement them as override). +/// +/// Each entry is the name of such a method and the description tells you when it gets used by PUN. +/// +/// Make sure to read the remarks per entry as some methods have optional parameters. +/// +/// \ingroup publicApi +public enum PhotonNetworkingMessage +{ + /// + /// Called when the initial connection got established but before you can use the server. OnJoinedLobby() or OnConnectedToMaster() are called when PUN is ready. + /// + /// + /// This callback is only useful to detect if the server can be reached at all (technically). + /// Most often, it's enough to implement OnFailedToConnectToPhoton() and OnDisconnectedFromPhoton(). + /// + /// OnJoinedLobby() or OnConnectedToMaster() are called when PUN is ready. + /// + /// When this is called, the low level connection is established and PUN will send your AppId, the user, etc in the background. + /// This is not called for transitions from the masterserver to game servers. + /// + /// Example: void OnConnectedToPhoton() { ... } + /// + OnConnectedToPhoton, + + /// + /// Called when the local user/client left a room. + /// + /// + /// When leaving a room, PUN brings you back to the Master Server. + /// Before you can use lobbies and join or create rooms, OnJoinedLobby() or OnConnectedToMaster() will get called again. + /// + /// Example: void OnLeftRoom() { ... } + /// + OnLeftRoom, + + /// + /// Called after switching to a new MasterClient when the current one leaves. + /// + /// + /// This is not called when this client enters a room. + /// The former MasterClient is still in the player list when this method get called. + /// + /// Example: void OnMasterClientSwitched(PhotonPlayer newMasterClient) { ... } + /// + OnMasterClientSwitched, + + /// + /// Called when a CreateRoom() call failed. Optional parameters provide ErrorCode and message. + /// + /// + /// Most likely because the room name is already in use (some other client was faster than you). + /// PUN logs some info if the PhotonNetwork.logLevel is >= PhotonLogLevel.Informational. + /// + /// Example: void OnPhotonCreateRoomFailed() { ... } + /// + /// Example: void OnPhotonCreateRoomFailed(object[] codeAndMsg) { // codeAndMsg[0] is short ErrorCode. codeAndMsg[1] is string debug msg. } + /// + OnPhotonCreateRoomFailed, + + /// + /// Called when a JoinRoom() call failed. Optional parameters provide ErrorCode and message. + /// + /// + /// Most likely error is that the room does not exist or the room is full (some other client was faster than you). + /// PUN logs some info if the PhotonNetwork.logLevel is >= PhotonLogLevel.Informational. + /// + /// Example: void OnPhotonJoinRoomFailed() { ... } + /// + /// Example: void OnPhotonJoinRoomFailed(object[] codeAndMsg) { // codeAndMsg[0] is short ErrorCode. codeAndMsg[1] is string debug msg. } + /// + OnPhotonJoinRoomFailed, + + /// + /// Called when this client created a room and entered it. OnJoinedRoom() will be called as well. + /// + /// + /// This callback is only called on the client which created a room (see PhotonNetwork.CreateRoom). + /// + /// As any client might close (or drop connection) anytime, there is a chance that the + /// creator of a room does not execute OnCreatedRoom. + /// + /// If you need specific room properties or a "start signal", it is safer to implement + /// OnMasterClientSwitched() and to make the new MasterClient check the room's state. + /// + /// Example: void OnCreatedRoom() { ... } + /// + OnCreatedRoom, + + /// + /// Called on entering a lobby on the Master Server. The actual room-list updates will call OnReceivedRoomListUpdate(). + /// + /// + /// Note: When PhotonNetwork.autoJoinLobby is false, OnConnectedToMaster() will be called and the room list won't become available. + /// + /// While in the lobby, the roomlist is automatically updated in fixed intervals (which you can't modify). + /// The room list gets available when OnReceivedRoomListUpdate() gets called after OnJoinedLobby(). + /// + /// Example: void OnJoinedLobby() { ... } + /// + OnJoinedLobby, + + /// + /// Called after leaving a lobby. + /// + /// + /// When you leave a lobby, [CreateRoom](@ref PhotonNetwork.CreateRoom) and [JoinRandomRoom](@ref PhotonNetwork.JoinRandomRoom) + /// automatically refer to the default lobby. + /// + /// Example: void OnLeftLobby() { ... } + /// + OnLeftLobby, + + /// + /// Called after disconnecting from the Photon server. + /// + /// + /// In some cases, other callbacks are called before OnDisconnectedFromPhoton is called. + /// Examples: OnConnectionFail() and OnFailedToConnectToPhoton(). + /// + /// Example: void OnDisconnectedFromPhoton() { ... } + /// + OnDisconnectedFromPhoton, + + /// + /// Called when something causes the connection to fail (after it was established), followed by a call to OnDisconnectedFromPhoton(). + /// + /// + /// If the server could not be reached in the first place, OnFailedToConnectToPhoton is called instead. + /// The reason for the error is provided as StatusCode. + /// + /// Example: void OnConnectionFail(DisconnectCause cause) { ... } + /// + OnConnectionFail, + + /// + /// Called if a connect call to the Photon server failed before the connection was established, followed by a call to OnDisconnectedFromPhoton(). + /// + /// + /// OnConnectionFail only gets called when a connection to a Photon server was established in the first place. + /// + /// Example: void OnFailedToConnectToPhoton(DisconnectCause cause) { ... } + /// + OnFailedToConnectToPhoton, + + /// + /// Called for any update of the room-listing while in a lobby (PhotonNetwork.insideLobby) on the Master Server + /// or when a response is received for PhotonNetwork.GetCustomRoomList(). + /// + /// + /// PUN provides the list of rooms by PhotonNetwork.GetRoomList().
+ /// Each item is a RoomInfo which might include custom properties (provided you defined those as lobby-listed when creating a room). + /// + /// Not all types of lobbies provide a listing of rooms to the client. Some are silent and specialized for server-side matchmaking. + /// + /// Example: void OnReceivedRoomListUpdate() { ... } + ///
+ OnReceivedRoomListUpdate, + + /// + /// Called when entering a room (by creating or joining it). Called on all clients (including the Master Client). + /// + /// + /// This method is commonly used to instantiate player characters. + /// If a match has to be started "actively", you can instead call an [PunRPC](@ref PhotonView.RPC) triggered by a user's button-press or a timer. + /// + /// When this is called, you can usually already access the existing players in the room via PhotonNetwork.playerList. + /// Also, all custom properties should be already available as Room.customProperties. Check Room.playerCount to find out if + /// enough players are in the room to start playing. + /// + /// Example: void OnJoinedRoom() { ... } + /// + OnJoinedRoom, + + /// + /// Called when a remote player entered the room. This PhotonPlayer is already added to the playerlist at this time. + /// + /// + /// If your game starts with a certain number of players, this callback can be useful to check the + /// Room.playerCount and find out if you can start. + /// + /// Example: void OnPhotonPlayerConnected(PhotonPlayer newPlayer) { ... } + /// + OnPhotonPlayerConnected, + + /// + /// Called when a remote player left the room. This PhotonPlayer is already removed from the playerlist at this time. + /// + /// + /// When your client calls PhotonNetwork.leaveRoom, PUN will call this method on the remaining clients. + /// When a remote client drops connection or gets closed, this callback gets executed. after a timeout + /// of several seconds. + /// + /// Example: void OnPhotonPlayerDisconnected(PhotonPlayer otherPlayer) { ... } + /// + OnPhotonPlayerDisconnected, + + /// + /// Called after a JoinRandom() call failed. Optional parameters provide ErrorCode and message. + /// + /// + /// Most likely all rooms are full or no rooms are available. + /// When using multiple lobbies (via JoinLobby or TypedLobby), another lobby might have more/fitting rooms. + /// PUN logs some info if the PhotonNetwork.logLevel is >= PhotonLogLevel.Informational. + /// + /// Example: void OnPhotonRandomJoinFailed() { ... } + /// + /// Example: void OnPhotonRandomJoinFailed(object[] codeAndMsg) { // codeAndMsg[0] is short ErrorCode. codeAndMsg[1] is string debug msg. } + /// + OnPhotonRandomJoinFailed, + + /// + /// Called after the connection to the master is established and authenticated but only when PhotonNetwork.autoJoinLobby is false. + /// + /// + /// If you set PhotonNetwork.autoJoinLobby to true, OnJoinedLobby() will be called instead of this. + /// + /// You can join rooms and create them even without being in a lobby. The default lobby is used in that case. + /// The list of available rooms won't become available unless you join a lobby via PhotonNetwork.joinLobby. + /// + /// Example: void OnConnectedToMaster() { ... } + /// + OnConnectedToMaster, + + /// + /// Implement to customize the data a PhotonView regularly synchronizes. Called every 'network-update' when observed by PhotonView. + /// + /// + /// This method will be called in scripts that are assigned as Observed component of a PhotonView. + /// PhotonNetwork.sendRateOnSerialize affects how often this method is called. + /// PhotonNetwork.sendRate affects how often packages are sent by this client. + /// + /// Implementing this method, you can customize which data a PhotonView regularly synchronizes. + /// Your code defines what is being sent (content) and how your data is used by receiving clients. + /// + /// Unlike other callbacks, OnPhotonSerializeView only gets called when it is assigned + /// to a PhotonView as PhotonView.observed script. + /// + /// To make use of this method, the PhotonStream is essential. It will be in "writing" mode" on the + /// client that controls a PhotonView (PhotonStream.isWriting == true) and in "reading mode" on the + /// remote clients that just receive that the controlling client sends. + /// + /// If you skip writing any value into the stream, PUN will skip the update. Used carefully, this can + /// conserve bandwidth and messages (which have a limit per room/second). + /// + /// Note that OnPhotonSerializeView is not called on remote clients when the sender does not send + /// any update. This can't be used as "x-times per second Update()". + /// + /// Example: void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) { ... } + /// + OnPhotonSerializeView, + + /// + /// Called on all scripts on a GameObject (and children) that have been Instantiated using PhotonNetwork.Instantiate. + /// + /// + /// PhotonMessageInfo parameter provides info about who created the object and when (based off PhotonNetworking.time). + /// + /// Example: void OnPhotonInstantiate(PhotonMessageInfo info) { ... } + /// + OnPhotonInstantiate, + + /// + /// Because the concurrent user limit was (temporarily) reached, this client is rejected by the server and disconnecting. + /// + /// + /// When this happens, the user might try again later. You can't create or join rooms in OnPhotonMaxCcuReached(), cause the client will be disconnecting. + /// You can raise the CCU limits with a new license (when you host yourself) or extended subscription (when using the Photon Cloud). + /// The Photon Cloud will mail you when the CCU limit was reached. This is also visible in the Dashboard (webpage). + /// + /// Example: void OnPhotonMaxCccuReached() { ... } + /// + OnPhotonMaxCccuReached, + + /// + /// Called when a room's custom properties changed. The propertiesThatChanged contains all that was set via Room.SetCustomProperties. + /// + /// + /// Since v1.25 this method has one parameter: Hashtable propertiesThatChanged. + /// Changing properties must be done by Room.SetCustomProperties, which causes this callback locally, too. + /// + /// Example: void OnPhotonCustomRoomPropertiesChanged(Hashtable propertiesThatChanged) { ... } + /// + OnPhotonCustomRoomPropertiesChanged, + + /// + /// Called when custom player-properties are changed. Player and the changed properties are passed as object[]. + /// + /// + /// Since v1.25 this method has one parameter: object[] playerAndUpdatedProps, which contains two entries.
+ /// [0] is the affected PhotonPlayer.
+ /// [1] is the Hashtable of properties that changed.
+ /// + /// We are using a object[] due to limitations of Unity's GameObject.SendMessage (which has only one optional parameter). + /// + /// Changing properties must be done by PhotonPlayer.SetCustomProperties, which causes this callback locally, too. + /// + /// Example:
+    /// void OnPhotonPlayerPropertiesChanged(object[] playerAndUpdatedProps) {
+    ///     PhotonPlayer player = playerAndUpdatedProps[0] as PhotonPlayer;
+    ///     Hashtable props = playerAndUpdatedProps[1] as Hashtable;
+    ///     //...
+    /// }
+ ///
+ OnPhotonPlayerPropertiesChanged, + + /// + /// Called when the server sent the response to a FindFriends request and updated PhotonNetwork.Friends. + /// + /// + /// The friends list is available as PhotonNetwork.Friends, listing name, online state and + /// the room a user is in (if any). + /// + /// Example: void OnUpdatedFriendList() { ... } + /// + OnUpdatedFriendList, + + /// + /// Called when the custom authentication failed. Followed by disconnect! + /// + /// + /// Custom Authentication can fail due to user-input, bad tokens/secrets. + /// If authentication is successful, this method is not called. Implement OnJoinedLobby() or OnConnectedToMaster() (as usual). + /// + /// During development of a game, it might also fail due to wrong configuration on the server side. + /// In those cases, logging the debugMessage is very important. + /// + /// Unless you setup a custom authentication service for your app (in the [Dashboard](https://www.photonengine.com/dashboard)), + /// this won't be called! + /// + /// Example: void OnCustomAuthenticationFailed(string debugMessage) { ... } + /// + OnCustomAuthenticationFailed, + + /// + /// Called when your Custom Authentication service responds with additional data. + /// + /// + /// Custom Authentication services can include some custom data in their response. + /// When present, that data is made available in this callback as Dictionary. + /// While the keys of your data have to be strings, the values can be either string or a number (in Json). + /// You need to make extra sure, that the value type is the one you expect. Numbers become (currently) int64. + /// + /// Example: void OnCustomAuthenticationResponse(Dictionary<string, object> data) { ... } + /// + /// + OnCustomAuthenticationResponse, + + /// + /// Called by PUN when the response to a WebRPC is available. See PhotonNetwork.WebRPC. + /// + /// + /// Important: The response.ReturnCode is 0 if Photon was able to reach your web-service. + /// The content of the response is what your web-service sent. You can create a WebResponse instance from it. + /// Example: WebRpcResponse webResponse = new WebRpcResponse(operationResponse); + /// + /// Please note: Class OperationResponse is in a namespace which needs to be "used": + /// using ExitGames.Client.Photon; // includes OperationResponse (and other classes) + /// + /// The OperationResponse.ReturnCode by Photon is: + /// 0 for "OK" + /// -3 for "Web-Service not configured" (see Dashboard / WebHooks) + /// -5 for "Web-Service does now have RPC path/name" (at least for Azure) + /// + /// Example: void OnWebRpcResponse(OperationResponse response) { ... } + /// + OnWebRpcResponse, + + /// + /// Called when another player requests ownership of a PhotonView from you (the current owner). + /// + /// + /// The parameter viewAndPlayer contains: + /// + /// PhotonView view = viewAndPlayer[0] as PhotonView; + /// + /// PhotonPlayer requestingPlayer = viewAndPlayer[1] as PhotonPlayer; + /// + /// void OnOwnershipRequest(object[] viewAndPlayer) {} // + OnOwnershipRequest, + + /// + /// Called when the Master Server sent an update for the Lobby Statistics, updating PhotonNetwork.LobbyStatistics. + /// + /// + /// This callback has two preconditions: + /// EnableLobbyStatistics must be set to true, before this client connects. + /// And the client has to be connected to the Master Server, which is providing the info about lobbies. + /// + OnLobbyStatisticsUpdate, + + + /// + /// Called when a remote Photon Player activity changed. This will be called ONLY is PlayerTtl is greater then 0. + /// + /// Use PhotonPlayer.IsInactive to check the current activity state + /// + /// Example: void OnPhotonPlayerActivityChanged(PhotonPlayer otherPlayer) {...} + /// + /// + /// This callback has precondition: + /// PlayerTtl must be greater then 0 + /// + OnPhotonPlayerActivityChanged, + + + /// + /// Called when a PhotonView Owner is transfered to a Player. + /// + /// + /// The parameter viewAndPlayers contains: + /// + /// PhotonView view = viewAndPlayers[0] as PhotonView; + /// + /// PhotonPlayer newOwner = viewAndPlayers[1] as PhotonPlayer; + /// + /// PhotonPlayer oldOwner = viewAndPlayers[2] as PhotonPlayer; + /// + /// void OnOwnershipTransfered(object[] viewAndPlayers) {} // + OnOwnershipTransfered, +} + + +/// Used to define the level of logging output created by the PUN classes. Either log errors, info (some more) or full. +/// \ingroup publicApi +public enum PhotonLogLevel +{ + /// Show only errors. Minimal output. Note: Some might be "runtime errors" which you have to expect. + ErrorsOnly, + /// Logs some of the workflow, calls and results. + Informational, + /// Every available log call gets into the console/log. Only use for debugging. + Full +} + + +/// Enum of "target" options for RPCs. These define which remote clients get your RPC call. +/// \ingroup publicApi +public enum PhotonTargets +{ + /// Sends the RPC to everyone else and executes it immediately on this client. Player who join later will not execute this RPC. + All, + /// Sends the RPC to everyone else. This client does not execute the RPC. Player who join later will not execute this RPC. + Others, + /// Sends the RPC to MasterClient only. Careful: The MasterClient might disconnect before it executes the RPC and that might cause dropped RPCs. + MasterClient, + /// Sends the RPC to everyone else and executes it immediately on this client. New players get the RPC when they join as it's buffered (until this client leaves). + AllBuffered, + /// Sends the RPC to everyone. This client does not execute the RPC. New players get the RPC when they join as it's buffered (until this client leaves). + OthersBuffered, + /// Sends the RPC to everyone (including this client) through the server. + /// + /// This client executes the RPC like any other when it received it from the server. + /// Benefit: The server's order of sending the RPCs is the same on all clients. + /// + AllViaServer, + /// Sends the RPC to everyone (including this client) through the server and buffers it for players joining later. + /// + /// This client executes the RPC like any other when it received it from the server. + /// Benefit: The server's order of sending the RPCs is the same on all clients. + /// + AllBufferedViaServer +} + + +/// Currently available Photon Cloud regions as enum. +/// +/// This is used in PhotonNetwork.ConnectToRegion. +/// +public enum CloudRegionCode +{ + /// European servers in Amsterdam. + eu = 0, + /// US servers (East Coast). + us = 1, + /// Asian servers in Singapore. + asia = 2, + /// Japanese servers in Tokyo. + jp = 3, + /// Australian servers in Melbourne. + au = 5, + ///USA West, San José, usw + usw = 6, + ///South America, Sao Paulo, sa + sa = 7, + ///Canada East, Montreal, cae + cae = 8, + ///South Korea, Seoul, kr + kr = 9, + ///India, Chennai, in + @in = 10, + /// Russia, ru + ru = 11, + /// Russia East, rue + rue = 12, + + /// No region selected. + none = 4 +}; + + +/// +/// Available regions as enum of flags. To be used as "enabled" flags for Best Region pinging. +/// +/// Note that these enum values skip CloudRegionCode.none and their values are in strict order (power of 2). +[Flags] +public enum CloudRegionFlag +{ + eu = 1 << 0, + us = 1 << 1, + asia = 1 << 2, + jp = 1 << 3, + au = 1 << 4, + usw = 1 << 5, + sa = 1 << 6, + cae = 1 << 7, + kr = 1 << 8, + @in = 1 << 9, + ru = 1 << 10, + rue = 1 << 11 +}; + + +/// +/// High level connection state of the client. Better use the more detailed . +/// +public enum ConnectionState +{ + Disconnected, + Connecting, + Connected, + Disconnecting, + InitializingApplication +} + + +/// +/// Defines how the communication gets encrypted. +/// +public enum EncryptionMode +{ + /// + /// This is the default encryption mode: Messages get encrypted only on demand (when you send operations with the "encrypt" parameter set to true). + /// + PayloadEncryption, + /// + /// With this encryption mode for UDP, the connection gets setup and all further datagrams get encrypted almost entirely. On-demand message encryption (like in PayloadEncryption) is skipped. + /// + /// + /// This mode requires AuthOnce or AuthOnceWss as AuthMode! + /// + DatagramEncryption = 10, +} + + +public static class EncryptionDataParameters +{ + /// + /// Key for encryption mode + /// + public const byte Mode = 0; + /// + /// Key for first secret + /// + public const byte Secret1 = 1; + /// + /// Key for second secret + /// + public const byte Secret2 = 2; +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Enums.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Enums.cs.meta new file mode 100644 index 0000000..d612c91 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Enums.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b7962bbdaba2a4940b1341d755abd40d +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Extensions.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Extensions.cs new file mode 100644 index 0000000..6359599 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Extensions.cs @@ -0,0 +1,246 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2011 Exit Games GmbH +// +// +// Provides some helpful methods and extensions for Hashtables, etc. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using UnityEngine; +using Hashtable = ExitGames.Client.Photon.Hashtable; +using SupportClassPun = ExitGames.Client.Photon.SupportClass; + + +/// +/// This static class defines some useful extension methods for several existing classes (e.g. Vector3, float and others). +/// +public static class Extensions +{ + + public static Dictionary ParametersOfMethods = new Dictionary(); + public static ParameterInfo[] GetCachedParemeters(this MethodInfo mo) + { + ParameterInfo[] result; + bool cached= ParametersOfMethods.TryGetValue(mo, out result); + + if (!cached) + { + result = mo.GetParameters(); + ParametersOfMethods[mo] = result; + } + + return result; + } + + public static PhotonView[] GetPhotonViewsInChildren(this UnityEngine.GameObject go) + { + return go.GetComponentsInChildren(true) as PhotonView[]; + } + + public static PhotonView GetPhotonView(this UnityEngine.GameObject go) + { + return go.GetComponent() as PhotonView; + } + + /// compares the squared magnitude of target - second to given float value + public static bool AlmostEquals(this Vector3 target, Vector3 second, float sqrMagnitudePrecision) + { + return (target - second).sqrMagnitude < sqrMagnitudePrecision; // TODO: inline vector methods to optimize? + } + + /// compares the squared magnitude of target - second to given float value + public static bool AlmostEquals(this Vector2 target, Vector2 second, float sqrMagnitudePrecision) + { + return (target - second).sqrMagnitude < sqrMagnitudePrecision; // TODO: inline vector methods to optimize? + } + + /// compares the angle between target and second to given float value + public static bool AlmostEquals(this Quaternion target, Quaternion second, float maxAngle) + { + return Quaternion.Angle(target, second) < maxAngle; + } + + /// compares two floats and returns true of their difference is less than floatDiff + public static bool AlmostEquals(this float target, float second, float floatDiff) + { + return Mathf.Abs(target - second) < floatDiff; + } + + /// + /// Merges all keys from addHash into the target. Adds new keys and updates the values of existing keys in target. + /// + /// The IDictionary to update. + /// The IDictionary containing data to merge into target. + public static void Merge(this IDictionary target, IDictionary addHash) + { + if (addHash == null || target.Equals(addHash)) + { + return; + } + + foreach (object key in addHash.Keys) + { + target[key] = addHash[key]; + } + } + + /// + /// Merges keys of type string to target Hashtable. + /// + /// + /// Does not remove keys from target (so non-string keys CAN be in target if they were before). + /// + /// The target IDicitionary passed in plus all string-typed keys from the addHash. + /// A IDictionary that should be merged partly into target to update it. + public static void MergeStringKeys(this IDictionary target, IDictionary addHash) + { + if (addHash == null || target.Equals(addHash)) + { + return; + } + + foreach (object key in addHash.Keys) + { + // only merge keys of type string + if (key is string) + { + target[key] = addHash[key]; + } + } + } + + /// Helper method for debugging of IDictionary content, inlcuding type-information. Using this is not performant. + /// Should only be used for debugging as necessary. + /// Some Dictionary or Hashtable. + /// String of the content of the IDictionary. + public static string ToStringFull(this IDictionary origin) + { + return SupportClassPun.DictionaryToString(origin, false); + } + + + /// Helper method for debugging of object[] content. Using this is not performant. + /// Should only be used for debugging as necessary. + /// Any object[]. + /// A comma-separated string containing each value's ToString(). + public static string ToStringFull(this object[] data) + { + if (data == null) return "null"; + + string[] sb = new string[data.Length]; + for (int i = 0; i < data.Length; i++) + { + object o = data[i]; + sb[i] = (o != null) ? o.ToString() : "null"; + } + + return string.Join(", ", sb); + } + + + /// + /// This method copies all string-typed keys of the original into a new Hashtable. + /// + /// + /// Does not recurse (!) into hashes that might be values in the root-hash. + /// This does not modify the original. + /// + /// The original IDictonary to get string-typed keys from. + /// New Hashtable containing only string-typed keys of the original. + public static Hashtable StripToStringKeys(this IDictionary original) + { + Hashtable target = new Hashtable(); + if (original != null) + { + foreach (object key in original.Keys) + { + if (key is string) + { + target[key] = original[key]; + } + } + } + + return target; + } + + /// + /// This removes all key-value pairs that have a null-reference as value. + /// Photon properties are removed by setting their value to null. + /// Changes the original passed IDictionary! + /// + /// The IDictionary to strip of keys with null-values. + public static void StripKeysWithNullValues(this IDictionary original) + { + object[] keys = new object[original.Count]; + //original.Keys.CopyTo(keys, 0); // todo: figure out which platform didn't support this + int i = 0; + foreach (object k in original.Keys) + { + keys[i++] = k; + } + + for (int index = 0; index < keys.Length; index++) + { + var key = keys[index]; + if (original[key] == null) + { + original.Remove(key); + } + } + } + + /// + /// Checks if a particular integer value is in an int-array. + /// + /// This might be useful to look up if a particular actorNumber is in the list of players of a room. + /// The array of ints to check. + /// The number to lookup in target. + /// True if nr was found in target. + public static bool Contains(this int[] target, int nr) + { + if (target == null) + { + return false; + } + + for (int index = 0; index < target.Length; index++) + { + if (target[index] == nr) + { + return true; + } + } + + return false; + } +} + + +/// Small number of extension methods that make it easier for PUN to work cross-Unity-versions. +public static class GameObjectExtensions +{ + /// Unity-version-independent replacement for active GO property. + /// Unity 3.5: active. Any newer Unity: activeInHierarchy. + public static bool GetActive(this GameObject target) + { + #if UNITY_3_5 + return target.active; + #else + return target.activeInHierarchy; + #endif + } + + #if UNITY_3_5 + /// Unity-version-independent setter for active and SetActive(). + public static void SetActive(this GameObject target, bool value) + { + target.active = value; + } + #endif +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Extensions.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Extensions.cs.meta new file mode 100644 index 0000000..b86a6e0 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Extensions.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3c0464991e33a70498abdd85c150cc59 +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/FriendInfo.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/FriendInfo.cs new file mode 100644 index 0000000..8701da7 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/FriendInfo.cs @@ -0,0 +1,29 @@ +// ---------------------------------------------------------------------------- +// +// Loadbalancing Framework for Photon - Copyright (C) 2013 Exit Games GmbH +// +// +// Collection of values related to a user / friend. +// +// developer@photonengine.com +// ---------------------------------------------------------------------------- + + +/// +/// Used to store info about a friend's online state and in which room he/she is. +/// +public class FriendInfo +{ + [System.Obsolete("Use UserId.")] + public string Name { get { return this.UserId; } } + public string UserId { get; internal protected set; } + + public bool IsOnline { get; internal protected set; } + public string Room { get; internal protected set; } + public bool IsInRoom { get { return IsOnline && !string.IsNullOrEmpty(this.Room); } } + + public override string ToString() + { + return string.Format("{0}\t is: {1}", this.UserId, (!this.IsOnline) ? "offline" : this.IsInRoom ? "playing" : "on master"); + } +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/FriendInfo.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/FriendInfo.cs.meta new file mode 100644 index 0000000..f2b1b67 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/FriendInfo.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 94ba1138c322ea04c8c37cfbcf87f468 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/GizmoType.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/GizmoType.cs new file mode 100644 index 0000000..0cf7cee --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/GizmoType.cs @@ -0,0 +1,36 @@ +using UnityEngine; + +namespace ExitGames.Client.GUI +{ + public enum GizmoType + { + WireSphere, + Sphere, + WireCube, + Cube, + } + + public class GizmoTypeDrawer + { + public static void Draw( Vector3 center, GizmoType type, Color color, float size ) + { + Gizmos.color = color; + + switch( type ) + { + case GizmoType.Cube: + Gizmos.DrawCube( center, Vector3.one * size ); + break; + case GizmoType.Sphere: + Gizmos.DrawSphere( center, size * 0.5f ); + break; + case GizmoType.WireCube: + Gizmos.DrawWireCube( center, Vector3.one * size ); + break; + case GizmoType.WireSphere: + Gizmos.DrawWireSphere( center, size * 0.5f ); + break; + } + } + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/GizmoType.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/GizmoType.cs.meta new file mode 100644 index 0000000..4d968d5 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/GizmoType.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a744e8c91e32ce742b8f79e048a8714a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/LoadbalancingPeer.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/LoadbalancingPeer.cs new file mode 100644 index 0000000..4e74f0f --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/LoadbalancingPeer.cs @@ -0,0 +1,1965 @@ +// ---------------------------------------------------------------------------- +// +// Loadbalancing Framework for Photon - Copyright (C) 2016 Exit Games GmbH +// +// +// Provides operations to use the LoadBalancing and Cloud photon servers. +// No logic is implemented here. +// +// developer@photonengine.com +// ---------------------------------------------------------------------------- + +using System; +using System.Collections; +using System.Collections.Generic; +using ExitGames.Client.Photon; + +#if UNITY_4_0 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5 || UNITY_5_0 || UNITY_5_1 || UNITY_5_3_OR_NEWER + using UnityEngine; + using Hashtable = ExitGames.Client.Photon.Hashtable; + using SupportClassPun = ExitGames.Client.Photon.SupportClass; +#endif + + + /// + /// A LoadbalancingPeer provides the operations and enum definitions needed to use the loadbalancing server application which is also used in Photon Cloud. + /// + /// + /// Internally used by PUN. + /// The LoadBalancingPeer does not keep a state, instead this is done by a LoadBalancingClient. + /// + internal class LoadBalancingPeer : PhotonPeer + { + + internal bool IsProtocolSecure + { + get { return this.UsedProtocol == ConnectionProtocol.WebSocketSecure; } + } + + private readonly Dictionary opParameters = new Dictionary(); // used in OpRaiseEvent() (avoids lots of new Dictionary() calls) + + + /// + /// Creates a Peer with specified connection protocol. You need to set the Listener before using the peer. + /// + /// Each connection protocol has it's own default networking ports for Photon. + /// The preferred option is UDP. + public LoadBalancingPeer(ConnectionProtocol protocolType) : base(protocolType) + { + // this does not require a Listener, so: + // make sure to set this.Listener before using a peer! + } + + /// + /// Creates a Peer with specified connection protocol and a Listener for callbacks. + /// + public LoadBalancingPeer(IPhotonPeerListener listener, ConnectionProtocol protocolType) : this(protocolType) + { + this.Listener = listener; + } + + public virtual bool OpGetRegions(string appId) + { + Dictionary parameters = new Dictionary(); + parameters[(byte)ParameterCode.ApplicationId] = appId; + + return this.OpCustom(OperationCode.GetRegions, parameters, true, 0, true); + } + + /// + /// Joins the lobby on the Master Server, where you get a list of RoomInfos of currently open rooms. + /// This is an async request which triggers a OnOperationResponse() call. + /// + /// The lobby join to. + /// If the operation could be sent (has to be connected). + public virtual bool OpJoinLobby(TypedLobby lobby = null) + { + if (this.DebugOut >= DebugLevel.INFO) + { + this.Listener.DebugReturn(DebugLevel.INFO, "OpJoinLobby()"); + } + + Dictionary parameters = null; + if (lobby != null && !lobby.IsDefault) + { + parameters = new Dictionary(); + parameters[(byte)ParameterCode.LobbyName] = lobby.Name; + parameters[(byte)ParameterCode.LobbyType] = (byte)lobby.Type; + } + + return this.OpCustom(OperationCode.JoinLobby, parameters, true); + } + + + /// + /// Leaves the lobby on the Master Server. + /// This is an async request which triggers a OnOperationResponse() call. + /// + /// If the operation could be sent (requires connection). + public virtual bool OpLeaveLobby() + { + if (this.DebugOut >= DebugLevel.INFO) + { + this.Listener.DebugReturn(DebugLevel.INFO, "OpLeaveLobby()"); + } + + return this.OpCustom(OperationCode.LeaveLobby, null, true); + } + + + /// Used in the RoomOptionFlags parameter, this bitmask toggles options in the room. + enum RoomOptionBit : int + { + CheckUserOnJoin = 0x01, // toggles a check of the UserId when joining (enabling returning to a game) + DeleteCacheOnLeave = 0x02, // deletes cache on leave + SuppressRoomEvents = 0x04, // suppresses all room events + PublishUserId = 0x08, // signals that we should publish userId + DeleteNullProps = 0x10, // signals that we should remove property if its value was set to null. see RoomOption to Delete Null Properties + BroadcastPropsChangeToAll = 0x20, // signals that we should send PropertyChanged event to all room players including initiator + } + + private void RoomOptionsToOpParameters(Dictionary op, RoomOptions roomOptions) + { + if (roomOptions == null) + { + roomOptions = new RoomOptions(); + } + + Hashtable gameProperties = new Hashtable(); + gameProperties[GamePropertyKey.IsOpen] = roomOptions.IsOpen; + gameProperties[GamePropertyKey.IsVisible] = roomOptions.IsVisible; + gameProperties[GamePropertyKey.PropsListedInLobby] = (roomOptions.CustomRoomPropertiesForLobby == null) ? new string[0] : roomOptions.CustomRoomPropertiesForLobby; + gameProperties.MergeStringKeys(roomOptions.CustomRoomProperties); + if (roomOptions.MaxPlayers > 0) + { + gameProperties[GamePropertyKey.MaxPlayers] = roomOptions.MaxPlayers; + } + op[ParameterCode.GameProperties] = gameProperties; + + + int flags = 0; // a new way to send the room options as bitwise-flags + op[ParameterCode.CleanupCacheOnLeave] = roomOptions.CleanupCacheOnLeave; // this is actually setting the room's config + if (roomOptions.CleanupCacheOnLeave) + { + flags = flags | (int)RoomOptionBit.DeleteCacheOnLeave; + gameProperties[GamePropertyKey.CleanupCacheOnLeave] = true; // this is only informational for the clients which join + } + + // in PUN v1.88 and PUN 2, CheckUserOnJoin is set by default: + flags = flags | (int)RoomOptionBit.CheckUserOnJoin; + op[ParameterCode.CheckUserOnJoin] = true; + + if (roomOptions.PlayerTtl > 0 || roomOptions.PlayerTtl == -1) + { + op[ParameterCode.PlayerTTL] = roomOptions.PlayerTtl; // TURNBASED + } + + if (roomOptions.EmptyRoomTtl > 0) + { + op[ParameterCode.EmptyRoomTTL] = roomOptions.EmptyRoomTtl; //TURNBASED + } + + if (roomOptions.SuppressRoomEvents) + { + flags = flags | (int)RoomOptionBit.SuppressRoomEvents; + op[ParameterCode.SuppressRoomEvents] = true; + } + if (roomOptions.Plugins != null) + { + op[ParameterCode.Plugins] = roomOptions.Plugins; + } + if (roomOptions.PublishUserId) + { + flags = flags | (int)RoomOptionBit.PublishUserId; + op[ParameterCode.PublishUserId] = true; + } + if (roomOptions.DeleteNullProperties) + { + flags = flags | (int)RoomOptionBit.DeleteNullProps; // this is only settable as flag + } + + op[ParameterCode.RoomOptionFlags] = flags; + } + + + /// + /// Creates a room (on either Master or Game Server). + /// The OperationResponse depends on the server the peer is connected to: + /// Master will return a Game Server to connect to. + /// Game Server will return the joined Room's data. + /// This is an async request which triggers a OnOperationResponse() call. + /// + /// + /// If the room is already existing, the OperationResponse will have a returnCode of ErrorCode.GameAlreadyExists. + /// + public virtual bool OpCreateRoom(EnterRoomParams opParams) + { + if (this.DebugOut >= DebugLevel.INFO) + { + this.Listener.DebugReturn(DebugLevel.INFO, "OpCreateRoom()"); + } + + Dictionary op = new Dictionary(); + + if (!string.IsNullOrEmpty(opParams.RoomName)) + { + op[ParameterCode.RoomName] = opParams.RoomName; + } + if (opParams.Lobby != null && !string.IsNullOrEmpty(opParams.Lobby.Name)) + { + op[ParameterCode.LobbyName] = opParams.Lobby.Name; + op[ParameterCode.LobbyType] = (byte)opParams.Lobby.Type; + } + + if (opParams.ExpectedUsers != null && opParams.ExpectedUsers.Length > 0) + { + op[ParameterCode.Add] = opParams.ExpectedUsers; + } + if (opParams.OnGameServer) + { + if (opParams.PlayerProperties != null && opParams.PlayerProperties.Count > 0) + { + op[ParameterCode.PlayerProperties] = opParams.PlayerProperties; + op[ParameterCode.Broadcast] = true; // TODO: check if this also makes sense when creating a room?! // broadcast actor properties + } + + this.RoomOptionsToOpParameters(op, opParams.RoomOptions); + } + + //UnityEngine.Debug.Log("CreateRoom: " + SupportClassPun.DictionaryToString(op)); + return this.OpCustom(OperationCode.CreateGame, op, true); + } + + /// + /// Joins a room by name or creates new room if room with given name not exists. + /// The OperationResponse depends on the server the peer is connected to: + /// Master will return a Game Server to connect to. + /// Game Server will return the joined Room's data. + /// This is an async request which triggers a OnOperationResponse() call. + /// + /// + /// If the room is not existing (anymore), the OperationResponse will have a returnCode of ErrorCode.GameDoesNotExist. + /// Other possible ErrorCodes are: GameClosed, GameFull. + /// + /// If the operation could be sent (requires connection). + public virtual bool OpJoinRoom(EnterRoomParams opParams) + { + if (this.DebugOut >= DebugLevel.INFO) + { + this.Listener.DebugReturn(DebugLevel.INFO, "OpJoinRoom()"); + } + Dictionary op = new Dictionary(); + + if (!string.IsNullOrEmpty(opParams.RoomName)) + { + op[ParameterCode.RoomName] = opParams.RoomName; + } + + if (opParams.CreateIfNotExists) + { + op[ParameterCode.JoinMode] = (byte)JoinMode.CreateIfNotExists; + if (opParams.Lobby != null) + { + op[ParameterCode.LobbyName] = opParams.Lobby.Name; + op[ParameterCode.LobbyType] = (byte)opParams.Lobby.Type; + } + } + + if (opParams.RejoinOnly) + { + op[ParameterCode.JoinMode] = (byte)JoinMode.RejoinOnly; // changed from JoinMode.JoinOrRejoin + } + + if (opParams.ExpectedUsers != null && opParams.ExpectedUsers.Length > 0) + { + op[ParameterCode.Add] = opParams.ExpectedUsers; + } + + if (opParams.OnGameServer) + { + if (opParams.PlayerProperties != null && opParams.PlayerProperties.Count > 0) + { + op[ParameterCode.PlayerProperties] = opParams.PlayerProperties; + op[ParameterCode.Broadcast] = true; // broadcast actor properties + } + + if (opParams.CreateIfNotExists) + { + this.RoomOptionsToOpParameters(op, opParams.RoomOptions); + } + } + + // UnityEngine.Debug.Log("JoinRoom: " + SupportClassPun.DictionaryToString(op)); + return this.OpCustom(OperationCode.JoinGame, op, true); + } + + + /// + /// Operation to join a random, available room. Overloads take additional player properties. + /// This is an async request which triggers a OnOperationResponse() call. + /// If all rooms are closed or full, the OperationResponse will have a returnCode of ErrorCode.NoRandomMatchFound. + /// If successful, the OperationResponse contains a gameserver address and the name of some room. + /// + /// If the operation could be sent currently (requires connection). + public virtual bool OpJoinRandomRoom(OpJoinRandomRoomParams opJoinRandomRoomParams) + { + if (this.DebugOut >= DebugLevel.INFO) + { + this.Listener.DebugReturn(DebugLevel.INFO, "OpJoinRandomRoom()"); + } + + Hashtable expectedRoomProperties = new Hashtable(); + expectedRoomProperties.MergeStringKeys(opJoinRandomRoomParams.ExpectedCustomRoomProperties); + if (opJoinRandomRoomParams.ExpectedMaxPlayers > 0) + { + expectedRoomProperties[GamePropertyKey.MaxPlayers] = opJoinRandomRoomParams.ExpectedMaxPlayers; + } + + Dictionary opParameters = new Dictionary(); + if (expectedRoomProperties.Count > 0) + { + opParameters[ParameterCode.GameProperties] = expectedRoomProperties; + } + + if (opJoinRandomRoomParams.MatchingType != MatchmakingMode.FillRoom) + { + opParameters[ParameterCode.MatchMakingType] = (byte)opJoinRandomRoomParams.MatchingType; + } + + if (opJoinRandomRoomParams.TypedLobby != null && !string.IsNullOrEmpty(opJoinRandomRoomParams.TypedLobby.Name)) + { + opParameters[ParameterCode.LobbyName] = opJoinRandomRoomParams.TypedLobby.Name; + opParameters[ParameterCode.LobbyType] = (byte)opJoinRandomRoomParams.TypedLobby.Type; + } + + if (!string.IsNullOrEmpty(opJoinRandomRoomParams.SqlLobbyFilter)) + { + opParameters[ParameterCode.Data] = opJoinRandomRoomParams.SqlLobbyFilter; + } + + if (opJoinRandomRoomParams.ExpectedUsers != null && opJoinRandomRoomParams.ExpectedUsers.Length > 0) + { + opParameters[ParameterCode.Add] = opJoinRandomRoomParams.ExpectedUsers; + } + + // UnityEngine.Debug.LogWarning("OpJoinRandom: " + opParameters.ToStringFull()); + return this.OpCustom(OperationCode.JoinRandomGame, opParameters, true); + } + + + /// + /// Leaves a room with option to come back later or "for good". + /// + /// Async games can be re-joined (loaded) later on. Set to false, if you want to abandon a game entirely. + /// If the opteration can be send currently. + public virtual bool OpLeaveRoom(bool becomeInactive) + { + Dictionary parameters = null; + if (becomeInactive) + { + parameters = new Dictionary(); + parameters[ParameterCode.IsInactive] = becomeInactive; + } + return this.OpCustom(OperationCode.Leave, parameters, true); + } + + /// Gets a list of games matching a SQL-like where clause. + /// + /// Operation is only available in lobbies of type SqlLobby. + /// This is an async request which triggers a OnOperationResponse() call. + /// Returned game list is stored in RoomInfoList. + /// + /// + /// The lobby to query. Has to be of type SqlLobby. + /// The sql query statement. + /// If the operation could be sent (has to be connected). + public virtual bool OpGetGameList(TypedLobby lobby, string queryData) + { + if (this.DebugOut >= DebugLevel.INFO) + { + this.Listener.DebugReturn(DebugLevel.INFO, "OpGetGameList()"); + } + + if (lobby == null) + { + if (this.DebugOut >= DebugLevel.INFO) + { + this.Listener.DebugReturn(DebugLevel.INFO, "OpGetGameList not sent. Lobby cannot be null."); + } + return false; + } + + if (lobby.Type != LobbyType.SqlLobby) + { + if (this.DebugOut >= DebugLevel.INFO) + { + this.Listener.DebugReturn(DebugLevel.INFO, "OpGetGameList not sent. LobbyType must be SqlLobby."); + } + return false; + } + + Dictionary opParameters = new Dictionary(); + opParameters[(byte)ParameterCode.LobbyName] = lobby.Name; + opParameters[(byte)ParameterCode.LobbyType] = (byte)lobby.Type; + opParameters[(byte)ParameterCode.Data] = queryData; + + return this.OpCustom(OperationCode.GetGameList, opParameters, true); + } + + /// + /// Request the rooms and online status for a list of friends (each client must set a unique username via OpAuthenticate). + /// + /// + /// Used on Master Server to find the rooms played by a selected list of users. + /// Users identify themselves by using OpAuthenticate with a unique username. + /// The list of usernames must be fetched from some other source (not provided by Photon). + /// + /// The server response includes 2 arrays of info (each index matching a friend from the request): + /// ParameterCode.FindFriendsResponseOnlineList = bool[] of online states + /// ParameterCode.FindFriendsResponseRoomIdList = string[] of room names (empty string if not in a room) + /// + /// Array of friend's names (make sure they are unique). + /// If the operation could be sent (requires connection). + public virtual bool OpFindFriends(string[] friendsToFind) + { + Dictionary opParameters = new Dictionary(); + if (friendsToFind != null && friendsToFind.Length > 0) + { + opParameters[ParameterCode.FindFriendsRequestList] = friendsToFind; + } + + return this.OpCustom(OperationCode.FindFriends, opParameters, true); + } + + public bool OpSetCustomPropertiesOfActor(int actorNr, Hashtable actorProperties) + { + return this.OpSetPropertiesOfActor(actorNr, actorProperties.StripToStringKeys(), null); + } + + /// + /// Sets properties of a player / actor. + /// Internally this uses OpSetProperties, which can be used to either set room or player properties. + /// + /// The payer ID (a.k.a. actorNumber) of the player to attach these properties to. + /// The properties to add or update. + /// If set, these must be in the current properties-set (on the server) to set actorProperties: CAS. + /// Set to true, to forward the set properties to a WebHook, defined for this app (in Dashboard). + /// If the operation could be sent (requires connection). + protected internal bool OpSetPropertiesOfActor(int actorNr, Hashtable actorProperties, Hashtable expectedProperties = null, bool webForward = false) + { + if (this.DebugOut >= DebugLevel.INFO) + { + this.Listener.DebugReturn(DebugLevel.INFO, "OpSetPropertiesOfActor()"); + } + + if (actorNr <= 0 || actorProperties == null) + { + if (this.DebugOut >= DebugLevel.INFO) + { + this.Listener.DebugReturn(DebugLevel.INFO, "OpSetPropertiesOfActor not sent. ActorNr must be > 0 and actorProperties != null."); + } + return false; + } + + Dictionary opParameters = new Dictionary(); + opParameters.Add(ParameterCode.Properties, actorProperties); + opParameters.Add(ParameterCode.ActorNr, actorNr); + opParameters.Add(ParameterCode.Broadcast, true); + if (expectedProperties != null && expectedProperties.Count != 0) + { + opParameters.Add(ParameterCode.ExpectedValues, expectedProperties); + } + + if (webForward) + { + opParameters[ParameterCode.EventForward] = true; + } + + return this.OpCustom((byte)OperationCode.SetProperties, opParameters, true, 0, false); + } + + + protected internal void OpSetPropertyOfRoom(byte propCode, object value) + { + Hashtable properties = new Hashtable(); + properties[propCode] = value; + this.OpSetPropertiesOfRoom(properties, expectedProperties: null, webForward: false); + } + + public bool OpSetCustomPropertiesOfRoom(Hashtable gameProperties, bool broadcast, byte channelId) + { + return this.OpSetPropertiesOfRoom(gameProperties.StripToStringKeys(), expectedProperties: null, webForward: false); + } + + /// + /// Sets properties of a room. + /// Internally this uses OpSetProperties, which can be used to either set room or player properties. + /// + /// The properties to add or update. + /// The properties expected when update occurs. (CAS : "Check And Swap") + /// "WebFlag" to indicate if request should be forwarded as "PathProperties" webhook or not. + /// If the operation could be sent (has to be connected). + protected internal bool OpSetPropertiesOfRoom(Hashtable gameProperties, Hashtable expectedProperties = null, bool webForward = false) + { + if (this.DebugOut >= DebugLevel.INFO) + { + this.Listener.DebugReturn(DebugLevel.INFO, "OpSetPropertiesOfRoom()"); + } + + Dictionary opParameters = new Dictionary(); + opParameters.Add(ParameterCode.Properties, gameProperties); + opParameters.Add(ParameterCode.Broadcast, true); + if (expectedProperties != null && expectedProperties.Count != 0) + { + opParameters.Add(ParameterCode.ExpectedValues, expectedProperties); + } + + if (webForward) + { + opParameters[ParameterCode.EventForward] = true; + } + + return this.OpCustom((byte)OperationCode.SetProperties, opParameters, true, 0, false); + } + + /// + /// Sends this app's appId and appVersion to identify this application server side. + /// This is an async request which triggers a OnOperationResponse() call. + /// + /// + /// This operation makes use of encryption, if that is established before. + /// See: EstablishEncryption(). Check encryption with IsEncryptionAvailable. + /// This operation is allowed only once per connection (multiple calls will have ErrorCode != Ok). + /// + /// Your application's name or ID to authenticate. This is assigned by Photon Cloud (webpage). + /// The client's version (clients with differing client appVersions are separated and players don't meet). + /// Contains all values relevant for authentication. Even without account system (external Custom Auth), the clients are allowed to identify themselves. + /// Optional region code, if the client should connect to a specific Photon Cloud Region. + /// Set to true on Master Server to receive "Lobby Statistics" events. + /// If the operation could be sent (has to be connected). + public virtual bool OpAuthenticate(string appId, string appVersion, AuthenticationValues authValues, string regionCode, bool getLobbyStatistics) + { + if (this.DebugOut >= DebugLevel.INFO) + { + this.Listener.DebugReturn(DebugLevel.INFO, "OpAuthenticate()"); + } + + Dictionary opParameters = new Dictionary(); + if (getLobbyStatistics) + { + // must be sent in operation, even if a Token is available + opParameters[ParameterCode.LobbyStats] = true; + } + + // shortcut, if we have a Token + if (authValues != null && authValues.Token != null) + { + opParameters[ParameterCode.Secret] = authValues.Token; + return this.OpCustom(OperationCode.Authenticate, opParameters, true, (byte)0, false); // we don't have to encrypt, when we have a token (which is encrypted) + } + + + // without a token, we send a complete op auth + + opParameters[ParameterCode.AppVersion] = appVersion; + opParameters[ParameterCode.ApplicationId] = appId; + + if (!string.IsNullOrEmpty(regionCode)) + { + opParameters[ParameterCode.Region] = regionCode; + } + + if (authValues != null) + { + + if (!string.IsNullOrEmpty(authValues.UserId)) + { + opParameters[ParameterCode.UserId] = authValues.UserId; + } + + if (authValues.AuthType != CustomAuthenticationType.None) + { + if (!this.IsProtocolSecure && !this.IsEncryptionAvailable) + { + this.Listener.DebugReturn(DebugLevel.ERROR, "OpAuthenticate() failed. When you want Custom Authentication encryption is mandatory."); + return false; + } + + opParameters[ParameterCode.ClientAuthenticationType] = (byte) authValues.AuthType; + if (!string.IsNullOrEmpty(authValues.Token)) + { + opParameters[ParameterCode.Secret] = authValues.Token; + } + else + { + if (!string.IsNullOrEmpty(authValues.AuthGetParameters)) + { + opParameters[ParameterCode.ClientAuthenticationParams] = authValues.AuthGetParameters; + } + if (authValues.AuthPostData != null) + { + opParameters[ParameterCode.ClientAuthenticationData] = authValues.AuthPostData; + } + } + } + } + + bool sent = this.OpCustom(OperationCode.Authenticate, opParameters, true, (byte) 0, this.IsEncryptionAvailable); + if (!sent) + { + this.Listener.DebugReturn(DebugLevel.ERROR, "Error calling OpAuthenticate! Did not work. Check log output, AuthValues and if you're connected."); + } + return sent; + } + + + /// + /// Sends this app's appId and appVersion to identify this application server side. + /// This is an async request which triggers a OnOperationResponse() call. + /// + /// + /// This operation makes use of encryption, if that is established before. + /// See: EstablishEncryption(). Check encryption with IsEncryptionAvailable. + /// This operation is allowed only once per connection (multiple calls will have ErrorCode != Ok). + /// + /// Your application's name or ID to authenticate. This is assigned by Photon Cloud (webpage). + /// The client's version (clients with differing client appVersions are separated and players don't meet). + /// Optional authentication values. The client can set no values or a UserId or some parameters for Custom Authentication by a server. + /// Optional region code, if the client should connect to a specific Photon Cloud Region. + /// + /// + /// If the operation could be sent (has to be connected). + public virtual bool OpAuthenticateOnce(string appId, string appVersion, AuthenticationValues authValues, string regionCode, EncryptionMode encryptionMode, ConnectionProtocol expectedProtocol) + { + if (this.DebugOut >= DebugLevel.INFO) + { + this.Listener.DebugReturn(DebugLevel.INFO, "OpAuthenticate()"); + } + + + var opParameters = new Dictionary(); + + // shortcut, if we have a Token + if (authValues != null && authValues.Token != null) + { + opParameters[ParameterCode.Secret] = authValues.Token; + return this.OpCustom(OperationCode.AuthenticateOnce, opParameters, true, (byte)0, false); // we don't have to encrypt, when we have a token (which is encrypted) + } + + if (encryptionMode == EncryptionMode.DatagramEncryption && expectedProtocol != ConnectionProtocol.Udp) + { + Debug.LogWarning("Expected protocol set to UDP, due to encryption mode DatagramEncryption. Changing protocol in PhotonServerSettings from: " + PhotonNetwork.PhotonServerSettings.Protocol); + PhotonNetwork.PhotonServerSettings.Protocol = ConnectionProtocol.Udp; + expectedProtocol = ConnectionProtocol.Udp; + } + + opParameters[ParameterCode.ExpectedProtocol] = (byte)expectedProtocol; + opParameters[ParameterCode.EncryptionMode] = (byte)encryptionMode; + + opParameters[ParameterCode.AppVersion] = appVersion; + opParameters[ParameterCode.ApplicationId] = appId; + + if (!string.IsNullOrEmpty(regionCode)) + { + opParameters[ParameterCode.Region] = regionCode; + } + + if (authValues != null) + { + if (!string.IsNullOrEmpty(authValues.UserId)) + { + opParameters[ParameterCode.UserId] = authValues.UserId; + } + + if (authValues.AuthType != CustomAuthenticationType.None) + { + opParameters[ParameterCode.ClientAuthenticationType] = (byte)authValues.AuthType; + if (!string.IsNullOrEmpty(authValues.Token)) + { + opParameters[ParameterCode.Secret] = authValues.Token; + } + else + { + if (!string.IsNullOrEmpty(authValues.AuthGetParameters)) + { + opParameters[ParameterCode.ClientAuthenticationParams] = authValues.AuthGetParameters; + } + if (authValues.AuthPostData != null) + { + opParameters[ParameterCode.ClientAuthenticationData] = authValues.AuthPostData; + } + } + } + } + + return this.OpCustom(OperationCode.AuthenticateOnce, opParameters, true, (byte)0, this.IsEncryptionAvailable); + } + + /// + /// Operation to handle this client's interest groups (for events in room). + /// + /// + /// Note the difference between passing null and byte[0]: + /// null won't add/remove any groups. + /// byte[0] will add/remove all (existing) groups. + /// First, removing groups is executed. This way, you could leave all groups and join only the ones provided. + /// + /// Changes become active not immediately but when the server executes this operation (approximately RTT/2). + /// + /// Groups to remove from interest. Null will not remove any. A byte[0] will remove all. + /// Groups to add to interest. Null will not add any. A byte[0] will add all current. + /// If operation could be enqueued for sending. Sent when calling: Service or SendOutgoingCommands. + public virtual bool OpChangeGroups(byte[] groupsToRemove, byte[] groupsToAdd) + { + if (this.DebugOut >= DebugLevel.ALL) + { + this.Listener.DebugReturn(DebugLevel.ALL, "OpChangeGroups()"); + } + + Dictionary opParameters = new Dictionary(); + if (groupsToRemove != null) + { + opParameters[(byte)ParameterCode.Remove] = groupsToRemove; + } + if (groupsToAdd != null) + { + opParameters[(byte)ParameterCode.Add] = groupsToAdd; + } + + return this.OpCustom((byte)OperationCode.ChangeGroups, opParameters, true, 0); + } + + + /// + /// Send an event with custom code/type and any content to the other players in the same room. + /// + /// This override explicitly uses another parameter order to not mix it up with the implementation for Hashtable only. + /// Identifies this type of event (and the content). Your game's event codes can start with 0. + /// Any serializable datatype (including Hashtable like the other OpRaiseEvent overloads). + /// If this event has to arrive reliably (potentially repeated if it's lost). + /// Contains (slightly) less often used options. If you pass null, the default options will be used. + /// If operation could be enqueued for sending. Sent when calling: Service or SendOutgoingCommands. + public virtual bool OpRaiseEvent(byte eventCode, object customEventContent, bool sendReliable, RaiseEventOptions raiseEventOptions) + { + this.opParameters.Clear(); // re-used private variable to avoid many new Dictionary() calls (garbage collection) + this.opParameters[(byte)ParameterCode.Code] = (byte)eventCode; + if (customEventContent != null) + { + this.opParameters[(byte) ParameterCode.Data] = customEventContent; + } + + if (raiseEventOptions == null) + { + raiseEventOptions = RaiseEventOptions.Default; + } + else + { + if (raiseEventOptions.CachingOption != EventCaching.DoNotCache) + { + this.opParameters[(byte) ParameterCode.Cache] = (byte) raiseEventOptions.CachingOption; + } + if (raiseEventOptions.Receivers != ReceiverGroup.Others) + { + this.opParameters[(byte) ParameterCode.ReceiverGroup] = (byte) raiseEventOptions.Receivers; + } + if (raiseEventOptions.InterestGroup != 0) + { + this.opParameters[(byte) ParameterCode.Group] = (byte) raiseEventOptions.InterestGroup; + } + if (raiseEventOptions.TargetActors != null) + { + this.opParameters[(byte) ParameterCode.ActorList] = raiseEventOptions.TargetActors; + } + if (raiseEventOptions.ForwardToWebhook) + { + this.opParameters[(byte) ParameterCode.EventForward] = true; //TURNBASED + } + } + + return this.OpCustom((byte) OperationCode.RaiseEvent, this.opParameters, sendReliable, raiseEventOptions.SequenceChannel, raiseEventOptions.Encrypt); + } + + + #if PHOTON_LIB_MIN_4_1_2 + /// + /// Send an event with custom code/type and any content to the other players in the same room. + /// + /// This override explicitly uses another parameter order to not mix it up with the implementation for Hashtable only. + /// Identifies this type of event (and the content). Your game's event codes can start with 0. + /// Any serializable datatype (including Hashtable like the other OpRaiseEvent overloads). + /// Contains (slightly) less often used options. If you pass null, the default options will be used. + /// Send options wrap up reliability, sequencing and channel. + /// If operation could be enqueued for sending. Sent when calling: Service or SendOutgoingCommands. + public virtual bool OpRaiseEvent(byte eventCode, object customEventContent, RaiseEventOptions raiseEventOptions, SendOptions sendOptions) + { + this.opParameters.Clear(); // re-used private variable to avoid many new Dictionary() calls (garbage collection) + this.opParameters[(byte)ParameterCode.Code] = (byte)eventCode; + if (customEventContent != null) + { + this.opParameters[(byte)ParameterCode.Data] = customEventContent; + } + + if (raiseEventOptions == null) + { + raiseEventOptions = RaiseEventOptions.Default; + } + else + { + if (sendOptions.Channel != raiseEventOptions.SequenceChannel || sendOptions.Encrypt != raiseEventOptions.Encrypt) + { + // TODO: This should be a one-time warning. + // NOTE: Later on, it will be impossible to mix up SendOptions and RaiseEventOptions, as they won't have overlapping settings. + this.Listener.DebugReturn(DebugLevel.WARNING, "You are using RaiseEventOptions and SendOptions with conflicting settings. Please check channel and encryption value."); + } + + if (raiseEventOptions.CachingOption != EventCaching.DoNotCache) + { + this.opParameters[(byte)ParameterCode.Cache] = (byte)raiseEventOptions.CachingOption; + } + if (raiseEventOptions.Receivers != ReceiverGroup.Others) + { + this.opParameters[(byte)ParameterCode.ReceiverGroup] = (byte)raiseEventOptions.Receivers; + } + if (raiseEventOptions.InterestGroup != 0) + { + this.opParameters[(byte)ParameterCode.Group] = (byte)raiseEventOptions.InterestGroup; + } + if (raiseEventOptions.TargetActors != null) + { + this.opParameters[(byte)ParameterCode.ActorList] = raiseEventOptions.TargetActors; + } + //if (raiseEventOptions.Flags.HttpForward) + //{ + // this.opParameters[(byte)ParameterCode.EventForward] = raiseEventOptions.Flags.WebhookFlags; //TURNBASED + //} + } + + return this.SendOperation(OperationCode.RaiseEvent, this.opParameters, sendOptions); + } + #endif + + /// + /// Internally used operation to set some "per server" settings. This is for the Master Server. + /// + /// Set to true, to get Lobby Statistics (lists of existing lobbies). + /// False if the operation could not be sent. + public virtual bool OpSettings(bool receiveLobbyStats) + { + if (this.DebugOut >= DebugLevel.ALL) + { + this.Listener.DebugReturn(DebugLevel.ALL, "OpSettings()"); + } + + // re-used private variable to avoid many new Dictionary() calls (garbage collection) + this.opParameters.Clear(); + + // implementation for Master Server: + if (receiveLobbyStats) + { + this.opParameters[(byte)0] = receiveLobbyStats; + } + + if (this.opParameters.Count == 0) + { + // no need to send op in case we set the default values + return true; + } + return this.OpCustom((byte)OperationCode.ServerSettings, this.opParameters, true); + } + } + + + + internal class OpJoinRandomRoomParams + { + public Hashtable ExpectedCustomRoomProperties; + public byte ExpectedMaxPlayers; + public MatchmakingMode MatchingType; + public TypedLobby TypedLobby; + public string SqlLobbyFilter; + public string[] ExpectedUsers; + } + + internal class EnterRoomParams + { + public string RoomName; + public RoomOptions RoomOptions; + public TypedLobby Lobby; + public Hashtable PlayerProperties; + public bool OnGameServer = true; // defaults to true! better send more parameter than too few (GS needs all) + public bool CreateIfNotExists; + public bool RejoinOnly; + public string[] ExpectedUsers; + } + + + /// + /// ErrorCode defines the default codes associated with Photon client/server communication. + /// + public class ErrorCode + { + /// (0) is always "OK", anything else an error or specific situation. + public const int Ok = 0; + + // server - Photon low(er) level: <= 0 + + /// + /// (-3) Operation can't be executed yet (e.g. OpJoin can't be called before being authenticated, RaiseEvent cant be used before getting into a room). + /// + /// + /// Before you call any operations on the Cloud servers, the automated client workflow must complete its authorization. + /// In PUN, wait until State is: JoinedLobby (with AutoJoinLobby = true) or ConnectedToMaster (AutoJoinLobby = false) + /// + public const int OperationNotAllowedInCurrentState = -3; + + /// (-2) The operation you called is not implemented on the server (application) you connect to. Make sure you run the fitting applications. + [Obsolete("Use InvalidOperation.")] + public const int InvalidOperationCode = -2; + + /// (-2) The operation you called could not be executed on the server. + /// + /// Make sure you are connected to the server you expect. + /// + /// This code is used in several cases: + /// The arguments/parameters of the operation might be out of range, missing entirely or conflicting. + /// The operation you called is not implemented on the server (application). Server-side plugins affect the available operations. + /// + public const int InvalidOperation = -2; + + /// (-1) Something went wrong in the server. Try to reproduce and contact Exit Games. + public const int InternalServerError = -1; + + // server - PhotonNetwork: 0x7FFF and down + // logic-level error codes start with short.max + + /// (32767) Authentication failed. Possible cause: AppId is unknown to Photon (in cloud service). + public const int InvalidAuthentication = 0x7FFF; + + /// (32766) GameId (name) already in use (can't create another). Change name. + public const int GameIdAlreadyExists = 0x7FFF - 1; + + /// (32765) Game is full. This rarely happens when some player joined the room before your join completed. + public const int GameFull = 0x7FFF - 2; + + /// (32764) Game is closed and can't be joined. Join another game. + public const int GameClosed = 0x7FFF - 3; + + [Obsolete("No longer used, cause random matchmaking is no longer a process.")] + public const int AlreadyMatched = 0x7FFF - 4; + + /// (32762) Not in use currently. + public const int ServerFull = 0x7FFF - 5; + + /// (32761) Not in use currently. + public const int UserBlocked = 0x7FFF - 6; + + /// (32760) Random matchmaking only succeeds if a room exists thats neither closed nor full. Repeat in a few seconds or create a new room. + public const int NoRandomMatchFound = 0x7FFF - 7; + + /// (32758) Join can fail if the room (name) is not existing (anymore). This can happen when players leave while you join. + public const int GameDoesNotExist = 0x7FFF - 9; + + /// (32757) Authorization on the Photon Cloud failed becaus the concurrent users (CCU) limit of the app's subscription is reached. + /// + /// Unless you have a plan with "CCU Burst", clients might fail the authentication step during connect. + /// Affected client are unable to call operations. Please note that players who end a game and return + /// to the master server will disconnect and re-connect, which means that they just played and are rejected + /// in the next minute / re-connect. + /// This is a temporary measure. Once the CCU is below the limit, players will be able to connect an play again. + /// + /// OpAuthorize is part of connection workflow but only on the Photon Cloud, this error can happen. + /// Self-hosted Photon servers with a CCU limited license won't let a client connect at all. + /// + public const int MaxCcuReached = 0x7FFF - 10; + + /// (32756) Authorization on the Photon Cloud failed because the app's subscription does not allow to use a particular region's server. + /// + /// Some subscription plans for the Photon Cloud are region-bound. Servers of other regions can't be used then. + /// Check your master server address and compare it with your Photon Cloud Dashboard's info. + /// https://www.photonengine.com/dashboard + /// + /// OpAuthorize is part of connection workflow but only on the Photon Cloud, this error can happen. + /// Self-hosted Photon servers with a CCU limited license won't let a client connect at all. + /// + public const int InvalidRegion = 0x7FFF - 11; + + /// + /// (32755) Custom Authentication of the user failed due to setup reasons (see Cloud Dashboard) or the provided user data (like username or token). Check error message for details. + /// + public const int CustomAuthenticationFailed = 0x7FFF - 12; + + /// (32753) The Authentication ticket expired. Usually, this is refreshed behind the scenes. Connect (and authorize) again. + public const int AuthenticationTicketExpired = 0x7FF1; + + /// + /// (32752) A server-side plugin (or webhook) failed to execute and reported an error. Check the OperationResponse.DebugMessage. + /// + public const int PluginReportedError = 0x7FFF - 15; + + /// + /// (32751) CreateRoom/JoinRoom/Join operation fails if expected plugin does not correspond to loaded one. + /// + public const int PluginMismatch = 0x7FFF - 16; + + /// + /// (32750) for join requests. Indicates the current peer already called join and is joined to the room. + /// + public const int JoinFailedPeerAlreadyJoined = 32750; // 0x7FFF - 17, + + /// + /// (32749) for join requests. Indicates the list of InactiveActors already contains an actor with the requested ActorNr or UserId. + /// + public const int JoinFailedFoundInactiveJoiner = 32749; // 0x7FFF - 18, + + /// + /// (32748) for join requests. Indicates the list of Actors (active and inactive) did not contain an actor with the requested ActorNr or UserId. + /// + public const int JoinFailedWithRejoinerNotFound = 32748; // 0x7FFF - 19, + + /// + /// (32747) for join requests. Note: for future use - Indicates the requested UserId was found in the ExcludedList. + /// + public const int JoinFailedFoundExcludedUserId = 32747; // 0x7FFF - 20, + + /// + /// (32746) for join requests. Indicates the list of ActiveActors already contains an actor with the requested ActorNr or UserId. + /// + public const int JoinFailedFoundActiveJoiner = 32746; // 0x7FFF - 21, + + /// + /// (32745) for SetProerties and Raisevent (if flag HttpForward is true) requests. Indicates the maximum allowd http requests per minute was reached. + /// + public const int HttpLimitReached = 32745; // 0x7FFF - 22, + + /// + /// (32744) for WebRpc requests. Indicates the the call to the external service failed. + /// + public const int ExternalHttpCallFailed = 32744; // 0x7FFF - 23, + + /// + /// (32742) Server error during matchmaking with slot reservation. E.g. the reserved slots can not exceed MaxPlayers. + /// + public const int SlotError = 32742; // 0x7FFF - 25, + + /// + /// (32741) Server will react with this error if invalid encryption parameters provided by token + /// + public const int InvalidEncryptionParameters = 32741; // 0x7FFF - 24, + +} + + + /// + /// Class for constants. These (byte) values define "well known" properties for an Actor / Player. + /// + /// + /// Pun uses these constants internally. + /// "Custom properties" have to use a string-type as key. They can be assigned at will. + /// + public class ActorProperties + { + /// (255) Name of a player/actor. + public const byte PlayerName = 255; // was: 1 + + /// (254) Tells you if the player is currently in this game (getting events live). + /// A server-set value for async games, where players can leave the game and return later. + public const byte IsInactive = 254; + + /// (253) UserId of the player. Sent when room gets created with RoomOptions.PublishUserId = true. + public const byte UserId = 253; + } + + + /// + /// Class for constants. These (byte) values are for "well known" room/game properties used in Photon Loadbalancing. + /// + /// + /// Pun uses these constants internally. + /// "Custom properties" have to use a string-type as key. They can be assigned at will. + /// + public class GamePropertyKey + { + /// (255) Max number of players that "fit" into this room. 0 is for "unlimited". + public const byte MaxPlayers = 255; + + /// (254) Makes this room listed or not in the lobby on master. + public const byte IsVisible = 254; + + /// (253) Allows more players to join a room (or not). + public const byte IsOpen = 253; + + /// (252) Current count of players in the room. Used only in the lobby on master. + public const byte PlayerCount = 252; + + /// (251) True if the room is to be removed from room listing (used in update to room list in lobby on master) + public const byte Removed = 251; + + /// (250) A list of the room properties to pass to the RoomInfo list in a lobby. This is used in CreateRoom, which defines this list once per room. + public const byte PropsListedInLobby = 250; + + /// (249) Equivalent of Operation Join parameter CleanupCacheOnLeave. + public const byte CleanupCacheOnLeave = 249; + + /// (248) Code for MasterClientId, which is synced by server. When sent as op-parameter this is (byte)203. As room property this is (byte)248. + /// Tightly related to ParameterCode.MasterClientId. + public const byte MasterClientId = (byte)248; + + /// (247) Code for ExpectedUsers in a room. Matchmaking keeps a slot open for the players with these userIDs. + public const byte ExpectedUsers = (byte)247; + + /// (246) Player Time To Live. How long any player can be inactive (due to disconnect or leave) before the user gets removed from the playerlist (freeing a slot). + public const byte PlayerTtl = (byte)246; + + /// (245) Room Time To Live. How long a room stays available (and in server-memory), after the last player becomes inactive. After this time, the room gets persisted or destroyed. + public const byte EmptyRoomTtl = (byte)245; +} + + + /// + /// Class for constants. These values are for events defined by Photon Loadbalancing. + /// + /// They start at 255 and go DOWN. Your own in-game events can start at 0. Pun uses these constants internally. + public class EventCode + { + /// (230) Initial list of RoomInfos (in lobby on Master) + public const byte GameList = 230; + + /// (229) Update of RoomInfos to be merged into "initial" list (in lobby on Master) + public const byte GameListUpdate = 229; + + /// (228) Currently not used. State of queueing in case of server-full + public const byte QueueState = 228; + + /// (227) Currently not used. Event for matchmaking + public const byte Match = 227; + + /// (226) Event with stats about this application (players, rooms, etc) + public const byte AppStats = 226; + + /// (224) This event provides a list of lobbies with their player and game counts. + public const byte LobbyStats = 224; + + /// (210) Internally used in case of hosting by Azure + [Obsolete("TCP routing was removed after becoming obsolete.")] + public const byte AzureNodeInfo = 210; + + /// (255) Event Join: someone joined the game. The new actorNumber is provided as well as the properties of that actor (if set in OpJoin). + public const byte Join = (byte)255; + + /// (254) Event Leave: The player who left the game can be identified by the actorNumber. + public const byte Leave = (byte)254; + + /// (253) When you call OpSetProperties with the broadcast option "on", this event is fired. It contains the properties being set. + public const byte PropertiesChanged = (byte)253; + + /// (253) When you call OpSetProperties with the broadcast option "on", this event is fired. It contains the properties being set. + [Obsolete("Use PropertiesChanged now.")] + public const byte SetProperties = (byte)253; + + /// (252) When player left game unexpected and the room has a playerTtl != 0, this event is fired to let everyone know about the timeout. + /// Obsolete. Replaced by Leave. public const byte Disconnect = LiteEventCode.Disconnect; + + /// (251) Sent by Photon Cloud when a plugin-call or webhook-call failed. Usually, the execution on the server continues, despite the issue. Contains: ParameterCode.Info. + /// + public const byte ErrorInfo = 251; + + /// (250) Sent by Photon whent he event cache slice was changed. Done by OpRaiseEvent. + public const byte CacheSliceChanged = 250; + + /// (223) Sent by Photon to update a token before it times out. + public const byte AuthEvent = 223; + } + + + /// Class for constants. Codes for parameters of Operations and Events. + /// Pun uses these constants internally. + public class ParameterCode + { + /// (237) A bool parameter for creating games. If set to true, no room events are sent to the clients on join and leave. Default: false (and not sent). + public const byte SuppressRoomEvents = 237; + + /// (236) Time To Live (TTL) for a room when the last player leaves. Keeps room in memory for case a player re-joins soon. In milliseconds. + public const byte EmptyRoomTTL = 236; + + /// (235) Time To Live (TTL) for an 'actor' in a room. If a client disconnects, this actor is inactive first and removed after this timeout. In milliseconds. + public const byte PlayerTTL = 235; + + /// (234) Optional parameter of OpRaiseEvent and OpSetCustomProperties to forward the event/operation to a web-service. + public const byte EventForward = 234; + + /// (233) Optional parameter of OpLeave in async games. If false, the player does abandons the game (forever). By default players become inactive and can re-join. + [Obsolete("Use: IsInactive")] + public const byte IsComingBack = (byte)233; + + /// (233) Used in EvLeave to describe if a user is inactive (and might come back) or not. In rooms with PlayerTTL, becoming inactive is the default case. + public const byte IsInactive = (byte)233; + + /// (232) Used when creating rooms to define if any userid can join the room only once. + public const byte CheckUserOnJoin = (byte)232; + + /// (231) Code for "Check And Swap" (CAS) when changing properties. + public const byte ExpectedValues = (byte)231; + + /// (230) Address of a (game) server to use. + public const byte Address = 230; + + /// (229) Count of players in this application in a rooms (used in stats event) + public const byte PeerCount = 229; + + /// (228) Count of games in this application (used in stats event) + public const byte GameCount = 228; + + /// (227) Count of players on the master server (in this app, looking for rooms) + public const byte MasterPeerCount = 227; + + /// (225) User's ID + public const byte UserId = 225; + + /// (224) Your application's ID: a name on your own Photon or a GUID on the Photon Cloud + public const byte ApplicationId = 224; + + /// (223) Not used currently (as "Position"). If you get queued before connect, this is your position + public const byte Position = 223; + + /// (223) Modifies the matchmaking algorithm used for OpJoinRandom. Allowed parameter values are defined in enum MatchmakingMode. + public const byte MatchMakingType = 223; + + /// (222) List of RoomInfos about open / listed rooms + public const byte GameList = 222; + + /// (221) Internally used to establish encryption + public const byte Secret = 221; + + /// (220) Version of your application + public const byte AppVersion = 220; + + /// (210) Internally used in case of hosting by Azure + [Obsolete("TCP routing was removed after becoming obsolete.")] + public const byte AzureNodeInfo = 210; // only used within events, so use: EventCode.AzureNodeInfo + + /// (209) Internally used in case of hosting by Azure + [Obsolete("TCP routing was removed after becoming obsolete.")] + public const byte AzureLocalNodeId = 209; + + /// (208) Internally used in case of hosting by Azure + [Obsolete("TCP routing was removed after becoming obsolete.")] + public const byte AzureMasterNodeId = 208; + + /// (255) Code for the gameId/roomName (a unique name per room). Used in OpJoin and similar. + public const byte RoomName = (byte)255; + + /// (250) Code for broadcast parameter of OpSetProperties method. + public const byte Broadcast = (byte)250; + + /// (252) Code for list of players in a room. Currently not used. + public const byte ActorList = (byte)252; + + /// (254) Code of the Actor of an operation. Used for property get and set. + public const byte ActorNr = (byte)254; + + /// (249) Code for property set (Hashtable). + public const byte PlayerProperties = (byte)249; + + /// (245) Code of data/custom content of an event. Used in OpRaiseEvent. + public const byte CustomEventContent = (byte)245; + + /// (245) Code of data of an event. Used in OpRaiseEvent. + public const byte Data = (byte)245; + + /// (244) Code used when sending some code-related parameter, like OpRaiseEvent's event-code. + /// This is not the same as the Operation's code, which is no longer sent as part of the parameter Dictionary in Photon 3. + public const byte Code = (byte)244; + + /// (248) Code for property set (Hashtable). + public const byte GameProperties = (byte)248; + + /// + /// (251) Code for property-set (Hashtable). This key is used when sending only one set of properties. + /// If either ActorProperties or GameProperties are used (or both), check those keys. + /// + public const byte Properties = (byte)251; + + /// (253) Code of the target Actor of an operation. Used for property set. Is 0 for game + public const byte TargetActorNr = (byte)253; + + /// (246) Code to select the receivers of events (used in Lite, Operation RaiseEvent). + public const byte ReceiverGroup = (byte)246; + + /// (247) Code for caching events while raising them. + public const byte Cache = (byte)247; + + /// (241) Bool parameter of CreateRoom Operation. If true, server cleans up roomcache of leaving players (their cached events get removed). + public const byte CleanupCacheOnLeave = (byte)241; + + /// (240) Code for "group" operation-parameter (as used in Op RaiseEvent). + public const byte Group = 240; + + /// (239) The "Remove" operation-parameter can be used to remove something from a list. E.g. remove groups from player's interest groups. + public const byte Remove = 239; + + /// (239) Used in Op Join to define if UserIds of the players are broadcast in the room. Useful for FindFriends and reserving slots for expected users. + public const byte PublishUserId = 239; + + /// (238) The "Add" operation-parameter can be used to add something to some list or set. E.g. add groups to player's interest groups. + public const byte Add = 238; + + /// (218) Content for EventCode.ErrorInfo and internal debug operations. + public const byte Info = 218; + + /// (217) This key's (byte) value defines the target custom authentication type/service the client connects with. Used in OpAuthenticate + public const byte ClientAuthenticationType = 217; + + /// (216) This key's (string) value provides parameters sent to the custom authentication type/service the client connects with. Used in OpAuthenticate + public const byte ClientAuthenticationParams = 216; + + /// (215) Makes the server create a room if it doesn't exist. OpJoin uses this to always enter a room, unless it exists and is full/closed. + // public const byte CreateIfNotExists = 215; + + /// (215) The JoinMode enum defines which variant of joining a room will be executed: Join only if available, create if not exists or re-join. + /// Replaces CreateIfNotExists which was only a bool-value. + public const byte JoinMode = 215; + + /// (214) This key's (string or byte[]) value provides parameters sent to the custom authentication service setup in Photon Dashboard. Used in OpAuthenticate + public const byte ClientAuthenticationData = 214; + + /// (203) Code for MasterClientId, which is synced by server. When sent as op-parameter this is code 203. + /// Tightly related to GamePropertyKey.MasterClientId. + public const byte MasterClientId = (byte)203; + + /// (1) Used in Op FindFriends request. Value must be string[] of friends to look up. + public const byte FindFriendsRequestList = (byte)1; + + /// (1) Used in Op FindFriends response. Contains bool[] list of online states (false if not online). + public const byte FindFriendsResponseOnlineList = (byte)1; + + /// (2) Used in Op FindFriends response. Contains string[] of room names ("" where not known or no room joined). + public const byte FindFriendsResponseRoomIdList = (byte)2; + + /// (213) Used in matchmaking-related methods and when creating a room to name a lobby (to join or to attach a room to). + public const byte LobbyName = (byte)213; + + /// (212) Used in matchmaking-related methods and when creating a room to define the type of a lobby. Combined with the lobby name this identifies the lobby. + public const byte LobbyType = (byte)212; + + /// (211) This (optional) parameter can be sent in Op Authenticate to turn on Lobby Stats (info about lobby names and their user- and game-counts). See: PhotonNetwork.Lobbies + public const byte LobbyStats = (byte)211; + + /// (210) Used for region values in OpAuth and OpGetRegions. + public const byte Region = (byte)210; + + /// (209) Path of the WebRPC that got called. Also known as "WebRpc Name". Type: string. + public const byte UriPath = 209; + + /// (208) Parameters for a WebRPC as: Dictionary<string, object>. This will get serialized to JSon. + public const byte WebRpcParameters = 208; + + /// (207) ReturnCode for the WebRPC, as sent by the web service (not by Photon, which uses ErrorCode). Type: byte. + public const byte WebRpcReturnCode = 207; + + /// (206) Message returned by WebRPC server. Analog to Photon's debug message. Type: string. + public const byte WebRpcReturnMessage = 206; + + /// (205) Used to define a "slice" for cached events. Slices can easily be removed from cache. Type: int. + public const byte CacheSliceIndex = 205; + + /// (204) Informs the server of the expected plugin setup. + /// + /// The operation will fail in case of a plugin mismatch returning error code PluginMismatch 32751(0x7FFF - 16). + /// Setting string[]{} means the client expects no plugin to be setup. + /// Note: for backwards compatibility null omits any check. + /// + public const byte Plugins = 204; + + /// (202) Used by the server in Operation Responses, when it sends the nickname of the client (the user's nickname). + public const byte NickName = 202; + + /// (201) Informs user about name of plugin load to game + public const byte PluginName = 201; + + /// (200) Informs user about version of plugin load to game + public const byte PluginVersion = 200; + + /// (195) Protocol which will be used by client to connect master/game servers. Used for nameserver. + public const byte ExpectedProtocol = 195; + + /// (194) Set of custom parameters which are sent in auth request. + public const byte CustomInitData = 194; + + /// (193) How are we going to encrypt data. + public const byte EncryptionMode = 193; + + /// (192) Parameter of Authentication, which contains encryption keys (depends on AuthMode and EncryptionMode). + public const byte EncryptionData = 192; + + /// (191) An int parameter summarizing several boolean room-options with bit-flags. + public const byte RoomOptionFlags = 191; + } + + + /// + /// Class for constants. Contains operation codes. + /// Pun uses these constants internally. + /// + public class OperationCode + { + [Obsolete("Exchanging encrpytion keys is done internally in the lib now. Don't expect this operation-result.")] + public const byte ExchangeKeysForEncryption = 250; + + /// (255) Code for OpJoin, to get into a room. + [Obsolete] + public const byte Join = 255; + + /// (231) Authenticates this peer and connects to a virtual application + public const byte AuthenticateOnce = 231; + + /// (230) Authenticates this peer and connects to a virtual application + public const byte Authenticate = 230; + + /// (229) Joins lobby (on master) + public const byte JoinLobby = 229; + + /// (228) Leaves lobby (on master) + public const byte LeaveLobby = 228; + + /// (227) Creates a game (or fails if name exists) + public const byte CreateGame = 227; + + /// (226) Join game (by name) + public const byte JoinGame = 226; + + /// (225) Joins random game (on master) + public const byte JoinRandomGame = 225; + + // public const byte CancelJoinRandom = 224; // obsolete, cause JoinRandom no longer is a "process". now provides result immediately + + /// (254) Code for OpLeave, to get out of a room. + public const byte Leave = (byte)254; + + /// (253) Raise event (in a room, for other actors/players) + public const byte RaiseEvent = (byte)253; + + /// (252) Set Properties (of room or actor/player) + public const byte SetProperties = (byte)252; + + /// (251) Get Properties + public const byte GetProperties = (byte)251; + + /// (248) Operation code to change interest groups in Rooms (Lite application and extending ones). + public const byte ChangeGroups = (byte)248; + + /// (222) Request the rooms and online status for a list of friends (by name, which should be unique). + public const byte FindFriends = 222; + + /// (221) Request statistics about a specific list of lobbies (their user and game count). + public const byte GetLobbyStats = 221; + + /// (220) Get list of regional servers from a NameServer. + public const byte GetRegions = 220; + + /// (219) WebRpc Operation. + public const byte WebRpc = 219; + + /// (218) Operation to set some server settings. Used with different parameters on various servers. + public const byte ServerSettings = 218; + + /// (217) Get the game list matching a supplied sql filter (SqlListLobby only) + public const byte GetGameList = 217; + } + + /// Defines possible values for OpJoinRoom and OpJoinOrCreate. It tells the server if the room can be only be joined normally, created implicitly or found on a web-service for Turnbased games. + /// These values are not directly used by a game but implicitly set. + public enum JoinMode : byte + { + /// Regular join. The room must exist. + Default = 0, + + /// Join or create the room if it's not existing. Used for OpJoinOrCreate for example. + CreateIfNotExists = 1, + + /// The room might be out of memory and should be loaded (if possible) from a Turnbased web-service. + JoinOrRejoin = 2, + + /// Only re-join will be allowed. If the user is not yet in the room, this will fail. + RejoinOnly = 3, + } + + /// + /// Options for matchmaking rules for OpJoinRandom. + /// + public enum MatchmakingMode : byte + { + /// Fills up rooms (oldest first) to get players together as fast as possible. Default. + /// Makes most sense with MaxPlayers > 0 and games that can only start with more players. + FillRoom = 0, + + /// Distributes players across available rooms sequentially but takes filter into account. Without filter, rooms get players evenly distributed. + SerialMatching = 1, + + /// Joins a (fully) random room. Expected properties must match but aside from this, any available room might be selected. + RandomMatching = 2 + } + + + /// + /// Lite - OpRaiseEvent lets you chose which actors in the room should receive events. + /// By default, events are sent to "Others" but you can overrule this. + /// + public enum ReceiverGroup : byte + { + /// Default value (not sent). Anyone else gets my event. + Others = 0, + + /// Everyone in the current room (including this peer) will get this event. + All = 1, + + /// The server sends this event only to the actor with the lowest actorNumber. + /// The "master client" does not have special rights but is the one who is in this room the longest time. + MasterClient = 2, + } + + /// + /// Lite - OpRaiseEvent allows you to cache events and automatically send them to joining players in a room. + /// Events are cached per event code and player: Event 100 (example!) can be stored once per player. + /// Cached events can be modified, replaced and removed. + /// + /// + /// Caching works only combination with ReceiverGroup options Others and All. + /// + public enum EventCaching : byte + { + /// Default value (not sent). + DoNotCache = 0, + + /// Will merge this event's keys with those already cached. + [Obsolete] + MergeCache = 1, + + /// Replaces the event cache for this eventCode with this event's content. + [Obsolete] + ReplaceCache = 2, + + /// Removes this event (by eventCode) from the cache. + [Obsolete] + RemoveCache = 3, + + /// Adds an event to the room's cache + AddToRoomCache = 4, + + /// Adds this event to the cache for actor 0 (becoming a "globally owned" event in the cache). + AddToRoomCacheGlobal = 5, + + /// Remove fitting event from the room's cache. + RemoveFromRoomCache = 6, + + /// Removes events of players who already left the room (cleaning up). + RemoveFromRoomCacheForActorsLeft = 7, + + /// Increase the index of the sliced cache. + SliceIncreaseIndex = 10, + + /// Set the index of the sliced cache. You must set RaiseEventOptions.CacheSliceIndex for this. + SliceSetIndex = 11, + + /// Purge cache slice with index. Exactly one slice is removed from cache. You must set RaiseEventOptions.CacheSliceIndex for this. + SlicePurgeIndex = 12, + + /// Purge cache slices with specified index and anything lower than that. You must set RaiseEventOptions.CacheSliceIndex for this. + SlicePurgeUpToIndex = 13, + } + + /// + /// Flags for "types of properties", being used as filter in OpGetProperties. + /// + [Flags] + public enum PropertyTypeFlag : byte + { + /// (0x00) Flag type for no property type. + None = 0x00, + + /// (0x01) Flag type for game-attached properties. + Game = 0x01, + + /// (0x02) Flag type for actor related propeties. + Actor = 0x02, + + /// (0x01) Flag type for game AND actor properties. Equal to 'Game' + GameAndActor = Game | Actor + } + + + /// Wraps up common room properties needed when you create rooms. Read the individual entries for more details. + /// This directly maps to the fields in the Room class. + public class RoomOptions + { + /// Defines if this room is listed in the lobby. If not, it also is not joined randomly. + /// + /// A room that is not visible will be excluded from the room lists that are sent to the clients in lobbies. + /// An invisible room can be joined by name but is excluded from random matchmaking. + /// + /// Use this to "hide" a room and simulate "private rooms". Players can exchange a roomname and create it + /// invisble to avoid anyone else joining it. + /// + public bool IsVisible { get { return this.isVisibleField; } set { this.isVisibleField = value; } } + private bool isVisibleField = true; + + /// Defines if this room can be joined at all. + /// + /// If a room is closed, no player can join this. As example this makes sense when 3 of 4 possible players + /// start their gameplay early and don't want anyone to join during the game. + /// The room can still be listed in the lobby (set IsVisible to control lobby-visibility). + /// + public bool IsOpen { get { return this.isOpenField; } set { this.isOpenField = value; } } + private bool isOpenField = true; + + /// Max number of players that can be in the room at any time. 0 means "no limit". + public byte MaxPlayers; + + + /// Time To Live (TTL) for an 'actor' in a room. If a client disconnects, this actor is inactive first and removed after this timeout. In milliseconds. + public int PlayerTtl; + + + /// Time To Live (TTL) for a room when the last player leaves. Keeps room in memory for case a player re-joins soon. In milliseconds. + public int EmptyRoomTtl; + + ///// Activates UserId checks on joining - allowing a users to be only once in the room. + ///// + ///// Turnbased rooms should be created with this check turned on! They should also use custom authentication. + ///// Disabled by default for backwards-compatibility. + ///// + //public bool CheckUserOnJoin { get { return this.checkUserOnJoinField; } set { this.checkUserOnJoinField = value; } } + //private bool checkUserOnJoinField = false; + + /// Removes a user's events and properties from the room when a user leaves. + /// + /// This makes sense when in rooms where players can't place items in the room and just vanish entirely. + /// When you disable this, the event history can become too long to load if the room stays in use indefinitely. + /// Default: true. Cleans up the cache and props of leaving users. + /// + public bool CleanupCacheOnLeave { get { return this.cleanupCacheOnLeaveField; } set { this.cleanupCacheOnLeaveField = value; } } + private bool cleanupCacheOnLeaveField = PhotonNetwork.autoCleanUpPlayerObjects; + + /// The room's custom properties to set. Use string keys! + /// + /// Custom room properties are any key-values you need to define the game's setup. + /// The shorter your keys are, the better. + /// Example: Map, Mode (could be "m" when used with "Map"), TileSet (could be "t"). + /// + public Hashtable CustomRoomProperties; + + /// Defines the custom room properties that get listed in the lobby. + /// + /// Name the custom room properties that should be available to clients that are in a lobby. + /// Use with care. Unless a custom property is essential for matchmaking or user info, it should + /// not be sent to the lobby, which causes traffic and delays for clients in the lobby. + /// + /// Default: No custom properties are sent to the lobby. + /// + public string[] CustomRoomPropertiesForLobby = new string[0]; + + /// Informs the server of the expected plugin setup. + /// + /// The operation will fail in case of a plugin missmatch returning error code PluginMismatch 32757(0x7FFF - 10). + /// Setting string[]{} means the client expects no plugin to be setup. + /// Note: for backwards compatibility null omits any check. + /// + public string[] Plugins; + + /// + /// Tells the server to skip room events for joining and leaving players. + /// + /// + /// Using this makes the client unaware of the other players in a room. + /// That can save some traffic if you have some server logic that updates players + /// but it can also limit the client's usability. + /// + /// PUN will break if you use this, so it's not settable. + /// + public bool SuppressRoomEvents { get { return this.suppressRoomEventsField; } /*set { this.suppressRoomEventsField = value; }*/ } + private bool suppressRoomEventsField = false; + + /// + /// Defines if the UserIds of players get "published" in the room. Useful for FindFriends, if players want to play another game together. + /// + /// + /// When you set this to true, Photon will publish the UserIds of the players in that room. + /// In that case, you can use PhotonPlayer.UserId, to access any player's userID. + /// This is useful for FindFriends and to set "expected users" to reserve slots in a room (see PhotonNetwork.JoinRoom e.g.). + /// + public bool PublishUserId { get { return this.publishUserIdField; } set { this.publishUserIdField = value; } } + private bool publishUserIdField = false; + + /// Optionally, properties get deleted, when null gets assigned as value. Defaults to off / false. + /// + /// When Op SetProperties is setting a key's value to null, the server and clients should remove the key/value from the Custom Properties. + /// By default, the server keeps the keys (and null values) and sends them to joining players. + /// + /// Important: Only when SetProperties does a "broadcast", the change (key, value = null) is sent to clients to update accordingly. + /// This applies to Custom Properties for rooms and actors/players. + /// + public bool DeleteNullProperties { get { return this.deleteNullPropertiesField; } set { this.deleteNullPropertiesField = value; } } + private bool deleteNullPropertiesField = false; + + #region Obsoleted Naming + + [Obsolete("Use property with uppercase naming instead.")] + public bool isVisible { get { return this.isVisibleField; } set { this.isVisibleField = value; } } + [Obsolete("Use property with uppercase naming instead.")] + public bool isOpen { get { return this.isOpenField; } set { this.isOpenField = value; } } + [Obsolete("Use property with uppercase naming instead.")] + public byte maxPlayers { get { return this.MaxPlayers; } set { this.MaxPlayers = value; } } + [Obsolete("Use property with uppercase naming instead.")] + public bool cleanupCacheOnLeave { get { return this.cleanupCacheOnLeaveField; } set { this.cleanupCacheOnLeaveField = value; } } + [Obsolete("Use property with uppercase naming instead.")] + public Hashtable customRoomProperties { get { return this.CustomRoomProperties; } set { this.CustomRoomProperties = value; } } + [Obsolete("Use property with uppercase naming instead.")] + public string[] customRoomPropertiesForLobby { get { return this.CustomRoomPropertiesForLobby; } set { this.CustomRoomPropertiesForLobby = value; } } + [Obsolete("Use property with uppercase naming instead.")] + public string[] plugins { get { return this.Plugins; } set { this.Plugins = value; } } + [Obsolete("Use property with uppercase naming instead.")] + public bool suppressRoomEvents { get { return this.suppressRoomEventsField; } } + [Obsolete("Use property with uppercase naming instead.")] + public bool publishUserId { get { return this.publishUserIdField; } set { this.publishUserIdField = value; } } + + #endregion +} + + + /// Aggregates several less-often used options for operation RaiseEvent. See field descriptions for usage details. + public class RaiseEventOptions + { + /// Default options: CachingOption: DoNotCache, InterestGroup: 0, targetActors: null, receivers: Others, sequenceChannel: 0. + public readonly static RaiseEventOptions Default = new RaiseEventOptions(); + + /// + /// Reset this instance. For better memory handling than instanciating a new one always, + /// + public void Reset() + { + this.CachingOption = Default.CachingOption; + this.InterestGroup = Default.InterestGroup; + this.TargetActors = Default.TargetActors; + this.Receivers = Default.Receivers; + this.SequenceChannel = Default.SequenceChannel; + this.ForwardToWebhook = Default.ForwardToWebhook; + this.Encrypt = Default.Encrypt; + } + + /// Defines if the server should simply send the event, put it in the cache or remove events that are like this one. + /// + /// When using option: SliceSetIndex, SlicePurgeIndex or SlicePurgeUpToIndex, set a CacheSliceIndex. All other options except SequenceChannel get ignored. + /// + public EventCaching CachingOption; + + /// The number of the Interest Group to send this to. 0 goes to all users but to get 1 and up, clients must subscribe to the group first. + public byte InterestGroup; + + /// A list of PhotonPlayer.IDs to send this event to. You can implement events that just go to specific users this way. + public int[] TargetActors; + + /// Sends the event to All, MasterClient or Others (default). Be careful with MasterClient, as the client might disconnect before it got the event and it gets lost. + public ReceiverGroup Receivers; + + /// Events are ordered per "channel". If you have events that are independent of others, they can go into another sequence or channel. + public byte SequenceChannel; + + /// Events can be forwarded to Webhooks, which can evaluate and use the events to follow the game's state. + public bool ForwardToWebhook; + + ///// Used along with CachingOption SliceSetIndex, SlicePurgeIndex or SlicePurgeUpToIndex if you want to set or purge a specific cache-slice. + //public int CacheSliceIndex; + + public bool Encrypt; + } + + /// + /// Options of lobby types available. Lobby types might be implemented in certain Photon versions and won't be available on older servers. + /// + public enum LobbyType :byte + { + /// This lobby is used unless another is defined by game or JoinRandom. Room-lists will be sent and JoinRandomRoom can filter by matching properties. + Default = 0, + /// This lobby type lists rooms like Default but JoinRandom has a parameter for SQL-like "where" clauses for filtering. This allows bigger, less, or and and combinations. + SqlLobby = 2, + /// This lobby does not send lists of games. It is only used for OpJoinRandomRoom. It keeps rooms available for a while when there are only inactive users left. + AsyncRandomLobby = 3 + } + + /// Refers to a specific lobby (and type) on the server. + /// + /// The name and type are the unique identifier for a lobby.
+ /// Join a lobby via PhotonNetwork.JoinLobby(TypedLobby lobby).
+ /// The current lobby is stored in PhotonNetwork.lobby. + ///
+ public class TypedLobby + { + /// Name of the lobby this game gets added to. Default: null, attached to default lobby. Lobbies are unique per lobbyName plus lobbyType, so the same name can be used when several types are existing. + public string Name; + /// Type of the (named)lobby this game gets added to + public LobbyType Type; + + public static readonly TypedLobby Default = new TypedLobby(); + public bool IsDefault { get { return this.Type == LobbyType.Default && string.IsNullOrEmpty(this.Name); } } + + public TypedLobby() + { + this.Name = string.Empty; + this.Type = LobbyType.Default; + } + + public TypedLobby(string name, LobbyType type) + { + this.Name = name; + this.Type = type; + } + + public override string ToString() + { + return String.Format((string) "lobby '{0}'[{1}]", (object) this.Name, (object) this.Type); + } + } + + public class TypedLobbyInfo : TypedLobby + { + public int PlayerCount; + public int RoomCount; + + public override string ToString() + { + return string.Format("TypedLobbyInfo '{0}'[{1}] rooms: {2} players: {3}", this.Name, this.Type, this.RoomCount, this.PlayerCount); + } + } + + + /// + /// Options for authentication modes. From "classic" auth on each server to AuthOnce (on NameServer). + /// + public enum AuthModeOption { Auth, AuthOnce, AuthOnceWss } + + + /// + /// Options for optional "Custom Authentication" services used with Photon. Used by OpAuthenticate after connecting to Photon. + /// + public enum CustomAuthenticationType : byte + { + /// Use a custom authentification service. Currently the only implemented option. + Custom = 0, + + /// Authenticates users by their Steam Account. Set auth values accordingly! + Steam = 1, + + /// Authenticates users by their Facebook Account. Set auth values accordingly! + Facebook = 2, + + /// Authenticates users by their Oculus Account and token. + Oculus = 3, + + /// Authenticates users by their PSN Account and token. + PlayStation = 4, + + /// Authenticates users by their Xbox Account and XSTS token. + Xbox = 5, + + /// Disables custom authentification. Same as not providing any AuthenticationValues for connect (more precisely for: OpAuthenticate). + None = byte.MaxValue + } + + + /// + /// Container for user authentication in Photon. Set AuthValues before you connect - all else is handled. + /// + /// + /// On Photon, user authentication is optional but can be useful in many cases. + /// If you want to FindFriends, a unique ID per user is very practical. + /// + /// There are basically three options for user authentification: None at all, the client sets some UserId + /// or you can use some account web-service to authenticate a user (and set the UserId server-side). + /// + /// Custom Authentication lets you verify end-users by some kind of login or token. It sends those + /// values to Photon which will verify them before granting access or disconnecting the client. + /// + /// The AuthValues are sent in OpAuthenticate when you connect, so they must be set before you connect. + /// Should you not set any AuthValues, PUN will create them and set the playerName as userId in them. + /// If the AuthValues.userId is null or empty when it's sent to the server, then the Photon Server assigns a userId! + /// + /// The Photon Cloud Dashboard will let you enable this feature and set important server values for it. + /// https://www.photonengine.com/dashboard + /// + public class AuthenticationValues + { + /// See AuthType. + private CustomAuthenticationType authType = CustomAuthenticationType.None; + + /// The type of custom authentication provider that should be used. Currently only "Custom" or "None" (turns this off). + public CustomAuthenticationType AuthType + { + get { return authType; } + set { authType = value; } + } + + /// This string must contain any (http get) parameters expected by the used authentication service. By default, username and token. + /// Standard http get parameters are used here and passed on to the service that's defined in the server (Photon Cloud Dashboard). + public string AuthGetParameters { get; set; } + + /// Data to be passed-on to the auth service via POST. Default: null (not sent). Either string or byte[] (see setters). + public object AuthPostData { get; private set; } + + /// After initial authentication, Photon provides a token for this client / user, which is subsequently used as (cached) validation. + public string Token { get; set; } + + /// The UserId should be a unique identifier per user. This is for finding friends, etc.. + /// See remarks of AuthValues for info about how this is set and used. + public string UserId { get; set; } + + + /// Creates empty auth values without any info. + public AuthenticationValues() + { + } + + /// Creates minimal info about the user. If this is authenticated or not, depends on the set AuthType. + /// Some UserId to set in Photon. + public AuthenticationValues(string userId) + { + this.UserId = userId; + } + + /// Sets the data to be passed-on to the auth service via POST. + /// AuthPostData is just one value. Each SetAuthPostData replaces any previous value. It can be either a string, a byte[] or a dictionary. Each SetAuthPostData replaces any previous value. + /// String data to be used in the body of the POST request. Null or empty string will set AuthPostData to null. + public virtual void SetAuthPostData(string stringData) + { + this.AuthPostData = (string.IsNullOrEmpty(stringData)) ? null : stringData; + } + + /// Sets the data to be passed-on to the auth service via POST. + /// AuthPostData is just one value. Each SetAuthPostData replaces any previous value. It can be either a string, a byte[] or a dictionary. Each SetAuthPostData replaces any previous value. + /// Binary token / auth-data to pass on. + public virtual void SetAuthPostData(byte[] byteData) + { + this.AuthPostData = byteData; + } + + /// Sets data to be passed-on to the auth service as Json (Content-Type: "application/json") via Post. + /// AuthPostData is just one value. Each SetAuthPostData replaces any previous value. It can be either a string, a byte[] or a dictionary. Each SetAuthPostData replaces any previous value. + /// A authentication-data dictionary will be converted to Json and passed to the Auth webservice via HTTP Post. + public virtual void SetAuthPostData(Dictionary dictData) + { + this.AuthPostData = dictData; + } + + /// Adds a key-value pair to the get-parameters used for Custom Auth. + /// This method does uri-encoding for you. + /// Key for the value to set. + /// Some value relevant for Custom Authentication. + public virtual void AddAuthParameter(string key, string value) + { + string ampersand = string.IsNullOrEmpty(this.AuthGetParameters) ? "" : "&"; + this.AuthGetParameters = string.Format("{0}{1}{2}={3}", this.AuthGetParameters, ampersand, System.Uri.EscapeDataString(key), System.Uri.EscapeDataString(value)); + } + + public override string ToString() + { + return string.Format("AuthenticationValues UserId: {0}, GetParameters: {1} Token available: {2}", this.UserId, this.AuthGetParameters, this.Token != null); + } + } diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/LoadbalancingPeer.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/LoadbalancingPeer.cs.meta new file mode 100644 index 0000000..285a822 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/LoadbalancingPeer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 35c989013c977244186e524a4c90dcee +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs new file mode 100644 index 0000000..8606e39 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs @@ -0,0 +1,4712 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Part of: Photon Unity Networking (PUN) +// +// -------------------------------------------------------------------------------------------------------------------- + +using ExitGames.Client.Photon; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using UnityEngine; +using Hashtable = ExitGames.Client.Photon.Hashtable; +using SupportClassPun = ExitGames.Client.Photon.SupportClass; +using UnityEngine.SceneManagement; + + + +#region Enums + +/// +/// Detailed connection / networking peer state. +/// PUN implements a loadbalancing and authentication workflow "behind the scenes", so +/// some states will automatically advance to some follow up state. Those states are +/// commented with "(will-change)". +/// +/// \ingroup publicApi +public enum ClientState +{ + /// Not running. Only set before initialization and first use. + Uninitialized, + + /// Created and available to connect. + PeerCreated, + + /// Not used at the moment. + Queued, + + /// The application is authenticated. PUN usually joins the lobby now. + /// (will-change) Unless AutoJoinLobby is false. + Authenticated, + + /// Client is in the lobby of the Master Server and gets room listings. + /// Use Join, Create or JoinRandom to get into a room to play. + JoinedLobby, + + /// Disconnecting. + /// (will-change) + DisconnectingFromMasterserver, + + /// Connecting to game server (to join/create a room and play). + /// (will-change) + ConnectingToGameserver, + + /// Similar to Connected state but on game server. Still in process to join/create room. + /// (will-change) + ConnectedToGameserver, + + /// In process to join/create room (on game server). + /// (will-change) + Joining, + + /// Final state of a room join/create sequence. This client can now exchange events / call RPCs with other clients. + Joined, + + /// Leaving a room. + /// (will-change) + Leaving, + + /// Workflow is leaving the game server and will re-connect to the master server. + /// (will-change) + DisconnectingFromGameserver, + + /// Workflow is connected to master server and will establish encryption and authenticate your app. + /// (will-change) + ConnectingToMasterserver, + + /// Same Queued but coming from game server. + /// (will-change) + QueuedComingFromGameserver, + + /// PUN is disconnecting. This leads to Disconnected. + /// (will-change) + Disconnecting, + + /// No connection is setup, ready to connect. Similar to PeerCreated. + Disconnected, + + /// Final state for connecting to master without joining the lobby (AutoJoinLobby is false). + ConnectedToMaster, + + /// Client connects to the NameServer. This process includes low level connecting and setting up encryption. When done, state becomes ConnectedToNameServer. + ConnectingToNameServer, + + /// Client is connected to the NameServer and established enctryption already. You should call OpGetRegions or ConnectToRegionMaster. + ConnectedToNameServer, + + /// When disconnecting from a Photon NameServer. + /// (will-change) + DisconnectingFromNameServer, + + /// When connecting to a Photon Server, this state is intermediate before you can call any operations. + /// (will-change) + Authenticating +} + + + /// + /// Internal state, how this peer gets into a particular room (joining it or creating it). + /// + internal enum JoinType + { + /// This client creates a room, gets into it (no need to join) and can set room properties. + CreateRoom, + /// The room existed already and we join into it (not setting room properties). + JoinRoom, + /// Done on Master Server and (if successful) followed by a Join on Game Server. + JoinRandomRoom, + /// Client is either joining or creating a room. On Master- and Game-Server. + JoinOrCreateRoom + } + + +/// +/// Summarizes the cause for a disconnect. Used in: OnConnectionFail and OnFailedToConnectToPhoton. +/// +/// Extracted from the status codes from ExitGames.Client.Photon.StatusCode. +/// +/// \ingroup publicApi +public enum DisconnectCause +{ + /// Server actively disconnected this client. + /// Possible cause: The server's user limit was hit and client was forced to disconnect (on connect). + DisconnectByServerUserLimit = StatusCode.DisconnectByServerUserLimit, + + /// Connection could not be established. + /// Possible cause: Local server not running. + ExceptionOnConnect = StatusCode.ExceptionOnConnect, + + /// Timeout disconnect by server (which decided an ACK was missing for too long). + DisconnectByServerTimeout = StatusCode.DisconnectByServer, + + /// Server actively disconnected this client. + /// Possible cause: Server's send buffer full (too much data for client). + DisconnectByServerLogic = StatusCode.DisconnectByServerLogic, + + /// Some exception caused the connection to close. + Exception = StatusCode.Exception, + + /// (32767) The Photon Cloud rejected the sent AppId. Check your Dashboard and make sure the AppId you use is complete and correct. + InvalidAuthentication = ErrorCode.InvalidAuthentication, + + /// (32757) Authorization on the Photon Cloud failed because the concurrent users (CCU) limit of the app's subscription is reached. + MaxCcuReached = ErrorCode.MaxCcuReached, + + /// (32756) Authorization on the Photon Cloud failed because the app's subscription does not allow to use a particular region's server. + InvalidRegion = ErrorCode.InvalidRegion, + + /// The security settings for client or server don't allow a connection (see remarks). + /// + /// A common cause for this is that browser clients read a "crossdomain" file from the server. + /// If that file is unavailable or not configured to let the client connect, this exception is thrown. + /// Photon usually provides this crossdomain file for Unity. + /// If it fails, read: + /// https://doc.photonengine.com/en-us/onpremise/current/operations/policy-files + /// + SecurityExceptionOnConnect = StatusCode.SecurityExceptionOnConnect, + + /// Timeout disconnect by client (which decided an ACK was missing for too long). + DisconnectByClientTimeout = StatusCode.TimeoutDisconnect, + + /// Exception in the receive-loop. + /// Possible cause: Socket failure. + InternalReceiveException = StatusCode.ExceptionOnReceive, + + /// (32753) The Authentication ticket expired. Handle this by connecting again (which includes an authenticate to get a fresh ticket). + AuthenticationTicketExpired = 32753, +} + +/// Available server (types) for internally used field: server. +/// Photon uses 3 different roles of servers: Name Server, Master Server and Game Server. +public enum ServerConnection +{ + /// This server is where matchmaking gets done and where clients can get lists of rooms in lobbies. + MasterServer, + /// This server handles a number of rooms to execute and relay the messages between players (in a room). + GameServer, + /// This server is used initially to get the address (IP) of a Master Server for a specific region. Not used for Photon OnPremise (self hosted). + NameServer +} + +#endregion + +/// +/// Implements Photon LoadBalancing used in PUN. +/// This class is used internally by PhotonNetwork and not intended as public API. +/// +internal class NetworkingPeer : LoadBalancingPeer, IPhotonPeerListener +{ + /// Combination of GameVersion+"_"+PunVersion. Separates players per app by version. + protected internal string AppVersion + { + get { return string.Format("{0}_{1}", PhotonNetwork.gameVersion, PhotonNetwork.versionPUN); } + } + + /// Contains the AppId for the Photon Cloud (ignored by Photon Servers). + protected internal string AppId; + + /// + /// A user's authentication values used during connect for Custom Authentication with Photon (and a custom service/community). + /// Set these before calling Connect if you want custom authentication. + /// + public AuthenticationValues AuthValues { get; set; } + + /// Internally used cache for the server's token. Identifies a user/session and can be used to rejoin. + private string tokenCache; + + + /// Enables the new Authentication workflow + public AuthModeOption AuthMode = AuthModeOption.Auth; + + /// Defines how the communication gets encrypted. + public EncryptionMode EncryptionMode = EncryptionMode.PayloadEncryption; + + + ///Simplifies getting the token for connect/init requests, if this feature is enabled. + private string TokenForInit + { + get + { + if (this.AuthMode == AuthModeOption.Auth) + { + return null; + } + return (this.AuthValues != null) ? this.AuthValues.Token : null; + } + } + + /// True if this client uses a NameServer to get the Master Server address. + public bool IsUsingNameServer { get; protected internal set; } + + /// Name Server Host Name for Photon Cloud. Without port and without any prefix. + #if !UNITY_EDITOR && UNITY_SWITCH + public const string NameServerHost = "nameserver-eu.cloudapp.net";//set to "ns.exitgames.com" after Nintendo has fixed the traffic manager bug in their dns-resolver for which this is a workaround + #else + public const string NameServerHost = "ns.exitgames.com"; + #endif + + /// Name Server for HTTP connections to the Photon Cloud. Includes prefix and port. + public const string NameServerHttp = "http://ns.exitgamescloud.com:80/photon/n"; + + /// Name Server port per protocol (the UDP port is different than TCP, etc). + private static readonly Dictionary ProtocolToNameServerPort = new Dictionary() { { ConnectionProtocol.Udp, 5058 }, { ConnectionProtocol.Tcp, 4533 }, { ConnectionProtocol.WebSocket, 9093 }, { ConnectionProtocol.WebSocketSecure, 19093 } }; //, { ConnectionProtocol.RHttp, 6063 } }; + + /// Name Server Address for Photon Cloud (based on current protocol). You can use the default values and usually won't have to set this value. + public string NameServerAddress { get { return this.GetNameServerAddress(); } } + + /// Your Master Server address. In PhotonCloud, call ConnectToRegionMaster() to find your Master Server. + /// + /// In the Photon Cloud, explicit definition of a Master Server Address is not best practice. + /// The Photon Cloud has a "Name Server" which redirects clients to a specific Master Server (per Region and AppId). + /// + public string MasterServerAddress { get; protected internal set; } + + /// The game server's address for a particular room. In use temporarily, as assigned by master. + public string GameServerAddress { get; protected internal set; } + + /// The server this client is currently connected or connecting to. + /// + /// Each server (NameServer, MasterServer, GameServer) allow some operations and reject others. + /// + protected internal ServerConnection Server { get; private set; } + + public ClientState State { get; internal set; } + + public bool IsInitialConnect = false; + + + public bool insideLobby = false; + public TypedLobby lobby { get; set; } + + + private bool requestLobbyStatistics + { + get { return PhotonNetwork.EnableLobbyStatistics && this.Server == ServerConnection.MasterServer; } + } + + protected internal List LobbyStatistics = new List(); + + + public Dictionary mGameList = new Dictionary(); + public RoomInfo[] mGameListCopy = new RoomInfo[0]; + + private string playername = ""; + + public string PlayerName + { + get + { + return this.playername; + } + + set + { + if (string.IsNullOrEmpty(value) || value.Equals(this.playername)) + { + return; + } + + if (this.LocalPlayer != null) + { + this.LocalPlayer.NickName = value; + } + + this.playername = value; + if (this.CurrentRoom != null) + { + // Only when in a room + this.SendPlayerName(); + } + } + } + + // "public" access to the current game - is null unless a room is joined on a gameserver + // isLocalClientInside becomes true when op join result is positive on GameServer + private bool mPlayernameHasToBeUpdated; + + + public Room CurrentRoom + { + get + { + if (this.currentRoom != null && this.currentRoom.IsLocalClientInside) + { + return this.currentRoom; + } + + return null; + } + + private set { this.currentRoom = value; } + } + + private Room currentRoom; + + public PhotonPlayer LocalPlayer { get; internal set; } + + /// Statistic value available on master server: Players on master (looking for games). + public int PlayersOnMasterCount { get; internal set; } + + /// Statistic value available on master server: Players in rooms (playing). + public int PlayersInRoomsCount { get; internal set; } + + /// Statistic value available on master server: Rooms currently created. + public int RoomsCount { get; internal set; } + + /// Internally used to decide if a room must be created or joined on game server. + private JoinType lastJoinType; + + protected internal EnterRoomParams enterRoomParamsCache; + + + /// Internally used to trigger OpAuthenticate when encryption was established after a connect. + private bool didAuthenticate; + + + + /// Contains the list of names of friends to look up their state on the server. + private string[] friendListRequested; + + /// + /// Age of friend list info (in milliseconds). It's 0 until a friend list is fetched. + /// + protected internal int FriendListAge { get { return (this.isFetchingFriendList || this.friendListTimestamp == 0) ? 0 : Environment.TickCount - this.friendListTimestamp; } } + + private int friendListTimestamp; + + /// Internal flag to know if the client currently fetches a friend list. + private bool isFetchingFriendList; + + /// Internally used to check if a "Secret" is available to use. Sent by Photon Cloud servers, it simplifies authentication when switching servers. + public bool IsAuthorizeSecretAvailable + { + get + { + return this.AuthValues != null && !String.IsNullOrEmpty(this.AuthValues.Token); + } + } + + /// A list of region names for the Photon Cloud. Set by the result of OpGetRegions(). + /// Put a "case OperationCode.GetRegions:" into your OnOperationResponse method to notice when the result is available. + public List AvailableRegions { get; protected internal set; } + + /// The cloud region this client connects to. Set by ConnectToRegionMaster(). + public CloudRegionCode CloudRegion { get; protected internal set; } + + + + public Dictionary mActors = new Dictionary(); + + public PhotonPlayer[] mOtherPlayerListCopy = new PhotonPlayer[0]; + public PhotonPlayer[] mPlayerListCopy = new PhotonPlayer[0]; + + + public int mMasterClientId + { + get + { + if (PhotonNetwork.offlineMode) return this.LocalPlayer.ID; + return (this.CurrentRoom == null) ? 0 : this.CurrentRoom.MasterClientId; + } + private set + { + if (this.CurrentRoom != null) + { + this.CurrentRoom.MasterClientId = value; + } + } + } + + public bool hasSwitchedMC = false; + + private HashSet allowedReceivingGroups = new HashSet(); + + private HashSet blockSendingGroups = new HashSet(); + + protected internal Dictionary photonViewList = new Dictionary(); //TODO: make private again + + private readonly PhotonStream readStream = new PhotonStream(false, null); // only used in OnSerializeRead() + private readonly PhotonStream pStream = new PhotonStream(true, null); // only used in OnSerializeWrite() + private readonly Dictionary dataPerGroupReliable = new Dictionary(); // only used in RunViewUpdate() + private readonly Dictionary dataPerGroupUnreliable = new Dictionary(); // only used in RunViewUpdate() + + protected internal short currentLevelPrefix = 0; + + /// Internally used to flag if the message queue was disabled by a "scene sync" situation (to re-enable it). + protected internal bool loadingLevelAndPausedNetwork = false; + + /// For automatic scene syncing, the loaded scene is put into a room property. This is the name of said prop. + protected internal const string CurrentSceneProperty = "curScn"; + protected internal const string CurrentScenePropertyLoadAsync = "curScnLa"; + + public static bool UsePrefabCache = true; + + internal IPunPrefabPool ObjectPool; + + public static Dictionary PrefabCache = new Dictionary(); + + private Dictionary> monoRPCMethodsCache = new Dictionary>(); + + private readonly Dictionary rpcShortcuts; // lookup "table" for the index (shortcut) of an RPC name + + /// Caches PhotonNetworkingMessage.OnPhotonInstantiate.ToString(), because DoInstantiate calls it often (and ToString() on the enum is astonishingly expensive). + private static readonly string OnPhotonInstantiateString = PhotonNetworkingMessage.OnPhotonInstantiate.ToString(); + + + // Connection setup caching for reconnection + private string cachedServerAddress; + private string cachedApplicationName; + private ServerConnection cachedServerType; + + // TODO: CAS must be implemented for OfflineMode + + // for asynchronous loading network synched loading. + private AsyncOperation _AsyncLevelLoadingOperation; + + + public NetworkingPeer(string playername, ConnectionProtocol connectionProtocol) : base(connectionProtocol) + { + this.Listener = this; + this.LimitOfUnreliableCommands = 40; + + this.lobby = TypedLobby.Default; + this.PlayerName = playername; + this.LocalPlayer = new PhotonPlayer(true, -1, this.playername); + this.AddNewPlayer(this.LocalPlayer.ID, this.LocalPlayer); + + // RPC shortcut lookup creation (from list of RPCs, which is updated by Editor scripts) + rpcShortcuts = new Dictionary(PhotonNetwork.PhotonServerSettings.RpcList.Count); + for (int index = 0; index < PhotonNetwork.PhotonServerSettings.RpcList.Count; index++) + { + var name = PhotonNetwork.PhotonServerSettings.RpcList[index]; + rpcShortcuts[name] = index; + } + + this.State = ClientState.PeerCreated; + } + + /// + /// Gets the NameServer Address (with prefix and port), based on the set protocol (this.UsedProtocol). + /// + /// NameServer Address (with prefix and port). + private string GetNameServerAddress() + { + #if RHTTP + if (currentProtocol == ConnectionProtocol.RHttp) + { + return NameServerHttp; + } + #endif + + ConnectionProtocol currentProtocol = this.TransportProtocol; + int protocolPort = 0; + ProtocolToNameServerPort.TryGetValue(currentProtocol, out protocolPort); + + string protocolPrefix = string.Empty; + if (currentProtocol == ConnectionProtocol.WebSocket) + { + protocolPrefix = "ws://"; + } + else if (currentProtocol == ConnectionProtocol.WebSocketSecure) + { + protocolPrefix = "wss://"; + } + + if (PhotonNetwork.UseAlternativeUdpPorts && this.TransportProtocol == ConnectionProtocol.Udp) + { + protocolPort = 27000; + } + string result = string.Format("{0}{1}:{2}", protocolPrefix, NameServerHost, protocolPort); + + //Debug.Log("NameServer: " + result); + return result; + } + +#region Operations and Connection Methods + + + public override bool Connect(string serverAddress, string applicationName) + { + Debug.LogError("Avoid using this directly. Thanks."); + return false; + } + + /// Can be used to reconnect to the master server after a disconnect. + /// Common use case: Press the Lock Button on a iOS device and you get disconnected immediately. + public bool ReconnectToMaster() + { + if (this.AuthValues == null) + { + Debug.LogWarning("ReconnectToMaster() with AuthValues == null is not correct!"); + this.AuthValues = new AuthenticationValues(); + } + this.AuthValues.Token = this.tokenCache; + + return this.Connect(this.MasterServerAddress, ServerConnection.MasterServer); + } + + /// + /// Can be used to return to a room quickly, by directly reconnecting to a game server to rejoin a room. + /// + /// False, if the conditions are not met. Then, this client does not attempt the ReconnectAndRejoin. + public bool ReconnectAndRejoin() + { + if (this.AuthValues == null) + { + Debug.LogWarning("ReconnectAndRejoin() with AuthValues == null is not correct!"); + this.AuthValues = new AuthenticationValues(); + } + this.AuthValues.Token = this.tokenCache; + + if (!string.IsNullOrEmpty(this.GameServerAddress) && this.enterRoomParamsCache != null) + { + this.lastJoinType = JoinType.JoinRoom; + this.enterRoomParamsCache.RejoinOnly = true; + return this.Connect(this.GameServerAddress, ServerConnection.GameServer); + } + + return false; + } + + + public bool Connect(string serverAddress, ServerConnection type) + { + if (PhotonHandler.AppQuits) + { + Debug.LogWarning("Ignoring Connect() because app gets closed. If this is an error, check PhotonHandler.AppQuits."); + return false; + } + + if (this.State == ClientState.Disconnecting) + { + Debug.LogError("Connect() failed. Can't connect while disconnecting (still). Current state: " + PhotonNetwork.connectionStateDetailed); + return false; + } + + this.cachedServerType = type; + this.cachedServerAddress = serverAddress; + this.cachedApplicationName = string.Empty; + + this.SetupProtocol(type); + + // connect might fail, if the DNS name can't be resolved or if no network connection is available + bool connecting = base.Connect(serverAddress, "", this.TokenForInit); + + if (connecting) + { + switch (type) + { + case ServerConnection.NameServer: + State = ClientState.ConnectingToNameServer; + break; + case ServerConnection.MasterServer: + State = ClientState.ConnectingToMasterserver; + break; + case ServerConnection.GameServer: + State = ClientState.ConnectingToGameserver; + break; + } + } + + return connecting; + } + + bool _isReconnecting; + + /// + /// Reconnect this instance. Uses the exact same settings as the developer used to connect using cached properties ( serverAddress, ApplicationName and Protocol Type) + /// This is used for switching from UDP to TCP on udp connection timeout. + /// + bool Reconnect() + { + _isReconnecting = true; + + PhotonNetwork.SwitchToProtocol(PhotonNetwork.PhotonServerSettings.Protocol); + this.SetupProtocol(this.cachedServerType); + + bool connecting = base.Connect(cachedServerAddress, cachedApplicationName, this.TokenForInit); + + if (connecting) + { + switch (this.cachedServerType) + { + case ServerConnection.NameServer: + State = ClientState.ConnectingToNameServer; + break; + case ServerConnection.MasterServer: + State = ClientState.ConnectingToMasterserver; + break; + case ServerConnection.GameServer: + State = ClientState.ConnectingToGameserver; + break; + } + } + + return connecting; + } + + + + /// + /// Connects to the NameServer for Photon Cloud, where a region-list can be fetched. + /// + /// + /// If the workflow was started or failed right away. + public bool ConnectToNameServer() + { + if (PhotonHandler.AppQuits) + { + Debug.LogWarning("Ignoring Connect() because app gets closed. If this is an error, check PhotonHandler.AppQuits."); + return false; + } + + this.IsUsingNameServer = true; + this.CloudRegion = CloudRegionCode.none; + + if (this.State == ClientState.ConnectedToNameServer) + { + return true; + } + + this.SetupProtocol(ServerConnection.NameServer); + + this.cachedServerType = ServerConnection.NameServer; + cachedServerAddress = this.NameServerAddress; + cachedApplicationName = "ns"; + + if (!base.Connect(this.NameServerAddress, "ns", this.TokenForInit)) + { + return false; + } + + this.State = ClientState.ConnectingToNameServer; + return true; + } + + /// + /// Connects you to a specific region's Master Server, using the Name Server to find the IP. + /// + /// If the operation could be sent. If false, no operation was sent. + public bool ConnectToRegionMaster(CloudRegionCode region) + { + if (PhotonHandler.AppQuits) + { + Debug.LogWarning("Ignoring Connect() because app gets closed. If this is an error, check PhotonHandler.AppQuits."); + return false; + } + + this.IsUsingNameServer = true; + this.CloudRegion = region; + + if (this.State == ClientState.ConnectedToNameServer) + { + return this.CallAuthenticate(); + } + + this.cachedServerType = ServerConnection.NameServer; + cachedServerAddress = this.NameServerAddress; + cachedApplicationName = "ns"; + + this.SetupProtocol(ServerConnection.NameServer); + if (!base.Connect(this.NameServerAddress, "ns", this.TokenForInit)) + { + return false; + } + + this.State = ClientState.ConnectingToNameServer; + return true; + } + + // this sets up the protocol to us, depending on auth-mode and or export. + protected internal void SetupProtocol(ServerConnection serverType) + { + ConnectionProtocol protocolOverride = this.TransportProtocol; + + #if !UNITY_EDITOR && UNITY_XBOXONE + this.AuthMode = AuthModeOption.Auth; + if (this.AuthValues == null) + { + UnityEngine.Debug.LogError("UNITY_XBOXONE builds must set AuthValues. Set this before calling any Connect method. Refer to the online docs for guidance."); + throw new Exception("UNITY_XBOXONE builds must set AuthValues."); + } + if (this.AuthValues.AuthPostData == null) + { + UnityEngine.Debug.LogError("UNITY_XBOXONE builds must use Photon's XBox Authentication and set the XSTS token by calling: PhotonNetwork.AuthValues.SetAuthPostData(xstsToken). Refer to the online docs for guidance."); + throw new Exception("UNITY_XBOXONE builds must use Photon's XBox Authentication."); + } + if (this.AuthValues.AuthType != CustomAuthenticationType.Xbox) + { + UnityEngine.Debug.LogWarning("UNITY_XBOXONE builds must use AuthValues.AuthType \"CustomAuthenticationType.Xbox\". PUN sets this value now. Refer to the online docs to avoid this warning."); + this.AuthValues.AuthType = CustomAuthenticationType.Xbox; + } + if (this.TransportProtocol != ConnectionProtocol.WebSocketSecure) + { + UnityEngine.Debug.LogWarning("UNITY_XBOXONE builds must use WSS (Secure WebSockets) as Transport Protocol. Overriding PhotonServerSettings."); + protocolOverride = ConnectionProtocol.WebSocketSecure; + } + #endif + + if (this.AuthMode == AuthModeOption.AuthOnceWss) + { + if (serverType != ServerConnection.NameServer) + { + if (PhotonNetwork.logLevel >= PhotonLogLevel.ErrorsOnly) + { + Debug.LogWarning("Using PhotonServerSettings.Protocol when leaving the NameServer (AuthMode is AuthOnceWss): " + PhotonNetwork.PhotonServerSettings.Protocol); + } + protocolOverride = PhotonNetwork.PhotonServerSettings.Protocol; + } + else + { + if (PhotonNetwork.logLevel >= PhotonLogLevel.ErrorsOnly) + { + Debug.LogWarning("Using WebSocket to connect NameServer (AuthMode is AuthOnceWss)."); + } + protocolOverride = ConnectionProtocol.WebSocketSecure; + } + } + + Type socketTcp = null; + #if !UNITY_EDITOR && UNITY_XBOXONE + socketTcp = Type.GetType("ExitGames.Client.Photon.SocketWebTcpNativeDynamic, Assembly-CSharp", false); + if (socketTcp == null) + { + socketTcp = Type.GetType("ExitGames.Client.Photon.SocketWebTcpNativeDynamic, Assembly-CSharp-firstpass", false); + } + #else + // to support WebGL export in Unity, we find and assign the SocketWebTcp class (if it's in the project). + // alternatively class SocketWebTcp might be in the Photon3Unity3D.dll + socketTcp = Type.GetType("ExitGames.Client.Photon.SocketWebTcp, Assembly-CSharp", false); + if (socketTcp == null) + { + socketTcp = Type.GetType("ExitGames.Client.Photon.SocketWebTcp, Assembly-CSharp-firstpass", false); + } + #endif + if (socketTcp != null) + { + this.SocketImplementationConfig[ConnectionProtocol.WebSocket] = socketTcp; + this.SocketImplementationConfig[ConnectionProtocol.WebSocketSecure] = socketTcp; + } + + + #if UNITY_WEBGL + if (this.TransportProtocol != ConnectionProtocol.WebSocket && this.TransportProtocol != ConnectionProtocol.WebSocketSecure) + { + Debug.Log("WebGL only supports WebSocket protocol. Overriding PhotonServerSettings."); + protocolOverride = ConnectionProtocol.WebSocketSecure; + } + PhotonHandler.PingImplementation = typeof(PingHttp); + #endif + + + #if !UNITY_EDITOR && (UNITY_WINRT) + // this automatically uses a separate assembly-file with Win8-style Socket usage (not possible in Editor) + Debug.LogWarning("Using PingWindowsStore"); + PhotonHandler.PingImplementation = typeof(PingWindowsStore); // but for ping, we have to set the implementation explicitly to Win 8 Store/Phone + #endif + + + #pragma warning disable 0162 // the library variant defines if we should use PUN's SocketUdp variant (at all) + if (PhotonPeer.NoSocket) + { + #if !UNITY_EDITOR && (UNITY_PS3 || UNITY_ANDROID) + this.SocketImplementationConfig[ConnectionProtocol.Udp] = typeof(SocketUdpNativeDynamic); + PhotonHandler.PingImplementation = typeof(PingNativeDynamic); + #elif !UNITY_EDITOR && (UNITY_IPHONE || UNITY_SWITCH) + this.SocketImplementationConfig[ConnectionProtocol.Udp] = typeof(SocketUdpNativeStatic); + PhotonHandler.PingImplementation = typeof(PingNativeStatic); + #elif !UNITY_EDITOR && UNITY_WINRT + // this automatically uses a separate assembly-file with Win8-style Socket usage (not possible in Editor) + #else + this.SocketImplementationConfig[ConnectionProtocol.Udp] = typeof(SocketUdp); + PhotonHandler.PingImplementation = typeof(PingMonoEditor); + #endif + + if (this.SocketImplementationConfig[ConnectionProtocol.Udp] == null) + { + Debug.Log("No socket implementation set for 'NoSocket' assembly. Please check your settings."); + } + } + #pragma warning restore 0162 + + if (PhotonHandler.PingImplementation == null) + { + PhotonHandler.PingImplementation = typeof(PingMono); + } + + + if (this.TransportProtocol == protocolOverride) + { + return; + } + + + if (PhotonNetwork.logLevel >= PhotonLogLevel.ErrorsOnly) + { + Debug.LogWarning("Protocol switch from: " + this.TransportProtocol + " to: " + protocolOverride + "."); + } + + this.TransportProtocol = protocolOverride; + } + + /// + /// Complete disconnect from photon (and the open master OR game server) + /// + public override void Disconnect() + { + if (this.PeerState == PeerStateValue.Disconnected) + { + if (!PhotonHandler.AppQuits) + { + Debug.LogWarning(string.Format("Can't execute Disconnect() while not connected. Nothing changed. State: {0}", this.State)); + } + return; + } + + this.State = ClientState.Disconnecting; + base.Disconnect(); + + //this.LeftRoomCleanup(); + //this.LeftLobbyCleanup(); + } + + private bool CallAuthenticate() + { + // once encryption is availble, the client should send one (secure) authenticate. it includes the AppId (which identifies your app on the Photon Cloud) + AuthenticationValues auth = this.AuthValues ?? new AuthenticationValues() { UserId = this.PlayerName }; + if (this.AuthMode == AuthModeOption.Auth) + { + return this.OpAuthenticate(this.AppId, this.AppVersion, auth, this.CloudRegion.ToString(), this.requestLobbyStatistics); + } + else + { + return this.OpAuthenticateOnce(this.AppId, this.AppVersion, auth, this.CloudRegion.ToString(), this.EncryptionMode, PhotonNetwork.PhotonServerSettings.Protocol); + } + } + + + + /// + /// Internally used only. Triggers OnStateChange with "Disconnect" in next dispatch which is the signal to re-connect (if at all). + /// + private void DisconnectToReconnect() + { + switch (this.Server) + { + case ServerConnection.NameServer: + this.State = ClientState.DisconnectingFromNameServer; + base.Disconnect(); + break; + case ServerConnection.MasterServer: + this.State = ClientState.DisconnectingFromMasterserver; + base.Disconnect(); + //LeftLobbyCleanup(); + break; + case ServerConnection.GameServer: + this.State = ClientState.DisconnectingFromGameserver; + base.Disconnect(); + //this.LeftRoomCleanup(); + break; + } + } + + /// + /// While on the NameServer, this gets you the list of regional servers (short names and their IPs to ping them). + /// + /// If the operation could be sent. If false, no operation was sent (e.g. while not connected to the NameServer). + public bool GetRegions() + { + if (this.Server != ServerConnection.NameServer) + { + return false; + } + + bool sent = this.OpGetRegions(this.AppId); + if (sent) + { + this.AvailableRegions = null; + } + + return sent; + } + + /// + /// Request the rooms and online status for a list of friends. All client must set a unique username via PlayerName property. The result is available in this.Friends. + /// + /// + /// Used on Master Server to find the rooms played by a selected list of users. + /// The result will be mapped to LoadBalancingClient.Friends when available. + /// The list is initialized by OpFindFriends on first use (before that, it is null). + /// + /// Users identify themselves by setting a PlayerName in the LoadBalancingClient instance. + /// This in turn will send the name in OpAuthenticate after each connect (to master and game servers). + /// Note: Changing a player's name doesn't make sense when using a friend list. + /// + /// The list of usernames must be fetched from some other source (not provided by Photon). + /// + /// + /// Internal: + /// The server response includes 2 arrays of info (each index matching a friend from the request): + /// ParameterCode.FindFriendsResponseOnlineList = bool[] of online states + /// ParameterCode.FindFriendsResponseRoomIdList = string[] of room names (empty string if not in a room) + /// + /// Array of friend's names (make sure they are unique). + /// If the operation could be sent (requires connection, only one request is allowed at any time). Always false in offline mode. + public override bool OpFindFriends(string[] friendsToFind) + { + if (this.isFetchingFriendList) + { + return false; // fetching friends currently, so don't do it again (avoid changing the list while fetching friends) + } + + this.friendListRequested = friendsToFind; + this.isFetchingFriendList = true; + + return base.OpFindFriends(friendsToFind); + } + + /// NetworkingPeer.OpCreateGame + public bool OpCreateGame(EnterRoomParams enterRoomParams) + { + bool onGameServer = this.Server == ServerConnection.GameServer; + enterRoomParams.OnGameServer = onGameServer; + enterRoomParams.PlayerProperties = GetLocalActorProperties(); + if (!onGameServer) + { + enterRoomParamsCache = enterRoomParams; + } + + this.lastJoinType = JoinType.CreateRoom; + return base.OpCreateRoom(enterRoomParams); + } + + /// NetworkingPeer.OpJoinRoom + public override bool OpJoinRoom(EnterRoomParams opParams) + { + bool onGameServer = this.Server == ServerConnection.GameServer; + opParams.OnGameServer = onGameServer; + if (!onGameServer) + { + this.enterRoomParamsCache = opParams; + } + + this.lastJoinType = (opParams.CreateIfNotExists) ? JoinType.JoinOrCreateRoom : JoinType.JoinRoom; + return base.OpJoinRoom(opParams); + } + + /// NetworkingPeer.OpJoinRandomRoom + /// this override just makes sure we have a mRoomToGetInto, even if it's blank (the properties provided in this method are filters. they are not set when we join the game) + public override bool OpJoinRandomRoom(OpJoinRandomRoomParams opJoinRandomRoomParams) + { + enterRoomParamsCache = new EnterRoomParams(); // this is used when the client arrives on the GS and joins the room + enterRoomParamsCache.Lobby = opJoinRandomRoomParams.TypedLobby; + this.enterRoomParamsCache.ExpectedUsers = opJoinRandomRoomParams.ExpectedUsers; + + this.lastJoinType = JoinType.JoinRandomRoom; + return base.OpJoinRandomRoom(opJoinRandomRoomParams); + } + + + public override bool OpRaiseEvent(byte eventCode, object customEventContent, bool sendReliable, RaiseEventOptions raiseEventOptions) + { + if (PhotonNetwork.offlineMode) + { + return false; + } + + return base.OpRaiseEvent(eventCode, customEventContent, sendReliable, raiseEventOptions); + } + + + #if PHOTON_LIB_MIN_4_1_2 + public override bool OpRaiseEvent(byte eventCode, object customEventContent, RaiseEventOptions raiseEventOptions, SendOptions sendOptions) + { + if (PhotonNetwork.offlineMode) + { + return false; + } + + return base.OpRaiseEvent(eventCode, customEventContent, raiseEventOptions, sendOptions); + } + #endif + + #endregion + + #region Helpers + + private void ReadoutProperties(Hashtable gameProperties, Hashtable pActorProperties, int targetActorNr) + { + // Debug.LogWarning("ReadoutProperties gameProperties: " + gameProperties.ToStringFull() + " pActorProperties: " + pActorProperties.ToStringFull() + " targetActorNr: " + targetActorNr); + + // read per-player properties (or those of one target player) and cache those locally + if (pActorProperties != null && pActorProperties.Count > 0) + { + if (targetActorNr > 0) + { + // we have a single entry in the pActorProperties with one + // user's name + // targets MUST exist before you set properties + PhotonPlayer target = this.GetPlayerWithId(targetActorNr); + if (target != null) + { + Hashtable props = this.ReadoutPropertiesForActorNr(pActorProperties, targetActorNr); + target.InternalCacheProperties(props); + SendMonoMessage(PhotonNetworkingMessage.OnPhotonPlayerPropertiesChanged, target, props); + } + } + else + { + // in this case, we've got a key-value pair per actor (each + // value is a hashtable with the actor's properties then) + int actorNr; + Hashtable props; + string newName; + PhotonPlayer target; + + foreach (object key in pActorProperties.Keys) + { + actorNr = (int)key; + props = (Hashtable)pActorProperties[key]; + newName = (string)props[ActorProperties.PlayerName]; + + target = this.GetPlayerWithId(actorNr); + if (target == null) + { + target = new PhotonPlayer(false, actorNr, newName); + this.AddNewPlayer(actorNr, target); + } + + target.InternalCacheProperties(props); + SendMonoMessage(PhotonNetworkingMessage.OnPhotonPlayerPropertiesChanged, target, props); + } + } + } + + // read game properties and cache them locally + if (this.CurrentRoom != null && gameProperties != null) + { + this.CurrentRoom.InternalCacheProperties(gameProperties); + SendMonoMessage(PhotonNetworkingMessage.OnPhotonCustomRoomPropertiesChanged, gameProperties); + if (PhotonNetwork.automaticallySyncScene) + { + this.LoadLevelIfSynced(); // will load new scene if sceneName was changed + } + } + } + + private Hashtable ReadoutPropertiesForActorNr(Hashtable actorProperties, int actorNr) + { + if (actorProperties.ContainsKey(actorNr)) + { + return (Hashtable)actorProperties[actorNr]; + } + + return actorProperties; + } + + public void ChangeLocalID(int newID) + { + if (this.LocalPlayer == null) + { + Debug.LogWarning(string.Format("LocalPlayer is null or not in mActors! LocalPlayer: {0} mActors==null: {1} newID: {2}",this.LocalPlayer,this.mActors == null,newID)); + } + + if (this.mActors.ContainsKey(this.LocalPlayer.ID)) + { + this.mActors.Remove(this.LocalPlayer.ID); + } + + this.LocalPlayer.InternalChangeLocalID(newID); + this.mActors[this.LocalPlayer.ID] = this.LocalPlayer; + this.RebuildPlayerListCopies(); + } + + /// + /// Called at disconnect/leavelobby etc. This CAN also be called when we are not in a lobby (e.g. disconnect from room) + /// + /// Calls callback method OnLeftLobby if this client was in a lobby initially. Clears the lobby's game lists. + private void LeftLobbyCleanup() + { + this.mGameList = new Dictionary(); + this.mGameListCopy = new RoomInfo[0]; + + if (this.insideLobby) + { + this.insideLobby = false; + SendMonoMessage(PhotonNetworkingMessage.OnLeftLobby); + } + } + + /// + /// Called when "this client" left a room to clean up. + /// + private void LeftRoomCleanup() + { + bool wasInRoom = this.CurrentRoom != null; + // when leaving a room, we clean up depending on that room's settings. + bool autoCleanupSettingOfRoom = (this.CurrentRoom != null) ? this.CurrentRoom.AutoCleanUp : PhotonNetwork.autoCleanUpPlayerObjects; + + this.hasSwitchedMC = false; + this.CurrentRoom = null; + this.mActors = new Dictionary(); + this.mPlayerListCopy = new PhotonPlayer[0]; + this.mOtherPlayerListCopy = new PhotonPlayer[0]; + this.allowedReceivingGroups = new HashSet(); + this.blockSendingGroups = new HashSet(); + this.mGameList = new Dictionary(); + this.mGameListCopy = new RoomInfo[0]; + this.isFetchingFriendList = false; + + this.ChangeLocalID(-1); + + // Cleanup all network objects (all spawned PhotonViews, local and remote) + if (autoCleanupSettingOfRoom) + { + this.LocalCleanupAnythingInstantiated(true); + PhotonNetwork.manuallyAllocatedViewIds = new List(); // filled and easier to replace completely + } + + if (wasInRoom) + { + SendMonoMessage(PhotonNetworkingMessage.OnLeftRoom); + } + } + + /// + /// Cleans up anything that was instantiated in-game (not loaded with the scene). + /// + protected internal void LocalCleanupAnythingInstantiated(bool destroyInstantiatedGameObjects) + { + if (this.tempInstantiationData.Count > 0) + { + Debug.LogWarning("It seems some instantiation is not completed, as instantiation data is used. You should make sure instantiations are paused when calling this method. Cleaning now, despite this."); + } + + // Destroy GO's (if we should) + if (destroyInstantiatedGameObjects) + { + // Fill list with Instantiated objects + HashSet instantiatedGos = new HashSet(); + foreach (PhotonView view in this.photonViewList.Values) + { + if (view.isRuntimeInstantiated) + { + instantiatedGos.Add(view.gameObject); // HashSet keeps each object only once + } + } + + foreach (GameObject go in instantiatedGos) + { + this.RemoveInstantiatedGO(go, true); + } + } + + // photonViewList is cleared of anything instantiated (so scene items are left inside) + // any other lists can be + this.tempInstantiationData.Clear(); // should be empty but to be safe we clear (no new list needed) + PhotonNetwork.lastUsedViewSubId = 0; + PhotonNetwork.lastUsedViewSubIdStatic = 0; + } + + + private void GameEnteredOnGameServer(OperationResponse operationResponse) + { + if (operationResponse.ReturnCode != 0) + { + switch (operationResponse.OperationCode) + { + case OperationCode.CreateGame: + if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + { + Debug.Log("Create failed on GameServer. Changing back to MasterServer. Msg: " + operationResponse.DebugMessage); + } + SendMonoMessage(PhotonNetworkingMessage.OnPhotonCreateRoomFailed, operationResponse.ReturnCode, operationResponse.DebugMessage); + break; + case OperationCode.JoinGame: + if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + { + Debug.Log("Join failed on GameServer. Changing back to MasterServer. Msg: " + operationResponse.DebugMessage); + if (operationResponse.ReturnCode == ErrorCode.GameDoesNotExist) + { + Debug.Log("Most likely the game became empty during the switch to GameServer."); + } + } + SendMonoMessage(PhotonNetworkingMessage.OnPhotonJoinRoomFailed, operationResponse.ReturnCode, operationResponse.DebugMessage); + break; + case OperationCode.JoinRandomGame: + if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + { + Debug.Log("Join failed on GameServer. Changing back to MasterServer. Msg: " + operationResponse.DebugMessage); + if (operationResponse.ReturnCode == ErrorCode.GameDoesNotExist) + { + Debug.Log("Most likely the game became empty during the switch to GameServer."); + } + } + SendMonoMessage(PhotonNetworkingMessage.OnPhotonRandomJoinFailed, operationResponse.ReturnCode, operationResponse.DebugMessage); + break; + } + + this.DisconnectToReconnect(); + return; + } + + Room current = new Room(this.enterRoomParamsCache.RoomName, null); + current.IsLocalClientInside = true; + this.CurrentRoom = current; + + this.State = ClientState.Joined; + + if (operationResponse.Parameters.ContainsKey(ParameterCode.ActorList)) + { + int[] actorsInRoom = (int[])operationResponse.Parameters[ParameterCode.ActorList]; + this.UpdatedActorList(actorsInRoom); + } + + // the local player's actor-properties are not returned in join-result. add this player to the list + int localActorNr = (int)operationResponse[ParameterCode.ActorNr]; + this.ChangeLocalID(localActorNr); + + + Hashtable actorProperties = (Hashtable)operationResponse[ParameterCode.PlayerProperties]; + Hashtable gameProperties = (Hashtable)operationResponse[ParameterCode.GameProperties]; + this.ReadoutProperties(gameProperties, actorProperties, 0); + + if (!this.CurrentRoom.serverSideMasterClient) this.CheckMasterClient(-1); + + if (this.mPlayernameHasToBeUpdated) + { + this.SendPlayerName(); + } + + switch (operationResponse.OperationCode) + { + case OperationCode.CreateGame: + SendMonoMessage(PhotonNetworkingMessage.OnCreatedRoom); + break; + case OperationCode.JoinGame: + case OperationCode.JoinRandomGame: + // the mono message for this is sent at another place + break; + } + } + + private void AddNewPlayer(int ID, PhotonPlayer player) + { + if (!this.mActors.ContainsKey(ID)) + { + this.mActors[ID] = player; + RebuildPlayerListCopies(); + } + else + { + Debug.LogError("Adding player twice: " + ID); + } + } + + void RemovePlayer(int ID, PhotonPlayer player) + { + this.mActors.Remove(ID); + if (!player.IsLocal) + { + RebuildPlayerListCopies(); + } + } + + void RebuildPlayerListCopies() + { + this.mPlayerListCopy = new PhotonPlayer[this.mActors.Count]; + this.mActors.Values.CopyTo(this.mPlayerListCopy, 0); + + List otherP = new List(); + for (int i = 0; i < this.mPlayerListCopy.Length; i++) + { + PhotonPlayer player = this.mPlayerListCopy[i]; + if (!player.IsLocal) + { + otherP.Add(player); + } + } + + this.mOtherPlayerListCopy = otherP.ToArray(); + } + + /// + /// Resets the PhotonView "lastOnSerializeDataSent" so that "OnReliable" synched PhotonViews send a complete state to new clients (if the state doesnt change, no messages would be send otherwise!). + /// Note that due to this reset, ALL other players will receive the full OnSerialize. + /// + private void ResetPhotonViewsOnSerialize() + { + foreach (PhotonView photonView in this.photonViewList.Values) + { + photonView.lastOnSerializeDataSent = null; + } + } + + /// + /// Called when the event Leave (of some other player) arrived. + /// Cleans game objects, views locally. The master will also clean the + /// + /// ID of player who left. + private void HandleEventLeave(int actorID, EventData evLeave) + { + if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + Debug.Log("HandleEventLeave for player ID: " + actorID + " evLeave: " + evLeave.ToStringFull()); + + + // actorNr is fetched out of event + PhotonPlayer player = this.GetPlayerWithId(actorID); + if (player == null) + { + Debug.LogError(String.Format("Received event Leave for unknown player ID: {0}", actorID)); + return; + } + + bool _isAlreadyInactive = player.IsInactive; + + if (evLeave.Parameters.ContainsKey(ParameterCode.IsInactive)) + { + // player becomes inactive (but might return / is not gone for good) + player.IsInactive = (bool)evLeave.Parameters[ParameterCode.IsInactive]; + + + if (player.IsInactive != _isAlreadyInactive) + { + SendMonoMessage(PhotonNetworkingMessage.OnPhotonPlayerActivityChanged, player); + } + + if (player.IsInactive && _isAlreadyInactive) + { + Debug.LogWarning("HandleEventLeave for player ID: " + actorID + " isInactive: " + player.IsInactive + ". Stopping handling if inactive."); + return; + } + } + + // having a new master before calling destroy for the leaving player is important! + // so we elect a new masterclient and ignore the leaving player (who is still in playerlists). + // note: there is/was a server-side-error which sent 0 as new master instead of skipping the key/value. below is a check for 0 due to that + if (evLeave.Parameters.ContainsKey(ParameterCode.MasterClientId)) + { + int newMaster = (int) evLeave[ParameterCode.MasterClientId]; + if (newMaster != 0) + { + this.mMasterClientId = (int)evLeave[ParameterCode.MasterClientId]; + this.UpdateMasterClient(); + } + } + else if (!this.CurrentRoom.serverSideMasterClient) + { + this.CheckMasterClient(actorID); + } + + + // we let the player up if inactive but if we were already inactive, then we have to actually remove the player properly. + if (player.IsInactive && !_isAlreadyInactive) + { + return; + } + + // destroy objects & buffered messages + if (this.CurrentRoom != null && this.CurrentRoom.AutoCleanUp) + { + this.DestroyPlayerObjects(actorID, true); + } + + RemovePlayer(actorID, player); + + // finally, send notification (the playerList and masterclient are now updated) + SendMonoMessage(PhotonNetworkingMessage.OnPhotonPlayerDisconnected, player); + } + + /// Picks the new master client from player list, if the current Master is leaving (leavingPlayerId) or if no master was assigned so far. + /// + /// The ignored player is the one who's leaving and should not become master (again). Pass -1 to select any player from the list. + /// + private void CheckMasterClient(int leavingPlayerId) + { + bool currentMasterIsLeaving = this.mMasterClientId == leavingPlayerId; + bool someoneIsLeaving = leavingPlayerId > 0; + + // return early if SOME player (leavingId > 0) is leaving AND it's NOT the current master + if (someoneIsLeaving && !currentMasterIsLeaving) + { + return; + } + + // picking the player with lowest ID (longest in game). + int lowestActorNumber; + if (this.mActors.Count <= 1) + { + lowestActorNumber = this.LocalPlayer.ID; + } + else + { + // keys in mActors are their actorNumbers + lowestActorNumber = Int32.MaxValue; + foreach (int key in this.mActors.Keys) + { + if (key < lowestActorNumber && key != leavingPlayerId) + { + lowestActorNumber = key; + } + } + } + this.mMasterClientId = lowestActorNumber; + + // callback ONLY when the current master left + if (someoneIsLeaving) + { + SendMonoMessage(PhotonNetworkingMessage.OnMasterClientSwitched, this.GetPlayerWithId(lowestActorNumber)); + } + } + + /// Call when the server provides a MasterClientId (due to joining or the current MC leaving, etc). + internal protected void UpdateMasterClient() + { + SendMonoMessage(PhotonNetworkingMessage.OnMasterClientSwitched, PhotonNetwork.masterClient); + } + + private static int ReturnLowestPlayerId(PhotonPlayer[] players, int playerIdToIgnore) + { + if (players == null || players.Length == 0) + { + return -1; + } + + int lowestActorNumber = Int32.MaxValue; + for (int i = 0; i < players.Length; i++) + { + PhotonPlayer photonPlayer = players[i]; + if (photonPlayer.ID == playerIdToIgnore) + { + continue; + } + + if (photonPlayer.ID < lowestActorNumber) + { + lowestActorNumber = photonPlayer.ID; + } + } + + return lowestActorNumber; + } + + /// Fake-sets a new Master Client for this room via RaiseEvent. + /// Does not affect RaiseEvent with target MasterClient but RPC(). + internal protected bool SetMasterClient(int playerId, bool sync) + { + bool masterReplaced = this.mMasterClientId != playerId; + if (!masterReplaced || !this.mActors.ContainsKey(playerId)) + { + return false; + } + + if (sync) + { + bool sent = this.OpRaiseEvent(PunEvent.AssignMaster, new Hashtable() { { (byte)1, playerId } }, true, null); + if (!sent) + { + return false; + } + } + + this.hasSwitchedMC = true; + this.CurrentRoom.MasterClientId = playerId; + SendMonoMessage(PhotonNetworkingMessage.OnMasterClientSwitched, this.GetPlayerWithId(playerId)); // we only callback when an actual change is done + return true; + } + + /// Uses a well-known property to set someone new as Master Client in room (requires "Server Side Master Client" feature). + public bool SetMasterClient(int nextMasterId) + { + Hashtable newProps = new Hashtable() { { GamePropertyKey.MasterClientId, nextMasterId } }; + Hashtable prevProps = new Hashtable() { { GamePropertyKey.MasterClientId, this.mMasterClientId } }; + return this.OpSetPropertiesOfRoom(newProps, expectedProperties: prevProps, webForward: false); + } + + protected internal PhotonPlayer GetPlayerWithId(int number) + { + if (this.mActors == null) return null; + + PhotonPlayer player = null; + this.mActors.TryGetValue(number, out player); + return player; + } + + private void SendPlayerName() + { + if (this.State == ClientState.Joining) + { + // this means, the join on the gameServer is sent (with an outdated name). send the new when in game + this.mPlayernameHasToBeUpdated = true; + return; + } + + if (this.LocalPlayer != null) + { + this.LocalPlayer.NickName = this.PlayerName; + Hashtable properties = new Hashtable(); + properties[ActorProperties.PlayerName] = this.PlayerName; + if (this.LocalPlayer.ID > 0) + { + this.OpSetPropertiesOfActor(this.LocalPlayer.ID, properties, null); + this.mPlayernameHasToBeUpdated = false; + } + } + } + + private Hashtable GetLocalActorProperties() + { + if (PhotonNetwork.player != null) + { + return PhotonNetwork.player.AllProperties; + } + + Hashtable actorProperties = new Hashtable(); + actorProperties[ActorProperties.PlayerName] = this.PlayerName; + return actorProperties; + } + + #endregion + + #region Implementation of IPhotonPeerListener + + public void DebugReturn(DebugLevel level, string message) + { + if (level == DebugLevel.ERROR) + { + Debug.LogError(message); + } + else if (level == DebugLevel.WARNING) + { + Debug.LogWarning(message); + } + else if (level == DebugLevel.INFO && PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + { + Debug.Log(message); + } + else if (level == DebugLevel.ALL && PhotonNetwork.logLevel == PhotonLogLevel.Full) + { + Debug.Log(message); + } + } + + public void OnOperationResponse(OperationResponse operationResponse) + { + if (PhotonNetwork.networkingPeer.State == ClientState.Disconnecting) + { + if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + { + Debug.Log("OperationResponse ignored while disconnecting. Code: " + operationResponse.OperationCode); + } + return; + } + + // extra logging for error debugging (helping developers with a bit of automated analysis) + if (operationResponse.ReturnCode == 0) + { + if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + Debug.Log(operationResponse.ToString()); + } + else + { + if (operationResponse.ReturnCode == ErrorCode.OperationNotAllowedInCurrentState) + { + Debug.LogError("Operation " + operationResponse.OperationCode + " could not be executed (yet). Wait for state JoinedLobby or ConnectedToMaster and their callbacks before calling operations. WebRPCs need a server-side configuration. Enum OperationCode helps identify the operation."); + } + else if (operationResponse.ReturnCode == ErrorCode.PluginReportedError) + { + Debug.LogError("Operation " + operationResponse.OperationCode + " failed in a server-side plugin. Check the configuration in the Dashboard. Message from server-plugin: " + operationResponse.DebugMessage); + } + else if (operationResponse.ReturnCode == ErrorCode.NoRandomMatchFound) + { + Debug.LogWarning("Operation failed: " + operationResponse.ToStringFull()); + } + else + { + Debug.LogError("Operation failed: " + operationResponse.ToStringFull() + " Server: " + this.Server); + } + } + + // use the "secret" or "token" whenever we get it. doesn't really matter if it's in AuthResponse. + if (operationResponse.Parameters.ContainsKey(ParameterCode.Secret)) + { + if (this.AuthValues == null) + { + this.AuthValues = new AuthenticationValues(); + // this.DebugReturn(DebugLevel.ERROR, "Server returned secret. Created AuthValues."); + } + + this.AuthValues.Token = operationResponse[ParameterCode.Secret] as string; + this.tokenCache = this.AuthValues.Token; + } + + switch (operationResponse.OperationCode) + { + case OperationCode.Authenticate: + case OperationCode.AuthenticateOnce: + { + // ClientState oldState = this.State; + + if (operationResponse.ReturnCode != 0) + { + if (operationResponse.ReturnCode == ErrorCode.InvalidOperation) + { + Debug.LogError(string.Format("If you host Photon yourself, make sure to start the 'Instance LoadBalancing' "+ this.ServerAddress)); + } + else if (operationResponse.ReturnCode == ErrorCode.InvalidAuthentication) + { + Debug.LogError(string.Format("The appId this client sent is unknown on the server (Cloud). Check settings. If using the Cloud, check account.")); + SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, DisconnectCause.InvalidAuthentication); + } + else if (operationResponse.ReturnCode == ErrorCode.CustomAuthenticationFailed) + { + Debug.LogError(string.Format("Custom Authentication failed (either due to user-input or configuration or AuthParameter string format). Calling: OnCustomAuthenticationFailed()")); + SendMonoMessage(PhotonNetworkingMessage.OnCustomAuthenticationFailed, operationResponse.DebugMessage); + } + else + { + Debug.LogError(string.Format("Authentication failed: '{0}' Code: {1}", operationResponse.DebugMessage, operationResponse.ReturnCode)); + } + + this.State = ClientState.Disconnecting; + this.Disconnect(); + + if (operationResponse.ReturnCode == ErrorCode.MaxCcuReached) + { + if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + Debug.LogWarning(string.Format("Currently, the limit of users is reached for this title. Try again later. Disconnecting")); + SendMonoMessage(PhotonNetworkingMessage.OnPhotonMaxCccuReached); + SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, DisconnectCause.MaxCcuReached); + } + else if (operationResponse.ReturnCode == ErrorCode.InvalidRegion) + { + if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + Debug.LogError(string.Format("The used master server address is not available with the subscription currently used. Got to Photon Cloud Dashboard or change URL. Disconnecting.")); + SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, DisconnectCause.InvalidRegion); + } + else if (operationResponse.ReturnCode == ErrorCode.AuthenticationTicketExpired) + { + if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + Debug.LogError(string.Format("The authentication ticket expired. You need to connect (and authenticate) again. Disconnecting.")); + SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, DisconnectCause.AuthenticationTicketExpired); + } + break; + } + else + { + // successful connect/auth. depending on the used server, do next steps: + + if (this.Server == ServerConnection.NameServer || this.Server == ServerConnection.MasterServer) + { + if (operationResponse.Parameters.ContainsKey(ParameterCode.UserId)) + { + string incomingId = (string)operationResponse.Parameters[ParameterCode.UserId]; + if (!string.IsNullOrEmpty(incomingId)) + { + if (this.AuthValues == null) + { + this.AuthValues = new AuthenticationValues(); + } + this.AuthValues.UserId = incomingId; + PhotonNetwork.player.UserId = incomingId; + + if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + { + this.DebugReturn(DebugLevel.INFO, string.Format("Received your UserID from server. Updating local value to: {0}", incomingId)); + } + } + } + if (operationResponse.Parameters.ContainsKey(ParameterCode.NickName)) + { + this.PlayerName = (string)operationResponse.Parameters[ParameterCode.NickName]; + if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + { + this.DebugReturn(DebugLevel.INFO, string.Format("Received your NickName from server. Updating local value to: {0}", this.playername)); + } + } + + if (operationResponse.Parameters.ContainsKey(ParameterCode.EncryptionData)) + { + this.SetupEncryption((Dictionary)operationResponse.Parameters[ParameterCode.EncryptionData]); + } + } + + if (this.Server == ServerConnection.NameServer) + { + // on the NameServer, authenticate returns the MasterServer address for a region and we hop off to there + this.MasterServerAddress = operationResponse[ParameterCode.Address] as string; + if (PhotonNetwork.UseAlternativeUdpPorts && this.TransportProtocol == ConnectionProtocol.Udp) + { + this.MasterServerAddress = this.MasterServerAddress.Replace("5058", "27000").Replace("5055", "27001").Replace("5056", "27002"); + } + this.DisconnectToReconnect(); + } + else if (this.Server == ServerConnection.MasterServer) + { + if (this.AuthMode != AuthModeOption.Auth) + { + this.OpSettings(this.requestLobbyStatistics); + } + if (PhotonNetwork.autoJoinLobby) + { + this.State = ClientState.Authenticated; + this.OpJoinLobby(this.lobby); + } + else + { + this.State = ClientState.ConnectedToMaster; + SendMonoMessage(PhotonNetworkingMessage.OnConnectedToMaster); + } + } + else if (this.Server == ServerConnection.GameServer) + { + this.State = ClientState.Joining; + this.enterRoomParamsCache.PlayerProperties = GetLocalActorProperties(); + this.enterRoomParamsCache.OnGameServer = true; + + if (this.lastJoinType == JoinType.JoinRoom || this.lastJoinType == JoinType.JoinRandomRoom || this.lastJoinType == JoinType.JoinOrCreateRoom) + { + // if we just "join" the game, do so. if we wanted to "create the room on demand", we have to send this to the game server as well. + this.OpJoinRoom(this.enterRoomParamsCache); + } + else if (this.lastJoinType == JoinType.CreateRoom) + { + this.OpCreateGame(this.enterRoomParamsCache); + } + } + + if (operationResponse.Parameters.ContainsKey(ParameterCode.Data)) + { + // optionally, OpAuth may return some data for the client to use. if it's available, call OnCustomAuthenticationResponse + Dictionary data = (Dictionary)operationResponse.Parameters[ParameterCode.Data]; + if (data != null) + { + SendMonoMessage(PhotonNetworkingMessage.OnCustomAuthenticationResponse, data); + } + } + } + break; + } + + case OperationCode.GetRegions: + // Debug.Log("GetRegions returned: " + operationResponse.ToStringFull()); + + if (operationResponse.ReturnCode == ErrorCode.InvalidAuthentication) + { + Debug.LogError(string.Format("The appId this client sent is unknown on the server (Cloud). Check settings. If using the Cloud, check account.")); + SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, DisconnectCause.InvalidAuthentication); + + this.State = ClientState.Disconnecting; + this.Disconnect(); + break; + } + if (operationResponse.ReturnCode != ErrorCode.Ok) + { + Debug.LogError("GetRegions failed. Can't provide regions list. Error: " + operationResponse.ReturnCode + ": " + operationResponse.DebugMessage); + break; + } + + string[] regions = operationResponse[ParameterCode.Region] as string[]; + string[] servers = operationResponse[ParameterCode.Address] as string[]; + if (regions == null || servers == null || regions.Length != servers.Length) + { + Debug.LogError("The region arrays from Name Server are not ok. Must be non-null and same length. " + (regions ==null)+ " " + (servers==null) + "\n"+operationResponse.ToStringFull()); + break; + } + + this.AvailableRegions = new List(regions.Length); + for (int i = 0; i < regions.Length; i++) + { + string regionCodeString = regions[i]; + if (string.IsNullOrEmpty(regionCodeString)) + { + continue; + } + regionCodeString = regionCodeString.ToLower(); + CloudRegionCode code = Region.Parse(regionCodeString); + + // check if enabled (or ignored by PhotonServerSettings.EnabledRegions) + bool enabledRegion = true; + if (PhotonNetwork.PhotonServerSettings.HostType == ServerSettings.HostingOption.BestRegion && PhotonNetwork.PhotonServerSettings.EnabledRegions != 0) + { + CloudRegionFlag flag = Region.ParseFlag(code); + enabledRegion = ((PhotonNetwork.PhotonServerSettings.EnabledRegions & flag) != 0); + if (!enabledRegion && PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + { + Debug.Log("Skipping region because it's not in PhotonServerSettings.EnabledRegions: " + code); + } + } + if (enabledRegion) + { + this.AvailableRegions.Add(new Region(code, regionCodeString, servers[i])); + } + } + + // PUN assumes you fetch the name-server's list of regions to ping them + if (PhotonNetwork.PhotonServerSettings.HostType == ServerSettings.HostingOption.BestRegion) + { + + CloudRegionCode bestFromPrefs = PhotonHandler.BestRegionCodeInPreferences; + if (bestFromPrefs != CloudRegionCode.none && + this.AvailableRegions.Exists(x => x.Code == bestFromPrefs) + ) + { + Debug.Log("Best region found in PlayerPrefs. Connecting to: " + bestFromPrefs); + if (!this.ConnectToRegionMaster(bestFromPrefs)) + { + PhotonHandler.PingAvailableRegionsAndConnectToBest(); + } + }else{ + + PhotonHandler.PingAvailableRegionsAndConnectToBest(); + } + } + break; + + case OperationCode.CreateGame: + { + if (this.Server == ServerConnection.GameServer) + { + this.GameEnteredOnGameServer(operationResponse); + } + else + { + if (operationResponse.ReturnCode != 0) + { + if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + Debug.LogWarning(string.Format("CreateRoom failed, client stays on masterserver: {0}.", operationResponse.ToStringFull())); + + this.State = (this.insideLobby) ? ClientState.JoinedLobby : ClientState.ConnectedToMaster; + SendMonoMessage(PhotonNetworkingMessage.OnPhotonCreateRoomFailed, operationResponse.ReturnCode, operationResponse.DebugMessage); + break; + } + + string gameID = (string) operationResponse[ParameterCode.RoomName]; + if (!string.IsNullOrEmpty(gameID)) + { + // is only sent by the server's response, if it has not been + // sent with the client's request before! + this.enterRoomParamsCache.RoomName = gameID; + } + + this.GameServerAddress = (string)operationResponse[ParameterCode.Address]; + if (PhotonNetwork.UseAlternativeUdpPorts && this.TransportProtocol == ConnectionProtocol.Udp) + { + this.GameServerAddress = this.GameServerAddress.Replace("5058", "27000").Replace("5055", "27001").Replace("5056", "27002"); + } + this.DisconnectToReconnect(); + } + + break; + } + + case OperationCode.JoinGame: + { + if (this.Server != ServerConnection.GameServer) + { + if (operationResponse.ReturnCode != 0) + { + if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + Debug.Log(string.Format("JoinRoom failed (room maybe closed by now). Client stays on masterserver: {0}. State: {1}", operationResponse.ToStringFull(), this.State)); + + SendMonoMessage(PhotonNetworkingMessage.OnPhotonJoinRoomFailed, operationResponse.ReturnCode, operationResponse.DebugMessage); + break; + } + + this.GameServerAddress = (string)operationResponse[ParameterCode.Address]; + if (PhotonNetwork.UseAlternativeUdpPorts && this.TransportProtocol == ConnectionProtocol.Udp) + { + this.GameServerAddress = this.GameServerAddress.Replace("5058", "27000").Replace("5055", "27001").Replace("5056", "27002"); + } + this.DisconnectToReconnect(); + } + else + { + this.GameEnteredOnGameServer(operationResponse); + } + + break; + } + + case OperationCode.JoinRandomGame: + { + // happens only on master. on gameserver, this is a regular join (we don't need to find a random game again) + // the operation OpJoinRandom either fails (with returncode 8) or returns game-to-join information + if (operationResponse.ReturnCode != 0) + { + if (operationResponse.ReturnCode == ErrorCode.NoRandomMatchFound) + { + if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) + Debug.Log("JoinRandom failed: No open game. Calling: OnPhotonRandomJoinFailed() and staying on master server."); + } + else if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + { + Debug.LogWarning(string.Format("JoinRandom failed: {0}.", operationResponse.ToStringFull())); + } + + SendMonoMessage(PhotonNetworkingMessage.OnPhotonRandomJoinFailed, operationResponse.ReturnCode, operationResponse.DebugMessage); + break; + } + + string roomName = (string)operationResponse[ParameterCode.RoomName]; + this.enterRoomParamsCache.RoomName = roomName; + this.GameServerAddress = (string)operationResponse[ParameterCode.Address]; + if (PhotonNetwork.UseAlternativeUdpPorts && this.TransportProtocol == ConnectionProtocol.Udp) + { + this.GameServerAddress = this.GameServerAddress.Replace("5058", "27000").Replace("5055", "27001").Replace("5056", "27002"); + } + this.DisconnectToReconnect(); + break; + } + + case OperationCode.GetGameList: + if (operationResponse.ReturnCode != 0) + { + this.DebugReturn(DebugLevel.ERROR, "GetGameList failed: " + operationResponse.ToStringFull()); + break; + } + + this.mGameList = new Dictionary(); + Hashtable games = (Hashtable)operationResponse[ParameterCode.GameList]; + foreach (var gameKey in games.Keys) + { + string gameName = (string)gameKey; + this.mGameList[gameName] = new RoomInfo(gameName, (Hashtable)games[gameKey]); + } + mGameListCopy = new RoomInfo[mGameList.Count]; + mGameList.Values.CopyTo(mGameListCopy, 0); + SendMonoMessage(PhotonNetworkingMessage.OnReceivedRoomListUpdate); + break; + + case OperationCode.JoinLobby: + this.State = ClientState.JoinedLobby; + this.insideLobby = true; + SendMonoMessage(PhotonNetworkingMessage.OnJoinedLobby); + + // this.mListener.joinLobbyReturn(); + break; + case OperationCode.LeaveLobby: + this.State = ClientState.Authenticated; + this.LeftLobbyCleanup(); // will set insideLobby = false + break; + + case OperationCode.Leave: + this.DisconnectToReconnect(); + break; + + case OperationCode.SetProperties: + // this.mListener.setPropertiesReturn(returnCode, debugMsg); + break; + + case OperationCode.GetProperties: + { + Hashtable actorProperties = (Hashtable)operationResponse[ParameterCode.PlayerProperties]; + Hashtable gameProperties = (Hashtable)operationResponse[ParameterCode.GameProperties]; + this.ReadoutProperties(gameProperties, actorProperties, 0); + + // RemoveByteTypedPropertyKeys(actorProperties, false); + // RemoveByteTypedPropertyKeys(gameProperties, false); + // this.mListener.getPropertiesReturn(gameProperties, actorProperties, returnCode, debugMsg); + break; + } + + case OperationCode.RaiseEvent: + // this usually doesn't give us a result. only if the caching is affected the server will send one. + break; + + case OperationCode.FindFriends: + bool[] onlineList = operationResponse[ParameterCode.FindFriendsResponseOnlineList] as bool[]; + string[] roomList = operationResponse[ParameterCode.FindFriendsResponseRoomIdList] as string[]; + + if (onlineList != null && roomList != null && this.friendListRequested != null && onlineList.Length == this.friendListRequested.Length) + { + List friendList = new List(this.friendListRequested.Length); + for (int index = 0; index < this.friendListRequested.Length; index++) + { + FriendInfo friend = new FriendInfo(); + friend.UserId = this.friendListRequested[index]; + friend.Room = roomList[index]; + friend.IsOnline = onlineList[index]; + friendList.Insert(index, friend); + } + PhotonNetwork.Friends = friendList; + } + else + { + // any of the lists is null and shouldn't. print a error + Debug.LogError("FindFriends failed to apply the result, as a required value wasn't provided or the friend list length differed from result."); + } + + this.friendListRequested = null; + this.isFetchingFriendList = false; + this.friendListTimestamp = Environment.TickCount; + if (this.friendListTimestamp == 0) + { + this.friendListTimestamp = 1; // makes sure the timestamp is not accidentally 0 + } + + SendMonoMessage(PhotonNetworkingMessage.OnUpdatedFriendList); + break; + + case OperationCode.WebRpc: + SendMonoMessage(PhotonNetworkingMessage.OnWebRpcResponse, operationResponse); + break; + + default: + Debug.LogWarning(string.Format("OperationResponse unhandled: {0}", operationResponse.ToString())); + break; + } + + //this.externalListener.OnOperationResponse(operationResponse); + } + + public void OnStatusChanged(StatusCode statusCode) + { + if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + Debug.Log(string.Format("OnStatusChanged: {0} current State: {1}", statusCode.ToString(), this.State)); + + switch (statusCode) + { + case StatusCode.Connect: + if (this.State == ClientState.ConnectingToNameServer) + { + if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) + Debug.Log("Connected to NameServer."); + + this.Server = ServerConnection.NameServer; + if (this.AuthValues != null) + { + this.AuthValues.Token = null; // when connecting to NameServer, invalidate any auth values + } + } + + if (this.State == ClientState.ConnectingToGameserver) + { + if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) + Debug.Log("Connected to gameserver."); + + this.Server = ServerConnection.GameServer; + this.State = ClientState.ConnectedToGameserver; + } + + if (this.State == ClientState.ConnectingToMasterserver) + { + if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) + Debug.Log("Connected to masterserver."); + + this.Server = ServerConnection.MasterServer; + this.State = ClientState.Authenticating; // photon v4 always requires OpAuthenticate. even self-hosted Photon Server + + if (this.IsInitialConnect) + { + this.IsInitialConnect = false; // after handling potential initial-connect issues with special messages, we are now sure we can reach a server + SendMonoMessage(PhotonNetworkingMessage.OnConnectedToPhoton); + } + } + + + if (this.TransportProtocol != ConnectionProtocol.WebSocketSecure) + { + if (this.Server == ServerConnection.NameServer || this.AuthMode == AuthModeOption.Auth) + { + if (!PhotonNetwork.offlineMode) + this.EstablishEncryption(); + } + } + else + { + if (DebugOut == DebugLevel.INFO) + { + Debug.Log("Skipping EstablishEncryption. Protocol is secure."); + } + + goto case StatusCode.EncryptionEstablished; + } + break; + + case StatusCode.EncryptionEstablished: + + // reset flags + _isReconnecting = false; + + // on nameserver, the "process" is stopped here, so the developer/game can either get regions or authenticate with a specific region + if (this.Server == ServerConnection.NameServer) + { + this.State = ClientState.ConnectedToNameServer; + + if (!this.didAuthenticate && this.CloudRegion == CloudRegionCode.none) + { + // this client is not setup to connect to a default region. find out which regions there are! + this.OpGetRegions(this.AppId); + } + } + + if (this.Server != ServerConnection.NameServer && (this.AuthMode == AuthModeOption.AuthOnce || this.AuthMode == AuthModeOption.AuthOnceWss)) + { + // AuthMode "Once" means we only authenticate on the NameServer + Debug.Log("didAuthenticate " + didAuthenticate + " AuthMode "+ AuthMode); + break; + } + + + // we might need to authenticate automatically now, so the client can do anything at all + if (!this.didAuthenticate && (!this.IsUsingNameServer || this.CloudRegion != CloudRegionCode.none)) + { + this.didAuthenticate = this.CallAuthenticate(); + + if (this.didAuthenticate) + { + this.State = ClientState.Authenticating; + } + } + break; + + case StatusCode.EncryptionFailedToEstablish: + Debug.LogError("Encryption wasn't established: " + statusCode + ". Going to authenticate anyways."); + AuthenticationValues authV = this.AuthValues ?? new AuthenticationValues() { UserId = this.PlayerName }; + this.OpAuthenticate(this.AppId, this.AppVersion, authV, this.CloudRegion.ToString(), this.requestLobbyStatistics); // TODO: check if there are alternatives + break; + + case StatusCode.Disconnect: + this.didAuthenticate = false; + this.isFetchingFriendList = false; + if (this.Server == ServerConnection.GameServer) this.LeftRoomCleanup(); + if (this.Server == ServerConnection.MasterServer) this.LeftLobbyCleanup(); + + if (this.State == ClientState.DisconnectingFromMasterserver) + { + if (this.Connect(this.GameServerAddress, ServerConnection.GameServer)) + { + this.State = ClientState.ConnectingToGameserver; + } + } + else if (this.State == ClientState.DisconnectingFromGameserver || this.State == ClientState.DisconnectingFromNameServer) + { + this.SetupProtocol(ServerConnection.MasterServer); + if (this.Connect(this.MasterServerAddress, ServerConnection.MasterServer)) + { + this.State = ClientState.ConnectingToMasterserver; + } + } + else + { + if (_isReconnecting) + { + return; + } + + if (this.AuthValues != null) + { + this.AuthValues.Token = null; // invalidate any custom auth secrets + } + + this.IsInitialConnect = false; // not "connecting" anymore + this.State = ClientState.PeerCreated; // if we set another state here, we could keep clients from connecting in OnDisconnectedFromPhoton right here. + SendMonoMessage(PhotonNetworkingMessage.OnDisconnectedFromPhoton); + } + break; + + case StatusCode.ExceptionOnConnect: + case StatusCode.SecurityExceptionOnConnect: + this.IsInitialConnect = false; + + this.State = ClientState.PeerCreated; + if (this.AuthValues != null) + { + this.AuthValues.Token = null; // invalidate any custom auth secrets + } + + DisconnectCause cause = (DisconnectCause)statusCode; + SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, cause); + break; + + case StatusCode.Exception: + if (this.IsInitialConnect) + { + Debug.LogError("Exception while connecting to: " + this.ServerAddress + ". Check if the server is available."); + if (this.ServerAddress == null || this.ServerAddress.StartsWith("127.0.0.1")) + { + Debug.LogWarning("The server address is 127.0.0.1 (localhost): Make sure the server is running on this machine. Android and iOS emulators have their own localhost."); + if (this.ServerAddress == this.GameServerAddress) + { + Debug.LogWarning("This might be a misconfiguration in the game server config. You need to edit it to a (public) address."); + } + } + + this.State = ClientState.PeerCreated; + cause = (DisconnectCause)statusCode; + this.IsInitialConnect = false; + SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, cause); + } + else + { + this.State = ClientState.PeerCreated; + + cause = (DisconnectCause)statusCode; + SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, cause); + } + + this.Disconnect(); + break; + + case StatusCode.TimeoutDisconnect: + if (this.IsInitialConnect) + { + // UNITY_IOS || UNITY_EDITOR + #if FALSE + if (this.UsedProtocol == ConnectionProtocol.Udp) + { + + Debug.LogWarning("UDP Connection timed out, Reconnecting using TCP"); + + PhotonNetwork.PhotonServerSettings.Protocol = ConnectionProtocol.Tcp; + + // replace port in cached address: + // This is limited... The Photon ServerSettings only has one field for serverPort, + // so we can't know if the TCP port would have had a different port on a custom server + if (this.cachedServerAddress.Contains(":")) + { + this.cachedServerAddress = this.cachedServerAddress.Split(':')[0]; + this.cachedServerAddress += ":4530"; + } + + this.Reconnect(); + return; + } + #endif + + if (!_isReconnecting) + { + Debug.LogWarning(statusCode + " while connecting to: " + this.ServerAddress + ". Check if the server is available."); + + this.IsInitialConnect = false; + cause = (DisconnectCause)statusCode; + SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, cause); + } + } + else + { + cause = (DisconnectCause)statusCode; + SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, cause); + } + if (this.AuthValues != null) + { + this.AuthValues.Token = null; // invalidate any custom auth secrets + } + + /* JF: we need this when reconnecting and joining. + if (this.ServerAddress.Equals(this.GameServerAddress)) + { + this.GameServerAddress = null; + } + if (this.ServerAddress.Equals(this.MasterServerAddress)) + { + this.ServerAddress = null; + } + */ + + this.Disconnect(); + break; + + case StatusCode.ExceptionOnReceive: + case StatusCode.DisconnectByServer: + case StatusCode.DisconnectByServerLogic: + case StatusCode.DisconnectByServerUserLimit: + if (this.IsInitialConnect) + { + Debug.LogWarning(statusCode + " while connecting to: " + this.ServerAddress + ". Check if the server is available."); + + this.IsInitialConnect = false; + cause = (DisconnectCause)statusCode; + SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, cause); + } + else + { + cause = (DisconnectCause)statusCode; + SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, cause); + } + if (this.AuthValues != null) + { + this.AuthValues.Token = null; // invalidate any custom auth secrets + } + + this.Disconnect(); + break; + + case StatusCode.SendError: + // this.mListener.clientErrorReturn(statusCode); + break; + + //case StatusCode.QueueOutgoingReliableWarning: + //case StatusCode.QueueOutgoingUnreliableWarning: + //case StatusCode.QueueOutgoingAcksWarning: + //case StatusCode.QueueSentWarning: + // // this.mListener.warningReturn(statusCode); + // break; + + //case StatusCode.QueueIncomingReliableWarning: + //case StatusCode.QueueIncomingUnreliableWarning: + // Debug.Log(statusCode + ". This client buffers many incoming messages. This is OK temporarily. With lots of these warnings, check if you send too much or execute messages too slow. " + (PhotonNetwork.isMessageQueueRunning? "":"Your isMessageQueueRunning is false. This can cause the issue temporarily.") ); + // break; + + // // TCP "routing" is an option of Photon that's not currently needed (or supported) by PUN + //case StatusCode.TcpRouterResponseOk: + // break; + //case StatusCode.TcpRouterResponseEndpointUnknown: + //case StatusCode.TcpRouterResponseNodeIdUnknown: + //case StatusCode.TcpRouterResponseNodeNotReady: + + // this.DebugReturn(DebugLevel.ERROR, "Unexpected router response: " + statusCode); + // break; + + default: + + // this.mListener.serverErrorReturn(statusCode.value()); + Debug.LogError("Received unknown status code: " + statusCode); + break; + } + + //this.externalListener.OnStatusChanged(statusCode); + } + + + public void OnEvent(EventData photonEvent) + { + if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + Debug.Log(string.Format("OnEvent: {0}", photonEvent.ToString())); + + int actorNr = -1; + PhotonPlayer originatingPlayer = null; + + if (photonEvent.Parameters.ContainsKey(ParameterCode.ActorNr)) + { + actorNr = (int)photonEvent[ParameterCode.ActorNr]; + originatingPlayer = this.GetPlayerWithId(actorNr); + + //else + //{ + // // the actor sending this event is not in actorlist. this is usually no problem + // if (photonEvent.Code != (byte)LiteOpCode.Join) + // { + // Debug.LogWarning("Received event, but we do not have this actor: " + actorNr); + // } + //} + } + + switch (photonEvent.Code) + { + case PunEvent.OwnershipRequest: + { + int[] requestValues = (int[]) photonEvent.Parameters[ParameterCode.CustomEventContent]; + int requestedViewId = requestValues[0]; + int currentOwner = requestValues[1]; + + + PhotonView requestedView = PhotonView.Find(requestedViewId); + if (requestedView == null) + { + Debug.LogWarning("Can't find PhotonView of incoming OwnershipRequest. ViewId not found: " + requestedViewId); + break; + } + + if (PhotonNetwork.logLevel == PhotonLogLevel.Informational) + Debug.Log("Ev OwnershipRequest " + requestedView.ownershipTransfer + ". ActorNr: " + actorNr + " takes from: " + currentOwner + ". local RequestedView.ownerId: " + requestedView.ownerId + " isOwnerActive: " + requestedView.isOwnerActive + ". MasterClient: " + this.mMasterClientId + ". This client's player: " + PhotonNetwork.player.ToStringFull()); + + switch (requestedView.ownershipTransfer) + { + case OwnershipOption.Fixed: + Debug.LogWarning("Ownership mode == fixed. Ignoring request."); + break; + case OwnershipOption.Takeover: + if (currentOwner == requestedView.ownerId || (currentOwner == 0 && requestedView.ownerId == this.mMasterClientId) || requestedView.ownerId == 0) + { + // a takeover is successful automatically, if taken from current owner + requestedView.OwnerShipWasTransfered = true; + int _oldOwnerId = requestedView.ownerId; + PhotonPlayer _oldOwner = this.GetPlayerWithId(_oldOwnerId); + + requestedView.ownerId = actorNr; + + + if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + { + Debug.LogWarning(requestedView + " ownership transfered to: "+ actorNr); + } + + SendMonoMessage(PhotonNetworkingMessage.OnOwnershipTransfered, new object[] {requestedView, originatingPlayer,_oldOwner}); + + } + break; + case OwnershipOption.Request: + if (currentOwner == PhotonNetwork.player.ID || PhotonNetwork.player.IsMasterClient) + { + if ((requestedView.ownerId == PhotonNetwork.player.ID) || (PhotonNetwork.player.IsMasterClient && !requestedView.isOwnerActive)) + { + SendMonoMessage(PhotonNetworkingMessage.OnOwnershipRequest, new object[] {requestedView, originatingPlayer}); + } + } + break; + default: + break; + } + } + break; + + case PunEvent.OwnershipTransfer: + { + int[] transferViewToUserID = (int[]) photonEvent.Parameters[ParameterCode.CustomEventContent]; + + if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + { + Debug.Log("Ev OwnershipTransfer. ViewID " + transferViewToUserID[0] + " to: " + transferViewToUserID[1] + " Time: " + Environment.TickCount%1000); + } + + + + int requestedViewId = transferViewToUserID[0]; + int newOwnerId = transferViewToUserID[1]; + + PhotonView pv = PhotonView.Find(requestedViewId); + if (pv != null) + { + int _oldOwnerID = pv.ownerId; + pv.OwnerShipWasTransfered = true; + pv.ownerId = newOwnerId; + + SendMonoMessage(PhotonNetworkingMessage.OnOwnershipTransfered, new object[] {pv, PhotonPlayer.Find(newOwnerId),PhotonPlayer.Find(_oldOwnerID)}); + } + + + break; + } + case EventCode.GameList: + { + this.mGameList = new Dictionary(); + Hashtable games = (Hashtable)photonEvent[ParameterCode.GameList]; + foreach (var gameKey in games.Keys) + { + string gameName = (string)gameKey; + this.mGameList[gameName] = new RoomInfo(gameName, (Hashtable)games[gameKey]); + } + mGameListCopy = new RoomInfo[mGameList.Count]; + mGameList.Values.CopyTo(mGameListCopy, 0); + SendMonoMessage(PhotonNetworkingMessage.OnReceivedRoomListUpdate); + break; + } + + case EventCode.GameListUpdate: + { + Hashtable games = (Hashtable)photonEvent[ParameterCode.GameList]; + foreach (var roomKey in games.Keys) + { + string gameName = (string)roomKey; + RoomInfo game = new RoomInfo(gameName, (Hashtable)games[roomKey]); + if (game.removedFromList) + { + this.mGameList.Remove(gameName); + } + else + { + this.mGameList[gameName] = game; + } + } + this.mGameListCopy = new RoomInfo[this.mGameList.Count]; + this.mGameList.Values.CopyTo(this.mGameListCopy, 0); + SendMonoMessage(PhotonNetworkingMessage.OnReceivedRoomListUpdate); + break; + } + + case EventCode.AppStats: + // Debug.LogInfo("Received stats!"); + this.PlayersInRoomsCount = (int)photonEvent[ParameterCode.PeerCount]; + this.PlayersOnMasterCount = (int)photonEvent[ParameterCode.MasterPeerCount]; + this.RoomsCount = (int)photonEvent[ParameterCode.GameCount]; + break; + + case EventCode.Join: + + // save the IsInactive Property to be able to detect if activity state changed + bool wasInactive = false; + + // actorNr is fetched out of event above + Hashtable actorProperties = (Hashtable)photonEvent[ParameterCode.PlayerProperties]; + if (originatingPlayer == null) + { + bool isLocal = this.LocalPlayer.ID == actorNr; + this.AddNewPlayer(actorNr, new PhotonPlayer(isLocal, actorNr, actorProperties)); + this.ResetPhotonViewsOnSerialize(); // This sets the correct OnSerializeState for Reliable OnSerialize + } + else + { + wasInactive = originatingPlayer.IsInactive; + + originatingPlayer.InternalCacheProperties(actorProperties); + originatingPlayer.IsInactive = false; + } + + if (actorNr == this.LocalPlayer.ID) + { + // in this player's 'own' join event, we get a complete list of players in the room, so check if we know all players + int[] actorsInRoom = (int[])photonEvent[ParameterCode.ActorList]; + this.UpdatedActorList(actorsInRoom); + + // joinWithCreateOnDemand can turn an OpJoin into creating the room. Then actorNumber is 1 and callback: OnCreatedRoom() + if (this.lastJoinType == JoinType.JoinOrCreateRoom && this.LocalPlayer.ID == 1) + { + SendMonoMessage(PhotonNetworkingMessage.OnCreatedRoom); + } + SendMonoMessage(PhotonNetworkingMessage.OnJoinedRoom); //Always send OnJoinedRoom + + } + else + { + SendMonoMessage(PhotonNetworkingMessage.OnPhotonPlayerConnected, this.mActors[actorNr]); + + if (wasInactive) + { + SendMonoMessage(PhotonNetworkingMessage.OnPhotonPlayerActivityChanged, this.mActors[actorNr]); + } + + } + break; + + case EventCode.Leave: + this.HandleEventLeave(actorNr, photonEvent); + break; + + case EventCode.PropertiesChanged: + int targetActorNr = (int)photonEvent[ParameterCode.TargetActorNr]; + Hashtable gameProperties = null; + Hashtable actorProps = null; + if (targetActorNr == 0) + { + gameProperties = (Hashtable)photonEvent[ParameterCode.Properties]; + } + else + { + actorProps = (Hashtable)photonEvent[ParameterCode.Properties]; + } + + this.ReadoutProperties(gameProperties, actorProps, targetActorNr); + break; + + case PunEvent.RPC: + //ts: each event now contains a single RPC. execute this + // Debug.Log("Ev RPC from: " + originatingPlayer); + + this.ExecuteRpc(photonEvent[ParameterCode.Data] as Hashtable, actorNr); + break; + + case PunEvent.SendSerialize: + case PunEvent.SendSerializeReliable: + Hashtable serializeData = (Hashtable)photonEvent[ParameterCode.Data]; + //Debug.Log(serializeData.ToStringFull()); + + int remoteUpdateServerTimestamp = (int)serializeData[(byte)0]; + short remoteLevelPrefix = -1; + byte initialDataIndex = 10; + int headerLength = 1; + if (serializeData.ContainsKey((byte)1)) + { + remoteLevelPrefix = (short)serializeData[(byte)1]; + headerLength = 2; + } + + for (byte s = initialDataIndex; s - initialDataIndex < serializeData.Count - headerLength; s++) + { + this.OnSerializeRead(serializeData[s] as object[], originatingPlayer, remoteUpdateServerTimestamp, remoteLevelPrefix); + } + break; + + case PunEvent.Instantiation: + this.DoInstantiate((Hashtable)photonEvent[ParameterCode.Data], originatingPlayer, null); + break; + + case PunEvent.CloseConnection: + // MasterClient "requests" a disconnection from us + if (originatingPlayer == null || !originatingPlayer.IsMasterClient) + { + Debug.LogError("Error: Someone else(" + originatingPlayer + ") then the masterserver requests a disconnect!"); + } + else + { + PhotonNetwork.LeaveRoom(false); + } + + break; + + case PunEvent.DestroyPlayer: + Hashtable evData = (Hashtable)photonEvent[ParameterCode.Data]; + int targetPlayerId = (int)evData[(byte)0]; + if (targetPlayerId >= 0) + { + this.DestroyPlayerObjects(targetPlayerId, true); + } + else + { + if (this.DebugOut >= DebugLevel.INFO) Debug.Log("Ev DestroyAll! By PlayerId: " + actorNr); + this.DestroyAll(true); + } + break; + + case PunEvent.Destroy: + evData = (Hashtable)photonEvent[ParameterCode.Data]; + int instantiationId = (int)evData[(byte)0]; + // Debug.Log("Ev Destroy for viewId: " + instantiationId + " sent by owner: " + (instantiationId / PhotonNetwork.MAX_VIEW_IDS == actorNr) + " this client is owner: " + (instantiationId / PhotonNetwork.MAX_VIEW_IDS == this.LocalPlayer.ID)); + + + PhotonView pvToDestroy = null; + if (this.photonViewList.TryGetValue(instantiationId, out pvToDestroy)) + { + this.RemoveInstantiatedGO(pvToDestroy.gameObject, true); + } + else + { + if (this.DebugOut >= DebugLevel.ERROR) Debug.LogError("Ev Destroy Failed. Could not find PhotonView with instantiationId " + instantiationId + ". Sent by actorNr: " + actorNr); + } + + break; + + case PunEvent.AssignMaster: + evData = (Hashtable)photonEvent[ParameterCode.Data]; + int newMaster = (int)evData[(byte)1]; + this.SetMasterClient(newMaster, false); + break; + + case EventCode.LobbyStats: + //Debug.Log("LobbyStats EV: " + photonEvent.ToStringFull()); + + string[] names = photonEvent[ParameterCode.LobbyName] as string[]; + byte[] types = photonEvent[ParameterCode.LobbyType] as byte[]; + int[] peers = photonEvent[ParameterCode.PeerCount] as int[]; + int[] rooms = photonEvent[ParameterCode.GameCount] as int[]; + + this.LobbyStatistics.Clear(); + for (int i = 0; i < names.Length; i++) + { + TypedLobbyInfo info = new TypedLobbyInfo(); + info.Name = names[i]; + info.Type = (LobbyType)types[i]; + info.PlayerCount = peers[i]; + info.RoomCount = rooms[i]; + + this.LobbyStatistics.Add(info); + } + + SendMonoMessage(PhotonNetworkingMessage.OnLobbyStatisticsUpdate); + break; + + case EventCode.ErrorInfo: + if (PhotonNetwork.OnEventCall != null) + { + object content = photonEvent[ParameterCode.Info]; + PhotonNetwork.OnEventCall(photonEvent.Code, content, actorNr); + } + else + { + Debug.LogWarning("Warning: Unhandled Event ErrorInfo (251). Set PhotonNetwork.OnEventCall to the method PUN should call for this event."); + } + break; + + case EventCode.AuthEvent: + if (this.AuthValues == null) + { + this.AuthValues = new AuthenticationValues(); + } + + this.AuthValues.Token = photonEvent[ParameterCode.Secret] as string; + this.tokenCache = this.AuthValues.Token; + break; + + + default: + if (photonEvent.Code < 200) + { + if (PhotonNetwork.OnEventCall != null) + { + object content = photonEvent[ParameterCode.Data]; + PhotonNetwork.OnEventCall(photonEvent.Code, content, actorNr); + } + else + { + Debug.LogWarning("Warning: Unhandled event " + photonEvent + ". Set PhotonNetwork.OnEventCall."); + } + } + break; + } + + //this.externalListener.OnEvent(photonEvent); + } + + public void OnMessage(object messages) + { + // not used here + } + + #endregion + + + private void SetupEncryption(Dictionary encryptionData) + { + // this should not be called when authentication is done per server. this mode does not support the required "key-exchange via token" + if (this.AuthMode == AuthModeOption.Auth) + { + if (DebugOut == DebugLevel.ERROR) + { + UnityEngine.Debug.LogWarning("SetupEncryption() called but ignored. Not XB1 compiled. EncryptionData: " + encryptionData.ToStringFull()); + return; + } + } + + + // for AuthOnce and AuthOnceWss, we can keep the same secret across machines (for the session, basically) + if (DebugOut == DebugLevel.INFO) + { + UnityEngine.Debug.Log("SetupEncryption() got called. "+encryptionData.ToStringFull()); + } + + var mode = (EncryptionMode)(byte)encryptionData[EncryptionDataParameters.Mode]; + switch (mode) + { + case EncryptionMode.PayloadEncryption: + byte[] secret = (byte[])encryptionData[EncryptionDataParameters.Secret1]; + this.InitPayloadEncryption(secret); + break; + case EncryptionMode.DatagramEncryption: + { + byte[] secret1 = (byte[])encryptionData[EncryptionDataParameters.Secret1]; + byte[] secret2 = (byte[])encryptionData[EncryptionDataParameters.Secret2]; + this.InitDatagramEncryption(secret1, secret2); + } + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + + + protected internal void UpdatedActorList(int[] actorsInRoom) + { + for (int i = 0; i < actorsInRoom.Length; i++) + { + int actorNrToCheck = actorsInRoom[i]; + if (this.LocalPlayer.ID != actorNrToCheck && !this.mActors.ContainsKey(actorNrToCheck)) + { + this.AddNewPlayer(actorNrToCheck, new PhotonPlayer(false, actorNrToCheck, string.Empty)); + } + } + } + + private void SendVacantViewIds() + { + Debug.Log("SendVacantViewIds()"); + List vacantViews = new List(); + foreach (PhotonView view in this.photonViewList.Values) + { + if (!view.isOwnerActive) + { + vacantViews.Add(view.viewID); + } + } + + Debug.Log("Sending vacant view IDs. Length: " + vacantViews.Count); + //this.OpRaiseEvent(PunEvent.VacantViewIds, true, vacantViews.ToArray()); + this.OpRaiseEvent(PunEvent.VacantViewIds, vacantViews.ToArray(), true, null); + } + + public static void SendMonoMessage(PhotonNetworkingMessage methodString, params object[] parameters) + { + HashSet objectsToCall; + if (PhotonNetwork.SendMonoMessageTargets != null) + { + objectsToCall = PhotonNetwork.SendMonoMessageTargets; + } + else + { + objectsToCall = PhotonNetwork.FindGameObjectsWithComponent(PhotonNetwork.SendMonoMessageTargetType); + } + + string methodName = methodString.ToString(); + object callParameter = (parameters != null && parameters.Length == 1) ? parameters[0] : parameters; + foreach (GameObject gameObject in objectsToCall) + { + if (gameObject!=null) + { + gameObject.SendMessage(methodName, callParameter, SendMessageOptions.DontRequireReceiver); + } + } + } + + // PHOTONVIEW/RPC related + + /// + /// Executes a received RPC event + /// + protected internal void ExecuteRpc(Hashtable rpcData, int senderID = 0) + { + if (rpcData == null || !rpcData.ContainsKey((byte)0)) + { + Debug.LogError("Malformed RPC; this should never occur. Content: " + SupportClassPun.DictionaryToString(rpcData)); + return; + } + + // ts: updated with "flat" event data + int netViewID = (int)rpcData[(byte)0]; // LIMITS PHOTONVIEWS&PLAYERS + int otherSidePrefix = 0; // by default, the prefix is 0 (and this is not being sent) + if (rpcData.ContainsKey((byte)1)) + { + otherSidePrefix = (short)rpcData[(byte)1]; + } + + + string inMethodName; + if (rpcData.ContainsKey((byte)5)) + { + int rpcIndex = (byte)rpcData[(byte)5]; // LIMITS RPC COUNT + if (rpcIndex > PhotonNetwork.PhotonServerSettings.RpcList.Count - 1) + { + Debug.LogError("Could not find RPC with index: " + rpcIndex + ". Going to ignore! Check PhotonServerSettings.RpcList"); + return; + } + else + { + inMethodName = PhotonNetwork.PhotonServerSettings.RpcList[rpcIndex]; + } + } + else + { + inMethodName = (string)rpcData[(byte)3]; + } + + object[] inMethodParameters = null; + if (rpcData.ContainsKey((byte)4)) + { + inMethodParameters = (object[])rpcData[(byte)4]; + } + + if (inMethodParameters == null) + { + inMethodParameters = new object[0]; + } + + PhotonView photonNetview = this.GetPhotonView(netViewID); + if (photonNetview == null) + { + int viewOwnerId = netViewID/PhotonNetwork.MAX_VIEW_IDS; + bool owningPv = (viewOwnerId == this.LocalPlayer.ID); + bool ownerSent = (viewOwnerId == senderID); + + if (owningPv) + { + Debug.LogWarning("Received RPC \"" + inMethodName + "\" for viewID " + netViewID + " but this PhotonView does not exist! View was/is ours." + (ownerSent ? " Owner called." : " Remote called.") + " By: " + senderID); + } + else + { + Debug.LogWarning("Received RPC \"" + inMethodName + "\" for viewID " + netViewID + " but this PhotonView does not exist! Was remote PV." + (ownerSent ? " Owner called." : " Remote called.") + " By: " + senderID + " Maybe GO was destroyed but RPC not cleaned up."); + } + return; + } + + if (photonNetview.prefix != otherSidePrefix) + { + Debug.LogError("Received RPC \"" + inMethodName + "\" on viewID " + netViewID + " with a prefix of " + otherSidePrefix + ", our prefix is " + photonNetview.prefix + ". The RPC has been ignored."); + return; + } + + // Get method name + if (string.IsNullOrEmpty(inMethodName)) + { + Debug.LogError("Malformed RPC; this should never occur. Content: " + SupportClassPun.DictionaryToString(rpcData)); + return; + } + + if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) + Debug.Log("Received RPC: " + inMethodName); + + + // SetReceiving filtering + if (photonNetview.group != 0 && !allowedReceivingGroups.Contains(photonNetview.group)) + { + return; // Ignore group + } + + Type[] argTypes = new Type[0]; + if (inMethodParameters.Length > 0) + { + argTypes = new Type[inMethodParameters.Length]; + int i = 0; + for (int index = 0; index < inMethodParameters.Length; index++) + { + object objX = inMethodParameters[index]; + if (objX == null) + { + argTypes[i] = null; + } + else + { + argTypes[i] = objX.GetType(); + } + + i++; + } + } + + int receivers = 0; + int foundMethods = 0; + if (!PhotonNetwork.UseRpcMonoBehaviourCache || photonNetview.RpcMonoBehaviours == null || photonNetview.RpcMonoBehaviours.Length == 0) + { + photonNetview.RefreshRpcMonoBehaviourCache(); + } + + for (int componentsIndex = 0; componentsIndex < photonNetview.RpcMonoBehaviours.Length; componentsIndex++) + { + MonoBehaviour monob = photonNetview.RpcMonoBehaviours[componentsIndex]; + if (monob == null) + { + Debug.LogError("ERROR You have missing MonoBehaviours on your gameobjects!"); + continue; + } + + Type type = monob.GetType(); + + // Get [PunRPC] methods from cache + List cachedRPCMethods = null; + bool methodsOfTypeInCache = this.monoRPCMethodsCache.TryGetValue(type, out cachedRPCMethods); + + if (!methodsOfTypeInCache) + { + List entries = SupportClassPun.GetMethods(type, typeof(PunRPC)); + + this.monoRPCMethodsCache[type] = entries; + cachedRPCMethods = entries; + } + + if (cachedRPCMethods == null) + { + continue; + } + + // Check cache for valid methodname+arguments + for (int index = 0; index < cachedRPCMethods.Count; index++) + { + MethodInfo mInfo = cachedRPCMethods[index]; + if (mInfo.Name.Equals(inMethodName)) + { + foundMethods++; + ParameterInfo[] pArray = mInfo.GetCachedParemeters(); + + if (pArray.Length == argTypes.Length) + { + // Normal, PhotonNetworkMessage left out + if (this.CheckTypeMatch(pArray, argTypes)) + { + receivers++; + object result = mInfo.Invoke((object)monob, inMethodParameters); + if (PhotonNetwork.StartRpcsAsCoroutine && mInfo.ReturnType == typeof(IEnumerator)) + { + monob.StartCoroutine((IEnumerator)result); + } + } + } + else if ((pArray.Length - 1) == argTypes.Length) + { + // Check for PhotonNetworkMessage being the last + if (this.CheckTypeMatch(pArray, argTypes)) + { + if (pArray[pArray.Length - 1].ParameterType == typeof(PhotonMessageInfo)) + { + receivers++; + + int sendTime = (int)rpcData[(byte)2]; + object[] deParamsWithInfo = new object[inMethodParameters.Length + 1]; + inMethodParameters.CopyTo(deParamsWithInfo, 0); + + + deParamsWithInfo[deParamsWithInfo.Length - 1] = new PhotonMessageInfo(this.GetPlayerWithId(senderID), sendTime, photonNetview); + + object result = mInfo.Invoke((object)monob, deParamsWithInfo); + if (PhotonNetwork.StartRpcsAsCoroutine && mInfo.ReturnType == typeof(IEnumerator)) + { + monob.StartCoroutine((IEnumerator)result); + } + } + } + } + else if (pArray.Length == 1 && pArray[0].ParameterType.IsArray) + { + receivers++; + object result = mInfo.Invoke((object)monob, new object[] { inMethodParameters }); + if (PhotonNetwork.StartRpcsAsCoroutine && mInfo.ReturnType == typeof(IEnumerator)) + { + monob.StartCoroutine((IEnumerator)result); + } + } + } + } + } + + // Error handling + if (receivers != 1) + { + string argsString = string.Empty; + for (int index = 0; index < argTypes.Length; index++) + { + Type ty = argTypes[index]; + if (argsString != string.Empty) + { + argsString += ", "; + } + + if (ty == null) + { + argsString += "null"; + } + else + { + argsString += ty.Name; + } + } + + if (receivers == 0) + { + if (foundMethods == 0) + { + Debug.LogError("PhotonView with ID " + netViewID + " has no method \"" + inMethodName + "\" marked with the [PunRPC](C#) or @PunRPC(JS) property! Args: " + argsString); + } + else + { + Debug.LogError("PhotonView with ID " + netViewID + " has no method \"" + inMethodName + "\" that takes " + argTypes.Length + " argument(s): " + argsString); + } + } + else + { + Debug.LogError("PhotonView with ID " + netViewID + " has " + receivers + " methods \"" + inMethodName + "\" that takes " + argTypes.Length + " argument(s): " + argsString + ". Should be just one?"); + } + } + } + + /// + /// Check if all types match with parameters. We can have more paramters then types (allow last RPC type to be different). + /// + /// + /// + /// If the types-array has matching parameters (of method) in the parameters array (which may be longer). + private bool CheckTypeMatch(ParameterInfo[] methodParameters, Type[] callParameterTypes) + { + if (methodParameters.Length < callParameterTypes.Length) + { + return false; + } + + for (int index = 0; index < callParameterTypes.Length; index++) + { + #if NETFX_CORE + TypeInfo methodParamTI = methodParameters[index].ParameterType.GetTypeInfo(); + TypeInfo callParamTI = callParameterTypes[index].GetTypeInfo(); + + if (callParameterTypes[index] != null && !methodParamTI.IsAssignableFrom(callParamTI) && !(callParamTI.IsEnum && System.Enum.GetUnderlyingType(methodParamTI.AsType()).GetTypeInfo().IsAssignableFrom(callParamTI))) + { + return false; + } + #else + Type type = methodParameters[index].ParameterType; + if (callParameterTypes[index] != null && !type.IsAssignableFrom(callParameterTypes[index]) && !(type.IsEnum && System.Enum.GetUnderlyingType(type).IsAssignableFrom(callParameterTypes[index]))) + { + return false; + } + #endif + } + + return true; + } + + internal Hashtable SendInstantiate(string prefabName, Vector3 position, Quaternion rotation, byte group, int[] viewIDs, object[] data, bool isGlobalObject) + { + // first viewID is now also the gameobject's instantiateId + int instantiateId = viewIDs[0]; // LIMITS PHOTONVIEWS&PLAYERS + + //TODO: reduce hashtable key usage by using a parameter array for the various values + Hashtable instantiateEvent = new Hashtable(); // This players info is sent via ActorID + instantiateEvent[(byte)0] = prefabName; + + if (position != Vector3.zero) + { + instantiateEvent[(byte)1] = position; + } + + if (rotation != Quaternion.identity) + { + instantiateEvent[(byte)2] = rotation; + } + + if (group != 0) + { + instantiateEvent[(byte)3] = group; + } + + // send the list of viewIDs only if there are more than one. else the instantiateId is the viewID + if (viewIDs.Length > 1) + { + instantiateEvent[(byte)4] = viewIDs; // LIMITS PHOTONVIEWS&PLAYERS + } + + if (data != null) + { + instantiateEvent[(byte)5] = data; + } + + if (this.currentLevelPrefix > 0) + { + instantiateEvent[(byte)8] = this.currentLevelPrefix; // photonview's / object's level prefix + } + + instantiateEvent[(byte)6] = PhotonNetwork.ServerTimestamp; + instantiateEvent[(byte)7] = instantiateId; + + + RaiseEventOptions options = new RaiseEventOptions(); + options.CachingOption = (isGlobalObject) ? EventCaching.AddToRoomCacheGlobal : EventCaching.AddToRoomCache; + + this.OpRaiseEvent(PunEvent.Instantiation, instantiateEvent, true, options); + return instantiateEvent; + } + + internal GameObject DoInstantiate(Hashtable evData, PhotonPlayer photonPlayer, GameObject resourceGameObject) + { + // some values always present: + string prefabName = (string)evData[(byte)0]; + int serverTime = (int)evData[(byte)6]; + int instantiationId = (int)evData[(byte)7]; + + Vector3 position; + if (evData.ContainsKey((byte)1)) + { + position = (Vector3)evData[(byte)1]; + } + else + { + position = Vector3.zero; + } + + Quaternion rotation = Quaternion.identity; + if (evData.ContainsKey((byte)2)) + { + rotation = (Quaternion)evData[(byte)2]; + } + + byte group = 0; + if (evData.ContainsKey((byte)3)) + { + group = (byte)evData[(byte)3]; + } + + short objLevelPrefix = 0; + if (evData.ContainsKey((byte)8)) + { + objLevelPrefix = (short)evData[(byte)8]; + } + + int[] viewsIDs; + if (evData.ContainsKey((byte)4)) + { + viewsIDs = (int[])evData[(byte)4]; + } + else + { + viewsIDs = new int[1] { instantiationId }; + } + + object[] incomingInstantiationData; + if (evData.ContainsKey((byte)5)) + { + incomingInstantiationData = (object[])evData[(byte)5]; + } + else + { + incomingInstantiationData = null; + } + + // SetReceiving filtering + if (group != 0 && !this.allowedReceivingGroups.Contains(group)) + { + return null; // Ignore group + } + + if (ObjectPool != null) + { + GameObject go = ObjectPool.Instantiate(prefabName, position, rotation); + + PhotonView[] photonViews = go.GetPhotonViewsInChildren(); + if (photonViews.Length != viewsIDs.Length) + { + throw new Exception("Error in Instantiation! The resource's PhotonView count is not the same as in incoming data."); + } + for (int i = 0; i < photonViews.Length; i++) + { + photonViews[i].didAwake = false; + photonViews[i].viewID = 0; + + photonViews[i].prefix = objLevelPrefix; + photonViews[i].instantiationId = instantiationId; + photonViews[i].isRuntimeInstantiated = true; + photonViews[i].instantiationDataField = incomingInstantiationData; + + photonViews[i].didAwake = true; + photonViews[i].viewID = viewsIDs[i]; // with didAwake true and viewID == 0, this will also register the view + } + + // Send OnPhotonInstantiate callback to newly created GO. + // GO will be enabled when instantiated from Prefab and it does not matter if the script is enabled or disabled. + go.SendMessage(OnPhotonInstantiateString, new PhotonMessageInfo(photonPlayer, serverTime, null), SendMessageOptions.DontRequireReceiver); + return go; + } + else + { + // load prefab, if it wasn't loaded before (calling methods might do this) + if (resourceGameObject == null) + { + if (!NetworkingPeer.UsePrefabCache || !NetworkingPeer.PrefabCache.TryGetValue(prefabName, out resourceGameObject)) + { + resourceGameObject = (GameObject)Resources.Load(prefabName, typeof (GameObject)); + if (NetworkingPeer.UsePrefabCache) + { + NetworkingPeer.PrefabCache.Add(prefabName, resourceGameObject); + } + } + + if (resourceGameObject == null) + { + Debug.LogError("PhotonNetwork error: Could not Instantiate the prefab [" + prefabName + "]. Please verify you have this gameobject in a Resources folder."); + return null; + } + } + + // now modify the loaded "blueprint" object before it becomes a part of the scene (by instantiating it) + PhotonView[] resourcePVs = resourceGameObject.GetPhotonViewsInChildren(); + if (resourcePVs.Length != viewsIDs.Length) + { + throw new Exception("Error in Instantiation! The resource's PhotonView count is not the same as in incoming data."); + } + + for (int i = 0; i < viewsIDs.Length; i++) + { + // NOTE instantiating the loaded resource will keep the viewID but would not copy instantiation data, so it's set below + // so we only set the viewID and instantiationId now. the instantiationData can be fetched + resourcePVs[i].viewID = viewsIDs[i]; + resourcePVs[i].prefix = objLevelPrefix; + resourcePVs[i].instantiationId = instantiationId; + resourcePVs[i].isRuntimeInstantiated = true; + } + + this.StoreInstantiationData(instantiationId, incomingInstantiationData); + + // load the resource and set it's values before instantiating it: + GameObject go = (GameObject)GameObject.Instantiate(resourceGameObject, position, rotation); + + for (int i = 0; i < viewsIDs.Length; i++) + { + // NOTE instantiating the loaded resource will keep the viewID but would not copy instantiation data, so it's set below + // so we only set the viewID and instantiationId now. the instantiationData can be fetched + resourcePVs[i].viewID = 0; + resourcePVs[i].prefix = -1; + resourcePVs[i].prefixBackup = -1; + resourcePVs[i].instantiationId = -1; + resourcePVs[i].isRuntimeInstantiated = false; + } + + this.RemoveInstantiationData(instantiationId); + + // Send OnPhotonInstantiate callback to newly created GO. + // GO will be enabled when instantiated from Prefab and it does not matter if the script is enabled or disabled. + go.SendMessage(OnPhotonInstantiateString, new PhotonMessageInfo(photonPlayer, serverTime, null), SendMessageOptions.DontRequireReceiver); + return go; + } + } + + private Dictionary tempInstantiationData = new Dictionary(); + + private void StoreInstantiationData(int instantiationId, object[] instantiationData) + { + // Debug.Log("StoreInstantiationData() instantiationId: " + instantiationId + " tempInstantiationData.Count: " + tempInstantiationData.Count); + tempInstantiationData[instantiationId] = instantiationData; + } + + public object[] FetchInstantiationData(int instantiationId) + { + object[] data = null; + if (instantiationId == 0) + { + return null; + } + + tempInstantiationData.TryGetValue(instantiationId, out data); + // Debug.Log("FetchInstantiationData() instantiationId: " + instantiationId + " tempInstantiationData.Count: " + tempInstantiationData.Count); + return data; + } + + private void RemoveInstantiationData(int instantiationId) + { + tempInstantiationData.Remove(instantiationId); + } + + + /// + /// Destroys all Instantiates and RPCs locally and (if not localOnly) sends EvDestroy(player) and clears related events in the server buffer. + /// + public void DestroyPlayerObjects(int playerId, bool localOnly) + { + if (playerId <= 0) + { + Debug.LogError("Failed to Destroy objects of playerId: " + playerId); + return; + } + + if (!localOnly) + { + // clean server's Instantiate and RPC buffers + this.OpRemoveFromServerInstantiationsOfPlayer(playerId); + this.OpCleanRpcBuffer(playerId); + + // send Destroy(player) to anyone else + this.SendDestroyOfPlayer(playerId); + } + + // locally cleaning up that player's objects + HashSet playersGameObjects = new HashSet(); + foreach (PhotonView view in this.photonViewList.Values) + { + if (view!=null && view.CreatorActorNr == playerId) + { + playersGameObjects.Add(view.gameObject); + } + } + + // any non-local work is already done, so with the list of that player's objects, we can clean up (locally only) + foreach (GameObject gameObject in playersGameObjects) + { + this.RemoveInstantiatedGO(gameObject, true); + } + + // with ownership transfer, some objects might lose their owner. + // in that case, the creator becomes the owner again. every client can apply this. done below. + foreach (PhotonView view in this.photonViewList.Values) + { + if (view.ownerId == playerId) + { + view.ownerId = view.CreatorActorNr; + //Debug.Log("Creator is: " + view.ownerId); + } + } + } + + public void DestroyAll(bool localOnly) + { + if (!localOnly) + { + this.OpRemoveCompleteCache(); + this.SendDestroyOfAll(); + } + + this.LocalCleanupAnythingInstantiated(true); + } + + /// Removes GameObject and the PhotonViews on it from local lists and optionally updates remotes. GameObject gets destroyed at end. + /// + /// This method might fail and quit early due to several tests. + /// + /// GameObject to cleanup. + /// For localOnly, tests of control are skipped and the server is not updated. + protected internal void RemoveInstantiatedGO(GameObject go, bool localOnly) + { + if (go == null) + { + Debug.LogError("Failed to 'network-remove' GameObject because it's null."); + return; + } + + // Don't remove the GO if it doesn't have any PhotonView + PhotonView[] views = go.GetComponentsInChildren(true); + if (views == null || views.Length <= 0) + { + Debug.LogError("Failed to 'network-remove' GameObject because has no PhotonView components: " + go); + return; + } + + PhotonView viewZero = views[0]; + int creatorId = viewZero.CreatorActorNr; // creatorId of obj is needed to delete EvInstantiate (only if it's from that user) + int instantiationId = viewZero.instantiationId; // actual, live InstantiationIds start with 1 and go up + + // Don't remove GOs that are owned by others (unless this is the master and the remote player left) + if (!localOnly) + { + if (!viewZero.isMine) + { + Debug.LogError("Failed to 'network-remove' GameObject. Client is neither owner nor masterClient taking over for owner who left: " + viewZero); + return; + } + + // Don't remove the Instantiation from the server, if it doesn't have a proper ID + if (instantiationId < 1) + { + Debug.LogError("Failed to 'network-remove' GameObject because it is missing a valid InstantiationId on view: " + viewZero + ". Not Destroying GameObject or PhotonViews!"); + return; + } + } + + + // cleanup instantiation (event and local list) + if (!localOnly) + { + this.ServerCleanInstantiateAndDestroy(instantiationId, creatorId, viewZero.isRuntimeInstantiated); // server cleaning + } + + + // cleanup PhotonViews and their RPCs events (if not localOnly) + for (int j = views.Length - 1; j >= 0; j--) + { + PhotonView view = views[j]; + if (view == null) + { + continue; + } + + // we only destroy/clean PhotonViews that were created by PhotonNetwork.Instantiate (and those have an instantiationId!) + if (view.instantiationId >= 1) + { + this.LocalCleanPhotonView(view); + } + if (!localOnly) + { + this.OpCleanRpcBuffer(view); + } + } + + if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) + { + Debug.Log("Network destroy Instantiated GO: " + go.name); + } + + + if (this.ObjectPool != null) + { + PhotonView[] photonViews = go.GetPhotonViewsInChildren(); + for (int i = 0; i < photonViews.Length; i++) + { + photonViews[i].viewID = 0; // marks the PV as not being in use currently. + } + this.ObjectPool.Destroy(go); + } + else + { + GameObject.Destroy(go); + } + } + + /// + /// Removes an instantiation event from the server's cache. Needs id and actorNr of player who instantiated. + /// + private void ServerCleanInstantiateAndDestroy(int instantiateId, int creatorId, bool isRuntimeInstantiated) + { + Hashtable removeFilter = new Hashtable(); + removeFilter[(byte)7] = instantiateId; + + RaiseEventOptions options = new RaiseEventOptions() { CachingOption = EventCaching.RemoveFromRoomCache, TargetActors = new int[] { creatorId } }; + this.OpRaiseEvent(PunEvent.Instantiation, removeFilter, true, options); + //this.OpRaiseEvent(PunEvent.Instantiation, removeFilter, true, 0, new int[] { actorNr }, EventCaching.RemoveFromRoomCache); + + Hashtable evData = new Hashtable(); + evData[(byte)0] = instantiateId; + options = null; + if (!isRuntimeInstantiated) + { + // if the view got loaded with the scene, the EvDestroy must be cached (there is no Instantiate-msg which we can remove) + // reason: joining players will load the obj and have to destroy it (too) + options = new RaiseEventOptions(); + options.CachingOption = EventCaching.AddToRoomCacheGlobal; + Debug.Log("Destroying GO as global. ID: " + instantiateId); + } + this.OpRaiseEvent(PunEvent.Destroy, evData, true, options); + } + + private void SendDestroyOfPlayer(int actorNr) + { + Hashtable evData = new Hashtable(); + evData[(byte)0] = actorNr; + + this.OpRaiseEvent(PunEvent.DestroyPlayer, evData, true, null); + //this.OpRaiseEvent(PunEvent.DestroyPlayer, evData, true, 0, EventCaching.DoNotCache, ReceiverGroup.Others); + } + + private void SendDestroyOfAll() + { + Hashtable evData = new Hashtable(); + evData[(byte)0] = -1; + + + this.OpRaiseEvent(PunEvent.DestroyPlayer, evData, true, null); + //this.OpRaiseEvent(PunEvent.DestroyPlayer, evData, true, 0, EventCaching.DoNotCache, ReceiverGroup.Others); + } + + private void OpRemoveFromServerInstantiationsOfPlayer(int actorNr) + { + // removes all "Instantiation" events of player actorNr. this is not an event for anyone else + RaiseEventOptions options = new RaiseEventOptions() { CachingOption = EventCaching.RemoveFromRoomCache, TargetActors = new int[] { actorNr } }; + this.OpRaiseEvent(PunEvent.Instantiation, null, true, options); + //this.OpRaiseEvent(PunEvent.Instantiation, null, true, 0, new int[] { actorNr }, EventCaching.RemoveFromRoomCache); + } + + internal protected void RequestOwnership(int viewID, int fromOwner) + { + Debug.Log("RequestOwnership(): " + viewID + " from: " + fromOwner + " Time: " + Environment.TickCount % 1000); + //PhotonNetwork.networkingPeer.OpRaiseEvent(PunEvent.OwnershipRequest, true, new int[] { viewID, fromOwner }, 0, EventCaching.DoNotCache, null, ReceiverGroup.All, 0); + this.OpRaiseEvent(PunEvent.OwnershipRequest, new int[] {viewID, fromOwner}, true, new RaiseEventOptions() { Receivers = ReceiverGroup.All }); // All sends to all via server (including self) + } + + internal protected void TransferOwnership(int viewID, int playerID) + { + Debug.Log("TransferOwnership() view " + viewID + " to: " + playerID + " Time: " + Environment.TickCount % 1000); + //PhotonNetwork.networkingPeer.OpRaiseEvent(PunEvent.OwnershipTransfer, true, new int[] {viewID, playerID}, 0, EventCaching.DoNotCache, null, ReceiverGroup.All, 0); + this.OpRaiseEvent(PunEvent.OwnershipTransfer, new int[] { viewID, playerID }, true, new RaiseEventOptions() { Receivers = ReceiverGroup.All }); // All sends to all via server (including self) + } + + public bool LocalCleanPhotonView(PhotonView view) + { + view.removedFromLocalViewList = true; + return this.photonViewList.Remove(view.viewID); + } + + public PhotonView GetPhotonView(int viewID) + { + PhotonView result = null; + this.photonViewList.TryGetValue(viewID, out result); + + if (result == null) + { + PhotonView[] views = GameObject.FindObjectsOfType(typeof(PhotonView)) as PhotonView[]; + + for (int i = 0; i < views.Length; i++) + { + PhotonView view = views[i]; + if (view.viewID == viewID) + { + if (view.didAwake) + { + Debug.LogWarning("Had to lookup view that wasn't in photonViewList: " + view); + } + return view; + } + } + } + + return result; + } + + public void RegisterPhotonView(PhotonView netView) + { + if (!Application.isPlaying) + { + this.photonViewList = new Dictionary(); + return; + } + + if (netView.viewID == 0) + { + // don't register views with ID 0 (not initialized). they register when a ID is assigned later on + Debug.Log("PhotonView register is ignored, because viewID is 0. No id assigned yet to: " + netView); + return; + } + + PhotonView listedView = null; + bool isViewListed = this.photonViewList.TryGetValue(netView.viewID, out listedView); + if (isViewListed) + { + // if some other view is in the list already, we got a problem. it might be undestructible. print out error + if (netView != listedView) + { + Debug.LogError(string.Format("PhotonView ID duplicate found: {0}. New: {1} old: {2}. Maybe one wasn't destroyed on scene load?! Check for 'DontDestroyOnLoad'. Destroying old entry, adding new.", netView.viewID, netView, listedView)); + } + else + { + return; + } + + this.RemoveInstantiatedGO(listedView.gameObject, true); + } + + // Debug.Log("adding view to known list: " + netView); + this.photonViewList.Add(netView.viewID, netView); + //Debug.LogError("view being added. " + netView); // Exit Games internal log + + if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) + { + Debug.Log("Registered PhotonView: " + netView.viewID); + } + } + + ///// + ///// Will remove the view from list of views (by its ID). + ///// + //public void RemovePhotonView(PhotonView netView) + //{ + // if (!Application.isPlaying) + // { + // this.photonViewList = new Dictionary(); + // return; + // } + + // //PhotonView removedView = null; + // //this.photonViewList.TryGetValue(netView.viewID, out removedView); + // //if (removedView != netView) + // //{ + // // Debug.LogError("Detected two differing PhotonViews with same viewID: " + netView.viewID); + // //} + + // this.photonViewList.Remove(netView.viewID); + + // //if (this.DebugOut >= DebugLevel.ALL) + // //{ + // // this.DebugReturn(DebugLevel.ALL, "Removed PhotonView: " + netView.viewID); + // //} + //} + + /// + /// Removes the RPCs of someone else (to be used as master). + /// This won't clean any local caches. It just tells the server to forget a player's RPCs and instantiates. + /// + /// + public void OpCleanRpcBuffer(int actorNumber) + { + RaiseEventOptions options = new RaiseEventOptions() { CachingOption = EventCaching.RemoveFromRoomCache, TargetActors = new int[] { actorNumber } }; + this.OpRaiseEvent(PunEvent.RPC, null, true, options); + //this.OpRaiseEvent(PunEvent.RPC, null, true, 0, new int[] { actorNumber }, EventCaching.RemoveFromRoomCache); + } + + /// + /// Instead removing RPCs or Instantiates, this removed everything cached by the actor. + /// + /// + public void OpRemoveCompleteCacheOfPlayer(int actorNumber) + { + RaiseEventOptions options = new RaiseEventOptions() { CachingOption = EventCaching.RemoveFromRoomCache, TargetActors = new int[] { actorNumber } }; + this.OpRaiseEvent(0, null, true, options); + //this.OpRaiseEvent(0, null, true, 0, new int[] { actorNumber }, EventCaching.RemoveFromRoomCache); + } + + + public void OpRemoveCompleteCache() + { + RaiseEventOptions options = new RaiseEventOptions() { CachingOption = EventCaching.RemoveFromRoomCache, Receivers = ReceiverGroup.MasterClient }; + this.OpRaiseEvent(0, null, true, options); + //this.OpRaiseEvent(0, null, true, 0, EventCaching.RemoveFromRoomCache, ReceiverGroup.MasterClient); // TODO: check who gets this event? + } + + /// This clears the cache of any player/actor who's no longer in the room (making it a simple clean-up option for a new master) + private void RemoveCacheOfLeftPlayers() + { + Dictionary opParameters = new Dictionary(); + opParameters[ParameterCode.Code] = (byte)0; // any event + opParameters[ParameterCode.Cache] = (byte)EventCaching.RemoveFromRoomCacheForActorsLeft; // option to clear the room cache of all events of players who left + + this.OpCustom((byte)OperationCode.RaiseEvent, opParameters, true, 0); + } + + // Remove RPCs of view (if they are local player's RPCs) + public void CleanRpcBufferIfMine(PhotonView view) + { + if (view.ownerId != this.LocalPlayer.ID && !LocalPlayer.IsMasterClient) + { + Debug.LogError("Cannot remove cached RPCs on a PhotonView thats not ours! " + view.owner + " scene: " + view.isSceneView); + return; + } + + this.OpCleanRpcBuffer(view); + } + + /// Cleans server RPCs for PhotonView (without any further checks). + public void OpCleanRpcBuffer(PhotonView view) + { + Hashtable rpcFilterByViewId = new Hashtable(); + rpcFilterByViewId[(byte)0] = view.viewID; + + RaiseEventOptions options = new RaiseEventOptions() { CachingOption = EventCaching.RemoveFromRoomCache }; + this.OpRaiseEvent(PunEvent.RPC, rpcFilterByViewId, true, options); + //this.OpRaiseEvent(PunEvent.RPC, rpcFilterByViewId, true, 0, EventCaching.RemoveFromRoomCache, ReceiverGroup.Others); + } + + public void RemoveRPCsInGroup(int group) + { + foreach (PhotonView view in this.photonViewList.Values) + { + if (view.group == group) + { + this.CleanRpcBufferIfMine(view); + } + } + } + + public void SetLevelPrefix(short prefix) + { + this.currentLevelPrefix = prefix; + // TODO: should we really change the prefix for existing PVs?! better keep it! + //foreach (PhotonView view in this.photonViewList.Values) + //{ + // view.prefix = prefix; + //} + } + + + /// RPC Hashtable Structure + /// (byte)0 -> (int) ViewId (combined from actorNr and actor-unique-id) + /// (byte)1 -> (short) prefix (level) + /// (byte)2 -> (int) server timestamp + /// (byte)3 -> (string) methodname + /// (byte)4 -> (object[]) parameters + /// (byte)5 -> (byte) method shortcut (alternative to name) + /// + /// This is sent as event (code: 200) which will contain a sender (origin of this RPC). + + internal void RPC(PhotonView view, string methodName, PhotonTargets target, PhotonPlayer player, bool encrypt, params object[] parameters) + { + if (this.blockSendingGroups.Contains(view.group)) + { + return; // Block sending on this group + } + + if (view.viewID < 1) + { + Debug.LogError("Illegal view ID:" + view.viewID + " method: " + methodName + " GO:" + view.gameObject.name); + } + + if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) + { + Debug.Log("Sending RPC \"" + methodName + "\" to target: " + target + " or player:" + player + "."); + } + + + //ts: changed RPCs to a one-level hashtable as described in internal.txt + Hashtable rpcEvent = new Hashtable(); + rpcEvent[(byte)0] = (int)view.viewID; // LIMITS NETWORKVIEWS&PLAYERS + if (view.prefix > 0) + { + rpcEvent[(byte)1] = (short)view.prefix; + } + rpcEvent[(byte)2] = PhotonNetwork.ServerTimestamp; + + + // send name or shortcut (if available) + int shortcut = 0; + if (rpcShortcuts.TryGetValue(methodName, out shortcut)) + { + rpcEvent[(byte)5] = (byte)shortcut; // LIMITS RPC COUNT + } + else + { + rpcEvent[(byte)3] = methodName; + } + + if (parameters != null && parameters.Length > 0) + { + rpcEvent[(byte)4] = (object[])parameters; + } + + + // if sent to target player, this overrides the target + if (player != null) + { + if (this.LocalPlayer.ID == player.ID) + { + this.ExecuteRpc(rpcEvent, player.ID); + } + else + { + RaiseEventOptions options = new RaiseEventOptions() { TargetActors = new int[] { player.ID }, Encrypt = encrypt }; + this.OpRaiseEvent(PunEvent.RPC, rpcEvent, true, options); + } + + return; + } + + // send to a specific set of players + if (target == PhotonTargets.All) + { + RaiseEventOptions options = new RaiseEventOptions() { InterestGroup = (byte)view.group, Encrypt = encrypt }; + this.OpRaiseEvent(PunEvent.RPC, rpcEvent, true, options); + + // Execute local + this.ExecuteRpc(rpcEvent, this.LocalPlayer.ID); + } + else if (target == PhotonTargets.Others) + { + RaiseEventOptions options = new RaiseEventOptions() { InterestGroup = (byte)view.group, Encrypt = encrypt }; + this.OpRaiseEvent(PunEvent.RPC, rpcEvent, true, options); + } + else if (target == PhotonTargets.AllBuffered) + { + RaiseEventOptions options = new RaiseEventOptions() { CachingOption = EventCaching.AddToRoomCache, Encrypt = encrypt }; + this.OpRaiseEvent(PunEvent.RPC, rpcEvent, true, options); + + // Execute local + this.ExecuteRpc(rpcEvent, this.LocalPlayer.ID); + } + else if (target == PhotonTargets.OthersBuffered) + { + RaiseEventOptions options = new RaiseEventOptions() { CachingOption = EventCaching.AddToRoomCache, Encrypt = encrypt }; + this.OpRaiseEvent(PunEvent.RPC, rpcEvent, true, options); + } + else if (target == PhotonTargets.MasterClient) + { + if (this.mMasterClientId == this.LocalPlayer.ID) + { + this.ExecuteRpc(rpcEvent, this.LocalPlayer.ID); + } + else + { + RaiseEventOptions options = new RaiseEventOptions() { Receivers = ReceiverGroup.MasterClient, Encrypt = encrypt }; + this.OpRaiseEvent(PunEvent.RPC, rpcEvent, true, options); + } + } + else if (target == PhotonTargets.AllViaServer) + { + RaiseEventOptions options = new RaiseEventOptions() { InterestGroup = (byte)view.group, Receivers = ReceiverGroup.All, Encrypt = encrypt }; + this.OpRaiseEvent(PunEvent.RPC, rpcEvent, true, options); + if (PhotonNetwork.offlineMode) + { + this.ExecuteRpc(rpcEvent, this.LocalPlayer.ID); + } + } + else if (target == PhotonTargets.AllBufferedViaServer) + { + RaiseEventOptions options = new RaiseEventOptions() { InterestGroup = (byte)view.group, Receivers = ReceiverGroup.All, CachingOption = EventCaching.AddToRoomCache, Encrypt = encrypt }; + this.OpRaiseEvent(PunEvent.RPC, rpcEvent, true, options); + if (PhotonNetwork.offlineMode) + { + this.ExecuteRpc(rpcEvent, this.LocalPlayer.ID); + } + } + else + { + Debug.LogError("Unsupported target enum: " + target); + } + } + + + public void SetInterestGroups(byte[] disableGroups, byte[] enableGroups) + { + if (disableGroups != null) + { + if (disableGroups.Length == 0) + { + // a byte[0] should disable ALL groups in one step and before any groups are enabled. we do this locally, too. + this.allowedReceivingGroups.Clear(); + } + else + { + for (int index = 0; index < disableGroups.Length; index++) + { + byte g = disableGroups[index]; + if (g <= 0) + { + Debug.LogError("Error: PhotonNetwork.SetInterestGroups was called with an illegal group number: " + g + ". The group number should be at least 1."); + continue; + } + + if (this.allowedReceivingGroups.Contains(g)) + { + this.allowedReceivingGroups.Remove(g); + } + } + } + } + + if (enableGroups != null) + { + if (enableGroups.Length == 0) + { + // a byte[0] should enable ALL groups in one step. we do this locally, too. + for (byte index = 0; index < byte.MaxValue; index++) + { + this.allowedReceivingGroups.Add(index); + } + + // add this group separately to avoid an overflow exception in the previous loop + this.allowedReceivingGroups.Add(byte.MaxValue); + } + else + { + for (int index = 0; index < enableGroups.Length; index++) + { + byte g = enableGroups[index]; + if (g <= 0) + { + Debug.LogError("Error: PhotonNetwork.SetInterestGroups was called with an illegal group number: " + g + ". The group number should be at least 1."); + continue; + } + + this.allowedReceivingGroups.Add(g); + } + } + } + + this.OpChangeGroups(disableGroups, enableGroups); + } + + + // SetSending + public void SetSendingEnabled(byte group, bool enabled) + { + if (!enabled) + { + this.blockSendingGroups.Add(group); // can be added to HashSet no matter if already in it + } + else + { + this.blockSendingGroups.Remove(group); + } + } + + + public void SetSendingEnabled(byte[] disableGroups, byte[] enableGroups) + { + if (disableGroups != null) + { + for (int index = 0; index < disableGroups.Length; index++) + { + byte g = disableGroups[index]; + this.blockSendingGroups.Add(g); + } + } + + if (enableGroups != null) + { + for (int index = 0; index < enableGroups.Length; index++) + { + byte g = enableGroups[index]; + this.blockSendingGroups.Remove(g); + } + } + } + + + public void NewSceneLoaded() + { + if (this.loadingLevelAndPausedNetwork) + { + this.loadingLevelAndPausedNetwork = false; + PhotonNetwork.isMessageQueueRunning = true; + } + // Debug.Log("OnLevelWasLoaded photonViewList.Count: " + photonViewList.Count); // Exit Games internal log + + List removeKeys = new List(); + foreach (KeyValuePair kvp in this.photonViewList) + { + PhotonView view = kvp.Value; + if (view == null) + { + removeKeys.Add(kvp.Key); + } + } + + for (int index = 0; index < removeKeys.Count; index++) + { + int key = removeKeys[index]; + this.photonViewList.Remove(key); + } + + if (removeKeys.Count > 0) + { + if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + Debug.Log("New level loaded. Removed " + removeKeys.Count + " scene view IDs from last level."); + } + } + + /// + /// Defines how many OnPhotonSerialize()-calls might get summarized in one message. + /// + /// + /// A low number increases overhead, a high number might mean fragmentation. + /// + public static int ObjectsInOneUpdate = 10; + + // cache the RaiseEventOptions to prevent redundant Memory Allocation + RaiseEventOptions options = new RaiseEventOptions(); + + // this is called by Update() and in Unity that means it's single threaded. + public void RunViewUpdate() + { + if (!PhotonNetwork.connected || PhotonNetwork.offlineMode || this.mActors == null) + { + return; + } + + // no need to send OnSerialize messages while being alone (these are not buffered anyway) + if (this.mActors.Count <= 1) + { + #if !PHOTON_DEVELOP + return; + #endif + } + + + /* Format of the data hashtable: + * Hasthable dataPergroup* + * [(byte)0] = PhotonNetwork.ServerTimestamp; + * [(byte)1] = currentLevelPrefix; OPTIONAL! + * + * [(byte)10] = data 1 + * [(byte)11] = data 2 ... + * + * We only combine updates for XY objects into one RaiseEvent to avoid fragmentation + */ + + int countOfUpdatesToSend = 0; + + // reset cached raisedEventOptions; + // we got updates to send. every group is send it's own message and unreliable and reliable are split as well + options.Reset(); + + #if PHOTON_DEVELOP + options.Receivers = ReceiverGroup.All; + #endif + + List toRemove = null; + + var enumerator = this.photonViewList.GetEnumerator(); // replacing foreach (PhotonView view in this.photonViewList.Values) for memory allocation improvement + while (enumerator.MoveNext()) + { + PhotonView view = enumerator.Current.Value; + + if (view == null) + { + Debug.LogError(string.Format("PhotonView with ID {0} wasn't properly unregistered! Please report this case to developer@photonengine.com", enumerator.Current.Key)); + + if (toRemove == null) + { + toRemove = new List(4); + } + toRemove.Add(enumerator.Current.Key); + + continue; + } + + // a client only sends updates for active, synchronized PhotonViews that are under it's control (isMine) + if (view.synchronization == ViewSynchronization.Off || view.isMine == false || view.gameObject.activeInHierarchy == false) + { + continue; + } + + if (this.blockSendingGroups.Contains(view.group)) + { + continue; // Block sending on this group + } + + + // call the PhotonView's serialize method(s) + object[] evData = this.OnSerializeWrite(view); + if (evData == null) + { + continue; + } + + if (view.synchronization == ViewSynchronization.ReliableDeltaCompressed || view.mixedModeIsReliable) + { + Hashtable groupHashtable = null; + bool found = this.dataPerGroupReliable.TryGetValue(view.group, out groupHashtable); + if (!found) + { + groupHashtable = new Hashtable(NetworkingPeer.ObjectsInOneUpdate); + this.dataPerGroupReliable[view.group] = groupHashtable; + } + + groupHashtable.Add((byte)(groupHashtable.Count+10), evData); + countOfUpdatesToSend++; + + // if any group has XY elements, we should send it right away (to avoid bigger messages which need fragmentation and reliable transfer). + if (groupHashtable.Count >= NetworkingPeer.ObjectsInOneUpdate) + { + countOfUpdatesToSend -= groupHashtable.Count; + + options.InterestGroup = (byte)view.group; + groupHashtable[(byte)0] = PhotonNetwork.ServerTimestamp; + if (this.currentLevelPrefix >= 0) + { + groupHashtable[(byte)1] = this.currentLevelPrefix; + } + + this.OpRaiseEvent(PunEvent.SendSerializeReliable, groupHashtable, true, options); + //Debug.Log("SendSerializeReliable (10) " + PhotonNetwork.networkingPeer.ByteCountLastOperation); + groupHashtable.Clear(); + } + } + else + { + Hashtable groupHashtable = null; + bool found = this.dataPerGroupUnreliable.TryGetValue(view.group, out groupHashtable); + if (!found) + { + groupHashtable = new Hashtable(NetworkingPeer.ObjectsInOneUpdate); + this.dataPerGroupUnreliable[view.group] = groupHashtable; + } + + groupHashtable.Add((byte)(groupHashtable.Count+10), evData); + countOfUpdatesToSend++; + + // if any group has XY elements, we should send it right away (to avoid bigger messages which need fragmentation and reliable transfer). + if (groupHashtable.Count >= NetworkingPeer.ObjectsInOneUpdate) + { + countOfUpdatesToSend -= groupHashtable.Count; + + options.InterestGroup = (byte)view.group; + groupHashtable[(byte)0] = PhotonNetwork.ServerTimestamp; + if (this.currentLevelPrefix >= 0) + { + groupHashtable[(byte)1] = this.currentLevelPrefix; + } + + this.OpRaiseEvent(PunEvent.SendSerialize, groupHashtable, false, options); + groupHashtable.Clear(); + //Debug.Log("SendSerializeUnreliable (10) " + PhotonNetwork.networkingPeer.ByteCountLastOperation); + } + } + } // all views serialized + + if (toRemove != null) + { + for (int idx = 0, count = toRemove.Count; idx < count; ++idx) + { + this.photonViewList.Remove(toRemove[idx]); + } + } + + // if we didn't produce anything to send, don't do it + if (countOfUpdatesToSend == 0) + { + return; + } + + + foreach (int groupId in this.dataPerGroupReliable.Keys) + { + options.InterestGroup = (byte)groupId; + Hashtable groupHashtable = this.dataPerGroupReliable[groupId]; + if (groupHashtable.Count == 0) + { + continue; + } + + groupHashtable[(byte)0] = PhotonNetwork.ServerTimestamp; + if (this.currentLevelPrefix >= 0) + { + groupHashtable[(byte)1] = this.currentLevelPrefix; + } + + this.OpRaiseEvent(PunEvent.SendSerializeReliable, groupHashtable, true, options); + groupHashtable.Clear(); + } + foreach (int groupId in this.dataPerGroupUnreliable.Keys) + { + options.InterestGroup = (byte)groupId; + Hashtable groupHashtable = this.dataPerGroupUnreliable[groupId]; + if (groupHashtable.Count == 0) + { + continue; + } + + groupHashtable[(byte)0] = PhotonNetwork.ServerTimestamp; + if (this.currentLevelPrefix >= 0) + { + groupHashtable[(byte)1] = this.currentLevelPrefix; + } + + this.OpRaiseEvent(PunEvent.SendSerialize, groupHashtable, false, options); + groupHashtable.Clear(); + } + } + + + // calls OnPhotonSerializeView (through ExecuteOnSerialize) + // the content created here is consumed by receivers in: ReadOnSerialize + private object[] OnSerializeWrite(PhotonView view) + { + if (view.synchronization == ViewSynchronization.Off) + { + return null; + } + + + // each view creates a list of values that should be sent + PhotonMessageInfo info = new PhotonMessageInfo(this.LocalPlayer, PhotonNetwork.ServerTimestamp, view); + this.pStream.ResetWriteStream(); + this.pStream.SendNext(null); + this.pStream.SendNext(null); + this.pStream.SendNext(null); + view.SerializeView(this.pStream, info); + + // check if there are actual values to be sent (after the "header" of viewId, (bool)compressed and (int[])nullValues) + if (this.pStream.Count <= SyncFirstValue) + { + return null; + } + + + object[] currentValues = this.pStream.ToArray(); + currentValues[0] = view.viewID; + currentValues[1] = false; + currentValues[2] = null; + + if (view.synchronization == ViewSynchronization.Unreliable) + { + return currentValues; + } + + + // ViewSynchronization: Off, Unreliable, UnreliableOnChange, ReliableDeltaCompressed + if (view.synchronization == ViewSynchronization.UnreliableOnChange) + { + if (AlmostEquals(currentValues, view.lastOnSerializeDataSent)) + { + if (view.mixedModeIsReliable) + { + return null; + } + + view.mixedModeIsReliable = true; + view.lastOnSerializeDataSent = currentValues; + } + else + { + view.mixedModeIsReliable = false; + view.lastOnSerializeDataSent = currentValues; + } + + return currentValues; + } + + if (view.synchronization == ViewSynchronization.ReliableDeltaCompressed) + { + // compress content of data set (by comparing to view.lastOnSerializeDataSent) + // the "original" dataArray is NOT modified by DeltaCompressionWrite + object[] dataToSend = this.DeltaCompressionWrite(view.lastOnSerializeDataSent, currentValues); + + // cache the values that were written this time (not the compressed values) + view.lastOnSerializeDataSent = currentValues; + + return dataToSend; + } + + return null; + } + + /// + /// Reads updates created by OnSerializeWrite + /// + private void OnSerializeRead(object[] data, PhotonPlayer sender, int networkTime, short correctPrefix) + { + // read view ID from key (byte)0: a int-array (PUN 1.17++) + int viewID = (int)data[SyncViewId]; + + + // debug: + //LogObjectArray(data); + + PhotonView view = this.GetPhotonView(viewID); + if (view == null) + { + Debug.LogWarning("Received OnSerialization for view ID " + viewID + ". We have no such PhotonView! Ignored this if you're leaving a room. State: " + this.State); + return; + } + + if (view.prefix > 0 && correctPrefix != view.prefix) + { + Debug.LogError("Received OnSerialization for view ID " + viewID + " with prefix " + correctPrefix + ". Our prefix is " + view.prefix); + return; + } + + // SetReceiving filtering + if (view.group != 0 && !this.allowedReceivingGroups.Contains(view.group)) + { + return; // Ignore group + } + + + + + if (view.synchronization == ViewSynchronization.ReliableDeltaCompressed) + { + object[] uncompressed = this.DeltaCompressionRead(view.lastOnSerializeDataReceived, data); + //LogObjectArray(uncompressed,"uncompressed "); + if (uncompressed == null) + { + // Skip this packet as we haven't got received complete-copy of this view yet. + if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + { + Debug.Log("Skipping packet for " + view.name + " [" + view.viewID + "] as we haven't received a full packet for delta compression yet. This is OK if it happens for the first few frames after joining a game."); + } + return; + } + + // store last received values (uncompressed) for delta-compression usage + view.lastOnSerializeDataReceived = uncompressed; + data = uncompressed; + } + + // This is when joining late to assign ownership to the sender + // this has nothing to do with reading the actual synchronization update. + // We don't do anything is OwnerShip Was Touched, which means we got the infos already. We only possibly act if ownership was never transfered. + // We do override OwnerShipWasTransfered if owner is the masterClient. + if (sender.ID != view.ownerId && (!view.OwnerShipWasTransfered || view.ownerId == 0) && view.currentMasterID == -1 ) + { + // obviously the owner changed and we didn't yet notice. + //Debug.Log("Adjusting owner to sender of updates. From: " + view.ownerId + " to: " + sender.ID); + view.ownerId = sender.ID; + } + + this.readStream.SetReadStream(data, 3); + PhotonMessageInfo info = new PhotonMessageInfo(sender, networkTime, view); + + view.DeserializeView(this.readStream, info); + } + + + // compresses currentContent by using NULL as value if currentContent equals previousContent + // skips initial indexes, as defined by SyncFirstValue + // to conserve memory, the previousContent is re-used as buffer for the result! duplicate the values before using this, if needed + // returns null, if nothing must be sent (current content might be null, which also returns null) + // SyncFirstValue should be the index of the first actual data-value (3 in PUN's case, as 0=viewId, 1=(bool)compressed, 2=(int[])values that are now null) + public const int SyncViewId = 0; + public const int SyncCompressed = 1; + public const int SyncNullValues = 2; + public const int SyncFirstValue = 3; + + private object[] DeltaCompressionWrite(object[] previousContent, object[] currentContent) + { + if (currentContent == null || previousContent == null || previousContent.Length != currentContent.Length) + { + return currentContent; // the current data needs to be sent (which might be null) + } + + if (currentContent.Length <= SyncFirstValue) + { + return null; // this send doesn't contain values (except the "headers"), so it's not being sent + } + + + object[] compressedContent = previousContent; // the previous content is no longer needed, once we compared the values! + compressedContent[SyncCompressed] = false; + int compressedValues = 0; + + Queue valuesThatAreChangedToNull = null; + for (int index = SyncFirstValue; index < currentContent.Length; index++) + { + object newObj = currentContent[index]; + object oldObj = previousContent[index]; + if (this.AlmostEquals(newObj, oldObj)) + { + // compress (by using null, instead of value, which is same as before) + compressedValues++; + compressedContent[index] = null; + } + else + { + compressedContent[index] = newObj; + + // value changed, we don't replace it with null + // new value is null (like a compressed value): we have to mark it so it STAYS null instead of being replaced with previous value + if (newObj == null) + { + if (valuesThatAreChangedToNull == null) + { + valuesThatAreChangedToNull = new Queue(currentContent.Length); + } + valuesThatAreChangedToNull.Enqueue(index); + } + } + } + + // Only send the list of compressed fields if we actually compressed 1 or more fields. + if (compressedValues > 0) + { + if (compressedValues == currentContent.Length - SyncFirstValue) + { + // all values are compressed to null, we have nothing to send + return null; + } + + compressedContent[SyncCompressed] = true; + if (valuesThatAreChangedToNull != null) + { + compressedContent[SyncNullValues] = valuesThatAreChangedToNull.ToArray(); // data that is actually null (not just cause we didn't want to send it) + } + } + + compressedContent[SyncViewId] = currentContent[SyncViewId]; + return compressedContent; // some data was compressed but we need to send something + } + + private object[] DeltaCompressionRead(object[] lastOnSerializeDataReceived, object[] incomingData) + { + if ((bool)incomingData[SyncCompressed] == false) + { + // index 1 marks "compressed" as being true. + return incomingData; + } + + // Compression was applied (as data[1] == true) + // we need a previous "full" list of values to restore values that are null in this msg. else, ignore this + if (lastOnSerializeDataReceived == null) + { + return null; + } + + + int[] indexesThatAreChangedToNull = incomingData[(byte)2] as int[]; + for (int index = SyncFirstValue; index < incomingData.Length; index++) + { + if (indexesThatAreChangedToNull != null && indexesThatAreChangedToNull.Contains(index)) + { + continue; // if a value was set to null in this update, we don't need to fetch it from an earlier update + } + if (incomingData[index] == null) + { + // we replace null values in this received msg unless a index is in the "changed to null" list + object lastValue = lastOnSerializeDataReceived[index]; + incomingData[index] = lastValue; + } + } + + return incomingData; + } + + + // startIndex should be the index of the first actual data-value (3 in PUN's case, as 0=viewId, 1=(bool)compressed, 2=(int[])values that are now null) + // returns the incomingData with modified content. any object being null (means: value unchanged) gets replaced with a previously sent value. incomingData is being modified + + + private bool AlmostEquals(object[] lastData, object[] currentContent) + { + if (lastData == null && currentContent == null) + { + return true; + } + + if (lastData == null || currentContent == null || (lastData.Length != currentContent.Length)) + { + return false; + } + + for (int index = 0; index < currentContent.Length; index++) + { + object newObj = currentContent[index]; + object oldObj = lastData[index]; + if (!this.AlmostEquals(newObj, oldObj)) + { + return false; + } + } + + return true; + } + + /// + /// Returns true if both objects are almost identical. + /// Used to check whether two objects are similar enough to skip an update. + /// + bool AlmostEquals(object one, object two) + { + if (one == null || two == null) + { + return one == null && two == null; + } + + if (!one.Equals(two)) + { + // if A is not B, lets check if A is almost B + if (one is Vector3) + { + Vector3 a = (Vector3)one; + Vector3 b = (Vector3)two; + if (a.AlmostEquals(b, PhotonNetwork.precisionForVectorSynchronization)) + { + return true; + } + } + else if (one is Vector2) + { + Vector2 a = (Vector2)one; + Vector2 b = (Vector2)two; + if (a.AlmostEquals(b, PhotonNetwork.precisionForVectorSynchronization)) + { + return true; + } + } + else if (one is Quaternion) + { + Quaternion a = (Quaternion)one; + Quaternion b = (Quaternion)two; + if (a.AlmostEquals(b, PhotonNetwork.precisionForQuaternionSynchronization)) + { + return true; + } + } + else if (one is float) + { + float a = (float)one; + float b = (float)two; + if (a.AlmostEquals(b, PhotonNetwork.precisionForFloatSynchronization)) + { + return true; + } + } + + // one does not equal two + return false; + } + + return true; + } + + internal protected static bool GetMethod(MonoBehaviour monob, string methodType, out MethodInfo mi) + { + mi = null; + + if (monob == null || string.IsNullOrEmpty(methodType)) + { + return false; + } + + List methods = SupportClassPun.GetMethods(monob.GetType(), null); + for (int index = 0; index < methods.Count; index++) + { + MethodInfo methodInfo = methods[index]; + if (methodInfo.Name.Equals(methodType)) + { + mi = methodInfo; + return true; + } + } + + return false; + } + + + + + /// Internally used to detect the current scene and load it if PhotonNetwork.automaticallySyncScene is enabled. + internal protected void LoadLevelIfSynced() + { + if (!PhotonNetwork.automaticallySyncScene || PhotonNetwork.isMasterClient || PhotonNetwork.room == null) + { + return; + } + + // we only check if scene is not loading in the background. + if (_AsyncLevelLoadingOperation != null) { + if (_AsyncLevelLoadingOperation.isDone) + { + _AsyncLevelLoadingOperation = null; + }else{ + return; + } + } + + // check if "current level" is set in props + if (!PhotonNetwork.room.CustomProperties.ContainsKey(NetworkingPeer.CurrentSceneProperty)) + { + return; + } + + // check if we are loading asynchronously + bool LoadAsync = PhotonNetwork.room.CustomProperties.ContainsKey (NetworkingPeer.CurrentScenePropertyLoadAsync); + + // if loaded level is not the one defined my master in props, load that level + object sceneId = PhotonNetwork.room.CustomProperties[NetworkingPeer.CurrentSceneProperty]; + if (sceneId is int) + { + if (SceneManagerHelper.ActiveSceneBuildIndex != (int)sceneId) + { + if (LoadAsync) + { + PhotonNetwork.LoadLevelAsync((int)sceneId); + }else{ + PhotonNetwork.LoadLevel((int)sceneId); + } + } + } + else if (sceneId is string) + { + if (SceneManagerHelper.ActiveSceneName != (string)sceneId) + { + if (LoadAsync) + { + PhotonNetwork.LoadLevelAsync((string)sceneId); + }else{ + PhotonNetwork.LoadLevel((string)sceneId); + } + } + } + } + + protected internal void SetLevelInPropsIfSynced(object levelId, bool asyncLoading = false) + { + if (!PhotonNetwork.automaticallySyncScene || !PhotonNetwork.isMasterClient || PhotonNetwork.room == null) + { + return; + } + if (levelId == null) + { + Debug.LogError("Parameter levelId can't be null!"); + return; + } + + // check if "current level" is already set in props + if (!asyncLoading && PhotonNetwork.room.CustomProperties.ContainsKey(NetworkingPeer.CurrentSceneProperty)) + { + object levelIdInProps = PhotonNetwork.room.CustomProperties[NetworkingPeer.CurrentSceneProperty]; + if (levelIdInProps is int && SceneManagerHelper.ActiveSceneBuildIndex == (int)levelIdInProps) + { + return; + } + if (levelIdInProps is string && SceneManagerHelper.ActiveSceneName != null && SceneManagerHelper.ActiveSceneName.Equals((string)levelIdInProps)) + { + return; + } + } + + // current level is not yet in props, so this client has to set it + Hashtable setScene = new Hashtable(); + if (levelId is int) setScene[NetworkingPeer.CurrentSceneProperty] = (int)levelId; + else if (levelId is string) setScene[NetworkingPeer.CurrentSceneProperty] = (string)levelId; + else Debug.LogError("Parameter levelId must be int or string!"); + + + if (asyncLoading) { + setScene[NetworkingPeer.CurrentScenePropertyLoadAsync] = true; + } + + PhotonNetwork.room.SetCustomProperties(setScene); + this.SendOutgoingCommands(); // send immediately! because: in most cases the client will begin to load and not send for a while + } + + + + public void SetApp(string appId, string gameVersion) + { + this.AppId = appId.Trim(); + + if (!string.IsNullOrEmpty(gameVersion)) + { + PhotonNetwork.gameVersion = gameVersion.Trim(); + } + } + + + public bool WebRpc(string uriPath, object parameters) + { + Dictionary opParameters = new Dictionary(); + opParameters.Add(ParameterCode.UriPath, uriPath); + opParameters.Add(ParameterCode.WebRpcParameters, parameters); + + return this.OpCustom(OperationCode.WebRpc, opParameters, true); + + } +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs.meta new file mode 100644 index 0000000..5cd136f --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6389c32085f1ef04f88e046b96ab6fc6 +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonClasses.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonClasses.cs new file mode 100644 index 0000000..6091106 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonClasses.cs @@ -0,0 +1,1570 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2011 Exit Games GmbH +// +// +// +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +#pragma warning disable 1587 +/// \file +/// Wraps up smaller classes that don't need their own file. +/// +/// +/// \defgroup publicApi Public API +/// \brief Groups the most important classes that you need to understand early on. +/// +/// \defgroup optionalGui Optional Gui Elements +/// \brief Useful GUI elements for PUN. +#pragma warning restore 1587 + +#if UNITY_5 && !UNITY_5_0 && !UNITY_5_1 && !UNITY_5_2 || UNITY_5_4_OR_NEWER +#define UNITY_MIN_5_3 +#endif + +using System; +using System.Collections.Generic; +using ExitGames.Client.Photon; +using UnityEngine; + +using Hashtable = ExitGames.Client.Photon.Hashtable; +using SupportClassPun = ExitGames.Client.Photon.SupportClass; + + +/// Defines the OnPhotonSerializeView method to make it easy to implement correctly for observable scripts. +/// \ingroup publicApi +public interface IPunObservable +{ + /// + /// Called by PUN several times per second, so that your script can write and read synchronization data for the PhotonView. + /// + /// + /// This method will be called in scripts that are assigned as Observed component of a PhotonView.
+ /// PhotonNetwork.sendRateOnSerialize affects how often this method is called.
+ /// PhotonNetwork.sendRate affects how often packages are sent by this client.
+ /// + /// Implementing this method, you can customize which data a PhotonView regularly synchronizes. + /// Your code defines what is being sent (content) and how your data is used by receiving clients. + /// + /// Unlike other callbacks, OnPhotonSerializeView only gets called when it is assigned + /// to a PhotonView as PhotonView.observed script. + /// + /// To make use of this method, the PhotonStream is essential. It will be in "writing" mode" on the + /// client that controls a PhotonView (PhotonStream.isWriting == true) and in "reading mode" on the + /// remote clients that just receive that the controlling client sends. + /// + /// If you skip writing any value into the stream, PUN will skip the update. Used carefully, this can + /// conserve bandwidth and messages (which have a limit per room/second). + /// + /// Note that OnPhotonSerializeView is not called on remote clients when the sender does not send + /// any update. This can't be used as "x-times per second Update()". + ///
+ /// \ingroup publicApi + void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info); +} + +/// +/// This interface is used as definition of all callback methods of PUN, except OnPhotonSerializeView. Preferably, implement them individually. +/// +/// +/// This interface is available for completeness, more than for actually implementing it in a game. +/// You can implement each method individually in any MonoMehaviour, without implementing IPunCallbacks. +/// +/// PUN calls all callbacks by name. Don't use implement callbacks with fully qualified name. +/// Example: IPunCallbacks.OnConnectedToPhoton won't get called by Unity's SendMessage(). +/// +/// PUN will call these methods on any script that implements them, analog to Unity's events and callbacks. +/// The situation that triggers the call is described per method. +/// +/// OnPhotonSerializeView is NOT called like these callbacks! It's usage frequency is much higher and it is implemented in: IPunObservable. +/// +/// \ingroup publicApi +public interface IPunCallbacks +{ + /// + /// Called when the initial connection got established but before you can use the server. OnJoinedLobby() or OnConnectedToMaster() are called when PUN is ready. + /// + /// + /// This callback is only useful to detect if the server can be reached at all (technically). + /// Most often, it's enough to implement OnFailedToConnectToPhoton() and OnDisconnectedFromPhoton(). + /// + /// OnJoinedLobby() or OnConnectedToMaster() are called when PUN is ready. + /// + /// When this is called, the low level connection is established and PUN will send your AppId, the user, etc in the background. + /// This is not called for transitions from the masterserver to game servers. + /// + void OnConnectedToPhoton(); + + /// + /// Called when the local user/client left a room. + /// + /// + /// When leaving a room, PUN brings you back to the Master Server. + /// Before you can use lobbies and join or create rooms, OnJoinedLobby() or OnConnectedToMaster() will get called again. + /// + void OnLeftRoom(); + + /// + /// Called after switching to a new MasterClient when the current one leaves. + /// + /// + /// This is not called when this client enters a room. + /// The former MasterClient is still in the player list when this method get called. + /// + void OnMasterClientSwitched(PhotonPlayer newMasterClient); + + /// + /// Called when a CreateRoom() call failed. The parameter provides ErrorCode and message (as array). + /// + /// + /// Most likely because the room name is already in use (some other client was faster than you). + /// PUN logs some info if the PhotonNetwork.logLevel is >= PhotonLogLevel.Informational. + /// + /// codeAndMsg[0] is short ErrorCode and codeAndMsg[1] is a string debug msg. + void OnPhotonCreateRoomFailed(object[] codeAndMsg); + + /// + /// Called when a JoinRoom() call failed. The parameter provides ErrorCode and message (as array). + /// + /// + /// Most likely error is that the room does not exist or the room is full (some other client was faster than you). + /// PUN logs some info if the PhotonNetwork.logLevel is >= PhotonLogLevel.Informational. + /// + /// codeAndMsg[0] is short ErrorCode and codeAndMsg[1] is string debug msg. + void OnPhotonJoinRoomFailed(object[] codeAndMsg); + + /// + /// Called when this client created a room and entered it. OnJoinedRoom() will be called as well. + /// + /// + /// This callback is only called on the client which created a room (see PhotonNetwork.CreateRoom). + /// + /// As any client might close (or drop connection) anytime, there is a chance that the + /// creator of a room does not execute OnCreatedRoom. + /// + /// If you need specific room properties or a "start signal", it is safer to implement + /// OnMasterClientSwitched() and to make the new MasterClient check the room's state. + /// + void OnCreatedRoom(); + + /// + /// Called on entering a lobby on the Master Server. The actual room-list updates will call OnReceivedRoomListUpdate(). + /// + /// + /// Note: When PhotonNetwork.autoJoinLobby is false, OnConnectedToMaster() will be called and the room list won't become available. + /// + /// While in the lobby, the roomlist is automatically updated in fixed intervals (which you can't modify). + /// The room list gets available when OnReceivedRoomListUpdate() gets called after OnJoinedLobby(). + /// + void OnJoinedLobby(); + + /// + /// Called after leaving a lobby. + /// + /// + /// When you leave a lobby, [CreateRoom](@ref PhotonNetwork.CreateRoom) and [JoinRandomRoom](@ref PhotonNetwork.JoinRandomRoom) + /// automatically refer to the default lobby. + /// + void OnLeftLobby(); + + /// + /// Called if a connect call to the Photon server failed before the connection was established, followed by a call to OnDisconnectedFromPhoton(). + /// + /// + /// This is called when no connection could be established at all. + /// It differs from OnConnectionFail, which is called when an existing connection fails. + /// + void OnFailedToConnectToPhoton(DisconnectCause cause); + + /// + /// Called when something causes the connection to fail (after it was established), followed by a call to OnDisconnectedFromPhoton(). + /// + /// + /// If the server could not be reached in the first place, OnFailedToConnectToPhoton is called instead. + /// The reason for the error is provided as DisconnectCause. + /// + void OnConnectionFail(DisconnectCause cause); + + /// + /// Called after disconnecting from the Photon server. + /// + /// + /// In some cases, other callbacks are called before OnDisconnectedFromPhoton is called. + /// Examples: OnConnectionFail() and OnFailedToConnectToPhoton(). + /// + void OnDisconnectedFromPhoton(); + + /// + /// Called on all scripts on a GameObject (and children) that have been Instantiated using PhotonNetwork.Instantiate. + /// + /// + /// PhotonMessageInfo parameter provides info about who created the object and when (based off PhotonNetworking.time). + /// + void OnPhotonInstantiate(PhotonMessageInfo info); + + /// + /// Called for any update of the room-listing while in a lobby (PhotonNetwork.insideLobby) on the Master Server + /// or when a response is received for PhotonNetwork.GetCustomRoomList(). + /// + /// + /// PUN provides the list of rooms by PhotonNetwork.GetRoomList().
+ /// Each item is a RoomInfo which might include custom properties (provided you defined those as lobby-listed when creating a room). + /// + /// Not all types of lobbies provide a listing of rooms to the client. Some are silent and specialized for server-side matchmaking. + ///
+ void OnReceivedRoomListUpdate(); + + /// + /// Called when entering a room (by creating or joining it). Called on all clients (including the Master Client). + /// + /// + /// This method is commonly used to instantiate player characters. + /// If a match has to be started "actively", you can call an [PunRPC](@ref PhotonView.RPC) triggered by a user's button-press or a timer. + /// + /// When this is called, you can usually already access the existing players in the room via PhotonNetwork.playerList. + /// Also, all custom properties should be already available as Room.customProperties. Check Room.playerCount to find out if + /// enough players are in the room to start playing. + /// + void OnJoinedRoom(); + + /// + /// Called when a remote player entered the room. This PhotonPlayer is already added to the playerlist at this time. + /// + /// + /// If your game starts with a certain number of players, this callback can be useful to check the + /// Room.playerCount and find out if you can start. + /// + void OnPhotonPlayerConnected(PhotonPlayer newPlayer); + + /// + /// Called when a remote player left the room. This PhotonPlayer is already removed from the playerlist at this time. + /// + /// + /// When your client calls PhotonNetwork.leaveRoom, PUN will call this method on the remaining clients. + /// When a remote client drops connection or gets closed, this callback gets executed. after a timeout + /// of several seconds. + /// + void OnPhotonPlayerDisconnected(PhotonPlayer otherPlayer); + + /// + /// Called when a JoinRandom() call failed. The parameter provides ErrorCode and message. + /// + /// + /// Most likely all rooms are full or no rooms are available.
+ /// When using multiple lobbies (via JoinLobby or TypedLobby), another lobby might have more/fitting rooms.
+ /// PUN logs some info if the PhotonNetwork.logLevel is >= PhotonLogLevel.Informational. + ///
+ /// codeAndMsg[0] is short ErrorCode. codeAndMsg[1] is string debug msg. + void OnPhotonRandomJoinFailed(object[] codeAndMsg); + + /// + /// Called after the connection to the master is established and authenticated but only when PhotonNetwork.autoJoinLobby is false. + /// + /// + /// If you set PhotonNetwork.autoJoinLobby to true, OnJoinedLobby() will be called instead of this. + /// + /// You can join rooms and create them even without being in a lobby. The default lobby is used in that case. + /// The list of available rooms won't become available unless you join a lobby via PhotonNetwork.joinLobby. + /// + void OnConnectedToMaster(); + + /// + /// Because the concurrent user limit was (temporarily) reached, this client is rejected by the server and disconnecting. + /// + /// + /// When this happens, the user might try again later. You can't create or join rooms in OnPhotonMaxCcuReached(), cause the client will be disconnecting. + /// You can raise the CCU limits with a new license (when you host yourself) or extended subscription (when using the Photon Cloud). + /// The Photon Cloud will mail you when the CCU limit was reached. This is also visible in the Dashboard (webpage). + /// + void OnPhotonMaxCccuReached(); + + /// + /// Called when a room's custom properties changed. The propertiesThatChanged contains all that was set via Room.SetCustomProperties. + /// + /// + /// Since v1.25 this method has one parameter: Hashtable propertiesThatChanged.
+ /// Changing properties must be done by Room.SetCustomProperties, which causes this callback locally, too. + ///
+ /// + void OnPhotonCustomRoomPropertiesChanged(Hashtable propertiesThatChanged); + + /// + /// Called when custom player-properties are changed. Player and the changed properties are passed as object[]. + /// + /// + /// Since v1.25 this method has one parameter: object[] playerAndUpdatedProps, which contains two entries.
+ /// [0] is the affected PhotonPlayer.
+ /// [1] is the Hashtable of properties that changed.
+ /// + /// We are using a object[] due to limitations of Unity's GameObject.SendMessage (which has only one optional parameter). + /// + /// Changing properties must be done by PhotonPlayer.SetCustomProperties, which causes this callback locally, too. + /// + /// Example:
+    /// void OnPhotonPlayerPropertiesChanged(object[] playerAndUpdatedProps) {
+    ///     PhotonPlayer player = playerAndUpdatedProps[0] as PhotonPlayer;
+    ///     Hashtable props = playerAndUpdatedProps[1] as Hashtable;
+    ///     //...
+    /// }
+ ///
+ /// Contains PhotonPlayer and the properties that changed See remarks. + void OnPhotonPlayerPropertiesChanged(object[] playerAndUpdatedProps); + + /// + /// Called when the server sent the response to a FindFriends request and updated PhotonNetwork.Friends. + /// + /// + /// The friends list is available as PhotonNetwork.Friends, listing name, online state and + /// the room a user is in (if any). + /// + void OnUpdatedFriendList(); + + /// + /// Called when the custom authentication failed. Followed by disconnect! + /// + /// + /// Custom Authentication can fail due to user-input, bad tokens/secrets. + /// If authentication is successful, this method is not called. Implement OnJoinedLobby() or OnConnectedToMaster() (as usual). + /// + /// During development of a game, it might also fail due to wrong configuration on the server side. + /// In those cases, logging the debugMessage is very important. + /// + /// Unless you setup a custom authentication service for your app (in the [Dashboard](https://www.photonengine.com/dashboard)), + /// this won't be called! + /// + /// Contains a debug message why authentication failed. This has to be fixed during development time. + void OnCustomAuthenticationFailed(string debugMessage); + + /// + /// Called when your Custom Authentication service responds with additional data. + /// + /// + /// Custom Authentication services can include some custom data in their response. + /// When present, that data is made available in this callback as Dictionary. + /// While the keys of your data have to be strings, the values can be either string or a number (in Json). + /// You need to make extra sure, that the value type is the one you expect. Numbers become (currently) int64. + /// + /// Example: void OnCustomAuthenticationResponse(Dictionary<string, object> data) { ... } + /// + /// + void OnCustomAuthenticationResponse(Dictionary data); + + /// + /// Called by PUN when the response to a WebRPC is available. See PhotonNetwork.WebRPC. + /// + /// + /// Important: The response.ReturnCode is 0 if Photon was able to reach your web-service.
+ /// The content of the response is what your web-service sent. You can create a WebRpcResponse from it.
+ /// Example: WebRpcResponse webResponse = new WebRpcResponse(operationResponse);
+ /// + /// Please note: Class OperationResponse is in a namespace which needs to be "used":
+ /// using ExitGames.Client.Photon; // includes OperationResponse (and other classes) + /// + /// The OperationResponse.ReturnCode by Photon is:
+    ///  0 for "OK"
+    /// -3 for "Web-Service not configured" (see Dashboard / WebHooks)
+    /// -5 for "Web-Service does now have RPC path/name" (at least for Azure)
+ ///
+ void OnWebRpcResponse(OperationResponse response); + + /// + /// Called when another player requests ownership of a PhotonView from you (the current owner). + /// + /// + /// The parameter viewAndPlayer contains: + /// + /// PhotonView view = viewAndPlayer[0] as PhotonView; + /// + /// PhotonPlayer requestingPlayer = viewAndPlayer[1] as PhotonPlayer; + /// + /// The PhotonView is viewAndPlayer[0] and the requesting player is viewAndPlayer[1]. + void OnOwnershipRequest(object[] viewAndPlayer); + + /// + /// Called when the Master Server sent an update for the Lobby Statistics, updating PhotonNetwork.LobbyStatistics. + /// + /// + /// This callback has two preconditions: + /// EnableLobbyStatistics must be set to true, before this client connects. + /// And the client has to be connected to the Master Server, which is providing the info about lobbies. + /// + void OnLobbyStatisticsUpdate(); + + /// + /// Called when a remote Photon Player activity changed. This will be called ONLY if PlayerTtl is greater than 0. + /// + /// + /// Use PhotonPlayer.IsInactive to check a player's current activity state. + /// + /// Example: void OnPhotonPlayerActivityChanged(PhotonPlayer otherPlayer) {...} + /// + /// This callback has precondition: + /// PlayerTtl must be greater than 0. + /// + void OnPhotonPlayerActivityChanged(PhotonPlayer otherPlayer); + + /// + /// Called when ownership of a PhotonView is transfered to another player. + /// + /// + /// The parameter viewAndPlayers contains: + /// + /// PhotonView view = viewAndPlayers[0] as PhotonView; + /// + /// PhotonPlayer newOwner = viewAndPlayers[1] as PhotonPlayer; + /// + /// PhotonPlayer oldOwner = viewAndPlayers[2] as PhotonPlayer; + /// + /// void OnOwnershipTransfered(object[] viewAndPlayers) {} // + void OnOwnershipTransfered(object[] viewAndPlayers); +} + +/// +/// Defines all the methods that a Object Pool must implement, so that PUN can use it. +/// +/// +/// To use a Object Pool for instantiation, you can set PhotonNetwork.ObjectPool. +/// That is used for all objects, as long as ObjectPool is not null. +/// The pool has to return a valid non-null GameObject when PUN calls Instantiate. +/// Also, the position and rotation must be applied. +/// +/// Please note that pooled GameObjects don't get the usual Awake and Start calls. +/// OnEnable will be called (by your pool) but the networking values are not updated yet +/// when that happens. OnEnable will have outdated values for PhotonView (isMine, etc.). +/// You might have to adjust scripts. +/// +/// PUN will call OnPhotonInstantiate (see IPunCallbacks). This should be used to +/// setup the re-used object with regards to networking values / ownership. +/// +public interface IPunPrefabPool +{ + /// + /// This is called when PUN wants to create a new instance of an entity prefab. Must return valid GameObject with PhotonView. + /// + /// The id of this prefab. + /// The position we want the instance instantiated at. + /// The rotation we want the instance to take. + /// The newly instantiated object, or null if a prefab with was not found. + GameObject Instantiate(string prefabId, Vector3 position, Quaternion rotation); + + /// + /// This is called when PUN wants to destroy the instance of an entity prefab. + /// + /// + /// A pool needs some way to find out which type of GameObject got returned via Destroy(). + /// It could be a tag or name or anything similar. + /// + /// The instance to destroy. + void Destroy(GameObject gameObject); +} + + +namespace Photon +{ + using Hashtable = ExitGames.Client.Photon.Hashtable; + + /// + /// This class adds the property photonView, while logging a warning when your game still uses the networkView. + /// + public class MonoBehaviour : UnityEngine.MonoBehaviour + { + /// Cache field for the PhotonView on this GameObject. + private PhotonView pvCache = null; + + /// A cached reference to a PhotonView on this GameObject. + /// + /// If you intend to work with a PhotonView in a script, it's usually easier to write this.photonView. + /// + /// If you intend to remove the PhotonView component from the GameObject but keep this Photon.MonoBehaviour, + /// avoid this reference or modify this code to use PhotonView.Get(obj) instead. + /// + public PhotonView photonView + { + get + { + if (pvCache == null) + { + pvCache = PhotonView.Get(this); + } + return pvCache; + } + } + + #if !UNITY_MIN_5_3 + /// + /// This property is only here to notify developers when they use the outdated value. + /// + /// + /// If Unity 5.x logs a compiler warning "Use the new keyword if hiding was intended" or + /// "The new keyword is not required", you may suffer from an Editor issue. + /// Try to modify networkView with a if-def condition: + /// + /// #if UNITY_EDITOR + /// new + /// #endif + /// public PhotonView networkView + /// + [Obsolete("Use a photonView")] + public new PhotonView networkView + { + get + { + Debug.LogWarning("Why are you still using networkView? should be PhotonView?"); + return PhotonView.Get(this); + } + } + #endif + } + + + /// + /// This class provides a .photonView and all callbacks/events that PUN can call. Override the events/methods you want to use. + /// + /// + /// By extending this class, you can implement individual methods as override. + /// + /// Visual Studio and MonoDevelop should provide the list of methods when you begin typing "override". + /// Your implementation does not have to call "base.method()". + /// + /// This class implements IPunCallbacks, which is used as definition of all PUN callbacks. + /// Don't implement IPunCallbacks in your classes. Instead, implent PunBehaviour or individual methods. + /// + /// \ingroup publicApi + // the documentation for the interface methods becomes inherited when Doxygen builds it. + public class PunBehaviour : Photon.MonoBehaviour, IPunCallbacks + { + /// + /// Called when the initial connection got established but before you can use the server. OnJoinedLobby() or OnConnectedToMaster() are called when PUN is ready. + /// + /// + /// This callback is only useful to detect if the server can be reached at all (technically). + /// Most often, it's enough to implement OnFailedToConnectToPhoton() and OnDisconnectedFromPhoton(). + /// + /// OnJoinedLobby() or OnConnectedToMaster() are called when PUN is ready. + /// + /// When this is called, the low level connection is established and PUN will send your AppId, the user, etc in the background. + /// This is not called for transitions from the masterserver to game servers. + /// + public virtual void OnConnectedToPhoton() + { + } + + /// + /// Called when the local user/client left a room. + /// + /// + /// When leaving a room, PUN brings you back to the Master Server. + /// Before you can use lobbies and join or create rooms, OnJoinedLobby() or OnConnectedToMaster() will get called again. + /// + public virtual void OnLeftRoom() + { + } + + /// + /// Called after switching to a new MasterClient when the current one leaves. + /// + /// + /// This is not called when this client enters a room. + /// The former MasterClient is still in the player list when this method get called. + /// + public virtual void OnMasterClientSwitched(PhotonPlayer newMasterClient) + { + } + + /// + /// Called when a CreateRoom() call failed. The parameter provides ErrorCode and message (as array). + /// + /// + /// Most likely because the room name is already in use (some other client was faster than you). + /// PUN logs some info if the PhotonNetwork.logLevel is >= PhotonLogLevel.Informational. + /// + /// codeAndMsg[0] is a short ErrorCode and codeAndMsg[1] is a string debug msg. + public virtual void OnPhotonCreateRoomFailed(object[] codeAndMsg) + { + } + + /// + /// Called when a JoinRoom() call failed. The parameter provides ErrorCode and message (as array). + /// + /// + /// Most likely error is that the room does not exist or the room is full (some other client was faster than you). + /// PUN logs some info if the PhotonNetwork.logLevel is >= PhotonLogLevel.Informational. + /// + /// codeAndMsg[0] is short ErrorCode. codeAndMsg[1] is string debug msg. + public virtual void OnPhotonJoinRoomFailed(object[] codeAndMsg) + { + } + + /// + /// Called when this client created a room and entered it. OnJoinedRoom() will be called as well. + /// + /// + /// This callback is only called on the client which created a room (see PhotonNetwork.CreateRoom). + /// + /// As any client might close (or drop connection) anytime, there is a chance that the + /// creator of a room does not execute OnCreatedRoom. + /// + /// If you need specific room properties or a "start signal", it is safer to implement + /// OnMasterClientSwitched() and to make the new MasterClient check the room's state. + /// + public virtual void OnCreatedRoom() + { + } + + /// + /// Called on entering a lobby on the Master Server. The actual room-list updates will call OnReceivedRoomListUpdate(). + /// + /// + /// Note: When PhotonNetwork.autoJoinLobby is false, OnConnectedToMaster() will be called and the room list won't become available. + /// + /// While in the lobby, the roomlist is automatically updated in fixed intervals (which you can't modify). + /// The room list gets available when OnReceivedRoomListUpdate() gets called after OnJoinedLobby(). + /// + public virtual void OnJoinedLobby() + { + } + + /// + /// Called after leaving a lobby. + /// + /// + /// When you leave a lobby, [CreateRoom](@ref PhotonNetwork.CreateRoom) and [JoinRandomRoom](@ref PhotonNetwork.JoinRandomRoom) + /// automatically refer to the default lobby. + /// + public virtual void OnLeftLobby() + { + } + + /// + /// Called if a connect call to the Photon server failed before the connection was established, followed by a call to OnDisconnectedFromPhoton(). + /// + /// + /// This is called when no connection could be established at all. + /// It differs from OnConnectionFail, which is called when an existing connection fails. + /// + public virtual void OnFailedToConnectToPhoton(DisconnectCause cause) + { + } + + /// + /// Called after disconnecting from the Photon server. + /// + /// + /// In some cases, other callbacks are called before OnDisconnectedFromPhoton is called. + /// Examples: OnConnectionFail() and OnFailedToConnectToPhoton(). + /// + public virtual void OnDisconnectedFromPhoton() + { + } + + /// + /// Called when something causes the connection to fail (after it was established), followed by a call to OnDisconnectedFromPhoton(). + /// + /// + /// If the server could not be reached in the first place, OnFailedToConnectToPhoton is called instead. + /// The reason for the error is provided as DisconnectCause. + /// + public virtual void OnConnectionFail(DisconnectCause cause) + { + } + + /// + /// Called on all scripts on a GameObject (and children) that have been Instantiated using PhotonNetwork.Instantiate. + /// + /// + /// PhotonMessageInfo parameter provides info about who created the object and when (based off PhotonNetworking.time). + /// + public virtual void OnPhotonInstantiate(PhotonMessageInfo info) + { + } + + /// + /// Called for any update of the room-listing while in a lobby (PhotonNetwork.insideLobby) on the Master Server + /// or when a response is received for PhotonNetwork.GetCustomRoomList(). + /// + /// + /// PUN provides the list of rooms by PhotonNetwork.GetRoomList().
+ /// Each item is a RoomInfo which might include custom properties (provided you defined those as lobby-listed when creating a room). + /// + /// Not all types of lobbies provide a listing of rooms to the client. Some are silent and specialized for server-side matchmaking. + ///
+ public virtual void OnReceivedRoomListUpdate() + { + } + + /// + /// Called when entering a room (by creating or joining it). Called on all clients (including the Master Client). + /// + /// + /// This method is commonly used to instantiate player characters. + /// If a match has to be started "actively", you can call an [PunRPC](@ref PhotonView.RPC) triggered by a user's button-press or a timer. + /// + /// When this is called, you can usually already access the existing players in the room via PhotonNetwork.playerList. + /// Also, all custom properties should be already available as Room.customProperties. Check Room.playerCount to find out if + /// enough players are in the room to start playing. + /// + public virtual void OnJoinedRoom() + { + } + + /// + /// Called when a remote player entered the room. This PhotonPlayer is already added to the playerlist at this time. + /// + /// + /// If your game starts with a certain number of players, this callback can be useful to check the + /// Room.playerCount and find out if you can start. + /// + public virtual void OnPhotonPlayerConnected(PhotonPlayer newPlayer) + { + } + + /// + /// Called when a remote player left the room. This PhotonPlayer is already removed from the playerlist at this time. + /// + /// + /// When your client calls PhotonNetwork.leaveRoom, PUN will call this method on the remaining clients. + /// When a remote client drops connection or gets closed, this callback gets executed. after a timeout + /// of several seconds. + /// + public virtual void OnPhotonPlayerDisconnected(PhotonPlayer otherPlayer) + { + } + + /// + /// Called when a JoinRandom() call failed. The parameter provides ErrorCode and message. + /// + /// + /// Most likely all rooms are full or no rooms are available.
+ /// When using multiple lobbies (via JoinLobby or TypedLobby), another lobby might have more/fitting rooms.
+ /// PUN logs some info if the PhotonNetwork.logLevel is >= PhotonLogLevel.Informational. + ///
+ /// codeAndMsg[0] is short ErrorCode. codeAndMsg[1] is string debug msg. + public virtual void OnPhotonRandomJoinFailed(object[] codeAndMsg) + { + } + + /// + /// Called after the connection to the master is established and authenticated but only when PhotonNetwork.autoJoinLobby is false. + /// + /// + /// If you set PhotonNetwork.autoJoinLobby to true, OnJoinedLobby() will be called instead of this. + /// + /// You can join rooms and create them even without being in a lobby. The default lobby is used in that case. + /// The list of available rooms won't become available unless you join a lobby via PhotonNetwork.joinLobby. + /// + public virtual void OnConnectedToMaster() + { + } + + /// + /// Because the concurrent user limit was (temporarily) reached, this client is rejected by the server and disconnecting. + /// + /// + /// When this happens, the user might try again later. You can't create or join rooms in OnPhotonMaxCcuReached(), cause the client will be disconnecting. + /// You can raise the CCU limits with a new license (when you host yourself) or extended subscription (when using the Photon Cloud). + /// The Photon Cloud will mail you when the CCU limit was reached. This is also visible in the Dashboard (webpage). + /// + public virtual void OnPhotonMaxCccuReached() + { + } + + /// + /// Called when a room's custom properties changed. The propertiesThatChanged contains all that was set via Room.SetCustomProperties. + /// + /// + /// Since v1.25 this method has one parameter: Hashtable propertiesThatChanged.
+ /// Changing properties must be done by Room.SetCustomProperties, which causes this callback locally, too. + ///
+ /// + public virtual void OnPhotonCustomRoomPropertiesChanged(Hashtable propertiesThatChanged) + { + } + + /// + /// Called when custom player-properties are changed. Player and the changed properties are passed as object[]. + /// + /// + /// Since v1.25 this method has one parameter: object[] playerAndUpdatedProps, which contains two entries.
+ /// [0] is the affected PhotonPlayer.
+ /// [1] is the Hashtable of properties that changed.
+ /// + /// We are using a object[] due to limitations of Unity's GameObject.SendMessage (which has only one optional parameter). + /// + /// Changing properties must be done by PhotonPlayer.SetCustomProperties, which causes this callback locally, too. + /// + /// Example:
+        /// void OnPhotonPlayerPropertiesChanged(object[] playerAndUpdatedProps) {
+        ///     PhotonPlayer player = playerAndUpdatedProps[0] as PhotonPlayer;
+        ///     Hashtable props = playerAndUpdatedProps[1] as Hashtable;
+        ///     //...
+        /// }
+ ///
+ /// Contains PhotonPlayer and the properties that changed See remarks. + public virtual void OnPhotonPlayerPropertiesChanged(object[] playerAndUpdatedProps) + { + } + + /// + /// Called when the server sent the response to a FindFriends request and updated PhotonNetwork.Friends. + /// + /// + /// The friends list is available as PhotonNetwork.Friends, listing name, online state and + /// the room a user is in (if any). + /// + public virtual void OnUpdatedFriendList() + { + } + + /// + /// Called when the custom authentication failed. Followed by disconnect! + /// + /// + /// Custom Authentication can fail due to user-input, bad tokens/secrets. + /// If authentication is successful, this method is not called. Implement OnJoinedLobby() or OnConnectedToMaster() (as usual). + /// + /// During development of a game, it might also fail due to wrong configuration on the server side. + /// In those cases, logging the debugMessage is very important. + /// + /// Unless you setup a custom authentication service for your app (in the [Dashboard](https://www.photonengine.com/dashboard)), + /// this won't be called! + /// + /// Contains a debug message why authentication failed. This has to be fixed during development time. + public virtual void OnCustomAuthenticationFailed(string debugMessage) + { + } + + /// + /// Called when your Custom Authentication service responds with additional data. + /// + /// + /// Custom Authentication services can include some custom data in their response. + /// When present, that data is made available in this callback as Dictionary. + /// While the keys of your data have to be strings, the values can be either string or a number (in Json). + /// You need to make extra sure, that the value type is the one you expect. Numbers become (currently) int64. + /// + /// Example: void OnCustomAuthenticationResponse(Dictionary<string, object> data) { ... } + /// + /// + public virtual void OnCustomAuthenticationResponse(Dictionary data) + { + } + + /// + /// Called by PUN when the response to a WebRPC is available. See PhotonNetwork.WebRPC. + /// + /// + /// Important: The response.ReturnCode is 0 if Photon was able to reach your web-service. + /// The content of the response is what your web-service sent. You can create a WebResponse instance from it. + /// Example: WebRpcResponse webResponse = new WebRpcResponse(operationResponse); + /// + /// Please note: Class OperationResponse is in a namespace which needs to be "used": + /// using ExitGames.Client.Photon; // includes OperationResponse (and other classes) + /// + /// The OperationResponse.ReturnCode by Photon is:
+        ///  0 for "OK"
+        /// -3 for "Web-Service not configured" (see Dashboard / WebHooks)
+        /// -5 for "Web-Service does now have RPC path/name" (at least for Azure)
+ ///
+ public virtual void OnWebRpcResponse(OperationResponse response) + { + } + + /// + /// Called when another player requests ownership of a PhotonView from you (the current owner). + /// + /// + /// The parameter viewAndPlayer contains: + /// + /// PhotonView view = viewAndPlayer[0] as PhotonView; + /// + /// PhotonPlayer requestingPlayer = viewAndPlayer[1] as PhotonPlayer; + /// + /// The PhotonView is viewAndPlayer[0] and the requesting player is viewAndPlayer[1]. + public virtual void OnOwnershipRequest(object[] viewAndPlayer) + { + } + + /// + /// Called when the Master Server sent an update for the Lobby Statistics, updating PhotonNetwork.LobbyStatistics. + /// + /// + /// This callback has two preconditions: + /// EnableLobbyStatistics must be set to true, before this client connects. + /// And the client has to be connected to the Master Server, which is providing the info about lobbies. + /// + public virtual void OnLobbyStatisticsUpdate() + { + } + + /// + /// Called when a remote Photon Player activity changed. This will be called ONLY if PlayerTtl is greater than 0. + /// + /// + /// Use PhotonPlayer.IsInactive to check a player's current activity state. + /// + /// Example: void OnPhotonPlayerActivityChanged(PhotonPlayer otherPlayer) {...} + /// + /// This callback has precondition: + /// PlayerTtl must be greater than 0. + /// + public virtual void OnPhotonPlayerActivityChanged(PhotonPlayer otherPlayer) + { + } + + /// + /// Called when ownership of a PhotonView is transfered to another player. + /// + /// + /// The parameter viewAndPlayers contains: + /// + /// PhotonView view = viewAndPlayers[0] as PhotonView; + /// + /// PhotonPlayer newOwner = viewAndPlayers[1] as PhotonPlayer; + /// + /// PhotonPlayer oldOwner = viewAndPlayers[2] as PhotonPlayer; + /// + /// void OnOwnershipTransfered(object[] viewAndPlayers) {} // + public virtual void OnOwnershipTransfered(object[] viewAndPlayers) + { + } + } +} + + +/// +/// Container class for info about a particular message, RPC or update. +/// +/// \ingroup publicApi +public struct PhotonMessageInfo +{ + private readonly int timeInt; + /// The sender of a message / event. May be null. + public readonly PhotonPlayer sender; + public readonly PhotonView photonView; + + public PhotonMessageInfo(PhotonPlayer player, int timestamp, PhotonView view) + { + this.sender = player; + this.timeInt = timestamp; + this.photonView = view; + } + + public double timestamp + { + get + { + uint u = (uint)this.timeInt; + double t = u; + return t / 1000; + } + } + + public override string ToString() + { + return string.Format("[PhotonMessageInfo: Sender='{1}' Senttime={0}]", this.timestamp, this.sender); + } +} + + + +/// Defines Photon event-codes as used by PUN. +internal class PunEvent +{ + public const byte RPC = 200; + public const byte SendSerialize = 201; + public const byte Instantiation = 202; + public const byte CloseConnection = 203; + public const byte Destroy = 204; + public const byte RemoveCachedRPCs = 205; + public const byte SendSerializeReliable = 206; // TS: added this but it's not really needed anymore + public const byte DestroyPlayer = 207; // TS: added to make others remove all GOs of a player + public const byte AssignMaster = 208; // TS: added to assign someone master client (overriding the current) + public const byte OwnershipRequest = 209; + public const byte OwnershipTransfer = 210; + public const byte VacantViewIds = 211; +} + +/// +/// This container is used in OnPhotonSerializeView() to either provide incoming data of a PhotonView or for you to provide it. +/// +/// +/// The isWriting property will be true if this client is the "owner" of the PhotonView (and thus the GameObject). +/// Add data to the stream and it's sent via the server to the other players in a room. +/// On the receiving side, isWriting is false and the data should be read. +/// +/// Send as few data as possible to keep connection quality up. An empty PhotonStream will not be sent. +/// +/// Use either Serialize() for reading and writing or SendNext() and ReceiveNext(). The latter two are just explicit read and +/// write methods but do about the same work as Serialize(). It's a matter of preference which methods you use. +/// +/// +/// \ingroup publicApi +public class PhotonStream +{ + bool write = false; + private Queue writeData; + private object[] readData; + internal byte currentItem = 0; //Used to track the next item to receive. + + /// + /// Creates a stream and initializes it. Used by PUN internally. + /// + public PhotonStream(bool write, object[] incomingData) + { + this.write = write; + if (incomingData == null) + { + this.writeData = new Queue(10); + } + else + { + this.readData = incomingData; + } + } + + public void SetReadStream(object[] incomingData, byte pos = 0) + { + this.readData = incomingData; + this.currentItem = pos; + this.write = false; + } + + internal void ResetWriteStream() + { + writeData.Clear(); + } + + /// If true, this client should add data to the stream to send it. + public bool isWriting + { + get { return this.write; } + } + + /// If true, this client should read data send by another client. + public bool isReading + { + get { return !this.write; } + } + + /// Count of items in the stream. + public int Count + { + get + { + return (this.isWriting) ? this.writeData.Count : this.readData.Length; + } + } + + /// Read next piece of data from the stream when isReading is true. + public object ReceiveNext() + { + if (this.write) + { + Debug.LogError("Error: you cannot read this stream that you are writing!"); + return null; + } + + object obj = this.readData[this.currentItem]; + this.currentItem++; + return obj; + } + + /// Read next piece of data from the stream without advancing the "current" item. + public object PeekNext() + { + if (this.write) + { + Debug.LogError("Error: you cannot read this stream that you are writing!"); + return null; + } + + object obj = this.readData[this.currentItem]; + //this.currentItem++; + return obj; + } + + /// Add another piece of data to send it when isWriting is true. + public void SendNext(object obj) + { + if (!this.write) + { + Debug.LogError("Error: you cannot write/send to this stream that you are reading!"); + return; + } + + this.writeData.Enqueue(obj); + } + + /// Turns the stream into a new object[]. + public object[] ToArray() + { + return this.isWriting ? this.writeData.ToArray() : this.readData; + } + + /// + /// Will read or write the value, depending on the stream's isWriting value. + /// + public void Serialize(ref bool myBool) + { + if (this.write) + { + this.writeData.Enqueue(myBool); + } + else + { + if (this.readData.Length > currentItem) + { + myBool = (bool)this.readData[currentItem]; + this.currentItem++; + } + } + } + + /// + /// Will read or write the value, depending on the stream's isWriting value. + /// + public void Serialize(ref int myInt) + { + if (write) + { + this.writeData.Enqueue(myInt); + } + else + { + if (this.readData.Length > currentItem) + { + myInt = (int)this.readData[currentItem]; + currentItem++; + } + } + } + + /// + /// Will read or write the value, depending on the stream's isWriting value. + /// + public void Serialize(ref string value) + { + if (write) + { + this.writeData.Enqueue(value); + } + else + { + if (this.readData.Length > currentItem) + { + value = (string)this.readData[currentItem]; + currentItem++; + } + } + } + + /// + /// Will read or write the value, depending on the stream's isWriting value. + /// + public void Serialize(ref char value) + { + if (write) + { + this.writeData.Enqueue(value); + } + else + { + if (this.readData.Length > currentItem) + { + value = (char)this.readData[currentItem]; + currentItem++; + } + } + } + + /// + /// Will read or write the value, depending on the stream's isWriting value. + /// + public void Serialize(ref short value) + { + if (write) + { + this.writeData.Enqueue(value); + } + else + { + if (this.readData.Length > currentItem) + { + value = (short)this.readData[currentItem]; + currentItem++; + } + } + } + + /// + /// Will read or write the value, depending on the stream's isWriting value. + /// + public void Serialize(ref float obj) + { + if (write) + { + this.writeData.Enqueue(obj); + } + else + { + if (this.readData.Length > currentItem) + { + obj = (float)this.readData[currentItem]; + currentItem++; + } + } + } + + /// + /// Will read or write the value, depending on the stream's isWriting value. + /// + public void Serialize(ref PhotonPlayer obj) + { + if (write) + { + this.writeData.Enqueue(obj); + } + else + { + if (this.readData.Length > currentItem) + { + obj = (PhotonPlayer)this.readData[currentItem]; + currentItem++; + } + } + } + + /// + /// Will read or write the value, depending on the stream's isWriting value. + /// + public void Serialize(ref Vector3 obj) + { + if (write) + { + this.writeData.Enqueue(obj); + } + else + { + if (this.readData.Length > currentItem) + { + obj = (Vector3)this.readData[currentItem]; + currentItem++; + } + } + } + + /// + /// Will read or write the value, depending on the stream's isWriting value. + /// + public void Serialize(ref Vector2 obj) + { + if (write) + { + this.writeData.Enqueue(obj); + } + else + { + if (this.readData.Length > currentItem) + { + obj = (Vector2)this.readData[currentItem]; + currentItem++; + } + } + } + + /// + /// Will read or write the value, depending on the stream's isWriting value. + /// + public void Serialize(ref Quaternion obj) + { + if (write) + { + this.writeData.Enqueue(obj); + } + else + { + if (this.readData.Length > currentItem) + { + obj = (Quaternion)this.readData[currentItem]; + currentItem++; + } + } + } +} + + +#if UNITY_5_0 || !UNITY_5 && !UNITY_5_3_OR_NEWER +/// Empty implementation of the upcoming HelpURL of Unity 5.1. This one is only for compatibility of attributes. +/// http://feedback.unity3d.com/suggestions/override-component-documentation-slash-help-link +public class HelpURL : Attribute +{ + public HelpURL(string url) + { + } +} +#endif + + +#if !UNITY_MIN_5_3 +// in Unity 5.3 and up, we have to use a SceneManager. This section re-implements it for older Unity versions + +#if UNITY_EDITOR +namespace UnityEditor.SceneManagement +{ + /// Minimal implementation of the EditorSceneManager for older Unity, up to v5.2. + public class EditorSceneManager + { + public static int loadedSceneCount + { + get { return string.IsNullOrEmpty(UnityEditor.EditorApplication.currentScene) ? -1 : 1; } + } + + public static void OpenScene(string name) + { + UnityEditor.EditorApplication.OpenScene(name); + } + + public static void SaveOpenScenes() + { + UnityEditor.EditorApplication.SaveScene(); + } + + public static void SaveCurrentModifiedScenesIfUserWantsTo() + { + UnityEditor.EditorApplication.SaveCurrentSceneIfUserWantsTo(); + } + } +} +#endif + +namespace UnityEngine.SceneManagement +{ + public enum LoadSceneMode + { + Single, + Additive + } + + /// Minimal implementation of the SceneManager for older Unity, up to v5.2. + public class SceneManager + { + public static void LoadScene(string name) + { + Application.LoadLevel(name); + } + + public static void LoadScene(int buildIndex) + { + Application.LoadLevel(buildIndex); + } + + public static AsyncOperation LoadSceneAsync(string name,LoadSceneMode mode = LoadSceneMode.Single) + { + if (mode == UnityEngine.SceneManagement.LoadSceneMode.Single) { + return Application.LoadLevelAsync (name); + } else { + return Application.LoadLevelAdditiveAsync(name); + } + } + + public static AsyncOperation LoadSceneAsync(int buildIndex,LoadSceneMode mode = LoadSceneMode.Single) + { + if (mode == UnityEngine.SceneManagement.LoadSceneMode.Single) { + return Application.LoadLevelAsync (buildIndex); + } else { + return Application.LoadLevelAdditiveAsync(buildIndex); + } + } + + } +} + +#endif + + +public class SceneManagerHelper +{ + public static string ActiveSceneName + { + get + { + #if UNITY_MIN_5_3 + UnityEngine.SceneManagement.Scene s = UnityEngine.SceneManagement.SceneManager.GetActiveScene(); + return s.name; + #else + return Application.loadedLevelName; + #endif + } + } + + public static int ActiveSceneBuildIndex + { + get + { + #if UNITY_MIN_5_3 + return UnityEngine.SceneManagement.SceneManager.GetActiveScene().buildIndex; + #else + return Application.loadedLevel; + #endif + } + } + + +#if UNITY_EDITOR + public static string EditorActiveSceneName + { + get + { + #if UNITY_MIN_5_3 + return UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().name; + #else + return System.IO.Path.GetFileNameWithoutExtension(UnityEditor.EditorApplication.currentScene); + #endif + } + } +#endif +} + + +/// Reads an operation response of a WebRpc and provides convenient access to most common values. +/// +/// See method PhotonNetwork.WebRpc.
+/// Create a WebRpcResponse to access common result values.
+/// The operationResponse.OperationCode should be: OperationCode.WebRpc.
+///
+public class WebRpcResponse +{ + /// Name of the WebRpc that was called. + public string Name { get; private set; } + /// ReturnCode of the WebService that answered the WebRpc. + /// + /// 0 is commonly used to signal success.
+ /// -1 tells you: Got no ReturnCode from WebRpc service.
+ /// Other ReturnCodes are defined by the individual WebRpc and service. + ///
+ public int ReturnCode { get; private set; } + /// Might be empty or null. + public string DebugMessage { get; private set; } + /// Other key/values returned by the webservice that answered the WebRpc. + public Dictionary Parameters { get; private set; } + + /// An OperationResponse for a WebRpc is needed to read it's values. + public WebRpcResponse(OperationResponse response) + { + object value; + response.Parameters.TryGetValue(ParameterCode.UriPath, out value); + this.Name = value as string; + + response.Parameters.TryGetValue(ParameterCode.WebRpcReturnCode, out value); + this.ReturnCode = (value != null) ? (byte)value : -1; + + response.Parameters.TryGetValue(ParameterCode.WebRpcParameters, out value); + this.Parameters = value as Dictionary; + + response.Parameters.TryGetValue(ParameterCode.WebRpcReturnMessage, out value); + this.DebugMessage = value as string; + } + + /// Turns the response into an easier to read string. + /// String resembling the result. + public string ToStringFull() + { + return string.Format("{0}={2}: {1} \"{3}\"", Name, SupportClassPun.DictionaryToString(Parameters), ReturnCode, DebugMessage); + } +} + +/** +public class PBitStream +{ + List streamBytes; + private int currentByte; + private int totalBits = 0; + + public int ByteCount + { + get { return BytesForBits(this.totalBits); } + } + + public int BitCount + { + get { return this.totalBits; } + private set { this.totalBits = value; } + } + + public PBitStream() + { + this.streamBytes = new List(1); + } + + public PBitStream(int bitCount) + { + this.streamBytes = new List(BytesForBits(bitCount)); + } + + public PBitStream(IEnumerable bytes, int bitCount) + { + this.streamBytes = new List(bytes); + this.BitCount = bitCount; + } + + public static int BytesForBits(int bitCount) + { + if (bitCount <= 0) + { + return 0; + } + + return ((bitCount - 1) / 8) + 1; + } + + public void Add(bool val) + { + int bytePos = this.totalBits / 8; + if (bytePos > this.streamBytes.Count-1 || this.totalBits == 0) + { + this.streamBytes.Add(0); + } + + if (val) + { + int currentByteBit = 7 - (this.totalBits % 8); + this.streamBytes[bytePos] |= (byte)(1 << currentByteBit); + } + + this.totalBits++; + } + + public byte[] ToBytes() + { + return this.streamBytes.ToArray(); + } + + public int Position { get; set; } + + public bool GetNext() + { + if (this.Position > this.totalBits) + { + throw new Exception("End of PBitStream reached. Can't read more."); + } + + return Get(this.Position++); + } + + public bool Get(int bitIndex) + { + int byteIndex = bitIndex / 8; + int bitInByIndex = 7 - (bitIndex % 8); + return ((this.streamBytes[byteIndex] & (byte)(1 << bitInByIndex)) > 0); + } + + public void Set(int bitIndex, bool value) + { + int byteIndex = bitIndex / 8; + int bitInByIndex = 7 - (bitIndex % 8); + this.streamBytes[byteIndex] |= (byte)(1 << bitInByIndex); + } +} +**/ diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonClasses.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonClasses.cs.meta new file mode 100644 index 0000000..811f77b --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonClasses.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f40f16a0227e5c14293e269c875c0f9b +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonHandler.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonHandler.cs new file mode 100644 index 0000000..dc32628 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonHandler.cs @@ -0,0 +1,331 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Part of: Photon Unity Networking +// +// -------------------------------------------------------------------------------------------------------------------- + +using System; +using System.Collections; +using System.Diagnostics; +using ExitGames.Client.Photon; +using UnityEngine; +using Debug = UnityEngine.Debug; +using Hashtable = ExitGames.Client.Photon.Hashtable; +using SupportClassPun = ExitGames.Client.Photon.SupportClass; + +#if UNITY_5_5_OR_NEWER +using UnityEngine.Profiling; +#endif + + +#if UNITY_WEBGL +#pragma warning disable 0649 +#endif + +/// +/// Internal Monobehaviour that allows Photon to run an Update loop. +/// +internal class PhotonHandler : MonoBehaviour +{ + public static PhotonHandler SP; + + public int updateInterval; // time [ms] between consecutive SendOutgoingCommands calls + + public int updateIntervalOnSerialize; // time [ms] between consecutive RunViewUpdate calls (sending syncs, etc) + + private int nextSendTickCount = 0; + + private int nextSendTickCountOnSerialize = 0; + + private static bool sendThreadShouldRun; + + private static Stopwatch timerToStopConnectionInBackground; + + protected internal static bool AppQuits; + + protected internal static Type PingImplementation = null; + + protected void Awake() + { + if (SP != null && SP != this && SP.gameObject != null) + { + GameObject.DestroyImmediate(SP.gameObject); + } + + SP = this; + DontDestroyOnLoad(this.gameObject); + + this.updateInterval = 1000 / PhotonNetwork.sendRate; + this.updateIntervalOnSerialize = 1000 / PhotonNetwork.sendRateOnSerialize; + + PhotonHandler.StartFallbackSendAckThread(); + } + + + #if UNITY_5_4_OR_NEWER + + protected void Start() + { + UnityEngine.SceneManagement.SceneManager.sceneLoaded += (scene, loadingMode) => + { + PhotonNetwork.networkingPeer.NewSceneLoaded(); + PhotonNetwork.networkingPeer.SetLevelInPropsIfSynced(SceneManagerHelper.ActiveSceneName); + }; + } + + #else + + /// Called by Unity after a new level was loaded. + protected void OnLevelWasLoaded(int level) + { + PhotonNetwork.networkingPeer.NewSceneLoaded(); + PhotonNetwork.networkingPeer.SetLevelInPropsIfSynced(SceneManagerHelper.ActiveSceneName); + } + + #endif + + + /// Called by Unity when the application is closed. Disconnects. + protected void OnApplicationQuit() + { + PhotonHandler.AppQuits = true; + PhotonHandler.StopFallbackSendAckThread(); + PhotonNetwork.Disconnect(); + } + + /// + /// Called by Unity when the application gets paused (e.g. on Android when in background). + /// + /// + /// Sets a disconnect timer when PhotonNetwork.BackgroundTimeout > 0.1f. See PhotonNetwork.BackgroundTimeout. + /// + /// Some versions of Unity will give false values for pause on Android (and possibly on other platforms). + /// + /// If the app pauses. + protected void OnApplicationPause(bool pause) + { + if (PhotonNetwork.BackgroundTimeout > 0.1f) + { + if (timerToStopConnectionInBackground == null) + { + timerToStopConnectionInBackground = new Stopwatch(); + } + timerToStopConnectionInBackground.Reset(); + + if (pause) + { + timerToStopConnectionInBackground.Start(); + } + else + { + timerToStopConnectionInBackground.Stop(); + } + } + } + + /// Called by Unity when the play mode ends. Used to cleanup. + protected void OnDestroy() + { + //Debug.Log("OnDestroy on PhotonHandler."); + PhotonHandler.StopFallbackSendAckThread(); + //PhotonNetwork.Disconnect(); + } + + protected void Update() + { + if (PhotonNetwork.networkingPeer == null) + { + Debug.LogError("NetworkPeer broke!"); + return; + } + + if (PhotonNetwork.connectionStateDetailed == ClientState.PeerCreated || PhotonNetwork.connectionStateDetailed == ClientState.Disconnected || PhotonNetwork.offlineMode) + { + return; + } + + // the messageQueue might be paused. in that case a thread will send acknowledgements only. nothing else to do here. + if (!PhotonNetwork.isMessageQueueRunning) + { + return; + } + + bool doDispatch = true; + while (PhotonNetwork.isMessageQueueRunning && doDispatch) + { + // DispatchIncomingCommands() returns true of it found any command to dispatch (event, result or state change) + Profiler.BeginSample("DispatchIncomingCommands"); + doDispatch = PhotonNetwork.networkingPeer.DispatchIncomingCommands(); + Profiler.EndSample(); + } + + int currentMsSinceStart = (int)(Time.realtimeSinceStartup * 1000); // avoiding Environment.TickCount, which could be negative on long-running platforms + if (PhotonNetwork.isMessageQueueRunning && currentMsSinceStart > this.nextSendTickCountOnSerialize) + { + PhotonNetwork.networkingPeer.RunViewUpdate(); + this.nextSendTickCountOnSerialize = currentMsSinceStart + this.updateIntervalOnSerialize; + this.nextSendTickCount = 0; // immediately send when synchronization code was running + } + + currentMsSinceStart = (int)(Time.realtimeSinceStartup * 1000); + if (currentMsSinceStart > this.nextSendTickCount) + { + bool doSend = true; + while (PhotonNetwork.isMessageQueueRunning && doSend) + { + // Send all outgoing commands + Profiler.BeginSample("SendOutgoingCommands"); + doSend = PhotonNetwork.networkingPeer.SendOutgoingCommands(); + Profiler.EndSample(); + } + + this.nextSendTickCount = currentMsSinceStart + this.updateInterval; + } + } + + protected void OnJoinedRoom() + { + PhotonNetwork.networkingPeer.LoadLevelIfSynced(); + } + + protected void OnCreatedRoom() + { + PhotonNetwork.networkingPeer.SetLevelInPropsIfSynced(SceneManagerHelper.ActiveSceneName); + } + + public static void StartFallbackSendAckThread() + { + #if !UNITY_WEBGL + if (sendThreadShouldRun) + { + return; + } + + sendThreadShouldRun = true; + SupportClassPun.StartBackgroundCalls(FallbackSendAckThread); // thread will call this every 100ms until method returns false + #endif + } + + public static void StopFallbackSendAckThread() + { + #if !UNITY_WEBGL + sendThreadShouldRun = false; + #endif + } + + /// A thread which runs independent from the Update() calls. Keeps connections online while loading or in background. See PhotonNetwork.BackgroundTimeout. + public static bool FallbackSendAckThread() + { + if (sendThreadShouldRun && !PhotonNetwork.offlineMode && PhotonNetwork.networkingPeer != null) + { + // check if the client should disconnect after some seconds in background + if (timerToStopConnectionInBackground != null && PhotonNetwork.BackgroundTimeout > 0.1f) + { + if (timerToStopConnectionInBackground.ElapsedMilliseconds > PhotonNetwork.BackgroundTimeout * 1000) + { + if (PhotonNetwork.connected) + { + PhotonNetwork.Disconnect(); + } + timerToStopConnectionInBackground.Stop(); + timerToStopConnectionInBackground.Reset(); + return sendThreadShouldRun; + } + } + + if (!PhotonNetwork.isMessageQueueRunning || PhotonNetwork.networkingPeer.ConnectionTime - PhotonNetwork.networkingPeer.LastSendOutgoingTime > 200) + { + PhotonNetwork.networkingPeer.SendAcksOnly(); + } + } + + return sendThreadShouldRun; + } + + + #region Photon Cloud Ping Evaluation + + + private const string PlayerPrefsKey = "PUNCloudBestRegion"; + + internal static CloudRegionCode BestRegionCodeInPreferences + { + get + { + string prefsRegionCode = PlayerPrefs.GetString(PlayerPrefsKey, ""); + if (!string.IsNullOrEmpty(prefsRegionCode)) + { + CloudRegionCode loadedRegion = Region.Parse(prefsRegionCode); + return loadedRegion; + } + + return CloudRegionCode.none; + } + set + { + if (value == CloudRegionCode.none) + { + PlayerPrefs.DeleteKey(PlayerPrefsKey); + } + else + { + PlayerPrefs.SetString(PlayerPrefsKey, value.ToString()); + } + } + } + + + internal protected static void PingAvailableRegionsAndConnectToBest() + { + SP.StartCoroutine(SP.PingAvailableRegionsCoroutine(true)); + } + + + internal IEnumerator PingAvailableRegionsCoroutine(bool connectToBest) + { + while (PhotonNetwork.networkingPeer.AvailableRegions == null) + { + if (PhotonNetwork.connectionStateDetailed != ClientState.ConnectingToNameServer && PhotonNetwork.connectionStateDetailed != ClientState.ConnectedToNameServer) + { + Debug.LogError("Call ConnectToNameServer to ping available regions."); + yield break; // break if we don't connect to the nameserver at all + } + + Debug.Log("Waiting for AvailableRegions. State: " + PhotonNetwork.connectionStateDetailed + " Server: " + PhotonNetwork.Server + " PhotonNetwork.networkingPeer.AvailableRegions " + (PhotonNetwork.networkingPeer.AvailableRegions != null)); + yield return new WaitForSeconds(0.25f); // wait until pinging finished (offline mode won't ping) + } + + if (PhotonNetwork.networkingPeer.AvailableRegions == null || PhotonNetwork.networkingPeer.AvailableRegions.Count == 0) + { + Debug.LogError("No regions available. Are you sure your appid is valid and setup?"); + yield break; // break if we don't get regions at all + } + + PhotonPingManager pingManager = new PhotonPingManager(); + foreach (Region region in PhotonNetwork.networkingPeer.AvailableRegions) + { + SP.StartCoroutine(pingManager.PingSocket(region)); + } + + while (!pingManager.Done) + { + yield return new WaitForSeconds(0.1f); // wait until pinging finished (offline mode won't ping) + } + + + Region best = pingManager.BestRegion; + PhotonHandler.BestRegionCodeInPreferences = best.Code; + + Debug.Log("Found best region: '" + best.Code + "' ping: " + best.Ping + ". Calling ConnectToRegionMaster() is: " + connectToBest); + + if (connectToBest) + { + PhotonNetwork.networkingPeer.ConnectToRegionMaster(best.Code); + } + } + + + + #endregion + +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonHandler.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonHandler.cs.meta new file mode 100644 index 0000000..97b4d82 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonHandler.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 177bddf229f8d8445a70c0652f03b7df +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonLagSimulationGui.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonLagSimulationGui.cs new file mode 100644 index 0000000..0a15b0a --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonLagSimulationGui.cs @@ -0,0 +1,97 @@ +#pragma warning disable 1587 +/// \file +/// Part of the [Optional GUI](@ref optionalGui). +#pragma warning restore 1587 + + +using ExitGames.Client.Photon; +using UnityEngine; + + +/// +/// This MonoBehaviour is a basic GUI for the Photon client's network-simulation feature. +/// It can modify lag (fixed delay), jitter (random lag) and packet loss. +/// +/// \ingroup optionalGui +public class PhotonLagSimulationGui : MonoBehaviour +{ + /// Positioning rect for window. + public Rect WindowRect = new Rect(0, 100, 120, 100); + + /// Unity GUI Window ID (must be unique or will cause issues). + public int WindowId = 101; + + /// Shows or hides GUI (does not affect settings). + public bool Visible = true; + + /// The peer currently in use (to set the network simulation). + public PhotonPeer Peer { get; set; } + + public void Start() + { + this.Peer = PhotonNetwork.networkingPeer; + } + + public void OnGUI() + { + if (!this.Visible) + { + return; + } + + if (this.Peer == null) + { + this.WindowRect = GUILayout.Window(this.WindowId, this.WindowRect, this.NetSimHasNoPeerWindow, "Netw. Sim."); + } + else + { + this.WindowRect = GUILayout.Window(this.WindowId, this.WindowRect, this.NetSimWindow, "Netw. Sim."); + } + } + + private void NetSimHasNoPeerWindow(int windowId) + { + GUILayout.Label("No peer to communicate with. "); + } + + private void NetSimWindow(int windowId) + { + GUILayout.Label(string.Format("Rtt:{0,4} +/-{1,3}", this.Peer.RoundTripTime, this.Peer.RoundTripTimeVariance)); + + bool simEnabled = this.Peer.IsSimulationEnabled; + bool newSimEnabled = GUILayout.Toggle(simEnabled, "Simulate"); + if (newSimEnabled != simEnabled) + { + this.Peer.IsSimulationEnabled = newSimEnabled; + } + + float inOutLag = this.Peer.NetworkSimulationSettings.IncomingLag; + GUILayout.Label("Lag " + inOutLag); + inOutLag = GUILayout.HorizontalSlider(inOutLag, 0, 500); + + this.Peer.NetworkSimulationSettings.IncomingLag = (int)inOutLag; + this.Peer.NetworkSimulationSettings.OutgoingLag = (int)inOutLag; + + float inOutJitter = this.Peer.NetworkSimulationSettings.IncomingJitter; + GUILayout.Label("Jit " + inOutJitter); + inOutJitter = GUILayout.HorizontalSlider(inOutJitter, 0, 100); + + this.Peer.NetworkSimulationSettings.IncomingJitter = (int)inOutJitter; + this.Peer.NetworkSimulationSettings.OutgoingJitter = (int)inOutJitter; + + float loss = this.Peer.NetworkSimulationSettings.IncomingLossPercentage; + GUILayout.Label("Loss " + loss); + loss = GUILayout.HorizontalSlider(loss, 0, 10); + + this.Peer.NetworkSimulationSettings.IncomingLossPercentage = (int)loss; + this.Peer.NetworkSimulationSettings.OutgoingLossPercentage = (int)loss; + + // if anything was clicked, the height of this window is likely changed. reduce it to be layouted again next frame + if (GUI.changed) + { + this.WindowRect.height = 100; + } + + GUI.DragWindow(); + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonLagSimulationGui.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonLagSimulationGui.cs.meta new file mode 100644 index 0000000..3a15b86 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonLagSimulationGui.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5867a53c8db0e6745818285bb6b6e1b9 +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonNetwork.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonNetwork.cs new file mode 100644 index 0000000..be05c3c --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonNetwork.cs @@ -0,0 +1,3505 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Part of: Photon Unity Networking +// +// -------------------------------------------------------------------------------------------------------------------- + + +using System.Diagnostics; +using UnityEngine; +using System; +using System.Collections.Generic; +using ExitGames.Client.Photon; +using UnityEngine.SceneManagement; +using Debug = UnityEngine.Debug; +using Hashtable = ExitGames.Client.Photon.Hashtable; + +#if UNITY_EDITOR +using UnityEditor; +using System.IO; +#endif + + +/// +/// The main class to use the PhotonNetwork plugin. +/// This class is static. +/// +/// \ingroup publicApi +public static class PhotonNetwork +{ + /// Version number of PUN. Also used in GameVersion to separate client version from each other. + public const string versionPUN = "1.90"; + + /// Version string for your this build. Can be used to separate incompatible clients. Sent during connect. + /// This is only sent when you connect so that is also the place you set it usually (e.g. in ConnectUsingSettings). + public static string gameVersion { get; set; } + + /// + /// This Monobehaviour allows Photon to run an Update loop. + /// + internal static readonly PhotonHandler photonMono; + + /// + /// Photon peer class that implements LoadBalancing in PUN. + /// Primary use is internal (by PUN itself). + /// + internal static NetworkingPeer networkingPeer; + + /// + /// The maximum number of assigned PhotonViews per player (or scene). See the [General Documentation](@ref general) topic "Limitations" on how to raise this limitation. + /// + public static readonly int MAX_VIEW_IDS = 1000; // VIEW & PLAYER LIMIT CAN BE EASILY CHANGED, SEE DOCS + + + /// Name of the PhotonServerSettings file (used to load and by PhotonEditor to save new files). + internal const string serverSettingsAssetFile = "PhotonServerSettings"; + + /// Serialized server settings, written by the Setup Wizard for use in ConnectUsingSettings. + public static ServerSettings PhotonServerSettings = (ServerSettings)Resources.Load(PhotonNetwork.serverSettingsAssetFile, typeof(ServerSettings)); + + /// Currently used server address (no matter if master or game server). + public static string ServerAddress { get { return (networkingPeer != null) ? networkingPeer.ServerAddress : ""; } } + + /// Currently used Cloud Region (if any). As long as the client is not on a Master Server or Game Server, the region is not yet defined. + public static CloudRegionCode CloudRegion { get { return (networkingPeer != null && connected && Server!=ServerConnection.NameServer) ? networkingPeer.CloudRegion : CloudRegionCode.none; } } + + /// + /// False until you connected to Photon initially. True in offline mode, while connected to any server and even while switching servers. + /// + public static bool connected + { + get + { + if (offlineMode) + { + return true; + } + + if (networkingPeer == null) + { + return false; + } + + return !networkingPeer.IsInitialConnect && networkingPeer.State != ClientState.PeerCreated && networkingPeer.State != ClientState.Disconnected && networkingPeer.State != ClientState.Disconnecting && networkingPeer.State != ClientState.ConnectingToNameServer; + } + } + + /// + /// True when you called ConnectUsingSettings (or similar) until the low level connection to Photon gets established. + /// + public static bool connecting + { + get { return networkingPeer.IsInitialConnect && !offlineMode; } + } + + /// + /// A refined version of connected which is true only if your connection to the server is ready to accept operations like join, leave, etc. + /// + public static bool connectedAndReady + { + get + { + // connected property will check offlineMode and networkingPeer being null + if (!connected) + { + return false; + } + + if (offlineMode) + { + return true; + } + + switch (connectionStateDetailed) + { + case ClientState.PeerCreated: + case ClientState.Disconnected: + case ClientState.Disconnecting: + case ClientState.Authenticating: + case ClientState.ConnectingToGameserver: + case ClientState.ConnectingToMasterserver: + case ClientState.ConnectingToNameServer: + case ClientState.Joining: + return false; // we are not ready to execute any operations + } + + return true; + } + } + + /// + /// Simplified connection state + /// + public static ConnectionState connectionState + { + get + { + if (offlineMode) + { + return ConnectionState.Connected; + } + + if (networkingPeer == null) + { + return ConnectionState.Disconnected; + } + + switch (networkingPeer.PeerState) + { + case PeerStateValue.Disconnected: + return ConnectionState.Disconnected; + case PeerStateValue.Connecting: + return ConnectionState.Connecting; + case PeerStateValue.Connected: + return ConnectionState.Connected; + case PeerStateValue.Disconnecting: + return ConnectionState.Disconnecting; + case PeerStateValue.InitializingApplication: + return ConnectionState.InitializingApplication; + } + + return ConnectionState.Disconnected; + } + } + + /// + /// Detailed connection state (ignorant of PUN, so it can be "disconnected" while switching servers). + /// + /// + /// In OfflineMode, this is ClientState.Joined (after create/join) or it is ConnectedToMaster in all other cases. + /// + public static ClientState connectionStateDetailed + { + get + { + if (offlineMode) + { + return (offlineModeRoom != null) ? ClientState.Joined : ClientState.ConnectedToMaster; + } + + if (networkingPeer == null) + { + return ClientState.Disconnected; + } + + return networkingPeer.State; + } + } + + /// The server (type) this client is currently connected or connecting to. + /// Photon uses 3 different roles of servers: Name Server, Master Server and Game Server. + public static ServerConnection Server { get { return (PhotonNetwork.networkingPeer != null) ? PhotonNetwork.networkingPeer.Server : ServerConnection.NameServer; } } + + /// + /// A user's authentication values used during connect. + /// + /// + /// Set these before calling Connect if you want custom authentication. + /// These values set the userId, if and how that userId gets verified (server-side), etc.. + /// + /// If authentication fails for any values, PUN will call your implementation of OnCustomAuthenticationFailed(string debugMsg). + /// See: PhotonNetworkingMessage.OnCustomAuthenticationFailed + /// + public static AuthenticationValues AuthValues + { + get { return (networkingPeer != null) ? networkingPeer.AuthValues : null; } + set { if (networkingPeer != null) networkingPeer.AuthValues = value; } + } + + /// + /// Get the room we're currently in. Null if we aren't in any room. + /// + public static Room room + { + get + { + if (isOfflineMode) + { + return offlineModeRoom; + } + + return networkingPeer.CurrentRoom; + } + } + + /// If true, Instantiate methods will check if you are in a room and fail if you are not. + /// + /// Instantiating anything outside of a specific room is very likely to break things. + /// Turn this off only if you know what you do. + public static bool InstantiateInRoomOnly = true; + + /// + /// Network log level. Controls how verbose PUN is. + /// + public static PhotonLogLevel logLevel = PhotonLogLevel.ErrorsOnly; + + /// + /// The local PhotonPlayer. Always available and represents this player. + /// CustomProperties can be set before entering a room and will be synced as well. + /// + public static PhotonPlayer player + { + get + { + if (networkingPeer == null) + { + return null; // Surpress ExitApplication errors + } + + return networkingPeer.LocalPlayer; + } + } + + /// + /// The Master Client of the current room or null (outside of rooms). + /// + /// + /// Can be used as "authoritative" client/player to make descisions, run AI or other. + /// + /// If the current Master Client leaves the room (leave/disconnect), the server will quickly assign someone else. + /// If the current Master Client times out (closed app, lost connection, etc), messages sent to this client are + /// effectively lost for the others! A timeout can take 10 seconds in which no Master Client is active. + /// + /// Implement the method IPunCallbacks.OnMasterClientSwitched to be called when the Master Client switched. + /// + /// Use PhotonNetwork.SetMasterClient, to switch manually to some other player / client. + /// + /// With offlineMode == true, this always returns the PhotonNetwork.player. + /// + public static PhotonPlayer masterClient + { + get + { + if (offlineMode) + { + return PhotonNetwork.player; + } + + if (networkingPeer == null) + { + return null; + } + + return networkingPeer.GetPlayerWithId(networkingPeer.mMasterClientId); + } + } + + /// + /// Set to synchronize the player's nickname with everyone in the room(s) you enter. This sets PhotonNetwork.player.NickName. + /// + /// + /// The playerName is just a nickname and does not have to be unique or backed up with some account.
+ /// Set the value any time (e.g. before you connect) and it will be available to everyone you play with.
+ /// Access the names of players by: PhotonPlayer.NickName.
+ /// PhotonNetwork.otherPlayers is a list of other players - each contains the playerName the remote player set. + ///
+ public static string playerName + { + get + { + return networkingPeer.PlayerName; + } + + set + { + networkingPeer.PlayerName = value; + } + } + + /// The list of players in the current room, including the local player. + /// + /// This list is only valid, while the client is in a room. + /// It automatically gets updated when someone joins or leaves. + /// + /// This can be used to list all players in a room. + /// Each player's PhotonPlayer.customProperties are accessible (set and synchronized via + /// PhotonPlayer.SetCustomProperties). + /// + /// You can use a PhotonPlayer.TagObject to store an arbitrary object for reference. + /// That is not synchronized via the network. + /// + public static PhotonPlayer[] playerList + { + get + { + if (networkingPeer == null) + return new PhotonPlayer[0]; + + return networkingPeer.mPlayerListCopy; + } + } + + /// The list of players in the current room, excluding the local player. + /// + /// This list is only valid, while the client is in a room. + /// It automatically gets updated when someone joins or leaves. + /// + /// This can be used to list all other players in a room. + /// Each player's PhotonPlayer.customProperties are accessible (set and synchronized via + /// PhotonPlayer.SetCustomProperties). + /// + /// You can use a PhotonPlayer.TagObject to store an arbitrary object for reference. + /// That is not synchronized via the network. + /// + public static PhotonPlayer[] otherPlayers + { + get + { + if (networkingPeer == null) + return new PhotonPlayer[0]; + + return networkingPeer.mOtherPlayerListCopy; + } + } + + /// + /// Read-only list of friends, their online status and the room they are in. Null until initialized by a FindFriends call. + /// + /// + /// Do not modify this list! + /// It is internally handled by FindFriends and only available to read the values. + /// The value of FriendListAge tells you how old the data is in milliseconds. + /// + /// Don't get this list more often than useful (> 10 seconds). In best case, keep the list you fetch really short. + /// You could (e.g.) get the full list only once, then request a few updates only for friends who are online. + /// After a while (e.g. 1 minute), you can get the full list again (to update online states). + /// + public static List Friends { get; internal set; } + + /// + /// Age of friend list info (in milliseconds). It's 0 until a friend list is fetched. + /// + public static int FriendsListAge + { + get { return (networkingPeer != null) ? networkingPeer.FriendListAge : 0; } + } + + /// + /// The minimum difference that a Vector2 or Vector3(e.g. a transforms rotation) needs to change before we send it via a PhotonView's OnSerialize/ObservingComponent. + /// + /// + /// Note that this is the sqrMagnitude. E.g. to send only after a 0.01 change on the Y-axix, we use 0.01f*0.01f=0.0001f. As a remedy against float inaccuracy we use 0.000099f instead of 0.0001f. + /// + public static float precisionForVectorSynchronization = 0.000099f; + + /// + /// The minimum angle that a rotation needs to change before we send it via a PhotonView's OnSerialize/ObservingComponent. + /// + public static float precisionForQuaternionSynchronization = 1.0f; + + /// + /// The minimum difference between floats before we send it via a PhotonView's OnSerialize/ObservingComponent. + /// + public static float precisionForFloatSynchronization = 0.01f; + + /// + /// While enabled, the MonoBehaviours on which we call RPCs are cached, avoiding costly GetComponents() calls. + /// + /// + /// RPCs are called on the MonoBehaviours of a target PhotonView. Those have to be found via GetComponents. + /// + /// When set this to true, the list of MonoBehaviours gets cached in each PhotonView. + /// You can use photonView.RefreshRpcMonoBehaviourCache() to manually refresh a PhotonView's + /// list of MonoBehaviours on demand (when a new MonoBehaviour gets added to a networked GameObject, e.g.). + /// + public static bool UseRpcMonoBehaviourCache; + + /// + /// While enabled (true), Instantiate uses PhotonNetwork.PrefabCache to keep game objects in memory (improving instantiation of the same prefab). + /// + /// + /// Setting UsePrefabCache to false during runtime will not clear PrefabCache but will ignore it right away. + /// You could clean and modify the cache yourself. Read its comments. + /// + public static bool UsePrefabCache = true; + + /// + /// An Object Pool can be used to keep and reuse instantiated object instances. It replaced Unity's default Instantiate and Destroy methods. + /// + /// + /// To use a GameObject pool, implement IPunPrefabPool and assign it here. + /// Prefabs are identified by name. + /// + public static IPunPrefabPool PrefabPool { get { return networkingPeer.ObjectPool; } set { networkingPeer.ObjectPool = value; }} + + /// + /// Keeps references to GameObjects for frequent instantiation (out of memory instead of loading the Resources). + /// + /// + /// You should be able to modify the cache anytime you like, except while Instantiate is used. Best do it only in the main-Thread. + /// + public static Dictionary PrefabCache = new Dictionary(); + + /// + /// If not null, this is the (exclusive) list of GameObjects that get called by PUN SendMonoMessage(). + /// + /// + /// For all callbacks defined in PhotonNetworkingMessage, PUN will use SendMonoMessage and + /// call FindObjectsOfType() to find all scripts and GameObjects that might want a callback by PUN. + /// + /// PUN callbacks are not very frequent (in-game, property updates are most frequent) but + /// FindObjectsOfType is time consuming and with a large number of GameObjects, performance might + /// suffer. + /// + /// Optionally, SendMonoMessageTargets can be used to supply a list of target GameObjects. This + /// skips the FindObjectsOfType() but any GameObject that needs callbacks will have to Add itself + /// to this list. + /// + /// If null, the default behaviour is to do a SendMessage on each GameObject with a MonoBehaviour. + /// + public static HashSet SendMonoMessageTargets; + + + /// + /// Defines which classes can contain PUN Callback implementations. + /// + /// + /// This provides the option to optimize your runtime for speed.
+ /// The more specific this Type is, the fewer classes will be checked with reflection for callback methods. + ///
+ public static Type SendMonoMessageTargetType = typeof(MonoBehaviour); + + /// + /// Can be used to skip starting RPCs as Coroutine, which can be a performance issue. + /// + public static bool StartRpcsAsCoroutine = true; + + /// + /// Offline mode can be set to re-use your multiplayer code in singleplayer game modes. + /// When this is on PhotonNetwork will not create any connections and there is near to + /// no overhead. Mostly usefull for reusing RPC's and PhotonNetwork.Instantiate + /// + public static bool offlineMode + { + get + { + return isOfflineMode; + } + + set + { + if (value == isOfflineMode) + { + return; + } + + if (value && connected) + { + Debug.LogError("Can't start OFFLINE mode while connected!"); + return; + } + + if (networkingPeer.PeerState != PeerStateValue.Disconnected) + { + networkingPeer.Disconnect(); // Cleanup (also calls OnLeftRoom to reset stuff) + } + isOfflineMode = value; + if (isOfflineMode) + { + networkingPeer.ChangeLocalID(-1); + NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnConnectedToMaster); + } + else + { + offlineModeRoom = null; + networkingPeer.ChangeLocalID(-1); + } + } + } + + private static bool isOfflineMode = false; + private static Room offlineModeRoom = null; + + + /// Only used in Unity Networking. In PUN, set the number of players in PhotonNetwork.CreateRoom. + [Obsolete("Used for compatibility with Unity networking only.")] + public static int maxConnections; + + /// Defines if all clients in a room should load the same level as the Master Client (if that used PhotonNetwork.LoadLevel). + /// + /// To synchronize the loaded level, the Master Client should use PhotonNetwork.LoadLevel. + /// All clients will load the new scene when they get the update or when they join. + /// + /// Internally, a Custom Room Property is set for the loaded scene. When a client reads that + /// and is not in the same scene yet, it will immediately pause the Message Queue + /// (PhotonNetwork.isMessageQueueRunning = false) and load. When the scene finished loading, + /// PUN will automatically re-enable the Message Queue. + /// + public static bool automaticallySyncScene + { + get + { + return _mAutomaticallySyncScene; + } + set + { + _mAutomaticallySyncScene = value; + if (_mAutomaticallySyncScene && room != null) + { + networkingPeer.LoadLevelIfSynced(); + } + } + } + + private static bool _mAutomaticallySyncScene = false; + + /// + /// This setting defines per room, if network-instantiated GameObjects (with PhotonView) get cleaned up when the creator of it leaves. + /// + /// + /// This setting is done per room. It can't be changed in the room and it will override the settings of individual clients. + /// + /// If room.AutoCleanUp is enabled in a room, the PUN clients will destroy a player's GameObjects on leave. + /// This includes GameObjects manually instantiated (via RPCs, e.g.). + /// When enabled, the server will clean RPCs, instantiated GameObjects and PhotonViews of the leaving player, too. and + /// Players who join after someone left, won't get the events of that player anymore. + /// + /// Under the hood, this setting is stored as a Custom Room Property. + /// Enabled by default. + /// + public static bool autoCleanUpPlayerObjects + { + get + { + return m_autoCleanUpPlayerObjects; + } + set + { + if (room != null) + Debug.LogError("Setting autoCleanUpPlayerObjects while in a room is not supported."); + else m_autoCleanUpPlayerObjects = value; + } + } + + private static bool m_autoCleanUpPlayerObjects = true; + + /// + /// Set in PhotonServerSettings asset. Defines if the PhotonNetwork should join the "lobby" when connected to the Master server. + /// + /// + /// If this is false, OnConnectedToMaster() will be called when connection to the Master is available. + /// OnJoinedLobby() will NOT be called if this is false. + /// + /// Enabled by default. + /// + /// The room listing will not become available. + /// Rooms can be created and joined (randomly) without joining the lobby (and getting sent the room list). + /// + public static bool autoJoinLobby + { + get + { + return PhotonNetwork.PhotonServerSettings.JoinLobby; + } + set + { + PhotonNetwork.PhotonServerSettings.JoinLobby = value; + } + } + + + /// + /// Set in PhotonServerSettings asset. Enable to get a list of active lobbies from the Master Server. + /// + /// + /// Lobby Statistics can be useful if a game uses multiple lobbies and you want + /// to show activity of each to players. + /// + /// This value is stored in PhotonServerSettings. + /// + /// PhotonNetwork.LobbyStatistics is updated when you connect to the Master Server. + /// There is also a callback PunBehaviour. + /// + public static bool EnableLobbyStatistics + { + get + { + return PhotonNetwork.PhotonServerSettings.EnableLobbyStatistics; + } + set + { + PhotonNetwork.PhotonServerSettings.EnableLobbyStatistics = value; + } + } + + /// + /// If turned on, the Master Server will provide information about active lobbies for this application. + /// + /// + /// Lobby Statistics can be useful if a game uses multiple lobbies and you want + /// to show activity of each to players. Per lobby, you get: name, type, room- and player-count. + /// + /// PhotonNetwork.LobbyStatistics is updated when you connect to the Master Server. + /// There is also a callback PunBehaviour.OnLobbyStatisticsUpdate, which you should implement + /// to update your UI (e.g.). + /// + /// Lobby Statistics are not turned on by default. + /// Enable them in the PhotonServerSettings file of the project. + /// + public static List LobbyStatistics + { + get { return PhotonNetwork.networkingPeer.LobbyStatistics; } + // only available to reset the state conveniently. done by state updates of PUN + private set { PhotonNetwork.networkingPeer.LobbyStatistics = value; } + } + + + /// True while this client is in a lobby. + /// + /// Implement IPunCallbacks.OnReceivedRoomListUpdate() for a notification when the list of rooms + /// becomes available or updated. + /// + /// You are automatically leaving any lobby when you join a room! + /// Lobbies only exist on the Master Server (whereas rooms are handled by Game Servers). + /// + public static bool insideLobby + { + get + { + return networkingPeer.insideLobby; + } + } + + /// + /// The lobby that will be used when PUN joins a lobby or creates a game. + /// + /// + /// The default lobby uses an empty string as name. + /// PUN will enter a lobby on the Master Server if autoJoinLobby is set to true. + /// So when you connect or leave a room, PUN automatically gets you into a lobby again. + /// + /// Check PhotonNetwork.insideLobby if the client is in a lobby. + /// (@ref masterServerAndLobby) + /// + public static TypedLobby lobby + { + get { return networkingPeer.lobby; } + set { networkingPeer.lobby = value; } + } + + /// + /// Defines how many times per second PhotonNetwork should send a package. If you change + /// this, do not forget to also change 'sendRateOnSerialize'. + /// + /// + /// Less packages are less overhead but more delay. + /// Setting the sendRate to 50 will create up to 50 packages per second (which is a lot!). + /// Keep your target platform in mind: mobile networks are slower and less reliable. + /// + public static int sendRate + { + get + { + return 1000 / sendInterval; + } + + set + { + sendInterval = 1000 / value; + if (photonMono != null) + { + photonMono.updateInterval = sendInterval; + } + + if (value < sendRateOnSerialize) + { + // sendRateOnSerialize needs to be <= sendRate + sendRateOnSerialize = value; + } + } + } + + /// + /// Defines how many times per second OnPhotonSerialize should be called on PhotonViews. + /// + /// + /// Choose this value in relation to PhotonNetwork.sendRate. OnPhotonSerialize will create updates and messages to be sent.
+ /// A lower rate takes up less performance but will cause more lag. + ///
+ public static int sendRateOnSerialize + { + get + { + return 1000 / sendIntervalOnSerialize; + } + + set + { + if (value > sendRate) + { + Debug.LogError("Error: Can not set the OnSerialize rate higher than the overall SendRate."); + value = sendRate; + } + + sendIntervalOnSerialize = 1000 / value; + if (photonMono != null) + { + photonMono.updateIntervalOnSerialize = sendIntervalOnSerialize; + } + } + } + + private static int sendInterval = 50; // in miliseconds. + + private static int sendIntervalOnSerialize = 100; // in miliseconds. I.e. 100 = 100ms which makes 10 times/second + + /// + /// Can be used to pause dispatching of incoming evtents (RPCs, Instantiates and anything else incoming). + /// + /// + /// While IsMessageQueueRunning == false, the OnPhotonSerializeView calls are not done and nothing is sent by + /// a client. Also, incoming messages will be queued until you re-activate the message queue. + /// + /// This can be useful if you first want to load a level, then go on receiving data of PhotonViews and RPCs. + /// The client will go on receiving and sending acknowledgements for incoming packages and your RPCs/Events. + /// This adds "lag" and can cause issues when the pause is longer, as all incoming messages are just queued. + /// + public static bool isMessageQueueRunning + { + get + { + return m_isMessageQueueRunning; + } + + set + { + if (value) PhotonHandler.StartFallbackSendAckThread(); + networkingPeer.IsSendingOnlyAcks = !value; + m_isMessageQueueRunning = value; + } + } + + /// Backup for property isMessageQueueRunning. + private static bool m_isMessageQueueRunning = true; + + /// + /// Used once per dispatch to limit unreliable commands per channel (so after a pause, many channels can still cause a lot of unreliable commands) + /// + public static int unreliableCommandsLimit + { + get + { + return networkingPeer.LimitOfUnreliableCommands; + } + + set + { + networkingPeer.LimitOfUnreliableCommands = value; + } + } + + /// + /// Photon network time, synched with the server. + /// + /// + /// v1.55
+ /// This time value depends on the server's Environment.TickCount. It is different per server + /// but inside a Room, all clients should have the same value (Rooms are on one server only).
+ /// This is not a DateTime!
+ /// + /// Use this value with care:
+ /// It can start with any positive value.
+ /// It will "wrap around" from 4294967.295 to 0! + ///
+ public static double time + { + get + { + uint u = (uint)ServerTimestamp; + double t = u; + return t / 1000; + } + } + + /// + /// The current server's millisecond timestamp. + /// + /// + /// This can be useful to sync actions and events on all clients in one room. + /// The timestamp is based on the server's Environment.TickCount. + /// + /// It will overflow from a positive to a negative value every so often, so + /// be careful to use only time-differences to check the time delta when things + /// happen. + /// + /// This is the basis for PhotonNetwork.time. + /// + public static int ServerTimestamp + { + get + { + if (offlineMode) + { + if (UsePreciseTimer && startupStopwatch != null && startupStopwatch.IsRunning) + { + return (int)startupStopwatch.ElapsedMilliseconds; + } + return Environment.TickCount; + } + + return networkingPeer.ServerTimeInMilliSeconds; + } + } + + /// If true, PUN will use a Stopwatch to measure time since start/connect. This is more precise than the Environment.TickCount used by default. + private static bool UsePreciseTimer = false; + static Stopwatch startupStopwatch; + + /// + /// Defines how many seconds PUN keeps the connection, after Unity's OnApplicationPause(true) call. Default: 60 seconds. + /// + /// + /// It's best practice to disconnect inactive apps/connections after a while but to also allow users to take calls, etc.. + /// We think a reasonable backgroung timeout is 60 seconds. + /// + /// To handle the timeout, implement: OnDisconnectedFromPhoton(), as usual. + /// Your application will "notice" the background disconnect when it becomes active again (running the Update() loop). + /// + /// If you need to separate this case from others, you need to track if the app was in the background + /// (there is no special callback by PUN). + /// + /// A value below 0.1 seconds will disable this timeout (careful: connections can be kept indefinitely). + /// + /// + /// Info: + /// PUN is running a "fallback thread" to send ACKs to the server, even when Unity is not calling Update() regularly. + /// This helps keeping the connection while loading scenes and assets and when the app is in the background. + /// + /// Note: + /// Some platforms (e.g. iOS) don't allow to keep a connection while the app is in background. + /// In those cases, this value does not change anything, the app immediately loses connection in background. + /// + /// Unity's OnApplicationPause() callback is broken in some exports (Android) of some Unity versions. + /// Make sure OnApplicationPause() gets the callbacks you'd expect on the platform you target! + /// Check PhotonHandler.OnApplicationPause(bool pause), to see the implementation. + /// + public static float BackgroundTimeout = 60.0f; + + /// + /// Are we the master client? + /// + public static bool isMasterClient + { + get + { + if (offlineMode) + { + return true; + } + else + { + return networkingPeer.mMasterClientId == player.ID; + } + } + } + + /// Is true while being in a room (connectionStateDetailed == ClientState.Joined). + /// + /// Many actions can only be executed in a room, like Instantiate or Leave, etc. + /// You can join a room in offline mode, too. + /// + public static bool inRoom + { + get + { + // in offline mode, you can be in a room too and connectionStateDetailed then returns Joined like on online mode! + return connectionStateDetailed == ClientState.Joined; + } + } + + /// + /// True if we are in a room (client) and NOT the room's masterclient + /// + public static bool isNonMasterClientInRoom + { + get + { + return !isMasterClient && room != null; + } + } + + /// + /// The count of players currently looking for a room (available on MasterServer in 5sec intervals). + /// + public static int countOfPlayersOnMaster + { + get + { + return networkingPeer.PlayersOnMasterCount; + } + } + + /// + /// Count of users currently playing your app in some room (sent every 5sec by Master Server). + /// Use PhotonNetwork.playerList.Length or PhotonNetwork.room.PlayerCount to get the count of players in the room you're in! + /// + public static int countOfPlayersInRooms + { + get + { + return networkingPeer.PlayersInRoomsCount; + } + } + + /// + /// The count of players currently using this application (available on MasterServer in 5sec intervals). + /// + public static int countOfPlayers + { + get + { + return networkingPeer.PlayersInRoomsCount + networkingPeer.PlayersOnMasterCount; + } + } + + /// + /// The count of rooms currently in use (available on MasterServer in 5sec intervals). + /// + /// + /// While inside the lobby you can also check the count of listed rooms as: PhotonNetwork.GetRoomList().Length. + /// Since PUN v1.25 this is only based on the statistic event Photon sends (counting all rooms). + /// + public static int countOfRooms + { + get + { + return networkingPeer.RoomsCount; + } + } + + /// + /// Enables or disables the collection of statistics about this client's traffic. + /// + /// + /// If you encounter issues with clients, the traffic stats are a good starting point to find solutions. + /// Only with enabled stats, you can use GetVitalStats + /// + public static bool NetworkStatisticsEnabled + { + get + { + return networkingPeer.TrafficStatsEnabled; + } + + set + { + networkingPeer.TrafficStatsEnabled = value; + } + } + + /// + /// Count of commands that got repeated (due to local repeat-timing before an ACK was received). + /// + /// + /// If this value increases a lot, there is a good chance that a timeout disconnect will happen due to bad conditions. + /// + public static int ResentReliableCommands + { + get { return networkingPeer.ResentReliableCommands; } + } + + /// Crc checks can be useful to detect and avoid issues with broken datagrams. Can be enabled while not connected. + public static bool CrcCheckEnabled + { + get { return networkingPeer.CrcEnabled; } + set + { + if (!connected && !connecting) + { + networkingPeer.CrcEnabled = value; + } + else + { + Debug.Log("Can't change CrcCheckEnabled while being connected. CrcCheckEnabled stays " + networkingPeer.CrcEnabled); + } + } + } + + /// If CrcCheckEnabled, this counts the incoming packages that don't have a valid CRC checksum and got rejected. + public static int PacketLossByCrcCheck + { + get { return networkingPeer.PacketLossByCrc; } + } + + /// Defines the number of times a reliable message can be resent before not getting an ACK for it will trigger a disconnect. Default: 5. + /// Less resends mean quicker disconnects, while more can lead to much more lag without helping. Min: 3. Max: 10. + public static int MaxResendsBeforeDisconnect + { + get { return networkingPeer.SentCountAllowance; } + set + { + if (value < 3) value = 3; + if (value > 10) value = 10; + networkingPeer.SentCountAllowance = value; + } + } + + /// In case of network loss, reliable messages can be repeated quickly up to 3 times. + /// + /// When reliable messages get lost more than once, subsequent repeats are delayed a bit + /// to allow the network to recover.
+ /// With this option, the repeats 2 and 3 can be sped up. This can help avoid timeouts but + /// also it increases the speed in which gaps are closed.
+ /// When you set this, increase PhotonNetwork.MaxResendsBeforeDisconnect to 6 or 7. + ///
+ public static int QuickResends + { + get { return networkingPeer.QuickResendAttempts; } + set + { + if (value < 0) value = 0; + if (value > 3) value = 3; + networkingPeer.QuickResendAttempts = (byte)value; + } + } + + /// Switch to alternative ports for a UDP connection to the Public Cloud. + /// + /// This should be used when a customer has issues with connection stability. Some players + /// reported better connectivity for Steam games. The effect might vary, which is why the + /// alternative ports are not the new default. + /// + /// The alternative (server) ports are 27000 up to 27003. + /// + /// The values are appplied by replacing any incoming server-address string accordingly. + /// You only need to set this to true though. + /// + /// This value does not affect TCP or WebSocket connections. + /// + public static bool UseAlternativeUdpPorts { get; set; } + + + /// + /// Defines the delegate usable in OnEventCall. + /// + /// Any eventCode < 200 will be forwarded to your delegate(s). + /// The code assigend to the incoming event. + /// The content the sender put into the event. + /// The ID of the player who sent the event. It might be 0, if the "room" sent the event. + public delegate void EventCallback(byte eventCode, object content, int senderId); + + /// Register your RaiseEvent handling methods here by using "+=". + /// Any eventCode < 200 will be forwarded to your delegate(s). + /// + public static EventCallback OnEventCall; + + + internal static int lastUsedViewSubId = 0; // each player only needs to remember it's own (!) last used subId to speed up assignment + internal static int lastUsedViewSubIdStatic = 0; // per room, the master is able to instantiate GOs. the subId for this must be unique too + internal static List manuallyAllocatedViewIds = new List(); + + /// + /// Static constructor used for basic setup. + /// + static PhotonNetwork() + { + #if UNITY_EDITOR + if (PhotonServerSettings == null) + { + // create PhotonServerSettings + CreateSettings(); + } + + if (!EditorApplication.isPlaying && !EditorApplication.isPlayingOrWillChangePlaymode) + { + //Debug.Log(string.Format("PhotonNetwork.ctor() Not playing {0} {1}", UnityEditor.EditorApplication.isPlaying, UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)); + return; + } + + // This can happen when you recompile a script IN play made + // This helps to surpress some errors, but will not fix breaking + PhotonHandler[] photonHandlers = GameObject.FindObjectsOfType(typeof(PhotonHandler)) as PhotonHandler[]; + if (photonHandlers != null && photonHandlers.Length > 0) + { + Debug.LogWarning("Unity recompiled. Connection gets closed and replaced. You can connect as 'new' client."); + foreach (PhotonHandler photonHandler in photonHandlers) + { + //Debug.Log("Handler: " + photonHandler + " photonHandler.gameObject: " + photonHandler.gameObject); + photonHandler.gameObject.hideFlags = 0; + GameObject.DestroyImmediate(photonHandler.gameObject); + Component.DestroyImmediate(photonHandler); + } + } + #endif + + if (PhotonServerSettings != null) + { + Application.runInBackground = PhotonServerSettings.RunInBackground; + } + + // Set up a MonoBehaviour to run Photon, and hide it + GameObject photonGO = new GameObject(); + photonMono = (PhotonHandler)photonGO.AddComponent(); + photonGO.name = "PhotonMono"; + photonGO.hideFlags = HideFlags.HideInHierarchy; + + + // Set up the NetworkingPeer and use protocol of PhotonServerSettings + ConnectionProtocol protocol = PhotonNetwork.PhotonServerSettings.Protocol; + networkingPeer = new NetworkingPeer(string.Empty, protocol); + networkingPeer.QuickResendAttempts = 2; + networkingPeer.SentCountAllowance = 7; + + + #if !UNITY_EDITOR && UNITY_XBOXONE + networkingPeer.AuthMode = AuthModeOption.Auth; + #endif + + if (UsePreciseTimer) + { + Debug.Log("Using Stopwatch as precision timer for PUN."); + startupStopwatch = new Stopwatch(); + startupStopwatch.Start(); + networkingPeer.LocalMsTimestampDelegate = () => (int)startupStopwatch.ElapsedMilliseconds; + } + + // Local player + CustomTypes.Register(); + } + + /// + /// While offline, the network protocol can be switched (which affects the ports you can use to connect). + /// + /// + /// When you switch the protocol, make sure to also switch the port for the master server. Default ports are: + /// TCP: 4530 + /// UDP: 5055 + /// + /// This could look like this:
+ /// Connect(serverAddress, , appID, gameVersion) + /// + /// Or when you use ConnectUsingSettings(), the PORT in the settings can be switched like so:
+ /// PhotonNetwork.PhotonServerSettings.ServerPort = 4530; + /// + /// The current protocol can be read this way:
+ /// PhotonNetwork.networkingPeer.UsedProtocol + /// + /// This does not work with the native socket plugin of PUN+ on mobile! + ///
+ /// Network protocol to use as low level connection. UDP is default. TCP is not available on all platforms (see remarks). + public static void SwitchToProtocol(ConnectionProtocol cp) + { + // Debug.Log("SwitchToProtocol: " + cp + " PhotonNetwork.connected: " + PhotonNetwork.connected); + networkingPeer.TransportProtocol = cp; + } + + + /// Connect to Photon as configured in the editor (saved in PhotonServerSettings file). + /// + /// This method will disable offlineMode (which won't destroy any instantiated GOs) and it + /// will set isMessageQueueRunning to true. + /// + /// Your server configuration is created by the PUN Wizard and contains the AppId and + /// region for Photon Cloud games and the server address if you host Photon yourself. + /// These settings usually don't change often. + /// + /// To ignore the config file and connect anywhere call: PhotonNetwork.ConnectToMaster. + /// + /// To connect to the Photon Cloud, a valid AppId must be in the settings file (shown in the Photon Cloud Dashboard). + /// https://www.photonengine.com/dashboard + /// + /// Connecting to the Photon Cloud might fail due to: + /// - Invalid AppId (calls: OnFailedToConnectToPhoton(). check exact AppId value) + /// - Network issues (calls: OnFailedToConnectToPhoton()) + /// - Invalid region (calls: OnConnectionFail() with DisconnectCause.InvalidRegion) + /// - Subscription CCU limit reached (calls: OnConnectionFail() with DisconnectCause.MaxCcuReached. also calls: OnPhotonMaxCccuReached()) + /// + /// + /// This client's version number. Users are separated from each other by gameversion (which allows you to make breaking changes). + public static bool ConnectUsingSettings(string gameVersion) + { + if (networkingPeer.PeerState != PeerStateValue.Disconnected) + { + Debug.LogWarning("ConnectUsingSettings() failed. Can only connect while in state 'Disconnected'. Current state: " + networkingPeer.PeerState); + return false; + } + if (PhotonServerSettings == null) + { + Debug.LogError("Can't connect: Loading settings failed. ServerSettings asset must be in any 'Resources' folder as: " + serverSettingsAssetFile); + return false; + } + if (PhotonServerSettings.HostType == ServerSettings.HostingOption.NotSet) + { + Debug.LogError("You did not select a Hosting Type in your PhotonServerSettings. Please set it up or don't use ConnectUsingSettings()."); + return false; + } + + // only apply Settings if logLevel is default ( see ServerSettings.cs), else it means it's been set programmatically + if (PhotonNetwork.logLevel == PhotonLogLevel.ErrorsOnly) + { + PhotonNetwork.logLevel = PhotonServerSettings.PunLogging; + } + + // only apply Settings if logLevel is default ( see ServerSettings.cs), else it means it's been set programmatically + if (PhotonNetwork.networkingPeer.DebugOut == DebugLevel.ERROR) + { + PhotonNetwork.networkingPeer.DebugOut = PhotonServerSettings.NetworkLogging; + } + + + SwitchToProtocol(PhotonServerSettings.Protocol); + networkingPeer.SetApp(PhotonServerSettings.AppID, gameVersion); + + if (PhotonServerSettings.HostType == ServerSettings.HostingOption.OfflineMode) + { + offlineMode = true; + return true; + } + + if (offlineMode) + { + // someone can set offlineMode in code and then call ConnectUsingSettings() with non-offline settings. Warning for that case: + Debug.LogWarning("ConnectUsingSettings() disabled the offline mode. No longer offline."); + } + + offlineMode = false; // Cleanup offline mode + isMessageQueueRunning = true; + networkingPeer.IsInitialConnect = true; + + if (PhotonServerSettings.HostType == ServerSettings.HostingOption.SelfHosted) + { + networkingPeer.IsUsingNameServer = false; + networkingPeer.MasterServerAddress = (PhotonServerSettings.ServerPort == 0) ? PhotonServerSettings.ServerAddress : PhotonServerSettings.ServerAddress + ":" + PhotonServerSettings.ServerPort; + + return networkingPeer.Connect(networkingPeer.MasterServerAddress, ServerConnection.MasterServer); + } + + if (PhotonServerSettings.HostType == ServerSettings.HostingOption.BestRegion) + { + return ConnectToBestCloudServer(gameVersion); + } + + return networkingPeer.ConnectToRegionMaster(PhotonServerSettings.PreferredRegion); + } + + /// Connect to a Photon Master Server by address, port, appID and game(client) version. + /// + /// To connect to the Photon Cloud, a valid AppId must be in the settings file (shown in the Photon Cloud Dashboard). + /// https://www.photonengine.com/dashboard + /// + /// Connecting to the Photon Cloud might fail due to: + /// - Invalid AppId (calls: OnFailedToConnectToPhoton(). check exact AppId value) + /// - Network issues (calls: OnFailedToConnectToPhoton()) + /// - Invalid region (calls: OnConnectionFail() with DisconnectCause.InvalidRegion) + /// - Subscription CCU limit reached (calls: OnConnectionFail() with DisconnectCause.MaxCcuReached. also calls: OnPhotonMaxCccuReached()) + /// + /// + /// The server's address (either your own or Photon Cloud address). + /// The server's port to connect to. + /// Your application ID (Photon Cloud provides you with a GUID for your game). + /// This client's version number. Users are separated by gameversion (which allows you to make breaking changes). + public static bool ConnectToMaster(string masterServerAddress, int port, string appID, string gameVersion) + { + if (networkingPeer.PeerState != PeerStateValue.Disconnected) + { + Debug.LogWarning("ConnectToMaster() failed. Can only connect while in state 'Disconnected'. Current state: " + networkingPeer.PeerState); + return false; + } + + if (offlineMode) + { + offlineMode = false; // Cleanup offline mode + Debug.LogWarning("ConnectToMaster() disabled the offline mode. No longer offline."); + } + + if (!isMessageQueueRunning) + { + isMessageQueueRunning = true; + Debug.LogWarning("ConnectToMaster() enabled isMessageQueueRunning. Needs to be able to dispatch incoming messages."); + } + + networkingPeer.SetApp(appID, gameVersion); + networkingPeer.IsUsingNameServer = false; + networkingPeer.IsInitialConnect = true; + networkingPeer.MasterServerAddress = (port == 0) ? masterServerAddress : masterServerAddress + ":" + port; + + return networkingPeer.Connect(networkingPeer.MasterServerAddress, ServerConnection.MasterServer); + } + + /// Can be used to reconnect to the master server after a disconnect. + /// + /// After losing connection, you can use this to connect a client to the region Master Server again. + /// Cache the room name you're in and use ReJoin(roomname) to return to a game. + /// Common use case: Press the Lock Button on a iOS device and you get disconnected immediately. + /// + public static bool Reconnect() + { + if (string.IsNullOrEmpty(networkingPeer.MasterServerAddress)) + { + Debug.LogWarning("Reconnect() failed. It seems the client wasn't connected before?! Current state: " + networkingPeer.PeerState); + return false; + } + + if (networkingPeer.PeerState != PeerStateValue.Disconnected) + { + Debug.LogWarning("Reconnect() failed. Can only connect while in state 'Disconnected'. Current state: " + networkingPeer.PeerState); + return false; + } + + if (offlineMode) + { + offlineMode = false; // Cleanup offline mode + Debug.LogWarning("Reconnect() disabled the offline mode. No longer offline."); + } + + if (!isMessageQueueRunning) + { + isMessageQueueRunning = true; + Debug.LogWarning("Reconnect() enabled isMessageQueueRunning. Needs to be able to dispatch incoming messages."); + } + + networkingPeer.IsUsingNameServer = false; + networkingPeer.IsInitialConnect = false; + return networkingPeer.ReconnectToMaster(); + } + + + /// When the client lost connection during gameplay, this method attempts to reconnect and rejoin the room. + /// + /// This method re-connects directly to the game server which was hosting the room PUN was in before. + /// If the room was shut down in the meantime, PUN will call OnPhotonJoinRoomFailed and return this client to the Master Server. + /// + /// Check the return value, if this client will attempt a reconnect and rejoin (if the conditions are met). + /// If ReconnectAndRejoin returns false, you can still attempt a Reconnect and ReJoin. + /// + /// Similar to PhotonNetwork.ReJoin, this requires you to use unique IDs per player (the UserID). + /// + /// False, if there is no known room or game server to return to. Then, this client does not attempt the ReconnectAndRejoin. + public static bool ReconnectAndRejoin() + { + if (networkingPeer.PeerState != PeerStateValue.Disconnected) + { + Debug.LogWarning("ReconnectAndRejoin() failed. Can only connect while in state 'Disconnected'. Current state: " + networkingPeer.PeerState); + return false; + } + if (offlineMode) + { + offlineMode = false; // Cleanup offline mode + Debug.LogWarning("ReconnectAndRejoin() disabled the offline mode. No longer offline."); + } + + if (string.IsNullOrEmpty(networkingPeer.GameServerAddress)) + { + Debug.LogWarning("ReconnectAndRejoin() failed. It seems the client wasn't connected to a game server before (no address)."); + return false; + } + if (networkingPeer.enterRoomParamsCache == null) + { + Debug.LogWarning("ReconnectAndRejoin() failed. It seems the client doesn't have any previous room to re-join."); + return false; + } + + if (!isMessageQueueRunning) + { + isMessageQueueRunning = true; + Debug.LogWarning("ReconnectAndRejoin() enabled isMessageQueueRunning. Needs to be able to dispatch incoming messages."); + } + + networkingPeer.IsUsingNameServer = false; + networkingPeer.IsInitialConnect = false; + return networkingPeer.ReconnectAndRejoin(); + } + + + /// + /// Connect to the Photon Cloud region with the lowest ping (on platforms that support Unity's Ping). + /// + /// + /// Will save the result of pinging all cloud servers in PlayerPrefs. Calling this the first time can take +-2 seconds. + /// The ping result can be overridden via PhotonNetwork.OverrideBestCloudServer(..) + /// This call can take up to 2 seconds if it is the first time you are using this, all cloud servers will be pinged to check for the best region. + /// + /// The PUN Setup Wizard stores your appID in a settings file and applies a server address/port. + /// To connect to the Photon Cloud, a valid AppId must be in the settings file (shown in the Photon Cloud Dashboard). + /// https://www.photonengine.com/dashboard + /// + /// Connecting to the Photon Cloud might fail due to: + /// - Invalid AppId (calls: OnFailedToConnectToPhoton(). check exact AppId value) + /// - Network issues (calls: OnFailedToConnectToPhoton()) + /// - Invalid region (calls: OnConnectionFail() with DisconnectCause.InvalidRegion) + /// - Subscription CCU limit reached (calls: OnConnectionFail() with DisconnectCause.MaxCcuReached. also calls: OnPhotonMaxCccuReached()) + /// + /// + /// This client's version number. Users are separated from each other by gameversion (which allows you to make breaking changes). + /// If this client is going to connect to cloud server based on ping. Even if true, this does not guarantee a connection but the attempt is being made. + public static bool ConnectToBestCloudServer(string gameVersion) + { + if (networkingPeer.PeerState != PeerStateValue.Disconnected) + { + Debug.LogWarning("ConnectToBestCloudServer() failed. Can only connect while in state 'Disconnected'. Current state: " + networkingPeer.PeerState); + return false; + } + + if (PhotonServerSettings == null) + { + Debug.LogError("Can't connect: Loading settings failed. ServerSettings asset must be in any 'Resources' folder as: " + PhotonNetwork.serverSettingsAssetFile); + return false; + } + + if (PhotonServerSettings.HostType == ServerSettings.HostingOption.OfflineMode) + { + return PhotonNetwork.ConnectUsingSettings(gameVersion); + } + + networkingPeer.IsInitialConnect = true; + networkingPeer.SetApp(PhotonServerSettings.AppID, gameVersion); + + bool couldConnect = PhotonNetwork.networkingPeer.ConnectToNameServer(); + return couldConnect; + } + + + /// + /// Connects to the Photon Cloud region of choice. + /// + public static bool ConnectToRegion(CloudRegionCode region, string gameVersion) + { + if (networkingPeer.PeerState != PeerStateValue.Disconnected) + { + Debug.LogWarning("ConnectToRegion() failed. Can only connect while in state 'Disconnected'. Current state: " + networkingPeer.PeerState); + return false; + } + + if (PhotonServerSettings == null) + { + Debug.LogError("Can't connect: ServerSettings asset must be in any 'Resources' folder as: " + PhotonNetwork.serverSettingsAssetFile); + return false; + } + + if (PhotonServerSettings.HostType == ServerSettings.HostingOption.OfflineMode) + { + return PhotonNetwork.ConnectUsingSettings(gameVersion); + } + + networkingPeer.IsInitialConnect = true; + networkingPeer.SetApp(PhotonServerSettings.AppID, gameVersion); + + if (region != CloudRegionCode.none) + { + Debug.Log("ConnectToRegion: " + region); + return networkingPeer.ConnectToRegionMaster(region); + } + + return false; + } + + /// Overwrites the region that is used for ConnectToBestCloudServer(string gameVersion). + /// + /// This will overwrite the result of pinging all cloud servers.
+ /// Use this to allow your users to save a manually selected region in the player preferences.
+ /// Note: You can also use PhotonNetwork.ConnectToRegion to (temporarily) connect to a specific region. + ///
+ public static void OverrideBestCloudServer(CloudRegionCode region) + { + PhotonHandler.BestRegionCodeInPreferences = region; + } + + /// Pings all cloud servers again to find the one with best ping (currently). + public static void RefreshCloudServerRating() + { + throw new NotImplementedException("not available at the moment"); + } + + + /// + /// Resets the traffic stats and re-enables them. + /// + public static void NetworkStatisticsReset() + { + networkingPeer.TrafficStatsReset(); + } + + + /// + /// Only available when NetworkStatisticsEnabled was used to gather some stats. + /// + /// A string with vital networking statistics. + public static string NetworkStatisticsToString() + { + if (networkingPeer == null || offlineMode) + { + return "Offline or in OfflineMode. No VitalStats available."; + } + + return networkingPeer.VitalStatsToString(false); + } + + /// + /// Used for compatibility with Unity networking only. Encryption is automatically initialized while connecting. + /// + [Obsolete("Used for compatibility with Unity networking only. Encryption is automatically initialized while connecting.")] + public static void InitializeSecurity() + { + return; + } + + /// + /// Helper function which is called inside this class to erify if certain functions can be used (e.g. RPC when not connected) + /// + /// + private static bool VerifyCanUseNetwork() + { + if (connected) + { + return true; + } + + Debug.LogError("Cannot send messages when not connected. Either connect to Photon OR use offline mode!"); + return false; + } + + /// + /// Makes this client disconnect from the photon server, a process that leaves any room and calls OnDisconnectedFromPhoton on completion. + /// + /// + /// When you disconnect, the client will send a "disconnecting" message to the server. This speeds up leave/disconnect + /// messages for players in the same room as you (otherwise the server would timeout this client's connection). + /// When used in offlineMode, the state-change and event-call OnDisconnectedFromPhoton are immediate. + /// Offline mode is set to false as well. + /// Once disconnected, the client can connect again. Use ConnectUsingSettings. + /// + public static void Disconnect() + { + if (offlineMode) + { + offlineMode = false; + offlineModeRoom = null; + networkingPeer.State = ClientState.Disconnecting; + networkingPeer.OnStatusChanged(StatusCode.Disconnect); + return; + } + + if (networkingPeer == null) + { + return; // Surpress error when quitting playmode in the editor + } + + networkingPeer.Disconnect(); + } + + /// + /// Requests the rooms and online status for a list of friends and saves the result in PhotonNetwork.Friends. + /// + /// + /// Works only on Master Server to find the rooms played by a selected list of users. + /// + /// The result will be stored in PhotonNetwork.Friends when available. + /// That list is initialized on first use of OpFindFriends (before that, it is null). + /// To refresh the list, call FindFriends again (in 5 seconds or 10 or 20). + /// + /// Users identify themselves by setting a unique userId in the PhotonNetwork.AuthValues. + /// See remarks of AuthenticationValues for info about how this is set and used. + /// + /// The list of friends must be fetched from some other source (not provided by Photon). + /// + /// + /// Internal: + /// The server response includes 2 arrays of info (each index matching a friend from the request): + /// ParameterCode.FindFriendsResponseOnlineList = bool[] of online states + /// ParameterCode.FindFriendsResponseRoomIdList = string[] of room names (empty string if not in a room) + /// + /// Array of friend (make sure to use unique playerName or AuthValues). + /// If the operation could be sent (requires connection, only one request is allowed at any time). Always false in offline mode. + public static bool FindFriends(string[] friendsToFind) + { + if (networkingPeer == null || isOfflineMode) + { + return false; + } + + return networkingPeer.OpFindFriends(friendsToFind); + } + + + /// + /// Creates a room with given name but fails if this room(name) is existing already. Creates random name for roomName null. + /// + /// + /// If you don't want to create a unique room-name, pass null or "" as name and the server will assign a roomName (a GUID as string). + /// + /// The created room is automatically placed in the currently used lobby (if any) or the default-lobby if you didn't explicitly join one. + /// + /// Call this only on the master server. + /// Internally, the master will respond with a server-address (and roomName, if needed). Both are used internally + /// to switch to the assigned game server and roomName. + /// + /// PhotonNetwork.autoCleanUpPlayerObjects will become this room's AutoCleanUp property and that's used by all clients that join this room. + /// + /// Unique name of the room to create. + /// If the operation got queued and will be sent. + public static bool CreateRoom(string roomName) + { + return CreateRoom(roomName, null, null, null); + } + + /// + /// Creates a room but fails if this room is existing already. Can only be called on Master Server. + /// + /// + /// When successful, this calls the callbacks OnCreatedRoom and OnJoinedRoom (the latter, cause you join as first player). + /// If the room can't be created (because it exists already), OnPhotonCreateRoomFailed gets called. + /// + /// If you don't want to create a unique room-name, pass null or "" as name and the server will assign a roomName (a GUID as string). + /// + /// Rooms can be created in any number of lobbies. Those don't have to exist before you create a room in them (they get + /// auto-created on demand). Lobbies can be useful to split room lists on the server-side already. That can help keep the room + /// lists short and manageable. + /// If you set a typedLobby parameter, the room will be created in that lobby (no matter if you are active in any). + /// If you don't set a typedLobby, the room is automatically placed in the currently active lobby (if any) or the + /// default-lobby. + /// + /// Call this only on the master server. + /// Internally, the master will respond with a server-address (and roomName, if needed). Both are used internally + /// to switch to the assigned game server and roomName. + /// + /// PhotonNetwork.autoCleanUpPlayerObjects will become this room's autoCleanUp property and that's used by all clients that join this room. + /// + /// Unique name of the room to create. Pass null or "" to make the server generate a name. + /// Common options for the room like MaxPlayers, initial custom room properties and similar. See RoomOptions type.. + /// If null, the room is automatically created in the currently used lobby (which is "default" when you didn't join one explicitly). + /// If the operation got queued and will be sent. + public static bool CreateRoom(string roomName, RoomOptions roomOptions, TypedLobby typedLobby) + { + return CreateRoom(roomName, roomOptions, typedLobby, null); + } + + /// + /// Creates a room but fails if this room is existing already. Can only be called on Master Server. + /// + /// + /// When successful, this calls the callbacks OnCreatedRoom and OnJoinedRoom (the latter, cause you join as first player). + /// If the room can't be created (because it exists already), OnPhotonCreateRoomFailed gets called. + /// + /// If you don't want to create a unique room-name, pass null or "" as name and the server will assign a roomName (a GUID as string). + /// + /// Rooms can be created in any number of lobbies. Those don't have to exist before you create a room in them (they get + /// auto-created on demand). Lobbies can be useful to split room lists on the server-side already. That can help keep the room + /// lists short and manageable. + /// If you set a typedLobby parameter, the room will be created in that lobby (no matter if you are active in any). + /// If you don't set a typedLobby, the room is automatically placed in the currently active lobby (if any) or the + /// default-lobby. + /// + /// Call this only on the master server. + /// Internally, the master will respond with a server-address (and roomName, if needed). Both are used internally + /// to switch to the assigned game server and roomName. + /// + /// PhotonNetwork.autoCleanUpPlayerObjects will become this room's autoCleanUp property and that's used by all clients that join this room. + /// + /// You can define an array of expectedUsers, to block player slots in the room for these users. + /// The corresponding feature in Photon is called "Slot Reservation" and can be found in the doc pages. + /// + /// Unique name of the room to create. Pass null or "" to make the server generate a name. + /// Common options for the room like MaxPlayers, initial custom room properties and similar. See RoomOptions type.. + /// If null, the room is automatically created in the currently used lobby (which is "default" when you didn't join one explicitly). + /// Optional list of users (by UserId) who are expected to join this game and who you want to block a slot for. + /// If the operation got queued and will be sent. + public static bool CreateRoom(string roomName, RoomOptions roomOptions, TypedLobby typedLobby, string[] expectedUsers) + { + if (offlineMode) + { + if (offlineModeRoom != null) + { + Debug.LogError("CreateRoom failed. In offline mode you still have to leave a room to enter another."); + return false; + } + EnterOfflineRoom(roomName, roomOptions, true); + return true; + } + if (networkingPeer.Server != ServerConnection.MasterServer || !connectedAndReady) + { + Debug.LogError("CreateRoom failed. Client is not on Master Server or not yet ready to call operations. Wait for callback: OnJoinedLobby or OnConnectedToMaster."); + return false; + } + + typedLobby = typedLobby ?? ((networkingPeer.insideLobby) ? networkingPeer.lobby : null); // use given lobby, or active lobby (if any active) or none + + EnterRoomParams opParams = new EnterRoomParams(); + opParams.RoomName = roomName; + opParams.RoomOptions = roomOptions; + opParams.Lobby = typedLobby; + opParams.ExpectedUsers = expectedUsers; + + return networkingPeer.OpCreateGame(opParams); + } + + + /// Join room by roomname and on success calls OnJoinedRoom(). This is not affected by lobbies. + /// + /// On success, the method OnJoinedRoom() is called on any script. You can implement it to react to joining a room. + /// + /// JoinRoom fails if the room is either full or no longer available (it might become empty while you attempt to join). + /// Implement OnPhotonJoinRoomFailed() to get a callback in error case. + /// + /// To join a room from the lobby's listing, use RoomInfo.Name as roomName here. + /// Despite using multiple lobbies, a roomName is always "global" for your application and so you don't + /// have to specify which lobby it's in. The Master Server will find the room. + /// In the Photon Cloud, an application is defined by AppId, Game- and PUN-version. + /// + /// + /// + /// Unique name of the room to join. + /// If the operation got queued and will be sent. + public static bool JoinRoom(string roomName) + { + return JoinRoom(roomName, null); + } + + /// Join room by roomname and on success calls OnJoinedRoom(). This is not affected by lobbies. + /// + /// On success, the method OnJoinedRoom() is called on any script. You can implement it to react to joining a room. + /// + /// JoinRoom fails if the room is either full or no longer available (it might become empty while you attempt to join). + /// Implement OnPhotonJoinRoomFailed() to get a callback in error case. + /// + /// To join a room from the lobby's listing, use RoomInfo.Name as roomName here. + /// Despite using multiple lobbies, a roomName is always "global" for your application and so you don't + /// have to specify which lobby it's in. The Master Server will find the room. + /// In the Photon Cloud, an application is defined by AppId, Game- and PUN-version. + /// + /// You can define an array of expectedUsers, to block player slots in the room for these users. + /// The corresponding feature in Photon is called "Slot Reservation" and can be found in the doc pages. + /// + /// + /// + /// Unique name of the room to join. + /// Optional list of users (by UserId) who are expected to join this game and who you want to block a slot for. + /// If the operation got queued and will be sent. + public static bool JoinRoom(string roomName, string[] expectedUsers) + { + if (offlineMode) + { + if (offlineModeRoom != null) + { + Debug.LogError("JoinRoom failed. In offline mode you still have to leave a room to enter another."); + return false; + } + EnterOfflineRoom(roomName, null, true); + return true; + } + if (networkingPeer.Server != ServerConnection.MasterServer || !connectedAndReady) + { + Debug.LogError("JoinRoom failed. Client is not on Master Server or not yet ready to call operations. Wait for callback: OnJoinedLobby or OnConnectedToMaster."); + return false; + } + if (string.IsNullOrEmpty(roomName)) + { + Debug.LogError("JoinRoom failed. A roomname is required. If you don't know one, how will you join?"); + return false; + } + + + EnterRoomParams opParams = new EnterRoomParams(); + opParams.RoomName = roomName; + opParams.ExpectedUsers = expectedUsers; + + return networkingPeer.OpJoinRoom(opParams); + } + + + /// Lets you either join a named room or create it on the fly - you don't have to know if someone created the room already. + /// + /// This makes it easier for groups of players to get into the same room. Once the group + /// exchanged a roomName, any player can call JoinOrCreateRoom and it doesn't matter who + /// actually joins or creates the room. + /// + /// The parameters roomOptions and typedLobby are only used when the room actually gets created by this client. + /// You know if this client created a room, if you get a callback OnCreatedRoom (before OnJoinedRoom gets called as well). + /// + /// Name of the room to join. Must be non null. + /// Options for the room, in case it does not exist yet. Else these values are ignored. + /// Lobby you want a new room to be listed in. Ignored if the room was existing and got joined. + /// If the operation got queued and will be sent. + public static bool JoinOrCreateRoom(string roomName, RoomOptions roomOptions, TypedLobby typedLobby) + { + return JoinOrCreateRoom(roomName, roomOptions, typedLobby, null); + } + + /// Lets you either join a named room or create it on the fly - you don't have to know if someone created the room already. + /// + /// This makes it easier for groups of players to get into the same room. Once the group + /// exchanged a roomName, any player can call JoinOrCreateRoom and it doesn't matter who + /// actually joins or creates the room. + /// + /// The parameters roomOptions and typedLobby are only used when the room actually gets created by this client. + /// You know if this client created a room, if you get a callback OnCreatedRoom (before OnJoinedRoom gets called as well). + /// + /// You can define an array of expectedUsers, to block player slots in the room for these users. + /// The corresponding feature in Photon is called "Slot Reservation" and can be found in the doc pages. + /// + /// Name of the room to join. Must be non null. + /// Options for the room, in case it does not exist yet. Else these values are ignored. + /// Lobby you want a new room to be listed in. Ignored if the room was existing and got joined. + /// Optional list of users (by UserId) who are expected to join this game and who you want to block a slot for. + /// If the operation got queued and will be sent. + public static bool JoinOrCreateRoom(string roomName, RoomOptions roomOptions, TypedLobby typedLobby, string[] expectedUsers) + { + if (offlineMode) + { + if (offlineModeRoom != null) + { + Debug.LogError("JoinOrCreateRoom failed. In offline mode you still have to leave a room to enter another."); + return false; + } + EnterOfflineRoom(roomName, roomOptions, true); // in offline mode, JoinOrCreateRoom assumes you create the room + return true; + } + if (networkingPeer.Server != ServerConnection.MasterServer || !connectedAndReady) + { + Debug.LogError("JoinOrCreateRoom failed. Client is not on Master Server or not yet ready to call operations. Wait for callback: OnJoinedLobby or OnConnectedToMaster."); + return false; + } + if (string.IsNullOrEmpty(roomName)) + { + Debug.LogError("JoinOrCreateRoom failed. A roomname is required. If you don't know one, how will you join?"); + return false; + } + + typedLobby = typedLobby ?? ((networkingPeer.insideLobby) ? networkingPeer.lobby : null); // use given lobby, or active lobby (if any active) or none + + EnterRoomParams opParams = new EnterRoomParams(); + opParams.RoomName = roomName; + opParams.RoomOptions = roomOptions; + opParams.Lobby = typedLobby; + opParams.CreateIfNotExists = true; + opParams.PlayerProperties = player.CustomProperties; + opParams.ExpectedUsers = expectedUsers; + + return networkingPeer.OpJoinRoom(opParams); + } + + /// + /// Joins any available room of the currently used lobby and fails if none is available. + /// + /// + /// Rooms can be created in arbitrary lobbies which get created on demand. + /// You can join rooms from any lobby without actually joining the lobby. + /// Use the JoinRandomRoom overload with TypedLobby parameter. + /// + /// This method will only match rooms attached to one lobby! If you use many lobbies, you + /// might have to repeat JoinRandomRoom, to find some fitting room. + /// This method looks up a room in the currently active lobby or (if no lobby is joined) + /// in the default lobby. + /// + /// If this fails, you can still create a room (and make this available for the next who uses JoinRandomRoom). + /// Alternatively, try again in a moment. + /// + public static bool JoinRandomRoom() + { + return JoinRandomRoom(null, 0, MatchmakingMode.FillRoom, null, null); + } + + /// + /// Attempts to join an open room with fitting, custom properties but fails if none is currently available. + /// + /// + /// Rooms can be created in arbitrary lobbies which get created on demand. + /// You can join rooms from any lobby without actually joining the lobby. + /// Use the JoinRandomRoom overload with TypedLobby parameter. + /// + /// This method will only match rooms attached to one lobby! If you use many lobbies, you + /// might have to repeat JoinRandomRoom, to find some fitting room. + /// This method looks up a room in the currently active lobby or (if no lobby is joined) + /// in the default lobby. + /// + /// If this fails, you can still create a room (and make this available for the next who uses JoinRandomRoom). + /// Alternatively, try again in a moment. + /// + /// Filters for rooms that match these custom properties (string keys and values). To ignore, pass null. + /// Filters for a particular maxplayer setting. Use 0 to accept any maxPlayer value. + /// If the operation got queued and will be sent. + public static bool JoinRandomRoom(Hashtable expectedCustomRoomProperties, byte expectedMaxPlayers) + { + return JoinRandomRoom(expectedCustomRoomProperties, expectedMaxPlayers, MatchmakingMode.FillRoom, null, null); + } + + /// + /// Attempts to join an open room with fitting, custom properties but fails if none is currently available. + /// + /// + /// Rooms can be created in arbitrary lobbies which get created on demand. + /// You can join rooms from any lobby without actually joining the lobby with this overload. + /// + /// This method will only match rooms attached to one lobby! If you use many lobbies, you + /// might have to repeat JoinRandomRoom, to find some fitting room. + /// This method looks up a room in the specified lobby or the currently active lobby (if none specified) + /// or in the default lobby (if none active). + /// + /// If this fails, you can still create a room (and make this available for the next who uses JoinRandomRoom). + /// Alternatively, try again in a moment. + /// + /// In offlineMode, a room will be created but no properties will be set and all parameters of this + /// JoinRandomRoom call are ignored. The event/callback OnJoinedRoom gets called (see enum PhotonNetworkingMessage). + /// + /// You can define an array of expectedUsers, to block player slots in the room for these users. + /// The corresponding feature in Photon is called "Slot Reservation" and can be found in the doc pages. + /// + /// Filters for rooms that match these custom properties (string keys and values). To ignore, pass null. + /// Filters for a particular maxplayer setting. Use 0 to accept any maxPlayer value. + /// Selects one of the available matchmaking algorithms. See MatchmakingMode enum for options. + /// The lobby in which you want to lookup a room. Pass null, to use the default lobby. This does not join that lobby and neither sets the lobby property. + /// A filter-string for SQL-typed lobbies. + /// Optional list of users (by UserId) who are expected to join this game and who you want to block a slot for. + /// If the operation got queued and will be sent. + public static bool JoinRandomRoom(Hashtable expectedCustomRoomProperties, byte expectedMaxPlayers, MatchmakingMode matchingType, TypedLobby typedLobby, string sqlLobbyFilter, string[] expectedUsers = null) + { + if (offlineMode) + { + if (offlineModeRoom != null) + { + Debug.LogError("JoinRandomRoom failed. In offline mode you still have to leave a room to enter another."); + return false; + } + EnterOfflineRoom("offline room", null, true); + return true; + } + if (networkingPeer.Server != ServerConnection.MasterServer || !connectedAndReady) + { + Debug.LogError("JoinRandomRoom failed. Client is not on Master Server or not yet ready to call operations. Wait for callback: OnJoinedLobby or OnConnectedToMaster."); + return false; + } + + typedLobby = typedLobby ?? ((networkingPeer.insideLobby) ? networkingPeer.lobby : null); // use given lobby, or active lobby (if any active) or none + + OpJoinRandomRoomParams opParams = new OpJoinRandomRoomParams(); + opParams.ExpectedCustomRoomProperties = expectedCustomRoomProperties; + opParams.ExpectedMaxPlayers = expectedMaxPlayers; + opParams.MatchingType = matchingType; + opParams.TypedLobby = typedLobby; + opParams.SqlLobbyFilter = sqlLobbyFilter; + opParams.ExpectedUsers = expectedUsers; + + return networkingPeer.OpJoinRandomRoom(opParams); + } + + + /// Can be used to return to a room after a disconnect and reconnect. + /// + /// After losing connection, you might be able to return to a room and continue playing, + /// if the client is reconnecting fast enough. Use Reconnect() and this method. + /// Cache the room name you're in and use ReJoin(roomname) to return to a game. + /// + /// Note: To be able to ReJoin any room, you need to use UserIDs! + /// You also need to set RoomOptions.PlayerTtl. + /// + /// Important: Instantiate() and use of RPCs is not yet supported. + /// The ownership rules of PhotonViews prevent a seamless return to a game. + /// Use Custom Properties and RaiseEvent with event caching instead. + /// + /// Common use case: Press the Lock Button on a iOS device and you get disconnected immediately. + /// + public static bool ReJoinRoom(string roomName) + { + if (offlineMode) + { + Debug.LogError("ReJoinRoom failed due to offline mode."); + return false; + } + if (networkingPeer.Server != ServerConnection.MasterServer || !connectedAndReady) + { + Debug.LogError("ReJoinRoom failed. Client is not on Master Server or not yet ready to call operations. Wait for callback: OnJoinedLobby or OnConnectedToMaster."); + return false; + } + if (string.IsNullOrEmpty(roomName)) + { + Debug.LogError("ReJoinRoom failed. A roomname is required. If you don't know one, how will you join?"); + return false; + } + + EnterRoomParams opParams = new EnterRoomParams(); + opParams.RoomName = roomName; + opParams.RejoinOnly = true; + opParams.PlayerProperties = player.CustomProperties; + + return networkingPeer.OpJoinRoom(opParams); + } + + + /// + /// Internally used helper-method to setup an offline room, the numbers for actor and master-client and to do the callbacks. + /// + private static void EnterOfflineRoom(string roomName, RoomOptions roomOptions, bool createdRoom) + { + offlineModeRoom = new Room(roomName, roomOptions); + networkingPeer.ChangeLocalID(1); + networkingPeer.State = ClientState.ConnectingToGameserver; + networkingPeer.OnStatusChanged(StatusCode.Connect); + offlineModeRoom.MasterClientId = 1; + + if (createdRoom) + { + NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnCreatedRoom); + } + NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnJoinedRoom); + } + + /// On MasterServer this joins the default lobby which list rooms currently in use. + /// + /// The room list is sent and refreshed by the server. You can access this cached list by + /// PhotonNetwork.GetRoomList(). + /// + /// Per room you should check if it's full or not before joining. Photon also lists rooms that are + /// full, unless you close and hide them (room.open = false and room.visible = false). + /// + /// In best case, you make your clients join random games, as described here: + /// https://doc.photonengine.com/en-us/pun/current/lobby-and-matchmaking/matchmaking-and-lobby + /// + /// You can show your current players and room count without joining a lobby (but you must + /// be on the master server). Use: countOfPlayers, countOfPlayersOnMaster, countOfPlayersInRooms and + /// countOfRooms. + /// + /// You can use more than one lobby to keep the room lists shorter. See JoinLobby(TypedLobby lobby). + /// When creating new rooms, they will be "attached" to the currently used lobby or the default lobby. + /// + /// You can use JoinRandomRoom without being in a lobby! + /// Set autoJoinLobby = false before you connect, to not join a lobby. In that case, the + /// connect-workflow will call OnConnectedToMaster (if you implement it) when it's done. + /// + public static bool JoinLobby() + { + return JoinLobby(null); + } + + /// On a Master Server you can join a lobby to get lists of available rooms. + /// + /// The room list is sent and refreshed by the server. You can access this cached list by + /// PhotonNetwork.GetRoomList(). + /// + /// Any client can "make up" any lobby on the fly. Splitting rooms into multiple lobbies will + /// keep each list shorter. However, having too many lists might ruin the matchmaking experience. + /// + /// In best case, you create a limited number of lobbies. For example, create a lobby per + /// game-mode: "koth" for king of the hill and "ffa" for free for all, etc. + /// + /// There is no listing of lobbies at the moment. + /// + /// Sql-typed lobbies offer a different filtering model for random matchmaking. This might be more + /// suited for skillbased-games. However, you will also need to follow the conventions for naming + /// filterable properties in sql-lobbies! Both is explained in the matchmaking doc linked below. + /// + /// In best case, you make your clients join random games, as described here: + /// http://confluence.exitgames.com/display/PTN/Op+JoinRandomGame + /// + /// + /// Per room you should check if it's full or not before joining. Photon does list rooms that are + /// full, unless you close and hide them (room.open = false and room.visible = false). + /// + /// You can show your games current players and room count without joining a lobby (but you must + /// be on the master server). Use: countOfPlayers, countOfPlayersOnMaster, countOfPlayersInRooms and + /// countOfRooms. + /// + /// When creating new rooms, they will be "attached" to the currently used lobby or the default lobby. + /// + /// You can use JoinRandomRoom without being in a lobby! + /// Set autoJoinLobby = false before you connect, to not join a lobby. In that case, the + /// connect-workflow will call OnConnectedToMaster (if you implement it) when it's done. + /// + /// A typed lobby to join (must have name and type). + public static bool JoinLobby(TypedLobby typedLobby) + { + if (PhotonNetwork.connected && PhotonNetwork.Server == ServerConnection.MasterServer) + { + if (typedLobby == null) + { + typedLobby = TypedLobby.Default; + } + + bool sending = networkingPeer.OpJoinLobby(typedLobby); + if (sending) + { + networkingPeer.lobby = typedLobby; + + } + return sending; + } + + return false; + } + + /// Leave a lobby to stop getting updates about available rooms. + /// + /// This does not reset PhotonNetwork.lobby! This allows you to join this particular lobby later + /// easily. + /// + /// The values countOfPlayers, countOfPlayersOnMaster, countOfPlayersInRooms and countOfRooms + /// are received even without being in a lobby. + /// + /// You can use JoinRandomRoom without being in a lobby. + /// Use autoJoinLobby to not join a lobby when you connect. + /// + public static bool LeaveLobby() + { + if (PhotonNetwork.connected && PhotonNetwork.Server == ServerConnection.MasterServer) + { + return networkingPeer.OpLeaveLobby(); + } + + return false; + } + + /// Leave the current room and return to the Master Server where you can join or create rooms (see remarks). + /// + /// This will clean up all (network) GameObjects with a PhotonView, unless you changed autoCleanUp to false. + /// Returns to the Master Server. + /// + /// In OfflineMode, the local "fake" room gets cleaned up and OnLeftRoom gets called immediately. + /// + /// In a room with playerTTL < 0, LeaveRoom just turns a client inactive. The player stays in the room's player list + /// and can return later on. Setting becomeInactive to false deliberately, means to "abandon" the room, despite the + /// playerTTL allowing you to come back. + /// + /// In a room with playerTTL == 0, become inactive has no effect (clients are removed from the room right away). + /// + /// If this client becomes inactive in a room with playerTTL < 0. Defaults to true. + public static bool LeaveRoom(bool becomeInactive = true) + { + if (offlineMode) + { + offlineModeRoom = null; + NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnLeftRoom); + } + else + { + if (room == null) + { + Debug.LogWarning("PhotonNetwork.room is null. You don't have to call LeaveRoom() when you're not in one. State: " + PhotonNetwork.connectionStateDetailed); + } + else + { + becomeInactive = becomeInactive && room.PlayerTtl != 0; // in a room with playerTTL == 0, the operation "leave" will never turn a client inactive + } + return networkingPeer.OpLeaveRoom(becomeInactive); + } + + return true; + } + + /// Fetches a custom list of games from the server, matching a SQL-like "where" clause, then triggers OnReceivedRoomListUpdate callback. + /// + /// Operation is only available for lobbies of type SqlLobby. Note: You don't have to join that lobby. + /// This is an async request. + /// + /// When done, OnReceivedRoomListUpdate gets called. Use GetRoomList() to access it. + /// + /// + /// The lobby to query. Has to be of type SqlLobby. + /// The sql query statement. + /// If the operation could be sent (has to be connected). + public static bool GetCustomRoomList(TypedLobby typedLobby, string sqlLobbyFilter) + { + return networkingPeer.OpGetGameList(typedLobby, sqlLobbyFilter); + } + + /// + /// Gets currently cached rooms of the last rooms list sent by the server as RoomInfo array. + /// This list is either available and updated automatically and periodically while in a lobby (check insideLobby) or + /// received as a response to PhotonNetwork.GetCustomRoomList(). + /// + /// + /// This list is a cached copy of the internal rooms list so it can be accessed each frame if needed. + /// Per RoomInfo you can check if the room is full by comparing playerCount and MaxPlayers before you allow a join. + /// + /// The name of a room must be used to join it (via JoinRoom). + /// + /// Closed rooms are also listed by lobbies but they can't be joined. While in a room, any player can set + /// Room.visible and Room.open to hide rooms from matchmaking and close them. + /// + /// Cached RoomInfo[] of last room list sent by the server. + public static RoomInfo[] GetRoomList() + { + if (offlineMode || networkingPeer == null) + { + return new RoomInfo[0]; + } + + return networkingPeer.mGameListCopy; + } + + /// + /// Sets this (local) player's properties and synchronizes them to the other players (don't modify them directly). + /// + /// + /// While in a room, your properties are synced with the other players. + /// CreateRoom, JoinRoom and JoinRandomRoom will all apply your player's custom properties when you enter the room. + /// The whole Hashtable will get sent. Minimize the traffic by setting only updated key/values. + /// + /// If the Hashtable is null, the custom properties will be cleared. + /// Custom properties are never cleared automatically, so they carry over to the next room, if you don't change them. + /// + /// Don't set properties by modifying PhotonNetwork.player.customProperties! + /// + /// Only string-typed keys will be used from this hashtable. If null, custom properties are all deleted. + public static void SetPlayerCustomProperties(Hashtable customProperties) + { + if (customProperties == null) + { + customProperties = new Hashtable(); + foreach (object k in player.CustomProperties.Keys) + { + customProperties[(string)k] = null; + } + } + + if (room != null && room.IsLocalClientInside) + { + player.SetCustomProperties(customProperties); + } + else + { + player.InternalCacheProperties(customProperties); + } + } + + /// + /// Locally removes Custom Properties of "this" player. Important: This does not synchronize the change! Useful when you switch rooms. + /// + /// + /// Use this method with care. It can create inconsistencies of state between players! + /// This only changes the player.customProperties locally. This can be useful to clear your + /// Custom Properties between games (let's say they store which turn you made, kills, etc). + /// + /// SetPlayerCustomProperties() syncs and can be used to set values to null while in a room. + /// That can be considered "removed" while in a room. + /// + /// If customPropertiesToDelete is null or has 0 entries, all Custom Properties are deleted (replaced with a new Hashtable). + /// If you specify keys to remove, those will be removed from the Hashtable but other keys are unaffected. + /// + /// List of Custom Property keys to remove. See remarks. + public static void RemovePlayerCustomProperties(string[] customPropertiesToDelete) + { + if (customPropertiesToDelete == null || customPropertiesToDelete.Length == 0 || player.CustomProperties == null) + { + player.CustomProperties = new Hashtable(); + return; + } + + // if a specific list of props should be deleted, we do that here + for (int i = 0; i < customPropertiesToDelete.Length; i++) + { + string key = customPropertiesToDelete[i]; + if (player.CustomProperties.ContainsKey(key)) + { + player.CustomProperties.Remove(key); + } + } + } + + /// + /// Sends fully customizable events in a room. Events consist of at least an EventCode (0..199) and can have content. + /// + /// + /// To receive the events someone sends, register your handling method in PhotonNetwork.OnEventCall. + /// + /// Example: + /// private void OnEventHandler(byte eventCode, object content, int senderId) + /// { Debug.Log("OnEventHandler"); } + /// + /// PhotonNetwork.OnEventCall += this.OnEventHandler; + /// + /// With the senderId, you can look up the PhotonPlayer who sent the event. + /// It is best practice to assign a eventCode for each different type of content and action. You have to cast the content. + /// + /// The eventContent is optional. To be able to send something, it must be a "serializable type", something that + /// the client can turn into a byte[] basically. Most basic types and arrays of them are supported, including + /// Unity's Vector2, Vector3, Quaternion. Transforms or classes some project defines are NOT supported! + /// You can make your own class a "serializable type" by following the example in CustomTypes.cs. + /// + /// + /// The RaiseEventOptions have some (less intuitive) combination rules: + /// If you set targetActors (an array of PhotonPlayer.ID values), the receivers parameter gets ignored. + /// When using event caching, the targetActors, receivers and interestGroup can't be used. Buffered events go to all. + /// When using cachingOption removeFromRoomCache, the eventCode and content are actually not sent but used as filter. + /// + /// A byte identifying the type of event. You might want to use a code per action or to signal which content can be expected. Allowed: 0..199. + /// Some serializable object like string, byte, integer, float (etc) and arrays of those. Hashtables with byte keys are good to send variable content. + /// Makes sure this event reaches all players. It gets acknowledged, which requires bandwidth and it can't be skipped (might add lag in case of loss). + /// Allows more complex usage of events. If null, RaiseEventOptions.Default will be used (which is fine). + /// False if event could not be sent + public static bool RaiseEvent(byte eventCode, object eventContent, bool sendReliable, RaiseEventOptions options) + { + if (!inRoom || eventCode >= 200) + { + Debug.LogWarning("RaiseEvent() failed. Your event is not being sent! Check if your are in a Room and the eventCode must be less than 200 (0..199)."); + return false; + } + + return networkingPeer.OpRaiseEvent(eventCode, eventContent, sendReliable, options); + } + + #if PHOTON_LIB_MIN_4_1_2 + public static bool RaiseEvent(byte eventCode, object eventContent, RaiseEventOptions raiseEventOptions, SendOptions sendOptions) + { + if (!inRoom || eventCode >= 200) + { + Debug.LogWarning("RaiseEvent() failed. Your event is not being sent! Check if your are in a Room and the eventCode must be less than 200 (0..199)."); + return false; + } + + return networkingPeer.OpRaiseEvent(eventCode, eventContent, raiseEventOptions, sendOptions); + } + #endif + + /// + /// Allocates a viewID that's valid for the current/local player. + /// + /// A viewID that can be used for a new PhotonView. + public static int AllocateViewID() + { + int manualId = AllocateViewID(player.ID); + manuallyAllocatedViewIds.Add(manualId); + return manualId; + } + + + /// + /// Enables the Master Client to allocate a viewID that is valid for scene objects. + /// + /// A viewID that can be used for a new PhotonView or -1 in case of an error. + public static int AllocateSceneViewID() + { + if (!PhotonNetwork.isMasterClient) + { + Debug.LogError("Only the Master Client can AllocateSceneViewID(). Check PhotonNetwork.isMasterClient!"); + return -1; + } + + int manualId = AllocateViewID(0); + manuallyAllocatedViewIds.Add(manualId); + return manualId; + } + + // use 0 for scene-targetPhotonView-ids + // returns viewID (combined owner and sub id) + private static int AllocateViewID(int ownerId) + { + if (ownerId == 0) + { + // we look up a fresh subId for the owner "room" (mind the "sub" in subId) + int newSubId = lastUsedViewSubIdStatic; + int newViewId; + int ownerIdOffset = ownerId * MAX_VIEW_IDS; + for (int i = 1; i < MAX_VIEW_IDS; i++) + { + newSubId = (newSubId + 1) % MAX_VIEW_IDS; + if (newSubId == 0) + { + continue; // avoid using subID 0 + } + + newViewId = newSubId + ownerIdOffset; + if (!networkingPeer.photonViewList.ContainsKey(newViewId)) + { + lastUsedViewSubIdStatic = newSubId; + return newViewId; + } + } + + // this is the error case: we didn't find any (!) free subId for this user + throw new Exception(string.Format("AllocateViewID() failed. Room (user {0}) is out of 'scene' viewIDs. It seems all available are in use.", ownerId)); + } + else + { + // we look up a fresh SUBid for the owner + int newSubId = lastUsedViewSubId; + int newViewId; + int ownerIdOffset = ownerId * MAX_VIEW_IDS; + for (int i = 1; i < MAX_VIEW_IDS; i++) + { + newSubId = (newSubId + 1) % MAX_VIEW_IDS; + if (newSubId == 0) + { + continue; // avoid using subID 0 + } + + newViewId = newSubId + ownerIdOffset; + if (!networkingPeer.photonViewList.ContainsKey(newViewId) && !manuallyAllocatedViewIds.Contains(newViewId)) + { + lastUsedViewSubId = newSubId; + return newViewId; + } + } + + throw new Exception(string.Format("AllocateViewID() failed. User {0} is out of subIds, as all viewIDs are used.", ownerId)); + } + } + + private static int[] AllocateSceneViewIDs(int countOfNewViews) + { + int[] viewIDs = new int[countOfNewViews]; + for (int view = 0; view < countOfNewViews; view++) + { + viewIDs[view] = AllocateViewID(0); + } + + return viewIDs; + } + + /// + /// Unregister a viewID (of manually instantiated and destroyed networked objects). + /// + /// A viewID manually allocated by this player. + public static void UnAllocateViewID(int viewID) + { + manuallyAllocatedViewIds.Remove(viewID); + + if (networkingPeer.photonViewList.ContainsKey(viewID)) + { + Debug.LogWarning(string.Format("UnAllocateViewID() should be called after the PhotonView was destroyed (GameObject.Destroy()). ViewID: {0} still found in: {1}", viewID, networkingPeer.photonViewList[viewID])); + } + } + + /// + /// Instantiate a prefab over the network. This prefab needs to be located in the root of a "Resources" folder. + /// + /// + /// Instead of using prefabs in the Resources folder, you can manually Instantiate and assign PhotonViews. See doc. + /// + /// Name of the prefab to instantiate. + /// Position Vector3 to apply on instantiation. + /// Rotation Quaternion to apply on instantiation. + /// The group for this PhotonView. + /// The new instance of a GameObject with initialized PhotonView. + public static GameObject Instantiate(string prefabName, Vector3 position, Quaternion rotation, byte group) + { + return Instantiate(prefabName, position, rotation, group, null); + } + + /// + /// Instantiate a prefab over the network. This prefab needs to be located in the root of a "Resources" folder. + /// + /// Instead of using prefabs in the Resources folder, you can manually Instantiate and assign PhotonViews. See doc. + /// Name of the prefab to instantiate. + /// Position Vector3 to apply on instantiation. + /// Rotation Quaternion to apply on instantiation. + /// The group for this PhotonView. + /// Optional instantiation data. This will be saved to it's PhotonView.instantiationData. + /// The new instance of a GameObject with initialized PhotonView. + public static GameObject Instantiate(string prefabName, Vector3 position, Quaternion rotation, byte group, object[] data) + { + if (!connected || (InstantiateInRoomOnly && !inRoom)) + { + Debug.LogError("Failed to Instantiate prefab: " + prefabName + ". Client should be in a room. Current connectionStateDetailed: " + PhotonNetwork.connectionStateDetailed); + return null; + } + + GameObject prefabGo; + if (!UsePrefabCache || !PrefabCache.TryGetValue(prefabName, out prefabGo)) + { + prefabGo = (GameObject)Resources.Load(prefabName, typeof(GameObject)); + if (UsePrefabCache) + { + PrefabCache.Add(prefabName, prefabGo); + } + } + + if (prefabGo == null) + { + Debug.LogError("Failed to Instantiate prefab: " + prefabName + ". Verify the Prefab is in a Resources folder (and not in a subfolder)"); + return null; + } + + // a scene object instantiated with network visibility has to contain a PhotonView + if (prefabGo.GetComponent() == null) + { + Debug.LogError("Failed to Instantiate prefab:" + prefabName + ". Prefab must have a PhotonView component."); + return null; + } + + Component[] views = (Component[])prefabGo.GetPhotonViewsInChildren(); + int[] viewIDs = new int[views.Length]; + for (int i = 0; i < viewIDs.Length; i++) + { + //Debug.Log("Instantiate prefabName: " + prefabName + " player.ID: " + player.ID); + viewIDs[i] = AllocateViewID(player.ID); + } + + // Send to others, create info + Hashtable instantiateEvent = networkingPeer.SendInstantiate(prefabName, position, rotation, group, viewIDs, data, false); + + // Instantiate the GO locally (but the same way as if it was done via event). This will also cache the instantiationId + return networkingPeer.DoInstantiate(instantiateEvent, networkingPeer.LocalPlayer, prefabGo); + } + + + /// + /// Instantiate a scene-owned prefab over the network. The PhotonViews will be controllable by the MasterClient. This prefab needs to be located in the root of a "Resources" folder. + /// + /// + /// Only the master client can Instantiate scene objects. + /// Instead of using prefabs in the Resources folder, you can manually Instantiate and assign PhotonViews. See doc. + /// + /// Name of the prefab to instantiate. + /// Position Vector3 to apply on instantiation. + /// Rotation Quaternion to apply on instantiation. + /// The group for this PhotonView. + /// Optional instantiation data. This will be saved to it's PhotonView.instantiationData. + /// The new instance of a GameObject with initialized PhotonView. + public static GameObject InstantiateSceneObject(string prefabName, Vector3 position, Quaternion rotation, byte group, object[] data) + { + if (!connected || (InstantiateInRoomOnly && !inRoom)) + { + Debug.LogError("Failed to InstantiateSceneObject prefab: " + prefabName + ". Client should be in a room. Current connectionStateDetailed: " + PhotonNetwork.connectionStateDetailed); + return null; + } + + if (!isMasterClient) + { + Debug.LogError("Failed to InstantiateSceneObject prefab: " + prefabName + ". Client is not the MasterClient in this room."); + return null; + } + + GameObject prefabGo; + if (!UsePrefabCache || !PrefabCache.TryGetValue(prefabName, out prefabGo)) + { + prefabGo = (GameObject)Resources.Load(prefabName, typeof(GameObject)); + if (UsePrefabCache) + { + PrefabCache.Add(prefabName, prefabGo); + } + } + + if (prefabGo == null) + { + Debug.LogError("Failed to InstantiateSceneObject prefab: " + prefabName + ". Verify the Prefab is in a Resources folder (and not in a subfolder)"); + return null; + } + + // a scene object instantiated with network visibility has to contain a PhotonView + if (prefabGo.GetComponent() == null) + { + Debug.LogError("Failed to InstantiateSceneObject prefab:" + prefabName + ". Prefab must have a PhotonView component."); + return null; + } + + Component[] views = (Component[])prefabGo.GetPhotonViewsInChildren(); + int[] viewIDs = AllocateSceneViewIDs(views.Length); + + if (viewIDs == null) + { + Debug.LogError("Failed to InstantiateSceneObject prefab: " + prefabName + ". No ViewIDs are free to use. Max is: " + MAX_VIEW_IDS); + return null; + } + + // Send to others, create info + Hashtable instantiateEvent = networkingPeer.SendInstantiate(prefabName, position, rotation, group, viewIDs, data, true); + + // Instantiate the GO locally (but the same way as if it was done via event). This will also cache the instantiationId + return networkingPeer.DoInstantiate(instantiateEvent, networkingPeer.LocalPlayer, prefabGo); + } + + /// + /// The current roundtrip time to the photon server. + /// + /// Roundtrip time (to server and back). + public static int GetPing() + { + return networkingPeer.RoundTripTime; + } + + /// Refreshes the server timestamp (async operation, takes a roundtrip). + /// Can be useful if a bad connection made the timestamp unusable or imprecise. + public static void FetchServerTimestamp() + { + if (networkingPeer != null) + { + networkingPeer.FetchServerTimestamp(); + } + } + + /// + /// Can be used to immediately send the RPCs and Instantiates just called, so they are on their way to the other players. + /// + /// + /// This could be useful if you do a RPC to load a level and then load it yourself. + /// While loading, no RPCs are sent to others, so this would delay the "load" RPC. + /// You can send the RPC to "others", use this method, disable the message queue + /// (by isMessageQueueRunning) and then load. + /// + public static void SendOutgoingCommands() + { + if (!VerifyCanUseNetwork()) + { + return; + } + + while (networkingPeer.SendOutgoingCommands()) + { + } + } + + /// Request a client to disconnect (KICK). Only the master client can do this + /// Only the target player gets this event. That player will disconnect automatically, which is what the others will notice, too. + /// The PhotonPlayer to kick. + public static bool CloseConnection(PhotonPlayer kickPlayer) + { + if (!VerifyCanUseNetwork()) + { + return false; + } + + if (!player.IsMasterClient) + { + Debug.LogError("CloseConnection: Only the masterclient can kick another player."); + return false; + } + + if (kickPlayer == null) + { + Debug.LogError("CloseConnection: No such player connected!"); + return false; + } + + RaiseEventOptions options = new RaiseEventOptions() { TargetActors = new int[] { kickPlayer.ID } }; + return networkingPeer.OpRaiseEvent(PunEvent.CloseConnection, null, true, options); + } + + /// + /// Asks the server to assign another player as Master Client of your current room. + /// + /// + /// RPCs and RaiseEvent have the option to send messages only to the Master Client of a room. + /// SetMasterClient affects which client gets those messages. + /// + /// This method calls an operation on the server to set a new Master Client, which takes a roundtrip. + /// In case of success, this client and the others get the new Master Client from the server. + /// + /// SetMasterClient tells the server which current Master Client should be replaced with the new one. + /// It will fail, if anything switches the Master Client moments earlier. There is no callback for this + /// error. All clients should get the new Master Client assigned by the server anyways. + /// + /// See also: PhotonNetwork.masterClient + /// + /// On v3 servers: + /// The ReceiverGroup.MasterClient (usable in RPCs) is not affected by this (still points to lowest player.ID in room). + /// Avoid using this enum value (and send to a specific player instead). + /// + /// If the current Master Client leaves, PUN will detect a new one by "lowest player ID". Implement OnMasterClientSwitched + /// to get a callback in this case. The PUN-selected Master Client might assign a new one. + /// + /// Make sure you don't create an endless loop of Master-assigning! When selecting a custom Master Client, all clients + /// should point to the same player, no matter who actually assigns this player. + /// + /// Locally the Master Client is immediately switched, while remote clients get an event. This means the game + /// is tempoarily without Master Client like when a current Master Client leaves. + /// + /// When switching the Master Client manually, keep in mind that this user might leave and not do it's work, just like + /// any Master Client. + /// + /// + /// The player to become the next Master Client. + /// False when this operation couldn't be done. Must be in a room (not in offlineMode). + public static bool SetMasterClient(PhotonPlayer masterClientPlayer) + { + if (!inRoom || !VerifyCanUseNetwork() || offlineMode) + { + if (logLevel == PhotonLogLevel.Informational) Debug.Log("Can not SetMasterClient(). Not in room or in offlineMode."); + return false; + } + + if (room.serverSideMasterClient) + { + Hashtable newProps = new Hashtable() { { GamePropertyKey.MasterClientId, masterClientPlayer.ID } }; + Hashtable prevProps = new Hashtable() { { GamePropertyKey.MasterClientId, networkingPeer.mMasterClientId } }; + return networkingPeer.OpSetPropertiesOfRoom(newProps, expectedProperties: prevProps, webForward: false); + } + else + { + if (!isMasterClient) + { + return false; + } + return networkingPeer.SetMasterClient(masterClientPlayer.ID, true); + } + } + + /// + /// Network-Destroy the GameObject associated with the PhotonView, unless the PhotonView is static or not under this client's control. + /// + /// + /// Destroying a networked GameObject while in a Room includes: + /// - Removal of the Instantiate call from the server's room buffer. + /// - Removing RPCs buffered for PhotonViews that got created indirectly with the PhotonNetwork.Instantiate call. + /// - Sending a message to other clients to remove the GameObject also (affected by network lag). + /// + /// Usually, when you leave a room, the GOs get destroyed automatically. + /// If you have to destroy a GO while not in a room, the Destroy is only done locally. + /// + /// Destroying networked objects works only if they got created with PhotonNetwork.Instantiate(). + /// Objects loaded with a scene are ignored, no matter if they have PhotonView components. + /// + /// The GameObject must be under this client's control: + /// - Instantiated and owned by this client. + /// - Instantiated objects of players who left the room are controlled by the Master Client. + /// - Scene-owned game objects are controlled by the Master Client. + /// - GameObject can be destroyed while client is not in a room. + /// + /// Nothing. Check error debug log for any issues. + public static void Destroy(PhotonView targetView) + { + if (targetView != null) + { + networkingPeer.RemoveInstantiatedGO(targetView.gameObject, !inRoom); + } + else + { + Debug.LogError("Destroy(targetPhotonView) failed, cause targetPhotonView is null."); + } + } + + /// + /// Network-Destroy the GameObject, unless it is static or not under this client's control. + /// + /// + /// Destroying a networked GameObject includes: + /// - Removal of the Instantiate call from the server's room buffer. + /// - Removing RPCs buffered for PhotonViews that got created indirectly with the PhotonNetwork.Instantiate call. + /// - Sending a message to other clients to remove the GameObject also (affected by network lag). + /// + /// Usually, when you leave a room, the GOs get destroyed automatically. + /// If you have to destroy a GO while not in a room, the Destroy is only done locally. + /// + /// Destroying networked objects works only if they got created with PhotonNetwork.Instantiate(). + /// Objects loaded with a scene are ignored, no matter if they have PhotonView components. + /// + /// The GameObject must be under this client's control: + /// - Instantiated and owned by this client. + /// - Instantiated objects of players who left the room are controlled by the Master Client. + /// - Scene-owned game objects are controlled by the Master Client. + /// - GameObject can be destroyed while client is not in a room. + /// + /// Nothing. Check error debug log for any issues. + public static void Destroy(GameObject targetGo) + { + networkingPeer.RemoveInstantiatedGO(targetGo, !inRoom); + } + + /// + /// Network-Destroy all GameObjects, PhotonViews and their RPCs of targetPlayer. Can only be called on local player (for "self") or Master Client (for anyone). + /// + /// + /// Destroying a networked GameObject includes: + /// - Removal of the Instantiate call from the server's room buffer. + /// - Removing RPCs buffered for PhotonViews that got created indirectly with the PhotonNetwork.Instantiate call. + /// - Sending a message to other clients to remove the GameObject also (affected by network lag). + /// + /// Destroying networked objects works only if they got created with PhotonNetwork.Instantiate(). + /// Objects loaded with a scene are ignored, no matter if they have PhotonView components. + /// + /// Nothing. Check error debug log for any issues. + public static void DestroyPlayerObjects(PhotonPlayer targetPlayer) + { + if (player == null) + { + Debug.LogError("DestroyPlayerObjects() failed, cause parameter 'targetPlayer' was null."); + } + + DestroyPlayerObjects(targetPlayer.ID); + } + + /// + /// Network-Destroy all GameObjects, PhotonViews and their RPCs of this player (by ID). Can only be called on local player (for "self") or Master Client (for anyone). + /// + /// + /// Destroying a networked GameObject includes: + /// - Removal of the Instantiate call from the server's room buffer. + /// - Removing RPCs buffered for PhotonViews that got created indirectly with the PhotonNetwork.Instantiate call. + /// - Sending a message to other clients to remove the GameObject also (affected by network lag). + /// + /// Destroying networked objects works only if they got created with PhotonNetwork.Instantiate(). + /// Objects loaded with a scene are ignored, no matter if they have PhotonView components. + /// + /// Nothing. Check error debug log for any issues. + public static void DestroyPlayerObjects(int targetPlayerId) + { + if (!VerifyCanUseNetwork()) + { + return; + } + if (player.IsMasterClient || targetPlayerId == player.ID) + { + networkingPeer.DestroyPlayerObjects(targetPlayerId, false); + } + else + { + Debug.LogError("DestroyPlayerObjects() failed, cause players can only destroy their own GameObjects. A Master Client can destroy anyone's. This is master: " + PhotonNetwork.isMasterClient); + } + } + + /// + /// Network-Destroy all GameObjects, PhotonViews and their RPCs in the room. Removes anything buffered from the server. Can only be called by Master Client (for anyone). + /// + /// + /// Can only be called by Master Client (for anyone). + /// Unlike the Destroy methods, this will remove anything from the server's room buffer. If your game + /// buffers anything beyond Instantiate and RPC calls, that will be cleaned as well from server. + /// + /// Destroying all includes: + /// - Remove anything from the server's room buffer (Instantiate, RPCs, anything buffered). + /// - Sending a message to other clients to destroy everything locally, too (affected by network lag). + /// + /// Destroying networked objects works only if they got created with PhotonNetwork.Instantiate(). + /// Objects loaded with a scene are ignored, no matter if they have PhotonView components. + /// + /// Nothing. Check error debug log for any issues. + public static void DestroyAll() + { + if (isMasterClient) + { + networkingPeer.DestroyAll(false); + } + else + { + Debug.LogError("Couldn't call DestroyAll() as only the master client is allowed to call this."); + } + } + + /// + /// Remove all buffered RPCs from server that were sent by targetPlayer. Can only be called on local player (for "self") or Master Client (for anyone). + /// + /// + /// This method requires either: + /// - This is the targetPlayer's client. + /// - This client is the Master Client (can remove any PhotonPlayer's RPCs). + /// + /// If the targetPlayer calls RPCs at the same time that this is called, + /// network lag will determine if those get buffered or cleared like the rest. + /// + /// This player's buffered RPCs get removed from server buffer. + public static void RemoveRPCs(PhotonPlayer targetPlayer) + { + if (!VerifyCanUseNetwork()) + { + return; + } + + if (!targetPlayer.IsLocal && !isMasterClient) + { + Debug.LogError("Error; Only the MasterClient can call RemoveRPCs for other players."); + return; + } + + networkingPeer.OpCleanRpcBuffer(targetPlayer.ID); + } + + /// + /// Remove all buffered RPCs from server that were sent via targetPhotonView. The Master Client and the owner of the targetPhotonView may call this. + /// + /// + /// This method requires either: + /// - The targetPhotonView is owned by this client (Instantiated by it). + /// - This client is the Master Client (can remove any PhotonView's RPCs). + /// + /// RPCs buffered for this PhotonView get removed from server buffer. + public static void RemoveRPCs(PhotonView targetPhotonView) + { + if (!VerifyCanUseNetwork()) + { + return; + } + + networkingPeer.CleanRpcBufferIfMine(targetPhotonView); + } + + /// + /// Remove all buffered RPCs from server that were sent in the targetGroup, if this is the Master Client or if this controls the individual PhotonView. + /// + /// + /// This method requires either: + /// - This client is the Master Client (can remove any RPCs per group). + /// - Any other client: each PhotonView is checked if it is under this client's control. Only those RPCs are removed. + /// + /// Interest group that gets all RPCs removed. + public static void RemoveRPCsInGroup(int targetGroup) + { + if (!VerifyCanUseNetwork()) + { + return; + } + + networkingPeer.RemoveRPCsInGroup(targetGroup); + } + + /// + /// Internal to send an RPC on given PhotonView. Do not call this directly but use: PhotonView.RPC! + /// + internal static void RPC(PhotonView view, string methodName, PhotonTargets target, bool encrypt, params object[] parameters) + { + if (!VerifyCanUseNetwork()) + { + return; + } + + if (room == null) + { + Debug.LogWarning("RPCs can only be sent in rooms. Call of \"" + methodName + "\" gets executed locally only, if at all."); + return; + } + + if (networkingPeer != null) + { + if (PhotonNetwork.room.serverSideMasterClient) + { + networkingPeer.RPC(view, methodName, target, null, encrypt, parameters); + } + else + { + if (PhotonNetwork.networkingPeer.hasSwitchedMC && target == PhotonTargets.MasterClient) + { + networkingPeer.RPC(view, methodName, PhotonTargets.Others, PhotonNetwork.masterClient, encrypt, parameters); + } + else + { + networkingPeer.RPC(view, methodName, target, null, encrypt, parameters); + } + } + } + else + { + Debug.LogWarning("Could not execute RPC " + methodName + ". Possible scene loading in progress?"); + } + } + + /// + /// Internal to send an RPC on given PhotonView. Do not call this directly but use: PhotonView.RPC! + /// + internal static void RPC(PhotonView view, string methodName, PhotonPlayer targetPlayer, bool encrpyt, params object[] parameters) + { + if (!VerifyCanUseNetwork()) + { + return; + } + + if (room == null) + { + Debug.LogWarning("RPCs can only be sent in rooms. Call of \"" + methodName + "\" gets executed locally only, if at all."); + return; + } + + if (player == null) + { + Debug.LogError("RPC can't be sent to target PhotonPlayer being null! Did not send \"" + methodName + "\" call."); + } + + if (networkingPeer != null) + { + networkingPeer.RPC(view, methodName, PhotonTargets.Others, targetPlayer, encrpyt, parameters); + } + else + { + Debug.LogWarning("Could not execute RPC " + methodName + ". Possible scene loading in progress?"); + } + } + + /// + /// Populates SendMonoMessageTargets with currently existing GameObjects that have a Component of type. + /// + /// If null, this will use SendMonoMessageTargets as component-type (MonoBehaviour by default). + public static void CacheSendMonoMessageTargets(Type type) + { + if (type == null) type = SendMonoMessageTargetType; + PhotonNetwork.SendMonoMessageTargets = FindGameObjectsWithComponent(type); + } + + /// Finds the GameObjects with Components of a specific type (using FindObjectsOfType). + /// Type must be a Component + /// HashSet with GameObjects that have a specific type of Component. + public static HashSet FindGameObjectsWithComponent(Type type) + { + HashSet objectsWithComponent = new HashSet(); + + Component[] targetComponents = (Component[]) GameObject.FindObjectsOfType(type); + for (int index = 0; index < targetComponents.Length; index++) + { + if (targetComponents[index] != null) + { + objectsWithComponent.Add(targetComponents[index].gameObject); + } + } + + return objectsWithComponent; + } + + + + [Obsolete("Use SetInterestGroups(byte group, bool enabled) instead.")] + public static void SetReceivingEnabled(int group, bool enabled) + { + if (!VerifyCanUseNetwork()) + { + return; + } + + SetInterestGroups((byte)group, enabled); + } + + /// Enable/disable receiving events from a given Interest Group. + /// + /// A client can tell the server which Interest Groups it's interested in. + /// The server will only forward events for those Interest Groups to that client (saving bandwidth and performance). + /// + /// See: https://doc.photonengine.com/en-us/pun/current/gameplay/interestgroups + /// + /// See: https://doc.photonengine.com/en-us/pun/current/demos-and-tutorials/package-demos/culling-demo + /// + /// The interest group to affect. + /// Sets if receiving from group to enabled (or not). + public static void SetInterestGroups(byte group, bool enabled) + { + if (!VerifyCanUseNetwork()) + { + return; + } + + if (enabled) + { + byte[] groups = new byte[1] { (byte)group }; + networkingPeer.SetInterestGroups(null, groups); + } + else + { + byte[] groups = new byte[1] { (byte)group }; + networkingPeer.SetInterestGroups(groups, null); + } + } + + + [Obsolete("Use SetInterestGroups(byte[] disableGroups, byte[] enableGroups) instead. Mind the parameter order!")] + public static void SetReceivingEnabled(int[] enableGroups, int[] disableGroups) + { + if (!VerifyCanUseNetwork()) + { + return; + } + + byte[] disableByteGroups = null; + byte[] enableByteGroups = null; + + if (enableGroups != null) + { + enableByteGroups = new byte[enableGroups.Length]; + Array.Copy(enableGroups, enableByteGroups, enableGroups.Length); + } + if (disableGroups != null) + { + disableByteGroups = new byte[disableGroups.Length]; + Array.Copy(disableGroups, disableByteGroups, disableGroups.Length); + } + + networkingPeer.SetInterestGroups(disableByteGroups, enableByteGroups); + } + + /// Enable/disable receiving on given Interest Groups (applied to PhotonViews). + /// + /// A client can tell the server which Interest Groups it's interested in. + /// The server will only forward events for those Interest Groups to that client (saving bandwidth and performance). + /// + /// See: https://doc.photonengine.com/en-us/pun/current/gameplay/interestgroups + /// + /// See: https://doc.photonengine.com/en-us/pun/current/demos-and-tutorials/package-demos/culling-demo + /// + /// The interest groups to disable (or null). + /// The interest groups to enable (or null). + public static void SetInterestGroups(byte[] disableGroups, byte[] enableGroups) + { + if (!VerifyCanUseNetwork()) + { + return; + } + networkingPeer.SetInterestGroups(disableGroups, enableGroups); + } + + + + [Obsolete("Use SetSendingEnabled(byte group, bool enabled). Interest Groups have a byte-typed ID. Mind the parameter order.")] + public static void SetSendingEnabled(int group, bool enabled) + { + SetSendingEnabled((byte)group, enabled); + } + + /// Enable/disable sending on given group (applied to PhotonViews) + /// + /// This does not interact with the Photon server-side. + /// It's just a client-side setting to suppress updates, should they be sent to one of the blocked groups. + /// + /// This setting is not particularly useful, as it means that updates literally never reach the server or anyone else. + /// Use with care. + /// + /// The interest group to affect. + /// Sets if sending to group is enabled (or not). + public static void SetSendingEnabled(byte group, bool enabled) + { + if (!VerifyCanUseNetwork()) + { + return; + } + + networkingPeer.SetSendingEnabled(group, enabled); + } + + + [Obsolete("Use SetSendingEnabled(byte group, bool enabled). Interest Groups have a byte-typed ID. Mind the parameter order.")] + public static void SetSendingEnabled(int[] enableGroups, int[] disableGroups) + { + byte[] disableByteGroups = null; + byte[] enableByteGroups = null; + + if (enableGroups != null) + { + enableByteGroups = new byte[enableGroups.Length]; + Array.Copy(enableGroups, enableByteGroups, enableGroups.Length); + } + if (disableGroups != null) + { + disableByteGroups = new byte[disableGroups.Length]; + Array.Copy(disableGroups, disableByteGroups, disableGroups.Length); + } + + SetSendingEnabled(disableByteGroups, enableByteGroups); + } + + /// Enable/disable sending on given groups (applied to PhotonViews) + /// + /// This does not interact with the Photon server-side. + /// It's just a client-side setting to suppress updates, should they be sent to one of the blocked groups. + /// + /// This setting is not particularly useful, as it means that updates literally never reach the server or anyone else. + /// Use with care. + /// The interest groups to enable sending on (or null). + /// The interest groups to disable sending on (or null). + public static void SetSendingEnabled(byte[] disableGroups, byte[] enableGroups) + { + if (!VerifyCanUseNetwork()) + { + return; + } + + networkingPeer.SetSendingEnabled(disableGroups, enableGroups); + } + + + + /// + /// Sets level prefix for PhotonViews instantiated later on. Don't set it if you need only one! + /// + /// + /// Important: If you don't use multiple level prefixes, simply don't set this value. The + /// default value is optimized out of the traffic. + /// + /// This won't affect existing PhotonViews (they can't be changed yet for existing PhotonViews). + /// + /// Messages sent with a different level prefix will be received but not executed. This affects + /// RPCs, Instantiates and synchronization. + /// + /// Be aware that PUN never resets this value, you'll have to do so yourself. + /// + /// Max value is short.MaxValue = 32767 + public static void SetLevelPrefix(short prefix) + { + if (!VerifyCanUseNetwork()) + { + return; + } + + networkingPeer.SetLevelPrefix(prefix); + } + + + /// Wraps loading a level to pause the network message-queue. Optionally syncs the loaded level in a room. + /// + /// To sync the loaded level in a room, set PhotonNetwork.automaticallySyncScene to true. + /// The Master Client of a room will then sync the loaded level with every other player in the room. + /// + /// While loading levels, it makes sense to not dispatch messages received by other players. + /// This method takes care of that by setting PhotonNetwork.isMessageQueueRunning = false and enabling + /// the queue when the level was loaded. + /// + /// You should make sure you don't fire RPCs before you load another scene (which doesn't contain + /// the same GameObjects and PhotonViews). You can call this in OnJoinedRoom. + /// + /// This uses Application.LoadLevel in Unity version not yet featuring the SceneManager API. + /// + /// + /// Number of the level to load. When using level numbers, make sure they are identical on all clients. + /// + public static void LoadLevel(int levelNumber) + { + if (PhotonNetwork.automaticallySyncScene) { + networkingPeer.SetLevelInPropsIfSynced (levelNumber); + } + + PhotonNetwork.isMessageQueueRunning = false; + networkingPeer.loadingLevelAndPausedNetwork = true; + SceneManager.LoadScene(levelNumber); + } + + + /// Wraps single asynchronous loading of a level to pause the network message-queue. Optionally syncs the loaded level in a room. + /// + /// To sync the loaded level in a room, set PhotonNetwork.automaticallySyncScene to true. + /// The Master Client of a room will then sync the loaded level with every other player in the room. + /// + /// While loading levels, it makes sense to not dispatch messages received by other players. + /// This method takes care of that by setting PhotonNetwork.isMessageQueueRunning = false and enabling + /// the queue when the level was loaded. + /// + /// You should make sure you don't fire RPCs before you load another scene (which doesn't contain + /// the same GameObjects and PhotonViews). You can call this in OnJoinedRoom. + /// + /// This uses Application.LoadLevel in Unity version not yet featuring the SceneManager API. + /// + /// The async operation. + /// + /// Number of the level to load. When using level numbers, make sure they are identical on all clients. + /// + public static AsyncOperation LoadLevelAsync(int levelNumber) + { + if (PhotonNetwork.automaticallySyncScene) { + networkingPeer.SetLevelInPropsIfSynced (levelNumber,true); + } + + PhotonNetwork.isMessageQueueRunning = false; + networkingPeer.loadingLevelAndPausedNetwork = true; + return SceneManager.LoadSceneAsync(levelNumber,LoadSceneMode.Single); + } + + + /// Wraps loading a level to pause the network message-queue. Optionally syncs the loaded level in a room. + /// + /// While loading levels, it makes sense to not dispatch messages received by other players. + /// This method takes care of that by setting PhotonNetwork.isMessageQueueRunning = false and enabling + /// the queue when the level was loaded. + /// + /// To sync the loaded level in a room, set PhotonNetwork.automaticallySyncScene to true. + /// The Master Client of a room will then sync the loaded level with every other player in the room. + /// + /// You should make sure you don't fire RPCs before you load another scene (which doesn't contain + /// the same GameObjects and PhotonViews). You can call this in OnJoinedRoom. + /// + /// This uses Application.LoadLevel in Unity version not yet featuring the SceneManager API. + /// + /// + /// Name of the level to load. Make sure it's available to all clients in the same room. + /// + public static void LoadLevel(string levelName) + { + if (PhotonNetwork.automaticallySyncScene) { + networkingPeer.SetLevelInPropsIfSynced (levelName); + } + + PhotonNetwork.isMessageQueueRunning = false; + networkingPeer.loadingLevelAndPausedNetwork = true; + SceneManager.LoadScene(levelName); + } + + + /// Wraps single asynchronous loading of a level to pause the network message-queue. Optionally syncs the loaded level in a room. + /// + /// While loading levels, it makes sense to not dispatch messages received by other players. + /// This method takes care of that by setting PhotonNetwork.isMessageQueueRunning = false and enabling + /// the queue when the level was loaded. + /// + /// To sync the loaded level in a room, set PhotonNetwork.automaticallySyncScene to true. + /// The Master Client of a room will then sync the loaded level with every other player in the room. + /// + /// You should make sure you don't fire RPCs before you load another scene (which doesn't contain + /// the same GameObjects and PhotonViews). You can call this in OnJoinedRoom. + /// + /// This uses Application.LoadLevel in Unity version not yet featuring the SceneManager API. + /// + /// The async operation. + /// + /// Name of the level to load. Make sure it's available to all clients in the same room. + /// + /// LoadSceneMode either single or additive + public static AsyncOperation LoadLevelAsync(string levelName) + { + if (PhotonNetwork.automaticallySyncScene) { + networkingPeer.SetLevelInPropsIfSynced (levelName,true); + } + + PhotonNetwork.isMessageQueueRunning = false; + networkingPeer.loadingLevelAndPausedNetwork = true; + return SceneManager.LoadSceneAsync(levelName,LoadSceneMode.Single); + } + + + /// + /// This operation makes Photon call your custom web-service by name (path) with the given parameters. + /// + /// + /// This is a server-side feature which must be setup in the Photon Cloud Dashboard prior to use. + /// + /// The Parameters will be converted into JSon format, so make sure your parameters are compatible. + /// + /// See PhotonNetworkingMessage.OnWebRpcResponse on how to get a response. + /// + /// It's important to understand that the OperationResponse only tells if the WebRPC could be called. + /// The content of the response contains any values your web-service sent and the error/success code. + /// In case the web-service failed, an error code and a debug message are usually inside the + /// OperationResponse. + /// + /// The class WebRpcResponse is a helper-class that extracts the most valuable content from the WebRPC + /// response. + /// + /// + /// Example callback implementation:
+    ///
+    /// public void OnWebRpcResponse(OperationResponse response)
+    /// {
+    ///     WebRpcResponse webResponse = new WebRpcResponse(operationResponse);
+    ///     if (webResponse.ReturnCode != 0) { //...
+    ///     }
+    ///
+    ///     switch (webResponse.Name) { //...
+    ///     }
+    ///     // and so on
+    /// }
+ ///
+ public static bool WebRpc(string name, object parameters) + { + return networkingPeer.WebRpc(name, parameters); + } + + +#if UNITY_EDITOR + + + /// + /// Finds the asset path base on its name or search query: https://docs.unity3d.com/ScriptReference/AssetDatabase.FindAssets.html + /// + /// The asset path. + /// Asset. + public static string FindAssetPath(string asset) + { + string[] guids = AssetDatabase.FindAssets (asset, null); + if (guids.Length != 1) + { + return string.Empty; + } else + { + return AssetDatabase.GUIDToAssetPath (guids [0]); + } + } + + + /// + /// Finds the pun asset folder. Something like Assets/Photon Unity Networking/Resources/ + /// + /// The pun asset folder. + public static string FindPunAssetFolder() + { + string _thisPath = FindAssetPath("PhotonClasses"); + string _PunFolderPath = string.Empty; + + _PunFolderPath = GetParent(_thisPath,"Photon Unity Networking"); + + if (_PunFolderPath != null) + { + return "Assets" + _PunFolderPath.Substring(Application.dataPath.Length)+"/"; + } + + return "Assets/Photon Unity Networking/"; + } + + /// + /// Gets the parent directory of a path. Recursive Function, will return null if parentName not found + /// + /// The parent directory + /// Path. + /// Parent name. + public static string GetParent(string path, string parentName) + { + var dir = new DirectoryInfo(path); + + if (dir.Parent == null) + { + return null; + } + + if (string.IsNullOrEmpty(parentName)) + { + return dir.Parent.FullName; + } + + if (dir.Parent.Name == parentName) + { + return dir.Parent.FullName; + } + + return GetParent(dir.Parent.FullName, parentName); + } + + + [Conditional("UNITY_EDITOR")] + public static void CreateSettings() + { + PhotonNetwork.PhotonServerSettings = (ServerSettings)Resources.Load(PhotonNetwork.serverSettingsAssetFile, typeof(ServerSettings)); + if (PhotonNetwork.PhotonServerSettings != null) + { + return; + } + + // find out if ServerSettings can be instantiated (existing script check) + ScriptableObject serverSettingTest = ScriptableObject.CreateInstance("ServerSettings"); + if (serverSettingTest == null) + { + Debug.LogError("missing settings script"); + return; + } + UnityEngine.Object.DestroyImmediate(serverSettingTest); + + + // if still not loaded, create one + if (PhotonNetwork.PhotonServerSettings == null) + { + string _PunResourcesPath = PhotonNetwork.FindPunAssetFolder(); + + _PunResourcesPath += "Resources/"; + + + string serverSettingsAssetPath = _PunResourcesPath+ PhotonNetwork.serverSettingsAssetFile + ".asset"; + string settingsPath = Path.GetDirectoryName(serverSettingsAssetPath); + if (!Directory.Exists(settingsPath)) + { + Directory.CreateDirectory(settingsPath); + AssetDatabase.ImportAsset(settingsPath); + } + + PhotonNetwork.PhotonServerSettings = (ServerSettings)ScriptableObject.CreateInstance("ServerSettings"); + if (PhotonNetwork.PhotonServerSettings != null) + { + AssetDatabase.CreateAsset(PhotonNetwork.PhotonServerSettings, serverSettingsAssetPath); + } + else + { + Debug.LogError("PUN failed creating a settings file. ScriptableObject.CreateInstance(\"ServerSettings\") returned null. Will try again later."); + } + } + } + + + /// + /// Internally used by Editor scripts, called on Hierarchy change (includes scene save) to remove surplus hidden PhotonHandlers. + /// + public static void InternalCleanPhotonMonoFromSceneIfStuck() + { + PhotonHandler[] photonHandlers = GameObject.FindObjectsOfType(typeof(PhotonHandler)) as PhotonHandler[]; + if (photonHandlers != null && photonHandlers.Length > 0) + { + Debug.Log("Cleaning up hidden PhotonHandler instances in scene. Please save it. This is not an issue."); + foreach (PhotonHandler photonHandler in photonHandlers) + { + // Debug.Log("Removing Handler: " + photonHandler + " photonHandler.gameObject: " + photonHandler.gameObject); + photonHandler.gameObject.hideFlags = 0; + + if (photonHandler.gameObject != null && photonHandler.gameObject.name == "PhotonMono") + { + GameObject.DestroyImmediate(photonHandler.gameObject); + } + + Component.DestroyImmediate(photonHandler); + } + } + } +#endif + +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonNetwork.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonNetwork.cs.meta new file mode 100644 index 0000000..23f48a0 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonNetwork.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 88e11b3353de7e94d84b1ec5adbdd15e +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonPlayer.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonPlayer.cs new file mode 100644 index 0000000..6ea4946 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonPlayer.cs @@ -0,0 +1,428 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2011 Exit Games GmbH +// +// +// Represents a player, identified by actorID (a.k.a. ActorNumber). +// Caches properties of a player. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using ExitGames.Client.Photon; +using UnityEngine; +using Hashtable = ExitGames.Client.Photon.Hashtable; + + +/// +/// Summarizes a "player" within a room, identified (in that room) by actorID. +/// +/// +/// Each player has an actorId (or ID), valid for that room. It's -1 until it's assigned by server. +/// Each client can set it's player's custom properties with SetCustomProperties, even before being in a room. +/// They are synced when joining a room. +/// +/// \ingroup publicApi +public class PhotonPlayer : IComparable, IComparable, IEquatable, IEquatable +{ + /// This player's actorID + public int ID + { + get { return this.actorID; } + } + + /// Identifier of this player in current room. + private int actorID = -1; + + private string nameField = ""; + + /// Nickname of this player. + /// Set the PhotonNetwork.playerName to make the name synchronized in a room. + public string NickName + { + get + { + return this.nameField; + } + set + { + if (!IsLocal) + { + Debug.LogError("Error: Cannot change the name of a remote player!"); + return; + } + if (string.IsNullOrEmpty(value) || value.Equals(this.nameField)) + { + return; + } + + this.nameField = value; + PhotonNetwork.playerName = value; // this will sync the local player's name in a room + } + } + + /// UserId of the player, available when the room got created with RoomOptions.PublishUserId = true. + /// Useful for PhotonNetwork.FindFriends and blocking slots in a room for expected players (e.g. in PhotonNetwork.CreateRoom). + public string UserId { get; internal set; } + + /// Only one player is controlled by each client. Others are not local. + public readonly bool IsLocal = false; + + /// + /// True if this player is the Master Client of the current room. + /// + /// + /// See also: PhotonNetwork.masterClient. + /// + public bool IsMasterClient + { + get { return (PhotonNetwork.networkingPeer.mMasterClientId == this.ID); } + } + + /// Players might be inactive in a room when PlayerTTL for a room is > 0. If true, the player is not getting events from this room (now) but can return later. + public bool IsInactive { get; set; } // needed for rejoins + + /// Read-only cache for custom properties of player. Set via PhotonPlayer.SetCustomProperties. + /// + /// Don't modify the content of this Hashtable. Use SetCustomProperties and the + /// properties of this class to modify values. When you use those, the client will + /// sync values with the server. + /// + /// + public Hashtable CustomProperties { get; internal set; } + + /// Creates a Hashtable with all properties (custom and "well known" ones). + /// If used more often, this should be cached. + public Hashtable AllProperties + { + get + { + Hashtable allProps = new Hashtable(); + allProps.Merge(this.CustomProperties); + allProps[ActorProperties.PlayerName] = this.NickName; + return allProps; + } + } + + /// Can be used to store a reference that's useful to know "by player". + /// Example: Set a player's character as Tag by assigning the GameObject on Instantiate. + public object TagObject; + + + /// + /// Creates a PhotonPlayer instance. + /// + /// If this is the local peer's player (or a remote one). + /// ID or ActorNumber of this player in the current room (a shortcut to identify each player in room) + /// Name of the player (a "well known property"). + public PhotonPlayer(bool isLocal, int actorID, string name) + { + this.CustomProperties = new Hashtable(); + this.IsLocal = isLocal; + this.actorID = actorID; + this.nameField = name; + } + + /// + /// Internally used to create players from event Join + /// + protected internal PhotonPlayer(bool isLocal, int actorID, Hashtable properties) + { + this.CustomProperties = new Hashtable(); + this.IsLocal = isLocal; + this.actorID = actorID; + + this.InternalCacheProperties(properties); + } + + /// + /// Makes PhotonPlayer comparable + /// + public override bool Equals(object p) + { + PhotonPlayer pp = p as PhotonPlayer; + return (pp != null && this.GetHashCode() == pp.GetHashCode()); + } + + public override int GetHashCode() + { + return this.ID; + } + + /// + /// Used internally, to update this client's playerID when assigned. + /// + internal void InternalChangeLocalID(int newID) + { + if (!this.IsLocal) + { + Debug.LogError("ERROR You should never change PhotonPlayer IDs!"); + return; + } + + this.actorID = newID; + } + + /// + /// Caches custom properties for this player. + /// + internal void InternalCacheProperties(Hashtable properties) + { + if (properties == null || properties.Count == 0 || this.CustomProperties.Equals(properties)) + { + return; + } + + if (properties.ContainsKey(ActorProperties.PlayerName)) + { + this.nameField = (string)properties[ActorProperties.PlayerName]; + } + if (properties.ContainsKey(ActorProperties.UserId)) + { + this.UserId = (string)properties[ActorProperties.UserId]; + } + if (properties.ContainsKey(ActorProperties.IsInactive)) + { + this.IsInactive = (bool)properties[ActorProperties.IsInactive]; //TURNBASED new well-known propery for players + } + + this.CustomProperties.MergeStringKeys(properties); + this.CustomProperties.StripKeysWithNullValues(); + } + + + /// + /// Updates the this player's Custom Properties with new/updated key-values. + /// + /// + /// Custom Properties are a key-value set (Hashtable) which is available to all players in a room. + /// They can relate to the room or individual players and are useful when only the current value + /// of something is of interest. For example: The map of a room. + /// All keys must be strings. + /// + /// The Room and the PhotonPlayer class both have SetCustomProperties methods. + /// Also, both classes offer access to current key-values by: customProperties. + /// + /// Always use SetCustomProperties to change values. + /// To reduce network traffic, set only values that actually changed. + /// New properties are added, existing values are updated. + /// Other values will not be changed, so only provide values that changed or are new. + /// + /// To delete a named (custom) property of this room, use null as value. + /// + /// Locally, SetCustomProperties will update it's cache without delay. + /// Other clients are updated through Photon (the server) with a fitting operation. + /// + /// Check and Swap + /// + /// SetCustomProperties have the option to do a server-side Check-And-Swap (CAS): + /// Values only get updated if the expected values are correct. + /// The expectedValues can be different key/values than the propertiesToSet. So you can + /// check some key and set another key's value (if the check succeeds). + /// + /// If the client's knowledge of properties is wrong or outdated, it can't set values with CAS. + /// This can be useful to keep players from concurrently setting values. For example: If all players + /// try to pickup some card or item, only one should get it. With CAS, only the first SetProperties + /// gets executed server-side and any other (sent at the same time) fails. + /// + /// The server will broadcast successfully changed values and the local "cache" of customProperties + /// only gets updated after a roundtrip (if anything changed). + /// + /// You can do a "webForward": Photon will send the changed properties to a WebHook defined + /// for your application. + /// + /// OfflineMode + /// + /// While PhotonNetwork.offlineMode is true, the expectedValues and webForward parameters are ignored. + /// In OfflineMode, the local customProperties values are immediately updated (without the roundtrip). + /// + /// The new properties to be set. + /// At least one property key/value set to check server-side. Key and value must be correct. Ignored in OfflineMode. + /// Set to true, to forward the set properties to a WebHook, defined for this app (in Dashboard). Ignored in OfflineMode. + public void SetCustomProperties(Hashtable propertiesToSet, Hashtable expectedValues = null, bool webForward = false) + { + if (propertiesToSet == null) + { + return; + } + + Hashtable customProps = propertiesToSet.StripToStringKeys() as Hashtable; + Hashtable customPropsToCheck = expectedValues.StripToStringKeys() as Hashtable; + + + // no expected values -> set and callback + bool noCas = customPropsToCheck == null || customPropsToCheck.Count == 0; + bool inOnlineRoom = this.actorID > 0 && !PhotonNetwork.offlineMode; + + if (noCas) + { + this.CustomProperties.Merge(customProps); + this.CustomProperties.StripKeysWithNullValues(); + } + + if (inOnlineRoom) + { + PhotonNetwork.networkingPeer.OpSetPropertiesOfActor(this.actorID, customProps, customPropsToCheck, webForward); + } + + if (!inOnlineRoom || noCas) + { + this.InternalCacheProperties(customProps); + NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnPhotonPlayerPropertiesChanged, this, customProps); + } + } + + /// + /// Try to get a specific player by id. + /// + /// ActorID + /// The player with matching actorID or null, if the actorID is not in use. + public static PhotonPlayer Find(int ID) + { + if (PhotonNetwork.networkingPeer != null) + { + return PhotonNetwork.networkingPeer.GetPlayerWithId(ID); + } + return null; + } + + public PhotonPlayer Get(int id) + { + return PhotonPlayer.Find(id); + } + + public PhotonPlayer GetNext() + { + return GetNextFor(this.ID); + } + + public PhotonPlayer GetNextFor(PhotonPlayer currentPlayer) + { + if (currentPlayer == null) + { + return null; + } + return GetNextFor(currentPlayer.ID); + } + + public PhotonPlayer GetNextFor(int currentPlayerId) + { + if (PhotonNetwork.networkingPeer == null || PhotonNetwork.networkingPeer.mActors == null || PhotonNetwork.networkingPeer.mActors.Count < 2) + { + return null; + } + + Dictionary players = PhotonNetwork.networkingPeer.mActors; + int nextHigherId = int.MaxValue; // we look for the next higher ID + int lowestId = currentPlayerId; // if we are the player with the highest ID, there is no higher and we return to the lowest player's id + + foreach (int playerid in players.Keys) + { + if (playerid < lowestId) + { + lowestId = playerid; // less than any other ID (which must be at least less than this player's id). + } + else if (playerid > currentPlayerId && playerid < nextHigherId) + { + nextHigherId = playerid; // more than our ID and less than those found so far. + } + } + + //UnityEngine.Debug.LogWarning("Debug. " + currentPlayerId + " lower: " + lowestId + " higher: " + nextHigherId + " "); + //UnityEngine.Debug.LogWarning(this.RoomReference.GetPlayer(currentPlayerId)); + //UnityEngine.Debug.LogWarning(this.RoomReference.GetPlayer(lowestId)); + //if (nextHigherId != int.MaxValue) UnityEngine.Debug.LogWarning(this.RoomReference.GetPlayer(nextHigherId)); + return (nextHigherId != int.MaxValue) ? players[nextHigherId] : players[lowestId]; + } + + #region IComparable implementation + + public int CompareTo (PhotonPlayer other) + { + if ( other == null) + { + return 0; + } + + return this.GetHashCode().CompareTo(other.GetHashCode()); + } + + public int CompareTo (int other) + { + return this.GetHashCode().CompareTo(other); + } + + #endregion + + #region IEquatable implementation + + public bool Equals (PhotonPlayer other) + { + if ( other == null) + { + return false; + } + + return this.GetHashCode().Equals(other.GetHashCode()); + } + + public bool Equals (int other) + { + return this.GetHashCode().Equals(other); + } + + #endregion + + /// + /// Brief summary string of the PhotonPlayer. Includes name or player.ID and if it's the Master Client. + /// + public override string ToString() + { + if (string.IsNullOrEmpty(this.NickName)) + { + return string.Format("#{0:00}{1}{2}", this.ID, this.IsInactive ? " (inactive)" : " ", this.IsMasterClient ? "(master)":""); + } + + return string.Format("'{0}'{1}{2}", this.NickName, this.IsInactive ? " (inactive)" : " ", this.IsMasterClient ? "(master)" : ""); + } + + /// + /// String summary of the PhotonPlayer: player.ID, name and all custom properties of this user. + /// + /// + /// Use with care and not every frame! + /// Converts the customProperties to a String on every single call. + /// + public string ToStringFull() + { + return string.Format("#{0:00} '{1}'{2} {3}", this.ID, this.NickName, this.IsInactive ? " (inactive)" : "", this.CustomProperties.ToStringFull()); + } + + + #region Obsoleted variable names + + [Obsolete("Please use NickName (updated case for naming).")] + public string name { get { return this.NickName; } set { this.NickName = value; } } + + [Obsolete("Please use UserId (updated case for naming).")] + public string userId { get { return this.UserId; } internal set { this.UserId = value; } } + + [Obsolete("Please use IsLocal (updated case for naming).")] + public bool isLocal { get { return this.IsLocal; } } + + [Obsolete("Please use IsMasterClient (updated case for naming).")] + public bool isMasterClient { get { return this.IsMasterClient; } } + + [Obsolete("Please use IsInactive (updated case for naming).")] + public bool isInactive { get { return this.IsInactive; } set { this.IsInactive = value; } } + + [Obsolete("Please use CustomProperties (updated case for naming).")] + public Hashtable customProperties { get { return this.CustomProperties; } internal set { this.CustomProperties = value; } } + + [Obsolete("Please use AllProperties (updated case for naming).")] + public Hashtable allProperties { get { return this.AllProperties; } } + + #endregion +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonPlayer.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonPlayer.cs.meta new file mode 100644 index 0000000..f24dbae --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonPlayer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e3e4b5bebc687044b9c6c2803c36be3d +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonStatsGui.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonStatsGui.cs new file mode 100644 index 0000000..2f8a4c2 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonStatsGui.cs @@ -0,0 +1,159 @@ +#pragma warning disable 1587 +/// \file +/// Part of the [Optional GUI](@ref optionalGui). +#pragma warning restore 1587 + + +using ExitGames.Client.Photon; +using UnityEngine; + + +/// +/// Basic GUI to show traffic and health statistics of the connection to Photon, +/// toggled by shift+tab. +/// +/// +/// The shown health values can help identify problems with connection losses or performance. +/// Example: +/// If the time delta between two consecutive SendOutgoingCommands calls is a second or more, +/// chances rise for a disconnect being caused by this (because acknowledgements to the server +/// need to be sent in due time). +/// +/// \ingroup optionalGui +public class PhotonStatsGui : MonoBehaviour +{ + /// Shows or hides GUI (does not affect if stats are collected). + public bool statsWindowOn = true; + + /// Option to turn collecting stats on or off (used in Update()). + public bool statsOn = true; + + /// Shows additional "health" values of connection. + public bool healthStatsVisible; + + /// Shows additional "lower level" traffic stats. + public bool trafficStatsOn; + + /// Show buttons to control stats and reset them. + public bool buttonsOn; + + /// Positioning rect for window. + public Rect statsRect = new Rect(0, 100, 200, 50); + + /// Unity GUI Window ID (must be unique or will cause issues). + public int WindowId = 100; + + + public void Start() + { + if (this.statsRect.x <= 0) + { + this.statsRect.x = Screen.width - this.statsRect.width; + } + } + + /// Checks for shift+tab input combination (to toggle statsOn). + public void Update() + { + if (Input.GetKeyDown(KeyCode.Tab) && Input.GetKey(KeyCode.LeftShift)) + { + this.statsWindowOn = !this.statsWindowOn; + this.statsOn = true; // enable stats when showing the window + } + } + + public void OnGUI() + { + if (PhotonNetwork.networkingPeer.TrafficStatsEnabled != statsOn) + { + PhotonNetwork.networkingPeer.TrafficStatsEnabled = this.statsOn; + } + + if (!this.statsWindowOn) + { + return; + } + + this.statsRect = GUILayout.Window(this.WindowId, this.statsRect, this.TrafficStatsWindow, "Messages (shift+tab)"); + } + + public void TrafficStatsWindow(int windowID) + { + bool statsToLog = false; + TrafficStatsGameLevel gls = PhotonNetwork.networkingPeer.TrafficStatsGameLevel; + long elapsedMs = PhotonNetwork.networkingPeer.TrafficStatsElapsedMs / 1000; + if (elapsedMs == 0) + { + elapsedMs = 1; + } + + GUILayout.BeginHorizontal(); + this.buttonsOn = GUILayout.Toggle(this.buttonsOn, "buttons"); + this.healthStatsVisible = GUILayout.Toggle(this.healthStatsVisible, "health"); + this.trafficStatsOn = GUILayout.Toggle(this.trafficStatsOn, "traffic"); + GUILayout.EndHorizontal(); + + string total = string.Format("Out {0,4} | In {1,4} | Sum {2,4}", gls.TotalOutgoingMessageCount, gls.TotalIncomingMessageCount, gls.TotalMessageCount); + string elapsedTime = string.Format("{0}sec average:", elapsedMs); + string average = string.Format("Out {0,4} | In {1,4} | Sum {2,4}", gls.TotalOutgoingMessageCount / elapsedMs, gls.TotalIncomingMessageCount / elapsedMs, gls.TotalMessageCount / elapsedMs); + GUILayout.Label(total); + GUILayout.Label(elapsedTime); + GUILayout.Label(average); + + if (this.buttonsOn) + { + GUILayout.BeginHorizontal(); + this.statsOn = GUILayout.Toggle(this.statsOn, "stats on"); + if (GUILayout.Button("Reset")) + { + PhotonNetwork.networkingPeer.TrafficStatsReset(); + PhotonNetwork.networkingPeer.TrafficStatsEnabled = true; + } + statsToLog = GUILayout.Button("To Log"); + GUILayout.EndHorizontal(); + } + + string trafficStatsIn = string.Empty; + string trafficStatsOut = string.Empty; + if (this.trafficStatsOn) + { + GUILayout.Box("Traffic Stats"); + trafficStatsIn = "Incoming: \n" + PhotonNetwork.networkingPeer.TrafficStatsIncoming.ToString(); + trafficStatsOut = "Outgoing: \n" + PhotonNetwork.networkingPeer.TrafficStatsOutgoing.ToString(); + GUILayout.Label(trafficStatsIn); + GUILayout.Label(trafficStatsOut); + } + + string healthStats = string.Empty; + if (this.healthStatsVisible) + { + GUILayout.Box("Health Stats"); + healthStats = string.Format( + "ping: {6}[+/-{7}]ms resent:{8} \n\nmax ms between\nsend: {0,4} \ndispatch: {1,4} \n\nlongest dispatch for: \nev({3}):{2,3}ms \nop({5}):{4,3}ms", + gls.LongestDeltaBetweenSending, + gls.LongestDeltaBetweenDispatching, + gls.LongestEventCallback, + gls.LongestEventCallbackCode, + gls.LongestOpResponseCallback, + gls.LongestOpResponseCallbackOpCode, + PhotonNetwork.networkingPeer.RoundTripTime, + PhotonNetwork.networkingPeer.RoundTripTimeVariance, + PhotonNetwork.networkingPeer.ResentReliableCommands); + GUILayout.Label(healthStats); + } + + if (statsToLog) + { + string complete = string.Format("{0}\n{1}\n{2}\n{3}\n{4}\n{5}", total, elapsedTime, average, trafficStatsIn, trafficStatsOut, healthStats); + Debug.Log(complete); + } + + // if anything was clicked, the height of this window is likely changed. reduce it to be layouted again next frame + if (GUI.changed) + { + this.statsRect.height = 100; + } + + GUI.DragWindow(); + } +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonStatsGui.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonStatsGui.cs.meta new file mode 100644 index 0000000..fadf07f --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonStatsGui.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d06466c03d263624786afa88b52928b6 +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonStreamQueue.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonStreamQueue.cs new file mode 100644 index 0000000..ec3f9c6 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonStreamQueue.cs @@ -0,0 +1,187 @@ +using System.Collections.Generic; +using UnityEngine; + +/// +/// The PhotonStreamQueue helps you poll object states at higher frequencies then what +/// PhotonNetwork.sendRate dictates and then sends all those states at once when +/// Serialize() is called. +/// On the receiving end you can call Deserialize() and then the stream will roll out +/// the received object states in the same order and timeStep they were recorded in. +/// +public class PhotonStreamQueue +{ + #region Members + + private int m_SampleRate; + private int m_SampleCount; + private int m_ObjectsPerSample = -1; + + private float m_LastSampleTime = -Mathf.Infinity; + private int m_LastFrameCount = -1; + private int m_NextObjectIndex = -1; + + private List m_Objects = new List(); + + private bool m_IsWriting; + + #endregion + + /// + /// Initializes a new instance of the class. + /// + /// How many times per second should the object states be sampled + public PhotonStreamQueue(int sampleRate) + { + this.m_SampleRate = sampleRate; + } + + private void BeginWritePackage() + { + //If not enough time has passed since the last sample, we don't want to write anything + if (Time.realtimeSinceStartup < this.m_LastSampleTime + 1f/this.m_SampleRate) + { + this.m_IsWriting = false; + return; + } + + if (this.m_SampleCount == 1) + { + this.m_ObjectsPerSample = this.m_Objects.Count; + //Debug.Log( "Setting m_ObjectsPerSample to " + m_ObjectsPerSample ); + } + else if (this.m_SampleCount > 1) + { + if (this.m_Objects.Count/this.m_SampleCount != this.m_ObjectsPerSample) + { + Debug.LogWarning("The number of objects sent via a PhotonStreamQueue has to be the same each frame"); + Debug.LogWarning("Objects in List: " + this.m_Objects.Count + " / Sample Count: " + this.m_SampleCount + " = " + (this.m_Objects.Count/this.m_SampleCount) + " != " + this.m_ObjectsPerSample); + } + } + + this.m_IsWriting = true; + this.m_SampleCount++; + this.m_LastSampleTime = Time.realtimeSinceStartup; + + /*if( m_SampleCount > 1 ) + { + Debug.Log( "Check: " + m_Objects.Count + " / " + m_SampleCount + " = " + ( m_Objects.Count / m_SampleCount ) + " = " + m_ObjectsPerSample ); + }*/ + } + + /// + /// Resets the PhotonStreamQueue. You need to do this whenever the amount of objects you are observing changes + /// + public void Reset() + { + this.m_SampleCount = 0; + this.m_ObjectsPerSample = -1; + + this.m_LastSampleTime = -Mathf.Infinity; + this.m_LastFrameCount = -1; + + this.m_Objects.Clear(); + } + + /// + /// Adds the next object to the queue. This works just like PhotonStream.SendNext + /// + /// The object you want to add to the queue + public void SendNext(object obj) + { + if (Time.frameCount != this.m_LastFrameCount) + { + BeginWritePackage(); + } + + this.m_LastFrameCount = Time.frameCount; + + if (this.m_IsWriting == false) + { + return; + } + + this.m_Objects.Add(obj); + } + + /// + /// Determines whether the queue has stored any objects + /// + public bool HasQueuedObjects() + { + return this.m_NextObjectIndex != -1; + } + + /// + /// Receives the next object from the queue. This works just like PhotonStream.ReceiveNext + /// + /// + public object ReceiveNext() + { + if (this.m_NextObjectIndex == -1) + { + return null; + } + + if (this.m_NextObjectIndex >= this.m_Objects.Count) + { + this.m_NextObjectIndex -= this.m_ObjectsPerSample; + } + + return this.m_Objects[this.m_NextObjectIndex++]; + } + + /// + /// Serializes the specified stream. Call this in your OnPhotonSerializeView method to send the whole recorded stream. + /// + /// The PhotonStream you receive as a parameter in OnPhotonSerializeView + public void Serialize(PhotonStream stream) + { + // TODO: find a better solution for this: + // the "if" is a workaround for packages which have only 1 sample/frame. in that case, SendNext didn't set the obj per sample. + if (m_Objects.Count > 0 && this.m_ObjectsPerSample < 0) + { + this.m_ObjectsPerSample = m_Objects.Count; + } + + stream.SendNext(this.m_SampleCount); + stream.SendNext(this.m_ObjectsPerSample); + + for (int i = 0; i < this.m_Objects.Count; ++i) + { + stream.SendNext(this.m_Objects[i]); + } + + //Debug.Log( "Serialize " + m_SampleCount + " samples with " + m_ObjectsPerSample + " objects per sample. object count: " + m_Objects.Count + " / " + ( m_SampleCount * m_ObjectsPerSample ) ); + + this.m_Objects.Clear(); + this.m_SampleCount = 0; + } + + /// + /// Deserializes the specified stream. Call this in your OnPhotonSerializeView method to receive the whole recorded stream. + /// + /// The PhotonStream you receive as a parameter in OnPhotonSerializeView + public void Deserialize(PhotonStream stream) + { + this.m_Objects.Clear(); + + this.m_SampleCount = (int)stream.ReceiveNext(); + this.m_ObjectsPerSample = (int)stream.ReceiveNext(); + + for (int i = 0; i < this.m_SampleCount*this.m_ObjectsPerSample; ++i) + { + this.m_Objects.Add(stream.ReceiveNext()); + } + + if (this.m_Objects.Count > 0) + { + this.m_NextObjectIndex = 0; + } + else + { + this.m_NextObjectIndex = -1; + } + + //Debug.Log( "Deserialized " + m_SampleCount + " samples with " + m_ObjectsPerSample + " objects per sample. object count: " + m_Objects.Count + " / " + ( m_SampleCount * m_ObjectsPerSample ) ); + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonStreamQueue.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonStreamQueue.cs.meta new file mode 100644 index 0000000..b225d0d --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonStreamQueue.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 006991e32d9020c4d896f161318a2bc0 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonView.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonView.cs new file mode 100644 index 0000000..03bff45 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonView.cs @@ -0,0 +1,692 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2011 Exit Games GmbH +// +// +// +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +using System; +using UnityEngine; +using System.Reflection; +using System.Collections.Generic; +using ExitGames.Client.Photon; + +#if UNITY_EDITOR +using UnityEditor; +#endif + + +public enum ViewSynchronization { Off, ReliableDeltaCompressed, Unreliable, UnreliableOnChange } +public enum OnSerializeTransform { OnlyPosition, OnlyRotation, OnlyScale, PositionAndRotation, All } +public enum OnSerializeRigidBody { OnlyVelocity, OnlyAngularVelocity, All } + +/// +/// Options to define how Ownership Transfer is handled per PhotonView. +/// +/// +/// This setting affects how RequestOwnership and TransferOwnership work at runtime. +/// +public enum OwnershipOption +{ + /// + /// Ownership is fixed. Instantiated objects stick with their creator, scene objects always belong to the Master Client. + /// + Fixed, + /// + /// Ownership can be taken away from the current owner who can't object. + /// + Takeover, + /// + /// Ownership can be requested with PhotonView.RequestOwnership but the current owner has to agree to give up ownership. + /// + /// The current owner has to implement IPunCallbacks.OnOwnershipRequest to react to the ownership request. + Request +} + + +/// +/// PUN's NetworkView replacement class for networking. Use it like a NetworkView. +/// +/// \ingroup publicApi +[AddComponentMenu("Photon Networking/Photon View &v")] +public class PhotonView : Photon.MonoBehaviour +{ + #if UNITY_EDITOR + [ContextMenu("Open PUN Wizard")] + void OpenPunWizard() + { + EditorApplication.ExecuteMenuItem("Window/Photon Unity Networking"); + } + #endif + + public int ownerId; + + public byte group = 0; + + protected internal bool mixedModeIsReliable = false; + + + /// + /// Flag to check if ownership of this photonView was set during the lifecycle. Used for checking when joining late if event with mismatched owner and sender needs addressing. + /// + /// true if owner ship was transfered; otherwise, false. + public bool OwnerShipWasTransfered; + + + // NOTE: this is now an integer because unity won't serialize short (needed for instantiation). we SEND only a short though! + // NOTE: prefabs have a prefixBackup of -1. this is replaced with any currentLevelPrefix that's used at runtime. instantiated GOs get their prefix set pre-instantiation (so those are not -1 anymore) + public int prefix + { + get + { + if (this.prefixBackup == -1 && PhotonNetwork.networkingPeer != null) + { + this.prefixBackup = PhotonNetwork.networkingPeer.currentLevelPrefix; + } + + return this.prefixBackup; + } + set { this.prefixBackup = value; } + } + + // this field is serialized by unity. that means it is copied when instantiating a persistent obj into the scene + public int prefixBackup = -1; + + /// + /// This is the instantiationData that was passed when calling PhotonNetwork.Instantiate* (if that was used to spawn this prefab) + /// + public object[] instantiationData + { + get + { + if (!this.didAwake) + { + // even though viewID and instantiationID are setup before the GO goes live, this data can't be set. as workaround: fetch it if needed + this.instantiationDataField = PhotonNetwork.networkingPeer.FetchInstantiationData(this.instantiationId); + } + return this.instantiationDataField; + } + set { this.instantiationDataField = value; } + } + + internal object[] instantiationDataField; + + /// + /// For internal use only, don't use + /// + protected internal object[] lastOnSerializeDataSent = null; + + /// + /// For internal use only, don't use + /// + protected internal object[] lastOnSerializeDataReceived = null; + + public ViewSynchronization synchronization; + + public OnSerializeTransform onSerializeTransformOption = OnSerializeTransform.PositionAndRotation; + + public OnSerializeRigidBody onSerializeRigidBodyOption = OnSerializeRigidBody.All; + + /// Defines if ownership of this PhotonView is fixed, can be requested or simply taken. + /// + /// Note that you can't edit this value at runtime. + /// The options are described in enum OwnershipOption. + /// The current owner has to implement IPunCallbacks.OnOwnershipRequest to react to the ownership request. + /// + public OwnershipOption ownershipTransfer = OwnershipOption.Fixed; + + public List ObservedComponents; + Dictionary m_OnSerializeMethodInfos = new Dictionary(3); + +#if UNITY_EDITOR + // Suppressing compiler warning "this variable is never used". Only used in the CustomEditor, only in Editor + #pragma warning disable 0414 + [SerializeField] + bool ObservedComponentsFoldoutOpen = true; + #pragma warning restore 0414 +#endif + + [SerializeField] + private int viewIdField = 0; + + /// + /// The ID of the PhotonView. Identifies it in a networked game (per room). + /// + /// See: [Network Instantiation](@ref instantiateManual) + public int viewID + { + get { return this.viewIdField; } + set + { + // if ID was 0 for an awakened PhotonView, the view should add itself into the networkingPeer.photonViewList after setup + bool viewMustRegister = this.didAwake && this.viewIdField == 0; + + // TODO: decide if a viewID can be changed once it wasn't 0. most likely that is not a good idea + // check if this view is in networkingPeer.photonViewList and UPDATE said list (so we don't keep the old viewID with a reference to this object) + // PhotonNetwork.networkingPeer.RemovePhotonView(this, true); + + this.ownerId = value / PhotonNetwork.MAX_VIEW_IDS; + + this.viewIdField = value; + + if (viewMustRegister) + { + PhotonNetwork.networkingPeer.RegisterPhotonView(this); + } + //Debug.Log("Set viewID: " + value + " -> owner: " + this.ownerId + " subId: " + this.subId); + } + } + + public int instantiationId; // if the view was instantiated with a GO, this GO has a instantiationID (first view's viewID) + + /// True if the PhotonView was loaded with the scene (game object) or instantiated with InstantiateSceneObject. + /// + /// Scene objects are not owned by a particular player but belong to the scene. Thus they don't get destroyed when their + /// creator leaves the game and the current Master Client can control them (whoever that is). + /// The ownerId is 0 (player IDs are 1 and up). + /// + public bool isSceneView + { + get { return this.CreatorActorNr == 0; } + } + + /// + /// The owner of a PhotonView is the player who created the GameObject with that view. Objects in the scene don't have an owner. + /// + /// + /// The owner/controller of a PhotonView is also the client which sends position updates of the GameObject. + /// + /// Ownership can be transferred to another player with PhotonView.TransferOwnership or any player can request + /// ownership by calling the PhotonView's RequestOwnership method. + /// The current owner has to implement IPunCallbacks.OnOwnershipRequest to react to the ownership request. + /// + public PhotonPlayer owner + { + get + { + return PhotonPlayer.Find(this.ownerId); + } + } + + public int OwnerActorNr + { + get { return this.ownerId; } + } + + public bool isOwnerActive + { + get { return this.ownerId != 0 && PhotonNetwork.networkingPeer.mActors.ContainsKey(this.ownerId); } + } + + public int CreatorActorNr + { + get { return this.viewIdField / PhotonNetwork.MAX_VIEW_IDS; } + } + + /// + /// True if the PhotonView is "mine" and can be controlled by this client. + /// + /// + /// PUN has an ownership concept that defines who can control and destroy each PhotonView. + /// True in case the owner matches the local PhotonPlayer. + /// True if this is a scene photonview on the Master client. + /// + public bool isMine + { + get + { + return (this.ownerId == PhotonNetwork.player.ID) || (!this.isOwnerActive && PhotonNetwork.isMasterClient); + } + } + + /// + /// The current master ID so that we can compare when we receive OnMasterClientSwitched() callback + /// It's public so that we can check it during ownerId assignments in networkPeer script + /// TODO: Maybe we can have the networkPeer always aware of the previous MasterClient? + /// + public int currentMasterID = -1; + protected internal bool didAwake; + + [SerializeField] + protected internal bool isRuntimeInstantiated; + + protected internal bool removedFromLocalViewList; + + internal MonoBehaviour[] RpcMonoBehaviours; + private MethodInfo OnSerializeMethodInfo; + + private bool failedToFindOnSerialize; + + /// Called by Unity on start of the application and does a setup the PhotonView. + protected internal void Awake() + { + if (this.viewID != 0) + { + // registration might be too late when some script (on this GO) searches this view BUT GetPhotonView() can search ALL in that case + PhotonNetwork.networkingPeer.RegisterPhotonView(this); + this.instantiationDataField = PhotonNetwork.networkingPeer.FetchInstantiationData(this.instantiationId); + } + + this.didAwake = true; + } + + /// + /// Depending on the PhotonView's ownershipTransfer setting, any client can request to become owner of the PhotonView. + /// + /// + /// Requesting ownership can give you control over a PhotonView, if the ownershipTransfer setting allows that. + /// The current owner might have to implement IPunCallbacks.OnOwnershipRequest to react to the ownership request. + /// + /// The owner/controller of a PhotonView is also the client which sends position updates of the GameObject. + /// + public void RequestOwnership() + { + PhotonNetwork.networkingPeer.RequestOwnership(this.viewID, this.ownerId); + } + + /// + /// Transfers the ownership of this PhotonView (and GameObject) to another player. + /// + /// + /// The owner/controller of a PhotonView is also the client which sends position updates of the GameObject. + /// + public void TransferOwnership(PhotonPlayer newOwner) + { + this.TransferOwnership(newOwner.ID); + } + + /// + /// Transfers the ownership of this PhotonView (and GameObject) to another player. + /// + /// + /// The owner/controller of a PhotonView is also the client which sends position updates of the GameObject. + /// + public void TransferOwnership(int newOwnerId) + { + PhotonNetwork.networkingPeer.TransferOwnership(this.viewID, newOwnerId); + this.ownerId = newOwnerId; // immediately switch ownership locally, to avoid more updates sent from this client. + } + + /// + ///Check ownerId assignment for sceneObjects to keep being owned by the MasterClient. + /// + /// New master client. + public void OnMasterClientSwitched(PhotonPlayer newMasterClient) + { + if (this.CreatorActorNr == 0 && !this.OwnerShipWasTransfered && (this.currentMasterID== -1 || this.ownerId==this.currentMasterID)) + { + this.ownerId = newMasterClient.ID; + } + + this.currentMasterID = newMasterClient.ID; + } + + + protected internal void OnDestroy() + { + if (!this.removedFromLocalViewList) + { + bool wasInList = PhotonNetwork.networkingPeer.LocalCleanPhotonView(this); + bool loading = false; + + #if (!UNITY_5 || UNITY_5_0 || UNITY_5_1) && !UNITY_5_3_OR_NEWER + loading = Application.isLoadingLevel; + #endif + + if (wasInList && !loading && this.instantiationId > 0 && !PhotonHandler.AppQuits && PhotonNetwork.logLevel >= PhotonLogLevel.Informational) + { + Debug.Log("PUN-instantiated '" + this.gameObject.name + "' got destroyed by engine. This is OK when loading levels. Otherwise use: PhotonNetwork.Destroy()."); + } + } + } + + public void SerializeView(PhotonStream stream, PhotonMessageInfo info) + { + if (this.ObservedComponents != null && this.ObservedComponents.Count > 0) + { + for (int i = 0; i < this.ObservedComponents.Count; ++i) + { + SerializeComponent(this.ObservedComponents[i], stream, info); + } + } + } + + public void DeserializeView(PhotonStream stream, PhotonMessageInfo info) + { + if (this.ObservedComponents != null && this.ObservedComponents.Count > 0) + { + for (int i = 0; i < this.ObservedComponents.Count; ++i) + { + DeserializeComponent(this.ObservedComponents[i], stream, info); + } + } + } + + protected internal void DeserializeComponent(Component component, PhotonStream stream, PhotonMessageInfo info) + { + if (component == null) + { + return; + } + + // Use incoming data according to observed type + if (component is MonoBehaviour) + { + ExecuteComponentOnSerialize(component, stream, info); + } + else if (component is Transform) + { + Transform trans = (Transform) component; + + switch (this.onSerializeTransformOption) + { + case OnSerializeTransform.All: + trans.localPosition = (Vector3) stream.ReceiveNext(); + trans.localRotation = (Quaternion) stream.ReceiveNext(); + trans.localScale = (Vector3) stream.ReceiveNext(); + break; + case OnSerializeTransform.OnlyPosition: + trans.localPosition = (Vector3) stream.ReceiveNext(); + break; + case OnSerializeTransform.OnlyRotation: + trans.localRotation = (Quaternion) stream.ReceiveNext(); + break; + case OnSerializeTransform.OnlyScale: + trans.localScale = (Vector3) stream.ReceiveNext(); + break; + case OnSerializeTransform.PositionAndRotation: + trans.localPosition = (Vector3) stream.ReceiveNext(); + trans.localRotation = (Quaternion) stream.ReceiveNext(); + break; + } + } + else if (component is Rigidbody) + { + Rigidbody rigidB = (Rigidbody) component; + + switch (this.onSerializeRigidBodyOption) + { + case OnSerializeRigidBody.All: + rigidB.velocity = (Vector3) stream.ReceiveNext(); + rigidB.angularVelocity = (Vector3) stream.ReceiveNext(); + break; + case OnSerializeRigidBody.OnlyAngularVelocity: + rigidB.angularVelocity = (Vector3) stream.ReceiveNext(); + break; + case OnSerializeRigidBody.OnlyVelocity: + rigidB.velocity = (Vector3) stream.ReceiveNext(); + break; + } + } + else if (component is Rigidbody2D) + { + Rigidbody2D rigidB = (Rigidbody2D) component; + + switch (this.onSerializeRigidBodyOption) + { + case OnSerializeRigidBody.All: + rigidB.velocity = (Vector2) stream.ReceiveNext(); + rigidB.angularVelocity = (float) stream.ReceiveNext(); + break; + case OnSerializeRigidBody.OnlyAngularVelocity: + rigidB.angularVelocity = (float) stream.ReceiveNext(); + break; + case OnSerializeRigidBody.OnlyVelocity: + rigidB.velocity = (Vector2) stream.ReceiveNext(); + break; + } + } + else + { + Debug.LogError("Type of observed is unknown when receiving."); + } + } + + protected internal void SerializeComponent(Component component, PhotonStream stream, PhotonMessageInfo info) + { + if (component == null) + { + return; + } + + if (component is MonoBehaviour) + { + ExecuteComponentOnSerialize(component, stream, info); + } + else if (component is Transform) + { + Transform trans = (Transform) component; + + switch (this.onSerializeTransformOption) + { + case OnSerializeTransform.All: + stream.SendNext(trans.localPosition); + stream.SendNext(trans.localRotation); + stream.SendNext(trans.localScale); + break; + case OnSerializeTransform.OnlyPosition: + stream.SendNext(trans.localPosition); + break; + case OnSerializeTransform.OnlyRotation: + stream.SendNext(trans.localRotation); + break; + case OnSerializeTransform.OnlyScale: + stream.SendNext(trans.localScale); + break; + case OnSerializeTransform.PositionAndRotation: + stream.SendNext(trans.localPosition); + stream.SendNext(trans.localRotation); + break; + } + } + else if (component is Rigidbody) + { + Rigidbody rigidB = (Rigidbody) component; + + switch (this.onSerializeRigidBodyOption) + { + case OnSerializeRigidBody.All: + stream.SendNext(rigidB.velocity); + stream.SendNext(rigidB.angularVelocity); + break; + case OnSerializeRigidBody.OnlyAngularVelocity: + stream.SendNext(rigidB.angularVelocity); + break; + case OnSerializeRigidBody.OnlyVelocity: + stream.SendNext(rigidB.velocity); + break; + } + } + else if (component is Rigidbody2D) + { + Rigidbody2D rigidB = (Rigidbody2D) component; + + switch (this.onSerializeRigidBodyOption) + { + case OnSerializeRigidBody.All: + stream.SendNext(rigidB.velocity); + stream.SendNext(rigidB.angularVelocity); + break; + case OnSerializeRigidBody.OnlyAngularVelocity: + stream.SendNext(rigidB.angularVelocity); + break; + case OnSerializeRigidBody.OnlyVelocity: + stream.SendNext(rigidB.velocity); + break; + } + } + else + { + Debug.LogError("Observed type is not serializable: " + component.GetType()); + } + } + + protected internal void ExecuteComponentOnSerialize(Component component, PhotonStream stream, PhotonMessageInfo info) + { + IPunObservable observable = component as IPunObservable; + if (observable != null) + { + observable.OnPhotonSerializeView(stream, info); + } + else if (component != null) + { + MethodInfo method = null; + bool found = this.m_OnSerializeMethodInfos.TryGetValue(component, out method); + if (!found) + { + bool foundMethod = NetworkingPeer.GetMethod(component as MonoBehaviour, PhotonNetworkingMessage.OnPhotonSerializeView.ToString(), out method); + + if (foundMethod == false) + { + Debug.LogError("The observed monobehaviour (" + component.name + ") of this PhotonView does not implement OnPhotonSerializeView()!"); + method = null; + } + + this.m_OnSerializeMethodInfos.Add(component, method); + } + + if (method != null) + { + method.Invoke(component, new object[] {stream, info}); + } + } + } + + + /// + /// Can be used to refesh the list of MonoBehaviours on this GameObject while PhotonNetwork.UseRpcMonoBehaviourCache is true. + /// + /// + /// Set PhotonNetwork.UseRpcMonoBehaviourCache to true to enable the caching. + /// Uses this.GetComponents() to get a list of MonoBehaviours to call RPCs on (potentially). + /// + /// While PhotonNetwork.UseRpcMonoBehaviourCache is false, this method has no effect, + /// because the list is refreshed when a RPC gets called. + /// + public void RefreshRpcMonoBehaviourCache() + { + this.RpcMonoBehaviours = this.GetComponents(); + } + + + /// + /// Call a RPC method of this GameObject on remote clients of this room (or on all, inclunding this client). + /// + /// + /// [Remote Procedure Calls](@ref rpcManual) are an essential tool in making multiplayer games with PUN. + /// It enables you to make every client in a room call a specific method. + /// + /// RPC calls can target "All" or the "Others". + /// Usually, the target "All" gets executed locally immediately after sending the RPC. + /// The "*ViaServer" options send the RPC to the server and execute it on this client when it's sent back. + /// Of course, calls are affected by this client's lag and that of remote clients. + /// + /// Each call automatically is routed to the same PhotonView (and GameObject) that was used on the + /// originating client. + /// + /// See: [Remote Procedure Calls](@ref rpcManual). + /// + /// The name of a fitting method that was has the RPC attribute. + /// The group of targets and the way the RPC gets sent. + /// The parameters that the RPC method has (must fit this call!). + public void RPC(string methodName, PhotonTargets target, params object[] parameters) + { + PhotonNetwork.RPC(this, methodName, target, false, parameters); + } + + /// + /// Call a RPC method of this GameObject on remote clients of this room (or on all, inclunding this client). + /// + /// + /// [Remote Procedure Calls](@ref rpcManual) are an essential tool in making multiplayer games with PUN. + /// It enables you to make every client in a room call a specific method. + /// + /// RPC calls can target "All" or the "Others". + /// Usually, the target "All" gets executed locally immediately after sending the RPC. + /// The "*ViaServer" options send the RPC to the server and execute it on this client when it's sent back. + /// Of course, calls are affected by this client's lag and that of remote clients. + /// + /// Each call automatically is routed to the same PhotonView (and GameObject) that was used on the + /// originating client. + /// + /// See: [Remote Procedure Calls](@ref rpcManual). + /// + ///The name of a fitting method that was has the RPC attribute. + ///The group of targets and the way the RPC gets sent. + /// + ///The parameters that the RPC method has (must fit this call!). + public void RpcSecure(string methodName, PhotonTargets target, bool encrypt, params object[] parameters) + { + PhotonNetwork.RPC(this, methodName, target, encrypt, parameters); + } + + /// + /// Call a RPC method of this GameObject on remote clients of this room (or on all, inclunding this client). + /// + /// + /// [Remote Procedure Calls](@ref rpcManual) are an essential tool in making multiplayer games with PUN. + /// It enables you to make every client in a room call a specific method. + /// + /// This method allows you to make an RPC calls on a specific player's client. + /// Of course, calls are affected by this client's lag and that of remote clients. + /// + /// Each call automatically is routed to the same PhotonView (and GameObject) that was used on the + /// originating client. + /// + /// See: [Remote Procedure Calls](@ref rpcManual). + /// + /// The name of a fitting method that was has the RPC attribute. + /// The group of targets and the way the RPC gets sent. + /// The parameters that the RPC method has (must fit this call!). + public void RPC(string methodName, PhotonPlayer targetPlayer, params object[] parameters) + { + PhotonNetwork.RPC(this, methodName, targetPlayer, false, parameters); + } + + /// + /// Call a RPC method of this GameObject on remote clients of this room (or on all, inclunding this client). + /// + /// + /// [Remote Procedure Calls](@ref rpcManual) are an essential tool in making multiplayer games with PUN. + /// It enables you to make every client in a room call a specific method. + /// + /// This method allows you to make an RPC calls on a specific player's client. + /// Of course, calls are affected by this client's lag and that of remote clients. + /// + /// Each call automatically is routed to the same PhotonView (and GameObject) that was used on the + /// originating client. + /// + /// See: [Remote Procedure Calls](@ref rpcManual). + /// + ///The name of a fitting method that was has the RPC attribute. + ///The group of targets and the way the RPC gets sent. + /// + ///The parameters that the RPC method has (must fit this call!). + public void RpcSecure(string methodName, PhotonPlayer targetPlayer, bool encrypt, params object[] parameters) + { + PhotonNetwork.RPC(this, methodName, targetPlayer, encrypt, parameters); + } + + public static PhotonView Get(Component component) + { + return component.GetComponent(); + } + + public static PhotonView Get(GameObject gameObj) + { + return gameObj.GetComponent(); + } + + public static PhotonView Find(int viewID) + { + return PhotonNetwork.networkingPeer.GetPhotonView(viewID); + } + + public override string ToString() + { + return string.Format("View ({3}){0} on {1} {2}", this.viewID, (this.gameObject != null) ? this.gameObject.name : "GO==null", (this.isSceneView) ? "(scene)" : string.Empty, this.prefix); + } +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonView.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonView.cs.meta new file mode 100644 index 0000000..b2b8709 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonView.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: aa584fbee541324448dd18d8409c7a41 +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PingCloudRegions.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PingCloudRegions.cs new file mode 100644 index 0000000..3603333 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PingCloudRegions.cs @@ -0,0 +1,352 @@ +using System; +using System.Net; +using System.Collections; +using System.Diagnostics; +using ExitGames.Client.Photon; +using UnityEngine; +using Debug = UnityEngine.Debug; +using SupportClassPun = ExitGames.Client.Photon.SupportClass; + + +#if UNITY_EDITOR || (!UNITY_ANDROID && !UNITY_IPHONE && !UNITY_PS3 && !UNITY_WINRT) + +using System.Net.Sockets; + + +/// Uses C# Socket class from System.Net.Sockets (as Unity usually does). +/// Incompatible with Windows 8 Store/Phone API. +public class PingMonoEditor : PhotonPing +{ + private Socket sock; + + /// + /// Sends a "Photon Ping" to a server. + /// + /// Address in IPv4 or IPv6 format. An address containing a '.' will be interpretet as IPv4. + /// True if the Photon Ping could be sent. + public override bool StartPing(string ip) + { + base.Init(); + + try + { + if (ip.Contains(".")) + { + this.sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + } + else + { + this.sock = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp); + } + + sock.ReceiveTimeout = 5000; + sock.Connect(ip, 5055); + + PingBytes[PingBytes.Length - 1] = PingId; + sock.Send(PingBytes); + PingBytes[PingBytes.Length - 1] = (byte)(PingId - 1); + } + catch (Exception e) + { + sock = null; + Console.WriteLine(e); + } + + return false; + } + + public override bool Done() + { + if (this.GotResult || sock == null) + { + return true; + } + + if (sock.Available <= 0) + { + return false; + } + + int read = sock.Receive(PingBytes, SocketFlags.None); + //Debug.Log("Got: " + SupportClassPun.ByteArrayToString(PingBytes)); + bool replyMatch = PingBytes[PingBytes.Length - 1] == PingId && read == PingLength; + if (!replyMatch) Debug.Log("ReplyMatch is false! "); + + + this.Successful = read == PingBytes.Length && PingBytes[PingBytes.Length - 1] == PingId; + this.GotResult = true; + return true; + } + + public override void Dispose() + { + try + { + sock.Close(); + } + catch + { + } + sock = null; + } + +} + +#endif + + +#if UNITY_WEBGL + +public class PingHttp : PhotonPing +{ + private WWW webRequest; + + public override bool StartPing(string address) + { + address = "https://" + address + "/photon/m/?ping&r=" + UnityEngine.Random.Range(0, 10000); + Debug.Log("StartPing: " + address); + this.webRequest = new WWW(address); + return true; + } + + public override bool Done() + { + if (this.webRequest.isDone) + { + Successful = true; + return true; + } + + return false; + } + + public override void Dispose() + { + this.webRequest.Dispose(); + } +} + +#endif + + +public class PhotonPingManager +{ + public bool UseNative; + public static int Attempts = 5; + public static bool IgnoreInitialAttempt = true; + public static int MaxMilliseconsPerPing = 800; // enter a value you're sure some server can beat (have a lower rtt) + + private const string wssProtocolString = "wss://"; + + public Region BestRegion + { + get + { + Region result = null; + int bestRtt = Int32.MaxValue; + foreach (Region region in PhotonNetwork.networkingPeer.AvailableRegions) + { + Debug.Log("BestRegion checks region: " + region); + if (region.Ping != 0 && region.Ping < bestRtt) + { + bestRtt = region.Ping; + result = region; + } + } + + return (Region)result; + } + } + + public bool Done + { + get { return this.PingsRunning == 0; } + } + + private int PingsRunning; + + + /// + /// Affected by frame-rate of app, as this Coroutine checks the socket for a result once per frame. + /// + public IEnumerator PingSocket(Region region) + { + region.Ping = Attempts*MaxMilliseconsPerPing; + + this.PingsRunning++; // TODO: Add try-catch to make sure the PingsRunning are reduced at the end and that the lib does not crash the app + PhotonPing ping; + if (PhotonHandler.PingImplementation == typeof(PingNativeDynamic)) + { + Debug.Log("Using constructor for new PingNativeDynamic()"); // it seems on Android, the Activator can't find the default Constructor + ping = new PingNativeDynamic(); + } + else if(PhotonHandler.PingImplementation == typeof(PingNativeStatic)) + { + Debug.Log("Using constructor for new PingNativeStatic()"); // it seems on Switch, the Activator can't find the default Constructor + ping = new PingNativeStatic(); + } + else if (PhotonHandler.PingImplementation == typeof(PingMono)) + { + ping = new PingMono(); // using this type explicitly saves it from IL2CPP bytecode stripping + } + #if UNITY_WEBGL + else if (PhotonHandler.PingImplementation == typeof(PingHttp)) + { + ping = new PingHttp(); + } + #endif + else + { + ping = (PhotonPing)Activator.CreateInstance(PhotonHandler.PingImplementation); + } + + //Debug.Log(region); + + float rttSum = 0.0f; + int replyCount = 0; + + // all addresses for Photon region servers will contain a :port ending. this needs to be removed first. + // PhotonPing.StartPing() requires a plain (IP) address without port or protocol-prefix (on all but Windows 8.1 and WebGL platforms). + + string regionAddress = region.HostAndPort; + int indexOfColon = regionAddress.LastIndexOf(':'); + if (indexOfColon > 1) + { + regionAddress = regionAddress.Substring(0, indexOfColon); + } + + // we also need to remove the protocol or Dns.GetHostAddresses(hostName) will throw an exception + // This is for xBox One for example. + int indexOfProtocol = regionAddress.IndexOf(PhotonPingManager.wssProtocolString); + if (indexOfProtocol > -1) + { + regionAddress = regionAddress.Substring(indexOfProtocol+PhotonPingManager.wssProtocolString.Length); + } + regionAddress = ResolveHost(regionAddress); + + Debug.Log("Ping Debug - PhotonHandler.PingImplementation: " + PhotonHandler.PingImplementation + " ping.GetType():" + ping.GetType() + " regionAddress:" + regionAddress); + for (int i = 0; i < Attempts; i++) + { + bool overtime = false; + Stopwatch sw = new Stopwatch(); + sw.Start(); + + try + { + ping.StartPing(regionAddress); + } + catch (Exception e) + { + Debug.Log("catched: " + e); + this.PingsRunning--; + break; + } + + + while (!ping.Done()) + { + if (sw.ElapsedMilliseconds >= MaxMilliseconsPerPing) + { + overtime = true; + break; + } + yield return 0; // keep this loop tight, to avoid adding local lag to rtt. + } + int rtt = (int)sw.ElapsedMilliseconds; + + + if (IgnoreInitialAttempt && i == 0) + { + // do nothing. + } + else if (ping.Successful && !overtime) + { + rttSum += rtt; + replyCount++; + region.Ping = (int)((rttSum) / replyCount); + //Debug.Log("region " + region.Code + " RTT " + region.Ping + " success: " + ping.Successful + " over: " + overtime); + } + + yield return new WaitForSeconds(0.1f); + } + ping.Dispose(); + + this.PingsRunning--; + + //Debug.Log("this.PingsRunning: " + this.PingsRunning + " this debug: " + ping.DebugString); + yield return null; + } + +#if (UNITY_WINRT && !UNITY_EDITOR) || UNITY_WEBGL + + public static string ResolveHost(string hostName) + { + #if UNITY_WEBGL + if (hostName.StartsWith("wss://")) + { + hostName = hostName.Substring(6); + } + if (hostName.StartsWith("ws://")) + { + hostName = hostName.Substring(5); + } + #endif + + return hostName; + } + +#else + + /// + /// Attempts to resolve a hostname into an IP string or returns empty string if that fails. + /// + /// + /// To be compatible with most platforms, the address family is checked like this:
+ /// if (ipAddress.AddressFamily.ToString().Contains("6")) // ipv6... + ///
+ /// Hostname to resolve. + /// IP string or empty string if resolution fails + public static string ResolveHost(string hostName) + { + string ipv4Address = string.Empty; + + try + { + IPAddress[] address = Dns.GetHostAddresses(hostName); + //foreach (IPAddress adr in address) + //{ + // Debug.Log(hostName + " -> Adress: " + adr + " family: " + adr.AddressFamily.ToString()); + //} + + if (address.Length == 1) + { + return address[0].ToString(); + } + + // if we got more addresses, try to pick a IPv4 one + for (int index = 0; index < address.Length; index++) + { + IPAddress ipAddress = address[index]; + if (ipAddress != null) + { + // checking ipAddress.ToString() means we don't have to import System.Net.Sockets, which is not available on some platforms (Metro) + if (ipAddress.ToString().Contains(":")) + { + return ipAddress.ToString(); + } + if (string.IsNullOrEmpty(ipv4Address)) + { + ipv4Address = address.ToString(); + } + } + } + } + catch (System.Exception e) + { + Debug.Log("Exception caught! " + e.Source + " Message: " + e.Message); + } + + return ipv4Address; + } +#endif +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PingCloudRegions.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PingCloudRegions.cs.meta new file mode 100644 index 0000000..3467d9e --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/PingCloudRegions.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 207807222df026f40ac3688a3a051e38 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/RPC.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/RPC.cs new file mode 100644 index 0000000..477f44c --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/RPC.cs @@ -0,0 +1,12 @@ + +#pragma warning disable 1587 +/// \file +/// Reimplements a RPC Attribute, as it's no longer in all versions of the UnityEngine assembly. +#pragma warning restore 1587 + +using System; + +/// Replacement for RPC attribute with different name. Used to flag methods as remote-callable. +public class PunRPC : Attribute +{ +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/RPC.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/RPC.cs.meta new file mode 100644 index 0000000..52e838f --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/RPC.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c40d255b1edd61842ae10e3346a2251e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Room.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Room.cs new file mode 100644 index 0000000..9f5a74a --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Room.cs @@ -0,0 +1,428 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2011 Exit Games GmbH +// +// +// Represents a room/game on the server and caches the properties of that. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +using System; +using ExitGames.Client.Photon; +using UnityEngine; + + +/// +/// This class resembles a room that PUN joins (or joined). +/// The properties are settable as opposed to those of a RoomInfo and you can close or hide "your" room. +/// +/// \ingroup publicApi +public class Room : RoomInfo +{ + /// The name of a room. Unique identifier (per Loadbalancing group) for a room/match. + public new string Name + { + get + { + return this.nameField; + } + + internal set + { + this.nameField = value; + } + } + + /// + /// Defines if the room can be joined. + /// This does not affect listing in a lobby but joining the room will fail if not open. + /// If not open, the room is excluded from random matchmaking. + /// Due to racing conditions, found matches might become closed before they are joined. + /// Simply re-connect to master and find another. + /// Use property "visible" to not list the room. + /// + public new bool IsOpen + { + get + { + return this.openField; + } + + set + { + if (!this.Equals(PhotonNetwork.room)) + { + UnityEngine.Debug.LogWarning("Can't set open when not in that room."); + } + + if (value != this.openField && !PhotonNetwork.offlineMode) + { + PhotonNetwork.networkingPeer.OpSetPropertiesOfRoom(new Hashtable() { { GamePropertyKey.IsOpen, value } }, expectedProperties: null, webForward: false); + } + + this.openField = value; + } + } + + /// + /// Defines if the room is listed in its lobby. + /// Rooms can be created invisible, or changed to invisible. + /// To change if a room can be joined, use property: open. + /// + public new bool IsVisible + { + get + { + return this.visibleField; + } + + set + { + if (!this.Equals(PhotonNetwork.room)) + { + UnityEngine.Debug.LogWarning("Can't set visible when not in that room."); + } + + if (value != this.visibleField && !PhotonNetwork.offlineMode) + { + PhotonNetwork.networkingPeer.OpSetPropertiesOfRoom(new Hashtable() { { GamePropertyKey.IsVisible, value } }, expectedProperties: null, webForward: false); + } + + this.visibleField = value; + } + } + + /// + /// A list of custom properties that should be forwarded to the lobby and listed there. + /// + public string[] PropertiesListedInLobby { get; private set; } + + /// + /// Gets if this room uses autoCleanUp to remove all (buffered) RPCs and instantiated GameObjects when a player leaves. + /// + public bool AutoCleanUp + { + get + { + return this.autoCleanUpField; + } + } + + /// + /// Sets a limit of players to this room. This property is shown in lobby, too. + /// If the room is full (players count == maxplayers), joining this room will fail. + /// + public new int MaxPlayers + { + get + { + return (int)this.maxPlayersField; + } + + set + { + if (!this.Equals(PhotonNetwork.room)) + { + UnityEngine.Debug.LogWarning("Can't set MaxPlayers when not in that room."); + } + + if (value > 255) + { + UnityEngine.Debug.LogWarning("Can't set Room.MaxPlayers to: " + value + ". Using max value: 255."); + value = 255; + } + + if (value != this.maxPlayersField && !PhotonNetwork.offlineMode) + { + PhotonNetwork.networkingPeer.OpSetPropertiesOfRoom(new Hashtable() { { GamePropertyKey.MaxPlayers, (byte)value } }, expectedProperties: null, webForward: false); + } + + this.maxPlayersField = (byte)value; + } + } + + /// Count of players in this room. + public new int PlayerCount + { + get + { + if (PhotonNetwork.playerList != null) + { + return PhotonNetwork.playerList.Length; + } + else + { + return 0; + } + } + } + + /// + /// List of users who are expected to join this room. In matchmaking, Photon blocks a slot for each of these UserIDs out of the MaxPlayers. + /// + /// + /// The corresponding feature in Photon is called "Slot Reservation" and can be found in the doc pages. + /// Define expected players in the PhotonNetwork methods: CreateRoom, JoinRoom and JoinOrCreateRoom. + /// + public string[] ExpectedUsers + { + get { return this.expectedUsersField; } + } + + /// Player Time To Live. How long any player can be inactive (due to disconnect or leave) before the user gets removed from the playerlist (freeing a slot). + public int PlayerTtl + { + get { return this.playerTtlField; } + set + { + if (!this.Equals(PhotonNetwork.room)) + { + UnityEngine.Debug.LogWarning("Can't set PlayerTtl when not in a room."); + } + + if (value != this.playerTtlField && !PhotonNetwork.offlineMode) + { + PhotonNetwork.networkingPeer.OpSetPropertyOfRoom(GamePropertyKey.PlayerTtl, value); + } + + this.playerTtlField = value; + } + } + + /// Room Time To Live. How long a room stays available (and in server-memory), after the last player becomes inactive. After this time, the room gets persisted or destroyed. + public int EmptyRoomTtl + { + get { return this.emptyRoomTtlField; } + set + { + if (!this.Equals(PhotonNetwork.room)) + { + UnityEngine.Debug.LogWarning("Can't set EmptyRoomTtl when not in a room."); + } + + if (value != this.emptyRoomTtlField && !PhotonNetwork.offlineMode) + { + PhotonNetwork.networkingPeer.OpSetPropertyOfRoom(GamePropertyKey.EmptyRoomTtl, value); + } + + this.emptyRoomTtlField = value; + } + } + + /// The ID (actorNumber) of the current Master Client of this room. + /// See also: PhotonNetwork.masterClient. + protected internal int MasterClientId + { + get + { + return this.masterClientIdField; + } + set + { + this.masterClientIdField = value; + } + } + + + internal Room(string roomName, RoomOptions options) : base(roomName, null) + { + if (options == null) + { + options = new RoomOptions(); + } + + this.visibleField = options.IsVisible; + this.openField = options.IsOpen; + this.maxPlayersField = (byte)options.MaxPlayers; + this.autoCleanUpField = false; // defaults to false, unless set to true when room gets created. + + this.InternalCacheProperties(options.CustomRoomProperties); + this.PropertiesListedInLobby = options.CustomRoomPropertiesForLobby; + } + + + /// + /// Updates the current room's Custom Properties with new/updated key-values. + /// + /// + /// Custom Properties are a key-value set (Hashtable) which is available to all players in a room. + /// They can relate to the room or individual players and are useful when only the current value + /// of something is of interest. For example: The map of a room. + /// All keys must be strings. + /// + /// The Room and the PhotonPlayer class both have SetCustomProperties methods. + /// Also, both classes offer access to current key-values by: customProperties. + /// + /// Always use SetCustomProperties to change values. + /// To reduce network traffic, set only values that actually changed. + /// New properties are added, existing values are updated. + /// Other values will not be changed, so only provide values that changed or are new. + /// + /// To delete a named (custom) property of this room, use null as value. + /// + /// Locally, SetCustomProperties will update it's cache without delay. + /// Other clients are updated through Photon (the server) with a fitting operation. + /// + /// Check and Swap + /// + /// SetCustomProperties have the option to do a server-side Check-And-Swap (CAS): + /// Values only get updated if the expected values are correct. + /// The expectedValues can be different key/values than the propertiesToSet. So you can + /// check some key and set another key's value (if the check succeeds). + /// + /// If the client's knowledge of properties is wrong or outdated, it can't set values with CAS. + /// This can be useful to keep players from concurrently setting values. For example: If all players + /// try to pickup some card or item, only one should get it. With CAS, only the first SetProperties + /// gets executed server-side and any other (sent at the same time) fails. + /// + /// The server will broadcast successfully changed values and the local "cache" of customProperties + /// only gets updated after a roundtrip (if anything changed). + /// + /// You can do a "webForward": Photon will send the changed properties to a WebHook defined + /// for your application. + /// + /// OfflineMode + /// + /// While PhotonNetwork.offlineMode is true, the expectedValues and webForward parameters are ignored. + /// In OfflineMode, the local customProperties values are immediately updated (without the roundtrip). + /// + /// The new properties to be set. + /// At least one property key/value set to check server-side. Key and value must be correct. Ignored in OfflineMode. + /// Set to true, to forward the set properties to a WebHook, defined for this app (in Dashboard). Ignored in OfflineMode. + public void SetCustomProperties(Hashtable propertiesToSet, Hashtable expectedValues = null, bool webForward = false) + { + if (propertiesToSet == null) + { + return; + } + + Hashtable customProps = propertiesToSet.StripToStringKeys() as Hashtable; + Hashtable customPropsToCheck = expectedValues.StripToStringKeys() as Hashtable; + + + // no expected values -> set and callback + bool noCas = customPropsToCheck == null || customPropsToCheck.Count == 0; + + if (PhotonNetwork.offlineMode || noCas) + { + this.CustomProperties.Merge(customProps); // the customProps are already stripped to string-keys-only (custom-props keys) + this.CustomProperties.StripKeysWithNullValues(); + } + + if (!PhotonNetwork.offlineMode) + { + PhotonNetwork.networkingPeer.OpSetPropertiesOfRoom(customProps, customPropsToCheck, webForward); // as the customProps are stripped already, this equals OpSetCustomPropertiesOfRoom() + } + + if (PhotonNetwork.offlineMode || noCas) + { + NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnPhotonCustomRoomPropertiesChanged, customProps); + } + } + + /// + /// Enables you to define the properties available in the lobby if not all properties are needed to pick a room. + /// + /// + /// It makes sense to limit the amount of properties sent to users in the lobby as this improves speed and stability. + /// + /// An array of custom room property names to forward to the lobby. + public void SetPropertiesListedInLobby(string[] propsListedInLobby) + { + Hashtable customProps = new Hashtable(); + customProps[GamePropertyKey.PropsListedInLobby] = propsListedInLobby; + PhotonNetwork.networkingPeer.OpSetPropertiesOfRoom(customProps, expectedProperties: null, webForward: false); + + this.PropertiesListedInLobby = propsListedInLobby; + } + + /// + /// Attempts to remove all current expected users from the server's Slot Reservation list. + /// + /// + /// Note that this operation can conflict with new/other users joining. They might be + /// adding users to the list of expected users before or after this client called ClearExpectedUsers. + /// + /// This room's expectedUsers value will update, when the server sends a successful update. + /// + /// Internals: This methods wraps up setting the ExpectedUsers property of a room. + /// + public void ClearExpectedUsers() + { + Hashtable props = new Hashtable(); + props[GamePropertyKey.ExpectedUsers] = new string[0]; + Hashtable expected = new Hashtable(); + expected[GamePropertyKey.ExpectedUsers] = this.ExpectedUsers; + PhotonNetwork.networkingPeer.OpSetPropertiesOfRoom(props, expected, webForward: false); + } + + /// + /// Attempts to set the current expected users list. + /// + /// + /// Note that this operation can conflict with new/other users joining. They might be + /// adding users to the list of expected users before or after this client called SetExpectedUsers. + /// If the list changes before this operation arrives, the server will not modify the list and + /// SetExpectedUsers() fails. + /// + /// This room's expectedUsers value will be sent by the server. + /// + /// Internals: This methods wraps up setting the ExpectedUsers property of a room. + /// + public void SetExpectedUsers(string[] expectedUsers) + { + Hashtable props = new Hashtable(); + props[GamePropertyKey.ExpectedUsers] = expectedUsers; + Hashtable expected = new Hashtable(); + expected[GamePropertyKey.ExpectedUsers] = this.ExpectedUsers; + PhotonNetwork.networkingPeer.OpSetPropertiesOfRoom(props, expected, webForward: false); + } + + + /// Returns a summary of this Room instance as string. + /// Summary of this Room instance. + public override string ToString() + { + return string.Format("Room: '{0}' {1},{2} {4}/{3} players.", this.nameField, this.visibleField ? "visible" : "hidden", this.openField ? "open" : "closed", this.maxPlayersField, this.PlayerCount); + } + + /// Returns a summary of this Room instance as longer string, including Custom Properties. + /// Summary of this Room instance. + public new string ToStringFull() + { + return string.Format("Room: '{0}' {1},{2} {4}/{3} players.\ncustomProps: {5}", this.nameField, this.visibleField ? "visible" : "hidden", this.openField ? "open" : "closed", this.maxPlayersField, this.PlayerCount, this.CustomProperties.ToStringFull()); + } + + + #region Obsoleted variable names + + [Obsolete("Please use Name (updated case for naming).")] + public new string name { get { return this.Name; } internal set { this.Name = value; } } + + [Obsolete("Please use IsOpen (updated case for naming).")] + public new bool open { get { return this.IsOpen; } set { this.IsOpen = value; } } + + [Obsolete("Please use IsVisible (updated case for naming).")] + public new bool visible { get { return this.IsVisible; } set { this.IsVisible = value; } } + + [Obsolete("Please use PropertiesListedInLobby (updated case for naming).")] + public string[] propertiesListedInLobby { get { return this.PropertiesListedInLobby; } private set { this.PropertiesListedInLobby = value; } } + + [Obsolete("Please use AutoCleanUp (updated case for naming).")] + public bool autoCleanUp { get { return this.AutoCleanUp; } } + + [Obsolete("Please use MaxPlayers (updated case for naming).")] + public new int maxPlayers { get { return this.MaxPlayers; } set { this.MaxPlayers = value; } } + + [Obsolete("Please use PlayerCount (updated case for naming).")] + public new int playerCount { get { return this.PlayerCount; } } + + [Obsolete("Please use ExpectedUsers (updated case for naming).")] + public string[] expectedUsers { get { return this.ExpectedUsers; } } + + [Obsolete("Please use MasterClientId (updated case for naming).")] + protected internal int masterClientId { get { return this.MasterClientId; } set { this.MasterClientId = value; } } + + #endregion +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Room.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Room.cs.meta new file mode 100644 index 0000000..31bdf30 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Room.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 17568a7a5552c09428dd48e73548b8b8 +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/RoomInfo.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/RoomInfo.cs new file mode 100644 index 0000000..67c7bf2 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/RoomInfo.cs @@ -0,0 +1,298 @@ +// ---------------------------------------------------------------------------- +// +// Loadbalancing Framework for Photon - Copyright (C) 2011 Exit Games GmbH +// +// +// This class resembles info about available rooms, as sent by the Master +// server's lobby. Consider all values as readonly. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +using System; +using ExitGames.Client.Photon; + + +/// +/// A simplified room with just the info required to list and join, used for the room listing in the lobby. +/// The properties are not settable (open, MaxPlayers, etc). +/// +/// +/// This class resembles info about available rooms, as sent by the Master server's lobby. +/// Consider all values as readonly. None are synced (only updated by events by server). +/// +/// \ingroup publicApi +public class RoomInfo +{ + /// Used internally in lobby, to mark rooms that are no longer listed. + public bool removedFromList { get; internal set; } + + /// Backing field for property. + private Hashtable customPropertiesField = new Hashtable(); + + /// Backing field for property. + protected byte maxPlayersField = 0; + + /// Backing field for property. + protected int emptyRoomTtlField = 0; + + /// Backing field for property. + protected int playerTtlField = 0; + + /// Backing field for property. + protected string[] expectedUsersField; + + /// Backing field for property. + protected bool openField = true; + + /// Backing field for property. + protected bool visibleField = true; + + /// Backing field for property. False unless the GameProperty is set to true (else it's not sent). + protected bool autoCleanUpField = PhotonNetwork.autoCleanUpPlayerObjects; + + /// Backing field for property. + protected string nameField; + + /// Backing field for master client id (actorNumber). defined by server in room props and ev leave. + protected internal int masterClientIdField; + + protected internal bool serverSideMasterClient { get; private set; } + + /// Read-only "cache" of custom properties of a room. Set via Room.SetCustomProperties (not available for RoomInfo class!). + /// All keys are string-typed and the values depend on the game/application. + /// + public Hashtable CustomProperties + { + get + { + return this.customPropertiesField; + } + } + + /// The name of a room. Unique identifier (per Loadbalancing group) for a room/match. + public string Name + { + get + { + return this.nameField; + } + } + + /// + /// Only used internally in lobby, to display number of players in room (while you're not in). + /// + public int PlayerCount { get; private set; } + + /// + /// State if the local client is already in the game or still going to join it on gameserver (in lobby always false). + /// + public bool IsLocalClientInside { get; set; } + + /// + /// Sets a limit of players to this room. This property is shown in lobby, too. + /// If the room is full (players count == maxplayers), joining this room will fail. + /// + /// + /// As part of RoomInfo this can't be set. + /// As part of a Room (which the player joined), the setter will update the server and all clients. + /// + public byte MaxPlayers + { + get + { + return this.maxPlayersField; + } + } + + /// + /// Defines if the room can be joined. + /// This does not affect listing in a lobby but joining the room will fail if not open. + /// If not open, the room is excluded from random matchmaking. + /// Due to racing conditions, found matches might become closed before they are joined. + /// Simply re-connect to master and find another. + /// Use property "IsVisible" to not list the room. + /// + /// + /// As part of RoomInfo this can't be set. + /// As part of a Room (which the player joined), the setter will update the server and all clients. + /// + public bool IsOpen + { + get + { + return this.openField; + } + } + + /// + /// Defines if the room is listed in its lobby. + /// Rooms can be created invisible, or changed to invisible. + /// To change if a room can be joined, use property: open. + /// + /// + /// As part of RoomInfo this can't be set. + /// As part of a Room (which the player joined), the setter will update the server and all clients. + /// + public bool IsVisible + { + get + { + return this.visibleField; + } + } + + /// + /// Constructs a RoomInfo to be used in room listings in lobby. + /// + /// + /// + protected internal RoomInfo(string roomName, Hashtable properties) + { + this.InternalCacheProperties(properties); + + this.nameField = roomName; + } + + /// + /// Makes RoomInfo comparable (by name). + /// + public override bool Equals(object other) + { + RoomInfo otherRoomInfo = other as RoomInfo; + return (otherRoomInfo != null && this.Name.Equals(otherRoomInfo.nameField)); + } + + /// + /// Accompanies Equals, using the name's HashCode as return. + /// + /// + public override int GetHashCode() + { + return this.nameField.GetHashCode(); + } + + + /// Simple printingin method. + /// Summary of this RoomInfo instance. + public override string ToString() + { + return string.Format("Room: '{0}' {1},{2} {4}/{3} players.", this.nameField, this.visibleField ? "visible" : "hidden", this.openField ? "open" : "closed", this.maxPlayersField, this.PlayerCount); + } + + /// Simple printingin method. + /// Summary of this RoomInfo instance. + public string ToStringFull() + { + return string.Format("Room: '{0}' {1},{2} {4}/{3} players.\ncustomProps: {5}", this.nameField, this.visibleField ? "visible" : "hidden", this.openField ? "open" : "closed", this.maxPlayersField, this.PlayerCount, this.customPropertiesField.ToStringFull()); + } + + /// Copies "well known" properties to fields (IsVisible, etc) and caches the custom properties (string-keys only) in a local hashtable. + /// New or updated properties to store in this RoomInfo. + protected internal void InternalCacheProperties(Hashtable propertiesToCache) + { + if (propertiesToCache == null || propertiesToCache.Count == 0 || this.customPropertiesField.Equals(propertiesToCache)) + { + return; + } + + // check of this game was removed from the list. in that case, we don't + // need to read any further properties + // list updates will remove this game from the game listing + if (propertiesToCache.ContainsKey(GamePropertyKey.Removed)) + { + this.removedFromList = (Boolean)propertiesToCache[GamePropertyKey.Removed]; + if (this.removedFromList) + { + return; + } + } + + // fetch the "well known" properties of the room, if available + if (propertiesToCache.ContainsKey(GamePropertyKey.MaxPlayers)) + { + this.maxPlayersField = (byte)propertiesToCache[GamePropertyKey.MaxPlayers]; + } + + if (propertiesToCache.ContainsKey(GamePropertyKey.IsOpen)) + { + this.openField = (bool)propertiesToCache[GamePropertyKey.IsOpen]; + } + + if (propertiesToCache.ContainsKey(GamePropertyKey.IsVisible)) + { + this.visibleField = (bool)propertiesToCache[GamePropertyKey.IsVisible]; + } + + if (propertiesToCache.ContainsKey(GamePropertyKey.PlayerCount)) + { + this.PlayerCount = (int)((byte)propertiesToCache[GamePropertyKey.PlayerCount]); + } + + if (propertiesToCache.ContainsKey(GamePropertyKey.CleanupCacheOnLeave)) + { + this.autoCleanUpField = (bool)propertiesToCache[GamePropertyKey.CleanupCacheOnLeave]; + } + + if (propertiesToCache.ContainsKey(GamePropertyKey.MasterClientId)) + { + this.serverSideMasterClient = true; + bool isUpdate = this.masterClientIdField != 0; + this.masterClientIdField = (int) propertiesToCache[GamePropertyKey.MasterClientId]; + if (isUpdate) + { + PhotonNetwork.networkingPeer.UpdateMasterClient(); + } + } + + //if (propertiesToCache.ContainsKey(GamePropertyKey.PropsListedInLobby)) + //{ + // // could be cached but isn't useful + //} + + if (propertiesToCache.ContainsKey((byte)GamePropertyKey.ExpectedUsers)) + { + this.expectedUsersField = (string[])propertiesToCache[GamePropertyKey.ExpectedUsers]; + } + + if (propertiesToCache.ContainsKey((byte)GamePropertyKey.EmptyRoomTtl)) + { + this.emptyRoomTtlField = (int)propertiesToCache[GamePropertyKey.EmptyRoomTtl]; + } + + if (propertiesToCache.ContainsKey((byte)GamePropertyKey.PlayerTtl)) + { + this.playerTtlField = (int)propertiesToCache[GamePropertyKey.PlayerTtl]; + } + + // merge the custom properties (from your application) to the cache (only string-typed keys will be kept) + this.customPropertiesField.MergeStringKeys(propertiesToCache); + this.customPropertiesField.StripKeysWithNullValues(); + } + + + #region Obsoleted variable names + + [Obsolete("Please use CustomProperties (updated case for naming).")] + public Hashtable customProperties { get { return this.CustomProperties; } } + + [Obsolete("Please use Name (updated case for naming).")] + public string name { get { return this.Name; } } + + [Obsolete("Please use PlayerCount (updated case for naming).")] + public int playerCount { get { return this.PlayerCount; } set { this.PlayerCount = value; } } + + [Obsolete("Please use IsLocalClientInside (updated case for naming).")] + public bool isLocalClientInside { get { return this.IsLocalClientInside; } set { this.IsLocalClientInside = value; } } + + [Obsolete("Please use MaxPlayers (updated case for naming).")] + public byte maxPlayers { get { return this.MaxPlayers; } } + + [Obsolete("Please use IsOpen (updated case for naming).")] + public bool open { get { return this.IsOpen; } } + + [Obsolete("Please use IsVisible (updated case for naming).")] + public bool visible { get { return this.IsVisible; } } + + #endregion +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/RoomInfo.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/RoomInfo.cs.meta new file mode 100644 index 0000000..a6c05a2 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/RoomInfo.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 71760b65ad7d5b842942c797a0366fa7 +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/ServerSettings.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/ServerSettings.cs new file mode 100644 index 0000000..7667eb5 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/ServerSettings.cs @@ -0,0 +1,186 @@ +#pragma warning disable 1587 +/// \file +/// ScriptableObject defining a server setup. An instance is created as PhotonServerSettings. +#pragma warning restore 1587 + +using System; +using System.Collections.Generic; +using ExitGames.Client.Photon; +using UnityEngine; + + +public class Region +{ + public CloudRegionCode Code; + /// Unlike the CloudRegionCode, this may contain cluster information. + public string Cluster; + public string HostAndPort; + public int Ping; + + public Region(CloudRegionCode code) + { + this.Code = code; + this.Cluster = code.ToString(); + } + + public Region(CloudRegionCode code, string regionCodeString, string address) + { + this.Code = code; + this.Cluster = regionCodeString; + this.HostAndPort = address; + } + + public static CloudRegionCode Parse(string codeAsString) + { + if (codeAsString == null) + { + return CloudRegionCode.none; + } + + int slash = codeAsString.IndexOf('/'); + if (slash > 0) + { + codeAsString = codeAsString.Substring(0, slash); + } + codeAsString = codeAsString.ToLower(); + + if (Enum.IsDefined(typeof(CloudRegionCode), codeAsString)) + { + return (CloudRegionCode)Enum.Parse(typeof(CloudRegionCode), codeAsString); + } + + return CloudRegionCode.none; + } + + + internal static CloudRegionFlag ParseFlag(CloudRegionCode region) + { + if (Enum.IsDefined(typeof(CloudRegionFlag), region.ToString())) + { + return (CloudRegionFlag)Enum.Parse(typeof(CloudRegionFlag), region.ToString()); + } + + return (CloudRegionFlag)0; + } + + [Obsolete] + internal static CloudRegionFlag ParseFlag(string codeAsString) + { + codeAsString = codeAsString.ToLower(); + + CloudRegionFlag code = 0; + if (Enum.IsDefined(typeof(CloudRegionFlag), codeAsString)) + { + code = (CloudRegionFlag)Enum.Parse(typeof(CloudRegionFlag), codeAsString); + } + + return code; + } + + public override string ToString() + { + return string.Format("'{0}' \t{1}ms \t{2}", this.Cluster, this.Ping, this.HostAndPort); + } +} + + +/// +/// Collection of connection-relevant settings, used internally by PhotonNetwork.ConnectUsingSettings. +/// +[Serializable] +public class ServerSettings : ScriptableObject +{ + public enum HostingOption { NotSet = 0, PhotonCloud = 1, SelfHosted = 2, OfflineMode = 3, BestRegion = 4 } + + public string AppID = ""; + public string VoiceAppID = ""; + public string ChatAppID = ""; + + public HostingOption HostType = HostingOption.NotSet; + + public CloudRegionCode PreferredRegion; + public CloudRegionFlag EnabledRegions = (CloudRegionFlag)(-1); + + public ConnectionProtocol Protocol = ConnectionProtocol.Udp; + public string ServerAddress = ""; + public int ServerPort = 5055; + public int VoiceServerPort = 5055; // Voice only uses UDP + + + public bool JoinLobby; + public bool EnableLobbyStatistics; + public PhotonLogLevel PunLogging = PhotonLogLevel.ErrorsOnly; + public DebugLevel NetworkLogging = DebugLevel.ERROR; + + public bool RunInBackground = true; + + public List RpcList = new List(); // set by scripts and or via Inspector + + [HideInInspector] + public bool DisableAutoOpenWizard; + + + public void UseCloudBestRegion(string cloudAppid) + { + this.HostType = HostingOption.BestRegion; + this.AppID = cloudAppid; + } + + public void UseCloud(string cloudAppid) + { + this.HostType = HostingOption.PhotonCloud; + this.AppID = cloudAppid; + } + + public void UseCloud(string cloudAppid, CloudRegionCode code) + { + this.HostType = HostingOption.PhotonCloud; + this.AppID = cloudAppid; + this.PreferredRegion = code; + } + + public void UseMyServer(string serverAddress, int serverPort, string application) + { + this.HostType = HostingOption.SelfHosted; + this.AppID = (application != null) ? application : "master"; + + this.ServerAddress = serverAddress; + this.ServerPort = serverPort; + } + + /// Checks if a string is a Guid by attempting to create one. + /// The potential guid to check. + /// True if new Guid(val) did not fail. + public static bool IsAppId(string val) + { + try + { + new Guid(val); + } + catch + { + return false; + } + return true; + } + + /// + /// Gets the best region code in preferences. + /// This composes the PhotonHandler, since its Internal and can not be accessed by the custom inspector + /// + /// The best region code in preferences. + public static CloudRegionCode BestRegionCodeInPreferences + { + get { return PhotonHandler.BestRegionCodeInPreferences; } + } + + public static void ResetBestRegionCodeInPreferences() + { + PhotonHandler.BestRegionCodeInPreferences = CloudRegionCode.none; + } + + public override string ToString() + { + return "ServerSettings: " + HostType + " " + ServerAddress; + } +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/ServerSettings.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/ServerSettings.cs.meta new file mode 100644 index 0000000..401bf34 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/ServerSettings.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 9f3758f8f58fdef43803eb9be1df0608 +labels: +- ExitGames +- PUN +- Photon +- Networking +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/SocketUdp.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/SocketUdp.cs new file mode 100644 index 0000000..f72a3e5 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/SocketUdp.cs @@ -0,0 +1,229 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Protocol & Photon Client Lib - Copyright (C) 2013 Exit Games GmbH +// +// +// Uses the UDP socket for a peer to send and receive enet/Photon messages. +// +// developer@exitgames.com +// -------------------------------------------------------------------------------------------------------------------- + +#if UNITY_EDITOR || (!UNITY_ANDROID && !UNITY_IPHONE && !UNITY_PS3 && !UNITY_WINRT && !UNITY_WP8) + +namespace ExitGames.Client.Photon +{ + using System; + using System.Net; + using System.Net.Sockets; + using System.Security; + using System.Threading; + + /// Internal class to encapsulate the network i/o functionality for the realtime libary. + internal class SocketUdp : IPhotonSocket, IDisposable + { + private Socket sock; + + private readonly object syncer = new object(); + + public SocketUdp(PeerBase npeer) : base(npeer) + { + if (this.ReportDebugOfLevel(DebugLevel.ALL)) + { + this.Listener.DebugReturn(DebugLevel.ALL, "CSharpSocket: UDP, Unity3d."); + } + + //this.Protocol = ConnectionProtocol.Udp; + this.PollReceive = false; + } + + public void Dispose() + { + this.State = PhotonSocketState.Disconnecting; + + if (this.sock != null) + { + try + { + if (this.sock.Connected) this.sock.Close(); + } + catch (Exception ex) + { + this.EnqueueDebugReturn(DebugLevel.INFO, "Exception in Dispose(): " + ex); + } + } + + this.sock = null; + this.State = PhotonSocketState.Disconnected; + } + + public override bool Connect() + { + lock (this.syncer) + { + bool baseOk = base.Connect(); + if (!baseOk) + { + return false; + } + + this.State = PhotonSocketState.Connecting; + + Thread dns = new Thread(this.DnsAndConnect); + dns.Name = "photon dns thread"; + dns.IsBackground = true; + dns.Start(); + + return true; + } + } + + public override bool Disconnect() + { + if (this.ReportDebugOfLevel(DebugLevel.INFO)) + { + this.EnqueueDebugReturn(DebugLevel.INFO, "CSharpSocket.Disconnect()"); + } + + this.State = PhotonSocketState.Disconnecting; + + lock (this.syncer) + { + if (this.sock != null) + { + try + { + this.sock.Close(); + } + catch (Exception ex) + { + this.EnqueueDebugReturn(DebugLevel.INFO, "Exception in Disconnect(): " + ex); + } + + this.sock = null; + } + } + + this.State = PhotonSocketState.Disconnected; + return true; + } + + /// used by PhotonPeer* + public override PhotonSocketError Send(byte[] data, int length) + { + lock (this.syncer) + { + if (this.sock == null || !this.sock.Connected) + { + return PhotonSocketError.Skipped; + } + + try + { + sock.Send(data, 0, length, SocketFlags.None); + } + catch (Exception e) + { + if (this.ReportDebugOfLevel(DebugLevel.ERROR)) + { + this.EnqueueDebugReturn(DebugLevel.ERROR, "Cannot send to: " + this.ServerAddress + ". " + e.Message); + } + return PhotonSocketError.Exception; + } + } + + return PhotonSocketError.Success; + } + + public override PhotonSocketError Receive(out byte[] data) + { + data = null; + return PhotonSocketError.NoData; + } + + internal void DnsAndConnect() + { + IPAddress ipAddress = null; + try + { + ipAddress = IPhotonSocket.GetIpAddress(this.ServerAddress); + if (ipAddress == null) + { + // this covers cases of failed DNS lookup and bad addresses. + throw new ArgumentException("Invalid IPAddress. Address: " + this.ServerAddress); + } + + lock (this.syncer) + { + if (this.State == PhotonSocketState.Disconnecting || this.State == PhotonSocketState.Disconnected) + { + return; + } + + this.sock = new Socket(ipAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp); + this.sock.Connect(ipAddress, this.ServerPort); + + this.AddressResolvedAsIpv6 = this.IsIpv6SimpleCheck(ipAddress); + this.State = PhotonSocketState.Connected; + + this.peerBase.OnConnect(); + } + } + catch (SecurityException se) + { + if (this.ReportDebugOfLevel(DebugLevel.ERROR)) + { + this.Listener.DebugReturn(DebugLevel.ERROR, "Connect() to '" + this.ServerAddress + "' (" + ((ipAddress == null ) ? "": ipAddress.AddressFamily.ToString()) + ") failed: " + se.ToString()); + } + + this.HandleException(StatusCode.SecurityExceptionOnConnect); + return; + } + catch (Exception se) + { + if (this.ReportDebugOfLevel(DebugLevel.ERROR)) + { + this.Listener.DebugReturn(DebugLevel.ERROR, "Connect() to '" + this.ServerAddress + "' (" + ((ipAddress == null) ? "" : ipAddress.AddressFamily.ToString()) + ") failed: " + se.ToString()); + } + + this.HandleException(StatusCode.ExceptionOnConnect); + return; + } + + Thread run = new Thread(new ThreadStart(ReceiveLoop)); + run.Name = "photon receive thread"; + run.IsBackground = true; + run.Start(); + } + + /// Endless loop, run in Receive Thread. + public void ReceiveLoop() + { + byte[] inBuffer = new byte[this.MTU]; + while (this.State == PhotonSocketState.Connected) + { + try + { + int read = this.sock.Receive(inBuffer); + this.HandleReceivedDatagram(inBuffer, read, true); + } + catch (Exception e) + { + if (this.State != PhotonSocketState.Disconnecting && this.State != PhotonSocketState.Disconnected) + { + if (this.ReportDebugOfLevel(DebugLevel.ERROR)) + { + this.EnqueueDebugReturn(DebugLevel.ERROR, "Receive issue. State: " + this.State + ". Server: '" + this.ServerAddress + "' Exception: " + e); + } + + this.HandleException(StatusCode.ExceptionOnReceive); + } + } + } //while Connected receive + + // on exit of the receive-loop: disconnect socket + this.Disconnect(); + } + } //class + +} +#endif diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/SocketUdp.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/SocketUdp.cs.meta new file mode 100644 index 0000000..345aec5 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/SocketUdp.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: fdcd4031513ba944ba1cc57b3aff328a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/SocketWebTcp.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/SocketWebTcp.cs new file mode 100644 index 0000000..5b0637d --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/SocketWebTcp.cs @@ -0,0 +1,283 @@ +#if UNITY_WEBGL || WEBSOCKET + +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) Exit Games GmbH. All rights reserved. +// +// +// Internal class to encapsulate the network i/o functionality for the realtime libary. +// +// developer@exitgames.com +// -------------------------------------------------------------------------------------------------------------------- + +using System; +using System.Collections; +using UnityEngine; +using SupportClassPun = ExitGames.Client.Photon.SupportClass; + + +namespace ExitGames.Client.Photon +{ +#if UNITY_5_3 || UNITY_5_3_OR_NEWER + /// + /// Yield Instruction to Wait for real seconds. Very important to keep connection working if Time.TimeScale is altered, we still want accurate network events + /// + public sealed class WaitForRealSeconds : CustomYieldInstruction + { + private readonly float _endTime; + + public override bool keepWaiting + { + get { return _endTime > Time.realtimeSinceStartup; } + } + + public WaitForRealSeconds(float seconds) + { + _endTime = Time.realtimeSinceStartup + seconds; + } + } +#endif + + /// + /// Internal class to encapsulate the network i/o functionality for the realtime libary. + /// + public class SocketWebTcp : IPhotonSocket, IDisposable + { + private WebSocket sock; + + private readonly object syncer = new object(); + + public SocketWebTcp(PeerBase npeer) : base(npeer) + { + ServerAddress = npeer.ServerAddress; + if (this.ReportDebugOfLevel(DebugLevel.INFO)) + { + Listener.DebugReturn(DebugLevel.INFO, "new SocketWebTcp() for Unity. Server: " + ServerAddress); + } + + //this.Protocol = ConnectionProtocol.WebSocket; + this.PollReceive = false; + } + + public void Dispose() + { + this.State = PhotonSocketState.Disconnecting; + + if (this.sock != null) + { + try + { + if (this.sock.Connected) this.sock.Close(); + } + catch (Exception ex) + { + this.EnqueueDebugReturn(DebugLevel.INFO, "Exception in Dispose(): " + ex); + } + } + + this.sock = null; + this.State = PhotonSocketState.Disconnected; + } + + GameObject websocketConnectionObject; + public override bool Connect() + { + //bool baseOk = base.Connect(); + //if (!baseOk) + //{ + // return false; + //} + + + State = PhotonSocketState.Connecting; + + if (this.websocketConnectionObject != null) + { + UnityEngine.Object.Destroy(this.websocketConnectionObject); + } + + this.websocketConnectionObject = new GameObject("websocketConnectionObject"); + MonoBehaviour mb = this.websocketConnectionObject.AddComponent(); + this.websocketConnectionObject.hideFlags = HideFlags.HideInHierarchy; + UnityEngine.Object.DontDestroyOnLoad(this.websocketConnectionObject); + + this.sock = new WebSocket(new Uri(ServerAddress)); + this.sock.Connect(); + + mb.StartCoroutine(this.ReceiveLoop()); + return true; + } + + + public override bool Disconnect() + { + if (ReportDebugOfLevel(DebugLevel.INFO)) + { + this.Listener.DebugReturn(DebugLevel.INFO, "SocketWebTcp.Disconnect()"); + } + + State = PhotonSocketState.Disconnecting; + + lock (this.syncer) + { + if (this.sock != null) + { + try + { + this.sock.Close(); + } + catch (Exception ex) + { + this.Listener.DebugReturn(DebugLevel.ERROR, "Exception in Disconnect(): " + ex); + } + this.sock = null; + } + } + + if (this.websocketConnectionObject != null) + { + UnityEngine.Object.Destroy(this.websocketConnectionObject); + } + + State = PhotonSocketState.Disconnected; + return true; + } + + /// + /// used by TPeer* + /// + public override PhotonSocketError Send(byte[] data, int length) + { + if (this.State != PhotonSocketState.Connected) + { + return PhotonSocketError.Skipped; + } + + try + { + if (this.ReportDebugOfLevel(DebugLevel.ALL)) + { + this.Listener.DebugReturn(DebugLevel.ALL, "Sending: " + SupportClassPun.ByteArrayToString(data)); + } + + if (this.sock != null) + { + this.sock.Send(data); + } + } + catch (Exception e) + { + this.Listener.DebugReturn(DebugLevel.ERROR, "Cannot send to: " + this.ServerAddress + ". " + e.Message); + + HandleException(StatusCode.Exception); + return PhotonSocketError.Exception; + } + + return PhotonSocketError.Success; + } + + public override PhotonSocketError Receive(out byte[] data) + { + data = null; + return PhotonSocketError.NoData; + } + + + internal const int ALL_HEADER_BYTES = 9; + internal const int TCP_HEADER_BYTES = 7; + internal const int MSG_HEADER_BYTES = 2; + + public IEnumerator ReceiveLoop() + { + this.Listener.DebugReturn(DebugLevel.INFO, "ReceiveLoop()"); + if (this.sock != null) + { + while (this.sock != null && !this.sock.Connected && this.sock.Error == null) + { +#if UNITY_5_3 || UNITY_5_3_OR_NEWER + yield return new WaitForRealSeconds(0.1f); +#else + float waittime = Time.realtimeSinceStartup + 0.1f; + while (Time.realtimeSinceStartup < waittime) yield return 0; +#endif + } + + if (this.sock != null) + { + if (this.sock.Error != null) + { + this.Listener.DebugReturn(DebugLevel.ERROR, "Exiting receive thread. Server: " + this.ServerAddress + ":" + this.ServerPort + " Error: " + this.sock.Error); + this.HandleException(StatusCode.ExceptionOnConnect); + } + else + { + // connected + if (this.ReportDebugOfLevel(DebugLevel.ALL)) + { + this.Listener.DebugReturn(DebugLevel.ALL, "Receiving by websocket. this.State: " + State); + } + State = PhotonSocketState.Connected; + while (State == PhotonSocketState.Connected) + { + if (this.sock != null) + { + if (this.sock.Error != null) + { + this.Listener.DebugReturn(DebugLevel.ERROR, "Exiting receive thread (inside loop). Server: " + this.ServerAddress + ":" + this.ServerPort + " Error: " + this.sock.Error); + this.HandleException(StatusCode.ExceptionOnReceive); + break; + } + else + { + byte[] inBuff = this.sock.Recv(); + if (inBuff == null || inBuff.Length == 0) + { + // nothing received. wait a bit, try again +#if UNITY_5_3 || UNITY_5_3_OR_NEWER + yield return new WaitForRealSeconds(0.02f); +#else + float waittime = Time.realtimeSinceStartup + 0.02f; + while (Time.realtimeSinceStartup < waittime) yield return 0; +#endif + continue; + } + + if (this.ReportDebugOfLevel(DebugLevel.ALL)) + { + this.Listener.DebugReturn(DebugLevel.ALL, "TCP << " + inBuff.Length + " = " + SupportClassPun.ByteArrayToString(inBuff)); + } + + if (inBuff.Length > 0) + { + try + { + HandleReceivedDatagram(inBuff, inBuff.Length, false); + } + catch (Exception e) + { + if (this.State != PhotonSocketState.Disconnecting && this.State != PhotonSocketState.Disconnected) + { + if (this.ReportDebugOfLevel(DebugLevel.ERROR)) + { + this.EnqueueDebugReturn(DebugLevel.ERROR, "Receive issue. State: " + this.State + ". Server: '" + this.ServerAddress + "' Exception: " + e); + } + + this.HandleException(StatusCode.ExceptionOnReceive); + } + } + } + } + } + } + } + } + } + + this.Disconnect(); + } + } + + internal class MonoBehaviourExt : MonoBehaviour { } +} + +#endif \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/SocketWebTcp.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/SocketWebTcp.cs.meta new file mode 100644 index 0000000..d5d058e --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/SocketWebTcp.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ac953d6a57a9ea94e96ec689598995d5 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views.meta new file mode 100644 index 0000000..b1f9138 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 8bda2ddbdfb774d41a5c6961127c7c9c +folderAsset: yes +timeCreated: 1525372512 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonAnimatorView.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonAnimatorView.cs new file mode 100644 index 0000000..49b9270 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonAnimatorView.cs @@ -0,0 +1,544 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2016 Exit Games GmbH +// +// +// Component to synchronize Mecanim animations via PUN. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +using System.Collections.Generic; +using UnityEngine; + +/// +/// This class helps you to synchronize Mecanim animations +/// Simply add the component to your GameObject and make sure that +/// the PhotonAnimatorView is added to the list of observed components +/// +/// +/// When Using Trigger Parameters, make sure the component that sets the trigger is higher in the stack of Components on the GameObject than 'PhotonAnimatorView' +/// Triggers are raised true during one frame only. +/// +[RequireComponent(typeof(Animator))] +[RequireComponent(typeof(PhotonView))] +[AddComponentMenu("Photon Networking/Photon Animator View")] +public class PhotonAnimatorView : MonoBehaviour, IPunObservable +{ + #region Enums + + public enum ParameterType + { + Float = 1, + Int = 3, + Bool = 4, + Trigger = 9, + } + + public enum SynchronizeType + { + Disabled = 0, + Discrete = 1, + Continuous = 2, + } + + [System.Serializable] + public class SynchronizedParameter + { + public ParameterType Type; + public SynchronizeType SynchronizeType; + public string Name; + } + + [System.Serializable] + public class SynchronizedLayer + { + public SynchronizeType SynchronizeType; + public int LayerIndex; + } + + #endregion + + #region Properties + +#if PHOTON_DEVELOP + public PhotonAnimatorView ReceivingSender; +#endif + + #endregion + + #region Members + + private Animator m_Animator; + + private PhotonStreamQueue m_StreamQueue; + + //These fields are only used in the CustomEditor for this script and would trigger a + //"this variable is never used" warning, which I am suppressing here +#pragma warning disable 0414 + [HideInInspector] + [SerializeField] + private bool ShowLayerWeightsInspector = true; + + [HideInInspector] + [SerializeField] + private bool ShowParameterInspector = true; +#pragma warning restore 0414 + + [HideInInspector] + [SerializeField] + private List m_SynchronizeParameters = new List(); + + [HideInInspector] + [SerializeField] + private List m_SynchronizeLayers = new List(); + + private Vector3 m_ReceiverPosition; + private float m_LastDeserializeTime; + private bool m_WasSynchronizeTypeChanged = true; + private PhotonView m_PhotonView; + + /// + /// Cached raised triggers that are set to be synchronized in discrete mode. since a Trigger only stay up for less than a frame, + /// We need to cache it until the next discrete serialization call. + /// + List m_raisedDiscreteTriggersCache = new List(); + + #endregion + + #region Unity + + private void Awake() + { + this.m_PhotonView = GetComponent(); + this.m_StreamQueue = new PhotonStreamQueue(120); + + this.m_Animator = GetComponent(); + } + + private void Update() + { + if (this.m_Animator.applyRootMotion && this.m_PhotonView.isMine == false && PhotonNetwork.connected == true) + { + this.m_Animator.applyRootMotion = false; + } + + if (PhotonNetwork.inRoom == false || PhotonNetwork.room.PlayerCount <= 1) + { + this.m_StreamQueue.Reset(); + return; + } + + if (this.m_PhotonView.isMine == true) + { + this.SerializeDataContinuously(); + + this.CacheDiscreteTriggers(); + } + else + { + this.DeserializeDataContinuously(); + } + } + + #endregion + + #region Setup Synchronizing Methods + + /// + /// Caches the discrete triggers values for keeping track of raised triggers, and will be reseted after the sync routine got performed + /// + public void CacheDiscreteTriggers() + { + for (int i = 0; i < this.m_SynchronizeParameters.Count; ++i) + { + SynchronizedParameter parameter = this.m_SynchronizeParameters[i]; + + if (parameter.SynchronizeType == SynchronizeType.Discrete && parameter.Type == ParameterType.Trigger && this.m_Animator.GetBool(parameter.Name)) + { + if (parameter.Type == ParameterType.Trigger) + { + this.m_raisedDiscreteTriggersCache.Add(parameter.Name); + break; + } + } + } + } + + /// + /// Check if a specific layer is configured to be synchronize + /// + /// Index of the layer. + /// True if the layer is synchronized + public bool DoesLayerSynchronizeTypeExist(int layerIndex) + { + return this.m_SynchronizeLayers.FindIndex(item => item.LayerIndex == layerIndex) != -1; + } + + /// + /// Check if the specified parameter is configured to be synchronized + /// + /// The name of the parameter. + /// True if the parameter is synchronized + public bool DoesParameterSynchronizeTypeExist(string name) + { + return this.m_SynchronizeParameters.FindIndex(item => item.Name == name) != -1; + } + + /// + /// Get a list of all synchronized layers + /// + /// List of SynchronizedLayer objects + public List GetSynchronizedLayers() + { + return this.m_SynchronizeLayers; + } + + /// + /// Get a list of all synchronized parameters + /// + /// List of SynchronizedParameter objects + public List GetSynchronizedParameters() + { + return this.m_SynchronizeParameters; + } + + /// + /// Gets the type how the layer is synchronized + /// + /// Index of the layer. + /// Disabled/Discrete/Continuous + public SynchronizeType GetLayerSynchronizeType(int layerIndex) + { + int index = this.m_SynchronizeLayers.FindIndex(item => item.LayerIndex == layerIndex); + + if (index == -1) + { + return SynchronizeType.Disabled; + } + + return this.m_SynchronizeLayers[index].SynchronizeType; + } + + /// + /// Gets the type how the parameter is synchronized + /// + /// The name of the parameter. + /// Disabled/Discrete/Continuous + public SynchronizeType GetParameterSynchronizeType(string name) + { + int index = this.m_SynchronizeParameters.FindIndex(item => item.Name == name); + + if (index == -1) + { + return SynchronizeType.Disabled; + } + + return this.m_SynchronizeParameters[index].SynchronizeType; + } + + /// + /// Sets the how a layer should be synchronized + /// + /// Index of the layer. + /// Disabled/Discrete/Continuous + public void SetLayerSynchronized(int layerIndex, SynchronizeType synchronizeType) + { + if (Application.isPlaying == true) + { + this.m_WasSynchronizeTypeChanged = true; + } + + int index = this.m_SynchronizeLayers.FindIndex(item => item.LayerIndex == layerIndex); + + if (index == -1) + { + this.m_SynchronizeLayers.Add(new SynchronizedLayer { LayerIndex = layerIndex, SynchronizeType = synchronizeType }); + } + else + { + this.m_SynchronizeLayers[index].SynchronizeType = synchronizeType; + } + } + + /// + /// Sets the how a parameter should be synchronized + /// + /// The name of the parameter. + /// The type of the parameter. + /// Disabled/Discrete/Continuous + public void SetParameterSynchronized(string name, ParameterType type, SynchronizeType synchronizeType) + { + if (Application.isPlaying == true) + { + this.m_WasSynchronizeTypeChanged = true; + } + + int index = this.m_SynchronizeParameters.FindIndex(item => item.Name == name); + + if (index == -1) + { + this.m_SynchronizeParameters.Add(new SynchronizedParameter { Name = name, Type = type, SynchronizeType = synchronizeType }); + } + else + { + this.m_SynchronizeParameters[index].SynchronizeType = synchronizeType; + } + } + + #endregion + + #region Serialization + + private void SerializeDataContinuously() + { + if (this.m_Animator == null) + { + return; + } + + for (int i = 0; i < this.m_SynchronizeLayers.Count; ++i) + { + if (this.m_SynchronizeLayers[i].SynchronizeType == SynchronizeType.Continuous) + { + this.m_StreamQueue.SendNext(this.m_Animator.GetLayerWeight(this.m_SynchronizeLayers[i].LayerIndex)); + } + } + + for (int i = 0; i < this.m_SynchronizeParameters.Count; ++i) + { + SynchronizedParameter parameter = this.m_SynchronizeParameters[i]; + + if (parameter.SynchronizeType == SynchronizeType.Continuous) + { + switch (parameter.Type) + { + case ParameterType.Bool: + this.m_StreamQueue.SendNext(this.m_Animator.GetBool(parameter.Name)); + break; + case ParameterType.Float: + this.m_StreamQueue.SendNext(this.m_Animator.GetFloat(parameter.Name)); + break; + case ParameterType.Int: + this.m_StreamQueue.SendNext(this.m_Animator.GetInteger(parameter.Name)); + break; + case ParameterType.Trigger: + this.m_StreamQueue.SendNext(this.m_Animator.GetBool(parameter.Name)); + break; + } + } + } + } + + + private void DeserializeDataContinuously() + { + if (this.m_StreamQueue.HasQueuedObjects() == false) + { + return; + } + + for (int i = 0; i < this.m_SynchronizeLayers.Count; ++i) + { + if (this.m_SynchronizeLayers[i].SynchronizeType == SynchronizeType.Continuous) + { + this.m_Animator.SetLayerWeight(this.m_SynchronizeLayers[i].LayerIndex, (float)this.m_StreamQueue.ReceiveNext()); + } + } + + for (int i = 0; i < this.m_SynchronizeParameters.Count; ++i) + { + SynchronizedParameter parameter = this.m_SynchronizeParameters[i]; + + if (parameter.SynchronizeType == SynchronizeType.Continuous) + { + switch (parameter.Type) + { + case ParameterType.Bool: + this.m_Animator.SetBool(parameter.Name, (bool)this.m_StreamQueue.ReceiveNext()); + break; + case ParameterType.Float: + this.m_Animator.SetFloat(parameter.Name, (float)this.m_StreamQueue.ReceiveNext()); + break; + case ParameterType.Int: + this.m_Animator.SetInteger(parameter.Name, (int)this.m_StreamQueue.ReceiveNext()); + break; + case ParameterType.Trigger: + this.m_Animator.SetBool(parameter.Name, (bool)this.m_StreamQueue.ReceiveNext()); + break; + } + } + } + } + + private void SerializeDataDiscretly(PhotonStream stream) + { + for (int i = 0; i < this.m_SynchronizeLayers.Count; ++i) + { + if (this.m_SynchronizeLayers[i].SynchronizeType == SynchronizeType.Discrete) + { + stream.SendNext(this.m_Animator.GetLayerWeight(this.m_SynchronizeLayers[i].LayerIndex)); + } + } + + for (int i = 0; i < this.m_SynchronizeParameters.Count; ++i) + { + SynchronizedParameter parameter = this.m_SynchronizeParameters[i]; + + if (parameter.SynchronizeType == SynchronizeType.Discrete) + { + switch (parameter.Type) + { + case ParameterType.Bool: + stream.SendNext(this.m_Animator.GetBool(parameter.Name)); + break; + case ParameterType.Float: + stream.SendNext(this.m_Animator.GetFloat(parameter.Name)); + break; + case ParameterType.Int: + stream.SendNext(this.m_Animator.GetInteger(parameter.Name)); + break; + case ParameterType.Trigger: + // here we can't rely on the current real state of the trigger, we might have missed its raise + stream.SendNext(this.m_raisedDiscreteTriggersCache.Contains(parameter.Name)); + break; + } + } + } + + // reset the cache, we've synchronized. + this.m_raisedDiscreteTriggersCache.Clear(); + } + + private void DeserializeDataDiscretly(PhotonStream stream) + { + for (int i = 0; i < this.m_SynchronizeLayers.Count; ++i) + { + if (this.m_SynchronizeLayers[i].SynchronizeType == SynchronizeType.Discrete) + { + this.m_Animator.SetLayerWeight(this.m_SynchronizeLayers[i].LayerIndex, (float)stream.ReceiveNext()); + } + } + + for (int i = 0; i < this.m_SynchronizeParameters.Count; ++i) + { + SynchronizedParameter parameter = this.m_SynchronizeParameters[i]; + + if (parameter.SynchronizeType == SynchronizeType.Discrete) + { + switch (parameter.Type) + { + case ParameterType.Bool: + if (stream.PeekNext() is bool == false) + { + return; + } + this.m_Animator.SetBool(parameter.Name, (bool)stream.ReceiveNext()); + break; + case ParameterType.Float: + if (stream.PeekNext() is float == false) + { + return; + } + + this.m_Animator.SetFloat(parameter.Name, (float)stream.ReceiveNext()); + break; + case ParameterType.Int: + if (stream.PeekNext() is int == false) + { + return; + } + + this.m_Animator.SetInteger(parameter.Name, (int)stream.ReceiveNext()); + break; + case ParameterType.Trigger: + if (stream.PeekNext() is bool == false) + { + return; + } + + if ((bool)stream.ReceiveNext()) + { + this.m_Animator.SetTrigger(parameter.Name); + } + break; + } + } + } + } + + private void SerializeSynchronizationTypeState(PhotonStream stream) + { + byte[] states = new byte[this.m_SynchronizeLayers.Count + this.m_SynchronizeParameters.Count]; + + for (int i = 0; i < this.m_SynchronizeLayers.Count; ++i) + { + states[i] = (byte)this.m_SynchronizeLayers[i].SynchronizeType; + } + + for (int i = 0; i < this.m_SynchronizeParameters.Count; ++i) + { + states[this.m_SynchronizeLayers.Count + i] = (byte)this.m_SynchronizeParameters[i].SynchronizeType; + } + + stream.SendNext(states); + } + + private void DeserializeSynchronizationTypeState(PhotonStream stream) + { + byte[] state = (byte[])stream.ReceiveNext(); + + for (int i = 0; i < this.m_SynchronizeLayers.Count; ++i) + { + this.m_SynchronizeLayers[i].SynchronizeType = (SynchronizeType)state[i]; + } + + for (int i = 0; i < this.m_SynchronizeParameters.Count; ++i) + { + this.m_SynchronizeParameters[i].SynchronizeType = (SynchronizeType)state[this.m_SynchronizeLayers.Count + i]; + } + } + + public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) + { + if (this.m_Animator == null) + { + return; + } + + if (stream.isWriting == true) + { + if (this.m_WasSynchronizeTypeChanged == true) + { + this.m_StreamQueue.Reset(); + this.SerializeSynchronizationTypeState(stream); + + this.m_WasSynchronizeTypeChanged = false; + } + + this.m_StreamQueue.Serialize(stream); + this.SerializeDataDiscretly(stream); + } + else + { +#if PHOTON_DEVELOP + if( ReceivingSender != null ) + { + ReceivingSender.OnPhotonSerializeView( stream, info ); + } + else +#endif + { + if (stream.PeekNext() is byte[]) + { + this.DeserializeSynchronizationTypeState(stream); + } + + this.m_StreamQueue.Deserialize(stream); + this.DeserializeDataDiscretly(stream); + } + } + } + + #endregion +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonAnimatorView.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonAnimatorView.cs.meta new file mode 100644 index 0000000..9232492 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonAnimatorView.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9b8c4a61274f60b4ea5fb4299cfdbf14 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonRigidbody2DView.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonRigidbody2DView.cs new file mode 100644 index 0000000..25aaf6b --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonRigidbody2DView.cs @@ -0,0 +1,68 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2016 Exit Games GmbH +// +// +// Component to synchronize 2d rigidbodies via PUN. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +using UnityEngine; + +/// +/// This class helps you to synchronize the velocities of a 2d physics RigidBody. +/// Note that only the velocities are synchronized and because Unitys physics +/// engine is not deterministic (ie. the results aren't always the same on all +/// computers) - the actual positions of the objects may go out of sync. If you +/// want to have the position of this object the same on all clients, you should +/// also add a PhotonTransformView to synchronize the position. +/// Simply add the component to your GameObject and make sure that +/// the PhotonRigidbody2DView is added to the list of observed components +/// +[RequireComponent(typeof(PhotonView))] +[RequireComponent(typeof(Rigidbody2D))] +[AddComponentMenu("Photon Networking/Photon Rigidbody 2D View")] +public class PhotonRigidbody2DView : MonoBehaviour, IPunObservable +{ + [SerializeField] + bool m_SynchronizeVelocity = true; + + [SerializeField] + bool m_SynchronizeAngularVelocity = true; + + Rigidbody2D m_Body; + + void Awake() + { + this.m_Body = GetComponent(); + } + + public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) + { + if (stream.isWriting == true) + { + if (this.m_SynchronizeVelocity == true) + { + stream.SendNext(this.m_Body.velocity); + } + + if (this.m_SynchronizeAngularVelocity == true) + { + stream.SendNext(this.m_Body.angularVelocity); + } + } + else + { + if (this.m_SynchronizeVelocity == true) + { + this.m_Body.velocity = (Vector2)stream.ReceiveNext(); + } + + if (this.m_SynchronizeAngularVelocity == true) + { + this.m_Body.angularVelocity = (float)stream.ReceiveNext(); + } + } + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonRigidbody2DView.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonRigidbody2DView.cs.meta new file mode 100644 index 0000000..b2e6d08 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonRigidbody2DView.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0e7cb724808c322458aa4d15f5035fa9 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonRigidbodyView.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonRigidbodyView.cs new file mode 100644 index 0000000..bec072f --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonRigidbodyView.cs @@ -0,0 +1,68 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2016 Exit Games GmbH +// +// +// Component to synchronize rigidbodies via PUN. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +using UnityEngine; + +/// +/// This class helps you to synchronize the velocities of a physics RigidBody. +/// Note that only the velocities are synchronized and because Unitys physics +/// engine is not deterministic (ie. the results aren't always the same on all +/// computers) - the actual positions of the objects may go out of sync. If you +/// want to have the position of this object the same on all clients, you should +/// also add a PhotonTransformView to synchronize the position. +/// Simply add the component to your GameObject and make sure that +/// the PhotonRigidbodyView is added to the list of observed components +/// +[RequireComponent(typeof(PhotonView))] +[RequireComponent(typeof(Rigidbody))] +[AddComponentMenu("Photon Networking/Photon Rigidbody View")] +public class PhotonRigidbodyView : MonoBehaviour, IPunObservable +{ + [SerializeField] + bool m_SynchronizeVelocity = true; + + [SerializeField] + bool m_SynchronizeAngularVelocity = true; + + Rigidbody m_Body; + + void Awake() + { + this.m_Body = GetComponent(); + } + + public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) + { + if (stream.isWriting == true) + { + if (this.m_SynchronizeVelocity == true) + { + stream.SendNext(this.m_Body.velocity); + } + + if (this.m_SynchronizeAngularVelocity == true) + { + stream.SendNext(this.m_Body.angularVelocity); + } + } + else + { + if (this.m_SynchronizeVelocity == true) + { + this.m_Body.velocity = (Vector3)stream.ReceiveNext(); + } + + if (this.m_SynchronizeAngularVelocity == true) + { + this.m_Body.angularVelocity = (Vector3)stream.ReceiveNext(); + } + } + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonRigidbodyView.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonRigidbodyView.cs.meta new file mode 100644 index 0000000..e8c398f --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonRigidbodyView.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 64179f3720bbfe947b7724caa67b7c1d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformView.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformView.cs new file mode 100644 index 0000000..a008141 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformView.cs @@ -0,0 +1,214 @@ + // ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2016 Exit Games GmbH +// +// +// Component to synchronize Transforms via PUN PhotonView. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +using UnityEngine; + +/// +/// This class helps you to synchronize position, rotation and scale +/// of a GameObject. It also gives you many different options to make +/// the synchronized values appear smooth, even when the data is only +/// send a couple of times per second. +/// Simply add the component to your GameObject and make sure that +/// the PhotonTransformView is added to the list of observed components +/// +[RequireComponent(typeof(PhotonView))] +[AddComponentMenu("Photon Networking/Photon Transform View")] +public class PhotonTransformView : MonoBehaviour, IPunObservable +{ + //Since this component is very complex, we seperated it into multiple objects. + //The PositionModel, RotationModel and ScaleMode store the data you are able to + //configure in the inspector while the control objects below are actually moving + //the object and calculating all the inter- and extrapolation + + [SerializeField] + public PhotonTransformViewPositionModel m_PositionModel = new PhotonTransformViewPositionModel(); + + [SerializeField] + public PhotonTransformViewRotationModel m_RotationModel = new PhotonTransformViewRotationModel(); + + [SerializeField] + public PhotonTransformViewScaleModel m_ScaleModel = new PhotonTransformViewScaleModel(); + + PhotonTransformViewPositionControl m_PositionControl; + PhotonTransformViewRotationControl m_RotationControl; + PhotonTransformViewScaleControl m_ScaleControl; + + PhotonView m_PhotonView; + + bool m_ReceivedNetworkUpdate = false; + + /// + /// Flag to skip initial data when Object is instantiated and rely on the first deserialized data instead. + /// + bool m_firstTake = false; + + void Awake() + { + this.m_PhotonView = GetComponent(); + + this.m_PositionControl = new PhotonTransformViewPositionControl(this.m_PositionModel); + this.m_RotationControl = new PhotonTransformViewRotationControl(this.m_RotationModel); + this.m_ScaleControl = new PhotonTransformViewScaleControl(this.m_ScaleModel); + } + + void OnEnable() + { + m_firstTake = true; + } + + void Update() + { + if (this.m_PhotonView == null || this.m_PhotonView.isMine == true || PhotonNetwork.connected == false) + { + return; + } + + this.UpdatePosition(); + this.UpdateRotation(); + this.UpdateScale(); + } + + void UpdatePosition() + { + if (this.m_PositionModel.SynchronizeEnabled == false || this.m_ReceivedNetworkUpdate == false) + { + return; + } + + transform.localPosition = this.m_PositionControl.UpdatePosition(transform.localPosition); + } + + void UpdateRotation() + { + if (this.m_RotationModel.SynchronizeEnabled == false || this.m_ReceivedNetworkUpdate == false) + { + return; + } + + transform.localRotation = this.m_RotationControl.GetRotation(transform.localRotation); + } + + void UpdateScale() + { + if (this.m_ScaleModel.SynchronizeEnabled == false || this.m_ReceivedNetworkUpdate == false) + { + return; + } + + transform.localScale = this.m_ScaleControl.GetScale(transform.localScale); + } + + /// + /// These values are synchronized to the remote objects if the interpolation mode + /// or the extrapolation mode SynchronizeValues is used. Your movement script should pass on + /// the current speed (in units/second) and turning speed (in angles/second) so the remote + /// object can use them to predict the objects movement. + /// + /// The current movement vector of the object in units/second. + /// The current turn speed of the object in angles/second. + public void SetSynchronizedValues(Vector3 speed, float turnSpeed) + { + this.m_PositionControl.SetSynchronizedValues(speed, turnSpeed); + } + + public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) + { + this.m_PositionControl.OnPhotonSerializeView(transform.localPosition, stream, info); + this.m_RotationControl.OnPhotonSerializeView(transform.localRotation, stream, info); + this.m_ScaleControl.OnPhotonSerializeView(transform.localScale, stream, info); + + if (this.m_PhotonView.isMine == false && this.m_PositionModel.DrawErrorGizmo == true) + { + this.DoDrawEstimatedPositionError(); + } + + if (stream.isReading == true) + { + this.m_ReceivedNetworkUpdate = true; + + // force latest data to avoid initial drifts when player is instantiated. + if (m_firstTake) + { + m_firstTake = false; + + if (this.m_PositionModel.SynchronizeEnabled) + { + this.transform.localPosition = this.m_PositionControl.GetNetworkPosition(); + } + + if (this.m_RotationModel.SynchronizeEnabled) + { + this.transform.localRotation = this.m_RotationControl.GetNetworkRotation(); + } + + if (this.m_ScaleModel.SynchronizeEnabled) + { + this.transform.localScale = this.m_ScaleControl.GetNetworkScale(); + } + + } + + } + } + + //void OnDrawGizmos() + //{ + // if( Application.isPlaying == false || m_PhotonView == null || m_PhotonView.isMine == true || PhotonNetwork.connected == false ) + // { + // return; + // } + + // DoDrawNetworkPositionGizmo(); + // DoDrawExtrapolatedPositionGizmo(); + //} + + void DoDrawEstimatedPositionError() + { + Vector3 targetPosition = this.m_PositionControl.GetNetworkPosition(); + + // we are synchronizing the localPosition, so we need to add the parent position for a proper positioning. + if (transform.parent != null) + { + targetPosition = transform.parent.position + targetPosition ; + } + + Debug.DrawLine(targetPosition, transform.position, Color.red, 2f); + Debug.DrawLine(transform.position, transform.position + Vector3.up, Color.green, 2f); + Debug.DrawLine(targetPosition , targetPosition + Vector3.up, Color.red, 2f); + } + + //void DoDrawNetworkPositionGizmo() + //{ + // if( m_PositionModel.DrawNetworkGizmo == false || m_PositionControl == null ) + // { + // return; + // } + + // ExitGames.Client.GUI.GizmoTypeDrawer.Draw( m_PositionControl.GetNetworkPosition(), + // m_PositionModel.NetworkGizmoType, + // m_PositionModel.NetworkGizmoColor, + // m_PositionModel.NetworkGizmoSize ); + //} + + //void DoDrawExtrapolatedPositionGizmo() + //{ + // if( m_PositionModel.DrawExtrapolatedGizmo == false || + // m_PositionModel.ExtrapolateOption == PhotonTransformViewPositionModel.ExtrapolateOptions.Disabled || + // m_PositionControl == null ) + // { + // return; + // } + + // ExitGames.Client.GUI.GizmoTypeDrawer.Draw( m_PositionControl.GetNetworkPosition() + m_PositionControl.GetExtrapolatedPositionOffset(), + // m_PositionModel.ExtrapolatedGizmoType, + // m_PositionModel.ExtrapolatedGizmoColor, + // m_PositionModel.ExtrapolatedGizmoSize ); + //} +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformView.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformView.cs.meta new file mode 100644 index 0000000..963d8ee --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformView.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 627855c7f81362d41938ffe0b1475957 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewPositionControl.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewPositionControl.cs new file mode 100644 index 0000000..550fd7b --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewPositionControl.cs @@ -0,0 +1,246 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2016 Exit Games GmbH +// +// +// Component to synchronize position via PUN PhotonView. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +using UnityEngine; +using System.Collections; +using System.Collections.Generic; + +public class PhotonTransformViewPositionControl +{ + PhotonTransformViewPositionModel m_Model; + float m_CurrentSpeed; + double m_LastSerializeTime; + Vector3 m_SynchronizedSpeed = Vector3.zero; + float m_SynchronizedTurnSpeed = 0; + + Vector3 m_NetworkPosition; + Queue m_OldNetworkPositions = new Queue(); + + bool m_UpdatedPositionAfterOnSerialize = true; + + public PhotonTransformViewPositionControl( PhotonTransformViewPositionModel model ) + { + m_Model = model; + } + + Vector3 GetOldestStoredNetworkPosition() + { + Vector3 oldPosition = m_NetworkPosition; + + if( m_OldNetworkPositions.Count > 0 ) + { + oldPosition = m_OldNetworkPositions.Peek(); + } + + return oldPosition; + } + + /// + /// These values are synchronized to the remote objects if the interpolation mode + /// or the extrapolation mode SynchronizeValues is used. Your movement script should pass on + /// the current speed (in units/second) and turning speed (in angles/second) so the remote + /// object can use them to predict the objects movement. + /// + /// The current movement vector of the object in units/second. + /// The current turn speed of the object in angles/second. + public void SetSynchronizedValues( Vector3 speed, float turnSpeed ) + { + m_SynchronizedSpeed = speed; + m_SynchronizedTurnSpeed = turnSpeed; + } + + /// + /// Calculates the new position based on the values setup in the inspector + /// + /// The current position. + /// The new position. + public Vector3 UpdatePosition( Vector3 currentPosition ) + { + Vector3 targetPosition = GetNetworkPosition() + GetExtrapolatedPositionOffset(); + + switch( m_Model.InterpolateOption ) + { + case PhotonTransformViewPositionModel.InterpolateOptions.Disabled: + if( m_UpdatedPositionAfterOnSerialize == false ) + { + currentPosition = targetPosition; + m_UpdatedPositionAfterOnSerialize = true; + } + break; + + case PhotonTransformViewPositionModel.InterpolateOptions.FixedSpeed: + currentPosition = Vector3.MoveTowards( currentPosition, targetPosition, Time.deltaTime * m_Model.InterpolateMoveTowardsSpeed ); + break; + + case PhotonTransformViewPositionModel.InterpolateOptions.EstimatedSpeed: + if (m_OldNetworkPositions.Count == 0) + { + // special case: we have no previous updates in memory, so we can't guess a speed! + break; + } + + // knowing the last (incoming) position and the one before, we can guess a speed. + // note that the speed is times sendRateOnSerialize! we send X updates/sec, so our estimate has to factor that in. + float estimatedSpeed = (Vector3.Distance(m_NetworkPosition, GetOldestStoredNetworkPosition()) / m_OldNetworkPositions.Count) * PhotonNetwork.sendRateOnSerialize; + + // move towards the targetPosition (including estimates, if that's active) with the speed calculated from the last updates. + currentPosition = Vector3.MoveTowards(currentPosition, targetPosition, Time.deltaTime * estimatedSpeed ); + break; + + case PhotonTransformViewPositionModel.InterpolateOptions.SynchronizeValues: + if( m_SynchronizedSpeed.magnitude == 0 ) + { + currentPosition = targetPosition; + } + else + { + currentPosition = Vector3.MoveTowards( currentPosition, targetPosition, Time.deltaTime * m_SynchronizedSpeed.magnitude ); + } + break; + + case PhotonTransformViewPositionModel.InterpolateOptions.Lerp: + currentPosition = Vector3.Lerp( currentPosition, targetPosition, Time.deltaTime * m_Model.InterpolateLerpSpeed ); + break; + + /*case PhotonTransformViewPositionModel.InterpolateOptions.MoveTowardsComplex: + float distanceToTarget = Vector3.Distance( currentPosition, targetPosition ); + float targetSpeed = m_Model.InterpolateSpeedCurve.Evaluate( distanceToTarget ) * m_Model.InterpolateMoveTowardsSpeed; + + if( targetSpeed > m_CurrentSpeed ) + { + m_CurrentSpeed = Mathf.MoveTowards( m_CurrentSpeed, targetSpeed, Time.deltaTime * m_Model.InterpolateMoveTowardsAcceleration ); + } + else + { + m_CurrentSpeed = Mathf.MoveTowards( m_CurrentSpeed, targetSpeed, Time.deltaTime * m_Model.InterpolateMoveTowardsDeceleration ); + } + + //Debug.Log( m_CurrentSpeed + " - " + targetSpeed + " - " + transform.localPosition + " - " + targetPosition ); + + currentPosition = Vector3.MoveTowards( currentPosition, targetPosition, Time.deltaTime * m_CurrentSpeed ); + break;*/ + } + + if( m_Model.TeleportEnabled == true ) + { + if( Vector3.Distance( currentPosition, GetNetworkPosition() ) > m_Model.TeleportIfDistanceGreaterThan ) + { + currentPosition = GetNetworkPosition(); + } + } + + return currentPosition; + } + + /// + /// Gets the last position that was received through the network + /// + /// + public Vector3 GetNetworkPosition() + { + return m_NetworkPosition; + } + + /// + /// Calculates an estimated position based on the last synchronized position, + /// the time when the last position was received and the movement speed of the object + /// + /// Estimated position of the remote object + public Vector3 GetExtrapolatedPositionOffset() + { + float timePassed = (float)( PhotonNetwork.time - m_LastSerializeTime ); + + if( m_Model.ExtrapolateIncludingRoundTripTime == true ) + { + timePassed += (float)PhotonNetwork.GetPing() / 1000f; + } + + Vector3 extrapolatePosition = Vector3.zero; + + switch( m_Model.ExtrapolateOption ) + { + case PhotonTransformViewPositionModel.ExtrapolateOptions.SynchronizeValues: + Quaternion turnRotation = Quaternion.Euler( 0, m_SynchronizedTurnSpeed * timePassed, 0 ); + extrapolatePosition = turnRotation * ( m_SynchronizedSpeed * timePassed ); + break; + case PhotonTransformViewPositionModel.ExtrapolateOptions.FixedSpeed: + Vector3 moveDirection = ( m_NetworkPosition - GetOldestStoredNetworkPosition() ).normalized; + + extrapolatePosition = moveDirection * m_Model.ExtrapolateSpeed * timePassed; + break; + case PhotonTransformViewPositionModel.ExtrapolateOptions.EstimateSpeedAndTurn: + Vector3 moveDelta = ( m_NetworkPosition - GetOldestStoredNetworkPosition() ) * PhotonNetwork.sendRateOnSerialize; + extrapolatePosition = moveDelta * timePassed; + break; + } + + return extrapolatePosition; + } + + public void OnPhotonSerializeView( Vector3 currentPosition, PhotonStream stream, PhotonMessageInfo info ) + { + if( m_Model.SynchronizeEnabled == false ) + { + return; + } + + if( stream.isWriting == true ) + { + SerializeData( currentPosition, stream, info ); + } + else + { + DeserializeData( stream, info ); + } + + m_LastSerializeTime = PhotonNetwork.time; + m_UpdatedPositionAfterOnSerialize = false; + } + + void SerializeData( Vector3 currentPosition, PhotonStream stream, PhotonMessageInfo info ) + { + stream.SendNext( currentPosition ); + m_NetworkPosition = currentPosition; + + if( m_Model.ExtrapolateOption == PhotonTransformViewPositionModel.ExtrapolateOptions.SynchronizeValues || + m_Model.InterpolateOption == PhotonTransformViewPositionModel.InterpolateOptions.SynchronizeValues ) + { + stream.SendNext( m_SynchronizedSpeed ); + stream.SendNext( m_SynchronizedTurnSpeed ); + } + } + + void DeserializeData( PhotonStream stream, PhotonMessageInfo info ) + { + Vector3 readPosition = (Vector3)stream.ReceiveNext(); + if( m_Model.ExtrapolateOption == PhotonTransformViewPositionModel.ExtrapolateOptions.SynchronizeValues || + m_Model.InterpolateOption == PhotonTransformViewPositionModel.InterpolateOptions.SynchronizeValues ) + { + m_SynchronizedSpeed = (Vector3)stream.ReceiveNext(); + m_SynchronizedTurnSpeed = (float)stream.ReceiveNext(); + } + + if (m_OldNetworkPositions.Count == 0) + { + // if we don't have old positions yet, this is the very first update this client reads. let's use this as current AND old position. + m_NetworkPosition = readPosition; + } + + // the previously received position becomes the old(er) one and queued. the new one is the m_NetworkPosition + m_OldNetworkPositions.Enqueue( m_NetworkPosition ); + m_NetworkPosition = readPosition; + + // reduce items in queue to defined number of stored positions. + while( m_OldNetworkPositions.Count > m_Model.ExtrapolateNumberOfStoredPositions ) + { + m_OldNetworkPositions.Dequeue(); + } + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewPositionControl.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewPositionControl.cs.meta new file mode 100644 index 0000000..003f24d --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewPositionControl.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 83c7620118e76384db972fbb42e91b20 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewPositionModel.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewPositionModel.cs new file mode 100644 index 0000000..f234807 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewPositionModel.cs @@ -0,0 +1,67 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2016 Exit Games GmbH +// +// +// Model to synchronize position via PUN PhotonView. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +using UnityEngine; +using System.Collections; + +[System.Serializable] +public class PhotonTransformViewPositionModel +{ + public enum InterpolateOptions + { + Disabled, + FixedSpeed, + EstimatedSpeed, + SynchronizeValues, + //MoveTowardsComplex, + Lerp, + } + + public enum ExtrapolateOptions + { + Disabled, + SynchronizeValues, + EstimateSpeedAndTurn, + FixedSpeed, + } + + public bool SynchronizeEnabled; + + public bool TeleportEnabled = true; + public float TeleportIfDistanceGreaterThan = 3f; + + public InterpolateOptions InterpolateOption = InterpolateOptions.EstimatedSpeed; + public float InterpolateMoveTowardsSpeed = 1f; + public float InterpolateLerpSpeed = 1f; + public float InterpolateMoveTowardsAcceleration = 2; + public float InterpolateMoveTowardsDeceleration = 2; + public AnimationCurve InterpolateSpeedCurve = new AnimationCurve( new Keyframe[] { + new Keyframe( -1, 0, 0, Mathf.Infinity ), + new Keyframe( 0, 1, 0, 0 ), + new Keyframe( 1, 1, 0, 1 ), + new Keyframe( 4, 4, 1, 0 ) } ); + + public ExtrapolateOptions ExtrapolateOption = ExtrapolateOptions.Disabled; + public float ExtrapolateSpeed = 1f; + public bool ExtrapolateIncludingRoundTripTime = true; + public int ExtrapolateNumberOfStoredPositions = 1; + + //public bool DrawNetworkGizmo = true; + //public Color NetworkGizmoColor = Color.red; + //public ExitGames.Client.GUI.GizmoType NetworkGizmoType; + //public float NetworkGizmoSize = 1f; + + //public bool DrawExtrapolatedGizmo = true; + //public Color ExtrapolatedGizmoColor = Color.yellow; + //public ExitGames.Client.GUI.GizmoType ExtrapolatedGizmoType; + //public float ExtrapolatedGizmoSize = 1f; + + public bool DrawErrorGizmo = true; +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewPositionModel.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewPositionModel.cs.meta new file mode 100644 index 0000000..58b8945 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewPositionModel.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 50a9ddcc59cdf244883cf0ec646cc8c1 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewRotationControl.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewRotationControl.cs new file mode 100644 index 0000000..490fda4 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewRotationControl.cs @@ -0,0 +1,64 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2016 Exit Games GmbH +// +// +// Component to synchronize rotations via PUN PhotonView. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +using UnityEngine; +using System.Collections; + +public class PhotonTransformViewRotationControl +{ + PhotonTransformViewRotationModel m_Model; + Quaternion m_NetworkRotation; + + public PhotonTransformViewRotationControl( PhotonTransformViewRotationModel model ) + { + m_Model = model; + } + + /// + /// Gets the last rotation that was received through the network + /// + /// + public Quaternion GetNetworkRotation() + { + return m_NetworkRotation; + } + + public Quaternion GetRotation( Quaternion currentRotation ) + { + switch( m_Model.InterpolateOption ) + { + default: + case PhotonTransformViewRotationModel.InterpolateOptions.Disabled: + return m_NetworkRotation; + case PhotonTransformViewRotationModel.InterpolateOptions.RotateTowards: + return Quaternion.RotateTowards( currentRotation, m_NetworkRotation, m_Model.InterpolateRotateTowardsSpeed * Time.deltaTime ); + case PhotonTransformViewRotationModel.InterpolateOptions.Lerp: + return Quaternion.Lerp( currentRotation, m_NetworkRotation, m_Model.InterpolateLerpSpeed * Time.deltaTime ); + } + } + + public void OnPhotonSerializeView( Quaternion currentRotation, PhotonStream stream, PhotonMessageInfo info ) + { + if( m_Model.SynchronizeEnabled == false ) + { + return; + } + + if( stream.isWriting == true ) + { + stream.SendNext( currentRotation ); + m_NetworkRotation = currentRotation; + } + else + { + m_NetworkRotation = (Quaternion)stream.ReceiveNext(); + } + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewRotationControl.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewRotationControl.cs.meta new file mode 100644 index 0000000..f3520cd --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewRotationControl.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c6756f3d99937134d9b25f9573d60f27 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewRotationModel.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewRotationModel.cs new file mode 100644 index 0000000..2a81c4f --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewRotationModel.cs @@ -0,0 +1,29 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2016 Exit Games GmbH +// +// +// Model class to synchronize rotations via PUN PhotonView. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +using UnityEngine; +using System.Collections; + +[System.Serializable] +public class PhotonTransformViewRotationModel +{ + public enum InterpolateOptions + { + Disabled, + RotateTowards, + Lerp, + } + + public bool SynchronizeEnabled; + + public InterpolateOptions InterpolateOption = InterpolateOptions.RotateTowards; + public float InterpolateRotateTowardsSpeed = 180; + public float InterpolateLerpSpeed = 5; +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewRotationModel.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewRotationModel.cs.meta new file mode 100644 index 0000000..288faef --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewRotationModel.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fc810f3956379f34dae4b1487445d290 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewScaleControl.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewScaleControl.cs new file mode 100644 index 0000000..1d2930e --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewScaleControl.cs @@ -0,0 +1,64 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2016 Exit Games GmbH +// +// +// Component to synchronize scale via PUN PhotonView. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +using UnityEngine; +using System.Collections; + +public class PhotonTransformViewScaleControl +{ + PhotonTransformViewScaleModel m_Model; + Vector3 m_NetworkScale = Vector3.one; + + public PhotonTransformViewScaleControl( PhotonTransformViewScaleModel model ) + { + m_Model = model; + } + + /// + /// Gets the last scale that was received through the network + /// + /// + public Vector3 GetNetworkScale() + { + return m_NetworkScale; + } + + public Vector3 GetScale( Vector3 currentScale ) + { + switch( m_Model.InterpolateOption ) + { + default: + case PhotonTransformViewScaleModel.InterpolateOptions.Disabled: + return m_NetworkScale; + case PhotonTransformViewScaleModel.InterpolateOptions.MoveTowards: + return Vector3.MoveTowards( currentScale, m_NetworkScale, m_Model.InterpolateMoveTowardsSpeed * Time.deltaTime ); + case PhotonTransformViewScaleModel.InterpolateOptions.Lerp: + return Vector3.Lerp( currentScale, m_NetworkScale, m_Model.InterpolateLerpSpeed * Time.deltaTime ); + } + } + + public void OnPhotonSerializeView( Vector3 currentScale, PhotonStream stream, PhotonMessageInfo info ) + { + if( m_Model.SynchronizeEnabled == false ) + { + return; + } + + if( stream.isWriting == true ) + { + stream.SendNext( currentScale ); + m_NetworkScale = currentScale; + } + else + { + m_NetworkScale = (Vector3)stream.ReceiveNext(); + } + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewScaleControl.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewScaleControl.cs.meta new file mode 100644 index 0000000..b9c242e --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewScaleControl.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f8ddd626f728c0c4f9305c4fc472b1a2 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewScaleModel.cs b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewScaleModel.cs new file mode 100644 index 0000000..5c5f914 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewScaleModel.cs @@ -0,0 +1,29 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2016 Exit Games GmbH +// +// +// Model to synchronize scale via PUN PhotonView. +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + +using UnityEngine; +using System.Collections; + +[System.Serializable] +public class PhotonTransformViewScaleModel +{ + public enum InterpolateOptions + { + Disabled, + MoveTowards, + Lerp, + } + + public bool SynchronizeEnabled; + + public InterpolateOptions InterpolateOption = InterpolateOptions.Disabled; + public float InterpolateMoveTowardsSpeed = 1f; + public float InterpolateLerpSpeed; +} diff --git a/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewScaleModel.cs.meta b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewScaleModel.cs.meta new file mode 100644 index 0000000..b4f63a8 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Plugins/PhotonNetwork/Views/PhotonTransformViewScaleModel.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7379c1718ac64ca48bdb60b1dd644a5c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/PunIcon-White-128.png b/Close Enough!/Assets/Photon Unity Networking/PunIcon-White-128.png new file mode 100644 index 0000000..885c22f Binary files /dev/null and b/Close Enough!/Assets/Photon Unity Networking/PunIcon-White-128.png differ diff --git a/Close Enough!/Assets/Photon Unity Networking/PunIcon-White-128.png.meta b/Close Enough!/Assets/Photon Unity Networking/PunIcon-White-128.png.meta new file mode 100644 index 0000000..90a3a83 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/PunIcon-White-128.png.meta @@ -0,0 +1,45 @@ +fileFormatVersion: 2 +guid: e1e27211415083e41bd38b51da93f58b +TextureImporter: + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 128 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/Resources.meta b/Close Enough!/Assets/Photon Unity Networking/Resources.meta new file mode 100644 index 0000000..0bddcd1 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Resources.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: bcdf0a0361a4c403f979be5ae37b19e5 +folderAsset: yes +timeCreated: 1525372543 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Photon Unity Networking/Resources/PhotonServerSettings.asset b/Close Enough!/Assets/Photon Unity Networking/Resources/PhotonServerSettings.asset new file mode 100644 index 0000000..0da45fb --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Resources/PhotonServerSettings.asset @@ -0,0 +1,39 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9f3758f8f58fdef43803eb9be1df0608, type: 3} + m_Name: PhotonServerSettings + m_EditorClassIdentifier: + AppID: + VoiceAppID: + ChatAppID: + HostType: 0 + PreferredRegion: 0 + EnabledRegions: -1 + Protocol: 0 + ServerAddress: + ServerPort: 5055 + VoiceServerPort: 5055 + JoinLobby: 0 + EnableLobbyStatistics: 0 + PunLogging: 0 + NetworkLogging: 1 + RunInBackground: 1 + RpcList: + - Chat + - DestroyRpc + - InstantiateRpc + - PickupItemInit + - PunPickup + - PunPickupSimple + - PunRespawn + - RequestForPickupItems + - RequestForPickupTimes + DisableAutoOpenWizard: 1 diff --git a/Close Enough!/Assets/Photon Unity Networking/Resources/PhotonServerSettings.asset.meta b/Close Enough!/Assets/Photon Unity Networking/Resources/PhotonServerSettings.asset.meta new file mode 100644 index 0000000..caf0819 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/Resources/PhotonServerSettings.asset.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: a1c950de08c0946778f61d54eb804bbb +timeCreated: 1525372543 +licenseType: Free +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts.meta new file mode 100644 index 0000000..d1e7bcc --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 2c3ebb8ef5b9a42d0b61dcc32db03989 +folderAsset: yes +timeCreated: 1525372511 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/ConnectAndJoinRandom.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/ConnectAndJoinRandom.cs new file mode 100644 index 0000000..1e21e56 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/ConnectAndJoinRandom.cs @@ -0,0 +1,70 @@ +using System; +using UnityEngine; +using System.Collections; + +/// +/// This script automatically connects to Photon (using the settings file), +/// tries to join a random room and creates one if none was found (which is ok). +/// +public class ConnectAndJoinRandom : Photon.MonoBehaviour +{ + /// Connect automatically? If false you can set this to true later on or call ConnectUsingSettings in your own scripts. + public bool AutoConnect = true; + + public byte Version = 1; + + /// if we don't want to connect in Start(), we have to "remember" if we called ConnectUsingSettings() + private bool ConnectInUpdate = true; + + + public virtual void Start() + { + PhotonNetwork.autoJoinLobby = false; // we join randomly. always. no need to join a lobby to get the list of rooms. + } + + public virtual void Update() + { + if (ConnectInUpdate && AutoConnect && !PhotonNetwork.connected) + { + Debug.Log("Update() was called by Unity. Scene is loaded. Let's connect to the Photon Master Server. Calling: PhotonNetwork.ConnectUsingSettings();"); + + ConnectInUpdate = false; + PhotonNetwork.ConnectUsingSettings(Version + "." + SceneManagerHelper.ActiveSceneBuildIndex); + } + } + + + // below, we implement some callbacks of PUN + // you can find PUN's callbacks in the class PunBehaviour or in enum PhotonNetworkingMessage + + + public virtual void OnConnectedToMaster() + { + Debug.Log("OnConnectedToMaster() was called by PUN. Now this client is connected and could join a room. Calling: PhotonNetwork.JoinRandomRoom();"); + PhotonNetwork.JoinRandomRoom(); + } + + public virtual void OnJoinedLobby() + { + Debug.Log("OnJoinedLobby(). This client is connected and does get a room-list, which gets stored as PhotonNetwork.GetRoomList(). This script now calls: PhotonNetwork.JoinRandomRoom();"); + PhotonNetwork.JoinRandomRoom(); + } + + public virtual void OnPhotonRandomJoinFailed() + { + Debug.Log("OnPhotonRandomJoinFailed() was called by PUN. No random room available, so we create one. Calling: PhotonNetwork.CreateRoom(null, new RoomOptions() {maxPlayers = 4}, null);"); + PhotonNetwork.CreateRoom(null, new RoomOptions() { MaxPlayers = 4 }, null); + } + + // the following methods are implemented to give you some context. re-implement them as needed. + + public virtual void OnFailedToConnectToPhoton(DisconnectCause cause) + { + Debug.LogError("Cause: " + cause); + } + + public void OnJoinedRoom() + { + Debug.Log("OnJoinedRoom() called by PUN. Now this client is in a room. From here on, your game would be running. For reference, all callbacks are listed in enum: PhotonNetworkingMessage"); + } +} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/ConnectAndJoinRandom.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/ConnectAndJoinRandom.cs.meta new file mode 100644 index 0000000..13f1494 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/ConnectAndJoinRandom.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5c1b84a427010e0469ce0df07ab64dbc +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/CullArea.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/CullArea.cs new file mode 100644 index 0000000..d958e3b --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/CullArea.cs @@ -0,0 +1,466 @@ +using System.Collections.Generic; +using UnityEngine; + +/// +/// Represents the cull area used for network culling. +/// +[HelpURL("https://doc.photonengine.com/en-us/pun/current/demos-and-tutorials/package-demos/culling-demo")] +public class CullArea : MonoBehaviour +{ + private const int MAX_NUMBER_OF_ALLOWED_CELLS = 250; + + public const int MAX_NUMBER_OF_SUBDIVISIONS = 3; + + /// + /// This represents the first ID which is assigned to the first created cell. + /// If you already have some interest groups blocking this first ID, fell free to change it. + /// However increasing the first group ID decreases the maximum amount of allowed cells. + /// Allowed values are in range from 1 to 250. + /// + public readonly byte FIRST_GROUP_ID = 1; + + /// + /// This represents the order in which updates are sent. + /// The number represents the subdivision of the cell hierarchy: + /// - 0: message is sent to all players + /// - 1: message is sent to players who are interested in the matching cell of the first subdivision + /// If there is only one subdivision we are sending one update to all players + /// before sending three consequent updates only to players who are in the same cell + /// or interested in updates of the current cell. + /// + public readonly int[] SUBDIVISION_FIRST_LEVEL_ORDER = new int[4] { 0, 1, 1, 1 }; + + /// + /// This represents the order in which updates are sent. + /// The number represents the subdivision of the cell hierarchy: + /// - 0: message is sent to all players + /// - 1: message is sent to players who are interested in the matching cell of the first subdivision + /// - 2: message is sent to players who are interested in the matching cell of the second subdivision + /// If there are two subdivisions we are sending every second update only to players + /// who are in the same cell or interested in updates of the current cell. + /// + public readonly int[] SUBDIVISION_SECOND_LEVEL_ORDER = new int[8] { 0, 2, 1, 2, 0, 2, 1, 2 }; + + /// + /// This represents the order in which updates are sent. + /// The number represents the subdivision of the cell hierarchy: + /// - 0: message is sent to all players + /// - 1: message is sent to players who are interested in the matching cell of the first subdivision + /// - 2: message is sent to players who are interested in the matching cell of the second subdivision + /// - 3: message is sent to players who are interested in the matching cell of the third subdivision + /// If there are two subdivisions we are sending every second update only to players + /// who are in the same cell or interested in updates of the current cell. + /// + public readonly int[] SUBDIVISION_THIRD_LEVEL_ORDER = new int[12] { 0, 3, 2, 3, 1, 3, 2, 3, 1, 3, 2, 3 }; + + public Vector2 Center; + public Vector2 Size = new Vector2(25.0f, 25.0f); + + public Vector2[] Subdivisions = new Vector2[MAX_NUMBER_OF_SUBDIVISIONS]; + + public int NumberOfSubdivisions; + + public int CellCount { get; private set; } + + public CellTree CellTree { get; private set; } + + public Dictionary Map { get; private set; } + + public bool YIsUpAxis = false; + public bool RecreateCellHierarchy = false; + + private byte idCounter; + + /// + /// Creates the cell hierarchy at runtime. + /// + private void Awake() + { + this.idCounter = this.FIRST_GROUP_ID; + + this.CreateCellHierarchy(); + } + + /// + /// Creates the cell hierarchy in editor and draws the cell view. + /// + public void OnDrawGizmos() + { + this.idCounter = this.FIRST_GROUP_ID; + + if (this.RecreateCellHierarchy) + { + this.CreateCellHierarchy(); + } + + this.DrawCells(); + } + + /// + /// Creates the cell hierarchy. + /// + private void CreateCellHierarchy() + { + if (!this.IsCellCountAllowed()) + { + if (Debug.isDebugBuild) + { + Debug.LogError("There are too many cells created by your subdivision options. Maximum allowed number of cells is " + (MAX_NUMBER_OF_ALLOWED_CELLS - this.FIRST_GROUP_ID) + + ". Current number of cells is " + this.CellCount + "."); + return; + } + else + { + Application.Quit(); + } + } + + CellTreeNode rootNode = new CellTreeNode(this.idCounter++, CellTreeNode.ENodeType.Root, null); + + if (this.YIsUpAxis) + { + this.Center = new Vector2(transform.position.x, transform.position.y); + this.Size = new Vector2(transform.localScale.x, transform.localScale.y); + + rootNode.Center = new Vector3(this.Center.x, this.Center.y, 0.0f); + rootNode.Size = new Vector3(this.Size.x, this.Size.y, 0.0f); + rootNode.TopLeft = new Vector3((this.Center.x - (this.Size.x/2.0f)), (this.Center.y - (this.Size.y/2.0f)), 0.0f); + rootNode.BottomRight = new Vector3((this.Center.x + (this.Size.x/2.0f)), (this.Center.y + (this.Size.y/2.0f)), 0.0f); + } + else + { + this.Center = new Vector2(transform.position.x, transform.position.z); + this.Size = new Vector2(transform.localScale.x, transform.localScale.z); + + rootNode.Center = new Vector3(this.Center.x, 0.0f, this.Center.y); + rootNode.Size = new Vector3(this.Size.x, 0.0f, this.Size.y); + rootNode.TopLeft = new Vector3((this.Center.x - (this.Size.x/2.0f)), 0.0f, (this.Center.y - (this.Size.y/2.0f))); + rootNode.BottomRight = new Vector3((this.Center.x + (this.Size.x/2.0f)), 0.0f, (this.Center.y + (this.Size.y/2.0f))); + } + + this.CreateChildCells(rootNode, 1); + + this.CellTree = new CellTree(rootNode); + + this.RecreateCellHierarchy = false; + } + + /// + /// Creates all child cells. + /// + /// The current parent node. + /// The cell level within the current hierarchy. + private void CreateChildCells(CellTreeNode parent, int cellLevelInHierarchy) + { + if (cellLevelInHierarchy > this.NumberOfSubdivisions) + { + return; + } + + int rowCount = (int)this.Subdivisions[(cellLevelInHierarchy - 1)].x; + int columnCount = (int)this.Subdivisions[(cellLevelInHierarchy - 1)].y; + + float startX = parent.Center.x - (parent.Size.x/2.0f); + float width = parent.Size.x/rowCount; + + for (int row = 0; row < rowCount; ++row) + { + for (int column = 0; column < columnCount; ++column) + { + float xPos = startX + (row*width) + (width/2.0f); + + CellTreeNode node = new CellTreeNode(this.idCounter++, (this.NumberOfSubdivisions == cellLevelInHierarchy) ? CellTreeNode.ENodeType.Leaf : CellTreeNode.ENodeType.Node, parent); + + if (this.YIsUpAxis) + { + float startY = parent.Center.y - (parent.Size.y/2.0f); + float height = parent.Size.y/columnCount; + float yPos = startY + (column*height) + (height/2.0f); + + node.Center = new Vector3(xPos, yPos, 0.0f); + node.Size = new Vector3(width, height, 0.0f); + node.TopLeft = new Vector3(xPos - (width/2.0f), yPos - (height/2.0f), 0.0f); + node.BottomRight = new Vector3(xPos + (width/2.0f), yPos + (height/2.0f), 0.0f); + } + else + { + float startZ = parent.Center.z - (parent.Size.z/2.0f); + float depth = parent.Size.z/columnCount; + float zPos = startZ + (column*depth) + (depth/2.0f); + + node.Center = new Vector3(xPos, 0.0f, zPos); + node.Size = new Vector3(width, 0.0f, depth); + node.TopLeft = new Vector3(xPos - (width/2.0f), 0.0f, zPos - (depth/2.0f)); + node.BottomRight = new Vector3(xPos + (width/2.0f), 0.0f, zPos + (depth/2.0f)); + } + + parent.AddChild(node); + + this.CreateChildCells(node, (cellLevelInHierarchy + 1)); + } + } + } + + /// + /// Draws the cells. + /// + private void DrawCells() + { + if ((this.CellTree != null) && (this.CellTree.RootNode != null)) + { + this.CellTree.RootNode.Draw(); + } + else + { + this.RecreateCellHierarchy = true; + } + } + + /// + /// Checks if the cell count is allowed. + /// + /// True if the cell count is allowed, false if the cell count is too large. + private bool IsCellCountAllowed() + { + int horizontalCells = 1; + int verticalCells = 1; + + foreach (Vector2 v in this.Subdivisions) + { + horizontalCells *= (int)v.x; + verticalCells *= (int)v.y; + } + + this.CellCount = horizontalCells*verticalCells; + + return (this.CellCount <= (MAX_NUMBER_OF_ALLOWED_CELLS - this.FIRST_GROUP_ID)); + } + + /// + /// Gets a list of all cell IDs the player is currently inside or nearby. + /// + /// The current position of the player. + /// A list containing all cell IDs the player is currently inside or nearby. + public List GetActiveCells(Vector3 position) + { + List activeCells = new List(0); + this.CellTree.RootNode.GetActiveCells(activeCells, this.YIsUpAxis, position); + + return activeCells; + } +} + +/// +/// Represents the tree accessible from its root node. +/// +public class CellTree +{ + /// + /// Represents the root node of the cell tree. + /// + public CellTreeNode RootNode { get; private set; } + + /// + /// Default constructor. + /// + public CellTree() + { + } + + /// + /// Constructor to define the root node. + /// + /// The root node of the tree. + public CellTree(CellTreeNode root) + { + this.RootNode = root; + } +} + +/// +/// Represents a single node of the tree. +/// +public class CellTreeNode +{ + public enum ENodeType + { + Root, + Node, + Leaf + } + + /// + /// Represents the unique ID of the cell. + /// + public byte Id; + + /// + /// Represents the center, top-left or bottom-right position of the cell + /// or the size of the cell. + /// + public Vector3 Center, Size, TopLeft, BottomRight; + + /// + /// Describes the current node type of the cell tree node. + /// + public ENodeType NodeType; + + /// + /// Reference to the parent node. + /// + public CellTreeNode Parent; + + /// + /// A list containing all child nodes. + /// + public List Childs; + + /// + /// The max distance the player can have to the center of the cell for being 'nearby'. + /// This is calculated once at runtime. + /// + private float maxDistance; + + /// + /// Default constructor. + /// + public CellTreeNode() + { + } + + /// + /// Constructor to define the ID and the node type as well as setting a parent node. + /// + /// The ID of the cell is used as the interest group. + /// The node type of the cell tree node. + /// The parent node of the cell tree node. + public CellTreeNode(byte id, ENodeType nodeType, CellTreeNode parent) + { + this.Id = id; + + this.NodeType = nodeType; + + this.Parent = parent; + } + + /// + /// Adds the given child to the node. + /// + /// The child which is added to the node. + public void AddChild(CellTreeNode child) + { + if (this.Childs == null) + { + this.Childs = new List(1); + } + + this.Childs.Add(child); + } + + /// + /// Draws the cell in the editor. + /// + public void Draw() + { +#if UNITY_EDITOR + if (this.Childs != null) + { + foreach (CellTreeNode node in this.Childs) + { + node.Draw(); + } + } + + Gizmos.color = new Color((this.NodeType == ENodeType.Root) ? 1 : 0, (this.NodeType == ENodeType.Node) ? 1 : 0, (this.NodeType == ENodeType.Leaf) ? 1 : 0); + Gizmos.DrawWireCube(this.Center, this.Size); + + UnityEditor.Handles.Label(this.Center, this.Id.ToString(), new GUIStyle() { fontStyle = FontStyle.Bold }); +#endif + } + + /// + /// Gathers all cell IDs the player is currently inside or nearby. + /// + /// The list to add all cell IDs to the player is currently inside or nearby. + /// Describes if the y-axis is used as up-axis. + /// The current position of the player. + public void GetActiveCells(List activeCells, bool yIsUpAxis, Vector3 position) + { + if (this.NodeType != ENodeType.Leaf) + { + foreach (CellTreeNode node in this.Childs) + { + node.GetActiveCells(activeCells, yIsUpAxis, position); + } + } + else + { + if (this.IsPointNearCell(yIsUpAxis, position)) + { + if (this.IsPointInsideCell(yIsUpAxis, position)) + { + activeCells.Insert(0, this.Id); + + CellTreeNode p = this.Parent; + while (p != null) + { + activeCells.Insert(0, p.Id); + + p = p.Parent; + } + } + else + { + activeCells.Add(this.Id); + } + } + } + } + + /// + /// Checks if the given point is inside the cell. + /// + /// Describes if the y-axis is used as up-axis. + /// The point to check. + /// True if the point is inside the cell, false if the point is not inside the cell. + public bool IsPointInsideCell(bool yIsUpAxis, Vector3 point) + { + if ((point.x < this.TopLeft.x) || (point.x > this.BottomRight.x)) + { + return false; + } + + if (yIsUpAxis) + { + if ((point.y >= this.TopLeft.y) && (point.y <= this.BottomRight.y)) + { + return true; + } + } + else + { + if ((point.z >= this.TopLeft.z) && (point.z <= this.BottomRight.z)) + { + return true; + } + } + + return false; + } + + /// + /// Checks if the given point is near the cell. + /// + /// Describes if the y-axis is used as up-axis. + /// The point to check. + /// True if the point is near the cell, false if the point is too far away. + public bool IsPointNearCell(bool yIsUpAxis, Vector3 point) + { + if (this.maxDistance == 0.0f) + { + this.maxDistance = (this.Size.x + this.Size.y + this.Size.z)/2.0f; + } + + return ((point - this.Center).sqrMagnitude <= (this.maxDistance*this.maxDistance)); + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/CullArea.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/CullArea.cs.meta new file mode 100644 index 0000000..9f081cd --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/CullArea.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dfb1c264fdc576442b2f42c998bed4a2 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/InRoomChat.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/InRoomChat.cs new file mode 100644 index 0000000..731de0e --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/InRoomChat.cs @@ -0,0 +1,95 @@ +using System.Collections.Generic; +using UnityEngine; +using System.Collections; + +[RequireComponent(typeof(PhotonView))] +public class InRoomChat : Photon.MonoBehaviour +{ + public Rect GuiRect = new Rect(0,0, 250,300); + public bool IsVisible = true; + public bool AlignBottom = false; + public List messages = new List(); + private string inputLine = ""; + private Vector2 scrollPos = Vector2.zero; + + public static readonly string ChatRPC = "Chat"; + + public void Start() + { + if (this.AlignBottom) + { + this.GuiRect.y = Screen.height - this.GuiRect.height; + } + } + + public void OnGUI() + { + if (!this.IsVisible || !PhotonNetwork.inRoom) + { + return; + } + + if (Event.current.type == EventType.KeyDown && (Event.current.keyCode == KeyCode.KeypadEnter || Event.current.keyCode == KeyCode.Return)) + { + if (!string.IsNullOrEmpty(this.inputLine)) + { + this.photonView.RPC("Chat", PhotonTargets.All, this.inputLine); + this.inputLine = ""; + GUI.FocusControl(""); + return; // printing the now modified list would result in an error. to avoid this, we just skip this single frame + } + else + { + GUI.FocusControl("ChatInput"); + } + } + + GUI.SetNextControlName(""); + GUILayout.BeginArea(this.GuiRect); + + scrollPos = GUILayout.BeginScrollView(scrollPos); + GUILayout.FlexibleSpace(); + for (int i = messages.Count - 1; i >= 0; i--) + { + GUILayout.Label(messages[i]); + } + GUILayout.EndScrollView(); + + GUILayout.BeginHorizontal(); + GUI.SetNextControlName("ChatInput"); + inputLine = GUILayout.TextField(inputLine); + if (GUILayout.Button("Send", GUILayout.ExpandWidth(false))) + { + this.photonView.RPC("Chat", PhotonTargets.All, this.inputLine); + this.inputLine = ""; + GUI.FocusControl(""); + } + GUILayout.EndHorizontal(); + GUILayout.EndArea(); + } + + [PunRPC] + public void Chat(string newLine, PhotonMessageInfo mi) + { + string senderName = "anonymous"; + + if (mi.sender != null) + { + if (!string.IsNullOrEmpty(mi.sender.NickName)) + { + senderName = mi.sender.NickName; + } + else + { + senderName = "player " + mi.sender.ID; + } + } + + this.messages.Add(senderName +": " + newLine); + } + + public void AddLine(string newLine) + { + this.messages.Add(newLine); + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/InRoomChat.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/InRoomChat.cs.meta new file mode 100644 index 0000000..b704ebe --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/InRoomChat.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 043bd8ce63fde7c41a9ee103809fa981 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/InputToEvent.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/InputToEvent.cs new file mode 100644 index 0000000..0ef7bd7 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/InputToEvent.cs @@ -0,0 +1,118 @@ +using UnityEngine; + +/// +/// Utility component to forward mouse or touch input to clicked gameobjects. +/// Calls OnPress, OnClick and OnRelease methods on "first" game object. +/// +public class InputToEvent : MonoBehaviour +{ + private GameObject lastGo; + public static Vector3 inputHitPos; + public bool DetectPointedAtGameObject; + public static GameObject goPointedAt { get; private set; } + + private Vector2 pressedPosition = Vector2.zero; + private Vector2 currentPos = Vector2.zero; + public bool Dragging; + + private Camera m_Camera; + + public Vector2 DragVector + { + get { return this.Dragging ? this.currentPos - this.pressedPosition : Vector2.zero; } + } + + private void Start() + { + this.m_Camera = GetComponent(); + } + + // Update is called once per frame + private void Update() + { + if (this.DetectPointedAtGameObject) + { + goPointedAt = RaycastObject(Input.mousePosition); + } + + if (Input.touchCount > 0) + { + Touch touch = Input.GetTouch(0); + this.currentPos = touch.position; + + if (touch.phase == TouchPhase.Began) + { + Press(touch.position); + } + else if (touch.phase == TouchPhase.Ended) + { + Release(touch.position); + } + + return; + } + + this.currentPos = Input.mousePosition; + if (Input.GetMouseButtonDown(0)) + { + Press(Input.mousePosition); + } + if (Input.GetMouseButtonUp(0)) + { + Release(Input.mousePosition); + } + + if (Input.GetMouseButtonDown(1)) + { + this.pressedPosition = Input.mousePosition; + this.lastGo = RaycastObject(this.pressedPosition); + if (this.lastGo != null) + { + this.lastGo.SendMessage("OnPressRight", SendMessageOptions.DontRequireReceiver); + } + } + } + + + private void Press(Vector2 screenPos) + { + this.pressedPosition = screenPos; + this.Dragging = true; + + this.lastGo = RaycastObject(screenPos); + if (this.lastGo != null) + { + this.lastGo.SendMessage("OnPress", SendMessageOptions.DontRequireReceiver); + } + } + + private void Release(Vector2 screenPos) + { + if (this.lastGo != null) + { + GameObject currentGo = RaycastObject(screenPos); + if (currentGo == this.lastGo) + { + this.lastGo.SendMessage("OnClick", SendMessageOptions.DontRequireReceiver); + } + + this.lastGo.SendMessage("OnRelease", SendMessageOptions.DontRequireReceiver); + this.lastGo = null; + } + + this.pressedPosition = Vector2.zero; + this.Dragging = false; + } + + private GameObject RaycastObject(Vector2 screenPos) + { + RaycastHit info; + if (Physics.Raycast(this.m_Camera.ScreenPointToRay(screenPos), out info, 200)) + { + inputHitPos = info.point; + return info.collider.gameObject; + } + + return null; + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/InputToEvent.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/InputToEvent.cs.meta new file mode 100644 index 0000000..d80b061 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/InputToEvent.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4fdde8222e647b24b816eec3ad67ff32 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/ManualPhotonViewAllocator.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/ManualPhotonViewAllocator.cs new file mode 100644 index 0000000..d02e432 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/ManualPhotonViewAllocator.cs @@ -0,0 +1,31 @@ +using UnityEngine; +using System.Collections; + +[RequireComponent(typeof(PhotonView))] +public class ManualPhotonViewAllocator : MonoBehaviour +{ + public GameObject Prefab; + + public void AllocateManualPhotonView() + { + PhotonView pv = this.gameObject.GetPhotonView(); + if (pv == null) + { + Debug.LogError("Can't do manual instantiation without PhotonView component."); + return; + } + + int viewID = PhotonNetwork.AllocateViewID(); + pv.RPC("InstantiateRpc", PhotonTargets.AllBuffered, viewID); + } + + [PunRPC] + public void InstantiateRpc(int viewID) + { + GameObject go = GameObject.Instantiate(Prefab, InputToEvent.inputHitPos + new Vector3(0, 5f, 0), Quaternion.identity) as GameObject; + go.GetPhotonView().viewID = viewID; + + OnClickDestroy ocd = go.GetComponent(); + ocd.DestroyByRpc = true; + } +} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/ManualPhotonViewAllocator.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/ManualPhotonViewAllocator.cs.meta new file mode 100644 index 0000000..96ab252 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/ManualPhotonViewAllocator.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2668418d0a8c6804facdeca6e5fc6d98 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/MoveByKeys.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/MoveByKeys.cs new file mode 100644 index 0000000..551af7c --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/MoveByKeys.cs @@ -0,0 +1,85 @@ +using UnityEngine; + +/// +/// Very basic component to move a GameObject by WASD and Space. +/// +/// +/// Requires a PhotonView. +/// Disables itself on GameObjects that are not owned on Start. +/// +/// Speed affects movement-speed. +/// JumpForce defines how high the object "jumps". +/// JumpTimeout defines after how many seconds you can jump again. +/// +[RequireComponent(typeof (PhotonView))] +public class MoveByKeys : Photon.MonoBehaviour +{ + public float Speed = 10f; + public float JumpForce = 200f; + public float JumpTimeout = 0.5f; + + private bool isSprite; + private float jumpingTime; + private Rigidbody body; + private Rigidbody2D body2d; + + public void Start() + { + //enabled = photonView.isMine; + this.isSprite = (GetComponent() != null); + + this.body2d = GetComponent(); + this.body = GetComponent(); + } + + + // Update is called once per frame + public void FixedUpdate() + { + if (!photonView.isMine) + { + return; + } + + if ((Input.GetAxisRaw("Horizontal") < -0.1f) || (Input.GetAxisRaw("Horizontal") > 0.1f)) + { + transform.position += Vector3.right * (Speed * Time.deltaTime) * Input.GetAxisRaw("Horizontal"); + } + + // jumping has a simple "cooldown" time but you could also jump in the air + if (this.jumpingTime <= 0.0f) + { + if (this.body != null || this.body2d != null) + { + // obj has a Rigidbody and can jump (AddForce) + if (Input.GetKey(KeyCode.Space)) + { + this.jumpingTime = this.JumpTimeout; + + Vector2 jump = Vector2.up*this.JumpForce; + if (this.body2d != null) + { + this.body2d.AddForce(jump); + } + else if (this.body != null) + { + this.body.AddForce(jump); + } + } + } + } + else + { + this.jumpingTime -= Time.deltaTime; + } + + // 2d objects can't be moved in 3d "forward" + if (!this.isSprite) + { + if ((Input.GetAxisRaw("Vertical") < -0.1f) || (Input.GetAxisRaw("Vertical") > 0.1f)) + { + transform.position += Vector3.forward * (Speed * Time.deltaTime) * Input.GetAxisRaw("Vertical"); + } + } + } +} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/MoveByKeys.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/MoveByKeys.cs.meta new file mode 100644 index 0000000..63447da --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/MoveByKeys.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 99b4daedc5e674a429acdf1e77da6a55 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/NetworkCullingHandler.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/NetworkCullingHandler.cs new file mode 100644 index 0000000..c492e78 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/NetworkCullingHandler.cs @@ -0,0 +1,218 @@ +using System.Collections.Generic; +using UnityEngine; + +/// +/// Handles the network culling. +/// +[RequireComponent(typeof(PhotonView))] +public class NetworkCullingHandler : MonoBehaviour, IPunObservable +{ + #region VARIABLES + + private int orderIndex; + + private CullArea cullArea; + + private List previousActiveCells, activeCells; + + private PhotonView pView; + + private Vector3 lastPosition, currentPosition; + + #endregion + + #region UNITY_FUNCTIONS + + /// + /// Gets references to the PhotonView component and the cull area game object. + /// + private void OnEnable() + { + if (this.pView == null) + { + this.pView = GetComponent(); + + if (!this.pView.isMine) + { + return; + } + } + + if (this.cullArea == null) + { + this.cullArea = FindObjectOfType(); + } + + this.previousActiveCells = new List(0); + this.activeCells = new List(0); + + this.currentPosition = this.lastPosition = transform.position; + } + + /// + /// Initializes the right interest group or prepares the permanent change of the interest group of the PhotonView component. + /// + private void Start() + { + if (!this.pView.isMine) + { + return; + } + + if (PhotonNetwork.inRoom) + { + if (this.cullArea.NumberOfSubdivisions == 0) + { + this.pView.group = this.cullArea.FIRST_GROUP_ID; + + PhotonNetwork.SetInterestGroups(this.cullArea.FIRST_GROUP_ID, true); + } + else + { + // This is used to continuously update the active group. + this.pView.ObservedComponents.Add(this); + } + } + } + + /// + /// Checks if the player has moved previously and updates the interest groups if necessary. + /// + private void Update() + { + if (!this.pView.isMine) + { + return; + } + + this.lastPosition = this.currentPosition; + this.currentPosition = transform.position; + + // This is a simple position comparison of the current and the previous position. + // When using Network Culling in a bigger project keep in mind that there might + // be more transform-related options, e.g. the rotation, or other options to check. + if (this.currentPosition != this.lastPosition) + { + if (this.HaveActiveCellsChanged()) + { + this.UpdateInterestGroups(); + } + } + } + + /// + /// Drawing informations. + /// + private void OnGUI() + { + if (!this.pView.isMine) + { + return; + } + + string subscribedAndActiveCells = "Inside cells:\n"; + string subscribedCells = "Subscribed cells:\n"; + + for (int index = 0; index < this.activeCells.Count; ++index) + { + if (index <= this.cullArea.NumberOfSubdivisions) + { + subscribedAndActiveCells += this.activeCells[index] + " | "; + } + + subscribedCells += this.activeCells[index] + " | "; + } + GUI.Label(new Rect(20.0f, Screen.height - 120.0f, 200.0f, 40.0f), "PhotonView Group: " + this.pView.group + "", new GUIStyle() { alignment = TextAnchor.UpperLeft, fontSize = 16 }); + GUI.Label(new Rect(20.0f, Screen.height - 100.0f, 200.0f, 40.0f), "" + subscribedAndActiveCells + "", new GUIStyle() { alignment = TextAnchor.UpperLeft, fontSize = 16 }); + GUI.Label(new Rect(20.0f, Screen.height - 60.0f, 200.0f, 40.0f), "" + subscribedCells + "", new GUIStyle() { alignment = TextAnchor.UpperLeft, fontSize = 16 }); + } + + #endregion + + /// + /// Checks if the previously active cells have changed. + /// + /// True if the previously active cells have changed and false otherwise. + private bool HaveActiveCellsChanged() + { + if (this.cullArea.NumberOfSubdivisions == 0) + { + return false; + } + + this.previousActiveCells = new List(this.activeCells); + this.activeCells = this.cullArea.GetActiveCells(transform.position); + + // If the player leaves the area we insert the whole area itself as an active cell. + // This can be removed if it is sure that the player is not able to leave the area. + while (this.activeCells.Count <= this.cullArea.NumberOfSubdivisions) + { + this.activeCells.Add(this.cullArea.FIRST_GROUP_ID); + } + + if (this.activeCells.Count != this.previousActiveCells.Count) + { + return true; + } + + if (this.activeCells[this.cullArea.NumberOfSubdivisions] != this.previousActiveCells[this.cullArea.NumberOfSubdivisions]) + { + return true; + } + + return false; + } + + /// + /// Unsubscribes from old and subscribes to new interest groups. + /// + private void UpdateInterestGroups() + { + List disable = new List(0); + + foreach (byte groupId in this.previousActiveCells) + { + if (!this.activeCells.Contains(groupId)) + { + disable.Add(groupId); + } + } + + PhotonNetwork.SetInterestGroups(disable.ToArray(), this.activeCells.ToArray()); + } + + #region IPunObservable implementation + + /// + /// This time OnPhotonSerializeView is not used to send or receive any kind of data. + /// It is used to change the currently active group of the PhotonView component, making it work together with PUN more directly. + /// Keep in mind that this function is only executed, when there is at least one more player in the room. + /// + public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) + { + // If the player leaves the area we insert the whole area itself as an active cell. + // This can be removed if it is sure that the player is not able to leave the area. + while (this.activeCells.Count <= this.cullArea.NumberOfSubdivisions) + { + this.activeCells.Add(this.cullArea.FIRST_GROUP_ID); + } + + if (this.cullArea.NumberOfSubdivisions == 1) + { + this.orderIndex = (++this.orderIndex%this.cullArea.SUBDIVISION_FIRST_LEVEL_ORDER.Length); + this.pView.group = this.activeCells[this.cullArea.SUBDIVISION_FIRST_LEVEL_ORDER[this.orderIndex]]; + } + else if (this.cullArea.NumberOfSubdivisions == 2) + { + this.orderIndex = (++this.orderIndex%this.cullArea.SUBDIVISION_SECOND_LEVEL_ORDER.Length); + this.pView.group = this.activeCells[this.cullArea.SUBDIVISION_SECOND_LEVEL_ORDER[this.orderIndex]]; + } + else if (this.cullArea.NumberOfSubdivisions == 3) + { + this.orderIndex = (++this.orderIndex%this.cullArea.SUBDIVISION_THIRD_LEVEL_ORDER.Length); + this.pView.group = this.activeCells[this.cullArea.SUBDIVISION_THIRD_LEVEL_ORDER[this.orderIndex]]; + } + } + + #endregion +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/NetworkCullingHandler.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/NetworkCullingHandler.cs.meta new file mode 100644 index 0000000..74b7441 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/NetworkCullingHandler.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 84db789113d4b01418c1becb128c4561 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnClickDestroy.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnClickDestroy.cs new file mode 100644 index 0000000..80153f1 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnClickDestroy.cs @@ -0,0 +1,45 @@ +using UnityEngine; +using System.Collections; + +/// +/// Implements OnClick to destroy the GameObject it's attached to. Optionally a RPC is sent to do this. +/// +/// +/// Using an RPC to Destroy a GameObject allows any player to Destroy a GameObject. But it might cause errors. +/// RPC and the Instantiated GameObject are not fully linked on the server. One might stick in the server witout +/// the other. +/// +/// A buffered RPC gets cleaned up when the sending player leaves the room. This means, the RPC gets lost. +/// +/// Vice versus, a GameObject Instantiate might get cleaned up when the creating player leaves a room. +/// This way, the GameObject that a RPC targets might become lost. +/// +/// It makes sense to test those cases. Many are not breaking errors and you just have to be aware of them. +/// +/// Gets OnClick() calls by InputToEvent class attached to a camera. +/// +[RequireComponent(typeof(PhotonView))] +public class OnClickDestroy : Photon.MonoBehaviour +{ + public bool DestroyByRpc; + + public void OnClick() + { + if (!DestroyByRpc) + { + PhotonNetwork.Destroy(this.gameObject); + } + else + { + this.photonView.RPC("DestroyRpc", PhotonTargets.AllBuffered); + } + } + + [PunRPC] + public IEnumerator DestroyRpc() + { + GameObject.Destroy(this.gameObject); + yield return 0; // if you allow 1 frame to pass, the object's OnDestroy() method gets called and cleans up references. + PhotonNetwork.UnAllocateViewID(this.photonView.viewID); + } +} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnClickDestroy.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnClickDestroy.cs.meta new file mode 100644 index 0000000..f091f18 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnClickDestroy.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9dab7328ba500e944a99d62065fba6c0 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnClickInstantiate.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnClickInstantiate.cs new file mode 100644 index 0000000..30f4308 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnClickInstantiate.cs @@ -0,0 +1,42 @@ +using UnityEngine; +using System.Collections; + +public class OnClickInstantiate : MonoBehaviour +{ + public GameObject Prefab; + public int InstantiateType; + private string[] InstantiateTypeNames = {"Mine", "Scene"}; + + public bool showGui; + + void OnClick() + { + if (!PhotonNetwork.inRoom) + { + // only use PhotonNetwork.Instantiate while in a room. + return; + } + + switch (InstantiateType) + { + case 0: + PhotonNetwork.Instantiate(Prefab.name, InputToEvent.inputHitPos + new Vector3(0, 5f, 0), Quaternion.identity, 0); + break; + case 1: + PhotonNetwork.InstantiateSceneObject(Prefab.name, InputToEvent.inputHitPos + new Vector3(0, 5f, 0), Quaternion.identity, 0, null); + break; + } + } + + void OnGUI() + { + if (showGui) + { + GUILayout.BeginArea(new Rect(Screen.width - 180, 0, 180, 50)); + InstantiateType = GUILayout.Toolbar(InstantiateType, InstantiateTypeNames); + GUILayout.EndArea(); + } + } + + +} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnClickInstantiate.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnClickInstantiate.cs.meta new file mode 100644 index 0000000..1150759 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnClickInstantiate.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9b79a9b62449de940a073364858c3f9b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnJoinedInstantiate.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnJoinedInstantiate.cs new file mode 100644 index 0000000..c460354 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnJoinedInstantiate.cs @@ -0,0 +1,33 @@ +using UnityEngine; +using System.Collections; + +public class OnJoinedInstantiate : MonoBehaviour +{ + public Transform SpawnPosition; + public float PositionOffset = 2.0f; + public GameObject[] PrefabsToInstantiate; // set in inspector + + public void OnJoinedRoom() + { + if (this.PrefabsToInstantiate != null) + { + foreach (GameObject o in this.PrefabsToInstantiate) + { + Debug.Log("Instantiating: " + o.name); + + Vector3 spawnPos = Vector3.up; + if (this.SpawnPosition != null) + { + spawnPos = this.SpawnPosition.position; + } + + Vector3 random = Random.insideUnitSphere; + random.y = 0; + random = random.normalized; + Vector3 itempos = spawnPos + this.PositionOffset * random; + + PhotonNetwork.Instantiate(o.name, itempos, Quaternion.identity, 0); + } + } + } +} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnJoinedInstantiate.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnJoinedInstantiate.cs.meta new file mode 100644 index 0000000..5b4fba0 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnJoinedInstantiate.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ed3b5dcba7bf9114cb13fc59e0a71f55 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnStartDelete.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnStartDelete.cs new file mode 100644 index 0000000..1ef64de --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnStartDelete.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +/// This component will destroy the GameObject it is attached to (in Start()). +public class OnStartDelete : MonoBehaviour +{ + // Use this for initialization + void Start() + { + Destroy(this.gameObject); + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnStartDelete.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnStartDelete.cs.meta new file mode 100644 index 0000000..4f4d47a --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/OnStartDelete.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f8d56a54ae062da4a87516fb994f4e30 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer.meta new file mode 100644 index 0000000..473b84a --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 1722c5a334af441bdab62c776237bdc8 +folderAsset: yes +timeCreated: 1525372512 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/Editor.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/Editor.meta new file mode 100644 index 0000000..957c94f --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/Editor.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 3d7b7901a130c44c59e737feadfbd6ae +folderAsset: yes +timeCreated: 1525372512 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/Editor/PlayerRoomIndexingInspector.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/Editor/PlayerRoomIndexingInspector.cs new file mode 100644 index 0000000..6662799 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/Editor/PlayerRoomIndexingInspector.cs @@ -0,0 +1,73 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Part of: Photon Unity Utilities, +// +// +// Custom inspector for PlayerRoomIndexing +// +// developer@exitgames.com +// -------------------------------------------------------------------------------------------------------------------- + + +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using UnityEditor; + +namespace ExitGames.UtilityScripts +{ + [CustomEditor(typeof(PlayerRoomIndexing))] + public class PlayerRoomIndexingInspector : Editor { + + PlayerRoomIndexing _target; + int localPlayerIndex; + + void OnEnable () { + _target = (PlayerRoomIndexing)target; + _target.OnRoomIndexingChanged += RefreshData; + } + + void OnDisable () { + _target = (PlayerRoomIndexing)target; + _target.OnRoomIndexingChanged -= RefreshData; + } + + public override void OnInspectorGUI() + { + _target = (PlayerRoomIndexing)target; + + _target.OnRoomIndexingChanged += RefreshData; + + if (PhotonNetwork.inRoom) + { + EditorGUILayout.LabelField("Player Index", "PhotonPlayer ID"); + if (_target.PlayerIds != null) + { + int index = 0; + foreach(int ID in _target.PlayerIds) + { + GUI.enabled = ID!=0; + EditorGUILayout.LabelField("Player " +index + + (PhotonNetwork.player.ID==ID?" - You -":"") + + (PhotonNetwork.masterClient.ID==ID?" Master":"") + , ID==0?"n/a":PhotonPlayer.Find(ID).ToStringFull()); + GUI.enabled = true; + index++; + } + } + }else{ + GUILayout.Label("Room Indexing only works when localPlayer is inside a room"); + } + } + + /// + /// force repaint fo the inspector, else we would not see the new data in the inspector. + /// This is better then doing it in OnInspectorGUI too many times per frame for no need + /// + void RefreshData() + { + Repaint(); + } + + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/Editor/PlayerRoomIndexingInspector.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/Editor/PlayerRoomIndexingInspector.cs.meta new file mode 100644 index 0000000..7cb1083 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/Editor/PlayerRoomIndexingInspector.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d6590f39353bf4efdb3b14691166135f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/Editor/PunTeamsInspector.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/Editor/PunTeamsInspector.cs new file mode 100644 index 0000000..bba3b2b --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/Editor/PunTeamsInspector.cs @@ -0,0 +1,57 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Part of: Photon Unity Utilities, +// +// +// Custom inspector for PunTeams +// +// developer@exitgames.com +// -------------------------------------------------------------------------------------------------------------------- + +using System; +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using UnityEditor; + +namespace ExitGames.UtilityScripts +{ + [CustomEditor(typeof(PunTeams))] + public class PunTeamsInspector : Editor { + + + Dictionary _Foldouts ; + + public override void OnInspectorGUI() + { + if (_Foldouts==null) + { + _Foldouts = new Dictionary(); + } + + if (PunTeams.PlayersPerTeam!=null) + { + foreach (KeyValuePair> _pair in PunTeams.PlayersPerTeam) + { + if (!_Foldouts.ContainsKey(_pair.Key)) + { + _Foldouts[_pair.Key] = true; + } + + _Foldouts[_pair.Key] = EditorGUILayout.Foldout(_Foldouts[_pair.Key],"Team "+_pair.Key +" ("+_pair.Value.Count+")"); + + if (_Foldouts[_pair.Key]) + { + EditorGUI.indentLevel++; + foreach(PhotonPlayer _player in _pair.Value) + { + EditorGUILayout.LabelField("",_player.ToString() + (PhotonNetwork.player==_player?" - You -":"")); + } + EditorGUI.indentLevel--; + } + + } + } + } + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/Editor/PunTeamsInspector.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/Editor/PunTeamsInspector.cs.meta new file mode 100644 index 0000000..ff6b7e0 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/Editor/PunTeamsInspector.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7dcadaf22424c4f5d82f4d48c3b8097f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/PlayerRoomIndexing.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/PlayerRoomIndexing.cs new file mode 100644 index 0000000..48e7714 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/PlayerRoomIndexing.cs @@ -0,0 +1,287 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Part of: Photon Unity Utilities, +// +// +// Assign numbers to Players in a room. Uses Room custom Properties +// +// developer@exitgames.com +// -------------------------------------------------------------------------------------------------------------------- + +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +using Photon; +using ExitGames.Client.Photon; +using Hashtable = ExitGames.Client.Photon.Hashtable; + + + +namespace ExitGames.UtilityScripts +{ + /// + /// Implements consistent indexing in a room/game with help of room properties. Access them by PhotonPlayer.GetRoomIndex() extension. + /// + /// + /// indexing ranges from 0 to the maximum number of Players. + /// indexing remains for the player while in room. + /// If a Player is indexed 2 and player indexes 1 leaves, index 1 become vacant and will assigned to the future player joining (the first available vacant index is assigned when joining) + /// + public class PlayerRoomIndexing : PunBehaviour + { + + #region Public Properties + + /// + /// The instance. EntryPoint to query about Room Indexing. + /// + public static PlayerRoomIndexing instance; + + /// + /// OnRoomIndexingChanged delegate. Use + /// + public delegate void RoomIndexingChanged(); + /// + /// Called everytime the room Indexing was updated. Use this for discrete updates. Always better than brute force calls every frame. + /// + public RoomIndexingChanged OnRoomIndexingChanged; + + /// Defines the room custom property name to use for room player indexing tracking. + public const string RoomPlayerIndexedProp = "PlayerIndexes"; + + /// + /// Cached list of Player indexes. You can use .GetRoomIndex() + /// + /// The player identifiers. + public int[] PlayerIds + { + get { + return _playerIds; + } + } + + #endregion + + + + #region Private Properties + + int[] _playerIds; + object _indexes; + Dictionary _indexesLUT; + List _indexesPool; + PhotonPlayer _p; + + #endregion + + #region MonoBehaviours methods + + public void Awake() + { + if (instance!=null) + { + Debug.LogError("Existing instance of PlayerRoomIndexing found. Only One instance is required at the most. Please correct and have only one at any time."); + } + instance = this; + + // check if we are already in room, likely if component was added at runtime or came late into scene + if (PhotonNetwork.room!=null) + { + SanitizeIndexing(true); + } + } + + #endregion + + + #region PunBehavior Overrides + + public override void OnJoinedRoom() + { + if (PhotonNetwork.isMasterClient) + { + AssignIndex(PhotonNetwork.player); + }else{ + RefreshData(); + } + } + + public override void OnLeftRoom() + { + RefreshData(); + } + + public override void OnPhotonPlayerConnected (PhotonPlayer newPlayer) + { + if (PhotonNetwork.isMasterClient) + { + AssignIndex(newPlayer); + } + + } + + public override void OnPhotonPlayerDisconnected(PhotonPlayer otherPlayer) + { + if (PhotonNetwork.isMasterClient) + { + UnAssignIndex(otherPlayer); + } + } + + public override void OnPhotonCustomRoomPropertiesChanged(Hashtable propertiesThatChanged) + { + if (propertiesThatChanged.ContainsKey(PlayerRoomIndexing.RoomPlayerIndexedProp)) + { + RefreshData(); + } + } + + + public override void OnMasterClientSwitched(PhotonPlayer newMasterClient) + { + if (PhotonNetwork.isMasterClient) + { + SanitizeIndexing(); + } + } + + #endregion + + /// Get the room index of a particular PhotonPlayer. You can also use .GetRoomIndex() + /// persistent index in room. -1 for none + public int GetRoomIndex( PhotonPlayer player) + { + if (_indexesLUT!=null && _indexesLUT.ContainsKey(player.ID)) + { + return _indexesLUT[player.ID]; + } + return -1; + } + + + /// + /// Sanitizes the indexing incase a player join while masterclient was changed and missed it. + /// + void SanitizeIndexing(bool forceIndexing = false) + { + if (!forceIndexing && !PhotonNetwork.isMasterClient) + { + return; + } + + if (PhotonNetwork.room==null) + { + return; + } + + // attempt to access index props. + Dictionary _indexesLUT_local = new Dictionary(); + if(PhotonNetwork.room.CustomProperties.TryGetValue(PlayerRoomIndexing.RoomPlayerIndexedProp, out _indexes)) + { + _indexesLUT_local = _indexes as Dictionary; + } + + // check if we need to assign + if (_indexesLUT_local.Count != PhotonNetwork.room.PlayerCount) + { + foreach(PhotonPlayer _p in PhotonNetwork.playerList) + { + if (!_indexesLUT_local.ContainsKey(_p.ID)) + { + // Debug.Log("Sanitizing Index for "+_p); + AssignIndex(_p); + } + } + + } + + } + + /// + /// Internal call Refresh the cached data and call the OnRoomIndexingChanged delegate. + /// + void RefreshData() + { + if (PhotonNetwork.room!=null) + { + _playerIds = new int[PhotonNetwork.room.MaxPlayers]; + if (PhotonNetwork.room.CustomProperties.TryGetValue(PlayerRoomIndexing.RoomPlayerIndexedProp, out _indexes)) + { + _indexesLUT = _indexes as Dictionary; + + foreach(KeyValuePair _entry in _indexesLUT) + { + //Debug.Log("Entry; "+_entry.Key+":"+_entry.Value); + _p = PhotonPlayer.Find(_entry.Key); + _playerIds[_entry.Value] = _p.ID; + } + } + }else{ + _playerIds = new int[0]; + } + + + if (OnRoomIndexingChanged!=null) OnRoomIndexingChanged(); + } + + + void AssignIndex(PhotonPlayer player) + { + if (PhotonNetwork.room.CustomProperties.TryGetValue(PlayerRoomIndexing.RoomPlayerIndexedProp, out _indexes)) + { + _indexesLUT = _indexes as Dictionary; + + }else{ + _indexesLUT = new Dictionary(); + } + + List _indexesPool = new List( new bool[PhotonNetwork.room.MaxPlayers] ); + foreach(KeyValuePair _entry in _indexesLUT) + { + _indexesPool[_entry.Value] = true; + } + + _indexesLUT[player.ID] = Mathf.Max (0,_indexesPool.IndexOf(false)); + + PhotonNetwork.room.SetCustomProperties(new Hashtable() {{PlayerRoomIndexing.RoomPlayerIndexedProp, _indexesLUT}}); + + RefreshData(); + } + + + void UnAssignIndex(PhotonPlayer player) + { + if (PhotonNetwork.room.CustomProperties.TryGetValue(PlayerRoomIndexing.RoomPlayerIndexedProp, out _indexes)) + { + _indexesLUT = _indexes as Dictionary; + + _indexesLUT.Remove(player.ID); + PhotonNetwork.room.SetCustomProperties(new Hashtable() {{PlayerRoomIndexing.RoomPlayerIndexedProp, _indexesLUT}}); + }else{ + + } + + RefreshData(); + } + + } + + /// Extension used for PlayerRoomIndexing and PhotonPlayer class. + public static class PlayerRoomIndexingExtensions + { + /// Extension for PhotonPlayer class to wrap up access to the player's custom property. + /// persistent index in room. -1 for no indexing + public static int GetRoomIndex(this PhotonPlayer player) + { + if (PlayerRoomIndexing.instance == null) + { + Debug.LogError("Missing PlayerRoomIndexing Component in Scene"); + return -1; + } + return PlayerRoomIndexing.instance.GetRoomIndex(player); + } + + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/PlayerRoomIndexing.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/PlayerRoomIndexing.cs.meta new file mode 100644 index 0000000..2911e8b --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PhotonPlayer/PlayerRoomIndexing.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f5a097d1ab84b464395a16e9a7bb35b1 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PickupItem.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PickupItem.cs new file mode 100644 index 0000000..8413ba1 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PickupItem.cs @@ -0,0 +1,213 @@ +using System.Collections.Generic; +using UnityEngine; +using System.Collections; +using Hashtable = ExitGames.Client.Photon.Hashtable; + +/// +/// Makes a scene object pickup-able. Needs a PhotonView which belongs to the scene. +/// +/// Includes a OnPhotonSerializeView implementation that +[RequireComponent(typeof(PhotonView))] +public class PickupItem : Photon.MonoBehaviour, IPunObservable +{ + ///Enables you to define a timeout when the picked up item should re-spawn at the same place it was before. + /// + /// Set in Inspector per GameObject! The value in code is just the default. + /// + /// If you don't want an item to respawn, set SecondsBeforeRespawn == 0. + /// If an item does not respawn, it could be consumed or carried around and dropped somewhere else. + /// + /// A respawning item should stick to a fixed position. It should not be observed at all (in any PhotonView). + /// It can only be consumed and can't be dropped somewhere else (cause that would double the item). + /// + /// This script uses PunRespawn() as RPC and as method that gets called by Invoke() after a timeout. + /// No matter if the item respawns timed or by Drop, that method makes sure (temporary) owner and other status-values + /// are being re-set. + /// + public float SecondsBeforeRespawn = 2; + + /// The most likely trigger to pick up an item. Set in inspector! + /// Edit the collider and set collision masks to avoid pickups by random objects. + public bool PickupOnTrigger; + + /// If the pickup item is currently yours. Interesting in OnPickedUp(PickupItem item). + public bool PickupIsMine; + + /// GameObject to send an event "OnPickedUp(PickupItem item)" to. + /// + /// Implement OnPickedUp(PickupItem item) {} in some script on the linked game object. + /// The item will be "this" and item.PickupIsMine will help you to find if this pickup was done by "this player". + /// + public MonoBehaviour OnPickedUpCall; + + + // these values are internally used. they are public for debugging only + + /// If this client sent a pickup. To avoid sending multiple pickup requests before reply is there. + public bool SentPickup; + + /// Timestamp when to respawn the item (compared to PhotonNetwork.time). + public double TimeOfRespawn; // needed when we want to update new players when a PickupItem respawns + + /// + public int ViewID { get { return this.photonView.viewID; } } + + public static HashSet DisabledPickupItems = new HashSet(); + + + public void OnTriggerEnter(Collider other) + { + // we only call Pickup() if "our" character collides with this PickupItem. + // note: if you "position" remote characters by setting their translation, triggers won't be hit. + + PhotonView otherpv = other.GetComponent(); + if (this.PickupOnTrigger && otherpv != null && otherpv.isMine) + { + //Debug.Log("OnTriggerEnter() calls Pickup()."); + this.Pickup(); + } + } + + + + public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) + { + // read the description in SecondsBeforeRespawn + + if (stream.isWriting && SecondsBeforeRespawn <= 0) + { + stream.SendNext(this.gameObject.transform.position); + } + else + { + // this will directly apply the last received position for this PickupItem. No smoothing. Usually not needed though. + Vector3 lastIncomingPos = (Vector3)stream.ReceiveNext(); + this.gameObject.transform.position = lastIncomingPos; + } + } + + + public void Pickup() + { + if (this.SentPickup) + { + // skip sending more pickups until the original pickup-RPC got back to this client + return; + } + + this.SentPickup = true; + this.photonView.RPC("PunPickup", PhotonTargets.AllViaServer); + } + + + /// Makes use of RPC PunRespawn to drop an item (sent through server for all). + public void Drop() + { + if (this.PickupIsMine) + { + this.photonView.RPC("PunRespawn", PhotonTargets.AllViaServer); + } + } + + /// Makes use of RPC PunRespawn to drop an item (sent through server for all). + public void Drop(Vector3 newPosition) + { + if (this.PickupIsMine) + { + this.photonView.RPC("PunRespawn", PhotonTargets.AllViaServer, newPosition); + } + } + + + [PunRPC] + public void PunPickup(PhotonMessageInfo msgInfo) + { + // when this client's RPC gets executed, this client no longer waits for a sent pickup and can try again + if (msgInfo.sender.IsLocal) this.SentPickup = false; + + + // In this solution, picked up items are disabled. They can't be picked up again this way, etc. + // You could check "active" first, if you're not interested in failed pickup-attempts. + if (!this.gameObject.GetActive()) + { + // optional logging: + Debug.Log("Ignored PU RPC, cause item is inactive. " + this.gameObject + " SecondsBeforeRespawn: " + SecondsBeforeRespawn + " TimeOfRespawn: " + this.TimeOfRespawn + " respawn in future: " + (TimeOfRespawn > PhotonNetwork.time)); + return; // makes this RPC being ignored + } + + + // if the RPC isn't ignored by now, this is a successful pickup. this might be "my" pickup and we should do a callback + this.PickupIsMine = msgInfo.sender.IsLocal; + + // call the method OnPickedUp(PickupItem item) if a GameObject was defined as callback target + if (this.OnPickedUpCall != null) + { + // you could also skip callbacks for items that are not picked up by this client by using: if (this.PickupIsMine) + this.OnPickedUpCall.SendMessage("OnPickedUp", this); + } + + + // setup a respawn (or none, if the item has to be dropped) + if (SecondsBeforeRespawn <= 0) + { + this.PickedUp(0.0f); // item doesn't auto-respawn. must be dropped + } + else + { + // how long it is until this item respanws, depends on the pickup time and the respawn time + double timeSinceRpcCall = (PhotonNetwork.time - msgInfo.timestamp); + double timeUntilRespawn = SecondsBeforeRespawn - timeSinceRpcCall; + + //Debug.Log("msg timestamp: " + msgInfo.timestamp + " time until respawn: " + timeUntilRespawn); + + if (timeUntilRespawn > 0) + { + this.PickedUp((float)timeUntilRespawn); + } + } + } + + internal void PickedUp(float timeUntilRespawn) + { + // this script simply disables the GO for a while until it respawns. + this.gameObject.SetActive(false); + PickupItem.DisabledPickupItems.Add(this); + this.TimeOfRespawn = 0; + + if (timeUntilRespawn > 0) + { + this.TimeOfRespawn = PhotonNetwork.time + timeUntilRespawn; + Invoke("PunRespawn", timeUntilRespawn); + } + } + + + [PunRPC] + internal void PunRespawn(Vector3 pos) + { + Debug.Log("PunRespawn with Position."); + this.PunRespawn(); + this.gameObject.transform.position = pos; + } + + [PunRPC] + internal void PunRespawn() + { + #if DEBUG + // debugging: in some cases, the respawn is "late". it's unclear why! just be aware of this. + double timeDiffToRespawnTime = PhotonNetwork.time - this.TimeOfRespawn; + if (timeDiffToRespawnTime > 0.1f) Debug.LogWarning("Spawn time is wrong by: " + timeDiffToRespawnTime + " (this is not an error. you just need to be aware of this.)"); + #endif + + + // if this is called from another thread, we might want to do this in OnEnable() instead of here (depends on Invoke's implementation) + PickupItem.DisabledPickupItems.Remove(this); + this.TimeOfRespawn = 0; + this.PickupIsMine = false; + + if (this.gameObject != null) + { + this.gameObject.SetActive(true); + } + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PickupItem.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PickupItem.cs.meta new file mode 100644 index 0000000..a3dbbcb --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PickupItem.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 49a81ce8037f41540ac70f51e9a19d7f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PickupItemSimple.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PickupItemSimple.cs new file mode 100644 index 0000000..a738daf --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PickupItemSimple.cs @@ -0,0 +1,85 @@ +using UnityEngine; +using System.Collections; + +/// +/// Makes a scene object pickup-able. Needs a PhotonView which belongs to the scene. +/// +[RequireComponent(typeof(PhotonView))] +public class PickupItemSimple : Photon.MonoBehaviour +{ + public float SecondsBeforeRespawn = 2; + public bool PickupOnCollide; + public bool SentPickup; + + public void OnTriggerEnter(Collider other) + { + // we only call Pickup() if "our" character collides with this PickupItem. + // note: if you "position" remote characters by setting their translation, triggers won't be hit. + + PhotonView otherpv = other.GetComponent(); + if (this.PickupOnCollide && otherpv != null && otherpv.isMine) + { + //Debug.Log("OnTriggerEnter() calls Pickup()."); + this.Pickup(); + } + } + + public void Pickup() + { + if (this.SentPickup) + { + // skip sending more pickups until the original pickup-RPC got back to this client + return; + } + + this.SentPickup = true; + this.photonView.RPC("PunPickupSimple", PhotonTargets.AllViaServer); + } + + [PunRPC] + public void PunPickupSimple(PhotonMessageInfo msgInfo) + { + // one of the messages might be ours + // note: you could check "active" first, if you're not interested in your own, failed pickup-attempts. + if (this.SentPickup && msgInfo.sender.IsLocal) + { + if (this.gameObject.GetActive()) + { + // picked up! yay. + } + else + { + // pickup failed. too late (compared to others) + } + } + + this.SentPickup = false; + + if (!this.gameObject.GetActive()) + { + Debug.Log("Ignored PU RPC, cause item is inactive. " + this.gameObject); + return; + } + + + // how long it is until this item respanws, depends on the pickup time and the respawn time + double timeSinceRpcCall = (PhotonNetwork.time - msgInfo.timestamp); + float timeUntilRespawn = SecondsBeforeRespawn - (float)timeSinceRpcCall; + //Debug.Log("msg timestamp: " + msgInfo.timestamp + " time until respawn: " + timeUntilRespawn); + + if (timeUntilRespawn > 0) + { + // this script simply disables the GO for a while until it respawns. + this.gameObject.SetActive(false); + Invoke("RespawnAfter", timeUntilRespawn); + } + } + + public void RespawnAfter() + { + if (this.gameObject != null) + { + this.gameObject.SetActive(true); + } + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PickupItemSimple.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PickupItemSimple.cs.meta new file mode 100644 index 0000000..4adcc55 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PickupItemSimple.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7dcf9a2d8dc276745bb51228cc019f52 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PickupItemSyncer.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PickupItemSyncer.cs new file mode 100644 index 0000000..0723f8a --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PickupItemSyncer.cs @@ -0,0 +1,170 @@ +using System.Collections.Generic; +using UnityEngine; +using System.Collections; +using System; +using Hashtable = ExitGames.Client.Photon.Hashtable; + +/// Finds out which PickupItems are not spawned at the moment and send this to new players. +/// Attach this component to a single GameObject in the scene, not to all PickupItems. +[RequireComponent(typeof(PhotonView))] +public class PickupItemSyncer : Photon.MonoBehaviour +{ + public bool IsWaitingForPickupInit; + private const float TimeDeltaToIgnore = 0.2f; + + + public void OnPhotonPlayerConnected(PhotonPlayer newPlayer) + { + if (PhotonNetwork.isMasterClient) + { + this.SendPickedUpItems(newPlayer); + } + } + + public void OnJoinedRoom() + { + Debug.Log("Joined Room. isMasterClient: " + PhotonNetwork.isMasterClient + " id: " + PhotonNetwork.player.ID); + // this client joined the room. let's see if there are players and if someone has to inform us about pickups + this.IsWaitingForPickupInit = !PhotonNetwork.isMasterClient; + + if (PhotonNetwork.playerList.Length >= 2) + { + this.Invoke("AskForPickupItemSpawnTimes", 2.0f); + } + } + + + public void AskForPickupItemSpawnTimes() + { + if (this.IsWaitingForPickupInit) + { + if (PhotonNetwork.playerList.Length < 2) + { + Debug.Log("Cant ask anyone else for PickupItem spawn times."); + this.IsWaitingForPickupInit = false; + return; + } + + + // find a another player (than the master, who likely is gone) to ask for the PickupItem spawn times + PhotonPlayer nextPlayer = PhotonNetwork.masterClient.GetNext(); + if (nextPlayer == null || nextPlayer.Equals(PhotonNetwork.player)) + { + nextPlayer = PhotonNetwork.player.GetNext(); + //Debug.Log("This player is the Master's next. Asking this client's 'next' player: " + ((nextPlayer != null) ? nextPlayer.ToStringFull() : "")); + } + + if (nextPlayer != null && !nextPlayer.Equals(PhotonNetwork.player)) + { + this.photonView.RPC("RequestForPickupItems", nextPlayer); + + // you could restart this invoke and try to find another player after 4 seconds. but after a while it doesnt make a difference anymore + //this.Invoke("AskForPickupItemSpawnTimes", 2.0f); + } + else + { + Debug.Log("No player left to ask"); + this.IsWaitingForPickupInit = false; + } + } + } + + [PunRPC] + [Obsolete("Use RequestForPickupItems(PhotonMessageInfo msgInfo) with corrected typing instead.")] + public void RequestForPickupTimes(PhotonMessageInfo msgInfo) + { + RequestForPickupItems(msgInfo); + } + + [PunRPC] + public void RequestForPickupItems(PhotonMessageInfo msgInfo) + { + if (msgInfo.sender == null) + { + Debug.LogError("Unknown player asked for PickupItems"); + return; + } + + SendPickedUpItems(msgInfo.sender); + } + + /// Summarizes all PickupItem ids and spawn times for new players. Calls RPC "PickupItemInit". + /// The player to send the pickup times to. It's a targetted RPC. + private void SendPickedUpItems(PhotonPlayer targetPlayer) + { + if (targetPlayer == null) + { + Debug.LogWarning("Cant send PickupItem spawn times to unknown targetPlayer."); + return; + } + + double now = PhotonNetwork.time; + double soon = now + TimeDeltaToIgnore; + + + PickupItem[] items = new PickupItem[PickupItem.DisabledPickupItems.Count]; + PickupItem.DisabledPickupItems.CopyTo(items); + + List valuesToSend = new List(items.Length * 2); + for (int i = 0; i < items.Length; i++) + { + PickupItem pi = items[i]; + if (pi.SecondsBeforeRespawn <= 0) + { + valuesToSend.Add(pi.ViewID); + valuesToSend.Add((float)0.0f); + } + else + { + double timeUntilRespawn = pi.TimeOfRespawn - PhotonNetwork.time; + if (pi.TimeOfRespawn > soon) + { + // the respawn of this item is not "immediately", so we include it in the message "these items are not active" for the new player + Debug.Log(pi.ViewID + " respawn: " + pi.TimeOfRespawn + " timeUntilRespawn: " + timeUntilRespawn + " (now: " + PhotonNetwork.time + ")"); + valuesToSend.Add(pi.ViewID); + valuesToSend.Add((float)timeUntilRespawn); + } + } + } + + Debug.Log("Sent count: " + valuesToSend.Count + " now: " + now); + this.photonView.RPC("PickupItemInit", targetPlayer, PhotonNetwork.time, valuesToSend.ToArray()); + } + + + [PunRPC] + public void PickupItemInit(double timeBase, float[] inactivePickupsAndTimes) + { + this.IsWaitingForPickupInit = false; + + // if there are no inactive pickups, the sender will send a list of 0 items. this is not a problem... + for (int i = 0; i < inactivePickupsAndTimes.Length / 2; i++) + { + int arrayIndex = i*2; + int viewIdOfPickup = (int)inactivePickupsAndTimes[arrayIndex]; + float timeUntilRespawnBasedOnTimeBase = inactivePickupsAndTimes[arrayIndex + 1]; + + + PhotonView view = PhotonView.Find(viewIdOfPickup); + PickupItem pi = view.GetComponent(); + + if (timeUntilRespawnBasedOnTimeBase <= 0) + { + pi.PickedUp(0.0f); + } + else + { + double timeOfRespawn = timeUntilRespawnBasedOnTimeBase + timeBase; + + Debug.Log(view.viewID + " respawn: " + timeOfRespawn + " timeUntilRespawnBasedOnTimeBase:" + timeUntilRespawnBasedOnTimeBase + " SecondsBeforeRespawn: " + pi.SecondsBeforeRespawn); + double timeBeforeRespawn = timeOfRespawn - PhotonNetwork.time; + if (timeUntilRespawnBasedOnTimeBase <= 0) + { + timeBeforeRespawn = 0.0f; + } + + pi.PickedUp((float) timeBeforeRespawn); + } + } + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PickupItemSyncer.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PickupItemSyncer.cs.meta new file mode 100644 index 0000000..57643c5 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PickupItemSyncer.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d6826804b93f54045a69115648b2a143 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PointedAtGameObjectInfo.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PointedAtGameObjectInfo.cs new file mode 100644 index 0000000..90a5f12 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PointedAtGameObjectInfo.cs @@ -0,0 +1,19 @@ +using UnityEngine; +using System.Collections; + +[RequireComponent(typeof(InputToEvent))] +public class PointedAtGameObjectInfo : MonoBehaviour +{ + void OnGUI() + { + if (InputToEvent.goPointedAt != null) + { + PhotonView pv = InputToEvent.goPointedAt.GetPhotonView(); + if (pv != null) + { + GUI.Label(new Rect(Input.mousePosition.x + 5, Screen.height - Input.mousePosition.y - 15, 300, 30), string.Format("ViewID {0} {1}{2}", pv.viewID, (pv.isSceneView) ? "scene " : "", (pv.isMine) ? "mine" : "owner: " + pv.ownerId)); + } + } + } + +} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PointedAtGameObjectInfo.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PointedAtGameObjectInfo.cs.meta new file mode 100644 index 0000000..9ffbb4f --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PointedAtGameObjectInfo.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e6262dd9a9b078c4e8cbd47495aa6d23 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PunPlayerScores.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PunPlayerScores.cs new file mode 100644 index 0000000..dd50863 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PunPlayerScores.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using UnityEngine; +using System.Collections; +using Hashtable = ExitGames.Client.Photon.Hashtable; + +public class PunPlayerScores : MonoBehaviour +{ + public const string PlayerScoreProp = "score"; +} + +public static class ScoreExtensions +{ + public static void SetScore(this PhotonPlayer player, int newScore) + { + Hashtable score = new Hashtable(); // using PUN's implementation of Hashtable + score[PunPlayerScores.PlayerScoreProp] = newScore; + + player.SetCustomProperties(score); // this locally sets the score and will sync it in-game asap. + } + + public static void AddScore(this PhotonPlayer player, int scoreToAddToCurrent) + { + int current = player.GetScore(); + current = current + scoreToAddToCurrent; + + Hashtable score = new Hashtable(); // using PUN's implementation of Hashtable + score[PunPlayerScores.PlayerScoreProp] = current; + + player.SetCustomProperties(score); // this locally sets the score and will sync it in-game asap. + } + + public static int GetScore(this PhotonPlayer player) + { + object score; + if (player.CustomProperties.TryGetValue(PunPlayerScores.PlayerScoreProp, out score)) + { + return (int) score; + } + + return 0; + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PunPlayerScores.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PunPlayerScores.cs.meta new file mode 100644 index 0000000..5904915 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PunPlayerScores.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 6b4df3943860f1d45bfe232053a58d80 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PunTeams.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PunTeams.cs new file mode 100644 index 0000000..e9e4b23 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PunTeams.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using ExitGames.Client.Photon; +using UnityEngine; +using Hashtable = ExitGames.Client.Photon.Hashtable; + + +/// +/// Implements teams in a room/game with help of player properties. Access them by PhotonPlayer.GetTeam extension. +/// +/// +/// Teams are defined by enum Team. Change this to get more / different teams. +/// There are no rules when / if you can join a team. You could add this in JoinTeam or something. +/// +public class PunTeams : MonoBehaviour +{ + /// Enum defining the teams available. First team should be neutral (it's the default value any field of this enum gets). + public enum Team : byte {none, red, blue}; + + /// The main list of teams with their player-lists. Automatically kept up to date. + /// Note that this is static. Can be accessed by PunTeam.PlayersPerTeam. You should not modify this. + public static Dictionary> PlayersPerTeam; + + /// Defines the player custom property name to use for team affinity of "this" player. + public const string TeamPlayerProp = "team"; + + + #region Events by Unity and Photon + + public void Start() + { + PlayersPerTeam = new Dictionary>(); + Array enumVals = Enum.GetValues(typeof (Team)); + foreach (var enumVal in enumVals) + { + PlayersPerTeam[(Team)enumVal] = new List(); + } + } + + public void OnDisable() + { + PlayersPerTeam = new Dictionary>(); + } + + /// Needed to update the team lists when joining a room. + /// Called by PUN. See enum PhotonNetworkingMessage for an explanation. + public void OnJoinedRoom() + { + + this.UpdateTeams(); + } + + public void OnLeftRoom() + { + Start(); + } + + /// Refreshes the team lists. It could be a non-team related property change, too. + /// Called by PUN. See enum PhotonNetworkingMessage for an explanation. + public void OnPhotonPlayerPropertiesChanged(object[] playerAndUpdatedProps) + { + this.UpdateTeams(); + } + + public void OnPhotonPlayerDisconnected(PhotonPlayer otherPlayer) + { + this.UpdateTeams(); + } + + public void OnPhotonPlayerConnected(PhotonPlayer newPlayer) + { + this.UpdateTeams(); + } + + #endregion + + + public void UpdateTeams() + { + Array enumVals = Enum.GetValues(typeof(Team)); + foreach (var enumVal in enumVals) + { + PlayersPerTeam[(Team)enumVal].Clear(); + } + + for (int i = 0; i < PhotonNetwork.playerList.Length; i++) + { + PhotonPlayer player = PhotonNetwork.playerList[i]; + Team playerTeam = player.GetTeam(); + PlayersPerTeam[playerTeam].Add(player); + } + } +} + +/// Extension used for PunTeams and PhotonPlayer class. Wraps access to the player's custom property. +public static class TeamExtensions +{ + /// Extension for PhotonPlayer class to wrap up access to the player's custom property. + /// PunTeam.Team.none if no team was found (yet). + public static PunTeams.Team GetTeam(this PhotonPlayer player) + { + object teamId; + if (player.CustomProperties.TryGetValue(PunTeams.TeamPlayerProp, out teamId)) + { + return (PunTeams.Team)teamId; + } + + return PunTeams.Team.none; + } + + /// Switch that player's team to the one you assign. + /// Internally checks if this player is in that team already or not. Only team switches are actually sent. + /// + /// + public static void SetTeam(this PhotonPlayer player, PunTeams.Team team) + { + if (!PhotonNetwork.connectedAndReady) + { + Debug.LogWarning("JoinTeam was called in state: " + PhotonNetwork.connectionStateDetailed + ". Not connectedAndReady."); + return; + } + + PunTeams.Team currentTeam = player.GetTeam(); + if (currentTeam != team) + { + player.SetCustomProperties(new Hashtable() {{PunTeams.TeamPlayerProp, (byte) team}}); + } + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PunTeams.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PunTeams.cs.meta new file mode 100644 index 0000000..9dffb8a --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PunTeams.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 6587c8104d7524f4280d0a68dd779f27 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PunTurnManager.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PunTurnManager.cs new file mode 100644 index 0000000..ee6015d --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PunTurnManager.cs @@ -0,0 +1,411 @@ +// ---------------------------------------------------------------------------- +// +// PhotonNetwork Framework for Unity - Copyright (C) 2016 Exit Games GmbH +// +// +// Manager for Turn Based games, using PUN +// +// developer@exitgames.com +// ---------------------------------------------------------------------------- + + +using System; +using System.Collections.Generic; +using ExitGames.Client.Photon; +using Photon; +using UnityEngine; +using ExitGames = ExitGames.Client.Photon.Hashtable; + +/// +/// Pun turnBased Game manager. +/// Provides an Interface (IPunTurnManagerCallbacks) for the typical turn flow and logic, between players +/// Provides Extensions for PhotonPlayer, Room and RoomInfo to feature dedicated api for TurnBased Needs +/// +public class PunTurnManager : PunBehaviour +{ + /// + /// Wraps accessing the "turn" custom properties of a room. + /// + /// The turn index + public int Turn + { + get { return PhotonNetwork.room.GetTurn(); } + private set { + + _isOverCallProcessed = false; + + PhotonNetwork.room.SetTurn(value, true); + } + } + + + /// + /// The duration of the turn in seconds. + /// + public float TurnDuration = 20f; + + /// + /// Gets the elapsed time in the current turn in seconds + /// + /// The elapsed time in the turn. + public float ElapsedTimeInTurn + { + get { return ((float)(PhotonNetwork.ServerTimestamp - PhotonNetwork.room.GetTurnStart()))/1000.0f; } + } + + + /// + /// Gets the remaining seconds for the current turn. Ranges from 0 to TurnDuration + /// + /// The remaining seconds fo the current turn + public float RemainingSecondsInTurn + { + get { return Mathf.Max(0f,this.TurnDuration - this.ElapsedTimeInTurn); } + } + + + /// + /// Gets a value indicating whether the turn is completed by all. + /// + /// true if this turn is completed by all; otherwise, false. + public bool IsCompletedByAll + { + get { return PhotonNetwork.room != null && Turn > 0 && this.finishedPlayers.Count == PhotonNetwork.room.PlayerCount; } + } + + /// + /// Gets a value indicating whether the current turn is finished by me. + /// + /// true if the current turn is finished by me; otherwise, false. + public bool IsFinishedByMe + { + get { return this.finishedPlayers.Contains(PhotonNetwork.player); } + } + + /// + /// Gets a value indicating whether the current turn is over. That is the ElapsedTimeinTurn is greater or equal to the TurnDuration + /// + /// true if the current turn is over; otherwise, false. + public bool IsOver + { + get { return this.RemainingSecondsInTurn <= 0f; } + } + + /// + /// The turn manager listener. Set this to your own script instance to catch Callbacks + /// + public IPunTurnManagerCallbacks TurnManagerListener; + + + /// + /// The finished players. + /// + private readonly HashSet finishedPlayers = new HashSet(); + + /// + /// The turn manager event offset event message byte. Used internaly for defining data in Room Custom Properties + /// + public const byte TurnManagerEventOffset = 0; + /// + /// The Move event message byte. Used internaly for saving data in Room Custom Properties + /// + public const byte EvMove = 1 + TurnManagerEventOffset; + /// + /// The Final Move event message byte. Used internaly for saving data in Room Custom Properties + /// + public const byte EvFinalMove = 2 + TurnManagerEventOffset; + + // keep track of message calls + private bool _isOverCallProcessed = false; + + #region MonoBehaviour CallBack + /// + /// Register for Event Call from PhotonNetwork. + /// + void Start() + { + PhotonNetwork.OnEventCall = OnEvent; + } + + void Update() + { + if (Turn > 0 && this.IsOver && !_isOverCallProcessed) + { + _isOverCallProcessed = true; + this.TurnManagerListener.OnTurnTimeEnds(this.Turn); + } + + } + + + #endregion + + + /// + /// Tells the TurnManager to begins a new turn. + /// + public void BeginTurn() + { + Turn = this.Turn + 1; // note: this will set a property in the room, which is available to the other players. + } + + + /// + /// Call to send an action. Optionally finish the turn, too. + /// The move object can be anything. Try to optimize though and only send the strict minimum set of information to define the turn move. + /// + /// + /// + public void SendMove(object move, bool finished) + { + if (IsFinishedByMe) + { + UnityEngine.Debug.LogWarning("Can't SendMove. Turn is finished by this player."); + return; + } + + // along with the actual move, we have to send which turn this move belongs to + Hashtable moveHt = new Hashtable(); + moveHt.Add("turn", Turn); + moveHt.Add("move", move); + + byte evCode = (finished) ? EvFinalMove : EvMove; + PhotonNetwork.RaiseEvent(evCode, moveHt, true, new RaiseEventOptions() { CachingOption = EventCaching.AddToRoomCache }); + if (finished) + { + PhotonNetwork.player.SetFinishedTurn(Turn); + } + + // the server won't send the event back to the origin (by default). to get the event, call it locally + // (note: the order of events might be mixed up as we do this locally) + OnEvent(evCode, moveHt, PhotonNetwork.player.ID); + } + + /// + /// Gets if the player finished the current turn. + /// + /// true, if player finished the current turn, false otherwise. + /// The Player to check for + public bool GetPlayerFinishedTurn(PhotonPlayer player) + { + if (player != null && this.finishedPlayers != null && this.finishedPlayers.Contains(player)) + { + return true; + } + + return false; + } + + #region Callbacks + + /// + /// Called by PhotonNetwork.OnEventCall registration + /// + /// Event code. + /// Content. + /// Sender identifier. + public void OnEvent(byte eventCode, object content, int senderId) + { + PhotonPlayer sender = PhotonPlayer.Find(senderId); + switch (eventCode) + { + case EvMove: + { + Hashtable evTable = content as Hashtable; + int turn = (int)evTable["turn"]; + object move = evTable["move"]; + this.TurnManagerListener.OnPlayerMove(sender, turn, move); + + break; + } + case EvFinalMove: + { + Hashtable evTable = content as Hashtable; + int turn = (int)evTable["turn"]; + object move = evTable["move"]; + + if (turn == this.Turn) + { + this.finishedPlayers.Add(sender); + + this.TurnManagerListener.OnPlayerFinished(sender, turn, move); + + } + + if (IsCompletedByAll) + { + this.TurnManagerListener.OnTurnCompleted(this.Turn); + } + break; + } + } + } + + /// + /// Called by PhotonNetwork + /// + /// Properties that changed. + public override void OnPhotonCustomRoomPropertiesChanged(Hashtable propertiesThatChanged) + { + + // Debug.Log("OnPhotonCustomRoomPropertiesChanged: "+propertiesThatChanged.ToStringFull()); + + if (propertiesThatChanged.ContainsKey("Turn")) + { + _isOverCallProcessed = false; + this.finishedPlayers.Clear(); + this.TurnManagerListener.OnTurnBegins(this.Turn); + } + } + + #endregion +} + + +public interface IPunTurnManagerCallbacks +{ + /// + /// Called the turn begins event. + /// + /// Turn Index + void OnTurnBegins(int turn); + + /// + /// Called when a turn is completed (finished by all players) + /// + /// Turn Index + void OnTurnCompleted(int turn); + + /// + /// Called when a player moved (but did not finish the turn) + /// + /// Player reference + /// Turn Index + /// Move Object data + void OnPlayerMove(PhotonPlayer player, int turn, object move); + + /// + /// When a player finishes a turn (includes the action/move of that player) + /// + /// Player reference + /// Turn index + /// Move Object data + void OnPlayerFinished(PhotonPlayer player, int turn, object move); + + + /// + /// Called when a turn completes due to a time constraint (timeout for a turn) + /// + /// Turn index + void OnTurnTimeEnds(int turn); +} + + +public static class TurnExtensions +{ + /// + /// currently ongoing turn number + /// + public static readonly string TurnPropKey = "Turn"; + + /// + /// start (server) time for currently ongoing turn (used to calculate end) + /// + public static readonly string TurnStartPropKey = "TStart"; + + /// + /// Finished Turn of Actor (followed by number) + /// + public static readonly string FinishedTurnPropKey = "FToA"; + + /// + /// Sets the turn. + /// + /// Room reference + /// Turn index + /// If set to true set start time. + public static void SetTurn(this Room room, int turn, bool setStartTime = false) + { + if (room == null || room.CustomProperties == null) + { + return; + } + + Hashtable turnProps = new Hashtable(); + turnProps[TurnPropKey] = turn; + if (setStartTime) + { + turnProps[TurnStartPropKey] = PhotonNetwork.ServerTimestamp; + } + + room.SetCustomProperties(turnProps); + } + + /// + /// Gets the current turn from a RoomInfo + /// + /// The turn index + /// RoomInfo reference + public static int GetTurn(this RoomInfo room) + { + if (room == null || room.CustomProperties == null || !room.CustomProperties.ContainsKey(TurnPropKey)) + { + return 0; + } + + return (int)room.CustomProperties[TurnPropKey]; + } + + + /// + /// Returns the start time when the turn began. This can be used to calculate how long it's going on. + /// + /// The turn start. + /// Room. + public static int GetTurnStart(this RoomInfo room) + { + if (room == null || room.CustomProperties == null || !room.CustomProperties.ContainsKey(TurnStartPropKey)) + { + return 0; + } + + return (int)room.CustomProperties[TurnStartPropKey]; + } + + /// + /// gets the player's finished turn (from the ROOM properties) + /// + /// The finished turn index + /// Player reference + public static int GetFinishedTurn(this PhotonPlayer player) + { + Room room = PhotonNetwork.room; + if (room == null || room.CustomProperties == null || !room.CustomProperties.ContainsKey(TurnPropKey)) + { + return 0; + } + + string propKey = FinishedTurnPropKey + player.ID; + return (int)room.CustomProperties[propKey]; + } + + /// + /// Sets the player's finished turn (in the ROOM properties) + /// + /// Player Reference + /// Turn Index + public static void SetFinishedTurn(this PhotonPlayer player, int turn) + { + Room room = PhotonNetwork.room; + if (room == null || room.CustomProperties == null) + { + return; + } + + string propKey = FinishedTurnPropKey + player.ID; + Hashtable finishedTurnProp = new Hashtable(); + finishedTurnProp[propKey] = turn; + + room.SetCustomProperties(finishedTurnProp); + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PunTurnManager.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PunTurnManager.cs.meta new file mode 100644 index 0000000..0076919 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/PunTurnManager.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1a1b3bda60e9e804f87fd1e5d20a885a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/QuitOnEscapeOrBack.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/QuitOnEscapeOrBack.cs new file mode 100644 index 0000000..d1020ae --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/QuitOnEscapeOrBack.cs @@ -0,0 +1,14 @@ +using UnityEngine; +using System.Collections; + +public class QuitOnEscapeOrBack : MonoBehaviour +{ + private void Update() + { + // "back" button of phone equals "Escape". quit app if that's pressed + if (Input.GetKeyDown(KeyCode.Escape)) + { + Application.Quit(); + } + } +} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/QuitOnEscapeOrBack.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/QuitOnEscapeOrBack.cs.meta new file mode 100644 index 0000000..6133070 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/QuitOnEscapeOrBack.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1fbabafd914a48f4eb6108d8d8f43d29 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/ShowStatusWhenConnecting.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/ShowStatusWhenConnecting.cs new file mode 100644 index 0000000..8f2dc55 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/ShowStatusWhenConnecting.cs @@ -0,0 +1,45 @@ +using UnityEngine; +using System.Collections; + +public class ShowStatusWhenConnecting : MonoBehaviour +{ + public GUISkin Skin; + + void OnGUI() + { + if( Skin != null ) + { + GUI.skin = Skin; + } + + float width = 400; + float height = 100; + + Rect centeredRect = new Rect( ( Screen.width - width ) / 2, ( Screen.height - height ) / 2, width, height ); + + GUILayout.BeginArea( centeredRect, GUI.skin.box ); + { + GUILayout.Label( "Connecting" + GetConnectingDots(), GUI.skin.customStyles[ 0 ] ); + GUILayout.Label( "Status: " + PhotonNetwork.connectionStateDetailed ); + } + GUILayout.EndArea(); + + if( PhotonNetwork.inRoom ) + { + enabled = false; + } + } + + string GetConnectingDots() + { + string str = ""; + int numberOfDots = Mathf.FloorToInt( Time.timeSinceLevelLoad * 3f % 4 ); + + for( int i = 0; i < numberOfDots; ++i ) + { + str += " ."; + } + + return str; + } +} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/ShowStatusWhenConnecting.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/ShowStatusWhenConnecting.cs.meta new file mode 100644 index 0000000..a6a7b83 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/ShowStatusWhenConnecting.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 321c592dfcb49cd458c8f2cbe497513d +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/SmoothSyncMovement.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/SmoothSyncMovement.cs new file mode 100644 index 0000000..cc49e49 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/SmoothSyncMovement.cs @@ -0,0 +1,54 @@ +using UnityEngine; +using System.Collections; + +[RequireComponent(typeof(PhotonView))] +public class SmoothSyncMovement : Photon.MonoBehaviour, IPunObservable +{ + public float SmoothingDelay = 5; + public void Awake() + { + bool observed = false; + foreach (Component observedComponent in this.photonView.ObservedComponents) + { + if (observedComponent == this) + { + observed = true; + break; + } + } + if (!observed) + { + Debug.LogWarning(this + " is not observed by this object's photonView! OnPhotonSerializeView() in this class won't be used."); + } + } + + public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) + { + if (stream.isWriting) + { + //We own this player: send the others our data + stream.SendNext(transform.position); + stream.SendNext(transform.rotation); + } + else + { + //Network player, receive data + correctPlayerPos = (Vector3)stream.ReceiveNext(); + correctPlayerRot = (Quaternion)stream.ReceiveNext(); + } + } + + private Vector3 correctPlayerPos = Vector3.zero; //We lerp towards this + private Quaternion correctPlayerRot = Quaternion.identity; //We lerp towards this + + public void Update() + { + if (!photonView.isMine) + { + //Update remote player (smooth this, this looks good, at the cost of some accuracy) + transform.position = Vector3.Lerp(transform.position, correctPlayerPos, Time.deltaTime * this.SmoothingDelay); + transform.rotation = Quaternion.Lerp(transform.rotation, correctPlayerRot, Time.deltaTime * this.SmoothingDelay); + } + } + +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/SmoothSyncMovement.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/SmoothSyncMovement.cs.meta new file mode 100644 index 0000000..ed3764a --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/SmoothSyncMovement.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 35144820bcc25444bb8f0fd767d9423e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/SupportLogger.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/SupportLogger.cs new file mode 100644 index 0000000..a6906b0 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/SupportLogger.cs @@ -0,0 +1,109 @@ +using System.Text; +using UnityEngine; +using System.Collections; +using ExitGames.Client.Photon; + +public class SupportLogger : MonoBehaviour +{ + public bool LogTrafficStats = true; + + public void Start() + { + GameObject go = GameObject.Find("PunSupportLogger"); + if (go == null) + { + go = new GameObject("PunSupportLogger"); + DontDestroyOnLoad(go); + SupportLogging sl = go.AddComponent(); + sl.LogTrafficStats = this.LogTrafficStats; + } + } +} + +public class SupportLogging : MonoBehaviour +{ + public bool LogTrafficStats; + + public void Start() + { + if (LogTrafficStats) + { + this.InvokeRepeating("LogStats", 10, 10); + } + } + + + protected void OnApplicationPause(bool pause) + { + Debug.Log("SupportLogger OnApplicationPause: " + pause + " connected: " + PhotonNetwork.connected); + } + + public void OnApplicationQuit() + { + this.CancelInvoke(); + } + + public void LogStats() + { + if (this.LogTrafficStats) + { + Debug.Log("SupportLogger " + PhotonNetwork.NetworkStatisticsToString()); + } + } + + private void LogBasics() + { + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("SupportLogger Info: PUN {0}: ", PhotonNetwork.versionPUN); + + sb.AppendFormat("AppID: {0}*** GameVersion: {1} PeerId: {2} ", PhotonNetwork.networkingPeer.AppId.Substring(0, 8), PhotonNetwork.networkingPeer.AppVersion, PhotonNetwork.networkingPeer.PeerID); + sb.AppendFormat("Server: {0}. Region: {1} ", PhotonNetwork.ServerAddress, PhotonNetwork.networkingPeer.CloudRegion); + sb.AppendFormat("HostType: {0} ", PhotonNetwork.PhotonServerSettings.HostType); + + + Debug.Log(sb.ToString()); + } + + + public void OnConnectedToPhoton() + { + Debug.Log("SupportLogger OnConnectedToPhoton()."); + this.LogBasics(); + + if (LogTrafficStats) + { + PhotonNetwork.NetworkStatisticsEnabled = true; + } + } + + public void OnFailedToConnectToPhoton(DisconnectCause cause) + { + Debug.Log("SupportLogger OnFailedToConnectToPhoton("+cause+")."); + this.LogBasics(); + } + + public void OnJoinedLobby() + { + Debug.Log("SupportLogger OnJoinedLobby(" + PhotonNetwork.lobby + ")."); + } + + public void OnJoinedRoom() + { + Debug.Log("SupportLogger OnJoinedRoom(" + PhotonNetwork.room + "). " + PhotonNetwork.lobby + " GameServer:" + PhotonNetwork.ServerAddress); + } + + public void OnCreatedRoom() + { + Debug.Log("SupportLogger OnCreatedRoom(" + PhotonNetwork.room + "). " + PhotonNetwork.lobby + " GameServer:" + PhotonNetwork.ServerAddress); + } + + public void OnLeftRoom() + { + Debug.Log("SupportLogger OnLeftRoom()."); + } + + public void OnDisconnectedFromPhoton() + { + Debug.Log("SupportLogger OnDisconnectedFromPhoton()."); + } +} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/SupportLogger.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/SupportLogger.cs.meta new file mode 100644 index 0000000..7e8b7cc --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/SupportLogger.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9b61c60d38639484ebbd7f2100dd3d08 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/TimeKeeper.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/TimeKeeper.cs new file mode 100644 index 0000000..8cc124a --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/TimeKeeper.cs @@ -0,0 +1,62 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Exit Games GmbH, 2012 +// +// +// TimeKeeper Helper. See class description. +// +// developer@exitgames.com +// -------------------------------------------------------------------------------------------------------------------- + +namespace ExitGames.Client.DemoParticle +{ + using System; + + /// + /// A utility class that turns it's ShouldExecute property to true after a set interval time has passed. + /// + /// + /// TimeKeepers can be useful to execute tasks in a certain interval within a game loop (integrating a recurring task into a certain thread). + /// + /// An interval can be overridden, when you set ShouldExecute to true. + /// Call Reset after execution of whatever you do to re-enable the TimeKeeper (ShouldExecute becomes false until interval passed). + /// Being based on Environment.TickCount, this is not very precise but cheap. + /// + public class TimeKeeper + { + private int lastExecutionTime = Environment.TickCount; + private bool shouldExecute; + + /// Interval in which ShouldExecute should be true (and something is executed). + public int Interval { get; set; } + + /// A disabled TimeKeeper never turns ShouldExecute to true. Reset won't affect IsEnabled! + public bool IsEnabled { get; set; } + + /// Turns true of the time interval has passed (after reset or creation) or someone set ShouldExecute manually. + /// Call Reset to start a new interval. + public bool ShouldExecute + { + get { return (this.IsEnabled && (this.shouldExecute || (Environment.TickCount - this.lastExecutionTime > this.Interval))); } + set { this.shouldExecute = value; } + } + + /// + /// Creates a new, enabled TimeKeeper and sets it's interval. + /// + /// + public TimeKeeper(int interval) + { + this.IsEnabled = true; + this.Interval = interval; + } + + /// ShouldExecute becomes false and the time interval is refreshed for next execution. + /// Does not affect IsEnabled. + public void Reset() + { + this.shouldExecute = false; + this.lastExecutionTime = Environment.TickCount; + } + } +} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/TimeKeeper.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/TimeKeeper.cs.meta new file mode 100644 index 0000000..5acc98e --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/TimeKeeper.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 11b45bfcb19ad694bb6f199fb97642ce +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI.meta new file mode 100644 index 0000000..99fe724 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: af1b526e222a644b3a8cf8c3742879ab +folderAsset: yes +timeCreated: 1525372512 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI/ButtonInsideScrollList.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI/ButtonInsideScrollList.cs new file mode 100644 index 0000000..36fe137 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI/ButtonInsideScrollList.cs @@ -0,0 +1,55 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Part of: Photon Unity Utilities, +// +// +// Used on Buttons inside UI lists to prevent scrollRect parent to scroll when down on buttons. +// +// developer@exitgames.com +// -------------------------------------------------------------------------------------------------------------------- + + +using UnityEngine; +using System.Collections; +using UnityEngine.EventSystems; +using UnityEngine.UI; + +namespace ExitGames.UtilityScripts +{ + /// + /// Button inside scroll list will stop scrolling ability of scrollRect container, so that when pressing down on a button and draggin up and down will not affect scrolling. + /// this doesn't do anything if no scrollRect component found in Parent Hierarchy. + /// + public class ButtonInsideScrollList : MonoBehaviour, IPointerDownHandler, IPointerUpHandler { + + ScrollRect scrollRect; + + // Use this for initialization + void Start () { + scrollRect = GetComponentInParent(); + } + + #region IPointerDownHandler implementation + void IPointerDownHandler.OnPointerDown (PointerEventData eventData) + { + if (scrollRect !=null) + { + scrollRect.StopMovement(); + scrollRect.enabled = false; + } + } + #endregion + + #region IPointerUpHandler implementation + + void IPointerUpHandler.OnPointerUp (PointerEventData eventData) + { + if (scrollRect !=null && !scrollRect.enabled) + { + scrollRect.enabled = true; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI/ButtonInsideScrollList.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI/ButtonInsideScrollList.cs.meta new file mode 100644 index 0000000..9e18870 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI/ButtonInsideScrollList.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e0e8b381f2c05442ca5c01638958156a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI/TextButtonTransition.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI/TextButtonTransition.cs new file mode 100644 index 0000000..d4e293c --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI/TextButtonTransition.cs @@ -0,0 +1,45 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// +// +// Use this on Button texts to have some color transition on the text as well without corrupting button's behaviour. +// +// developer@exitgames.com +// -------------------------------------------------------------------------------------------------------------------- + + +using UnityEngine; +using System.Collections; +using UnityEngine.EventSystems; +using UnityEngine.UI; + +namespace ExitGames.UtilityScripts +{ + + /// + /// Use this on Button texts to have some color transition on the text as well without corrupting button's behaviour. + /// + [RequireComponent(typeof(Text))] + public class TextButtonTransition : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler { + + Text _text; + + public Color NormalColor= Color.white; + public Color HoverColor = Color.black; + + public void Awake() + { + _text = GetComponent(); + } + + public void OnPointerEnter(PointerEventData eventData) + { + _text.color = HoverColor; + } + + public void OnPointerExit(PointerEventData eventData) + { + _text.color = NormalColor; + } + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI/TextButtonTransition.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI/TextButtonTransition.cs.meta new file mode 100644 index 0000000..43cf251 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI/TextButtonTransition.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9d234639538a34b8d9e3cc6362a7afd0 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI/TextToggleIsOnTransition.cs b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI/TextToggleIsOnTransition.cs new file mode 100644 index 0000000..81befa6 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI/TextToggleIsOnTransition.cs @@ -0,0 +1,68 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// +// +// Use this on Button texts to have some color transition on the text as well without corrupting button's behaviour. +// +// developer@exitgames.com +// -------------------------------------------------------------------------------------------------------------------- + + +using UnityEngine; +using System.Collections; +using UnityEngine.EventSystems; +using UnityEngine.UI; + +namespace ExitGames.UtilityScripts +{ + + /// + /// Use this on toggles texts to have some color transition on the text depending on the isOnState. + /// + [RequireComponent(typeof(Text))] + public class TextToggleIsOnTransition : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler { + + public Toggle toggle; + + Text _text; + + public Color NormalOnColor= Color.white; + public Color NormalOffColor = Color.black; + public Color HoverOnColor= Color.black; + public Color HoverOffColor = Color.black; + + bool isHover; + + public void OnEnable() + { + _text = GetComponent(); + + toggle.onValueChanged.AddListener(OnValueChanged); + } + + public void OnDisable() + { + toggle.onValueChanged.RemoveListener(OnValueChanged); + } + + public void OnValueChanged(bool isOn) + { + + _text.color = isOn? (isHover?HoverOnColor:HoverOffColor) : (isHover?NormalOnColor:NormalOffColor) ; + + } + + public void OnPointerEnter(PointerEventData eventData) + { + isHover = true; + _text.color = toggle.isOn?HoverOnColor:HoverOffColor; + } + + public void OnPointerExit(PointerEventData eventData) + { + isHover = false; + _text.color = toggle.isOn?NormalOnColor:NormalOffColor; + } + + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI/TextToggleIsOnTransition.cs.meta b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI/TextToggleIsOnTransition.cs.meta new file mode 100644 index 0000000..a2ae161 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/UtilityScripts/UI/TextToggleIsOnTransition.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ec99d371d7c8e44899ce4b834dfd4d6a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/link.xml b/Close Enough!/Assets/Photon Unity Networking/link.xml new file mode 100644 index 0000000..c916499 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/link.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Close Enough!/Assets/Photon Unity Networking/link.xml.meta b/Close Enough!/Assets/Photon Unity Networking/link.xml.meta new file mode 100644 index 0000000..850d94d --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/link.xml.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: cecd4a32eba31cd4393c185e20824bfc +TextScriptImporter: + userData: diff --git a/Close Enough!/Assets/Photon Unity Networking/readme.txt b/Close Enough!/Assets/Photon Unity Networking/readme.txt new file mode 100644 index 0000000..aa7c700 --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/readme.txt @@ -0,0 +1,96 @@ + +Photon Unity Networking (PUN) + This package is a re-implementation of Unity 4's Networking, using Photon. + Also included: A setup wizard, demo scenes, documentation and Editor extensions. + + +PUN & PUN+ + PUN is the free package of Photon Unity Networking. Export to iOS or Android from Unity 4 requires Unity Pro Licenses. + PUN+ contains special native plugins that allow export to mobiles from Unity 4.x Free. You also get a Photon Cloud subscription upgrade. See below. + Unity 5 does not restrict export to mobiles. + + +Android and iOS Exports + See "PUN & PUN+" + iOS: Set the stripping level to "Strip Bytecode" and use ".Net 2.0" in the player settings. + More aggressive stripping will break the runtime and you can't connect anymore with PUN Free. + + +UnityScript / JavaScript + PUN is written with C# in mind primarily. + To use PUN from UnityScript, you need to move some folders in your project. + Move both folders "PhotonNetwork" and "UtilityScripts" to the Assets\Plugins\ folder. + from: \Photon Unity Networking\Plugins\ + and: \Photon Unity Networking\ + to: \Plugins\ + Now PUN compiles before UnityScript and that makes it available from regular UnityScript code. + + +Help and Documentation + Please read the included chm (or pdf). + Online documentation: https://doc.photonengine.com/en-us/pun + Exit Games Forum: https://forum.photonengine.com/categories/unity-networking-plugin-pun + Unity Forum Thread: https://forum.unity3d.com/threads/photon-unity-networking.101734/ + + +Integration + This package adds an Editor window "PUN Wizard" for connection setup: + Menu -> Window -> Photon Unity Networking (shortcut: ALT+P) + It also adds a commonly used component "PhotonView" to this menu: + Menu -> Component -> Miscellaneous -> PhotonView (shortcut: ALT+V) + When imported into a new, empty project, the "PunStartup" script opens the "demo hub" and setup scenes to build. + + +Clean PUN Import (no demos) + To get a clean import of PUN and PUN+ into your project, just skip the folders "Demos" and "UtilityScripts". + UtilityScripts can be useful for rapid prototyping but are optional to use. + "Important Files" are listed below. + + +Server + Exit Games Photon can be run on your servers or you can subscribe to the Photon Cloud for managed servers. + + The window "Photon Unity Networking" will help you setup a Photon Cloud account. + This service is geared towards room-based games and the server cannot be modified. + Read more about it: http://www.photonengine.com + + Alternatively, download the Server SDK and run your own Photon Server. + The SDK has the binaries to run immediately but also includes the source code and projects + for the game logic. You can use that as basis to modify and extend it. + A 100 concurrent user license is free (also for commercial use) per game. + Read more about it: http://www.photonengine.com/en/OnPremise + + +PUN+ and Networking Guide Subscriptions + Follow these steps when you bought an asset that includes an upgrade for a Photon Cloud subscription: + • Use an existing Photon Cloud Account or register. https://www.photonengine.com/Account/SignUp + • Sign in and open the Dashboard. https://www.photonengine.com/dashboard/Realtime/ + • Select the Subscription to upgrade and click "Apply Unity Purchase". + • Enter your Unity Invoice Number and App ID. + + • You find the App ID on: https://www.photonengine.com/dashboard/Realtime/ + • You find your Unity Invoice Number in the Unity AssetStore: + https://www.assetstore.unity3d.com/en/#!/account/transactions + Or while logged in to the Asset Store, click on your name on the top right. + From the drop-down select the payment method you used to obtain PUN+). + Navigate to your PUN+ purchase and copy the number following the "#" symbol (excluding the "#" and spaces). + + +Important Files + + Documentation + PhotonNetwork-Documentation.chm (a pdf is also included) + changelog.txt + + Extensions & Source + Photon Unity Networking\Editor\PhotonNetwork\*.* + Photon Unity Networking\Plugins\PhotonNetwork\*.* + Plugins\**\Photon*.* + + + The server-setup will be saved as file (can be moved into any Resources folder and edited in inspector) + Photon Unity Networking\Resources\PhotonServerSettings.asset + + Demos + All demos are in separate folders in Photon Unity Networking\Demos\. Delete this folder in your projects. + Each has a Demo-Scene. diff --git a/Close Enough!/Assets/Photon Unity Networking/readme.txt.meta b/Close Enough!/Assets/Photon Unity Networking/readme.txt.meta new file mode 100644 index 0000000..e8c13cd --- /dev/null +++ b/Close Enough!/Assets/Photon Unity Networking/readme.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d90864ccbf99d4a449c87472b0a181e8 +labels: +- ExitGames +- PUN +- Photon +- Networking diff --git a/Close Enough!/Assets/PhotonChatApi.meta b/Close Enough!/Assets/PhotonChatApi.meta new file mode 100644 index 0000000..a00995c --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: aa21c62a5faaf4a04afa0a314a8233e1 +folderAsset: yes +timeCreated: 1525372511 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/PhotonChatApi/ChatChannel.cs b/Close Enough!/Assets/PhotonChatApi/ChatChannel.cs new file mode 100644 index 0000000..4d9c7ca --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/ChatChannel.cs @@ -0,0 +1,106 @@ +// ---------------------------------------------------------------------------------------------------------------------- +// The Photon Chat Api enables clients to connect to a chat server and communicate with other clients. +// ChatClient is the main class of this api. +// Photon Chat Api - Copyright (C) 2014 Exit Games GmbH +// ---------------------------------------------------------------------------------------------------------------------- + +#if UNITY_4_7 || UNITY_5 || UNITY_5_0 || UNITY_5_1 || UNITY_5_3_OR_NEWER +#define UNITY +#endif + +namespace ExitGames.Client.Photon.Chat +{ + using System.Collections.Generic; + using System.Text; + + #if UNITY || NETFX_CORE + using Hashtable = ExitGames.Client.Photon.Hashtable; + using SupportClass = ExitGames.Client.Photon.SupportClass; + #endif + + + /// + /// A channel of communication in Photon Chat, updated by ChatClient and provided as READ ONLY. + /// + /// + /// Contains messages and senders to use (read!) and display by your GUI. + /// Access these by: + /// ChatClient.PublicChannels + /// ChatClient.PrivateChannels + /// + public class ChatChannel + { + /// Name of the channel (used to subscribe and unsubscribe). + public readonly string Name; + + /// Senders of messages in chronoligical order. Senders and Messages refer to each other by index. Senders[x] is the sender of Messages[x]. + public readonly List Senders = new List(); + + /// Messages in chronoligical order. Senders and Messages refer to each other by index. Senders[x] is the sender of Messages[x]. + public readonly List Messages = new List(); + + /// If greater than 0, this channel will limit the number of messages, that it caches locally. + public int MessageLimit; + + /// Is this a private 1:1 channel? + public bool IsPrivate { get; internal protected set; } + + /// Count of messages this client still buffers/knows for this channel. + public int MessageCount { get { return this.Messages.Count; } } + + + /// Used internally to create new channels. This does NOT create a channel on the server! Use ChatClient.Subscribe. + public ChatChannel(string name) + { + this.Name = name; + } + + /// Used internally to add messages to this channel. + public void Add(string sender, object message) + { + this.Senders.Add(sender); + this.Messages.Add(message); + this.TruncateMessages(); + } + + /// Used internally to add messages to this channel. + public void Add(string[] senders, object[] messages) + { + this.Senders.AddRange(senders); + this.Messages.AddRange(messages); + this.TruncateMessages(); + } + + /// Reduces the number of locally cached messages in this channel to the MessageLimit (if set). + public void TruncateMessages() + { + if (this.MessageLimit <= 0 || this.Messages.Count <= this.MessageLimit) + { + return; + } + + int excessCount = this.Messages.Count - this.MessageLimit; + this.Senders.RemoveRange(0, excessCount); + this.Messages.RemoveRange(0, excessCount); + } + + /// Clear the local cache of messages currently stored. This frees memory but doesn't affect the server. + public void ClearMessages() + { + this.Senders.Clear(); + this.Messages.Clear(); + } + + /// Provides a string-representation of all messages in this channel. + /// All known messages in format "Sender: Message", line by line. + public string ToStringMessages() + { + StringBuilder txt = new StringBuilder(); + for (int i = 0; i < this.Messages.Count; i++) + { + txt.AppendLine(string.Format("{0}: {1}", this.Senders[i], this.Messages[i])); + } + return txt.ToString(); + } + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/PhotonChatApi/ChatChannel.cs.meta b/Close Enough!/Assets/PhotonChatApi/ChatChannel.cs.meta new file mode 100644 index 0000000..0d73965 --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/ChatChannel.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 35b2a4878e5e99e438c97fbe8dbbd863 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/PhotonChatApi/ChatClient.cs b/Close Enough!/Assets/PhotonChatApi/ChatClient.cs new file mode 100644 index 0000000..1a678c7 --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/ChatClient.cs @@ -0,0 +1,1169 @@ +// ---------------------------------------------------------------------------------------------------------------------- +// The Photon Chat Api enables clients to connect to a chat server and communicate with other clients. +// ChatClient is the main class of this api. +// Photon Chat Api - Copyright (C) 2014 Exit Games GmbH +// ---------------------------------------------------------------------------------------------------------------------- + +#if UNITY_4_7 || UNITY_5 || UNITY_5_0 || UNITY_5_1 || UNITY_5_3_OR_NEWER +#define UNITY +#endif + +namespace ExitGames.Client.Photon.Chat +{ + using System; + using System.Collections.Generic; + using ExitGames.Client.Photon; + + #if UNITY || NETFX_CORE + using Hashtable = ExitGames.Client.Photon.Hashtable; + using SupportClass = ExitGames.Client.Photon.SupportClass; + #endif + + + /// Central class of the Photon Chat API to connect, handle channels and messages. + /// + /// This class must be instantiated with a IChatClientListener instance to get the callbacks. + /// Integrate it into your game loop by calling Service regularly. If the target platform supports Threads/Tasks, + /// set UseBackgroundWorkerForSending = true, to let the ChatClient keep the connection by sending from + /// an independent thread. + /// + /// Call Connect with an AppId that is setup as Photon Chat application. Note: Connect covers multiple + /// messages between this client and the servers. A short workflow will connect you to a chat server. + /// + /// Each ChatClient resembles a user in chat (set in Connect). Each user automatically subscribes a channel + /// for incoming private messages and can message any other user privately. + /// Before you publish messages in any non-private channel, that channel must be subscribed. + /// + /// PublicChannels is a list of subscribed channels, containing messages and senders. + /// PrivateChannels contains all incoming and sent private messages. + /// + public class ChatClient : IPhotonPeerListener + { + const int FriendRequestListMax = 1024; + + /// The address of last connected Name Server. + public string NameServerAddress { get; private set; } + + /// The address of the actual chat server assigned from NameServer. Public for read only. + public string FrontendAddress { get; private set; } + + /// Region used to connect to. Currently all chat is done in EU. It can make sense to use only one region for the whole game. + private string chatRegion = "EU"; + + /// Settable only before you connect! Defaults to "EU". + public string ChatRegion + { + get { return this.chatRegion; } + set { this.chatRegion = value; } + } + + /// Current state of the ChatClient. Also use CanChat. + public ChatState State { get; private set; } + + public ChatDisconnectCause DisconnectedCause { get; private set; } + + public bool CanChat + { + get { return this.State == ChatState.ConnectedToFrontEnd && this.HasPeer; } + } + + public bool CanChatInChannel(string channelName) + { + return this.CanChat && this.PublicChannels.ContainsKey(channelName) && !this.PublicChannelsUnsubscribing.Contains(channelName); + } + + private bool HasPeer + { + get { return this.chatPeer != null; } + } + + /// The version of your client. A new version also creates a new "virtual app" to separate players from older client versions. + public string AppVersion { get; private set; } + + /// The AppID as assigned from the Photon Cloud. If you host yourself, this is the "regular" Photon Server Application Name (most likely: "LoadBalancing"). + public string AppId { get; private set; } + + + /// Settable only before you connect! + public AuthenticationValues AuthValues { get; set; } + + /// The unique ID of a user/person, stored in AuthValues.UserId. Set it before you connect. + /// + /// This value wraps AuthValues.UserId. + /// It's not a nickname and we assume users with the same userID are the same person. + public string UserId + { + get + { + return (this.AuthValues != null) ? this.AuthValues.UserId : null; + } + private set + { + if (this.AuthValues == null) + { + this.AuthValues = new AuthenticationValues(); + } + this.AuthValues.UserId = value; + } + } + + /// If greater than 0, new channels will limit the number of messages they cache locally. + /// + /// This can be useful to limit the amount of memory used by chats. + /// You can set a MessageLimit per channel but this value gets applied to new ones. + /// + /// Note: + /// Changing this value, does not affect ChatChannels that are already in use! + /// + public int MessageLimit; + + public readonly Dictionary PublicChannels; + public readonly Dictionary PrivateChannels; + + // channels being in unsubscribing process + // items will be removed on successful unsubscription or subscription (the latter required after attempt to unsubscribe from not existing channel) + private readonly HashSet PublicChannelsUnsubscribing; + + private readonly IChatClientListener listener = null; + public ChatPeer chatPeer = null; + private const string ChatAppName = "chat"; + private bool didAuthenticate; + + private int msDeltaForServiceCalls = 50; + private int msTimestampOfLastServiceCall; + + /// Defines if a background thread will call SendOutgoingCommands, while your code calls Service to dispatch received messages. + /// + /// The benefit of using a background thread to call SendOutgoingCommands is this: + /// + /// Even if your game logic is being paused, the background thread will keep the connection to the server up. + /// On a lower level, acknowledgements and pings will prevent a server-side timeout while (e.g.) Unity loads assets. + /// + /// Your game logic still has to call Service regularly, or else incoming messages are not dispatched. + /// As this typicalls triggers UI updates, it's easier to call Service from the main/UI thread. + /// + public bool UseBackgroundWorkerForSending { get; set; } + + /// Exposes the TransportProtocol of the used PhotonPeer. Settable while not connected. + public ConnectionProtocol TransportProtocol + { + get { return this.chatPeer.TransportProtocol; } + set + { + if (this.chatPeer == null || this.chatPeer.PeerState != PeerStateValue.Disconnected) + { + this.listener.DebugReturn(DebugLevel.WARNING, "Can't set TransportProtocol. Disconnect first! " + ((this.chatPeer != null) ? "PeerState: " + this.chatPeer.PeerState : "The chatPeer is null.")); + return; + } + this.chatPeer.TransportProtocol = value; + } + } + + /// Defines which IPhotonSocket class to use per ConnectionProtocol. + /// + /// Several platforms have special Socket implementations and slightly different APIs. + /// To accomodate this, switching the socket implementation for a network protocol was made available. + /// By default, UDP and TCP have socket implementations assigned. + /// + /// You only need to set the SocketImplementationConfig once, after creating a PhotonPeer + /// and before connecting. If you switch the TransportProtocol, the correct implementation is being used. + /// + public Dictionary SocketImplementationConfig + { + get { return this.chatPeer.SocketImplementationConfig; } + } + + + public ChatClient(IChatClientListener listener, ConnectionProtocol protocol = ConnectionProtocol.Udp) + { + this.listener = listener; + this.State = ChatState.Uninitialized; + + this.chatPeer = new ChatPeer(this, protocol); + + this.PublicChannels = new Dictionary(); + this.PrivateChannels = new Dictionary(); + + this.PublicChannelsUnsubscribing = new HashSet(); + } + + /// + /// Connects this client to the Photon Chat Cloud service, which will also authenticate the user (and set a UserId). + /// + /// Get your Photon Chat AppId from the Dashboard. + /// Any version string you make up. Used to separate users and variants of your clients, which might be incompatible. + /// Values for authentication. You can leave this null, if you set a UserId before. If you set authValues, they will override any UserId set before. + /// + public bool Connect(string appId, string appVersion, AuthenticationValues authValues) + { + this.chatPeer.TimePingInterval = 3000; + this.DisconnectedCause = ChatDisconnectCause.None; + + if (authValues != null) + { + this.AuthValues = authValues; + if (string.IsNullOrEmpty(this.AuthValues.UserId)) + { + if (this.DebugOut >= DebugLevel.ERROR) + { + this.listener.DebugReturn(DebugLevel.ERROR, "Connect failed: no UserId specified in authentication values."); + } + return false; + } + } + else + { + if (this.DebugOut >= DebugLevel.ERROR) + { + this.listener.DebugReturn(DebugLevel.ERROR, "Connect failed: no authentication values specified"); + } + return false; + } + this.AppId = appId; + this.AppVersion = appVersion; + this.didAuthenticate = false; + this.chatPeer.QuickResendAttempts = 2; + this.chatPeer.SentCountAllowance = 7; + + + // clean all channels + this.PublicChannels.Clear(); + this.PrivateChannels.Clear(); + this.PublicChannelsUnsubscribing.Clear(); + + + #if UNITY_WEBGL + if (this.TransportProtocol == ConnectionProtocol.Tcp || this.TransportProtocol == ConnectionProtocol.Udp) + { + this.listener.DebugReturn(DebugLevel.WARNING, "WebGL requires WebSockets. Switching TransportProtocol to WebSocketSecure."); + this.TransportProtocol = ConnectionProtocol.WebSocketSecure; + } + #endif + + + this.NameServerAddress = this.chatPeer.NameServerAddress; + bool isConnecting = this.chatPeer.Connect(); + if (isConnecting) + { + this.State = ChatState.ConnectingToNameServer; + } + + if (this.UseBackgroundWorkerForSending) + { + SupportClass.StartBackgroundCalls(this.SendOutgoingInBackground, this.msDeltaForServiceCalls, "ChatClient Service Thread"); + } + + return isConnecting; + } + + /// + /// Must be called regularly to keep connection between client and server alive and to process incoming messages. + /// + /// + /// This method limits the effort it does automatically using the private variable msDeltaForServiceCalls. + /// That value is lower for connect and multiplied by 4 when chat-server connection is ready. + /// + public void Service() + { + // Dispatch until every already-received message got dispatched + while (this.HasPeer && this.chatPeer.DispatchIncomingCommands()) + { + } + + // if there is no background thread for sending, Service() will do that as well, in intervals + if (!this.UseBackgroundWorkerForSending) + { + if (Environment.TickCount - this.msTimestampOfLastServiceCall > this.msDeltaForServiceCalls || this.msTimestampOfLastServiceCall == 0) + { + this.msTimestampOfLastServiceCall = Environment.TickCount; + + while (this.HasPeer && this.chatPeer.SendOutgoingCommands()) + { + } + } + } + } + + /// + /// Called by a separate thread, this sends outgoing commands of this peer, as long as it's connected. + /// + /// True as long as the client is not disconnected. + private bool SendOutgoingInBackground() + { + while (this.HasPeer && this.chatPeer.SendOutgoingCommands()) + { + } + + return this.State != ChatState.Disconnected; + } + + + [Obsolete("Better use UseBackgroundWorkerForSending and Service().")] + public void SendAcksOnly() + { + if (this.HasPeer) this.chatPeer.SendAcksOnly(); + } + + + /// + /// Disconnects from the Chat Server by sending a "disconnect command", which prevents a timeout server-side. + /// + public void Disconnect() + { + if (this.HasPeer && this.chatPeer.PeerState != PeerStateValue.Disconnected) + { + this.chatPeer.Disconnect(); + } + } + + /// + /// Locally shuts down the connection to the Chat Server. This resets states locally but the server will have to timeout this peer. + /// + public void StopThread() + { + if (this.HasPeer) + { + this.chatPeer.StopThread(); + } + } + + /// Sends operation to subscribe to a list of channels by name. + /// List of channels to subscribe to. Avoid null or empty values. + /// If the operation could be sent at all (Example: Fails if not connected to Chat Server). + public bool Subscribe(string[] channels) + { + return this.Subscribe(channels, 0); + } + + /// + /// Sends operation to subscribe client to channels, optionally fetching a number of messages from the cache. + /// + /// + /// Subscribes channels will forward new messages to this user. Use PublishMessage to do so. + /// The messages cache is limited but can be useful to get into ongoing conversations, if that's needed. + /// + /// List of channels to subscribe to. Avoid null or empty values. + /// 0: no history. 1 and higher: number of messages in history. -1: all available history. + /// If the operation could be sent at all (Example: Fails if not connected to Chat Server). + public bool Subscribe(string[] channels, int messagesFromHistory) + { + if (!this.CanChat) + { + if (this.DebugOut >= DebugLevel.ERROR) + { + this.listener.DebugReturn(DebugLevel.ERROR, "Subscribe called while not connected to front end server."); + } + return false; + } + + if (channels == null || channels.Length == 0) + { + if (this.DebugOut >= DebugLevel.WARNING) + { + this.listener.DebugReturn(DebugLevel.WARNING, "Subscribe can't be called for empty or null channels-list."); + } + return false; + } + + return this.SendChannelOperation(channels, (byte)ChatOperationCode.Subscribe, messagesFromHistory); + } + + /// Unsubscribes from a list of channels, which stops getting messages from those. + /// + /// The client will remove these channels from the PublicChannels dictionary once the server sent a response to this request. + /// + /// The request will be sent to the server and IChatClientListener.OnUnsubscribed gets called when the server + /// actually removed the channel subscriptions. + /// + /// Unsubscribe will fail if you include null or empty channel names. + /// + /// Names of channels to unsubscribe. + /// False, if not connected to a chat server. + public bool Unsubscribe(string[] channels) + { + if (!this.CanChat) + { + if (this.DebugOut >= DebugLevel.ERROR) + { + this.listener.DebugReturn(DebugLevel.ERROR, "Unsubscribe called while not connected to front end server."); + } + return false; + } + + if (channels == null || channels.Length == 0) + { + if (this.DebugOut >= DebugLevel.WARNING) + { + this.listener.DebugReturn(DebugLevel.WARNING, "Unsubscribe can't be called for empty or null channels-list."); + } + return false; + } + + foreach (string ch in channels) + { + this.PublicChannelsUnsubscribing.Add(ch); + } + return this.SendChannelOperation(channels, ChatOperationCode.Unsubscribe, 0); + } + + /// Sends a message to a public channel which this client subscribed to. + /// + /// Before you publish to a channel, you have to subscribe it. + /// Everyone in that channel will get the message. + /// + /// Name of the channel to publish to. + /// Your message (string or any serializable data). + /// Optionally, public messages can be forwarded as webhooks. Configure webhooks for your Chat app to use this. + /// False if the client is not yet ready to send messages. + public bool PublishMessage(string channelName, object message, bool forwardAsWebhook = false) + { + return this.publishMessage(channelName, message, true, forwardAsWebhook); + } + + internal bool PublishMessageUnreliable(string channelName, object message, bool forwardAsWebhook = false) + { + return this.publishMessage(channelName, message, false, forwardAsWebhook); + } + + private bool publishMessage(string channelName, object message, bool reliable, bool forwardAsWebhook = false) + { + if (!this.CanChat) + { + if (this.DebugOut >= DebugLevel.ERROR) + { + this.listener.DebugReturn(DebugLevel.ERROR, "PublishMessage called while not connected to front end server."); + } + return false; + } + + if (string.IsNullOrEmpty(channelName) || message == null) + { + if (this.DebugOut >= DebugLevel.WARNING) + { + this.listener.DebugReturn(DebugLevel.WARNING, "PublishMessage parameters must be non-null and not empty."); + } + return false; + } + + Dictionary parameters = new Dictionary + { + { (byte)ChatParameterCode.Channel, channelName }, + { (byte)ChatParameterCode.Message, message } + }; + if (forwardAsWebhook) + { + parameters.Add(ChatParameterCode.WebFlags, (byte)0x1); + } + return this.chatPeer.OpCustom((byte)ChatOperationCode.Publish, parameters, reliable); + } + + /// + /// Sends a private message to a single target user. Calls OnPrivateMessage on the receiving client. + /// + /// Username to send this message to. + /// The message you want to send. Can be a simple string or anything serializable. + /// Optionally, private messages can be forwarded as webhooks. Configure webhooks for your Chat app to use this. + /// True if this clients can send the message to the server. + public bool SendPrivateMessage(string target, object message, bool forwardAsWebhook = false) + { + return this.SendPrivateMessage(target, message, false, forwardAsWebhook); + } + + /// + /// Sends a private message to a single target user. Calls OnPrivateMessage on the receiving client. + /// + /// Username to send this message to. + /// The message you want to send. Can be a simple string or anything serializable. + /// Optionally, private messages can be encrypted. Encryption is not end-to-end as the server decrypts the message. + /// Optionally, private messages can be forwarded as webhooks. Configure webhooks for your Chat app to use this. + /// True if this clients can send the message to the server. + public bool SendPrivateMessage(string target, object message, bool encrypt, bool forwardAsWebhook) + { + return this.sendPrivateMessage(target, message, encrypt, true, forwardAsWebhook); + } + + internal bool SendPrivateMessageUnreliable(string target, object message, bool encrypt, bool forwardAsWebhook = false) + { + return this.sendPrivateMessage(target, message, encrypt, false, forwardAsWebhook); + } + + private bool sendPrivateMessage(string target, object message, bool encrypt, bool reliable, bool forwardAsWebhook = false) + { + if (!this.CanChat) + { + if (this.DebugOut >= DebugLevel.ERROR) + { + this.listener.DebugReturn(DebugLevel.ERROR, "SendPrivateMessage called while not connected to front end server."); + } + return false; + } + + if (string.IsNullOrEmpty(target) || message == null) + { + if (this.DebugOut >= DebugLevel.WARNING) + { + this.listener.DebugReturn(DebugLevel.WARNING, "SendPrivateMessage parameters must be non-null and not empty."); + } + return false; + } + + Dictionary parameters = new Dictionary + { + { ChatParameterCode.UserId, target }, + { ChatParameterCode.Message, message } + }; + if (forwardAsWebhook) + { + parameters.Add(ChatParameterCode.WebFlags, (byte)0x1); + } + return this.chatPeer.OpCustom((byte)ChatOperationCode.SendPrivate, parameters, reliable, 0, encrypt); + } + + /// Sets the user's status (pre-defined or custom) and an optional message. + /// + /// The predefined status values can be found in class ChatUserStatus. + /// State ChatUserStatus.Invisible will make you offline for everyone and send no message. + /// + /// You can set custom values in the status integer. Aside from the pre-configured ones, + /// all states will be considered visible and online. Else, no one would see the custom state. + /// + /// The message object can be anything that Photon can serialize, including (but not limited to) + /// Hashtable, object[] and string. This value is defined by your own conventions. + /// + /// Predefined states are in class ChatUserStatus. Other values can be used at will. + /// Optional string message or null. + /// If true, the message gets ignored. It can be null but won't replace any current message. + /// True if the operation gets called on the server. + private bool SetOnlineStatus(int status, object message, bool skipMessage) + { + if (!this.CanChat) + { + if (this.DebugOut >= DebugLevel.ERROR) + { + this.listener.DebugReturn(DebugLevel.ERROR, "SetOnlineStatus called while not connected to front end server."); + } + return false; + } + + Dictionary parameters = new Dictionary + { + { ChatParameterCode.Status, status }, + }; + + if (skipMessage) + { + parameters[ChatParameterCode.SkipMessage] = true; + } + else + { + parameters[ChatParameterCode.Message] = message; + } + return this.chatPeer.OpCustom(ChatOperationCode.UpdateStatus, parameters, true); + } + + /// Sets the user's status without changing your status-message. + /// + /// The predefined status values can be found in class ChatUserStatus. + /// State ChatUserStatus.Invisible will make you offline for everyone and send no message. + /// + /// You can set custom values in the status integer. Aside from the pre-configured ones, + /// all states will be considered visible and online. Else, no one would see the custom state. + /// + /// This overload does not change the set message. + /// + /// Predefined states are in class ChatUserStatus. Other values can be used at will. + /// True if the operation gets called on the server. + public bool SetOnlineStatus(int status) + { + return this.SetOnlineStatus(status, null, true); + } + + /// Sets the user's status without changing your status-message. + /// + /// The predefined status values can be found in class ChatUserStatus. + /// State ChatUserStatus.Invisible will make you offline for everyone and send no message. + /// + /// You can set custom values in the status integer. Aside from the pre-configured ones, + /// all states will be considered visible and online. Else, no one would see the custom state. + /// + /// The message object can be anything that Photon can serialize, including (but not limited to) + /// Hashtable, object[] and string. This value is defined by your own conventions. + /// + /// Predefined states are in class ChatUserStatus. Other values can be used at will. + /// Also sets a status-message which your friends can get. + /// True if the operation gets called on the server. + public bool SetOnlineStatus(int status, object message) + { + return this.SetOnlineStatus(status, message, false); + } + + /// + /// Adds friends to a list on the Chat Server which will send you status updates for those. + /// + /// + /// AddFriends and RemoveFriends enable clients to handle their friend list + /// in the Photon Chat server. Having users on your friends list gives you access + /// to their current online status (and whatever info your client sets in it). + /// + /// Each user can set an online status consisting of an integer and an arbitratry + /// (serializable) object. The object can be null, Hashtable, object[] or anything + /// else Photon can serialize. + /// + /// The status is published automatically to friends (anyone who set your user ID + /// with AddFriends). + /// + /// Photon flushes friends-list when a chat client disconnects, so it has to be + /// set each time. If your community API gives you access to online status already, + /// you could filter and set online friends in AddFriends. + /// + /// Actual friend relations are not persistent and have to be stored outside + /// of Photon. + /// + /// Array of friend userIds. + /// If the operation could be sent. + public bool AddFriends(string[] friends) + { + if (!this.CanChat) + { + if (this.DebugOut >= DebugLevel.ERROR) + { + this.listener.DebugReturn(DebugLevel.ERROR, "AddFriends called while not connected to front end server."); + } + return false; + } + + if (friends == null || friends.Length == 0) + { + if (this.DebugOut >= DebugLevel.WARNING) + { + this.listener.DebugReturn(DebugLevel.WARNING, "AddFriends can't be called for empty or null list."); + } + return false; + } + if (friends.Length > FriendRequestListMax) + { + if (this.DebugOut >= DebugLevel.WARNING) + { + this.listener.DebugReturn(DebugLevel.WARNING, "AddFriends max list size exceeded: " + friends.Length + " > " + FriendRequestListMax); + } + return false; + } + + Dictionary parameters = new Dictionary + { + { ChatParameterCode.Friends, friends }, + }; + return this.chatPeer.OpCustom(ChatOperationCode.AddFriends, parameters, true); + } + + /// + /// Removes the provided entries from the list on the Chat Server and stops their status updates. + /// + /// + /// Photon flushes friends-list when a chat client disconnects. Unless you want to + /// remove individual entries, you don't have to RemoveFriends. + /// + /// AddFriends and RemoveFriends enable clients to handle their friend list + /// in the Photon Chat server. Having users on your friends list gives you access + /// to their current online status (and whatever info your client sets in it). + /// + /// Each user can set an online status consisting of an integer and an arbitratry + /// (serializable) object. The object can be null, Hashtable, object[] or anything + /// else Photon can serialize. + /// + /// The status is published automatically to friends (anyone who set your user ID + /// with AddFriends). + /// + /// Photon flushes friends-list when a chat client disconnects, so it has to be + /// set each time. If your community API gives you access to online status already, + /// you could filter and set online friends in AddFriends. + /// + /// Actual friend relations are not persistent and have to be stored outside + /// of Photon. + /// + /// AddFriends and RemoveFriends enable clients to handle their friend list + /// in the Photon Chat server. Having users on your friends list gives you access + /// to their current online status (and whatever info your client sets in it). + /// + /// Each user can set an online status consisting of an integer and an arbitratry + /// (serializable) object. The object can be null, Hashtable, object[] or anything + /// else Photon can serialize. + /// + /// The status is published automatically to friends (anyone who set your user ID + /// with AddFriends). + /// + /// + /// Actual friend relations are not persistent and have to be stored outside + /// of Photon. + /// + /// Array of friend userIds. + /// If the operation could be sent. + public bool RemoveFriends(string[] friends) + { + if (!this.CanChat) + { + if (this.DebugOut >= DebugLevel.ERROR) + { + this.listener.DebugReturn(DebugLevel.ERROR, "RemoveFriends called while not connected to front end server."); + } + return false; + } + + if (friends == null || friends.Length == 0) + { + if (this.DebugOut >= DebugLevel.WARNING) + { + this.listener.DebugReturn(DebugLevel.WARNING, "RemoveFriends can't be called for empty or null list."); + } + return false; + } + if (friends.Length > FriendRequestListMax) + { + if (this.DebugOut >= DebugLevel.WARNING) + { + this.listener.DebugReturn(DebugLevel.WARNING, "RemoveFriends max list size exceeded: " + friends.Length + " > " + FriendRequestListMax); + } + return false; + } + + Dictionary parameters = new Dictionary + { + { ChatParameterCode.Friends, friends }, + }; + return this.chatPeer.OpCustom(ChatOperationCode.RemoveFriends, parameters, true); + } + + /// + /// Get you the (locally used) channel name for the chat between this client and another user. + /// + /// Remote user's name or UserId. + /// The (locally used) channel name for a private channel. + public string GetPrivateChannelNameByUser(string userName) + { + return string.Format("{0}:{1}", this.UserId, userName); + } + + /// + /// Simplified access to either private or public channels by name. + /// + /// Name of the channel to get. For private channels, the channel-name is composed of both user's names. + /// Define if you expect a private or public channel. + /// Out parameter gives you the found channel, if any. + /// True if the channel was found. + public bool TryGetChannel(string channelName, bool isPrivate, out ChatChannel channel) + { + if (!isPrivate) + { + return this.PublicChannels.TryGetValue(channelName, out channel); + } + else + { + return this.PrivateChannels.TryGetValue(channelName, out channel); + } + } + + /// + /// Simplified access to all channels by name. Checks public channels first, then private ones. + /// + /// Name of the channel to get. + /// Out parameter gives you the found channel, if any. + /// True if the channel was found. + public bool TryGetChannel(string channelName, out ChatChannel channel) + { + bool found = false; + found = this.PublicChannels.TryGetValue(channelName, out channel); + if (found) return true; + + found = this.PrivateChannels.TryGetValue(channelName, out channel); + return found; + } + + /// + /// Sets the level (and amount) of debug output provided by the library. + /// + /// + /// This affects the callbacks to IChatClientListener.DebugReturn. + /// Default Level: Error. + /// + public DebugLevel DebugOut + { + set { this.chatPeer.DebugOut = value; } + get { return this.chatPeer.DebugOut; } + } + + #region Private methods area + + #region IPhotonPeerListener implementation + + void IPhotonPeerListener.DebugReturn(DebugLevel level, string message) + { + this.listener.DebugReturn(level, message); + } + + void IPhotonPeerListener.OnEvent(EventData eventData) + { + switch (eventData.Code) + { + case ChatEventCode.ChatMessages: + this.HandleChatMessagesEvent(eventData); + break; + case ChatEventCode.PrivateMessage: + this.HandlePrivateMessageEvent(eventData); + break; + case ChatEventCode.StatusUpdate: + this.HandleStatusUpdate(eventData); + break; + case ChatEventCode.Subscribe: + this.HandleSubscribeEvent(eventData); + break; + case ChatEventCode.Unsubscribe: + this.HandleUnsubscribeEvent(eventData); + break; + } + } + + void IPhotonPeerListener.OnOperationResponse(OperationResponse operationResponse) + { + switch (operationResponse.OperationCode) + { + case (byte)ChatOperationCode.Authenticate: + this.HandleAuthResponse(operationResponse); + break; + + // the following operations usually don't return useful data and no error. + case (byte)ChatOperationCode.Subscribe: + case (byte)ChatOperationCode.Unsubscribe: + case (byte)ChatOperationCode.Publish: + case (byte)ChatOperationCode.SendPrivate: + default: + if ((operationResponse.ReturnCode != 0) && (this.DebugOut >= DebugLevel.ERROR)) + { + if (operationResponse.ReturnCode == -2) + { + this.listener.DebugReturn(DebugLevel.ERROR, string.Format("Chat Operation {0} unknown on server. Check your AppId and make sure it's for a Chat application.", operationResponse.OperationCode)); + } + else + { + this.listener.DebugReturn(DebugLevel.ERROR, string.Format("Chat Operation {0} failed (Code: {1}). Debug Message: {2}", operationResponse.OperationCode, operationResponse.ReturnCode, operationResponse.DebugMessage)); + } + } + break; + } + } + + void IPhotonPeerListener.OnStatusChanged(StatusCode statusCode) + { + switch (statusCode) + { + case StatusCode.Connect: + if (!this.chatPeer.IsProtocolSecure) + { + this.chatPeer.EstablishEncryption(); + } + else + { + if (!this.didAuthenticate) + { + this.didAuthenticate = this.chatPeer.AuthenticateOnNameServer(this.AppId, this.AppVersion, this.chatRegion, this.AuthValues); + if (!this.didAuthenticate) + { + if (this.DebugOut >= DebugLevel.ERROR) + { + ((IPhotonPeerListener)this).DebugReturn(DebugLevel.ERROR, "Error calling OpAuthenticate! Did not work. Check log output, AuthValues and if you're connected. State: " + this.State); + } + } + } + } + + if (this.State == ChatState.ConnectingToNameServer) + { + this.State = ChatState.ConnectedToNameServer; + this.listener.OnChatStateChange(this.State); + } + else if (this.State == ChatState.ConnectingToFrontEnd) + { + this.AuthenticateOnFrontEnd(); + } + break; + case StatusCode.EncryptionEstablished: + // once encryption is availble, the client should send one (secure) authenticate. it includes the AppId (which identifies your app on the Photon Cloud) + if (!this.didAuthenticate) + { + this.didAuthenticate = this.chatPeer.AuthenticateOnNameServer(this.AppId, this.AppVersion, this.chatRegion, this.AuthValues); + if (!this.didAuthenticate) + { + if (this.DebugOut >= DebugLevel.ERROR) + { + ((IPhotonPeerListener)this).DebugReturn(DebugLevel.ERROR, "Error calling OpAuthenticate! Did not work. Check log output, AuthValues and if you're connected. State: " + this.State); + } + } + } + break; + case StatusCode.EncryptionFailedToEstablish: + this.State = ChatState.Disconnecting; + this.chatPeer.Disconnect(); + break; + case StatusCode.Disconnect: + if (this.State == ChatState.Authenticated) + { + this.ConnectToFrontEnd(); + } + else + { + this.State = ChatState.Disconnected; + this.listener.OnChatStateChange(ChatState.Disconnected); + this.listener.OnDisconnected(); + } + break; + } + } + + #if SDK_V4 + void IPhotonPeerListener.OnMessage(object msg) + { + // in v4 interface IPhotonPeerListener + return; + } + #endif + + #endregion + + private bool SendChannelOperation(string[] channels, byte operation, int historyLength) + { + Dictionary opParameters = new Dictionary { { (byte)ChatParameterCode.Channels, channels } }; + + if (historyLength != 0) + { + opParameters.Add((byte)ChatParameterCode.HistoryLength, historyLength); + } + + return this.chatPeer.OpCustom(operation, opParameters, true); + } + + private void HandlePrivateMessageEvent(EventData eventData) + { + //Console.WriteLine(SupportClass.DictionaryToString(eventData.Parameters)); + + object message = (object)eventData.Parameters[(byte)ChatParameterCode.Message]; + string sender = (string)eventData.Parameters[(byte)ChatParameterCode.Sender]; + + string channelName; + if (this.UserId != null && this.UserId.Equals(sender)) + { + string target = (string)eventData.Parameters[(byte)ChatParameterCode.UserId]; + channelName = this.GetPrivateChannelNameByUser(target); + } + else + { + channelName = this.GetPrivateChannelNameByUser(sender); + } + + ChatChannel channel; + if (!this.PrivateChannels.TryGetValue(channelName, out channel)) + { + channel = new ChatChannel(channelName); + channel.IsPrivate = true; + channel.MessageLimit = this.MessageLimit; + this.PrivateChannels.Add(channel.Name, channel); + } + + channel.Add(sender, message); + this.listener.OnPrivateMessage(sender, message, channelName); + } + + private void HandleChatMessagesEvent(EventData eventData) + { + object[] messages = (object[])eventData.Parameters[(byte)ChatParameterCode.Messages]; + string[] senders = (string[])eventData.Parameters[(byte)ChatParameterCode.Senders]; + string channelName = (string)eventData.Parameters[(byte)ChatParameterCode.Channel]; + + ChatChannel channel; + if (!this.PublicChannels.TryGetValue(channelName, out channel)) + { + if (this.DebugOut >= DebugLevel.WARNING) + { + this.listener.DebugReturn(DebugLevel.WARNING, "Channel " + channelName + " for incoming message event not found."); + } + return; + } + + channel.Add(senders, messages); + this.listener.OnGetMessages(channelName, senders, messages); + } + + private void HandleSubscribeEvent(EventData eventData) + { + string[] channelsInResponse = (string[])eventData.Parameters[ChatParameterCode.Channels]; + bool[] results = (bool[])eventData.Parameters[ChatParameterCode.SubscribeResults]; + + for (int i = 0; i < channelsInResponse.Length; i++) + { + if (results[i]) + { + string channelName = channelsInResponse[i]; + if (!this.PublicChannels.ContainsKey(channelName)) + { + ChatChannel channel = new ChatChannel(channelName); + channel.MessageLimit = this.MessageLimit; + this.PublicChannels.Add(channel.Name, channel); + } + } + } + + this.listener.OnSubscribed(channelsInResponse, results); + } + + private void HandleUnsubscribeEvent(EventData eventData) + { + string[] channelsInRequest = (string[])eventData[ChatParameterCode.Channels]; + for (int i = 0; i < channelsInRequest.Length; i++) + { + string channelName = channelsInRequest[i]; + this.PublicChannels.Remove(channelName); + this.PublicChannelsUnsubscribing.Remove(channelName); + } + + this.listener.OnUnsubscribed(channelsInRequest); + } + + private void HandleAuthResponse(OperationResponse operationResponse) + { + if (this.DebugOut >= DebugLevel.INFO) + { + this.listener.DebugReturn(DebugLevel.INFO, operationResponse.ToStringFull() + " on: " + this.chatPeer.NameServerAddress); + } + + if (operationResponse.ReturnCode == 0) + { + if (this.State == ChatState.ConnectedToNameServer) + { + this.State = ChatState.Authenticated; + this.listener.OnChatStateChange(this.State); + + if (operationResponse.Parameters.ContainsKey(ParameterCode.Secret)) + { + if (this.AuthValues == null) + { + this.AuthValues = new AuthenticationValues(); + } + this.AuthValues.Token = operationResponse[ParameterCode.Secret] as string; + this.FrontendAddress = (string)operationResponse[ParameterCode.Address]; + + // we disconnect and status handler starts to connect to front end + this.chatPeer.Disconnect(); + } + else + { + if (this.DebugOut >= DebugLevel.ERROR) + { + this.listener.DebugReturn(DebugLevel.ERROR, "No secret in authentication response."); + } + } + } + else if (this.State == ChatState.ConnectingToFrontEnd) + { + this.State = ChatState.ConnectedToFrontEnd; + this.listener.OnChatStateChange(this.State); + this.listener.OnConnected(); + } + } + else + { + //this.listener.DebugReturn(DebugLevel.INFO, operationResponse.ToStringFull() + " NS: " + this.NameServerAddress + " FrontEnd: " + this.frontEndAddress); + + switch (operationResponse.ReturnCode) + { + case ErrorCode.InvalidAuthentication: + this.DisconnectedCause = ChatDisconnectCause.InvalidAuthentication; + break; + case ErrorCode.CustomAuthenticationFailed: + this.DisconnectedCause = ChatDisconnectCause.CustomAuthenticationFailed; + break; + case ErrorCode.InvalidRegion: + this.DisconnectedCause = ChatDisconnectCause.InvalidRegion; + break; + case ErrorCode.MaxCcuReached: + this.DisconnectedCause = ChatDisconnectCause.MaxCcuReached; + break; + case ErrorCode.OperationNotAllowedInCurrentState: + this.DisconnectedCause = ChatDisconnectCause.OperationNotAllowedInCurrentState; + break; + } + + if (this.DebugOut >= DebugLevel.ERROR) + { + this.listener.DebugReturn(DebugLevel.ERROR, "Authentication request error: " + operationResponse.ReturnCode + ". Disconnecting."); + } + + + this.State = ChatState.Disconnecting; + this.chatPeer.Disconnect(); + } + } + + private void HandleStatusUpdate(EventData eventData) + { + string user = (string)eventData.Parameters[ChatParameterCode.Sender]; + int status = (int)eventData.Parameters[ChatParameterCode.Status]; + + object message = null; + bool gotMessage = eventData.Parameters.ContainsKey(ChatParameterCode.Message); + if (gotMessage) + { + message = eventData.Parameters[ChatParameterCode.Message]; + } + + this.listener.OnStatusUpdate(user, status, gotMessage, message); + } + + private void ConnectToFrontEnd() + { + this.State = ChatState.ConnectingToFrontEnd; + + if (this.DebugOut >= DebugLevel.INFO) + { + this.listener.DebugReturn(DebugLevel.INFO, "Connecting to frontend " + this.FrontendAddress); + } + + #if UNITY_WEBGL + if (this.TransportProtocol == ConnectionProtocol.Tcp || this.TransportProtocol == ConnectionProtocol.Udp) + { + this.listener.DebugReturn(DebugLevel.WARNING, "WebGL requires WebSockets. Switching TransportProtocol to WebSocketSecure."); + this.TransportProtocol = ConnectionProtocol.WebSocketSecure; + } + #endif + + this.chatPeer.Connect(this.FrontendAddress, ChatAppName); + } + + private bool AuthenticateOnFrontEnd() + { + if (this.AuthValues != null) + { + if (this.AuthValues.Token == null || this.AuthValues.Token == "") + { + if (this.DebugOut >= DebugLevel.ERROR) + { + this.listener.DebugReturn(DebugLevel.ERROR, "Can't authenticate on front end server. Secret is not set"); + } + return false; + } + else + { + Dictionary opParameters = new Dictionary { { (byte)ChatParameterCode.Secret, this.AuthValues.Token } }; + return this.chatPeer.OpCustom((byte)ChatOperationCode.Authenticate, opParameters, true); + } + } + else + { + if (this.DebugOut >= DebugLevel.ERROR) + { + this.listener.DebugReturn(DebugLevel.ERROR, "Can't authenticate on front end server. Authentication Values are not set"); + } + return false; + } + } + + #endregion + } +} diff --git a/Close Enough!/Assets/PhotonChatApi/ChatClient.cs.meta b/Close Enough!/Assets/PhotonChatApi/ChatClient.cs.meta new file mode 100644 index 0000000..0a1bea9 --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/ChatClient.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 692e391fa2a297c45b3d530aa85be610 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/PhotonChatApi/ChatDisconnectCause.cs b/Close Enough!/Assets/PhotonChatApi/ChatDisconnectCause.cs new file mode 100644 index 0000000..1b56f41 --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/ChatDisconnectCause.cs @@ -0,0 +1,36 @@ +// ---------------------------------------------------------------------------------------------------------------------- +// The Photon Chat Api enables clients to connect to a chat server and communicate with other clients. +// ChatClient is the main class of this api. +// Photon Chat Api - Copyright (C) 2014 Exit Games GmbH +// ---------------------------------------------------------------------------------------------------------------------- + +namespace ExitGames.Client.Photon.Chat +{ + /// Enumaration of causes for Disconnects (used in LoadBalancingClient.DisconnectedCause). + /// Read the individual descriptions to find out what to do about this type of disconnect. + public enum ChatDisconnectCause + { + /// No error was tracked. + None, + /// OnStatusChanged: The CCUs count of your Photon Server License is exausted (temporarily). + DisconnectByServerUserLimit, + /// OnStatusChanged: The server is not available or the address is wrong. Make sure the port is provided and the server is up. + ExceptionOnConnect, + /// OnStatusChanged: The server disconnected this client. Most likely the server's send buffer is full (receiving too much from other clients). + DisconnectByServer, + /// OnStatusChanged: This client detected that the server's responses are not received in due time. Maybe you send / receive too much? + TimeoutDisconnect, + /// OnStatusChanged: Some internal exception caused the socket code to fail. Contact Exit Games. + Exception, + /// OnOperationResponse: Authenticate in the Photon Cloud with invalid AppId. Update your subscription or contact Exit Games. + InvalidAuthentication, + /// OnOperationResponse: Authenticate (temporarily) failed when using a Photon Cloud subscription without CCU Burst. Update your subscription. + MaxCcuReached, + /// OnOperationResponse: Authenticate when the app's Photon Cloud subscription is locked to some (other) region(s). Update your subscription or master server address. + InvalidRegion, + /// OnOperationResponse: Operation that's (currently) not available for this client (not authorized usually). Only tracked for op Authenticate. + OperationNotAllowedInCurrentState, + /// OnOperationResponse: Authenticate in the Photon Cloud with invalid client values or custom authentication setup in Cloud Dashboard. + CustomAuthenticationFailed, + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/PhotonChatApi/ChatDisconnectCause.cs.meta b/Close Enough!/Assets/PhotonChatApi/ChatDisconnectCause.cs.meta new file mode 100644 index 0000000..c1f0c5b --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/ChatDisconnectCause.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b90b85043f1857f43b94fd00edfc1ef1 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/PhotonChatApi/ChatEventCode.cs b/Close Enough!/Assets/PhotonChatApi/ChatEventCode.cs new file mode 100644 index 0000000..ea58a4a --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/ChatEventCode.cs @@ -0,0 +1,22 @@ +// ---------------------------------------------------------------------------------------------------------------------- +// The Photon Chat Api enables clients to connect to a chat server and communicate with other clients. +// ChatClient is the main class of this api. +// Photon Chat Api - Copyright (C) 2014 Exit Games GmbH +// ---------------------------------------------------------------------------------------------------------------------- + +namespace ExitGames.Client.Photon.Chat +{ + /// + /// Wraps up internally used constants in Photon Chat events. You don't have to use them directly usually. + /// + public class ChatEventCode + { + public const byte ChatMessages = 0; + public const byte Users = 1;// List of users or List of changes for List of users + public const byte PrivateMessage = 2; + public const byte FriendsList = 3; + public const byte StatusUpdate = 4; + public const byte Subscribe = 5; + public const byte Unsubscribe = 6; + } +} diff --git a/Close Enough!/Assets/PhotonChatApi/ChatEventCode.cs.meta b/Close Enough!/Assets/PhotonChatApi/ChatEventCode.cs.meta new file mode 100644 index 0000000..4c0b2e6 --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/ChatEventCode.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 188e4a680bce12d4cbad8d57a24f7d44 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/PhotonChatApi/ChatOperationCode.cs b/Close Enough!/Assets/PhotonChatApi/ChatOperationCode.cs new file mode 100644 index 0000000..4a716fa --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/ChatOperationCode.cs @@ -0,0 +1,36 @@ +// ---------------------------------------------------------------------------------------------------------------------- +// The Photon Chat Api enables clients to connect to a chat server and communicate with other clients. +// ChatClient is the main class of this api. +// Photon Chat Api - Copyright (C) 2014 Exit Games GmbH +// ---------------------------------------------------------------------------------------------------------------------- + +namespace ExitGames.Client.Photon.Chat +{ + /// + /// Wraps up codes for operations used internally in Photon Chat. You don't have to use them directly usually. + /// + public class ChatOperationCode + { + /// (230) Operation Authenticate. + public const byte Authenticate = 230; + + /// (0) Operation to subscribe to chat channels. + public const byte Subscribe = 0; + /// (1) Operation to unsubscribe from chat channels. + public const byte Unsubscribe = 1; + /// (2) Operation to publish a message in a chat channel. + public const byte Publish = 2; + /// (3) Operation to send a private message to some other user. + public const byte SendPrivate = 3; + + /// (4) Not used yet. + public const byte ChannelHistory = 4; + + /// (5) Set your (client's) status. + public const byte UpdateStatus = 5; + /// (6) Add friends the list of friends that should update you of their status. + public const byte AddFriends = 6; + /// (7) Remove friends from list of friends that should update you of their status. + public const byte RemoveFriends = 7; + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/PhotonChatApi/ChatOperationCode.cs.meta b/Close Enough!/Assets/PhotonChatApi/ChatOperationCode.cs.meta new file mode 100644 index 0000000..0375688 --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/ChatOperationCode.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c90a2a73f3ce648409739c724d3e6cef +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/PhotonChatApi/ChatParameterCode.cs b/Close Enough!/Assets/PhotonChatApi/ChatParameterCode.cs new file mode 100644 index 0000000..46f776e --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/ChatParameterCode.cs @@ -0,0 +1,52 @@ +// ---------------------------------------------------------------------------------------------------------------------- +// The Photon Chat Api enables clients to connect to a chat server and communicate with other clients. +// ChatClient is the main class of this api. +// Photon Chat Api - Copyright (C) 2014 Exit Games GmbH +// ---------------------------------------------------------------------------------------------------------------------- + +namespace ExitGames.Client.Photon.Chat +{ + /// + /// Wraps up codes for parameters (in operations and events) used internally in Photon Chat. You don't have to use them directly usually. + /// + public class ChatParameterCode + { + /// (0) Array of chat channels. + public const byte Channels = 0; + /// (1) Name of a single chat channel. + public const byte Channel = 1; + /// (2) Array of chat messages. + public const byte Messages = 2; + /// (3) A single chat message. + public const byte Message = 3; + /// (4) Array of names of the users who sent the array of chat mesages. + public const byte Senders = 4; + /// (5) Name of a the user who sent a chat message. + public const byte Sender = 5; + /// (6) Not used. + public const byte ChannelUserCount = 6; + /// (225) Name of user to send a (private) message to.The code is used in LoadBalancing and copied over here. + public const byte UserId = 225; + /// (8) Id of a message. + public const byte MsgId = 8; + /// (9) Not used. + public const byte MsgIds = 9; + /// (221) Secret token to identify an authorized user.The code is used in LoadBalancing and copied over here. + public const byte Secret = 221; + /// (15) Subscribe operation result parameter. A bool[] with result per channel. + public const byte SubscribeResults = 15; + + /// (10) Status + public const byte Status = 10; + /// (11) Friends + public const byte Friends = 11; + /// (12) SkipMessage is used in SetOnlineStatus and if true, the message is not being broadcast. + public const byte SkipMessage = 12; + + /// (14) Number of message to fetch from history. 0: no history. 1 and higher: number of messages in history. -1: all history. + public const byte HistoryLength = 14; + + /// (21) WebFlags object for changing behaviour of webhooks from client. + public const byte WebFlags = 21; + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/PhotonChatApi/ChatParameterCode.cs.meta b/Close Enough!/Assets/PhotonChatApi/ChatParameterCode.cs.meta new file mode 100644 index 0000000..b0d8707 --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/ChatParameterCode.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d7a17b60c85fb30448492e397c58c7ce +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/PhotonChatApi/ChatPeer.cs b/Close Enough!/Assets/PhotonChatApi/ChatPeer.cs new file mode 100644 index 0000000..37765fe --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/ChatPeer.cs @@ -0,0 +1,397 @@ +// ---------------------------------------------------------------------------------------------------------------------- +// The Photon Chat Api enables clients to connect to a chat server and communicate with other clients. +// ChatClient is the main class of this api. +// Photon Chat Api - Copyright (C) 2014 Exit Games GmbH +// ---------------------------------------------------------------------------------------------------------------------- + +#if UNITY_4_7 || UNITY_5 || UNITY_5_0 || UNITY_5_1 || UNITY_5_3_OR_NEWER +#define UNITY +#endif + +namespace ExitGames.Client.Photon.Chat +{ + using System; + using System.Diagnostics; + using System.Collections.Generic; + using ExitGames.Client.Photon; + + #if UNITY || NETFX_CORE + using Hashtable = ExitGames.Client.Photon.Hashtable; + using SupportClass = ExitGames.Client.Photon.SupportClass; + #endif + + + /// + /// Provides basic operations of the Photon Chat server. This internal class is used by public ChatClient. + /// + public class ChatPeer : PhotonPeer + { + /// Name Server Host Name for Photon Cloud. Without port and without any prefix. + public const string NameServerHost = "ns.exitgames.com"; + + /// Name Server for HTTP connections to the Photon Cloud. Includes prefix and port. + public const string NameServerHttp = "http://ns.exitgamescloud.com:80/photon/n"; + + /// Name Server port per protocol (the UDP port is different than TCP, etc). + private static readonly Dictionary ProtocolToNameServerPort = new Dictionary() { { ConnectionProtocol.Udp, 5058 }, { ConnectionProtocol.Tcp, 4533 }, { ConnectionProtocol.WebSocket, 9093 }, { ConnectionProtocol.WebSocketSecure, 19093 } }; //, { ConnectionProtocol.RHttp, 6063 } }; + + /// Name Server Address for Photon Cloud (based on current protocol). You can use the default values and usually won't have to set this value. + public string NameServerAddress { get { return this.GetNameServerAddress(); } } + + virtual internal bool IsProtocolSecure { get { return this.UsedProtocol == ConnectionProtocol.WebSocketSecure; } } + + + public ChatPeer(IPhotonPeerListener listener, ConnectionProtocol protocol) : base(listener, protocol) + { + this.ConfigUnitySockets(); + } + + + [Conditional("UNITY")] + private void ConfigUnitySockets() + { + #pragma warning disable 0162 // the library variant defines if we should use PUN's SocketUdp variant (at all) + if (PhotonPeer.NoSocket) + { + #if !UNITY_EDITOR && (UNITY_PS3 || UNITY_ANDROID) + this.SocketImplementationConfig[ConnectionProtocol.Udp] = typeof(SocketUdpNativeDynamic); + #elif !UNITY_EDITOR && UNITY_IPHONE + this.SocketImplementationConfig[ConnectionProtocol.Udp] = typeof(SocketUdpNativeStatic); + #elif !UNITY_EDITOR && (UNITY_WINRT) + // this automatically uses a separate assembly-file with Win8-style Socket usage (not possible in Editor) + #else + Type udpSocket = Type.GetType("ExitGames.Client.Photon.SocketUdp, Assembly-CSharp"); + this.SocketImplementationConfig[ConnectionProtocol.Udp] = udpSocket; + if (udpSocket == null) + { + #if UNITY + UnityEngine.Debug.Log("Could not find a suitable C# socket class. This Photon3Unity3D.dll only supports native socket plugins."); + #endif + } + #endif + } + #pragma warning restore 0162 + + + #if UNITY_WEBGL + if (this.TransportProtocol != ConnectionProtocol.WebSocket && this.TransportProtocol != ConnectionProtocol.WebSocketSecure) + { + UnityEngine.Debug.Log("For UNITY_WEBGL, use protocol WebSocketSecure. Overriding currently set protcol " + this.TransportProtocol + "."); + this.TransportProtocol = ConnectionProtocol.WebSocketSecure; + } + #endif + + + // to support WebGL export in Unity, we find and assign the SocketWebTcpThread or SocketWebTcpCoroutine class (if it's in the project). + Type websocketType = Type.GetType("ExitGames.Client.Photon.SocketWebTcpThread, Assembly-CSharp", false); + websocketType = websocketType ?? Type.GetType("ExitGames.Client.Photon.SocketWebTcpThread, Assembly-CSharp-firstpass", false); + websocketType = websocketType ?? Type.GetType("ExitGames.Client.Photon.SocketWebTcpCoroutine, Assembly-CSharp", false); + websocketType = websocketType ?? Type.GetType("ExitGames.Client.Photon.SocketWebTcpCoroutine, Assembly-CSharp-firstpass", false); + if (websocketType != null) + { + this.SocketImplementationConfig[ConnectionProtocol.WebSocket] = websocketType; + this.SocketImplementationConfig[ConnectionProtocol.WebSocketSecure] = websocketType; + } + } + + + /// + /// Gets the NameServer Address (with prefix and port), based on the set protocol (this.UsedProtocol). + /// + /// NameServer Address (with prefix and port). + private string GetNameServerAddress() + { + var protocolPort = 0; + ProtocolToNameServerPort.TryGetValue(this.TransportProtocol, out protocolPort); + + switch (this.TransportProtocol) + { + case ConnectionProtocol.Udp: + case ConnectionProtocol.Tcp: + return string.Format("{0}:{1}", NameServerHost, protocolPort); + #if RHTTP + case ConnectionProtocol.RHttp: + return NameServerHttp; + #endif + case ConnectionProtocol.WebSocket: + return string.Format("ws://{0}:{1}", NameServerHost, protocolPort); + case ConnectionProtocol.WebSocketSecure: + return string.Format("wss://{0}:{1}", NameServerHost, protocolPort); + default: + throw new ArgumentOutOfRangeException(); + } + } + + public bool Connect() + { + if (this.DebugOut >= DebugLevel.INFO) + { + this.Listener.DebugReturn(DebugLevel.INFO, "Connecting to nameserver " + this.NameServerAddress); + } + + return this.Connect(this.NameServerAddress, "NameServer"); + } + + public bool AuthenticateOnNameServer(string appId, string appVersion, string region, AuthenticationValues authValues) + { + if (this.DebugOut >= DebugLevel.INFO) + { + this.Listener.DebugReturn(DebugLevel.INFO, "OpAuthenticate()"); + } + + var opParameters = new Dictionary(); + + opParameters[ParameterCode.AppVersion] = appVersion; + opParameters[ParameterCode.ApplicationId] = appId; + opParameters[ParameterCode.Region] = region; + + if (authValues != null) + { + if (!string.IsNullOrEmpty(authValues.UserId)) + { + opParameters[ParameterCode.UserId] = authValues.UserId; + } + + if (authValues != null && authValues.AuthType != CustomAuthenticationType.None) + { + opParameters[ParameterCode.ClientAuthenticationType] = (byte) authValues.AuthType; + if (!string.IsNullOrEmpty(authValues.Token)) + { + opParameters[ParameterCode.Secret] = authValues.Token; + } + else + { + if (!string.IsNullOrEmpty(authValues.AuthGetParameters)) + { + opParameters[ParameterCode.ClientAuthenticationParams] = authValues.AuthGetParameters; + } + if (authValues.AuthPostData != null) + { + opParameters[ParameterCode.ClientAuthenticationData] = authValues.AuthPostData; + } + } + } + } + + return this.OpCustom((byte)ChatOperationCode.Authenticate, opParameters, true, (byte)0, this.IsEncryptionAvailable); + } + } + + /// + /// Options for optional "Custom Authentication" services used with Photon. Used by OpAuthenticate after connecting to Photon. + /// + public enum CustomAuthenticationType : byte + { + /// Use a custom authentification service. Currently the only implemented option. + Custom = 0, + + /// Authenticates users by their Steam Account. Set auth values accordingly! + Steam = 1, + + /// Authenticates users by their Facebook Account. Set auth values accordingly! + Facebook = 2, + + /// Authenticates users by their Oculus Account and token. + Oculus = 3, + + /// Authenticates users by their PSN Account and token. + PlayStation = 4, + + /// Authenticates users by their Xbox Account and XSTS token. + Xbox = 5, + + /// Disables custom authentification. Same as not providing any AuthenticationValues for connect (more precisely for: OpAuthenticate). + None = byte.MaxValue + } + + + + /// + /// Container for user authentication in Photon. Set AuthValues before you connect - all else is handled. + /// + /// + /// On Photon, user authentication is optional but can be useful in many cases. + /// If you want to FindFriends, a unique ID per user is very practical. + /// + /// There are basically three options for user authentification: None at all, the client sets some UserId + /// or you can use some account web-service to authenticate a user (and set the UserId server-side). + /// + /// Custom Authentication lets you verify end-users by some kind of login or token. It sends those + /// values to Photon which will verify them before granting access or disconnecting the client. + /// + /// The Photon Cloud Dashboard will let you enable this feature and set important server values for it. + /// https://www.photonengine.com/dashboard + /// + public class AuthenticationValues + { + /// See AuthType. + private CustomAuthenticationType authType = CustomAuthenticationType.None; + + /// The type of custom authentication provider that should be used. Currently only "Custom" or "None" (turns this off). + public CustomAuthenticationType AuthType + { + get { return authType; } + set { authType = value; } + } + + /// This string must contain any (http get) parameters expected by the used authentication service. By default, username and token. + /// Standard http get parameters are used here and passed on to the service that's defined in the server (Photon Cloud Dashboard). + public string AuthGetParameters { get; set; } + + /// Data to be passed-on to the auth service via POST. Default: null (not sent). Either string or byte[] (see setters). + public object AuthPostData { get; private set; } + + /// After initial authentication, Photon provides a token for this client / user, which is subsequently used as (cached) validation. + public string Token { get; set; } + + /// The UserId should be a unique identifier per user. This is for finding friends, etc.. + public string UserId { get; set; } + + + /// Creates empty auth values without any info. + public AuthenticationValues() + { + } + + /// Creates minimal info about the user. If this is authenticated or not, depends on the set AuthType. + /// Some UserId to set in Photon. + public AuthenticationValues(string userId) + { + this.UserId = userId; + } + + /// Sets the data to be passed-on to the auth service via POST. + /// String data to be used in the body of the POST request. Null or empty string will set AuthPostData to null. + public virtual void SetAuthPostData(string stringData) + { + this.AuthPostData = (string.IsNullOrEmpty(stringData)) ? null : stringData; + } + + /// Sets the data to be passed-on to the auth service via POST. + /// Binary token / auth-data to pass on. + public virtual void SetAuthPostData(byte[] byteData) + { + this.AuthPostData = byteData; + } + + /// Adds a key-value pair to the get-parameters used for Custom Auth. + /// This method does uri-encoding for you. + /// Key for the value to set. + /// Some value relevant for Custom Authentication. + public virtual void AddAuthParameter(string key, string value) + { + string ampersand = string.IsNullOrEmpty(this.AuthGetParameters) ? "" : "&"; + this.AuthGetParameters = string.Format("{0}{1}{2}={3}", this.AuthGetParameters, ampersand, System.Uri.EscapeDataString(key), System.Uri.EscapeDataString(value)); + } + + public override string ToString() + { + return string.Format("AuthenticationValues UserId: {0}, GetParameters: {1} Token available: {2}", UserId, this.AuthGetParameters, Token != null); + } + } + + + public class ParameterCode + { + public const byte ApplicationId = 224; + /// (221) Internally used to establish encryption + public const byte Secret = 221; + public const byte AppVersion = 220; + /// (217) This key's (byte) value defines the target custom authentication type/service the client connects with. Used in OpAuthenticate + public const byte ClientAuthenticationType = 217; + + /// (216) This key's (string) value provides parameters sent to the custom authentication type/service the client connects with. Used in OpAuthenticate + public const byte ClientAuthenticationParams = 216; + + /// (214) This key's (string or byte[]) value provides parameters sent to the custom authentication service setup in Photon Dashboard. Used in OpAuthenticate + public const byte ClientAuthenticationData = 214; + /// (210) Used for region values in OpAuth and OpGetRegions. + public const byte Region = 210; + /// (230) Address of a (game) server to use. + public const byte Address = 230; + /// (225) User's ID + public const byte UserId = 225; + } + /// + /// ErrorCode defines the default codes associated with Photon client/server communication. + /// + public class ErrorCode + { + /// (0) is always "OK", anything else an error or specific situation. + public const int Ok = 0; + + // server - Photon low(er) level: <= 0 + + /// + /// (-3) Operation can't be executed yet (e.g. OpJoin can't be called before being authenticated, RaiseEvent cant be used before getting into a room). + /// + /// + /// Before you call any operations on the Cloud servers, the automated client workflow must complete its authorization. + /// In PUN, wait until State is: JoinedLobby (with AutoJoinLobby = true) or ConnectedToMaster (AutoJoinLobby = false) + /// + public const int OperationNotAllowedInCurrentState = -3; + + /// (-2) The operation you called is not implemented on the server (application) you connect to. Make sure you run the fitting applications. + public const int InvalidOperationCode = -2; + + /// (-1) Something went wrong in the server. Try to reproduce and contact Exit Games. + public const int InternalServerError = -1; + + // server - PhotonNetwork: 0x7FFF and down + // logic-level error codes start with short.max + + /// (32767) Authentication failed. Possible cause: AppId is unknown to Photon (in cloud service). + public const int InvalidAuthentication = 0x7FFF; + + /// (32766) GameId (name) already in use (can't create another). Change name. + public const int GameIdAlreadyExists = 0x7FFF - 1; + + /// (32765) Game is full. This rarely happens when some player joined the room before your join completed. + public const int GameFull = 0x7FFF - 2; + + /// (32764) Game is closed and can't be joined. Join another game. + public const int GameClosed = 0x7FFF - 3; + + /// (32762) Not in use currently. + public const int ServerFull = 0x7FFF - 5; + + /// (32761) Not in use currently. + public const int UserBlocked = 0x7FFF - 6; + + /// (32760) Random matchmaking only succeeds if a room exists thats neither closed nor full. Repeat in a few seconds or create a new room. + public const int NoRandomMatchFound = 0x7FFF - 7; + + /// (32758) Join can fail if the room (name) is not existing (anymore). This can happen when players leave while you join. + public const int GameDoesNotExist = 0x7FFF - 9; + + /// (32757) Authorization on the Photon Cloud failed becaus the concurrent users (CCU) limit of the app's subscription is reached. + /// + /// Unless you have a plan with "CCU Burst", clients might fail the authentication step during connect. + /// Affected client are unable to call operations. Please note that players who end a game and return + /// to the master server will disconnect and re-connect, which means that they just played and are rejected + /// in the next minute / re-connect. + /// This is a temporary measure. Once the CCU is below the limit, players will be able to connect an play again. + /// + /// OpAuthorize is part of connection workflow but only on the Photon Cloud, this error can happen. + /// Self-hosted Photon servers with a CCU limited license won't let a client connect at all. + /// + public const int MaxCcuReached = 0x7FFF - 10; + + /// (32756) Authorization on the Photon Cloud failed because the app's subscription does not allow to use a particular region's server. + /// + /// Some subscription plans for the Photon Cloud are region-bound. Servers of other regions can't be used then. + /// Check your master server address and compare it with your Photon Cloud Dashboard's info. + /// https://cloud.photonengine.com/dashboard + /// + /// OpAuthorize is part of connection workflow but only on the Photon Cloud, this error can happen. + /// Self-hosted Photon servers with a CCU limited license won't let a client connect at all. + /// + public const int InvalidRegion = 0x7FFF - 11; + + /// + /// (32755) Custom Authentication of the user failed due to setup reasons (see Cloud Dashboard) or the provided user data (like username or token). Check error message for details. + /// + public const int CustomAuthenticationFailed = 0x7FFF - 12; + } + +} diff --git a/Close Enough!/Assets/PhotonChatApi/ChatPeer.cs.meta b/Close Enough!/Assets/PhotonChatApi/ChatPeer.cs.meta new file mode 100644 index 0000000..a002c43 --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/ChatPeer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3f712805dec728943a668b3bf19dc422 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/PhotonChatApi/ChatState.cs b/Close Enough!/Assets/PhotonChatApi/ChatState.cs new file mode 100644 index 0000000..cc81c6d --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/ChatState.cs @@ -0,0 +1,37 @@ +// ---------------------------------------------------------------------------------------------------------------------- +// The Photon Chat Api enables clients to connect to a chat server and communicate with other clients. +// ChatClient is the main class of this api. +// Photon Chat Api - Copyright (C) 2014 Exit Games GmbH +// ---------------------------------------------------------------------------------------------------------------------- + +namespace ExitGames.Client.Photon.Chat +{ + /// Possible states for a LoadBalancingClient. + public enum ChatState + { + /// Peer is created but not used yet. + Uninitialized, + /// Connecting to master (includes connect, authenticate and joining the lobby) + ConnectingToNameServer, + /// Connected to master server. + ConnectedToNameServer, + /// Usually when Authenticated, the client will join a game or the lobby (if AutoJoinLobby is true). + Authenticating, + /// Usually when Authenticated, the client will join a game or the lobby (if AutoJoinLobby is true). + Authenticated, + /// Transition from master to game server. + DisconnectingFromNameServer, + /// Transition to gameserver (client will authenticate and join/create game). + ConnectingToFrontEnd, + /// Connected to gameserver (going to auth and join game). + ConnectedToFrontEnd, + /// Transition from gameserver to master (after leaving a room/game). + DisconnectingFromFrontEnd, + /// Currently not used. + QueuedComingFromFrontEnd, + /// The client disconnects (from any server). + Disconnecting, + /// The client is no longer connected (to any server). Connect to master to go on. + Disconnected, + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/PhotonChatApi/ChatState.cs.meta b/Close Enough!/Assets/PhotonChatApi/ChatState.cs.meta new file mode 100644 index 0000000..e862818 --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/ChatState.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8f482d8c4fe7ade4cbb08eb4a2d83b39 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/PhotonChatApi/ChatUserStatus.cs b/Close Enough!/Assets/PhotonChatApi/ChatUserStatus.cs new file mode 100644 index 0000000..b7d7fa5 --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/ChatUserStatus.cs @@ -0,0 +1,35 @@ +// ---------------------------------------------------------------------------------------------------------------------- +// The Photon Chat Api enables clients to connect to a chat server and communicate with other clients. +// ChatClient is the main class of this api. +// Photon Chat Api - Copyright (C) 2014 Exit Games GmbH +// ---------------------------------------------------------------------------------------------------------------------- + +namespace ExitGames.Client.Photon.Chat +{ + /// Contains commonly used status values for SetOnlineStatus. You can define your own. + /// + /// While "online" (value 2 and up), the status message will be sent to anyone who has you on his friend list. + /// + /// Define custom online status values as you like with these rules: + /// 0: Means "offline". It will be used when you are not connected. In this status, there is no status message. + /// 1: Means "invisible" and is sent to friends as "offline". They see status 0, no message but you can chat. + /// 2: And any higher value will be treated as "online". Status can be set. + /// + public static class ChatUserStatus + { + /// (0) Offline. + public const int Offline = 0; + /// (1) Be invisible to everyone. Sends no message. + public const int Invisible = 1; + /// (2) Online and available. + public const int Online = 2; + /// (3) Online but not available. + public const int Away = 3; + /// (4) Do not disturb. + public const int DND = 4; + /// (5) Looking For Game/Group. Could be used when you want to be invited or do matchmaking. + public const int LFG = 5; + /// (6) Could be used when in a room, playing. + public const int Playing = 6; + } +} diff --git a/Close Enough!/Assets/PhotonChatApi/ChatUserStatus.cs.meta b/Close Enough!/Assets/PhotonChatApi/ChatUserStatus.cs.meta new file mode 100644 index 0000000..bfd0c52 --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/ChatUserStatus.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7db67e7f5face2e42b6daafcaf4e6c82 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/PhotonChatApi/IChatClientListener.cs b/Close Enough!/Assets/PhotonChatApi/IChatClientListener.cs new file mode 100644 index 0000000..52a19a3 --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/IChatClientListener.cs @@ -0,0 +1,86 @@ +// ---------------------------------------------------------------------------------------------------------------------- +// The Photon Chat Api enables clients to connect to a chat server and communicate with other clients. +// ChatClient is the main class of this api. +// Photon Chat Api - Copyright (C) 2014 Exit Games GmbH +// ---------------------------------------------------------------------------------------------------------------------- + +namespace ExitGames.Client.Photon.Chat +{ + /// + /// Callback interface for Chat client side. Contains callback methods to notify your app about updates. + /// Must be provided to new ChatClient in constructor + /// + public interface IChatClientListener + { + /// + /// All debug output of the library will be reported through this method. Print it or put it in a + /// buffer to use it on-screen. + /// + /// DebugLevel (severity) of the message. + /// Debug text. Print to System.Console or screen. + void DebugReturn(DebugLevel level, string message); + + /// + /// Disconnection happened. + /// + void OnDisconnected(); + + /// + /// Client is connected now. + /// + /// + /// Clients have to be connected before they can send their state, subscribe to channels and send any messages. + /// + void OnConnected(); + + /// The ChatClient's state changed. Usually, OnConnected and OnDisconnected are the callbacks to react to. + /// The new state. + void OnChatStateChange(ChatState state); + + /// + /// Notifies app that client got new messages from server + /// Number of senders is equal to number of messages in 'messages'. Sender with number '0' corresponds to message with + /// number '0', sender with number '1' corresponds to message with number '1' and so on + /// + /// channel from where messages came + /// list of users who sent messages + /// list of messages it self + void OnGetMessages(string channelName, string[] senders, object[] messages); + + /// + /// Notifies client about private message + /// + /// user who sent this message + /// message it self + /// channelName for private messages (messages you sent yourself get added to a channel per target username) + void OnPrivateMessage(string sender, object message, string channelName); + + /// + /// Result of Subscribe operation. Returns subscription result for every requested channel name. + /// + /// + /// If multiple channels sent in Subscribe operation, OnSubscribed may be called several times, each call with part of sent array or with single channel in "channels" parameter. + /// Calls order and order of channels in "channels" parameter may differ from order of channels in "channels" parameter of Subscribe operation. + /// + /// Array of channel names. + /// Per channel result if subscribed. + void OnSubscribed(string[] channels, bool[] results); + + /// + /// Result of Unsubscribe operation. Returns for channel name if the channel is now unsubscribed. + /// + /// If multiple channels sent in Unsubscribe operation, OnUnsubscribed may be called several times, each call with part of sent array or with single channel in "channels" parameter. + /// Calls order and order of channels in "channels" parameter may differ from order of channels in "channels" parameter of Unsubscribe operation. + /// Array of channel names that are no longer subscribed. + void OnUnsubscribed(string[] channels); + + /// + /// New status of another user (you get updates for users set in your friends list). + /// + /// Name of the user. + /// New status of that user. + /// True if the status contains a message you should cache locally. False: This status update does not include a message (keep any you have). + /// Message that user set. + void OnStatusUpdate(string user, int status, bool gotMessage, object message); + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/PhotonChatApi/IChatClientListener.cs.meta b/Close Enough!/Assets/PhotonChatApi/IChatClientListener.cs.meta new file mode 100644 index 0000000..797bdea --- /dev/null +++ b/Close Enough!/Assets/PhotonChatApi/IChatClientListener.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bab7c8053b486e34aa0d4ca99dcbec80 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Plugins.meta b/Close Enough!/Assets/Plugins.meta new file mode 100644 index 0000000..cd8630c --- /dev/null +++ b/Close Enough!/Assets/Plugins.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: fce9029fe222348f1bb6653ceb5a5ccb +folderAsset: yes +timeCreated: 1525372511 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Plugins/Metro.meta b/Close Enough!/Assets/Plugins/Metro.meta new file mode 100644 index 0000000..9932476 --- /dev/null +++ b/Close Enough!/Assets/Plugins/Metro.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: a952ed70ae65a4110abfbd7d0a9df28a +folderAsset: yes +timeCreated: 1525372511 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Plugins/Metro/Photon3Unity3D.dll b/Close Enough!/Assets/Plugins/Metro/Photon3Unity3D.dll new file mode 100644 index 0000000..53116db Binary files /dev/null and b/Close Enough!/Assets/Plugins/Metro/Photon3Unity3D.dll differ diff --git a/Close Enough!/Assets/Plugins/Metro/Photon3Unity3D.dll.meta b/Close Enough!/Assets/Plugins/Metro/Photon3Unity3D.dll.meta new file mode 100644 index 0000000..a7b44bb --- /dev/null +++ b/Close Enough!/Assets/Plugins/Metro/Photon3Unity3D.dll.meta @@ -0,0 +1,67 @@ +fileFormatVersion: 2 +guid: 3b5a0a7dce46a13459199d174ad3db3f +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + platformData: + Android: + enabled: 0 + settings: + CPU: AnyCPU + Any: + enabled: 0 + settings: {} + Editor: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + Linux: + enabled: 0 + settings: + CPU: x86 + Linux64: + enabled: 0 + settings: + CPU: x86_64 + OSXIntel: + enabled: 0 + settings: + CPU: AnyCPU + OSXIntel64: + enabled: 0 + settings: + CPU: AnyCPU + WP8: + enabled: 0 + settings: + CPU: AnyCPU + DontProcess: False + PlaceholderPath: Assets/Plugins/Photon3Unity3D.dll + Win: + enabled: 0 + settings: + CPU: AnyCPU + Win64: + enabled: 0 + settings: + CPU: AnyCPU + WindowsStoreApps: + enabled: 1 + settings: + CPU: AnyCPU + DontProcess: False + PlaceholderPath: Assets/Plugins/Photon3Unity3D.dll + SDK: AnySDK + ScriptingBackend: DotNet + iOS: + enabled: 0 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Plugins/Metro/Photon3Unity3D.pri b/Close Enough!/Assets/Plugins/Metro/Photon3Unity3D.pri new file mode 100644 index 0000000..fa910b6 Binary files /dev/null and b/Close Enough!/Assets/Plugins/Metro/Photon3Unity3D.pri differ diff --git a/Close Enough!/Assets/Plugins/Metro/Photon3Unity3D.pri.meta b/Close Enough!/Assets/Plugins/Metro/Photon3Unity3D.pri.meta new file mode 100644 index 0000000..eb420ef --- /dev/null +++ b/Close Enough!/Assets/Plugins/Metro/Photon3Unity3D.pri.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3439a9e4030efca45b6cc06240106c02 +timeCreated: 1460035811 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Plugins/Photon3Unity3D.dll b/Close Enough!/Assets/Plugins/Photon3Unity3D.dll new file mode 100644 index 0000000..1a1d6e3 Binary files /dev/null and b/Close Enough!/Assets/Plugins/Photon3Unity3D.dll differ diff --git a/Close Enough!/Assets/Plugins/Photon3Unity3D.dll.meta b/Close Enough!/Assets/Plugins/Photon3Unity3D.dll.meta new file mode 100644 index 0000000..f8184f3 --- /dev/null +++ b/Close Enough!/Assets/Plugins/Photon3Unity3D.dll.meta @@ -0,0 +1,95 @@ +fileFormatVersion: 2 +guid: aadb37a20a33632429047acaef43658a +labels: +- ExitGames +- PUN +- Photon +- Networking +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + platformData: + Android: + enabled: 1 + settings: + CPU: AnyCPU + Any: + enabled: 0 + settings: {} + Editor: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + Linux: + enabled: 1 + settings: + CPU: x86 + Linux64: + enabled: 1 + settings: + CPU: x86_64 + LinuxUniversal: + enabled: 1 + settings: {} + OSXIntel: + enabled: 1 + settings: + CPU: AnyCPU + OSXIntel64: + enabled: 1 + settings: + CPU: AnyCPU + OSXUniversal: + enabled: 1 + settings: {} + PS4: + enabled: 1 + settings: {} + WP8: + enabled: 0 + settings: + CPU: AnyCPU + DontProcess: False + PlaceholderPath: + Web: + enabled: 1 + settings: {} + WebGL: + enabled: 1 + settings: {} + WebStreamed: + enabled: 1 + settings: {} + Win: + enabled: 1 + settings: + CPU: AnyCPU + Win64: + enabled: 1 + settings: + CPU: AnyCPU + WindowsStoreApps: + enabled: 1 + settings: + CPU: AnyCPU + DontProcess: False + PlaceholderPath: + SDK: AnySDK + ScriptingBackend: Il2Cpp + iOS: + enabled: 1 + settings: + CompileFlags: + FrameworkDependencies: + tvOS: + enabled: 1 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Plugins/Photon3Unity3D.xml b/Close Enough!/Assets/Plugins/Photon3Unity3D.xml new file mode 100644 index 0000000..86ed756 --- /dev/null +++ b/Close Enough!/Assets/Plugins/Photon3Unity3D.xml @@ -0,0 +1,2109 @@ + + + + Photon3Unity3D + + + + + This is a substitute for the Hashtable class, missing in: Win8RT and Windows Phone. It uses a Dictionary<object,object> as base. + + + Please be aware that this class might act differently than the Hashtable equivalent. + As far as Photon is concerned, the substitution is sufficiently precise. + + + + + Creates a shallow copy of the Hashtable. + + + A shallow copy of a collection copies only the elements of the collection, whether they are + reference types or value types, but it does not copy the objects that the references refer + to. The references in the new collection point to the same objects that the references in + the original collection point to. + + Shallow copy of the Hashtable. + + + + Contains several (more or less) useful static methods, mostly used for debugging. + + + + + Gets the local machine's "milliseconds since start" value (precision is described in remarks). + + + This method uses Environment.TickCount (cheap but with only 16ms precision). + PhotonPeer.LocalMsTimestampDelegate is available to set the delegate (unless already connected). + + Fraction of the current time in Milliseconds (this is not a proper datetime timestamp). + + + + Creates a background thread that calls the passed function in 100ms intervals, as long as that returns true. + + + + + Creates a background thread that calls the passed function in intervals, as long as that returns true. + + The function to call. Must return true, if it should be called again. + Milliseconds to sleep between calls of myThread. Default: 100ms. + An optional name for the task for eased debugging. + + + + Ends the thread with the given id (= index of the thread list). + + The unique ID of the thread. + True if the thread is canceled and false otherwise, e.g. if the thread with the given ID does not exist. + + + + Ends the thread with the given id (= index of the thread list). + + The unique ID of the thread. + True if the thread is canceled and false otherwise, e.g. if the thread with the given ID does not exist. + + + + Writes the exception's stack trace to the received stream. + + Exception to obtain information from. + Output sream used to write to. + + + + Writes the exception's stack trace to the received stream. Writes to: System.Diagnostics.Debug. + + Exception to obtain information from. + + + + This method returns a string, representing the content of the given IDictionary. + Returns "null" if parameter is null. + + + IDictionary to return as string. + + + The string representation of keys and values in IDictionary. + + + + + This method returns a string, representing the content of the given IDictionary. + Returns "null" if parameter is null. + + IDictionary to return as string. + + + + + Converts a byte-array to string (useful as debugging output). + Uses BitConverter.ToString(list) internally after a null-check of list. + + Byte-array to convert to string. + + List of bytes as string. + + + + + Class to wrap static access to the random.Next() call in a thread safe manner. + + + + + Defines block size for encryption/decryption algorithm + + + + + Defines IV size for encryption/decryption algorithm + + + + + Defines HMAC size for packet authentication algorithm + + + + + Enumeration of situations that change the peers internal status. + Used in calls to OnStatusChanged to inform your application of various situations that might happen. + + + Most of these codes are referenced somewhere else in the documentation when they are relevant to methods. + + + + the PhotonPeer is connected.
See {@link PhotonListener#OnStatusChanged}*
+
+ + the PhotonPeer just disconnected.
See {@link PhotonListener#OnStatusChanged}*
+
+ + the PhotonPeer encountered an exception and will disconnect, too.
See {@link PhotonListener#OnStatusChanged}*
+
+ + the PhotonPeer encountered an exception while opening the incoming connection to the server. The server could be down / not running or the client has no network or a misconfigured DNS.
See {@link PhotonListener#OnStatusChanged}*
+
+ + Used on platforms that throw a security exception on connect. Unity3d does this, e.g., if a webplayer build could not fetch a policy-file from a remote server. + + + PhotonPeer outgoing queue is filling up. send more often. + + + PhotonPeer outgoing queue is filling up. send more often. + + + Sending command failed. Either not connected, or the requested channel is bigger than the number of initialized channels. + + + PhotonPeer outgoing queue is filling up. send more often. + + + PhotonPeer incoming queue is filling up. Dispatch more often. + + + PhotonPeer incoming queue is filling up. Dispatch more often. + + + PhotonPeer incoming queue is filling up. Dispatch more often. + + + Exception, if a server cannot be connected. Most likely, the server is not responding. Ask user to try again later. + + + Disconnection due to a timeout (client did no longer receive ACKs from server). + + + Disconnect by server due to timeout (received a disconnect command, cause server misses ACKs of client). + + + Disconnect by server due to concurrent user limit reached (received a disconnect command). + + + Disconnect by server due to server's logic (received a disconnect command). + + + (1048) Value for OnStatusChanged()-call, when the encryption-setup for secure communication finished successfully. + + + (1049) Value for OnStatusChanged()-call, when the encryption-setup failed for some reason. Check debug logs. + + + + Callback interface for the Photon client side. Must be provided to a new PhotonPeer in its constructor. + + + These methods are used by your PhotonPeer instance to keep your app updated. Read each method's + description and check out the samples to see how to use them. + + + + + Provides textual descriptions for various error conditions and noteworthy situations. + In cases where the application needs to react, a call to OnStatusChanged is used. + OnStatusChanged gives "feedback" to the game, DebugReturn provies human readable messages + on the background. + + + All debug output of the library will be reported through this method. Print it or put it in a + buffer to use it on-screen. Use PhotonPeer.DebugOut to select how verbose the output is. + + DebugLevel (severity) of the message. + Debug text. Print to System.Console or screen. + + + + Callback method which gives you (async) responses for called operations. + + + Similar to method-calling, operations can have a result. + Because operation-calls are non-blocking and executed on the server, responses are provided + after a roundtrip as call to this method. + + Example: Trying to create a room usually succeeds but can fail if the room's name is already + in use (room names are their IDs). + + This method is used as general callback for all operations. Each response corresponds to a certain + "type" of operation by its OperationCode. + + + + When you join a room, the server will assign a consecutive number to each client: the + "actorNr" or "player number". This is sent back in the OperationResult's + Parameters as value of key . + + Fetch your actorNr of a Join response like this: + int actorNr = (int)operationResponse[(byte)OperationCode.ActorNr]; + + The response to an operation\-call. + + + + OnStatusChanged is called to let the game know when asyncronous actions finished or when errors happen. + + + Not all of the many StatusCode values will apply to your game. Example: If you don't use encryption, + the respective status changes are never made. + + The values are all part of the StatusCode enumeration and described value-by-value. + + A code to identify the situation. + + + + Called whenever an event from the Photon Server is dispatched. + + + Events are used for communication between clients and allow the server to update clients over time. + The creation of an event is often triggered by an operation (called by this client or an other). + + Each event carries its specific content in its Parameters. Your application knows which content to + expect by checking the event's 'type', given by the event's Code. + + Events can be defined and extended server-side. + + If you use the LoadBalancing application as base, several events like EvJoin and EvLeave are already defined. + For these events and their Parameters, the library provides constants, so check the EventCode and ParameterCode + classes. + + Photon also allows you to come up with custom events on the fly, purely client-side. To do so, use + OpRaiseEvent. + + Events are buffered on the client side and must be Dispatched. This way, OnEvent is always taking + place in the same thread as a call. + + The event currently being dispatched. + + + + The bytes between Position and Length are copied to the beginning of the buffer. Length decreased by Position. Position set to 0. + + + + + Brings StreamBuffer to the state as after writing of 'length' bytes. Returned buffer and offset can be used to actually fill "written" segment with data. + + + + + Sets stream length. If current position is greater than specified value, it's set to the value. + + + SetLength(0) resets the stream to initial state but preserves underlying byte[] buffer. + + + + + Guarantees that the buffer is at least neededSize bytes. + + + + + Value range for a Peer's connection and initialization state, as returned by the PeerState property. + + + While this is not the same as the StatusCode of IPhotonPeerListener.OnStatusChanged(), it directly relates to it. + In most cases, it makes more sense to build a game's state on top of the OnStatusChanged() as you get changes. + + + + The peer is disconnected and can't call Operations. Call Connect(). + + + The peer is establishing the connection: opening a socket, exchanging packages with Photon. + + + The connection is established and now sends the application name to Photon. + You set the "application name" by calling PhotonPeer.Connect(). + + + The peer is connected and initialized (selected an application). You can now use operations. + + + The peer is disconnecting. It sent a disconnect to the server, which will acknowledge closing the connection. + + + + These are the options that can be used as underlying transport protocol. + + + + Use UDP to connect to Photon, which allows you to send operations reliable or unreliable on demand. + + + Use TCP to connect to Photon. + + + A TCP-based protocol commonly supported by browsers.For WebGL games mostly. Note: No WebSocket IPhotonSocket implementation is in this Assembly. + This protocol is only available in Unity exports to WebGL. + + + A TCP-based, encrypted protocol commonly supported by browsers. For WebGL games mostly. Note: No WebSocket IPhotonSocket implementation is in this Assembly. + This protocol is only available in Unity exports to WebGL. + + + + Level / amount of DebugReturn callbacks. Each debug level includes output for lower ones: OFF, ERROR, WARNING, INFO, ALL. + + + + No debug out. + + + Only error descriptions. + + + Warnings and errors. + + + Information about internal workflows, warnings and errors. + + + Most complete workflow description (but lots of debug output), info, warnings and errors. + + + + Instances of the PhotonPeer class are used to connect to a Photon server and communicate with it. + + + A PhotonPeer instance allows communication with the Photon Server, which in turn distributes messages + to other PhotonPeer clients. + An application can use more than one PhotonPeer instance, which are treated as separate users on the + server. Each should have its own listener instance, to separate the operations, callbacks and events. + + + + False if this library build contains C# Socket code. If true, you must set some type as SocketImplementation before connecting. + + + True, if this library needs a native Photon "Encryptor" plugin library for "Datagram Encryption". If false, this dll attempts to use managed encryption. + + + True if the library was compiled with DEBUG setting. + + + A simplified identifier for client SDKs. Photon's APIs might modify this (as a dll can be used in more than one product). Helps debugging. + + + For the Init-request, we shift the ClientId by one and the last bit signals a "debug" (0) or "release" build (1). + + + Defines if Key Exchange for Encryption is done asynchronously in another thread. + + + Version of this library as string. + + + Enables selection of a (Photon-)serialization protocol. Used in Connect methods. + Defaults to SerializationProtocol.GpBinaryV16; + + + Defines which IPhotonSocket class to use per ConnectionProtocol. + + Several platforms have special Socket implementations and slightly different APIs. + To accomodate this, switching the socket implementation for a network protocol was made available. + By default, UDP and TCP have socket implementations assigned. + + You only need to set the SocketImplementationConfig once, after creating a PhotonPeer + and before connecting. If you switch the TransportProtocol, the correct implementation is being used. + + + + + Can be used to read the IPhotonSocket implementation at runtime (before connecting). + + + Use the SocketImplementationConfig to define which IPhotonSocket is used per ConnectionProtocol. + + + + + Sets the level (and amount) of debug output provided by the library. + + + This affects the callbacks to IPhotonPeerListener.DebugReturn. + Default Level: Error. + + + + + Gets the IPhotonPeerListener of this instance (set in constructor). + Can be used in derived classes for Listener.DebugReturn(). + + + + + Gets count of all bytes coming in (including headers, excluding UDP/TCP overhead) + + + + + Gets count of all bytes going out (including headers, excluding UDP/TCP overhead) + + + + + Gets the size of the dispatched event or operation-result in bytes. + This value is set before OnEvent() or OnOperationResponse() is called (within DispatchIncomingCommands()). + + + Get this value directly in OnEvent() or OnOperationResponse(). Example: + void OnEvent(...) { + int eventSizeInBytes = this.peer.ByteCountCurrentDispatch; + //... + + void OnOperationResponse(...) { + int resultSizeInBytes = this.peer.ByteCountCurrentDispatch; + //... + + + + Returns the debug string of the event or operation-response currently being dispatched or string. Empty if none. + In a release build of the lib, this will always be empty. + + + + Gets the size of the last serialized operation call in bytes. + The value includes all headers for this single operation but excludes those of UDP, Enet Package Headers and TCP. + + + Get this value immediately after calling an operation. + Example: + + this.loadbalancingClient.OpJoinRoom("myroom"); + int opjoinByteCount = this.loadbalancingClient.ByteCountLastOperation; + + + + + Gets the byte-count of incoming "low level" messages, which are either Enet Commands or Tcp Messages. + These include all headers, except those of the underlying internet protocol Udp or Tcp. + + + + + Gets the byte-count of outgoing "low level" messages, which are either Enet Commands or Tcp Messages. + These include all headers, except those of the underlying internet protocol Udp or Tcp. + + + + + Gets a statistic of incoming and outgoing traffic, split by operation, operation-result and event. + + + Operations are outgoing traffic, results and events are incoming. + Includes the per-command header sizes (Udp: Enet Command Header or Tcp: Message Header). + + + + + Returns the count of milliseconds the stats are enabled for tracking. + + + + + Enables or disables collection of statistics in TrafficStatsIncoming, TrafficStatsOutgoing and TrafficstatsGameLevel. + + + Setting this to true, also starts the stopwatch to measure the timespan the stats are collected. + Enables the traffic statistics of a peer: TrafficStatsIncoming, TrafficStatsOutgoing and TrafficstatsGameLevel (nothing else). + Default value: false (disabled). + + + + + Creates new instances of TrafficStats and starts a new timer for those. + + + + Size of CommandLog. Default is 0, no logging. + + A bigger log is better for debugging but uses more memory. + Get the log as string via CommandLogToString. + + + + Converts the CommandLog into a readable table-like string with summary. + + Sent reliable commands begin with SND. Their acknowledgements with ACK. + ACKs list the reliable sequence number of the command they acknowledge (not their own). + Careful: This method should not be called frequently, as it's time- and memory-consuming to create the log. + + + + + Debugging option to tell the Photon Server to log all datagrams. + + + + + Up to 4 resend attempts for a reliable command can be done in quick succession (after RTT+4*Variance). + + + By default 0. Any later resend attempt will then double the time before the next resend. + Max value = 4; + Make sure to adjust SentCountAllowance to a slightly higher value, as more repeats will get done. + + + + + This is the (low level) state of the connection to the server of a PhotonPeer. Managed internally and read-only. + + + Don't mix this up with the StatusCode provided in IPhotonListener.OnStatusChanged(). + Applications should use the StatusCode of OnStatusChanged() to track their state, as + it also covers the higher level initialization between a client and Photon. + + + + + This peer's ID as assigned by the server or 0 if not using UDP. Will be 0xFFFF before the client connects. + + Used for debugging only. This value is not useful in everyday Photon usage. + + + + Initial size internal lists for incoming/outgoing commands (reliable and unreliable). + + + This sets only the initial size. All lists simply grow in size as needed. This means that + incoming or outgoing commands can pile up and consume heap size if Service is not called + often enough to handle the messages in either direction. + + Configure the WarningSize, to get callbacks when the lists reach a certain size. + + UDP: Incoming and outgoing commands each have separate buffers for reliable and unreliable sending. + There are additional buffers for "sent commands" and "ACKs". + TCP: Only two buffers exist: incoming and outgoing commands. + + + + (default=2) minimum number of open connections + + + (default=6) maximum number of open connections, should be > RhttpMinConnections + + + + Limits the queue of received unreliable commands within DispatchIncomingCommands before dispatching them. + This works only in UDP. + This limit is applied when you call DispatchIncomingCommands. If this client (already) received more than + LimitOfUnreliableCommands, it will throw away the older ones instead of dispatching them. This can produce + bigger gaps for unreliable commands but your client catches up faster. + + + This can be useful when the client couldn't dispatch anything for some time (cause it was in a room but + loading a level). + If set to 20, the incoming unreliable queues are truncated to 20. + If 0, all received unreliable commands will be dispatched. + This is a "per channel" value, so each channel can hold up to LimitOfUnreliableCommands commands. + This value interacts with DispatchIncomingCommands: If that is called less often, more commands get skipped. + + + + + Count of all currently received but not-yet-Dispatched reliable commands + (events and operation results) from all channels. + + + + + Count of all commands currently queued as outgoing, including all channels and reliable, unreliable. + + + + + Gets / sets the number of channels available in UDP connections with Photon. + Photon Channels are only supported for UDP. + The default ChannelCount is 2. Channel IDs start with 0 and 255 is a internal channel. + + + + + While not connected, this controls if the next connection(s) should use a per-package CRC checksum. + + + While turned on, the client and server will add a CRC checksum to every sent package. + The checksum enables both sides to detect and ignore packages that were corrupted during transfer. + Corrupted packages have the same impact as lost packages: They require a re-send, adding a delay + and could lead to timeouts. + + Building the checksum has a low processing overhead but increases integrity of sent and received data. + Packages discarded due to failed CRC cecks are counted in PhotonPeer.PacketLossByCrc. + + + + + Count of packages dropped due to failed CRC checks for this connection. + + + + + + Count of packages dropped due to wrong challenge for this connection. + + + + + Count of commands that got repeated (due to local repeat-timing before an ACK was received). + + + + + The WarningSize was used test all message queues for congestion. + + + + + Number of send retries before a peer is considered lost/disconnected. Default: 7. + The initial timeout countdown of a command is calculated by the current roundTripTime + 4 * roundTripTimeVariance. + Please note that the timeout span until a command will be resent is not constant, but based on + the roundtrip time at the initial sending, which will be doubled with every failed retry. + + DisconnectTimeout and SentCountAllowance are competing settings: either might trigger a disconnect on the + client first, depending on the values and Roundtrip Time. + + + + + Sets the milliseconds without reliable command before a ping command (reliable) will be sent (Default: 1000ms). + The ping command is used to keep track of the connection in case the client does not send reliable commands + by itself. + A ping (or reliable commands) will update the RoundTripTime calculation. + + + + + Milliseconds before an individual command must be ACKed by server - after this a timeout-disconnect is triggered. + DisconnectTimeout is not an exact value for a timeout. The exact timing of the timeout depends on the frequency + of Service() calls and commands that are sent with long roundtrip-times and variance are checked less often for + re-sending! + + DisconnectTimeout and SentCountAllowance are competing settings: either might trigger a disconnect on the + client first, depending on the values and Roundtrip Time. + Default: 10000 ms. + + + + + Approximated Environment.TickCount value of server (while connected). + + + UDP: The server's timestamp is automatically fetched after connecting (once). This is done + internally by a command which is acknowledged immediately by the server. + TCP: The server's timestamp fetched with each ping but set only after connecting (once). + + The approximation will be off by +/- 10ms in most cases. Per peer/client and connection, the + offset will be constant (unless FetchServerTimestamp() is used). A constant offset should be + better to adjust for. Unfortunately there is no way to find out how much the local value + differs from the original. + + The approximation adds RoundtripTime / 2 and uses this.LocalTimeInMilliSeconds to calculate + in-between values (this property returns a new value per tick). + + The value sent by Photon equals Environment.TickCount in the logic layer. + + + 0 until connected. + While connected, the value is an approximation of the server's current timestamp. + + + + The internally used "per connection" time value, which is updated infrequently, when the library executes some connectio-related tasks. + + This integer value is an infrequently updated value by design. + The lib internally sets the value when it sends outgoing commands or reads incoming packages. + This is based on SupportClass.GetTickCount() and an initial time value per (server) connection. + This value is also used in low level Enet commands as sent time and optional logging. + + + + The last ConnectionTime value, when some ACKs were sent out by this client. + Only applicable to UDP connections. + + + The last ConnectionTime value, when SendOutgoingCommands actually checked outgoing queues to send them. Must be connected. + Available for UDP and TCP connections. + + + + Gets a local timestamp in milliseconds by calling SupportClass.GetTickCount(). + See LocalMsTimestampDelegate. + + + + + This setter for the (local-) timestamp delegate replaces the default Environment.TickCount with any equal function. + + + About Environment.TickCount: + The value of this property is derived from the system timer and is stored as a 32-bit signed integer. + Consequently, if the system runs continuously, TickCount will increment from zero to Int32..::.MaxValue + for approximately 24.9 days, then jump to Int32..::.MinValue, which is a negative number, then increment + back to zero during the next 24.9 days. + + Exception is thrown peer.PeerState is not PS_DISCONNECTED. + + + + Time until a reliable command is acknowledged by the server. + + The value measures network latency and for UDP it includes the server's ACK-delay (setting in config). + In TCP, there is no ACK-delay, so the value is slightly lower (if you use default settings for Photon). + + RoundTripTime is updated constantly. Every reliable command will contribute a fraction to this value. + + This is also the approximate time until a raised event reaches another client or until an operation + result is available. + + + + + Changes of the roundtriptime as variance value. Gives a hint about how much the time is changing. + + + + + + The server address which was used in PhotonPeer.Connect() or null (before Connect() was called). + + + The ServerAddress can only be changed for HTTP connections (to replace one that goes through a Loadbalancer with a direct URL). + + + + The protocol this peer is currently connected/connecting with (or 0). + + + This is the transport protocol to be used for next connect (see remarks). + The TransportProtocol can be changed anytime but it will not change the + currently active connection. Instead, TransportProtocol will be applied on next Connect. + + + + + Gets or sets the network simulation "enabled" setting. + Changing this value also locks this peer's sending and when setting false, + the internally used queues are executed (so setting to false can take some cycles). + + + + + Gets the settings for built-in Network Simulation for this peer instance + while IsSimulationEnabled will enable or disable them. + Once obtained, the settings can be modified by changing the properties. + + + + + Defines the initial size of an internally used StreamBuffer for Tcp. + The StreamBuffer is used to aggregate operation into (less) send calls, + which uses less resoures. + + + The size is not restricing the buffer and does not affect when poutgoing data is actually sent. + + + + + The Maximum Trasfer Unit (MTU) defines the (network-level) packet-content size that is + guaranteed to arrive at the server in one piece. The Photon Protocol uses this + size to split larger data into packets and for receive-buffers of packets. + + + This value affects the Packet-content. The resulting UDP packages will have additional + headers that also count against the package size (so it's bigger than this limit in the end) + Setting this value while being connected is not allowed and will throw an Exception. + Minimum is 576. Huge values won't speed up connections in most cases! + + + + + This property is set internally, when OpExchangeKeysForEncryption successfully finished. + While it's true, encryption can be used for operations. + + + + + While true, the peer will not send any other commands except ACKs (used in UDP connections). + + + + Implements the message-protocol, based on the underlying network protocol (udp, tcp, http). + + + + Creates a new PhotonPeer instance to communicate with Photon and selects the transport protocol. We recommend UDP. + + a IPhotonPeerListener implementation + Protocol to use to connect to Photon. + + + + Connects to a Photon server. This wraps up DNS name resolution, sending the AppId and establishing encryption. + + + This method does a DNS lookup (if necessary) and connects to the given serverAddress. + + The return value gives you feedback if the address has the correct format. If so, this + starts the process to establish the connection itself, which might take a few seconds. + + When the connection is established, a callback to IPhotonPeerListener.OnStatusChanged + will be done. If the connection can't be established, despite having a valid address, + the OnStatusChanged is called with an error-value. + + The applicationName defines the application logic to use server-side and it should match the name of + one of the apps in your server's config. + + By default, the applicationName is "LoadBalancing" but there is also the "MmoDemo". + You can setup your own application and name it any way you like. + + + Address of the Photon server. Format: ip:port (e.g. 127.0.0.1:5055) or hostname:port (e.g. localhost:5055) + + + The name of the application to use within Photon or the appId of PhotonCloud. + Should match a "Name" for an application, as setup in your PhotonServer.config. + + + true if IP is available (DNS name is resolved) and server is being connected. false on error. + + + + + Connects to a Photon server. This wraps up DNS name resolution, sending the AppId and establishing encryption. + + + This method does a DNS lookup (if necessary) and connects to the given serverAddress. + + The return value gives you feedback if the address has the correct format. If so, this + starts the process to establish the connection itself, which might take a few seconds. + + When the connection is established, a callback to IPhotonPeerListener.OnStatusChanged + will be done. If the connection can't be established, despite having a valid address, + the OnStatusChanged is called with an error-value. + + The applicationName defines the application logic to use server-side and it should match the name of + one of the apps in your server's config. + + By default, the applicationName is "LoadBalancing" but there is also the "MmoDemo". + You can setup your own application and name it any way you like. + + + Address of the Photon server. Format: ip:port (e.g. 127.0.0.1:5055) or hostname:port (e.g. localhost:5055) + + + The name of the application to use within Photon or the appId of PhotonCloud. + Should match a "Name" for an application, as setup in your PhotonServer.config. + + + Allows you to send some data, which may be used by server during peer creation + (e.g. as additional authentication info). + You can use any serializable data type of Photon. + Helpful for self-hosted solutions. Server will read this info on peer creation stage, + and may reject client without creating of peer if auth info is invalid. + + + true if IP is available (DNS name is resolved) and server is being connected. false on error. + + + + + This method initiates a mutual disconnect between this client and the server. + + + Calling this method does not immediately close a connection. Disconnect lets the server + know that this client is no longer listening. For the server, this is a much faster way + to detect that the client is gone but it requires the client to send a few final messages. + + On completion, OnStatusChanged is called with the StatusCode.Disconnect. + + If the client is disconnected already or the connection thread is stopped, then there is no callback. + + The default server logic will leave any joined game and trigger the respective event + () for the remaining players. + + + + + This method immediately closes a connection (pure client side) and ends related listening Threads. + + + Unlike Disconnect, this method will simply stop to listen to the server. Udp connections will timeout. + If the connections was open, this will trigger a callback to OnStatusChanged with code StatusCode.Disconnect. + + + + + This will fetch the server's timestamp and update the approximation for property ServerTimeInMilliseconds. + + + The server time approximation will NOT become more accurate by repeated calls. Accuracy currently depends + on a single roundtrip which is done as fast as possible. + + The command used for this is immediately acknowledged by the server. This makes sure the roundtrip time is + low and the timestamp + rountriptime / 2 is close to the original value. + + + + + This method creates a public key for this client and exchanges it with the server. + + + Encryption is not instantly available but calls OnStatusChanged when it finishes. + Check for StatusCode EncryptionEstablished and EncryptionFailedToEstablish. + + Calling this method sets IsEncryptionAvailable to false. + This method must be called before the "encrypt" parameter of OpCustom can be used. + + If operation could be enqueued for sending + + + PayloadEncryption Secret. Message payloads get encrypted with it individually and on demand. + + + + Initializes Datagram Encryption. + + secret used to chipher udp packets + secret used for authentication of udp packets + + + + This method excutes DispatchIncomingCommands and SendOutgoingCommands in your application Thread-context. + + + The Photon client libraries are designed to fit easily into a game or application. The application + is in control of the context (thread) in which incoming events and responses are executed and has + full control of the creation of UDP/TCP packages. + + Sending packages and dispatching received messages are two separate tasks. Service combines them + into one method at the cost of control. It calls DispatchIncomingCommands and SendOutgoingCommands. + + Call this method regularly (2..20 times a second). + + This will Dispatch ANY remaining buffered responses and events AND will send queued outgoing commands. + Fewer calls might be more effective if a device cannot send many packets per second, as multiple + operations might be combined into one package. + + + You could replace Service by: + + while (DispatchIncomingCommands()); //Dispatch until everything is Dispatched... + SendOutgoingCommands(); //Send a UDP/TCP package with outgoing messages + + + + + + + Creates and sends a UDP/TCP package with outgoing commands (operations and acknowledgements). Also called by Service(). + + + As the Photon library does not create any UDP/TCP packages by itself. Instead, the application + fully controls how many packages are sent and when. A tradeoff, an application will + lose connection, if it is no longer calling SendOutgoingCommands or Service. + + If multiple operations and ACKs are waiting to be sent, they will be aggregated into one + package. The package fills in this order: + ACKs for received commands + A "Ping" - only if no reliable data was sent for a while + Starting with the lowest Channel-Nr: + Reliable Commands in channel + Unreliable Commands in channel + + This gives a higher priority to lower channels. + + A longer interval between sends will lower the overhead per sent operation but + increase the internal delay (which adds "lag"). + + Call this 2..20 times per second (depending on your target platform). + + The if commands are not yet sent. Udp limits it's package size, Tcp doesnt. + + + + Dispatching received messages (commands), causes callbacks for events, responses and state changes within a IPhotonPeerListener. + + + DispatchIncomingCommands only executes a single received + command per call. If a command was dispatched, the return value is true and the method + should be called again. + + This method is called by Service() until currently available commands are dispatched. + In general, this method should be called until it returns false. In a few cases, it might + make sense to pause dispatching (if a certain state is reached and the app needs to load + data, before it should handle new events). + + The callbacks to the peer's IPhotonPeerListener are executed in the same thread that is + calling DispatchIncomingCommands. This makes things easier in a game loop: Event execution + won't clash with painting objects or the game logic. + + + + + Returns a string of the most interesting connection statistics. + When you have issues on the client side, these might contain hints about the issue's cause. + + If true, Incoming and Outgoing low-level stats are included in the string. + Stats as string. + + + + Channel-less wrapper for OpCustom(). + + Operations are handled by their byte\-typed code. + The codes of the "LoadBalancong" application are in the class . + Containing parameters as key\-value pair. The key is byte\-typed, while the value is any serializable datatype. + Selects if the operation must be acknowledged or not. If false, the + operation is not guaranteed to reach the server. + If operation could be enqueued for sending + + + + Allows the client to send any operation to the Photon Server by setting any opCode and the operation's parameters. + + + Photon can be extended with new operations which are identified by a single + byte, defined server side and known as operation code (opCode). Similarly, the operation's parameters + are defined server side as byte keys of values, which a client sends as customOpParameters + accordingly. + Operations are handled by their byte\-typed code. The codes of the + "LoadBalancing" application are in the class . + Containing parameters as key\-value pair. The key is byte\-typed, while the value is any serializable datatype. + Selects if the operation must be acknowledged or not. If false, the + operation is not guaranteed to reach the server. + The channel in which this operation should be sent. + If operation could be enqueued for sending + + + + Allows the client to send any operation to the Photon Server by setting any opCode and the operation's parameters. + + + Variant with encryption parameter. + + Use this only after encryption was established by EstablishEncryption and waiting for the OnStateChanged callback. + + Operations are handled by their byte\-typed code. The codes of the + "LoadBalancing" application are in the class . + Containing parameters as key\-value pair. The key is byte\-typed, while the value is any serializable datatype. + Selects if the operation must be acknowledged or not. If false, the + operation is not guaranteed to reach the server. + The channel in which this operation should be sent. + Can only be true, while IsEncryptionAvailable is true, too. + If operation could be enqueued for sending + + + + Allows the client to send any operation to the Photon Server by setting any opCode and the operation's parameters. + + + Variant with an OperationRequest object. + + This variant offers an alternative way to describe a operation request. Operation code and it's parameters + are wrapped up in a object. Still, the parameters are a Dictionary. + + The operation to call on Photon. + Use unreliable (false) if the call might get lost (when it's content is soon outdated). + Defines the sequence of requests this operation belongs to. + Encrypt request before sending. Depends on IsEncryptionAvailable. + If operation could be enqueued for sending + + + + Registers new types/classes for de/serialization and the fitting methods to call for this type. + + + SerializeMethod and DeserializeMethod are complementary: Feed the product of serializeMethod to + the constructor, to get a comparable instance of the object. + + After registering a Type, it can be used in events and operations and will be serialized like + built-in types. + + Type (class) to register. + A byte-code used as shortcut during transfer of this Type. + Method delegate to create a byte[] from a customType instance. + Method delegate to create instances of customType's from byte[]. + If the Type was registered successfully. + + + Param code. Used in internal op: InitEncryption. + + + Encryption-Mode code. Used in internal op: InitEncryption. + + + Param code. Used in internal op: InitEncryption. + + + Code of internal op: InitEncryption. + + + TODO: Code of internal op: Ping (used in PUN binary websockets). + + + Result code for any (internal) operation. + + + The server's address, as set by a Connect() call, including any protocol, ports and or path. + If rHTTP is used, this can be set directly. + + + Byte count of last sent operation (set during serialization). + + + Byte count of last dispatched message (set during dispatch/deserialization). + + + The command that's currently being dispatched. + + + EnetPeer will set this value, so trafficstats can use it. TCP has 0 bytes per package extra + + + See PhotonPeer value. + + + See PhotonPeer value. + + + See PhotonPeer value. + + + See PhotonPeer value. + + + This ID is assigned by the Realtime Server upon connection. + The application does not have to care about this, but it is useful in debugging. + + + + This is the (low level) connection state of the peer. It's internal and based on eNet's states. + + Applications can read the "high level" state as PhotonPeer.PeerState, which uses a different enum. + + + + The serverTimeOffset is serverTimestamp - localTime. Used to approximate the serverTimestamp with help of localTime + + + + + Gets the currently used settings for the built-in network simulation. + Please check the description of NetworkSimulationSet for more details. + + + + Size of CommandLog. Default is 0, no logging. + + + Log of sent reliable commands and incoming ACKs. + + + Log of incoming reliable commands, used to track which commands from the server this client got. Part of the PhotonPeer.CommandLogToString() result. + + + Reduce CommandLog to CommandLogSize. Oldest entries get discarded. + + + Initializes the CommandLog and InReliableLog according to CommandLogSize. A value of 0 will set both logs to 0. + + + Converts the CommandLog into a readable table-like string with summary. + + + + Count of all bytes going out (including headers) + + + + + Count of all bytes coming in (including headers) + + + + Set via Connect(..., customObject) and sent in Init-Request. + + + Temporary cache of AppId. Used in Connect() to keep the AppId until we send the Init-Request (after the network-level (and Enet) connect). + + + + This is the replacement for the const values used in eNet like: PS_DISCONNECTED, PS_CONNECTED, etc. + + + + No connection is available. Use connect. + + + Establishing a connection already. The app should wait for a status callback. + + + + The low level connection with Photon is established. On connect, the library will automatically + send an Init package to select the application it connects to (see also PhotonPeer.Connect()). + When the Init is done, IPhotonPeerListener.OnStatusChanged() is called with connect. + + Please note that calling operations is only possible after the OnStatusChanged() with StatusCode.Connect. + + + Connection going to be ended. Wait for status callback. + + + Acknowledging a disconnect from Photon. Wait for status callback. + + + Connection not properly disconnected. + + + Set to timeInt, whenever SendOutgoingCommands actually checks outgoing queues to send them. Must be connected. + + + Connect to server and send Init (which inlcudes the appId). + If customData is not null, the new init will be used (http-based). + + + If IPhotonSocket.Connected is true, this value shows if the server's address resolved as IPv6 address. + + You must check the socket's IsConnected state. Otherwise, this value is not initialized. + Sent to server in Init-Request. + + + + Must be called by a IPhotonSocket when it connected to set IsIpv6. + The new value of IsIpv6. + + + + + + + + + + + + Checks the incoming queue and Dispatches received data if possible. + + If a Dispatch happened or not, which shows if more Dispatches might be needed. + + + + Checks outgoing queues for commands to send and puts them on their way. + This creates one package per go in UDP. + + If commands are not sent, cause they didn't fit into the package that's sent. + + + Returns the UDP Payload starting with Magic Number for binary protocol + + + Maximum Transfer Unit to be used for UDP+TCP + + + (default=2) Rhttp: minimum number of open connections + + + (default=6) Rhttp: maximum number of open connections, should be > rhttpMinConnections + + + + Internally uses an operation to exchange encryption keys with the server. + + If the op could be sent. + + + + Core of the Network Simulation, which is available in Debug builds. + Called by a timer in intervals. + + + + One list for all channels keeps sent commands (for re-sending). + + + One pool of ACK byte arrays ( 20 bytes each) for all channels to keep acknowledgements. + + + Gets enabled by "request" from server (not by client). + + + Initial PeerId as used in Connect command. If EnableServerTracing is false. + + + Initial PeerId to enable Photon Tracing, as used in Connect command. See: EnableServerTracing. + + + + Checks the incoming queue and Dispatches received data if possible. + + If a Dispatch happened or not, which shows if more Dispatches might be needed. + + + + gathers acks until udp-packet is full and sends it! + + + + + gathers commands from all (out)queues until udp-packet is full and sends it! + + + + + Checks if any channel has a outgoing reliable command. + + True if any channel has a outgoing reliable command. False otherwise. + + + + Checks connected state and channel before operation is serialized and enqueued for sending. + + operation parameters + code of operation + send as reliable command + channel (sequence) for command + encrypt or not + usually EgMessageType.Operation + if operation could be enqueued + + + reliable-udp-level function to send some byte[] to the server via un/reliable command + only called when a custom operation should be send + (enet) command type + data to carry (operation) + channel in which to send + the invocation ID for this operation (the payload) + + + Serializes an operation into our binary messages (magic number, msg-type byte and message). Optionally encrypts. + This method is mostly the same in EnetPeer, TPeer and HttpPeerBase. Also, for raw messages, we have another variant. + + + reads incoming udp-packages to create and queue incoming commands* + + + queues incoming commands in the correct order as either unreliable, reliable or unsequenced. return value determines if the command is queued / done. + + + removes commands which are acknowledged* + + + Internal class for "commands" - the package in which operations are sent. + + + this variant does only create outgoing commands and increments . incoming ones are created from a DataInputStream + + + + ACKs should never be created as NCommand. use CreateACK to wrtie the serialized ACK right away... + + + + + + + + + reads the command values (commandHeader and command-values) from incoming bytestream and populates the incoming command* + + + TCP "Package" header: 7 bytes + + + TCP "Message" header: 2 bytes + + + TCP header combined: 9 bytes + + + Defines if the (TCP) socket implementation needs to do "framing". + The WebSocket protocol (e.g.) includes framing, so when that is used, we set DoFraming to false. + + + + Checks the incoming queue and Dispatches received data if possible. Returns if a Dispatch happened or + not, which shows if more Dispatches might be needed. + + + + + gathers commands from all (out)queues until udp-packet is full and sends it! + + + + Sends a ping in intervals to keep connection alive (server will timeout connection if nothing is sent). + Always false in this case (local queues are ignored. true would be: "call again to send remaining data"). + + + Serializes an operation into our binary messages (magic number, msg-type byte and message). Optionally encrypts. + This method is mostly the same in EnetPeer, TPeer and HttpPeerBase. Also, for raw messages, we have another variant. + + + enqueues serialized operations to be sent as tcp stream / package + + + Sends a ping and modifies this.lastPingResult to avoid another ping for a while. + + + reads incoming tcp-packages to create and queue incoming commands* + + + + Serialize creates a byte-array from the given object and returns it. + + The object to serialize + The serialized byte-array + + + + Deserialize returns an object reassembled from the given StreamBuffer. + + The buffer to be Deserialized + The Deserialized object + + + + Deserialize returns an object reassembled from the given byte-array. + + The byte-array to be Deserialized + The Deserialized object + + + + Container for an Operation request, which is a code and parameters. + + + On the lowest level, Photon only allows byte-typed keys for operation parameters. + The values of each such parameter can be any serializable datatype: byte, int, hashtable and many more. + + + + Byte-typed code for an operation - the short identifier for the server's method to call. + + + The parameters of the operation - each identified by a byte-typed code in Photon. + + + + Contains the server's response for an operation called by this peer. + The indexer of this class actually provides access to the Parameters Dictionary. + + + The OperationCode defines the type of operation called on Photon and in turn also the Parameters that + are set in the request. Those are provided as Dictionary with byte-keys. + There are pre-defined constants for various codes defined in the LoadBalancing application. + Check: OperationCode, ParameterCode, etc. + + An operation's request is summarized by the ReturnCode: a short typed code for "Ok" or + some different result. The code's meaning is specific per operation. An optional DebugMessage can be + provided to simplify debugging. + + Each call of an operation gets an ID, called the "invocID". This can be matched to the IDs + returned with any operation calls. This way, an application could track if a certain OpRaiseEvent + call was successful. + + + + The code for the operation called initially (by this peer). + Use enums or constants to be able to handle those codes, like OperationCode does. + + + A code that "summarizes" the operation's success or failure. Specific per operation. 0 usually means "ok". + + + An optional string sent by the server to provide readable feedback in error-cases. Might be null. + + + A Dictionary of values returned by an operation, using byte-typed keys per value. + + + + Alternative access to the Parameters, which wraps up a TryGetValue() call on the Parameters Dictionary. + + The byte-code of a returned value. + The value returned by the server, or null if the key does not exist in Parameters. + + + ToString() override. + Relatively short output of OpCode and returnCode. + + + Extensive output of operation results. + To be used in debug situations only, as it returns a string for each value. + + + + Contains all components of a Photon Event. + Event Parameters, like OperationRequests and OperationResults, consist of a Dictionary with byte-typed keys per value. + + + The indexer of this class provides access to the Parameters Dictionary. + + The operation RaiseEvent allows you to provide custom event content. Defined in LoadBalancing, this + CustomContent will be made the value of key ParameterCode.CustomEventContent. + + + + The event code identifies the type of event. + + + The Parameters of an event is a Dictionary<byte, object>. + + + + Alternative access to the Parameters. + + The key byte-code of a event value. + The Parameters value, or null if the key does not exist in Parameters. + + + ToString() override. + Short output of "Event" and it's Code. + + + Extensive output of the event content. + To be used in debug situations only, as it returns a string for each value. + + + + Type of serialization methods to add custom type support. + Use PhotonPeer.ReisterType() to register new types with serialization and deserialization methods. + + The method will get objects passed that were registered with it in RegisterType(). + Return a byte[] that resembles the object passed in. The framework will surround it with length and type info, so don't include it. + + + + Type of deserialization methods to add custom type support. + Use PhotonPeer.RegisterType() to register new types with serialization and deserialization methods. + + The framwork passes in the data it got by the associated SerializeMethod. The type code and length are stripped and applied before a DeserializeMethod is called. + Return a object of the type that was associated with this method through RegisterType(). + + + + Provides tools for the Exit Games Protocol + + + + + Serialize creates a byte-array from the given object and returns it. + + The object to serialize + The serialized byte-array + + + + Deserialize returns an object reassembled from the given byte-array. + + The byte-array to be Deserialized + The Deserialized object + + + + Serializes a short typed value into a byte-array (target) starting at the also given targetOffset. + The altered offset is known to the caller, because it is given via a referenced parameter. + + The short value to be serialized + The byte-array to serialize the short to + The offset in the byte-array + + + + Serializes an int typed value into a byte-array (target) starting at the also given targetOffset. + The altered offset is known to the caller, because it is given via a referenced parameter. + + The int value to be serialized + The byte-array to serialize the short to + The offset in the byte-array + + + + Serializes an float typed value into a byte-array (target) starting at the also given targetOffset. + The altered offset is known to the caller, because it is given via a referenced parameter. + + The float value to be serialized + The byte-array to serialize the short to + The offset in the byte-array + + + + Deserialize fills the given int typed value with the given byte-array (source) starting at the also given offset. + The result is placed in a variable (value). There is no need to return a value because the parameter value is given by reference. + The altered offset is this way also known to the caller. + + The int value to deserialize into + The byte-array to deserialize from + The offset in the byte-array + + + + Deserialize fills the given short typed value with the given byte-array (source) starting at the also given offset. + The result is placed in a variable (value). There is no need to return a value because the parameter value is given by reference. + The altered offset is this way also known to the caller. + + The short value to deserialized into + The byte-array to deserialize from + The offset in the byte-array + + + + Deserialize fills the given float typed value with the given byte-array (source) starting at the also given offset. + The result is placed in a variable (value). There is no need to return a value because the parameter value is given by reference. + The altered offset is this way also known to the caller. + + The float value to deserialize + The byte-array to deserialize from + The offset in the byte-array + + + + Exit Games GpBinaryV16 protocol implementation + + + + + The gp type. + + + + + Unkown type. + + + + + An array of objects. + + + This type is new in version 1.5. + + + + + A boolean Value. + + + + + A byte value. + + + + + An array of bytes. + + + + + An array of objects. + + + + + A 16-bit integer value. + + + + + A 32-bit floating-point value. + + + This type is new in version 1.5. + + + + + A dictionary + + + This type is new in version 1.6. + + + + + A 64-bit floating-point value. + + + This type is new in version 1.5. + + + + + A Hashtable. + + + + + A 32-bit integer value. + + + + + An array of 32-bit integer values. + + + + + A 64-bit integer value. + + + + + A string value. + + + + + An array of string values. + + + + + A custom type. 0x63 + + + + + Null value don't have types. + + + + + Calls the correct serialization method for the passed object. + + + + + DeserializeInteger returns an Integer typed value from the given stream. + + + + Uses C# Socket class from System.Net.Sockets (as Unity usually does). + Incompatible with Windows 8 Store/Phone API. + + + + Sends a "Photon Ping" to a server. + + Address in IPv4 or IPv6 format. An address containing a '.' will be interpretet as IPv4. + True if the Photon Ping could be sent. + + + The protocol for this socket, defined in constructor. + + + Address, as defined via a Connect() call. Including protocol, port and or path. + + + Contains only the server's hostname (stripped protocol, port and or path). Set in IphotonSocket.Connect(). + + + Contains only the server's port address (as string). Set in IphotonSocket.Connect(). + + + Where available, this exposes if the server's address was resolved into an IPv6 address or not. + + + + Separates the given address into address (host name or IP) and port. Port must be included after colon! + + + This method expects any address to include a port. The final ':' in addressAndPort has to separate it. + IPv6 addresses have multiple colons and must use brackets to separate address from port. + + Examples: + ns.exitgames.com:5058 + http://[2001:db8:1f70::999:de8:7648:6e8]:100/ + [2001:db8:1f70::999:de8:7648:6e8]:100 + See: + http://serverfault.com/questions/205793/how-can-one-distinguish-the-host-and-the-port-in-an-ipv6-url + + + + Implements a (very) simple test if a (valid) IPAddress is IPv6 by testing for colons (:). + The reason we use this, is that some DotNet platforms don't provide (or allow usage of) the System.Net namespace. + A valid IPAddress or null. + If the IPAddress.ToString() contains a colon (which means it's IPv6). + + + + Returns null or the IPAddress representing the address, doing Dns resolution if needed. + + Only returns IPv4 or IPv6 adresses, no others. + The string address of a server (hostname or IP). + IPAddress for the string address or null, if the address is neither IPv4, IPv6 or some hostname that could be resolved. + + + Internal class to encapsulate the network i/o functionality for the realtime libary. + + + used by PhotonPeer* + + + Endless loop, run in Receive Thread. + + + + Internal class to encapsulate the network i/o functionality for the realtime libary. + + + + + used by TPeer* + + + + + A simulation item is an action that can be queued to simulate network lag. + + + + With this, the actual delay can be measured, compared to the intended lag. + + + Timestamp after which this item must be executed. + + + Action to execute when the lag-time passed. + + + Starts a new Stopwatch + + + + A set of network simulation settings, enabled (and disabled) by PhotonPeer.IsSimulationEnabled. + + + For performance reasons, the lag and jitter settings can't be produced exactly. + In some cases, the resulting lag will be up to 20ms bigger than the lag settings. + Even if all settings are 0, simulation will be used. Set PhotonPeer.IsSimulationEnabled + to false to disable it if no longer needed. + + All lag, jitter and loss is additional to the current, real network conditions. + If the network is slow in reality, this will add even more lag. + The jitter values will affect the lag positive and negative, so the lag settings + describe the medium lag even with jitter. The jitter influence is: [-jitter..+jitter]. + Packets "lost" due to OutgoingLossPercentage count for BytesOut and LostPackagesOut. + Packets "lost" due to IncomingLossPercentage count for BytesIn and LostPackagesIn. + + + + internal + + + internal + + + internal + + + internal + + + internal + + + internal + + + internal + + + This setting overrides all other settings and turns simulation on/off. Default: false. + + + Outgoing packages delay in ms. Default: 100. + + + Randomizes OutgoingLag by [-OutgoingJitter..+OutgoingJitter]. Default: 0. + + + Percentage of outgoing packets that should be lost. Between 0..100. Default: 1. TCP ignores this setting. + + + Incoming packages delay in ms. Default: 100. + + + Randomizes IncomingLag by [-IncomingJitter..+IncomingJitter]. Default: 0. + + + Percentage of incoming packets that should be lost. Between 0..100. Default: 1. TCP ignores this setting. + + + Counts how many outgoing packages actually got lost. TCP connections ignore loss and this stays 0. + + + Counts how many incoming packages actually got lost. TCP connections ignore loss and this stays 0. + + + + Only in use as long as PhotonPeer.TrafficStatsEnabled = true; + + + + Gets sum of outgoing operations in bytes. + + + Gets count of outgoing operations. + + + Gets sum of byte-cost of incoming operation-results. + + + Gets count of incoming operation-results. + + + Gets sum of byte-cost of incoming events. + + + Gets count of incoming events. + + + + Gets longest time it took to complete a call to OnOperationResponse (in your code). + If such a callback takes long, it will lower the network performance and might lead to timeouts. + + + + Gets OperationCode that causes the LongestOpResponseCallback. See that description. + + + + Gets longest time a call to OnEvent (in your code) took. + If such a callback takes long, it will lower the network performance and might lead to timeouts. + + + + Gets EventCode that caused the LongestEventCallback. See that description. + + + + Gets longest time between subsequent calls to DispatchIncomgingCommands in milliseconds. + Note: This is not a crucial timing for the networking. Long gaps just add "local lag" to events that are available already. + + + + + Gets longest time between subsequent calls to SendOutgoingCommands in milliseconds. + Note: This is a crucial value for network stability. Without calling SendOutgoingCommands, + nothing will be sent to the server, who might time out this client. + + + + + Gets number of calls of DispatchIncomingCommands. + + + + + Gets number of calls of DispatchIncomingCommands. + + + + + Gets number of calls of SendOutgoingCommands. + + + + Gets sum of byte-cost of all "logic level" messages. + + + Gets sum of counted "logic level" messages. + + + Gets sum of byte-cost of all incoming "logic level" messages. + + + Gets sum of counted incoming "logic level" messages. + + + Gets sum of byte-cost of all outgoing "logic level" messages (= OperationByteCount). + + + Gets sum of counted outgoing "logic level" messages (= OperationCount). + + + + Resets the values that can be maxed out, like LongestDeltaBetweenDispatching. See remarks. + + + Set to 0: LongestDeltaBetweenDispatching, LongestDeltaBetweenSending, LongestEventCallback, LongestEventCallbackCode, LongestOpResponseCallback, LongestOpResponseCallbackOpCode. + Also resets internal values: timeOfLastDispatchCall and timeOfLastSendCall (so intervals are tracked correctly). + + + + Gets the byte-size of per-package headers. + + + + Counts commands created/received by this client, ignoring repeats (out command count can be higher due to repeats). + + + + Gets count of bytes as traffic, excluding UDP/TCP headers (42 bytes / x bytes). + + + Timestamp of the last incoming ACK that has been read (every PhotonPeer.TimePingInterval milliseconds this client sends a PING which must be ACKd). + + + Timestamp of last incoming reliable command (every second we expect a PING). + + + + Provides classical Diffie-Hellman Modular Exponentiation Groups defined by the + OAKLEY Key Determination Protocol (RFC 2412). + + + + + Gets the genrator (N) used by the the well known groups 1,2 and 5. + + + + + Gets the 768 bit prime for the well known group 1. + + + + + Gets the 1024 bit prime for the well known group 2. + + + + + Gets the 1536 bit prime for the well known group 5. + + + + + Initializes a new instance of the class. + + + + + Gets the public key that can be used by another DiffieHellmanCryptoProvider object + to generate a shared secret agreement. + + + + + Derives the shared key is generated from the secret agreement between two parties, + given a byte array that contains the second party's public key. + + + The second party's public key. + + +
+
diff --git a/Close Enough!/Assets/Plugins/Photon3Unity3D.xml.meta b/Close Enough!/Assets/Plugins/Photon3Unity3D.xml.meta new file mode 100644 index 0000000..671d824 --- /dev/null +++ b/Close Enough!/Assets/Plugins/Photon3Unity3D.xml.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 8d4f08d435c4b6343969d8af249460ff +labels: +- ExitGames +- PUN +- Photon +- Networking +TextScriptImporter: + userData: diff --git a/Close Enough!/Assets/Plugins/WebSocket.meta b/Close Enough!/Assets/Plugins/WebSocket.meta new file mode 100644 index 0000000..0fc4f26 --- /dev/null +++ b/Close Enough!/Assets/Plugins/WebSocket.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 045e8c90e7cd648c4904a29e9c0c649c +folderAsset: yes +timeCreated: 1525372511 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Plugins/WebSocket/WebSocket.cs b/Close Enough!/Assets/Plugins/WebSocket/WebSocket.cs new file mode 100644 index 0000000..25094bc --- /dev/null +++ b/Close Enough!/Assets/Plugins/WebSocket/WebSocket.cs @@ -0,0 +1,155 @@ +#if UNITY_WEBGL || UNITY_XBOXONE || WEBSOCKET + +using System; +using System.Text; + +#if UNITY_WEBGL && !UNITY_EDITOR +using System.Runtime.InteropServices; +#else +using System.Collections.Generic; +using System.Security.Authentication; +#endif + + +public class WebSocket +{ + private Uri mUrl; + + public WebSocket(Uri url) + { + mUrl = url; + + string protocol = mUrl.Scheme; + if (!protocol.Equals("ws") && !protocol.Equals("wss")) + throw new ArgumentException("Unsupported protocol: " + protocol); + } + + public void SendString(string str) + { + Send(Encoding.UTF8.GetBytes (str)); + } + + public string RecvString() + { + byte[] retval = Recv(); + if (retval == null) + return null; + return Encoding.UTF8.GetString (retval); + } + +#if UNITY_WEBGL && !UNITY_EDITOR + [DllImport("__Internal")] + private static extern int SocketCreate (string url); + + [DllImport("__Internal")] + private static extern int SocketState (int socketInstance); + + [DllImport("__Internal")] + private static extern void SocketSend (int socketInstance, byte[] ptr, int length); + + [DllImport("__Internal")] + private static extern void SocketRecv (int socketInstance, byte[] ptr, int length); + + [DllImport("__Internal")] + private static extern int SocketRecvLength (int socketInstance); + + [DllImport("__Internal")] + private static extern void SocketClose (int socketInstance); + + [DllImport("__Internal")] + private static extern int SocketError (int socketInstance, byte[] ptr, int length); + + int m_NativeRef = 0; + + public void Send(byte[] buffer) + { + SocketSend (m_NativeRef, buffer, buffer.Length); + } + + public byte[] Recv() + { + int length = SocketRecvLength (m_NativeRef); + if (length == 0) + return null; + byte[] buffer = new byte[length]; + SocketRecv (m_NativeRef, buffer, length); + return buffer; + } + + public void Connect() + { + m_NativeRef = SocketCreate (mUrl.ToString()); + + //while (SocketState(m_NativeRef) == 0) + // yield return 0; + } + + public void Close() + { + SocketClose(m_NativeRef); + } + + public bool Connected + { + get { return SocketState(m_NativeRef) != 0; } + } + + public string Error + { + get { + const int bufsize = 1024; + byte[] buffer = new byte[bufsize]; + int result = SocketError (m_NativeRef, buffer, bufsize); + + if (result == 0) + return null; + + return Encoding.UTF8.GetString (buffer); + } + } +#else + WebSocketSharp.WebSocket m_Socket; + Queue m_Messages = new Queue(); + bool m_IsConnected = false; + string m_Error = null; + + public void Connect() + { + m_Socket = new WebSocketSharp.WebSocket(mUrl.ToString(), new string[] { "GpBinaryV16" });// modified by TS + m_Socket.SslConfiguration.EnabledSslProtocols = m_Socket.SslConfiguration.EnabledSslProtocols | (SslProtocols)(3072| 768); + m_Socket.OnMessage += (sender, e) => m_Messages.Enqueue(e.RawData); + m_Socket.OnOpen += (sender, e) => m_IsConnected = true; + m_Socket.OnError += (sender, e) => m_Error = e.Message + (e.Exception == null ? "" : " / " + e.Exception); + m_Socket.ConnectAsync(); + } + + public bool Connected { get { return m_IsConnected; } }// added by TS + + + public void Send(byte[] buffer) + { + m_Socket.Send(buffer); + } + + public byte[] Recv() + { + if (m_Messages.Count == 0) + return null; + return m_Messages.Dequeue(); + } + + public void Close() + { + m_Socket.Close(); + } + + public string Error + { + get + { + return m_Error; + } + } +#endif +} +#endif \ No newline at end of file diff --git a/Close Enough!/Assets/Plugins/WebSocket/WebSocket.cs.meta b/Close Enough!/Assets/Plugins/WebSocket/WebSocket.cs.meta new file mode 100644 index 0000000..241c921 --- /dev/null +++ b/Close Enough!/Assets/Plugins/WebSocket/WebSocket.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b1bad04f7805f764dba77f0d4518e0f0 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Close Enough!/Assets/Plugins/WebSocket/WebSocket.jslib b/Close Enough!/Assets/Plugins/WebSocket/WebSocket.jslib new file mode 100644 index 0000000..c85639e --- /dev/null +++ b/Close Enough!/Assets/Plugins/WebSocket/WebSocket.jslib @@ -0,0 +1,116 @@ +var LibraryWebSockets = { +$webSocketInstances: [], + +SocketCreate: function(url) +{ + var str = Pointer_stringify(url); + var socket = { + socket: new WebSocket(str, ['GpBinaryV16']), + buffer: new Uint8Array(0), + error: null, + messages: [] + } + socket.socket.binaryType = 'arraybuffer'; + socket.socket.onmessage = function (e) { +// if (e.data instanceof Blob) +// { +// var reader = new FileReader(); +// reader.addEventListener("loadend", function() { +// var array = new Uint8Array(reader.result); +// socket.messages.push(array); +// }); +// reader.readAsArrayBuffer(e.data); +// } + if (e.data instanceof ArrayBuffer) + { + var array = new Uint8Array(e.data); + socket.messages.push(array); + } + }; + socket.socket.onclose = function (e) { + if (e.code != 1000) + { + if (e.reason != null && e.reason.length > 0) + socket.error = e.reason; + else + { + switch (e.code) + { + case 1001: + socket.error = "Endpoint going away."; + break; + case 1002: + socket.error = "Protocol error."; + break; + case 1003: + socket.error = "Unsupported message."; + break; + case 1005: + socket.error = "No status."; + break; + case 1006: + socket.error = "Abnormal disconnection."; + break; + case 1009: + socket.error = "Data frame too large."; + break; + default: + socket.error = "Error "+e.code; + } + } + } + } + var instance = webSocketInstances.push(socket) - 1; + return instance; +}, + +SocketState: function (socketInstance) +{ + var socket = webSocketInstances[socketInstance]; + return socket.socket.readyState; +}, + +SocketError: function (socketInstance, ptr, bufsize) +{ + var socket = webSocketInstances[socketInstance]; + if (socket.error == null) + return 0; + var str = socket.error.slice(0, Math.max(0, bufsize - 1)); + writeStringToMemory(str, ptr, false); + return 1; +}, + +SocketSend: function (socketInstance, ptr, length) +{ + var socket = webSocketInstances[socketInstance]; + socket.socket.send (HEAPU8.buffer.slice(ptr, ptr+length)); +}, + +SocketRecvLength: function(socketInstance) +{ + var socket = webSocketInstances[socketInstance]; + if (socket.messages.length == 0) + return 0; + return socket.messages[0].length; +}, + +SocketRecv: function (socketInstance, ptr, length) +{ + var socket = webSocketInstances[socketInstance]; + if (socket.messages.length == 0) + return 0; + if (socket.messages[0].length > length) + return 0; + HEAPU8.set(socket.messages[0], ptr); + socket.messages = socket.messages.slice(1); +}, + +SocketClose: function (socketInstance) +{ + var socket = webSocketInstances[socketInstance]; + socket.socket.close(); +} +}; + +autoAddDeps(LibraryWebSockets, '$webSocketInstances'); +mergeInto(LibraryManager.library, LibraryWebSockets); diff --git a/Close Enough!/Assets/Plugins/WebSocket/WebSocket.jslib.meta b/Close Enough!/Assets/Plugins/WebSocket/WebSocket.jslib.meta new file mode 100644 index 0000000..e5a1c7d --- /dev/null +++ b/Close Enough!/Assets/Plugins/WebSocket/WebSocket.jslib.meta @@ -0,0 +1,21 @@ +fileFormatVersion: 2 +guid: 04bb5f307f2e48b4fbaa6da865fd4091 +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + platformData: + Any: + enabled: 0 + settings: {} + Editor: + enabled: 0 + settings: + DefaultValueInitialized: true + WebGL: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Plugins/WebSocket/websocket-sharp.README b/Close Enough!/Assets/Plugins/WebSocket/websocket-sharp.README new file mode 100644 index 0000000..10d150b --- /dev/null +++ b/Close Enough!/Assets/Plugins/WebSocket/websocket-sharp.README @@ -0,0 +1,3 @@ +websocket-sharp.dll built from https://github.com/sta/websocket-sharp.git, commit 869dfb09778de51081b0ae64bd2c3217cffe0699 on Aug 24, 2016. + +websocket-sharp is provided under The MIT License as mentioned here: https://github.com/sta/websocket-sharp#license \ No newline at end of file diff --git a/Close Enough!/Assets/Plugins/WebSocket/websocket-sharp.README.meta b/Close Enough!/Assets/Plugins/WebSocket/websocket-sharp.README.meta new file mode 100644 index 0000000..47cc15d --- /dev/null +++ b/Close Enough!/Assets/Plugins/WebSocket/websocket-sharp.README.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 3e262c2b04eaa8440987b50a91e86674 +DefaultImporter: + userData: diff --git a/Close Enough!/Assets/Plugins/WebSocket/websocket-sharp.dll b/Close Enough!/Assets/Plugins/WebSocket/websocket-sharp.dll new file mode 100644 index 0000000..6eabebe Binary files /dev/null and b/Close Enough!/Assets/Plugins/WebSocket/websocket-sharp.dll differ diff --git a/Close Enough!/Assets/Plugins/WebSocket/websocket-sharp.dll.meta b/Close Enough!/Assets/Plugins/WebSocket/websocket-sharp.dll.meta new file mode 100644 index 0000000..a586786 --- /dev/null +++ b/Close Enough!/Assets/Plugins/WebSocket/websocket-sharp.dll.meta @@ -0,0 +1,69 @@ +fileFormatVersion: 2 +guid: 748eb70bc0d7515498ef73fed155520a +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + platformData: + Android: + enabled: 0 + settings: + CPU: AnyCPU + Any: + enabled: 0 + settings: {} + Editor: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + Linux: + enabled: 0 + settings: + CPU: x86 + Linux64: + enabled: 0 + settings: + CPU: x86_64 + OSXIntel: + enabled: 0 + settings: + CPU: AnyCPU + OSXIntel64: + enabled: 0 + settings: + CPU: AnyCPU + WP8: + enabled: 0 + settings: + CPU: AnyCPU + DontProcess: False + PlaceholderPath: + Win: + enabled: 0 + settings: + CPU: AnyCPU + Win64: + enabled: 0 + settings: + CPU: AnyCPU + WindowsStoreApps: + enabled: 0 + settings: + CPU: AnyCPU + DontProcess: False + PlaceholderPath: + SDK: AnySDK + XboxOne: + enabled: 1 + settings: {} + iOS: + enabled: 0 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Plugins/release_history.txt b/Close Enough!/Assets/Plugins/release_history.txt new file mode 100644 index 0000000..56e9af0 --- /dev/null +++ b/Close Enough!/Assets/Plugins/release_history.txt @@ -0,0 +1,1421 @@ +* release_history.txt +* Release history for the DotNet Photon Client Library (DotNet / Unity / Windows Store 8.1 and 10) +(C) 2016 Exit Games GmbH, http://www.photonengine.com + +Questions? Visit: +https://www.photonengine.com +https://doc.photonengine.com +http://forum.photonengine.com + + +*** Version 4.1.1.19 (9. April 2018 - rev4590) + Fixed: WSS now sends an operation "ping" in SendAcksOnly() (and SendOutgoingCommands()) to avoid getting timed out. This happens right away, while other commands/operations stay in queue. + + +*** Version 4.1.1.18 (19. December 2017 - rev4540) + Fixed: Exception in QueueOutgoingAcknowledgement() with a lock(). This avoids threading issues between Send- and Receive-thread. This was an issue mostly seen in Photon Voice, which uses the library multi-threaded. + Changed: Network Simulation now only stores the actual data of messages, instead of storing an action/delegate. + Note: The delegate IL code for Network Simulation was instantiating a "display class" instance and caused GC garbage, even if no simulation was running. +LoadBalancing: + Changed: FriendInfo.Name is now "UserId", which is up to date with it's usage. + Changed: CheckUserOnJoin is now set by default. The RoomOptions.CheckUserOnJoin got removed. + + +*** Version 4.1.1.17 (11. October 2017 - rev4465) + Fixed: Fetching the server timestamp now works for the "No C# Sockets"-library build for WebSockets. This affected libraries used for XB1 and as a result, the serve time was not synced. E.g. PhotonNetwork.time was locked at 0. + Changed: XML doc of PhotonPeer.DisconnectTimeout. This is no longer a UDP exclusive setting and clearly states that the unit is milliseconds. + Updated: Several documentation comments for the PhotonPeer. Using shorter summaries and remarks for the details. +LoadBalancing: + Changed: OperationCode const byte Join = 255 is now marked obsolete. We use "JoinGame" instead. + Added: DisconnectCause.AuthenticationTicketExpired. + Fixed: DebugReturn call in Unity WebGL. +Chat: + Fixed: Unity "6" compile define is now UNITY_2017. + +*** Version 4.1.1.16 (1. September 2017 - rev4349) + Fixed: The native implementations for "PhotonPing", which are used for PUN's "Best Region" selection in the "No Sockets" dlls (Android and iOS for Unity 4.x). Disposing the "dynamic" version was causing an exception (due to an attempted fix of a less-obvious memory leak). This caused the Best Region selection to stall. + +*** Version 4.1.1.15 (17. July 2017 - rev4232) +WebSocket: + Changed: WebSockets are now treated like "addons", as their implementations are complex and potentially not running on some platforms (be it UWP or some Unity export). The Readme-Photon-WebSocket.txt tells you how to add them to your project and set them up. + Added: Folder "PhotonWebSocket" with SocketWebTcpCoroutine and SocketWebTcpThread classes, to support platforms with and without Thread API. + Added: PingHttp.cs for Unity WebGL exports, to support "Best Region" selection in PUN. +LoadBalancing: + Added: LoadBalancingClient.TransportProtocol as shortcut to the use PhotonPeer's TransportProtocol value. This enables setting the protocol easily while not connected. + Added: LoadBalancingClient.SocketImplementationConfig as shortcut to modify PhotonPeer's SocketImplementationConfig. This enables you to setup which IPhotonSocket implementation to use for which network protocol. + Changed: LoadBalancingPeer.ConfigUnitySockets() to try to find our websocket implementations in the assembly, making the SocketWebTcpCoroutine and SocketWebTcpThread classes optional. + Removed: Class "SocketWebTcp" is no longer found by ConfigUnitySockets(). +Chat: + Added: ChatClient.TransportProtocol as shortcut to the use PhotonPeer's TransportProtocol value. This enables setting the protocol easily while not connected. + Added: ChatClient.SocketImplementationConfig as shortcut to modify PhotonPeer's SocketImplementationConfig. This enables you to setup which IPhotonSocket implementation to use for which network protocol. + Changed: ChatPeer.ConfigUnitySockets() to try to find our websocket implementations in the assembly, making the SocketWebTcpCoroutine and SocketWebTcpThread classes optional. + Removed: Class "SocketWebTcp" is no longer found by ConfigUnitySockets(). + +*** Version 4.1.1.14 (5. July 2017 - rev4191) + Changed: SupportClass StartBackgroundCalls method now assigns an ID to each thread/task and enables you to cancel it explicitly via StopBackgroundCalls. CallInBackground is now obsolete due to renaming. +LoadBalancing + Changed: The ClientState "Uninitialized" is now "PeerCreated". This is the initial state. ConnectedToMaster is now ConnectedToMasterserver (both use the same value). + Updated: ClientState values descriptions. + Internal: GameEnteredOnGameServer() first sets the local player's actorNumber, then updates the player lists. +Chat: + Added: ChatClient can optionally run a thread to call SendOutgoingCommands in intervals. This makes sure the connection doesn't fail easily (e.g. when Unity is loading scenes, etc.). You still have to call Service to dispatch received messages. + Added: ChatClient.UseBackgroundWorkerForSending. Set this to true, to use the new background thread. Note: Do not use this in WebGL exports from Unity cause Threads are unavailable in them. +WebSocket: + Changed: Updated enabled protocols for WebSocket.cs. Now it is posible to connect to a server which supports only either TLS 1.1 or TLS 1.2 or TLS 1.0 or any combination of them. + +*** Version 4.1.1.13 (2. June 2017 - rev4112) + Internal: Fixed StreamBuffer.Seek() which was throwing an exception when seeking position 0 in an empty stream. + Removed: The queue-length checks which were using OnStatusChanged to warn about the amount of data queued for sending. Several StatusCode values are now obsolete accordingly. + Removed: StatusCode InternalReceiveException = 1039 and TcpRouter* which were obsolete for a longer time. + +*** Version 4.1.1.12 (24. May 2017 - rev4086) + Fixed: Peer.timeLastSendOutgoing was set in SendAcksOnly and ReceiveIncomingCommands. This should not happen. In PUN, this led to an issue with the fallback thread, which could not keep the connection. + Fixed: DNS resolution in the UDP socket is no longer inside a lock. Even if it takes longer (without network), the socket can now be closed before it's even opened properly, avoiding a freeze. + Fixed: UWP clients can set a SocketImplementationConfig. This opens up the use of WebSockets or any IPhotonSocket implementation in UWP, too. + Internal: Acknowledgements are no longer created as "commands" and serialized on send. Instead, they are directly written to a byte[] buffer, which is using less memory. + Added: PhotonPeer.EnableServerTracing to enable UDP Datagram Tracing on server side. We might ask you to use this when debugging connection issues. Otherwise, don't use this, as you can't access the server's logs anyways. + +*** Version 4.1.1.11 (13. April 2017 - rev3922) + Fixed: Bug of v4.1.1.10, which caused disconnects after a short time. + +*** Version 4.1.1.10 (11. April 2017 - rev3916) + Internal: Memory Allocation for nCommand and EnetPeer within SendoutGoingCommand, and AreReliableCommandInTransit + Internal: Refactoring of SerializeToBuffer to prevent memory allocation and access udpBuffer directly instead of using BlockCopy. + Internal: EnetPeer.channels got removed and replaced by a simple array and a GetChannel() method to access all channels. + +*** Version 4.1.1.9 (15. March 2017 - rev3884) + Fixed: Size calculation for Datagram Encryption (used on one console only, so far), when the MTU was changed from default. In some cases, an Exception was thrown: ArgumentException: Offset and length were out of bounds [...] at System.Buffer.BlockCopy. Adjusted GetFragmentLength() and CalculateBufferLen() internally. + +*** Version 4.1.1.8 (24. February 2017 - rev3873) + Fixed: Handling of non-fatal "WouldBlock" SocketExceptions when receiving data via TCP. This led to disconnects before. This affects only TCP connections in libs other than Windows Store. + Changed: Memory usage for TCP socket usage. Less memory is being allocated per receive. As we have to queue incoming data, it still has to get copied once. + Changed: Memory usage for encrypting messages. + Changed: SupportClass.DictionaryToString() now logs the length of a byte-array (not the content). + Changed: Deserializing unknown "Custom Types" returns the sent byte[]. There is no warning/error log yet but deserialization won't fail entirely. + Changed: PeerBase.SerializeMessageToMessage() to use less memory for encryption. Also, Raw-Messages can now be de/encrypted successfully. + Internal: Added StreamBuffer.ToArrayFromPos(), enabling you to get a buffer copy, starting with some offset (position of the buffer). + Internal: Removed some NETFX special build cases (obsolete due to using our own SteamBuffer). +PhotonVoice: + Breaking: LocalVoice.Transmit = true by default. + Fixed: LoadBalancingFrontend.DebugEchoMode setter checks if value changed. + Changed: better singleton handling and error logging. +LoadBalancing: + Added: Player.UserId field and code to read published UserIds from the player properties in CacheProperties(). When publishing the UserId in a room (RoomOptions.PublishUserId = true), the UserId becomes available for all players in a room. Good to find/make friends or follow a team player into another room. + Added: New matchmaking operation: OpGetGameList(typedLobby, sqlFilter). This fetches a list of rooms that match the filter. You can show lists of rooms with specific properties, if needed (or still use OpJoinRandom). + Fixed: WebFlags properties setters. + +*** Version 4.1.1.7 (16. December 2016) + Note: No new lib version. Just updated demos for the SDK. +Demos: + Fixed: Demos with persistent (Turnbased) games. The Memory Demo was not setting up rooms correctly (which led to errors joining them) and used a "join" rather than a "rejoin" to get into saved games (getting added to the room once more). + +*** Version 4.1.1.6 (9. December 2016 - rev3801) + Changed: Default SentCountAllowance = 7. +Loadbalancing: + Added: OpJoinRandom will now "remember" to send ExpectedUsers to the Game Server (by caching the value). + Added: AuthEvent and it's handling. This (internally sent) event can now update the client's token anytime (before that expires). + Added: LoadBalancingClient.OpChangeGroups(). + Changed: LoadBalancingClient.Disconnect() no longer sets it's own State to Disconnected. It waits till the state-change callback gets called by the lib. + +*** Version 4.1.1.5 (18. November 2016 - rev3775) +Internal: + Fixed: Photon-init request is now created by the factory method CreateAndEnqueueCommand to make sure we fragment the init if needed (for small MTU and more init-data). + Fixed: Bug in TrafficStatsReset method, which caused the averaged stats to go up infinitely after a reset. + +*** Version 4.1.1.4 (21. October 2016 - rev3737) + Internal: Added ArraySegment support for byte[]. This way, we can internally reuse more memory. + Changed: Implementations of PeerBase Disconnect() are now using EnqueueStatusCallback(StatusCode.Disconnect) to delay the "callback". That enables any thread to call Disconnect() while the status change correctly gets called in the main thread via DispatchIncomingCommands(). + Changed: When a SocketImplementationConfig for UDP is set, this will be used via Activator.CreateInstance(socketImplementation, this). + +*** Version 4.1.1.3 (20. September 2016 - rev3673) + Changed: NETFX_CORE implementation for UDP. This no longer attempts to detach the stream after every single Send, which caused issues when connecting and getting a lot of messages. + +*** Version 4.1.1.2 (13. September 2016 - rev3652) + Changed: There are less variants of the Photon library now, which makes it easier to integrate, run and test. There is a general "DotNet" version and a Windows Store (universal) dll. These two also come as Unity build and in Debug and Release. UWP can use the Universal/WSA library. + Added: PhotonPeer.SocketImplementationConfig. This allows easier configuration of the IPhotonSocket type to use per protocol, so that switching protocols is easier (compared to having to set a SocketImplementation before connecting). + Changed: PhotonPeer.SocketImplementation can't be set public. Use the SocketImplementationConfig instead. + Internal: This release summarizes a lot of internal refactorings. It's easy now to switch protocols (internally), to set socket implementations (platform dependent) if needed, etc. +LoadBalancing: + Removed: LoadBalancingClient.PlayerName and Player.Name. Were obsolete for more than a year. There is a NickName and the UserId can be set in the AuthValues. + Removed: OpJoinRoom() overload with actorNumber. This was obsolete. To enable clients to return to a room, set AuthValues and a userID. + Changed: LoadBalancingClient no longer overrides the protocol for Unity WebGL. This is done in the LoadBalancingPeer.ConfigUnitySockets(). + Changed: GetNameServerAddress() is the same in Chat and LoadBalancing APIs now. + Added: DisconnectCause.DisconnectByServerLogic and handling for this case. You can check this DisconnectedCause when the LoadBalancingClient.State is ClientState.Disconnected. + Added: Hashtable definition to use Photon's own implementation for Windows Store builds (NETFX_CORE). This must be used but it means you to use the same Hashtable definition in all builds (no matter if 8.1 or 10). + Added: Support for WebGL export in Unity. + Changed: OnStateChangeAction, OnEventAction and OnOpResponseAction are now events. To register a method in one of those, use += and to deregister you need to use -=. This prevents assigning a new method and de-registering any previously registered ones. +Chat: + Changed: ChatPeer now has ConfigUnitySockets(), which defines the SocketImplementationConfig. It's only used in Unity (using UNITY define). + Changed: ChatClient is not setting socket implementations anymore. + Added: Hashtable definition to use Photon's own implementation for Windows Store builds (NETFX_CORE). This must be used but it means you to use the same Hashtable definition in all builds (no matter if 8.1 or 10). + Added: Support for WebGL export in Unity. + +*** Version 4.1.1.1 (22. August 2016 - rev3549) + Fixed: IPv6 support. The init-message was missing it in 4.1.1.0. + Fixed: UWP build for Unity now has (Photon-)Hashtable class once more. Unlike Windows RT, UWP does support Hashtable (again). But in Unity, we always use ours. + +*** Version 4.1.1.0 (15. August 2016 - rev3536) + Changed: Unity exports now need to set the API Compatibility to ".Net 2.0". The ".Net 2.0 Subset" won't work anymore, due to need of some features for a new encryption mode. + Fixed: Windows Store implementation of TCP Socket. This is now compatible with 8.1 and 10 and the locally configured timeout is also applied while connecting initially. + Fixed: OpWebRPC documentation. +LoadBalancing: + Fixed: Room.ClearExpectedUsers() is now sending it's current, local "expected users" to update the server with "CAS" (Check and Swap). This gives the client an update when the values become valid (which updates the local cache after the roundtrip). + Added: Support for the 'Server Side Master Client' feature. The Room will read master client updates from the server accordingly. Room.SetMasterClient() enables you to override the server's selection (provided it did not change before your operation gets executed). + Changed: Option for bool WebForward into the new "WebFlags". This allows fine control of which data is being sent to WebHooks. This affects all SetProperties, OpWebRPC and the RaiseEventOptions. + Added: WebRPC.cs to the LoadBalancing API folder (was available separately before). It contains WebFlags and WebRpcResponse. +Internal: + Changed: Instead of Windows Phone 8.0 support, we now have a Windows 8.1 Universal library ("Metro") and one for Windows 10 Universal ("UWP"). + Changed: Changed initialization of PhotonPeer and related classes. + Changed: Workflow to send Init command. + Added: Option for "Datagram Encryption" and a new Authentication Workflow ("AuthOnce" and "AuthOnceWss"). This is part of the LoadBalancing API. + Added: ClientSdkId, which is used internally for reference. + +*** Version 4.1.0.6 (30. June 2016 - rev3400) + Changed: ExchangeKeysForEncryption() and internally called DeriveSharedKey() can now be executed in their own Thread. + Added: static PhotonPeer.AsyncKeyExchange to define if encryption calculations are done in parallel. +Internal: + Changed: NetworkSimulationSet.IsSimulationEnabled only does any work, if the value gets changed (saving some surplus work). + +*** Version 4.1.0.6 (21. June 2016 - rev3376) +Internal: + Removed: The wrapper for the optional "native encryption library" from most assemblies. It didn't get certified for the Windows Store and caused problems in the Unity WebPlayer. This will be provided on demand instead. + Removed: Our upcoming protocol implementation until it's fully compatible with all supported platforms. Despite not being used, it also caused some issues on some Unity exports. + Changed: Usage of MemoryStream is being replaced with a StreamBuffer. This is our own implementation and always grants access to the underlying byte[] (which is not possible in Windows Phone / Store API in some cases). For your Custom Type serialization, replace MemoryStream with StreamBuffer. That's all. + Internal: Commands are now split into header and payload byte-arrays, instead of copying them into yet another buffer before sending them. + Added: Support for IPv6 adresses in Photon Ping classes. This supports "Best Region" usage in PUN. + Fixed: After DNS resolution, IPv6 adresses are preferred over IPv4 ones. +LoadBalancing: + Fixed: LoadBalancingPeer.OpRaiseEvent(...) to send operations (and events) unencrypted again. + +*** Version 4.1.0.4 (19. May 2016 - rev3322) +Internal: + Updated: For Unity, the usage of the optional "native sockets" library is now compatible with IPv6 addresses, as required by Apple. + +*** Version 4.1.0.3 (28. April 2016) +Internal: + Added: An optional native library for encryption. This speeds up the (rarely used) key-exchange and encryption of messages. The usual case is to use the C# variant, as before. + +*** Version 4.1.0.2 (21. April 2016 - rev3283) +Internal: + Changed: PeerBase: ipv6 flag set in INIT_BYTES[5] after dns lookup, when ip address type already known + Changed: PeerBase: INIT_BYTES[4] contains clientlibid and release flag (15) + Changed: PeerBase: client version packed in INIT_BYTES[5,7,6] bytes + Changed: pProtocol prefix and path parsed (and trimmed) in IPhotonSocket.TryParseAddress to support websocket urls + Changed: Client version moved to separate version.cs + Changed: Protocol static methods reworked to instance methods, IProtocol interface extracted + Changed: PeerBase.DeserializeMessageAndCallback() to use a variant of new MemoryStream that exists in Windows 10 Universal APIs, too. +LoadBalancing: + Added: Expected Users. This affects the Room, LoadBalancingClient, JoinRoom, JoinOrCreateRoom and CreateRoom. + Added: null check in Extensions.StripToStringKeys(). + Fixed: FriendInfo.IsInRoom, which returned the opposite of it's naming! Also changed FriendInfo ToString() according to PUN's. + Added: RoomInfo expectedUsersField, which is updated with room properties (well known ones). + Added: Room.ExpectedUsers and ClearExpectedUsers() to expose the list of expected players. + Added: RoomInfo.serverSideMasterClient and masterClientIdField (also updated with well known properties). + Changed: OpRaiseEvent now re-uses a Dictionary in the LoadBalancingPeer. It uses Clear(), rather than creating a new Dict each time. + Changed: AuthenticationValues to also use C# properties and and backup-fields. This is guaranteed to work in Unity. + Updated: EventCode ErrorInfo reference with a link to "WebHooks" doc online. + Changed: Disconnect handling in the LoadBalancingClient. The client should reset correctly and log info, if it's in a State where a disconnect is a proper error. Note: In some cases like "switching server", a disconnect is expected, so it's not an error then. + Fixed: PlayerProperties sent to game server will now include well-known properties again. This fixes the "NickName missing" bug. + Fixed: LoadBalancingClient.State value when the client fails to join or create a game on the Master Server. The state is correctly re-set to ClientState.JoinedLobby or ClientState.ConnectedToMaster. + Internal: Added private inLobby value, to store if the client was/is in a lobby on the Master Server. + Fixed: DemoClient (in demo-loadbalancing) now makes use of the Name Server by using: ConnectToRegionMaster("eu"). + Added: DemoClient now has debug output when the connection times out or can't be established. + + +*** Version 4.0.5.1 (18. January 2016 - rev3187) + Fixed: EnetPeer.ExecuteCommand(). Fixed: Receiving a Disconnect-command didn't clear the receive-buffers. However, it has to be the last command executed. + Note: The bug related to the Disconnect-command happened, when an app paused, queued incoming commands and executed the Disconnect while incoming commands were queued. + Fixed: Setting of DisconnectTimeout for TCP connections (ReceiveTimeout and SendTimeout). + Changed: Our protocol serializes Enums implicitly as their underlying Type. This means you can easily send them but will lose the Type info (they don't arrive as your Enum type). This is now also working in Windows Store libraries (NETFX_CORE). +LoadBalancing: + Added: OpSetCustomPropertiesOfActor() and OpSetCustomPropertiesOfRoom() now check locally, if the client is currently in a room. It must be, to be able to set these properties. An exception exists for setting properties for the local player's actorNumber, but those are better set via LoadBalancingClient.LocalPlayer. +Unity SDK: + Changed: The Unity condition which defines "using Hashtable = ExitGames.Client.Photon.Hashtable;". All versions of Unity 4 and up now define that Photon's Hashtable is needed. This is only in the LoadBalancing API, not in the demos. + Added: WebGL support + +*** Version 4.0.5.0 (3. December 2015 - rev3144) + Changed: Signature of SetCustomProperties methods. All overloads now include a final, optional "webForward" parameter. This enables you to update a WebHook when properties change. This is intended for turnbased games, not for high-frequency updates - use with care. + Internal: Added more debug output to error messages from the socket usage. This should now always include the ServerAddress to make things easier to debug server-side, if needed. + Added: Serveral new ErrorCode values, which will be used by v4RC5 and newer servers. See ErrorCode.JoinFailed***, HttpLimitReached and ExternalHttpCallFailed. + Fixed: LoadBalancing API now reads the correct "NickName" key from the server's authentication response. So far, it was reading a key that is never used. Note: This means you can set a user's NickName server-side to override the client's nickname. +Chat + Added: A MessageLimit field for ChatClient and ChatChannel to limit the number of messages the client keeps locally. It might be useful to limit memory usage in long running chats. Set ChatClient.MessageLimit to apply the limit to any channel subscribed afterwards or apply a limit individually. + +*** Version 4.0.0.12 (3. November 2015 - rev3112) + Added: Support for IPv6. Note: IPv6 does not work in Unity yet. It has issues with IPv6. (Case 740910) + Note: Host name resolution will prefer IPv4 over IPv6, if both IPs should be available. IPv6 Addresses must use brackets! Example: [::1]:5055. This separates the port from the address. + Added: Error logging when Addresses can not be resolved to IPs. + Changed: LoadBalancingClient OpJoinOrCreateRoom() no longer allows you to re-join a room. Simply remove the ActorNumber from the parameters. To re-join, use OpJoin with actorNumber (Player.ID that was assigned in the room). + Added: Support for PS4 in Unity LoadBalancing SDK. Note: The demos are not all updated with controller support, as we use the old UI, still. To test export, use the Particle Demo. + +*** Version 4.0.0.11 (28. October 2015 - rev3093) + Changed: Sending a generic Dictionary (with specific types) will now throw an Exception, if any key or value is null. This limitation does not include Dictionaries which use object as type. Those Exceptions are one of the few, which are not catched and turned into a debug message. Catch them by wrapping Operation calls, where needed (OpRaiseEvent()). + Changed: TrafficStatsGameLevel public properties are now settable. This enables you to reset individual values to (e.g.) show "LongestDeltaBetweenSending of the past second". + Added: CommandLog debugging option. This can be used to get a list of sent reliable commands and their ACKs (from the server). Default is 0 size ("off"). + Added: CommandLogSize and CommandLogToString() to PhotonPeer. This is part of a LoadBalancingClient.loadBalancingPeer. + Added: Several PhotonPeer values to analyze connections: ConnectionTime, LastSendAckTime and LastSendOutgoingTime. PacketLossByChallenge is probably a tempoary addition to check if we have to drop corrupted packages due to bad "challenge" value. + Added: Log for incoming reliable commands. The most recent 200 entries will be logged with the CommandLogToString(). This is probably temporary. + Changed: Timing for resending reliable commands in RUDP. The peer will check the sent-queue more frequently now, no matter at what time some random command would have to be repeated. Repeats should be more timely, based on their dynamic resend-timing. + Changed: PhotonPeer.MaximumTransferUnit minimum is now 576 (was 520, which was lower than on the server). + Internal: Channels in the EnetPeer are now stored in an array, so we can replace some foreach-loops with for-loops. +LoadBalancing (Realtime and Turnbased API) + Added: LeaveLobby handling in OnOperationResponse(), which sets the client's state correctly. + Changed: Order of execution for Ev Join. If user is known (inactive user rejoins), the player's props are read. The actor list is used, if available. + Changed: RoomOptions to use properties with backup-fields to avoid issues in Unity which has issues with Object Initializer (curly brackets). + Changed: JoinMode 2 is now "JoinOrRejoin". Was: "Rejoin". + Added: ErrorCode constant AuthenticationTicketExpired. + Internal: OpJoinRoom, OpCreateRoom and OpJoinRandomRoom no longer use a (growing) list of properties. Instead, classes were created to "sum up" their parameters. The api for games didn't change. + Internal: Related to the refactoring of Join/Create, the LoadBalancingClient now creates a Room instance when the client arrived on the GameServer (before, it got created in the initial "create" call). +Chat + Added: More sanity checks on operations (empty userId or secret, max friends). + Added: Special debug logging when the server returns an error for "Operation Unknown". In this case, it's highly likely that you don't use a Chat AppId. + Added: More helpful error logging. + +*** Version 4.0.0.10 (14. July 2015 - rev2988) + Removed: LitePeer class and complete "Lite" namespace. It's highly recommended to use the LoadBalancing API (LoadBalancingClient, etc). The (few) operations that were defined in Lite are no longer required really. + Refactored: Some "base" enumerations that were provided by the Lite peer. They are now in LoadBalancingPeer. + Added: support for RoomOptions.Plugins. Which we need now since we support multiple plugins per plugin dll - for testing purposes for instance. + Fixed: The wrapper classes for the native sockets now do a Sleep(15) when there's nothing to receive. This reduces CPU load considerably. + Fixed: Unity library SocketWebTcp class for websocket support. It requires a coroutine on a new GameObject which is now marked as DontDestroyOnLoad(go) and survives scene loading. + Fixed: The Windows 8 SDKs now include the release assemblies. This makes sure you can submit your app to the Windows Store. + Added: ConnectionProtocol WebSocket and WebSocketSecure. It's simply a different protocol, compared to UDP and TCP, so it should be separated. + Internal: DoFraming is now a part of TPeer (was in IPhotonSocket). It's set by the ConnectionProtocol which avoids misconfiguration. + Changed: SendPing can now send a ping binary message or enqueue the Ping Operation (when DoFraming is false). + Added: A null-check for TrafficStatsStopwatch to avoid NullReferenceExceptions. + Added: Compile condition for Ping result handling. It's only used when the client uses Sockets as well (for the time being). + Added: Unity WebGL export also sets a "using" Hashtable definition. + Fixed: An exception in Photon.Hashtable.ToString() if a value was null. The assumption was that there are no null-values. + Changed: SocketUdp and SocketTcp now implement IDisposable, which seems to help with infrequent freezes in the Unity Editor. + Added: PhotonPeer.QuickResendAttempts. Sets how many resend attempts for a reliable command will be done in quick succession (after RTT+4*Variance), before the time between repeats will be increased. Use with care and with low values. + Added: IP/Hostname to logged exceptions when Connect fails. This is easier to support (e.g. DNS lookup fails). + Fixed: Library for PUN+ export to WebGL. Originally, we forced UDP as protocol for PUN+ export, as the native sockets library doesn't support TCP. However, WebGL export introduced a new use case. + Added: LoadBalancingClient.EnableLobbyStatistics and .LobbyStatistics. They provide an overview which lobbies your game uses and how busy they are. + Fixed: The LB Demo should set CustomProperties instead of directly setting (any) properties. + Fixed: SocketWebTcp is completely empty, unless WEBSOCKET is defined. Before the file still contained the "using" part of the class. +LoadBalancing (Realtime and Turnbased API) + Updated: Description for IsConnectedAndReady. + Changed: NameServerAddress to return a fitting address depending on protocol (including WebSocket but not yet RHTTP). + Updated: The only name server host is now "ns.exitgames.com", which gets turned into a proper address by protocol. + Changed: LoadBalancingClient.CustomAuthenticationValues is now .AuthValues. You can use those values to identify a user, even if you don't setup an external, custom authentication service. + Changed: LoadBalancingClient.UserId no longer directly stores the id but puts it into AuthValues. This means, the UserId could also be set via setting AuthValues. + Changed: The API of AuthenticationValues. There is now the UserId and AddAuthParameter() replaces the less general SetAuthParameters() (which only set specific key/values). + Changed: PlayerName gets renamed to NickName, so PhotonPlayer.Name becomes .NickName and LoadBalancingClient.Name becomes .NickName, too. The old naming is marked as obsolete. + Changed: Particle Demo now connects to the Cloud by default (because it's easier to setup and try). You can define your own Master Server (Photon OnPremise) of course. + Added: GamePropertyKey.MasterClientId (248) and ParameterCode.MasterClientId (203) + Added: ParameterCode.ExpectedValues (231) + Added: ParameterCode.SuppressRoomEvents (237) +Chat API: + Added: A Unity 4.6 demo with uGUI. It's missing a few features but should give you a good start to making your own. + Added: Unity/WebGL support (merged from PUN). + Added: Breaking! IChatClientListener.DebugReturn(). Photon lib and chat client log via this method (no logging to console by default). + Changed: ChatClient.CustomAuthenticationValues is now .AuthValues. You can use those values to identify a user, even if you don't setup an external, custom authentication service. + Changed: ChatClient.UserId no longer directly stores the id but puts it into AuthValues. This means, the UserId could also be set via setting AuthValues. + Changed: The API of AuthenticationValues. There is now the UserId and AddAuthParameter() replaces the less general SetAuthParameters() (which only set specific key/values). + Note: All users should have a UserId. You can set chatClient.UserId before you connect, or you can set the AuthenticationValues in Connect(..., authValues) to set a UserId. + Added: ChatChannel.ToStringMessages(), which gets all messages in a single string, line by line. The format is "Sender:Message". + Added: ChatClient.TryGetChannel() to find a channel only by name, no matter if public or private. +Photon Unity SDK + Changed: Organization of APIs and Assemblies in SDK. Now you can copy the content of folder "PhotonAssets" into your project's Assets folder and you have all APIs. + Added: PhotonAssets-U5 folder which includes only the Windows Universal DLL. + +*** Version 4.0.0.8 (14. January 2015 - rev2765) + Fixed: Serialization of custom types with nested Serialize-calls. In this case, re-using a specific memory stream breaks it. + +*** Version 4.0.0.7 (12. January 2015 - rev2763) + Fixed: Serialization of arrays of custom-types. +Chat API + Internal: Changed code for UserID from 7 to 225. The latter is used in LoadBalancing, too, so we want to re-use the code here. + +*** Version 4.0.0.6 (05. December 2014 - rev2758) + Added: ChatApi and LoadBalancingApi folders to Unity SDK. They are needed in any Photon project with Unity. When updating, copy and paste the files over existing ones and make sure to replace the assembly-files, too. + Changed: Protocol to save more memory or re-use it. The idea is to have less Garbage Collection (primarily for Unity/PUN and custom types). + Added: New CustomType de/serialization methods which provide the MemoryStream, instead of a byte[] COPY from the stream. + Changed: Now using one method to identify a Type. This was duplicated code before. + Changed: De/Serialization of some types. + Note: The drawback is now, that there are more places with: lock(). This is far from optimal but the alternative would be to make Protocol instances per thread. As most is static at the moment, this would not be an easy task. + Added: position check for DeserializeStreamFunction() call. Stream position must be "previous + customtype length". It gets corrected but at the moment no error is thrown. + Changed: DispatchIncomingCommands() no longer instantiates the commandsToRemove each call. This is reused and thus saves memory. + Changed: net_fx build will now check IsConstructedGenericType to detect if something is a dictionary +LoadBalancing + Added: LoadBalancingClient.OpJoinOrCreateRoom overload which has lobby as parameter. If a room gets created, this defines in which lobby it belongs. + Changed: LoadBalancingPeer: Added new error code PluginMismatch, documentation for Plugins parameter code. + +*** Version 4.0.0.5 (23. September 2014 - rev2738) + Updated: AddFriends and RemoveFriends doc. + Changed: Logging level for two cases. Dropping a package due to failed CRC-check is now logged for INFO. It's expected and certainly not an error. Dropping a package when the incoming challenge does not match is also not an ERROR. It is expected when you switch servers and packages arrive late. This is now debug level ALL. + +*** Version 4.0.0.4 (19. September 2014 - rev2736) + Fixed: Fragmentation when CRC checks are enabled. This kept clients from sending fragmented commands when the additional 4 bytes CRC were included later on. + Fixed: An issue in the ChatClient which was referring to a class from Photon Unity networking. This caused compile issues in the Unity Chat Demo. + Updated: Reference doc generation. + +*** Version 4.0.0.3 (15. September 2014 - rev2731) + Updated: Doc generation settings and style. + Note: This version has no code changes to rev2728 described below. That version is already released in the Unity Asset Store in PUN. + +*** Version 4.0.0.3 (11. September 2014 - rev2728) + Fixed: A simple "order of things" issue when detecting a timeout (due to resends). We first have to set "Zombie" state so that any Disconnect() call created a disconnect-command with reserved byte = 2 = "due to timeout". + Fixed: Chat to be compatible with native sockets of PUN+ (iOS and Android exports from Unity). + Fixed: Access to native sockets (in classes SocketUdpNativeDynamic and SocketUdpNativeStatic) is now using a lock(). The native methods are not thread safe but we need more than one socket for PUN+ and Chat (with native sockets, too). + Changed: Logging for the case "Ignoring received package due to wrong challenge". This got logged on log-level ERROR but maybe is better as WARNING only. Now this should log less often. + Internal: Updated to a newer native-sockets interface. + Internal: Updated to a newer native-sockets interface (affects PUN+ only). Cleaned up precompile defines and #if usage. + +*** Version 4.0.0.2 (01. August 2014 - rev2715) + Added: PhotonPing class and subclasses per platform. Allows clients to use regular UDP messages to ping our servers and find the best region. + Added: Native and Win8 support for PhotonPing. + Known Issue: Native ping has to be done "one by one" and without any other connection in Unity. It's not yet thread safe (but that is ok as we don't want to ping most of the time but only rarely and out of game). + Added: PhotonPing class/file to Win8 platforms. + Changed: The extern static methods for the native libs are now internal (instead of private). Pings are using them, too. + Changed: WebRpcResponse.ReturnCode comment to include fail code. + Changed: OpWebRpc doc is now much more complete and helpful. + Updated: Unity SDK Particle Demo (more) and LoadBalancing Demo (just a bit). + +*** Version 4.0.0.1 (17. June 2014 - rev2663) + Fixed: DotNet assembly no longer contains classes that try to include our Unity native socket libs. This was causing issues in some cases. + Added: PhotonPeer.CommandInfoCurrentDispatch. This property gives you the debug string of the currently dispatched command (events or responses). Only useful for UDP. +LoadBalancing: + Added: LoadBalancingClient.OpRaiseEvent(). Now that LoadBalancingClient USES a loadBalancingPeer (and doesn't extend it), things are much easier by offering this method, too! + Added: LoadBalancingClient.IsConnected and .IsConnectedAndReady to LB API. Going to be part of the API from now on. + Removed: Unused fields clientId and clientCount. + Changed: Field for internal use "lastJoinActorNumber" is now private as intended. + Changed: LoadBalancingClient.Disconnect is now setting it's own state to Disconnected if the connection got closed (as expected). +Chat: + Changed: How the server responds to Subscribe and Unsubscribe. Events will now contain success/failure of those. This allows us to send the answer after calling a WebHook if needed and we can even send it to multiple clients (which authenticated with the same userID). + Changed: Handling of subscription responsed. This is done to allow web services to subscribe a client remotely and to be able to prevent joining some channel that a user should not join (the channel of some guild or another team, e.g.). + Changed: Debug loggging. In Unity we can't use Debug.Assert, etc. So we have to log more cleanly. This works in Editor and several platforms (but not all). + Changed: Folder for Chat API. It now begins with "Photon" which provides some context no matter where you copy the files. Easier to find in Unity projects. + Changed: Operation FriendList and method SendFriendList renamed to AddFriends + Added: Operation RemoveFriends and corresponding method in ChatClient.cs + Added: Console Demo has new command 'fr' to remove friends + +*** Version 4.0.0.0 (23. May 2014 - rev2614) + Changed: This version contains a few features that are not compatible with the Photon Server SDK v3.x. Notable features that are not in the Server SDK are: NameServer, WebHooks and Turnbased API features. + Changed: This SDK is the first that contains all current APIs for Realtime, Turnbased and Chat. + Fixed: Release build of the Unity assembly now also excludes native-socket using code, fixing a Unity Free export issue. We only use the debug assembly in our demos though and suggest you do the same. +LoadBalancing: + Changed: LoadBalancingClient.FriendList creation/update is delayed until the server's response is available. This avoids cases where the friends are offline for the moment between requesting the update and getting it. Initially, it is null as before. + Added: some methods to Player to find next player, etc. Useful for turnbased games to find an opponent. + Added: LoadBalancingClient.UserId, which is the ID of a user(account). This is used in FindFriends and when you fetch account-related data (like save-games for Turnbased games). Set it before Connect*(). As fallback when empty during connect, the PlayerName is used instead. + Removed: LoadBalancingPeer.OpSetCustomPropertiesOfActor and OpSetPropertyOfRoom which were too special to be so low level. Could be implemented to LBClient. +Turnbased: + Fixed: OpJoinRandomRoom and OpCreateRoom which didn't reset the ActorNr to claim when entering the room. Depending on previous actions, some calls of those methods did fail when the actorNumber wasn't available. + Changed: OperationCode.Rpc is now called OperationCode.WebRpc. It's simply much cleaner (considering PUN has RPCs as well but in a different context). + Changed: WebRpcResponse reading to be able to handle additional data. + Added: Parameter webForward to: OpSetCustomPropertiesOfRoom and OpSetPropertiesOfRoom. The "old" overloads of these methods are still there, too. If webForward is true, the properties are sent to the WebHooks. +Chat: + Added: SendPrivateMessage() overload that has option to encrypt private messages. Public messages don't need encryption. + Removed: lastId and LastMessageIndex from channels. Those were impractical and should be removed from the API. + Changed: UserStatus class to ChatUserStatus. + Changed: Most classes are defined in their own file now. + Removed: Folders "Shared" and their subfolders. This gives a much better overview. + Added: Handling for event SubscribeResponse. This is not actually a response but gives you info about channels that got subscribed (e.g. when you re-login quickly or when a user is logged in in multiple clients). + Added: HandleSubscriptionResults() method to handle the event and proper responses. + +*** Version 3.2.2.6 (13. May - rev2575) + Fixed: Windows Store and Windows Phone libraries now only send the bytes they should send. This means we have to copy the payload from the "complete package buffer" in order to send it. + Fixed: SocketTcp now handles all exceptions during reading. Still, abort-by-server is treated as ServerDisconnect. Everything else as client side disconnect. This fix is especially for iOS exports from Unity. The iOS Power-button will immediately cut any connection. The Home-button allows us to keep the connection if we return the app to focus within a few seconds. + Fixed: TPeer.StopConnection() now clears the incoming queue when it disconnects. This avoids getting any more (already received) commands. + Changed: TPeer.Disconnect() now uses StopConnection instead of implementing the same code again. + +*** Version 3.2.2.5 (30. April - rev2566) +LoadBalancing: + Added: TypedLobby class to replace lobby name/type pair. + Added: LoadbalancingClient.CurrentLobby property. CurrentLobbyName and CurrentLobbyType are obsolete. + Added: New overloads in LoadbalancingClient with TypedLobby parameter instead of separate lobby name and type: OpJoinLobby, OpJoinRandomRoom. Old methods marked obsolete. + Added: New overloads in LoadbalancingClient for OpJoinOrCreateRoom, OpCreateRoom, CreateRoom with parameters packed in RoomOptions class. Old methods marked obsolete. + Breaking: LoadbalancingClient.CreateRoom parameters changed to (string roomName, RoomOptions opt). + Internal: Removed obsolete LoadBalancingPeer overloads of OpCreateRoom and OpJoinRoom + Internal: Added 'onGameServer' parameter to LoadBalancingPeer OpCreateRoom, OpJoinRoom; used to avoid sending extra data to master (player- and room-props) + Internal: Loadbalancing Room constructor(string roomName, RoomOptions opt). + Internal: Added use of the "JoinMode" parameter which is used in context of Turnbased games. + Fixed: Bug in OpLeaveLobby which joined the default lobby instead of leaving any lobby. +General: + Fixed: Server ports were read as short, which was wrong. We now use the correct unsigned short to convert from the address string). + Fixed: A minor issue in the SupportClass ToString conversion which used a Hashtable's key type instead of the value's type in one place. + +*** Version 3.2.2.4 (21. March 2014 - rev2519) + Internal: For Unity, the classes that handle native sockets can now be compiled in a variant that does not actually reference the native-socket-libs. The dll for PUN+ uses native sockets and need the native libs. Any regular dll will have the (not used and empty) classes for build-compatibility reasons. + Added: Values to enum EventCaching: SliceIncreaseIndex, SliceSetIndex, SlicePurgeIndex and SlicePurgeUpToIndex. They are in Lite but used in LoadBalancing. This is likely to be cleaned up in the next major release. + Changed: EventCaching MergeCache, ReplaceCache and RemoveCache as they belong to an outdated form of caching. The "RoomCache" is the better option in any case. +LoadBalancing: + Added: RaiseEventOptions class. It's used for OpRaiseEvent to avoid further parameter- and overload-clutter for this operation. While it's still not optimal for all cases, the fields in the RaiseEventOptions class are hopefully more clear how to use. Maybe some constructors will be added soon. + Changed: All OpRaiseEvent variants, except the one with RaiseEventOptions is now obsolete. + Added: Event Cache Slicing. Cached events can now be organized into "slices" which allows you to handle them in chunks. You can purge events in specific slices (e.g. get rid of the previous game-rounds events). +Turnbased: + Added: RaiseEventOptions.ForwardToWebhook which allows you to forward an event to a webhook (to be defined in Dashboard). Use this rarely, as it has an impact on (server) performance! + +*** Version 3.2.2.3 (18. February 2013 - rev2493) + Added: const PhotonPeer.NoSocket, so programs using our assemblies can detect if they must provide an external SocketImplementation. Some builds avoid using the Socket class (cause Unity Free doesn't support it on all platforms). + Added: PhotonPeer.SendMessage method in order to send any serializable object to server. + Added: IPhotonPeerListener.OnMessage in order to be notified about getting message from server. + Added: new 'Connect' method, which accepts as third parameter any serializable object. You may use this object on server before creating peer. + Added: OnMessage callback to samples + Changed: TCP and UDP both set the socket to null explicitly in Disconnect(). Hopefully this fixes a misbehaviour in Unity Editor which locked up often. + Changed: SocketTCP now has a syncer object and locks in Disconnect(), so only one Disconnect call can be made anytime. + Fixed: Nullreference when calling DispatchIncomingCommands() before Connect(). This was due to a (new) use of the socket wrapper. Commented this out until needed. + Fixed: Nullreference when calling SendAcksOnly() before Connect() with a new non-null check. + Fixed: breaking issue in Hashtable replacement class. Enumerators used in 2 "foreach" loops were breaking with a nullreference. Fix: No caching of enumerator. + Changed: AutoJoinLobby now uses this.CurrentLobbyName and this.CurrentLobbyType to join a specified lobby. + Changed: EnetPeer.StopConnection will always reset the state to be able to re-connect. + Changed: Disconnect() in SocketTcp and SocketUdp sets this.socket = null, even if socket.Close() caused an exception. This is what was expected. + Added: SocketUdpNativeDynamic and SocketUdpNativeStatic to "regular" Unity Lib, to improve compatibility in Unity for different export platforms (with and without native sockets). + +*** Version 3.2.2.1 (17. October 2013 - rev2335) + Note: This lib contains a lot of breaking changes and socket handling has been refactored. By now, this is well tested and confirmed working. + Changed: The way sockets are handled and added native-socket-lib support. There is a new IPhotonSocket interface which even allows to use external classes as socket wrapper. + Added: SocketImplementation property to set a class as socket implementation (Unity. sets native implementation or c# socket at compile time) + Changed: Win 8 RT and Phone now use fewer separate classes and files. Instead, more files from the (regular) DotNet client are used. RT and Phone are now part of the trunk folder in our SVN. + Added: TrafficStats.TimestampOfLastAck and .TimestampOfLastReliableCommand + Changed: Handling of server-side shutdown (a form of TCP disconnect) is now handled specifically as server-side-disconnect (was: generic receive exception) + Added: If a UDP connection times out in a client, it sends a special flag in it's disconnect command (to the server). This enables us to detect which side is triggering timeouts more often (and we can improve things). +LoadBalancing API + Fixed: issue where we called a virtual member from a constructor (http://confluence.jetbrains.com/display/ReSharper/Virtual+method+call+in+constructor) + Changed: LocalPlayer is now a property which checks null and returns a new Player (via virtual CreatePlayer) on demand. + Added: OpJoinRoom now optionally creates a room if parameter "createIfNotExists" is set to true and the room didn't exist. Room properties can't be set "on create" this way. LocalPlayer.IsMasterClient will be true. + Added: When OpJoinRoom can create a room, it also won't define which properties go into the lobby. You can use the new Room.SetPropertiesListedInLobby(). + Added: You can pass a actorNumber to OpJoinRoom when you re-enter a room and want to reclaim a specific actorNumber in that room. In best case, the client can re-join after a disconnect/crash and seamlessly go on playing. + +*** Version 3.2.1.6 (15. August 2013 - rev2272) + Changed: The library for Unity now contains a ExitGames.Client.Photon.Hashtable to be compatible with Win 8 exports. This must be used from now on! + Note: In Unity, the compiler will complain about ambiguous Hashtable definitions. To solve this, add this to the "using" part of your code: using Hashtable = ExitGames.Client.Photon.Hashtable; + Removed: Builds for Silverlight and Windows Phone 7.1 (this is not affecting Windows 8 RT and Windows 8 Phone SDKs which are of course supported) + Fixed: A null-reference check for a TCP connection's SendAcksOnly(). + +*** Version 3.2.1.5 (06.08.2013 - rev2242) + Added: Steam and Facebook entries to CustomAuthenticationType enum. + Fixed: Potential nullreference exception in TCP SendAcksOnly() code. If called before Connect(), this always failed. + Updated: Replacement classes for datatypes not supported on some platforms (Hashtable mostly). + Added: Hashtable got a new GetEnumerator that returns a IDictionary just like the standard Hashtable does. + Changed: Constructor with int InitialSize now calls the matching base constructor. + Removed: Synchronized() method which didn't do much and is not used. + Changed: ToString is now an override instead a "new" method. + Changed: DataTypes.cs: the Stopwatch is only implemented for Silverlight (non Windows Phone 8) + Updated: Description. + Changed: Protocol to expect Hashtable always providing a DictionaryEntry. Related to change in DataTypes.cs. + Changed: Protocol now has conditional "Dictionary" detection. In WP8 the API is different for that. Uses #if WINDOWS_PHONE. same file now works in W8 and WP8. + Changed: Removed PRPCAttribute from SupportClass.cs. This is used only in PUN and needs conditional per-platform compilation anyways, so it gets implemented there. + Removed: surplus debug output in ReceiveIncomingCommands(). + Fixed: Debug output in FetchServerTimestamp() depended on the Thread calling the method. Correct: The output is enqueued and dispatched later on. + Fixed: FetchServerTimestamp no longer fails with a SendError when the state is not "Connected". + Internal: Metro-Alike project now uses DataTypes.cs of Silverlight (like everyone else). Removed surplus copy. + Internal: DataTypes.cs and Protocol.cs files can now be used in DotNet 3.5, Windows Store and Windows 8 Phone. + Internal: outdated compiler-definitions "Photon" and "METROALIKE". + +*** Version 3.2.1.4 (10.07.2013 - rev2209) + Added: "Typed Lobby" API. Photon Cloud and Loadbalancing now support multiple lobbies per app/title. Also, different types of lobbies are now possible, each can have different options and different rules for matchmaking. + Added: enum LobbyType with "Default" and "SqlLobby". The SqlLobby is a new type of lobby that uses up to 10 room properties with sql-like filters. The filter being written like the "where" part of a sql query. + Changed: FetchServerTimestamp now enqueues callbacks (can be called by socket-receive-thread). also no longer causes a disconnect callback if offline + Changed: RemoveSentReliableCommand now enqueues callbacks (can be called by socket-receive-thread) + Internal: SendAcksOnly override in TCP's TPeer class. This now sends pings but nothing else. That resets the server's timeout for this peer +LoadBalancing API + Updated: LoadBalancing API in the Unity demos (now gets copied over at build time, making sure it's identical to the DotNet "original") + Fixed: LoadBalancingClient now handles SecurityException and InternalReceiveExceptions and disconnects correctly. Before, especially Unity web clients would get stuck in "Disconnecting" state. + Fixed: LoadBalancingClient state on disconnect (no matter what caused the disconnect). + +*** Version 3.2.1.3 (19.06.2013 - rev2170) + Fixed: surplus conversion of incoming data to string, which was used in debugging. + +*** Version 3.2.1.2 (17.06.2013 - rev2160) + Fixed: custom auth will send custom auth parameters if any authentication params are set + +*** Version 3.2.1.1 (10.06.2013 - rev2148) + Added: new POST value for Custom Authentication. POST can carry more data than GET (usually used). AuthenticationValues has a setter for this. +LoadBalancing API + Changed: LoadBalancingClient.AuthValues is renamed to CustomAuthenticationValues property (sets the custom authentication values). + Changed: Player class now compares by ActorNumer (assigned by server) instead of comparing the instance. + Internal: SupportClass.GetMethods() now returns type.GetRuntimeMethods(), filtered by attribute (if at all needed). This is used by Photon Unity Networking (PUN) internally. It also returns inherited methods now, not only Declared. + +*** Version 3.2.1.0 (24.05.2013 - rev2112) + Added: Feature "Custom Authentication" which lets you authorize players/users in the Photon Cloud with an external account/user service. More on that online: http://doc.photonengine.com/photon-cloud/CustomAuthentication + Added: LoadBalancing API Feature "Friend Finding" which enables a client to find friends in rooms by userId. If an external service provides a userID per player and a friend list, this can be used to find a friend's room (game) and join it (unless closed or full). + Added: CustomAuthenticationType enum to enable differnt types of custom auth later on (only one actually useful value so far). + Added: Class AuthenticationValues as container for authentication values. + Added: LoadBalancingClient.Connect overload which takes a AuthenticationValues parameter. + Added: LoadBalancingPeer.AuthValues property to set the custom authentication values. + Added: Parameter authValues to OpAuthenticate. This is used to provide the authentication parameters and or the secret/ticket provided by Photon. + Added: ErrorCode.CustomAuthenticationFailed to be used in switches for OperationResponse.ErrorCode (for OpAuthenticate). + Changed: LoadBalancingClient.PlayerName can be set before connecting to get a UserId which is "findable" by OpFindFriends(). Find friends does NOT use any values set for custom authentication! + Added: Class FriendInfo to contain a friend's name, online state and room name (if available and after using OpFindFriends()). + Added: OpFindFriends() to actually find the friends. Use on the Master Server only, not on a room. + Added: LoadBalancingClient.FriendList, a List of FriendInfo entries. Filled by using OpFindFriends (don't modify this list directly!). + Added: LoadBalancingClient.FriendListAge, to let you know how old the FriendList is. Only get updates when the list gets "old". + Fixed: OpRaiseEvent will no longer send "group" if it's 0 (which is the default). + Added: OpRaiseEvent overload to send object instead of Hashtable. This overload uses another parameter order to not mix up with the older implementation. You can send any serializable datatype now but must be aware if the event is Hashtable or something else. + Changed: Several variants of OpAuthenticate(), Connect() and ConnectToMaster() are now obsolete or removed. Use the alternative implementations (which should be cleaner). + Internal: Added several (operation) parameters to enum ParameterCode: ClientAuthenticationType, ClientAuthenticationParams, FindFriendsRequestList, FindFriendsResponseOnlineList, FindFriendsResponseRoomIdList. + Added: PhotonPeer.ResentReliableCommands to get count of re-sent commands (might be higher than out command count (as that counts created commands only) + Internal: Address (string) handling now uses string.Split instead of IndexOf to separate port from address and short.TryParse instead of short.Parse + Added: TrafficStatsGameLevel.ResetMaximumCounters() to reset those values that could max-out easily. Allows to get "longest delta between SendOutgoingCommands()-calls since last query". + +*** Version 3.2.0.2 (21.02.2013 - rev2066) + Fixed: Potential lock-up during sending. This could cause infinite blocking and thus a crash in some apps. (Win8 / Win Store api only) + +*** Version 3.2.0.1 (15.02.2013 - rev2060) + Fixed: Issue with delayed sending of operations in udp. The data could become overwritten before being sent. The bug was leading to high disconnect rates for clients using Windows Phone 7 and 8 and Silverlight or any client that used Network Simulation. + +*** Version 3.2.0.0 (13.02.2013 - rev2053) + Note: This release only changed the version, matching the new Server SDK v3.2.0.0 + Updated: readme.txt + Fixed: Reference for Windows 8 RT and Windows Phone 8 SDKs. + Added: Particle Demo to Unity Client SDK. + +*** Version 3.0.1.18 (11.02.2013 - rev1998) + Added: Optional per package CRC checksums to filter out compromised packages (avoiding more issues, compared to reading bad values). + Added: PhotonPeer .CrcEnabled and .PacketLossByCrc to handle CRC and get the count of affected (incoming) packages. + Note: Checking packages with CRC will take some computation time. Consider this an option to detect if/why someone's connection is bad. It's likely not good to be enabled by default. +Windows 8 RT & Windows 8 Phone: + Fixed: Serialization of foat and double values. These caused exceptions when used in object-arrays. + +*** Version 3.0.1.17 (19.12.2012 - rev1946) + Added: New Platform: Mono 4 Android. Please check the Readme.txt for hints how to build the demo in Mono 4 Android. + Changed: The referenced DotNet assemblies used by our libraries, which makes ours compatible with Mono 4 Android and others. + Changed: The Particle Demo Logic to also handle events sent by JavaScript clients. In case these are used, the types used in event differ from what DotNet or other clients send. + Changed: PhotonPeer.LocalTimeInMilliSeconds property now uses SupportClass.GetTickCount(). That method is using Environment.TickCount (which can be replaced if needed). + Changed: Any place that directly used Environment.TickCount (as the way SupportClass.GetTickCount() gets the value can be replaced). + Renamed: GetLocalMsTimestampDelegate is now: SupportClass.IntegerMillisecondsDelegate (rarely used if at all). + +*** Version 3.0.1.16 (29.11.2012 - rev1923) + Internal: A client timeout now internally sets connectionState to Zombie and then calls Disconnect() instead of stopping the connection right away. + Changed: Disconnect() sends a disconnect-command in any case (except not connected or disconnecting). If the connection is not in state connected anymore, said command is unsequenced (unreliable) and the disconnect is locally executed immediately as call to StopThread(). As before, disconnecting and disconnected clients won't send this. + Changed: Ping creation is now more strict and checks also if any reliable commands are outgoing AreReliableCommandsInTransit(). this avoids a few pings. + Fixed: NullReference exception in StopConnection() if it's called before being connected for the first time (late object creation made this fail). + Changed: PhotonPeer.LocalTimeInMilliSeconds property now uses SupportClass.GetTickCount(). That method is using Environment.TickCount (which can be replaced if needed). + Changed: Any place that directly used Environment.TickCount (as the way SupportClass.GetTickCount() gets the value can be replaced). + Renamed: GetLocalMsTimestampDelegate is now: SupportClass.IntegerMillisecondsDelegate (rarely used if at all). + + +*** Version 3.0.1.15 (27.11.2012 - rev1917) + Note: Silverlight SDK release only! + Updated: Silverlight projects with proper references (hopefully). In case you wonder: Some projects are included even though only their (source) files are linked in Silverlight. We can't reference DotNet projects directly, so we use the (shared) files instead. + Updated: Silverlight Particle Demo now has a basic gui and hopefully helps with your first steps. + +*** Version 3.0.1.14 (16.11.2012 - rev1891) + Added: Interest Groups! In rooms, you might send events to an interest group, identified by a byte (255 groups are currently allowed). OpChangeGroups lets you add or remove groups you're interested in. + Added: New platform! Welcome Windows 8 RT and Windows Phone 8. Both are "preview" releases but based on the stable DotNet basis we have. + Note: The Windows Phone 8 SDK does not yet have a LoadBalancing demo but the API is available (Windows Phone 8 is separate from the still existing Windows Phone 7.1 SDK). + Added: Another new platform: Playstation Mobile! This is Sony's SDK for mobile platforms. Find out more about it: www.playstation.com/psm + Added: Silverlight 4 SDK is back. Now with LoadBalancing API (the demo implementation is not finished but the basic "logic" is running). + Fixed: Windows Phone 7 and Silverlight TCP error handling while connecting to the server. This should fix issues with failing connects due to missing policy settings. + Internal: Windows Phone 7 and Silverlight TCP connections now set their state a bit differently (this doesn't affect the workflow though). + Internal: Http implementation now checks if a Proxy was set deliberately. Check is: (WebRequest.DefaultWebProxy as WebProxy != null). + Internal: DispatchIncomingCommands() now avoids copying lists when checking for commands that need a repeat. + Internal: SendOutgoingCommands() now re-uses a buffer to create UDP packages in before sending. This should save a lot of memory allocation. +LoadBalancing API: + Added: New demo "Particle". You will notice it's similar to the "Realtime Demo" but LoadBalancing- and Cloud-compatible and it makes better use of the default features. Check out Particle "Logic". + Added: LoadBalancingClient.DisconnectedCause to track certain disconnect causes (no matter if the connection or an operation caused the disconnect). + Added: DisconnectCause enum to enumerate those disconnection causes. + Changed: LoadBalancing OnOperationResponse() and OnStatusChanged() to track most disconnect reasons (in DisconnectedCause). + Removed: LoadBalancing Connect() variants that essentially were duplicates of others. + Changed: LoadBalancingClient debug output now goes to: Debug.WriteLine (which is available in debugger, while Console is not always). + Changed: CacheProperties method is now virtual for Room and Player. This allows you to override it and use this as callback to update props. + Added: Player.Tag to store arbitrary (game) data with the Player. Put in (e.g.) a player's representation/avatar or similar. + Added: ErrorCode constants MaxCcuReached and InvalidRegion. These are important for the Photon Cloud. + Added: Handling for DisconnectedByUserLimit. This is a status of OnStatusChanged when a Photon Server License's CCU limit is reached. This no longer will try to connect to a Game Server (where it gets rejected, too). + Changed: Debug output of loadBalancingClient now goes to Debug.WriteLine (which is available in debugger). + Changed: API now uses a factory method to create Room instances (this makes it possible to extend the Room class and instantiate the new class instead). + Changed: The Player constructor now has an "actorProperties" parameter and will cache the provided properties. This makes sure actor-props are available locally. +Windows Phone 8: + Added: Demo for Cloud / LoadBalancing. The Particle Demo only has a special WP8 GUI and links it's logic from a separate project (read: folder). +Windows 8 RT: + Added: Demo "Phong", which is a simplified, basic multiplayer game. It's focus is to show how to sync data, not to make it super smooth and error free. Let us know any issues but bear with us as it isn't fully featured. + +*** Version 3.0.1.13 (26.09.2012 - rev1731) + Fixed: Internals of method DispatchIncomingCommands() for UDP. In some cases this removed commands from a dictionary inside a foreach loop (which causes an Exception due to changing the dictionary) + Added: Support for Dictionary<,>[]. This is not a very lean way to send data (especially when using ) but if needed, it now works + Changed: Replaced several foreach loops with for loops (it doesn't change usage but in Unity exports to iOS, foreach uses more memory than for) + Added: Doc for public methods in Protocol class (they are useful to quickly write values into an existing byte-array) + Fixed: Unity UDP send code: iOS 5 devices will kill a socket when the power button is pressed (screen locked). This case was not detectable by checking socket.Connected. + Added: Unity UDP send code: Now tries to open another socket to refresh/keep the connection. This is affected by timeouts still, of course (as are all connections). + Internal: locked usage of UDP / enet channels + +*** Version 3.0.1.12 (26.07.2012 - rev1683) + Changed: The DotNet client libraries are now Thread safe! You could start a background Thread to keep calling SendOutgoingCommands in intervals and still call it from a game loop, too + Changed: Due to the thread safety, the demos no longer use excessive locks. This is now solved by the lib, more streamlined and hidden. One Thread is used instead of Timers (which could fire concurrently if execution was longer then their interval) + Changed: Moved the enable/disable property fro NetworkSimulationSettings to PhotonPeer.IsSimulationEnabled (this should now be thread safe) + Changed: NetworkSimulation will create and keep one thread when you first enable it in a (debug) client. Disabling it, will execute any delayed action immediately (in IsSimulationEnabled!) and pause the simulation thread + Changed: All demos are updated. We assigned new event codes (starting at 0, like any developer's code should) and extended the comments. Check them out + Changed: All Loadbalancing demos are now using the same DemoBasisCode linked in, so it can be changed in one position. Where needed an extension is made + Updated: comments / documentation for LoadBalancing API, Lite API and basic Photon API (basically anything public) + Changed: SupportClass.NumberToByteArray is now obsolete. It can be replaced with Protocol.Serialize() easily and that is performing better + Fixed: Windows Phone UDP socket was sending a full package of zeros on connect. It didn't break anything but is not needed, of course. + Fixed: SupportClass.StripKeysWithNullValues method was prone to throw an exception +LoadBalancing API: + Changed: LoadBalancingClient.OpLeaveRoom() skips execution when the room is null or the server is not GameServer or the client is disconnecting from GS already + Note: LoadBalancingClient.OpLeaveRoom() returns false in those cases and won't change the state, so check return of this method + Fixed: workflow for authentication (which should be called only once per connection, instead of "any time we establish encryption) + +*** Version 3.0.1.11 (05.06.2012 - rev1569) + Fixed: Udp issue with channels and unreliable commands. Unreliable commands of one channel were discarded, when another channel had unreliable commands, too + +*** Version 3.0.1.10 (04.06.2012 - rev1561) + Fixed: TCP connection issues for DotNet and Unity (Silverlight and WindowsPhone are different) + Fixed: DotNet+Unity TCP send calls with 0 bytes to send (this was ignored by the socket but useless anyways) + Moved: DNS resolution and socket.Connect() are now handled in the connection thread (TCP in DotNet and Unity) + Fixed: Issue with (TCP) socket connections being closed directly while connecting. in this case, socket.Receive() might receive 0 bytes instead of blocking until more bytes are available. without sending anything, the socket never updates its .Connected state and never throws a Exception. now we send a ping and thus trigger a exception + Fixed: Some documentation errors (due to changed API, etc) +Loadbalancing API: + Changed: LoadBalancingClient.OnEvent() now uses a join-event's actornumber-list to create Player instances for anyone who wasn't created as Player before + Fixed: LoadBalancingClient.OnEvent() handling for join-event does not expect any actor/player properties anymore (which fixes a potential null-reference exception when not even a name is set) + +*** Version 3.0.1.9 (10.05.2012 - rev1512) + Fixed: Reference to project in Windows Phone SDK + +*** Version 3.0.1.8 (09.05.2012 - rev1508) + Fixed: The OpJoinRandom of the LoadBalancingAPI failed to filter rooms for their custom room properties. Instead, any room matched. This is fixed now. + Added: New Demo for Windows Phone: Cloud Basics + Changed: The loadbalancing / cloud-based demos are refactored to share a similar codebase + +*** Version 3.0.1.6 (07.05.2012 - rev1489) + Note: This is a "stable" release, containing only a few updates. The bulk of changes are in the "odd" numbered releases. Read those updates carefully. + +*** Version 3.0.1.5 + Changed: adopted the even/odd version numbering system. versions ending on a odd number = intermediate/in-development version, even number = released (that makes 3.0.1.5 a intermediate) + Fixed: When NetworkSimulation is disabled, all remaining packages are sent/received immediately (ignoring the former delays) + Note: NetworkSimulation should be working nicely now. Be aware that sudden, additional lag might (!) lead to a disconnect. Play with the settings to find out which ones work for you + Changed: Protocol class now has a few methods to (effectively) serialize some datatypes to arrays (and into existing arrays) + Removed: Surplus public methods from Protocol that were "type-named" like SerializeFloat. The functionality is in still with overloaded methods + Added: count of packages (requests) outgoing if TrafficStatsEnabled +Demo Realtime: + Changed: The commandline arguments are now server:port, protocol (udp,tcp,http), reliable sending, interval dispatch, interval send, interval move. Example: localhost:5055 Udp false 15 25 15 + Changed: Demo Realtime: If the commandline sets an unknown protocol, the client shows a message and closes gracefully + Changed: Demo Realtime: The demo now starts in the grid view (showing something). Local player and player list are created with the Game instance. Player startpoint is randomized. +Loadbalancing API: + Renamed: LoadBalancingClient.lbPeer to .loadBalancingPeer + Fixed: LocalPlayer.SetCustomProperties() usage + Added: Service() method, which calls the LoadBalancingClient's Service simply + Changed: LoadBalancingClient is no longer extending LoadBalancingPeer but instead using one + Changed: the many overloads of Operations are gone in LoadBalancingPeer to streamline the api + Changed: ActorProperties are no longer set via JoinRoom, JoinRandomRoom or CreateRoom. instead, set the properties in the LocalPlayer and let the LoadBalancingClient send and sync them where necessary + Fixed: MasterClientId is now 0 when there are no more players in the room (it was set to int.max before) +Internal: + Changed: all DispatchIncomingCommands now use a while loop to dispatch the ActionQueue (in the hope this is the fastest way to do it) + Changed: DispatchIncomingCommands now looks for the received unreliable command with lowest unreliable seqNr to dispatch this + Changed: DispatchIncomingCommands discards commands if the reliable OR unreliable sequence is beyond the command's sequences + Changed: DispatchIncomingCommands now truncates the incoming unreliable commands to limitOfUnreliableCommands (if that's > 0) + Changed: the next reliable command to dispatch is now fetched with Dictionary.TryGetValue() (for being faster) + Changed: no longer using BinaryReader streams anywhere (this should improve speed and reduce mem usage) + Changed: PeerBase accordingly + Changed: Unit test MyType de/serialization now supports null-references (as 1 byte being 0) + Changed: Protocol.SerializeOperationRequest is now used in the same way, no matter if request is "top level" or inside some other datatype + Changed: the peer bases accordingly to use only one SerializeMemStream and lock it + Changed: how encryption fits in to the new serialization (it is a special case, as only the operation bytes get encrypted) + Added: Protocol.SerializeParameterTable() as requests, events and responses all use the same way to write their parameters + Changed: SerializeOperationToMessage parameter order + Changed: Order of Protocol methods to make more sense (from byte to more complex types for serialization) + New: PhotonDotNet library prototype for windows 8 metro + +*** Version 3.0.1.3 (13.04.2012 - rev1430) + Known issues: The Network Simulation is currently not guaranteed to work properly. Please bear with us. + Note: the following change might be a breaking one: + Changed: When dispatching a server's disconnect-command, the state is changed to ConnectionStateValue.Disconnecting BEFORE any callback due to state change is called. This should disallow game-code from calling any operations immediately. + Changed: Many internals. This should result in better performance + Changed: Service() now calls SendOutgoingCommands() until send-queues are empty. This might take more time but gets important commands out. If you need more control, Service() can be replaced with DispatchIncomingCommands and SendOutgoingCommands! + Added: null check to GetEndpoint() to avoid issues when the host address is null + Fixed: queueIncomingCommand() debug out message when a command is being received AND in in-queue (the list it accesses is now a dict) + Added: new "vital" stats to TrafficStats + Added: LongestOpResponseCallback and LongestOpResponseCallbackOpCode (opcode and time of longest callback) + Added: LongestEventCallback and LongestEventCallbackCode (event code and time of longest callback) + Added: LongestDeltaBetweenDispatching and LongestDeltaBetweenSending to detect "gaps" between subsequent calls of those + Added: DispatchCalls and SendOutgoingCommandsCalls to measure average call-rate + Fixed: PeerBase.TrafficStatsEnabledTime now checks if a stopwatch is set, else it returns 0 + Fixed: TrafficStatsReset() now works as intended (starting a new stopwatch, too) +Internal: + Changed: name of variable timeLastReceive. is now: timeLastAckReceive (better fit with what it does) + Internal: queueOutgoingReliableCommand() to use a lock on the channel it accesses + Internal: SerializeOperationRequest() now locks the MemoryStream while using it (avoids threading-issues with calling OPs) + Internal: SendUdpPackage() now checks if socket is obsolete (and disconnected for a reason) or not. only if not, a error is logged + Internal: EnetChannel now uses Dictionary and Queue for commands (should be faster to access) + Internal: simplified access methods in EnetChannel according to changes + Internal: outgoingAcknowledgementsList is now a Queue + Internal: receiveIncomingCommands() no longer has a local variable sentTime. instead using this.serverSentTime directly + Internal: UDP sending is now done with a synchronous socket call (profiling told us: this is cheaper) + Internal: re-using the socket arguments for receiving packages (saves some buffer allocation) + Internal: socket to non-blocking (maybe not possible on all devices) + Removed: initial-HTTP-protocol support (HTTP support not public yet) + Added: support for encryption with HTTP protocol + +*** Version 3.0.1.2 +- Added: Rooms now have a "well known" property to list the custom properties that should be available in the lobby. This can be set per room (but most likely makes sense per title/application). +- Added: LoadBalancingClient.OpCreateRoom() has a new parameter "propsListedInLobby" and Room.PropsListedInLobby is available to check this list (if needed at all). +- Added: GameProperties.PropsListedInLobby as "well known property" key +- Changed: LoadBalancingPeer.OpCreateRoom now sets ParameterCode.CleanupCacheOnLeave to true by default. This makes the server clean a player's event cache on leave. +- Added: SupportClass.DictionaryToString() will now print values of string[] and optionally leaves out type information. +- Note: 3.0.1.1 didn't get it's own SDK, so read that version's changes, too + +*** Version 3.0.1.1 +- Added: PhotonPeer.TrafficStatsElapsedMs, which gives you the milliseconds that the traffic stats are enabled. This internally uses a stopwatch (for now) which might not be available on all platforms. Please report if this new SDK causes issues. +- Added: PhotonPeer.TrafficStatsReset() to reset the traffic stats and the timer. This could be useful to get stats of "in game" versus "out of game". Note: Loadbalancing includes frequent server-switching and each disconnect/reconnect causes a reset. +- Changed: In LoadBalancingPeer EventCode.SetProperties is obsolete and replaced with EventCode.PropertiesChanged. Please switch to new constant. +- Added: Support in LoadBalancingAPI for Player.IsMasterClient. For this, the Players now get a RoomReference set (when added). The active player with the lowest ID is the master (per room). +- Added: Room.MasterClientId, which is updated when new players are added or the current master is removed. +- Added: SupportClass.DictionaryToString() has an overload which doesn't "print" the Type per key/value. +- Added: Loadbalancing API overload for OpJoinRandomRoom(...) taking additional parameter 'playerProperties' +- Added: Loadbalancing API CacheProperties() and Room.GetPlayer() are public now +- Added: LoadBalancingClient will now handle ExceptionOnConnect and keep clients from re-connecting if establishing a connection fails +- Note: The following changes affect only HTTP, which is an upcoming option for connections. So far, the public server SDKs don't support this. Feel free to contact us about it. +- Added: setter for PhotonPeer.ServerAddress to allow setting a http url (even while connected) +- Added: PhotonPeer.HttpUrlParameters setting parameters to be added to end of url (must begin with '&') +- Added: HttpUrlParameters to PeerBase +- Added: HttpUrlParameters is now attached to the end of a URL in http usecase +- Added: "Http2" support to Unity library +- Internal: method HttpBase.ConnectAsync is no longer needed and Request() is now directly passed to thread + +*** Version 3.0.1.0 +- Added: Loadbalancing (Cloud) Features +- Added: Project with the Loadbalancing sourcecode for DotNet, WindowsPhone and Unity3d (usable without PUN) +- Added: Initial, simple Loadbalancing demos for each platform (will update and extend those) +- Note: The API of the client libraries didn't change. The new features were added on top of the known API +- Added: VS2010 solutions for DotNet and Windows Phone SDKs containing the demos and APIs in the package +- Added: readme.txt with initial help to setup the Cloud/Loadbalancing demos +- Added: default appId for Loadblanacing demos: "" + +*** Version 3.0.0.10 +- Added: When UDP StartConnection (internal method) fails, callbacks to OnStatusChanged(StatusCode.Disconnect) are now done additionally to the SecurityExceptionOnConnect and ExceptionOnConnect calls. This happens direcly inside PhotonPeer.Connect()! +- Changed: When Unity UDP implementation fails to connect due to missing DNS resolution, it now also calls OnStatusChanged(StatusCode.ExceptionOnConnect) +- Removed: StatusCode.Exception_Connect value (obsolete, replaced by ExceptionOnConnect, same value) +- Fixed: Http connections (DotNet & Unity) now skip results while in disconnected state +- Fixed: Http connections (DotNet & Unity) now ignore results after a disconnect and reconnect was done (this applies only to HttpBase, not HttpBase2) +- Fixed: misleading debug out (pointing to WindowsPhone while the class is now in general use) +- Changed: DotNet UDP connection now only logs socket errors if the connection isn't obsolete (disconnected) already + +*** Version 3.0.0.9 +- Fixed: issue with HTTP connections and EstablishEncryption() +- Changed: ActionQueue is now a Queue, allowing Dequeue in a while loop instead of foreach(i in list) and clear() +- Changed: Unity HttpBase DispatchIncomingCommands() to make use of the queue +- Fixed: init byte[] length (internal. did not have consequences) +- Fixed: LitePeer OpRaiseEvent() was sending encrypted +- Internal: ContainsUnreliableSequenceNumber() check if reliable list needed sorting +- Fixed: Unity/Silverlight bug with encryption. Their implementation of BigInteger.GetBytes() failed when the 2nd, 3rd or 4th of the first 4 bytes was 0 but the previous wasnt. This led to incompatible secrets. +- Changed: TCP socket sending debug output now checks debuglevel (when send is skipped, cause the sender is obsolete already) +- Added: caching option RemoveFromRoomCacheForActorsLeft = 7 +- Internal: Added another http-based communication protocol. Please note: The fitting server's are not yet publicly released. This does not affect UDP or TCP protocols. + +*** Version 3.0.0.8 +- Fixed: Udp fragment reassembly in case fragments are received out of order and incoming queue was not yet sorted +- Fixed: Handling of incoming reliable commands (udp) which were skipped in some cases, if not received in order +- Fixed: Network simulation issue which caused lost incoming commands +- Fixed: Demo Realtime. protocol is now again Udp, fitting the default server address "localhost:5055" (make sure to build the demo with your server's address if Photon is not on the same machine) + +*** Version 3.0.0.7 +- Changed: Udp socket usage for Unity 3d lib. Both threads (send (in game loop) and receive (separate)) now have minimal locks while using the socket +- Fixed: SendOutgoingCommands now returns true if anything didn't make it into the outgoing UDP package +- Internal: TCP connections also skip network simulation when it's turned off + +*** Version 3.0.0.6 +- Fixed: SendOutgoingCommands now returns true if commands are remaining in outgoing queues (UDP only sends one package per call, TCP will send anything outgoing). +- Added: New "RoomCache" for Events. The EventCaching enum allows you to use it. Events in this cache will keep the order in which they arrived in the server. A filter makes deleting them very flexible. +- Internal: Ability to make lib send only ACKs and nothing else. This is probably a temp solution as it might be better to make sending and calling ops completely thread safe. +- Internal: PhotonPeer.IsSendingOnlyAcks, which is locked with the sending (not changing while sending). This makes SendOutgoingCommands() thread safe, which is good if you need a separate thread to keep connection. You could call operations while sending. +- Internal: Unity3d's connection now also syncs socket usage + +*** Version 3.0.0.5 +- Fixed: ObjectDisposedException in DotNet UDP workflow. This was caused by disconnecting while incoming data was processed (and before the next datagram was accepted) +- Added: PhotonPeer.LimitOfUnreliableCommands property. This helps you skip potentially "outdated" unreliable commands (events), which helps if you couldn't dispatch for a while +- Internal: Minor performance improvements. Example: The check if network simulation is turned on is done earlier in the workflow, which avoids a bit of overhead + +*** Version 3.0.0.4 +- Fixed: Tcp connections have been throwing ArgumentNullException in DispatchIncomgingCommands() if they were not connected yet +- Internal: Adjusted Http client to server rev2360 + +*** Version 3.0.0.3 RC2 +- Internal: Communication with HTTP server is WIP (Work In Progress - not a publicly available feature) + +*** Version 3.0.0.2 +- Fixed: OpRaiseEvent overload with EventCaching and ReceiverGroup parameters was not sending the customEventContent as expected. This was always null. +- Fixed: Time fetching case where no time was accepted. Servertime is now accepted, if the fetch-time-command was less or equal as the current roundtrip time. Avoids issues if rtt is exceptionally low immediately. +- Internal: When using multiple channels, dispatching incoming commands now will continue with the next channel, if one doesn't yet have the next reliable command (reliable sequence of one channel does not affect others) +- Internal: Changed protocol for TCP and message headers. This will support bigger message sizes. Also changed debug out related to unknown headers. +- Internal: Changed handling of TCP receive-callbacks for unfinished messages in Silverlight and WP. This should fix handling of very big data that's received in multiple "chunks" +- Internal: Http messages are now deserialized the same way that content in tcp or udp is handled + +*** Version 3.0.0.1 RC1 +- Fixed: Packaging of SDK now includes all files in demo folders, except a list of ignored file-endings (xaml and jpg files were missing in previous Silverlight and WindowsPhone SDKs) + +*** Version 3.0.0.0 RC1 +- Changed: Filenames! Now include a '3' for Photon v3. Update your references! Also, Silverlight libraries now use "Silverlight" in the filename (was: SL) +- Changed: Versioning. A dll's version has now 4 digits. The first 2 match Major and Minor number of the Server SDK. The latter 2 are Release and Build respectively +- Changed: Silverlight DataTypes (like Hashtable) are now in namespace ExitGames.Client.Photon. This is easier to include (as that namespace is in "using" in most cases) + +*** Version 6.4.5 +- Changed: Parameters for OpCustom are now of type Dictionary, making sure that only byte-codes are used for parameters +- Changed: Most IPhotonPeer names (to match those in server code): EventAction -> OnEvent, OperationResult -> OnOperationResponse, PeerStatusCallback -> OnStatusChanged +- Added: SupportClass.DictionaryToString(), which converts the content to string (includes support for Hashtables) +- Moved: Definitions of Lite and Lite Lobby specific codes for Parameters, operations and events are now in LitePeer. Will be available as source and could be replaced +- Changed: Usage of codes in Lite and Lite Lobby. Now pre-defined codes are starting at 255 and go down. Your events, operations and operation-parameters can now start at 0 and go up without clashing with pre-defined ones +- Changed: Constants that are non-exclusive (like event codes and OpKeys, which can be extended) are no longer "defined" as enums but as class of const byte values. Less casting but also less convenient "name" representation in debug output +- Added: LiteEventKey.CustomContent as key to access the content you sent via OpRaiseEvent ("Data" seems a bit misleading but is also available) +- Changed: Namespace of LitePeer to ExitGames.Client.Photon.Lite (the Lite-specific class is still compiled into the library for convenience but can be ignored quite easily this way) +- Added: Property MaximumTransferUnit. The default is 1200 bytes. Usually this is ok. In few cases, it might make sense to lower this value to ~520, which is commonly assumed the minimum MTU. Don't change this, if you don't know why. +- Added: New classes to wrap up op-requests (OperationRequest), op-results (OperationResponse) and events (EventData). Those new classes are now used in callback methods OnEvent and OnOperationResponse +- Changed: by using the new classes (note above), the client is a bit more like the server in its naming. We didn't want to change every last bit though. +- Internal: Changed protocol (to 1.6) so that it does not require any parameter codes internally. Any application can now define any operation, parameter and event codes it wants to. +- Changed: Encryption is now triggered by you and resolved by the library. You don't have to look out for the result of EstablishEncryption and use it. Instead: wait for OnPeerStateChanged call with either EncryptionEstablished or EncryptionFailedToEstablish +- Removed: InvocationId. This concept was very rarely used but confusing. It's easy to implement, if needed. If you don't know what this means: Nevermind. +- Changed: Operation calls now return bool: if they could be enqueued or not. If enqueued (cause you are connected and the data was serializable), then SendOutgoingCommands will send those operations (as before). +- Added: Support to de/serialize Dictionary. If the types are more specific than object, the serialization writes the type-code only once (lean byte usage in protocol) +- Added: Support to de/serialize null. Enables you to send a null value, e.g. in a Hashtable +- Added: ReceiverGroup enum to select a range of players that get an event via Operation Raise Event +- Added: Event Caching. Any event sent via RaiseEvent can now be buffered on the server side and is "repeated" when a new player is joining a room. This is similar to Properties but lets you categorize your info better and works just like regular events, too. +- Added: EventCaching enum to select if an event is to be cached and how it's cached: either "not at all" (default), replacing anything cached so far (fast) or "merge" (which will add new and replace old keys with new values). Optionally, a event can be raise with option "remove". +- Added: new overload of OpRaiseEvent() with the two new parameters noted above +- Added: Support for custom de/serializer methods. By writing 2 methods to convert a object into a byte-array (and back from that), Photon now supports any custom object type (standard datatypes are still supported out of the box) +- Added: PhotonPeer.RegisterType() to register serializer and deserialize methods for a certain type. Per object, a length and one byte 'type code' are added to the serialized data +- Added: Support for non-strict object[]. Unlike strictly-typed array, here each element will carry its own type. +- Note: If you want to use the new Custom Types or the object[], you have to update your server! Older Servers don't support the new features. As long as you don't use these features, the library is compatible with previous servers. +- Added: ByteCountCurrentDispatch and ByteCountLastOperation properties to PhotonPeer (the ancestor of LiteGame, etc). A game can now access the size of operation-results and events as well as operation-call size. +- Added: Traffic statistic set: PhotonPeer.TrafficStatsGameLevel as "high level" game-related traffic statistic. Counts bytes used by operations, their results and events. This includes overhead for these types of messages, but excludes connection-related overhead +- Added: Traffic statistic set: PhotonPeer.TrafficStatsIncoming and PhotonPeer.TrafficStatsOutgoing as low level statistics of the traffic +- Added: PhotonPeer.TrafficStatsEnabled which enables two sets of traffic statistics. By default, statistics are turned off. +- Added: Classes TrafficStats and TrafficStatsGameLevel for the two statistic cases metioned above +- Changed: NetworkSimulation now starts a Thread when it becomes enabled and the thread ends on simulation disable. Disable the NetworkSimulation to stop the thread, as Disconnect does not change the simulation settings! +- Internal: Cleanup and renaming of several properties +- Internal: Each new peer increases the PeerCount but it is no longer reduced on disconnect (it is existing still, after all) +- Internal: Udp commands will be buffered when serialized. This saves some work when re-sending a reliable command +- Added: TCP Routing code (not in Silverlight). To be used when running Photon on Azure (can be ignored in regular use) +- Added: to StatusCode: TcpRouterResponseOk = 1044, TcpRouterResponseNodeIdUnknown = 1045, TcpRouterResponseEndpointUnknown = 1046 and TcpRouterResponseNodeNotReady = 1047, +- Added: override for PhotonPeer.Connect() with node +- Internal: DotNet now reads the 2 bytes routing response, if a routing request was made (also, not in Silverlight) +- Internal: If TConnect sent a routing request, nothing else will be sent until 2 bytes response are read. +- Internal: If the routing-response does not start with ProxyResponseMarkerByte = 0xF1, a debug message is enqueued and TCP will disconnect +- Internal: Init request for TCP is now always enqueued instead sent directly. This way, it can be delayed if a routing node is selected +- Internal: TPeer EnqueueInit() and SendProxyInit() now create init and routing request respectively +- Internal: TConnect.sendTcp() checks isRunning before it tries to send (the socket might close before the NetSim does). This won't be an issue anytime, still INFO-level callback to DebugReturn is done. +- Removed: debug out for "send package" situation (even on ALL-level, this is more or less spam) +- Internal: updated version numbers of init to 6.4.5 +- Changed: SupportClass HashtableToString() returns "null" if parameter is null +- Internal: Removed SortedCommandList and CommandList classes. Replaced by List and a Sort() where necessary +- Internal: EnetPeer.channels is now a Dictionary instead of a SortedList +- Internal: the channels are initialized with channel 0xff first - this makes 0xff high prio in all foreach usaged +- Internal: NCommand class is now IComparable for usage in Sort() + + +*** Version 6.4.4 +- Added: PhotonPeer.TimestampOfLastSocketReceive now provides the time when something was received. Can be used warn players of bad communication-timing even before the disconnect timeout will be happening +- Fixed: OpGetPropertiesOfActor did use the actorNrList correctly, which always got you all properties of all players + +*** Version 6.4.3 +- Changed: A udp connection timeout in Unity will now end the socket-handling thread correctly +- Changed: The thread for Network simulation is now stopped when the client disconnects and started on connection (instead of keeping it per peer) +- Fixed: Exceptions in network simulation, when Disconnect() was called soon after Connect() but before the connection was established. + +*** Version 6.4.2 +- Fixed: It was possible to send PhotonPeer.FetchServerTimestamp() before being connected properly. Now the method triggers debug output (INFO level) and the callback PeerStatusCallback(StatusCode.SendError) +- Internal: Added a lock in the UDP version of SendOutgoingCommands(). It's still illegal to access a peer from multiple threads but the follow-up issues this lock avoids are very difficult to track. +- Internal: to stay compatible with all exports of Unity, the use of System.Threading.Interlocked.Exchange was replaced by simply replacing the list's reference instead + +*** Version 6.4.1 +- Changed: The Unity library now uses the WWW class for Http based requests. Results are checked within DispatchIncomingCommands(). Important: Unity allows handling WWW requests only on the MainThread, so dispatch must be called from this context! +- Note: Photon does not support Http requests out of the box. Customers get access to a fitting server on demand +- Changed: outgoing list is now replaced on send, instead of calling remove(0) repeatedly (which takes longer). Internal: this uses System.Threading.Interlocked.Exchange to switch to a new outgoing list in one step + +*** Version 6.4.0 +- Fixed: TCP handling of incoming data. This avoids loss of data (operation-results or events) when a lot of data is incoming. +- Changed: PeerStatusCallback() is less often called for queue-length warnings (e.g.: StatusCode.QueueIncomingReliableWarning). Only if a queue has a multiple of PhotonPeer.WarningSize items. +- Changed: WarningSize is now 100 by default +- Changed: Description of PhotonPeer.WarningSize and PhotonPeer.CommandBufferSize, which really is just the initial size of any buffer. The warnings are there to avoid situations where all heap is used up. +- Changed: Naming: StatusCode.Exception_Connect is now Obsolete and replaced with StatusCode.ExceptionOnConnect +- Added: Missing summary for StatusCode.SecurityExceptionOnConnect +- Added: NetworkSimulationSet.ToString override to provide a better overview +- Added: Support for arrays of Hashtables + +*** Version 6.3.1 +- Fixed: Network simulation now delays incoming packages by IncomingLag and IncomingJitter as expected (it was using the outgoing values, too) + +*** Version 6.3.0 +- Added: Network simulation (lag, jitter and drop rate) to debug builds +- Added: class NetworkSimulationSet with properties to control network simulation +- Added: NetworkSimulationSettings.NetworkSimulationSettings property to get current simulation settings +- Changed: only the first peerId of a VerifyConnect is accepted in client (avoids surplus peerID changes) +- Internal: added PeerBase.SendNetworkSimulated() and PeerBase.ReceiveNetworkSimulated() and a Thread to run delay simulation +Siverlight: +- Updated: to Silverlight v4.0 +- Added: Encryption to Silverlight library +- Internal: updated internal BigInteger class for Silverlight +- Internal: DiffieHellmanCryptoProvider in Silverlight, so it uses AesManaged instead of Rijndael (which is not part of Silverlight 3) +- Added: Stopwatch class to DataTypes.cs (for Silverlight only) + +*** Version 6.2.0 +- Added: "Demo LiteLobby Chatroom" to Unity SDK +- Updated: Demo Realtime in Unity client SDK. It's still compatible with the demo on other platforms but cleaned up and much better commented +- Updated: Documentation is now clearer on where the Lite logic is used (it runs on Photon but is not the only application logic) +- Updated: Documentation for the enumerations in IPhotonListener. The Lite application based ones are better described and it's now clear which ones are essential to the Photon client (not only in Lite) +- Updated: Documentation in several other places +- Added: StatusCode.SecurityExceptionOnConnect which is thrown if a security exception keeps a socket from connecting (happens in Unity when it's missing a policy file) +- Added: PhotonEventKey and PhotonOpParameterKey which contain the fixed byte keys that cannot be re-assigned by applications at will (as these keys are used in the clients and server in their respective context) +- Change: PhotonPeer.PeerState is no longer a byte but of type PhotonPeer.PeerStateValue, which makes checking the state simpler. The PeerStateCallback() for state changes is still called as before. +- Changed: Property PhotonPeer.PeerState. It now converts the low level ConnectionStateValue to a PeerStateValue, which now includes a state InitializingApplication. See reference for PeerStateValue. +- Changed: PeerStateValue enum is now part of the ExitGames.Client.Photon namespace, making it more accessible +- Internal: NConnect in DotNet and Unity to catch security exceptions +- Internal: from using var to explicit type usage in DiffieHellmanCryptoProvider.cs (Mono Develop friendly) +- Internal: made const: ENET_PEER_PACKET_LOSS_SCALE, ENET_PEER_DEFAULT_ROUND_TRIP_TIME and ENET_PEER_PACKET_THROTTLE_INTERVAL +- Internal: PeerBase "PeerStateValue peerState" is now: "ConnectionStateValue peerConnectionState" (holding the low level connection state, nothing more) +- Internal: added PeerBase.ApplicationIsInitialized, which stores if the init command was answered by Photon (reset on connect/disconnect) +- Removed: PhotonDemoServerUrlPort and PhotonDemoServerIpPort of PhotonPeer. All demos now use "localhost:5055" and you should run your own server. +- Added: enum ConnectionProtocol to get rid of the "useTcp" parameter in the PhotonPeer constructor (which was less clear than the explicit enum now in use) +- Added: overload of PhotonPeer constructor, which is still compatible with the "useTcp" bool parameter (to avoid a breaking change for the time being) +- Added: PhotonPeer.UsedProtocol property to find out this peer's protcol +- Added: LitePeer.OpLeave() overload without the gameName parameter. That name is not checked in the Lite application (on the server), so it's not really needed + +*** Version 6.1.0 +- Added: Encryption for Unity and DotNet. Operations (and their responses) can be encrypted after exchanging the public keys with the server +- Added: OpExchangeKeysForEncryption(), DeriveSharedKey() and IsEncryptionAvailable to PhotonPeer (and LitePeer inherits these) +- Added: OpCustom() will throw an ArgumentException if the operation should be encrypted but keys are not yet exchanged (exchange keys first) +- Added: LiteOpCode.ExchangeKeysForEncryption = (byte)95 +- Added: Overloaded PhotonPeer.OpCustom() with new "encrypt" parameter +- Added: property PhotonPeer.IsEncryptionAvailable is true if public-keys are exchanged and the secret is compiled from them +- Added: Encryption demo to Realtime Demo. Press E to exchange keys and R to toggle encrypted sending for the move data (even though events are never encrypted) +- Changed: PeerBase methods: sendOperation()->EnqueueOperation(...,encrypt), updateRoundTripTimeAndVariance()->UpdateRoundTripTimeAndVariance() +- Updated: the Unity client is now a Unity v3.1 project. Make sure to change the server address before you build for iPhone (localhost:5055 won't work on the mobile) +- Removed: the outdated, separate iPhone demo (was: Unity v1.7 for iPhone) +- Updated: PhotonPeer documentation for Service(), DispatchIncomingCommands() and SendOutgoingCommands() +- Added: OpRaiseEvent() overload with parameter TargetActors. Sends optional list of actors that will receive the event (if null, all *other* actors will receive the event, as default) +- Internal: Added source BigInteger.cs, DiffieHellmanCryptoProvider.cs and OakleyGroups.cs +- Internal: PeerBase.CryptoProvider, PeerBase.ExchangeKeysForEncryption() and PeerBase.DeriveSharedKey() +- Internal: EnetPeer.initPhotonPeer() and TPeer.initPhotonPeer() are setting PeerBase.isEncryptionAvailable = false +- Internal: De/Serialization methods (and some variables for it) are moved from NConnect to PeerBase and renamed to: SerializeOperationToMessage() and DeserializeMessageAndCallback() +- Internal: switched project to allow "unsafe" functions (used by BigInteger) +- Internal: renamed PhotonPeer.sendOperation()->EnqueueOperation +- Internal: changed assembly version to 6.1.0 and "client version" in init-byte-block to 6,1,0 +- Internal: moved protocol handling to EnetPeer and TPeer classes (where encryption is added) +- Internal: moved InitBlock to (shared) PeerBase (same for UDP/TCP) +- Internal: serialization is now done by Protocol.SerializeOpParameters(), which excludes the message header. this makes encryption simpler + +*** Version 6.0.0 +- Changed: This library requires Photon v2.2.0 and up! (in other words: the libraries are not compatible with older Photon servers, due to servertime changes) +- Added: Support for arrays in arrays. Any serializable datatype can now be used in nested arrays. Even arrays of Hashtables are possible. +- Added: Realtime Demo optional command line arguments for game config. set all or none: serverAddress, useTcp (true/false), useReliable (true/false), int intervalDispatch, intervalSend (ms), intervalMove (ms) +- Note: Realtime Demo commandline might look like this: start demo-realtime.exe localhost:5055 false true 5 25 100 +- Changed: renamed GetLocalMsTimestamp property to LocalMsTimestampDelegate (it does not have a getter, despite the old name's implication) +- Added: PhotonPeer.LocalTimeInMilliSeconds property to use the timestamp delegate to get the current client milliseconds (by default this is Environment.TickCount) +- Changed: UDP: The default value for PhotonPeer.RoundTripTime (300ms, used before connecting) is now replaced with the turnaround time of connect. This should lead to accurate RTT values much sooner +- Changed: PhotonPeer.ServerTimeInMilliSeconds is no longer updated all the time. Instead it's fetched soon after connect (when initialization won't affect rountrips anymore) and extrapolated. It should be better to be off by a constant value than by a changing value +- Changed: PhotonPeer.ServerTimeInMilliSeconds now returns 0 until the server's timestamp is fetched. Updated the documentation with some internals for this. +- Added: PhotonPeer.FetchServerTimestamp() to send the time fetch command (this is done automatically as well. this method is here for completeness) +- Fixed: roundtrip time calculation is no longer affected by long intervals between Service() or DispatchIncomingCommands() calls (bug of v5.9.0, caused by internal action queues) +- Added: internally for UDP, we use a new command to fetch the timestamp which minimizes the latency for that roundtrip. this one is excluded in roundtrip time measuring +- Changed: internal: ACKs by the server are again directly executed (other commands which are put into the action queue and dispatched) +- Fixed: Peers with TCP as protocol will no longer try to disconnect while not being connected (does not do anything of disconnected or disconnecting) +- Changed: Peers with TCP as protocol will clear the outgoing queue when disconnect() is called (while connected. see fix above) +- Updated: Silverlight Realtime Demo slightly +- Added: PhotonPeer.Listener property to give subclasses access to the IPhotonPeerListener (set in constructor). Can be useful to call Listener.DebugReturn() +- Added: LitePeer-Source.cs to demo-realtime. This is the source of a LitePeer and could be used as sample to create custom operations on the client side + +*** Version 5.9.0 +- Release: of changes in 5.7.6 and 5.7.5 + +*** Version 5.7.6 +- Fixed: a debug output line for TCP connections which did not heed the debug-level. +- Changed: PhotonPeer uses less locking internally and will handle incoming data in the game thread (inside DispatchIncomingCommands() or Service()). +- Changed: Internally, all commands are put into a (locked) queue which is processed within DispatchIncomingCommands(). Your dispatch interval affects local lag but not the PhotonPeer.RoundTripTime value. +- Note: Don't use a peer from multiple threads! It's not thread safe. All callbacks to IPhotonPeerListener methods are happening in your game thread (again: inside DispatchIncomingCommands()). +- Changed: removed locks inside the callbacks (according to above change). +- Changed: DNS resolution is now done in Connect() unless you provide a valid IP address (if IPAddress.Parse(address) is successful, the IP is used directly). +- Fixed: PhotonPeer.Connect() should fail if the IP is unknown or unavailable. Exception: using a localhost might succeed but fail when we try to receive anything. +- Updated: Game.cs now initialized the timing intervals. This avoids issues if the client system is having a negative TickCount. +- Added: ServerAddress property to PhotonPeer, which might help while developing with several servers and peers. +- Changed: This version includes GetLocalMsTimestampDelegate and the PhotonPeer property GetLocalMsTimestamp to set the delegate for local timestamp. + +*** Version 5.7.5 +- Changed: All precompiled demos now connect to localhost! From now on, you need to run Photon before trying any of the demos (as we don't guarantee that udp.exitgames.com is online anyways) +- Changed: OpCustom() now accepts null as parameter Hashtable, which is a shortcut to "no parameters" for simple operations (an empty hashtable is sent though, it does not reduce bandwidth) +- Added: new feature: UDP timeout definition by setting PhotonPeer.DisconnectTimeout (individual per command, set in milliseconds, checked when a command is repeated) +- Renamed: enum ReturnCode to StatusCode. The StatusCode values are only used for status callbacks (not as operation results) +- Changed: parameter type of PeerStatusCallback() from int to StatusCode (to differentiate them from operation ReturnCodes, which are customizable) +- Removed: StatusCode.Ok (as it was actually an Operation ReturnCode) +- Added: new StatusCallback value: StatusCode.SendError. Used for sending error cases: "not connected" and "channel not available" +- Changed: sendOperation() (Udp and Tcp) does not throw an exception while disconnected or for wrong channel (using StatusCode.SendError instead) +- Changed: callback DebugReturn() now has the additional parameter (DebugLevel)level, analog to logging +- Changed: UDP connection is disconnected when a read exception happens (before we tried to read despite this until a timeout ended it) +- Changed: EnetPeer.Disconnect() now ignores calls when peer is disconnected or disconnecting already +- Fixed: TCP code tried to detect socket issues by checking for IOExceptions but now checks SocketException instead +- Changed: internal threading: Callbacks due to incoming packages and commands are now queued and triggered by dispatch (in game loop) +- Changed: dispatch of action-queue as added to DispatchIncomingCommands (in EnetPeer and TPeer) +- Changed: internally, there is no locking for outgoing reliable and unreliable command lists anymore +- Changed: Realtime Demo timer usage to avoid nullref on form-close +- Changed: Realtime Demo propety isReliable is now in the Player class +- Changed: Game.cs and Player.cs for all realtime demos. There is now something like a gameloop (Update()) which must be called regularly and makes (pretty) sure just one thread accesses the peer +- Changed: all realtime demos to use the new Update() method and use more similar Game and Player classes (cleanup for less differences) +- Fixed: RoundtripTimeVariance is now also reset on connect / init, so the resend-timing of reliable udp does not suffer when a peer connects after a disconnect +- Fixed: typo in ExitGames.Client.Photon.StatusCode.QueueIncomingUnreliableWarning (was QueueIncomingUneliableWarning) + +*** Version 5.7.4 RC3 +- Changed: Unity3D lib again has it's own UDP handling (the DotNet one causes browser crashes on web-player exit) + +*** Version 5.7.3 RC3 +- Changed: Unity3D lib is now identical to DotNet lib (Unity iPhone is compatible with DotNet 2.0 now and this got tested) +- Fixed: DNS resolution (did not work for "localhost", which gave two results (IPv4 and IPv6), mixing up things + +*** Version 5.7.2 RC3 +- Changed: Unity3D lib: the receive thread will now receive until no data is available, then sleep 5ms and check again +- Changed: serverTime is now a signed int (as on server) and adds averaged rountripTime/2 when it gets an update +- Changed: ServerTimeInMilliSeconds doc (more concrete, explains how server time works) +- Added: support for serverTime, RountripTime and RoundtripTimeVariance when using TCP (Silverlight does not allow UDP) +- Added: Silverlight supports either URL:Port and IP:Port as server url string + +*** Version 5.7.1 RC2 +- Added: DotNet "Lobby Demo" which uses the "LiteLobby" application of the server SDK to show running games and their player-count +- Changed: the realtime demos to use the more similar Game and Player classes + +*** Version 5.7.0 RC1 +- Added: documentation: project for Silverlight Hashtable and ArrayList substitutes. +- Changed: RealtimeDemo uses same classes Game and Player for Unity3 + Silverlight +- Changed: Silverlight: Hashtable and ArrayList are now a separate project / lib +- Internal: Silverlight: listener interfaces (Photon and Neutron) now conditionally use ExitGames.Client datatypes from lib +- Changed: Photon: connect callback is now deferred to on-init-response (instead of enet-connect) which ensures "no ops before init" +- Changed: Unity Realtime demo: using game and player classes merged over from silverlight and re-wrote sample code to display players +- Internal: photon projects now have a pre-compile setting "Photon" +- Changed: SupportClass Namespace is now compiling into either ExitGames.Client .Photon or .Neutron (to avoid ambiguation) +- Added: LitePeer as Lite Application specific peer (with OpJoin and the rest) +- Changed: demos accordingly +- Changed: case of PhotonPeer methods to first-letter-is-uppercase (as usual in C#) +- Removed: nNet-prefix (Connect and Disconnect are self-explanatory) +- Renamed: PropertyTypes are now LitePropertyTypes (as they belong to the Lite application) +- Changed: Peer state constants with PS_* converted into enum "PeerStateValue" +- Removed: URL_RT_SERVER, URL_RT_SERVER_DEV, IP_RT_SERVER and IP_RT_SERVER_DEV +- Added: PhotonDemoServerUrlPort and PhotonDemoServerIpPort +- Renamed: NPeer to PhotonPeer +- Renamed: PhotonPeerListener to IPhotonListener (class and file) +- Changed: namespace from Com.ExitGames to ExitGames and ExitGames.Client, ExitGames.Client.Photon and ExitGames.Client.Neutron +- Removed: QueueOutgoingUnreliableError, QueueOutgoingAcksError, QueueIncomingReliableError, QueueIncomingUneliableError, QueueSentError (no errors, only warnings) +- Removed: error "report" when TCP incoming queue getts fuller +- Internal: updates Neutron part to run with Protocol.cs de/serialization (added a serializeParametersNeutron() as there are multiple differences to UDP part) +- Changed: projects and scripts to build documentation xml in debug builds +- Renamed: demo-photon-SL to demo-realtime-SL (according to other demo realtime implementations) +- Changed: many classes and properties are now internal. e.g. Protocol, EnetChannel, EnetPeer (and inner classes), TPeer, SuppportClass.ReadInput() +- Updated: AssemblyInfo.cs for photon dotnet and silverlight +- Internal: projects to have precompile-flags also in release builds +- Updated: build scripts for SDK building +- Removed: Compact Framework support + +*** Version 5.6.1 +- Fixed: 0 element arrays caused bugs +- Fixed: double type was cast incorrectly after being read + +*** Version 5.6.0 +- Added: more supported datatypes: float, double and arrays of all basic datatypes (no arrays of hashtable or arrays) +- Internal: changed Photon protocol internally to 1.5. (needs a server update to Photon Server SDK 1.6.1+)! +- Changed: Channels for Photon UDP are now priorized (from low to high) getting the lower channels out first +- Internal: switched de/serialization at several places from manual shifting to a support function, which should provide endian-correctness (Photon Unity PPC compatibility) +- Added: Unity info about "Application.runInBackground = true;" to Unity Appendix in doc +- Changed: Photon return values are put into a NEW hashtable on receive. not just a cleared one which was not reference-safe (no more need to deep-copy the data of events) +- Added: Photon support for "disconnect-reason" which is sent by server in the enet "reserved" byte +- Added: Photon ReturnCode.DisconnectByServerUserLimit and .DisconnectByServerLogic +- Removed: NPeer.IncomingReliableCommands (was more or less useless) +- Added: QueuedIncomingCommands and QueuedOutgoingCommands as metric for how effective send and dispatch is done +- Changed: now throwing exceptions when trying to set init-values at runtime (to be fixed at development-time) +- Added: doc for sequencing and updated channel doc, (too) short chapter on custom operations, topic "opCodes: byte versus short", doc for property-related functions +- Added: overloaded functions for opGetProperties*() for byte-keys +- Fixed: Realtime Demo keypress in input-fields have been used as in-game actions, too +- Changed: Realtime Demo game-name is now that of the native samples ("play" with other platform SDKs) +- Changed: Silverlight SDK has a different port in the constants NPeer.URL_RT_SERVER* and .IP_RT_SERVER* (as Silverlight uses TCP port 4350) + +*** Version 5.4.1 +- Added: missing documentation in Unity3d SDK + +*** Version 5.4.0 +- Change: The timespan until a sent and unacknowledged reliable command is considered lost, is now calculated by + current roundTripTime + 4 * roundTripTimeVariance + The result of this calculation is doubled with every following resend. The maximum number of retries can still be defined by calling SetSentCountAllowance. +- Change: Removed TimeAllowanceInt +- Change: removed surplus debug out, adjusted levels for other, output of command sent-time from hex to decimal +- Added: fragmentation support: bigger data is now placed into multiple packages and reassembled +- Internal: command-buffers are replaced with CommandList and SortedCommandList (major change, but fully internal) +- Fixed: possibility of command buffer overflow. now everything is stored and warnings are used as hint for temporary problems +- Added: property NPeer.IncomingReliableCommands, which returns the count of reliable commands currently queued +- Added: callback on NCommand.CT_DISCONNECT to inform the NPeerListener about a disconnect from server (see above) +- Added: disconnect command will be sent by server in case of timeout, connection-limitations or other issues +- Added: NPeer ReturnCode.DisconnectByServer is called on server-side disconnect (see description) +- Added: call to StopConnection() on disconnect (by server) +- Added: NPeer.PeerID property to get ENet's peerID (useful while debugging) +- Internal: SupportClass.WriteIntToByteArray() to ease writing ints to byte[] +- Internal: added several values to NCommand to store fragments +- Added: support for channels. read more about this in the documentation +- Added: NPeer.ChannelCount which sets the number of channels while not connected (default: 2) +- Changed: opRaiseEvent() and opCustom() now optionally have a channel parameter +- Added: Photon properties functions to NPeer (available with Photon Server SDK v1.5.0) and doc +- Added: LiteEventKey.SetProperties = 92 for broadcasted property set +- Added: LiteOpKey.Broadcast = 13 and .Properties = 12 +- Added: LiteEventKey.TargetActorNr = 10 (actorNr the properties are attached to) and .Properties = 12 (changed properties) + + +*** Version 5.3.11 +- Change: all bytes sent to and from server are treated as unsigned bytes (standard for c#). same for byte-arrays +- Change: updated realtime demo to use int for posx,posy but still sending just a byte-value (the field is 16x16, after all) + +*** Version 5.3.10 +- Change: switched from sbyte-array to byte-array in de/serialization! important: bytes (ev-keys etc) are sbyte. arrays of bytes are unsigned (on client and server) +- Change: NeutronListener functions getShadowReturn() and HasbadwordsReturn() now have byte-array return values. please adjust, even if you don't use those +- Internal: changed SupportClass for Compact Framework +- Internal: getting ticks sitched from expensive "System.DateTime.Now.Ticks / 10000" to cheap "Environment.TickCount" +- Change: Unity lib will now give more debug out if serialisation fails + +*** Version 5.3.9 +- Fixed: result-queue, timeouts and customOps work also fine for Unity build again (were broken due to Neutron Unity webplayer compatibility changes in 5.3.8 for Unity) +- Fixed: if the browser is closed and the unity webplayer immediatly can't use http anymore, Neutron now informs the application via NetworkStatusReturn() + +*** Version 5.3.8 +- Fixed: Neutron Unity now also works fine in webplayer -> Neutron and Photon now both support all platforms of Unity und Unity iPhone +- Fixed: default value for parameter encrypt of NeutronGame::RaiseEvent() now is false like for all other RaiseEvent methods and like on all other platforms, instead of true, as it was before + +*** Version 5.3.7 +- Fixed: .Net UDP issue, where standard MTU settings caused dropped UDP packages +- Internal: refactored ACK queue to arraylist + +*** Version 5.3.6 +- Fixed: NPeer issue with ACKs for repeated commands. this enhances handling of lost packages +- Changed: NPeer.opJoin() no longer needs the SID + +*** Version 5.3.5 +- Known issues: to use Photon on iPhone device, you do need Unity iPhone 1.0.2b1 or higher (current official release is 1.0.1, so please ask for a prerelease or wait until next official release), but of course you can use Photon with Unity iPhone 1.0.1 IDE +- Merged: renamed .NET 1.1 NeutronUnity3DiPhone into NeutronUnity3D to replace the old .NET 2.0 lib of that name, which means, that you can use the same .NET 1.1 based lib for Unity and for Unity iPhone now, since 1.1 cpmpatibility fixes are all done now +- Fixed: photon is fully compatible to .NET 1.1 now +- Internal: optimized UDP package size in Unity3D library (was sending surplus bytes, which were ignored) +- Fixed: NPeer.opCustom() now sends the operation given by parameter +- Changed: IP_RT_SERVER points to new server IP of udp.exitgames.com +- Changed: a new NeutronSession now clears the NetworkLoss state and the sendQueue +- Changed: timeout of a HTTP request to 10 seconds. it triggers + +*** Version 5.3.4 +- Added: prealpha Unity3DiPhone version of Neutron .NET: core lib already functional, but realtime part not usable on device yet +- Internal: there are 4 different versions of Neutron.NET now: + - Full .NET: .NET 2.0 based, with asnyc realtime part + - Compact Framework: .NET 2.0 based, with threaded realtime part + - Unity3D: .NET 2.0 based, with Unity www-class based http part and threaded realtime part + - Unity3DiPhone: .NET 1.1 based, with Unity www-class based http part and threaded realtime part + +*** Version 5.3.3 +- New: ReturnCode.RC_RT_EXCEPTION_CONNECT, which covers the cases where a server is not running +- New: NPeer can now be created with UDP or TCP (by new bool parameter) +- Change: renamed most of the constants for NPeer (in INPeerListener structs) +- Note: TCP does not offer ServerTime or RoundTripTime jet + +*** Version 5.3.2 +- Internal: reverted to threaded model in NConnect (as async UDP is not supported by Unity3D) + +*** Version 5.3.1 +- New: login(), register(), customOperation() and raiseEvent() (all variants) can be encrypted with additional parameter "encrypt" (overloaded function) +- New: encryption uses HTTPs as transfer, by changing the "http:" url to a "https:" url +- New: returnCode for failure of encrypted HTTPs requests: RC_SSL_AUTHENTICATION_FAILED (if certificate is not found, valid or expired) +- Fixed: Realtime Demo using the older Realtime Server + +*** Version 5.3.0 +- New: separated libraries into "Compact Framework" (CF) and "Regular Framework" (no name postfix) +- Change: libraries are now in "libs" folder as debug/release and in libs/CompactFramework debug/release +- Change: libs default URL set to EU/Test. use setServerURL() with Neutron.URL_NEUTRON_* for other Neutron instances +- Internal: lib now uses async UDP communication now with "regular" framework +- Added: properties serverTimeInMilliSeconds, serverTimeAsTimeSpan and serverTimeAsDateTime for getting the current server time +- Removed: serverTimeOffset is now internal only and removed from the API (was only needed to calculate the servertime by yourself, before neutron could do this for you) +- Change: debug out for realtime classes is now layered +- Change: debug level NPeer.DebugOut is now a NPeer.DebugLevel enum and will include all lower levels in output, default: DebugLevel.ERROR +- Fixed: size of realtime demo board +- Change: NPeer constructor now always throws an exception if listener is null +- Change: EventAction() parameter eventCode is now of type sbyte (was int), which corresponds to type of RaiseEvent (and server-side used type) +- Internal: NPeer.opRaiseEvent() now treats eventCode as parameter of operation RaiseEvent (as changed in latest RT server) +- Change: NPeer has its own listener (INPeerListener) and several (better named) structs for the constants used with NPeer / realtime +- Added: LiteOpKey and LiteOpKey.ActorNumber to have a constant for the only OP key of interest +- Change: EventAction() always returns the complete event, which contains a code, the ActorNumber (if any given) and data from raiseEvent (see below) +- Change: in custom events, the data from opRaiseEvent() is in placed as value of key: LiteEventKey.EV_RT_KEY_DATA. to get the data use: Hashtable data = (Hashtable)neutronEvent[LiteEventKey.EV_RT_KEY_DATA]; + +*** Version 5.2.0 +- changed library filename to neutron-lib__.dll with server "test" and "run" (no debug out) and billing "dummy" and "none" +- removed US build of library. please use NeutronSession.SetServerUrl() and the constants: Neutron.URL_NEUTRON_SERVER_*. + +*** Version 5.1.0 +- added realtime classes to DotNet library: ported NPeer (and internal: NCommand and NConnect) classes +- added nPeerReturn() to NeutronListener interface +- added constants for realtime returnCodes (RC_RT_*): RC_RT_CONNECT, RC_RT_DISCONNECT and RC_RT_EXCEPTION +- added constants for realtime eventCodes (EV_RT_*) +- added constants for Neutron servers to Neutron class: URL_NEUTRON_* +- added Reamtime Demo +- updated samples +- added test for UDP to NUnit + +*** Version 5.0.1 +- New: operation Spectate (including new SpectateReturn) to get events from any game (as admin) +- New: SetServerUrl and SetCustomServerUrl now return the URL to debugReturn +- Internal: constant "DEBUG_- InternalS" to be used for intern debugging output + +*** Version 5.0.0 +- New: hasBadwords() as OP and return. Server side check of strings for badwords + +*** Version 5.0.0 RC3 +- Internal: changed constant values: EV_KEY_PROPERTIES = "Data", EV_KEY_REVISION = "Rev" +- New: EV_KEY_CHANNELTYPE for channel-type in property-change events +- New: constants for default channels, CHANNEL_APPLICATION_LONGLIFE, CHANNEL_ACTOR_SHORTLIFE, CHANNEL_ACTOR_LONGLIFE and CHANNEL_APPINSTANCE +- Change: operations that fail due to missing moderation-rights now return RC_MODERATION_DENIED instead of RC_COMMAND_ACCESS_DENIED +- Change: actor-properties can no longer be broadcasted in any way - removed "broadcast" parameter from setActorProperties() +- Change: properties now have a revision which is increased on each change. this way outdated updates might be skipped +- Change: parameters of GetPropertiesReturn(). property-type is replaced by channel. added revision +- Change: EV_PROPERTIES_CHANGE now has a key EV_KEY_OWNERNR if it's a "player property" (the key is missing if it's a game-property) +- Internal: changed setProperties and getProperties to new operation-codes using different parameters (with similar results) +- New: parameter "textMessage" for NeutronGame.invite() adds personal message to invited players (in EV_INV and gameListInvitations()) +- New: key EV_KEY_INFO will be added to EV_INV if "textMessage" was used in NeutronGame.invite() (it's not there otherwise) +- New: gameListInvitations() has new value parameter {t} to get "textMessage" from NeutronGame.invite() +- New: RC_APPINSTANCE_NOT_OPEN is now used for "singleton namebased pools" where a game is full (not able to join / instanciate) +- New: gameCreate() with invitations will fail if the chosen game-name is already taken in a "singleton namebased pool" +- New: RC_APPINSTANCE_ALREADY_EXISTS for the case above + +*** Version 5.0.0 RC2 +- Change: gameCreateReturn() now returns RC_APPINSTANCE_NOT_OPEN (instead of RC_AI_TOO_MANY_ACTORSESSIONS) for full games in "singleton" pools +- Change: obsolete events EV_TURN, EV_TXTMSG and EV_DATA which could be sent by raiseEvent*() and still handled +- Change: switched Neutron URLs to "[..].neutron5.[..]" for test/run libs +- Fix: Polling (getEvents operation) again calls sendGameDataReturn() for all errors (as intended for v4.9.2 already) +- New: constant NeutronListener.EV_KEY_TYPE as part of event EV_BUDDNOTICE + +*** Version 5.0.0 RC1 +- New: RaiseEvent (all functions of this name) now has a "filter" parameter. If filter is true, all String-typed values in an event are badword filtered +- Change: signature of NeutronGame.raiseEvent(), NeutronGame.raiseEventInChannel(), NeutronSession.raiseEventInChannel(), NeutronSession.raiseEventForActor() start with: byte eventCode, Hashtable event, boolean filter +- Change: signature of NeutronSession.raiseEventForActor() is changed to "byte eventCode, Hashtable eventData, boolean filter, String userID, int minutesValid, byte maxTypeCount, byte channel" +- Change: NeutronGame.doModerate() is now isModerator() +- Change: moved GpOperation.SerializeData() and GpOperation.DeserializeData() to Neutron.SerializeData() and Neutron.DeserializeData(). +- New: errorCode RC_INVALID_TARGET and RC_PARAMETER_NOT_SUPPLIED added as constant. + +*** Version 4.9.3 +- New: Errors constants in NeutronListener: RC_FATAL_LOGIC, RC_MATCHMAKING_NOT_COMPLETED, RC_CHANNEL_ACCESS_VIOLATION +- New: for game-creation you can now reserve "spots", which are not filled up by Neutron matchmaking. players can be invited to fill the spots, or they can be deblocked later on +- New: Parameter reservedSpots in NeutronSession.gameCreate() +- New: NeutronGame.setReservedSpots() to modify the number of reserved slots (to make them available to matchmaking again, or block/reserve them) +- New: event EV_RESERVED_SPOTS will update the NeutronGame.reservedSpots value after a call to NeutronGame.setReservedSpots() +- New: NeutronSession.listBannedPlayers() gives you the list of banned players for a known game - only usable by "admin" users +- New: NeutronSession.unbanPlayer() is a modified "kick" operation which allows the respective user to join a certain game again - only usable by "admin" users +- New: the event invitation includes now the game's name (in the new key EV_KEY_NAME) +- New: NeutronSession.gameListPerPool() has now three options to sort the results: by game-name, player-count or "persistent games first" +- Removed: NeutronGame: handoverTurn(), sendData(), sendTextMsg(), getEventHistory() and getEventHistoryReturn(). Obsolete events: EV_TURN, EV_TXTMSG, EV_DATA. Session: getScorePosition()+getScorePositionReturn() +- Update: release_history.txt was updated from v4.0. All changes up to v4.0.4 are added to v4.9.3 + +*** Version 4.9.2 +- New: Players can be admins (by list of logins on server) or moderator (by being the first active player of a game) +- New: Players may request and become moderator for game: NeutronSession.gameCanModerate(boolean), NeutronSession.canModerate, NeutronGame.doModerate() and NeutronGame.moderatorActorNr +- Change: the new value NeutronSession.canModerate will be sent with gameCreate() operations (if set to true) +- New: Event key NeutronListener.EV_KEY_MODERATOR to get moderator's actorNr from events +- Change: EV_QUIT and EV_KICKED now carry the new key EV_KEY_MODERATOR which tells all players who is the current moderator (by actorNr); this is stored into NeutronGame.moderatorActorNr +- New: Players in NeutronGame can have new state PLAYER_KICKED (player-data is updated with EV_KICKED) +- New: NeutronGame.kickPlayer() (for moderators) and NeutronSession.kickPlayer() (for admin's who are not active in the game to shutdown) +- New: NeutronSession.shutdownGame() can be used by admin-players (for others, this operation will fail) +- New: Namebased pools can now be defined as "singleton": only one instance per pool and name will be created; if such a game is full players get an error instead of a new game +- New: Errors constants in NeutronListener: RC_ACTORSESSION_KICKED, RC_ACTORSESSION_BANNED, RC_APPINSTANCE_CLOSED, RC_ACTORSESSION_ALREADY_JOINED +- Change: NeutronGame.raiseEvent() accepts a "targetActorNr" which defines a single player to get the raised event; leave 0 to target "all players in game" (as before) +- New: NeutronGame.quitLocally() to release a NeutronGame instance locally (without having to quit()); used after a player was kicked or game shutdown +- Update: NeutronGame.playerGetCount() is updated to simply count all active or inactive players (excluding quit and kicked ones) +- Internal: NeutronGame constructor reads new parameter: P_MODERATOR +- Change: Polling (getEvents operation) now calls sendGameDataReturn() for all errors (not just RC_ACTORSESSION_EXPIRED and RC_ACTORSESSION_NOT_FOUND); takes care of kicked/banned errors +- Fix: Fatal server errors cause a returnCode of NeutronListener.RC_OP_SERVER again; debug test-server libs print out debug text! (during development fatal errors could happen in case of not matching client/server setups) +- Change: removed (already deprecated) NeutronListener.gameListPerPoolReturn() +- Change / Internal: canModerate is sent as Byte (not bool) as in definition; Code: if ( canModerate ) op.addParameter(Neutron.P_MODERATOR , new Byte((byte)1)); +- Add: NeutronGame.PLAYER_KICKED is now listed in JavaDoc for NeutronGame.playerGetStatus() +- Update: JavaDoc package.html, gameCreateReturn(), gamesListReturn(), EV_DEACTIVATE, kickPlayer(), quitLocally(), RC_ACTORSESSION_KICKED, RC_ACTORSESSION_BANNED, RC_APPINSTANCE_CLOSED, RC_ACTORSESSION_ALREADY_JOINED +- Added: Event EV_STATUS (50) includes a key EV_KEY_ISADMIN if the current player has administrator rights; the value is (byte)1 in that case. The key does not exist in any other case (normal users) +- Update: JavaDoc gameCreateReturn; +- New: Added constant RC_APPINSTANCE_NOT_FOUND = 137 for shutdownGameReturn() +- Fix: serializable datatypes are now completely listed in NeutronSession JavaDoc +- New: Constant for property-change events: EV_PROPERTIES_CHANGE including new keys: EV_KEY_PROPERTY_TYPE, EV_KEY_PROPERTIES, EV_KEY_ISDIFF +- Update: JavaDoc for properties in NeutronSession + +*** Version 4.1.1 +- Fix: gameListPerPool() defaults to 10 games and no offset if the values are less than 1 +- Fix: gamesListReturn() JavaDoc description for "listType" is now: 0 = open games; 1 = invitations; 2 = pool's open games list +- Update: gameListPerPool() sends "{gn}" as values-parameter if it's null +- Update: getPropertiesReturn() gets new parameters: actorNr, userID. These are optional and are available in certain situations only. See JavaDoc +- Update: gameListPerPoolReturn() is now deprecated and merged into gamesListReturn() which in turn got a "type" to identify the list-type +- New: getListBuddyIgnore() got one more value: 't'. This requests the type of relation to users. useful when getting lists of type "both". this is buddies and ignores. +- Change: renamed returned parameters to: count and countOnline. These values are referring to the number in the returned list +- Internal: parameter P_USERID = 85; used in getProperties +- New: made methods nullpointer resistant: getListBuddyIgnore, buddySet, get/set PlayerProperties, get/set ActorProperties, get/set GameProperties; some methods throw exceptions in debug version + +*** Version 4.1.0 +- New: Properties. NeutronSession: setActorProperties(), getActorProperties(). NeutronGame: setLocalPlayerProperties(), getPlayerProperties(), getGameProperties(), setGameProperties() +- New: Buddylist and Ignorelist in NeutronSession: listBuddies(), listIgnored(), getListBuddyIgnore(), buddySet() +- New: Listing of games per pool in NeutronSession: NeutronSession gameListPerPool() +- New: Games with password (only usable for named games) +- Internal: Changed parameter in buddySet from P_STATUS to P_TYPE + +*** Version 4.0.4 +- Change: NeutronGame.handoverTurn() and NeutronGame.sendData() are now getting a Hashtable parameter instead of Object +- New: RC_ACTORSESSION_BUSY (121) constant to help identify common development error! check in gameCreateReturn() + +*** Version 4.0.3 +- New: RC_INVALID_CONNECTIONSTRING (74) constant to help identify a common error! check in loginReturn() +- Update: list of serializable datatypes in NeutronSession JavaDoc +- Fix: Fatal server errors cause a returnCode of NeutronListener.RC_OP_SERVER again; debug test-server libs print out debug text! (during development fatal errors could happen in case of not matching client/server setups) + +*** Version 4.0.2 +- Internal: Neutron.deserializeData() now returns either the P_DATA part of the deserialized data (if available / serialized by serializeData()) or the resulting hashtable itself + +*** Version 4.0.1 +- New: NConnectSE connects to server defined by parameter: ipPort (before: fixed host) +- New: SE version is now completely independent from Java ME classes (were not used, but had to be present) +- Fix: Changed versioning for "ClientLibVersion" in Login/CC +*** Version 4.0.0.0 + +- Removed methods: + - NeutronSession.BuggyGetList - replaced by new GetListBuddyIgnore method; + - NeutronSession.ReSubscribe; + - NeutrinSession.ConfirmBilling; + - NeutronListener.ResubscribeReturn; + +- Added methods: + - NeutronSession.GameCreateNamed with password parameter; + - NeutronSession.GameListPerPool; + - NeutronSession.GetActorProperties; + - NeutronSession.SetActorProperties; + - NeutronSession.GetListBuddyIgnore - replaces removed BuggyGetList; + - NeutronSession.ListBuddies; + - NeutronSession.ListIgnore; + - NeutronSession.BillingInitPayment; + - NeutronSession.BillingProcessPayment; + - NeutronGame.Invite; + - NeutronGame.GetGameProperties; + - NeutronGame.SetGameProperties; + - NeutronGame.GetPlayerProperties; + - NeutronGame.SetLocatPlayerProperties; + - NeutronListener.GameInviteReturn; + - NeutronListener.GetPropertiesReturn; + - NeutronListener.SetPropertiesReturn; + +- Changed argument list: + - NeutronSession.GameCreate - added password parameter; + - NeutronListener.GamesListReturn added listType parameter; + - NeutronListener.BuddyGetListReturn all buddy related info now in passing in one strings array parrameter; + - NeutronListener.BuddySetReturn added type parameter; + - NeutronListener.BillingInitPaymentReturn; + + +- added constants: + - OPC_INVITE + - OPC_TELLAFRIEND + - OPC_LISTGAMES + - OPC_SETPROPERTIES + - OPC_GETPROPERTIES + - P_USERID + - P_RESERVE + - P_RESULT + - P_PROPERTIES + - P_BROADCAST + - P_ISDIFF + - RCB_CHARGING_ERROR + - RCB_POST_CHARGING_ERROR + - RCB_TIMEOUT + - RCB_PRICE_- Changed + - RCB_PRICE_INVALID + - RCB_FATAL_SERVER_ERROR + - RCB_FATAL_LOGIC_ERROR + - RCB_NOT_INCLUDED + - RCB_WMA_UNAVAILABLE + +*** Version 3.0.2.2 +- CLS-specifications largely corrected + +*** Version 3.0.1.1 +- changes in neutron-java-lib integrated + +*** +- Removed: NeutronGame: playerNames, playerIDs, playerLobbies, playerStats +- Change: removed GpOperation.roundtripTime, now using public Neutron.roundtripTime + to be sent in operation headers (GpOperation.serializeParameters(), internal) +- Change: channelRaiseEvent() is now raiseEventInChannel() and gets the eventCode + as seperate parameter value - analog to raiseEventForActor() +- Fix: renamed EV_KEY_M_MIPLAYERS to EV_KEY_M_MINPLAYERS (number of min players of game, before start) +- Fix: values for EV_KEY_M_MINPLAYERS and EV_KEY_M_MAXPLAYERS corrected (wrong case so far) +- Changed: Neutron.millisecondsToWait (current value of polling-interval) is now + set in Neutron.receiveResponse() for login, register and alike diff --git a/Close Enough!/Assets/Plugins/release_history.txt.meta b/Close Enough!/Assets/Plugins/release_history.txt.meta new file mode 100644 index 0000000..a06c625 --- /dev/null +++ b/Close Enough!/Assets/Plugins/release_history.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c29089d5f5388bf479c9c8c96ba6df54 +labels: +- ExitGames +- PUN +- Photon +- Networking diff --git a/Close Enough!/Assets/Prefabs.meta b/Close Enough!/Assets/Prefabs.meta new file mode 100644 index 0000000..71f814a --- /dev/null +++ b/Close Enough!/Assets/Prefabs.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 4ac144c09baba405f9b83d822ae19c43 +folderAsset: yes +timeCreated: 1525373953 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Prefabs/PlayerListing.prefab b/Close Enough!/Assets/Prefabs/PlayerListing.prefab new file mode 100644 index 0000000..03e3909 --- /dev/null +++ b/Close Enough!/Assets/Prefabs/PlayerListing.prefab @@ -0,0 +1,161 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 1116522181043838} + m_IsPrefabParent: 1 +--- !u!1 &1116522181043838 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 224566906713973478} + - component: {fileID: 222330507274483390} + - component: {fileID: 114805922259569090} + - component: {fileID: 114543554064006952} + m_Layer: 5 + m_Name: PlayerListing + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1543345152933284 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 224327524010404432} + - component: {fileID: 222624374170241598} + - component: {fileID: 114850199928320086} + m_Layer: 5 + m_Name: PlayerNameText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &114543554064006952 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1116522181043838} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 907d3294e2ffd4b2ea27387abdd0c826, type: 3} + m_Name: + m_EditorClassIdentifier: + _playerName: {fileID: 114850199928320086} +--- !u!114 &114805922259569090 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1116522181043838} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &114850199928320086 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1543345152933284} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.051470578, g: 0.051092118, b: 0.051092118, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 12800000, guid: 9ee58c86788afb1468f4ec78d2dd52ff, type: 3} + m_FontSize: 25 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 64 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 0 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Default Text +--- !u!222 &222330507274483390 +CanvasRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1116522181043838} +--- !u!222 &222624374170241598 +CanvasRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1543345152933284} +--- !u!224 &224327524010404432 +RectTransform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1543345152933284} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 224566906713973478} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0.000007629397, y: -0.00000095367} + m_SizeDelta: {x: 270, y: 40} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!224 &224566906713973478 +RectTransform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1116522181043838} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.78125, y: 0.78125, z: 0.78125} + m_Children: + - {fileID: 224327524010404432} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 347.075, y: -213.78998} + m_SizeDelta: {x: 270, y: 40} + m_Pivot: {x: 0.5, y: 0.5} diff --git a/Close Enough!/Assets/Prefabs/PlayerListing.prefab.meta b/Close Enough!/Assets/Prefabs/PlayerListing.prefab.meta new file mode 100644 index 0000000..0e66caf --- /dev/null +++ b/Close Enough!/Assets/Prefabs/PlayerListing.prefab.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 53c9be48b0bc1477691b754ac80d7d60 +timeCreated: 1525374104 +licenseType: Free +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 100100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Resources/Sounds.meta b/Close Enough!/Assets/Resources/Sounds.meta deleted file mode 100644 index f7292c4..0000000 --- a/Close Enough!/Assets/Resources/Sounds.meta +++ /dev/null @@ -1,10 +0,0 @@ -fileFormatVersion: 2 -guid: 748b0cdd241e74960989e7559f930949 -folderAsset: yes -timeCreated: 1524211988 -licenseType: Pro -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Close Enough!/Assets/Scenes/Main.unity b/Close Enough!/Assets/Scenes/Main.unity index fd26ea8..f395a95 100644 --- a/Close Enough!/Assets/Scenes/Main.unity +++ b/Close Enough!/Assets/Scenes/Main.unity @@ -366,11 +366,114 @@ RectTransform: m_AnchoredPosition: {x: 1.1749992, y: -3.2131195} m_SizeDelta: {x: 2.8499985, y: 22.21} m_Pivot: {x: 0.5, y: 0.5} +<<<<<<< HEAD +--- !u!1 &469279136 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 469279137} + - component: {fileID: 469279140} + - component: {fileID: 469279139} + - component: {fileID: 469279138} + m_Layer: 5 + m_Name: Undo + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &469279137 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 469279136} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1333615664} + m_Father: {fileID: 1154220189} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -344.76453, y: 129.88617} + m_SizeDelta: {x: 50, y: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &469279138 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 469279136} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 469279139} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1360377386} + m_MethodName: undo + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &469279139 +======= --- !u!114 &214529572 +>>>>>>> master MonoBehaviour: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} +<<<<<<< HEAD + m_GameObject: {fileID: 469279136} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} +======= m_GameObject: {fileID: 214529569} m_Enabled: 1 m_EditorHideFlags: 0 @@ -379,12 +482,24 @@ MonoBehaviour: m_EditorClassIdentifier: m_Material: {fileID: 0} m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} +>>>>>>> master m_RaycastTarget: 1 m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null +<<<<<<< HEAD + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 +--- !u!222 &469279140 +======= m_FontData: m_Font: {fileID: 12800000, guid: e81df6e094ca4478bb15a1016b03539e, type: 3} m_FontSize: 50 @@ -400,12 +515,18 @@ MonoBehaviour: m_LineSpacing: 1 m_Text: :00 --- !u!222 &214529573 +>>>>>>> master CanvasRenderer: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} +<<<<<<< HEAD + m_GameObject: {fileID: 469279136} +--- !u!1 &564082297 +======= m_GameObject: {fileID: 214529569} --- !u!1 &258566169 +>>>>>>> master GameObject: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} @@ -621,8 +742,101 @@ CanvasRenderer: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} +<<<<<<< HEAD + m_GameObject: {fileID: 1154220185} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_Children: + - {fileID: 564082298} + - {fileID: 469279137} + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!1 &1333615663 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1333615664} + - component: {fileID: 1333615666} + - component: {fileID: 1333615665} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1333615664 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1333615663} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 469279137} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1333615665 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1333615663} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Undo +--- !u!222 &1333615666 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1333615663} +--- !u!1 &1360377385 +======= m_GameObject: {fileID: 281243090} --- !u!1 &296905654 +>>>>>>> master GameObject: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} diff --git a/Close Enough!/Assets/Scenes/Menu Navigation.unity b/Close Enough!/Assets/Scenes/Menu Navigation.unity index 993bf77..1650535 100644 --- a/Close Enough!/Assets/Scenes/Menu Navigation.unity +++ b/Close Enough!/Assets/Scenes/Menu Navigation.unity @@ -320,6 +320,51 @@ CanvasRenderer: m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 65785645} +--- !u!1 &76871618 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 76871619} + - component: {fileID: 76871620} + m_Layer: 5 + m_Name: LobbyNetwork + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &76871619 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 76871618} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1483827831} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 100, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &76871620 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 76871618} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 81c8bbeace2004b9691a197f301b2660, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &187308848 GameObject: m_ObjectHideFlags: 0 @@ -394,6 +439,143 @@ CanvasRenderer: m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 187308848} +--- !u!1 &219509522 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 219509523} + - component: {fileID: 219509526} + - component: {fileID: 219509525} + - component: {fileID: 219509524} + m_Layer: 5 + m_Name: Viewport + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &219509523 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 219509522} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1595016515} + m_Father: {fileID: 2059613462} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -17, y: 0} + m_Pivot: {x: 0, y: 1} +--- !u!114 &219509524 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 219509522} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10917, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 +--- !u!222 &219509525 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 219509522} +--- !u!114 &219509526 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 219509522} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1200242548, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ShowMaskGraphic: 0 +--- !u!1 &234334110 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 234334111} + - component: {fileID: 234334113} + - component: {fileID: 234334112} + m_Layer: 0 + m_Name: PlayerNetwork + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &234334111 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 234334110} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1102842270} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &234334112 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 234334110} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6a5ab4672e46a4aeca847b2e57470702, type: 3} + m_Name: + m_EditorClassIdentifier: + nameInput: {fileID: 765888741} +--- !u!114 &234334113 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 234334110} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a2e09e220763b413f8e1866ed3a08c73, type: 3} + m_Name: + m_EditorClassIdentifier: + nameInput: {fileID: 0} + k__BackingField: --- !u!1 &248548570 GameObject: m_ObjectHideFlags: 0 @@ -405,6 +587,7 @@ GameObject: - component: {fileID: 248548574} - component: {fileID: 248548573} - component: {fileID: 248548572} + - component: {fileID: 248548575} m_Layer: 5 m_Name: Create Game Button m_TagString: Untagged @@ -492,6 +675,17 @@ MonoBehaviour: m_StringArgument: m_BoolArgument: 1 m_CallState: 2 + - m_Target: {fileID: 248548575} + m_MethodName: OnClick_CreateRoom + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null --- !u!114 &248548573 @@ -527,6 +721,17 @@ CanvasRenderer: m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 248548570} +--- !u!114 &248548575 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 248548570} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b6cd47d316ec64aa88594d72d1bb639f, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &312785262 GameObject: m_ObjectHideFlags: 0 @@ -717,7 +922,7 @@ Transform: m_LocalScale: {x: 1, y: 1, z: 1} m_Children: [] m_Father: {fileID: 0} - m_RootOrder: 4 + m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &323019184 MonoBehaviour: @@ -1106,7 +1311,7 @@ RectTransform: - {fileID: 1923159777} - {fileID: 553185370} m_Father: {fileID: 1020148503} - m_RootOrder: 4 + m_RootOrder: 5 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -1479,7 +1684,7 @@ RectTransform: - {fileID: 2077198728} - {fileID: 1178839219} m_Father: {fileID: 972579635} - m_RootOrder: 4 + m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -2047,6 +2252,7 @@ GameObject: - component: {fileID: 898120273} - component: {fileID: 898120272} - component: {fileID: 898120271} + - component: {fileID: 898120274} m_Layer: 5 m_Name: Next Button m_TagString: Untagged @@ -2134,6 +2340,17 @@ MonoBehaviour: m_StringArgument: m_BoolArgument: 1 m_CallState: 2 + - m_Target: {fileID: 898120274} + m_MethodName: OnClick_JoinRoom + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null --- !u!114 &898120272 @@ -2169,6 +2386,18 @@ CanvasRenderer: m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 898120269} +--- !u!114 &898120274 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 898120269} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5da7a41cbc72f464a86b65eb4b4b2ef2, type: 3} + m_Name: + m_EditorClassIdentifier: + roomName: {fileID: 1084027632} --- !u!1 &972579634 GameObject: m_ObjectHideFlags: 0 @@ -2185,7 +2414,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 + m_IsActive: 1 --- !u!224 &972579635 RectTransform: m_ObjectHideFlags: 0 @@ -2198,11 +2427,11 @@ RectTransform: m_Children: - {fileID: 1624071777} - {fileID: 1795314668} - - {fileID: 1577123207} - {fileID: 1152231006} - {fileID: 667685437} + - {fileID: 2059613462} m_Father: {fileID: 1020148503} - m_RootOrder: 3 + m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -2327,6 +2556,7 @@ RectTransform: m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 0, y: 0, z: 0} m_Children: + - {fileID: 1713611232} - {fileID: 1435764428} - {fileID: 1483827831} - {fileID: 1148650974} @@ -2539,6 +2769,47 @@ CanvasRenderer: m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 1089989750} +--- !u!1 &1102842269 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1102842270} + - component: {fileID: 1102842271} + m_Layer: 0 + m_Name: DDOL + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1102842270 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1102842269} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 240.91733, y: 421.28323, z: -20.27851} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 234334111} + m_Father: {fileID: 0} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1102842271 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1102842269} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 907e28078f4ac4bd29814f4ee719b83c, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &1111334210 GameObject: m_ObjectHideFlags: 0 @@ -2645,7 +2916,7 @@ RectTransform: - {fileID: 898120270} - {fileID: 1757390521} m_Father: {fileID: 1020148503} - m_RootOrder: 2 + m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -2715,7 +2986,7 @@ RectTransform: m_Children: - {fileID: 187308849} m_Father: {fileID: 972579635} - m_RootOrder: 3 + m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -2807,98 +3078,6 @@ CanvasRenderer: m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 1152231005} ---- !u!1 &1170772892 -GameObject: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - serializedVersion: 5 - m_Component: - - component: {fileID: 1170772893} - - component: {fileID: 1170772895} - - component: {fileID: 1170772894} - m_Layer: 5 - m_Name: Text - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &1170772893 -RectTransform: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 1170772892} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 1577123207} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.44761732} - m_AnchorMax: {x: 0.5, y: 0.44761732} - m_AnchoredPosition: {x: -0.000004321788, y: -80.76761} - m_SizeDelta: {x: 233.2, y: 450.1} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &1170772894 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 1170772892} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} - m_RaycastTarget: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, - Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_FontData: - m_Font: {fileID: 12800000, guid: 9ee58c86788afb1468f4ec78d2dd52ff, type: 3} - m_FontSize: 32 - m_FontStyle: 0 - m_BestFit: 0 - m_MinSize: 2 - m_MaxSize: 40 - m_Alignment: 0 - m_AlignByGeometry: 0 - m_RichText: 1 - m_HorizontalOverflow: 0 - m_VerticalOverflow: 0 - m_LineSpacing: 1 - m_Text: '1. Rdang - - 2. Bfann - - 3. ABerthon - - 4. Jluong - - 5. Btran - - 6. Ctran - - 7. Btang - - 8. JLittle - - 9. Athai - - 10. Dnguyen' ---- !u!222 &1170772895 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 1170772892} --- !u!1 &1178839218 GameObject: m_ObjectHideFlags: 0 @@ -3097,7 +3276,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!224 &1435764428 RectTransform: m_ObjectHideFlags: 0 @@ -3113,7 +3292,7 @@ RectTransform: - {fileID: 1439672850} - {fileID: 1089989751} m_Father: {fileID: 1020148503} - m_RootOrder: 0 + m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -3251,6 +3430,17 @@ MonoBehaviour: m_StringArgument: m_BoolArgument: 1 m_CallState: 2 + - m_Target: {fileID: 234334112} + m_MethodName: SetNickname + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null --- !u!114 &1439672852 @@ -3316,8 +3506,9 @@ RectTransform: - {fileID: 885015618} - {fileID: 248548571} - {fileID: 432435943} + - {fileID: 76871619} m_Father: {fileID: 1020148503} - m_RootOrder: 1 + m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -3357,120 +3548,90 @@ CanvasRenderer: m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 1483827830} ---- !u!1 &1577123206 +--- !u!1 &1595016514 GameObject: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} serializedVersion: 5 m_Component: - - component: {fileID: 1577123207} - - component: {fileID: 1577123211} - - component: {fileID: 1577123210} - - component: {fileID: 1577123209} - - component: {fileID: 1577123208} + - component: {fileID: 1595016515} + - component: {fileID: 1595016517} + - component: {fileID: 1595016516} + - component: {fileID: 1595016518} m_Layer: 5 - m_Name: ScrollBox + m_Name: PlayerLayoutGroup m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &1577123207 +--- !u!224 &1595016515 RectTransform: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 1577123206} + m_GameObject: {fileID: 1595016514} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 1170772893} - m_Father: {fileID: 972579635} - m_RootOrder: 2 + m_Children: [] + m_Father: {fileID: 219509523} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: -51.22544, y: -32} - m_SizeDelta: {x: 273.4, y: 261.2} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &1577123208 + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: -0.000010905711, y: -0.000011926711} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 1} +--- !u!114 &1595016516 MonoBehaviour: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 1577123206} + m_GameObject: {fileID: 1595016514} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: -1200242548, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Script: {fileID: 1741964061, guid: f70555f144d8491a825f0804e09c671c, type: 3} m_Name: m_EditorClassIdentifier: - m_ShowMaskGraphic: 1 ---- !u!114 &1577123209 + m_HorizontalFit: 0 + m_VerticalFit: 1 +--- !u!114 &1595016517 MonoBehaviour: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 1577123206} + m_GameObject: {fileID: 1595016514} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 1367256648, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Script: {fileID: 1297475563, guid: f70555f144d8491a825f0804e09c671c, type: 3} m_Name: m_EditorClassIdentifier: - m_Content: {fileID: 1170772893} - m_Horizontal: 1 - m_Vertical: 1 - m_MovementType: 2 - m_Elasticity: 0.1 - m_Inertia: 1 - m_DecelerationRate: 0.135 - m_ScrollSensitivity: 1 - m_Viewport: {fileID: 0} - m_HorizontalScrollbar: {fileID: 0} - m_VerticalScrollbar: {fileID: 0} - m_HorizontalScrollbarVisibility: 0 - m_VerticalScrollbarVisibility: 0 - m_HorizontalScrollbarSpacing: 0 - m_VerticalScrollbarSpacing: 0 - m_OnValueChanged: - m_PersistentCalls: - m_Calls: [] - m_TypeName: UnityEngine.UI.ScrollRect+ScrollRectEvent, UnityEngine.UI, Version=1.0.0.0, - Culture=neutral, PublicKeyToken=null ---- !u!114 &1577123210 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 1 + m_Spacing: 0 + m_ChildForceExpandWidth: 0 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 0 + m_ChildControlHeight: 0 +--- !u!114 &1595016518 MonoBehaviour: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 1577123206} + m_GameObject: {fileID: 1595016514} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Script: {fileID: 11500000, guid: 2e9345fa2090d45dc976906316175f64, type: 3} m_Name: m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, - Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - m_Sprite: {fileID: 21300000, guid: 8d6306d532861fa449c82d1f009dc270, type: 3} - m_Type: 0 - m_PreserveAspect: 0 - m_FillCenter: 1 - m_FillMethod: 4 - m_FillAmount: 1 - m_FillClockwise: 1 - m_FillOrigin: 0 ---- !u!222 &1577123211 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 1577123206} + _playerListingPrefab: {fileID: 1116522181043838, guid: 53c9be48b0bc1477691b754ac80d7d60, + type: 2} --- !u!1 &1601735969 GameObject: m_ObjectHideFlags: 0 @@ -3643,6 +3804,17 @@ MonoBehaviour: m_StringArgument: m_BoolArgument: 1 m_CallState: 2 + - m_Target: {fileID: 1595016518} + m_MethodName: OnClickLeaveRoom + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null --- !u!114 &1624071779 @@ -4029,12 +4201,12 @@ Transform: m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 1713611229} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -400, y: -300, z: 0} + m_LocalScale: {x: 0.78125, y: 0.78125, z: 0.78125} m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 3 + m_Father: {fileID: 1020148503} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1757390520 GameObject: @@ -4191,6 +4363,7 @@ GameObject: - component: {fileID: 1795314668} - component: {fileID: 1795314670} - component: {fileID: 1795314669} + - component: {fileID: 1795314671} m_Layer: 5 m_Name: Game Lobby Title Text m_TagString: Untagged @@ -4248,13 +4421,27 @@ MonoBehaviour: m_HorizontalOverflow: 1 m_VerticalOverflow: 1 m_LineSpacing: 1 - m_Text: RDANG'S GAME LOBBY + m_Text: 'Default Text + +' --- !u!222 &1795314670 CanvasRenderer: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 1795314667} +--- !u!114 &1795314671 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1795314667} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4377189935b6e4bdc89d33e435195f04, type: 3} + m_Name: + m_EditorClassIdentifier: + roomName: {fileID: 1795314669} --- !u!1 &1889146927 GameObject: m_ObjectHideFlags: 0 @@ -4753,6 +4940,107 @@ CanvasRenderer: m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} m_GameObject: {fileID: 2050305033} +--- !u!1 &2059613461 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 2059613462} + - component: {fileID: 2059613465} + - component: {fileID: 2059613464} + - component: {fileID: 2059613463} + m_Layer: 5 + m_Name: PlayerList + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2059613462 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2059613461} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 219509523} + m_Father: {fileID: 972579635} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: -49.715, y: -32} + m_SizeDelta: {x: -523.58, y: -323.58} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2059613463 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2059613461} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 0.392} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 +--- !u!222 &2059613464 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2059613461} +--- !u!114 &2059613465 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2059613461} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1367256648, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Content: {fileID: 1595016515} + m_Horizontal: 0 + m_Vertical: 1 + m_MovementType: 1 + m_Elasticity: 0.1 + m_Inertia: 1 + m_DecelerationRate: 0.135 + m_ScrollSensitivity: 1 + m_Viewport: {fileID: 219509523} + m_HorizontalScrollbar: {fileID: 0} + m_VerticalScrollbar: {fileID: 0} + m_HorizontalScrollbarVisibility: 2 + m_VerticalScrollbarVisibility: 2 + m_HorizontalScrollbarSpacing: -3 + m_VerticalScrollbarSpacing: -3 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.ScrollRect+ScrollRectEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null --- !u!1 &2077198727 GameObject: m_ObjectHideFlags: 0 diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts.meta b/Close Enough!/Assets/Scripts/Menu Navigation Scripts.meta new file mode 100644 index 0000000..94c9f32 --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 080099b0333c84a259fcafa2ffd72b44 +folderAsset: yes +timeCreated: 1525372307 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Generic.meta b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Generic.meta new file mode 100644 index 0000000..dc208b1 --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Generic.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: e92ee5752e89b471caf1e2e0e8945d0c +folderAsset: yes +timeCreated: 1525382640 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Generic/DDOL.cs b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Generic/DDOL.cs new file mode 100644 index 0000000..965bb6e --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Generic/DDOL.cs @@ -0,0 +1,8 @@ +using UnityEngine; + +public class DDOL : MonoBehaviour { + + private void Awake(){ + DontDestroyOnLoad(this); + } +} diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Generic/DDOL.cs.meta b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Generic/DDOL.cs.meta new file mode 100644 index 0000000..ac99271 --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Generic/DDOL.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 907e28078f4ac4bd29814f4ee719b83c +timeCreated: 1525378724 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Networks.meta b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Networks.meta new file mode 100644 index 0000000..2149f5f --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Networks.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: fda20f3f7ba264136bdc24534d1efe3d +folderAsset: yes +timeCreated: 1525382626 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Networks/LobbyNetwork.cs b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Networks/LobbyNetwork.cs new file mode 100644 index 0000000..bbc7b7e --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Networks/LobbyNetwork.cs @@ -0,0 +1,22 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class LobbyNetwork : MonoBehaviour { + + // Use this for initialization + void Start () { + print ("Connecting to server.."); + PhotonNetwork.ConnectUsingSettings("0.0.0"); + } + + private void OnConnectedToMaster(){ + print ("Connected to master."); + PhotonNetwork.playerName = PlayerNetwork.Instance.PlayerName; + PhotonNetwork.JoinLobby(TypedLobby.Default); + } + + private void OnJoinedLobby(){ + print("Joined lobby."); + } +} diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Networks/LobbyNetwork.cs.meta b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Networks/LobbyNetwork.cs.meta new file mode 100644 index 0000000..03cf7e5 --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Networks/LobbyNetwork.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 81c8bbeace2004b9691a197f301b2660 +timeCreated: 1525379619 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Networks/PlayerNetwork.cs b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Networks/PlayerNetwork.cs new file mode 100644 index 0000000..fa42371 --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Networks/PlayerNetwork.cs @@ -0,0 +1,19 @@ +using UnityEngine; +using UnityEngine.UI; + +public class PlayerNetwork : MonoBehaviour { + + public Text nameInput; + public static PlayerNetwork Instance; + public string PlayerName { get; set; } + + private void Awake() + { + Instance = this; + PlayerName = "Testing#" + Random.Range (1000, 9999); + } + + public void SetNickname(){ + PlayerName = nameInput.text + "#" + Random.Range (1000, 9999); + } +} diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Networks/PlayerNetwork.cs.meta b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Networks/PlayerNetwork.cs.meta new file mode 100644 index 0000000..4e8a1fd --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Networks/PlayerNetwork.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 6a5ab4672e46a4aeca847b2e57470702 +timeCreated: 1525378496 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room.meta b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room.meta new file mode 100644 index 0000000..7edf0c3 --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: e362428d108c345779ec4d455bb1a40a +folderAsset: yes +timeCreated: 1525385821 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/CreateRoom.cs b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/CreateRoom.cs new file mode 100644 index 0000000..02771b5 --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/CreateRoom.cs @@ -0,0 +1,24 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +public class CreateRoom : MonoBehaviour { + + public void OnClick_CreateRoom(){ + if (PhotonNetwork.CreateRoom (null)) { + print ("create room successfully sent."); + } + else { + print ("create room failed to send."); + } + } + + private void OnPhotonCreateRoomFailed(object[] codeAndMessage){ + print("Create room failed: " + codeAndMessage[1]); + } + + private void OnCreatedRoom(){ + print ("Room created successfully. TESTING randomized roomname = " + PhotonNetwork.room.Name); + } +} diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/CreateRoom.cs.meta b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/CreateRoom.cs.meta new file mode 100644 index 0000000..f205ada --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/CreateRoom.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: b6cd47d316ec64aa88594d72d1bb639f +timeCreated: 1525382041 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/DisplayRoomCode.cs b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/DisplayRoomCode.cs new file mode 100644 index 0000000..e9c7937 --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/DisplayRoomCode.cs @@ -0,0 +1,20 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + + +public class DisplayRoomCode : MonoBehaviour { + + public Text roomName; + + // Use this for initialization + void Start () { + if (PhotonNetwork.room.Name.Length > 0) { + roomName.text = PhotonNetwork.room.Name; + } + else { + roomName.text = "Error retrieving room ID"; + } + } +} diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/DisplayRoomCode.cs.meta b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/DisplayRoomCode.cs.meta new file mode 100644 index 0000000..ed8a4d8 --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/DisplayRoomCode.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 4377189935b6e4bdc89d33e435195f04 +timeCreated: 1525385586 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/JoinRoom.cs b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/JoinRoom.cs new file mode 100644 index 0000000..f73a881 --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/JoinRoom.cs @@ -0,0 +1,20 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + + +public class JoinRoom : MonoBehaviour { + + public Text roomName; + + public void OnClick_JoinRoom(){ + if (PhotonNetwork.JoinRoom(roomName.text)) { + } + else { + print ("Joint room failed."); + } + + } +} + \ No newline at end of file diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/JoinRoom.cs.meta b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/JoinRoom.cs.meta new file mode 100644 index 0000000..325aa73 --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/JoinRoom.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 5da7a41cbc72f464a86b65eb4b4b2ef2 +timeCreated: 1525383749 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/PlayerLayoutGroup.cs b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/PlayerLayoutGroup.cs new file mode 100644 index 0000000..a53bf65 --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/PlayerLayoutGroup.cs @@ -0,0 +1,66 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class PlayerLayoutGroup : MonoBehaviour { + + [SerializeField] + private GameObject _playerListingPrefab; + private GameObject PlayerListingPrefab{ + get { return _playerListingPrefab;} + } + + private List _playerListings = new List(); + private List PlayerListings { + get {return _playerListings;} + } + + //called by photon + private void OnJoinedRoom(){ + PhotonPlayer[] photonPlayers = PhotonNetwork.playerList; + for (int i = 0; i < photonPlayers.Length; i++) { + PlayerJoinedRoom(photonPlayers[i]); + } + + } + + //called by photon + private void OnPhotonPlayerConnected(PhotonPlayer photonPlayer){ + PlayerJoinedRoom(photonPlayer); + } + + //called by photon + private void OnPhotonPlayerDisconnected(PhotonPlayer photonPlayer){ + PlayerLeftRoom(photonPlayer); + } + + + private void PlayerJoinedRoom(PhotonPlayer photonPlayer){ + if(photonPlayer == null) + return; + + PlayerLeftRoom (photonPlayer); + + GameObject playerListingObj = Instantiate (PlayerListingPrefab); + playerListingObj.transform.SetParent(transform, false); + + PlayerListing playerListing = playerListingObj.GetComponent (); + playerListing.ApplyPhotonPlayer(photonPlayer); + + PlayerListings.Add(playerListing); + } + + private void PlayerLeftRoom(PhotonPlayer photonPlayer){ + int index = PlayerListings.FindIndex(x => x.PhotonPlayer == photonPlayer); + if (index != -1) { + Destroy (PlayerListings[index].gameObject); + PlayerListings.RemoveAt(index); + } + } + + public void OnClickLeaveRoom(){ + PhotonNetwork.LeaveRoom (); + } + +} + \ No newline at end of file diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/PlayerLayoutGroup.cs.meta b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/PlayerLayoutGroup.cs.meta new file mode 100644 index 0000000..51f63f4 --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/PlayerLayoutGroup.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 2e9345fa2090d45dc976906316175f64 +timeCreated: 1525372335 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/PlayerListing.cs b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/PlayerListing.cs new file mode 100644 index 0000000..f7a6398 --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/PlayerListing.cs @@ -0,0 +1,17 @@ +using UnityEngine; +using UnityEngine.UI; + +public class PlayerListing : MonoBehaviour { + + public PhotonPlayer PhotonPlayer { get; private set;} + + [SerializeField] + private Text _playerName; + private Text PlayerName{ + get{return _playerName;} + } + + public void ApplyPhotonPlayer(PhotonPlayer photonPlayer){ + PlayerName.text = photonPlayer.NickName; + } +} \ No newline at end of file diff --git a/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/PlayerListing.cs.meta b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/PlayerListing.cs.meta new file mode 100644 index 0000000..feffaaf --- /dev/null +++ b/Close Enough!/Assets/Scripts/Menu Navigation Scripts/Room/PlayerListing.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 907d3294e2ffd4b2ea27387abdd0c826 +timeCreated: 1525372319 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Assets/Scripts/PlayerData.cs b/Close Enough!/Assets/Scripts/PlayerData.cs index d108a1f..f451693 100644 --- a/Close Enough!/Assets/Scripts/PlayerData.cs +++ b/Close Enough!/Assets/Scripts/PlayerData.cs @@ -11,3 +11,5 @@ public void UpdateText() { Name = text.text; } } + +//might not need this one anymore diff --git a/Close Enough!/Assets/Scripts/State Management.meta b/Close Enough!/Assets/Scripts/State Management.meta deleted file mode 100644 index e16d5c1..0000000 --- a/Close Enough!/Assets/Scripts/State Management.meta +++ /dev/null @@ -1,10 +0,0 @@ -fileFormatVersion: 2 -guid: 68565d946c006414a9ee2655fb3c1765 -folderAsset: yes -timeCreated: 1524211988 -licenseType: Pro -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Close Enough!/Assets/Swipe.prefab b/Close Enough!/Assets/Swipe.prefab index 238540a..e52833f 100644 --- a/Close Enough!/Assets/Swipe.prefab +++ b/Close Enough!/Assets/Swipe.prefab @@ -152,5 +152,22 @@ LineRenderer: alignment: 0 textureMode: 0 generateLightingData: 0 +<<<<<<< HEAD + m_MinVertexDistance: 0.1 + m_Autodestruct: 0 +--- !u!114 &114816767584630334 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1202154236009936} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6f57808b243c1432eb9f6f79d44bfde2, type: 3} + m_Name: + m_EditorClassIdentifier: + width: 0.1 +======= m_UseWorldSpace: 1 m_Loop: 0 +>>>>>>> master diff --git a/Close Enough!/Assets/SwipeTrail.cs b/Close Enough!/Assets/SwipeTrail.cs new file mode 100644 index 0000000..37266a1 --- /dev/null +++ b/Close Enough!/Assets/SwipeTrail.cs @@ -0,0 +1,68 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +public class SwipeTrail : MonoBehaviour { + + public GameObject trailPrefab; + GameObject thisTrail; + Vector3 startPos; //3 + Plane objPlane; + private List instantiated; + int i; + + void Start(){ + objPlane = new Plane(Camera.main.transform.forward* -1, this.transform.position); + instantiated = new List(); + i = -1; + } + + void Update(){ + if ((Input.touchCount > 0 && Input.GetTouch (0).phase == TouchPhase.Began) || Input.GetMouseButtonDown (0)) { + Ray mRay = Camera.main.ScreenPointToRay (Input.mousePosition); + float rayDistance; + if (objPlane.Raycast (mRay, out rayDistance)) { + startPos = mRay.GetPoint (rayDistance); + } + thisTrail = (GameObject)Instantiate (trailPrefab, startPos, Quaternion.identity); + instantiated.Add(thisTrail); + i++; + } else if (((Input.touchCount > 0 && Input.GetTouch (0).phase == TouchPhase.Moved) || Input.GetMouseButton (0))) { + Ray mRay = Camera.main.ScreenPointToRay (Input.mousePosition); + float rayDistance; + if (objPlane.Raycast (mRay, out rayDistance)) { + thisTrail.transform.position = mRay.GetPoint (rayDistance); + } + } + //else if ((Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Ended) || Input.GetMouseButtonUp(0)) { + // if (Vector3.Distance(thisTrail.transform.position, startPos) < 0.1) { + // Destroy(thisTrail); + // } + //} + //if(Input.GetKeyDown(KeyCode.D)){ + // Destroy(instantiated[i]); + // instantiated.RemoveAt(i); + // i--; + } + + public void undo(){ + Destroy(instantiated[i]); + instantiated.RemoveAt(i); + i--; + Destroy(instantiated[i]); + instantiated.RemoveAt(i); + i--; + } +} + + + + // // Use this for initialization + // void Start () { + // + // } + + + + diff --git a/Close Enough!/Assets/SwipeTrail.cs.meta b/Close Enough!/Assets/SwipeTrail.cs.meta new file mode 100644 index 0000000..a63d211 --- /dev/null +++ b/Close Enough!/Assets/SwipeTrail.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: a3ee74d5d685846119ac8c00ec1c6315 +timeCreated: 1525366830 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Close Enough!/Library/AnnotationManager b/Close Enough!/Library/AnnotationManager deleted file mode 100644 index 1dc7b0f..0000000 Binary files a/Close Enough!/Library/AnnotationManager and /dev/null differ diff --git a/Close Enough!/Library/AssetImportState b/Close Enough!/Library/AssetImportState deleted file mode 100644 index 71a7592..0000000 --- a/Close Enough!/Library/AssetImportState +++ /dev/null @@ -1 +0,0 @@ -2;0;196608;0;0 \ No newline at end of file diff --git a/Close Enough!/Library/BuildPlayer.prefs b/Close Enough!/Library/BuildPlayer.prefs deleted file mode 100644 index e69de29..0000000 diff --git a/Close Enough!/Library/BuildSettings.asset b/Close Enough!/Library/BuildSettings.asset deleted file mode 100644 index 7012d3e..0000000 Binary files a/Close Enough!/Library/BuildSettings.asset and /dev/null differ diff --git a/Close Enough!/Library/CurrentLayout.dwlt b/Close Enough!/Library/CurrentLayout.dwlt deleted file mode 100644 index ad7cd63..0000000 --- a/Close Enough!/Library/CurrentLayout.dwlt +++ /dev/null @@ -1,759 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &1 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12004, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_PixelRect: - serializedVersion: 2 - x: 0 - y: 45 - width: 1280 - height: 685 - m_ShowMode: 4 - m_Title: - m_RootView: {fileID: 2} - m_MinSize: {x: 950, y: 300} - m_MaxSize: {x: 10000, y: 10000} ---- !u!114 &2 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12008, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: - - {fileID: 3} - - {fileID: 5} - - {fileID: 4} - m_Position: - serializedVersion: 2 - x: 0 - y: 0 - width: 1280 - height: 685 - m_MinSize: {x: 950, y: 300} - m_MaxSize: {x: 10000, y: 10000} ---- !u!114 &3 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12011, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: [] - m_Position: - serializedVersion: 2 - x: 0 - y: 0 - width: 950 - height: 30 - m_MinSize: {x: 0, y: 0} - m_MaxSize: {x: 0, y: 0} - m_LastLoadedLayoutName: 2 by 3 ---- !u!114 &4 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12042, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: [] - m_Position: - serializedVersion: 2 - x: 0 - y: 665 - width: 1280 - height: 20 - m_MinSize: {x: 0, y: 0} - m_MaxSize: {x: 0, y: 0} ---- !u!114 &5 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: - - {fileID: 6} - - {fileID: 9} - - {fileID: 10} - - {fileID: 11} - m_Position: - serializedVersion: 2 - x: 0 - y: 30 - width: 1280 - height: 635 - m_MinSize: {x: 917, y: 442} - m_MaxSize: {x: 22012, y: 10021} - vertical: 0 - controlID: 16099 ---- !u!114 &6 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: - - {fileID: 7} - - {fileID: 8} - m_Position: - serializedVersion: 2 - x: 0 - y: 0 - width: 422 - height: 635 - m_MinSize: {x: 202, y: 442} - m_MaxSize: {x: 4002, y: 8042} - vertical: 1 - controlID: 16100 ---- !u!114 &7 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: [] - m_Position: - serializedVersion: 2 - x: 0 - y: 0 - width: 422 - height: 325 - m_MinSize: {x: 202, y: 221} - m_MaxSize: {x: 4002, y: 4021} - m_ActualView: {fileID: 13} - m_Panes: - - {fileID: 13} - m_Selected: 0 - m_LastSelected: 0 ---- !u!114 &8 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: [] - m_Position: - serializedVersion: 2 - x: 0 - y: 325 - width: 422 - height: 310 - m_MinSize: {x: 202, y: 221} - m_MaxSize: {x: 4002, y: 4021} - m_ActualView: {fileID: 12} - m_Panes: - - {fileID: 12} - m_Selected: 0 - m_LastSelected: 0 ---- !u!114 &9 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: [] - m_Position: - serializedVersion: 2 - x: 422 - y: 0 - width: 204 - height: 635 - m_MinSize: {x: 204, y: 221} - m_MaxSize: {x: 4004, y: 4021} - m_ActualView: {fileID: 14} - m_Panes: - - {fileID: 14} - m_Selected: 0 - m_LastSelected: 0 ---- !u!114 &10 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: [] - m_Position: - serializedVersion: 2 - x: 626 - y: 0 - width: 368 - height: 635 - m_MinSize: {x: 234, y: 271} - m_MaxSize: {x: 10004, y: 10021} - m_ActualView: {fileID: 15} - m_Panes: - - {fileID: 15} - - {fileID: 16} - m_Selected: 0 - m_LastSelected: 1 ---- !u!114 &11 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: [] - m_Position: - serializedVersion: 2 - x: 994 - y: 0 - width: 286 - height: 635 - m_MinSize: {x: 277, y: 71} - m_MaxSize: {x: 4002, y: 4021} - m_ActualView: {fileID: 17} - m_Panes: - - {fileID: 17} - m_Selected: 0 - m_LastSelected: 0 ---- !u!114 &12 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12015, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_AutoRepaintOnSceneChange: 1 - m_MinSize: {x: 200, y: 200} - m_MaxSize: {x: 4000, y: 4000} - m_TitleContent: - m_Text: Game - m_Image: {fileID: -2087823869225018852, guid: 0000000000000000d000000000000000, - type: 0} - m_Tooltip: - m_DepthBufferBits: 32 - m_Pos: - serializedVersion: 2 - x: 0 - y: 419 - width: 420 - height: 289 - m_PersistentViewDataDictionary: {fileID: 0} - m_MaximizeOnPlay: 0 - m_Gizmos: 0 - m_Stats: 0 - m_SelectedSizes: 04000000000000000000000000000000000000000000000000000000000000000000000000000000 - m_TargetDisplay: 0 - m_ZoomArea: - m_HRangeLocked: 0 - m_VRangeLocked: 0 - m_HBaseRangeMin: -105 - m_HBaseRangeMax: 105 - m_VBaseRangeMin: -65.625 - m_VBaseRangeMax: 65.625 - m_HAllowExceedBaseRangeMin: 1 - m_HAllowExceedBaseRangeMax: 1 - m_VAllowExceedBaseRangeMin: 1 - m_VAllowExceedBaseRangeMax: 1 - m_ScaleWithWindow: 0 - m_HSlider: 0 - m_VSlider: 0 - m_IgnoreScrollWheelUntilClicked: 0 - m_EnableMouseInput: 1 - m_EnableSliderZoom: 0 - m_UniformScale: 1 - m_UpDirection: 1 - m_DrawArea: - serializedVersion: 2 - x: 0 - y: 17 - width: 420 - height: 272 - m_Scale: {x: 2, y: 2} - m_Translation: {x: 210, y: 136} - m_MarginLeft: 0 - m_MarginRight: 0 - m_MarginTop: 0 - m_MarginBottom: 0 - m_LastShownAreaInsideMargins: - serializedVersion: 2 - x: -105 - y: -68 - width: 210 - height: 136 - m_MinimalGUI: 1 - m_defaultScale: 2 - m_TargetTexture: {fileID: 0} - m_CurrentColorSpace: 0 - m_LastWindowPixelSize: {x: 840, y: 578} - m_ClearInEditMode: 1 - m_NoCameraWarning: 1 - m_LowResolutionForAspectRatios: 01000000000100000100 ---- !u!114 &13 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12013, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_AutoRepaintOnSceneChange: 1 - m_MinSize: {x: 200, y: 200} - m_MaxSize: {x: 4000, y: 4000} - m_TitleContent: - m_Text: Scene - m_Image: {fileID: 2318424515335265636, guid: 0000000000000000d000000000000000, - type: 0} - m_Tooltip: - m_DepthBufferBits: 32 - m_Pos: - serializedVersion: 2 - x: 0 - y: 94 - width: 420 - height: 304 - m_PersistentViewDataDictionary: {fileID: 0} - m_SceneLighting: 1 - lastFramingTime: 9490.332551002502 - m_2DMode: 1 - m_isRotationLocked: 0 - m_AudioPlay: 0 - m_Position: - m_Target: {x: -1.8438584, y: 0.41376585, z: -0.08241452} - speed: 2 - m_Value: {x: -1.8438584, y: 0.41376585, z: -0.08241452} - m_RenderMode: 0 - m_ValidateTrueMetals: 0 - m_SceneViewState: - showFog: 1 - showMaterialUpdate: 0 - showSkybox: 1 - showFlares: 1 - showImageEffects: 1 - showParticleSystems: 1 - grid: - xGrid: - m_Target: 0 - speed: 2 - m_Value: 0 - yGrid: - m_Target: 0 - speed: 2 - m_Value: 0 - zGrid: - m_Target: 1 - speed: 2 - m_Value: 1 - m_Rotation: - m_Target: {x: 0, y: 0, z: 0, w: 1} - speed: 2 - m_Value: {x: 0, y: 0, z: 0, w: 1} - m_Size: - m_Target: 11.126857 - speed: 2 - m_Value: 11.126857 - m_Ortho: - m_Target: 1 - speed: 2 - m_Value: 1 - m_ShowGlobalGrid: 1 - m_LastSceneViewRotation: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226} - m_LastSceneViewOrtho: 0 - m_ReplacementShader: {fileID: 0} - m_ReplacementString: - m_LastLockedObject: {fileID: 0} - m_ViewIsLockedToObject: 0 ---- !u!114 &14 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12061, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_AutoRepaintOnSceneChange: 0 - m_MinSize: {x: 200, y: 200} - m_MaxSize: {x: 4000, y: 4000} - m_TitleContent: - m_Text: Hierarchy - m_Image: {fileID: -590624980919486359, guid: 0000000000000000d000000000000000, - type: 0} - m_Tooltip: - m_DepthBufferBits: 0 - m_Pos: - serializedVersion: 2 - x: 424 - y: 94 - width: 200 - height: 614 - m_PersistentViewDataDictionary: {fileID: 0} - m_TreeViewState: - scrollPos: {x: 0, y: 75} - m_SelectedIDs: a2300000 - m_LastClickedID: 12450 - m_ExpandedIDs: 5e0bf9ff00dff9ff0a1ffaff642cfaff2e21fbff08cffbff46f3fbff1ae5ffff14ebffff00000000da2f000010300000323000007630000092300000a2300000d830000048310000 - m_RenameOverlay: - m_UserAcceptedRename: 0 - m_Name: Swipe(Clone) - m_OriginalName: Swipe(Clone) - m_EditFieldRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 0 - height: 0 - m_UserData: -905856 - m_IsWaitingForDelay: 0 - m_IsRenaming: 0 - m_OriginalEventType: 0 - m_IsRenamingFilename: 0 - m_ClientGUIView: {fileID: 9} - m_SearchString: - m_ExpandedScenes: - - Main - m_CurrenRootInstanceID: 0 - m_Locked: 1 - m_CurrentSortingName: TransformSorting ---- !u!114 &15 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12014, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_AutoRepaintOnSceneChange: 0 - m_MinSize: {x: 230, y: 250} - m_MaxSize: {x: 10000, y: 10000} - m_TitleContent: - m_Text: Project - m_Image: {fileID: -7501376956915960154, guid: 0000000000000000d000000000000000, - type: 0} - m_Tooltip: - m_DepthBufferBits: 0 - m_Pos: - serializedVersion: 2 - x: 628 - y: 94 - width: 364 - height: 614 - m_PersistentViewDataDictionary: {fileID: 0} - m_SearchFilter: - m_NameFilter: - m_ClassNames: [] - m_AssetLabels: [] - m_AssetBundleNames: [] - m_VersionControlStates: [] - m_SoftLockControlStates: [] - m_ReferencingInstanceIDs: - m_ScenePaths: [] - m_ShowAllHits: 0 - m_SearchArea: 0 - m_Folders: - - Assets - m_ViewMode: 1 - m_StartGridSize: 64 - m_LastFolders: - - Assets - m_LastFoldersGridSize: -1 - m_LastProjectPath: /Users/brianfann/Projects/CloseEnough/Close Enough! - m_IsLocked: 0 - m_FolderTreeState: - scrollPos: {x: 0, y: 0} - m_SelectedIDs: b22a0000 - m_LastClickedID: 10930 - m_ExpandedIDs: 00000000b22a0000c02a0000c62b0000ee2b0000c62c0000a62d00002a2e0000482e00004a2e00004e2e000000ca9a3bffffff7f - m_RenameOverlay: - m_UserAcceptedRename: 0 - m_Name: - m_OriginalName: - m_EditFieldRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 0 - height: 0 - m_UserData: 0 - m_IsWaitingForDelay: 0 - m_IsRenaming: 0 - m_OriginalEventType: 11 - m_IsRenamingFilename: 1 - m_ClientGUIView: {fileID: 10} - m_SearchString: - m_CreateAssetUtility: - m_EndAction: {fileID: 0} - m_InstanceID: 0 - m_Path: - m_Icon: {fileID: 0} - m_ResourceFile: - m_AssetTreeState: - scrollPos: {x: 0, y: 0} - m_SelectedIDs: - m_LastClickedID: 0 - m_ExpandedIDs: 00000000b22a0000c02a0000c62b0000ee2b0000c62c0000a62d00002a2e0000482e00004a2e00004e2e000000ca9a3bffffff7f - m_RenameOverlay: - m_UserAcceptedRename: 0 - m_Name: - m_OriginalName: - m_EditFieldRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 0 - height: 0 - m_UserData: 0 - m_IsWaitingForDelay: 0 - m_IsRenaming: 0 - m_OriginalEventType: 11 - m_IsRenamingFilename: 1 - m_ClientGUIView: {fileID: 0} - m_SearchString: - m_CreateAssetUtility: - m_EndAction: {fileID: 0} - m_InstanceID: 0 - m_Path: - m_Icon: {fileID: 0} - m_ResourceFile: - m_ListAreaState: - m_SelectedInstanceIDs: - m_LastClickedInstanceID: 0 - m_HadKeyboardFocusLastEvent: 1 - m_ExpandedInstanceIDs: 00000000 - m_RenameOverlay: - m_UserAcceptedRename: 0 - m_Name: - m_OriginalName: - m_EditFieldRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 0 - height: 0 - m_UserData: 0 - m_IsWaitingForDelay: 0 - m_IsRenaming: 0 - m_OriginalEventType: 11 - m_IsRenamingFilename: 1 - m_ClientGUIView: {fileID: 10} - m_CreateAssetUtility: - m_EndAction: {fileID: 0} - m_InstanceID: 0 - m_Path: - m_Icon: {fileID: 0} - m_ResourceFile: - m_NewAssetIndexInList: -1 - m_ScrollPosition: {x: 0, y: 2} - m_GridSize: 64 - m_DirectoriesAreaWidth: 172 ---- !u!114 &16 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12373, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_AutoRepaintOnSceneChange: 0 - m_MinSize: {x: 100, y: 100} - m_MaxSize: {x: 4000, y: 4000} - m_TitleContent: - m_Text: Audio Mixer - m_Image: {fileID: 5436946869657106676, guid: 0000000000000000d000000000000000, - type: 0} - m_Tooltip: - m_DepthBufferBits: 0 - m_Pos: - serializedVersion: 2 - x: 836 - y: 92 - width: 249 - height: 614 - m_PersistentViewDataDictionary: {fileID: 0} - m_MixersTreeState: - scrollPos: {x: 0, y: 0} - m_SelectedIDs: - m_LastClickedID: -346884 - m_ExpandedIDs: 12eb343c - m_RenameOverlay: - m_UserAcceptedRename: 0 - m_Name: - m_OriginalName: - m_EditFieldRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 0 - height: 0 - m_UserData: 0 - m_IsWaitingForDelay: 0 - m_IsRenaming: 0 - m_OriginalEventType: 11 - m_IsRenamingFilename: 0 - m_ClientGUIView: {fileID: 0} - m_SearchString: - m_CreateAssetUtility: - m_EndAction: {fileID: 0} - m_InstanceID: 0 - m_Path: - m_Icon: {fileID: 0} - m_ResourceFile: - m_LayoutStripsOnTop: - m_VerticalSplitter: - ID: 0 - splitterInitialOffset: 0 - currentActiveSplitter: -1 - realSizes: 4100000023000000 - relativeSizes: - - 0.65 - - 0.35000002 - minSizes: 5500000069000000 - maxSizes: 0000000000000000 - lastTotalSize: 0 - splitSize: 6 - xOffset: 0 - m_HorizontalSplitter: - ID: 0 - splitterInitialOffset: 0 - currentActiveSplitter: -1 - realSizes: 3c0000003c0000003c0000003c000000 - relativeSizes: - - 0.25 - - 0.25 - - 0.25 - - 0.25 - minSizes: 55000000550000005500000055000000 - maxSizes: 00000000000000000000000000000000 - lastTotalSize: 0 - splitSize: 6 - xOffset: 0 - m_LayoutStripsOnRight: - m_VerticalSplitter: - ID: 0 - splitterInitialOffset: 0 - currentActiveSplitter: -1 - realSizes: 3c0000003c0000003c0000003c000000 - relativeSizes: - - 0.25 - - 0.25 - - 0.25 - - 0.25 - minSizes: 64000000550000005500000055000000 - maxSizes: 00000000000000000000000000000000 - lastTotalSize: 0 - splitSize: 6 - xOffset: 0 - m_HorizontalSplitter: - ID: 95 - splitterInitialOffset: 0 - currentActiveSplitter: -1 - realSizes: a0000000a0000000 - relativeSizes: - - 0.3 - - 0.7 - minSizes: a0000000a0000000 - maxSizes: 0000000000000000 - lastTotalSize: 250 - splitSize: 6 - xOffset: -1 - m_SectionOrder: 00000000030000000100000002000000 - m_LayoutMode: 1 - m_SortGroupsAlphabetically: 0 - m_ShowReferencedBuses: 1 - m_ShowBusConnections: 0 - m_ShowBusConnectionsOfSelection: 0 ---- !u!114 &17 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12019, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_AutoRepaintOnSceneChange: 0 - m_MinSize: {x: 275, y: 50} - m_MaxSize: {x: 4000, y: 4000} - m_TitleContent: - m_Text: Inspector - m_Image: {fileID: -6905738622615590433, guid: 0000000000000000d000000000000000, - type: 0} - m_Tooltip: - m_DepthBufferBits: 0 - m_Pos: - serializedVersion: 2 - x: 996 - y: 94 - width: 284 - height: 614 - m_PersistentViewDataDictionary: {fileID: 0} - m_ScrollPosition: {x: 0, y: 0} - m_InspectorMode: 0 - m_PreviewResizer: - m_CachedPref: 100 - m_ControlHash: -371814159 - m_PrefName: Preview_InspectorPreview - m_PreviewWindow: {fileID: 0} diff --git a/Close Enough!/Library/CurrentMaximizeLayout.dwlt b/Close Enough!/Library/CurrentMaximizeLayout.dwlt deleted file mode 100644 index 96de81b..0000000 --- a/Close Enough!/Library/CurrentMaximizeLayout.dwlt +++ /dev/null @@ -1,672 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &1 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: - - {fileID: 3} - - {fileID: 7} - - {fileID: 9} - - {fileID: 12} - m_Position: - serializedVersion: 2 - x: 0 - y: 30 - width: 1280 - height: 638 - m_MinSize: {x: 913, y: 442} - m_MaxSize: {x: 22008, y: 10021} - vertical: 0 - controlID: 14950 ---- !u!114 &2 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12015, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_AutoRepaintOnSceneChange: 1 - m_MinSize: {x: 200, y: 200} - m_MaxSize: {x: 4000, y: 4000} - m_TitleContent: - m_Text: Game - m_Image: {fileID: -2087823869225018852, guid: 0000000000000000d000000000000000, - type: 0} - m_Tooltip: - m_DepthBufferBits: 32 - m_Pos: - serializedVersion: 2 - x: 0 - y: 421 - width: 420 - height: 290 - m_PersistentViewDataDictionary: {fileID: 0} - m_MaximizeOnPlay: 1 - m_Gizmos: 0 - m_Stats: 0 - m_SelectedSizes: 04000000000000000000000000000000000000000000000000000000000000000000000000000000 - m_TargetDisplay: 0 - m_ZoomArea: - m_HRangeLocked: 0 - m_VRangeLocked: 0 - m_HBaseRangeMin: -105 - m_HBaseRangeMax: 105 - m_VBaseRangeMin: -65.625 - m_VBaseRangeMax: 65.625 - m_HAllowExceedBaseRangeMin: 1 - m_HAllowExceedBaseRangeMax: 1 - m_VAllowExceedBaseRangeMin: 1 - m_VAllowExceedBaseRangeMax: 1 - m_ScaleWithWindow: 0 - m_HSlider: 0 - m_VSlider: 0 - m_IgnoreScrollWheelUntilClicked: 0 - m_EnableMouseInput: 1 - m_EnableSliderZoom: 0 - m_UniformScale: 1 - m_UpDirection: 1 - m_DrawArea: - serializedVersion: 2 - x: 0 - y: 17 - width: 420 - height: 273 - m_Scale: {x: 2, y: 2} - m_Translation: {x: 210, y: 136.5} - m_MarginLeft: 0 - m_MarginRight: 0 - m_MarginTop: 0 - m_MarginBottom: 0 - m_LastShownAreaInsideMargins: - serializedVersion: 2 - x: -105 - y: -68.25 - width: 210 - height: 136.5 - m_MinimalGUI: 1 - m_defaultScale: 1 - m_TargetTexture: {fileID: 0} - m_CurrentColorSpace: 0 - m_LastWindowPixelSize: {x: 840, y: 580} - m_ClearInEditMode: 1 - m_NoCameraWarning: 1 - m_LowResolutionForAspectRatios: 01000000000100000100 ---- !u!114 &3 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: - - {fileID: 4} - - {fileID: 6} - m_Position: - serializedVersion: 2 - x: 0 - y: 0 - width: 422 - height: 638 - m_MinSize: {x: 202, y: 442} - m_MaxSize: {x: 4002, y: 8042} - vertical: 1 - controlID: 14929 ---- !u!114 &4 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: [] - m_Position: - serializedVersion: 2 - x: 0 - y: 0 - width: 422 - height: 327 - m_MinSize: {x: 202, y: 221} - m_MaxSize: {x: 4002, y: 4021} - m_ActualView: {fileID: 5} - m_Panes: - - {fileID: 5} - m_Selected: 0 - m_LastSelected: 0 ---- !u!114 &5 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12013, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_AutoRepaintOnSceneChange: 1 - m_MinSize: {x: 200, y: 200} - m_MaxSize: {x: 4000, y: 4000} - m_TitleContent: - m_Text: Scene - m_Image: {fileID: 2318424515335265636, guid: 0000000000000000d000000000000000, - type: 0} - m_Tooltip: - m_DepthBufferBits: 32 - m_Pos: - serializedVersion: 2 - x: 0 - y: 94 - width: 420 - height: 306 - m_PersistentViewDataDictionary: {fileID: 0} - m_SceneLighting: 1 - lastFramingTime: 4160.858686923981 - m_2DMode: 1 - m_isRotationLocked: 0 - m_AudioPlay: 0 - m_Position: - m_Target: {x: -6.5519323, y: 160.20738, z: 0.33799827} - speed: 2 - m_Value: {x: -6.5519323, y: 160.20738, z: 0.33799827} - m_RenderMode: 0 - m_ValidateTrueMetals: 0 - m_SceneViewState: - showFog: 1 - showMaterialUpdate: 0 - showSkybox: 1 - showFlares: 1 - showImageEffects: 1 - showParticleSystems: 1 - grid: - xGrid: - m_Target: 0 - speed: 2 - m_Value: 0 - yGrid: - m_Target: 0 - speed: 2 - m_Value: 0 - zGrid: - m_Target: 1 - speed: 2 - m_Value: 1 - m_Rotation: - m_Target: {x: 0, y: 0, z: 0, w: 1} - speed: 2 - m_Value: {x: 0, y: 0, z: 0, w: 1} - m_Size: - m_Target: 197.5871 - speed: 2 - m_Value: 197.5871 - m_Ortho: - m_Target: 1 - speed: 2 - m_Value: 1 - m_ShowGlobalGrid: 1 - m_LastSceneViewRotation: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226} - m_LastSceneViewOrtho: 0 - m_ReplacementShader: {fileID: 0} - m_ReplacementString: - m_LastLockedObject: {fileID: 0} - m_ViewIsLockedToObject: 0 ---- !u!114 &6 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: [] - m_Position: - serializedVersion: 2 - x: 0 - y: 327 - width: 422 - height: 311 - m_MinSize: {x: 202, y: 221} - m_MaxSize: {x: 4002, y: 4021} - m_ActualView: {fileID: 2} - m_Panes: - - {fileID: 2} - m_Selected: 0 - m_LastSelected: 0 ---- !u!114 &7 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: [] - m_Position: - serializedVersion: 2 - x: 422 - y: 0 - width: 204 - height: 421 - m_MinSize: {x: 200, y: 200} - m_MaxSize: {x: 4000, y: 4000} - m_ActualView: {fileID: 8} - m_Panes: - - {fileID: 8} - m_Selected: 0 - m_LastSelected: 0 ---- !u!114 &8 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12061, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_AutoRepaintOnSceneChange: 0 - m_MinSize: {x: 200, y: 200} - m_MaxSize: {x: 4000, y: 4000} - m_TitleContent: - m_Text: Hierarchy - m_Image: {fileID: -590624980919486359, guid: 0000000000000000d000000000000000, - type: 0} - m_Tooltip: - m_DepthBufferBits: 0 - m_Pos: - serializedVersion: 2 - x: 424 - y: 94 - width: 200 - height: 400 - m_PersistentViewDataDictionary: {fileID: 0} - m_TreeViewState: - scrollPos: {x: 0, y: 0} - m_SelectedIDs: 26310000 - m_LastClickedID: 12582 - m_ExpandedIDs: 5e0bf9ff00dff9ff0a1ffaff642cfaff2e21fbff08cffbff46f3fbff1ae5ffff14ebffff00000000da2f000010300000323000007630000092300000a2300000d830000048310000 - m_RenameOverlay: - m_UserAcceptedRename: 0 - m_Name: - m_OriginalName: - m_EditFieldRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 0 - height: 0 - m_UserData: 0 - m_IsWaitingForDelay: 0 - m_IsRenaming: 0 - m_OriginalEventType: 11 - m_IsRenamingFilename: 0 - m_ClientGUIView: {fileID: 7} - m_SearchString: - m_ExpandedScenes: [] - m_CurrenRootInstanceID: 0 - m_Locked: 1 - m_CurrentSortingName: TransformSorting ---- !u!114 &9 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: [] - m_Position: - serializedVersion: 2 - x: 626 - y: 0 - width: 368 - height: 638 - m_MinSize: {x: 234, y: 271} - m_MaxSize: {x: 10004, y: 10021} - m_ActualView: {fileID: 10} - m_Panes: - - {fileID: 10} - - {fileID: 11} - m_Selected: 0 - m_LastSelected: 1 ---- !u!114 &10 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12014, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_AutoRepaintOnSceneChange: 0 - m_MinSize: {x: 230, y: 250} - m_MaxSize: {x: 10000, y: 10000} - m_TitleContent: - m_Text: Project - m_Image: {fileID: -7501376956915960154, guid: 0000000000000000d000000000000000, - type: 0} - m_Tooltip: - m_DepthBufferBits: 0 - m_Pos: - serializedVersion: 2 - x: 628 - y: 94 - width: 364 - height: 617 - m_PersistentViewDataDictionary: {fileID: 0} - m_SearchFilter: - m_NameFilter: - m_ClassNames: [] - m_AssetLabels: [] - m_AssetBundleNames: [] - m_VersionControlStates: [] - m_SoftLockControlStates: [] - m_ReferencingInstanceIDs: - m_ScenePaths: [] - m_ShowAllHits: 0 - m_SearchArea: 0 - m_Folders: - - Assets/Fonts/OpenSans - m_ViewMode: 1 - m_StartGridSize: 64 - m_LastFolders: - - Assets/Fonts/OpenSans - m_LastFoldersGridSize: -1 - m_LastProjectPath: /Users/brianfann/Projects/CloseEnough/Close Enough! - m_IsLocked: 0 - m_FolderTreeState: - scrollPos: {x: 0, y: 12} - m_SelectedIDs: c42e0000 - m_LastClickedID: 11972 - m_ExpandedIDs: 00000000b22a0000c02a0000c62b0000ee2b0000c62c0000a62d00002a2e0000482e00004a2e00004e2e000000ca9a3bffffff7f - m_RenameOverlay: - m_UserAcceptedRename: 0 - m_Name: - m_OriginalName: - m_EditFieldRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 0 - height: 0 - m_UserData: 0 - m_IsWaitingForDelay: 0 - m_IsRenaming: 0 - m_OriginalEventType: 11 - m_IsRenamingFilename: 1 - m_ClientGUIView: {fileID: 9} - m_SearchString: - m_CreateAssetUtility: - m_EndAction: {fileID: 0} - m_InstanceID: 0 - m_Path: - m_Icon: {fileID: 0} - m_ResourceFile: - m_AssetTreeState: - scrollPos: {x: 0, y: 0} - m_SelectedIDs: - m_LastClickedID: 0 - m_ExpandedIDs: 00000000b22a0000c02a0000c62b0000ee2b0000c62c0000a62d00002a2e0000482e00004a2e00004e2e000000ca9a3bffffff7f - m_RenameOverlay: - m_UserAcceptedRename: 0 - m_Name: - m_OriginalName: - m_EditFieldRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 0 - height: 0 - m_UserData: 0 - m_IsWaitingForDelay: 0 - m_IsRenaming: 0 - m_OriginalEventType: 11 - m_IsRenamingFilename: 1 - m_ClientGUIView: {fileID: 0} - m_SearchString: - m_CreateAssetUtility: - m_EndAction: {fileID: 0} - m_InstanceID: 0 - m_Path: - m_Icon: {fileID: 0} - m_ResourceFile: - m_ListAreaState: - m_SelectedInstanceIDs: 26310000 - m_LastClickedInstanceID: 12582 - m_HadKeyboardFocusLastEvent: 0 - m_ExpandedInstanceIDs: 00000000 - m_RenameOverlay: - m_UserAcceptedRename: 0 - m_Name: - m_OriginalName: - m_EditFieldRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 0 - height: 0 - m_UserData: 0 - m_IsWaitingForDelay: 0 - m_IsRenaming: 0 - m_OriginalEventType: 11 - m_IsRenamingFilename: 1 - m_ClientGUIView: {fileID: 9} - m_CreateAssetUtility: - m_EndAction: {fileID: 0} - m_InstanceID: 0 - m_Path: - m_Icon: {fileID: 0} - m_ResourceFile: - m_NewAssetIndexInList: -1 - m_ScrollPosition: {x: 0, y: 495} - m_GridSize: 64 - m_DirectoriesAreaWidth: 172 ---- !u!114 &11 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12373, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_AutoRepaintOnSceneChange: 0 - m_MinSize: {x: 100, y: 100} - m_MaxSize: {x: 4000, y: 4000} - m_TitleContent: - m_Text: Audio Mixer - m_Image: {fileID: 5436946869657106676, guid: 0000000000000000d000000000000000, - type: 0} - m_Tooltip: - m_DepthBufferBits: 0 - m_Pos: - serializedVersion: 2 - x: 836 - y: 92 - width: 249 - height: 614 - m_PersistentViewDataDictionary: {fileID: 0} - m_MixersTreeState: - scrollPos: {x: 0, y: 0} - m_SelectedIDs: - m_LastClickedID: -346884 - m_ExpandedIDs: 12eb343c - m_RenameOverlay: - m_UserAcceptedRename: 0 - m_Name: - m_OriginalName: - m_EditFieldRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 0 - height: 0 - m_UserData: 0 - m_IsWaitingForDelay: 0 - m_IsRenaming: 0 - m_OriginalEventType: 11 - m_IsRenamingFilename: 0 - m_ClientGUIView: {fileID: 0} - m_SearchString: - m_CreateAssetUtility: - m_EndAction: {fileID: 0} - m_InstanceID: 0 - m_Path: - m_Icon: {fileID: 0} - m_ResourceFile: - m_LayoutStripsOnTop: - m_VerticalSplitter: - ID: 0 - splitterInitialOffset: 0 - currentActiveSplitter: -1 - realSizes: 4100000023000000 - relativeSizes: - - 0.65 - - 0.35000002 - minSizes: 5500000069000000 - maxSizes: 0000000000000000 - lastTotalSize: 0 - splitSize: 6 - xOffset: 0 - m_HorizontalSplitter: - ID: 0 - splitterInitialOffset: 0 - currentActiveSplitter: -1 - realSizes: 3c0000003c0000003c0000003c000000 - relativeSizes: - - 0.25 - - 0.25 - - 0.25 - - 0.25 - minSizes: 55000000550000005500000055000000 - maxSizes: 00000000000000000000000000000000 - lastTotalSize: 0 - splitSize: 6 - xOffset: 0 - m_LayoutStripsOnRight: - m_VerticalSplitter: - ID: 0 - splitterInitialOffset: 0 - currentActiveSplitter: -1 - realSizes: 3c0000003c0000003c0000003c000000 - relativeSizes: - - 0.25 - - 0.25 - - 0.25 - - 0.25 - minSizes: 64000000550000005500000055000000 - maxSizes: 00000000000000000000000000000000 - lastTotalSize: 0 - splitSize: 6 - xOffset: 0 - m_HorizontalSplitter: - ID: 95 - splitterInitialOffset: 0 - currentActiveSplitter: -1 - realSizes: a0000000a0000000 - relativeSizes: - - 0.3 - - 0.7 - minSizes: a0000000a0000000 - maxSizes: 0000000000000000 - lastTotalSize: 250 - splitSize: 6 - xOffset: -1 - m_SectionOrder: 00000000030000000100000002000000 - m_LayoutMode: 1 - m_SortGroupsAlphabetically: 0 - m_ShowReferencedBuses: 1 - m_ShowBusConnections: 0 - m_ShowBusConnectionsOfSelection: 0 ---- !u!114 &12 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_Children: [] - m_Position: - serializedVersion: 2 - x: 994 - y: 0 - width: 286 - height: 638 - m_MinSize: {x: 277, y: 71} - m_MaxSize: {x: 4002, y: 4021} - m_ActualView: {fileID: 12} - m_Panes: - - {fileID: 13} - m_Selected: 0 - m_LastSelected: 0 ---- !u!114 &13 -MonoBehaviour: - m_ObjectHideFlags: 52 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 1 - m_Script: {fileID: 12019, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_AutoRepaintOnSceneChange: 0 - m_MinSize: {x: 275, y: 50} - m_MaxSize: {x: 4000, y: 4000} - m_TitleContent: - m_Text: Inspector - m_Image: {fileID: -6905738622615590433, guid: 0000000000000000d000000000000000, - type: 0} - m_Tooltip: - m_DepthBufferBits: 0 - m_Pos: - serializedVersion: 2 - x: 996 - y: 94 - width: 284 - height: 617 - m_PersistentViewDataDictionary: {fileID: 0} - m_ScrollPosition: {x: 0, y: 0} - m_InspectorMode: 0 - m_PreviewResizer: - m_CachedPref: 100 - m_ControlHash: -371814159 - m_PrefName: Preview_InspectorPreview - m_PreviewWindow: {fileID: 0} diff --git a/Close Enough!/Library/EditorUserBuildSettings.asset b/Close Enough!/Library/EditorUserBuildSettings.asset deleted file mode 100644 index da67890..0000000 Binary files a/Close Enough!/Library/EditorUserBuildSettings.asset and /dev/null differ diff --git a/Close Enough!/Library/EditorUserSettings.asset b/Close Enough!/Library/EditorUserSettings.asset deleted file mode 100644 index 13327b5..0000000 Binary files a/Close Enough!/Library/EditorUserSettings.asset and /dev/null differ diff --git a/Close Enough!/Library/InspectorExpandedItems.asset b/Close Enough!/Library/InspectorExpandedItems.asset deleted file mode 100644 index 16ab074..0000000 Binary files a/Close Enough!/Library/InspectorExpandedItems.asset and /dev/null differ diff --git a/Close Enough!/Library/LastBuild.buildreport b/Close Enough!/Library/LastBuild.buildreport deleted file mode 100644 index 48d15df..0000000 Binary files a/Close Enough!/Library/LastBuild.buildreport and /dev/null differ diff --git a/Close Enough!/Library/LastSceneManagerSetup.txt b/Close Enough!/Library/LastSceneManagerSetup.txt deleted file mode 100644 index 5c8d6b0..0000000 --- a/Close Enough!/Library/LastSceneManagerSetup.txt +++ /dev/null @@ -1,4 +0,0 @@ -sceneSetups: -- path: Assets/Scenes/Title Screen.unity - isLoaded: 1 - isActive: 1 diff --git a/Close Enough!/Library/LibraryFormatVersion.txt b/Close Enough!/Library/LibraryFormatVersion.txt deleted file mode 100644 index 6185f09..0000000 --- a/Close Enough!/Library/LibraryFormatVersion.txt +++ /dev/null @@ -1,2 +0,0 @@ -unityRebuildLibraryVersion: 11 -unityForwardCompatibleVersion: 40 diff --git a/Close Enough!/Library/MonoManager.asset b/Close Enough!/Library/MonoManager.asset deleted file mode 100644 index 5ba8a9f..0000000 Binary files a/Close Enough!/Library/MonoManager.asset and /dev/null differ diff --git a/Close Enough!/Library/ProjectSettings.asset b/Close Enough!/Library/ProjectSettings.asset deleted file mode 100644 index fc0b301..0000000 --- a/Close Enough!/Library/ProjectSettings.asset +++ /dev/null @@ -1,640 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!129 &1 -PlayerSettings: - m_ObjectHideFlags: 0 - serializedVersion: 14 - productGUID: 49cbe0d7845f54f64a104927bd6c1594 - AndroidProfiler: 0 - AndroidFilterTouchesWhenObscured: 0 - defaultScreenOrientation: 4 - targetDevice: 2 - useOnDemandResources: 0 - accelerometerFrequency: 60 - companyName: DefaultCompany - productName: Close Enough! - defaultCursor: {fileID: 0} - cursorHotspot: {x: 0, y: 0} - m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} - m_ShowUnitySplashScreen: 1 - m_ShowUnitySplashLogo: 1 - m_SplashScreenOverlayOpacity: 1 - m_SplashScreenAnimation: 1 - m_SplashScreenLogoStyle: 1 - m_SplashScreenDrawMode: 0 - m_SplashScreenBackgroundAnimationZoom: 1 - m_SplashScreenLogoAnimationZoom: 1 - m_SplashScreenBackgroundLandscapeAspect: 1 - m_SplashScreenBackgroundPortraitAspect: 1 - m_SplashScreenBackgroundLandscapeUvs: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - m_SplashScreenBackgroundPortraitUvs: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - m_SplashScreenLogos: [] - m_VirtualRealitySplashScreen: {fileID: 0} - m_HolographicTrackingLossScreen: {fileID: 0} - defaultScreenWidth: 1024 - defaultScreenHeight: 768 - defaultScreenWidthWeb: 960 - defaultScreenHeightWeb: 600 - m_StereoRenderingPath: 0 - m_ActiveColorSpace: 0 - m_MTRendering: 1 - m_StackTraceTypes: 010000000100000001000000010000000100000001000000 - iosShowActivityIndicatorOnLoading: -1 - androidShowActivityIndicatorOnLoading: -1 - tizenShowActivityIndicatorOnLoading: -1 - iosAppInBackgroundBehavior: 0 - displayResolutionDialog: 1 - iosAllowHTTPDownload: 1 - allowedAutorotateToPortrait: 1 - allowedAutorotateToPortraitUpsideDown: 1 - allowedAutorotateToLandscapeRight: 1 - allowedAutorotateToLandscapeLeft: 1 - useOSAutorotation: 1 - use32BitDisplayBuffer: 1 - preserveFramebufferAlpha: 0 - disableDepthAndStencilBuffers: 0 - androidBlitType: 0 - defaultIsFullScreen: 1 - defaultIsNativeResolution: 1 - macRetinaSupport: 1 - runInBackground: 0 - captureSingleScreen: 0 - muteOtherAudioSources: 0 - Prepare IOS For Recording: 0 - Force IOS Speakers When Recording: 0 - deferSystemGesturesMode: 0 - hideHomeButton: 0 - submitAnalytics: 1 - usePlayerLog: 1 - bakeCollisionMeshes: 0 - forceSingleInstance: 0 - resizableWindow: 0 - useMacAppStoreValidation: 0 - macAppStoreCategory: public.app-category.games - gpuSkinning: 0 - graphicsJobs: 0 - xboxPIXTextureCapture: 0 - xboxEnableAvatar: 0 - xboxEnableKinect: 0 - xboxEnableKinectAutoTracking: 0 - xboxEnableFitness: 0 - visibleInBackground: 1 - allowFullscreenSwitch: 1 - graphicsJobMode: 0 - macFullscreenMode: 2 - d3d11FullscreenMode: 1 - xboxSpeechDB: 0 - xboxEnableHeadOrientation: 0 - xboxEnableGuest: 0 - xboxEnablePIXSampling: 0 - metalFramebufferOnly: 0 - n3dsDisableStereoscopicView: 0 - n3dsEnableSharedListOpt: 1 - n3dsEnableVSync: 0 - xboxOneResolution: 0 - xboxOneSResolution: 0 - xboxOneXResolution: 3 - xboxOneMonoLoggingLevel: 0 - xboxOneLoggingLevel: 1 - xboxOneDisableEsram: 0 - xboxOnePresentImmediateThreshold: 0 - videoMemoryForVertexBuffers: 0 - psp2PowerMode: 0 - psp2AcquireBGM: 1 - wiiUTVResolution: 0 - wiiUGamePadMSAA: 1 - wiiUSupportsNunchuk: 0 - wiiUSupportsClassicController: 0 - wiiUSupportsBalanceBoard: 0 - wiiUSupportsMotionPlus: 0 - wiiUSupportsProController: 0 - wiiUAllowScreenCapture: 1 - wiiUControllerCount: 0 - m_SupportedAspectRatios: - 4:3: 1 - 5:4: 1 - 16:10: 1 - 16:9: 1 - Others: 1 - bundleVersion: 1.0 - preloadedAssets: [] - metroInputSource: 0 - wsaTransparentSwapchain: 0 - m_HolographicPauseOnTrackingLoss: 1 - xboxOneDisableKinectGpuReservation: 0 - xboxOneEnable7thCore: 0 - vrSettings: - cardboard: - depthFormat: 0 - enableTransitionView: 0 - daydream: - depthFormat: 0 - useSustainedPerformanceMode: 0 - enableVideoLayer: 0 - useProtectedVideoMemory: 0 - minimumSupportedHeadTracking: 0 - maximumSupportedHeadTracking: 1 - hololens: - depthFormat: 1 - depthBufferSharingEnabled: 0 - oculus: - sharedDepthBuffer: 0 - dashSupport: 0 - protectGraphicsMemory: 0 - useHDRDisplay: 0 - m_ColorGamuts: 00000000 - targetPixelDensity: 30 - resolutionScalingMode: 0 - androidSupportedAspectRatio: 1 - androidMaxAspectRatio: 2.1 - applicationIdentifier: {} - buildNumber: {} - AndroidBundleVersionCode: 1 - AndroidMinSdkVersion: 16 - AndroidTargetSdkVersion: 0 - AndroidPreferredInstallLocation: 1 - aotOptions: - stripEngineCode: 1 - iPhoneStrippingLevel: 0 - iPhoneScriptCallOptimization: 0 - ForceInternetPermission: 0 - ForceSDCardPermission: 0 - CreateWallpaper: 0 - APKExpansionFiles: 0 - keepLoadedShadersAlive: 0 - StripUnusedMeshComponents: 0 - VertexChannelCompressionMask: - serializedVersion: 2 - m_Bits: 238 - iPhoneSdkVersion: 988 - iOSTargetOSVersionString: 7.0 - tvOSSdkVersion: 0 - tvOSRequireExtendedGameController: 0 - tvOSTargetOSVersionString: 9.0 - uIPrerenderedIcon: 0 - uIRequiresPersistentWiFi: 0 - uIRequiresFullScreen: 1 - uIStatusBarHidden: 1 - uIExitOnSuspend: 0 - uIStatusBarStyle: 0 - iPhoneSplashScreen: {fileID: 0} - iPhoneHighResSplashScreen: {fileID: 0} - iPhoneTallHighResSplashScreen: {fileID: 0} - iPhone47inSplashScreen: {fileID: 0} - iPhone55inPortraitSplashScreen: {fileID: 0} - iPhone55inLandscapeSplashScreen: {fileID: 0} - iPhone58inPortraitSplashScreen: {fileID: 0} - iPhone58inLandscapeSplashScreen: {fileID: 0} - iPadPortraitSplashScreen: {fileID: 0} - iPadHighResPortraitSplashScreen: {fileID: 0} - iPadLandscapeSplashScreen: {fileID: 0} - iPadHighResLandscapeSplashScreen: {fileID: 0} - appleTVSplashScreen: {fileID: 0} - appleTVSplashScreen2x: {fileID: 0} - tvOSSmallIconLayers: [] - tvOSSmallIconLayers2x: [] - tvOSLargeIconLayers: [] - tvOSTopShelfImageLayers: [] - tvOSTopShelfImageLayers2x: [] - tvOSTopShelfImageWideLayers: [] - tvOSTopShelfImageWideLayers2x: [] - iOSLaunchScreenType: 0 - iOSLaunchScreenPortrait: {fileID: 0} - iOSLaunchScreenLandscape: {fileID: 0} - iOSLaunchScreenBackgroundColor: - serializedVersion: 2 - rgba: 0 - iOSLaunchScreenFillPct: 100 - iOSLaunchScreenSize: 100 - iOSLaunchScreenCustomXibPath: - iOSLaunchScreeniPadType: 0 - iOSLaunchScreeniPadImage: {fileID: 0} - iOSLaunchScreeniPadBackgroundColor: - serializedVersion: 2 - rgba: 0 - iOSLaunchScreeniPadFillPct: 100 - iOSLaunchScreeniPadSize: 100 - iOSLaunchScreeniPadCustomXibPath: - iOSUseLaunchScreenStoryboard: 0 - iOSLaunchScreenCustomStoryboardPath: - iOSDeviceRequirements: [] - iOSURLSchemes: [] - iOSBackgroundModes: 0 - iOSMetalForceHardShadows: 0 - metalEditorSupport: 0 - metalAPIValidation: 1 - iOSRenderExtraFrameOnPause: 0 - appleDeveloperTeamID: - iOSManualSigningProvisioningProfileID: - tvOSManualSigningProvisioningProfileID: - appleEnableAutomaticSigning: 0 - clonedFromGUID: 00000000000000000000000000000000 - AndroidTargetDevice: 0 - AndroidSplashScreenScale: 0 - androidSplashScreen: {fileID: 0} - AndroidKeystoreName: - AndroidKeyaliasName: - AndroidTVCompatibility: 1 - AndroidIsGame: 1 - AndroidEnableTango: 0 - androidEnableBanner: 1 - androidUseLowAccuracyLocation: 0 - m_AndroidBanners: - - width: 320 - height: 180 - banner: {fileID: 0} - androidGamepadSupportLevel: 0 - resolutionDialogBanner: {fileID: 0} - m_BuildTargetIcons: [] - m_BuildTargetBatching: [] - m_BuildTargetGraphicsAPIs: [] - m_BuildTargetVRSettings: [] - m_BuildTargetEnableVuforiaSettings: [] - openGLRequireES31: 0 - openGLRequireES31AEP: 0 - m_TemplateCustomTags: {} - mobileMTRendering: - Android: 1 - iPhone: 1 - tvOS: 1 - m_BuildTargetGroupLightmapEncodingQuality: [] - wiiUTitleID: 0005000011000000 - wiiUGroupID: 00010000 - wiiUCommonSaveSize: 4096 - wiiUAccountSaveSize: 2048 - wiiUOlvAccessKey: 0 - wiiUTinCode: 0 - wiiUJoinGameId: 0 - wiiUJoinGameModeMask: 0000000000000000 - wiiUCommonBossSize: 0 - wiiUAccountBossSize: 0 - wiiUAddOnUniqueIDs: [] - wiiUMainThreadStackSize: 3072 - wiiULoaderThreadStackSize: 1024 - wiiUSystemHeapSize: 128 - wiiUTVStartupScreen: {fileID: 0} - wiiUGamePadStartupScreen: {fileID: 0} - wiiUDrcBufferDisabled: 0 - wiiUProfilerLibPath: - playModeTestRunnerEnabled: 0 - actionOnDotNetUnhandledException: 1 - enableInternalProfiler: 0 - logObjCUncaughtExceptions: 1 - enableCrashReportAPI: 0 - cameraUsageDescription: - locationUsageDescription: - microphoneUsageDescription: - switchNetLibKey: - switchSocketMemoryPoolSize: 6144 - switchSocketAllocatorPoolSize: 128 - switchSocketConcurrencyLimit: 14 - switchScreenResolutionBehavior: 2 - switchUseCPUProfiler: 0 - switchApplicationID: 0x01004b9000490000 - switchNSODependencies: - switchTitleNames_0: - switchTitleNames_1: - switchTitleNames_2: - switchTitleNames_3: - switchTitleNames_4: - switchTitleNames_5: - switchTitleNames_6: - switchTitleNames_7: - switchTitleNames_8: - switchTitleNames_9: - switchTitleNames_10: - switchTitleNames_11: - switchTitleNames_12: - switchTitleNames_13: - switchTitleNames_14: - switchPublisherNames_0: - switchPublisherNames_1: - switchPublisherNames_2: - switchPublisherNames_3: - switchPublisherNames_4: - switchPublisherNames_5: - switchPublisherNames_6: - switchPublisherNames_7: - switchPublisherNames_8: - switchPublisherNames_9: - switchPublisherNames_10: - switchPublisherNames_11: - switchPublisherNames_12: - switchPublisherNames_13: - switchPublisherNames_14: - switchIcons_0: {fileID: 0} - switchIcons_1: {fileID: 0} - switchIcons_2: {fileID: 0} - switchIcons_3: {fileID: 0} - switchIcons_4: {fileID: 0} - switchIcons_5: {fileID: 0} - switchIcons_6: {fileID: 0} - switchIcons_7: {fileID: 0} - switchIcons_8: {fileID: 0} - switchIcons_9: {fileID: 0} - switchIcons_10: {fileID: 0} - switchIcons_11: {fileID: 0} - switchIcons_12: {fileID: 0} - switchIcons_13: {fileID: 0} - switchIcons_14: {fileID: 0} - switchSmallIcons_0: {fileID: 0} - switchSmallIcons_1: {fileID: 0} - switchSmallIcons_2: {fileID: 0} - switchSmallIcons_3: {fileID: 0} - switchSmallIcons_4: {fileID: 0} - switchSmallIcons_5: {fileID: 0} - switchSmallIcons_6: {fileID: 0} - switchSmallIcons_7: {fileID: 0} - switchSmallIcons_8: {fileID: 0} - switchSmallIcons_9: {fileID: 0} - switchSmallIcons_10: {fileID: 0} - switchSmallIcons_11: {fileID: 0} - switchSmallIcons_12: {fileID: 0} - switchSmallIcons_13: {fileID: 0} - switchSmallIcons_14: {fileID: 0} - switchManualHTML: - switchAccessibleURLs: - switchLegalInformation: - switchMainThreadStackSize: 1048576 - switchPresenceGroupId: - switchLogoHandling: 0 - switchReleaseVersion: 0 - switchDisplayVersion: 1.0.0 - switchStartupUserAccount: 0 - switchTouchScreenUsage: 0 - switchSupportedLanguagesMask: 0 - switchLogoType: 0 - switchApplicationErrorCodeCategory: - switchUserAccountSaveDataSize: 0 - switchUserAccountSaveDataJournalSize: 0 - switchApplicationAttribute: 0 - switchCardSpecSize: -1 - switchCardSpecClock: -1 - switchRatingsMask: 0 - switchRatingsInt_0: 0 - switchRatingsInt_1: 0 - switchRatingsInt_2: 0 - switchRatingsInt_3: 0 - switchRatingsInt_4: 0 - switchRatingsInt_5: 0 - switchRatingsInt_6: 0 - switchRatingsInt_7: 0 - switchRatingsInt_8: 0 - switchRatingsInt_9: 0 - switchRatingsInt_10: 0 - switchRatingsInt_11: 0 - switchLocalCommunicationIds_0: - switchLocalCommunicationIds_1: - switchLocalCommunicationIds_2: - switchLocalCommunicationIds_3: - switchLocalCommunicationIds_4: - switchLocalCommunicationIds_5: - switchLocalCommunicationIds_6: - switchLocalCommunicationIds_7: - switchParentalControl: 0 - switchAllowsScreenshot: 1 - switchAllowsVideoCapturing: 1 - switchAllowsRuntimeAddOnContentInstall: 0 - switchDataLossConfirmation: 0 - switchSupportedNpadStyles: 3 - switchSocketConfigEnabled: 0 - switchTcpInitialSendBufferSize: 32 - switchTcpInitialReceiveBufferSize: 64 - switchTcpAutoSendBufferSizeMax: 256 - switchTcpAutoReceiveBufferSizeMax: 256 - switchUdpSendBufferSize: 9 - switchUdpReceiveBufferSize: 42 - switchSocketBufferEfficiency: 4 - switchSocketInitializeEnabled: 1 - switchNetworkInterfaceManagerInitializeEnabled: 1 - switchPlayerConnectionEnabled: 1 - ps4NPAgeRating: 12 - ps4NPTitleSecret: - ps4NPTrophyPackPath: - ps4ParentalLevel: 11 - ps4ContentID: ED1633-NPXX51362_00-0000000000000000 - ps4Category: 0 - ps4MasterVersion: 01.00 - ps4AppVersion: 01.00 - ps4AppType: 0 - ps4ParamSfxPath: - ps4VideoOutPixelFormat: 0 - ps4VideoOutInitialWidth: 1920 - ps4VideoOutBaseModeInitialWidth: 1920 - ps4VideoOutReprojectionRate: 60 - ps4PronunciationXMLPath: - ps4PronunciationSIGPath: - ps4BackgroundImagePath: - ps4StartupImagePath: - ps4StartupImagesFolder: - ps4IconImagesFolder: - ps4SaveDataImagePath: - ps4SdkOverride: - ps4BGMPath: - ps4ShareFilePath: - ps4ShareOverlayImagePath: - ps4PrivacyGuardImagePath: - ps4NPtitleDatPath: - ps4RemotePlayKeyAssignment: -1 - ps4RemotePlayKeyMappingDir: - ps4PlayTogetherPlayerCount: 0 - ps4EnterButtonAssignment: 1 - ps4ApplicationParam1: 0 - ps4ApplicationParam2: 0 - ps4ApplicationParam3: 0 - ps4ApplicationParam4: 0 - ps4DownloadDataSize: 0 - ps4GarlicHeapSize: 2048 - ps4ProGarlicHeapSize: 2560 - ps4Passcode: 9nsQzldVI5ZuGXbEWRK5RhRXdCdG5nG5 - ps4pnSessions: 1 - ps4pnPresence: 1 - ps4pnFriends: 1 - ps4pnGameCustomData: 1 - playerPrefsSupport: 0 - restrictedAudioUsageRights: 0 - ps4UseResolutionFallback: 0 - ps4ReprojectionSupport: 0 - ps4UseAudio3dBackend: 0 - ps4SocialScreenEnabled: 0 - ps4ScriptOptimizationLevel: 0 - ps4Audio3dVirtualSpeakerCount: 14 - ps4attribCpuUsage: 0 - ps4PatchPkgPath: - ps4PatchLatestPkgPath: - ps4PatchChangeinfoPath: - ps4PatchDayOne: 0 - ps4attribUserManagement: 0 - ps4attribMoveSupport: 0 - ps4attrib3DSupport: 0 - ps4attribShareSupport: 0 - ps4attribExclusiveVR: 0 - ps4disableAutoHideSplash: 0 - ps4videoRecordingFeaturesUsed: 0 - ps4contentSearchFeaturesUsed: 0 - ps4attribEyeToEyeDistanceSettingVR: 0 - ps4IncludedModules: [] - monoEnv: - psp2Splashimage: {fileID: 0} - psp2NPTrophyPackPath: - psp2NPSupportGBMorGJP: 0 - psp2NPAgeRating: 12 - psp2NPTitleDatPath: - psp2NPCommsID: - psp2NPCommunicationsID: - psp2NPCommsPassphrase: - psp2NPCommsSig: - psp2ParamSfxPath: - psp2ManualPath: - psp2LiveAreaGatePath: - psp2LiveAreaBackroundPath: - psp2LiveAreaPath: - psp2LiveAreaTrialPath: - psp2PatchChangeInfoPath: - psp2PatchOriginalPackage: - psp2PackagePassword: azdNMK66MuCV6GXi5xr84P2R391UXaLH - psp2KeystoneFile: - psp2MemoryExpansionMode: 0 - psp2DRMType: 0 - psp2StorageType: 0 - psp2MediaCapacity: 0 - psp2DLCConfigPath: - psp2ThumbnailPath: - psp2BackgroundPath: - psp2SoundPath: - psp2TrophyCommId: - psp2TrophyPackagePath: - psp2PackagedResourcesPath: - psp2SaveDataQuota: 10240 - psp2ParentalLevel: 1 - psp2ShortTitle: Not Set - psp2ContentID: IV0000-ABCD12345_00-0123456789ABCDEF - psp2Category: 0 - psp2MasterVersion: 01.00 - psp2AppVersion: 01.00 - psp2TVBootMode: 0 - psp2EnterButtonAssignment: 2 - psp2TVDisableEmu: 0 - psp2AllowTwitterDialog: 1 - psp2Upgradable: 0 - psp2HealthWarning: 0 - psp2UseLibLocation: 0 - psp2InfoBarOnStartup: 0 - psp2InfoBarColor: 0 - psp2ScriptOptimizationLevel: 0 - psmSplashimage: {fileID: 0} - splashScreenBackgroundSourceLandscape: {fileID: 0} - splashScreenBackgroundSourcePortrait: {fileID: 0} - spritePackerPolicy: - webGLMemorySize: 256 - webGLExceptionSupport: 1 - webGLNameFilesAsHashes: 0 - webGLDataCaching: 0 - webGLDebugSymbols: 0 - webGLEmscriptenArgs: - webGLModulesDirectory: - webGLTemplate: APPLICATION:Default - webGLAnalyzeBuildSize: 0 - webGLUseEmbeddedResources: 0 - webGLUseWasm: 0 - webGLCompressionFormat: 1 - scriptingDefineSymbols: {} - platformArchitecture: {} - scriptingBackend: {} - incrementalIl2cppBuild: {} - additionalIl2CppArgs: - scriptingRuntimeVersion: 0 - apiCompatibilityLevelPerPlatform: {} - m_RenderingPath: 1 - m_MobileRenderingPath: 1 - metroPackageName: Close Enough! - metroPackageVersion: - metroCertificatePath: - metroCertificatePassword: - metroCertificateSubject: - metroCertificateIssuer: - metroCertificateNotAfter: 0000000000000000 - metroApplicationDescription: Close Enough! - wsaImages: {} - metroTileShortName: - metroCommandLineArgsFile: - metroTileShowName: 0 - metroMediumTileShowName: 0 - metroLargeTileShowName: 0 - metroWideTileShowName: 0 - metroDefaultTileSize: 1 - metroTileForegroundText: 2 - metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} - metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, - a: 1} - metroSplashScreenUseBackgroundColor: 0 - platformCapabilities: {} - metroFTAName: - metroFTAFileTypes: [] - metroProtocolName: - metroCompilationOverrides: 1 - tizenProductDescription: - tizenProductURL: - tizenSigningProfileName: - tizenGPSPermissions: 0 - tizenMicrophonePermissions: 0 - tizenDeploymentTarget: - tizenDeploymentTargetType: -1 - tizenMinOSVersion: 1 - n3dsUseExtSaveData: 0 - n3dsCompressStaticMem: 1 - n3dsExtSaveDataNumber: 0x12345 - n3dsStackSize: 131072 - n3dsTargetPlatform: 2 - n3dsRegion: 7 - n3dsMediaSize: 0 - n3dsLogoStyle: 3 - n3dsTitle: GameName - n3dsProductCode: - n3dsApplicationId: 0xFF3FF - XboxOneProductId: - XboxOneUpdateKey: - XboxOneSandboxId: - XboxOneContentId: - XboxOneTitleId: - XboxOneSCId: - XboxOneGameOsOverridePath: - XboxOnePackagingOverridePath: - XboxOneAppManifestOverridePath: - XboxOnePackageEncryption: 0 - XboxOnePackageUpdateGranularity: 2 - XboxOneDescription: - XboxOneLanguage: - - enus - XboxOneCapability: [] - XboxOneGameRating: {} - XboxOneIsContentPackage: 0 - XboxOneEnableGPUVariability: 0 - XboxOneSockets: {} - XboxOneSplashScreen: {fileID: 0} - XboxOneAllowedProductIds: [] - XboxOnePersistentLocalStorageSize: 0 - xboxOneScriptCompiler: 0 - vrEditorSettings: - daydream: - daydreamIconForeground: {fileID: 0} - daydreamIconBackground: {fileID: 0} - cloudServicesEnabled: {} - facebookSdkVersion: 7.9.4 - apiCompatibilityLevel: 2 - cloudProjectId: - projectName: - organizationId: - cloudEnabled: 0 - enableNativePlatformBackendsForNewInputSystem: 0 - disableOldInputManagerSupport: 0 diff --git a/Close Enough!/Library/ScriptAssemblies/Assembly-CSharp.dll b/Close Enough!/Library/ScriptAssemblies/Assembly-CSharp.dll deleted file mode 100755 index 603dc30..0000000 Binary files a/Close Enough!/Library/ScriptAssemblies/Assembly-CSharp.dll and /dev/null differ diff --git a/Close Enough!/Library/ScriptAssemblies/Assembly-CSharp.dll.mdb b/Close Enough!/Library/ScriptAssemblies/Assembly-CSharp.dll.mdb deleted file mode 100644 index 4645746..0000000 Binary files a/Close Enough!/Library/ScriptAssemblies/Assembly-CSharp.dll.mdb and /dev/null differ diff --git a/Close Enough!/Library/ScriptAssemblies/BuiltinAssemblies.stamp b/Close Enough!/Library/ScriptAssemblies/BuiltinAssemblies.stamp deleted file mode 100644 index f385a2c..0000000 --- a/Close Enough!/Library/ScriptAssemblies/BuiltinAssemblies.stamp +++ /dev/null @@ -1,2 +0,0 @@ -0000.5a6f802e.0000 -0000.5a6f94e2.0000 \ No newline at end of file diff --git a/Close Enough!/Library/ScriptMapper b/Close Enough!/Library/ScriptMapper deleted file mode 100644 index 96b9f92..0000000 Binary files a/Close Enough!/Library/ScriptMapper and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache.db b/Close Enough!/Library/ShaderCache.db deleted file mode 100644 index 93f0bb9..0000000 Binary files a/Close Enough!/Library/ShaderCache.db and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/0/08cea40e022618f56c7424a049c5d78e.bin b/Close Enough!/Library/ShaderCache/0/08cea40e022618f56c7424a049c5d78e.bin deleted file mode 100644 index 2759df0..0000000 Binary files a/Close Enough!/Library/ShaderCache/0/08cea40e022618f56c7424a049c5d78e.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/1/1081a244abfe2c53d6837e1d430fd82b.bin b/Close Enough!/Library/ShaderCache/1/1081a244abfe2c53d6837e1d430fd82b.bin deleted file mode 100644 index ea50a89..0000000 Binary files a/Close Enough!/Library/ShaderCache/1/1081a244abfe2c53d6837e1d430fd82b.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/1/14fdf68aebd7c7221f849f56a731febc.bin b/Close Enough!/Library/ShaderCache/1/14fdf68aebd7c7221f849f56a731febc.bin deleted file mode 100644 index 2759df0..0000000 Binary files a/Close Enough!/Library/ShaderCache/1/14fdf68aebd7c7221f849f56a731febc.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/1/1967d4786df598e4e151ab0faf325da7.bin b/Close Enough!/Library/ShaderCache/1/1967d4786df598e4e151ab0faf325da7.bin deleted file mode 100644 index c13935f..0000000 Binary files a/Close Enough!/Library/ShaderCache/1/1967d4786df598e4e151ab0faf325da7.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/1/1b40b71ee6c8ccea9c41482ef5bb21a9.bin b/Close Enough!/Library/ShaderCache/1/1b40b71ee6c8ccea9c41482ef5bb21a9.bin deleted file mode 100644 index 2759df0..0000000 Binary files a/Close Enough!/Library/ShaderCache/1/1b40b71ee6c8ccea9c41482ef5bb21a9.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/1/1d99b698aae2db8f766251029d7ba1f8.bin b/Close Enough!/Library/ShaderCache/1/1d99b698aae2db8f766251029d7ba1f8.bin deleted file mode 100644 index aaf4044..0000000 Binary files a/Close Enough!/Library/ShaderCache/1/1d99b698aae2db8f766251029d7ba1f8.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/1/1efc6252e9474ddb295e0995319cfadd.bin b/Close Enough!/Library/ShaderCache/1/1efc6252e9474ddb295e0995319cfadd.bin deleted file mode 100644 index f283220..0000000 Binary files a/Close Enough!/Library/ShaderCache/1/1efc6252e9474ddb295e0995319cfadd.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/2/217d1c242781b66d54e3df3a58fbe548.bin b/Close Enough!/Library/ShaderCache/2/217d1c242781b66d54e3df3a58fbe548.bin deleted file mode 100644 index 2759df0..0000000 Binary files a/Close Enough!/Library/ShaderCache/2/217d1c242781b66d54e3df3a58fbe548.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/2/2359af39d5886d85ef23b0f91d68a392.bin b/Close Enough!/Library/ShaderCache/2/2359af39d5886d85ef23b0f91d68a392.bin deleted file mode 100644 index 167d36d..0000000 Binary files a/Close Enough!/Library/ShaderCache/2/2359af39d5886d85ef23b0f91d68a392.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/2/2506cc1744df364cfed92d3305f307dc.bin b/Close Enough!/Library/ShaderCache/2/2506cc1744df364cfed92d3305f307dc.bin deleted file mode 100644 index aaf4044..0000000 Binary files a/Close Enough!/Library/ShaderCache/2/2506cc1744df364cfed92d3305f307dc.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/3/303cafc81dadaed5bb0d6944d29972b0.bin b/Close Enough!/Library/ShaderCache/3/303cafc81dadaed5bb0d6944d29972b0.bin deleted file mode 100644 index 68f447f..0000000 Binary files a/Close Enough!/Library/ShaderCache/3/303cafc81dadaed5bb0d6944d29972b0.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/3/374539e85a578689871d4dd155ff6396.bin b/Close Enough!/Library/ShaderCache/3/374539e85a578689871d4dd155ff6396.bin deleted file mode 100644 index f67ef3a..0000000 Binary files a/Close Enough!/Library/ShaderCache/3/374539e85a578689871d4dd155ff6396.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/3/3aa02a9c10d724db8d69f7652cc0e161.bin b/Close Enough!/Library/ShaderCache/3/3aa02a9c10d724db8d69f7652cc0e161.bin deleted file mode 100644 index a81d4ae..0000000 Binary files a/Close Enough!/Library/ShaderCache/3/3aa02a9c10d724db8d69f7652cc0e161.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/3/3d3ae902e0c3bf89c784c0f0e22fd76e.bin b/Close Enough!/Library/ShaderCache/3/3d3ae902e0c3bf89c784c0f0e22fd76e.bin deleted file mode 100644 index bcb1145..0000000 Binary files a/Close Enough!/Library/ShaderCache/3/3d3ae902e0c3bf89c784c0f0e22fd76e.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/3/3de59b4683cfbd9348e91b166fb51944.bin b/Close Enough!/Library/ShaderCache/3/3de59b4683cfbd9348e91b166fb51944.bin deleted file mode 100644 index a4b15d5..0000000 Binary files a/Close Enough!/Library/ShaderCache/3/3de59b4683cfbd9348e91b166fb51944.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/3/3fae34bc1110c7bb5a66791179ee0cd7.bin b/Close Enough!/Library/ShaderCache/3/3fae34bc1110c7bb5a66791179ee0cd7.bin deleted file mode 100644 index 9628ed7..0000000 Binary files a/Close Enough!/Library/ShaderCache/3/3fae34bc1110c7bb5a66791179ee0cd7.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/4/4132e6e64e0ea152188abb4cc949949d.bin b/Close Enough!/Library/ShaderCache/4/4132e6e64e0ea152188abb4cc949949d.bin deleted file mode 100644 index 2759df0..0000000 Binary files a/Close Enough!/Library/ShaderCache/4/4132e6e64e0ea152188abb4cc949949d.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/4/41597ad1fbae71d62c29c0631d59c968.bin b/Close Enough!/Library/ShaderCache/4/41597ad1fbae71d62c29c0631d59c968.bin deleted file mode 100644 index 880fbc0..0000000 Binary files a/Close Enough!/Library/ShaderCache/4/41597ad1fbae71d62c29c0631d59c968.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/4/44cf9ce7b97685387db2a76327f5f421.bin b/Close Enough!/Library/ShaderCache/4/44cf9ce7b97685387db2a76327f5f421.bin deleted file mode 100644 index 481b79e..0000000 Binary files a/Close Enough!/Library/ShaderCache/4/44cf9ce7b97685387db2a76327f5f421.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/4/4d44e2145eb7203fa9ec1f2d218fbafb.bin b/Close Enough!/Library/ShaderCache/4/4d44e2145eb7203fa9ec1f2d218fbafb.bin deleted file mode 100644 index bc1cb00..0000000 Binary files a/Close Enough!/Library/ShaderCache/4/4d44e2145eb7203fa9ec1f2d218fbafb.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/4/4d7f2437975963af6944088267214c24.bin b/Close Enough!/Library/ShaderCache/4/4d7f2437975963af6944088267214c24.bin deleted file mode 100644 index b48e1ea..0000000 Binary files a/Close Enough!/Library/ShaderCache/4/4d7f2437975963af6944088267214c24.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/5/53e82b2e79bb8a7f62f69ecc6440a8a1.bin b/Close Enough!/Library/ShaderCache/5/53e82b2e79bb8a7f62f69ecc6440a8a1.bin deleted file mode 100644 index c225775..0000000 Binary files a/Close Enough!/Library/ShaderCache/5/53e82b2e79bb8a7f62f69ecc6440a8a1.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/5/55b628e64dc959d635d8329a91359f0c.bin b/Close Enough!/Library/ShaderCache/5/55b628e64dc959d635d8329a91359f0c.bin deleted file mode 100644 index 5f750bc..0000000 Binary files a/Close Enough!/Library/ShaderCache/5/55b628e64dc959d635d8329a91359f0c.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/5/568147ecd2c287553fc2df0c9352cf02.bin b/Close Enough!/Library/ShaderCache/5/568147ecd2c287553fc2df0c9352cf02.bin deleted file mode 100644 index 2759df0..0000000 Binary files a/Close Enough!/Library/ShaderCache/5/568147ecd2c287553fc2df0c9352cf02.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/5/5b98453ea46d1c302e25e20730ff26dc.bin b/Close Enough!/Library/ShaderCache/5/5b98453ea46d1c302e25e20730ff26dc.bin deleted file mode 100644 index 50d747d..0000000 Binary files a/Close Enough!/Library/ShaderCache/5/5b98453ea46d1c302e25e20730ff26dc.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/5/5f541a08acbe457d0e51579eee74d900.bin b/Close Enough!/Library/ShaderCache/5/5f541a08acbe457d0e51579eee74d900.bin deleted file mode 100644 index 50d747d..0000000 Binary files a/Close Enough!/Library/ShaderCache/5/5f541a08acbe457d0e51579eee74d900.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/5/5fc1a73df3e7412b1918712426388655.bin b/Close Enough!/Library/ShaderCache/5/5fc1a73df3e7412b1918712426388655.bin deleted file mode 100644 index 5dc2d66..0000000 Binary files a/Close Enough!/Library/ShaderCache/5/5fc1a73df3e7412b1918712426388655.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/6/6195acea56568ddf0e651ba0780a5ed8.bin b/Close Enough!/Library/ShaderCache/6/6195acea56568ddf0e651ba0780a5ed8.bin deleted file mode 100644 index 3673864..0000000 Binary files a/Close Enough!/Library/ShaderCache/6/6195acea56568ddf0e651ba0780a5ed8.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/6/620d224fe1d90f0faec44cb6bdccbb75.bin b/Close Enough!/Library/ShaderCache/6/620d224fe1d90f0faec44cb6bdccbb75.bin deleted file mode 100644 index a5fcf74..0000000 Binary files a/Close Enough!/Library/ShaderCache/6/620d224fe1d90f0faec44cb6bdccbb75.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/6/66ada569c7d8277620b0a75b92c79897.bin b/Close Enough!/Library/ShaderCache/6/66ada569c7d8277620b0a75b92c79897.bin deleted file mode 100644 index bbcb094..0000000 Binary files a/Close Enough!/Library/ShaderCache/6/66ada569c7d8277620b0a75b92c79897.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/6/679128a86b40e62628bdbaba82c436a0.bin b/Close Enough!/Library/ShaderCache/6/679128a86b40e62628bdbaba82c436a0.bin deleted file mode 100644 index c19339c..0000000 Binary files a/Close Enough!/Library/ShaderCache/6/679128a86b40e62628bdbaba82c436a0.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/7/70daf7930721e0ccaef3198cd6348dec.bin b/Close Enough!/Library/ShaderCache/7/70daf7930721e0ccaef3198cd6348dec.bin deleted file mode 100644 index c89a1e2..0000000 Binary files a/Close Enough!/Library/ShaderCache/7/70daf7930721e0ccaef3198cd6348dec.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/7/71b6f694126105f1237fd59c71b18600.bin b/Close Enough!/Library/ShaderCache/7/71b6f694126105f1237fd59c71b18600.bin deleted file mode 100644 index ac1fc93..0000000 Binary files a/Close Enough!/Library/ShaderCache/7/71b6f694126105f1237fd59c71b18600.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/7/751feeb5da2bce9ee7de786f43b58acf.bin b/Close Enough!/Library/ShaderCache/7/751feeb5da2bce9ee7de786f43b58acf.bin deleted file mode 100644 index e3b4a7c..0000000 Binary files a/Close Enough!/Library/ShaderCache/7/751feeb5da2bce9ee7de786f43b58acf.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/7/7b16a21daaa763704034420d30cc209a.bin b/Close Enough!/Library/ShaderCache/7/7b16a21daaa763704034420d30cc209a.bin deleted file mode 100644 index 5f750bc..0000000 Binary files a/Close Enough!/Library/ShaderCache/7/7b16a21daaa763704034420d30cc209a.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/8/82ad14a10b072134a00f2efbbcdd9505.bin b/Close Enough!/Library/ShaderCache/8/82ad14a10b072134a00f2efbbcdd9505.bin deleted file mode 100644 index 674b2b2..0000000 Binary files a/Close Enough!/Library/ShaderCache/8/82ad14a10b072134a00f2efbbcdd9505.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/8/8ef79ebd0bd814b87209bfc6f06f0134.bin b/Close Enough!/Library/ShaderCache/8/8ef79ebd0bd814b87209bfc6f06f0134.bin deleted file mode 100644 index d2e37fc..0000000 Binary files a/Close Enough!/Library/ShaderCache/8/8ef79ebd0bd814b87209bfc6f06f0134.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/9/919876937b76b8a0851cc42257a676dd.bin b/Close Enough!/Library/ShaderCache/9/919876937b76b8a0851cc42257a676dd.bin deleted file mode 100644 index 4d52623..0000000 Binary files a/Close Enough!/Library/ShaderCache/9/919876937b76b8a0851cc42257a676dd.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/a/ab0acc73b04d2e029967c5e16f1ce6e8.bin b/Close Enough!/Library/ShaderCache/a/ab0acc73b04d2e029967c5e16f1ce6e8.bin deleted file mode 100644 index 05806d2..0000000 Binary files a/Close Enough!/Library/ShaderCache/a/ab0acc73b04d2e029967c5e16f1ce6e8.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/b/b36b99d594bc32f496424d9cccc3efcc.bin b/Close Enough!/Library/ShaderCache/b/b36b99d594bc32f496424d9cccc3efcc.bin deleted file mode 100644 index 2759df0..0000000 Binary files a/Close Enough!/Library/ShaderCache/b/b36b99d594bc32f496424d9cccc3efcc.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/b/b56a00030af2b04bbabdca2188f93807.bin b/Close Enough!/Library/ShaderCache/b/b56a00030af2b04bbabdca2188f93807.bin deleted file mode 100644 index 71f7a05..0000000 Binary files a/Close Enough!/Library/ShaderCache/b/b56a00030af2b04bbabdca2188f93807.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/b/b6e4cf6f7e3b8eb285caeeb3e74cad0a.bin b/Close Enough!/Library/ShaderCache/b/b6e4cf6f7e3b8eb285caeeb3e74cad0a.bin deleted file mode 100644 index 2759df0..0000000 Binary files a/Close Enough!/Library/ShaderCache/b/b6e4cf6f7e3b8eb285caeeb3e74cad0a.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/b/b7dd38aa3d5ad9988d3dc2e78c4cf8d5.bin b/Close Enough!/Library/ShaderCache/b/b7dd38aa3d5ad9988d3dc2e78c4cf8d5.bin deleted file mode 100644 index bbcb094..0000000 Binary files a/Close Enough!/Library/ShaderCache/b/b7dd38aa3d5ad9988d3dc2e78c4cf8d5.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/b/bb75332a2cf949bf2ab899db6ae5df33.bin b/Close Enough!/Library/ShaderCache/b/bb75332a2cf949bf2ab899db6ae5df33.bin deleted file mode 100644 index f2d0940..0000000 Binary files a/Close Enough!/Library/ShaderCache/b/bb75332a2cf949bf2ab899db6ae5df33.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/b/bf99210152a1399b4f51ed50fe146a11.bin b/Close Enough!/Library/ShaderCache/b/bf99210152a1399b4f51ed50fe146a11.bin deleted file mode 100644 index 7073db8..0000000 Binary files a/Close Enough!/Library/ShaderCache/b/bf99210152a1399b4f51ed50fe146a11.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/c/c749383b249c078553a052bf4f6bebbd.bin b/Close Enough!/Library/ShaderCache/c/c749383b249c078553a052bf4f6bebbd.bin deleted file mode 100644 index 2759df0..0000000 Binary files a/Close Enough!/Library/ShaderCache/c/c749383b249c078553a052bf4f6bebbd.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/d/d41cfb5521cc75eda0eb846dc30a95ec.bin b/Close Enough!/Library/ShaderCache/d/d41cfb5521cc75eda0eb846dc30a95ec.bin deleted file mode 100644 index ad74b2d..0000000 Binary files a/Close Enough!/Library/ShaderCache/d/d41cfb5521cc75eda0eb846dc30a95ec.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/e/e619f507b81de5c11274f6871390d6de.bin b/Close Enough!/Library/ShaderCache/e/e619f507b81de5c11274f6871390d6de.bin deleted file mode 100644 index baea59e..0000000 Binary files a/Close Enough!/Library/ShaderCache/e/e619f507b81de5c11274f6871390d6de.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/e/efea783369f3468a1fb97ba7cb65dde7.bin b/Close Enough!/Library/ShaderCache/e/efea783369f3468a1fb97ba7cb65dde7.bin deleted file mode 100644 index 481b79e..0000000 Binary files a/Close Enough!/Library/ShaderCache/e/efea783369f3468a1fb97ba7cb65dde7.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/f/f5f720ee06bd0004d05f1c81a57e659c.bin b/Close Enough!/Library/ShaderCache/f/f5f720ee06bd0004d05f1c81a57e659c.bin deleted file mode 100644 index 3311602..0000000 Binary files a/Close Enough!/Library/ShaderCache/f/f5f720ee06bd0004d05f1c81a57e659c.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/f/f6600fb29d58f21685f38ebc70d6a481.bin b/Close Enough!/Library/ShaderCache/f/f6600fb29d58f21685f38ebc70d6a481.bin deleted file mode 100644 index f263b57..0000000 Binary files a/Close Enough!/Library/ShaderCache/f/f6600fb29d58f21685f38ebc70d6a481.bin and /dev/null differ diff --git a/Close Enough!/Library/ShaderCache/f/fb3b6c582ba72cd13de8211a8836b195.bin b/Close Enough!/Library/ShaderCache/f/fb3b6c582ba72cd13de8211a8836b195.bin deleted file mode 100644 index 8c7c610..0000000 Binary files a/Close Enough!/Library/ShaderCache/f/fb3b6c582ba72cd13de8211a8836b195.bin and /dev/null differ diff --git a/Close Enough!/Library/SpriteAtlasDatabase.asset b/Close Enough!/Library/SpriteAtlasDatabase.asset deleted file mode 100644 index b3afd50..0000000 Binary files a/Close Enough!/Library/SpriteAtlasDatabase.asset and /dev/null differ diff --git a/Close Enough!/Library/TilemapEditorUserSettings.asset b/Close Enough!/Library/TilemapEditorUserSettings.asset deleted file mode 100644 index d9949fc..0000000 Binary files a/Close Enough!/Library/TilemapEditorUserSettings.asset and /dev/null differ diff --git a/Close Enough!/Library/assetDatabase3 b/Close Enough!/Library/assetDatabase3 deleted file mode 100644 index a145eff..0000000 Binary files a/Close Enough!/Library/assetDatabase3 and /dev/null differ diff --git a/Close Enough!/Library/expandedItems b/Close Enough!/Library/expandedItems deleted file mode 100644 index 82b98e9..0000000 Binary files a/Close Enough!/Library/expandedItems and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000001000000000000000 b/Close Enough!/Library/metadata/00/00000000000000001000000000000000 deleted file mode 100644 index d1be53e..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000001000000000000000 and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000001000000000000000.info b/Close Enough!/Library/metadata/00/00000000000000001000000000000000.info deleted file mode 100644 index 0a194ff..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000001000000000000000.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000002000000000000000 b/Close Enough!/Library/metadata/00/00000000000000002000000000000000 deleted file mode 100644 index 55e5fda..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000002000000000000000 and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000002000000000000000.info b/Close Enough!/Library/metadata/00/00000000000000002000000000000000.info deleted file mode 100644 index 593e5d4..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000002000000000000000.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000003000000000000000 b/Close Enough!/Library/metadata/00/00000000000000003000000000000000 deleted file mode 100644 index ecc900d..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000003000000000000000 and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000003000000000000000.info b/Close Enough!/Library/metadata/00/00000000000000003000000000000000.info deleted file mode 100644 index ec51f96..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000003000000000000000.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000004000000000000000 b/Close Enough!/Library/metadata/00/00000000000000004000000000000000 deleted file mode 100644 index 85f67a5..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000004000000000000000 and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000004000000000000000.info b/Close Enough!/Library/metadata/00/00000000000000004000000000000000.info deleted file mode 100644 index fc11fd0..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000004000000000000000.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000004100000000000000 b/Close Enough!/Library/metadata/00/00000000000000004100000000000000 deleted file mode 100644 index 9c51338..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000004100000000000000 and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000004100000000000000.info b/Close Enough!/Library/metadata/00/00000000000000004100000000000000.info deleted file mode 100644 index 65ed8e2..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000004100000000000000.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000005000000000000000 b/Close Enough!/Library/metadata/00/00000000000000005000000000000000 deleted file mode 100644 index edb9eb9..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000005000000000000000 and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000005000000000000000.info b/Close Enough!/Library/metadata/00/00000000000000005000000000000000.info deleted file mode 100644 index fade0c9..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000005000000000000000.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000005100000000000000 b/Close Enough!/Library/metadata/00/00000000000000005100000000000000 deleted file mode 100644 index bf17682..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000005100000000000000 and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000005100000000000000.info b/Close Enough!/Library/metadata/00/00000000000000005100000000000000.info deleted file mode 100644 index 5db0c0b..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000005100000000000000.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000006000000000000000 b/Close Enough!/Library/metadata/00/00000000000000006000000000000000 deleted file mode 100644 index 8a06f3f..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000006000000000000000 and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000006000000000000000.info b/Close Enough!/Library/metadata/00/00000000000000006000000000000000.info deleted file mode 100644 index bb46964..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000006000000000000000.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000006100000000000000 b/Close Enough!/Library/metadata/00/00000000000000006100000000000000 deleted file mode 100644 index 7e3db18..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000006100000000000000 and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000006100000000000000.info b/Close Enough!/Library/metadata/00/00000000000000006100000000000000.info deleted file mode 100644 index dfb760a..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000006100000000000000.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000007000000000000000 b/Close Enough!/Library/metadata/00/00000000000000007000000000000000 deleted file mode 100644 index d1a962b..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000007000000000000000 and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000007000000000000000.info b/Close Enough!/Library/metadata/00/00000000000000007000000000000000.info deleted file mode 100644 index a80c7dd..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000007000000000000000.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000007100000000000000 b/Close Enough!/Library/metadata/00/00000000000000007100000000000000 deleted file mode 100644 index 18be1f5..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000007100000000000000 and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000007100000000000000.info b/Close Enough!/Library/metadata/00/00000000000000007100000000000000.info deleted file mode 100644 index 1b7d26b..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000007100000000000000.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000008000000000000000 b/Close Enough!/Library/metadata/00/00000000000000008000000000000000 deleted file mode 100644 index 76bc39e..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000008000000000000000 and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000008000000000000000.info b/Close Enough!/Library/metadata/00/00000000000000008000000000000000.info deleted file mode 100644 index 5dc930f..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000008000000000000000.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000009000000000000000 b/Close Enough!/Library/metadata/00/00000000000000009000000000000000 deleted file mode 100644 index 009801d..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000009000000000000000 and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00000000000000009000000000000000.info b/Close Enough!/Library/metadata/00/00000000000000009000000000000000.info deleted file mode 100644 index bd8d03a..0000000 Binary files a/Close Enough!/Library/metadata/00/00000000000000009000000000000000.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/0000000000000000a000000000000000 b/Close Enough!/Library/metadata/00/0000000000000000a000000000000000 deleted file mode 100644 index 5ed901a..0000000 Binary files a/Close Enough!/Library/metadata/00/0000000000000000a000000000000000 and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/0000000000000000a000000000000000.info b/Close Enough!/Library/metadata/00/0000000000000000a000000000000000.info deleted file mode 100644 index be77da9..0000000 Binary files a/Close Enough!/Library/metadata/00/0000000000000000a000000000000000.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/0000000000000000a100000000000000 b/Close Enough!/Library/metadata/00/0000000000000000a100000000000000 deleted file mode 100644 index 5a5fd6d..0000000 Binary files a/Close Enough!/Library/metadata/00/0000000000000000a100000000000000 and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/0000000000000000a100000000000000.info b/Close Enough!/Library/metadata/00/0000000000000000a100000000000000.info deleted file mode 100644 index 552089b..0000000 Binary files a/Close Enough!/Library/metadata/00/0000000000000000a100000000000000.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/0000000000000000b000000000000000 b/Close Enough!/Library/metadata/00/0000000000000000b000000000000000 deleted file mode 100644 index 06400f3..0000000 Binary files a/Close Enough!/Library/metadata/00/0000000000000000b000000000000000 and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/0000000000000000b000000000000000.info b/Close Enough!/Library/metadata/00/0000000000000000b000000000000000.info deleted file mode 100644 index 3d0ea61..0000000 Binary files a/Close Enough!/Library/metadata/00/0000000000000000b000000000000000.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/0000000000000000c000000000000000 b/Close Enough!/Library/metadata/00/0000000000000000c000000000000000 deleted file mode 100644 index ca479dd..0000000 Binary files a/Close Enough!/Library/metadata/00/0000000000000000c000000000000000 and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/0000000000000000c000000000000000.info b/Close Enough!/Library/metadata/00/0000000000000000c000000000000000.info deleted file mode 100644 index 1af637d..0000000 Binary files a/Close Enough!/Library/metadata/00/0000000000000000c000000000000000.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00d8dad3aef084764961f3a9a63abe12 b/Close Enough!/Library/metadata/00/00d8dad3aef084764961f3a9a63abe12 deleted file mode 100644 index b9da05b..0000000 Binary files a/Close Enough!/Library/metadata/00/00d8dad3aef084764961f3a9a63abe12 and /dev/null differ diff --git a/Close Enough!/Library/metadata/00/00d8dad3aef084764961f3a9a63abe12.info b/Close Enough!/Library/metadata/00/00d8dad3aef084764961f3a9a63abe12.info deleted file mode 100644 index edd5d1b..0000000 Binary files a/Close Enough!/Library/metadata/00/00d8dad3aef084764961f3a9a63abe12.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/01/01718c103234346dca451682564285bd b/Close Enough!/Library/metadata/01/01718c103234346dca451682564285bd deleted file mode 100644 index 5b276bd..0000000 Binary files a/Close Enough!/Library/metadata/01/01718c103234346dca451682564285bd and /dev/null differ diff --git a/Close Enough!/Library/metadata/01/01718c103234346dca451682564285bd.info b/Close Enough!/Library/metadata/01/01718c103234346dca451682564285bd.info deleted file mode 100644 index f1cbba6..0000000 Binary files a/Close Enough!/Library/metadata/01/01718c103234346dca451682564285bd.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/01/017898a6c01c3f84390dd4f8102038d8 b/Close Enough!/Library/metadata/01/017898a6c01c3f84390dd4f8102038d8 deleted file mode 100644 index 8ddd1a1..0000000 Binary files a/Close Enough!/Library/metadata/01/017898a6c01c3f84390dd4f8102038d8 and /dev/null differ diff --git a/Close Enough!/Library/metadata/01/017898a6c01c3f84390dd4f8102038d8.info b/Close Enough!/Library/metadata/01/017898a6c01c3f84390dd4f8102038d8.info deleted file mode 100644 index b9fae95..0000000 Binary files a/Close Enough!/Library/metadata/01/017898a6c01c3f84390dd4f8102038d8.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/01/01b167077f96ef845aeb8363fc14cb2b b/Close Enough!/Library/metadata/01/01b167077f96ef845aeb8363fc14cb2b deleted file mode 100644 index 7e569b0..0000000 Binary files a/Close Enough!/Library/metadata/01/01b167077f96ef845aeb8363fc14cb2b and /dev/null differ diff --git a/Close Enough!/Library/metadata/01/01b167077f96ef845aeb8363fc14cb2b.info b/Close Enough!/Library/metadata/01/01b167077f96ef845aeb8363fc14cb2b.info deleted file mode 100644 index b831e2d..0000000 Binary files a/Close Enough!/Library/metadata/01/01b167077f96ef845aeb8363fc14cb2b.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/01/01cd679a1b9ee48bf9c546f6ce2cb97e b/Close Enough!/Library/metadata/01/01cd679a1b9ee48bf9c546f6ce2cb97e deleted file mode 100644 index b0003e9..0000000 Binary files a/Close Enough!/Library/metadata/01/01cd679a1b9ee48bf9c546f6ce2cb97e and /dev/null differ diff --git a/Close Enough!/Library/metadata/01/01cd679a1b9ee48bf9c546f6ce2cb97e.info b/Close Enough!/Library/metadata/01/01cd679a1b9ee48bf9c546f6ce2cb97e.info deleted file mode 100644 index 3344645..0000000 Binary files a/Close Enough!/Library/metadata/01/01cd679a1b9ee48bf9c546f6ce2cb97e.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/01/01f9f98b8d54d8949a4db0c655eef43a b/Close Enough!/Library/metadata/01/01f9f98b8d54d8949a4db0c655eef43a deleted file mode 100644 index 021fe53..0000000 Binary files a/Close Enough!/Library/metadata/01/01f9f98b8d54d8949a4db0c655eef43a and /dev/null differ diff --git a/Close Enough!/Library/metadata/01/01f9f98b8d54d8949a4db0c655eef43a.info b/Close Enough!/Library/metadata/01/01f9f98b8d54d8949a4db0c655eef43a.info deleted file mode 100644 index 146293c..0000000 Binary files a/Close Enough!/Library/metadata/01/01f9f98b8d54d8949a4db0c655eef43a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/01/01f9f98b8d54d8949a4db0c655eef43a.resource b/Close Enough!/Library/metadata/01/01f9f98b8d54d8949a4db0c655eef43a.resource deleted file mode 100644 index 5fcb523..0000000 Binary files a/Close Enough!/Library/metadata/01/01f9f98b8d54d8949a4db0c655eef43a.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/02/02b7026fdfd43a7489247047a2228914 b/Close Enough!/Library/metadata/02/02b7026fdfd43a7489247047a2228914 deleted file mode 100644 index 510c6c9..0000000 Binary files a/Close Enough!/Library/metadata/02/02b7026fdfd43a7489247047a2228914 and /dev/null differ diff --git a/Close Enough!/Library/metadata/02/02b7026fdfd43a7489247047a2228914.info b/Close Enough!/Library/metadata/02/02b7026fdfd43a7489247047a2228914.info deleted file mode 100644 index e61d2a7..0000000 Binary files a/Close Enough!/Library/metadata/02/02b7026fdfd43a7489247047a2228914.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/02/02c16aa602ac849dfaf41b4665c53e8a b/Close Enough!/Library/metadata/02/02c16aa602ac849dfaf41b4665c53e8a deleted file mode 100644 index f760a63..0000000 Binary files a/Close Enough!/Library/metadata/02/02c16aa602ac849dfaf41b4665c53e8a and /dev/null differ diff --git a/Close Enough!/Library/metadata/02/02c16aa602ac849dfaf41b4665c53e8a.info b/Close Enough!/Library/metadata/02/02c16aa602ac849dfaf41b4665c53e8a.info deleted file mode 100644 index 1de94dc..0000000 Binary files a/Close Enough!/Library/metadata/02/02c16aa602ac849dfaf41b4665c53e8a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/04/04a842e316b6f44bf8da702de26a8ed6 b/Close Enough!/Library/metadata/04/04a842e316b6f44bf8da702de26a8ed6 deleted file mode 100644 index 17b0615..0000000 Binary files a/Close Enough!/Library/metadata/04/04a842e316b6f44bf8da702de26a8ed6 and /dev/null differ diff --git a/Close Enough!/Library/metadata/04/04a842e316b6f44bf8da702de26a8ed6.info b/Close Enough!/Library/metadata/04/04a842e316b6f44bf8da702de26a8ed6.info deleted file mode 100644 index fa1a117..0000000 Binary files a/Close Enough!/Library/metadata/04/04a842e316b6f44bf8da702de26a8ed6.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/04/04af35f5285efc049ba17c428eb07b8a b/Close Enough!/Library/metadata/04/04af35f5285efc049ba17c428eb07b8a deleted file mode 100644 index f56ff7c..0000000 Binary files a/Close Enough!/Library/metadata/04/04af35f5285efc049ba17c428eb07b8a and /dev/null differ diff --git a/Close Enough!/Library/metadata/04/04af35f5285efc049ba17c428eb07b8a.info b/Close Enough!/Library/metadata/04/04af35f5285efc049ba17c428eb07b8a.info deleted file mode 100644 index 00b0a74..0000000 Binary files a/Close Enough!/Library/metadata/04/04af35f5285efc049ba17c428eb07b8a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/05/0542d4172d38b4bb693705d68966a20b b/Close Enough!/Library/metadata/05/0542d4172d38b4bb693705d68966a20b deleted file mode 100644 index e97bf1e..0000000 Binary files a/Close Enough!/Library/metadata/05/0542d4172d38b4bb693705d68966a20b and /dev/null differ diff --git a/Close Enough!/Library/metadata/05/0542d4172d38b4bb693705d68966a20b.info b/Close Enough!/Library/metadata/05/0542d4172d38b4bb693705d68966a20b.info deleted file mode 100644 index 0568e54..0000000 Binary files a/Close Enough!/Library/metadata/05/0542d4172d38b4bb693705d68966a20b.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/05/05abdcc0573bab446b7d167bd4049192 b/Close Enough!/Library/metadata/05/05abdcc0573bab446b7d167bd4049192 deleted file mode 100644 index 767b1db..0000000 Binary files a/Close Enough!/Library/metadata/05/05abdcc0573bab446b7d167bd4049192 and /dev/null differ diff --git a/Close Enough!/Library/metadata/05/05abdcc0573bab446b7d167bd4049192.info b/Close Enough!/Library/metadata/05/05abdcc0573bab446b7d167bd4049192.info deleted file mode 100644 index 5646111..0000000 Binary files a/Close Enough!/Library/metadata/05/05abdcc0573bab446b7d167bd4049192.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/06/0616288a5a1de2e4cb7eceee3625d8eb b/Close Enough!/Library/metadata/06/0616288a5a1de2e4cb7eceee3625d8eb deleted file mode 100644 index ab2c8cb..0000000 Binary files a/Close Enough!/Library/metadata/06/0616288a5a1de2e4cb7eceee3625d8eb and /dev/null differ diff --git a/Close Enough!/Library/metadata/06/0616288a5a1de2e4cb7eceee3625d8eb.info b/Close Enough!/Library/metadata/06/0616288a5a1de2e4cb7eceee3625d8eb.info deleted file mode 100644 index 9a74bad..0000000 Binary files a/Close Enough!/Library/metadata/06/0616288a5a1de2e4cb7eceee3625d8eb.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/06/0620c0473d493411caea4b5d4e897050 b/Close Enough!/Library/metadata/06/0620c0473d493411caea4b5d4e897050 deleted file mode 100644 index a2be18f..0000000 Binary files a/Close Enough!/Library/metadata/06/0620c0473d493411caea4b5d4e897050 and /dev/null differ diff --git a/Close Enough!/Library/metadata/06/0620c0473d493411caea4b5d4e897050.info b/Close Enough!/Library/metadata/06/0620c0473d493411caea4b5d4e897050.info deleted file mode 100644 index ef53055..0000000 Binary files a/Close Enough!/Library/metadata/06/0620c0473d493411caea4b5d4e897050.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/06/0621b4aab2236437592f1f292cb81d20 b/Close Enough!/Library/metadata/06/0621b4aab2236437592f1f292cb81d20 deleted file mode 100644 index c91c5af..0000000 Binary files a/Close Enough!/Library/metadata/06/0621b4aab2236437592f1f292cb81d20 and /dev/null differ diff --git a/Close Enough!/Library/metadata/06/0621b4aab2236437592f1f292cb81d20.info b/Close Enough!/Library/metadata/06/0621b4aab2236437592f1f292cb81d20.info deleted file mode 100644 index f0c6fe1..0000000 Binary files a/Close Enough!/Library/metadata/06/0621b4aab2236437592f1f292cb81d20.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/06/065bc04072e8eac46889ac488263b5e8 b/Close Enough!/Library/metadata/06/065bc04072e8eac46889ac488263b5e8 deleted file mode 100644 index c5a411f..0000000 Binary files a/Close Enough!/Library/metadata/06/065bc04072e8eac46889ac488263b5e8 and /dev/null differ diff --git a/Close Enough!/Library/metadata/06/065bc04072e8eac46889ac488263b5e8.info b/Close Enough!/Library/metadata/06/065bc04072e8eac46889ac488263b5e8.info deleted file mode 100644 index e387bf1..0000000 Binary files a/Close Enough!/Library/metadata/06/065bc04072e8eac46889ac488263b5e8.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/06/06a541a8ec68b6240b7d84970f683d44 b/Close Enough!/Library/metadata/06/06a541a8ec68b6240b7d84970f683d44 deleted file mode 100644 index aac9294..0000000 Binary files a/Close Enough!/Library/metadata/06/06a541a8ec68b6240b7d84970f683d44 and /dev/null differ diff --git a/Close Enough!/Library/metadata/06/06a541a8ec68b6240b7d84970f683d44.info b/Close Enough!/Library/metadata/06/06a541a8ec68b6240b7d84970f683d44.info deleted file mode 100644 index 9cbcc8b..0000000 Binary files a/Close Enough!/Library/metadata/06/06a541a8ec68b6240b7d84970f683d44.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/07/07ebb9a7e1a7f49b3bb8e5fd092f24ec b/Close Enough!/Library/metadata/07/07ebb9a7e1a7f49b3bb8e5fd092f24ec deleted file mode 100644 index 2888fa9..0000000 Binary files a/Close Enough!/Library/metadata/07/07ebb9a7e1a7f49b3bb8e5fd092f24ec and /dev/null differ diff --git a/Close Enough!/Library/metadata/07/07ebb9a7e1a7f49b3bb8e5fd092f24ec.info b/Close Enough!/Library/metadata/07/07ebb9a7e1a7f49b3bb8e5fd092f24ec.info deleted file mode 100644 index 0c7a2df..0000000 Binary files a/Close Enough!/Library/metadata/07/07ebb9a7e1a7f49b3bb8e5fd092f24ec.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/08/086f32566457e9b4399348747e15d7a8 b/Close Enough!/Library/metadata/08/086f32566457e9b4399348747e15d7a8 deleted file mode 100644 index 1212d0b..0000000 Binary files a/Close Enough!/Library/metadata/08/086f32566457e9b4399348747e15d7a8 and /dev/null differ diff --git a/Close Enough!/Library/metadata/08/086f32566457e9b4399348747e15d7a8.info b/Close Enough!/Library/metadata/08/086f32566457e9b4399348747e15d7a8.info deleted file mode 100644 index 278341d..0000000 Binary files a/Close Enough!/Library/metadata/08/086f32566457e9b4399348747e15d7a8.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/08/08ca75b5c24dc411bb6d059e543b79ef b/Close Enough!/Library/metadata/08/08ca75b5c24dc411bb6d059e543b79ef deleted file mode 100644 index f69d3dc..0000000 Binary files a/Close Enough!/Library/metadata/08/08ca75b5c24dc411bb6d059e543b79ef and /dev/null differ diff --git a/Close Enough!/Library/metadata/08/08ca75b5c24dc411bb6d059e543b79ef.info b/Close Enough!/Library/metadata/08/08ca75b5c24dc411bb6d059e543b79ef.info deleted file mode 100644 index 7630955..0000000 Binary files a/Close Enough!/Library/metadata/08/08ca75b5c24dc411bb6d059e543b79ef.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/09/0934303c345ed244eb39c38faa3dcbff b/Close Enough!/Library/metadata/09/0934303c345ed244eb39c38faa3dcbff deleted file mode 100644 index 59f92f3..0000000 Binary files a/Close Enough!/Library/metadata/09/0934303c345ed244eb39c38faa3dcbff and /dev/null differ diff --git a/Close Enough!/Library/metadata/09/0934303c345ed244eb39c38faa3dcbff.info b/Close Enough!/Library/metadata/09/0934303c345ed244eb39c38faa3dcbff.info deleted file mode 100644 index c647c9c..0000000 Binary files a/Close Enough!/Library/metadata/09/0934303c345ed244eb39c38faa3dcbff.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/09/0934303c345ed244eb39c38faa3dcbff.resource b/Close Enough!/Library/metadata/09/0934303c345ed244eb39c38faa3dcbff.resource deleted file mode 100644 index 3438568..0000000 Binary files a/Close Enough!/Library/metadata/09/0934303c345ed244eb39c38faa3dcbff.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/09/093c7c435f5d44d42be820cc0c5e61d4 b/Close Enough!/Library/metadata/09/093c7c435f5d44d42be820cc0c5e61d4 deleted file mode 100644 index 555e73b..0000000 Binary files a/Close Enough!/Library/metadata/09/093c7c435f5d44d42be820cc0c5e61d4 and /dev/null differ diff --git a/Close Enough!/Library/metadata/09/093c7c435f5d44d42be820cc0c5e61d4.info b/Close Enough!/Library/metadata/09/093c7c435f5d44d42be820cc0c5e61d4.info deleted file mode 100644 index e47e262..0000000 Binary files a/Close Enough!/Library/metadata/09/093c7c435f5d44d42be820cc0c5e61d4.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/09/093c7c435f5d44d42be820cc0c5e61d4.resource b/Close Enough!/Library/metadata/09/093c7c435f5d44d42be820cc0c5e61d4.resource deleted file mode 100644 index 6136a2f..0000000 Binary files a/Close Enough!/Library/metadata/09/093c7c435f5d44d42be820cc0c5e61d4.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/09/095c790b54a7c0849932e28597b85e72 b/Close Enough!/Library/metadata/09/095c790b54a7c0849932e28597b85e72 deleted file mode 100644 index 912ed49..0000000 Binary files a/Close Enough!/Library/metadata/09/095c790b54a7c0849932e28597b85e72 and /dev/null differ diff --git a/Close Enough!/Library/metadata/09/095c790b54a7c0849932e28597b85e72.info b/Close Enough!/Library/metadata/09/095c790b54a7c0849932e28597b85e72.info deleted file mode 100644 index 840be5d..0000000 Binary files a/Close Enough!/Library/metadata/09/095c790b54a7c0849932e28597b85e72.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/09/09a8d1cb18b5d419aa318575e7fa6bc7 b/Close Enough!/Library/metadata/09/09a8d1cb18b5d419aa318575e7fa6bc7 deleted file mode 100644 index 8cf653d..0000000 Binary files a/Close Enough!/Library/metadata/09/09a8d1cb18b5d419aa318575e7fa6bc7 and /dev/null differ diff --git a/Close Enough!/Library/metadata/09/09a8d1cb18b5d419aa318575e7fa6bc7.info b/Close Enough!/Library/metadata/09/09a8d1cb18b5d419aa318575e7fa6bc7.info deleted file mode 100644 index 8dfa8b1..0000000 Binary files a/Close Enough!/Library/metadata/09/09a8d1cb18b5d419aa318575e7fa6bc7.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/09/09adc1ab88d15384790e83f40a805daa b/Close Enough!/Library/metadata/09/09adc1ab88d15384790e83f40a805daa deleted file mode 100644 index e1e9af1..0000000 Binary files a/Close Enough!/Library/metadata/09/09adc1ab88d15384790e83f40a805daa and /dev/null differ diff --git a/Close Enough!/Library/metadata/09/09adc1ab88d15384790e83f40a805daa.info b/Close Enough!/Library/metadata/09/09adc1ab88d15384790e83f40a805daa.info deleted file mode 100644 index b89c4bf..0000000 Binary files a/Close Enough!/Library/metadata/09/09adc1ab88d15384790e83f40a805daa.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/0a/0a1f58d554ac2b44dae58255b6daa8de b/Close Enough!/Library/metadata/0a/0a1f58d554ac2b44dae58255b6daa8de deleted file mode 100644 index b04a6ce..0000000 Binary files a/Close Enough!/Library/metadata/0a/0a1f58d554ac2b44dae58255b6daa8de and /dev/null differ diff --git a/Close Enough!/Library/metadata/0a/0a1f58d554ac2b44dae58255b6daa8de.info b/Close Enough!/Library/metadata/0a/0a1f58d554ac2b44dae58255b6daa8de.info deleted file mode 100644 index ec59af9..0000000 Binary files a/Close Enough!/Library/metadata/0a/0a1f58d554ac2b44dae58255b6daa8de.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/0a/0ac306eb34e98bc45b8ecf76c94bc8bd b/Close Enough!/Library/metadata/0a/0ac306eb34e98bc45b8ecf76c94bc8bd deleted file mode 100644 index 7573136..0000000 Binary files a/Close Enough!/Library/metadata/0a/0ac306eb34e98bc45b8ecf76c94bc8bd and /dev/null differ diff --git a/Close Enough!/Library/metadata/0a/0ac306eb34e98bc45b8ecf76c94bc8bd.info b/Close Enough!/Library/metadata/0a/0ac306eb34e98bc45b8ecf76c94bc8bd.info deleted file mode 100644 index 689fe9e..0000000 Binary files a/Close Enough!/Library/metadata/0a/0ac306eb34e98bc45b8ecf76c94bc8bd.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/0b/0b0b0e10197c65549865e305ad891c6a b/Close Enough!/Library/metadata/0b/0b0b0e10197c65549865e305ad891c6a deleted file mode 100644 index 05bddc4..0000000 Binary files a/Close Enough!/Library/metadata/0b/0b0b0e10197c65549865e305ad891c6a and /dev/null differ diff --git a/Close Enough!/Library/metadata/0b/0b0b0e10197c65549865e305ad891c6a.info b/Close Enough!/Library/metadata/0b/0b0b0e10197c65549865e305ad891c6a.info deleted file mode 100644 index f8eb834..0000000 Binary files a/Close Enough!/Library/metadata/0b/0b0b0e10197c65549865e305ad891c6a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/0b/0b0b0e10197c65549865e305ad891c6a.resource b/Close Enough!/Library/metadata/0b/0b0b0e10197c65549865e305ad891c6a.resource deleted file mode 100644 index 879f146..0000000 Binary files a/Close Enough!/Library/metadata/0b/0b0b0e10197c65549865e305ad891c6a.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/0d/0d3bb855445e36e479c85976fc88383a b/Close Enough!/Library/metadata/0d/0d3bb855445e36e479c85976fc88383a deleted file mode 100644 index 9741183..0000000 Binary files a/Close Enough!/Library/metadata/0d/0d3bb855445e36e479c85976fc88383a and /dev/null differ diff --git a/Close Enough!/Library/metadata/0d/0d3bb855445e36e479c85976fc88383a.info b/Close Enough!/Library/metadata/0d/0d3bb855445e36e479c85976fc88383a.info deleted file mode 100644 index 1875dc8..0000000 Binary files a/Close Enough!/Library/metadata/0d/0d3bb855445e36e479c85976fc88383a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/0e/0ecc983340d3d754eaa469d39d448973 b/Close Enough!/Library/metadata/0e/0ecc983340d3d754eaa469d39d448973 deleted file mode 100644 index 3bf699b..0000000 Binary files a/Close Enough!/Library/metadata/0e/0ecc983340d3d754eaa469d39d448973 and /dev/null differ diff --git a/Close Enough!/Library/metadata/0e/0ecc983340d3d754eaa469d39d448973.info b/Close Enough!/Library/metadata/0e/0ecc983340d3d754eaa469d39d448973.info deleted file mode 100644 index c38cf47..0000000 Binary files a/Close Enough!/Library/metadata/0e/0ecc983340d3d754eaa469d39d448973.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/0e/0ecc983340d3d754eaa469d39d448973.resource b/Close Enough!/Library/metadata/0e/0ecc983340d3d754eaa469d39d448973.resource deleted file mode 100644 index 33e04af..0000000 Binary files a/Close Enough!/Library/metadata/0e/0ecc983340d3d754eaa469d39d448973.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/0e/0ee4babd283ae0c49bae56dd286a4132 b/Close Enough!/Library/metadata/0e/0ee4babd283ae0c49bae56dd286a4132 deleted file mode 100644 index 7934411..0000000 Binary files a/Close Enough!/Library/metadata/0e/0ee4babd283ae0c49bae56dd286a4132 and /dev/null differ diff --git a/Close Enough!/Library/metadata/0e/0ee4babd283ae0c49bae56dd286a4132.info b/Close Enough!/Library/metadata/0e/0ee4babd283ae0c49bae56dd286a4132.info deleted file mode 100644 index 0654fa5..0000000 Binary files a/Close Enough!/Library/metadata/0e/0ee4babd283ae0c49bae56dd286a4132.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/0f/0ff440e8c4d6b0d40aa6c99a7f79c616 b/Close Enough!/Library/metadata/0f/0ff440e8c4d6b0d40aa6c99a7f79c616 deleted file mode 100644 index dc6011f..0000000 Binary files a/Close Enough!/Library/metadata/0f/0ff440e8c4d6b0d40aa6c99a7f79c616 and /dev/null differ diff --git a/Close Enough!/Library/metadata/0f/0ff440e8c4d6b0d40aa6c99a7f79c616.info b/Close Enough!/Library/metadata/0f/0ff440e8c4d6b0d40aa6c99a7f79c616.info deleted file mode 100644 index a21d283..0000000 Binary files a/Close Enough!/Library/metadata/0f/0ff440e8c4d6b0d40aa6c99a7f79c616.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/10/107ef858fec3f1e4f9699c6eb404ff74 b/Close Enough!/Library/metadata/10/107ef858fec3f1e4f9699c6eb404ff74 deleted file mode 100644 index 1b6c3c5..0000000 Binary files a/Close Enough!/Library/metadata/10/107ef858fec3f1e4f9699c6eb404ff74 and /dev/null differ diff --git a/Close Enough!/Library/metadata/10/107ef858fec3f1e4f9699c6eb404ff74.info b/Close Enough!/Library/metadata/10/107ef858fec3f1e4f9699c6eb404ff74.info deleted file mode 100644 index 9736364..0000000 Binary files a/Close Enough!/Library/metadata/10/107ef858fec3f1e4f9699c6eb404ff74.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/10/107ef858fec3f1e4f9699c6eb404ff74.resource b/Close Enough!/Library/metadata/10/107ef858fec3f1e4f9699c6eb404ff74.resource deleted file mode 100644 index d514d49..0000000 Binary files a/Close Enough!/Library/metadata/10/107ef858fec3f1e4f9699c6eb404ff74.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/10/10bf81265ad87424d946598c575f45a0 b/Close Enough!/Library/metadata/10/10bf81265ad87424d946598c575f45a0 deleted file mode 100644 index ca25a88..0000000 Binary files a/Close Enough!/Library/metadata/10/10bf81265ad87424d946598c575f45a0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/10/10bf81265ad87424d946598c575f45a0.info b/Close Enough!/Library/metadata/10/10bf81265ad87424d946598c575f45a0.info deleted file mode 100644 index 1868553..0000000 Binary files a/Close Enough!/Library/metadata/10/10bf81265ad87424d946598c575f45a0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/10/10e376bdedb8e421a93a10432c23f710 b/Close Enough!/Library/metadata/10/10e376bdedb8e421a93a10432c23f710 deleted file mode 100644 index abe19c8..0000000 Binary files a/Close Enough!/Library/metadata/10/10e376bdedb8e421a93a10432c23f710 and /dev/null differ diff --git a/Close Enough!/Library/metadata/10/10e376bdedb8e421a93a10432c23f710.info b/Close Enough!/Library/metadata/10/10e376bdedb8e421a93a10432c23f710.info deleted file mode 100644 index 4fba087..0000000 Binary files a/Close Enough!/Library/metadata/10/10e376bdedb8e421a93a10432c23f710.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/11/1160cb3a61e32eb499ce539ba92d2e20 b/Close Enough!/Library/metadata/11/1160cb3a61e32eb499ce539ba92d2e20 deleted file mode 100644 index 10d8212..0000000 Binary files a/Close Enough!/Library/metadata/11/1160cb3a61e32eb499ce539ba92d2e20 and /dev/null differ diff --git a/Close Enough!/Library/metadata/11/1160cb3a61e32eb499ce539ba92d2e20.info b/Close Enough!/Library/metadata/11/1160cb3a61e32eb499ce539ba92d2e20.info deleted file mode 100644 index a10d9b8..0000000 Binary files a/Close Enough!/Library/metadata/11/1160cb3a61e32eb499ce539ba92d2e20.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/11/1194341cbcd9c47efa7073ca04773d2b b/Close Enough!/Library/metadata/11/1194341cbcd9c47efa7073ca04773d2b deleted file mode 100644 index 6d2660c..0000000 Binary files a/Close Enough!/Library/metadata/11/1194341cbcd9c47efa7073ca04773d2b and /dev/null differ diff --git a/Close Enough!/Library/metadata/11/1194341cbcd9c47efa7073ca04773d2b.info b/Close Enough!/Library/metadata/11/1194341cbcd9c47efa7073ca04773d2b.info deleted file mode 100644 index 52cc9b0..0000000 Binary files a/Close Enough!/Library/metadata/11/1194341cbcd9c47efa7073ca04773d2b.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/11/11c81b4b7f9a7274f99b0693a961ad3f b/Close Enough!/Library/metadata/11/11c81b4b7f9a7274f99b0693a961ad3f deleted file mode 100644 index 92d7809..0000000 Binary files a/Close Enough!/Library/metadata/11/11c81b4b7f9a7274f99b0693a961ad3f and /dev/null differ diff --git a/Close Enough!/Library/metadata/11/11c81b4b7f9a7274f99b0693a961ad3f.info b/Close Enough!/Library/metadata/11/11c81b4b7f9a7274f99b0693a961ad3f.info deleted file mode 100644 index 6e4185a..0000000 Binary files a/Close Enough!/Library/metadata/11/11c81b4b7f9a7274f99b0693a961ad3f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/11/11c81b4b7f9a7274f99b0693a961ad3f.resource b/Close Enough!/Library/metadata/11/11c81b4b7f9a7274f99b0693a961ad3f.resource deleted file mode 100644 index 002bcd8..0000000 Binary files a/Close Enough!/Library/metadata/11/11c81b4b7f9a7274f99b0693a961ad3f.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/11/11f191f8d6382e349be699ab8fe1d300 b/Close Enough!/Library/metadata/11/11f191f8d6382e349be699ab8fe1d300 deleted file mode 100644 index c957f3a..0000000 Binary files a/Close Enough!/Library/metadata/11/11f191f8d6382e349be699ab8fe1d300 and /dev/null differ diff --git a/Close Enough!/Library/metadata/11/11f191f8d6382e349be699ab8fe1d300.info b/Close Enough!/Library/metadata/11/11f191f8d6382e349be699ab8fe1d300.info deleted file mode 100644 index 45928dd..0000000 Binary files a/Close Enough!/Library/metadata/11/11f191f8d6382e349be699ab8fe1d300.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/12/12fd8a0055b84bb59e84c9835a37e333 b/Close Enough!/Library/metadata/12/12fd8a0055b84bb59e84c9835a37e333 deleted file mode 100644 index 820b7fd..0000000 Binary files a/Close Enough!/Library/metadata/12/12fd8a0055b84bb59e84c9835a37e333 and /dev/null differ diff --git a/Close Enough!/Library/metadata/12/12fd8a0055b84bb59e84c9835a37e333.info b/Close Enough!/Library/metadata/12/12fd8a0055b84bb59e84c9835a37e333.info deleted file mode 100644 index 2b82eba..0000000 Binary files a/Close Enough!/Library/metadata/12/12fd8a0055b84bb59e84c9835a37e333.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/13/131c9c805fb71184288c841af7ea71d0 b/Close Enough!/Library/metadata/13/131c9c805fb71184288c841af7ea71d0 deleted file mode 100644 index 52dc688..0000000 Binary files a/Close Enough!/Library/metadata/13/131c9c805fb71184288c841af7ea71d0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/13/131c9c805fb71184288c841af7ea71d0.info b/Close Enough!/Library/metadata/13/131c9c805fb71184288c841af7ea71d0.info deleted file mode 100644 index 9371c72..0000000 Binary files a/Close Enough!/Library/metadata/13/131c9c805fb71184288c841af7ea71d0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/13/1322fd896bbb15bb6e335591b766ae62 b/Close Enough!/Library/metadata/13/1322fd896bbb15bb6e335591b766ae62 deleted file mode 100644 index e524538..0000000 Binary files a/Close Enough!/Library/metadata/13/1322fd896bbb15bb6e335591b766ae62 and /dev/null differ diff --git a/Close Enough!/Library/metadata/13/1322fd896bbb15bb6e335591b766ae62.info b/Close Enough!/Library/metadata/13/1322fd896bbb15bb6e335591b766ae62.info deleted file mode 100644 index 7e86026..0000000 Binary files a/Close Enough!/Library/metadata/13/1322fd896bbb15bb6e335591b766ae62.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/13/134fe99eed19c48428491eac7d74694b b/Close Enough!/Library/metadata/13/134fe99eed19c48428491eac7d74694b deleted file mode 100644 index 2442bb6..0000000 Binary files a/Close Enough!/Library/metadata/13/134fe99eed19c48428491eac7d74694b and /dev/null differ diff --git a/Close Enough!/Library/metadata/13/134fe99eed19c48428491eac7d74694b.info b/Close Enough!/Library/metadata/13/134fe99eed19c48428491eac7d74694b.info deleted file mode 100644 index aa5a44f..0000000 Binary files a/Close Enough!/Library/metadata/13/134fe99eed19c48428491eac7d74694b.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/13/139086bdd1c7fd84b81df0968a55ce2d b/Close Enough!/Library/metadata/13/139086bdd1c7fd84b81df0968a55ce2d deleted file mode 100644 index e7b173f..0000000 Binary files a/Close Enough!/Library/metadata/13/139086bdd1c7fd84b81df0968a55ce2d and /dev/null differ diff --git a/Close Enough!/Library/metadata/13/139086bdd1c7fd84b81df0968a55ce2d.info b/Close Enough!/Library/metadata/13/139086bdd1c7fd84b81df0968a55ce2d.info deleted file mode 100644 index 1dba988..0000000 Binary files a/Close Enough!/Library/metadata/13/139086bdd1c7fd84b81df0968a55ce2d.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/13/13eb5a82bdc18418a887cfd2a7d4f927 b/Close Enough!/Library/metadata/13/13eb5a82bdc18418a887cfd2a7d4f927 deleted file mode 100644 index dfd0ffb..0000000 Binary files a/Close Enough!/Library/metadata/13/13eb5a82bdc18418a887cfd2a7d4f927 and /dev/null differ diff --git a/Close Enough!/Library/metadata/13/13eb5a82bdc18418a887cfd2a7d4f927.info b/Close Enough!/Library/metadata/13/13eb5a82bdc18418a887cfd2a7d4f927.info deleted file mode 100644 index 68a9c6a..0000000 Binary files a/Close Enough!/Library/metadata/13/13eb5a82bdc18418a887cfd2a7d4f927.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/15/15a8add8c0dda460eb2feb2c4be5c2ee b/Close Enough!/Library/metadata/15/15a8add8c0dda460eb2feb2c4be5c2ee deleted file mode 100644 index 9873a5e..0000000 Binary files a/Close Enough!/Library/metadata/15/15a8add8c0dda460eb2feb2c4be5c2ee and /dev/null differ diff --git a/Close Enough!/Library/metadata/15/15a8add8c0dda460eb2feb2c4be5c2ee.info b/Close Enough!/Library/metadata/15/15a8add8c0dda460eb2feb2c4be5c2ee.info deleted file mode 100644 index be433c2..0000000 Binary files a/Close Enough!/Library/metadata/15/15a8add8c0dda460eb2feb2c4be5c2ee.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/15/15be9c691b85a41a39c18beeff87e21b b/Close Enough!/Library/metadata/15/15be9c691b85a41a39c18beeff87e21b deleted file mode 100644 index 1543657..0000000 Binary files a/Close Enough!/Library/metadata/15/15be9c691b85a41a39c18beeff87e21b and /dev/null differ diff --git a/Close Enough!/Library/metadata/15/15be9c691b85a41a39c18beeff87e21b.info b/Close Enough!/Library/metadata/15/15be9c691b85a41a39c18beeff87e21b.info deleted file mode 100644 index 65f25f4..0000000 Binary files a/Close Enough!/Library/metadata/15/15be9c691b85a41a39c18beeff87e21b.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/15/15bf9c691b85b41a39c18bee2f87e21b b/Close Enough!/Library/metadata/15/15bf9c691b85b41a39c18bee2f87e21b deleted file mode 100644 index 935e135..0000000 Binary files a/Close Enough!/Library/metadata/15/15bf9c691b85b41a39c18bee2f87e21b and /dev/null differ diff --git a/Close Enough!/Library/metadata/15/15bf9c691b85b41a39c18bee2f87e21b.info b/Close Enough!/Library/metadata/15/15bf9c691b85b41a39c18bee2f87e21b.info deleted file mode 100644 index 7480e98..0000000 Binary files a/Close Enough!/Library/metadata/15/15bf9c691b85b41a39c18bee2f87e21b.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/16/164ede637b85c41c893d0619c9439b7c b/Close Enough!/Library/metadata/16/164ede637b85c41c893d0619c9439b7c deleted file mode 100644 index 4b64133..0000000 Binary files a/Close Enough!/Library/metadata/16/164ede637b85c41c893d0619c9439b7c and /dev/null differ diff --git a/Close Enough!/Library/metadata/16/164ede637b85c41c893d0619c9439b7c.info b/Close Enough!/Library/metadata/16/164ede637b85c41c893d0619c9439b7c.info deleted file mode 100644 index 02e33a6..0000000 Binary files a/Close Enough!/Library/metadata/16/164ede637b85c41c893d0619c9439b7c.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/17/1745a594dbe947744ad1b745cb90956a b/Close Enough!/Library/metadata/17/1745a594dbe947744ad1b745cb90956a deleted file mode 100644 index 725b253..0000000 Binary files a/Close Enough!/Library/metadata/17/1745a594dbe947744ad1b745cb90956a and /dev/null differ diff --git a/Close Enough!/Library/metadata/17/1745a594dbe947744ad1b745cb90956a.info b/Close Enough!/Library/metadata/17/1745a594dbe947744ad1b745cb90956a.info deleted file mode 100644 index 9fc1880..0000000 Binary files a/Close Enough!/Library/metadata/17/1745a594dbe947744ad1b745cb90956a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/17/176c16dc964b2c94a9283e84f1cc8899 b/Close Enough!/Library/metadata/17/176c16dc964b2c94a9283e84f1cc8899 deleted file mode 100644 index b6b52bc..0000000 Binary files a/Close Enough!/Library/metadata/17/176c16dc964b2c94a9283e84f1cc8899 and /dev/null differ diff --git a/Close Enough!/Library/metadata/17/176c16dc964b2c94a9283e84f1cc8899.info b/Close Enough!/Library/metadata/17/176c16dc964b2c94a9283e84f1cc8899.info deleted file mode 100644 index 943d495..0000000 Binary files a/Close Enough!/Library/metadata/17/176c16dc964b2c94a9283e84f1cc8899.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/17/176c16dc964b2c94a9283e84f1cc8899.resource b/Close Enough!/Library/metadata/17/176c16dc964b2c94a9283e84f1cc8899.resource deleted file mode 100644 index d58f341..0000000 Binary files a/Close Enough!/Library/metadata/17/176c16dc964b2c94a9283e84f1cc8899.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/19/1952f021273af4d43a61a2b428236c69 b/Close Enough!/Library/metadata/19/1952f021273af4d43a61a2b428236c69 deleted file mode 100644 index 59da678..0000000 Binary files a/Close Enough!/Library/metadata/19/1952f021273af4d43a61a2b428236c69 and /dev/null differ diff --git a/Close Enough!/Library/metadata/19/1952f021273af4d43a61a2b428236c69.info b/Close Enough!/Library/metadata/19/1952f021273af4d43a61a2b428236c69.info deleted file mode 100644 index 9f171ff..0000000 Binary files a/Close Enough!/Library/metadata/19/1952f021273af4d43a61a2b428236c69.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/19/1998a82d9ac19624fb69ae286855fd42 b/Close Enough!/Library/metadata/19/1998a82d9ac19624fb69ae286855fd42 deleted file mode 100644 index 167746e..0000000 Binary files a/Close Enough!/Library/metadata/19/1998a82d9ac19624fb69ae286855fd42 and /dev/null differ diff --git a/Close Enough!/Library/metadata/19/1998a82d9ac19624fb69ae286855fd42.info b/Close Enough!/Library/metadata/19/1998a82d9ac19624fb69ae286855fd42.info deleted file mode 100644 index c285cc8..0000000 Binary files a/Close Enough!/Library/metadata/19/1998a82d9ac19624fb69ae286855fd42.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/19/1998a82d9ac19624fb69ae286855fd42.resource b/Close Enough!/Library/metadata/19/1998a82d9ac19624fb69ae286855fd42.resource deleted file mode 100644 index e5a9f23..0000000 Binary files a/Close Enough!/Library/metadata/19/1998a82d9ac19624fb69ae286855fd42.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/19/19d866d3f6c29664797c6105e3200086 b/Close Enough!/Library/metadata/19/19d866d3f6c29664797c6105e3200086 deleted file mode 100644 index 895b338..0000000 Binary files a/Close Enough!/Library/metadata/19/19d866d3f6c29664797c6105e3200086 and /dev/null differ diff --git a/Close Enough!/Library/metadata/19/19d866d3f6c29664797c6105e3200086.info b/Close Enough!/Library/metadata/19/19d866d3f6c29664797c6105e3200086.info deleted file mode 100644 index a3acc8b..0000000 Binary files a/Close Enough!/Library/metadata/19/19d866d3f6c29664797c6105e3200086.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/19/19d866d3f6c29664797c6105e3200086.resource b/Close Enough!/Library/metadata/19/19d866d3f6c29664797c6105e3200086.resource deleted file mode 100644 index cc0aac0..0000000 Binary files a/Close Enough!/Library/metadata/19/19d866d3f6c29664797c6105e3200086.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/19/19e622e4234805a4b9eba29b4dfd2ada b/Close Enough!/Library/metadata/19/19e622e4234805a4b9eba29b4dfd2ada deleted file mode 100644 index 5c3abc9..0000000 Binary files a/Close Enough!/Library/metadata/19/19e622e4234805a4b9eba29b4dfd2ada and /dev/null differ diff --git a/Close Enough!/Library/metadata/19/19e622e4234805a4b9eba29b4dfd2ada.info b/Close Enough!/Library/metadata/19/19e622e4234805a4b9eba29b4dfd2ada.info deleted file mode 100644 index 17f45b5..0000000 Binary files a/Close Enough!/Library/metadata/19/19e622e4234805a4b9eba29b4dfd2ada.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/1b/1b289870ad53a9b4d9319c3a99c75c93 b/Close Enough!/Library/metadata/1b/1b289870ad53a9b4d9319c3a99c75c93 deleted file mode 100644 index 0a7d0ab..0000000 Binary files a/Close Enough!/Library/metadata/1b/1b289870ad53a9b4d9319c3a99c75c93 and /dev/null differ diff --git a/Close Enough!/Library/metadata/1b/1b289870ad53a9b4d9319c3a99c75c93.info b/Close Enough!/Library/metadata/1b/1b289870ad53a9b4d9319c3a99c75c93.info deleted file mode 100644 index 765f35e..0000000 Binary files a/Close Enough!/Library/metadata/1b/1b289870ad53a9b4d9319c3a99c75c93.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/1b/1b32bcce201b4494ea8848326290c5d5 b/Close Enough!/Library/metadata/1b/1b32bcce201b4494ea8848326290c5d5 deleted file mode 100644 index fe3dcfc..0000000 Binary files a/Close Enough!/Library/metadata/1b/1b32bcce201b4494ea8848326290c5d5 and /dev/null differ diff --git a/Close Enough!/Library/metadata/1b/1b32bcce201b4494ea8848326290c5d5.info b/Close Enough!/Library/metadata/1b/1b32bcce201b4494ea8848326290c5d5.info deleted file mode 100644 index 4c07946..0000000 Binary files a/Close Enough!/Library/metadata/1b/1b32bcce201b4494ea8848326290c5d5.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/1b/1ba0fda62ec7bb44ebfedb40b90b8c34 b/Close Enough!/Library/metadata/1b/1ba0fda62ec7bb44ebfedb40b90b8c34 deleted file mode 100644 index 29ac6cf..0000000 Binary files a/Close Enough!/Library/metadata/1b/1ba0fda62ec7bb44ebfedb40b90b8c34 and /dev/null differ diff --git a/Close Enough!/Library/metadata/1b/1ba0fda62ec7bb44ebfedb40b90b8c34.info b/Close Enough!/Library/metadata/1b/1ba0fda62ec7bb44ebfedb40b90b8c34.info deleted file mode 100644 index 4ffe051..0000000 Binary files a/Close Enough!/Library/metadata/1b/1ba0fda62ec7bb44ebfedb40b90b8c34.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/1c/1c03b08b33be3de44a4403c6ad7f693b b/Close Enough!/Library/metadata/1c/1c03b08b33be3de44a4403c6ad7f693b deleted file mode 100644 index 6e206db..0000000 Binary files a/Close Enough!/Library/metadata/1c/1c03b08b33be3de44a4403c6ad7f693b and /dev/null differ diff --git a/Close Enough!/Library/metadata/1c/1c03b08b33be3de44a4403c6ad7f693b.info b/Close Enough!/Library/metadata/1c/1c03b08b33be3de44a4403c6ad7f693b.info deleted file mode 100644 index 74874ea..0000000 Binary files a/Close Enough!/Library/metadata/1c/1c03b08b33be3de44a4403c6ad7f693b.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/1c/1c6d1fbb51834b64847b1b73a75bfc77 b/Close Enough!/Library/metadata/1c/1c6d1fbb51834b64847b1b73a75bfc77 deleted file mode 100644 index 35f8c45..0000000 Binary files a/Close Enough!/Library/metadata/1c/1c6d1fbb51834b64847b1b73a75bfc77 and /dev/null differ diff --git a/Close Enough!/Library/metadata/1c/1c6d1fbb51834b64847b1b73a75bfc77.info b/Close Enough!/Library/metadata/1c/1c6d1fbb51834b64847b1b73a75bfc77.info deleted file mode 100644 index 49491d0..0000000 Binary files a/Close Enough!/Library/metadata/1c/1c6d1fbb51834b64847b1b73a75bfc77.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/1d/1d17c9f1a79cf43479d9ac49a7e77a12 b/Close Enough!/Library/metadata/1d/1d17c9f1a79cf43479d9ac49a7e77a12 deleted file mode 100644 index af85a48..0000000 Binary files a/Close Enough!/Library/metadata/1d/1d17c9f1a79cf43479d9ac49a7e77a12 and /dev/null differ diff --git a/Close Enough!/Library/metadata/1d/1d17c9f1a79cf43479d9ac49a7e77a12.info b/Close Enough!/Library/metadata/1d/1d17c9f1a79cf43479d9ac49a7e77a12.info deleted file mode 100644 index adba30e..0000000 Binary files a/Close Enough!/Library/metadata/1d/1d17c9f1a79cf43479d9ac49a7e77a12.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/1d/1d1f5acf0fdddd54cbd02f890bae012e b/Close Enough!/Library/metadata/1d/1d1f5acf0fdddd54cbd02f890bae012e deleted file mode 100644 index a9c358c..0000000 Binary files a/Close Enough!/Library/metadata/1d/1d1f5acf0fdddd54cbd02f890bae012e and /dev/null differ diff --git a/Close Enough!/Library/metadata/1d/1d1f5acf0fdddd54cbd02f890bae012e.info b/Close Enough!/Library/metadata/1d/1d1f5acf0fdddd54cbd02f890bae012e.info deleted file mode 100644 index 9cbd9c3..0000000 Binary files a/Close Enough!/Library/metadata/1d/1d1f5acf0fdddd54cbd02f890bae012e.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/1d/1d52385378435406e9e8c2a7d679daef b/Close Enough!/Library/metadata/1d/1d52385378435406e9e8c2a7d679daef deleted file mode 100644 index 3f81388..0000000 Binary files a/Close Enough!/Library/metadata/1d/1d52385378435406e9e8c2a7d679daef and /dev/null differ diff --git a/Close Enough!/Library/metadata/1d/1d52385378435406e9e8c2a7d679daef.info b/Close Enough!/Library/metadata/1d/1d52385378435406e9e8c2a7d679daef.info deleted file mode 100644 index 8cb1875..0000000 Binary files a/Close Enough!/Library/metadata/1d/1d52385378435406e9e8c2a7d679daef.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/1e/1e695ba23d153c84690e962d6a3cb903 b/Close Enough!/Library/metadata/1e/1e695ba23d153c84690e962d6a3cb903 deleted file mode 100644 index 0cafe97..0000000 Binary files a/Close Enough!/Library/metadata/1e/1e695ba23d153c84690e962d6a3cb903 and /dev/null differ diff --git a/Close Enough!/Library/metadata/1e/1e695ba23d153c84690e962d6a3cb903.info b/Close Enough!/Library/metadata/1e/1e695ba23d153c84690e962d6a3cb903.info deleted file mode 100644 index 6c8e992..0000000 Binary files a/Close Enough!/Library/metadata/1e/1e695ba23d153c84690e962d6a3cb903.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/1e/1ed2f64f6b243ef4fab78cb32744133f b/Close Enough!/Library/metadata/1e/1ed2f64f6b243ef4fab78cb32744133f deleted file mode 100644 index 72f593e..0000000 Binary files a/Close Enough!/Library/metadata/1e/1ed2f64f6b243ef4fab78cb32744133f and /dev/null differ diff --git a/Close Enough!/Library/metadata/1e/1ed2f64f6b243ef4fab78cb32744133f.info b/Close Enough!/Library/metadata/1e/1ed2f64f6b243ef4fab78cb32744133f.info deleted file mode 100644 index 7bc3bec..0000000 Binary files a/Close Enough!/Library/metadata/1e/1ed2f64f6b243ef4fab78cb32744133f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/1f/1feb28054602bfc41bd953063a359f29 b/Close Enough!/Library/metadata/1f/1feb28054602bfc41bd953063a359f29 deleted file mode 100644 index 1272e2b..0000000 Binary files a/Close Enough!/Library/metadata/1f/1feb28054602bfc41bd953063a359f29 and /dev/null differ diff --git a/Close Enough!/Library/metadata/1f/1feb28054602bfc41bd953063a359f29.info b/Close Enough!/Library/metadata/1f/1feb28054602bfc41bd953063a359f29.info deleted file mode 100644 index 3761e63..0000000 Binary files a/Close Enough!/Library/metadata/1f/1feb28054602bfc41bd953063a359f29.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/1f/1feb28054602bfc41bd953063a359f29.resource b/Close Enough!/Library/metadata/1f/1feb28054602bfc41bd953063a359f29.resource deleted file mode 100644 index c147ea7..0000000 Binary files a/Close Enough!/Library/metadata/1f/1feb28054602bfc41bd953063a359f29.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/21/21250ca079e558f43b1f9be17dc5e647 b/Close Enough!/Library/metadata/21/21250ca079e558f43b1f9be17dc5e647 deleted file mode 100644 index 8af9e75..0000000 Binary files a/Close Enough!/Library/metadata/21/21250ca079e558f43b1f9be17dc5e647 and /dev/null differ diff --git a/Close Enough!/Library/metadata/21/21250ca079e558f43b1f9be17dc5e647.info b/Close Enough!/Library/metadata/21/21250ca079e558f43b1f9be17dc5e647.info deleted file mode 100644 index 4bdcd77..0000000 Binary files a/Close Enough!/Library/metadata/21/21250ca079e558f43b1f9be17dc5e647.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/21/216c0b23a00598644aadafdb01fd74a7 b/Close Enough!/Library/metadata/21/216c0b23a00598644aadafdb01fd74a7 deleted file mode 100644 index 91ba46b..0000000 Binary files a/Close Enough!/Library/metadata/21/216c0b23a00598644aadafdb01fd74a7 and /dev/null differ diff --git a/Close Enough!/Library/metadata/21/216c0b23a00598644aadafdb01fd74a7.info b/Close Enough!/Library/metadata/21/216c0b23a00598644aadafdb01fd74a7.info deleted file mode 100644 index 16f9588..0000000 Binary files a/Close Enough!/Library/metadata/21/216c0b23a00598644aadafdb01fd74a7.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/21/21eff446d50eaf44a85985cd4c0b6fa1 b/Close Enough!/Library/metadata/21/21eff446d50eaf44a85985cd4c0b6fa1 deleted file mode 100644 index e2cceee..0000000 Binary files a/Close Enough!/Library/metadata/21/21eff446d50eaf44a85985cd4c0b6fa1 and /dev/null differ diff --git a/Close Enough!/Library/metadata/21/21eff446d50eaf44a85985cd4c0b6fa1.info b/Close Enough!/Library/metadata/21/21eff446d50eaf44a85985cd4c0b6fa1.info deleted file mode 100644 index 084273e..0000000 Binary files a/Close Enough!/Library/metadata/21/21eff446d50eaf44a85985cd4c0b6fa1.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/22/220224b43fc464c28bc0e8de8f54a432 b/Close Enough!/Library/metadata/22/220224b43fc464c28bc0e8de8f54a432 deleted file mode 100644 index 3decf53..0000000 Binary files a/Close Enough!/Library/metadata/22/220224b43fc464c28bc0e8de8f54a432 and /dev/null differ diff --git a/Close Enough!/Library/metadata/22/220224b43fc464c28bc0e8de8f54a432.info b/Close Enough!/Library/metadata/22/220224b43fc464c28bc0e8de8f54a432.info deleted file mode 100644 index 039ca1f..0000000 Binary files a/Close Enough!/Library/metadata/22/220224b43fc464c28bc0e8de8f54a432.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/22/224ede67b4f3a4109bfec4d5cb161b05 b/Close Enough!/Library/metadata/22/224ede67b4f3a4109bfec4d5cb161b05 deleted file mode 100644 index c8c83aa..0000000 Binary files a/Close Enough!/Library/metadata/22/224ede67b4f3a4109bfec4d5cb161b05 and /dev/null differ diff --git a/Close Enough!/Library/metadata/22/224ede67b4f3a4109bfec4d5cb161b05.info b/Close Enough!/Library/metadata/22/224ede67b4f3a4109bfec4d5cb161b05.info deleted file mode 100644 index 0ea5642..0000000 Binary files a/Close Enough!/Library/metadata/22/224ede67b4f3a4109bfec4d5cb161b05.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/26/2682a692a2be7e14e901a738c7806da0 b/Close Enough!/Library/metadata/26/2682a692a2be7e14e901a738c7806da0 deleted file mode 100644 index 39a892d..0000000 Binary files a/Close Enough!/Library/metadata/26/2682a692a2be7e14e901a738c7806da0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/26/2682a692a2be7e14e901a738c7806da0.info b/Close Enough!/Library/metadata/26/2682a692a2be7e14e901a738c7806da0.info deleted file mode 100644 index e9959ab..0000000 Binary files a/Close Enough!/Library/metadata/26/2682a692a2be7e14e901a738c7806da0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/26/2689f980336715d4992d6dd9e693576d b/Close Enough!/Library/metadata/26/2689f980336715d4992d6dd9e693576d deleted file mode 100644 index 59d1d6b..0000000 Binary files a/Close Enough!/Library/metadata/26/2689f980336715d4992d6dd9e693576d and /dev/null differ diff --git a/Close Enough!/Library/metadata/26/2689f980336715d4992d6dd9e693576d.info b/Close Enough!/Library/metadata/26/2689f980336715d4992d6dd9e693576d.info deleted file mode 100644 index 66b7f49..0000000 Binary files a/Close Enough!/Library/metadata/26/2689f980336715d4992d6dd9e693576d.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/26/26c0bbb8e6792b546bf28bbe08d7c96d b/Close Enough!/Library/metadata/26/26c0bbb8e6792b546bf28bbe08d7c96d deleted file mode 100644 index a864e3c..0000000 Binary files a/Close Enough!/Library/metadata/26/26c0bbb8e6792b546bf28bbe08d7c96d and /dev/null differ diff --git a/Close Enough!/Library/metadata/26/26c0bbb8e6792b546bf28bbe08d7c96d.info b/Close Enough!/Library/metadata/26/26c0bbb8e6792b546bf28bbe08d7c96d.info deleted file mode 100644 index 63b880a..0000000 Binary files a/Close Enough!/Library/metadata/26/26c0bbb8e6792b546bf28bbe08d7c96d.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/26/26c225bad82fac84593755b91366e4f6 b/Close Enough!/Library/metadata/26/26c225bad82fac84593755b91366e4f6 deleted file mode 100644 index 5643257..0000000 Binary files a/Close Enough!/Library/metadata/26/26c225bad82fac84593755b91366e4f6 and /dev/null differ diff --git a/Close Enough!/Library/metadata/26/26c225bad82fac84593755b91366e4f6.info b/Close Enough!/Library/metadata/26/26c225bad82fac84593755b91366e4f6.info deleted file mode 100644 index 661bde6..0000000 Binary files a/Close Enough!/Library/metadata/26/26c225bad82fac84593755b91366e4f6.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/28/28efbdc99bfad6b4f81860f702ce4476 b/Close Enough!/Library/metadata/28/28efbdc99bfad6b4f81860f702ce4476 deleted file mode 100644 index 238cca3..0000000 Binary files a/Close Enough!/Library/metadata/28/28efbdc99bfad6b4f81860f702ce4476 and /dev/null differ diff --git a/Close Enough!/Library/metadata/28/28efbdc99bfad6b4f81860f702ce4476.info b/Close Enough!/Library/metadata/28/28efbdc99bfad6b4f81860f702ce4476.info deleted file mode 100644 index 9224e7e..0000000 Binary files a/Close Enough!/Library/metadata/28/28efbdc99bfad6b4f81860f702ce4476.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/29/297a44943c41c094d8aa3fff27623d82 b/Close Enough!/Library/metadata/29/297a44943c41c094d8aa3fff27623d82 deleted file mode 100644 index 6c05487..0000000 Binary files a/Close Enough!/Library/metadata/29/297a44943c41c094d8aa3fff27623d82 and /dev/null differ diff --git a/Close Enough!/Library/metadata/29/297a44943c41c094d8aa3fff27623d82.info b/Close Enough!/Library/metadata/29/297a44943c41c094d8aa3fff27623d82.info deleted file mode 100644 index 0e60486..0000000 Binary files a/Close Enough!/Library/metadata/29/297a44943c41c094d8aa3fff27623d82.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/29/29a40b844aa5acb458a045088724d344 b/Close Enough!/Library/metadata/29/29a40b844aa5acb458a045088724d344 deleted file mode 100644 index 1d90cdc..0000000 Binary files a/Close Enough!/Library/metadata/29/29a40b844aa5acb458a045088724d344 and /dev/null differ diff --git a/Close Enough!/Library/metadata/29/29a40b844aa5acb458a045088724d344.info b/Close Enough!/Library/metadata/29/29a40b844aa5acb458a045088724d344.info deleted file mode 100644 index 33d645b..0000000 Binary files a/Close Enough!/Library/metadata/29/29a40b844aa5acb458a045088724d344.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/29/29a40b844aa5acb458a045088724d344.resource b/Close Enough!/Library/metadata/29/29a40b844aa5acb458a045088724d344.resource deleted file mode 100644 index ff167f3..0000000 Binary files a/Close Enough!/Library/metadata/29/29a40b844aa5acb458a045088724d344.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/2a/2a81e83402ca5c34e893b5fa67bded99 b/Close Enough!/Library/metadata/2a/2a81e83402ca5c34e893b5fa67bded99 deleted file mode 100644 index d99a9d1..0000000 Binary files a/Close Enough!/Library/metadata/2a/2a81e83402ca5c34e893b5fa67bded99 and /dev/null differ diff --git a/Close Enough!/Library/metadata/2a/2a81e83402ca5c34e893b5fa67bded99.info b/Close Enough!/Library/metadata/2a/2a81e83402ca5c34e893b5fa67bded99.info deleted file mode 100644 index 05cedb0..0000000 Binary files a/Close Enough!/Library/metadata/2a/2a81e83402ca5c34e893b5fa67bded99.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/2a/2a893d93c68f7e14bb6e083e657475a0 b/Close Enough!/Library/metadata/2a/2a893d93c68f7e14bb6e083e657475a0 deleted file mode 100644 index a2c2fe3..0000000 Binary files a/Close Enough!/Library/metadata/2a/2a893d93c68f7e14bb6e083e657475a0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/2a/2a893d93c68f7e14bb6e083e657475a0.info b/Close Enough!/Library/metadata/2a/2a893d93c68f7e14bb6e083e657475a0.info deleted file mode 100644 index 5d1562a..0000000 Binary files a/Close Enough!/Library/metadata/2a/2a893d93c68f7e14bb6e083e657475a0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/2b/2bcd6b3920775cd4dbcbcfb6c69f668e b/Close Enough!/Library/metadata/2b/2bcd6b3920775cd4dbcbcfb6c69f668e deleted file mode 100644 index c16d442..0000000 Binary files a/Close Enough!/Library/metadata/2b/2bcd6b3920775cd4dbcbcfb6c69f668e and /dev/null differ diff --git a/Close Enough!/Library/metadata/2b/2bcd6b3920775cd4dbcbcfb6c69f668e.info b/Close Enough!/Library/metadata/2b/2bcd6b3920775cd4dbcbcfb6c69f668e.info deleted file mode 100644 index f3e7ed8..0000000 Binary files a/Close Enough!/Library/metadata/2b/2bcd6b3920775cd4dbcbcfb6c69f668e.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/2c/2c0536098f9a1644dacccbe9f8b6d5a2 b/Close Enough!/Library/metadata/2c/2c0536098f9a1644dacccbe9f8b6d5a2 deleted file mode 100644 index 5437ea1..0000000 Binary files a/Close Enough!/Library/metadata/2c/2c0536098f9a1644dacccbe9f8b6d5a2 and /dev/null differ diff --git a/Close Enough!/Library/metadata/2c/2c0536098f9a1644dacccbe9f8b6d5a2.info b/Close Enough!/Library/metadata/2c/2c0536098f9a1644dacccbe9f8b6d5a2.info deleted file mode 100644 index 52af979..0000000 Binary files a/Close Enough!/Library/metadata/2c/2c0536098f9a1644dacccbe9f8b6d5a2.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/2c/2c0536098f9a1644dacccbe9f8b6d5a2.resource b/Close Enough!/Library/metadata/2c/2c0536098f9a1644dacccbe9f8b6d5a2.resource deleted file mode 100644 index 237d66f..0000000 Binary files a/Close Enough!/Library/metadata/2c/2c0536098f9a1644dacccbe9f8b6d5a2.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/2c/2c0bcb700a3d1ea4f8bc5e7f607aa5f1 b/Close Enough!/Library/metadata/2c/2c0bcb700a3d1ea4f8bc5e7f607aa5f1 deleted file mode 100644 index a3616f6..0000000 Binary files a/Close Enough!/Library/metadata/2c/2c0bcb700a3d1ea4f8bc5e7f607aa5f1 and /dev/null differ diff --git a/Close Enough!/Library/metadata/2c/2c0bcb700a3d1ea4f8bc5e7f607aa5f1.info b/Close Enough!/Library/metadata/2c/2c0bcb700a3d1ea4f8bc5e7f607aa5f1.info deleted file mode 100644 index f5aca54..0000000 Binary files a/Close Enough!/Library/metadata/2c/2c0bcb700a3d1ea4f8bc5e7f607aa5f1.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/2c/2cf28051c91a64947a27d86020bf21b9 b/Close Enough!/Library/metadata/2c/2cf28051c91a64947a27d86020bf21b9 deleted file mode 100644 index 34af6e7..0000000 Binary files a/Close Enough!/Library/metadata/2c/2cf28051c91a64947a27d86020bf21b9 and /dev/null differ diff --git a/Close Enough!/Library/metadata/2c/2cf28051c91a64947a27d86020bf21b9.info b/Close Enough!/Library/metadata/2c/2cf28051c91a64947a27d86020bf21b9.info deleted file mode 100644 index 3885ed1..0000000 Binary files a/Close Enough!/Library/metadata/2c/2cf28051c91a64947a27d86020bf21b9.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/2d/2d4d46c70fdd242668a56e99799e8540 b/Close Enough!/Library/metadata/2d/2d4d46c70fdd242668a56e99799e8540 deleted file mode 100644 index 35e104d..0000000 Binary files a/Close Enough!/Library/metadata/2d/2d4d46c70fdd242668a56e99799e8540 and /dev/null differ diff --git a/Close Enough!/Library/metadata/2d/2d4d46c70fdd242668a56e99799e8540.info b/Close Enough!/Library/metadata/2d/2d4d46c70fdd242668a56e99799e8540.info deleted file mode 100644 index b8db6a0..0000000 Binary files a/Close Enough!/Library/metadata/2d/2d4d46c70fdd242668a56e99799e8540.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/2e/2e009229a990a3744ab82801fb0fc4e5 b/Close Enough!/Library/metadata/2e/2e009229a990a3744ab82801fb0fc4e5 deleted file mode 100644 index 2d3a110..0000000 Binary files a/Close Enough!/Library/metadata/2e/2e009229a990a3744ab82801fb0fc4e5 and /dev/null differ diff --git a/Close Enough!/Library/metadata/2e/2e009229a990a3744ab82801fb0fc4e5.info b/Close Enough!/Library/metadata/2e/2e009229a990a3744ab82801fb0fc4e5.info deleted file mode 100644 index 507700b..0000000 Binary files a/Close Enough!/Library/metadata/2e/2e009229a990a3744ab82801fb0fc4e5.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/2e/2e0c1663b1b8df94e9d959cc962d6b66 b/Close Enough!/Library/metadata/2e/2e0c1663b1b8df94e9d959cc962d6b66 deleted file mode 100644 index e1755dd..0000000 Binary files a/Close Enough!/Library/metadata/2e/2e0c1663b1b8df94e9d959cc962d6b66 and /dev/null differ diff --git a/Close Enough!/Library/metadata/2e/2e0c1663b1b8df94e9d959cc962d6b66.info b/Close Enough!/Library/metadata/2e/2e0c1663b1b8df94e9d959cc962d6b66.info deleted file mode 100644 index cdfc2c7..0000000 Binary files a/Close Enough!/Library/metadata/2e/2e0c1663b1b8df94e9d959cc962d6b66.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/2f/2f54f6f6eb14f4aeea75480394f7120d b/Close Enough!/Library/metadata/2f/2f54f6f6eb14f4aeea75480394f7120d deleted file mode 100644 index 2b68bc7..0000000 Binary files a/Close Enough!/Library/metadata/2f/2f54f6f6eb14f4aeea75480394f7120d and /dev/null differ diff --git a/Close Enough!/Library/metadata/2f/2f54f6f6eb14f4aeea75480394f7120d.info b/Close Enough!/Library/metadata/2f/2f54f6f6eb14f4aeea75480394f7120d.info deleted file mode 100644 index 8a342cf..0000000 Binary files a/Close Enough!/Library/metadata/2f/2f54f6f6eb14f4aeea75480394f7120d.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/2f/2fc8e7df4caaef14e97fb5dbb4825c5a b/Close Enough!/Library/metadata/2f/2fc8e7df4caaef14e97fb5dbb4825c5a deleted file mode 100644 index 438c0b0..0000000 Binary files a/Close Enough!/Library/metadata/2f/2fc8e7df4caaef14e97fb5dbb4825c5a and /dev/null differ diff --git a/Close Enough!/Library/metadata/2f/2fc8e7df4caaef14e97fb5dbb4825c5a.info b/Close Enough!/Library/metadata/2f/2fc8e7df4caaef14e97fb5dbb4825c5a.info deleted file mode 100644 index e47a84d..0000000 Binary files a/Close Enough!/Library/metadata/2f/2fc8e7df4caaef14e97fb5dbb4825c5a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/2f/2fe3476eabbbb6c448e6b55a2cc471f5 b/Close Enough!/Library/metadata/2f/2fe3476eabbbb6c448e6b55a2cc471f5 deleted file mode 100644 index d309320..0000000 Binary files a/Close Enough!/Library/metadata/2f/2fe3476eabbbb6c448e6b55a2cc471f5 and /dev/null differ diff --git a/Close Enough!/Library/metadata/2f/2fe3476eabbbb6c448e6b55a2cc471f5.info b/Close Enough!/Library/metadata/2f/2fe3476eabbbb6c448e6b55a2cc471f5.info deleted file mode 100644 index b7d8e89..0000000 Binary files a/Close Enough!/Library/metadata/2f/2fe3476eabbbb6c448e6b55a2cc471f5.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/30/3073fdea3110944638369df2c64dfb2a b/Close Enough!/Library/metadata/30/3073fdea3110944638369df2c64dfb2a deleted file mode 100644 index db28e9e..0000000 Binary files a/Close Enough!/Library/metadata/30/3073fdea3110944638369df2c64dfb2a and /dev/null differ diff --git a/Close Enough!/Library/metadata/30/3073fdea3110944638369df2c64dfb2a.info b/Close Enough!/Library/metadata/30/3073fdea3110944638369df2c64dfb2a.info deleted file mode 100644 index aa2a094..0000000 Binary files a/Close Enough!/Library/metadata/30/3073fdea3110944638369df2c64dfb2a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/30/30fddba69a8bcbf45b0034896a9a8d71 b/Close Enough!/Library/metadata/30/30fddba69a8bcbf45b0034896a9a8d71 deleted file mode 100644 index a934b2f..0000000 Binary files a/Close Enough!/Library/metadata/30/30fddba69a8bcbf45b0034896a9a8d71 and /dev/null differ diff --git a/Close Enough!/Library/metadata/30/30fddba69a8bcbf45b0034896a9a8d71.info b/Close Enough!/Library/metadata/30/30fddba69a8bcbf45b0034896a9a8d71.info deleted file mode 100644 index 7fa84c6..0000000 Binary files a/Close Enough!/Library/metadata/30/30fddba69a8bcbf45b0034896a9a8d71.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/30/30fddba69a8bcbf45b0034896a9a8d71.resource b/Close Enough!/Library/metadata/30/30fddba69a8bcbf45b0034896a9a8d71.resource deleted file mode 100644 index 7e1b2eb..0000000 Binary files a/Close Enough!/Library/metadata/30/30fddba69a8bcbf45b0034896a9a8d71.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/32/32188fd89022c154c81befa2f0e00be0 b/Close Enough!/Library/metadata/32/32188fd89022c154c81befa2f0e00be0 deleted file mode 100644 index 88fb16a..0000000 Binary files a/Close Enough!/Library/metadata/32/32188fd89022c154c81befa2f0e00be0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/32/32188fd89022c154c81befa2f0e00be0.info b/Close Enough!/Library/metadata/32/32188fd89022c154c81befa2f0e00be0.info deleted file mode 100644 index f353132..0000000 Binary files a/Close Enough!/Library/metadata/32/32188fd89022c154c81befa2f0e00be0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/32/328cc881519068e4eb7db4bb907ad2d9 b/Close Enough!/Library/metadata/32/328cc881519068e4eb7db4bb907ad2d9 deleted file mode 100644 index 08d210d..0000000 Binary files a/Close Enough!/Library/metadata/32/328cc881519068e4eb7db4bb907ad2d9 and /dev/null differ diff --git a/Close Enough!/Library/metadata/32/328cc881519068e4eb7db4bb907ad2d9.info b/Close Enough!/Library/metadata/32/328cc881519068e4eb7db4bb907ad2d9.info deleted file mode 100644 index 65d5010..0000000 Binary files a/Close Enough!/Library/metadata/32/328cc881519068e4eb7db4bb907ad2d9.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/33/333fa74f0fd044c46976e8b38e021069 b/Close Enough!/Library/metadata/33/333fa74f0fd044c46976e8b38e021069 deleted file mode 100644 index d080201..0000000 Binary files a/Close Enough!/Library/metadata/33/333fa74f0fd044c46976e8b38e021069 and /dev/null differ diff --git a/Close Enough!/Library/metadata/33/333fa74f0fd044c46976e8b38e021069.info b/Close Enough!/Library/metadata/33/333fa74f0fd044c46976e8b38e021069.info deleted file mode 100644 index 16f01fa..0000000 Binary files a/Close Enough!/Library/metadata/33/333fa74f0fd044c46976e8b38e021069.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/33/335e8de193316b54e9052b2d1439abd8 b/Close Enough!/Library/metadata/33/335e8de193316b54e9052b2d1439abd8 deleted file mode 100644 index 320711a..0000000 Binary files a/Close Enough!/Library/metadata/33/335e8de193316b54e9052b2d1439abd8 and /dev/null differ diff --git a/Close Enough!/Library/metadata/33/335e8de193316b54e9052b2d1439abd8.info b/Close Enough!/Library/metadata/33/335e8de193316b54e9052b2d1439abd8.info deleted file mode 100644 index a2303ac..0000000 Binary files a/Close Enough!/Library/metadata/33/335e8de193316b54e9052b2d1439abd8.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/33/335e8de193316b54e9052b2d1439abd8.resource b/Close Enough!/Library/metadata/33/335e8de193316b54e9052b2d1439abd8.resource deleted file mode 100644 index dfb1546..0000000 Binary files a/Close Enough!/Library/metadata/33/335e8de193316b54e9052b2d1439abd8.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/33/336523c374a5e6c4eb40aa6dc68e9906 b/Close Enough!/Library/metadata/33/336523c374a5e6c4eb40aa6dc68e9906 deleted file mode 100644 index 08baeee..0000000 Binary files a/Close Enough!/Library/metadata/33/336523c374a5e6c4eb40aa6dc68e9906 and /dev/null differ diff --git a/Close Enough!/Library/metadata/33/336523c374a5e6c4eb40aa6dc68e9906.info b/Close Enough!/Library/metadata/33/336523c374a5e6c4eb40aa6dc68e9906.info deleted file mode 100644 index 2071add..0000000 Binary files a/Close Enough!/Library/metadata/33/336523c374a5e6c4eb40aa6dc68e9906.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/35/35a2b819ed5d510488b6e51b12158f63 b/Close Enough!/Library/metadata/35/35a2b819ed5d510488b6e51b12158f63 deleted file mode 100644 index 98c7493..0000000 Binary files a/Close Enough!/Library/metadata/35/35a2b819ed5d510488b6e51b12158f63 and /dev/null differ diff --git a/Close Enough!/Library/metadata/35/35a2b819ed5d510488b6e51b12158f63.info b/Close Enough!/Library/metadata/35/35a2b819ed5d510488b6e51b12158f63.info deleted file mode 100644 index 075fc44..0000000 Binary files a/Close Enough!/Library/metadata/35/35a2b819ed5d510488b6e51b12158f63.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/35/35a2b819ed5d510488b6e51b12158f63.resource b/Close Enough!/Library/metadata/35/35a2b819ed5d510488b6e51b12158f63.resource deleted file mode 100644 index 592fb1d..0000000 Binary files a/Close Enough!/Library/metadata/35/35a2b819ed5d510488b6e51b12158f63.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/35/35e2b94eb1006514abf8ae501b17f4d1 b/Close Enough!/Library/metadata/35/35e2b94eb1006514abf8ae501b17f4d1 deleted file mode 100644 index 74ff961..0000000 Binary files a/Close Enough!/Library/metadata/35/35e2b94eb1006514abf8ae501b17f4d1 and /dev/null differ diff --git a/Close Enough!/Library/metadata/35/35e2b94eb1006514abf8ae501b17f4d1.info b/Close Enough!/Library/metadata/35/35e2b94eb1006514abf8ae501b17f4d1.info deleted file mode 100644 index 7a021f2..0000000 Binary files a/Close Enough!/Library/metadata/35/35e2b94eb1006514abf8ae501b17f4d1.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/35/35e5b60069b1d4945af0cbaefb902d02 b/Close Enough!/Library/metadata/35/35e5b60069b1d4945af0cbaefb902d02 deleted file mode 100644 index 8b92e70..0000000 Binary files a/Close Enough!/Library/metadata/35/35e5b60069b1d4945af0cbaefb902d02 and /dev/null differ diff --git a/Close Enough!/Library/metadata/35/35e5b60069b1d4945af0cbaefb902d02.info b/Close Enough!/Library/metadata/35/35e5b60069b1d4945af0cbaefb902d02.info deleted file mode 100644 index 07610ab..0000000 Binary files a/Close Enough!/Library/metadata/35/35e5b60069b1d4945af0cbaefb902d02.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/36/36b086f651d3646bcb039f39a42152aa b/Close Enough!/Library/metadata/36/36b086f651d3646bcb039f39a42152aa deleted file mode 100644 index 75084b1..0000000 Binary files a/Close Enough!/Library/metadata/36/36b086f651d3646bcb039f39a42152aa and /dev/null differ diff --git a/Close Enough!/Library/metadata/36/36b086f651d3646bcb039f39a42152aa.info b/Close Enough!/Library/metadata/36/36b086f651d3646bcb039f39a42152aa.info deleted file mode 100644 index 71b6c75..0000000 Binary files a/Close Enough!/Library/metadata/36/36b086f651d3646bcb039f39a42152aa.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/36/36c3096ad3231a747a80f0e4a5d0c45e b/Close Enough!/Library/metadata/36/36c3096ad3231a747a80f0e4a5d0c45e deleted file mode 100644 index ce752b2..0000000 Binary files a/Close Enough!/Library/metadata/36/36c3096ad3231a747a80f0e4a5d0c45e and /dev/null differ diff --git a/Close Enough!/Library/metadata/36/36c3096ad3231a747a80f0e4a5d0c45e.info b/Close Enough!/Library/metadata/36/36c3096ad3231a747a80f0e4a5d0c45e.info deleted file mode 100644 index 5d06979..0000000 Binary files a/Close Enough!/Library/metadata/36/36c3096ad3231a747a80f0e4a5d0c45e.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/36/36e8bb3feb5e6402185947b817a6ed8d b/Close Enough!/Library/metadata/36/36e8bb3feb5e6402185947b817a6ed8d deleted file mode 100644 index 0b53681..0000000 Binary files a/Close Enough!/Library/metadata/36/36e8bb3feb5e6402185947b817a6ed8d and /dev/null differ diff --git a/Close Enough!/Library/metadata/36/36e8bb3feb5e6402185947b817a6ed8d.info b/Close Enough!/Library/metadata/36/36e8bb3feb5e6402185947b817a6ed8d.info deleted file mode 100644 index f556c52..0000000 Binary files a/Close Enough!/Library/metadata/36/36e8bb3feb5e6402185947b817a6ed8d.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/37/375d8ff010a0a1d49a89566f596700df b/Close Enough!/Library/metadata/37/375d8ff010a0a1d49a89566f596700df deleted file mode 100644 index 5e0a238..0000000 Binary files a/Close Enough!/Library/metadata/37/375d8ff010a0a1d49a89566f596700df and /dev/null differ diff --git a/Close Enough!/Library/metadata/37/375d8ff010a0a1d49a89566f596700df.info b/Close Enough!/Library/metadata/37/375d8ff010a0a1d49a89566f596700df.info deleted file mode 100644 index ae905b9..0000000 Binary files a/Close Enough!/Library/metadata/37/375d8ff010a0a1d49a89566f596700df.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/37/375d8ff010a0a1d49a89566f596700df.resource b/Close Enough!/Library/metadata/37/375d8ff010a0a1d49a89566f596700df.resource deleted file mode 100644 index 639eeca..0000000 Binary files a/Close Enough!/Library/metadata/37/375d8ff010a0a1d49a89566f596700df.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/38/380c292c725b8e84ba5201a1b548832a b/Close Enough!/Library/metadata/38/380c292c725b8e84ba5201a1b548832a deleted file mode 100644 index b13a5b4..0000000 Binary files a/Close Enough!/Library/metadata/38/380c292c725b8e84ba5201a1b548832a and /dev/null differ diff --git a/Close Enough!/Library/metadata/38/380c292c725b8e84ba5201a1b548832a.info b/Close Enough!/Library/metadata/38/380c292c725b8e84ba5201a1b548832a.info deleted file mode 100644 index e0dfb05..0000000 Binary files a/Close Enough!/Library/metadata/38/380c292c725b8e84ba5201a1b548832a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/38/38c8faf1788024c02930a0c68a6e0edc b/Close Enough!/Library/metadata/38/38c8faf1788024c02930a0c68a6e0edc deleted file mode 100644 index 8e716d2..0000000 Binary files a/Close Enough!/Library/metadata/38/38c8faf1788024c02930a0c68a6e0edc and /dev/null differ diff --git a/Close Enough!/Library/metadata/38/38c8faf1788024c02930a0c68a6e0edc.info b/Close Enough!/Library/metadata/38/38c8faf1788024c02930a0c68a6e0edc.info deleted file mode 100644 index 0daa3ef..0000000 Binary files a/Close Enough!/Library/metadata/38/38c8faf1788024c02930a0c68a6e0edc.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/38/38c9d408cb540e44eb50baa27ba78bd2 b/Close Enough!/Library/metadata/38/38c9d408cb540e44eb50baa27ba78bd2 deleted file mode 100644 index d58bd32..0000000 Binary files a/Close Enough!/Library/metadata/38/38c9d408cb540e44eb50baa27ba78bd2 and /dev/null differ diff --git a/Close Enough!/Library/metadata/38/38c9d408cb540e44eb50baa27ba78bd2.info b/Close Enough!/Library/metadata/38/38c9d408cb540e44eb50baa27ba78bd2.info deleted file mode 100644 index 44f3f84..0000000 Binary files a/Close Enough!/Library/metadata/38/38c9d408cb540e44eb50baa27ba78bd2.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/38/38c9d408cb540e44eb50baa27ba78bd2.resource b/Close Enough!/Library/metadata/38/38c9d408cb540e44eb50baa27ba78bd2.resource deleted file mode 100644 index 7a7f07f..0000000 Binary files a/Close Enough!/Library/metadata/38/38c9d408cb540e44eb50baa27ba78bd2.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/38/38dc1f2160298714da1976a2b301c0b2 b/Close Enough!/Library/metadata/38/38dc1f2160298714da1976a2b301c0b2 deleted file mode 100644 index 993c41a..0000000 Binary files a/Close Enough!/Library/metadata/38/38dc1f2160298714da1976a2b301c0b2 and /dev/null differ diff --git a/Close Enough!/Library/metadata/38/38dc1f2160298714da1976a2b301c0b2.info b/Close Enough!/Library/metadata/38/38dc1f2160298714da1976a2b301c0b2.info deleted file mode 100644 index e90d80f..0000000 Binary files a/Close Enough!/Library/metadata/38/38dc1f2160298714da1976a2b301c0b2.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/38/38de513803c5e60498ad31fbc327b120 b/Close Enough!/Library/metadata/38/38de513803c5e60498ad31fbc327b120 deleted file mode 100644 index fbb73ee..0000000 Binary files a/Close Enough!/Library/metadata/38/38de513803c5e60498ad31fbc327b120 and /dev/null differ diff --git a/Close Enough!/Library/metadata/38/38de513803c5e60498ad31fbc327b120.info b/Close Enough!/Library/metadata/38/38de513803c5e60498ad31fbc327b120.info deleted file mode 100644 index d158f80..0000000 Binary files a/Close Enough!/Library/metadata/38/38de513803c5e60498ad31fbc327b120.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/38/38ef446d1a9f0424d83a111ef1030cb0 b/Close Enough!/Library/metadata/38/38ef446d1a9f0424d83a111ef1030cb0 deleted file mode 100644 index 9df1e8d..0000000 Binary files a/Close Enough!/Library/metadata/38/38ef446d1a9f0424d83a111ef1030cb0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/38/38ef446d1a9f0424d83a111ef1030cb0.info b/Close Enough!/Library/metadata/38/38ef446d1a9f0424d83a111ef1030cb0.info deleted file mode 100644 index fcfe6f7..0000000 Binary files a/Close Enough!/Library/metadata/38/38ef446d1a9f0424d83a111ef1030cb0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/3a/3a2741188c8501648a0b9b2e9616eb60 b/Close Enough!/Library/metadata/3a/3a2741188c8501648a0b9b2e9616eb60 deleted file mode 100644 index c590469..0000000 Binary files a/Close Enough!/Library/metadata/3a/3a2741188c8501648a0b9b2e9616eb60 and /dev/null differ diff --git a/Close Enough!/Library/metadata/3a/3a2741188c8501648a0b9b2e9616eb60.info b/Close Enough!/Library/metadata/3a/3a2741188c8501648a0b9b2e9616eb60.info deleted file mode 100644 index 256f2b8..0000000 Binary files a/Close Enough!/Library/metadata/3a/3a2741188c8501648a0b9b2e9616eb60.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/3a/3a2741188c8501648a0b9b2e9616eb60.resource b/Close Enough!/Library/metadata/3a/3a2741188c8501648a0b9b2e9616eb60.resource deleted file mode 100644 index e733c38..0000000 Binary files a/Close Enough!/Library/metadata/3a/3a2741188c8501648a0b9b2e9616eb60.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/3a/3a55fb580032dbd43a9894e13aa1ce02 b/Close Enough!/Library/metadata/3a/3a55fb580032dbd43a9894e13aa1ce02 deleted file mode 100644 index 66dbd84..0000000 Binary files a/Close Enough!/Library/metadata/3a/3a55fb580032dbd43a9894e13aa1ce02 and /dev/null differ diff --git a/Close Enough!/Library/metadata/3a/3a55fb580032dbd43a9894e13aa1ce02.info b/Close Enough!/Library/metadata/3a/3a55fb580032dbd43a9894e13aa1ce02.info deleted file mode 100644 index ff68e86..0000000 Binary files a/Close Enough!/Library/metadata/3a/3a55fb580032dbd43a9894e13aa1ce02.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/3a/3a55fb580032dbd43a9894e13aa1ce02.resource b/Close Enough!/Library/metadata/3a/3a55fb580032dbd43a9894e13aa1ce02.resource deleted file mode 100644 index 9f5618a..0000000 Binary files a/Close Enough!/Library/metadata/3a/3a55fb580032dbd43a9894e13aa1ce02.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/3a/3a84de5cd0624681b6b6dcd8921d912a b/Close Enough!/Library/metadata/3a/3a84de5cd0624681b6b6dcd8921d912a deleted file mode 100644 index 7455003..0000000 Binary files a/Close Enough!/Library/metadata/3a/3a84de5cd0624681b6b6dcd8921d912a and /dev/null differ diff --git a/Close Enough!/Library/metadata/3a/3a84de5cd0624681b6b6dcd8921d912a.info b/Close Enough!/Library/metadata/3a/3a84de5cd0624681b6b6dcd8921d912a.info deleted file mode 100644 index 454798c..0000000 Binary files a/Close Enough!/Library/metadata/3a/3a84de5cd0624681b6b6dcd8921d912a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/3c/3c0d76c55eed6214f9d3b070caede5d3 b/Close Enough!/Library/metadata/3c/3c0d76c55eed6214f9d3b070caede5d3 deleted file mode 100644 index deb931e..0000000 Binary files a/Close Enough!/Library/metadata/3c/3c0d76c55eed6214f9d3b070caede5d3 and /dev/null differ diff --git a/Close Enough!/Library/metadata/3c/3c0d76c55eed6214f9d3b070caede5d3.info b/Close Enough!/Library/metadata/3c/3c0d76c55eed6214f9d3b070caede5d3.info deleted file mode 100644 index 49a0dd0..0000000 Binary files a/Close Enough!/Library/metadata/3c/3c0d76c55eed6214f9d3b070caede5d3.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/3c/3c746ddce2130454a86b9a82a1325127 b/Close Enough!/Library/metadata/3c/3c746ddce2130454a86b9a82a1325127 deleted file mode 100644 index a4ca624..0000000 Binary files a/Close Enough!/Library/metadata/3c/3c746ddce2130454a86b9a82a1325127 and /dev/null differ diff --git a/Close Enough!/Library/metadata/3c/3c746ddce2130454a86b9a82a1325127.info b/Close Enough!/Library/metadata/3c/3c746ddce2130454a86b9a82a1325127.info deleted file mode 100644 index ece4a39..0000000 Binary files a/Close Enough!/Library/metadata/3c/3c746ddce2130454a86b9a82a1325127.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/3c/3cafcc1ae6118c64aad8e7fa71939c1e b/Close Enough!/Library/metadata/3c/3cafcc1ae6118c64aad8e7fa71939c1e deleted file mode 100644 index 64d78ce..0000000 Binary files a/Close Enough!/Library/metadata/3c/3cafcc1ae6118c64aad8e7fa71939c1e and /dev/null differ diff --git a/Close Enough!/Library/metadata/3c/3cafcc1ae6118c64aad8e7fa71939c1e.info b/Close Enough!/Library/metadata/3c/3cafcc1ae6118c64aad8e7fa71939c1e.info deleted file mode 100644 index 9b81726..0000000 Binary files a/Close Enough!/Library/metadata/3c/3cafcc1ae6118c64aad8e7fa71939c1e.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/3c/3cafcc1ae6118c64aad8e7fa71939c1e.resource b/Close Enough!/Library/metadata/3c/3cafcc1ae6118c64aad8e7fa71939c1e.resource deleted file mode 100644 index e711df6..0000000 Binary files a/Close Enough!/Library/metadata/3c/3cafcc1ae6118c64aad8e7fa71939c1e.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/3c/3cebe1a96232b44388b30b2f72dde434 b/Close Enough!/Library/metadata/3c/3cebe1a96232b44388b30b2f72dde434 deleted file mode 100644 index 60e6f35..0000000 Binary files a/Close Enough!/Library/metadata/3c/3cebe1a96232b44388b30b2f72dde434 and /dev/null differ diff --git a/Close Enough!/Library/metadata/3c/3cebe1a96232b44388b30b2f72dde434.info b/Close Enough!/Library/metadata/3c/3cebe1a96232b44388b30b2f72dde434.info deleted file mode 100644 index a042f2b..0000000 Binary files a/Close Enough!/Library/metadata/3c/3cebe1a96232b44388b30b2f72dde434.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/3d/3d3fbbc53c0b9764c98f63f557b46c39 b/Close Enough!/Library/metadata/3d/3d3fbbc53c0b9764c98f63f557b46c39 deleted file mode 100644 index 8f66992..0000000 Binary files a/Close Enough!/Library/metadata/3d/3d3fbbc53c0b9764c98f63f557b46c39 and /dev/null differ diff --git a/Close Enough!/Library/metadata/3d/3d3fbbc53c0b9764c98f63f557b46c39.info b/Close Enough!/Library/metadata/3d/3d3fbbc53c0b9764c98f63f557b46c39.info deleted file mode 100644 index 764318f..0000000 Binary files a/Close Enough!/Library/metadata/3d/3d3fbbc53c0b9764c98f63f557b46c39.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/3d/3d64d2d886796496d9b8b160cd7eb2f4 b/Close Enough!/Library/metadata/3d/3d64d2d886796496d9b8b160cd7eb2f4 deleted file mode 100644 index b301cfb..0000000 Binary files a/Close Enough!/Library/metadata/3d/3d64d2d886796496d9b8b160cd7eb2f4 and /dev/null differ diff --git a/Close Enough!/Library/metadata/3d/3d64d2d886796496d9b8b160cd7eb2f4.info b/Close Enough!/Library/metadata/3d/3d64d2d886796496d9b8b160cd7eb2f4.info deleted file mode 100644 index 66a064a..0000000 Binary files a/Close Enough!/Library/metadata/3d/3d64d2d886796496d9b8b160cd7eb2f4.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/3d/3d8829ac873af27488b1412b8db301ab b/Close Enough!/Library/metadata/3d/3d8829ac873af27488b1412b8db301ab deleted file mode 100644 index 0c84447..0000000 Binary files a/Close Enough!/Library/metadata/3d/3d8829ac873af27488b1412b8db301ab and /dev/null differ diff --git a/Close Enough!/Library/metadata/3d/3d8829ac873af27488b1412b8db301ab.info b/Close Enough!/Library/metadata/3d/3d8829ac873af27488b1412b8db301ab.info deleted file mode 100644 index e26703d..0000000 Binary files a/Close Enough!/Library/metadata/3d/3d8829ac873af27488b1412b8db301ab.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/3e/3e51059fc4021894d957dc5eb1485065 b/Close Enough!/Library/metadata/3e/3e51059fc4021894d957dc5eb1485065 deleted file mode 100644 index cdfb16d..0000000 Binary files a/Close Enough!/Library/metadata/3e/3e51059fc4021894d957dc5eb1485065 and /dev/null differ diff --git a/Close Enough!/Library/metadata/3e/3e51059fc4021894d957dc5eb1485065.info b/Close Enough!/Library/metadata/3e/3e51059fc4021894d957dc5eb1485065.info deleted file mode 100644 index dcb7800..0000000 Binary files a/Close Enough!/Library/metadata/3e/3e51059fc4021894d957dc5eb1485065.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/3f/3f67ccb6076f81944b103e66bee4e58f b/Close Enough!/Library/metadata/3f/3f67ccb6076f81944b103e66bee4e58f deleted file mode 100644 index 0ccc057..0000000 Binary files a/Close Enough!/Library/metadata/3f/3f67ccb6076f81944b103e66bee4e58f and /dev/null differ diff --git a/Close Enough!/Library/metadata/3f/3f67ccb6076f81944b103e66bee4e58f.info b/Close Enough!/Library/metadata/3f/3f67ccb6076f81944b103e66bee4e58f.info deleted file mode 100644 index b606156..0000000 Binary files a/Close Enough!/Library/metadata/3f/3f67ccb6076f81944b103e66bee4e58f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/3f/3f67ccb6076f81944b103e66bee4e58f.resource b/Close Enough!/Library/metadata/3f/3f67ccb6076f81944b103e66bee4e58f.resource deleted file mode 100644 index cc411cd..0000000 Binary files a/Close Enough!/Library/metadata/3f/3f67ccb6076f81944b103e66bee4e58f.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/3f/3fb61dee89de54f1aa04500d5bc96ba5 b/Close Enough!/Library/metadata/3f/3fb61dee89de54f1aa04500d5bc96ba5 deleted file mode 100644 index 1ba4c7f..0000000 Binary files a/Close Enough!/Library/metadata/3f/3fb61dee89de54f1aa04500d5bc96ba5 and /dev/null differ diff --git a/Close Enough!/Library/metadata/3f/3fb61dee89de54f1aa04500d5bc96ba5.info b/Close Enough!/Library/metadata/3f/3fb61dee89de54f1aa04500d5bc96ba5.info deleted file mode 100644 index 40ea09e..0000000 Binary files a/Close Enough!/Library/metadata/3f/3fb61dee89de54f1aa04500d5bc96ba5.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/40/405b9b51bb344a128608d968297df79c b/Close Enough!/Library/metadata/40/405b9b51bb344a128608d968297df79c deleted file mode 100644 index 8ce8aa0..0000000 Binary files a/Close Enough!/Library/metadata/40/405b9b51bb344a128608d968297df79c and /dev/null differ diff --git a/Close Enough!/Library/metadata/40/405b9b51bb344a128608d968297df79c.info b/Close Enough!/Library/metadata/40/405b9b51bb344a128608d968297df79c.info deleted file mode 100644 index d181f74..0000000 Binary files a/Close Enough!/Library/metadata/40/405b9b51bb344a128608d968297df79c.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/40/40abadb427f401a4f8a0f18e72bd6faf b/Close Enough!/Library/metadata/40/40abadb427f401a4f8a0f18e72bd6faf deleted file mode 100644 index 4b12021..0000000 Binary files a/Close Enough!/Library/metadata/40/40abadb427f401a4f8a0f18e72bd6faf and /dev/null differ diff --git a/Close Enough!/Library/metadata/40/40abadb427f401a4f8a0f18e72bd6faf.info b/Close Enough!/Library/metadata/40/40abadb427f401a4f8a0f18e72bd6faf.info deleted file mode 100644 index 7a3915f..0000000 Binary files a/Close Enough!/Library/metadata/40/40abadb427f401a4f8a0f18e72bd6faf.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/40/40dcb0b605bd2f04ca8fb83800780179 b/Close Enough!/Library/metadata/40/40dcb0b605bd2f04ca8fb83800780179 deleted file mode 100644 index 2f96854..0000000 Binary files a/Close Enough!/Library/metadata/40/40dcb0b605bd2f04ca8fb83800780179 and /dev/null differ diff --git a/Close Enough!/Library/metadata/40/40dcb0b605bd2f04ca8fb83800780179.info b/Close Enough!/Library/metadata/40/40dcb0b605bd2f04ca8fb83800780179.info deleted file mode 100644 index 591e0de..0000000 Binary files a/Close Enough!/Library/metadata/40/40dcb0b605bd2f04ca8fb83800780179.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/41/4113173d5e95493ab8765d7b08371de4 b/Close Enough!/Library/metadata/41/4113173d5e95493ab8765d7b08371de4 deleted file mode 100644 index 1604236..0000000 Binary files a/Close Enough!/Library/metadata/41/4113173d5e95493ab8765d7b08371de4 and /dev/null differ diff --git a/Close Enough!/Library/metadata/41/4113173d5e95493ab8765d7b08371de4.info b/Close Enough!/Library/metadata/41/4113173d5e95493ab8765d7b08371de4.info deleted file mode 100644 index 6a1f5f2..0000000 Binary files a/Close Enough!/Library/metadata/41/4113173d5e95493ab8765d7b08371de4.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/41/41d23afb87f73854984985a665852b53 b/Close Enough!/Library/metadata/41/41d23afb87f73854984985a665852b53 deleted file mode 100644 index feed6cc..0000000 Binary files a/Close Enough!/Library/metadata/41/41d23afb87f73854984985a665852b53 and /dev/null differ diff --git a/Close Enough!/Library/metadata/41/41d23afb87f73854984985a665852b53.info b/Close Enough!/Library/metadata/41/41d23afb87f73854984985a665852b53.info deleted file mode 100644 index ce191be..0000000 Binary files a/Close Enough!/Library/metadata/41/41d23afb87f73854984985a665852b53.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/43/432d27f28c1251041bd6d1753602d5f0 b/Close Enough!/Library/metadata/43/432d27f28c1251041bd6d1753602d5f0 deleted file mode 100644 index 4f723e1..0000000 Binary files a/Close Enough!/Library/metadata/43/432d27f28c1251041bd6d1753602d5f0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/43/432d27f28c1251041bd6d1753602d5f0.info b/Close Enough!/Library/metadata/43/432d27f28c1251041bd6d1753602d5f0.info deleted file mode 100644 index 99e1d5b..0000000 Binary files a/Close Enough!/Library/metadata/43/432d27f28c1251041bd6d1753602d5f0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/43/43b3e7f4af0a713409ccaea4b0135763 b/Close Enough!/Library/metadata/43/43b3e7f4af0a713409ccaea4b0135763 deleted file mode 100644 index 0cc1f86..0000000 Binary files a/Close Enough!/Library/metadata/43/43b3e7f4af0a713409ccaea4b0135763 and /dev/null differ diff --git a/Close Enough!/Library/metadata/43/43b3e7f4af0a713409ccaea4b0135763.info b/Close Enough!/Library/metadata/43/43b3e7f4af0a713409ccaea4b0135763.info deleted file mode 100644 index b8c3462..0000000 Binary files a/Close Enough!/Library/metadata/43/43b3e7f4af0a713409ccaea4b0135763.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/43/43d12af3b7369004994864638516ff11 b/Close Enough!/Library/metadata/43/43d12af3b7369004994864638516ff11 deleted file mode 100644 index 897af4c..0000000 Binary files a/Close Enough!/Library/metadata/43/43d12af3b7369004994864638516ff11 and /dev/null differ diff --git a/Close Enough!/Library/metadata/43/43d12af3b7369004994864638516ff11.info b/Close Enough!/Library/metadata/43/43d12af3b7369004994864638516ff11.info deleted file mode 100644 index cd975f7..0000000 Binary files a/Close Enough!/Library/metadata/43/43d12af3b7369004994864638516ff11.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/43/43d12af3b7369004994864638516ff11.resource b/Close Enough!/Library/metadata/43/43d12af3b7369004994864638516ff11.resource deleted file mode 100644 index 6b28a1a..0000000 Binary files a/Close Enough!/Library/metadata/43/43d12af3b7369004994864638516ff11.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/44/448ec8bf58b36da46b76e64d162d6c35 b/Close Enough!/Library/metadata/44/448ec8bf58b36da46b76e64d162d6c35 deleted file mode 100644 index 920665a..0000000 Binary files a/Close Enough!/Library/metadata/44/448ec8bf58b36da46b76e64d162d6c35 and /dev/null differ diff --git a/Close Enough!/Library/metadata/44/448ec8bf58b36da46b76e64d162d6c35.info b/Close Enough!/Library/metadata/44/448ec8bf58b36da46b76e64d162d6c35.info deleted file mode 100644 index f694e64..0000000 Binary files a/Close Enough!/Library/metadata/44/448ec8bf58b36da46b76e64d162d6c35.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/44/44af95e3aabc5e6409a20448e9c87cf6 b/Close Enough!/Library/metadata/44/44af95e3aabc5e6409a20448e9c87cf6 deleted file mode 100644 index c4d328c..0000000 Binary files a/Close Enough!/Library/metadata/44/44af95e3aabc5e6409a20448e9c87cf6 and /dev/null differ diff --git a/Close Enough!/Library/metadata/44/44af95e3aabc5e6409a20448e9c87cf6.info b/Close Enough!/Library/metadata/44/44af95e3aabc5e6409a20448e9c87cf6.info deleted file mode 100644 index 98c83f0..0000000 Binary files a/Close Enough!/Library/metadata/44/44af95e3aabc5e6409a20448e9c87cf6.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/44/44b4c06a3e5cb92469e54ab3298b4f09 b/Close Enough!/Library/metadata/44/44b4c06a3e5cb92469e54ab3298b4f09 deleted file mode 100644 index ccac67f..0000000 Binary files a/Close Enough!/Library/metadata/44/44b4c06a3e5cb92469e54ab3298b4f09 and /dev/null differ diff --git a/Close Enough!/Library/metadata/44/44b4c06a3e5cb92469e54ab3298b4f09.info b/Close Enough!/Library/metadata/44/44b4c06a3e5cb92469e54ab3298b4f09.info deleted file mode 100644 index 5ef0bb7..0000000 Binary files a/Close Enough!/Library/metadata/44/44b4c06a3e5cb92469e54ab3298b4f09.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/44/44f39a74ca5ee4bf5936b17e901f251c b/Close Enough!/Library/metadata/44/44f39a74ca5ee4bf5936b17e901f251c deleted file mode 100644 index f42d03d..0000000 Binary files a/Close Enough!/Library/metadata/44/44f39a74ca5ee4bf5936b17e901f251c and /dev/null differ diff --git a/Close Enough!/Library/metadata/44/44f39a74ca5ee4bf5936b17e901f251c.info b/Close Enough!/Library/metadata/44/44f39a74ca5ee4bf5936b17e901f251c.info deleted file mode 100644 index 9cbf350..0000000 Binary files a/Close Enough!/Library/metadata/44/44f39a74ca5ee4bf5936b17e901f251c.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/45/453f100e6bdae4dfd9e655927819dc85 b/Close Enough!/Library/metadata/45/453f100e6bdae4dfd9e655927819dc85 deleted file mode 100644 index fa76f35..0000000 Binary files a/Close Enough!/Library/metadata/45/453f100e6bdae4dfd9e655927819dc85 and /dev/null differ diff --git a/Close Enough!/Library/metadata/45/453f100e6bdae4dfd9e655927819dc85.info b/Close Enough!/Library/metadata/45/453f100e6bdae4dfd9e655927819dc85.info deleted file mode 100644 index 429b8bc..0000000 Binary files a/Close Enough!/Library/metadata/45/453f100e6bdae4dfd9e655927819dc85.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/45/45cada5d72049441eb28a4e39dade545 b/Close Enough!/Library/metadata/45/45cada5d72049441eb28a4e39dade545 deleted file mode 100644 index 5b47338..0000000 Binary files a/Close Enough!/Library/metadata/45/45cada5d72049441eb28a4e39dade545 and /dev/null differ diff --git a/Close Enough!/Library/metadata/45/45cada5d72049441eb28a4e39dade545.info b/Close Enough!/Library/metadata/45/45cada5d72049441eb28a4e39dade545.info deleted file mode 100644 index 478b69a..0000000 Binary files a/Close Enough!/Library/metadata/45/45cada5d72049441eb28a4e39dade545.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/46/4683845b3a6625941af78891ae09512d b/Close Enough!/Library/metadata/46/4683845b3a6625941af78891ae09512d deleted file mode 100644 index aac5d1f..0000000 Binary files a/Close Enough!/Library/metadata/46/4683845b3a6625941af78891ae09512d and /dev/null differ diff --git a/Close Enough!/Library/metadata/46/4683845b3a6625941af78891ae09512d.info b/Close Enough!/Library/metadata/46/4683845b3a6625941af78891ae09512d.info deleted file mode 100644 index 3dce6e3..0000000 Binary files a/Close Enough!/Library/metadata/46/4683845b3a6625941af78891ae09512d.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/46/4683845b3a6625941af78891ae09512d.resource b/Close Enough!/Library/metadata/46/4683845b3a6625941af78891ae09512d.resource deleted file mode 100644 index da1aba7..0000000 Binary files a/Close Enough!/Library/metadata/46/4683845b3a6625941af78891ae09512d.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/47/474fc939759cbbb4687e40836c4d377f b/Close Enough!/Library/metadata/47/474fc939759cbbb4687e40836c4d377f deleted file mode 100644 index 550aee8..0000000 Binary files a/Close Enough!/Library/metadata/47/474fc939759cbbb4687e40836c4d377f and /dev/null differ diff --git a/Close Enough!/Library/metadata/47/474fc939759cbbb4687e40836c4d377f.info b/Close Enough!/Library/metadata/47/474fc939759cbbb4687e40836c4d377f.info deleted file mode 100644 index a4ab442..0000000 Binary files a/Close Enough!/Library/metadata/47/474fc939759cbbb4687e40836c4d377f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/47/474fc939759cbbb4687e40836c4d377f.resource b/Close Enough!/Library/metadata/47/474fc939759cbbb4687e40836c4d377f.resource deleted file mode 100644 index 64a3f19..0000000 Binary files a/Close Enough!/Library/metadata/47/474fc939759cbbb4687e40836c4d377f.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/48/4841f729450ea354d8abdefab9a4d43f b/Close Enough!/Library/metadata/48/4841f729450ea354d8abdefab9a4d43f deleted file mode 100644 index 776faa4..0000000 Binary files a/Close Enough!/Library/metadata/48/4841f729450ea354d8abdefab9a4d43f and /dev/null differ diff --git a/Close Enough!/Library/metadata/48/4841f729450ea354d8abdefab9a4d43f.info b/Close Enough!/Library/metadata/48/4841f729450ea354d8abdefab9a4d43f.info deleted file mode 100644 index 9f77b04..0000000 Binary files a/Close Enough!/Library/metadata/48/4841f729450ea354d8abdefab9a4d43f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/48/4841f729450ea354d8abdefab9a4d43f.resource b/Close Enough!/Library/metadata/48/4841f729450ea354d8abdefab9a4d43f.resource deleted file mode 100644 index 173d89b..0000000 Binary files a/Close Enough!/Library/metadata/48/4841f729450ea354d8abdefab9a4d43f.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/48/488acd4d6a89f4415857c7ccc6966f06 b/Close Enough!/Library/metadata/48/488acd4d6a89f4415857c7ccc6966f06 deleted file mode 100644 index f04dd81..0000000 Binary files a/Close Enough!/Library/metadata/48/488acd4d6a89f4415857c7ccc6966f06 and /dev/null differ diff --git a/Close Enough!/Library/metadata/48/488acd4d6a89f4415857c7ccc6966f06.info b/Close Enough!/Library/metadata/48/488acd4d6a89f4415857c7ccc6966f06.info deleted file mode 100644 index 3ca2dcc..0000000 Binary files a/Close Enough!/Library/metadata/48/488acd4d6a89f4415857c7ccc6966f06.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/48/48986928cc2a449dbaecdd1654bc9bf6 b/Close Enough!/Library/metadata/48/48986928cc2a449dbaecdd1654bc9bf6 deleted file mode 100644 index ed1c2c6..0000000 Binary files a/Close Enough!/Library/metadata/48/48986928cc2a449dbaecdd1654bc9bf6 and /dev/null differ diff --git a/Close Enough!/Library/metadata/48/48986928cc2a449dbaecdd1654bc9bf6.info b/Close Enough!/Library/metadata/48/48986928cc2a449dbaecdd1654bc9bf6.info deleted file mode 100644 index 6076edf..0000000 Binary files a/Close Enough!/Library/metadata/48/48986928cc2a449dbaecdd1654bc9bf6.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/48/48b91f86428668e45a3442001cdee50a b/Close Enough!/Library/metadata/48/48b91f86428668e45a3442001cdee50a deleted file mode 100644 index 4355ac5..0000000 Binary files a/Close Enough!/Library/metadata/48/48b91f86428668e45a3442001cdee50a and /dev/null differ diff --git a/Close Enough!/Library/metadata/48/48b91f86428668e45a3442001cdee50a.info b/Close Enough!/Library/metadata/48/48b91f86428668e45a3442001cdee50a.info deleted file mode 100644 index 5131540..0000000 Binary files a/Close Enough!/Library/metadata/48/48b91f86428668e45a3442001cdee50a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/48/48c9e00d43dd18a4b82aa7979df9dc55 b/Close Enough!/Library/metadata/48/48c9e00d43dd18a4b82aa7979df9dc55 deleted file mode 100644 index 7faca5e..0000000 Binary files a/Close Enough!/Library/metadata/48/48c9e00d43dd18a4b82aa7979df9dc55 and /dev/null differ diff --git a/Close Enough!/Library/metadata/48/48c9e00d43dd18a4b82aa7979df9dc55.info b/Close Enough!/Library/metadata/48/48c9e00d43dd18a4b82aa7979df9dc55.info deleted file mode 100644 index 3348e06..0000000 Binary files a/Close Enough!/Library/metadata/48/48c9e00d43dd18a4b82aa7979df9dc55.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/49/49030a998b1efd348994ab0f97ae9594 b/Close Enough!/Library/metadata/49/49030a998b1efd348994ab0f97ae9594 deleted file mode 100644 index ef0ed67..0000000 Binary files a/Close Enough!/Library/metadata/49/49030a998b1efd348994ab0f97ae9594 and /dev/null differ diff --git a/Close Enough!/Library/metadata/49/49030a998b1efd348994ab0f97ae9594.info b/Close Enough!/Library/metadata/49/49030a998b1efd348994ab0f97ae9594.info deleted file mode 100644 index 06856ca..0000000 Binary files a/Close Enough!/Library/metadata/49/49030a998b1efd348994ab0f97ae9594.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/49/49030a998b1efd348994ab0f97ae9594.resource b/Close Enough!/Library/metadata/49/49030a998b1efd348994ab0f97ae9594.resource deleted file mode 100644 index 851b494..0000000 Binary files a/Close Enough!/Library/metadata/49/49030a998b1efd348994ab0f97ae9594.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/49/49380f32de3674218befda09d7686bee b/Close Enough!/Library/metadata/49/49380f32de3674218befda09d7686bee deleted file mode 100644 index 0f1ad78..0000000 Binary files a/Close Enough!/Library/metadata/49/49380f32de3674218befda09d7686bee and /dev/null differ diff --git a/Close Enough!/Library/metadata/49/49380f32de3674218befda09d7686bee.info b/Close Enough!/Library/metadata/49/49380f32de3674218befda09d7686bee.info deleted file mode 100644 index 04e225f..0000000 Binary files a/Close Enough!/Library/metadata/49/49380f32de3674218befda09d7686bee.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/49/498396d1f7988af4c83f8f17cc8acb64 b/Close Enough!/Library/metadata/49/498396d1f7988af4c83f8f17cc8acb64 deleted file mode 100644 index fbb6d31..0000000 Binary files a/Close Enough!/Library/metadata/49/498396d1f7988af4c83f8f17cc8acb64 and /dev/null differ diff --git a/Close Enough!/Library/metadata/49/498396d1f7988af4c83f8f17cc8acb64.info b/Close Enough!/Library/metadata/49/498396d1f7988af4c83f8f17cc8acb64.info deleted file mode 100644 index f7390c1..0000000 Binary files a/Close Enough!/Library/metadata/49/498396d1f7988af4c83f8f17cc8acb64.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/49/498396d1f7988af4c83f8f17cc8acb64.resource b/Close Enough!/Library/metadata/49/498396d1f7988af4c83f8f17cc8acb64.resource deleted file mode 100644 index 743b322..0000000 Binary files a/Close Enough!/Library/metadata/49/498396d1f7988af4c83f8f17cc8acb64.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/49/49f5766d0d4954f44b85d4bbd7131677 b/Close Enough!/Library/metadata/49/49f5766d0d4954f44b85d4bbd7131677 deleted file mode 100644 index 105bb83..0000000 Binary files a/Close Enough!/Library/metadata/49/49f5766d0d4954f44b85d4bbd7131677 and /dev/null differ diff --git a/Close Enough!/Library/metadata/49/49f5766d0d4954f44b85d4bbd7131677.info b/Close Enough!/Library/metadata/49/49f5766d0d4954f44b85d4bbd7131677.info deleted file mode 100644 index d77eade..0000000 Binary files a/Close Enough!/Library/metadata/49/49f5766d0d4954f44b85d4bbd7131677.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/4a/4a3ecb1425d14502837abea459cf2b70 b/Close Enough!/Library/metadata/4a/4a3ecb1425d14502837abea459cf2b70 deleted file mode 100644 index 1f29870..0000000 Binary files a/Close Enough!/Library/metadata/4a/4a3ecb1425d14502837abea459cf2b70 and /dev/null differ diff --git a/Close Enough!/Library/metadata/4a/4a3ecb1425d14502837abea459cf2b70.info b/Close Enough!/Library/metadata/4a/4a3ecb1425d14502837abea459cf2b70.info deleted file mode 100644 index 54adf87..0000000 Binary files a/Close Enough!/Library/metadata/4a/4a3ecb1425d14502837abea459cf2b70.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/4b/4b3fa4bde7f1451a8218c03ee6a8ded8 b/Close Enough!/Library/metadata/4b/4b3fa4bde7f1451a8218c03ee6a8ded8 deleted file mode 100644 index 75c06e1..0000000 Binary files a/Close Enough!/Library/metadata/4b/4b3fa4bde7f1451a8218c03ee6a8ded8 and /dev/null differ diff --git a/Close Enough!/Library/metadata/4b/4b3fa4bde7f1451a8218c03ee6a8ded8.info b/Close Enough!/Library/metadata/4b/4b3fa4bde7f1451a8218c03ee6a8ded8.info deleted file mode 100644 index d419994..0000000 Binary files a/Close Enough!/Library/metadata/4b/4b3fa4bde7f1451a8218c03ee6a8ded8.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/4b/4b4e87b100d026548b1690b71bac0d02 b/Close Enough!/Library/metadata/4b/4b4e87b100d026548b1690b71bac0d02 deleted file mode 100644 index beaaa75..0000000 Binary files a/Close Enough!/Library/metadata/4b/4b4e87b100d026548b1690b71bac0d02 and /dev/null differ diff --git a/Close Enough!/Library/metadata/4b/4b4e87b100d026548b1690b71bac0d02.info b/Close Enough!/Library/metadata/4b/4b4e87b100d026548b1690b71bac0d02.info deleted file mode 100644 index bbfea50..0000000 Binary files a/Close Enough!/Library/metadata/4b/4b4e87b100d026548b1690b71bac0d02.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/4b/4b7c40993f5428b448df3f71c9be5be6 b/Close Enough!/Library/metadata/4b/4b7c40993f5428b448df3f71c9be5be6 deleted file mode 100644 index 7c0ebea..0000000 Binary files a/Close Enough!/Library/metadata/4b/4b7c40993f5428b448df3f71c9be5be6 and /dev/null differ diff --git a/Close Enough!/Library/metadata/4b/4b7c40993f5428b448df3f71c9be5be6.info b/Close Enough!/Library/metadata/4b/4b7c40993f5428b448df3f71c9be5be6.info deleted file mode 100644 index 0799321..0000000 Binary files a/Close Enough!/Library/metadata/4b/4b7c40993f5428b448df3f71c9be5be6.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/4b/4b98cbe894926451badd531a6c5d5fa0 b/Close Enough!/Library/metadata/4b/4b98cbe894926451badd531a6c5d5fa0 deleted file mode 100644 index 2e01616..0000000 Binary files a/Close Enough!/Library/metadata/4b/4b98cbe894926451badd531a6c5d5fa0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/4b/4b98cbe894926451badd531a6c5d5fa0.info b/Close Enough!/Library/metadata/4b/4b98cbe894926451badd531a6c5d5fa0.info deleted file mode 100644 index 293e5e0..0000000 Binary files a/Close Enough!/Library/metadata/4b/4b98cbe894926451badd531a6c5d5fa0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/4b/4ba2329b63d54f0187bcaa12486b1b0f b/Close Enough!/Library/metadata/4b/4ba2329b63d54f0187bcaa12486b1b0f deleted file mode 100644 index 0b2ff91..0000000 Binary files a/Close Enough!/Library/metadata/4b/4ba2329b63d54f0187bcaa12486b1b0f and /dev/null differ diff --git a/Close Enough!/Library/metadata/4b/4ba2329b63d54f0187bcaa12486b1b0f.info b/Close Enough!/Library/metadata/4b/4ba2329b63d54f0187bcaa12486b1b0f.info deleted file mode 100644 index 20ea559..0000000 Binary files a/Close Enough!/Library/metadata/4b/4ba2329b63d54f0187bcaa12486b1b0f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/4c/4c6fe94acbb24417c988bab18cbd5209 b/Close Enough!/Library/metadata/4c/4c6fe94acbb24417c988bab18cbd5209 deleted file mode 100644 index 1e42e5b..0000000 Binary files a/Close Enough!/Library/metadata/4c/4c6fe94acbb24417c988bab18cbd5209 and /dev/null differ diff --git a/Close Enough!/Library/metadata/4c/4c6fe94acbb24417c988bab18cbd5209.info b/Close Enough!/Library/metadata/4c/4c6fe94acbb24417c988bab18cbd5209.info deleted file mode 100644 index f0c1fbb..0000000 Binary files a/Close Enough!/Library/metadata/4c/4c6fe94acbb24417c988bab18cbd5209.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/4d/4d262f8394320314fa535cf5ea3caff8 b/Close Enough!/Library/metadata/4d/4d262f8394320314fa535cf5ea3caff8 deleted file mode 100644 index e20f37b..0000000 Binary files a/Close Enough!/Library/metadata/4d/4d262f8394320314fa535cf5ea3caff8 and /dev/null differ diff --git a/Close Enough!/Library/metadata/4d/4d262f8394320314fa535cf5ea3caff8.info b/Close Enough!/Library/metadata/4d/4d262f8394320314fa535cf5ea3caff8.info deleted file mode 100644 index cadfaae..0000000 Binary files a/Close Enough!/Library/metadata/4d/4d262f8394320314fa535cf5ea3caff8.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/4d/4d262f8394320314fa535cf5ea3caff8.resource b/Close Enough!/Library/metadata/4d/4d262f8394320314fa535cf5ea3caff8.resource deleted file mode 100644 index 3865b52..0000000 Binary files a/Close Enough!/Library/metadata/4d/4d262f8394320314fa535cf5ea3caff8.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/4d/4d7e17dda2a11494596a04d884ee129b b/Close Enough!/Library/metadata/4d/4d7e17dda2a11494596a04d884ee129b deleted file mode 100644 index c20996c..0000000 Binary files a/Close Enough!/Library/metadata/4d/4d7e17dda2a11494596a04d884ee129b and /dev/null differ diff --git a/Close Enough!/Library/metadata/4d/4d7e17dda2a11494596a04d884ee129b.info b/Close Enough!/Library/metadata/4d/4d7e17dda2a11494596a04d884ee129b.info deleted file mode 100644 index 0aff564..0000000 Binary files a/Close Enough!/Library/metadata/4d/4d7e17dda2a11494596a04d884ee129b.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/4d/4d7e17dda2a11494596a04d884ee129b.resource b/Close Enough!/Library/metadata/4d/4d7e17dda2a11494596a04d884ee129b.resource deleted file mode 100644 index c7a684f..0000000 Binary files a/Close Enough!/Library/metadata/4d/4d7e17dda2a11494596a04d884ee129b.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/4d/4dc852954c67d1c489b6a7bd28f6805f b/Close Enough!/Library/metadata/4d/4dc852954c67d1c489b6a7bd28f6805f deleted file mode 100644 index 8328dd5..0000000 Binary files a/Close Enough!/Library/metadata/4d/4dc852954c67d1c489b6a7bd28f6805f and /dev/null differ diff --git a/Close Enough!/Library/metadata/4d/4dc852954c67d1c489b6a7bd28f6805f.info b/Close Enough!/Library/metadata/4d/4dc852954c67d1c489b6a7bd28f6805f.info deleted file mode 100644 index 9a7289f..0000000 Binary files a/Close Enough!/Library/metadata/4d/4dc852954c67d1c489b6a7bd28f6805f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/4d/4dc852954c67d1c489b6a7bd28f6805f.resource b/Close Enough!/Library/metadata/4d/4dc852954c67d1c489b6a7bd28f6805f.resource deleted file mode 100644 index c735fdf..0000000 Binary files a/Close Enough!/Library/metadata/4d/4dc852954c67d1c489b6a7bd28f6805f.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/4e/4e7c9ab97e5884e4eaa5967e9024f39c b/Close Enough!/Library/metadata/4e/4e7c9ab97e5884e4eaa5967e9024f39c deleted file mode 100644 index daabe67..0000000 Binary files a/Close Enough!/Library/metadata/4e/4e7c9ab97e5884e4eaa5967e9024f39c and /dev/null differ diff --git a/Close Enough!/Library/metadata/4e/4e7c9ab97e5884e4eaa5967e9024f39c.info b/Close Enough!/Library/metadata/4e/4e7c9ab97e5884e4eaa5967e9024f39c.info deleted file mode 100644 index 4bc2cc7..0000000 Binary files a/Close Enough!/Library/metadata/4e/4e7c9ab97e5884e4eaa5967e9024f39c.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/4f/4f0c19ab7320ac643a49a3b7e5e6312a b/Close Enough!/Library/metadata/4f/4f0c19ab7320ac643a49a3b7e5e6312a deleted file mode 100644 index dd5d7ad..0000000 Binary files a/Close Enough!/Library/metadata/4f/4f0c19ab7320ac643a49a3b7e5e6312a and /dev/null differ diff --git a/Close Enough!/Library/metadata/4f/4f0c19ab7320ac643a49a3b7e5e6312a.info b/Close Enough!/Library/metadata/4f/4f0c19ab7320ac643a49a3b7e5e6312a.info deleted file mode 100644 index 9cecad8..0000000 Binary files a/Close Enough!/Library/metadata/4f/4f0c19ab7320ac643a49a3b7e5e6312a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/4f/4f0c19ab7320ac643a49a3b7e5e6312a.resource b/Close Enough!/Library/metadata/4f/4f0c19ab7320ac643a49a3b7e5e6312a.resource deleted file mode 100644 index e6afb22..0000000 Binary files a/Close Enough!/Library/metadata/4f/4f0c19ab7320ac643a49a3b7e5e6312a.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/4f/4f234578336894dc081edf696f2ff5f2 b/Close Enough!/Library/metadata/4f/4f234578336894dc081edf696f2ff5f2 deleted file mode 100644 index 0d7f42f..0000000 Binary files a/Close Enough!/Library/metadata/4f/4f234578336894dc081edf696f2ff5f2 and /dev/null differ diff --git a/Close Enough!/Library/metadata/4f/4f234578336894dc081edf696f2ff5f2.info b/Close Enough!/Library/metadata/4f/4f234578336894dc081edf696f2ff5f2.info deleted file mode 100644 index 15de5bc..0000000 Binary files a/Close Enough!/Library/metadata/4f/4f234578336894dc081edf696f2ff5f2.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/50/50b1d1bf7def5424cb49eeea301da59b b/Close Enough!/Library/metadata/50/50b1d1bf7def5424cb49eeea301da59b deleted file mode 100644 index 8296c19..0000000 Binary files a/Close Enough!/Library/metadata/50/50b1d1bf7def5424cb49eeea301da59b and /dev/null differ diff --git a/Close Enough!/Library/metadata/50/50b1d1bf7def5424cb49eeea301da59b.info b/Close Enough!/Library/metadata/50/50b1d1bf7def5424cb49eeea301da59b.info deleted file mode 100644 index 1e5e3ab..0000000 Binary files a/Close Enough!/Library/metadata/50/50b1d1bf7def5424cb49eeea301da59b.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/51/510d1d319d2754ea4a47c6dd8c421ea0 b/Close Enough!/Library/metadata/51/510d1d319d2754ea4a47c6dd8c421ea0 deleted file mode 100644 index ae133bf..0000000 Binary files a/Close Enough!/Library/metadata/51/510d1d319d2754ea4a47c6dd8c421ea0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/51/510d1d319d2754ea4a47c6dd8c421ea0.info b/Close Enough!/Library/metadata/51/510d1d319d2754ea4a47c6dd8c421ea0.info deleted file mode 100644 index 8eda38c..0000000 Binary files a/Close Enough!/Library/metadata/51/510d1d319d2754ea4a47c6dd8c421ea0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/51/51148faf91d984e52876f817a73103e5 b/Close Enough!/Library/metadata/51/51148faf91d984e52876f817a73103e5 deleted file mode 100644 index 9a3b9d0..0000000 Binary files a/Close Enough!/Library/metadata/51/51148faf91d984e52876f817a73103e5 and /dev/null differ diff --git a/Close Enough!/Library/metadata/51/51148faf91d984e52876f817a73103e5.info b/Close Enough!/Library/metadata/51/51148faf91d984e52876f817a73103e5.info deleted file mode 100644 index 65e3798..0000000 Binary files a/Close Enough!/Library/metadata/51/51148faf91d984e52876f817a73103e5.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/51/511b368c9470f4dd386a1d0d38b18976 b/Close Enough!/Library/metadata/51/511b368c9470f4dd386a1d0d38b18976 deleted file mode 100644 index 2ac1f9a..0000000 Binary files a/Close Enough!/Library/metadata/51/511b368c9470f4dd386a1d0d38b18976 and /dev/null differ diff --git a/Close Enough!/Library/metadata/51/511b368c9470f4dd386a1d0d38b18976.info b/Close Enough!/Library/metadata/51/511b368c9470f4dd386a1d0d38b18976.info deleted file mode 100644 index 58a744e..0000000 Binary files a/Close Enough!/Library/metadata/51/511b368c9470f4dd386a1d0d38b18976.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/51/512e488bce130734aae5f494c86272be b/Close Enough!/Library/metadata/51/512e488bce130734aae5f494c86272be deleted file mode 100644 index 9b4653e..0000000 Binary files a/Close Enough!/Library/metadata/51/512e488bce130734aae5f494c86272be and /dev/null differ diff --git a/Close Enough!/Library/metadata/51/512e488bce130734aae5f494c86272be.info b/Close Enough!/Library/metadata/51/512e488bce130734aae5f494c86272be.info deleted file mode 100644 index 6606088..0000000 Binary files a/Close Enough!/Library/metadata/51/512e488bce130734aae5f494c86272be.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/51/517af1b5b81b93b43b9745d58f017562 b/Close Enough!/Library/metadata/51/517af1b5b81b93b43b9745d58f017562 deleted file mode 100644 index dfc75b7..0000000 Binary files a/Close Enough!/Library/metadata/51/517af1b5b81b93b43b9745d58f017562 and /dev/null differ diff --git a/Close Enough!/Library/metadata/51/517af1b5b81b93b43b9745d58f017562.info b/Close Enough!/Library/metadata/51/517af1b5b81b93b43b9745d58f017562.info deleted file mode 100644 index b9a37c2..0000000 Binary files a/Close Enough!/Library/metadata/51/517af1b5b81b93b43b9745d58f017562.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/51/51973f0999a2a6c4faf28df51b41cb2f b/Close Enough!/Library/metadata/51/51973f0999a2a6c4faf28df51b41cb2f deleted file mode 100644 index bc83ad3..0000000 Binary files a/Close Enough!/Library/metadata/51/51973f0999a2a6c4faf28df51b41cb2f and /dev/null differ diff --git a/Close Enough!/Library/metadata/51/51973f0999a2a6c4faf28df51b41cb2f.info b/Close Enough!/Library/metadata/51/51973f0999a2a6c4faf28df51b41cb2f.info deleted file mode 100644 index 69661e7..0000000 Binary files a/Close Enough!/Library/metadata/51/51973f0999a2a6c4faf28df51b41cb2f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/51/51973f0999a2a6c4faf28df51b41cb2f.resource b/Close Enough!/Library/metadata/51/51973f0999a2a6c4faf28df51b41cb2f.resource deleted file mode 100644 index 75665f9..0000000 Binary files a/Close Enough!/Library/metadata/51/51973f0999a2a6c4faf28df51b41cb2f.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/53/53ebcfaa2e1e4e2dbc85882cd5a73fa1 b/Close Enough!/Library/metadata/53/53ebcfaa2e1e4e2dbc85882cd5a73fa1 deleted file mode 100644 index 864d572..0000000 Binary files a/Close Enough!/Library/metadata/53/53ebcfaa2e1e4e2dbc85882cd5a73fa1 and /dev/null differ diff --git a/Close Enough!/Library/metadata/53/53ebcfaa2e1e4e2dbc85882cd5a73fa1.info b/Close Enough!/Library/metadata/53/53ebcfaa2e1e4e2dbc85882cd5a73fa1.info deleted file mode 100644 index 6b954b3..0000000 Binary files a/Close Enough!/Library/metadata/53/53ebcfaa2e1e4e2dbc85882cd5a73fa1.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/56/564fe1a7e6ab6f442b00263be257480c b/Close Enough!/Library/metadata/56/564fe1a7e6ab6f442b00263be257480c deleted file mode 100644 index 376c10f..0000000 Binary files a/Close Enough!/Library/metadata/56/564fe1a7e6ab6f442b00263be257480c and /dev/null differ diff --git a/Close Enough!/Library/metadata/56/564fe1a7e6ab6f442b00263be257480c.info b/Close Enough!/Library/metadata/56/564fe1a7e6ab6f442b00263be257480c.info deleted file mode 100644 index 9a85e46..0000000 Binary files a/Close Enough!/Library/metadata/56/564fe1a7e6ab6f442b00263be257480c.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/56/566357c56996d8243a94b15eb09c9d4f b/Close Enough!/Library/metadata/56/566357c56996d8243a94b15eb09c9d4f deleted file mode 100644 index afe6d63..0000000 Binary files a/Close Enough!/Library/metadata/56/566357c56996d8243a94b15eb09c9d4f and /dev/null differ diff --git a/Close Enough!/Library/metadata/56/566357c56996d8243a94b15eb09c9d4f.info b/Close Enough!/Library/metadata/56/566357c56996d8243a94b15eb09c9d4f.info deleted file mode 100644 index 1b7ddda..0000000 Binary files a/Close Enough!/Library/metadata/56/566357c56996d8243a94b15eb09c9d4f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/56/56c4630952ccd9546aa30a1eddc073e8 b/Close Enough!/Library/metadata/56/56c4630952ccd9546aa30a1eddc073e8 deleted file mode 100644 index a33011a..0000000 Binary files a/Close Enough!/Library/metadata/56/56c4630952ccd9546aa30a1eddc073e8 and /dev/null differ diff --git a/Close Enough!/Library/metadata/56/56c4630952ccd9546aa30a1eddc073e8.info b/Close Enough!/Library/metadata/56/56c4630952ccd9546aa30a1eddc073e8.info deleted file mode 100644 index 11fa4d8..0000000 Binary files a/Close Enough!/Library/metadata/56/56c4630952ccd9546aa30a1eddc073e8.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/56/56c75194b4ddca446bcd71555787e8f8 b/Close Enough!/Library/metadata/56/56c75194b4ddca446bcd71555787e8f8 deleted file mode 100644 index 561a44e..0000000 Binary files a/Close Enough!/Library/metadata/56/56c75194b4ddca446bcd71555787e8f8 and /dev/null differ diff --git a/Close Enough!/Library/metadata/56/56c75194b4ddca446bcd71555787e8f8.info b/Close Enough!/Library/metadata/56/56c75194b4ddca446bcd71555787e8f8.info deleted file mode 100644 index a4d3f47..0000000 Binary files a/Close Enough!/Library/metadata/56/56c75194b4ddca446bcd71555787e8f8.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/56/56f2557b618f3b44088e4035b437faeb b/Close Enough!/Library/metadata/56/56f2557b618f3b44088e4035b437faeb deleted file mode 100644 index 5d12b16..0000000 Binary files a/Close Enough!/Library/metadata/56/56f2557b618f3b44088e4035b437faeb and /dev/null differ diff --git a/Close Enough!/Library/metadata/56/56f2557b618f3b44088e4035b437faeb.info b/Close Enough!/Library/metadata/56/56f2557b618f3b44088e4035b437faeb.info deleted file mode 100644 index c4e4e78..0000000 Binary files a/Close Enough!/Library/metadata/56/56f2557b618f3b44088e4035b437faeb.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/56/56f2557b618f3b44088e4035b437faeb.resource b/Close Enough!/Library/metadata/56/56f2557b618f3b44088e4035b437faeb.resource deleted file mode 100644 index 130e3cf..0000000 Binary files a/Close Enough!/Library/metadata/56/56f2557b618f3b44088e4035b437faeb.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/57/5782f9e9e6e0bb94bac99aeea24814fc b/Close Enough!/Library/metadata/57/5782f9e9e6e0bb94bac99aeea24814fc deleted file mode 100644 index 9dd06bf..0000000 Binary files a/Close Enough!/Library/metadata/57/5782f9e9e6e0bb94bac99aeea24814fc and /dev/null differ diff --git a/Close Enough!/Library/metadata/57/5782f9e9e6e0bb94bac99aeea24814fc.info b/Close Enough!/Library/metadata/57/5782f9e9e6e0bb94bac99aeea24814fc.info deleted file mode 100644 index 2f38d58..0000000 Binary files a/Close Enough!/Library/metadata/57/5782f9e9e6e0bb94bac99aeea24814fc.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/57/57ee29ab286c04014b2ed5b4e07ee9f9 b/Close Enough!/Library/metadata/57/57ee29ab286c04014b2ed5b4e07ee9f9 deleted file mode 100644 index c326615..0000000 Binary files a/Close Enough!/Library/metadata/57/57ee29ab286c04014b2ed5b4e07ee9f9 and /dev/null differ diff --git a/Close Enough!/Library/metadata/57/57ee29ab286c04014b2ed5b4e07ee9f9.info b/Close Enough!/Library/metadata/57/57ee29ab286c04014b2ed5b4e07ee9f9.info deleted file mode 100644 index f189f92..0000000 Binary files a/Close Enough!/Library/metadata/57/57ee29ab286c04014b2ed5b4e07ee9f9.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/57/57f6270effd8da44ab7bc377a073e249 b/Close Enough!/Library/metadata/57/57f6270effd8da44ab7bc377a073e249 deleted file mode 100644 index cebc8ab..0000000 Binary files a/Close Enough!/Library/metadata/57/57f6270effd8da44ab7bc377a073e249 and /dev/null differ diff --git a/Close Enough!/Library/metadata/57/57f6270effd8da44ab7bc377a073e249.info b/Close Enough!/Library/metadata/57/57f6270effd8da44ab7bc377a073e249.info deleted file mode 100644 index ea03b47..0000000 Binary files a/Close Enough!/Library/metadata/57/57f6270effd8da44ab7bc377a073e249.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/5a/5a78353c03d362346b85af273d687d7f b/Close Enough!/Library/metadata/5a/5a78353c03d362346b85af273d687d7f deleted file mode 100644 index 66ab127..0000000 Binary files a/Close Enough!/Library/metadata/5a/5a78353c03d362346b85af273d687d7f and /dev/null differ diff --git a/Close Enough!/Library/metadata/5a/5a78353c03d362346b85af273d687d7f.info b/Close Enough!/Library/metadata/5a/5a78353c03d362346b85af273d687d7f.info deleted file mode 100644 index e8e8170..0000000 Binary files a/Close Enough!/Library/metadata/5a/5a78353c03d362346b85af273d687d7f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/5b/5b1c53c33216b4ae590eb509ba2b7d6a b/Close Enough!/Library/metadata/5b/5b1c53c33216b4ae590eb509ba2b7d6a deleted file mode 100644 index a7bbee7..0000000 Binary files a/Close Enough!/Library/metadata/5b/5b1c53c33216b4ae590eb509ba2b7d6a and /dev/null differ diff --git a/Close Enough!/Library/metadata/5b/5b1c53c33216b4ae590eb509ba2b7d6a.info b/Close Enough!/Library/metadata/5b/5b1c53c33216b4ae590eb509ba2b7d6a.info deleted file mode 100644 index 0b911f5..0000000 Binary files a/Close Enough!/Library/metadata/5b/5b1c53c33216b4ae590eb509ba2b7d6a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/5b/5b914d7e6b83f104da8b2a1c6bd64e3f b/Close Enough!/Library/metadata/5b/5b914d7e6b83f104da8b2a1c6bd64e3f deleted file mode 100644 index 3340138..0000000 Binary files a/Close Enough!/Library/metadata/5b/5b914d7e6b83f104da8b2a1c6bd64e3f and /dev/null differ diff --git a/Close Enough!/Library/metadata/5b/5b914d7e6b83f104da8b2a1c6bd64e3f.info b/Close Enough!/Library/metadata/5b/5b914d7e6b83f104da8b2a1c6bd64e3f.info deleted file mode 100644 index 3cc2e0a..0000000 Binary files a/Close Enough!/Library/metadata/5b/5b914d7e6b83f104da8b2a1c6bd64e3f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/5c/5c8e5df796a6ca14d8a4ccb53670d0a8 b/Close Enough!/Library/metadata/5c/5c8e5df796a6ca14d8a4ccb53670d0a8 deleted file mode 100644 index 7a13cf7..0000000 Binary files a/Close Enough!/Library/metadata/5c/5c8e5df796a6ca14d8a4ccb53670d0a8 and /dev/null differ diff --git a/Close Enough!/Library/metadata/5c/5c8e5df796a6ca14d8a4ccb53670d0a8.info b/Close Enough!/Library/metadata/5c/5c8e5df796a6ca14d8a4ccb53670d0a8.info deleted file mode 100644 index 4178708..0000000 Binary files a/Close Enough!/Library/metadata/5c/5c8e5df796a6ca14d8a4ccb53670d0a8.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/5d/5d757120c2679c94f95bbb8c06341f10 b/Close Enough!/Library/metadata/5d/5d757120c2679c94f95bbb8c06341f10 deleted file mode 100644 index e5c0d8e..0000000 Binary files a/Close Enough!/Library/metadata/5d/5d757120c2679c94f95bbb8c06341f10 and /dev/null differ diff --git a/Close Enough!/Library/metadata/5d/5d757120c2679c94f95bbb8c06341f10.info b/Close Enough!/Library/metadata/5d/5d757120c2679c94f95bbb8c06341f10.info deleted file mode 100644 index 82b010c..0000000 Binary files a/Close Enough!/Library/metadata/5d/5d757120c2679c94f95bbb8c06341f10.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/5d/5dc27209f60e37241aabbf1ee096cd6a b/Close Enough!/Library/metadata/5d/5dc27209f60e37241aabbf1ee096cd6a deleted file mode 100644 index d0f6362..0000000 Binary files a/Close Enough!/Library/metadata/5d/5dc27209f60e37241aabbf1ee096cd6a and /dev/null differ diff --git a/Close Enough!/Library/metadata/5d/5dc27209f60e37241aabbf1ee096cd6a.info b/Close Enough!/Library/metadata/5d/5dc27209f60e37241aabbf1ee096cd6a.info deleted file mode 100644 index 3481e30..0000000 Binary files a/Close Enough!/Library/metadata/5d/5dc27209f60e37241aabbf1ee096cd6a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/5e/5e99e3ba74ad04ff985bef9bf50fe483 b/Close Enough!/Library/metadata/5e/5e99e3ba74ad04ff985bef9bf50fe483 deleted file mode 100644 index da1aa90..0000000 Binary files a/Close Enough!/Library/metadata/5e/5e99e3ba74ad04ff985bef9bf50fe483 and /dev/null differ diff --git a/Close Enough!/Library/metadata/5e/5e99e3ba74ad04ff985bef9bf50fe483.info b/Close Enough!/Library/metadata/5e/5e99e3ba74ad04ff985bef9bf50fe483.info deleted file mode 100644 index f68a082..0000000 Binary files a/Close Enough!/Library/metadata/5e/5e99e3ba74ad04ff985bef9bf50fe483.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/5e/5ea9b321809ddd843873462c5770dbf0 b/Close Enough!/Library/metadata/5e/5ea9b321809ddd843873462c5770dbf0 deleted file mode 100644 index 8e50cd5..0000000 Binary files a/Close Enough!/Library/metadata/5e/5ea9b321809ddd843873462c5770dbf0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/5e/5ea9b321809ddd843873462c5770dbf0.info b/Close Enough!/Library/metadata/5e/5ea9b321809ddd843873462c5770dbf0.info deleted file mode 100644 index 03fc971..0000000 Binary files a/Close Enough!/Library/metadata/5e/5ea9b321809ddd843873462c5770dbf0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/5e/5ea9b321809ddd843873462c5770dbf0.resource b/Close Enough!/Library/metadata/5e/5ea9b321809ddd843873462c5770dbf0.resource deleted file mode 100644 index 939df3d..0000000 Binary files a/Close Enough!/Library/metadata/5e/5ea9b321809ddd843873462c5770dbf0.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/5e/5edc0e433386b443f8de1169a1cbcf11 b/Close Enough!/Library/metadata/5e/5edc0e433386b443f8de1169a1cbcf11 deleted file mode 100644 index 799054c..0000000 Binary files a/Close Enough!/Library/metadata/5e/5edc0e433386b443f8de1169a1cbcf11 and /dev/null differ diff --git a/Close Enough!/Library/metadata/5e/5edc0e433386b443f8de1169a1cbcf11.info b/Close Enough!/Library/metadata/5e/5edc0e433386b443f8de1169a1cbcf11.info deleted file mode 100644 index 262beca..0000000 Binary files a/Close Enough!/Library/metadata/5e/5edc0e433386b443f8de1169a1cbcf11.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/5f/5f32cd94baa94578a686d4b9d6b660f7 b/Close Enough!/Library/metadata/5f/5f32cd94baa94578a686d4b9d6b660f7 deleted file mode 100644 index cdf8d70..0000000 Binary files a/Close Enough!/Library/metadata/5f/5f32cd94baa94578a686d4b9d6b660f7 and /dev/null differ diff --git a/Close Enough!/Library/metadata/5f/5f32cd94baa94578a686d4b9d6b660f7.info b/Close Enough!/Library/metadata/5f/5f32cd94baa94578a686d4b9d6b660f7.info deleted file mode 100644 index a744203..0000000 Binary files a/Close Enough!/Library/metadata/5f/5f32cd94baa94578a686d4b9d6b660f7.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/60/600b943b633d37c45b1d7ae89111af4a b/Close Enough!/Library/metadata/60/600b943b633d37c45b1d7ae89111af4a deleted file mode 100644 index 02a48b9..0000000 Binary files a/Close Enough!/Library/metadata/60/600b943b633d37c45b1d7ae89111af4a and /dev/null differ diff --git a/Close Enough!/Library/metadata/60/600b943b633d37c45b1d7ae89111af4a.info b/Close Enough!/Library/metadata/60/600b943b633d37c45b1d7ae89111af4a.info deleted file mode 100644 index a17252d..0000000 Binary files a/Close Enough!/Library/metadata/60/600b943b633d37c45b1d7ae89111af4a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/60/6038d552660710e449af84fd26f6f959 b/Close Enough!/Library/metadata/60/6038d552660710e449af84fd26f6f959 deleted file mode 100644 index f474a0a..0000000 Binary files a/Close Enough!/Library/metadata/60/6038d552660710e449af84fd26f6f959 and /dev/null differ diff --git a/Close Enough!/Library/metadata/60/6038d552660710e449af84fd26f6f959.info b/Close Enough!/Library/metadata/60/6038d552660710e449af84fd26f6f959.info deleted file mode 100644 index 25b016a..0000000 Binary files a/Close Enough!/Library/metadata/60/6038d552660710e449af84fd26f6f959.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/60/60838594ef8f5524fae2f918c2fb7097 b/Close Enough!/Library/metadata/60/60838594ef8f5524fae2f918c2fb7097 deleted file mode 100644 index 4a1e348..0000000 Binary files a/Close Enough!/Library/metadata/60/60838594ef8f5524fae2f918c2fb7097 and /dev/null differ diff --git a/Close Enough!/Library/metadata/60/60838594ef8f5524fae2f918c2fb7097.info b/Close Enough!/Library/metadata/60/60838594ef8f5524fae2f918c2fb7097.info deleted file mode 100644 index 77fb271..0000000 Binary files a/Close Enough!/Library/metadata/60/60838594ef8f5524fae2f918c2fb7097.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/60/6089506019a488748a7063f3e9d99c29 b/Close Enough!/Library/metadata/60/6089506019a488748a7063f3e9d99c29 deleted file mode 100644 index 2cda80a..0000000 Binary files a/Close Enough!/Library/metadata/60/6089506019a488748a7063f3e9d99c29 and /dev/null differ diff --git a/Close Enough!/Library/metadata/60/6089506019a488748a7063f3e9d99c29.info b/Close Enough!/Library/metadata/60/6089506019a488748a7063f3e9d99c29.info deleted file mode 100644 index 4ec5f6a..0000000 Binary files a/Close Enough!/Library/metadata/60/6089506019a488748a7063f3e9d99c29.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/61/61296e529f3d9384dac3daa5b17ee44f b/Close Enough!/Library/metadata/61/61296e529f3d9384dac3daa5b17ee44f deleted file mode 100644 index 3e35e11..0000000 Binary files a/Close Enough!/Library/metadata/61/61296e529f3d9384dac3daa5b17ee44f and /dev/null differ diff --git a/Close Enough!/Library/metadata/61/61296e529f3d9384dac3daa5b17ee44f.info b/Close Enough!/Library/metadata/61/61296e529f3d9384dac3daa5b17ee44f.info deleted file mode 100644 index d9d3a7f..0000000 Binary files a/Close Enough!/Library/metadata/61/61296e529f3d9384dac3daa5b17ee44f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/61/616853845a4a54949ac851f2f807aa2a b/Close Enough!/Library/metadata/61/616853845a4a54949ac851f2f807aa2a deleted file mode 100644 index abcb187..0000000 Binary files a/Close Enough!/Library/metadata/61/616853845a4a54949ac851f2f807aa2a and /dev/null differ diff --git a/Close Enough!/Library/metadata/61/616853845a4a54949ac851f2f807aa2a.info b/Close Enough!/Library/metadata/61/616853845a4a54949ac851f2f807aa2a.info deleted file mode 100644 index 7af0b65..0000000 Binary files a/Close Enough!/Library/metadata/61/616853845a4a54949ac851f2f807aa2a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/62/6206041754a6d4303b66e7b42f8e09d8 b/Close Enough!/Library/metadata/62/6206041754a6d4303b66e7b42f8e09d8 deleted file mode 100644 index 30ca98f..0000000 Binary files a/Close Enough!/Library/metadata/62/6206041754a6d4303b66e7b42f8e09d8 and /dev/null differ diff --git a/Close Enough!/Library/metadata/62/6206041754a6d4303b66e7b42f8e09d8.info b/Close Enough!/Library/metadata/62/6206041754a6d4303b66e7b42f8e09d8.info deleted file mode 100644 index 40a791c..0000000 Binary files a/Close Enough!/Library/metadata/62/6206041754a6d4303b66e7b42f8e09d8.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/62/62772aad98ed04f0d955b7d20de61f7f b/Close Enough!/Library/metadata/62/62772aad98ed04f0d955b7d20de61f7f deleted file mode 100644 index 69d80ea..0000000 Binary files a/Close Enough!/Library/metadata/62/62772aad98ed04f0d955b7d20de61f7f and /dev/null differ diff --git a/Close Enough!/Library/metadata/62/62772aad98ed04f0d955b7d20de61f7f.info b/Close Enough!/Library/metadata/62/62772aad98ed04f0d955b7d20de61f7f.info deleted file mode 100644 index 5fa5483..0000000 Binary files a/Close Enough!/Library/metadata/62/62772aad98ed04f0d955b7d20de61f7f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/64/642e291abf06cb84280b8fde4d28a1d0 b/Close Enough!/Library/metadata/64/642e291abf06cb84280b8fde4d28a1d0 deleted file mode 100644 index ca3dd7d..0000000 Binary files a/Close Enough!/Library/metadata/64/642e291abf06cb84280b8fde4d28a1d0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/64/642e291abf06cb84280b8fde4d28a1d0.info b/Close Enough!/Library/metadata/64/642e291abf06cb84280b8fde4d28a1d0.info deleted file mode 100644 index e0293f5..0000000 Binary files a/Close Enough!/Library/metadata/64/642e291abf06cb84280b8fde4d28a1d0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/64/64b1a7cff5a85344fa1e0889f1f08839 b/Close Enough!/Library/metadata/64/64b1a7cff5a85344fa1e0889f1f08839 deleted file mode 100644 index d968853..0000000 Binary files a/Close Enough!/Library/metadata/64/64b1a7cff5a85344fa1e0889f1f08839 and /dev/null differ diff --git a/Close Enough!/Library/metadata/64/64b1a7cff5a85344fa1e0889f1f08839.info b/Close Enough!/Library/metadata/64/64b1a7cff5a85344fa1e0889f1f08839.info deleted file mode 100644 index c1a96b3..0000000 Binary files a/Close Enough!/Library/metadata/64/64b1a7cff5a85344fa1e0889f1f08839.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/64/64b1a7cff5a85344fa1e0889f1f08839.resource b/Close Enough!/Library/metadata/64/64b1a7cff5a85344fa1e0889f1f08839.resource deleted file mode 100644 index cedc251..0000000 Binary files a/Close Enough!/Library/metadata/64/64b1a7cff5a85344fa1e0889f1f08839.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/65/65250be5ddd02ea43bdc8bc04c49f962 b/Close Enough!/Library/metadata/65/65250be5ddd02ea43bdc8bc04c49f962 deleted file mode 100644 index 0301b62..0000000 Binary files a/Close Enough!/Library/metadata/65/65250be5ddd02ea43bdc8bc04c49f962 and /dev/null differ diff --git a/Close Enough!/Library/metadata/65/65250be5ddd02ea43bdc8bc04c49f962.info b/Close Enough!/Library/metadata/65/65250be5ddd02ea43bdc8bc04c49f962.info deleted file mode 100644 index df5d644..0000000 Binary files a/Close Enough!/Library/metadata/65/65250be5ddd02ea43bdc8bc04c49f962.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/65/6597c6ea86d36477081342001145d8d9 b/Close Enough!/Library/metadata/65/6597c6ea86d36477081342001145d8d9 deleted file mode 100644 index 6430cd1..0000000 Binary files a/Close Enough!/Library/metadata/65/6597c6ea86d36477081342001145d8d9 and /dev/null differ diff --git a/Close Enough!/Library/metadata/65/6597c6ea86d36477081342001145d8d9.info b/Close Enough!/Library/metadata/65/6597c6ea86d36477081342001145d8d9.info deleted file mode 100644 index 248dbd9..0000000 Binary files a/Close Enough!/Library/metadata/65/6597c6ea86d36477081342001145d8d9.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/67/67072e4bb99d7e84fa2afa9fc5830e35 b/Close Enough!/Library/metadata/67/67072e4bb99d7e84fa2afa9fc5830e35 deleted file mode 100644 index 71bb687..0000000 Binary files a/Close Enough!/Library/metadata/67/67072e4bb99d7e84fa2afa9fc5830e35 and /dev/null differ diff --git a/Close Enough!/Library/metadata/67/67072e4bb99d7e84fa2afa9fc5830e35.info b/Close Enough!/Library/metadata/67/67072e4bb99d7e84fa2afa9fc5830e35.info deleted file mode 100644 index 8942cc8..0000000 Binary files a/Close Enough!/Library/metadata/67/67072e4bb99d7e84fa2afa9fc5830e35.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/67/6722231e3f6fe2e46accc3f24885f478 b/Close Enough!/Library/metadata/67/6722231e3f6fe2e46accc3f24885f478 deleted file mode 100644 index 74b35d4..0000000 Binary files a/Close Enough!/Library/metadata/67/6722231e3f6fe2e46accc3f24885f478 and /dev/null differ diff --git a/Close Enough!/Library/metadata/67/6722231e3f6fe2e46accc3f24885f478.info b/Close Enough!/Library/metadata/67/6722231e3f6fe2e46accc3f24885f478.info deleted file mode 100644 index 66e8849..0000000 Binary files a/Close Enough!/Library/metadata/67/6722231e3f6fe2e46accc3f24885f478.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/69/6981461fe431401459211818212a29cf b/Close Enough!/Library/metadata/69/6981461fe431401459211818212a29cf deleted file mode 100644 index 9915277..0000000 Binary files a/Close Enough!/Library/metadata/69/6981461fe431401459211818212a29cf and /dev/null differ diff --git a/Close Enough!/Library/metadata/69/6981461fe431401459211818212a29cf.info b/Close Enough!/Library/metadata/69/6981461fe431401459211818212a29cf.info deleted file mode 100644 index bbaad88..0000000 Binary files a/Close Enough!/Library/metadata/69/6981461fe431401459211818212a29cf.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/6a/6a10b2909283487f913b00d94cd3faf5 b/Close Enough!/Library/metadata/6a/6a10b2909283487f913b00d94cd3faf5 deleted file mode 100644 index e4ee200..0000000 Binary files a/Close Enough!/Library/metadata/6a/6a10b2909283487f913b00d94cd3faf5 and /dev/null differ diff --git a/Close Enough!/Library/metadata/6a/6a10b2909283487f913b00d94cd3faf5.info b/Close Enough!/Library/metadata/6a/6a10b2909283487f913b00d94cd3faf5.info deleted file mode 100644 index bfed484..0000000 Binary files a/Close Enough!/Library/metadata/6a/6a10b2909283487f913b00d94cd3faf5.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/6a/6a970a8482fbcf14fb515e9843318b46 b/Close Enough!/Library/metadata/6a/6a970a8482fbcf14fb515e9843318b46 deleted file mode 100644 index ef8330a..0000000 Binary files a/Close Enough!/Library/metadata/6a/6a970a8482fbcf14fb515e9843318b46 and /dev/null differ diff --git a/Close Enough!/Library/metadata/6a/6a970a8482fbcf14fb515e9843318b46.info b/Close Enough!/Library/metadata/6a/6a970a8482fbcf14fb515e9843318b46.info deleted file mode 100644 index 393effa..0000000 Binary files a/Close Enough!/Library/metadata/6a/6a970a8482fbcf14fb515e9843318b46.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/6b/6b3da2c3291b36b4c9d431fad18e9b0f b/Close Enough!/Library/metadata/6b/6b3da2c3291b36b4c9d431fad18e9b0f deleted file mode 100644 index cfd258b..0000000 Binary files a/Close Enough!/Library/metadata/6b/6b3da2c3291b36b4c9d431fad18e9b0f and /dev/null differ diff --git a/Close Enough!/Library/metadata/6b/6b3da2c3291b36b4c9d431fad18e9b0f.info b/Close Enough!/Library/metadata/6b/6b3da2c3291b36b4c9d431fad18e9b0f.info deleted file mode 100644 index 64a4b1d..0000000 Binary files a/Close Enough!/Library/metadata/6b/6b3da2c3291b36b4c9d431fad18e9b0f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/6b/6b573461b9df6984897579165d7dcf86 b/Close Enough!/Library/metadata/6b/6b573461b9df6984897579165d7dcf86 deleted file mode 100644 index 87eccec..0000000 Binary files a/Close Enough!/Library/metadata/6b/6b573461b9df6984897579165d7dcf86 and /dev/null differ diff --git a/Close Enough!/Library/metadata/6b/6b573461b9df6984897579165d7dcf86.info b/Close Enough!/Library/metadata/6b/6b573461b9df6984897579165d7dcf86.info deleted file mode 100644 index 131c6b1..0000000 Binary files a/Close Enough!/Library/metadata/6b/6b573461b9df6984897579165d7dcf86.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/6b/6b573461b9df6984897579165d7dcf86.resource b/Close Enough!/Library/metadata/6b/6b573461b9df6984897579165d7dcf86.resource deleted file mode 100644 index 3c175cf..0000000 Binary files a/Close Enough!/Library/metadata/6b/6b573461b9df6984897579165d7dcf86.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/6c/6c1d1495b415647c2945258335115ace b/Close Enough!/Library/metadata/6c/6c1d1495b415647c2945258335115ace deleted file mode 100644 index ae7b458..0000000 Binary files a/Close Enough!/Library/metadata/6c/6c1d1495b415647c2945258335115ace and /dev/null differ diff --git a/Close Enough!/Library/metadata/6c/6c1d1495b415647c2945258335115ace.info b/Close Enough!/Library/metadata/6c/6c1d1495b415647c2945258335115ace.info deleted file mode 100644 index ec7eed2..0000000 Binary files a/Close Enough!/Library/metadata/6c/6c1d1495b415647c2945258335115ace.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/6e/6e45f5aa287d6a34e8154c1ab4c155d5 b/Close Enough!/Library/metadata/6e/6e45f5aa287d6a34e8154c1ab4c155d5 deleted file mode 100644 index 5b9c9b7..0000000 Binary files a/Close Enough!/Library/metadata/6e/6e45f5aa287d6a34e8154c1ab4c155d5 and /dev/null differ diff --git a/Close Enough!/Library/metadata/6e/6e45f5aa287d6a34e8154c1ab4c155d5.info b/Close Enough!/Library/metadata/6e/6e45f5aa287d6a34e8154c1ab4c155d5.info deleted file mode 100644 index 4eb1350..0000000 Binary files a/Close Enough!/Library/metadata/6e/6e45f5aa287d6a34e8154c1ab4c155d5.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/6e/6e7c8cfeedae74eb3a562055e069e441 b/Close Enough!/Library/metadata/6e/6e7c8cfeedae74eb3a562055e069e441 deleted file mode 100644 index 814a081..0000000 Binary files a/Close Enough!/Library/metadata/6e/6e7c8cfeedae74eb3a562055e069e441 and /dev/null differ diff --git a/Close Enough!/Library/metadata/6e/6e7c8cfeedae74eb3a562055e069e441.info b/Close Enough!/Library/metadata/6e/6e7c8cfeedae74eb3a562055e069e441.info deleted file mode 100644 index a280853..0000000 Binary files a/Close Enough!/Library/metadata/6e/6e7c8cfeedae74eb3a562055e069e441.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/6f/6f1eb092094634c708c8a4f2e0f9e262 b/Close Enough!/Library/metadata/6f/6f1eb092094634c708c8a4f2e0f9e262 deleted file mode 100644 index 766cdc5..0000000 Binary files a/Close Enough!/Library/metadata/6f/6f1eb092094634c708c8a4f2e0f9e262 and /dev/null differ diff --git a/Close Enough!/Library/metadata/6f/6f1eb092094634c708c8a4f2e0f9e262.info b/Close Enough!/Library/metadata/6f/6f1eb092094634c708c8a4f2e0f9e262.info deleted file mode 100644 index b6412f3..0000000 Binary files a/Close Enough!/Library/metadata/6f/6f1eb092094634c708c8a4f2e0f9e262.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/6f/6f57808b243c1432eb9f6f79d44bfde2 b/Close Enough!/Library/metadata/6f/6f57808b243c1432eb9f6f79d44bfde2 deleted file mode 100644 index 8889b73..0000000 Binary files a/Close Enough!/Library/metadata/6f/6f57808b243c1432eb9f6f79d44bfde2 and /dev/null differ diff --git a/Close Enough!/Library/metadata/6f/6f57808b243c1432eb9f6f79d44bfde2.info b/Close Enough!/Library/metadata/6f/6f57808b243c1432eb9f6f79d44bfde2.info deleted file mode 100644 index 6592df5..0000000 Binary files a/Close Enough!/Library/metadata/6f/6f57808b243c1432eb9f6f79d44bfde2.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/70/70899eda359f7b348890f4023a53950d b/Close Enough!/Library/metadata/70/70899eda359f7b348890f4023a53950d deleted file mode 100644 index cc5efe4..0000000 Binary files a/Close Enough!/Library/metadata/70/70899eda359f7b348890f4023a53950d and /dev/null differ diff --git a/Close Enough!/Library/metadata/70/70899eda359f7b348890f4023a53950d.info b/Close Enough!/Library/metadata/70/70899eda359f7b348890f4023a53950d.info deleted file mode 100644 index aa31f9b..0000000 Binary files a/Close Enough!/Library/metadata/70/70899eda359f7b348890f4023a53950d.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/70/70899eda359f7b348890f4023a53950d.resource b/Close Enough!/Library/metadata/70/70899eda359f7b348890f4023a53950d.resource deleted file mode 100644 index e39ac65..0000000 Binary files a/Close Enough!/Library/metadata/70/70899eda359f7b348890f4023a53950d.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/70/70ed02e882fd2ac46a242f45f5ea35df b/Close Enough!/Library/metadata/70/70ed02e882fd2ac46a242f45f5ea35df deleted file mode 100644 index 9a81019..0000000 Binary files a/Close Enough!/Library/metadata/70/70ed02e882fd2ac46a242f45f5ea35df and /dev/null differ diff --git a/Close Enough!/Library/metadata/70/70ed02e882fd2ac46a242f45f5ea35df.info b/Close Enough!/Library/metadata/70/70ed02e882fd2ac46a242f45f5ea35df.info deleted file mode 100644 index 5c8f955..0000000 Binary files a/Close Enough!/Library/metadata/70/70ed02e882fd2ac46a242f45f5ea35df.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/71/71a78dc26a02d42da872e2102d830088 b/Close Enough!/Library/metadata/71/71a78dc26a02d42da872e2102d830088 deleted file mode 100644 index a09bbf0..0000000 Binary files a/Close Enough!/Library/metadata/71/71a78dc26a02d42da872e2102d830088 and /dev/null differ diff --git a/Close Enough!/Library/metadata/71/71a78dc26a02d42da872e2102d830088.info b/Close Enough!/Library/metadata/71/71a78dc26a02d42da872e2102d830088.info deleted file mode 100644 index 07ecd6b..0000000 Binary files a/Close Enough!/Library/metadata/71/71a78dc26a02d42da872e2102d830088.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/71/71b90353f416d604581caefab0cea19b b/Close Enough!/Library/metadata/71/71b90353f416d604581caefab0cea19b deleted file mode 100644 index 032ccb7..0000000 Binary files a/Close Enough!/Library/metadata/71/71b90353f416d604581caefab0cea19b and /dev/null differ diff --git a/Close Enough!/Library/metadata/71/71b90353f416d604581caefab0cea19b.info b/Close Enough!/Library/metadata/71/71b90353f416d604581caefab0cea19b.info deleted file mode 100644 index f8f2029..0000000 Binary files a/Close Enough!/Library/metadata/71/71b90353f416d604581caefab0cea19b.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/71/71bd40054c6e34c609c3e408c00f29a4 b/Close Enough!/Library/metadata/71/71bd40054c6e34c609c3e408c00f29a4 deleted file mode 100644 index 998a0bc..0000000 Binary files a/Close Enough!/Library/metadata/71/71bd40054c6e34c609c3e408c00f29a4 and /dev/null differ diff --git a/Close Enough!/Library/metadata/71/71bd40054c6e34c609c3e408c00f29a4.info b/Close Enough!/Library/metadata/71/71bd40054c6e34c609c3e408c00f29a4.info deleted file mode 100644 index 4c3ae2d..0000000 Binary files a/Close Enough!/Library/metadata/71/71bd40054c6e34c609c3e408c00f29a4.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/72/72efec40e5ad34247949b667392e6e36 b/Close Enough!/Library/metadata/72/72efec40e5ad34247949b667392e6e36 deleted file mode 100644 index b86aa56..0000000 Binary files a/Close Enough!/Library/metadata/72/72efec40e5ad34247949b667392e6e36 and /dev/null differ diff --git a/Close Enough!/Library/metadata/72/72efec40e5ad34247949b667392e6e36.info b/Close Enough!/Library/metadata/72/72efec40e5ad34247949b667392e6e36.info deleted file mode 100644 index 0bcf0f4..0000000 Binary files a/Close Enough!/Library/metadata/72/72efec40e5ad34247949b667392e6e36.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/74/7432ae83addfec942bc296a705c5bce0 b/Close Enough!/Library/metadata/74/7432ae83addfec942bc296a705c5bce0 deleted file mode 100644 index e09fff1..0000000 Binary files a/Close Enough!/Library/metadata/74/7432ae83addfec942bc296a705c5bce0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/74/7432ae83addfec942bc296a705c5bce0.info b/Close Enough!/Library/metadata/74/7432ae83addfec942bc296a705c5bce0.info deleted file mode 100644 index 1cf47c5..0000000 Binary files a/Close Enough!/Library/metadata/74/7432ae83addfec942bc296a705c5bce0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/74/74aead1d2adbe4e4dad98809f3ecea32 b/Close Enough!/Library/metadata/74/74aead1d2adbe4e4dad98809f3ecea32 deleted file mode 100644 index a2093a1..0000000 Binary files a/Close Enough!/Library/metadata/74/74aead1d2adbe4e4dad98809f3ecea32 and /dev/null differ diff --git a/Close Enough!/Library/metadata/74/74aead1d2adbe4e4dad98809f3ecea32.info b/Close Enough!/Library/metadata/74/74aead1d2adbe4e4dad98809f3ecea32.info deleted file mode 100644 index e65d2d5..0000000 Binary files a/Close Enough!/Library/metadata/74/74aead1d2adbe4e4dad98809f3ecea32.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/75/75799de484ac4f4cadc268d2cbea830a b/Close Enough!/Library/metadata/75/75799de484ac4f4cadc268d2cbea830a deleted file mode 100644 index ccbeb2c..0000000 Binary files a/Close Enough!/Library/metadata/75/75799de484ac4f4cadc268d2cbea830a and /dev/null differ diff --git a/Close Enough!/Library/metadata/75/75799de484ac4f4cadc268d2cbea830a.info b/Close Enough!/Library/metadata/75/75799de484ac4f4cadc268d2cbea830a.info deleted file mode 100644 index 46565b2..0000000 Binary files a/Close Enough!/Library/metadata/75/75799de484ac4f4cadc268d2cbea830a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/76/76349cec627454d3a80423a2eeaf0e63 b/Close Enough!/Library/metadata/76/76349cec627454d3a80423a2eeaf0e63 deleted file mode 100644 index 1b626ef..0000000 Binary files a/Close Enough!/Library/metadata/76/76349cec627454d3a80423a2eeaf0e63 and /dev/null differ diff --git a/Close Enough!/Library/metadata/76/76349cec627454d3a80423a2eeaf0e63.info b/Close Enough!/Library/metadata/76/76349cec627454d3a80423a2eeaf0e63.info deleted file mode 100644 index 9763800..0000000 Binary files a/Close Enough!/Library/metadata/76/76349cec627454d3a80423a2eeaf0e63.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/76/763992d85d3f6d4428454c2a968ce084 b/Close Enough!/Library/metadata/76/763992d85d3f6d4428454c2a968ce084 deleted file mode 100644 index 836b835..0000000 Binary files a/Close Enough!/Library/metadata/76/763992d85d3f6d4428454c2a968ce084 and /dev/null differ diff --git a/Close Enough!/Library/metadata/76/763992d85d3f6d4428454c2a968ce084.info b/Close Enough!/Library/metadata/76/763992d85d3f6d4428454c2a968ce084.info deleted file mode 100644 index 892cd6a..0000000 Binary files a/Close Enough!/Library/metadata/76/763992d85d3f6d4428454c2a968ce084.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/76/7668179ede524d6396c8b7d84461ea29 b/Close Enough!/Library/metadata/76/7668179ede524d6396c8b7d84461ea29 deleted file mode 100644 index 7f52343..0000000 Binary files a/Close Enough!/Library/metadata/76/7668179ede524d6396c8b7d84461ea29 and /dev/null differ diff --git a/Close Enough!/Library/metadata/76/7668179ede524d6396c8b7d84461ea29.info b/Close Enough!/Library/metadata/76/7668179ede524d6396c8b7d84461ea29.info deleted file mode 100644 index 3cd2ef3..0000000 Binary files a/Close Enough!/Library/metadata/76/7668179ede524d6396c8b7d84461ea29.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/77/77f0f7e2291e7144b9356d3c6c7e50aa b/Close Enough!/Library/metadata/77/77f0f7e2291e7144b9356d3c6c7e50aa deleted file mode 100644 index 3d31b7e..0000000 Binary files a/Close Enough!/Library/metadata/77/77f0f7e2291e7144b9356d3c6c7e50aa and /dev/null differ diff --git a/Close Enough!/Library/metadata/77/77f0f7e2291e7144b9356d3c6c7e50aa.info b/Close Enough!/Library/metadata/77/77f0f7e2291e7144b9356d3c6c7e50aa.info deleted file mode 100644 index de8deee..0000000 Binary files a/Close Enough!/Library/metadata/77/77f0f7e2291e7144b9356d3c6c7e50aa.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/78/786ab818ba73bd8498d5f3cb829d14bb b/Close Enough!/Library/metadata/78/786ab818ba73bd8498d5f3cb829d14bb deleted file mode 100644 index 948bded..0000000 Binary files a/Close Enough!/Library/metadata/78/786ab818ba73bd8498d5f3cb829d14bb and /dev/null differ diff --git a/Close Enough!/Library/metadata/78/786ab818ba73bd8498d5f3cb829d14bb.info b/Close Enough!/Library/metadata/78/786ab818ba73bd8498d5f3cb829d14bb.info deleted file mode 100644 index 4be4adc..0000000 Binary files a/Close Enough!/Library/metadata/78/786ab818ba73bd8498d5f3cb829d14bb.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/78/786ab818ba73bd8498d5f3cb829d14bb.resource b/Close Enough!/Library/metadata/78/786ab818ba73bd8498d5f3cb829d14bb.resource deleted file mode 100644 index e018db0..0000000 Binary files a/Close Enough!/Library/metadata/78/786ab818ba73bd8498d5f3cb829d14bb.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/78/78d24a255b9ac45b39f0dd0ff7abcc5e b/Close Enough!/Library/metadata/78/78d24a255b9ac45b39f0dd0ff7abcc5e deleted file mode 100644 index d87d2b1..0000000 Binary files a/Close Enough!/Library/metadata/78/78d24a255b9ac45b39f0dd0ff7abcc5e and /dev/null differ diff --git a/Close Enough!/Library/metadata/78/78d24a255b9ac45b39f0dd0ff7abcc5e.info b/Close Enough!/Library/metadata/78/78d24a255b9ac45b39f0dd0ff7abcc5e.info deleted file mode 100644 index 165343d..0000000 Binary files a/Close Enough!/Library/metadata/78/78d24a255b9ac45b39f0dd0ff7abcc5e.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/79/7927683d1fc5848b5abfb54ebb1028ec b/Close Enough!/Library/metadata/79/7927683d1fc5848b5abfb54ebb1028ec deleted file mode 100644 index 5cced0e..0000000 Binary files a/Close Enough!/Library/metadata/79/7927683d1fc5848b5abfb54ebb1028ec and /dev/null differ diff --git a/Close Enough!/Library/metadata/79/7927683d1fc5848b5abfb54ebb1028ec.info b/Close Enough!/Library/metadata/79/7927683d1fc5848b5abfb54ebb1028ec.info deleted file mode 100644 index 73c6435..0000000 Binary files a/Close Enough!/Library/metadata/79/7927683d1fc5848b5abfb54ebb1028ec.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/79/799d96704ce178d43a0d96ceb1c329a0 b/Close Enough!/Library/metadata/79/799d96704ce178d43a0d96ceb1c329a0 deleted file mode 100644 index bd0473e..0000000 Binary files a/Close Enough!/Library/metadata/79/799d96704ce178d43a0d96ceb1c329a0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/79/799d96704ce178d43a0d96ceb1c329a0.info b/Close Enough!/Library/metadata/79/799d96704ce178d43a0d96ceb1c329a0.info deleted file mode 100644 index ed93420..0000000 Binary files a/Close Enough!/Library/metadata/79/799d96704ce178d43a0d96ceb1c329a0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/7a/7a2b6964f8e1c8b4db62c0310dbb8593 b/Close Enough!/Library/metadata/7a/7a2b6964f8e1c8b4db62c0310dbb8593 deleted file mode 100644 index 9ddfa0f..0000000 Binary files a/Close Enough!/Library/metadata/7a/7a2b6964f8e1c8b4db62c0310dbb8593 and /dev/null differ diff --git a/Close Enough!/Library/metadata/7a/7a2b6964f8e1c8b4db62c0310dbb8593.info b/Close Enough!/Library/metadata/7a/7a2b6964f8e1c8b4db62c0310dbb8593.info deleted file mode 100644 index 72c8b9a..0000000 Binary files a/Close Enough!/Library/metadata/7a/7a2b6964f8e1c8b4db62c0310dbb8593.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/7b/7b1b616a1a6227c47bce7a86d1eddfee b/Close Enough!/Library/metadata/7b/7b1b616a1a6227c47bce7a86d1eddfee deleted file mode 100644 index bfb497e..0000000 Binary files a/Close Enough!/Library/metadata/7b/7b1b616a1a6227c47bce7a86d1eddfee and /dev/null differ diff --git a/Close Enough!/Library/metadata/7b/7b1b616a1a6227c47bce7a86d1eddfee.info b/Close Enough!/Library/metadata/7b/7b1b616a1a6227c47bce7a86d1eddfee.info deleted file mode 100644 index e6e34c6..0000000 Binary files a/Close Enough!/Library/metadata/7b/7b1b616a1a6227c47bce7a86d1eddfee.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/7b/7b1b616a1a6227c47bce7a86d1eddfee.resource b/Close Enough!/Library/metadata/7b/7b1b616a1a6227c47bce7a86d1eddfee.resource deleted file mode 100644 index 87bd331..0000000 Binary files a/Close Enough!/Library/metadata/7b/7b1b616a1a6227c47bce7a86d1eddfee.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/7b/7b4c3dd59eeca454193b1735e82e7b59 b/Close Enough!/Library/metadata/7b/7b4c3dd59eeca454193b1735e82e7b59 deleted file mode 100644 index a5da5c2..0000000 Binary files a/Close Enough!/Library/metadata/7b/7b4c3dd59eeca454193b1735e82e7b59 and /dev/null differ diff --git a/Close Enough!/Library/metadata/7b/7b4c3dd59eeca454193b1735e82e7b59.info b/Close Enough!/Library/metadata/7b/7b4c3dd59eeca454193b1735e82e7b59.info deleted file mode 100644 index c2d6f33..0000000 Binary files a/Close Enough!/Library/metadata/7b/7b4c3dd59eeca454193b1735e82e7b59.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/7b/7bab365ec61303446bb27591e4c360a0 b/Close Enough!/Library/metadata/7b/7bab365ec61303446bb27591e4c360a0 deleted file mode 100644 index 4b97c11..0000000 Binary files a/Close Enough!/Library/metadata/7b/7bab365ec61303446bb27591e4c360a0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/7b/7bab365ec61303446bb27591e4c360a0.info b/Close Enough!/Library/metadata/7b/7bab365ec61303446bb27591e4c360a0.info deleted file mode 100644 index ebf1183..0000000 Binary files a/Close Enough!/Library/metadata/7b/7bab365ec61303446bb27591e4c360a0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/7b/7bab365ec61303446bb27591e4c360a0.resource b/Close Enough!/Library/metadata/7b/7bab365ec61303446bb27591e4c360a0.resource deleted file mode 100644 index c1234b9..0000000 Binary files a/Close Enough!/Library/metadata/7b/7bab365ec61303446bb27591e4c360a0.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/7c/7c3a5d6e39b874f468b2691537168513 b/Close Enough!/Library/metadata/7c/7c3a5d6e39b874f468b2691537168513 deleted file mode 100644 index cabc58d..0000000 Binary files a/Close Enough!/Library/metadata/7c/7c3a5d6e39b874f468b2691537168513 and /dev/null differ diff --git a/Close Enough!/Library/metadata/7c/7c3a5d6e39b874f468b2691537168513.info b/Close Enough!/Library/metadata/7c/7c3a5d6e39b874f468b2691537168513.info deleted file mode 100644 index be83f1d..0000000 Binary files a/Close Enough!/Library/metadata/7c/7c3a5d6e39b874f468b2691537168513.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/7c/7cb33d03ee42abb408f80c256002a32e b/Close Enough!/Library/metadata/7c/7cb33d03ee42abb408f80c256002a32e deleted file mode 100644 index a1ab830..0000000 Binary files a/Close Enough!/Library/metadata/7c/7cb33d03ee42abb408f80c256002a32e and /dev/null differ diff --git a/Close Enough!/Library/metadata/7c/7cb33d03ee42abb408f80c256002a32e.info b/Close Enough!/Library/metadata/7c/7cb33d03ee42abb408f80c256002a32e.info deleted file mode 100644 index 3d5e39f..0000000 Binary files a/Close Enough!/Library/metadata/7c/7cb33d03ee42abb408f80c256002a32e.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/7c/7cb71641b6ad9f94c8c202b67139055d b/Close Enough!/Library/metadata/7c/7cb71641b6ad9f94c8c202b67139055d deleted file mode 100644 index b255de6..0000000 Binary files a/Close Enough!/Library/metadata/7c/7cb71641b6ad9f94c8c202b67139055d and /dev/null differ diff --git a/Close Enough!/Library/metadata/7c/7cb71641b6ad9f94c8c202b67139055d.info b/Close Enough!/Library/metadata/7c/7cb71641b6ad9f94c8c202b67139055d.info deleted file mode 100644 index be635e1..0000000 Binary files a/Close Enough!/Library/metadata/7c/7cb71641b6ad9f94c8c202b67139055d.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/7c/7cb71641b6ad9f94c8c202b67139055d.resource b/Close Enough!/Library/metadata/7c/7cb71641b6ad9f94c8c202b67139055d.resource deleted file mode 100644 index cbbc50b..0000000 Binary files a/Close Enough!/Library/metadata/7c/7cb71641b6ad9f94c8c202b67139055d.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/7d/7d7858b68103e403c8c3c2502ae8a3db b/Close Enough!/Library/metadata/7d/7d7858b68103e403c8c3c2502ae8a3db deleted file mode 100644 index 49ab2f2..0000000 Binary files a/Close Enough!/Library/metadata/7d/7d7858b68103e403c8c3c2502ae8a3db and /dev/null differ diff --git a/Close Enough!/Library/metadata/7d/7d7858b68103e403c8c3c2502ae8a3db.info b/Close Enough!/Library/metadata/7d/7d7858b68103e403c8c3c2502ae8a3db.info deleted file mode 100644 index dc84d88..0000000 Binary files a/Close Enough!/Library/metadata/7d/7d7858b68103e403c8c3c2502ae8a3db.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/7d/7dd0b8042ef51a94491043a7dd1f17a9 b/Close Enough!/Library/metadata/7d/7dd0b8042ef51a94491043a7dd1f17a9 deleted file mode 100644 index 5973913..0000000 Binary files a/Close Enough!/Library/metadata/7d/7dd0b8042ef51a94491043a7dd1f17a9 and /dev/null differ diff --git a/Close Enough!/Library/metadata/7d/7dd0b8042ef51a94491043a7dd1f17a9.info b/Close Enough!/Library/metadata/7d/7dd0b8042ef51a94491043a7dd1f17a9.info deleted file mode 100644 index c20c408..0000000 Binary files a/Close Enough!/Library/metadata/7d/7dd0b8042ef51a94491043a7dd1f17a9.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/7e/7e3eb0c08f192444cb890e5cfa1c06d4 b/Close Enough!/Library/metadata/7e/7e3eb0c08f192444cb890e5cfa1c06d4 deleted file mode 100644 index 6fab281..0000000 Binary files a/Close Enough!/Library/metadata/7e/7e3eb0c08f192444cb890e5cfa1c06d4 and /dev/null differ diff --git a/Close Enough!/Library/metadata/7e/7e3eb0c08f192444cb890e5cfa1c06d4.info b/Close Enough!/Library/metadata/7e/7e3eb0c08f192444cb890e5cfa1c06d4.info deleted file mode 100644 index 32f5f9a..0000000 Binary files a/Close Enough!/Library/metadata/7e/7e3eb0c08f192444cb890e5cfa1c06d4.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/7e/7eca4182fce05457bb72c3b39d0c3729 b/Close Enough!/Library/metadata/7e/7eca4182fce05457bb72c3b39d0c3729 deleted file mode 100644 index 20dbbb2..0000000 Binary files a/Close Enough!/Library/metadata/7e/7eca4182fce05457bb72c3b39d0c3729 and /dev/null differ diff --git a/Close Enough!/Library/metadata/7e/7eca4182fce05457bb72c3b39d0c3729.info b/Close Enough!/Library/metadata/7e/7eca4182fce05457bb72c3b39d0c3729.info deleted file mode 100644 index 52c0519..0000000 Binary files a/Close Enough!/Library/metadata/7e/7eca4182fce05457bb72c3b39d0c3729.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/7e/7eeeb1d46c6fa48f8a10411b1d390925 b/Close Enough!/Library/metadata/7e/7eeeb1d46c6fa48f8a10411b1d390925 deleted file mode 100644 index b1ec005..0000000 Binary files a/Close Enough!/Library/metadata/7e/7eeeb1d46c6fa48f8a10411b1d390925 and /dev/null differ diff --git a/Close Enough!/Library/metadata/7e/7eeeb1d46c6fa48f8a10411b1d390925.info b/Close Enough!/Library/metadata/7e/7eeeb1d46c6fa48f8a10411b1d390925.info deleted file mode 100644 index 6fa47f2..0000000 Binary files a/Close Enough!/Library/metadata/7e/7eeeb1d46c6fa48f8a10411b1d390925.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/7f/7f237e9c262d5534d9f4d111274cdab6 b/Close Enough!/Library/metadata/7f/7f237e9c262d5534d9f4d111274cdab6 deleted file mode 100644 index f14a394..0000000 Binary files a/Close Enough!/Library/metadata/7f/7f237e9c262d5534d9f4d111274cdab6 and /dev/null differ diff --git a/Close Enough!/Library/metadata/7f/7f237e9c262d5534d9f4d111274cdab6.info b/Close Enough!/Library/metadata/7f/7f237e9c262d5534d9f4d111274cdab6.info deleted file mode 100644 index 0f92d05..0000000 Binary files a/Close Enough!/Library/metadata/7f/7f237e9c262d5534d9f4d111274cdab6.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/7f/7f858b30832aff046a2278ab9ef04e1a b/Close Enough!/Library/metadata/7f/7f858b30832aff046a2278ab9ef04e1a deleted file mode 100644 index 8612981..0000000 Binary files a/Close Enough!/Library/metadata/7f/7f858b30832aff046a2278ab9ef04e1a and /dev/null differ diff --git a/Close Enough!/Library/metadata/7f/7f858b30832aff046a2278ab9ef04e1a.info b/Close Enough!/Library/metadata/7f/7f858b30832aff046a2278ab9ef04e1a.info deleted file mode 100644 index 29f53ba..0000000 Binary files a/Close Enough!/Library/metadata/7f/7f858b30832aff046a2278ab9ef04e1a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/7f/7fd5e77e7e7ea4eea8198138cd9cc814 b/Close Enough!/Library/metadata/7f/7fd5e77e7e7ea4eea8198138cd9cc814 deleted file mode 100644 index 39be667..0000000 Binary files a/Close Enough!/Library/metadata/7f/7fd5e77e7e7ea4eea8198138cd9cc814 and /dev/null differ diff --git a/Close Enough!/Library/metadata/7f/7fd5e77e7e7ea4eea8198138cd9cc814.info b/Close Enough!/Library/metadata/7f/7fd5e77e7e7ea4eea8198138cd9cc814.info deleted file mode 100644 index 9858922..0000000 Binary files a/Close Enough!/Library/metadata/7f/7fd5e77e7e7ea4eea8198138cd9cc814.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/7f/7ff1b560cd403d249b3359b432be2796 b/Close Enough!/Library/metadata/7f/7ff1b560cd403d249b3359b432be2796 deleted file mode 100644 index 00f1129..0000000 Binary files a/Close Enough!/Library/metadata/7f/7ff1b560cd403d249b3359b432be2796 and /dev/null differ diff --git a/Close Enough!/Library/metadata/7f/7ff1b560cd403d249b3359b432be2796.info b/Close Enough!/Library/metadata/7f/7ff1b560cd403d249b3359b432be2796.info deleted file mode 100644 index e73c4f7..0000000 Binary files a/Close Enough!/Library/metadata/7f/7ff1b560cd403d249b3359b432be2796.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/80/80a3616ca19596e4da0f10f14d241e9f b/Close Enough!/Library/metadata/80/80a3616ca19596e4da0f10f14d241e9f deleted file mode 100644 index 81a3161..0000000 Binary files a/Close Enough!/Library/metadata/80/80a3616ca19596e4da0f10f14d241e9f and /dev/null differ diff --git a/Close Enough!/Library/metadata/80/80a3616ca19596e4da0f10f14d241e9f.info b/Close Enough!/Library/metadata/80/80a3616ca19596e4da0f10f14d241e9f.info deleted file mode 100644 index beedd87..0000000 Binary files a/Close Enough!/Library/metadata/80/80a3616ca19596e4da0f10f14d241e9f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/81/811523f8e578d6f4abb259f1fbaa5e0c b/Close Enough!/Library/metadata/81/811523f8e578d6f4abb259f1fbaa5e0c deleted file mode 100644 index 829ea71..0000000 Binary files a/Close Enough!/Library/metadata/81/811523f8e578d6f4abb259f1fbaa5e0c and /dev/null differ diff --git a/Close Enough!/Library/metadata/81/811523f8e578d6f4abb259f1fbaa5e0c.info b/Close Enough!/Library/metadata/81/811523f8e578d6f4abb259f1fbaa5e0c.info deleted file mode 100644 index eb12b5c..0000000 Binary files a/Close Enough!/Library/metadata/81/811523f8e578d6f4abb259f1fbaa5e0c.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/83/83fc3db633e34463cb1b92828ee197aa b/Close Enough!/Library/metadata/83/83fc3db633e34463cb1b92828ee197aa deleted file mode 100644 index af7c198..0000000 Binary files a/Close Enough!/Library/metadata/83/83fc3db633e34463cb1b92828ee197aa and /dev/null differ diff --git a/Close Enough!/Library/metadata/83/83fc3db633e34463cb1b92828ee197aa.info b/Close Enough!/Library/metadata/83/83fc3db633e34463cb1b92828ee197aa.info deleted file mode 100644 index 906d710..0000000 Binary files a/Close Enough!/Library/metadata/83/83fc3db633e34463cb1b92828ee197aa.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/84/844f815391db42d49455cbf1a7bfc434 b/Close Enough!/Library/metadata/84/844f815391db42d49455cbf1a7bfc434 deleted file mode 100644 index d4fcbd7..0000000 Binary files a/Close Enough!/Library/metadata/84/844f815391db42d49455cbf1a7bfc434 and /dev/null differ diff --git a/Close Enough!/Library/metadata/84/844f815391db42d49455cbf1a7bfc434.info b/Close Enough!/Library/metadata/84/844f815391db42d49455cbf1a7bfc434.info deleted file mode 100644 index bb8effc..0000000 Binary files a/Close Enough!/Library/metadata/84/844f815391db42d49455cbf1a7bfc434.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/84/848e835a7347c4941986c9b0ffd88db1 b/Close Enough!/Library/metadata/84/848e835a7347c4941986c9b0ffd88db1 deleted file mode 100644 index f0799c8..0000000 Binary files a/Close Enough!/Library/metadata/84/848e835a7347c4941986c9b0ffd88db1 and /dev/null differ diff --git a/Close Enough!/Library/metadata/84/848e835a7347c4941986c9b0ffd88db1.info b/Close Enough!/Library/metadata/84/848e835a7347c4941986c9b0ffd88db1.info deleted file mode 100644 index 572682e..0000000 Binary files a/Close Enough!/Library/metadata/84/848e835a7347c4941986c9b0ffd88db1.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/84/848e835a7347c4941986c9b0ffd88db1.resource b/Close Enough!/Library/metadata/84/848e835a7347c4941986c9b0ffd88db1.resource deleted file mode 100644 index f9fe919..0000000 Binary files a/Close Enough!/Library/metadata/84/848e835a7347c4941986c9b0ffd88db1.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/84/84aec3c9054b3402293139f2c0bc1029 b/Close Enough!/Library/metadata/84/84aec3c9054b3402293139f2c0bc1029 deleted file mode 100644 index e11c2dc..0000000 Binary files a/Close Enough!/Library/metadata/84/84aec3c9054b3402293139f2c0bc1029 and /dev/null differ diff --git a/Close Enough!/Library/metadata/84/84aec3c9054b3402293139f2c0bc1029.info b/Close Enough!/Library/metadata/84/84aec3c9054b3402293139f2c0bc1029.info deleted file mode 100644 index 99701f7..0000000 Binary files a/Close Enough!/Library/metadata/84/84aec3c9054b3402293139f2c0bc1029.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/84/84ca94c19f25ae14d83aa41bb3654390 b/Close Enough!/Library/metadata/84/84ca94c19f25ae14d83aa41bb3654390 deleted file mode 100644 index bc91417..0000000 Binary files a/Close Enough!/Library/metadata/84/84ca94c19f25ae14d83aa41bb3654390 and /dev/null differ diff --git a/Close Enough!/Library/metadata/84/84ca94c19f25ae14d83aa41bb3654390.info b/Close Enough!/Library/metadata/84/84ca94c19f25ae14d83aa41bb3654390.info deleted file mode 100644 index fe21083..0000000 Binary files a/Close Enough!/Library/metadata/84/84ca94c19f25ae14d83aa41bb3654390.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/85/85015d8aad4ce414c9a837359d739a33 b/Close Enough!/Library/metadata/85/85015d8aad4ce414c9a837359d739a33 deleted file mode 100644 index 2ec6fc5..0000000 Binary files a/Close Enough!/Library/metadata/85/85015d8aad4ce414c9a837359d739a33 and /dev/null differ diff --git a/Close Enough!/Library/metadata/85/85015d8aad4ce414c9a837359d739a33.info b/Close Enough!/Library/metadata/85/85015d8aad4ce414c9a837359d739a33.info deleted file mode 100644 index 31fd827..0000000 Binary files a/Close Enough!/Library/metadata/85/85015d8aad4ce414c9a837359d739a33.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/85/853cc3add9b870444a62c45d73e34aab b/Close Enough!/Library/metadata/85/853cc3add9b870444a62c45d73e34aab deleted file mode 100644 index c8cd7fb..0000000 Binary files a/Close Enough!/Library/metadata/85/853cc3add9b870444a62c45d73e34aab and /dev/null differ diff --git a/Close Enough!/Library/metadata/85/853cc3add9b870444a62c45d73e34aab.info b/Close Enough!/Library/metadata/85/853cc3add9b870444a62c45d73e34aab.info deleted file mode 100644 index 9738545..0000000 Binary files a/Close Enough!/Library/metadata/85/853cc3add9b870444a62c45d73e34aab.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/86/86c008322e7c647149878156c5b81940 b/Close Enough!/Library/metadata/86/86c008322e7c647149878156c5b81940 deleted file mode 100644 index 73e08e0..0000000 Binary files a/Close Enough!/Library/metadata/86/86c008322e7c647149878156c5b81940 and /dev/null differ diff --git a/Close Enough!/Library/metadata/86/86c008322e7c647149878156c5b81940.info b/Close Enough!/Library/metadata/86/86c008322e7c647149878156c5b81940.info deleted file mode 100644 index c8e6b51..0000000 Binary files a/Close Enough!/Library/metadata/86/86c008322e7c647149878156c5b81940.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/86/86c18994495874297b469aaa57ef9b44 b/Close Enough!/Library/metadata/86/86c18994495874297b469aaa57ef9b44 deleted file mode 100644 index 6942fce..0000000 Binary files a/Close Enough!/Library/metadata/86/86c18994495874297b469aaa57ef9b44 and /dev/null differ diff --git a/Close Enough!/Library/metadata/86/86c18994495874297b469aaa57ef9b44.info b/Close Enough!/Library/metadata/86/86c18994495874297b469aaa57ef9b44.info deleted file mode 100644 index 8a61dec..0000000 Binary files a/Close Enough!/Library/metadata/86/86c18994495874297b469aaa57ef9b44.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/87/870353891bb340e2b2a9c8707e7419ba b/Close Enough!/Library/metadata/87/870353891bb340e2b2a9c8707e7419ba deleted file mode 100644 index 050eb95..0000000 Binary files a/Close Enough!/Library/metadata/87/870353891bb340e2b2a9c8707e7419ba and /dev/null differ diff --git a/Close Enough!/Library/metadata/87/870353891bb340e2b2a9c8707e7419ba.info b/Close Enough!/Library/metadata/87/870353891bb340e2b2a9c8707e7419ba.info deleted file mode 100644 index a35de2a..0000000 Binary files a/Close Enough!/Library/metadata/87/870353891bb340e2b2a9c8707e7419ba.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/87/877abface241f504cbafaae1fa29d361 b/Close Enough!/Library/metadata/87/877abface241f504cbafaae1fa29d361 deleted file mode 100644 index 9f65767..0000000 Binary files a/Close Enough!/Library/metadata/87/877abface241f504cbafaae1fa29d361 and /dev/null differ diff --git a/Close Enough!/Library/metadata/87/877abface241f504cbafaae1fa29d361.info b/Close Enough!/Library/metadata/87/877abface241f504cbafaae1fa29d361.info deleted file mode 100644 index 69b12b1..0000000 Binary files a/Close Enough!/Library/metadata/87/877abface241f504cbafaae1fa29d361.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/87/879d16bac62b34099a7d303195210857 b/Close Enough!/Library/metadata/87/879d16bac62b34099a7d303195210857 deleted file mode 100644 index f1028ba..0000000 Binary files a/Close Enough!/Library/metadata/87/879d16bac62b34099a7d303195210857 and /dev/null differ diff --git a/Close Enough!/Library/metadata/87/879d16bac62b34099a7d303195210857.info b/Close Enough!/Library/metadata/87/879d16bac62b34099a7d303195210857.info deleted file mode 100644 index 6268e7b..0000000 Binary files a/Close Enough!/Library/metadata/87/879d16bac62b34099a7d303195210857.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/87/87c316b602156405d92e616621658222 b/Close Enough!/Library/metadata/87/87c316b602156405d92e616621658222 deleted file mode 100644 index 61fbe7e..0000000 Binary files a/Close Enough!/Library/metadata/87/87c316b602156405d92e616621658222 and /dev/null differ diff --git a/Close Enough!/Library/metadata/87/87c316b602156405d92e616621658222.info b/Close Enough!/Library/metadata/87/87c316b602156405d92e616621658222.info deleted file mode 100644 index a153698..0000000 Binary files a/Close Enough!/Library/metadata/87/87c316b602156405d92e616621658222.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/88/884f8f0e4025a420893d3a8d1d3063e1 b/Close Enough!/Library/metadata/88/884f8f0e4025a420893d3a8d1d3063e1 deleted file mode 100644 index ca005bc..0000000 Binary files a/Close Enough!/Library/metadata/88/884f8f0e4025a420893d3a8d1d3063e1 and /dev/null differ diff --git a/Close Enough!/Library/metadata/88/884f8f0e4025a420893d3a8d1d3063e1.info b/Close Enough!/Library/metadata/88/884f8f0e4025a420893d3a8d1d3063e1.info deleted file mode 100644 index 64bd319..0000000 Binary files a/Close Enough!/Library/metadata/88/884f8f0e4025a420893d3a8d1d3063e1.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/89/89253c950f61dbb47889a0d6f1473402 b/Close Enough!/Library/metadata/89/89253c950f61dbb47889a0d6f1473402 deleted file mode 100644 index 8789997..0000000 Binary files a/Close Enough!/Library/metadata/89/89253c950f61dbb47889a0d6f1473402 and /dev/null differ diff --git a/Close Enough!/Library/metadata/89/89253c950f61dbb47889a0d6f1473402.info b/Close Enough!/Library/metadata/89/89253c950f61dbb47889a0d6f1473402.info deleted file mode 100644 index 5785bb9..0000000 Binary files a/Close Enough!/Library/metadata/89/89253c950f61dbb47889a0d6f1473402.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/89/892e7927dae7bf2419a96bd0f9c84c38 b/Close Enough!/Library/metadata/89/892e7927dae7bf2419a96bd0f9c84c38 deleted file mode 100644 index e6645c7..0000000 Binary files a/Close Enough!/Library/metadata/89/892e7927dae7bf2419a96bd0f9c84c38 and /dev/null differ diff --git a/Close Enough!/Library/metadata/89/892e7927dae7bf2419a96bd0f9c84c38.info b/Close Enough!/Library/metadata/89/892e7927dae7bf2419a96bd0f9c84c38.info deleted file mode 100644 index d2d47a8..0000000 Binary files a/Close Enough!/Library/metadata/89/892e7927dae7bf2419a96bd0f9c84c38.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/89/89617ad407dbf7341a1e7276be68e8c6 b/Close Enough!/Library/metadata/89/89617ad407dbf7341a1e7276be68e8c6 deleted file mode 100644 index 16cf322..0000000 Binary files a/Close Enough!/Library/metadata/89/89617ad407dbf7341a1e7276be68e8c6 and /dev/null differ diff --git a/Close Enough!/Library/metadata/89/89617ad407dbf7341a1e7276be68e8c6.info b/Close Enough!/Library/metadata/89/89617ad407dbf7341a1e7276be68e8c6.info deleted file mode 100644 index a1a58b8..0000000 Binary files a/Close Enough!/Library/metadata/89/89617ad407dbf7341a1e7276be68e8c6.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/89/89617ad407dbf7341a1e7276be68e8c6.resource b/Close Enough!/Library/metadata/89/89617ad407dbf7341a1e7276be68e8c6.resource deleted file mode 100644 index 2c33410..0000000 Binary files a/Close Enough!/Library/metadata/89/89617ad407dbf7341a1e7276be68e8c6.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/89/89b3345b531885643a5611b3792ff491 b/Close Enough!/Library/metadata/89/89b3345b531885643a5611b3792ff491 deleted file mode 100644 index ee8e2da..0000000 Binary files a/Close Enough!/Library/metadata/89/89b3345b531885643a5611b3792ff491 and /dev/null differ diff --git a/Close Enough!/Library/metadata/89/89b3345b531885643a5611b3792ff491.info b/Close Enough!/Library/metadata/89/89b3345b531885643a5611b3792ff491.info deleted file mode 100644 index 830d912..0000000 Binary files a/Close Enough!/Library/metadata/89/89b3345b531885643a5611b3792ff491.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/89/89ff19d667a6a5d4bb76df1fcb718402 b/Close Enough!/Library/metadata/89/89ff19d667a6a5d4bb76df1fcb718402 deleted file mode 100644 index acd6055..0000000 Binary files a/Close Enough!/Library/metadata/89/89ff19d667a6a5d4bb76df1fcb718402 and /dev/null differ diff --git a/Close Enough!/Library/metadata/89/89ff19d667a6a5d4bb76df1fcb718402.info b/Close Enough!/Library/metadata/89/89ff19d667a6a5d4bb76df1fcb718402.info deleted file mode 100644 index d5bbf67..0000000 Binary files a/Close Enough!/Library/metadata/89/89ff19d667a6a5d4bb76df1fcb718402.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/8a/8a0b3e628e8c748e2aa72a5e3889c1ae b/Close Enough!/Library/metadata/8a/8a0b3e628e8c748e2aa72a5e3889c1ae deleted file mode 100644 index af79875..0000000 Binary files a/Close Enough!/Library/metadata/8a/8a0b3e628e8c748e2aa72a5e3889c1ae and /dev/null differ diff --git a/Close Enough!/Library/metadata/8a/8a0b3e628e8c748e2aa72a5e3889c1ae.info b/Close Enough!/Library/metadata/8a/8a0b3e628e8c748e2aa72a5e3889c1ae.info deleted file mode 100644 index 0c01910..0000000 Binary files a/Close Enough!/Library/metadata/8a/8a0b3e628e8c748e2aa72a5e3889c1ae.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/8a/8a991fb56d7502845b7a6cc73e272260 b/Close Enough!/Library/metadata/8a/8a991fb56d7502845b7a6cc73e272260 deleted file mode 100644 index b09c07b..0000000 Binary files a/Close Enough!/Library/metadata/8a/8a991fb56d7502845b7a6cc73e272260 and /dev/null differ diff --git a/Close Enough!/Library/metadata/8a/8a991fb56d7502845b7a6cc73e272260.info b/Close Enough!/Library/metadata/8a/8a991fb56d7502845b7a6cc73e272260.info deleted file mode 100644 index 93cbd89..0000000 Binary files a/Close Enough!/Library/metadata/8a/8a991fb56d7502845b7a6cc73e272260.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/8b/8b3205c077fb84174b47c7b480a0b378 b/Close Enough!/Library/metadata/8b/8b3205c077fb84174b47c7b480a0b378 deleted file mode 100644 index 53a2b7d..0000000 Binary files a/Close Enough!/Library/metadata/8b/8b3205c077fb84174b47c7b480a0b378 and /dev/null differ diff --git a/Close Enough!/Library/metadata/8b/8b3205c077fb84174b47c7b480a0b378.info b/Close Enough!/Library/metadata/8b/8b3205c077fb84174b47c7b480a0b378.info deleted file mode 100644 index b19b00b..0000000 Binary files a/Close Enough!/Library/metadata/8b/8b3205c077fb84174b47c7b480a0b378.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/8b/8b9085af6ca270f45982d61229c6925e b/Close Enough!/Library/metadata/8b/8b9085af6ca270f45982d61229c6925e deleted file mode 100644 index 509d734..0000000 Binary files a/Close Enough!/Library/metadata/8b/8b9085af6ca270f45982d61229c6925e and /dev/null differ diff --git a/Close Enough!/Library/metadata/8b/8b9085af6ca270f45982d61229c6925e.info b/Close Enough!/Library/metadata/8b/8b9085af6ca270f45982d61229c6925e.info deleted file mode 100644 index fdfe6bd..0000000 Binary files a/Close Enough!/Library/metadata/8b/8b9085af6ca270f45982d61229c6925e.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/8b/8bd4aae16c418eb4f9dc4537e1a78e6e b/Close Enough!/Library/metadata/8b/8bd4aae16c418eb4f9dc4537e1a78e6e deleted file mode 100644 index 73fec1d..0000000 Binary files a/Close Enough!/Library/metadata/8b/8bd4aae16c418eb4f9dc4537e1a78e6e and /dev/null differ diff --git a/Close Enough!/Library/metadata/8b/8bd4aae16c418eb4f9dc4537e1a78e6e.info b/Close Enough!/Library/metadata/8b/8bd4aae16c418eb4f9dc4537e1a78e6e.info deleted file mode 100644 index 6c9831f..0000000 Binary files a/Close Enough!/Library/metadata/8b/8bd4aae16c418eb4f9dc4537e1a78e6e.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/8b/8bd4aae16c418eb4f9dc4537e1a78e6e.resource b/Close Enough!/Library/metadata/8b/8bd4aae16c418eb4f9dc4537e1a78e6e.resource deleted file mode 100644 index 0435bc4..0000000 Binary files a/Close Enough!/Library/metadata/8b/8bd4aae16c418eb4f9dc4537e1a78e6e.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/8d/8d0f35861d7274ab88f83fb787bd8890 b/Close Enough!/Library/metadata/8d/8d0f35861d7274ab88f83fb787bd8890 deleted file mode 100644 index 7149b04..0000000 Binary files a/Close Enough!/Library/metadata/8d/8d0f35861d7274ab88f83fb787bd8890 and /dev/null differ diff --git a/Close Enough!/Library/metadata/8d/8d0f35861d7274ab88f83fb787bd8890.info b/Close Enough!/Library/metadata/8d/8d0f35861d7274ab88f83fb787bd8890.info deleted file mode 100644 index 2cb4100..0000000 Binary files a/Close Enough!/Library/metadata/8d/8d0f35861d7274ab88f83fb787bd8890.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/8d/8d6306d532861fa449c82d1f009dc270 b/Close Enough!/Library/metadata/8d/8d6306d532861fa449c82d1f009dc270 deleted file mode 100644 index 47722d0..0000000 Binary files a/Close Enough!/Library/metadata/8d/8d6306d532861fa449c82d1f009dc270 and /dev/null differ diff --git a/Close Enough!/Library/metadata/8d/8d6306d532861fa449c82d1f009dc270.info b/Close Enough!/Library/metadata/8d/8d6306d532861fa449c82d1f009dc270.info deleted file mode 100644 index 4a504cc..0000000 Binary files a/Close Enough!/Library/metadata/8d/8d6306d532861fa449c82d1f009dc270.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/8d/8d79c9f5935592f4286a327a48dc3538 b/Close Enough!/Library/metadata/8d/8d79c9f5935592f4286a327a48dc3538 deleted file mode 100644 index 02455a0..0000000 Binary files a/Close Enough!/Library/metadata/8d/8d79c9f5935592f4286a327a48dc3538 and /dev/null differ diff --git a/Close Enough!/Library/metadata/8d/8d79c9f5935592f4286a327a48dc3538.info b/Close Enough!/Library/metadata/8d/8d79c9f5935592f4286a327a48dc3538.info deleted file mode 100644 index c8d42b0..0000000 Binary files a/Close Enough!/Library/metadata/8d/8d79c9f5935592f4286a327a48dc3538.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/8d/8d8926d103089452c9e9a724d6726170 b/Close Enough!/Library/metadata/8d/8d8926d103089452c9e9a724d6726170 deleted file mode 100644 index 78ae823..0000000 Binary files a/Close Enough!/Library/metadata/8d/8d8926d103089452c9e9a724d6726170 and /dev/null differ diff --git a/Close Enough!/Library/metadata/8d/8d8926d103089452c9e9a724d6726170.info b/Close Enough!/Library/metadata/8d/8d8926d103089452c9e9a724d6726170.info deleted file mode 100644 index d2e8422..0000000 Binary files a/Close Enough!/Library/metadata/8d/8d8926d103089452c9e9a724d6726170.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/8e/8e7066e382b0fc749b25dbb1a3004dfe b/Close Enough!/Library/metadata/8e/8e7066e382b0fc749b25dbb1a3004dfe deleted file mode 100644 index 9e54ae0..0000000 Binary files a/Close Enough!/Library/metadata/8e/8e7066e382b0fc749b25dbb1a3004dfe and /dev/null differ diff --git a/Close Enough!/Library/metadata/8e/8e7066e382b0fc749b25dbb1a3004dfe.info b/Close Enough!/Library/metadata/8e/8e7066e382b0fc749b25dbb1a3004dfe.info deleted file mode 100644 index 4a69639..0000000 Binary files a/Close Enough!/Library/metadata/8e/8e7066e382b0fc749b25dbb1a3004dfe.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/8f/8f1de8125c0d77142bd6e1c9d15315d6 b/Close Enough!/Library/metadata/8f/8f1de8125c0d77142bd6e1c9d15315d6 deleted file mode 100644 index ca7198c..0000000 Binary files a/Close Enough!/Library/metadata/8f/8f1de8125c0d77142bd6e1c9d15315d6 and /dev/null differ diff --git a/Close Enough!/Library/metadata/8f/8f1de8125c0d77142bd6e1c9d15315d6.info b/Close Enough!/Library/metadata/8f/8f1de8125c0d77142bd6e1c9d15315d6.info deleted file mode 100644 index 22059a6..0000000 Binary files a/Close Enough!/Library/metadata/8f/8f1de8125c0d77142bd6e1c9d15315d6.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/8f/8f249f6b1635e482881c5f0b31502d67 b/Close Enough!/Library/metadata/8f/8f249f6b1635e482881c5f0b31502d67 deleted file mode 100644 index 6d4be93..0000000 Binary files a/Close Enough!/Library/metadata/8f/8f249f6b1635e482881c5f0b31502d67 and /dev/null differ diff --git a/Close Enough!/Library/metadata/8f/8f249f6b1635e482881c5f0b31502d67.info b/Close Enough!/Library/metadata/8f/8f249f6b1635e482881c5f0b31502d67.info deleted file mode 100644 index b5c162f..0000000 Binary files a/Close Enough!/Library/metadata/8f/8f249f6b1635e482881c5f0b31502d67.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/8f/8f83bbef550be744798b09c27919bd5f b/Close Enough!/Library/metadata/8f/8f83bbef550be744798b09c27919bd5f deleted file mode 100644 index 3e86538..0000000 Binary files a/Close Enough!/Library/metadata/8f/8f83bbef550be744798b09c27919bd5f and /dev/null differ diff --git a/Close Enough!/Library/metadata/8f/8f83bbef550be744798b09c27919bd5f.info b/Close Enough!/Library/metadata/8f/8f83bbef550be744798b09c27919bd5f.info deleted file mode 100644 index b6cc544..0000000 Binary files a/Close Enough!/Library/metadata/8f/8f83bbef550be744798b09c27919bd5f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/90/9078b7128e594410d9b89e5b24cffd01 b/Close Enough!/Library/metadata/90/9078b7128e594410d9b89e5b24cffd01 deleted file mode 100644 index 99a0e4c..0000000 Binary files a/Close Enough!/Library/metadata/90/9078b7128e594410d9b89e5b24cffd01 and /dev/null differ diff --git a/Close Enough!/Library/metadata/90/9078b7128e594410d9b89e5b24cffd01.info b/Close Enough!/Library/metadata/90/9078b7128e594410d9b89e5b24cffd01.info deleted file mode 100644 index 151e804..0000000 Binary files a/Close Enough!/Library/metadata/90/9078b7128e594410d9b89e5b24cffd01.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/90/90791303b72ec4ae198f99d637dfdf6c b/Close Enough!/Library/metadata/90/90791303b72ec4ae198f99d637dfdf6c deleted file mode 100644 index 13f6359..0000000 Binary files a/Close Enough!/Library/metadata/90/90791303b72ec4ae198f99d637dfdf6c and /dev/null differ diff --git a/Close Enough!/Library/metadata/90/90791303b72ec4ae198f99d637dfdf6c.info b/Close Enough!/Library/metadata/90/90791303b72ec4ae198f99d637dfdf6c.info deleted file mode 100644 index 02ab77f..0000000 Binary files a/Close Enough!/Library/metadata/90/90791303b72ec4ae198f99d637dfdf6c.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/90/9080d3ad371999e43bda5ab49690d047 b/Close Enough!/Library/metadata/90/9080d3ad371999e43bda5ab49690d047 deleted file mode 100644 index c0b575f..0000000 Binary files a/Close Enough!/Library/metadata/90/9080d3ad371999e43bda5ab49690d047 and /dev/null differ diff --git a/Close Enough!/Library/metadata/90/9080d3ad371999e43bda5ab49690d047.info b/Close Enough!/Library/metadata/90/9080d3ad371999e43bda5ab49690d047.info deleted file mode 100644 index 74648c9..0000000 Binary files a/Close Enough!/Library/metadata/90/9080d3ad371999e43bda5ab49690d047.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/90/9080d3ad371999e43bda5ab49690d047.resource b/Close Enough!/Library/metadata/90/9080d3ad371999e43bda5ab49690d047.resource deleted file mode 100644 index 724ebe8..0000000 Binary files a/Close Enough!/Library/metadata/90/9080d3ad371999e43bda5ab49690d047.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/90/909f328c7731fce45b924247bb4d89bc b/Close Enough!/Library/metadata/90/909f328c7731fce45b924247bb4d89bc deleted file mode 100644 index 5333e13..0000000 Binary files a/Close Enough!/Library/metadata/90/909f328c7731fce45b924247bb4d89bc and /dev/null differ diff --git a/Close Enough!/Library/metadata/90/909f328c7731fce45b924247bb4d89bc.info b/Close Enough!/Library/metadata/90/909f328c7731fce45b924247bb4d89bc.info deleted file mode 100644 index 7d78845..0000000 Binary files a/Close Enough!/Library/metadata/90/909f328c7731fce45b924247bb4d89bc.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/92/92788343ea5d34eff9d03db3646c9671 b/Close Enough!/Library/metadata/92/92788343ea5d34eff9d03db3646c9671 deleted file mode 100644 index d1e2407..0000000 Binary files a/Close Enough!/Library/metadata/92/92788343ea5d34eff9d03db3646c9671 and /dev/null differ diff --git a/Close Enough!/Library/metadata/92/92788343ea5d34eff9d03db3646c9671.info b/Close Enough!/Library/metadata/92/92788343ea5d34eff9d03db3646c9671.info deleted file mode 100644 index a710e7b..0000000 Binary files a/Close Enough!/Library/metadata/92/92788343ea5d34eff9d03db3646c9671.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/92/92a62c583a2e8734d9a6018eec4d27fb b/Close Enough!/Library/metadata/92/92a62c583a2e8734d9a6018eec4d27fb deleted file mode 100644 index aba9d6e..0000000 Binary files a/Close Enough!/Library/metadata/92/92a62c583a2e8734d9a6018eec4d27fb and /dev/null differ diff --git a/Close Enough!/Library/metadata/92/92a62c583a2e8734d9a6018eec4d27fb.info b/Close Enough!/Library/metadata/92/92a62c583a2e8734d9a6018eec4d27fb.info deleted file mode 100644 index aeaeb55..0000000 Binary files a/Close Enough!/Library/metadata/92/92a62c583a2e8734d9a6018eec4d27fb.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/93/937da6c9b239944b7a3def521f8b214a b/Close Enough!/Library/metadata/93/937da6c9b239944b7a3def521f8b214a deleted file mode 100644 index f346787..0000000 Binary files a/Close Enough!/Library/metadata/93/937da6c9b239944b7a3def521f8b214a and /dev/null differ diff --git a/Close Enough!/Library/metadata/93/937da6c9b239944b7a3def521f8b214a.info b/Close Enough!/Library/metadata/93/937da6c9b239944b7a3def521f8b214a.info deleted file mode 100644 index 9fd32fb..0000000 Binary files a/Close Enough!/Library/metadata/93/937da6c9b239944b7a3def521f8b214a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/94/9445bf901ece61b4682ec90280339739 b/Close Enough!/Library/metadata/94/9445bf901ece61b4682ec90280339739 deleted file mode 100644 index dbeeeb4..0000000 Binary files a/Close Enough!/Library/metadata/94/9445bf901ece61b4682ec90280339739 and /dev/null differ diff --git a/Close Enough!/Library/metadata/94/9445bf901ece61b4682ec90280339739.info b/Close Enough!/Library/metadata/94/9445bf901ece61b4682ec90280339739.info deleted file mode 100644 index c1403ba..0000000 Binary files a/Close Enough!/Library/metadata/94/9445bf901ece61b4682ec90280339739.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/94/94790735e9656144ea00615744dc2d64 b/Close Enough!/Library/metadata/94/94790735e9656144ea00615744dc2d64 deleted file mode 100644 index 841b3b9..0000000 Binary files a/Close Enough!/Library/metadata/94/94790735e9656144ea00615744dc2d64 and /dev/null differ diff --git a/Close Enough!/Library/metadata/94/94790735e9656144ea00615744dc2d64.info b/Close Enough!/Library/metadata/94/94790735e9656144ea00615744dc2d64.info deleted file mode 100644 index a50fbd2..0000000 Binary files a/Close Enough!/Library/metadata/94/94790735e9656144ea00615744dc2d64.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/94/94dff3a3ad1183f49aefcf0abddad7ca b/Close Enough!/Library/metadata/94/94dff3a3ad1183f49aefcf0abddad7ca deleted file mode 100644 index 2ffbd0c..0000000 Binary files a/Close Enough!/Library/metadata/94/94dff3a3ad1183f49aefcf0abddad7ca and /dev/null differ diff --git a/Close Enough!/Library/metadata/94/94dff3a3ad1183f49aefcf0abddad7ca.info b/Close Enough!/Library/metadata/94/94dff3a3ad1183f49aefcf0abddad7ca.info deleted file mode 100644 index befa6f4..0000000 Binary files a/Close Enough!/Library/metadata/94/94dff3a3ad1183f49aefcf0abddad7ca.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/97/976185be36bc0f14fa41452e89795d94 b/Close Enough!/Library/metadata/97/976185be36bc0f14fa41452e89795d94 deleted file mode 100644 index e9995de..0000000 Binary files a/Close Enough!/Library/metadata/97/976185be36bc0f14fa41452e89795d94 and /dev/null differ diff --git a/Close Enough!/Library/metadata/97/976185be36bc0f14fa41452e89795d94.info b/Close Enough!/Library/metadata/97/976185be36bc0f14fa41452e89795d94.info deleted file mode 100644 index 4f48f35..0000000 Binary files a/Close Enough!/Library/metadata/97/976185be36bc0f14fa41452e89795d94.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/97/976185be36bc0f14fa41452e89795d94.resource b/Close Enough!/Library/metadata/97/976185be36bc0f14fa41452e89795d94.resource deleted file mode 100644 index 3141c6a..0000000 Binary files a/Close Enough!/Library/metadata/97/976185be36bc0f14fa41452e89795d94.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/98/9886e7736aaab4b55b002f2246bb9a97 b/Close Enough!/Library/metadata/98/9886e7736aaab4b55b002f2246bb9a97 deleted file mode 100644 index b810d12..0000000 Binary files a/Close Enough!/Library/metadata/98/9886e7736aaab4b55b002f2246bb9a97 and /dev/null differ diff --git a/Close Enough!/Library/metadata/98/9886e7736aaab4b55b002f2246bb9a97.info b/Close Enough!/Library/metadata/98/9886e7736aaab4b55b002f2246bb9a97.info deleted file mode 100644 index 149c7ec..0000000 Binary files a/Close Enough!/Library/metadata/98/9886e7736aaab4b55b002f2246bb9a97.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/98/98fdd5dbe98024343bc0584d6b017a2d b/Close Enough!/Library/metadata/98/98fdd5dbe98024343bc0584d6b017a2d deleted file mode 100644 index f713931..0000000 Binary files a/Close Enough!/Library/metadata/98/98fdd5dbe98024343bc0584d6b017a2d and /dev/null differ diff --git a/Close Enough!/Library/metadata/98/98fdd5dbe98024343bc0584d6b017a2d.info b/Close Enough!/Library/metadata/98/98fdd5dbe98024343bc0584d6b017a2d.info deleted file mode 100644 index ef995ed..0000000 Binary files a/Close Enough!/Library/metadata/98/98fdd5dbe98024343bc0584d6b017a2d.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/99/991cb21055557f04a9b5e2fae1808c65 b/Close Enough!/Library/metadata/99/991cb21055557f04a9b5e2fae1808c65 deleted file mode 100644 index cbc2b97..0000000 Binary files a/Close Enough!/Library/metadata/99/991cb21055557f04a9b5e2fae1808c65 and /dev/null differ diff --git a/Close Enough!/Library/metadata/99/991cb21055557f04a9b5e2fae1808c65.info b/Close Enough!/Library/metadata/99/991cb21055557f04a9b5e2fae1808c65.info deleted file mode 100644 index 76091d7..0000000 Binary files a/Close Enough!/Library/metadata/99/991cb21055557f04a9b5e2fae1808c65.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/99/991cb21055557f04a9b5e2fae1808c65.resource b/Close Enough!/Library/metadata/99/991cb21055557f04a9b5e2fae1808c65.resource deleted file mode 100644 index ab9b20d..0000000 Binary files a/Close Enough!/Library/metadata/99/991cb21055557f04a9b5e2fae1808c65.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/99/9974dce51eb142b4091213b22c852f95 b/Close Enough!/Library/metadata/99/9974dce51eb142b4091213b22c852f95 deleted file mode 100644 index 828e0f7..0000000 Binary files a/Close Enough!/Library/metadata/99/9974dce51eb142b4091213b22c852f95 and /dev/null differ diff --git a/Close Enough!/Library/metadata/99/9974dce51eb142b4091213b22c852f95.info b/Close Enough!/Library/metadata/99/9974dce51eb142b4091213b22c852f95.info deleted file mode 100644 index ca75fa9..0000000 Binary files a/Close Enough!/Library/metadata/99/9974dce51eb142b4091213b22c852f95.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/99/99ddb49592ff84811804420a1910cb89 b/Close Enough!/Library/metadata/99/99ddb49592ff84811804420a1910cb89 deleted file mode 100644 index a50ab65..0000000 Binary files a/Close Enough!/Library/metadata/99/99ddb49592ff84811804420a1910cb89 and /dev/null differ diff --git a/Close Enough!/Library/metadata/99/99ddb49592ff84811804420a1910cb89.info b/Close Enough!/Library/metadata/99/99ddb49592ff84811804420a1910cb89.info deleted file mode 100644 index bd823ad..0000000 Binary files a/Close Enough!/Library/metadata/99/99ddb49592ff84811804420a1910cb89.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/9a/9a0312403f252434c912587ebde8fb96 b/Close Enough!/Library/metadata/9a/9a0312403f252434c912587ebde8fb96 deleted file mode 100644 index 13ee51d..0000000 Binary files a/Close Enough!/Library/metadata/9a/9a0312403f252434c912587ebde8fb96 and /dev/null differ diff --git a/Close Enough!/Library/metadata/9a/9a0312403f252434c912587ebde8fb96.info b/Close Enough!/Library/metadata/9a/9a0312403f252434c912587ebde8fb96.info deleted file mode 100644 index bfd0ab6..0000000 Binary files a/Close Enough!/Library/metadata/9a/9a0312403f252434c912587ebde8fb96.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/9a/9a1af8c2b03c38c43a3e9c2b43db4483 b/Close Enough!/Library/metadata/9a/9a1af8c2b03c38c43a3e9c2b43db4483 deleted file mode 100644 index 02c80eb..0000000 Binary files a/Close Enough!/Library/metadata/9a/9a1af8c2b03c38c43a3e9c2b43db4483 and /dev/null differ diff --git a/Close Enough!/Library/metadata/9a/9a1af8c2b03c38c43a3e9c2b43db4483.info b/Close Enough!/Library/metadata/9a/9a1af8c2b03c38c43a3e9c2b43db4483.info deleted file mode 100644 index 46d3f14..0000000 Binary files a/Close Enough!/Library/metadata/9a/9a1af8c2b03c38c43a3e9c2b43db4483.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/9a/9a7f0ed3a807f43a795e5ef325ebdadd b/Close Enough!/Library/metadata/9a/9a7f0ed3a807f43a795e5ef325ebdadd deleted file mode 100644 index c58f955..0000000 Binary files a/Close Enough!/Library/metadata/9a/9a7f0ed3a807f43a795e5ef325ebdadd and /dev/null differ diff --git a/Close Enough!/Library/metadata/9a/9a7f0ed3a807f43a795e5ef325ebdadd.info b/Close Enough!/Library/metadata/9a/9a7f0ed3a807f43a795e5ef325ebdadd.info deleted file mode 100644 index 8c01aeb..0000000 Binary files a/Close Enough!/Library/metadata/9a/9a7f0ed3a807f43a795e5ef325ebdadd.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/9b/9b8c3485a4843ff429b03b8e96c00d77 b/Close Enough!/Library/metadata/9b/9b8c3485a4843ff429b03b8e96c00d77 deleted file mode 100644 index 424a475..0000000 Binary files a/Close Enough!/Library/metadata/9b/9b8c3485a4843ff429b03b8e96c00d77 and /dev/null differ diff --git a/Close Enough!/Library/metadata/9b/9b8c3485a4843ff429b03b8e96c00d77.info b/Close Enough!/Library/metadata/9b/9b8c3485a4843ff429b03b8e96c00d77.info deleted file mode 100644 index 0c152c9..0000000 Binary files a/Close Enough!/Library/metadata/9b/9b8c3485a4843ff429b03b8e96c00d77.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/9b/9b8c3485a4843ff429b03b8e96c00d77.resource b/Close Enough!/Library/metadata/9b/9b8c3485a4843ff429b03b8e96c00d77.resource deleted file mode 100644 index 86ed191..0000000 Binary files a/Close Enough!/Library/metadata/9b/9b8c3485a4843ff429b03b8e96c00d77.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/9c/9c0578910bbe00d43919a92c7b9893fe b/Close Enough!/Library/metadata/9c/9c0578910bbe00d43919a92c7b9893fe deleted file mode 100644 index 0e06643..0000000 Binary files a/Close Enough!/Library/metadata/9c/9c0578910bbe00d43919a92c7b9893fe and /dev/null differ diff --git a/Close Enough!/Library/metadata/9c/9c0578910bbe00d43919a92c7b9893fe.info b/Close Enough!/Library/metadata/9c/9c0578910bbe00d43919a92c7b9893fe.info deleted file mode 100644 index 68dc3be..0000000 Binary files a/Close Enough!/Library/metadata/9c/9c0578910bbe00d43919a92c7b9893fe.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/9d/9de9e8523c82543c5b3e40a4b51aa2c9 b/Close Enough!/Library/metadata/9d/9de9e8523c82543c5b3e40a4b51aa2c9 deleted file mode 100644 index 57ce313..0000000 Binary files a/Close Enough!/Library/metadata/9d/9de9e8523c82543c5b3e40a4b51aa2c9 and /dev/null differ diff --git a/Close Enough!/Library/metadata/9d/9de9e8523c82543c5b3e40a4b51aa2c9.info b/Close Enough!/Library/metadata/9d/9de9e8523c82543c5b3e40a4b51aa2c9.info deleted file mode 100644 index 4d48747..0000000 Binary files a/Close Enough!/Library/metadata/9d/9de9e8523c82543c5b3e40a4b51aa2c9.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/9e/9ed40d4587c01474982757efbeba6910 b/Close Enough!/Library/metadata/9e/9ed40d4587c01474982757efbeba6910 deleted file mode 100644 index b7ac198..0000000 Binary files a/Close Enough!/Library/metadata/9e/9ed40d4587c01474982757efbeba6910 and /dev/null differ diff --git a/Close Enough!/Library/metadata/9e/9ed40d4587c01474982757efbeba6910.info b/Close Enough!/Library/metadata/9e/9ed40d4587c01474982757efbeba6910.info deleted file mode 100644 index 0155e40..0000000 Binary files a/Close Enough!/Library/metadata/9e/9ed40d4587c01474982757efbeba6910.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/9e/9ed87f276fd794617847d24586b8d9d4 b/Close Enough!/Library/metadata/9e/9ed87f276fd794617847d24586b8d9d4 deleted file mode 100644 index c0aae81..0000000 Binary files a/Close Enough!/Library/metadata/9e/9ed87f276fd794617847d24586b8d9d4 and /dev/null differ diff --git a/Close Enough!/Library/metadata/9e/9ed87f276fd794617847d24586b8d9d4.info b/Close Enough!/Library/metadata/9e/9ed87f276fd794617847d24586b8d9d4.info deleted file mode 100644 index c75c463..0000000 Binary files a/Close Enough!/Library/metadata/9e/9ed87f276fd794617847d24586b8d9d4.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/9e/9ee58c86788afb1468f4ec78d2dd52ff b/Close Enough!/Library/metadata/9e/9ee58c86788afb1468f4ec78d2dd52ff deleted file mode 100644 index 9678628..0000000 Binary files a/Close Enough!/Library/metadata/9e/9ee58c86788afb1468f4ec78d2dd52ff and /dev/null differ diff --git a/Close Enough!/Library/metadata/9e/9ee58c86788afb1468f4ec78d2dd52ff.info b/Close Enough!/Library/metadata/9e/9ee58c86788afb1468f4ec78d2dd52ff.info deleted file mode 100644 index 6de2f78..0000000 Binary files a/Close Enough!/Library/metadata/9e/9ee58c86788afb1468f4ec78d2dd52ff.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/9f/9f8b6b383cdd1834799e4c2c3cc694ca b/Close Enough!/Library/metadata/9f/9f8b6b383cdd1834799e4c2c3cc694ca deleted file mode 100644 index 5a07bc0..0000000 Binary files a/Close Enough!/Library/metadata/9f/9f8b6b383cdd1834799e4c2c3cc694ca and /dev/null differ diff --git a/Close Enough!/Library/metadata/9f/9f8b6b383cdd1834799e4c2c3cc694ca.info b/Close Enough!/Library/metadata/9f/9f8b6b383cdd1834799e4c2c3cc694ca.info deleted file mode 100644 index 5c7d2b9..0000000 Binary files a/Close Enough!/Library/metadata/9f/9f8b6b383cdd1834799e4c2c3cc694ca.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/a1/a113f422c28124fb5b36c215f7883926 b/Close Enough!/Library/metadata/a1/a113f422c28124fb5b36c215f7883926 deleted file mode 100644 index 07e9426..0000000 Binary files a/Close Enough!/Library/metadata/a1/a113f422c28124fb5b36c215f7883926 and /dev/null differ diff --git a/Close Enough!/Library/metadata/a1/a113f422c28124fb5b36c215f7883926.info b/Close Enough!/Library/metadata/a1/a113f422c28124fb5b36c215f7883926.info deleted file mode 100644 index 4048e2e..0000000 Binary files a/Close Enough!/Library/metadata/a1/a113f422c28124fb5b36c215f7883926.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/a1/a1282db12842e41618a0544a39237116 b/Close Enough!/Library/metadata/a1/a1282db12842e41618a0544a39237116 deleted file mode 100644 index cf6e69b..0000000 Binary files a/Close Enough!/Library/metadata/a1/a1282db12842e41618a0544a39237116 and /dev/null differ diff --git a/Close Enough!/Library/metadata/a1/a1282db12842e41618a0544a39237116.info b/Close Enough!/Library/metadata/a1/a1282db12842e41618a0544a39237116.info deleted file mode 100644 index 08ab082..0000000 Binary files a/Close Enough!/Library/metadata/a1/a1282db12842e41618a0544a39237116.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/a3/a342381d77833427fa10621e38fbae10 b/Close Enough!/Library/metadata/a3/a342381d77833427fa10621e38fbae10 deleted file mode 100644 index 0455d0e..0000000 Binary files a/Close Enough!/Library/metadata/a3/a342381d77833427fa10621e38fbae10 and /dev/null differ diff --git a/Close Enough!/Library/metadata/a3/a342381d77833427fa10621e38fbae10.info b/Close Enough!/Library/metadata/a3/a342381d77833427fa10621e38fbae10.info deleted file mode 100644 index a8d4a9f..0000000 Binary files a/Close Enough!/Library/metadata/a3/a342381d77833427fa10621e38fbae10.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/a3/a34a7c80f77c24e2280f89d3e2ba915f b/Close Enough!/Library/metadata/a3/a34a7c80f77c24e2280f89d3e2ba915f deleted file mode 100644 index b8668d5..0000000 Binary files a/Close Enough!/Library/metadata/a3/a34a7c80f77c24e2280f89d3e2ba915f and /dev/null differ diff --git a/Close Enough!/Library/metadata/a3/a34a7c80f77c24e2280f89d3e2ba915f.info b/Close Enough!/Library/metadata/a3/a34a7c80f77c24e2280f89d3e2ba915f.info deleted file mode 100644 index b754930..0000000 Binary files a/Close Enough!/Library/metadata/a3/a34a7c80f77c24e2280f89d3e2ba915f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/a3/a3605337237774b41a35498964c0e0a9 b/Close Enough!/Library/metadata/a3/a3605337237774b41a35498964c0e0a9 deleted file mode 100644 index 4145f13..0000000 Binary files a/Close Enough!/Library/metadata/a3/a3605337237774b41a35498964c0e0a9 and /dev/null differ diff --git a/Close Enough!/Library/metadata/a3/a3605337237774b41a35498964c0e0a9.info b/Close Enough!/Library/metadata/a3/a3605337237774b41a35498964c0e0a9.info deleted file mode 100644 index e61eeb4..0000000 Binary files a/Close Enough!/Library/metadata/a3/a3605337237774b41a35498964c0e0a9.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/a3/a37e18887fa954edf92bc36bc353b879 b/Close Enough!/Library/metadata/a3/a37e18887fa954edf92bc36bc353b879 deleted file mode 100644 index d2cc018..0000000 Binary files a/Close Enough!/Library/metadata/a3/a37e18887fa954edf92bc36bc353b879 and /dev/null differ diff --git a/Close Enough!/Library/metadata/a3/a37e18887fa954edf92bc36bc353b879.info b/Close Enough!/Library/metadata/a3/a37e18887fa954edf92bc36bc353b879.info deleted file mode 100644 index 99b8c82..0000000 Binary files a/Close Enough!/Library/metadata/a3/a37e18887fa954edf92bc36bc353b879.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/a3/a3ef6eb3b3ef7b640b278e36c5c7ee2c b/Close Enough!/Library/metadata/a3/a3ef6eb3b3ef7b640b278e36c5c7ee2c deleted file mode 100644 index 88b3415..0000000 Binary files a/Close Enough!/Library/metadata/a3/a3ef6eb3b3ef7b640b278e36c5c7ee2c and /dev/null differ diff --git a/Close Enough!/Library/metadata/a3/a3ef6eb3b3ef7b640b278e36c5c7ee2c.info b/Close Enough!/Library/metadata/a3/a3ef6eb3b3ef7b640b278e36c5c7ee2c.info deleted file mode 100644 index 5a744ae..0000000 Binary files a/Close Enough!/Library/metadata/a3/a3ef6eb3b3ef7b640b278e36c5c7ee2c.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/a3/a3ef6eb3b3ef7b640b278e36c5c7ee2c.resource b/Close Enough!/Library/metadata/a3/a3ef6eb3b3ef7b640b278e36c5c7ee2c.resource deleted file mode 100644 index 355dccb..0000000 Binary files a/Close Enough!/Library/metadata/a3/a3ef6eb3b3ef7b640b278e36c5c7ee2c.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/a4/a43bff32aaa89482380228d59cac1d60 b/Close Enough!/Library/metadata/a4/a43bff32aaa89482380228d59cac1d60 deleted file mode 100644 index b34b04a..0000000 Binary files a/Close Enough!/Library/metadata/a4/a43bff32aaa89482380228d59cac1d60 and /dev/null differ diff --git a/Close Enough!/Library/metadata/a4/a43bff32aaa89482380228d59cac1d60.info b/Close Enough!/Library/metadata/a4/a43bff32aaa89482380228d59cac1d60.info deleted file mode 100644 index 3a33488..0000000 Binary files a/Close Enough!/Library/metadata/a4/a43bff32aaa89482380228d59cac1d60.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/a5/a5d15f2051d09644ebccdef0f54b7bbb b/Close Enough!/Library/metadata/a5/a5d15f2051d09644ebccdef0f54b7bbb deleted file mode 100644 index 46ee6ec..0000000 Binary files a/Close Enough!/Library/metadata/a5/a5d15f2051d09644ebccdef0f54b7bbb and /dev/null differ diff --git a/Close Enough!/Library/metadata/a5/a5d15f2051d09644ebccdef0f54b7bbb.info b/Close Enough!/Library/metadata/a5/a5d15f2051d09644ebccdef0f54b7bbb.info deleted file mode 100644 index 9a3b063..0000000 Binary files a/Close Enough!/Library/metadata/a5/a5d15f2051d09644ebccdef0f54b7bbb.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/a6/a6842a74831964edc8fefa1c0aed89dc b/Close Enough!/Library/metadata/a6/a6842a74831964edc8fefa1c0aed89dc deleted file mode 100644 index c91901d..0000000 Binary files a/Close Enough!/Library/metadata/a6/a6842a74831964edc8fefa1c0aed89dc and /dev/null differ diff --git a/Close Enough!/Library/metadata/a6/a6842a74831964edc8fefa1c0aed89dc.info b/Close Enough!/Library/metadata/a6/a6842a74831964edc8fefa1c0aed89dc.info deleted file mode 100644 index 3de30d0..0000000 Binary files a/Close Enough!/Library/metadata/a6/a6842a74831964edc8fefa1c0aed89dc.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/a9/a93f5f1b9a1c81a4db522bb57fc9b735 b/Close Enough!/Library/metadata/a9/a93f5f1b9a1c81a4db522bb57fc9b735 deleted file mode 100644 index db185a6..0000000 Binary files a/Close Enough!/Library/metadata/a9/a93f5f1b9a1c81a4db522bb57fc9b735 and /dev/null differ diff --git a/Close Enough!/Library/metadata/a9/a93f5f1b9a1c81a4db522bb57fc9b735.info b/Close Enough!/Library/metadata/a9/a93f5f1b9a1c81a4db522bb57fc9b735.info deleted file mode 100644 index 9e9f982..0000000 Binary files a/Close Enough!/Library/metadata/a9/a93f5f1b9a1c81a4db522bb57fc9b735.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/a9/a97ffd97e95f12a45abf0bb60d3ab12c b/Close Enough!/Library/metadata/a9/a97ffd97e95f12a45abf0bb60d3ab12c deleted file mode 100644 index 87b953f..0000000 Binary files a/Close Enough!/Library/metadata/a9/a97ffd97e95f12a45abf0bb60d3ab12c and /dev/null differ diff --git a/Close Enough!/Library/metadata/a9/a97ffd97e95f12a45abf0bb60d3ab12c.info b/Close Enough!/Library/metadata/a9/a97ffd97e95f12a45abf0bb60d3ab12c.info deleted file mode 100644 index cc17cce..0000000 Binary files a/Close Enough!/Library/metadata/a9/a97ffd97e95f12a45abf0bb60d3ab12c.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/a9/a9a5231a693155f4f8ba0baa0e33af35 b/Close Enough!/Library/metadata/a9/a9a5231a693155f4f8ba0baa0e33af35 deleted file mode 100644 index 78f138c..0000000 Binary files a/Close Enough!/Library/metadata/a9/a9a5231a693155f4f8ba0baa0e33af35 and /dev/null differ diff --git a/Close Enough!/Library/metadata/a9/a9a5231a693155f4f8ba0baa0e33af35.info b/Close Enough!/Library/metadata/a9/a9a5231a693155f4f8ba0baa0e33af35.info deleted file mode 100644 index 64ebcb0..0000000 Binary files a/Close Enough!/Library/metadata/a9/a9a5231a693155f4f8ba0baa0e33af35.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ab/abbf2830e660f0f40867993f00ce7b9a b/Close Enough!/Library/metadata/ab/abbf2830e660f0f40867993f00ce7b9a deleted file mode 100644 index 01c42eb..0000000 Binary files a/Close Enough!/Library/metadata/ab/abbf2830e660f0f40867993f00ce7b9a and /dev/null differ diff --git a/Close Enough!/Library/metadata/ab/abbf2830e660f0f40867993f00ce7b9a.info b/Close Enough!/Library/metadata/ab/abbf2830e660f0f40867993f00ce7b9a.info deleted file mode 100644 index 47fc122..0000000 Binary files a/Close Enough!/Library/metadata/ab/abbf2830e660f0f40867993f00ce7b9a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ab/abd4c2a2c71a1214da4f39391c1a8122 b/Close Enough!/Library/metadata/ab/abd4c2a2c71a1214da4f39391c1a8122 deleted file mode 100644 index 8826924..0000000 Binary files a/Close Enough!/Library/metadata/ab/abd4c2a2c71a1214da4f39391c1a8122 and /dev/null differ diff --git a/Close Enough!/Library/metadata/ab/abd4c2a2c71a1214da4f39391c1a8122.info b/Close Enough!/Library/metadata/ab/abd4c2a2c71a1214da4f39391c1a8122.info deleted file mode 100644 index d3e6cf4..0000000 Binary files a/Close Enough!/Library/metadata/ab/abd4c2a2c71a1214da4f39391c1a8122.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ac/acdbbb1901a14c94c9ca7d68f2fb7c35 b/Close Enough!/Library/metadata/ac/acdbbb1901a14c94c9ca7d68f2fb7c35 deleted file mode 100644 index a9e4f9d..0000000 Binary files a/Close Enough!/Library/metadata/ac/acdbbb1901a14c94c9ca7d68f2fb7c35 and /dev/null differ diff --git a/Close Enough!/Library/metadata/ac/acdbbb1901a14c94c9ca7d68f2fb7c35.info b/Close Enough!/Library/metadata/ac/acdbbb1901a14c94c9ca7d68f2fb7c35.info deleted file mode 100644 index 799e25b..0000000 Binary files a/Close Enough!/Library/metadata/ac/acdbbb1901a14c94c9ca7d68f2fb7c35.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ac/ace554b28b3c23448817bd8c63e751ff b/Close Enough!/Library/metadata/ac/ace554b28b3c23448817bd8c63e751ff deleted file mode 100644 index 22a2a06..0000000 Binary files a/Close Enough!/Library/metadata/ac/ace554b28b3c23448817bd8c63e751ff and /dev/null differ diff --git a/Close Enough!/Library/metadata/ac/ace554b28b3c23448817bd8c63e751ff.info b/Close Enough!/Library/metadata/ac/ace554b28b3c23448817bd8c63e751ff.info deleted file mode 100644 index 2c06ff0..0000000 Binary files a/Close Enough!/Library/metadata/ac/ace554b28b3c23448817bd8c63e751ff.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ad/ad727d7e1462ecc4f83c898ecc501997 b/Close Enough!/Library/metadata/ad/ad727d7e1462ecc4f83c898ecc501997 deleted file mode 100644 index 740ac8b..0000000 Binary files a/Close Enough!/Library/metadata/ad/ad727d7e1462ecc4f83c898ecc501997 and /dev/null differ diff --git a/Close Enough!/Library/metadata/ad/ad727d7e1462ecc4f83c898ecc501997.info b/Close Enough!/Library/metadata/ad/ad727d7e1462ecc4f83c898ecc501997.info deleted file mode 100644 index b19d8df..0000000 Binary files a/Close Enough!/Library/metadata/ad/ad727d7e1462ecc4f83c898ecc501997.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ad/adab7787bd7d44c4a9d48b3aff189c47 b/Close Enough!/Library/metadata/ad/adab7787bd7d44c4a9d48b3aff189c47 deleted file mode 100644 index f584c4b..0000000 Binary files a/Close Enough!/Library/metadata/ad/adab7787bd7d44c4a9d48b3aff189c47 and /dev/null differ diff --git a/Close Enough!/Library/metadata/ad/adab7787bd7d44c4a9d48b3aff189c47.info b/Close Enough!/Library/metadata/ad/adab7787bd7d44c4a9d48b3aff189c47.info deleted file mode 100644 index 1656361..0000000 Binary files a/Close Enough!/Library/metadata/ad/adab7787bd7d44c4a9d48b3aff189c47.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ad/adebbd281f1a4ef3a30be7f21937e02f b/Close Enough!/Library/metadata/ad/adebbd281f1a4ef3a30be7f21937e02f deleted file mode 100644 index 6ad3093..0000000 Binary files a/Close Enough!/Library/metadata/ad/adebbd281f1a4ef3a30be7f21937e02f and /dev/null differ diff --git a/Close Enough!/Library/metadata/ad/adebbd281f1a4ef3a30be7f21937e02f.info b/Close Enough!/Library/metadata/ad/adebbd281f1a4ef3a30be7f21937e02f.info deleted file mode 100644 index c70deee..0000000 Binary files a/Close Enough!/Library/metadata/ad/adebbd281f1a4ef3a30be7f21937e02f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ae/ae013986df9744e1a8d3e1a1881bf504 b/Close Enough!/Library/metadata/ae/ae013986df9744e1a8d3e1a1881bf504 deleted file mode 100644 index c22c060..0000000 Binary files a/Close Enough!/Library/metadata/ae/ae013986df9744e1a8d3e1a1881bf504 and /dev/null differ diff --git a/Close Enough!/Library/metadata/ae/ae013986df9744e1a8d3e1a1881bf504.info b/Close Enough!/Library/metadata/ae/ae013986df9744e1a8d3e1a1881bf504.info deleted file mode 100644 index 4456db9..0000000 Binary files a/Close Enough!/Library/metadata/ae/ae013986df9744e1a8d3e1a1881bf504.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/af/affcaaed8b0a68d44999f9aa511c2656 b/Close Enough!/Library/metadata/af/affcaaed8b0a68d44999f9aa511c2656 deleted file mode 100644 index 8111404..0000000 Binary files a/Close Enough!/Library/metadata/af/affcaaed8b0a68d44999f9aa511c2656 and /dev/null differ diff --git a/Close Enough!/Library/metadata/af/affcaaed8b0a68d44999f9aa511c2656.info b/Close Enough!/Library/metadata/af/affcaaed8b0a68d44999f9aa511c2656.info deleted file mode 100644 index 5a140bb..0000000 Binary files a/Close Enough!/Library/metadata/af/affcaaed8b0a68d44999f9aa511c2656.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/af/affcaaed8b0a68d44999f9aa511c2656.resource b/Close Enough!/Library/metadata/af/affcaaed8b0a68d44999f9aa511c2656.resource deleted file mode 100644 index fab45a1..0000000 Binary files a/Close Enough!/Library/metadata/af/affcaaed8b0a68d44999f9aa511c2656.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/b0/b0286928aca715b43ae103c9668a0e47 b/Close Enough!/Library/metadata/b0/b0286928aca715b43ae103c9668a0e47 deleted file mode 100644 index 226484d..0000000 Binary files a/Close Enough!/Library/metadata/b0/b0286928aca715b43ae103c9668a0e47 and /dev/null differ diff --git a/Close Enough!/Library/metadata/b0/b0286928aca715b43ae103c9668a0e47.info b/Close Enough!/Library/metadata/b0/b0286928aca715b43ae103c9668a0e47.info deleted file mode 100644 index f08932d..0000000 Binary files a/Close Enough!/Library/metadata/b0/b0286928aca715b43ae103c9668a0e47.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/b1/b10a1d1e3418da84eb55ed366baf7152 b/Close Enough!/Library/metadata/b1/b10a1d1e3418da84eb55ed366baf7152 deleted file mode 100644 index 8e977da..0000000 Binary files a/Close Enough!/Library/metadata/b1/b10a1d1e3418da84eb55ed366baf7152 and /dev/null differ diff --git a/Close Enough!/Library/metadata/b1/b10a1d1e3418da84eb55ed366baf7152.info b/Close Enough!/Library/metadata/b1/b10a1d1e3418da84eb55ed366baf7152.info deleted file mode 100644 index dd5b83b..0000000 Binary files a/Close Enough!/Library/metadata/b1/b10a1d1e3418da84eb55ed366baf7152.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/b2/b23696cf08cecd141b18c7d3a1cbaf7c b/Close Enough!/Library/metadata/b2/b23696cf08cecd141b18c7d3a1cbaf7c deleted file mode 100644 index 4266480..0000000 Binary files a/Close Enough!/Library/metadata/b2/b23696cf08cecd141b18c7d3a1cbaf7c and /dev/null differ diff --git a/Close Enough!/Library/metadata/b2/b23696cf08cecd141b18c7d3a1cbaf7c.info b/Close Enough!/Library/metadata/b2/b23696cf08cecd141b18c7d3a1cbaf7c.info deleted file mode 100644 index 1b0d8c2..0000000 Binary files a/Close Enough!/Library/metadata/b2/b23696cf08cecd141b18c7d3a1cbaf7c.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/b2/b23696cf08cecd141b18c7d3a1cbaf7c.resource b/Close Enough!/Library/metadata/b2/b23696cf08cecd141b18c7d3a1cbaf7c.resource deleted file mode 100644 index 960b5d0..0000000 Binary files a/Close Enough!/Library/metadata/b2/b23696cf08cecd141b18c7d3a1cbaf7c.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/b2/b2b693dffac3a4433b3114fea0b7fd4e b/Close Enough!/Library/metadata/b2/b2b693dffac3a4433b3114fea0b7fd4e deleted file mode 100644 index bfcc379..0000000 Binary files a/Close Enough!/Library/metadata/b2/b2b693dffac3a4433b3114fea0b7fd4e and /dev/null differ diff --git a/Close Enough!/Library/metadata/b2/b2b693dffac3a4433b3114fea0b7fd4e.info b/Close Enough!/Library/metadata/b2/b2b693dffac3a4433b3114fea0b7fd4e.info deleted file mode 100644 index d172e84..0000000 Binary files a/Close Enough!/Library/metadata/b2/b2b693dffac3a4433b3114fea0b7fd4e.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/b2/b2bead50dbf86924f8e51f03ddbebf70 b/Close Enough!/Library/metadata/b2/b2bead50dbf86924f8e51f03ddbebf70 deleted file mode 100644 index cf506f6..0000000 Binary files a/Close Enough!/Library/metadata/b2/b2bead50dbf86924f8e51f03ddbebf70 and /dev/null differ diff --git a/Close Enough!/Library/metadata/b2/b2bead50dbf86924f8e51f03ddbebf70.info b/Close Enough!/Library/metadata/b2/b2bead50dbf86924f8e51f03ddbebf70.info deleted file mode 100644 index 004c758..0000000 Binary files a/Close Enough!/Library/metadata/b2/b2bead50dbf86924f8e51f03ddbebf70.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/b2/b2c7539e2fbe14397904396cbe33ebf0 b/Close Enough!/Library/metadata/b2/b2c7539e2fbe14397904396cbe33ebf0 deleted file mode 100644 index b1303f0..0000000 Binary files a/Close Enough!/Library/metadata/b2/b2c7539e2fbe14397904396cbe33ebf0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/b2/b2c7539e2fbe14397904396cbe33ebf0.info b/Close Enough!/Library/metadata/b2/b2c7539e2fbe14397904396cbe33ebf0.info deleted file mode 100644 index 5280c5a..0000000 Binary files a/Close Enough!/Library/metadata/b2/b2c7539e2fbe14397904396cbe33ebf0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/b3/b32abd1c9d73a4cce8389f084ac12b11 b/Close Enough!/Library/metadata/b3/b32abd1c9d73a4cce8389f084ac12b11 deleted file mode 100644 index 6f8c754..0000000 Binary files a/Close Enough!/Library/metadata/b3/b32abd1c9d73a4cce8389f084ac12b11 and /dev/null differ diff --git a/Close Enough!/Library/metadata/b3/b32abd1c9d73a4cce8389f084ac12b11.info b/Close Enough!/Library/metadata/b3/b32abd1c9d73a4cce8389f084ac12b11.info deleted file mode 100644 index 8415f44..0000000 Binary files a/Close Enough!/Library/metadata/b3/b32abd1c9d73a4cce8389f084ac12b11.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/b3/b3768e1d72e30224c8f395ff8e7aa742 b/Close Enough!/Library/metadata/b3/b3768e1d72e30224c8f395ff8e7aa742 deleted file mode 100644 index 91029f6..0000000 Binary files a/Close Enough!/Library/metadata/b3/b3768e1d72e30224c8f395ff8e7aa742 and /dev/null differ diff --git a/Close Enough!/Library/metadata/b3/b3768e1d72e30224c8f395ff8e7aa742.info b/Close Enough!/Library/metadata/b3/b3768e1d72e30224c8f395ff8e7aa742.info deleted file mode 100644 index 3e53e05..0000000 Binary files a/Close Enough!/Library/metadata/b3/b3768e1d72e30224c8f395ff8e7aa742.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/b3/b3768e1d72e30224c8f395ff8e7aa742.resource b/Close Enough!/Library/metadata/b3/b3768e1d72e30224c8f395ff8e7aa742.resource deleted file mode 100644 index 39dba7d..0000000 Binary files a/Close Enough!/Library/metadata/b3/b3768e1d72e30224c8f395ff8e7aa742.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/b3/b3e4a8b5e0cf24ff596c7ce54e68987c b/Close Enough!/Library/metadata/b3/b3e4a8b5e0cf24ff596c7ce54e68987c deleted file mode 100644 index 6ea0be3..0000000 Binary files a/Close Enough!/Library/metadata/b3/b3e4a8b5e0cf24ff596c7ce54e68987c and /dev/null differ diff --git a/Close Enough!/Library/metadata/b3/b3e4a8b5e0cf24ff596c7ce54e68987c.info b/Close Enough!/Library/metadata/b3/b3e4a8b5e0cf24ff596c7ce54e68987c.info deleted file mode 100644 index 500f3e5..0000000 Binary files a/Close Enough!/Library/metadata/b3/b3e4a8b5e0cf24ff596c7ce54e68987c.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/b4/b42edf68166d948bc843aad40004066e b/Close Enough!/Library/metadata/b4/b42edf68166d948bc843aad40004066e deleted file mode 100644 index e37d017..0000000 Binary files a/Close Enough!/Library/metadata/b4/b42edf68166d948bc843aad40004066e and /dev/null differ diff --git a/Close Enough!/Library/metadata/b4/b42edf68166d948bc843aad40004066e.info b/Close Enough!/Library/metadata/b4/b42edf68166d948bc843aad40004066e.info deleted file mode 100644 index 075136c..0000000 Binary files a/Close Enough!/Library/metadata/b4/b42edf68166d948bc843aad40004066e.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/b5/b51a3e520f9164da198dc59c8acfccd6 b/Close Enough!/Library/metadata/b5/b51a3e520f9164da198dc59c8acfccd6 deleted file mode 100644 index cd12f1d..0000000 Binary files a/Close Enough!/Library/metadata/b5/b51a3e520f9164da198dc59c8acfccd6 and /dev/null differ diff --git a/Close Enough!/Library/metadata/b5/b51a3e520f9164da198dc59c8acfccd6.info b/Close Enough!/Library/metadata/b5/b51a3e520f9164da198dc59c8acfccd6.info deleted file mode 100644 index 62d2155..0000000 Binary files a/Close Enough!/Library/metadata/b5/b51a3e520f9164da198dc59c8acfccd6.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/b5/b52e557db2c2b4eebb10444f1d582029 b/Close Enough!/Library/metadata/b5/b52e557db2c2b4eebb10444f1d582029 deleted file mode 100644 index 34ac597..0000000 Binary files a/Close Enough!/Library/metadata/b5/b52e557db2c2b4eebb10444f1d582029 and /dev/null differ diff --git a/Close Enough!/Library/metadata/b5/b52e557db2c2b4eebb10444f1d582029.info b/Close Enough!/Library/metadata/b5/b52e557db2c2b4eebb10444f1d582029.info deleted file mode 100644 index 8d43b22..0000000 Binary files a/Close Enough!/Library/metadata/b5/b52e557db2c2b4eebb10444f1d582029.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/b5/b58202ac774c98541938d7b809a4fe78 b/Close Enough!/Library/metadata/b5/b58202ac774c98541938d7b809a4fe78 deleted file mode 100644 index 2c805e8..0000000 Binary files a/Close Enough!/Library/metadata/b5/b58202ac774c98541938d7b809a4fe78 and /dev/null differ diff --git a/Close Enough!/Library/metadata/b5/b58202ac774c98541938d7b809a4fe78.info b/Close Enough!/Library/metadata/b5/b58202ac774c98541938d7b809a4fe78.info deleted file mode 100644 index 352402c..0000000 Binary files a/Close Enough!/Library/metadata/b5/b58202ac774c98541938d7b809a4fe78.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/b5/b5da970776034f77a070d99423d68791 b/Close Enough!/Library/metadata/b5/b5da970776034f77a070d99423d68791 deleted file mode 100644 index 2992fbd..0000000 Binary files a/Close Enough!/Library/metadata/b5/b5da970776034f77a070d99423d68791 and /dev/null differ diff --git a/Close Enough!/Library/metadata/b5/b5da970776034f77a070d99423d68791.info b/Close Enough!/Library/metadata/b5/b5da970776034f77a070d99423d68791.info deleted file mode 100644 index eab10b5..0000000 Binary files a/Close Enough!/Library/metadata/b5/b5da970776034f77a070d99423d68791.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/b5/b5f4343795a0e4626ac1fe4a9e6fce59 b/Close Enough!/Library/metadata/b5/b5f4343795a0e4626ac1fe4a9e6fce59 deleted file mode 100644 index d87183e..0000000 Binary files a/Close Enough!/Library/metadata/b5/b5f4343795a0e4626ac1fe4a9e6fce59 and /dev/null differ diff --git a/Close Enough!/Library/metadata/b5/b5f4343795a0e4626ac1fe4a9e6fce59.info b/Close Enough!/Library/metadata/b5/b5f4343795a0e4626ac1fe4a9e6fce59.info deleted file mode 100644 index 2964e98..0000000 Binary files a/Close Enough!/Library/metadata/b5/b5f4343795a0e4626ac1fe4a9e6fce59.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/b7/b78e844daec4c444387443eaf9885a09 b/Close Enough!/Library/metadata/b7/b78e844daec4c444387443eaf9885a09 deleted file mode 100644 index 39915b3..0000000 Binary files a/Close Enough!/Library/metadata/b7/b78e844daec4c444387443eaf9885a09 and /dev/null differ diff --git a/Close Enough!/Library/metadata/b7/b78e844daec4c444387443eaf9885a09.info b/Close Enough!/Library/metadata/b7/b78e844daec4c444387443eaf9885a09.info deleted file mode 100644 index db6692a..0000000 Binary files a/Close Enough!/Library/metadata/b7/b78e844daec4c444387443eaf9885a09.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/b7/b78e844daec4c444387443eaf9885a09.resource b/Close Enough!/Library/metadata/b7/b78e844daec4c444387443eaf9885a09.resource deleted file mode 100644 index 2a19993..0000000 Binary files a/Close Enough!/Library/metadata/b7/b78e844daec4c444387443eaf9885a09.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/b8/b8a0574e92bd43a59e19d6c3c6ae54c7 b/Close Enough!/Library/metadata/b8/b8a0574e92bd43a59e19d6c3c6ae54c7 deleted file mode 100644 index 9fc3d75..0000000 Binary files a/Close Enough!/Library/metadata/b8/b8a0574e92bd43a59e19d6c3c6ae54c7 and /dev/null differ diff --git a/Close Enough!/Library/metadata/b8/b8a0574e92bd43a59e19d6c3c6ae54c7.info b/Close Enough!/Library/metadata/b8/b8a0574e92bd43a59e19d6c3c6ae54c7.info deleted file mode 100644 index 0b0d619..0000000 Binary files a/Close Enough!/Library/metadata/b8/b8a0574e92bd43a59e19d6c3c6ae54c7.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/b9/b92a55b494e36964b92a8ba0d5d2dc3b b/Close Enough!/Library/metadata/b9/b92a55b494e36964b92a8ba0d5d2dc3b deleted file mode 100644 index a5ee069..0000000 Binary files a/Close Enough!/Library/metadata/b9/b92a55b494e36964b92a8ba0d5d2dc3b and /dev/null differ diff --git a/Close Enough!/Library/metadata/b9/b92a55b494e36964b92a8ba0d5d2dc3b.info b/Close Enough!/Library/metadata/b9/b92a55b494e36964b92a8ba0d5d2dc3b.info deleted file mode 100644 index 955f2ed..0000000 Binary files a/Close Enough!/Library/metadata/b9/b92a55b494e36964b92a8ba0d5d2dc3b.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/bb/bb63e33750f8a4c93898a278086b00dd b/Close Enough!/Library/metadata/bb/bb63e33750f8a4c93898a278086b00dd deleted file mode 100644 index 5c4f075..0000000 Binary files a/Close Enough!/Library/metadata/bb/bb63e33750f8a4c93898a278086b00dd and /dev/null differ diff --git a/Close Enough!/Library/metadata/bb/bb63e33750f8a4c93898a278086b00dd.info b/Close Enough!/Library/metadata/bb/bb63e33750f8a4c93898a278086b00dd.info deleted file mode 100644 index 2f9172a..0000000 Binary files a/Close Enough!/Library/metadata/bb/bb63e33750f8a4c93898a278086b00dd.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/bb/bbda0a9bd8265d54e9f43ddfe1f9800b b/Close Enough!/Library/metadata/bb/bbda0a9bd8265d54e9f43ddfe1f9800b deleted file mode 100644 index 2f90947..0000000 Binary files a/Close Enough!/Library/metadata/bb/bbda0a9bd8265d54e9f43ddfe1f9800b and /dev/null differ diff --git a/Close Enough!/Library/metadata/bb/bbda0a9bd8265d54e9f43ddfe1f9800b.info b/Close Enough!/Library/metadata/bb/bbda0a9bd8265d54e9f43ddfe1f9800b.info deleted file mode 100644 index 322a1c4..0000000 Binary files a/Close Enough!/Library/metadata/bb/bbda0a9bd8265d54e9f43ddfe1f9800b.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/bc/bc3f4dadd25403f46b92ae07a3291f49 b/Close Enough!/Library/metadata/bc/bc3f4dadd25403f46b92ae07a3291f49 deleted file mode 100644 index c3b033c..0000000 Binary files a/Close Enough!/Library/metadata/bc/bc3f4dadd25403f46b92ae07a3291f49 and /dev/null differ diff --git a/Close Enough!/Library/metadata/bc/bc3f4dadd25403f46b92ae07a3291f49.info b/Close Enough!/Library/metadata/bc/bc3f4dadd25403f46b92ae07a3291f49.info deleted file mode 100644 index 475aced..0000000 Binary files a/Close Enough!/Library/metadata/bc/bc3f4dadd25403f46b92ae07a3291f49.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/bc/bc3f4dadd25403f46b92ae07a3291f49.resource b/Close Enough!/Library/metadata/bc/bc3f4dadd25403f46b92ae07a3291f49.resource deleted file mode 100644 index 79eb650..0000000 Binary files a/Close Enough!/Library/metadata/bc/bc3f4dadd25403f46b92ae07a3291f49.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/bc/bcd27da1c9ae94d2cafe094482a20792 b/Close Enough!/Library/metadata/bc/bcd27da1c9ae94d2cafe094482a20792 deleted file mode 100644 index 66df35b..0000000 Binary files a/Close Enough!/Library/metadata/bc/bcd27da1c9ae94d2cafe094482a20792 and /dev/null differ diff --git a/Close Enough!/Library/metadata/bc/bcd27da1c9ae94d2cafe094482a20792.info b/Close Enough!/Library/metadata/bc/bcd27da1c9ae94d2cafe094482a20792.info deleted file mode 100644 index c4322a9..0000000 Binary files a/Close Enough!/Library/metadata/bc/bcd27da1c9ae94d2cafe094482a20792.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/bc/bcfc9cc82dd15e74aaefb3c50f1250e2 b/Close Enough!/Library/metadata/bc/bcfc9cc82dd15e74aaefb3c50f1250e2 deleted file mode 100644 index a1fa203..0000000 Binary files a/Close Enough!/Library/metadata/bc/bcfc9cc82dd15e74aaefb3c50f1250e2 and /dev/null differ diff --git a/Close Enough!/Library/metadata/bc/bcfc9cc82dd15e74aaefb3c50f1250e2.info b/Close Enough!/Library/metadata/bc/bcfc9cc82dd15e74aaefb3c50f1250e2.info deleted file mode 100644 index f2170e5..0000000 Binary files a/Close Enough!/Library/metadata/bc/bcfc9cc82dd15e74aaefb3c50f1250e2.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/bd/bd53a22f0b1936d498371a37d1b2b861 b/Close Enough!/Library/metadata/bd/bd53a22f0b1936d498371a37d1b2b861 deleted file mode 100644 index cb63cc9..0000000 Binary files a/Close Enough!/Library/metadata/bd/bd53a22f0b1936d498371a37d1b2b861 and /dev/null differ diff --git a/Close Enough!/Library/metadata/bd/bd53a22f0b1936d498371a37d1b2b861.info b/Close Enough!/Library/metadata/bd/bd53a22f0b1936d498371a37d1b2b861.info deleted file mode 100644 index e2b2e93..0000000 Binary files a/Close Enough!/Library/metadata/bd/bd53a22f0b1936d498371a37d1b2b861.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/bd/bd53a22f0b1936d498371a37d1b2b861.resource b/Close Enough!/Library/metadata/bd/bd53a22f0b1936d498371a37d1b2b861.resource deleted file mode 100644 index ad56d8e..0000000 Binary files a/Close Enough!/Library/metadata/bd/bd53a22f0b1936d498371a37d1b2b861.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/be/bedef836b85f29842b88d876e120e16c b/Close Enough!/Library/metadata/be/bedef836b85f29842b88d876e120e16c deleted file mode 100644 index 0adda13..0000000 Binary files a/Close Enough!/Library/metadata/be/bedef836b85f29842b88d876e120e16c and /dev/null differ diff --git a/Close Enough!/Library/metadata/be/bedef836b85f29842b88d876e120e16c.info b/Close Enough!/Library/metadata/be/bedef836b85f29842b88d876e120e16c.info deleted file mode 100644 index 0608ccc..0000000 Binary files a/Close Enough!/Library/metadata/be/bedef836b85f29842b88d876e120e16c.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/bf/bf735274fbcda460692cee073919c11a b/Close Enough!/Library/metadata/bf/bf735274fbcda460692cee073919c11a deleted file mode 100644 index dcdb3b9..0000000 Binary files a/Close Enough!/Library/metadata/bf/bf735274fbcda460692cee073919c11a and /dev/null differ diff --git a/Close Enough!/Library/metadata/bf/bf735274fbcda460692cee073919c11a.info b/Close Enough!/Library/metadata/bf/bf735274fbcda460692cee073919c11a.info deleted file mode 100644 index ab33ed4..0000000 Binary files a/Close Enough!/Library/metadata/bf/bf735274fbcda460692cee073919c11a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/c0/c000d25dbc468425ca2e39cf00d62e8d b/Close Enough!/Library/metadata/c0/c000d25dbc468425ca2e39cf00d62e8d deleted file mode 100644 index 17466bb..0000000 Binary files a/Close Enough!/Library/metadata/c0/c000d25dbc468425ca2e39cf00d62e8d and /dev/null differ diff --git a/Close Enough!/Library/metadata/c0/c000d25dbc468425ca2e39cf00d62e8d.info b/Close Enough!/Library/metadata/c0/c000d25dbc468425ca2e39cf00d62e8d.info deleted file mode 100644 index 0d5490d..0000000 Binary files a/Close Enough!/Library/metadata/c0/c000d25dbc468425ca2e39cf00d62e8d.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/c0/c051d21f8b9ec403d920415d95d183a9 b/Close Enough!/Library/metadata/c0/c051d21f8b9ec403d920415d95d183a9 deleted file mode 100644 index 8133c85..0000000 Binary files a/Close Enough!/Library/metadata/c0/c051d21f8b9ec403d920415d95d183a9 and /dev/null differ diff --git a/Close Enough!/Library/metadata/c0/c051d21f8b9ec403d920415d95d183a9.info b/Close Enough!/Library/metadata/c0/c051d21f8b9ec403d920415d95d183a9.info deleted file mode 100644 index dde3869..0000000 Binary files a/Close Enough!/Library/metadata/c0/c051d21f8b9ec403d920415d95d183a9.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/c0/c0978251ff7b10d4fb954a4b56acd9f0 b/Close Enough!/Library/metadata/c0/c0978251ff7b10d4fb954a4b56acd9f0 deleted file mode 100644 index fabf5cf..0000000 Binary files a/Close Enough!/Library/metadata/c0/c0978251ff7b10d4fb954a4b56acd9f0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/c0/c0978251ff7b10d4fb954a4b56acd9f0.info b/Close Enough!/Library/metadata/c0/c0978251ff7b10d4fb954a4b56acd9f0.info deleted file mode 100644 index f203566..0000000 Binary files a/Close Enough!/Library/metadata/c0/c0978251ff7b10d4fb954a4b56acd9f0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/c3/c32de72f872aad9448b3118fda0231fb b/Close Enough!/Library/metadata/c3/c32de72f872aad9448b3118fda0231fb deleted file mode 100644 index 67b20ae..0000000 Binary files a/Close Enough!/Library/metadata/c3/c32de72f872aad9448b3118fda0231fb and /dev/null differ diff --git a/Close Enough!/Library/metadata/c3/c32de72f872aad9448b3118fda0231fb.info b/Close Enough!/Library/metadata/c3/c32de72f872aad9448b3118fda0231fb.info deleted file mode 100644 index b397baa..0000000 Binary files a/Close Enough!/Library/metadata/c3/c32de72f872aad9448b3118fda0231fb.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/c3/c33d5d8b455df684c930e7c56d03919e b/Close Enough!/Library/metadata/c3/c33d5d8b455df684c930e7c56d03919e deleted file mode 100644 index b0235af..0000000 Binary files a/Close Enough!/Library/metadata/c3/c33d5d8b455df684c930e7c56d03919e and /dev/null differ diff --git a/Close Enough!/Library/metadata/c3/c33d5d8b455df684c930e7c56d03919e.info b/Close Enough!/Library/metadata/c3/c33d5d8b455df684c930e7c56d03919e.info deleted file mode 100644 index 4bc2a7f..0000000 Binary files a/Close Enough!/Library/metadata/c3/c33d5d8b455df684c930e7c56d03919e.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/c3/c33d5d8b455df684c930e7c56d03919e.resource b/Close Enough!/Library/metadata/c3/c33d5d8b455df684c930e7c56d03919e.resource deleted file mode 100644 index f11b86d..0000000 Binary files a/Close Enough!/Library/metadata/c3/c33d5d8b455df684c930e7c56d03919e.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/c3/c393b74a8c0163d46928cf2a97f1bbd0 b/Close Enough!/Library/metadata/c3/c393b74a8c0163d46928cf2a97f1bbd0 deleted file mode 100644 index 7dafb2f..0000000 Binary files a/Close Enough!/Library/metadata/c3/c393b74a8c0163d46928cf2a97f1bbd0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/c3/c393b74a8c0163d46928cf2a97f1bbd0.info b/Close Enough!/Library/metadata/c3/c393b74a8c0163d46928cf2a97f1bbd0.info deleted file mode 100644 index b95e302..0000000 Binary files a/Close Enough!/Library/metadata/c3/c393b74a8c0163d46928cf2a97f1bbd0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/c3/c3d5953bb1e2e47c69cb3f955f1fc5cc b/Close Enough!/Library/metadata/c3/c3d5953bb1e2e47c69cb3f955f1fc5cc deleted file mode 100644 index 3eb03d9..0000000 Binary files a/Close Enough!/Library/metadata/c3/c3d5953bb1e2e47c69cb3f955f1fc5cc and /dev/null differ diff --git a/Close Enough!/Library/metadata/c3/c3d5953bb1e2e47c69cb3f955f1fc5cc.info b/Close Enough!/Library/metadata/c3/c3d5953bb1e2e47c69cb3f955f1fc5cc.info deleted file mode 100644 index 0570375..0000000 Binary files a/Close Enough!/Library/metadata/c3/c3d5953bb1e2e47c69cb3f955f1fc5cc.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/c4/c452c88a87f3d48ae945e7bcf1b4a6ba b/Close Enough!/Library/metadata/c4/c452c88a87f3d48ae945e7bcf1b4a6ba deleted file mode 100644 index becf665..0000000 Binary files a/Close Enough!/Library/metadata/c4/c452c88a87f3d48ae945e7bcf1b4a6ba and /dev/null differ diff --git a/Close Enough!/Library/metadata/c4/c452c88a87f3d48ae945e7bcf1b4a6ba.info b/Close Enough!/Library/metadata/c4/c452c88a87f3d48ae945e7bcf1b4a6ba.info deleted file mode 100644 index 98c13e0..0000000 Binary files a/Close Enough!/Library/metadata/c4/c452c88a87f3d48ae945e7bcf1b4a6ba.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/c4/c454f0066ef17b94daa5753983170042 b/Close Enough!/Library/metadata/c4/c454f0066ef17b94daa5753983170042 deleted file mode 100644 index 6f348cc..0000000 Binary files a/Close Enough!/Library/metadata/c4/c454f0066ef17b94daa5753983170042 and /dev/null differ diff --git a/Close Enough!/Library/metadata/c4/c454f0066ef17b94daa5753983170042.info b/Close Enough!/Library/metadata/c4/c454f0066ef17b94daa5753983170042.info deleted file mode 100644 index 5adf302..0000000 Binary files a/Close Enough!/Library/metadata/c4/c454f0066ef17b94daa5753983170042.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/c4/c454f0066ef17b94daa5753983170042.resource b/Close Enough!/Library/metadata/c4/c454f0066ef17b94daa5753983170042.resource deleted file mode 100644 index 034da91..0000000 Binary files a/Close Enough!/Library/metadata/c4/c454f0066ef17b94daa5753983170042.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/c4/c45f0afbf9669834d9bac06fb9f06fb7 b/Close Enough!/Library/metadata/c4/c45f0afbf9669834d9bac06fb9f06fb7 deleted file mode 100644 index 0001d10..0000000 Binary files a/Close Enough!/Library/metadata/c4/c45f0afbf9669834d9bac06fb9f06fb7 and /dev/null differ diff --git a/Close Enough!/Library/metadata/c4/c45f0afbf9669834d9bac06fb9f06fb7.info b/Close Enough!/Library/metadata/c4/c45f0afbf9669834d9bac06fb9f06fb7.info deleted file mode 100644 index 5f79612..0000000 Binary files a/Close Enough!/Library/metadata/c4/c45f0afbf9669834d9bac06fb9f06fb7.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/c4/c48e36868ea707e4197846967f784081 b/Close Enough!/Library/metadata/c4/c48e36868ea707e4197846967f784081 deleted file mode 100644 index 7f74537..0000000 Binary files a/Close Enough!/Library/metadata/c4/c48e36868ea707e4197846967f784081 and /dev/null differ diff --git a/Close Enough!/Library/metadata/c4/c48e36868ea707e4197846967f784081.info b/Close Enough!/Library/metadata/c4/c48e36868ea707e4197846967f784081.info deleted file mode 100644 index 0b46bbc..0000000 Binary files a/Close Enough!/Library/metadata/c4/c48e36868ea707e4197846967f784081.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/c4/c49efa834f9a1424097b1167c7a824bc b/Close Enough!/Library/metadata/c4/c49efa834f9a1424097b1167c7a824bc deleted file mode 100644 index dadb137..0000000 Binary files a/Close Enough!/Library/metadata/c4/c49efa834f9a1424097b1167c7a824bc and /dev/null differ diff --git a/Close Enough!/Library/metadata/c4/c49efa834f9a1424097b1167c7a824bc.info b/Close Enough!/Library/metadata/c4/c49efa834f9a1424097b1167c7a824bc.info deleted file mode 100644 index 4c61d77..0000000 Binary files a/Close Enough!/Library/metadata/c4/c49efa834f9a1424097b1167c7a824bc.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/c4/c49efa834f9a1424097b1167c7a824bc.resource b/Close Enough!/Library/metadata/c4/c49efa834f9a1424097b1167c7a824bc.resource deleted file mode 100644 index 6cc599a..0000000 Binary files a/Close Enough!/Library/metadata/c4/c49efa834f9a1424097b1167c7a824bc.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/c4/c4e7547bb51f28942b46097186c6ac18 b/Close Enough!/Library/metadata/c4/c4e7547bb51f28942b46097186c6ac18 deleted file mode 100644 index cd40c28..0000000 Binary files a/Close Enough!/Library/metadata/c4/c4e7547bb51f28942b46097186c6ac18 and /dev/null differ diff --git a/Close Enough!/Library/metadata/c4/c4e7547bb51f28942b46097186c6ac18.info b/Close Enough!/Library/metadata/c4/c4e7547bb51f28942b46097186c6ac18.info deleted file mode 100644 index a8334ce..0000000 Binary files a/Close Enough!/Library/metadata/c4/c4e7547bb51f28942b46097186c6ac18.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/c4/c4e7547bb51f28942b46097186c6ac18.resource b/Close Enough!/Library/metadata/c4/c4e7547bb51f28942b46097186c6ac18.resource deleted file mode 100644 index c1d734c..0000000 Binary files a/Close Enough!/Library/metadata/c4/c4e7547bb51f28942b46097186c6ac18.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/c5/c5ba7626a737840ff88a3bd84b100482 b/Close Enough!/Library/metadata/c5/c5ba7626a737840ff88a3bd84b100482 deleted file mode 100644 index 435bd59..0000000 Binary files a/Close Enough!/Library/metadata/c5/c5ba7626a737840ff88a3bd84b100482 and /dev/null differ diff --git a/Close Enough!/Library/metadata/c5/c5ba7626a737840ff88a3bd84b100482.info b/Close Enough!/Library/metadata/c5/c5ba7626a737840ff88a3bd84b100482.info deleted file mode 100644 index 71bf878..0000000 Binary files a/Close Enough!/Library/metadata/c5/c5ba7626a737840ff88a3bd84b100482.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/c7/c723e4bfef5bd4c45bf820945afe70a0 b/Close Enough!/Library/metadata/c7/c723e4bfef5bd4c45bf820945afe70a0 deleted file mode 100644 index 4efecd8..0000000 Binary files a/Close Enough!/Library/metadata/c7/c723e4bfef5bd4c45bf820945afe70a0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/c7/c723e4bfef5bd4c45bf820945afe70a0.info b/Close Enough!/Library/metadata/c7/c723e4bfef5bd4c45bf820945afe70a0.info deleted file mode 100644 index b0345ba..0000000 Binary files a/Close Enough!/Library/metadata/c7/c723e4bfef5bd4c45bf820945afe70a0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/c7/c768acbc9cf24d398488bb4c93b91288 b/Close Enough!/Library/metadata/c7/c768acbc9cf24d398488bb4c93b91288 deleted file mode 100644 index ec9603f..0000000 Binary files a/Close Enough!/Library/metadata/c7/c768acbc9cf24d398488bb4c93b91288 and /dev/null differ diff --git a/Close Enough!/Library/metadata/c7/c768acbc9cf24d398488bb4c93b91288.info b/Close Enough!/Library/metadata/c7/c768acbc9cf24d398488bb4c93b91288.info deleted file mode 100644 index c91c60c..0000000 Binary files a/Close Enough!/Library/metadata/c7/c768acbc9cf24d398488bb4c93b91288.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/c9/c99bfe4fc4e5c4dc3917c14075acd117 b/Close Enough!/Library/metadata/c9/c99bfe4fc4e5c4dc3917c14075acd117 deleted file mode 100644 index 0b87c33..0000000 Binary files a/Close Enough!/Library/metadata/c9/c99bfe4fc4e5c4dc3917c14075acd117 and /dev/null differ diff --git a/Close Enough!/Library/metadata/c9/c99bfe4fc4e5c4dc3917c14075acd117.info b/Close Enough!/Library/metadata/c9/c99bfe4fc4e5c4dc3917c14075acd117.info deleted file mode 100644 index 726508d..0000000 Binary files a/Close Enough!/Library/metadata/c9/c99bfe4fc4e5c4dc3917c14075acd117.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ca/cabe052beac0c264bb4b4da0f32c8e38 b/Close Enough!/Library/metadata/ca/cabe052beac0c264bb4b4da0f32c8e38 deleted file mode 100644 index 5aaf201..0000000 Binary files a/Close Enough!/Library/metadata/ca/cabe052beac0c264bb4b4da0f32c8e38 and /dev/null differ diff --git a/Close Enough!/Library/metadata/ca/cabe052beac0c264bb4b4da0f32c8e38.info b/Close Enough!/Library/metadata/ca/cabe052beac0c264bb4b4da0f32c8e38.info deleted file mode 100644 index 261a217..0000000 Binary files a/Close Enough!/Library/metadata/ca/cabe052beac0c264bb4b4da0f32c8e38.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ca/cacc4c15378924bb4919f56011985568 b/Close Enough!/Library/metadata/ca/cacc4c15378924bb4919f56011985568 deleted file mode 100644 index c19227a..0000000 Binary files a/Close Enough!/Library/metadata/ca/cacc4c15378924bb4919f56011985568 and /dev/null differ diff --git a/Close Enough!/Library/metadata/ca/cacc4c15378924bb4919f56011985568.info b/Close Enough!/Library/metadata/ca/cacc4c15378924bb4919f56011985568.info deleted file mode 100644 index 310ac2d..0000000 Binary files a/Close Enough!/Library/metadata/ca/cacc4c15378924bb4919f56011985568.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/cb/cbb4c5083fc4fef4eacc744d17b71659 b/Close Enough!/Library/metadata/cb/cbb4c5083fc4fef4eacc744d17b71659 deleted file mode 100644 index 608e389..0000000 Binary files a/Close Enough!/Library/metadata/cb/cbb4c5083fc4fef4eacc744d17b71659 and /dev/null differ diff --git a/Close Enough!/Library/metadata/cb/cbb4c5083fc4fef4eacc744d17b71659.info b/Close Enough!/Library/metadata/cb/cbb4c5083fc4fef4eacc744d17b71659.info deleted file mode 100644 index 55495cc..0000000 Binary files a/Close Enough!/Library/metadata/cb/cbb4c5083fc4fef4eacc744d17b71659.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/cb/cbb4c5083fc4fef4eacc744d17b71659.resource b/Close Enough!/Library/metadata/cb/cbb4c5083fc4fef4eacc744d17b71659.resource deleted file mode 100644 index 5233277..0000000 Binary files a/Close Enough!/Library/metadata/cb/cbb4c5083fc4fef4eacc744d17b71659.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/cb/cbb74a54ff84d6840982890024fb92bc b/Close Enough!/Library/metadata/cb/cbb74a54ff84d6840982890024fb92bc deleted file mode 100644 index c2a1eba..0000000 Binary files a/Close Enough!/Library/metadata/cb/cbb74a54ff84d6840982890024fb92bc and /dev/null differ diff --git a/Close Enough!/Library/metadata/cb/cbb74a54ff84d6840982890024fb92bc.info b/Close Enough!/Library/metadata/cb/cbb74a54ff84d6840982890024fb92bc.info deleted file mode 100644 index e39dc11..0000000 Binary files a/Close Enough!/Library/metadata/cb/cbb74a54ff84d6840982890024fb92bc.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/cc/cc1b50b5501f748da8bec762294d9136 b/Close Enough!/Library/metadata/cc/cc1b50b5501f748da8bec762294d9136 deleted file mode 100644 index 97452a6..0000000 Binary files a/Close Enough!/Library/metadata/cc/cc1b50b5501f748da8bec762294d9136 and /dev/null differ diff --git a/Close Enough!/Library/metadata/cc/cc1b50b5501f748da8bec762294d9136.info b/Close Enough!/Library/metadata/cc/cc1b50b5501f748da8bec762294d9136.info deleted file mode 100644 index 3e6e779..0000000 Binary files a/Close Enough!/Library/metadata/cc/cc1b50b5501f748da8bec762294d9136.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/cc/cc8ceb12a74534923ad4cc3ec6041dd0 b/Close Enough!/Library/metadata/cc/cc8ceb12a74534923ad4cc3ec6041dd0 deleted file mode 100644 index b506d9b..0000000 Binary files a/Close Enough!/Library/metadata/cc/cc8ceb12a74534923ad4cc3ec6041dd0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/cc/cc8ceb12a74534923ad4cc3ec6041dd0.info b/Close Enough!/Library/metadata/cc/cc8ceb12a74534923ad4cc3ec6041dd0.info deleted file mode 100644 index a49ae55..0000000 Binary files a/Close Enough!/Library/metadata/cc/cc8ceb12a74534923ad4cc3ec6041dd0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/cc/ccb58ed657934fa4dacaa6afdf48bffc b/Close Enough!/Library/metadata/cc/ccb58ed657934fa4dacaa6afdf48bffc deleted file mode 100644 index 451b461..0000000 Binary files a/Close Enough!/Library/metadata/cc/ccb58ed657934fa4dacaa6afdf48bffc and /dev/null differ diff --git a/Close Enough!/Library/metadata/cc/ccb58ed657934fa4dacaa6afdf48bffc.info b/Close Enough!/Library/metadata/cc/ccb58ed657934fa4dacaa6afdf48bffc.info deleted file mode 100644 index 0fbf315..0000000 Binary files a/Close Enough!/Library/metadata/cc/ccb58ed657934fa4dacaa6afdf48bffc.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/cd/cd465618491504cf9b0a0fcdf0cb71e0 b/Close Enough!/Library/metadata/cd/cd465618491504cf9b0a0fcdf0cb71e0 deleted file mode 100644 index 9f39b26..0000000 Binary files a/Close Enough!/Library/metadata/cd/cd465618491504cf9b0a0fcdf0cb71e0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/cd/cd465618491504cf9b0a0fcdf0cb71e0.info b/Close Enough!/Library/metadata/cd/cd465618491504cf9b0a0fcdf0cb71e0.info deleted file mode 100644 index e4767fd..0000000 Binary files a/Close Enough!/Library/metadata/cd/cd465618491504cf9b0a0fcdf0cb71e0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/cd/cdda132d9b7e29445b741b37fd39cc2c b/Close Enough!/Library/metadata/cd/cdda132d9b7e29445b741b37fd39cc2c deleted file mode 100644 index 86e9584..0000000 Binary files a/Close Enough!/Library/metadata/cd/cdda132d9b7e29445b741b37fd39cc2c and /dev/null differ diff --git a/Close Enough!/Library/metadata/cd/cdda132d9b7e29445b741b37fd39cc2c.info b/Close Enough!/Library/metadata/cd/cdda132d9b7e29445b741b37fd39cc2c.info deleted file mode 100644 index cc4e0fb..0000000 Binary files a/Close Enough!/Library/metadata/cd/cdda132d9b7e29445b741b37fd39cc2c.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/cd/cdda132d9b7e29445b741b37fd39cc2c.resource b/Close Enough!/Library/metadata/cd/cdda132d9b7e29445b741b37fd39cc2c.resource deleted file mode 100644 index e7ca4fb..0000000 Binary files a/Close Enough!/Library/metadata/cd/cdda132d9b7e29445b741b37fd39cc2c.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/ce/ce4395ccdb12cf62fca756358be1a892 b/Close Enough!/Library/metadata/ce/ce4395ccdb12cf62fca756358be1a892 deleted file mode 100644 index f759975..0000000 Binary files a/Close Enough!/Library/metadata/ce/ce4395ccdb12cf62fca756358be1a892 and /dev/null differ diff --git a/Close Enough!/Library/metadata/ce/ce4395ccdb12cf62fca756358be1a892.info b/Close Enough!/Library/metadata/ce/ce4395ccdb12cf62fca756358be1a892.info deleted file mode 100644 index 2a5bf6e..0000000 Binary files a/Close Enough!/Library/metadata/ce/ce4395ccdb12cf62fca756358be1a892.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ce/ce5b10823768f084d8ea501f7a551cdf b/Close Enough!/Library/metadata/ce/ce5b10823768f084d8ea501f7a551cdf deleted file mode 100644 index 4edadc5..0000000 Binary files a/Close Enough!/Library/metadata/ce/ce5b10823768f084d8ea501f7a551cdf and /dev/null differ diff --git a/Close Enough!/Library/metadata/ce/ce5b10823768f084d8ea501f7a551cdf.info b/Close Enough!/Library/metadata/ce/ce5b10823768f084d8ea501f7a551cdf.info deleted file mode 100644 index 9331944..0000000 Binary files a/Close Enough!/Library/metadata/ce/ce5b10823768f084d8ea501f7a551cdf.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ce/cee0ff8b0f7196e4984fc7a713fc96a5 b/Close Enough!/Library/metadata/ce/cee0ff8b0f7196e4984fc7a713fc96a5 deleted file mode 100644 index 75da331..0000000 Binary files a/Close Enough!/Library/metadata/ce/cee0ff8b0f7196e4984fc7a713fc96a5 and /dev/null differ diff --git a/Close Enough!/Library/metadata/ce/cee0ff8b0f7196e4984fc7a713fc96a5.info b/Close Enough!/Library/metadata/ce/cee0ff8b0f7196e4984fc7a713fc96a5.info deleted file mode 100644 index 66e02b2..0000000 Binary files a/Close Enough!/Library/metadata/ce/cee0ff8b0f7196e4984fc7a713fc96a5.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ce/cef6c88d3b293b24ca236bb128e247fd b/Close Enough!/Library/metadata/ce/cef6c88d3b293b24ca236bb128e247fd deleted file mode 100644 index b0eb585..0000000 Binary files a/Close Enough!/Library/metadata/ce/cef6c88d3b293b24ca236bb128e247fd and /dev/null differ diff --git a/Close Enough!/Library/metadata/ce/cef6c88d3b293b24ca236bb128e247fd.info b/Close Enough!/Library/metadata/ce/cef6c88d3b293b24ca236bb128e247fd.info deleted file mode 100644 index 49a2a13..0000000 Binary files a/Close Enough!/Library/metadata/ce/cef6c88d3b293b24ca236bb128e247fd.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/cf/cf1acff8cf98a440dba907e79fd30ebc b/Close Enough!/Library/metadata/cf/cf1acff8cf98a440dba907e79fd30ebc deleted file mode 100644 index ed09e42..0000000 Binary files a/Close Enough!/Library/metadata/cf/cf1acff8cf98a440dba907e79fd30ebc and /dev/null differ diff --git a/Close Enough!/Library/metadata/cf/cf1acff8cf98a440dba907e79fd30ebc.info b/Close Enough!/Library/metadata/cf/cf1acff8cf98a440dba907e79fd30ebc.info deleted file mode 100644 index 1cb8ecd..0000000 Binary files a/Close Enough!/Library/metadata/cf/cf1acff8cf98a440dba907e79fd30ebc.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/cf/cfad4f1c0bf57bf418bc72bbe094b836 b/Close Enough!/Library/metadata/cf/cfad4f1c0bf57bf418bc72bbe094b836 deleted file mode 100644 index e284c02..0000000 Binary files a/Close Enough!/Library/metadata/cf/cfad4f1c0bf57bf418bc72bbe094b836 and /dev/null differ diff --git a/Close Enough!/Library/metadata/cf/cfad4f1c0bf57bf418bc72bbe094b836.info b/Close Enough!/Library/metadata/cf/cfad4f1c0bf57bf418bc72bbe094b836.info deleted file mode 100644 index f268ace..0000000 Binary files a/Close Enough!/Library/metadata/cf/cfad4f1c0bf57bf418bc72bbe094b836.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/d0/d05b96cee66e14240838de167097537a b/Close Enough!/Library/metadata/d0/d05b96cee66e14240838de167097537a deleted file mode 100644 index 95d9b29..0000000 Binary files a/Close Enough!/Library/metadata/d0/d05b96cee66e14240838de167097537a and /dev/null differ diff --git a/Close Enough!/Library/metadata/d0/d05b96cee66e14240838de167097537a.info b/Close Enough!/Library/metadata/d0/d05b96cee66e14240838de167097537a.info deleted file mode 100644 index 91382f3..0000000 Binary files a/Close Enough!/Library/metadata/d0/d05b96cee66e14240838de167097537a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/d0/d0a7b95fb51944d9ba72fa9020a08e14.info b/Close Enough!/Library/metadata/d0/d0a7b95fb51944d9ba72fa9020a08e14.info deleted file mode 100644 index 15453c2..0000000 Binary files a/Close Enough!/Library/metadata/d0/d0a7b95fb51944d9ba72fa9020a08e14.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/d1/d1c1a2d988f5148fd9ab17b2460d271e b/Close Enough!/Library/metadata/d1/d1c1a2d988f5148fd9ab17b2460d271e deleted file mode 100644 index e253970..0000000 Binary files a/Close Enough!/Library/metadata/d1/d1c1a2d988f5148fd9ab17b2460d271e and /dev/null differ diff --git a/Close Enough!/Library/metadata/d1/d1c1a2d988f5148fd9ab17b2460d271e.info b/Close Enough!/Library/metadata/d1/d1c1a2d988f5148fd9ab17b2460d271e.info deleted file mode 100644 index 27a7abc..0000000 Binary files a/Close Enough!/Library/metadata/d1/d1c1a2d988f5148fd9ab17b2460d271e.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/d2/d210941435b25aa46bcf2b9db8bd4dbf b/Close Enough!/Library/metadata/d2/d210941435b25aa46bcf2b9db8bd4dbf deleted file mode 100644 index 0c39a63..0000000 Binary files a/Close Enough!/Library/metadata/d2/d210941435b25aa46bcf2b9db8bd4dbf and /dev/null differ diff --git a/Close Enough!/Library/metadata/d2/d210941435b25aa46bcf2b9db8bd4dbf.info b/Close Enough!/Library/metadata/d2/d210941435b25aa46bcf2b9db8bd4dbf.info deleted file mode 100644 index 9f8f4bc..0000000 Binary files a/Close Enough!/Library/metadata/d2/d210941435b25aa46bcf2b9db8bd4dbf.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/d2/d210941435b25aa46bcf2b9db8bd4dbf.resource b/Close Enough!/Library/metadata/d2/d210941435b25aa46bcf2b9db8bd4dbf.resource deleted file mode 100644 index a0b52d0..0000000 Binary files a/Close Enough!/Library/metadata/d2/d210941435b25aa46bcf2b9db8bd4dbf.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/d2/d2ecedef70c48de4589b7f640de824d8 b/Close Enough!/Library/metadata/d2/d2ecedef70c48de4589b7f640de824d8 deleted file mode 100644 index 1c9c2a8..0000000 Binary files a/Close Enough!/Library/metadata/d2/d2ecedef70c48de4589b7f640de824d8 and /dev/null differ diff --git a/Close Enough!/Library/metadata/d2/d2ecedef70c48de4589b7f640de824d8.info b/Close Enough!/Library/metadata/d2/d2ecedef70c48de4589b7f640de824d8.info deleted file mode 100644 index 16ae02c..0000000 Binary files a/Close Enough!/Library/metadata/d2/d2ecedef70c48de4589b7f640de824d8.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/d3/d3249830c27045b4382a18ed87c3c0ef b/Close Enough!/Library/metadata/d3/d3249830c27045b4382a18ed87c3c0ef deleted file mode 100644 index 6a17c74..0000000 Binary files a/Close Enough!/Library/metadata/d3/d3249830c27045b4382a18ed87c3c0ef and /dev/null differ diff --git a/Close Enough!/Library/metadata/d3/d3249830c27045b4382a18ed87c3c0ef.info b/Close Enough!/Library/metadata/d3/d3249830c27045b4382a18ed87c3c0ef.info deleted file mode 100644 index 90ec585..0000000 Binary files a/Close Enough!/Library/metadata/d3/d3249830c27045b4382a18ed87c3c0ef.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/d3/d33d54853fd0f48e0ac8a63ea91e6626 b/Close Enough!/Library/metadata/d3/d33d54853fd0f48e0ac8a63ea91e6626 deleted file mode 100644 index 5cf9310..0000000 Binary files a/Close Enough!/Library/metadata/d3/d33d54853fd0f48e0ac8a63ea91e6626 and /dev/null differ diff --git a/Close Enough!/Library/metadata/d3/d33d54853fd0f48e0ac8a63ea91e6626.info b/Close Enough!/Library/metadata/d3/d33d54853fd0f48e0ac8a63ea91e6626.info deleted file mode 100644 index df7e2b0..0000000 Binary files a/Close Enough!/Library/metadata/d3/d33d54853fd0f48e0ac8a63ea91e6626.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/d5/d5156c0b327b8dd45a725d337f49b61c b/Close Enough!/Library/metadata/d5/d5156c0b327b8dd45a725d337f49b61c deleted file mode 100644 index af20d79..0000000 Binary files a/Close Enough!/Library/metadata/d5/d5156c0b327b8dd45a725d337f49b61c and /dev/null differ diff --git a/Close Enough!/Library/metadata/d5/d5156c0b327b8dd45a725d337f49b61c.info b/Close Enough!/Library/metadata/d5/d5156c0b327b8dd45a725d337f49b61c.info deleted file mode 100644 index bfdf497..0000000 Binary files a/Close Enough!/Library/metadata/d5/d5156c0b327b8dd45a725d337f49b61c.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/d5/d5b3378743033a245877b28078a8396c b/Close Enough!/Library/metadata/d5/d5b3378743033a245877b28078a8396c deleted file mode 100644 index 3d8c7f4..0000000 Binary files a/Close Enough!/Library/metadata/d5/d5b3378743033a245877b28078a8396c and /dev/null differ diff --git a/Close Enough!/Library/metadata/d5/d5b3378743033a245877b28078a8396c.info b/Close Enough!/Library/metadata/d5/d5b3378743033a245877b28078a8396c.info deleted file mode 100644 index 8d92a35..0000000 Binary files a/Close Enough!/Library/metadata/d5/d5b3378743033a245877b28078a8396c.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/d5/d5b3378743033a245877b28078a8396c.resource b/Close Enough!/Library/metadata/d5/d5b3378743033a245877b28078a8396c.resource deleted file mode 100644 index bb45470..0000000 Binary files a/Close Enough!/Library/metadata/d5/d5b3378743033a245877b28078a8396c.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/d6/d607a67dc772b484da060e66a3d61a4e b/Close Enough!/Library/metadata/d6/d607a67dc772b484da060e66a3d61a4e deleted file mode 100644 index 6b2e19c..0000000 Binary files a/Close Enough!/Library/metadata/d6/d607a67dc772b484da060e66a3d61a4e and /dev/null differ diff --git a/Close Enough!/Library/metadata/d6/d607a67dc772b484da060e66a3d61a4e.info b/Close Enough!/Library/metadata/d6/d607a67dc772b484da060e66a3d61a4e.info deleted file mode 100644 index f94fd6d..0000000 Binary files a/Close Enough!/Library/metadata/d6/d607a67dc772b484da060e66a3d61a4e.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/d6/d67d06a0671255c40a5bbcfa241bf583 b/Close Enough!/Library/metadata/d6/d67d06a0671255c40a5bbcfa241bf583 deleted file mode 100644 index 23747ad..0000000 Binary files a/Close Enough!/Library/metadata/d6/d67d06a0671255c40a5bbcfa241bf583 and /dev/null differ diff --git a/Close Enough!/Library/metadata/d6/d67d06a0671255c40a5bbcfa241bf583.info b/Close Enough!/Library/metadata/d6/d67d06a0671255c40a5bbcfa241bf583.info deleted file mode 100644 index f15f03c..0000000 Binary files a/Close Enough!/Library/metadata/d6/d67d06a0671255c40a5bbcfa241bf583.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/d8/d8acc5e2315864045bf9137ca06f1880 b/Close Enough!/Library/metadata/d8/d8acc5e2315864045bf9137ca06f1880 deleted file mode 100644 index 9ab59e5..0000000 Binary files a/Close Enough!/Library/metadata/d8/d8acc5e2315864045bf9137ca06f1880 and /dev/null differ diff --git a/Close Enough!/Library/metadata/d8/d8acc5e2315864045bf9137ca06f1880.info b/Close Enough!/Library/metadata/d8/d8acc5e2315864045bf9137ca06f1880.info deleted file mode 100644 index 6719e12..0000000 Binary files a/Close Enough!/Library/metadata/d8/d8acc5e2315864045bf9137ca06f1880.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/d8/d8acc5e2315864045bf9137ca06f1880.resource b/Close Enough!/Library/metadata/d8/d8acc5e2315864045bf9137ca06f1880.resource deleted file mode 100644 index 95df989..0000000 Binary files a/Close Enough!/Library/metadata/d8/d8acc5e2315864045bf9137ca06f1880.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/d9/d91035c548f23744c9bfb107348ed1c0 b/Close Enough!/Library/metadata/d9/d91035c548f23744c9bfb107348ed1c0 deleted file mode 100644 index 8ff965c..0000000 Binary files a/Close Enough!/Library/metadata/d9/d91035c548f23744c9bfb107348ed1c0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/d9/d91035c548f23744c9bfb107348ed1c0.info b/Close Enough!/Library/metadata/d9/d91035c548f23744c9bfb107348ed1c0.info deleted file mode 100644 index f476560..0000000 Binary files a/Close Enough!/Library/metadata/d9/d91035c548f23744c9bfb107348ed1c0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/d9/d929147d9f78c487397abb40f2c257b0 b/Close Enough!/Library/metadata/d9/d929147d9f78c487397abb40f2c257b0 deleted file mode 100644 index 73d6a8f..0000000 Binary files a/Close Enough!/Library/metadata/d9/d929147d9f78c487397abb40f2c257b0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/d9/d929147d9f78c487397abb40f2c257b0.info b/Close Enough!/Library/metadata/d9/d929147d9f78c487397abb40f2c257b0.info deleted file mode 100644 index 8924459..0000000 Binary files a/Close Enough!/Library/metadata/d9/d929147d9f78c487397abb40f2c257b0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/d9/d92d1f7a51efe0a46bd18a4539dabdda b/Close Enough!/Library/metadata/d9/d92d1f7a51efe0a46bd18a4539dabdda deleted file mode 100644 index 3ac44b8..0000000 Binary files a/Close Enough!/Library/metadata/d9/d92d1f7a51efe0a46bd18a4539dabdda and /dev/null differ diff --git a/Close Enough!/Library/metadata/d9/d92d1f7a51efe0a46bd18a4539dabdda.info b/Close Enough!/Library/metadata/d9/d92d1f7a51efe0a46bd18a4539dabdda.info deleted file mode 100644 index 06ac46b..0000000 Binary files a/Close Enough!/Library/metadata/d9/d92d1f7a51efe0a46bd18a4539dabdda.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/da/da799260fedfd204c8ae2c6928a16111 b/Close Enough!/Library/metadata/da/da799260fedfd204c8ae2c6928a16111 deleted file mode 100644 index 9338dc4..0000000 Binary files a/Close Enough!/Library/metadata/da/da799260fedfd204c8ae2c6928a16111 and /dev/null differ diff --git a/Close Enough!/Library/metadata/da/da799260fedfd204c8ae2c6928a16111.info b/Close Enough!/Library/metadata/da/da799260fedfd204c8ae2c6928a16111.info deleted file mode 100644 index dbf03de..0000000 Binary files a/Close Enough!/Library/metadata/da/da799260fedfd204c8ae2c6928a16111.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/dc/dc443db3e92b4983b9738c1131f555cb b/Close Enough!/Library/metadata/dc/dc443db3e92b4983b9738c1131f555cb deleted file mode 100644 index 91f9efc..0000000 Binary files a/Close Enough!/Library/metadata/dc/dc443db3e92b4983b9738c1131f555cb and /dev/null differ diff --git a/Close Enough!/Library/metadata/dc/dc443db3e92b4983b9738c1131f555cb.info b/Close Enough!/Library/metadata/dc/dc443db3e92b4983b9738c1131f555cb.info deleted file mode 100644 index ef29fd6..0000000 Binary files a/Close Enough!/Library/metadata/dc/dc443db3e92b4983b9738c1131f555cb.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/dc/dca4989c20c874139bbbb1376be105b1 b/Close Enough!/Library/metadata/dc/dca4989c20c874139bbbb1376be105b1 deleted file mode 100644 index 1702e7b..0000000 Binary files a/Close Enough!/Library/metadata/dc/dca4989c20c874139bbbb1376be105b1 and /dev/null differ diff --git a/Close Enough!/Library/metadata/dc/dca4989c20c874139bbbb1376be105b1.info b/Close Enough!/Library/metadata/dc/dca4989c20c874139bbbb1376be105b1.info deleted file mode 100644 index 0f23266..0000000 Binary files a/Close Enough!/Library/metadata/dc/dca4989c20c874139bbbb1376be105b1.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/dc/dcb374f3f88f00244a0b747d7cb34918 b/Close Enough!/Library/metadata/dc/dcb374f3f88f00244a0b747d7cb34918 deleted file mode 100644 index aedfd74..0000000 Binary files a/Close Enough!/Library/metadata/dc/dcb374f3f88f00244a0b747d7cb34918 and /dev/null differ diff --git a/Close Enough!/Library/metadata/dc/dcb374f3f88f00244a0b747d7cb34918.info b/Close Enough!/Library/metadata/dc/dcb374f3f88f00244a0b747d7cb34918.info deleted file mode 100644 index 6306f87..0000000 Binary files a/Close Enough!/Library/metadata/dc/dcb374f3f88f00244a0b747d7cb34918.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/dc/dcb374f3f88f00244a0b747d7cb34918.resource b/Close Enough!/Library/metadata/dc/dcb374f3f88f00244a0b747d7cb34918.resource deleted file mode 100644 index 2497de5..0000000 Binary files a/Close Enough!/Library/metadata/dc/dcb374f3f88f00244a0b747d7cb34918.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/dc/dcc7f8d8c9f81b6428ed1c534ea289e6 b/Close Enough!/Library/metadata/dc/dcc7f8d8c9f81b6428ed1c534ea289e6 deleted file mode 100644 index 2110c4e..0000000 Binary files a/Close Enough!/Library/metadata/dc/dcc7f8d8c9f81b6428ed1c534ea289e6 and /dev/null differ diff --git a/Close Enough!/Library/metadata/dc/dcc7f8d8c9f81b6428ed1c534ea289e6.info b/Close Enough!/Library/metadata/dc/dcc7f8d8c9f81b6428ed1c534ea289e6.info deleted file mode 100644 index 4102c24..0000000 Binary files a/Close Enough!/Library/metadata/dc/dcc7f8d8c9f81b6428ed1c534ea289e6.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/dc/dce91326f102345f3ba2f0987c0679c2 b/Close Enough!/Library/metadata/dc/dce91326f102345f3ba2f0987c0679c2 deleted file mode 100644 index 20e61a3..0000000 Binary files a/Close Enough!/Library/metadata/dc/dce91326f102345f3ba2f0987c0679c2 and /dev/null differ diff --git a/Close Enough!/Library/metadata/dc/dce91326f102345f3ba2f0987c0679c2.info b/Close Enough!/Library/metadata/dc/dce91326f102345f3ba2f0987c0679c2.info deleted file mode 100644 index 5c11764..0000000 Binary files a/Close Enough!/Library/metadata/dc/dce91326f102345f3ba2f0987c0679c2.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/dc/dced8f6ea9f964e8e8e61574ea889d21 b/Close Enough!/Library/metadata/dc/dced8f6ea9f964e8e8e61574ea889d21 deleted file mode 100644 index f0a1f02..0000000 Binary files a/Close Enough!/Library/metadata/dc/dced8f6ea9f964e8e8e61574ea889d21 and /dev/null differ diff --git a/Close Enough!/Library/metadata/dc/dced8f6ea9f964e8e8e61574ea889d21.info b/Close Enough!/Library/metadata/dc/dced8f6ea9f964e8e8e61574ea889d21.info deleted file mode 100644 index e717750..0000000 Binary files a/Close Enough!/Library/metadata/dc/dced8f6ea9f964e8e8e61574ea889d21.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/dd/dd3fe4d01807b864c8e5ebe8d028cea9 b/Close Enough!/Library/metadata/dd/dd3fe4d01807b864c8e5ebe8d028cea9 deleted file mode 100644 index 154160f..0000000 Binary files a/Close Enough!/Library/metadata/dd/dd3fe4d01807b864c8e5ebe8d028cea9 and /dev/null differ diff --git a/Close Enough!/Library/metadata/dd/dd3fe4d01807b864c8e5ebe8d028cea9.info b/Close Enough!/Library/metadata/dd/dd3fe4d01807b864c8e5ebe8d028cea9.info deleted file mode 100644 index f65508a..0000000 Binary files a/Close Enough!/Library/metadata/dd/dd3fe4d01807b864c8e5ebe8d028cea9.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/dd/dda7aafb2d8030547aa1fef2bd554ed9 b/Close Enough!/Library/metadata/dd/dda7aafb2d8030547aa1fef2bd554ed9 deleted file mode 100644 index e97cbc2..0000000 Binary files a/Close Enough!/Library/metadata/dd/dda7aafb2d8030547aa1fef2bd554ed9 and /dev/null differ diff --git a/Close Enough!/Library/metadata/dd/dda7aafb2d8030547aa1fef2bd554ed9.info b/Close Enough!/Library/metadata/dd/dda7aafb2d8030547aa1fef2bd554ed9.info deleted file mode 100644 index a069831..0000000 Binary files a/Close Enough!/Library/metadata/dd/dda7aafb2d8030547aa1fef2bd554ed9.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/dd/dda7aafb2d8030547aa1fef2bd554ed9.resource b/Close Enough!/Library/metadata/dd/dda7aafb2d8030547aa1fef2bd554ed9.resource deleted file mode 100644 index 82b1402..0000000 Binary files a/Close Enough!/Library/metadata/dd/dda7aafb2d8030547aa1fef2bd554ed9.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/df/df36c2430df5b0245bb86e9420c56d6f b/Close Enough!/Library/metadata/df/df36c2430df5b0245bb86e9420c56d6f deleted file mode 100644 index 7d1adf5..0000000 Binary files a/Close Enough!/Library/metadata/df/df36c2430df5b0245bb86e9420c56d6f and /dev/null differ diff --git a/Close Enough!/Library/metadata/df/df36c2430df5b0245bb86e9420c56d6f.info b/Close Enough!/Library/metadata/df/df36c2430df5b0245bb86e9420c56d6f.info deleted file mode 100644 index 8c84849..0000000 Binary files a/Close Enough!/Library/metadata/df/df36c2430df5b0245bb86e9420c56d6f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/df/df42be521ed11a0468b9ab121d4189af b/Close Enough!/Library/metadata/df/df42be521ed11a0468b9ab121d4189af deleted file mode 100644 index 0bd3906..0000000 Binary files a/Close Enough!/Library/metadata/df/df42be521ed11a0468b9ab121d4189af and /dev/null differ diff --git a/Close Enough!/Library/metadata/df/df42be521ed11a0468b9ab121d4189af.info b/Close Enough!/Library/metadata/df/df42be521ed11a0468b9ab121d4189af.info deleted file mode 100644 index f131994..0000000 Binary files a/Close Enough!/Library/metadata/df/df42be521ed11a0468b9ab121d4189af.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/e0/e056dfa4b1720f148ab8e632dca353fb b/Close Enough!/Library/metadata/e0/e056dfa4b1720f148ab8e632dca353fb deleted file mode 100644 index fa45929..0000000 Binary files a/Close Enough!/Library/metadata/e0/e056dfa4b1720f148ab8e632dca353fb and /dev/null differ diff --git a/Close Enough!/Library/metadata/e0/e056dfa4b1720f148ab8e632dca353fb.info b/Close Enough!/Library/metadata/e0/e056dfa4b1720f148ab8e632dca353fb.info deleted file mode 100644 index 50b6610..0000000 Binary files a/Close Enough!/Library/metadata/e0/e056dfa4b1720f148ab8e632dca353fb.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/e0/e056dfa4b1720f148ab8e632dca353fb.resource b/Close Enough!/Library/metadata/e0/e056dfa4b1720f148ab8e632dca353fb.resource deleted file mode 100644 index 8cf9a23..0000000 Binary files a/Close Enough!/Library/metadata/e0/e056dfa4b1720f148ab8e632dca353fb.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/e1/e1007cd261c84053beb0c3537782908d b/Close Enough!/Library/metadata/e1/e1007cd261c84053beb0c3537782908d deleted file mode 100644 index 9053325..0000000 Binary files a/Close Enough!/Library/metadata/e1/e1007cd261c84053beb0c3537782908d and /dev/null differ diff --git a/Close Enough!/Library/metadata/e1/e1007cd261c84053beb0c3537782908d.info b/Close Enough!/Library/metadata/e1/e1007cd261c84053beb0c3537782908d.info deleted file mode 100644 index 6ab7bda..0000000 Binary files a/Close Enough!/Library/metadata/e1/e1007cd261c84053beb0c3537782908d.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/e1/e1ae9de1b8dd57e41918d7f8b76a310d b/Close Enough!/Library/metadata/e1/e1ae9de1b8dd57e41918d7f8b76a310d deleted file mode 100644 index 43a7403..0000000 Binary files a/Close Enough!/Library/metadata/e1/e1ae9de1b8dd57e41918d7f8b76a310d and /dev/null differ diff --git a/Close Enough!/Library/metadata/e1/e1ae9de1b8dd57e41918d7f8b76a310d.info b/Close Enough!/Library/metadata/e1/e1ae9de1b8dd57e41918d7f8b76a310d.info deleted file mode 100644 index 074a10a..0000000 Binary files a/Close Enough!/Library/metadata/e1/e1ae9de1b8dd57e41918d7f8b76a310d.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/e2/e2acccebe54177840ac87b756601bad6 b/Close Enough!/Library/metadata/e2/e2acccebe54177840ac87b756601bad6 deleted file mode 100644 index d662967..0000000 Binary files a/Close Enough!/Library/metadata/e2/e2acccebe54177840ac87b756601bad6 and /dev/null differ diff --git a/Close Enough!/Library/metadata/e2/e2acccebe54177840ac87b756601bad6.info b/Close Enough!/Library/metadata/e2/e2acccebe54177840ac87b756601bad6.info deleted file mode 100644 index 1debb33..0000000 Binary files a/Close Enough!/Library/metadata/e2/e2acccebe54177840ac87b756601bad6.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/e2/e2acccebe54177840ac87b756601bad6.resource b/Close Enough!/Library/metadata/e2/e2acccebe54177840ac87b756601bad6.resource deleted file mode 100644 index c5a821a..0000000 Binary files a/Close Enough!/Library/metadata/e2/e2acccebe54177840ac87b756601bad6.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/e3/e3c4daf6d2a17a74f8c69b2b84e1187a b/Close Enough!/Library/metadata/e3/e3c4daf6d2a17a74f8c69b2b84e1187a deleted file mode 100644 index 950f71a..0000000 Binary files a/Close Enough!/Library/metadata/e3/e3c4daf6d2a17a74f8c69b2b84e1187a and /dev/null differ diff --git a/Close Enough!/Library/metadata/e3/e3c4daf6d2a17a74f8c69b2b84e1187a.info b/Close Enough!/Library/metadata/e3/e3c4daf6d2a17a74f8c69b2b84e1187a.info deleted file mode 100644 index 2071bbe..0000000 Binary files a/Close Enough!/Library/metadata/e3/e3c4daf6d2a17a74f8c69b2b84e1187a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/e3/e3d281454be7a494e9a0e63807f6eb4f b/Close Enough!/Library/metadata/e3/e3d281454be7a494e9a0e63807f6eb4f deleted file mode 100644 index 61847a3..0000000 Binary files a/Close Enough!/Library/metadata/e3/e3d281454be7a494e9a0e63807f6eb4f and /dev/null differ diff --git a/Close Enough!/Library/metadata/e3/e3d281454be7a494e9a0e63807f6eb4f.info b/Close Enough!/Library/metadata/e3/e3d281454be7a494e9a0e63807f6eb4f.info deleted file mode 100644 index de47a29..0000000 Binary files a/Close Enough!/Library/metadata/e3/e3d281454be7a494e9a0e63807f6eb4f.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/e3/e3d281454be7a494e9a0e63807f6eb4f.resource b/Close Enough!/Library/metadata/e3/e3d281454be7a494e9a0e63807f6eb4f.resource deleted file mode 100644 index 000948c..0000000 Binary files a/Close Enough!/Library/metadata/e3/e3d281454be7a494e9a0e63807f6eb4f.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/e4/e479ee01be8c5f1449c23a56feeb38d8 b/Close Enough!/Library/metadata/e4/e479ee01be8c5f1449c23a56feeb38d8 deleted file mode 100644 index 0fdd616..0000000 Binary files a/Close Enough!/Library/metadata/e4/e479ee01be8c5f1449c23a56feeb38d8 and /dev/null differ diff --git a/Close Enough!/Library/metadata/e4/e479ee01be8c5f1449c23a56feeb38d8.info b/Close Enough!/Library/metadata/e4/e479ee01be8c5f1449c23a56feeb38d8.info deleted file mode 100644 index 7341b39..0000000 Binary files a/Close Enough!/Library/metadata/e4/e479ee01be8c5f1449c23a56feeb38d8.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/e4/e47d9bde4d97b491ea04b20327dd0f50 b/Close Enough!/Library/metadata/e4/e47d9bde4d97b491ea04b20327dd0f50 deleted file mode 100644 index ae507f7..0000000 Binary files a/Close Enough!/Library/metadata/e4/e47d9bde4d97b491ea04b20327dd0f50 and /dev/null differ diff --git a/Close Enough!/Library/metadata/e4/e47d9bde4d97b491ea04b20327dd0f50.info b/Close Enough!/Library/metadata/e4/e47d9bde4d97b491ea04b20327dd0f50.info deleted file mode 100644 index 6a99d4f..0000000 Binary files a/Close Enough!/Library/metadata/e4/e47d9bde4d97b491ea04b20327dd0f50.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/e4/e48a9f9909298504cbf59fad1e442fdb b/Close Enough!/Library/metadata/e4/e48a9f9909298504cbf59fad1e442fdb deleted file mode 100644 index 2010291..0000000 Binary files a/Close Enough!/Library/metadata/e4/e48a9f9909298504cbf59fad1e442fdb and /dev/null differ diff --git a/Close Enough!/Library/metadata/e4/e48a9f9909298504cbf59fad1e442fdb.info b/Close Enough!/Library/metadata/e4/e48a9f9909298504cbf59fad1e442fdb.info deleted file mode 100644 index 5975abf..0000000 Binary files a/Close Enough!/Library/metadata/e4/e48a9f9909298504cbf59fad1e442fdb.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/e4/e4c217dd3241a4071839efb47f27df36 b/Close Enough!/Library/metadata/e4/e4c217dd3241a4071839efb47f27df36 deleted file mode 100644 index e072edb..0000000 Binary files a/Close Enough!/Library/metadata/e4/e4c217dd3241a4071839efb47f27df36 and /dev/null differ diff --git a/Close Enough!/Library/metadata/e4/e4c217dd3241a4071839efb47f27df36.info b/Close Enough!/Library/metadata/e4/e4c217dd3241a4071839efb47f27df36.info deleted file mode 100644 index fcf6274..0000000 Binary files a/Close Enough!/Library/metadata/e4/e4c217dd3241a4071839efb47f27df36.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/e4/e4f4cf1b9b434137a499903a7a1d651a b/Close Enough!/Library/metadata/e4/e4f4cf1b9b434137a499903a7a1d651a deleted file mode 100644 index ac4d8ad..0000000 Binary files a/Close Enough!/Library/metadata/e4/e4f4cf1b9b434137a499903a7a1d651a and /dev/null differ diff --git a/Close Enough!/Library/metadata/e4/e4f4cf1b9b434137a499903a7a1d651a.info b/Close Enough!/Library/metadata/e4/e4f4cf1b9b434137a499903a7a1d651a.info deleted file mode 100644 index 8569c4b..0000000 Binary files a/Close Enough!/Library/metadata/e4/e4f4cf1b9b434137a499903a7a1d651a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/e5/e56000d9fe63f894c87ca3f6ca69a7d1 b/Close Enough!/Library/metadata/e5/e56000d9fe63f894c87ca3f6ca69a7d1 deleted file mode 100644 index 4d8a796..0000000 Binary files a/Close Enough!/Library/metadata/e5/e56000d9fe63f894c87ca3f6ca69a7d1 and /dev/null differ diff --git a/Close Enough!/Library/metadata/e5/e56000d9fe63f894c87ca3f6ca69a7d1.info b/Close Enough!/Library/metadata/e5/e56000d9fe63f894c87ca3f6ca69a7d1.info deleted file mode 100644 index 77b03b2..0000000 Binary files a/Close Enough!/Library/metadata/e5/e56000d9fe63f894c87ca3f6ca69a7d1.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/e5/e5d3f9ab70a0b4f4ba8901437d9953fe b/Close Enough!/Library/metadata/e5/e5d3f9ab70a0b4f4ba8901437d9953fe deleted file mode 100644 index 4ee5c7a..0000000 Binary files a/Close Enough!/Library/metadata/e5/e5d3f9ab70a0b4f4ba8901437d9953fe and /dev/null differ diff --git a/Close Enough!/Library/metadata/e5/e5d3f9ab70a0b4f4ba8901437d9953fe.info b/Close Enough!/Library/metadata/e5/e5d3f9ab70a0b4f4ba8901437d9953fe.info deleted file mode 100644 index 668a883..0000000 Binary files a/Close Enough!/Library/metadata/e5/e5d3f9ab70a0b4f4ba8901437d9953fe.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/e6/e66249d5267b56c4a8f6f976c79b5900 b/Close Enough!/Library/metadata/e6/e66249d5267b56c4a8f6f976c79b5900 deleted file mode 100644 index 3735e27..0000000 Binary files a/Close Enough!/Library/metadata/e6/e66249d5267b56c4a8f6f976c79b5900 and /dev/null differ diff --git a/Close Enough!/Library/metadata/e6/e66249d5267b56c4a8f6f976c79b5900.info b/Close Enough!/Library/metadata/e6/e66249d5267b56c4a8f6f976c79b5900.info deleted file mode 100644 index 9a3565d..0000000 Binary files a/Close Enough!/Library/metadata/e6/e66249d5267b56c4a8f6f976c79b5900.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/e8/e81df6e094ca4478bb15a1016b03539e b/Close Enough!/Library/metadata/e8/e81df6e094ca4478bb15a1016b03539e deleted file mode 100644 index 3869412..0000000 Binary files a/Close Enough!/Library/metadata/e8/e81df6e094ca4478bb15a1016b03539e and /dev/null differ diff --git a/Close Enough!/Library/metadata/e8/e81df6e094ca4478bb15a1016b03539e.info b/Close Enough!/Library/metadata/e8/e81df6e094ca4478bb15a1016b03539e.info deleted file mode 100644 index ef05523..0000000 Binary files a/Close Enough!/Library/metadata/e8/e81df6e094ca4478bb15a1016b03539e.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/e8/e8c73b9efb84a8f4ba3f63e0a1106255 b/Close Enough!/Library/metadata/e8/e8c73b9efb84a8f4ba3f63e0a1106255 deleted file mode 100644 index bf10c55..0000000 Binary files a/Close Enough!/Library/metadata/e8/e8c73b9efb84a8f4ba3f63e0a1106255 and /dev/null differ diff --git a/Close Enough!/Library/metadata/e8/e8c73b9efb84a8f4ba3f63e0a1106255.info b/Close Enough!/Library/metadata/e8/e8c73b9efb84a8f4ba3f63e0a1106255.info deleted file mode 100644 index b47e314..0000000 Binary files a/Close Enough!/Library/metadata/e8/e8c73b9efb84a8f4ba3f63e0a1106255.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ea/ea1a353ad7fa01940ae37eca7f03bfbb b/Close Enough!/Library/metadata/ea/ea1a353ad7fa01940ae37eca7f03bfbb deleted file mode 100644 index 16abbc3..0000000 Binary files a/Close Enough!/Library/metadata/ea/ea1a353ad7fa01940ae37eca7f03bfbb and /dev/null differ diff --git a/Close Enough!/Library/metadata/ea/ea1a353ad7fa01940ae37eca7f03bfbb.info b/Close Enough!/Library/metadata/ea/ea1a353ad7fa01940ae37eca7f03bfbb.info deleted file mode 100644 index d533352..0000000 Binary files a/Close Enough!/Library/metadata/ea/ea1a353ad7fa01940ae37eca7f03bfbb.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ea/ea4abcc8b33d49846a985cc9f8ad5824 b/Close Enough!/Library/metadata/ea/ea4abcc8b33d49846a985cc9f8ad5824 deleted file mode 100644 index c921e55..0000000 Binary files a/Close Enough!/Library/metadata/ea/ea4abcc8b33d49846a985cc9f8ad5824 and /dev/null differ diff --git a/Close Enough!/Library/metadata/ea/ea4abcc8b33d49846a985cc9f8ad5824.info b/Close Enough!/Library/metadata/ea/ea4abcc8b33d49846a985cc9f8ad5824.info deleted file mode 100644 index 808a624..0000000 Binary files a/Close Enough!/Library/metadata/ea/ea4abcc8b33d49846a985cc9f8ad5824.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ea/ea4abcc8b33d49846a985cc9f8ad5824.resource b/Close Enough!/Library/metadata/ea/ea4abcc8b33d49846a985cc9f8ad5824.resource deleted file mode 100644 index 5bb57f1..0000000 Binary files a/Close Enough!/Library/metadata/ea/ea4abcc8b33d49846a985cc9f8ad5824.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/ea/ead147da21254ff9a0a936bdd75e1680 b/Close Enough!/Library/metadata/ea/ead147da21254ff9a0a936bdd75e1680 deleted file mode 100644 index f19a0ae..0000000 Binary files a/Close Enough!/Library/metadata/ea/ead147da21254ff9a0a936bdd75e1680 and /dev/null differ diff --git a/Close Enough!/Library/metadata/ea/ead147da21254ff9a0a936bdd75e1680.info b/Close Enough!/Library/metadata/ea/ead147da21254ff9a0a936bdd75e1680.info deleted file mode 100644 index 94bc2ff..0000000 Binary files a/Close Enough!/Library/metadata/ea/ead147da21254ff9a0a936bdd75e1680.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/eb/eb5828203f3400a4b96753d2bf40c876 b/Close Enough!/Library/metadata/eb/eb5828203f3400a4b96753d2bf40c876 deleted file mode 100644 index d5f7ed6..0000000 Binary files a/Close Enough!/Library/metadata/eb/eb5828203f3400a4b96753d2bf40c876 and /dev/null differ diff --git a/Close Enough!/Library/metadata/eb/eb5828203f3400a4b96753d2bf40c876.info b/Close Enough!/Library/metadata/eb/eb5828203f3400a4b96753d2bf40c876.info deleted file mode 100644 index 331a561..0000000 Binary files a/Close Enough!/Library/metadata/eb/eb5828203f3400a4b96753d2bf40c876.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/eb/ebe69bfcd108be84ca06a5e23d9c8516 b/Close Enough!/Library/metadata/eb/ebe69bfcd108be84ca06a5e23d9c8516 deleted file mode 100644 index 8edad92..0000000 Binary files a/Close Enough!/Library/metadata/eb/ebe69bfcd108be84ca06a5e23d9c8516 and /dev/null differ diff --git a/Close Enough!/Library/metadata/eb/ebe69bfcd108be84ca06a5e23d9c8516.info b/Close Enough!/Library/metadata/eb/ebe69bfcd108be84ca06a5e23d9c8516.info deleted file mode 100644 index 5892d03..0000000 Binary files a/Close Enough!/Library/metadata/eb/ebe69bfcd108be84ca06a5e23d9c8516.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ec/ecf9a9deb9896374dad7f408c1dbd172 b/Close Enough!/Library/metadata/ec/ecf9a9deb9896374dad7f408c1dbd172 deleted file mode 100644 index e407e82..0000000 Binary files a/Close Enough!/Library/metadata/ec/ecf9a9deb9896374dad7f408c1dbd172 and /dev/null differ diff --git a/Close Enough!/Library/metadata/ec/ecf9a9deb9896374dad7f408c1dbd172.info b/Close Enough!/Library/metadata/ec/ecf9a9deb9896374dad7f408c1dbd172.info deleted file mode 100644 index 52af349..0000000 Binary files a/Close Enough!/Library/metadata/ec/ecf9a9deb9896374dad7f408c1dbd172.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ec/ecf9a9deb9896374dad7f408c1dbd172.resource b/Close Enough!/Library/metadata/ec/ecf9a9deb9896374dad7f408c1dbd172.resource deleted file mode 100644 index 83d8430..0000000 Binary files a/Close Enough!/Library/metadata/ec/ecf9a9deb9896374dad7f408c1dbd172.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/ed/ed5a53f9cee4146148704b66c1a82539 b/Close Enough!/Library/metadata/ed/ed5a53f9cee4146148704b66c1a82539 deleted file mode 100644 index 6c8a414..0000000 Binary files a/Close Enough!/Library/metadata/ed/ed5a53f9cee4146148704b66c1a82539 and /dev/null differ diff --git a/Close Enough!/Library/metadata/ed/ed5a53f9cee4146148704b66c1a82539.info b/Close Enough!/Library/metadata/ed/ed5a53f9cee4146148704b66c1a82539.info deleted file mode 100644 index 403dbd0..0000000 Binary files a/Close Enough!/Library/metadata/ed/ed5a53f9cee4146148704b66c1a82539.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ed/ed7343f30e3843b3afda8f8b02669cea b/Close Enough!/Library/metadata/ed/ed7343f30e3843b3afda8f8b02669cea deleted file mode 100644 index cee30cc..0000000 Binary files a/Close Enough!/Library/metadata/ed/ed7343f30e3843b3afda8f8b02669cea and /dev/null differ diff --git a/Close Enough!/Library/metadata/ed/ed7343f30e3843b3afda8f8b02669cea.info b/Close Enough!/Library/metadata/ed/ed7343f30e3843b3afda8f8b02669cea.info deleted file mode 100644 index 19348d0..0000000 Binary files a/Close Enough!/Library/metadata/ed/ed7343f30e3843b3afda8f8b02669cea.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ee/ee1aad71d52134b1aa59daa42e5b13be b/Close Enough!/Library/metadata/ee/ee1aad71d52134b1aa59daa42e5b13be deleted file mode 100644 index 07348de..0000000 Binary files a/Close Enough!/Library/metadata/ee/ee1aad71d52134b1aa59daa42e5b13be and /dev/null differ diff --git a/Close Enough!/Library/metadata/ee/ee1aad71d52134b1aa59daa42e5b13be.info b/Close Enough!/Library/metadata/ee/ee1aad71d52134b1aa59daa42e5b13be.info deleted file mode 100644 index 541bac2..0000000 Binary files a/Close Enough!/Library/metadata/ee/ee1aad71d52134b1aa59daa42e5b13be.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ee/ee3f0b52fe10f194fb33c1423defa973 b/Close Enough!/Library/metadata/ee/ee3f0b52fe10f194fb33c1423defa973 deleted file mode 100644 index 23cf997..0000000 Binary files a/Close Enough!/Library/metadata/ee/ee3f0b52fe10f194fb33c1423defa973 and /dev/null differ diff --git a/Close Enough!/Library/metadata/ee/ee3f0b52fe10f194fb33c1423defa973.info b/Close Enough!/Library/metadata/ee/ee3f0b52fe10f194fb33c1423defa973.info deleted file mode 100644 index 7908d32..0000000 Binary files a/Close Enough!/Library/metadata/ee/ee3f0b52fe10f194fb33c1423defa973.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ee/eeed6954b3c264ca0b28a92aa6289bf0 b/Close Enough!/Library/metadata/ee/eeed6954b3c264ca0b28a92aa6289bf0 deleted file mode 100644 index 64b0e5f..0000000 Binary files a/Close Enough!/Library/metadata/ee/eeed6954b3c264ca0b28a92aa6289bf0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/ee/eeed6954b3c264ca0b28a92aa6289bf0.info b/Close Enough!/Library/metadata/ee/eeed6954b3c264ca0b28a92aa6289bf0.info deleted file mode 100644 index 4d381dd..0000000 Binary files a/Close Enough!/Library/metadata/ee/eeed6954b3c264ca0b28a92aa6289bf0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ef/ef656a92b5be2d043b5bf03b4113af23 b/Close Enough!/Library/metadata/ef/ef656a92b5be2d043b5bf03b4113af23 deleted file mode 100644 index 3fc39f1..0000000 Binary files a/Close Enough!/Library/metadata/ef/ef656a92b5be2d043b5bf03b4113af23 and /dev/null differ diff --git a/Close Enough!/Library/metadata/ef/ef656a92b5be2d043b5bf03b4113af23.info b/Close Enough!/Library/metadata/ef/ef656a92b5be2d043b5bf03b4113af23.info deleted file mode 100644 index 23df84a..0000000 Binary files a/Close Enough!/Library/metadata/ef/ef656a92b5be2d043b5bf03b4113af23.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ef/efeb9bb15a82532439a6b23b0ada6e62 b/Close Enough!/Library/metadata/ef/efeb9bb15a82532439a6b23b0ada6e62 deleted file mode 100644 index 4dd4b93..0000000 Binary files a/Close Enough!/Library/metadata/ef/efeb9bb15a82532439a6b23b0ada6e62 and /dev/null differ diff --git a/Close Enough!/Library/metadata/ef/efeb9bb15a82532439a6b23b0ada6e62.info b/Close Enough!/Library/metadata/ef/efeb9bb15a82532439a6b23b0ada6e62.info deleted file mode 100644 index c3f8c4f..0000000 Binary files a/Close Enough!/Library/metadata/ef/efeb9bb15a82532439a6b23b0ada6e62.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f1/f1045c695c5bf4fb7b8509687bc60fc0 b/Close Enough!/Library/metadata/f1/f1045c695c5bf4fb7b8509687bc60fc0 deleted file mode 100644 index 0c43e27..0000000 Binary files a/Close Enough!/Library/metadata/f1/f1045c695c5bf4fb7b8509687bc60fc0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/f1/f1045c695c5bf4fb7b8509687bc60fc0.info b/Close Enough!/Library/metadata/f1/f1045c695c5bf4fb7b8509687bc60fc0.info deleted file mode 100644 index edec865..0000000 Binary files a/Close Enough!/Library/metadata/f1/f1045c695c5bf4fb7b8509687bc60fc0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f1/f15fd70c0be012c478e63187edd763cc b/Close Enough!/Library/metadata/f1/f15fd70c0be012c478e63187edd763cc deleted file mode 100644 index e47e86b..0000000 Binary files a/Close Enough!/Library/metadata/f1/f15fd70c0be012c478e63187edd763cc and /dev/null differ diff --git a/Close Enough!/Library/metadata/f1/f15fd70c0be012c478e63187edd763cc.info b/Close Enough!/Library/metadata/f1/f15fd70c0be012c478e63187edd763cc.info deleted file mode 100644 index 7e72c94..0000000 Binary files a/Close Enough!/Library/metadata/f1/f15fd70c0be012c478e63187edd763cc.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f1/f15fd70c0be012c478e63187edd763cc.resource b/Close Enough!/Library/metadata/f1/f15fd70c0be012c478e63187edd763cc.resource deleted file mode 100644 index cbe1a4b..0000000 Binary files a/Close Enough!/Library/metadata/f1/f15fd70c0be012c478e63187edd763cc.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/f1/f1642e083c2c6584587ba5e1d422fae0 b/Close Enough!/Library/metadata/f1/f1642e083c2c6584587ba5e1d422fae0 deleted file mode 100644 index 8fa46ab..0000000 Binary files a/Close Enough!/Library/metadata/f1/f1642e083c2c6584587ba5e1d422fae0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/f1/f1642e083c2c6584587ba5e1d422fae0.info b/Close Enough!/Library/metadata/f1/f1642e083c2c6584587ba5e1d422fae0.info deleted file mode 100644 index cd8a38e..0000000 Binary files a/Close Enough!/Library/metadata/f1/f1642e083c2c6584587ba5e1d422fae0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f1/f1642e083c2c6584587ba5e1d422fae0.resource b/Close Enough!/Library/metadata/f1/f1642e083c2c6584587ba5e1d422fae0.resource deleted file mode 100644 index 2e56604..0000000 Binary files a/Close Enough!/Library/metadata/f1/f1642e083c2c6584587ba5e1d422fae0.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/f1/f180dd0ee39c24040aba47b5fa83c006 b/Close Enough!/Library/metadata/f1/f180dd0ee39c24040aba47b5fa83c006 deleted file mode 100644 index 7314cbe..0000000 Binary files a/Close Enough!/Library/metadata/f1/f180dd0ee39c24040aba47b5fa83c006 and /dev/null differ diff --git a/Close Enough!/Library/metadata/f1/f180dd0ee39c24040aba47b5fa83c006.info b/Close Enough!/Library/metadata/f1/f180dd0ee39c24040aba47b5fa83c006.info deleted file mode 100644 index d65a973..0000000 Binary files a/Close Enough!/Library/metadata/f1/f180dd0ee39c24040aba47b5fa83c006.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f1/f180dd0ee39c24040aba47b5fa83c006.resource b/Close Enough!/Library/metadata/f1/f180dd0ee39c24040aba47b5fa83c006.resource deleted file mode 100644 index e2d0fb3..0000000 Binary files a/Close Enough!/Library/metadata/f1/f180dd0ee39c24040aba47b5fa83c006.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/f2/f225b26bc1c734d24920b45184a88878 b/Close Enough!/Library/metadata/f2/f225b26bc1c734d24920b45184a88878 deleted file mode 100644 index b47f282..0000000 Binary files a/Close Enough!/Library/metadata/f2/f225b26bc1c734d24920b45184a88878 and /dev/null differ diff --git a/Close Enough!/Library/metadata/f2/f225b26bc1c734d24920b45184a88878.info b/Close Enough!/Library/metadata/f2/f225b26bc1c734d24920b45184a88878.info deleted file mode 100644 index f5d32a4..0000000 Binary files a/Close Enough!/Library/metadata/f2/f225b26bc1c734d24920b45184a88878.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f2/f243972c1872d5b458d7ebc296bc2193 b/Close Enough!/Library/metadata/f2/f243972c1872d5b458d7ebc296bc2193 deleted file mode 100644 index 8d8808f..0000000 Binary files a/Close Enough!/Library/metadata/f2/f243972c1872d5b458d7ebc296bc2193 and /dev/null differ diff --git a/Close Enough!/Library/metadata/f2/f243972c1872d5b458d7ebc296bc2193.info b/Close Enough!/Library/metadata/f2/f243972c1872d5b458d7ebc296bc2193.info deleted file mode 100644 index 757c44f..0000000 Binary files a/Close Enough!/Library/metadata/f2/f243972c1872d5b458d7ebc296bc2193.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f2/f28fcced5af094cf78eb4e1109a71981 b/Close Enough!/Library/metadata/f2/f28fcced5af094cf78eb4e1109a71981 deleted file mode 100644 index 7e5c465..0000000 Binary files a/Close Enough!/Library/metadata/f2/f28fcced5af094cf78eb4e1109a71981 and /dev/null differ diff --git a/Close Enough!/Library/metadata/f2/f28fcced5af094cf78eb4e1109a71981.info b/Close Enough!/Library/metadata/f2/f28fcced5af094cf78eb4e1109a71981.info deleted file mode 100644 index d4fdbb1..0000000 Binary files a/Close Enough!/Library/metadata/f2/f28fcced5af094cf78eb4e1109a71981.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f2/f2afa323d613f4a92b030960640c1fa1 b/Close Enough!/Library/metadata/f2/f2afa323d613f4a92b030960640c1fa1 deleted file mode 100644 index 268584a..0000000 Binary files a/Close Enough!/Library/metadata/f2/f2afa323d613f4a92b030960640c1fa1 and /dev/null differ diff --git a/Close Enough!/Library/metadata/f2/f2afa323d613f4a92b030960640c1fa1.info b/Close Enough!/Library/metadata/f2/f2afa323d613f4a92b030960640c1fa1.info deleted file mode 100644 index bb673a0..0000000 Binary files a/Close Enough!/Library/metadata/f2/f2afa323d613f4a92b030960640c1fa1.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f3/f363b4fb09c0e79449c971b8b68b5a5c b/Close Enough!/Library/metadata/f3/f363b4fb09c0e79449c971b8b68b5a5c deleted file mode 100644 index 61209f4..0000000 Binary files a/Close Enough!/Library/metadata/f3/f363b4fb09c0e79449c971b8b68b5a5c and /dev/null differ diff --git a/Close Enough!/Library/metadata/f3/f363b4fb09c0e79449c971b8b68b5a5c.info b/Close Enough!/Library/metadata/f3/f363b4fb09c0e79449c971b8b68b5a5c.info deleted file mode 100644 index 1c009c6..0000000 Binary files a/Close Enough!/Library/metadata/f3/f363b4fb09c0e79449c971b8b68b5a5c.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f3/f39203fd913316d41bab84c97d42a130 b/Close Enough!/Library/metadata/f3/f39203fd913316d41bab84c97d42a130 deleted file mode 100644 index 523e787..0000000 Binary files a/Close Enough!/Library/metadata/f3/f39203fd913316d41bab84c97d42a130 and /dev/null differ diff --git a/Close Enough!/Library/metadata/f3/f39203fd913316d41bab84c97d42a130.info b/Close Enough!/Library/metadata/f3/f39203fd913316d41bab84c97d42a130.info deleted file mode 100644 index 49cb0d4..0000000 Binary files a/Close Enough!/Library/metadata/f3/f39203fd913316d41bab84c97d42a130.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f3/f39203fd913316d41bab84c97d42a130.resource b/Close Enough!/Library/metadata/f3/f39203fd913316d41bab84c97d42a130.resource deleted file mode 100644 index 1386e4c..0000000 Binary files a/Close Enough!/Library/metadata/f3/f39203fd913316d41bab84c97d42a130.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/f3/f3f067cc7fc3d490c962d4b5a2bd9a2a b/Close Enough!/Library/metadata/f3/f3f067cc7fc3d490c962d4b5a2bd9a2a deleted file mode 100644 index 2974ecc..0000000 Binary files a/Close Enough!/Library/metadata/f3/f3f067cc7fc3d490c962d4b5a2bd9a2a and /dev/null differ diff --git a/Close Enough!/Library/metadata/f3/f3f067cc7fc3d490c962d4b5a2bd9a2a.info b/Close Enough!/Library/metadata/f3/f3f067cc7fc3d490c962d4b5a2bd9a2a.info deleted file mode 100644 index cde1578..0000000 Binary files a/Close Enough!/Library/metadata/f3/f3f067cc7fc3d490c962d4b5a2bd9a2a.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f4/f44102d9118da0f42a51a6a3dcbc8256 b/Close Enough!/Library/metadata/f4/f44102d9118da0f42a51a6a3dcbc8256 deleted file mode 100644 index 510dfa4..0000000 Binary files a/Close Enough!/Library/metadata/f4/f44102d9118da0f42a51a6a3dcbc8256 and /dev/null differ diff --git a/Close Enough!/Library/metadata/f4/f44102d9118da0f42a51a6a3dcbc8256.info b/Close Enough!/Library/metadata/f4/f44102d9118da0f42a51a6a3dcbc8256.info deleted file mode 100644 index 97762d6..0000000 Binary files a/Close Enough!/Library/metadata/f4/f44102d9118da0f42a51a6a3dcbc8256.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f4/f4dfdb696c7e8ee4f9f0f808727aac79 b/Close Enough!/Library/metadata/f4/f4dfdb696c7e8ee4f9f0f808727aac79 deleted file mode 100644 index 4352e27..0000000 Binary files a/Close Enough!/Library/metadata/f4/f4dfdb696c7e8ee4f9f0f808727aac79 and /dev/null differ diff --git a/Close Enough!/Library/metadata/f4/f4dfdb696c7e8ee4f9f0f808727aac79.info b/Close Enough!/Library/metadata/f4/f4dfdb696c7e8ee4f9f0f808727aac79.info deleted file mode 100644 index cc25e5b..0000000 Binary files a/Close Enough!/Library/metadata/f4/f4dfdb696c7e8ee4f9f0f808727aac79.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f4/f4fc607624fc01c49b348bf7d35905cc b/Close Enough!/Library/metadata/f4/f4fc607624fc01c49b348bf7d35905cc deleted file mode 100644 index 540f310..0000000 Binary files a/Close Enough!/Library/metadata/f4/f4fc607624fc01c49b348bf7d35905cc and /dev/null differ diff --git a/Close Enough!/Library/metadata/f4/f4fc607624fc01c49b348bf7d35905cc.info b/Close Enough!/Library/metadata/f4/f4fc607624fc01c49b348bf7d35905cc.info deleted file mode 100644 index 06c4e0f..0000000 Binary files a/Close Enough!/Library/metadata/f4/f4fc607624fc01c49b348bf7d35905cc.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f4/f4fc607624fc01c49b348bf7d35905cc.resource b/Close Enough!/Library/metadata/f4/f4fc607624fc01c49b348bf7d35905cc.resource deleted file mode 100644 index 7c7549b..0000000 Binary files a/Close Enough!/Library/metadata/f4/f4fc607624fc01c49b348bf7d35905cc.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/f5/f524ca1c9533d31438c756048859d377 b/Close Enough!/Library/metadata/f5/f524ca1c9533d31438c756048859d377 deleted file mode 100644 index ced8b0b..0000000 Binary files a/Close Enough!/Library/metadata/f5/f524ca1c9533d31438c756048859d377 and /dev/null differ diff --git a/Close Enough!/Library/metadata/f5/f524ca1c9533d31438c756048859d377.info b/Close Enough!/Library/metadata/f5/f524ca1c9533d31438c756048859d377.info deleted file mode 100644 index dfeb3bd..0000000 Binary files a/Close Enough!/Library/metadata/f5/f524ca1c9533d31438c756048859d377.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f5/f5bdc45de2463404f9d5519bf32a3b74 b/Close Enough!/Library/metadata/f5/f5bdc45de2463404f9d5519bf32a3b74 deleted file mode 100644 index 97eccd3..0000000 Binary files a/Close Enough!/Library/metadata/f5/f5bdc45de2463404f9d5519bf32a3b74 and /dev/null differ diff --git a/Close Enough!/Library/metadata/f5/f5bdc45de2463404f9d5519bf32a3b74.info b/Close Enough!/Library/metadata/f5/f5bdc45de2463404f9d5519bf32a3b74.info deleted file mode 100644 index cdbd013..0000000 Binary files a/Close Enough!/Library/metadata/f5/f5bdc45de2463404f9d5519bf32a3b74.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f5/f5bdc45de2463404f9d5519bf32a3b74.resource b/Close Enough!/Library/metadata/f5/f5bdc45de2463404f9d5519bf32a3b74.resource deleted file mode 100644 index c604ca1..0000000 Binary files a/Close Enough!/Library/metadata/f5/f5bdc45de2463404f9d5519bf32a3b74.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/f5/f5e9255f4adf4ce4eac51f12470052ea b/Close Enough!/Library/metadata/f5/f5e9255f4adf4ce4eac51f12470052ea deleted file mode 100644 index 333e5b7..0000000 Binary files a/Close Enough!/Library/metadata/f5/f5e9255f4adf4ce4eac51f12470052ea and /dev/null differ diff --git a/Close Enough!/Library/metadata/f5/f5e9255f4adf4ce4eac51f12470052ea.info b/Close Enough!/Library/metadata/f5/f5e9255f4adf4ce4eac51f12470052ea.info deleted file mode 100644 index ea82a03..0000000 Binary files a/Close Enough!/Library/metadata/f5/f5e9255f4adf4ce4eac51f12470052ea.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f5/f5e9255f4adf4ce4eac51f12470052ea.resource b/Close Enough!/Library/metadata/f5/f5e9255f4adf4ce4eac51f12470052ea.resource deleted file mode 100644 index d6dd127..0000000 Binary files a/Close Enough!/Library/metadata/f5/f5e9255f4adf4ce4eac51f12470052ea.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/f5/f5f67c52d1564df4a8936ccd202a3bd8 b/Close Enough!/Library/metadata/f5/f5f67c52d1564df4a8936ccd202a3bd8 deleted file mode 100644 index deb2656..0000000 Binary files a/Close Enough!/Library/metadata/f5/f5f67c52d1564df4a8936ccd202a3bd8 and /dev/null differ diff --git a/Close Enough!/Library/metadata/f5/f5f67c52d1564df4a8936ccd202a3bd8.info b/Close Enough!/Library/metadata/f5/f5f67c52d1564df4a8936ccd202a3bd8.info deleted file mode 100644 index 311e931..0000000 Binary files a/Close Enough!/Library/metadata/f5/f5f67c52d1564df4a8936ccd202a3bd8.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f6/f608853083b3b5a46bbe63f6ba879b88 b/Close Enough!/Library/metadata/f6/f608853083b3b5a46bbe63f6ba879b88 deleted file mode 100644 index 4e4760b..0000000 Binary files a/Close Enough!/Library/metadata/f6/f608853083b3b5a46bbe63f6ba879b88 and /dev/null differ diff --git a/Close Enough!/Library/metadata/f6/f608853083b3b5a46bbe63f6ba879b88.info b/Close Enough!/Library/metadata/f6/f608853083b3b5a46bbe63f6ba879b88.info deleted file mode 100644 index 5ebfb83..0000000 Binary files a/Close Enough!/Library/metadata/f6/f608853083b3b5a46bbe63f6ba879b88.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f7/f70555f144d8491a825f0804e09c671c b/Close Enough!/Library/metadata/f7/f70555f144d8491a825f0804e09c671c deleted file mode 100644 index 1a25fb2..0000000 Binary files a/Close Enough!/Library/metadata/f7/f70555f144d8491a825f0804e09c671c and /dev/null differ diff --git a/Close Enough!/Library/metadata/f7/f70555f144d8491a825f0804e09c671c.info b/Close Enough!/Library/metadata/f7/f70555f144d8491a825f0804e09c671c.info deleted file mode 100644 index df250ee..0000000 Binary files a/Close Enough!/Library/metadata/f7/f70555f144d8491a825f0804e09c671c.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f7/f76e83ab2ed1578439b461d13c693378 b/Close Enough!/Library/metadata/f7/f76e83ab2ed1578439b461d13c693378 deleted file mode 100644 index f19c990..0000000 Binary files a/Close Enough!/Library/metadata/f7/f76e83ab2ed1578439b461d13c693378 and /dev/null differ diff --git a/Close Enough!/Library/metadata/f7/f76e83ab2ed1578439b461d13c693378.info b/Close Enough!/Library/metadata/f7/f76e83ab2ed1578439b461d13c693378.info deleted file mode 100644 index 1760f4d..0000000 Binary files a/Close Enough!/Library/metadata/f7/f76e83ab2ed1578439b461d13c693378.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f7/f76e83ab2ed1578439b461d13c693378.resource b/Close Enough!/Library/metadata/f7/f76e83ab2ed1578439b461d13c693378.resource deleted file mode 100644 index 8a968a1..0000000 Binary files a/Close Enough!/Library/metadata/f7/f76e83ab2ed1578439b461d13c693378.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/f7/f7b54ff4a43d4fcf81b4538b678e0bcc b/Close Enough!/Library/metadata/f7/f7b54ff4a43d4fcf81b4538b678e0bcc deleted file mode 100644 index 8981fe8..0000000 Binary files a/Close Enough!/Library/metadata/f7/f7b54ff4a43d4fcf81b4538b678e0bcc and /dev/null differ diff --git a/Close Enough!/Library/metadata/f7/f7b54ff4a43d4fcf81b4538b678e0bcc.info b/Close Enough!/Library/metadata/f7/f7b54ff4a43d4fcf81b4538b678e0bcc.info deleted file mode 100644 index e6c932f..0000000 Binary files a/Close Enough!/Library/metadata/f7/f7b54ff4a43d4fcf81b4538b678e0bcc.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f8/f8612dd98b33c0749b53ead73bc8e672 b/Close Enough!/Library/metadata/f8/f8612dd98b33c0749b53ead73bc8e672 deleted file mode 100644 index c40353b..0000000 Binary files a/Close Enough!/Library/metadata/f8/f8612dd98b33c0749b53ead73bc8e672 and /dev/null differ diff --git a/Close Enough!/Library/metadata/f8/f8612dd98b33c0749b53ead73bc8e672.info b/Close Enough!/Library/metadata/f8/f8612dd98b33c0749b53ead73bc8e672.info deleted file mode 100644 index 4c54b7e..0000000 Binary files a/Close Enough!/Library/metadata/f8/f8612dd98b33c0749b53ead73bc8e672.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f8/f8612dd98b33c0749b53ead73bc8e672.resource b/Close Enough!/Library/metadata/f8/f8612dd98b33c0749b53ead73bc8e672.resource deleted file mode 100644 index bf7626e..0000000 Binary files a/Close Enough!/Library/metadata/f8/f8612dd98b33c0749b53ead73bc8e672.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/f8/f88c4539cfed90e4d8ca82072beb0383 b/Close Enough!/Library/metadata/f8/f88c4539cfed90e4d8ca82072beb0383 deleted file mode 100644 index 53d4ad6..0000000 Binary files a/Close Enough!/Library/metadata/f8/f88c4539cfed90e4d8ca82072beb0383 and /dev/null differ diff --git a/Close Enough!/Library/metadata/f8/f88c4539cfed90e4d8ca82072beb0383.info b/Close Enough!/Library/metadata/f8/f88c4539cfed90e4d8ca82072beb0383.info deleted file mode 100644 index 04a56a4..0000000 Binary files a/Close Enough!/Library/metadata/f8/f88c4539cfed90e4d8ca82072beb0383.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/f8/f88c4539cfed90e4d8ca82072beb0383.resource b/Close Enough!/Library/metadata/f8/f88c4539cfed90e4d8ca82072beb0383.resource deleted file mode 100644 index 9352012..0000000 Binary files a/Close Enough!/Library/metadata/f8/f88c4539cfed90e4d8ca82072beb0383.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/f9/f921084f58d340e4c99f8e10f4f1c0c0 b/Close Enough!/Library/metadata/f9/f921084f58d340e4c99f8e10f4f1c0c0 deleted file mode 100644 index b9bfabb..0000000 Binary files a/Close Enough!/Library/metadata/f9/f921084f58d340e4c99f8e10f4f1c0c0 and /dev/null differ diff --git a/Close Enough!/Library/metadata/f9/f921084f58d340e4c99f8e10f4f1c0c0.info b/Close Enough!/Library/metadata/f9/f921084f58d340e4c99f8e10f4f1c0c0.info deleted file mode 100644 index 08d119f..0000000 Binary files a/Close Enough!/Library/metadata/f9/f921084f58d340e4c99f8e10f4f1c0c0.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/fb/fbc9367e9c6eb2c4fa51d303d35992c9 b/Close Enough!/Library/metadata/fb/fbc9367e9c6eb2c4fa51d303d35992c9 deleted file mode 100644 index f95b58e..0000000 Binary files a/Close Enough!/Library/metadata/fb/fbc9367e9c6eb2c4fa51d303d35992c9 and /dev/null differ diff --git a/Close Enough!/Library/metadata/fb/fbc9367e9c6eb2c4fa51d303d35992c9.info b/Close Enough!/Library/metadata/fb/fbc9367e9c6eb2c4fa51d303d35992c9.info deleted file mode 100644 index c6e43e7..0000000 Binary files a/Close Enough!/Library/metadata/fb/fbc9367e9c6eb2c4fa51d303d35992c9.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/fd/fd46e146b1fa0b242b0be537406d6419 b/Close Enough!/Library/metadata/fd/fd46e146b1fa0b242b0be537406d6419 deleted file mode 100644 index 89fc7ea..0000000 Binary files a/Close Enough!/Library/metadata/fd/fd46e146b1fa0b242b0be537406d6419 and /dev/null differ diff --git a/Close Enough!/Library/metadata/fd/fd46e146b1fa0b242b0be537406d6419.info b/Close Enough!/Library/metadata/fd/fd46e146b1fa0b242b0be537406d6419.info deleted file mode 100644 index f35bce4..0000000 Binary files a/Close Enough!/Library/metadata/fd/fd46e146b1fa0b242b0be537406d6419.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/fd/fd46e146b1fa0b242b0be537406d6419.resource b/Close Enough!/Library/metadata/fd/fd46e146b1fa0b242b0be537406d6419.resource deleted file mode 100644 index 3a0253b..0000000 Binary files a/Close Enough!/Library/metadata/fd/fd46e146b1fa0b242b0be537406d6419.resource and /dev/null differ diff --git a/Close Enough!/Library/metadata/fd/fdd6bf471a247844d820975ce3477686 b/Close Enough!/Library/metadata/fd/fdd6bf471a247844d820975ce3477686 deleted file mode 100644 index 2332323..0000000 Binary files a/Close Enough!/Library/metadata/fd/fdd6bf471a247844d820975ce3477686 and /dev/null differ diff --git a/Close Enough!/Library/metadata/fd/fdd6bf471a247844d820975ce3477686.info b/Close Enough!/Library/metadata/fd/fdd6bf471a247844d820975ce3477686.info deleted file mode 100644 index bd96b64..0000000 Binary files a/Close Enough!/Library/metadata/fd/fdd6bf471a247844d820975ce3477686.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/fe/fec197bad419341558f81f2ec8a05e18 b/Close Enough!/Library/metadata/fe/fec197bad419341558f81f2ec8a05e18 deleted file mode 100644 index d370557..0000000 Binary files a/Close Enough!/Library/metadata/fe/fec197bad419341558f81f2ec8a05e18 and /dev/null differ diff --git a/Close Enough!/Library/metadata/fe/fec197bad419341558f81f2ec8a05e18.info b/Close Enough!/Library/metadata/fe/fec197bad419341558f81f2ec8a05e18.info deleted file mode 100644 index 40f4866..0000000 Binary files a/Close Enough!/Library/metadata/fe/fec197bad419341558f81f2ec8a05e18.info and /dev/null differ diff --git a/Close Enough!/Library/metadata/ff/ff5ef524183ddbc4182c4dc882131b2b b/Close Enough!/Library/metadata/ff/ff5ef524183ddbc4182c4dc882131b2b deleted file mode 100644 index 1baed28..0000000 Binary files a/Close Enough!/Library/metadata/ff/ff5ef524183ddbc4182c4dc882131b2b and /dev/null differ diff --git a/Close Enough!/Library/metadata/ff/ff5ef524183ddbc4182c4dc882131b2b.info b/Close Enough!/Library/metadata/ff/ff5ef524183ddbc4182c4dc882131b2b.info deleted file mode 100644 index 0086cd4..0000000 Binary files a/Close Enough!/Library/metadata/ff/ff5ef524183ddbc4182c4dc882131b2b.info and /dev/null differ diff --git a/Close Enough!/Library/p4plugin.log b/Close Enough!/Library/p4plugin.log deleted file mode 100644 index e69de29..0000000 diff --git a/Close Enough!/Library/shadercompiler-UnityShaderCompiler.exe0.log b/Close Enough!/Library/shadercompiler-UnityShaderCompiler.exe0.log deleted file mode 100644 index 5be4fab..0000000 --- a/Close Enough!/Library/shadercompiler-UnityShaderCompiler.exe0.log +++ /dev/null @@ -1,2 +0,0 @@ -Base path: C:/Program Files/Unity/Editor/Data -Cmd: initializeCompiler diff --git a/Close Enough!/Library/shadercompiler-UnityShaderCompiler0.log b/Close Enough!/Library/shadercompiler-UnityShaderCompiler0.log deleted file mode 100644 index 699af65..0000000 --- a/Close Enough!/Library/shadercompiler-UnityShaderCompiler0.log +++ /dev/null @@ -1,26 +0,0 @@ -Base path: /Applications/Unity/Unity.app/Contents -Cmd: initializeCompiler -Cmd: compileSnippet - api=15 type=0 insize=629 outsize=1853 kw=ETC1_EXTERNAL_ALPHA pd=UNITY_ENABLE_REFLECTION_BUFFERS UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING UNITY_ENABLE_DETAIL_NORMALMAP SHADER_API_DESKTOP UNITY_COLORSPACE_GAMMA UNITY_LIGHT_PROBE_PROXY_VOLUME UNITY_LIGHTMAP_FULL_HDR ok=1 -Cmd: compileSnippet - api=15 type=1 insize=629 outsize=0 kw=ETC1_EXTERNAL_ALPHA pd=UNITY_ENABLE_REFLECTION_BUFFERS UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING UNITY_ENABLE_DETAIL_NORMALMAP SHADER_API_DESKTOP UNITY_COLORSPACE_GAMMA UNITY_LIGHT_PROBE_PROXY_VOLUME UNITY_LIGHTMAP_FULL_HDR ok=1 -Cmd: compileSnippet - api=15 type=0 insize=1106 outsize=2591 kw=SHADOWS_DEPTH pd=UNITY_ENABLE_REFLECTION_BUFFERS UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING UNITY_ENABLE_DETAIL_NORMALMAP SHADER_API_DESKTOP UNITY_COLORSPACE_GAMMA UNITY_LIGHT_PROBE_PROXY_VOLUME UNITY_LIGHTMAP_FULL_HDR ok=1 -Cmd: compileSnippet - api=15 type=1 insize=1106 outsize=0 kw=SHADOWS_DEPTH pd=UNITY_ENABLE_REFLECTION_BUFFERS UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING UNITY_ENABLE_DETAIL_NORMALMAP SHADER_API_DESKTOP UNITY_COLORSPACE_GAMMA UNITY_LIGHT_PROBE_PROXY_VOLUME UNITY_LIGHTMAP_FULL_HDR ok=1 -Cmd: compileSnippet - api=15 type=0 insize=1464 outsize=15875 kw=DIRECTIONAL LIGHTPROBE_SH _EMISSION pd=UNITY_ENABLE_REFLECTION_BUFFERS UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING UNITY_ENABLE_DETAIL_NORMALMAP SHADER_API_DESKTOP UNITY_COLORSPACE_GAMMA UNITY_LIGHT_PROBE_PROXY_VOLUME UNITY_LIGHTMAP_FULL_HDR ok=1 -Cmd: compileSnippet - api=15 type=1 insize=1464 outsize=0 kw=DIRECTIONAL LIGHTPROBE_SH _EMISSION pd=UNITY_ENABLE_REFLECTION_BUFFERS UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING UNITY_ENABLE_DETAIL_NORMALMAP SHADER_API_DESKTOP UNITY_COLORSPACE_GAMMA UNITY_LIGHT_PROBE_PROXY_VOLUME UNITY_LIGHTMAP_FULL_HDR ok=1 -Cmd: compileSnippet - api=15 type=0 insize=1325 outsize=8130 kw=DIRECTIONAL pd=UNITY_ENABLE_REFLECTION_BUFFERS UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING UNITY_ENABLE_DETAIL_NORMALMAP SHADER_API_DESKTOP UNITY_COLORSPACE_GAMMA UNITY_LIGHT_PROBE_PROXY_VOLUME UNITY_LIGHTMAP_FULL_HDR ok=1 -Cmd: compileSnippet - api=15 type=1 insize=1325 outsize=0 kw=DIRECTIONAL pd=UNITY_ENABLE_REFLECTION_BUFFERS UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING UNITY_ENABLE_DETAIL_NORMALMAP SHADER_API_DESKTOP UNITY_COLORSPACE_GAMMA UNITY_LIGHT_PROBE_PROXY_VOLUME UNITY_LIGHTMAP_FULL_HDR ok=1 -Cmd: compileSnippet - api=15 type=0 insize=1464 outsize=15669 kw=DIRECTIONAL LIGHTPROBE_SH pd=UNITY_ENABLE_REFLECTION_BUFFERS UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING UNITY_ENABLE_DETAIL_NORMALMAP SHADER_API_DESKTOP UNITY_COLORSPACE_GAMMA UNITY_LIGHT_PROBE_PROXY_VOLUME UNITY_LIGHTMAP_FULL_HDR ok=1 -Cmd: compileSnippet - api=15 type=1 insize=1464 outsize=0 kw=DIRECTIONAL LIGHTPROBE_SH pd=UNITY_ENABLE_REFLECTION_BUFFERS UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING UNITY_ENABLE_DETAIL_NORMALMAP SHADER_API_DESKTOP UNITY_COLORSPACE_GAMMA UNITY_LIGHT_PROBE_PROXY_VOLUME UNITY_LIGHTMAP_FULL_HDR ok=1 -Cmd: compileSnippet - api=15 type=0 insize=2539 outsize=1599 kw= pd=UNITY_ENABLE_REFLECTION_BUFFERS UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING UNITY_ENABLE_DETAIL_NORMALMAP SHADER_API_DESKTOP UNITY_COLORSPACE_GAMMA UNITY_LIGHT_PROBE_PROXY_VOLUME UNITY_LIGHTMAP_FULL_HDR ok=1 -Cmd: compileSnippet - api=15 type=1 insize=2539 outsize=0 kw= pd=UNITY_ENABLE_REFLECTION_BUFFERS UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING UNITY_ENABLE_DETAIL_NORMALMAP SHADER_API_DESKTOP UNITY_COLORSPACE_GAMMA UNITY_LIGHT_PROBE_PROXY_VOLUME UNITY_LIGHTMAP_FULL_HDR ok=1 diff --git a/Close Enough!/Temp/UnityTempFile-047b9b8450c784974a6adebf6beaf72f b/Close Enough!/Temp/UnityTempFile-047b9b8450c784974a6adebf6beaf72f deleted file mode 100644 index 7ea43a3..0000000 --- a/Close Enough!/Temp/UnityTempFile-047b9b8450c784974a6adebf6beaf72f +++ /dev/null @@ -1,218 +0,0 @@ --debug --target:library --nowarn:0169 --langversion:4 --out:'Temp/Assembly-CSharp.dll' --unsafe --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CoreModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AccessibilityModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticleSystemModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VehiclesModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClothModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AnimationModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TextRenderingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainPhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.IMGUIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterInputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterRendererModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UNETModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.DirectorModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityAnalyticsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PerformanceReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityConnectModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WebModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ARModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VRModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIElementsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.StyleSheetsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AssetBundleModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CrashReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GameCenterModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GridModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ImageConversionModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.InputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.JSONSerializeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticlesLegacyModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.Physics2DModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ScreenCaptureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SharedInternalsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteMaskModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteShapeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TilemapModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestAudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestTextureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestWWWModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VideoModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WindModule.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/UnityEngine.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/Editor/UnityEditor.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/Editor/UnityEditor.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/UnityEngine.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/net35/unity-custom/nunit.framework.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/Editor/UnityEditor.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/Editor/UnityEditor.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/RuntimeEditor/UnityEngine.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/Editor/UnityEditor.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TreeEditor/Editor/UnityEditor.TreeEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/Editor/UnityEditor.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/RuntimeEditor/UnityEngine.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/Editor/UnityEditor.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/RuntimeEditor/UnityEngine.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/Editor/UnityEditor.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityVR/Editor/UnityEditor.VR.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.Graphs.dll' --r:'/Applications/Unity/Unity.app/Contents/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/UnityEngine.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/Editor/UnityEditor.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/UnityEngine.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/Editor/UnityEditor.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/UnityEngine.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/Editor/UnityEditor.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.standardevents@1.0.10/UnityEngine.StandardEvents.dll' --define:UNITY_5_3_OR_NEWER --define:UNITY_5_4_OR_NEWER --define:UNITY_5_5_OR_NEWER --define:UNITY_5_6_OR_NEWER --define:UNITY_2017_1_OR_NEWER --define:UNITY_2017_2_OR_NEWER --define:UNITY_2017_3_OR_NEWER --define:UNITY_2017_3_1 --define:UNITY_2017_3 --define:UNITY_2017 --define:PLATFORM_ARCH_64 --define:UNITY_64 --define:ENABLE_AUDIO --define:ENABLE_CACHING --define:ENABLE_CLOTH --define:ENABLE_DUCK_TYPING --define:ENABLE_GENERICS --define:ENABLE_PVR_GI --define:ENABLE_MICROPHONE --define:ENABLE_MULTIPLE_DISPLAYS --define:ENABLE_PHYSICS --define:ENABLE_SPRITERENDERER_FLIPPING --define:ENABLE_SPRITES --define:ENABLE_GRID --define:ENABLE_TILEMAP --define:ENABLE_TERRAIN --define:ENABLE_RAKNET --define:ENABLE_DIRECTOR --define:ENABLE_UNET --define:ENABLE_LZMA --define:ENABLE_UNITYEVENTS --define:ENABLE_WEBCAM --define:ENABLE_WWW --define:ENABLE_CLOUD_SERVICES_COLLAB --define:ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS --define:ENABLE_CLOUD_SERVICES_ADS --define:ENABLE_CLOUD_HUB --define:ENABLE_CLOUD_PROJECT_ID --define:ENABLE_CLOUD_SERVICES_USE_WEBREQUEST --define:ENABLE_CLOUD_SERVICES_UNET --define:ENABLE_CLOUD_SERVICES_BUILD --define:ENABLE_CLOUD_LICENSE --define:ENABLE_EDITOR_HUB --define:ENABLE_EDITOR_HUB_LICENSE --define:ENABLE_WEBSOCKET_CLIENT --define:ENABLE_DIRECTOR_AUDIO --define:ENABLE_DIRECTOR_TEXTURE --define:ENABLE_TIMELINE --define:ENABLE_EDITOR_METRICS --define:ENABLE_EDITOR_METRICS_CACHING --define:ENABLE_NATIVE_ARRAY --define:ENABLE_SPRITE_MASKING --define:INCLUDE_DYNAMIC_GI --define:INCLUDE_GI --define:ENABLE_MONO_BDWGC --define:PLATFORM_SUPPORTS_MONO --define:RENDER_SOFTWARE_CURSOR --define:INCLUDE_PUBNUB --define:ENABLE_PLAYMODE_TESTS_RUNNER --define:ENABLE_VIDEO --define:ENABLE_RMGUI --define:ENABLE_PACKMAN --define:ENABLE_CUSTOM_RENDER_TEXTURE --define:ENABLE_STYLE_SHEETS --define:ENABLE_LOCALIZATION --define:PLATFORM_STANDALONE_OSX --define:PLATFORM_STANDALONE --define:UNITY_STANDALONE_OSX --define:UNITY_STANDALONE --define:ENABLE_SUBSTANCE --define:ENABLE_GAMECENTER --define:ENABLE_RUNTIME_GI --define:ENABLE_MOVIES --define:ENABLE_NETWORK --define:ENABLE_CRUNCH_TEXTURE_COMPRESSION --define:ENABLE_UNITYWEBREQUEST --define:ENABLE_CLOUD_SERVICES --define:ENABLE_CLOUD_SERVICES_ANALYTICS --define:ENABLE_CLOUD_SERVICES_PURCHASING --define:ENABLE_CLOUD_SERVICES_CRASH_REPORTING --define:ENABLE_CLOUD_SERVICES_NATIVE_CRASH_REPORTING --define:ENABLE_CLUSTERINPUT --define:ENABLE_VR --define:ENABLE_AR --define:ENABLE_SPATIALTRACKING --define:ENABLE_WEBSOCKET_HOST --define:ENABLE_MONO --define:NET_2_0_SUBSET --define:ENABLE_PROFILER --define:DEBUG --define:TRACE --define:UNITY_ASSERTIONS --define:UNITY_EDITOR --define:UNITY_EDITOR_64 --define:UNITY_EDITOR_OSX --define:ENABLE_NATIVE_ARRAY_CHECKS --define:UNITY_TEAM_LICENSE -'Assets/Lobby/Scripts/DraggablePanel.cs' -'Assets/Lobby/Scripts/EventSystemChecker.cs' -'Assets/Lobby/Scripts/Lobby/LobbyCountdownPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyHook.cs' -'Assets/Lobby/Scripts/Lobby/LobbyInfoPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyMainMenu.cs' -'Assets/Lobby/Scripts/Lobby/LobbyManager.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayer.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerEntry.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyTopPanel.cs' -'Assets/SampleScenes/Scripts/NetworkAsteroid.cs' -'Assets/SampleScenes/Scripts/NetworkGameManager.cs' -'Assets/SampleScenes/Scripts/NetworkLobbyHook.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceship.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceshipBullet.cs' -'Assets/Scripts/ColorManager.cs' -'Assets/Scripts/ColorOption.cs' -'Assets/Scripts/ColorPicker.cs' -'Assets/Scripts/DoneButtonPressed.cs' -'Assets/Scripts/DoodleShake.cs' -'Assets/Scripts/FadingTextAnimation.cs' -'Assets/Scripts/LoadSceneOnTap.cs' -'Assets/Scripts/RandomSprite.cs' -'Assets/Scripts/ScreenCapture.cs' -'Assets/Scripts/SizeManager.cs' -'Assets/Scripts/SwipeTrail.cs' -'Assets/Scripts/Timer.cs' -'Assets/Scripts/ToolsStateManager.cs' -'Assets/Scripts/ToolState.cs' -'Assets/Scripts/UIRaycastDetector.cs' -'Assets/Scripts/Width.cs' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Runtime.Serialization.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Xml.Linq.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.Lang.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/Boo.Lang.dll' --sdk:unity diff --git a/Close Enough!/Temp/UnityTempFile-0ba0fe24ac8a94c68aa454f4c236103e b/Close Enough!/Temp/UnityTempFile-0ba0fe24ac8a94c68aa454f4c236103e deleted file mode 100644 index 7ea43a3..0000000 --- a/Close Enough!/Temp/UnityTempFile-0ba0fe24ac8a94c68aa454f4c236103e +++ /dev/null @@ -1,218 +0,0 @@ --debug --target:library --nowarn:0169 --langversion:4 --out:'Temp/Assembly-CSharp.dll' --unsafe --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CoreModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AccessibilityModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticleSystemModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VehiclesModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClothModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AnimationModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TextRenderingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainPhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.IMGUIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterInputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterRendererModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UNETModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.DirectorModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityAnalyticsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PerformanceReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityConnectModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WebModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ARModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VRModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIElementsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.StyleSheetsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AssetBundleModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CrashReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GameCenterModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GridModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ImageConversionModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.InputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.JSONSerializeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticlesLegacyModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.Physics2DModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ScreenCaptureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SharedInternalsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteMaskModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteShapeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TilemapModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestAudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestTextureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestWWWModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VideoModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WindModule.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/UnityEngine.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/Editor/UnityEditor.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/Editor/UnityEditor.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/UnityEngine.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/net35/unity-custom/nunit.framework.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/Editor/UnityEditor.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/Editor/UnityEditor.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/RuntimeEditor/UnityEngine.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/Editor/UnityEditor.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TreeEditor/Editor/UnityEditor.TreeEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/Editor/UnityEditor.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/RuntimeEditor/UnityEngine.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/Editor/UnityEditor.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/RuntimeEditor/UnityEngine.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/Editor/UnityEditor.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityVR/Editor/UnityEditor.VR.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.Graphs.dll' --r:'/Applications/Unity/Unity.app/Contents/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/UnityEngine.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/Editor/UnityEditor.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/UnityEngine.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/Editor/UnityEditor.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/UnityEngine.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/Editor/UnityEditor.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.standardevents@1.0.10/UnityEngine.StandardEvents.dll' --define:UNITY_5_3_OR_NEWER --define:UNITY_5_4_OR_NEWER --define:UNITY_5_5_OR_NEWER --define:UNITY_5_6_OR_NEWER --define:UNITY_2017_1_OR_NEWER --define:UNITY_2017_2_OR_NEWER --define:UNITY_2017_3_OR_NEWER --define:UNITY_2017_3_1 --define:UNITY_2017_3 --define:UNITY_2017 --define:PLATFORM_ARCH_64 --define:UNITY_64 --define:ENABLE_AUDIO --define:ENABLE_CACHING --define:ENABLE_CLOTH --define:ENABLE_DUCK_TYPING --define:ENABLE_GENERICS --define:ENABLE_PVR_GI --define:ENABLE_MICROPHONE --define:ENABLE_MULTIPLE_DISPLAYS --define:ENABLE_PHYSICS --define:ENABLE_SPRITERENDERER_FLIPPING --define:ENABLE_SPRITES --define:ENABLE_GRID --define:ENABLE_TILEMAP --define:ENABLE_TERRAIN --define:ENABLE_RAKNET --define:ENABLE_DIRECTOR --define:ENABLE_UNET --define:ENABLE_LZMA --define:ENABLE_UNITYEVENTS --define:ENABLE_WEBCAM --define:ENABLE_WWW --define:ENABLE_CLOUD_SERVICES_COLLAB --define:ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS --define:ENABLE_CLOUD_SERVICES_ADS --define:ENABLE_CLOUD_HUB --define:ENABLE_CLOUD_PROJECT_ID --define:ENABLE_CLOUD_SERVICES_USE_WEBREQUEST --define:ENABLE_CLOUD_SERVICES_UNET --define:ENABLE_CLOUD_SERVICES_BUILD --define:ENABLE_CLOUD_LICENSE --define:ENABLE_EDITOR_HUB --define:ENABLE_EDITOR_HUB_LICENSE --define:ENABLE_WEBSOCKET_CLIENT --define:ENABLE_DIRECTOR_AUDIO --define:ENABLE_DIRECTOR_TEXTURE --define:ENABLE_TIMELINE --define:ENABLE_EDITOR_METRICS --define:ENABLE_EDITOR_METRICS_CACHING --define:ENABLE_NATIVE_ARRAY --define:ENABLE_SPRITE_MASKING --define:INCLUDE_DYNAMIC_GI --define:INCLUDE_GI --define:ENABLE_MONO_BDWGC --define:PLATFORM_SUPPORTS_MONO --define:RENDER_SOFTWARE_CURSOR --define:INCLUDE_PUBNUB --define:ENABLE_PLAYMODE_TESTS_RUNNER --define:ENABLE_VIDEO --define:ENABLE_RMGUI --define:ENABLE_PACKMAN --define:ENABLE_CUSTOM_RENDER_TEXTURE --define:ENABLE_STYLE_SHEETS --define:ENABLE_LOCALIZATION --define:PLATFORM_STANDALONE_OSX --define:PLATFORM_STANDALONE --define:UNITY_STANDALONE_OSX --define:UNITY_STANDALONE --define:ENABLE_SUBSTANCE --define:ENABLE_GAMECENTER --define:ENABLE_RUNTIME_GI --define:ENABLE_MOVIES --define:ENABLE_NETWORK --define:ENABLE_CRUNCH_TEXTURE_COMPRESSION --define:ENABLE_UNITYWEBREQUEST --define:ENABLE_CLOUD_SERVICES --define:ENABLE_CLOUD_SERVICES_ANALYTICS --define:ENABLE_CLOUD_SERVICES_PURCHASING --define:ENABLE_CLOUD_SERVICES_CRASH_REPORTING --define:ENABLE_CLOUD_SERVICES_NATIVE_CRASH_REPORTING --define:ENABLE_CLUSTERINPUT --define:ENABLE_VR --define:ENABLE_AR --define:ENABLE_SPATIALTRACKING --define:ENABLE_WEBSOCKET_HOST --define:ENABLE_MONO --define:NET_2_0_SUBSET --define:ENABLE_PROFILER --define:DEBUG --define:TRACE --define:UNITY_ASSERTIONS --define:UNITY_EDITOR --define:UNITY_EDITOR_64 --define:UNITY_EDITOR_OSX --define:ENABLE_NATIVE_ARRAY_CHECKS --define:UNITY_TEAM_LICENSE -'Assets/Lobby/Scripts/DraggablePanel.cs' -'Assets/Lobby/Scripts/EventSystemChecker.cs' -'Assets/Lobby/Scripts/Lobby/LobbyCountdownPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyHook.cs' -'Assets/Lobby/Scripts/Lobby/LobbyInfoPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyMainMenu.cs' -'Assets/Lobby/Scripts/Lobby/LobbyManager.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayer.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerEntry.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyTopPanel.cs' -'Assets/SampleScenes/Scripts/NetworkAsteroid.cs' -'Assets/SampleScenes/Scripts/NetworkGameManager.cs' -'Assets/SampleScenes/Scripts/NetworkLobbyHook.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceship.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceshipBullet.cs' -'Assets/Scripts/ColorManager.cs' -'Assets/Scripts/ColorOption.cs' -'Assets/Scripts/ColorPicker.cs' -'Assets/Scripts/DoneButtonPressed.cs' -'Assets/Scripts/DoodleShake.cs' -'Assets/Scripts/FadingTextAnimation.cs' -'Assets/Scripts/LoadSceneOnTap.cs' -'Assets/Scripts/RandomSprite.cs' -'Assets/Scripts/ScreenCapture.cs' -'Assets/Scripts/SizeManager.cs' -'Assets/Scripts/SwipeTrail.cs' -'Assets/Scripts/Timer.cs' -'Assets/Scripts/ToolsStateManager.cs' -'Assets/Scripts/ToolState.cs' -'Assets/Scripts/UIRaycastDetector.cs' -'Assets/Scripts/Width.cs' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Runtime.Serialization.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Xml.Linq.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.Lang.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/Boo.Lang.dll' --sdk:unity diff --git a/Close Enough!/Temp/UnityTempFile-48cf37e228b0b42a2aaeb64f19c84f2d b/Close Enough!/Temp/UnityTempFile-48cf37e228b0b42a2aaeb64f19c84f2d deleted file mode 100644 index 7ea43a3..0000000 --- a/Close Enough!/Temp/UnityTempFile-48cf37e228b0b42a2aaeb64f19c84f2d +++ /dev/null @@ -1,218 +0,0 @@ --debug --target:library --nowarn:0169 --langversion:4 --out:'Temp/Assembly-CSharp.dll' --unsafe --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CoreModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AccessibilityModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticleSystemModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VehiclesModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClothModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AnimationModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TextRenderingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainPhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.IMGUIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterInputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterRendererModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UNETModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.DirectorModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityAnalyticsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PerformanceReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityConnectModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WebModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ARModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VRModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIElementsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.StyleSheetsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AssetBundleModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CrashReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GameCenterModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GridModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ImageConversionModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.InputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.JSONSerializeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticlesLegacyModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.Physics2DModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ScreenCaptureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SharedInternalsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteMaskModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteShapeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TilemapModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestAudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestTextureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestWWWModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VideoModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WindModule.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/UnityEngine.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/Editor/UnityEditor.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/Editor/UnityEditor.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/UnityEngine.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/net35/unity-custom/nunit.framework.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/Editor/UnityEditor.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/Editor/UnityEditor.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/RuntimeEditor/UnityEngine.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/Editor/UnityEditor.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TreeEditor/Editor/UnityEditor.TreeEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/Editor/UnityEditor.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/RuntimeEditor/UnityEngine.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/Editor/UnityEditor.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/RuntimeEditor/UnityEngine.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/Editor/UnityEditor.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityVR/Editor/UnityEditor.VR.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.Graphs.dll' --r:'/Applications/Unity/Unity.app/Contents/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/UnityEngine.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/Editor/UnityEditor.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/UnityEngine.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/Editor/UnityEditor.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/UnityEngine.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/Editor/UnityEditor.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.standardevents@1.0.10/UnityEngine.StandardEvents.dll' --define:UNITY_5_3_OR_NEWER --define:UNITY_5_4_OR_NEWER --define:UNITY_5_5_OR_NEWER --define:UNITY_5_6_OR_NEWER --define:UNITY_2017_1_OR_NEWER --define:UNITY_2017_2_OR_NEWER --define:UNITY_2017_3_OR_NEWER --define:UNITY_2017_3_1 --define:UNITY_2017_3 --define:UNITY_2017 --define:PLATFORM_ARCH_64 --define:UNITY_64 --define:ENABLE_AUDIO --define:ENABLE_CACHING --define:ENABLE_CLOTH --define:ENABLE_DUCK_TYPING --define:ENABLE_GENERICS --define:ENABLE_PVR_GI --define:ENABLE_MICROPHONE --define:ENABLE_MULTIPLE_DISPLAYS --define:ENABLE_PHYSICS --define:ENABLE_SPRITERENDERER_FLIPPING --define:ENABLE_SPRITES --define:ENABLE_GRID --define:ENABLE_TILEMAP --define:ENABLE_TERRAIN --define:ENABLE_RAKNET --define:ENABLE_DIRECTOR --define:ENABLE_UNET --define:ENABLE_LZMA --define:ENABLE_UNITYEVENTS --define:ENABLE_WEBCAM --define:ENABLE_WWW --define:ENABLE_CLOUD_SERVICES_COLLAB --define:ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS --define:ENABLE_CLOUD_SERVICES_ADS --define:ENABLE_CLOUD_HUB --define:ENABLE_CLOUD_PROJECT_ID --define:ENABLE_CLOUD_SERVICES_USE_WEBREQUEST --define:ENABLE_CLOUD_SERVICES_UNET --define:ENABLE_CLOUD_SERVICES_BUILD --define:ENABLE_CLOUD_LICENSE --define:ENABLE_EDITOR_HUB --define:ENABLE_EDITOR_HUB_LICENSE --define:ENABLE_WEBSOCKET_CLIENT --define:ENABLE_DIRECTOR_AUDIO --define:ENABLE_DIRECTOR_TEXTURE --define:ENABLE_TIMELINE --define:ENABLE_EDITOR_METRICS --define:ENABLE_EDITOR_METRICS_CACHING --define:ENABLE_NATIVE_ARRAY --define:ENABLE_SPRITE_MASKING --define:INCLUDE_DYNAMIC_GI --define:INCLUDE_GI --define:ENABLE_MONO_BDWGC --define:PLATFORM_SUPPORTS_MONO --define:RENDER_SOFTWARE_CURSOR --define:INCLUDE_PUBNUB --define:ENABLE_PLAYMODE_TESTS_RUNNER --define:ENABLE_VIDEO --define:ENABLE_RMGUI --define:ENABLE_PACKMAN --define:ENABLE_CUSTOM_RENDER_TEXTURE --define:ENABLE_STYLE_SHEETS --define:ENABLE_LOCALIZATION --define:PLATFORM_STANDALONE_OSX --define:PLATFORM_STANDALONE --define:UNITY_STANDALONE_OSX --define:UNITY_STANDALONE --define:ENABLE_SUBSTANCE --define:ENABLE_GAMECENTER --define:ENABLE_RUNTIME_GI --define:ENABLE_MOVIES --define:ENABLE_NETWORK --define:ENABLE_CRUNCH_TEXTURE_COMPRESSION --define:ENABLE_UNITYWEBREQUEST --define:ENABLE_CLOUD_SERVICES --define:ENABLE_CLOUD_SERVICES_ANALYTICS --define:ENABLE_CLOUD_SERVICES_PURCHASING --define:ENABLE_CLOUD_SERVICES_CRASH_REPORTING --define:ENABLE_CLOUD_SERVICES_NATIVE_CRASH_REPORTING --define:ENABLE_CLUSTERINPUT --define:ENABLE_VR --define:ENABLE_AR --define:ENABLE_SPATIALTRACKING --define:ENABLE_WEBSOCKET_HOST --define:ENABLE_MONO --define:NET_2_0_SUBSET --define:ENABLE_PROFILER --define:DEBUG --define:TRACE --define:UNITY_ASSERTIONS --define:UNITY_EDITOR --define:UNITY_EDITOR_64 --define:UNITY_EDITOR_OSX --define:ENABLE_NATIVE_ARRAY_CHECKS --define:UNITY_TEAM_LICENSE -'Assets/Lobby/Scripts/DraggablePanel.cs' -'Assets/Lobby/Scripts/EventSystemChecker.cs' -'Assets/Lobby/Scripts/Lobby/LobbyCountdownPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyHook.cs' -'Assets/Lobby/Scripts/Lobby/LobbyInfoPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyMainMenu.cs' -'Assets/Lobby/Scripts/Lobby/LobbyManager.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayer.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerEntry.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyTopPanel.cs' -'Assets/SampleScenes/Scripts/NetworkAsteroid.cs' -'Assets/SampleScenes/Scripts/NetworkGameManager.cs' -'Assets/SampleScenes/Scripts/NetworkLobbyHook.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceship.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceshipBullet.cs' -'Assets/Scripts/ColorManager.cs' -'Assets/Scripts/ColorOption.cs' -'Assets/Scripts/ColorPicker.cs' -'Assets/Scripts/DoneButtonPressed.cs' -'Assets/Scripts/DoodleShake.cs' -'Assets/Scripts/FadingTextAnimation.cs' -'Assets/Scripts/LoadSceneOnTap.cs' -'Assets/Scripts/RandomSprite.cs' -'Assets/Scripts/ScreenCapture.cs' -'Assets/Scripts/SizeManager.cs' -'Assets/Scripts/SwipeTrail.cs' -'Assets/Scripts/Timer.cs' -'Assets/Scripts/ToolsStateManager.cs' -'Assets/Scripts/ToolState.cs' -'Assets/Scripts/UIRaycastDetector.cs' -'Assets/Scripts/Width.cs' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Runtime.Serialization.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Xml.Linq.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.Lang.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/Boo.Lang.dll' --sdk:unity diff --git a/Close Enough!/Temp/UnityTempFile-51f0eb10b217e436e8e8e1a71922b912 b/Close Enough!/Temp/UnityTempFile-51f0eb10b217e436e8e8e1a71922b912 deleted file mode 100644 index 7ea43a3..0000000 --- a/Close Enough!/Temp/UnityTempFile-51f0eb10b217e436e8e8e1a71922b912 +++ /dev/null @@ -1,218 +0,0 @@ --debug --target:library --nowarn:0169 --langversion:4 --out:'Temp/Assembly-CSharp.dll' --unsafe --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CoreModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AccessibilityModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticleSystemModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VehiclesModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClothModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AnimationModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TextRenderingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainPhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.IMGUIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterInputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterRendererModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UNETModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.DirectorModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityAnalyticsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PerformanceReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityConnectModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WebModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ARModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VRModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIElementsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.StyleSheetsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AssetBundleModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CrashReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GameCenterModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GridModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ImageConversionModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.InputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.JSONSerializeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticlesLegacyModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.Physics2DModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ScreenCaptureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SharedInternalsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteMaskModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteShapeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TilemapModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestAudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestTextureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestWWWModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VideoModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WindModule.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/UnityEngine.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/Editor/UnityEditor.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/Editor/UnityEditor.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/UnityEngine.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/net35/unity-custom/nunit.framework.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/Editor/UnityEditor.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/Editor/UnityEditor.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/RuntimeEditor/UnityEngine.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/Editor/UnityEditor.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TreeEditor/Editor/UnityEditor.TreeEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/Editor/UnityEditor.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/RuntimeEditor/UnityEngine.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/Editor/UnityEditor.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/RuntimeEditor/UnityEngine.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/Editor/UnityEditor.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityVR/Editor/UnityEditor.VR.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.Graphs.dll' --r:'/Applications/Unity/Unity.app/Contents/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/UnityEngine.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/Editor/UnityEditor.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/UnityEngine.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/Editor/UnityEditor.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/UnityEngine.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/Editor/UnityEditor.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.standardevents@1.0.10/UnityEngine.StandardEvents.dll' --define:UNITY_5_3_OR_NEWER --define:UNITY_5_4_OR_NEWER --define:UNITY_5_5_OR_NEWER --define:UNITY_5_6_OR_NEWER --define:UNITY_2017_1_OR_NEWER --define:UNITY_2017_2_OR_NEWER --define:UNITY_2017_3_OR_NEWER --define:UNITY_2017_3_1 --define:UNITY_2017_3 --define:UNITY_2017 --define:PLATFORM_ARCH_64 --define:UNITY_64 --define:ENABLE_AUDIO --define:ENABLE_CACHING --define:ENABLE_CLOTH --define:ENABLE_DUCK_TYPING --define:ENABLE_GENERICS --define:ENABLE_PVR_GI --define:ENABLE_MICROPHONE --define:ENABLE_MULTIPLE_DISPLAYS --define:ENABLE_PHYSICS --define:ENABLE_SPRITERENDERER_FLIPPING --define:ENABLE_SPRITES --define:ENABLE_GRID --define:ENABLE_TILEMAP --define:ENABLE_TERRAIN --define:ENABLE_RAKNET --define:ENABLE_DIRECTOR --define:ENABLE_UNET --define:ENABLE_LZMA --define:ENABLE_UNITYEVENTS --define:ENABLE_WEBCAM --define:ENABLE_WWW --define:ENABLE_CLOUD_SERVICES_COLLAB --define:ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS --define:ENABLE_CLOUD_SERVICES_ADS --define:ENABLE_CLOUD_HUB --define:ENABLE_CLOUD_PROJECT_ID --define:ENABLE_CLOUD_SERVICES_USE_WEBREQUEST --define:ENABLE_CLOUD_SERVICES_UNET --define:ENABLE_CLOUD_SERVICES_BUILD --define:ENABLE_CLOUD_LICENSE --define:ENABLE_EDITOR_HUB --define:ENABLE_EDITOR_HUB_LICENSE --define:ENABLE_WEBSOCKET_CLIENT --define:ENABLE_DIRECTOR_AUDIO --define:ENABLE_DIRECTOR_TEXTURE --define:ENABLE_TIMELINE --define:ENABLE_EDITOR_METRICS --define:ENABLE_EDITOR_METRICS_CACHING --define:ENABLE_NATIVE_ARRAY --define:ENABLE_SPRITE_MASKING --define:INCLUDE_DYNAMIC_GI --define:INCLUDE_GI --define:ENABLE_MONO_BDWGC --define:PLATFORM_SUPPORTS_MONO --define:RENDER_SOFTWARE_CURSOR --define:INCLUDE_PUBNUB --define:ENABLE_PLAYMODE_TESTS_RUNNER --define:ENABLE_VIDEO --define:ENABLE_RMGUI --define:ENABLE_PACKMAN --define:ENABLE_CUSTOM_RENDER_TEXTURE --define:ENABLE_STYLE_SHEETS --define:ENABLE_LOCALIZATION --define:PLATFORM_STANDALONE_OSX --define:PLATFORM_STANDALONE --define:UNITY_STANDALONE_OSX --define:UNITY_STANDALONE --define:ENABLE_SUBSTANCE --define:ENABLE_GAMECENTER --define:ENABLE_RUNTIME_GI --define:ENABLE_MOVIES --define:ENABLE_NETWORK --define:ENABLE_CRUNCH_TEXTURE_COMPRESSION --define:ENABLE_UNITYWEBREQUEST --define:ENABLE_CLOUD_SERVICES --define:ENABLE_CLOUD_SERVICES_ANALYTICS --define:ENABLE_CLOUD_SERVICES_PURCHASING --define:ENABLE_CLOUD_SERVICES_CRASH_REPORTING --define:ENABLE_CLOUD_SERVICES_NATIVE_CRASH_REPORTING --define:ENABLE_CLUSTERINPUT --define:ENABLE_VR --define:ENABLE_AR --define:ENABLE_SPATIALTRACKING --define:ENABLE_WEBSOCKET_HOST --define:ENABLE_MONO --define:NET_2_0_SUBSET --define:ENABLE_PROFILER --define:DEBUG --define:TRACE --define:UNITY_ASSERTIONS --define:UNITY_EDITOR --define:UNITY_EDITOR_64 --define:UNITY_EDITOR_OSX --define:ENABLE_NATIVE_ARRAY_CHECKS --define:UNITY_TEAM_LICENSE -'Assets/Lobby/Scripts/DraggablePanel.cs' -'Assets/Lobby/Scripts/EventSystemChecker.cs' -'Assets/Lobby/Scripts/Lobby/LobbyCountdownPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyHook.cs' -'Assets/Lobby/Scripts/Lobby/LobbyInfoPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyMainMenu.cs' -'Assets/Lobby/Scripts/Lobby/LobbyManager.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayer.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerEntry.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyTopPanel.cs' -'Assets/SampleScenes/Scripts/NetworkAsteroid.cs' -'Assets/SampleScenes/Scripts/NetworkGameManager.cs' -'Assets/SampleScenes/Scripts/NetworkLobbyHook.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceship.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceshipBullet.cs' -'Assets/Scripts/ColorManager.cs' -'Assets/Scripts/ColorOption.cs' -'Assets/Scripts/ColorPicker.cs' -'Assets/Scripts/DoneButtonPressed.cs' -'Assets/Scripts/DoodleShake.cs' -'Assets/Scripts/FadingTextAnimation.cs' -'Assets/Scripts/LoadSceneOnTap.cs' -'Assets/Scripts/RandomSprite.cs' -'Assets/Scripts/ScreenCapture.cs' -'Assets/Scripts/SizeManager.cs' -'Assets/Scripts/SwipeTrail.cs' -'Assets/Scripts/Timer.cs' -'Assets/Scripts/ToolsStateManager.cs' -'Assets/Scripts/ToolState.cs' -'Assets/Scripts/UIRaycastDetector.cs' -'Assets/Scripts/Width.cs' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Runtime.Serialization.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Xml.Linq.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.Lang.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/Boo.Lang.dll' --sdk:unity diff --git a/Close Enough!/Temp/UnityTempFile-599f78c1646414895853583e977cbac7 b/Close Enough!/Temp/UnityTempFile-599f78c1646414895853583e977cbac7 deleted file mode 100644 index 7ea43a3..0000000 --- a/Close Enough!/Temp/UnityTempFile-599f78c1646414895853583e977cbac7 +++ /dev/null @@ -1,218 +0,0 @@ --debug --target:library --nowarn:0169 --langversion:4 --out:'Temp/Assembly-CSharp.dll' --unsafe --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CoreModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AccessibilityModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticleSystemModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VehiclesModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClothModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AnimationModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TextRenderingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainPhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.IMGUIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterInputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterRendererModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UNETModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.DirectorModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityAnalyticsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PerformanceReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityConnectModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WebModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ARModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VRModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIElementsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.StyleSheetsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AssetBundleModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CrashReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GameCenterModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GridModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ImageConversionModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.InputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.JSONSerializeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticlesLegacyModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.Physics2DModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ScreenCaptureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SharedInternalsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteMaskModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteShapeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TilemapModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestAudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestTextureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestWWWModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VideoModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WindModule.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/UnityEngine.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/Editor/UnityEditor.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/Editor/UnityEditor.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/UnityEngine.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/net35/unity-custom/nunit.framework.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/Editor/UnityEditor.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/Editor/UnityEditor.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/RuntimeEditor/UnityEngine.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/Editor/UnityEditor.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TreeEditor/Editor/UnityEditor.TreeEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/Editor/UnityEditor.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/RuntimeEditor/UnityEngine.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/Editor/UnityEditor.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/RuntimeEditor/UnityEngine.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/Editor/UnityEditor.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityVR/Editor/UnityEditor.VR.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.Graphs.dll' --r:'/Applications/Unity/Unity.app/Contents/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/UnityEngine.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/Editor/UnityEditor.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/UnityEngine.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/Editor/UnityEditor.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/UnityEngine.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/Editor/UnityEditor.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.standardevents@1.0.10/UnityEngine.StandardEvents.dll' --define:UNITY_5_3_OR_NEWER --define:UNITY_5_4_OR_NEWER --define:UNITY_5_5_OR_NEWER --define:UNITY_5_6_OR_NEWER --define:UNITY_2017_1_OR_NEWER --define:UNITY_2017_2_OR_NEWER --define:UNITY_2017_3_OR_NEWER --define:UNITY_2017_3_1 --define:UNITY_2017_3 --define:UNITY_2017 --define:PLATFORM_ARCH_64 --define:UNITY_64 --define:ENABLE_AUDIO --define:ENABLE_CACHING --define:ENABLE_CLOTH --define:ENABLE_DUCK_TYPING --define:ENABLE_GENERICS --define:ENABLE_PVR_GI --define:ENABLE_MICROPHONE --define:ENABLE_MULTIPLE_DISPLAYS --define:ENABLE_PHYSICS --define:ENABLE_SPRITERENDERER_FLIPPING --define:ENABLE_SPRITES --define:ENABLE_GRID --define:ENABLE_TILEMAP --define:ENABLE_TERRAIN --define:ENABLE_RAKNET --define:ENABLE_DIRECTOR --define:ENABLE_UNET --define:ENABLE_LZMA --define:ENABLE_UNITYEVENTS --define:ENABLE_WEBCAM --define:ENABLE_WWW --define:ENABLE_CLOUD_SERVICES_COLLAB --define:ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS --define:ENABLE_CLOUD_SERVICES_ADS --define:ENABLE_CLOUD_HUB --define:ENABLE_CLOUD_PROJECT_ID --define:ENABLE_CLOUD_SERVICES_USE_WEBREQUEST --define:ENABLE_CLOUD_SERVICES_UNET --define:ENABLE_CLOUD_SERVICES_BUILD --define:ENABLE_CLOUD_LICENSE --define:ENABLE_EDITOR_HUB --define:ENABLE_EDITOR_HUB_LICENSE --define:ENABLE_WEBSOCKET_CLIENT --define:ENABLE_DIRECTOR_AUDIO --define:ENABLE_DIRECTOR_TEXTURE --define:ENABLE_TIMELINE --define:ENABLE_EDITOR_METRICS --define:ENABLE_EDITOR_METRICS_CACHING --define:ENABLE_NATIVE_ARRAY --define:ENABLE_SPRITE_MASKING --define:INCLUDE_DYNAMIC_GI --define:INCLUDE_GI --define:ENABLE_MONO_BDWGC --define:PLATFORM_SUPPORTS_MONO --define:RENDER_SOFTWARE_CURSOR --define:INCLUDE_PUBNUB --define:ENABLE_PLAYMODE_TESTS_RUNNER --define:ENABLE_VIDEO --define:ENABLE_RMGUI --define:ENABLE_PACKMAN --define:ENABLE_CUSTOM_RENDER_TEXTURE --define:ENABLE_STYLE_SHEETS --define:ENABLE_LOCALIZATION --define:PLATFORM_STANDALONE_OSX --define:PLATFORM_STANDALONE --define:UNITY_STANDALONE_OSX --define:UNITY_STANDALONE --define:ENABLE_SUBSTANCE --define:ENABLE_GAMECENTER --define:ENABLE_RUNTIME_GI --define:ENABLE_MOVIES --define:ENABLE_NETWORK --define:ENABLE_CRUNCH_TEXTURE_COMPRESSION --define:ENABLE_UNITYWEBREQUEST --define:ENABLE_CLOUD_SERVICES --define:ENABLE_CLOUD_SERVICES_ANALYTICS --define:ENABLE_CLOUD_SERVICES_PURCHASING --define:ENABLE_CLOUD_SERVICES_CRASH_REPORTING --define:ENABLE_CLOUD_SERVICES_NATIVE_CRASH_REPORTING --define:ENABLE_CLUSTERINPUT --define:ENABLE_VR --define:ENABLE_AR --define:ENABLE_SPATIALTRACKING --define:ENABLE_WEBSOCKET_HOST --define:ENABLE_MONO --define:NET_2_0_SUBSET --define:ENABLE_PROFILER --define:DEBUG --define:TRACE --define:UNITY_ASSERTIONS --define:UNITY_EDITOR --define:UNITY_EDITOR_64 --define:UNITY_EDITOR_OSX --define:ENABLE_NATIVE_ARRAY_CHECKS --define:UNITY_TEAM_LICENSE -'Assets/Lobby/Scripts/DraggablePanel.cs' -'Assets/Lobby/Scripts/EventSystemChecker.cs' -'Assets/Lobby/Scripts/Lobby/LobbyCountdownPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyHook.cs' -'Assets/Lobby/Scripts/Lobby/LobbyInfoPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyMainMenu.cs' -'Assets/Lobby/Scripts/Lobby/LobbyManager.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayer.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerEntry.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyTopPanel.cs' -'Assets/SampleScenes/Scripts/NetworkAsteroid.cs' -'Assets/SampleScenes/Scripts/NetworkGameManager.cs' -'Assets/SampleScenes/Scripts/NetworkLobbyHook.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceship.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceshipBullet.cs' -'Assets/Scripts/ColorManager.cs' -'Assets/Scripts/ColorOption.cs' -'Assets/Scripts/ColorPicker.cs' -'Assets/Scripts/DoneButtonPressed.cs' -'Assets/Scripts/DoodleShake.cs' -'Assets/Scripts/FadingTextAnimation.cs' -'Assets/Scripts/LoadSceneOnTap.cs' -'Assets/Scripts/RandomSprite.cs' -'Assets/Scripts/ScreenCapture.cs' -'Assets/Scripts/SizeManager.cs' -'Assets/Scripts/SwipeTrail.cs' -'Assets/Scripts/Timer.cs' -'Assets/Scripts/ToolsStateManager.cs' -'Assets/Scripts/ToolState.cs' -'Assets/Scripts/UIRaycastDetector.cs' -'Assets/Scripts/Width.cs' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Runtime.Serialization.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Xml.Linq.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.Lang.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/Boo.Lang.dll' --sdk:unity diff --git a/Close Enough!/Temp/UnityTempFile-5eb0c54cb392445e6b6d5c30fd5516da b/Close Enough!/Temp/UnityTempFile-5eb0c54cb392445e6b6d5c30fd5516da deleted file mode 100644 index 7ea43a3..0000000 --- a/Close Enough!/Temp/UnityTempFile-5eb0c54cb392445e6b6d5c30fd5516da +++ /dev/null @@ -1,218 +0,0 @@ --debug --target:library --nowarn:0169 --langversion:4 --out:'Temp/Assembly-CSharp.dll' --unsafe --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CoreModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AccessibilityModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticleSystemModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VehiclesModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClothModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AnimationModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TextRenderingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainPhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.IMGUIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterInputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterRendererModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UNETModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.DirectorModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityAnalyticsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PerformanceReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityConnectModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WebModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ARModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VRModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIElementsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.StyleSheetsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AssetBundleModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CrashReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GameCenterModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GridModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ImageConversionModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.InputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.JSONSerializeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticlesLegacyModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.Physics2DModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ScreenCaptureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SharedInternalsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteMaskModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteShapeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TilemapModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestAudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestTextureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestWWWModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VideoModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WindModule.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/UnityEngine.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/Editor/UnityEditor.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/Editor/UnityEditor.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/UnityEngine.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/net35/unity-custom/nunit.framework.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/Editor/UnityEditor.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/Editor/UnityEditor.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/RuntimeEditor/UnityEngine.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/Editor/UnityEditor.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TreeEditor/Editor/UnityEditor.TreeEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/Editor/UnityEditor.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/RuntimeEditor/UnityEngine.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/Editor/UnityEditor.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/RuntimeEditor/UnityEngine.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/Editor/UnityEditor.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityVR/Editor/UnityEditor.VR.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.Graphs.dll' --r:'/Applications/Unity/Unity.app/Contents/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/UnityEngine.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/Editor/UnityEditor.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/UnityEngine.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/Editor/UnityEditor.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/UnityEngine.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/Editor/UnityEditor.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.standardevents@1.0.10/UnityEngine.StandardEvents.dll' --define:UNITY_5_3_OR_NEWER --define:UNITY_5_4_OR_NEWER --define:UNITY_5_5_OR_NEWER --define:UNITY_5_6_OR_NEWER --define:UNITY_2017_1_OR_NEWER --define:UNITY_2017_2_OR_NEWER --define:UNITY_2017_3_OR_NEWER --define:UNITY_2017_3_1 --define:UNITY_2017_3 --define:UNITY_2017 --define:PLATFORM_ARCH_64 --define:UNITY_64 --define:ENABLE_AUDIO --define:ENABLE_CACHING --define:ENABLE_CLOTH --define:ENABLE_DUCK_TYPING --define:ENABLE_GENERICS --define:ENABLE_PVR_GI --define:ENABLE_MICROPHONE --define:ENABLE_MULTIPLE_DISPLAYS --define:ENABLE_PHYSICS --define:ENABLE_SPRITERENDERER_FLIPPING --define:ENABLE_SPRITES --define:ENABLE_GRID --define:ENABLE_TILEMAP --define:ENABLE_TERRAIN --define:ENABLE_RAKNET --define:ENABLE_DIRECTOR --define:ENABLE_UNET --define:ENABLE_LZMA --define:ENABLE_UNITYEVENTS --define:ENABLE_WEBCAM --define:ENABLE_WWW --define:ENABLE_CLOUD_SERVICES_COLLAB --define:ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS --define:ENABLE_CLOUD_SERVICES_ADS --define:ENABLE_CLOUD_HUB --define:ENABLE_CLOUD_PROJECT_ID --define:ENABLE_CLOUD_SERVICES_USE_WEBREQUEST --define:ENABLE_CLOUD_SERVICES_UNET --define:ENABLE_CLOUD_SERVICES_BUILD --define:ENABLE_CLOUD_LICENSE --define:ENABLE_EDITOR_HUB --define:ENABLE_EDITOR_HUB_LICENSE --define:ENABLE_WEBSOCKET_CLIENT --define:ENABLE_DIRECTOR_AUDIO --define:ENABLE_DIRECTOR_TEXTURE --define:ENABLE_TIMELINE --define:ENABLE_EDITOR_METRICS --define:ENABLE_EDITOR_METRICS_CACHING --define:ENABLE_NATIVE_ARRAY --define:ENABLE_SPRITE_MASKING --define:INCLUDE_DYNAMIC_GI --define:INCLUDE_GI --define:ENABLE_MONO_BDWGC --define:PLATFORM_SUPPORTS_MONO --define:RENDER_SOFTWARE_CURSOR --define:INCLUDE_PUBNUB --define:ENABLE_PLAYMODE_TESTS_RUNNER --define:ENABLE_VIDEO --define:ENABLE_RMGUI --define:ENABLE_PACKMAN --define:ENABLE_CUSTOM_RENDER_TEXTURE --define:ENABLE_STYLE_SHEETS --define:ENABLE_LOCALIZATION --define:PLATFORM_STANDALONE_OSX --define:PLATFORM_STANDALONE --define:UNITY_STANDALONE_OSX --define:UNITY_STANDALONE --define:ENABLE_SUBSTANCE --define:ENABLE_GAMECENTER --define:ENABLE_RUNTIME_GI --define:ENABLE_MOVIES --define:ENABLE_NETWORK --define:ENABLE_CRUNCH_TEXTURE_COMPRESSION --define:ENABLE_UNITYWEBREQUEST --define:ENABLE_CLOUD_SERVICES --define:ENABLE_CLOUD_SERVICES_ANALYTICS --define:ENABLE_CLOUD_SERVICES_PURCHASING --define:ENABLE_CLOUD_SERVICES_CRASH_REPORTING --define:ENABLE_CLOUD_SERVICES_NATIVE_CRASH_REPORTING --define:ENABLE_CLUSTERINPUT --define:ENABLE_VR --define:ENABLE_AR --define:ENABLE_SPATIALTRACKING --define:ENABLE_WEBSOCKET_HOST --define:ENABLE_MONO --define:NET_2_0_SUBSET --define:ENABLE_PROFILER --define:DEBUG --define:TRACE --define:UNITY_ASSERTIONS --define:UNITY_EDITOR --define:UNITY_EDITOR_64 --define:UNITY_EDITOR_OSX --define:ENABLE_NATIVE_ARRAY_CHECKS --define:UNITY_TEAM_LICENSE -'Assets/Lobby/Scripts/DraggablePanel.cs' -'Assets/Lobby/Scripts/EventSystemChecker.cs' -'Assets/Lobby/Scripts/Lobby/LobbyCountdownPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyHook.cs' -'Assets/Lobby/Scripts/Lobby/LobbyInfoPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyMainMenu.cs' -'Assets/Lobby/Scripts/Lobby/LobbyManager.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayer.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerEntry.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyTopPanel.cs' -'Assets/SampleScenes/Scripts/NetworkAsteroid.cs' -'Assets/SampleScenes/Scripts/NetworkGameManager.cs' -'Assets/SampleScenes/Scripts/NetworkLobbyHook.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceship.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceshipBullet.cs' -'Assets/Scripts/ColorManager.cs' -'Assets/Scripts/ColorOption.cs' -'Assets/Scripts/ColorPicker.cs' -'Assets/Scripts/DoneButtonPressed.cs' -'Assets/Scripts/DoodleShake.cs' -'Assets/Scripts/FadingTextAnimation.cs' -'Assets/Scripts/LoadSceneOnTap.cs' -'Assets/Scripts/RandomSprite.cs' -'Assets/Scripts/ScreenCapture.cs' -'Assets/Scripts/SizeManager.cs' -'Assets/Scripts/SwipeTrail.cs' -'Assets/Scripts/Timer.cs' -'Assets/Scripts/ToolsStateManager.cs' -'Assets/Scripts/ToolState.cs' -'Assets/Scripts/UIRaycastDetector.cs' -'Assets/Scripts/Width.cs' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Runtime.Serialization.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Xml.Linq.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.Lang.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/Boo.Lang.dll' --sdk:unity diff --git a/Close Enough!/Temp/UnityTempFile-666a0a7ac2fa341ca81c69dc626b91ab b/Close Enough!/Temp/UnityTempFile-666a0a7ac2fa341ca81c69dc626b91ab deleted file mode 100644 index 7ea43a3..0000000 --- a/Close Enough!/Temp/UnityTempFile-666a0a7ac2fa341ca81c69dc626b91ab +++ /dev/null @@ -1,218 +0,0 @@ --debug --target:library --nowarn:0169 --langversion:4 --out:'Temp/Assembly-CSharp.dll' --unsafe --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CoreModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AccessibilityModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticleSystemModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VehiclesModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClothModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AnimationModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TextRenderingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainPhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.IMGUIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterInputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterRendererModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UNETModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.DirectorModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityAnalyticsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PerformanceReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityConnectModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WebModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ARModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VRModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIElementsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.StyleSheetsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AssetBundleModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CrashReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GameCenterModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GridModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ImageConversionModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.InputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.JSONSerializeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticlesLegacyModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.Physics2DModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ScreenCaptureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SharedInternalsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteMaskModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteShapeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TilemapModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestAudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestTextureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestWWWModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VideoModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WindModule.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/UnityEngine.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/Editor/UnityEditor.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/Editor/UnityEditor.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/UnityEngine.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/net35/unity-custom/nunit.framework.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/Editor/UnityEditor.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/Editor/UnityEditor.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/RuntimeEditor/UnityEngine.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/Editor/UnityEditor.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TreeEditor/Editor/UnityEditor.TreeEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/Editor/UnityEditor.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/RuntimeEditor/UnityEngine.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/Editor/UnityEditor.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/RuntimeEditor/UnityEngine.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/Editor/UnityEditor.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityVR/Editor/UnityEditor.VR.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.Graphs.dll' --r:'/Applications/Unity/Unity.app/Contents/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/UnityEngine.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/Editor/UnityEditor.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/UnityEngine.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/Editor/UnityEditor.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/UnityEngine.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/Editor/UnityEditor.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.standardevents@1.0.10/UnityEngine.StandardEvents.dll' --define:UNITY_5_3_OR_NEWER --define:UNITY_5_4_OR_NEWER --define:UNITY_5_5_OR_NEWER --define:UNITY_5_6_OR_NEWER --define:UNITY_2017_1_OR_NEWER --define:UNITY_2017_2_OR_NEWER --define:UNITY_2017_3_OR_NEWER --define:UNITY_2017_3_1 --define:UNITY_2017_3 --define:UNITY_2017 --define:PLATFORM_ARCH_64 --define:UNITY_64 --define:ENABLE_AUDIO --define:ENABLE_CACHING --define:ENABLE_CLOTH --define:ENABLE_DUCK_TYPING --define:ENABLE_GENERICS --define:ENABLE_PVR_GI --define:ENABLE_MICROPHONE --define:ENABLE_MULTIPLE_DISPLAYS --define:ENABLE_PHYSICS --define:ENABLE_SPRITERENDERER_FLIPPING --define:ENABLE_SPRITES --define:ENABLE_GRID --define:ENABLE_TILEMAP --define:ENABLE_TERRAIN --define:ENABLE_RAKNET --define:ENABLE_DIRECTOR --define:ENABLE_UNET --define:ENABLE_LZMA --define:ENABLE_UNITYEVENTS --define:ENABLE_WEBCAM --define:ENABLE_WWW --define:ENABLE_CLOUD_SERVICES_COLLAB --define:ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS --define:ENABLE_CLOUD_SERVICES_ADS --define:ENABLE_CLOUD_HUB --define:ENABLE_CLOUD_PROJECT_ID --define:ENABLE_CLOUD_SERVICES_USE_WEBREQUEST --define:ENABLE_CLOUD_SERVICES_UNET --define:ENABLE_CLOUD_SERVICES_BUILD --define:ENABLE_CLOUD_LICENSE --define:ENABLE_EDITOR_HUB --define:ENABLE_EDITOR_HUB_LICENSE --define:ENABLE_WEBSOCKET_CLIENT --define:ENABLE_DIRECTOR_AUDIO --define:ENABLE_DIRECTOR_TEXTURE --define:ENABLE_TIMELINE --define:ENABLE_EDITOR_METRICS --define:ENABLE_EDITOR_METRICS_CACHING --define:ENABLE_NATIVE_ARRAY --define:ENABLE_SPRITE_MASKING --define:INCLUDE_DYNAMIC_GI --define:INCLUDE_GI --define:ENABLE_MONO_BDWGC --define:PLATFORM_SUPPORTS_MONO --define:RENDER_SOFTWARE_CURSOR --define:INCLUDE_PUBNUB --define:ENABLE_PLAYMODE_TESTS_RUNNER --define:ENABLE_VIDEO --define:ENABLE_RMGUI --define:ENABLE_PACKMAN --define:ENABLE_CUSTOM_RENDER_TEXTURE --define:ENABLE_STYLE_SHEETS --define:ENABLE_LOCALIZATION --define:PLATFORM_STANDALONE_OSX --define:PLATFORM_STANDALONE --define:UNITY_STANDALONE_OSX --define:UNITY_STANDALONE --define:ENABLE_SUBSTANCE --define:ENABLE_GAMECENTER --define:ENABLE_RUNTIME_GI --define:ENABLE_MOVIES --define:ENABLE_NETWORK --define:ENABLE_CRUNCH_TEXTURE_COMPRESSION --define:ENABLE_UNITYWEBREQUEST --define:ENABLE_CLOUD_SERVICES --define:ENABLE_CLOUD_SERVICES_ANALYTICS --define:ENABLE_CLOUD_SERVICES_PURCHASING --define:ENABLE_CLOUD_SERVICES_CRASH_REPORTING --define:ENABLE_CLOUD_SERVICES_NATIVE_CRASH_REPORTING --define:ENABLE_CLUSTERINPUT --define:ENABLE_VR --define:ENABLE_AR --define:ENABLE_SPATIALTRACKING --define:ENABLE_WEBSOCKET_HOST --define:ENABLE_MONO --define:NET_2_0_SUBSET --define:ENABLE_PROFILER --define:DEBUG --define:TRACE --define:UNITY_ASSERTIONS --define:UNITY_EDITOR --define:UNITY_EDITOR_64 --define:UNITY_EDITOR_OSX --define:ENABLE_NATIVE_ARRAY_CHECKS --define:UNITY_TEAM_LICENSE -'Assets/Lobby/Scripts/DraggablePanel.cs' -'Assets/Lobby/Scripts/EventSystemChecker.cs' -'Assets/Lobby/Scripts/Lobby/LobbyCountdownPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyHook.cs' -'Assets/Lobby/Scripts/Lobby/LobbyInfoPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyMainMenu.cs' -'Assets/Lobby/Scripts/Lobby/LobbyManager.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayer.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerEntry.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyTopPanel.cs' -'Assets/SampleScenes/Scripts/NetworkAsteroid.cs' -'Assets/SampleScenes/Scripts/NetworkGameManager.cs' -'Assets/SampleScenes/Scripts/NetworkLobbyHook.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceship.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceshipBullet.cs' -'Assets/Scripts/ColorManager.cs' -'Assets/Scripts/ColorOption.cs' -'Assets/Scripts/ColorPicker.cs' -'Assets/Scripts/DoneButtonPressed.cs' -'Assets/Scripts/DoodleShake.cs' -'Assets/Scripts/FadingTextAnimation.cs' -'Assets/Scripts/LoadSceneOnTap.cs' -'Assets/Scripts/RandomSprite.cs' -'Assets/Scripts/ScreenCapture.cs' -'Assets/Scripts/SizeManager.cs' -'Assets/Scripts/SwipeTrail.cs' -'Assets/Scripts/Timer.cs' -'Assets/Scripts/ToolsStateManager.cs' -'Assets/Scripts/ToolState.cs' -'Assets/Scripts/UIRaycastDetector.cs' -'Assets/Scripts/Width.cs' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Runtime.Serialization.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Xml.Linq.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.Lang.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/Boo.Lang.dll' --sdk:unity diff --git a/Close Enough!/Temp/UnityTempFile-6935fa4a93ca748d5a04f0893efc6bbc b/Close Enough!/Temp/UnityTempFile-6935fa4a93ca748d5a04f0893efc6bbc deleted file mode 100644 index d0c48f7..0000000 --- a/Close Enough!/Temp/UnityTempFile-6935fa4a93ca748d5a04f0893efc6bbc +++ /dev/null @@ -1,201 +0,0 @@ --debug --target:library --nowarn:0169 --langversion:4 --out:'Temp/Assembly-CSharp.dll' --unsafe --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CoreModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AccessibilityModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticleSystemModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VehiclesModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClothModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AnimationModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TextRenderingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainPhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.IMGUIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterInputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterRendererModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UNETModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.DirectorModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityAnalyticsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PerformanceReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityConnectModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WebModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ARModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VRModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIElementsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.StyleSheetsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AssetBundleModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CrashReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GameCenterModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GridModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ImageConversionModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.InputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.JSONSerializeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticlesLegacyModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.Physics2DModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ScreenCaptureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SharedInternalsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteMaskModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteShapeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TilemapModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestAudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestTextureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestWWWModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VideoModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WindModule.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/UnityEngine.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/Editor/UnityEditor.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/Editor/UnityEditor.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/UnityEngine.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/net35/unity-custom/nunit.framework.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/Editor/UnityEditor.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/Editor/UnityEditor.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/RuntimeEditor/UnityEngine.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/Editor/UnityEditor.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TreeEditor/Editor/UnityEditor.TreeEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/Editor/UnityEditor.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/RuntimeEditor/UnityEngine.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/Editor/UnityEditor.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/RuntimeEditor/UnityEngine.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/Editor/UnityEditor.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityVR/Editor/UnityEditor.VR.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.Graphs.dll' --r:'/Applications/Unity/Unity.app/Contents/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/UnityEngine.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/Editor/UnityEditor.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/UnityEngine.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/Editor/UnityEditor.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/UnityEngine.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/Editor/UnityEditor.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.standardevents@1.0.10/UnityEngine.StandardEvents.dll' --define:UNITY_5_3_OR_NEWER --define:UNITY_5_4_OR_NEWER --define:UNITY_5_5_OR_NEWER --define:UNITY_5_6_OR_NEWER --define:UNITY_2017_1_OR_NEWER --define:UNITY_2017_2_OR_NEWER --define:UNITY_2017_3_OR_NEWER --define:UNITY_2017_3_1 --define:UNITY_2017_3 --define:UNITY_2017 --define:PLATFORM_ARCH_64 --define:UNITY_64 --define:ENABLE_AUDIO --define:ENABLE_CACHING --define:ENABLE_CLOTH --define:ENABLE_DUCK_TYPING --define:ENABLE_GENERICS --define:ENABLE_PVR_GI --define:ENABLE_MICROPHONE --define:ENABLE_MULTIPLE_DISPLAYS --define:ENABLE_PHYSICS --define:ENABLE_SPRITERENDERER_FLIPPING --define:ENABLE_SPRITES --define:ENABLE_GRID --define:ENABLE_TILEMAP --define:ENABLE_TERRAIN --define:ENABLE_RAKNET --define:ENABLE_DIRECTOR --define:ENABLE_UNET --define:ENABLE_LZMA --define:ENABLE_UNITYEVENTS --define:ENABLE_WEBCAM --define:ENABLE_WWW --define:ENABLE_CLOUD_SERVICES_COLLAB --define:ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS --define:ENABLE_CLOUD_SERVICES_ADS --define:ENABLE_CLOUD_HUB --define:ENABLE_CLOUD_PROJECT_ID --define:ENABLE_CLOUD_SERVICES_USE_WEBREQUEST --define:ENABLE_CLOUD_SERVICES_UNET --define:ENABLE_CLOUD_SERVICES_BUILD --define:ENABLE_CLOUD_LICENSE --define:ENABLE_EDITOR_HUB --define:ENABLE_EDITOR_HUB_LICENSE --define:ENABLE_WEBSOCKET_CLIENT --define:ENABLE_DIRECTOR_AUDIO --define:ENABLE_DIRECTOR_TEXTURE --define:ENABLE_TIMELINE --define:ENABLE_EDITOR_METRICS --define:ENABLE_EDITOR_METRICS_CACHING --define:ENABLE_NATIVE_ARRAY --define:ENABLE_SPRITE_MASKING --define:INCLUDE_DYNAMIC_GI --define:INCLUDE_GI --define:ENABLE_MONO_BDWGC --define:PLATFORM_SUPPORTS_MONO --define:RENDER_SOFTWARE_CURSOR --define:INCLUDE_PUBNUB --define:ENABLE_PLAYMODE_TESTS_RUNNER --define:ENABLE_VIDEO --define:ENABLE_RMGUI --define:ENABLE_PACKMAN --define:ENABLE_CUSTOM_RENDER_TEXTURE --define:ENABLE_STYLE_SHEETS --define:ENABLE_LOCALIZATION --define:PLATFORM_STANDALONE_OSX --define:PLATFORM_STANDALONE --define:UNITY_STANDALONE_OSX --define:UNITY_STANDALONE --define:ENABLE_SUBSTANCE --define:ENABLE_GAMECENTER --define:ENABLE_RUNTIME_GI --define:ENABLE_MOVIES --define:ENABLE_NETWORK --define:ENABLE_CRUNCH_TEXTURE_COMPRESSION --define:ENABLE_UNITYWEBREQUEST --define:ENABLE_CLOUD_SERVICES --define:ENABLE_CLOUD_SERVICES_ANALYTICS --define:ENABLE_CLOUD_SERVICES_PURCHASING --define:ENABLE_CLOUD_SERVICES_CRASH_REPORTING --define:ENABLE_CLOUD_SERVICES_NATIVE_CRASH_REPORTING --define:ENABLE_CLUSTERINPUT --define:ENABLE_VR --define:ENABLE_AR --define:ENABLE_SPATIALTRACKING --define:ENABLE_WEBSOCKET_HOST --define:ENABLE_MONO --define:NET_2_0_SUBSET --define:ENABLE_PROFILER --define:DEBUG --define:TRACE --define:UNITY_ASSERTIONS --define:UNITY_EDITOR --define:UNITY_EDITOR_64 --define:UNITY_EDITOR_OSX --define:ENABLE_NATIVE_ARRAY_CHECKS --define:UNITY_TEAM_LICENSE -'Assets/Scripts/ColorManager.cs' -'Assets/Scripts/ColorOption.cs' -'Assets/Scripts/ColorPicker.cs' -'Assets/Scripts/DoneButtonPressed.cs' -'Assets/Scripts/DoodleShake.cs' -'Assets/Scripts/FadingTextAnimation.cs' -'Assets/Scripts/LoadSceneOnTap.cs' -'Assets/Scripts/RandomSprite.cs' -'Assets/Scripts/ScreenCapture.cs' -'Assets/Scripts/SizeManager.cs' -'Assets/Scripts/SwipeTrail.cs' -'Assets/Scripts/Timer.cs' -'Assets/Scripts/ToolsStateManager.cs' -'Assets/Scripts/ToolState.cs' -'Assets/Scripts/UIRaycastDetector.cs' -'Assets/Scripts/Width.cs' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Runtime.Serialization.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Xml.Linq.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.Lang.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/Boo.Lang.dll' --sdk:unity diff --git a/Close Enough!/Temp/UnityTempFile-8b2cc79e7e66c4993a28a6b49d92c20f b/Close Enough!/Temp/UnityTempFile-8b2cc79e7e66c4993a28a6b49d92c20f deleted file mode 100644 index 7ea43a3..0000000 --- a/Close Enough!/Temp/UnityTempFile-8b2cc79e7e66c4993a28a6b49d92c20f +++ /dev/null @@ -1,218 +0,0 @@ --debug --target:library --nowarn:0169 --langversion:4 --out:'Temp/Assembly-CSharp.dll' --unsafe --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CoreModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AccessibilityModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticleSystemModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VehiclesModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClothModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AnimationModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TextRenderingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainPhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.IMGUIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterInputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterRendererModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UNETModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.DirectorModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityAnalyticsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PerformanceReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityConnectModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WebModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ARModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VRModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIElementsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.StyleSheetsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AssetBundleModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CrashReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GameCenterModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GridModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ImageConversionModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.InputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.JSONSerializeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticlesLegacyModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.Physics2DModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ScreenCaptureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SharedInternalsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteMaskModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteShapeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TilemapModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestAudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestTextureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestWWWModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VideoModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WindModule.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/UnityEngine.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/Editor/UnityEditor.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/Editor/UnityEditor.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/UnityEngine.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/net35/unity-custom/nunit.framework.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/Editor/UnityEditor.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/Editor/UnityEditor.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/RuntimeEditor/UnityEngine.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/Editor/UnityEditor.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TreeEditor/Editor/UnityEditor.TreeEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/Editor/UnityEditor.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/RuntimeEditor/UnityEngine.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/Editor/UnityEditor.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/RuntimeEditor/UnityEngine.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/Editor/UnityEditor.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityVR/Editor/UnityEditor.VR.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.Graphs.dll' --r:'/Applications/Unity/Unity.app/Contents/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/UnityEngine.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/Editor/UnityEditor.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/UnityEngine.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/Editor/UnityEditor.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/UnityEngine.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/Editor/UnityEditor.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.standardevents@1.0.10/UnityEngine.StandardEvents.dll' --define:UNITY_5_3_OR_NEWER --define:UNITY_5_4_OR_NEWER --define:UNITY_5_5_OR_NEWER --define:UNITY_5_6_OR_NEWER --define:UNITY_2017_1_OR_NEWER --define:UNITY_2017_2_OR_NEWER --define:UNITY_2017_3_OR_NEWER --define:UNITY_2017_3_1 --define:UNITY_2017_3 --define:UNITY_2017 --define:PLATFORM_ARCH_64 --define:UNITY_64 --define:ENABLE_AUDIO --define:ENABLE_CACHING --define:ENABLE_CLOTH --define:ENABLE_DUCK_TYPING --define:ENABLE_GENERICS --define:ENABLE_PVR_GI --define:ENABLE_MICROPHONE --define:ENABLE_MULTIPLE_DISPLAYS --define:ENABLE_PHYSICS --define:ENABLE_SPRITERENDERER_FLIPPING --define:ENABLE_SPRITES --define:ENABLE_GRID --define:ENABLE_TILEMAP --define:ENABLE_TERRAIN --define:ENABLE_RAKNET --define:ENABLE_DIRECTOR --define:ENABLE_UNET --define:ENABLE_LZMA --define:ENABLE_UNITYEVENTS --define:ENABLE_WEBCAM --define:ENABLE_WWW --define:ENABLE_CLOUD_SERVICES_COLLAB --define:ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS --define:ENABLE_CLOUD_SERVICES_ADS --define:ENABLE_CLOUD_HUB --define:ENABLE_CLOUD_PROJECT_ID --define:ENABLE_CLOUD_SERVICES_USE_WEBREQUEST --define:ENABLE_CLOUD_SERVICES_UNET --define:ENABLE_CLOUD_SERVICES_BUILD --define:ENABLE_CLOUD_LICENSE --define:ENABLE_EDITOR_HUB --define:ENABLE_EDITOR_HUB_LICENSE --define:ENABLE_WEBSOCKET_CLIENT --define:ENABLE_DIRECTOR_AUDIO --define:ENABLE_DIRECTOR_TEXTURE --define:ENABLE_TIMELINE --define:ENABLE_EDITOR_METRICS --define:ENABLE_EDITOR_METRICS_CACHING --define:ENABLE_NATIVE_ARRAY --define:ENABLE_SPRITE_MASKING --define:INCLUDE_DYNAMIC_GI --define:INCLUDE_GI --define:ENABLE_MONO_BDWGC --define:PLATFORM_SUPPORTS_MONO --define:RENDER_SOFTWARE_CURSOR --define:INCLUDE_PUBNUB --define:ENABLE_PLAYMODE_TESTS_RUNNER --define:ENABLE_VIDEO --define:ENABLE_RMGUI --define:ENABLE_PACKMAN --define:ENABLE_CUSTOM_RENDER_TEXTURE --define:ENABLE_STYLE_SHEETS --define:ENABLE_LOCALIZATION --define:PLATFORM_STANDALONE_OSX --define:PLATFORM_STANDALONE --define:UNITY_STANDALONE_OSX --define:UNITY_STANDALONE --define:ENABLE_SUBSTANCE --define:ENABLE_GAMECENTER --define:ENABLE_RUNTIME_GI --define:ENABLE_MOVIES --define:ENABLE_NETWORK --define:ENABLE_CRUNCH_TEXTURE_COMPRESSION --define:ENABLE_UNITYWEBREQUEST --define:ENABLE_CLOUD_SERVICES --define:ENABLE_CLOUD_SERVICES_ANALYTICS --define:ENABLE_CLOUD_SERVICES_PURCHASING --define:ENABLE_CLOUD_SERVICES_CRASH_REPORTING --define:ENABLE_CLOUD_SERVICES_NATIVE_CRASH_REPORTING --define:ENABLE_CLUSTERINPUT --define:ENABLE_VR --define:ENABLE_AR --define:ENABLE_SPATIALTRACKING --define:ENABLE_WEBSOCKET_HOST --define:ENABLE_MONO --define:NET_2_0_SUBSET --define:ENABLE_PROFILER --define:DEBUG --define:TRACE --define:UNITY_ASSERTIONS --define:UNITY_EDITOR --define:UNITY_EDITOR_64 --define:UNITY_EDITOR_OSX --define:ENABLE_NATIVE_ARRAY_CHECKS --define:UNITY_TEAM_LICENSE -'Assets/Lobby/Scripts/DraggablePanel.cs' -'Assets/Lobby/Scripts/EventSystemChecker.cs' -'Assets/Lobby/Scripts/Lobby/LobbyCountdownPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyHook.cs' -'Assets/Lobby/Scripts/Lobby/LobbyInfoPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyMainMenu.cs' -'Assets/Lobby/Scripts/Lobby/LobbyManager.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayer.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerEntry.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyTopPanel.cs' -'Assets/SampleScenes/Scripts/NetworkAsteroid.cs' -'Assets/SampleScenes/Scripts/NetworkGameManager.cs' -'Assets/SampleScenes/Scripts/NetworkLobbyHook.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceship.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceshipBullet.cs' -'Assets/Scripts/ColorManager.cs' -'Assets/Scripts/ColorOption.cs' -'Assets/Scripts/ColorPicker.cs' -'Assets/Scripts/DoneButtonPressed.cs' -'Assets/Scripts/DoodleShake.cs' -'Assets/Scripts/FadingTextAnimation.cs' -'Assets/Scripts/LoadSceneOnTap.cs' -'Assets/Scripts/RandomSprite.cs' -'Assets/Scripts/ScreenCapture.cs' -'Assets/Scripts/SizeManager.cs' -'Assets/Scripts/SwipeTrail.cs' -'Assets/Scripts/Timer.cs' -'Assets/Scripts/ToolsStateManager.cs' -'Assets/Scripts/ToolState.cs' -'Assets/Scripts/UIRaycastDetector.cs' -'Assets/Scripts/Width.cs' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Runtime.Serialization.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Xml.Linq.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.Lang.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/Boo.Lang.dll' --sdk:unity diff --git a/Close Enough!/Temp/UnityTempFile-b769cd41976dd4d82a1caad834d371ab b/Close Enough!/Temp/UnityTempFile-b769cd41976dd4d82a1caad834d371ab deleted file mode 100644 index 7ea43a3..0000000 --- a/Close Enough!/Temp/UnityTempFile-b769cd41976dd4d82a1caad834d371ab +++ /dev/null @@ -1,218 +0,0 @@ --debug --target:library --nowarn:0169 --langversion:4 --out:'Temp/Assembly-CSharp.dll' --unsafe --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CoreModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AccessibilityModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticleSystemModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VehiclesModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClothModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AnimationModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TextRenderingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainPhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.IMGUIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterInputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterRendererModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UNETModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.DirectorModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityAnalyticsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PerformanceReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityConnectModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WebModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ARModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VRModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIElementsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.StyleSheetsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AssetBundleModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CrashReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GameCenterModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GridModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ImageConversionModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.InputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.JSONSerializeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticlesLegacyModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.Physics2DModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ScreenCaptureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SharedInternalsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteMaskModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteShapeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TilemapModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestAudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestTextureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestWWWModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VideoModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WindModule.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/UnityEngine.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/Editor/UnityEditor.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/Editor/UnityEditor.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/UnityEngine.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/net35/unity-custom/nunit.framework.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/Editor/UnityEditor.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/Editor/UnityEditor.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/RuntimeEditor/UnityEngine.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/Editor/UnityEditor.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TreeEditor/Editor/UnityEditor.TreeEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/Editor/UnityEditor.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/RuntimeEditor/UnityEngine.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/Editor/UnityEditor.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/RuntimeEditor/UnityEngine.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/Editor/UnityEditor.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityVR/Editor/UnityEditor.VR.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.Graphs.dll' --r:'/Applications/Unity/Unity.app/Contents/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/UnityEngine.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/Editor/UnityEditor.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/UnityEngine.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/Editor/UnityEditor.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/UnityEngine.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/Editor/UnityEditor.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.standardevents@1.0.10/UnityEngine.StandardEvents.dll' --define:UNITY_5_3_OR_NEWER --define:UNITY_5_4_OR_NEWER --define:UNITY_5_5_OR_NEWER --define:UNITY_5_6_OR_NEWER --define:UNITY_2017_1_OR_NEWER --define:UNITY_2017_2_OR_NEWER --define:UNITY_2017_3_OR_NEWER --define:UNITY_2017_3_1 --define:UNITY_2017_3 --define:UNITY_2017 --define:PLATFORM_ARCH_64 --define:UNITY_64 --define:ENABLE_AUDIO --define:ENABLE_CACHING --define:ENABLE_CLOTH --define:ENABLE_DUCK_TYPING --define:ENABLE_GENERICS --define:ENABLE_PVR_GI --define:ENABLE_MICROPHONE --define:ENABLE_MULTIPLE_DISPLAYS --define:ENABLE_PHYSICS --define:ENABLE_SPRITERENDERER_FLIPPING --define:ENABLE_SPRITES --define:ENABLE_GRID --define:ENABLE_TILEMAP --define:ENABLE_TERRAIN --define:ENABLE_RAKNET --define:ENABLE_DIRECTOR --define:ENABLE_UNET --define:ENABLE_LZMA --define:ENABLE_UNITYEVENTS --define:ENABLE_WEBCAM --define:ENABLE_WWW --define:ENABLE_CLOUD_SERVICES_COLLAB --define:ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS --define:ENABLE_CLOUD_SERVICES_ADS --define:ENABLE_CLOUD_HUB --define:ENABLE_CLOUD_PROJECT_ID --define:ENABLE_CLOUD_SERVICES_USE_WEBREQUEST --define:ENABLE_CLOUD_SERVICES_UNET --define:ENABLE_CLOUD_SERVICES_BUILD --define:ENABLE_CLOUD_LICENSE --define:ENABLE_EDITOR_HUB --define:ENABLE_EDITOR_HUB_LICENSE --define:ENABLE_WEBSOCKET_CLIENT --define:ENABLE_DIRECTOR_AUDIO --define:ENABLE_DIRECTOR_TEXTURE --define:ENABLE_TIMELINE --define:ENABLE_EDITOR_METRICS --define:ENABLE_EDITOR_METRICS_CACHING --define:ENABLE_NATIVE_ARRAY --define:ENABLE_SPRITE_MASKING --define:INCLUDE_DYNAMIC_GI --define:INCLUDE_GI --define:ENABLE_MONO_BDWGC --define:PLATFORM_SUPPORTS_MONO --define:RENDER_SOFTWARE_CURSOR --define:INCLUDE_PUBNUB --define:ENABLE_PLAYMODE_TESTS_RUNNER --define:ENABLE_VIDEO --define:ENABLE_RMGUI --define:ENABLE_PACKMAN --define:ENABLE_CUSTOM_RENDER_TEXTURE --define:ENABLE_STYLE_SHEETS --define:ENABLE_LOCALIZATION --define:PLATFORM_STANDALONE_OSX --define:PLATFORM_STANDALONE --define:UNITY_STANDALONE_OSX --define:UNITY_STANDALONE --define:ENABLE_SUBSTANCE --define:ENABLE_GAMECENTER --define:ENABLE_RUNTIME_GI --define:ENABLE_MOVIES --define:ENABLE_NETWORK --define:ENABLE_CRUNCH_TEXTURE_COMPRESSION --define:ENABLE_UNITYWEBREQUEST --define:ENABLE_CLOUD_SERVICES --define:ENABLE_CLOUD_SERVICES_ANALYTICS --define:ENABLE_CLOUD_SERVICES_PURCHASING --define:ENABLE_CLOUD_SERVICES_CRASH_REPORTING --define:ENABLE_CLOUD_SERVICES_NATIVE_CRASH_REPORTING --define:ENABLE_CLUSTERINPUT --define:ENABLE_VR --define:ENABLE_AR --define:ENABLE_SPATIALTRACKING --define:ENABLE_WEBSOCKET_HOST --define:ENABLE_MONO --define:NET_2_0_SUBSET --define:ENABLE_PROFILER --define:DEBUG --define:TRACE --define:UNITY_ASSERTIONS --define:UNITY_EDITOR --define:UNITY_EDITOR_64 --define:UNITY_EDITOR_OSX --define:ENABLE_NATIVE_ARRAY_CHECKS --define:UNITY_TEAM_LICENSE -'Assets/Lobby/Scripts/DraggablePanel.cs' -'Assets/Lobby/Scripts/EventSystemChecker.cs' -'Assets/Lobby/Scripts/Lobby/LobbyCountdownPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyHook.cs' -'Assets/Lobby/Scripts/Lobby/LobbyInfoPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyMainMenu.cs' -'Assets/Lobby/Scripts/Lobby/LobbyManager.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayer.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerEntry.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyTopPanel.cs' -'Assets/SampleScenes/Scripts/NetworkAsteroid.cs' -'Assets/SampleScenes/Scripts/NetworkGameManager.cs' -'Assets/SampleScenes/Scripts/NetworkLobbyHook.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceship.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceshipBullet.cs' -'Assets/Scripts/ColorManager.cs' -'Assets/Scripts/ColorOption.cs' -'Assets/Scripts/ColorPicker.cs' -'Assets/Scripts/DoneButtonPressed.cs' -'Assets/Scripts/DoodleShake.cs' -'Assets/Scripts/FadingTextAnimation.cs' -'Assets/Scripts/LoadSceneOnTap.cs' -'Assets/Scripts/RandomSprite.cs' -'Assets/Scripts/ScreenCapture.cs' -'Assets/Scripts/SizeManager.cs' -'Assets/Scripts/SwipeTrail.cs' -'Assets/Scripts/Timer.cs' -'Assets/Scripts/ToolsStateManager.cs' -'Assets/Scripts/ToolState.cs' -'Assets/Scripts/UIRaycastDetector.cs' -'Assets/Scripts/Width.cs' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Runtime.Serialization.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Xml.Linq.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.Lang.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/Boo.Lang.dll' --sdk:unity diff --git a/Close Enough!/Temp/UnityTempFile-bd38a055b16bd4526b50e0a88d8c282d b/Close Enough!/Temp/UnityTempFile-bd38a055b16bd4526b50e0a88d8c282d deleted file mode 100644 index 7ea43a3..0000000 --- a/Close Enough!/Temp/UnityTempFile-bd38a055b16bd4526b50e0a88d8c282d +++ /dev/null @@ -1,218 +0,0 @@ --debug --target:library --nowarn:0169 --langversion:4 --out:'Temp/Assembly-CSharp.dll' --unsafe --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CoreModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AccessibilityModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticleSystemModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VehiclesModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClothModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AnimationModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TextRenderingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainPhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.IMGUIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterInputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterRendererModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UNETModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.DirectorModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityAnalyticsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PerformanceReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityConnectModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WebModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ARModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VRModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIElementsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.StyleSheetsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AssetBundleModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CrashReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GameCenterModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GridModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ImageConversionModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.InputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.JSONSerializeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticlesLegacyModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.Physics2DModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ScreenCaptureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SharedInternalsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteMaskModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteShapeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TilemapModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestAudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestTextureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestWWWModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VideoModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WindModule.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/UnityEngine.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/Editor/UnityEditor.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/Editor/UnityEditor.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/UnityEngine.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/net35/unity-custom/nunit.framework.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/Editor/UnityEditor.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/Editor/UnityEditor.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/RuntimeEditor/UnityEngine.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/Editor/UnityEditor.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TreeEditor/Editor/UnityEditor.TreeEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/Editor/UnityEditor.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/RuntimeEditor/UnityEngine.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/Editor/UnityEditor.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/RuntimeEditor/UnityEngine.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/Editor/UnityEditor.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityVR/Editor/UnityEditor.VR.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.Graphs.dll' --r:'/Applications/Unity/Unity.app/Contents/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/UnityEngine.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/Editor/UnityEditor.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/UnityEngine.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/Editor/UnityEditor.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/UnityEngine.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/Editor/UnityEditor.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.standardevents@1.0.10/UnityEngine.StandardEvents.dll' --define:UNITY_5_3_OR_NEWER --define:UNITY_5_4_OR_NEWER --define:UNITY_5_5_OR_NEWER --define:UNITY_5_6_OR_NEWER --define:UNITY_2017_1_OR_NEWER --define:UNITY_2017_2_OR_NEWER --define:UNITY_2017_3_OR_NEWER --define:UNITY_2017_3_1 --define:UNITY_2017_3 --define:UNITY_2017 --define:PLATFORM_ARCH_64 --define:UNITY_64 --define:ENABLE_AUDIO --define:ENABLE_CACHING --define:ENABLE_CLOTH --define:ENABLE_DUCK_TYPING --define:ENABLE_GENERICS --define:ENABLE_PVR_GI --define:ENABLE_MICROPHONE --define:ENABLE_MULTIPLE_DISPLAYS --define:ENABLE_PHYSICS --define:ENABLE_SPRITERENDERER_FLIPPING --define:ENABLE_SPRITES --define:ENABLE_GRID --define:ENABLE_TILEMAP --define:ENABLE_TERRAIN --define:ENABLE_RAKNET --define:ENABLE_DIRECTOR --define:ENABLE_UNET --define:ENABLE_LZMA --define:ENABLE_UNITYEVENTS --define:ENABLE_WEBCAM --define:ENABLE_WWW --define:ENABLE_CLOUD_SERVICES_COLLAB --define:ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS --define:ENABLE_CLOUD_SERVICES_ADS --define:ENABLE_CLOUD_HUB --define:ENABLE_CLOUD_PROJECT_ID --define:ENABLE_CLOUD_SERVICES_USE_WEBREQUEST --define:ENABLE_CLOUD_SERVICES_UNET --define:ENABLE_CLOUD_SERVICES_BUILD --define:ENABLE_CLOUD_LICENSE --define:ENABLE_EDITOR_HUB --define:ENABLE_EDITOR_HUB_LICENSE --define:ENABLE_WEBSOCKET_CLIENT --define:ENABLE_DIRECTOR_AUDIO --define:ENABLE_DIRECTOR_TEXTURE --define:ENABLE_TIMELINE --define:ENABLE_EDITOR_METRICS --define:ENABLE_EDITOR_METRICS_CACHING --define:ENABLE_NATIVE_ARRAY --define:ENABLE_SPRITE_MASKING --define:INCLUDE_DYNAMIC_GI --define:INCLUDE_GI --define:ENABLE_MONO_BDWGC --define:PLATFORM_SUPPORTS_MONO --define:RENDER_SOFTWARE_CURSOR --define:INCLUDE_PUBNUB --define:ENABLE_PLAYMODE_TESTS_RUNNER --define:ENABLE_VIDEO --define:ENABLE_RMGUI --define:ENABLE_PACKMAN --define:ENABLE_CUSTOM_RENDER_TEXTURE --define:ENABLE_STYLE_SHEETS --define:ENABLE_LOCALIZATION --define:PLATFORM_STANDALONE_OSX --define:PLATFORM_STANDALONE --define:UNITY_STANDALONE_OSX --define:UNITY_STANDALONE --define:ENABLE_SUBSTANCE --define:ENABLE_GAMECENTER --define:ENABLE_RUNTIME_GI --define:ENABLE_MOVIES --define:ENABLE_NETWORK --define:ENABLE_CRUNCH_TEXTURE_COMPRESSION --define:ENABLE_UNITYWEBREQUEST --define:ENABLE_CLOUD_SERVICES --define:ENABLE_CLOUD_SERVICES_ANALYTICS --define:ENABLE_CLOUD_SERVICES_PURCHASING --define:ENABLE_CLOUD_SERVICES_CRASH_REPORTING --define:ENABLE_CLOUD_SERVICES_NATIVE_CRASH_REPORTING --define:ENABLE_CLUSTERINPUT --define:ENABLE_VR --define:ENABLE_AR --define:ENABLE_SPATIALTRACKING --define:ENABLE_WEBSOCKET_HOST --define:ENABLE_MONO --define:NET_2_0_SUBSET --define:ENABLE_PROFILER --define:DEBUG --define:TRACE --define:UNITY_ASSERTIONS --define:UNITY_EDITOR --define:UNITY_EDITOR_64 --define:UNITY_EDITOR_OSX --define:ENABLE_NATIVE_ARRAY_CHECKS --define:UNITY_TEAM_LICENSE -'Assets/Lobby/Scripts/DraggablePanel.cs' -'Assets/Lobby/Scripts/EventSystemChecker.cs' -'Assets/Lobby/Scripts/Lobby/LobbyCountdownPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyHook.cs' -'Assets/Lobby/Scripts/Lobby/LobbyInfoPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyMainMenu.cs' -'Assets/Lobby/Scripts/Lobby/LobbyManager.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayer.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerEntry.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyTopPanel.cs' -'Assets/SampleScenes/Scripts/NetworkAsteroid.cs' -'Assets/SampleScenes/Scripts/NetworkGameManager.cs' -'Assets/SampleScenes/Scripts/NetworkLobbyHook.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceship.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceshipBullet.cs' -'Assets/Scripts/ColorManager.cs' -'Assets/Scripts/ColorOption.cs' -'Assets/Scripts/ColorPicker.cs' -'Assets/Scripts/DoneButtonPressed.cs' -'Assets/Scripts/DoodleShake.cs' -'Assets/Scripts/FadingTextAnimation.cs' -'Assets/Scripts/LoadSceneOnTap.cs' -'Assets/Scripts/RandomSprite.cs' -'Assets/Scripts/ScreenCapture.cs' -'Assets/Scripts/SizeManager.cs' -'Assets/Scripts/SwipeTrail.cs' -'Assets/Scripts/Timer.cs' -'Assets/Scripts/ToolsStateManager.cs' -'Assets/Scripts/ToolState.cs' -'Assets/Scripts/UIRaycastDetector.cs' -'Assets/Scripts/Width.cs' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Runtime.Serialization.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Xml.Linq.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.Lang.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/Boo.Lang.dll' --sdk:unity diff --git a/Close Enough!/Temp/UnityTempFile-d724ae483c2ae40de9f450984c7fc2cf b/Close Enough!/Temp/UnityTempFile-d724ae483c2ae40de9f450984c7fc2cf deleted file mode 100644 index 7ea43a3..0000000 --- a/Close Enough!/Temp/UnityTempFile-d724ae483c2ae40de9f450984c7fc2cf +++ /dev/null @@ -1,218 +0,0 @@ --debug --target:library --nowarn:0169 --langversion:4 --out:'Temp/Assembly-CSharp.dll' --unsafe --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CoreModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AccessibilityModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticleSystemModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VehiclesModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClothModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AnimationModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TextRenderingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainPhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.IMGUIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterInputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterRendererModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UNETModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.DirectorModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityAnalyticsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PerformanceReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityConnectModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WebModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ARModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VRModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIElementsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.StyleSheetsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AssetBundleModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CrashReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GameCenterModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GridModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ImageConversionModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.InputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.JSONSerializeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticlesLegacyModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.Physics2DModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ScreenCaptureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SharedInternalsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteMaskModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteShapeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TilemapModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestAudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestTextureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestWWWModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VideoModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WindModule.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/UnityEngine.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/Editor/UnityEditor.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/Editor/UnityEditor.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/UnityEngine.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/net35/unity-custom/nunit.framework.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/Editor/UnityEditor.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/Editor/UnityEditor.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/RuntimeEditor/UnityEngine.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/Editor/UnityEditor.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TreeEditor/Editor/UnityEditor.TreeEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/Editor/UnityEditor.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/RuntimeEditor/UnityEngine.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/Editor/UnityEditor.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/RuntimeEditor/UnityEngine.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/Editor/UnityEditor.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityVR/Editor/UnityEditor.VR.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.Graphs.dll' --r:'/Applications/Unity/Unity.app/Contents/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/UnityEngine.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/Editor/UnityEditor.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/UnityEngine.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/Editor/UnityEditor.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/UnityEngine.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/Editor/UnityEditor.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.standardevents@1.0.10/UnityEngine.StandardEvents.dll' --define:UNITY_5_3_OR_NEWER --define:UNITY_5_4_OR_NEWER --define:UNITY_5_5_OR_NEWER --define:UNITY_5_6_OR_NEWER --define:UNITY_2017_1_OR_NEWER --define:UNITY_2017_2_OR_NEWER --define:UNITY_2017_3_OR_NEWER --define:UNITY_2017_3_1 --define:UNITY_2017_3 --define:UNITY_2017 --define:PLATFORM_ARCH_64 --define:UNITY_64 --define:ENABLE_AUDIO --define:ENABLE_CACHING --define:ENABLE_CLOTH --define:ENABLE_DUCK_TYPING --define:ENABLE_GENERICS --define:ENABLE_PVR_GI --define:ENABLE_MICROPHONE --define:ENABLE_MULTIPLE_DISPLAYS --define:ENABLE_PHYSICS --define:ENABLE_SPRITERENDERER_FLIPPING --define:ENABLE_SPRITES --define:ENABLE_GRID --define:ENABLE_TILEMAP --define:ENABLE_TERRAIN --define:ENABLE_RAKNET --define:ENABLE_DIRECTOR --define:ENABLE_UNET --define:ENABLE_LZMA --define:ENABLE_UNITYEVENTS --define:ENABLE_WEBCAM --define:ENABLE_WWW --define:ENABLE_CLOUD_SERVICES_COLLAB --define:ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS --define:ENABLE_CLOUD_SERVICES_ADS --define:ENABLE_CLOUD_HUB --define:ENABLE_CLOUD_PROJECT_ID --define:ENABLE_CLOUD_SERVICES_USE_WEBREQUEST --define:ENABLE_CLOUD_SERVICES_UNET --define:ENABLE_CLOUD_SERVICES_BUILD --define:ENABLE_CLOUD_LICENSE --define:ENABLE_EDITOR_HUB --define:ENABLE_EDITOR_HUB_LICENSE --define:ENABLE_WEBSOCKET_CLIENT --define:ENABLE_DIRECTOR_AUDIO --define:ENABLE_DIRECTOR_TEXTURE --define:ENABLE_TIMELINE --define:ENABLE_EDITOR_METRICS --define:ENABLE_EDITOR_METRICS_CACHING --define:ENABLE_NATIVE_ARRAY --define:ENABLE_SPRITE_MASKING --define:INCLUDE_DYNAMIC_GI --define:INCLUDE_GI --define:ENABLE_MONO_BDWGC --define:PLATFORM_SUPPORTS_MONO --define:RENDER_SOFTWARE_CURSOR --define:INCLUDE_PUBNUB --define:ENABLE_PLAYMODE_TESTS_RUNNER --define:ENABLE_VIDEO --define:ENABLE_RMGUI --define:ENABLE_PACKMAN --define:ENABLE_CUSTOM_RENDER_TEXTURE --define:ENABLE_STYLE_SHEETS --define:ENABLE_LOCALIZATION --define:PLATFORM_STANDALONE_OSX --define:PLATFORM_STANDALONE --define:UNITY_STANDALONE_OSX --define:UNITY_STANDALONE --define:ENABLE_SUBSTANCE --define:ENABLE_GAMECENTER --define:ENABLE_RUNTIME_GI --define:ENABLE_MOVIES --define:ENABLE_NETWORK --define:ENABLE_CRUNCH_TEXTURE_COMPRESSION --define:ENABLE_UNITYWEBREQUEST --define:ENABLE_CLOUD_SERVICES --define:ENABLE_CLOUD_SERVICES_ANALYTICS --define:ENABLE_CLOUD_SERVICES_PURCHASING --define:ENABLE_CLOUD_SERVICES_CRASH_REPORTING --define:ENABLE_CLOUD_SERVICES_NATIVE_CRASH_REPORTING --define:ENABLE_CLUSTERINPUT --define:ENABLE_VR --define:ENABLE_AR --define:ENABLE_SPATIALTRACKING --define:ENABLE_WEBSOCKET_HOST --define:ENABLE_MONO --define:NET_2_0_SUBSET --define:ENABLE_PROFILER --define:DEBUG --define:TRACE --define:UNITY_ASSERTIONS --define:UNITY_EDITOR --define:UNITY_EDITOR_64 --define:UNITY_EDITOR_OSX --define:ENABLE_NATIVE_ARRAY_CHECKS --define:UNITY_TEAM_LICENSE -'Assets/Lobby/Scripts/DraggablePanel.cs' -'Assets/Lobby/Scripts/EventSystemChecker.cs' -'Assets/Lobby/Scripts/Lobby/LobbyCountdownPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyHook.cs' -'Assets/Lobby/Scripts/Lobby/LobbyInfoPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyMainMenu.cs' -'Assets/Lobby/Scripts/Lobby/LobbyManager.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayer.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerEntry.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyTopPanel.cs' -'Assets/SampleScenes/Scripts/NetworkAsteroid.cs' -'Assets/SampleScenes/Scripts/NetworkGameManager.cs' -'Assets/SampleScenes/Scripts/NetworkLobbyHook.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceship.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceshipBullet.cs' -'Assets/Scripts/ColorManager.cs' -'Assets/Scripts/ColorOption.cs' -'Assets/Scripts/ColorPicker.cs' -'Assets/Scripts/DoneButtonPressed.cs' -'Assets/Scripts/DoodleShake.cs' -'Assets/Scripts/FadingTextAnimation.cs' -'Assets/Scripts/LoadSceneOnTap.cs' -'Assets/Scripts/RandomSprite.cs' -'Assets/Scripts/ScreenCapture.cs' -'Assets/Scripts/SizeManager.cs' -'Assets/Scripts/SwipeTrail.cs' -'Assets/Scripts/Timer.cs' -'Assets/Scripts/ToolsStateManager.cs' -'Assets/Scripts/ToolState.cs' -'Assets/Scripts/UIRaycastDetector.cs' -'Assets/Scripts/Width.cs' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Runtime.Serialization.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Xml.Linq.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.Lang.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/Boo.Lang.dll' --sdk:unity diff --git a/Close Enough!/Temp/UnityTempFile-de82a01159e064d97b74b60f83bfd2a9 b/Close Enough!/Temp/UnityTempFile-de82a01159e064d97b74b60f83bfd2a9 deleted file mode 100644 index 7ea43a3..0000000 --- a/Close Enough!/Temp/UnityTempFile-de82a01159e064d97b74b60f83bfd2a9 +++ /dev/null @@ -1,218 +0,0 @@ --debug --target:library --nowarn:0169 --langversion:4 --out:'Temp/Assembly-CSharp.dll' --unsafe --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CoreModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AccessibilityModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticleSystemModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VehiclesModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClothModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AnimationModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TextRenderingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainPhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.IMGUIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterInputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterRendererModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UNETModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.DirectorModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityAnalyticsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PerformanceReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityConnectModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WebModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ARModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VRModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIElementsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.StyleSheetsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AssetBundleModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CrashReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GameCenterModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GridModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ImageConversionModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.InputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.JSONSerializeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticlesLegacyModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.Physics2DModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ScreenCaptureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SharedInternalsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteMaskModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteShapeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TilemapModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestAudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestTextureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestWWWModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VideoModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WindModule.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/UnityEngine.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/Editor/UnityEditor.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/Editor/UnityEditor.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/UnityEngine.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/net35/unity-custom/nunit.framework.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/Editor/UnityEditor.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/Editor/UnityEditor.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/RuntimeEditor/UnityEngine.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/Editor/UnityEditor.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TreeEditor/Editor/UnityEditor.TreeEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/Editor/UnityEditor.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/RuntimeEditor/UnityEngine.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/Editor/UnityEditor.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/RuntimeEditor/UnityEngine.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/Editor/UnityEditor.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityVR/Editor/UnityEditor.VR.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.Graphs.dll' --r:'/Applications/Unity/Unity.app/Contents/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/UnityEngine.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/Editor/UnityEditor.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/UnityEngine.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/Editor/UnityEditor.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/UnityEngine.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/Editor/UnityEditor.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.standardevents@1.0.10/UnityEngine.StandardEvents.dll' --define:UNITY_5_3_OR_NEWER --define:UNITY_5_4_OR_NEWER --define:UNITY_5_5_OR_NEWER --define:UNITY_5_6_OR_NEWER --define:UNITY_2017_1_OR_NEWER --define:UNITY_2017_2_OR_NEWER --define:UNITY_2017_3_OR_NEWER --define:UNITY_2017_3_1 --define:UNITY_2017_3 --define:UNITY_2017 --define:PLATFORM_ARCH_64 --define:UNITY_64 --define:ENABLE_AUDIO --define:ENABLE_CACHING --define:ENABLE_CLOTH --define:ENABLE_DUCK_TYPING --define:ENABLE_GENERICS --define:ENABLE_PVR_GI --define:ENABLE_MICROPHONE --define:ENABLE_MULTIPLE_DISPLAYS --define:ENABLE_PHYSICS --define:ENABLE_SPRITERENDERER_FLIPPING --define:ENABLE_SPRITES --define:ENABLE_GRID --define:ENABLE_TILEMAP --define:ENABLE_TERRAIN --define:ENABLE_RAKNET --define:ENABLE_DIRECTOR --define:ENABLE_UNET --define:ENABLE_LZMA --define:ENABLE_UNITYEVENTS --define:ENABLE_WEBCAM --define:ENABLE_WWW --define:ENABLE_CLOUD_SERVICES_COLLAB --define:ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS --define:ENABLE_CLOUD_SERVICES_ADS --define:ENABLE_CLOUD_HUB --define:ENABLE_CLOUD_PROJECT_ID --define:ENABLE_CLOUD_SERVICES_USE_WEBREQUEST --define:ENABLE_CLOUD_SERVICES_UNET --define:ENABLE_CLOUD_SERVICES_BUILD --define:ENABLE_CLOUD_LICENSE --define:ENABLE_EDITOR_HUB --define:ENABLE_EDITOR_HUB_LICENSE --define:ENABLE_WEBSOCKET_CLIENT --define:ENABLE_DIRECTOR_AUDIO --define:ENABLE_DIRECTOR_TEXTURE --define:ENABLE_TIMELINE --define:ENABLE_EDITOR_METRICS --define:ENABLE_EDITOR_METRICS_CACHING --define:ENABLE_NATIVE_ARRAY --define:ENABLE_SPRITE_MASKING --define:INCLUDE_DYNAMIC_GI --define:INCLUDE_GI --define:ENABLE_MONO_BDWGC --define:PLATFORM_SUPPORTS_MONO --define:RENDER_SOFTWARE_CURSOR --define:INCLUDE_PUBNUB --define:ENABLE_PLAYMODE_TESTS_RUNNER --define:ENABLE_VIDEO --define:ENABLE_RMGUI --define:ENABLE_PACKMAN --define:ENABLE_CUSTOM_RENDER_TEXTURE --define:ENABLE_STYLE_SHEETS --define:ENABLE_LOCALIZATION --define:PLATFORM_STANDALONE_OSX --define:PLATFORM_STANDALONE --define:UNITY_STANDALONE_OSX --define:UNITY_STANDALONE --define:ENABLE_SUBSTANCE --define:ENABLE_GAMECENTER --define:ENABLE_RUNTIME_GI --define:ENABLE_MOVIES --define:ENABLE_NETWORK --define:ENABLE_CRUNCH_TEXTURE_COMPRESSION --define:ENABLE_UNITYWEBREQUEST --define:ENABLE_CLOUD_SERVICES --define:ENABLE_CLOUD_SERVICES_ANALYTICS --define:ENABLE_CLOUD_SERVICES_PURCHASING --define:ENABLE_CLOUD_SERVICES_CRASH_REPORTING --define:ENABLE_CLOUD_SERVICES_NATIVE_CRASH_REPORTING --define:ENABLE_CLUSTERINPUT --define:ENABLE_VR --define:ENABLE_AR --define:ENABLE_SPATIALTRACKING --define:ENABLE_WEBSOCKET_HOST --define:ENABLE_MONO --define:NET_2_0_SUBSET --define:ENABLE_PROFILER --define:DEBUG --define:TRACE --define:UNITY_ASSERTIONS --define:UNITY_EDITOR --define:UNITY_EDITOR_64 --define:UNITY_EDITOR_OSX --define:ENABLE_NATIVE_ARRAY_CHECKS --define:UNITY_TEAM_LICENSE -'Assets/Lobby/Scripts/DraggablePanel.cs' -'Assets/Lobby/Scripts/EventSystemChecker.cs' -'Assets/Lobby/Scripts/Lobby/LobbyCountdownPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyHook.cs' -'Assets/Lobby/Scripts/Lobby/LobbyInfoPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyMainMenu.cs' -'Assets/Lobby/Scripts/Lobby/LobbyManager.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayer.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerEntry.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyTopPanel.cs' -'Assets/SampleScenes/Scripts/NetworkAsteroid.cs' -'Assets/SampleScenes/Scripts/NetworkGameManager.cs' -'Assets/SampleScenes/Scripts/NetworkLobbyHook.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceship.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceshipBullet.cs' -'Assets/Scripts/ColorManager.cs' -'Assets/Scripts/ColorOption.cs' -'Assets/Scripts/ColorPicker.cs' -'Assets/Scripts/DoneButtonPressed.cs' -'Assets/Scripts/DoodleShake.cs' -'Assets/Scripts/FadingTextAnimation.cs' -'Assets/Scripts/LoadSceneOnTap.cs' -'Assets/Scripts/RandomSprite.cs' -'Assets/Scripts/ScreenCapture.cs' -'Assets/Scripts/SizeManager.cs' -'Assets/Scripts/SwipeTrail.cs' -'Assets/Scripts/Timer.cs' -'Assets/Scripts/ToolsStateManager.cs' -'Assets/Scripts/ToolState.cs' -'Assets/Scripts/UIRaycastDetector.cs' -'Assets/Scripts/Width.cs' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Runtime.Serialization.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Xml.Linq.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.Lang.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/Boo.Lang.dll' --sdk:unity diff --git a/Close Enough!/Temp/UnityTempFile-e03aafa3bf56a4eb69a9a1eed102c1e4 b/Close Enough!/Temp/UnityTempFile-e03aafa3bf56a4eb69a9a1eed102c1e4 deleted file mode 100644 index 7ea43a3..0000000 --- a/Close Enough!/Temp/UnityTempFile-e03aafa3bf56a4eb69a9a1eed102c1e4 +++ /dev/null @@ -1,218 +0,0 @@ --debug --target:library --nowarn:0169 --langversion:4 --out:'Temp/Assembly-CSharp.dll' --unsafe --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CoreModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AccessibilityModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticleSystemModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VehiclesModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClothModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AnimationModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TextRenderingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainPhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.IMGUIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterInputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterRendererModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UNETModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.DirectorModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityAnalyticsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PerformanceReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityConnectModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WebModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ARModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VRModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIElementsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.StyleSheetsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AssetBundleModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CrashReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GameCenterModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GridModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ImageConversionModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.InputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.JSONSerializeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticlesLegacyModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.Physics2DModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ScreenCaptureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SharedInternalsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteMaskModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteShapeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TilemapModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestAudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestTextureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestWWWModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VideoModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WindModule.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/UnityEngine.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/Editor/UnityEditor.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/Editor/UnityEditor.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/UnityEngine.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/net35/unity-custom/nunit.framework.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/Editor/UnityEditor.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/Editor/UnityEditor.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/RuntimeEditor/UnityEngine.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/Editor/UnityEditor.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TreeEditor/Editor/UnityEditor.TreeEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/Editor/UnityEditor.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/RuntimeEditor/UnityEngine.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/Editor/UnityEditor.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/RuntimeEditor/UnityEngine.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/Editor/UnityEditor.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityVR/Editor/UnityEditor.VR.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.Graphs.dll' --r:'/Applications/Unity/Unity.app/Contents/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/UnityEngine.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/Editor/UnityEditor.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/UnityEngine.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/Editor/UnityEditor.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/UnityEngine.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/Editor/UnityEditor.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.standardevents@1.0.10/UnityEngine.StandardEvents.dll' --define:UNITY_5_3_OR_NEWER --define:UNITY_5_4_OR_NEWER --define:UNITY_5_5_OR_NEWER --define:UNITY_5_6_OR_NEWER --define:UNITY_2017_1_OR_NEWER --define:UNITY_2017_2_OR_NEWER --define:UNITY_2017_3_OR_NEWER --define:UNITY_2017_3_1 --define:UNITY_2017_3 --define:UNITY_2017 --define:PLATFORM_ARCH_64 --define:UNITY_64 --define:ENABLE_AUDIO --define:ENABLE_CACHING --define:ENABLE_CLOTH --define:ENABLE_DUCK_TYPING --define:ENABLE_GENERICS --define:ENABLE_PVR_GI --define:ENABLE_MICROPHONE --define:ENABLE_MULTIPLE_DISPLAYS --define:ENABLE_PHYSICS --define:ENABLE_SPRITERENDERER_FLIPPING --define:ENABLE_SPRITES --define:ENABLE_GRID --define:ENABLE_TILEMAP --define:ENABLE_TERRAIN --define:ENABLE_RAKNET --define:ENABLE_DIRECTOR --define:ENABLE_UNET --define:ENABLE_LZMA --define:ENABLE_UNITYEVENTS --define:ENABLE_WEBCAM --define:ENABLE_WWW --define:ENABLE_CLOUD_SERVICES_COLLAB --define:ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS --define:ENABLE_CLOUD_SERVICES_ADS --define:ENABLE_CLOUD_HUB --define:ENABLE_CLOUD_PROJECT_ID --define:ENABLE_CLOUD_SERVICES_USE_WEBREQUEST --define:ENABLE_CLOUD_SERVICES_UNET --define:ENABLE_CLOUD_SERVICES_BUILD --define:ENABLE_CLOUD_LICENSE --define:ENABLE_EDITOR_HUB --define:ENABLE_EDITOR_HUB_LICENSE --define:ENABLE_WEBSOCKET_CLIENT --define:ENABLE_DIRECTOR_AUDIO --define:ENABLE_DIRECTOR_TEXTURE --define:ENABLE_TIMELINE --define:ENABLE_EDITOR_METRICS --define:ENABLE_EDITOR_METRICS_CACHING --define:ENABLE_NATIVE_ARRAY --define:ENABLE_SPRITE_MASKING --define:INCLUDE_DYNAMIC_GI --define:INCLUDE_GI --define:ENABLE_MONO_BDWGC --define:PLATFORM_SUPPORTS_MONO --define:RENDER_SOFTWARE_CURSOR --define:INCLUDE_PUBNUB --define:ENABLE_PLAYMODE_TESTS_RUNNER --define:ENABLE_VIDEO --define:ENABLE_RMGUI --define:ENABLE_PACKMAN --define:ENABLE_CUSTOM_RENDER_TEXTURE --define:ENABLE_STYLE_SHEETS --define:ENABLE_LOCALIZATION --define:PLATFORM_STANDALONE_OSX --define:PLATFORM_STANDALONE --define:UNITY_STANDALONE_OSX --define:UNITY_STANDALONE --define:ENABLE_SUBSTANCE --define:ENABLE_GAMECENTER --define:ENABLE_RUNTIME_GI --define:ENABLE_MOVIES --define:ENABLE_NETWORK --define:ENABLE_CRUNCH_TEXTURE_COMPRESSION --define:ENABLE_UNITYWEBREQUEST --define:ENABLE_CLOUD_SERVICES --define:ENABLE_CLOUD_SERVICES_ANALYTICS --define:ENABLE_CLOUD_SERVICES_PURCHASING --define:ENABLE_CLOUD_SERVICES_CRASH_REPORTING --define:ENABLE_CLOUD_SERVICES_NATIVE_CRASH_REPORTING --define:ENABLE_CLUSTERINPUT --define:ENABLE_VR --define:ENABLE_AR --define:ENABLE_SPATIALTRACKING --define:ENABLE_WEBSOCKET_HOST --define:ENABLE_MONO --define:NET_2_0_SUBSET --define:ENABLE_PROFILER --define:DEBUG --define:TRACE --define:UNITY_ASSERTIONS --define:UNITY_EDITOR --define:UNITY_EDITOR_64 --define:UNITY_EDITOR_OSX --define:ENABLE_NATIVE_ARRAY_CHECKS --define:UNITY_TEAM_LICENSE -'Assets/Lobby/Scripts/DraggablePanel.cs' -'Assets/Lobby/Scripts/EventSystemChecker.cs' -'Assets/Lobby/Scripts/Lobby/LobbyCountdownPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyHook.cs' -'Assets/Lobby/Scripts/Lobby/LobbyInfoPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyMainMenu.cs' -'Assets/Lobby/Scripts/Lobby/LobbyManager.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayer.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerEntry.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyTopPanel.cs' -'Assets/SampleScenes/Scripts/NetworkAsteroid.cs' -'Assets/SampleScenes/Scripts/NetworkGameManager.cs' -'Assets/SampleScenes/Scripts/NetworkLobbyHook.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceship.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceshipBullet.cs' -'Assets/Scripts/ColorManager.cs' -'Assets/Scripts/ColorOption.cs' -'Assets/Scripts/ColorPicker.cs' -'Assets/Scripts/DoneButtonPressed.cs' -'Assets/Scripts/DoodleShake.cs' -'Assets/Scripts/FadingTextAnimation.cs' -'Assets/Scripts/LoadSceneOnTap.cs' -'Assets/Scripts/RandomSprite.cs' -'Assets/Scripts/ScreenCapture.cs' -'Assets/Scripts/SizeManager.cs' -'Assets/Scripts/SwipeTrail.cs' -'Assets/Scripts/Timer.cs' -'Assets/Scripts/ToolsStateManager.cs' -'Assets/Scripts/ToolState.cs' -'Assets/Scripts/UIRaycastDetector.cs' -'Assets/Scripts/Width.cs' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Runtime.Serialization.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Xml.Linq.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.Lang.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/Boo.Lang.dll' --sdk:unity diff --git a/Close Enough!/Temp/UnityTempFile-e10c0f128241f46269be1b852171f6fe b/Close Enough!/Temp/UnityTempFile-e10c0f128241f46269be1b852171f6fe deleted file mode 100644 index 7ea43a3..0000000 --- a/Close Enough!/Temp/UnityTempFile-e10c0f128241f46269be1b852171f6fe +++ /dev/null @@ -1,218 +0,0 @@ --debug --target:library --nowarn:0169 --langversion:4 --out:'Temp/Assembly-CSharp.dll' --unsafe --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CoreModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AccessibilityModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticleSystemModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VehiclesModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClothModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AnimationModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TextRenderingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainPhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.IMGUIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterInputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterRendererModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UNETModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.DirectorModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityAnalyticsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PerformanceReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityConnectModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WebModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ARModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VRModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIElementsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.StyleSheetsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AssetBundleModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CrashReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GameCenterModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GridModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ImageConversionModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.InputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.JSONSerializeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticlesLegacyModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.Physics2DModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ScreenCaptureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SharedInternalsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteMaskModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteShapeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TilemapModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestAudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestTextureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestWWWModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VideoModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WindModule.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/UnityEngine.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/Editor/UnityEditor.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/Editor/UnityEditor.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/UnityEngine.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/net35/unity-custom/nunit.framework.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/Editor/UnityEditor.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/Editor/UnityEditor.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/RuntimeEditor/UnityEngine.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/Editor/UnityEditor.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TreeEditor/Editor/UnityEditor.TreeEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/Editor/UnityEditor.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/RuntimeEditor/UnityEngine.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/Editor/UnityEditor.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/RuntimeEditor/UnityEngine.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/Editor/UnityEditor.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityVR/Editor/UnityEditor.VR.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.Graphs.dll' --r:'/Applications/Unity/Unity.app/Contents/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/UnityEngine.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/Editor/UnityEditor.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/UnityEngine.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/Editor/UnityEditor.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/UnityEngine.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/Editor/UnityEditor.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.standardevents@1.0.10/UnityEngine.StandardEvents.dll' --define:UNITY_5_3_OR_NEWER --define:UNITY_5_4_OR_NEWER --define:UNITY_5_5_OR_NEWER --define:UNITY_5_6_OR_NEWER --define:UNITY_2017_1_OR_NEWER --define:UNITY_2017_2_OR_NEWER --define:UNITY_2017_3_OR_NEWER --define:UNITY_2017_3_1 --define:UNITY_2017_3 --define:UNITY_2017 --define:PLATFORM_ARCH_64 --define:UNITY_64 --define:ENABLE_AUDIO --define:ENABLE_CACHING --define:ENABLE_CLOTH --define:ENABLE_DUCK_TYPING --define:ENABLE_GENERICS --define:ENABLE_PVR_GI --define:ENABLE_MICROPHONE --define:ENABLE_MULTIPLE_DISPLAYS --define:ENABLE_PHYSICS --define:ENABLE_SPRITERENDERER_FLIPPING --define:ENABLE_SPRITES --define:ENABLE_GRID --define:ENABLE_TILEMAP --define:ENABLE_TERRAIN --define:ENABLE_RAKNET --define:ENABLE_DIRECTOR --define:ENABLE_UNET --define:ENABLE_LZMA --define:ENABLE_UNITYEVENTS --define:ENABLE_WEBCAM --define:ENABLE_WWW --define:ENABLE_CLOUD_SERVICES_COLLAB --define:ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS --define:ENABLE_CLOUD_SERVICES_ADS --define:ENABLE_CLOUD_HUB --define:ENABLE_CLOUD_PROJECT_ID --define:ENABLE_CLOUD_SERVICES_USE_WEBREQUEST --define:ENABLE_CLOUD_SERVICES_UNET --define:ENABLE_CLOUD_SERVICES_BUILD --define:ENABLE_CLOUD_LICENSE --define:ENABLE_EDITOR_HUB --define:ENABLE_EDITOR_HUB_LICENSE --define:ENABLE_WEBSOCKET_CLIENT --define:ENABLE_DIRECTOR_AUDIO --define:ENABLE_DIRECTOR_TEXTURE --define:ENABLE_TIMELINE --define:ENABLE_EDITOR_METRICS --define:ENABLE_EDITOR_METRICS_CACHING --define:ENABLE_NATIVE_ARRAY --define:ENABLE_SPRITE_MASKING --define:INCLUDE_DYNAMIC_GI --define:INCLUDE_GI --define:ENABLE_MONO_BDWGC --define:PLATFORM_SUPPORTS_MONO --define:RENDER_SOFTWARE_CURSOR --define:INCLUDE_PUBNUB --define:ENABLE_PLAYMODE_TESTS_RUNNER --define:ENABLE_VIDEO --define:ENABLE_RMGUI --define:ENABLE_PACKMAN --define:ENABLE_CUSTOM_RENDER_TEXTURE --define:ENABLE_STYLE_SHEETS --define:ENABLE_LOCALIZATION --define:PLATFORM_STANDALONE_OSX --define:PLATFORM_STANDALONE --define:UNITY_STANDALONE_OSX --define:UNITY_STANDALONE --define:ENABLE_SUBSTANCE --define:ENABLE_GAMECENTER --define:ENABLE_RUNTIME_GI --define:ENABLE_MOVIES --define:ENABLE_NETWORK --define:ENABLE_CRUNCH_TEXTURE_COMPRESSION --define:ENABLE_UNITYWEBREQUEST --define:ENABLE_CLOUD_SERVICES --define:ENABLE_CLOUD_SERVICES_ANALYTICS --define:ENABLE_CLOUD_SERVICES_PURCHASING --define:ENABLE_CLOUD_SERVICES_CRASH_REPORTING --define:ENABLE_CLOUD_SERVICES_NATIVE_CRASH_REPORTING --define:ENABLE_CLUSTERINPUT --define:ENABLE_VR --define:ENABLE_AR --define:ENABLE_SPATIALTRACKING --define:ENABLE_WEBSOCKET_HOST --define:ENABLE_MONO --define:NET_2_0_SUBSET --define:ENABLE_PROFILER --define:DEBUG --define:TRACE --define:UNITY_ASSERTIONS --define:UNITY_EDITOR --define:UNITY_EDITOR_64 --define:UNITY_EDITOR_OSX --define:ENABLE_NATIVE_ARRAY_CHECKS --define:UNITY_TEAM_LICENSE -'Assets/Lobby/Scripts/DraggablePanel.cs' -'Assets/Lobby/Scripts/EventSystemChecker.cs' -'Assets/Lobby/Scripts/Lobby/LobbyCountdownPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyHook.cs' -'Assets/Lobby/Scripts/Lobby/LobbyInfoPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyMainMenu.cs' -'Assets/Lobby/Scripts/Lobby/LobbyManager.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayer.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerEntry.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyTopPanel.cs' -'Assets/SampleScenes/Scripts/NetworkAsteroid.cs' -'Assets/SampleScenes/Scripts/NetworkGameManager.cs' -'Assets/SampleScenes/Scripts/NetworkLobbyHook.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceship.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceshipBullet.cs' -'Assets/Scripts/ColorManager.cs' -'Assets/Scripts/ColorOption.cs' -'Assets/Scripts/ColorPicker.cs' -'Assets/Scripts/DoneButtonPressed.cs' -'Assets/Scripts/DoodleShake.cs' -'Assets/Scripts/FadingTextAnimation.cs' -'Assets/Scripts/LoadSceneOnTap.cs' -'Assets/Scripts/RandomSprite.cs' -'Assets/Scripts/ScreenCapture.cs' -'Assets/Scripts/SizeManager.cs' -'Assets/Scripts/SwipeTrail.cs' -'Assets/Scripts/Timer.cs' -'Assets/Scripts/ToolsStateManager.cs' -'Assets/Scripts/ToolState.cs' -'Assets/Scripts/UIRaycastDetector.cs' -'Assets/Scripts/Width.cs' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Runtime.Serialization.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Xml.Linq.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.Lang.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/Boo.Lang.dll' --sdk:unity diff --git a/Close Enough!/Temp/UnityTempFile-fa21fb1533b67497188d193858b65d24 b/Close Enough!/Temp/UnityTempFile-fa21fb1533b67497188d193858b65d24 deleted file mode 100644 index 7ea43a3..0000000 --- a/Close Enough!/Temp/UnityTempFile-fa21fb1533b67497188d193858b65d24 +++ /dev/null @@ -1,218 +0,0 @@ --debug --target:library --nowarn:0169 --langversion:4 --out:'Temp/Assembly-CSharp.dll' --unsafe --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CoreModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AccessibilityModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticleSystemModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VehiclesModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClothModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AnimationModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TextRenderingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainPhysicsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.IMGUIModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterInputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ClusterRendererModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UNETModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.DirectorModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityAnalyticsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.PerformanceReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityConnectModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WebModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ARModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VRModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UIElementsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.StyleSheetsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AssetBundleModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CrashReportingModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GameCenterModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.GridModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ImageConversionModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.InputModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.JSONSerializeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ParticlesLegacyModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.Physics2DModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ScreenCaptureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SharedInternalsModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteMaskModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.SpriteShapeModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TerrainModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.TilemapModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestAudioModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestTextureModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.UnityWebRequestWWWModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.VideoModule.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEngine/UnityEngine.WindModule.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/UnityEngine.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UIAutomation/Editor/UnityEditor.UIAutomation.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/Editor/UnityEditor.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/UnityEngine.TestRunner.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TestRunner/net35/unity-custom/nunit.framework.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Networking/Editor/UnityEditor.Networking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/Editor/UnityEditor.UI.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/RuntimeEditor/UnityEngine.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/Timeline/Editor/UnityEditor.Timeline.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/TreeEditor/Editor/UnityEditor.TreeEditor.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/Editor/UnityEditor.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityGoogleAudioSpatializer/RuntimeEditor/UnityEngine.GoogleAudioSpatializer.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/Editor/UnityEditor.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityHoloLens/RuntimeEditor/UnityEngine.HoloLens.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/Editor/UnityEditor.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnitySpatialTracking/RuntimeEditor/UnityEngine.SpatialTracking.dll' --r:'/Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/UnityVR/Editor/UnityEditor.VR.dll' --r:'/Applications/Unity/Unity.app/Contents/Managed/UnityEditor.Graphs.dll' --r:'/Applications/Unity/Unity.app/Contents/PlaybackEngines/MacStandaloneSupport/UnityEditor.OSXStandalone.Extensions.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/UnityEngine.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.ads@2.0.3/Editor/UnityEditor.Advertisements.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/UnityEngine.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.analytics@2.0.13/Editor/UnityEditor.Analytics.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/UnityEngine.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.purchasing@0.0.19/Editor/UnityEditor.Purchasing.dll' --r:'/Users/alexberthon/Library/Unity/cache/packages/packages.unity.com/com.unity.standardevents@1.0.10/UnityEngine.StandardEvents.dll' --define:UNITY_5_3_OR_NEWER --define:UNITY_5_4_OR_NEWER --define:UNITY_5_5_OR_NEWER --define:UNITY_5_6_OR_NEWER --define:UNITY_2017_1_OR_NEWER --define:UNITY_2017_2_OR_NEWER --define:UNITY_2017_3_OR_NEWER --define:UNITY_2017_3_1 --define:UNITY_2017_3 --define:UNITY_2017 --define:PLATFORM_ARCH_64 --define:UNITY_64 --define:ENABLE_AUDIO --define:ENABLE_CACHING --define:ENABLE_CLOTH --define:ENABLE_DUCK_TYPING --define:ENABLE_GENERICS --define:ENABLE_PVR_GI --define:ENABLE_MICROPHONE --define:ENABLE_MULTIPLE_DISPLAYS --define:ENABLE_PHYSICS --define:ENABLE_SPRITERENDERER_FLIPPING --define:ENABLE_SPRITES --define:ENABLE_GRID --define:ENABLE_TILEMAP --define:ENABLE_TERRAIN --define:ENABLE_RAKNET --define:ENABLE_DIRECTOR --define:ENABLE_UNET --define:ENABLE_LZMA --define:ENABLE_UNITYEVENTS --define:ENABLE_WEBCAM --define:ENABLE_WWW --define:ENABLE_CLOUD_SERVICES_COLLAB --define:ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS --define:ENABLE_CLOUD_SERVICES_ADS --define:ENABLE_CLOUD_HUB --define:ENABLE_CLOUD_PROJECT_ID --define:ENABLE_CLOUD_SERVICES_USE_WEBREQUEST --define:ENABLE_CLOUD_SERVICES_UNET --define:ENABLE_CLOUD_SERVICES_BUILD --define:ENABLE_CLOUD_LICENSE --define:ENABLE_EDITOR_HUB --define:ENABLE_EDITOR_HUB_LICENSE --define:ENABLE_WEBSOCKET_CLIENT --define:ENABLE_DIRECTOR_AUDIO --define:ENABLE_DIRECTOR_TEXTURE --define:ENABLE_TIMELINE --define:ENABLE_EDITOR_METRICS --define:ENABLE_EDITOR_METRICS_CACHING --define:ENABLE_NATIVE_ARRAY --define:ENABLE_SPRITE_MASKING --define:INCLUDE_DYNAMIC_GI --define:INCLUDE_GI --define:ENABLE_MONO_BDWGC --define:PLATFORM_SUPPORTS_MONO --define:RENDER_SOFTWARE_CURSOR --define:INCLUDE_PUBNUB --define:ENABLE_PLAYMODE_TESTS_RUNNER --define:ENABLE_VIDEO --define:ENABLE_RMGUI --define:ENABLE_PACKMAN --define:ENABLE_CUSTOM_RENDER_TEXTURE --define:ENABLE_STYLE_SHEETS --define:ENABLE_LOCALIZATION --define:PLATFORM_STANDALONE_OSX --define:PLATFORM_STANDALONE --define:UNITY_STANDALONE_OSX --define:UNITY_STANDALONE --define:ENABLE_SUBSTANCE --define:ENABLE_GAMECENTER --define:ENABLE_RUNTIME_GI --define:ENABLE_MOVIES --define:ENABLE_NETWORK --define:ENABLE_CRUNCH_TEXTURE_COMPRESSION --define:ENABLE_UNITYWEBREQUEST --define:ENABLE_CLOUD_SERVICES --define:ENABLE_CLOUD_SERVICES_ANALYTICS --define:ENABLE_CLOUD_SERVICES_PURCHASING --define:ENABLE_CLOUD_SERVICES_CRASH_REPORTING --define:ENABLE_CLOUD_SERVICES_NATIVE_CRASH_REPORTING --define:ENABLE_CLUSTERINPUT --define:ENABLE_VR --define:ENABLE_AR --define:ENABLE_SPATIALTRACKING --define:ENABLE_WEBSOCKET_HOST --define:ENABLE_MONO --define:NET_2_0_SUBSET --define:ENABLE_PROFILER --define:DEBUG --define:TRACE --define:UNITY_ASSERTIONS --define:UNITY_EDITOR --define:UNITY_EDITOR_64 --define:UNITY_EDITOR_OSX --define:ENABLE_NATIVE_ARRAY_CHECKS --define:UNITY_TEAM_LICENSE -'Assets/Lobby/Scripts/DraggablePanel.cs' -'Assets/Lobby/Scripts/EventSystemChecker.cs' -'Assets/Lobby/Scripts/Lobby/LobbyCountdownPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyHook.cs' -'Assets/Lobby/Scripts/Lobby/LobbyInfoPanel.cs' -'Assets/Lobby/Scripts/Lobby/LobbyMainMenu.cs' -'Assets/Lobby/Scripts/Lobby/LobbyManager.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayer.cs' -'Assets/Lobby/Scripts/Lobby/LobbyPlayerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerEntry.cs' -'Assets/Lobby/Scripts/Lobby/LobbyServerList.cs' -'Assets/Lobby/Scripts/Lobby/LobbyTopPanel.cs' -'Assets/SampleScenes/Scripts/NetworkAsteroid.cs' -'Assets/SampleScenes/Scripts/NetworkGameManager.cs' -'Assets/SampleScenes/Scripts/NetworkLobbyHook.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceship.cs' -'Assets/SampleScenes/Scripts/NetworkSpaceshipBullet.cs' -'Assets/Scripts/ColorManager.cs' -'Assets/Scripts/ColorOption.cs' -'Assets/Scripts/ColorPicker.cs' -'Assets/Scripts/DoneButtonPressed.cs' -'Assets/Scripts/DoodleShake.cs' -'Assets/Scripts/FadingTextAnimation.cs' -'Assets/Scripts/LoadSceneOnTap.cs' -'Assets/Scripts/RandomSprite.cs' -'Assets/Scripts/ScreenCapture.cs' -'Assets/Scripts/SizeManager.cs' -'Assets/Scripts/SwipeTrail.cs' -'Assets/Scripts/Timer.cs' -'Assets/Scripts/ToolsStateManager.cs' -'Assets/Scripts/ToolState.cs' -'Assets/Scripts/UIRaycastDetector.cs' -'Assets/Scripts/Width.cs' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Runtime.Serialization.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/System.Xml.Linq.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/UnityScript.Lang.dll' --r:'/Applications/Unity/Unity.app/Contents/Mono/lib/mono/unity/Boo.Lang.dll' --sdk:unity diff --git a/Close Enough!/obj/Debug/Assembly-CSharp.csproj.FilesWrittenAbsolute.txt b/Close Enough!/obj/Debug/Assembly-CSharp.csproj.FilesWrittenAbsolute.txt deleted file mode 100644 index 91fd652..0000000 --- a/Close Enough!/obj/Debug/Assembly-CSharp.csproj.FilesWrittenAbsolute.txt +++ /dev/null @@ -1,92 +0,0 @@ -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.UIAutomation.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.UIAutomation.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.TestRunner.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.TestRunner.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/nunit.framework.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.Networking.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.Networking.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.UI.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.UI.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.Timeline.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.Timeline.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.TreeEditor.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.GoogleAudioSpatializer.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.GoogleAudioSpatializer.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.HoloLens.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.HoloLens.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.SpatialTracking.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.SpatialTracking.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.VR.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.Graphs.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.OSXStandalone.Extensions.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.Advertisements.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.Advertisements.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.Analytics.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.Analytics.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.Purchasing.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.Purchasing.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.StandardEvents.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Unity.Cecil.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Unity.SerializationLogic.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Unity.DataContract.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/ExCSS.Unity.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Unity.Legacy.NRefactory.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Unity.UNetWeaver.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Unity.UNetWeaver.dll.mdb -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Unity.CecilTools.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Unity.Cecil.Pdb.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Unity.Cecil.Mdb.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.iOS.Extensions.Xcode.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.iOS.Extensions.Xcode.xml -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Assembly-CSharp.dll.mdb -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Assembly-CSharp.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/obj/Debug/Assembly-CSharp.dll -/Users/alexberthon/Documents/GitHub/CloseEnough/Close Enough!/obj/Debug/Assembly-CSharp.dll.mdb -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/obj/Debug/Assembly-CSharp.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/obj/Debug/Assembly-CSharp.dll.mdb -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.UI.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.UI.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.Networking.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.Networking.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.TestRunner.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.TestRunner.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/nunit.framework.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.Timeline.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.Timeline.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.TreeEditor.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.UIAutomation.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.UIAutomation.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.GoogleAudioSpatializer.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.GoogleAudioSpatializer.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.HoloLens.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.HoloLens.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.SpatialTracking.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.SpatialTracking.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.VR.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.Graphs.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.OSXStandalone.Extensions.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.Advertisements.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.Advertisements.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.Analytics.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.Analytics.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.Purchasing.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.Purchasing.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEngine.StandardEvents.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Unity.Cecil.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Unity.SerializationLogic.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Unity.DataContract.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/ExCSS.Unity.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Unity.Legacy.NRefactory.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Unity.UNetWeaver.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Unity.UNetWeaver.dll.mdb -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Unity.CecilTools.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Unity.Cecil.Pdb.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Unity.Cecil.Mdb.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.iOS.Extensions.Xcode.dll -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/UnityEditor.iOS.Extensions.Xcode.xml -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Assembly-CSharp.dll.mdb -/Users/jenniferluong/Documents/GitHub/CloseEnough/Close Enough!/Temp/bin/Debug/Assembly-CSharp.dll diff --git a/Close Enough!/obj/Debug/Assembly-CSharp.dll b/Close Enough!/obj/Debug/Assembly-CSharp.dll deleted file mode 100755 index d5867c2..0000000 Binary files a/Close Enough!/obj/Debug/Assembly-CSharp.dll and /dev/null differ diff --git a/Close Enough!/obj/Debug/Assembly-CSharp.dll.mdb b/Close Enough!/obj/Debug/Assembly-CSharp.dll.mdb deleted file mode 100644 index ef66e2d..0000000 Binary files a/Close Enough!/obj/Debug/Assembly-CSharp.dll.mdb and /dev/null differ