diff options
Diffstat (limited to 'Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts')
80 files changed, 5651 insertions, 0 deletions
diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling.meta new file mode 100644 index 0000000..408aec2 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 404d7999c3b78454798028d2efcb9336 +folderAsset: yes +timeCreated: 1529327267 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/CullArea.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/CullArea.cs new file mode 100644 index 0000000..0af640f --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/CullArea.cs @@ -0,0 +1,501 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="CullArea.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// Represents the cull area used for network culling. +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using System.Collections.Generic; +using UnityEngine; + +namespace Photon.Pun.UtilityScripts +{ + using System; + + + /// <summary> + /// Represents the cull area used for network culling. + /// </summary> + public class CullArea : MonoBehaviour + { + private const int MAX_NUMBER_OF_ALLOWED_CELLS = 250; + + public const int MAX_NUMBER_OF_SUBDIVISIONS = 3; + + /// <summary> + /// 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. + /// </summary> + public readonly byte FIRST_GROUP_ID = 1; + + /// <summary> + /// 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. + /// </summary> + public readonly int[] SUBDIVISION_FIRST_LEVEL_ORDER = new int[4] { 0, 1, 1, 1 }; + + /// <summary> + /// 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. + /// </summary> + public readonly int[] SUBDIVISION_SECOND_LEVEL_ORDER = new int[8] { 0, 2, 1, 2, 0, 2, 1, 2 }; + + /// <summary> + /// 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. + /// </summary> + 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<int, GameObject> Map { get; private set; } + + public bool YIsUpAxis = false; + public bool RecreateCellHierarchy = false; + + private byte idCounter; + + /// <summary> + /// Creates the cell hierarchy at runtime. + /// </summary> + private void Awake() + { + this.idCounter = this.FIRST_GROUP_ID; + + this.CreateCellHierarchy(); + } + + /// <summary> + /// Creates the cell hierarchy in editor and draws the cell view. + /// </summary> + public void OnDrawGizmos() + { + this.idCounter = this.FIRST_GROUP_ID; + + if (this.RecreateCellHierarchy) + { + this.CreateCellHierarchy(); + } + + this.DrawCells(); + } + + /// <summary> + /// Creates the cell hierarchy. + /// </summary> + 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; + } + + /// <summary> + /// Creates all child cells. + /// </summary> + /// <param name="parent">The current parent node.</param> + /// <param name="cellLevelInHierarchy">The cell level within the current hierarchy.</param> + 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)); + } + } + } + + /// <summary> + /// Draws the cells. + /// </summary> + private void DrawCells() + { + if ((this.CellTree != null) && (this.CellTree.RootNode != null)) + { + this.CellTree.RootNode.Draw(); + } + else + { + this.RecreateCellHierarchy = true; + } + } + + /// <summary> + /// Checks if the cell count is allowed. + /// </summary> + /// <returns>True if the cell count is allowed, false if the cell count is too large.</returns> + 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)); + } + + /// <summary> + /// Gets a list of all cell IDs the player is currently inside or nearby. + /// </summary> + /// <param name="position">The current position of the player.</param> + /// <returns>A list containing all cell IDs the player is currently inside or nearby.</returns> + public List<byte> GetActiveCells(Vector3 position) + { + List<byte> activeCells = new List<byte>(0); + this.CellTree.RootNode.GetActiveCells(activeCells, this.YIsUpAxis, position); + + // it makes sense to sort the "nearby" cells. those are in the list in positions after the subdivisions the point is inside. 2 subdivisions result in 3 areas the point is in. + int cellsActive = this.NumberOfSubdivisions + 1; + int cellsNearby = activeCells.Count - cellsActive; + if (cellsNearby > 0) + { + activeCells.Sort(cellsActive, cellsNearby, new ByteComparer()); + } + return activeCells; + } + } + + /// <summary> + /// Represents the tree accessible from its root node. + /// </summary> + public class CellTree + { + /// <summary> + /// Represents the root node of the cell tree. + /// </summary> + public CellTreeNode RootNode { get; private set; } + + /// <summary> + /// Default constructor. + /// </summary> + public CellTree() + { + } + + /// <summary> + /// Constructor to define the root node. + /// </summary> + /// <param name="root">The root node of the tree.</param> + public CellTree(CellTreeNode root) + { + this.RootNode = root; + } + } + + /// <summary> + /// Represents a single node of the tree. + /// </summary> + public class CellTreeNode + { + public enum ENodeType : byte + { + Root = 0, + Node = 1, + Leaf = 2 + } + + /// <summary> + /// Represents the unique ID of the cell. + /// </summary> + public byte Id; + + /// <summary> + /// Represents the center, top-left or bottom-right position of the cell + /// or the size of the cell. + /// </summary> + public Vector3 Center, Size, TopLeft, BottomRight; + + /// <summary> + /// Describes the current node type of the cell tree node. + /// </summary> + public ENodeType NodeType; + + /// <summary> + /// Reference to the parent node. + /// </summary> + public CellTreeNode Parent; + + /// <summary> + /// A list containing all child nodes. + /// </summary> + public List<CellTreeNode> Childs; + + /// <summary> + /// The max distance the player can have to the center of the cell for being 'nearby'. + /// This is calculated once at runtime. + /// </summary> + private float maxDistance; + + /// <summary> + /// Default constructor. + /// </summary> + public CellTreeNode() + { + } + + /// <summary> + /// Constructor to define the ID and the node type as well as setting a parent node. + /// </summary> + /// <param name="id">The ID of the cell is used as the interest group.</param> + /// <param name="nodeType">The node type of the cell tree node.</param> + /// <param name="parent">The parent node of the cell tree node.</param> + public CellTreeNode(byte id, ENodeType nodeType, CellTreeNode parent) + { + this.Id = id; + + this.NodeType = nodeType; + + this.Parent = parent; + } + + /// <summary> + /// Adds the given child to the node. + /// </summary> + /// <param name="child">The child which is added to the node.</param> + public void AddChild(CellTreeNode child) + { + if (this.Childs == null) + { + this.Childs = new List<CellTreeNode>(1); + } + + this.Childs.Add(child); + } + + /// <summary> + /// Draws the cell in the editor. + /// </summary> + 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); + + byte offset = (byte)this.NodeType; + GUIStyle gs = new GUIStyle() { fontStyle = FontStyle.Bold }; + gs.normal.textColor = Gizmos.color; + UnityEditor.Handles.Label(this.Center+(Vector3.forward*offset*1f), this.Id.ToString(), gs); +#endif + } + + /// <summary> + /// Gathers all cell IDs the player is currently inside or nearby. + /// </summary> + /// <param name="activeCells">The list to add all cell IDs to the player is currently inside or nearby.</param> + /// <param name="yIsUpAxis">Describes if the y-axis is used as up-axis.</param> + /// <param name="position">The current position of the player.</param> + public void GetActiveCells(List<byte> 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); + } + } + } + } + + /// <summary> + /// Checks if the given point is inside the cell. + /// </summary> + /// <param name="yIsUpAxis">Describes if the y-axis is used as up-axis.</param> + /// <param name="point">The point to check.</param> + /// <returns>True if the point is inside the cell, false if the point is not inside the cell.</returns> + 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; + } + + /// <summary> + /// Checks if the given point is near the cell. + /// </summary> + /// <param name="yIsUpAxis">Describes if the y-axis is used as up-axis.</param> + /// <param name="point">The point to check.</param> + /// <returns>True if the point is near the cell, false if the point is too far away.</returns> + 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)); + } + } + + + public class ByteComparer : IComparer<byte> + { + /// <inheritdoc /> + public int Compare(byte x, byte y) + { + return x == y ? 0 : x < y ? -1 : 1; + } + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/CullArea.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/CullArea.cs.meta new file mode 100644 index 0000000..9f081cd --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/CullArea.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dfb1c264fdc576442b2f42c998bed4a2 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/CullingHandler.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/CullingHandler.cs new file mode 100644 index 0000000..eb90b22 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/CullingHandler.cs @@ -0,0 +1,254 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="CullingHandler.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// Handles the network culling. +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using System.Collections.Generic; + +using UnityEngine; + +using Photon.Pun; + +namespace Photon.Pun.UtilityScripts +{ + using ExitGames.Client.Photon; + + + /// <summary> + /// Handles the network culling. + /// </summary> + [RequireComponent(typeof(PhotonView))] + public class CullingHandler : MonoBehaviour, IPunObservable + { + #region VARIABLES + + private int orderIndex; + + private CullArea cullArea; + + private List<byte> previousActiveCells, activeCells; + + private PhotonView pView; + + private Vector3 lastPosition, currentPosition; + + + // used to limit the number of UpdateInterestGroups calls per second (there is no use to change groups more than a few times per second, even if the Culling algorithm makes it look like that) + private float timeSinceUpdate; + // see timeSinceUpdate + private float timeBetweenUpdatesMin = 0.33f; + + + #endregion + + #region UNITY_FUNCTIONS + + /// <summary> + /// Gets references to the PhotonView component and the cull area game object. + /// </summary> + private void OnEnable() + { + if (this.pView == null) + { + this.pView = GetComponent<PhotonView>(); + + if (!this.pView.IsMine) + { + return; + } + } + + if (this.cullArea == null) + { + this.cullArea = FindObjectOfType<CullArea>(); + } + + this.previousActiveCells = new List<byte>(0); + this.activeCells = new List<byte>(0); + + this.currentPosition = this.lastPosition = transform.position; + } + + /// <summary> + /// Initializes the right interest group or prepares the permanent change of the interest Group of the PhotonView component. + /// </summary> + 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); + } + } + } + + + + /// <summary> + /// Checks if the player has moved previously and updates the interest groups if necessary. + /// </summary> + private void Update() + { + if (!this.pView.IsMine) + { + return; + } + + // we'll limit how often this update may run at all (to avoid too frequent changes and flooding the server with SetInterestGroups calls) + this.timeSinceUpdate += Time.deltaTime; + if (this.timeSinceUpdate < this.timeBetweenUpdatesMin) + { + 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(); + this.timeSinceUpdate = 0; + } + } + } + + /// <summary> + /// Drawing informations. + /// </summary> + 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), "<color=white>PhotonView Group: " + this.pView.Group + "</color>", new GUIStyle() { alignment = TextAnchor.UpperLeft, fontSize = 16 }); + GUI.Label(new Rect(20.0f, Screen.height - 100.0f, 200.0f, 40.0f), "<color=white>" + subscribedAndActiveCells + "</color>", new GUIStyle() { alignment = TextAnchor.UpperLeft, fontSize = 16 }); + GUI.Label(new Rect(20.0f, Screen.height - 60.0f, 200.0f, 40.0f), "<color=white>" + subscribedCells + "</color>", new GUIStyle() { alignment = TextAnchor.UpperLeft, fontSize = 16 }); + } + + #endregion + + /// <summary> + /// Checks if the previously active cells have changed. + /// </summary> + /// <returns>True if the previously active cells have changed and false otherwise.</returns> + private bool HaveActiveCellsChanged() + { + if (this.cullArea.NumberOfSubdivisions == 0) + { + return false; + } + + this.previousActiveCells = new List<byte>(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; + } + + /// <summary> + /// Unsubscribes from old and subscribes to new interest groups. + /// </summary> + private void UpdateInterestGroups() + { + List<byte> disable = new List<byte>(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 + + /// <summary> + /// 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. + /// </summary> + 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/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/CullingHandler.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/CullingHandler.cs.meta new file mode 100644 index 0000000..74b7441 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/CullingHandler.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 84db789113d4b01418c1becb128c4561 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/Editor.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/Editor.meta new file mode 100644 index 0000000..305366f --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/Editor.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: fcede10f4c76b443483f21320fee20e5 +folderAsset: yes +timeCreated: 1529329408 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/Editor/CullAreaEditor.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/Editor/CullAreaEditor.cs new file mode 100644 index 0000000..b306eeb --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/Editor/CullAreaEditor.cs @@ -0,0 +1,265 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="CullAreaEditor.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// Custom inspector for CullArea +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using UnityEditor; +using UnityEngine; + +namespace Photon.Pun.UtilityScripts +{ + [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<CullArea>().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(); + } + + /// <summary> + /// Represents the inspector GUI when edit mode is active. + /// </summary> + 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/v2/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(); + } + } + + /// <summary> + /// Represents the inspector GUI when play mode is active. + /// </summary> + 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(); + } + } + + /// <summary> + /// Aligns the editor view with the created grid. + /// </summary> + 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/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/Editor/CullAreaEditor.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/Editor/CullAreaEditor.cs.meta new file mode 100644 index 0000000..7d72143 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/Editor/CullAreaEditor.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: abadaa451a7bff0489078ed9eec61133 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/Editor/PhotonUnityNetworking.Utilities.Culling.Editor.asmdef b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/Editor/PhotonUnityNetworking.Utilities.Culling.Editor.asmdef new file mode 100644 index 0000000..2be9de1 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/Editor/PhotonUnityNetworking.Utilities.Culling.Editor.asmdef @@ -0,0 +1,12 @@ +{ + "name": "PhotonUnityNetworking.Utilities.Culling.Editor", + "references": [ + "PhotonUnityNetworking.Utilities" + ], + "optionalUnityReferences": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/Editor/PhotonUnityNetworking.Utilities.Culling.Editor.asmdef.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/Editor/PhotonUnityNetworking.Utilities.Culling.Editor.asmdef.meta new file mode 100644 index 0000000..b43d734 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Culling/Editor/PhotonUnityNetworking.Utilities.Culling.Editor.asmdef.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 06dafbbe6b7b3a84f84213f47aabe7f0 +timeCreated: 1537459565 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging.meta new file mode 100644 index 0000000..ec00ddc --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 72b80dd954bc647c4a2a924b87762f92 +folderAsset: yes +timeCreated: 1529327208 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/PhotonLagSimulationGui.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/PhotonLagSimulationGui.cs new file mode 100644 index 0000000..52c29c6 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/PhotonLagSimulationGui.cs @@ -0,0 +1,109 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="PhotonLagSimulationGui.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// 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. +// Part of the [Optional GUI](@ref optionalGui). +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + + +using UnityEngine; + +using Photon.Pun; +using Photon.Realtime; +using ExitGames.Client.Photon; + +namespace Photon.Pun.UtilityScripts +{ + /// <summary> + /// 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. + /// </summary> + /// \ingroup optionalGui + public class PhotonLagSimulationGui : MonoBehaviour + { + /// <summary>Positioning rect for window.</summary> + public Rect WindowRect = new Rect(0, 100, 120, 100); + + /// <summary>Unity GUI Window ID (must be unique or will cause issues).</summary> + public int WindowId = 101; + + /// <summary>Shows or hides GUI (does not affect settings).</summary> + public bool Visible = true; + + /// <summary>The peer currently in use (to set the network simulation).</summary> + public PhotonPeer Peer { get; set; } + + public void Start() + { + this.Peer = PhotonNetwork.NetworkingClient.LoadBalancingPeer; + } + + 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/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/PhotonLagSimulationGui.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/PhotonLagSimulationGui.cs.meta new file mode 100644 index 0000000..5a7173b --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/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/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/PhotonStatsGui.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/PhotonStatsGui.cs new file mode 100644 index 0000000..c4c7c15 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/PhotonStatsGui.cs @@ -0,0 +1,170 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="PhotonStatsGui.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// Basic GUI to show traffic and health statistics of the connection to Photon, +// toggled by shift+tab. +// Part of the [Optional GUI](@ref optionalGui). +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using UnityEngine; + +using Photon.Pun; +using Photon.Realtime; +using ExitGames.Client.Photon; + +namespace Photon.Pun.UtilityScripts +{ + /// <summary> + /// Basic GUI to show traffic and health statistics of the connection to Photon, + /// toggled by shift+tab. + /// </summary> + /// <remarks> + /// 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). + /// </remarks> + /// \ingroup optionalGui + public class PhotonStatsGui : MonoBehaviour + { + /// <summary>Shows or hides GUI (does not affect if stats are collected).</summary> + public bool statsWindowOn = true; + + /// <summary>Option to turn collecting stats on or off (used in Update()).</summary> + public bool statsOn = true; + + /// <summary>Shows additional "health" values of connection.</summary> + public bool healthStatsVisible; + + /// <summary>Shows additional "lower level" traffic stats.</summary> + public bool trafficStatsOn; + + /// <summary>Show buttons to control stats and reset them.</summary> + public bool buttonsOn; + + /// <summary>Positioning rect for window.</summary> + public Rect statsRect = new Rect(0, 100, 200, 50); + + /// <summary>Unity GUI Window ID (must be unique or will cause issues).</summary> + public int WindowId = 100; + + + public void Start() + { + if (this.statsRect.x <= 0) + { + this.statsRect.x = Screen.width - this.statsRect.width; + } + } + + /// <summary>Checks for shift+tab input combination (to toggle statsOn).</summary> + 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.NetworkingClient.LoadBalancingPeer.TrafficStatsEnabled != statsOn) + { + PhotonNetwork.NetworkingClient.LoadBalancingPeer.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.NetworkingClient.LoadBalancingPeer.TrafficStatsGameLevel; + long elapsedMs = PhotonNetwork.NetworkingClient.LoadBalancingPeer.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.NetworkingClient.LoadBalancingPeer.TrafficStatsReset(); + PhotonNetwork.NetworkingClient.LoadBalancingPeer.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.NetworkingClient.LoadBalancingPeer.TrafficStatsIncoming.ToString(); + trafficStatsOut = "Outgoing: \n" + PhotonNetwork.NetworkingClient.LoadBalancingPeer.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.NetworkingClient.LoadBalancingPeer.RoundTripTime, + PhotonNetwork.NetworkingClient.LoadBalancingPeer.RoundTripTimeVariance, + PhotonNetwork.NetworkingClient.LoadBalancingPeer.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(); + } + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/PhotonStatsGui.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/PhotonStatsGui.cs.meta new file mode 100644 index 0000000..dc1049b --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/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/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/PointedAtGameObjectInfo.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/PointedAtGameObjectInfo.cs new file mode 100644 index 0000000..239111c --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/PointedAtGameObjectInfo.cs @@ -0,0 +1,84 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="PointedAtGameObjectInfo.cs" company="Exit Games GmbH"> +// </copyright> +// <summary> +// Display ViewId, OwnerActorNr, IsCeneView and IsMine when clicked using the old UI system +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using System; + +using UnityEngine; +using UnityEngine.UI; +using UnityEngine.EventSystems; + +using Photon.Pun; +using Photon.Realtime; + +namespace Photon.Pun.UtilityScripts +{ + /// <summary> + /// Display ViewId, OwnerActorNr, IsCeneView and IsMine when clicked. + /// </summary> + public class PointedAtGameObjectInfo : MonoBehaviour + { + public static PointedAtGameObjectInfo Instance; + + public Text text; + + Transform focus; + + void Start() + { + if (Instance != null) + { + Debug.LogWarning("PointedAtGameObjectInfo is already featured in the scene, gameobject is destroyed"); + Destroy(this.gameObject); + } + + Instance = this; + } + + public void SetFocus(PhotonView pv) + { + + focus = pv != null ? pv.transform : null; + + if (pv != null) + { + text.text = string.Format("id {0} own: {1} {2}{3}", pv.ViewID, pv.OwnerActorNr, (pv.IsRoomView) ? "scn" : "", (pv.IsMine) ? " mine" : ""); + //GUI.Label (new Rect (Input.mousePosition.x + 5, Screen.height - Input.mousePosition.y - 15, 300, 30), ); + } + else + { + text.text = string.Empty; + + } + } + + public void RemoveFocus(PhotonView pv) + { + if (pv == null) + { + text.text = string.Empty; + return; + } + + if (pv.transform == focus) + { + text.text = string.Empty; + return; + } + + } + + void LateUpdate() + { + if (focus != null) + { + this.transform.position = Camera.main.WorldToScreenPoint(focus.position); + } + } + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/PointedAtGameObjectInfo.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/PointedAtGameObjectInfo.cs.meta new file mode 100644 index 0000000..9ffbb4f --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/PointedAtGameObjectInfo.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e6262dd9a9b078c4e8cbd47495aa6d23 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/StatesGui.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/StatesGui.cs new file mode 100644 index 0000000..7d09c0a --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/StatesGui.cs @@ -0,0 +1,212 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="TabViewManager.cs" company="Exit Games GmbH"> +// </copyright> +// <summary> +// Output detailed information about Pun Current states, using the old Unity UI framework. +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using UnityEngine; +using Photon.Realtime; + +namespace Photon.Pun.UtilityScripts +{ + /// <summary> + /// Output detailed information about Pun Current states, using the old Unity UI framework. + /// </summary> + public class StatesGui : MonoBehaviour + { + public Rect GuiOffset = new Rect(250, 0, 300, 300); + public bool DontDestroy = true; + public bool ServerTimestamp; + public bool DetailedConnection; + public bool Server; + public bool AppVersion; + public bool UserId; + public bool Room; + public bool RoomProps; + public bool EventsIn; + public bool LocalPlayer; + public bool PlayerProps; + public bool Others; + public bool Buttons; + public bool ExpectedUsers; + + private Rect GuiRect = new Rect(); + private static StatesGui Instance; + + void Awake() + { + if (Instance != null) + { + DestroyImmediate(this.gameObject); + return; + } + if (DontDestroy) + { + Instance = this; + DontDestroyOnLoad(this.gameObject); + } + + if (EventsIn) + { + PhotonNetwork.NetworkingClient.LoadBalancingPeer.TrafficStatsEnabled = true; + } + } + + void OnDisable() + { + if (DontDestroy && Instance == this) + { + Instance = null; + } + + } + + float native_width = 800; + float native_height = 480; + void OnGUI() + { + if (PhotonNetwork.NetworkingClient == null || PhotonNetwork.NetworkingClient.LoadBalancingPeer == null || PhotonNetwork.NetworkingClient.LoadBalancingPeer.TrafficStatsIncoming == null) + { + return; + } + + //set up scaling + float rx = Screen.width / native_width; + float ry = Screen.height / native_height; + GUI.matrix = Matrix4x4.TRS (new Vector3(0, 0, 0), Quaternion.identity, new Vector3 (rx, ry, 1)); + + Rect GuiOffsetRuntime = new Rect(this.GuiOffset); + + if (GuiOffsetRuntime.x < 0) + { + GuiOffsetRuntime.x = Screen.width - GuiOffsetRuntime.width; + } + GuiRect.xMin = GuiOffsetRuntime.x; + GuiRect.yMin = GuiOffsetRuntime.y; + GuiRect.xMax = GuiOffsetRuntime.x + GuiOffsetRuntime.width; + GuiRect.yMax = GuiOffsetRuntime.y + GuiOffsetRuntime.height; + GUILayout.BeginArea(GuiRect); + + GUILayout.BeginHorizontal(); + if (this.ServerTimestamp) + { + GUILayout.Label((((double)PhotonNetwork.ServerTimestamp) / 1000d).ToString("F3")); + } + + if (Server) + { + GUILayout.Label(PhotonNetwork.ServerAddress + " " + PhotonNetwork.Server); + } + if (DetailedConnection) + { + GUILayout.Label(PhotonNetwork.NetworkClientState.ToString()); + } + if (AppVersion) + { + GUILayout.Label(PhotonNetwork.NetworkingClient.AppVersion); + } + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(); + if (UserId) + { + GUILayout.Label("UID: " + ((PhotonNetwork.AuthValues != null) ? PhotonNetwork.AuthValues.UserId : "no UserId")); + GUILayout.Label("UserId:" + PhotonNetwork.LocalPlayer.UserId); + } + GUILayout.EndHorizontal(); + + if (Room) + { + if (PhotonNetwork.InRoom) + { + GUILayout.Label(this.RoomProps ? PhotonNetwork.CurrentRoom.ToStringFull() : PhotonNetwork.CurrentRoom.ToString()); + } + else + { + GUILayout.Label("not in room"); + } + } + + if (EventsIn) + { + int fragments = PhotonNetwork.NetworkingClient.LoadBalancingPeer.TrafficStatsIncoming.FragmentCommandCount; + GUILayout.Label("Events Received: "+PhotonNetwork.NetworkingClient.LoadBalancingPeer.TrafficStatsGameLevel.EventCount + " Fragments: "+fragments); + } + + + if (this.LocalPlayer) + { + GUILayout.Label(PlayerToString(PhotonNetwork.LocalPlayer)); + } + if (Others) + { + foreach (Player player in PhotonNetwork.PlayerListOthers) + { + GUILayout.Label(PlayerToString(player)); + } + } + if (ExpectedUsers) + { + if (PhotonNetwork.InRoom) + { + int countExpected = (PhotonNetwork.CurrentRoom.ExpectedUsers != null) ? PhotonNetwork.CurrentRoom.ExpectedUsers.Length : 0; + + GUILayout.Label("Expected: " + countExpected + " " + + ((PhotonNetwork.CurrentRoom.ExpectedUsers != null) ? string.Join(",", PhotonNetwork.CurrentRoom.ExpectedUsers) : "") + ); + + } + } + + + if (Buttons) + { + if (!PhotonNetwork.IsConnected && GUILayout.Button("Connect")) + { + PhotonNetwork.ConnectUsingSettings(); + } + GUILayout.BeginHorizontal(); + if (PhotonNetwork.IsConnected && GUILayout.Button("Disconnect")) + { + PhotonNetwork.Disconnect(); + } + if (PhotonNetwork.IsConnected && GUILayout.Button("Close Socket")) + { + PhotonNetwork.NetworkingClient.LoadBalancingPeer.StopThread(); + } + GUILayout.EndHorizontal(); + if (PhotonNetwork.IsConnected && PhotonNetwork.InRoom && GUILayout.Button("Leave")) + { + PhotonNetwork.LeaveRoom(); + } + if (PhotonNetwork.IsConnected && PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom.PlayerTtl>0 && GUILayout.Button("Leave(abandon)")) + { + PhotonNetwork.LeaveRoom(false); + } + if (PhotonNetwork.IsConnected && !PhotonNetwork.InRoom && GUILayout.Button("Join Random")) + { + PhotonNetwork.JoinRandomRoom(); + } + if (PhotonNetwork.IsConnected && !PhotonNetwork.InRoom && GUILayout.Button("Create Room")) + { + PhotonNetwork.CreateRoom(null); + } + } + + GUILayout.EndArea(); + } + + private string PlayerToString(Player player) + { + if (PhotonNetwork.NetworkingClient == null) + { + Debug.LogError("nwp is null"); + return ""; + } + return string.Format("#{0:00} '{1}'{5} {4}{2} {3} {6}", player.ActorNumber + "/userId:<" + player.UserId + ">", player.NickName, player.IsMasterClient ? "(master)" : "", this.PlayerProps ? player.CustomProperties.ToStringFull() : "", (PhotonNetwork.LocalPlayer.ActorNumber == player.ActorNumber) ? "(you)" : "", player.UserId, player.IsInactive ? " / Is Inactive" : ""); + } + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/StatesGui.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/StatesGui.cs.meta new file mode 100644 index 0000000..303a404 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Debugging/StatesGui.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 62880f27e95abf2418fd79e9d9d568b4 +timeCreated: 1493998271 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer.meta new file mode 100644 index 0000000..f112b84 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 94d453efd58794348867b36584d05a1e +folderAsset: yes +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor.meta new file mode 100644 index 0000000..70d9f8a --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f1d46a1c486645945a3667d8bbe2d2e7 +folderAsset: yes +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PhotonTeamsManagerInspector.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PhotonTeamsManagerInspector.cs new file mode 100644 index 0000000..0b62397 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PhotonTeamsManagerInspector.cs @@ -0,0 +1,246 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="PhotonTeamsManagerEditor.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// Custom inspector for PhotonTeamsManager +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using System; +using UnityEngine; +using System.Collections.Generic; +using Photon.Realtime; +using UnityEditor; + +namespace Photon.Pun.UtilityScripts +{ + [CustomEditor(typeof(PhotonTeamsManager))] + public class PhotonTeamsManagerEditor : Editor + { + private Dictionary<byte, bool> foldouts = new Dictionary<byte, bool>(); + private PhotonTeamsManager photonTeams; + private SerializedProperty teamsListSp; + private SerializedProperty listFoldIsOpenSp; + + private const string proSkinString = + "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAECAYAAACzzX7wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi/P//PwM+wHL06FG8KpgYCABGZWVlvCYABBgA7/sHvGw+cz8AAAAASUVORK5CYII="; + private const string lightSkinString = "iVBORw0KGgoAAAANSUhEUgAAAAgAAAACCAIAAADq9gq6AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABVJREFUeNpiVFZWZsAGmBhwAIAAAwAURgBt4C03ZwAAAABJRU5ErkJggg=="; + private const string removeTextureName = "removeButton_generated"; + private Texture removeTexture; + + private bool isOpen; + + public override bool RequiresConstantRepaint() + { + return true; + } + + private void OnEnable() + { + photonTeams = target as PhotonTeamsManager; + teamsListSp = serializedObject.FindProperty("teamsList"); + listFoldIsOpenSp = serializedObject.FindProperty("listFoldIsOpen"); + isOpen = listFoldIsOpenSp.boolValue; + removeTexture = LoadTexture(removeTextureName, proSkinString, lightSkinString); + } + + /// <summary> + /// Read width and height if PNG file in pixels. + /// </summary> + /// <param name="imageData">PNG image data.</param> + /// <param name="width">Width of image in pixels.</param> + /// <param name="height">Height of image in pixels.</param> + 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 ]; + } + + private Texture LoadTexture(string textureName, string proSkin, string lightSkin) + { + string skin = EditorGUIUtility.isProSkin ? proSkin : lightSkin; + // Get image data (PNG) from base64 encoded strings. + byte[] imageData = Convert.FromBase64String( skin ); + // 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 = textureName; + tex.filterMode = FilterMode.Point; + tex.LoadImage( imageData ); + return tex; + } + + public override void OnInspectorGUI() + { + if (!Application.isPlaying) + { + DrawTeamsList(); + return; + } + PhotonTeam[] availableTeams = photonTeams.GetAvailableTeams(); + if (availableTeams != null) + { + EditorGUI.indentLevel++; + foreach (var availableTeam in availableTeams) + { + if (!foldouts.ContainsKey(availableTeam.Code)) + { + foldouts[availableTeam.Code] = true; + } + Player[] teamMembers; + if (photonTeams.TryGetTeamMembers(availableTeam, out teamMembers) && teamMembers != null) + { + foldouts[availableTeam.Code] = EditorGUILayout.Foldout(foldouts[availableTeam.Code], + string.Format("{0} ({1})", availableTeam.Name, teamMembers.Length)); + } + else + { + foldouts[availableTeam.Code] = EditorGUILayout.Foldout(foldouts[availableTeam.Code], + string.Format("{0} (0)", availableTeam.Name)); + } + if (foldouts[availableTeam.Code] && teamMembers != null) + { + EditorGUI.indentLevel++; + foreach (var player in teamMembers) + { + EditorGUILayout.LabelField(string.Empty, string.Format("{0} {1}", player, player.IsLocal ? " - You -" : string.Empty)); + } + EditorGUI.indentLevel--; + } + } + EditorGUI.indentLevel--; + } + } + + private void DrawTeamsList() + { + GUILayout.Space(5); + HashSet<byte> codes = new HashSet<byte>(); + HashSet<string> names = new HashSet<string>(); + for (int i = 0; i < teamsListSp.arraySize; i++) + { + SerializedProperty e = teamsListSp.GetArrayElementAtIndex(i); + string name = e.FindPropertyRelative("Name").stringValue; + byte code = (byte)e.FindPropertyRelative("Code").intValue; + codes.Add(code); + names.Add(name); + } + this.serializedObject.Update(); + EditorGUI.BeginChangeCheck(); + isOpen = PhotonGUI.ContainerHeaderFoldout(string.Format("Teams List ({0})", teamsListSp.arraySize), isOpen); + if (EditorGUI.EndChangeCheck()) + { + listFoldIsOpenSp.boolValue = isOpen; + } + if (isOpen) + { + const float containerElementHeight = 22; + const float propertyHeight = 16; + const float paddingRight = 29; + const float paddingLeft = 5; + const float spacingY = 3; + float containerHeight = (teamsListSp.arraySize + 1) * containerElementHeight; + Rect containerRect = PhotonGUI.ContainerBody(containerHeight); + float propertyWidth = containerRect.width - paddingRight; + float codePropertyWidth = propertyWidth / 5; + float namePropertyWidth = 4 * propertyWidth / 5; + Rect elementRect = new Rect(containerRect.xMin, containerRect.yMin, + containerRect.width, containerElementHeight); + Rect propertyPosition = new Rect(elementRect.xMin + paddingLeft, elementRect.yMin + spacingY, + codePropertyWidth, propertyHeight); + EditorGUI.LabelField(propertyPosition, "Code"); + Rect secondPropertyPosition = new Rect(elementRect.xMin + paddingLeft + codePropertyWidth, elementRect.yMin + spacingY, + namePropertyWidth, propertyHeight); + EditorGUI.LabelField(secondPropertyPosition, "Name"); + for (int i = 0; i < teamsListSp.arraySize; ++i) + { + elementRect = new Rect(containerRect.xMin, containerRect.yMin + containerElementHeight * (i + 1), + containerRect.width, containerElementHeight); + propertyPosition = new Rect(elementRect.xMin + paddingLeft, elementRect.yMin + spacingY, + codePropertyWidth, propertyHeight); + SerializedProperty teamElementSp = teamsListSp.GetArrayElementAtIndex(i); + SerializedProperty teamNameSp = teamElementSp.FindPropertyRelative("Name"); + SerializedProperty teamCodeSp = teamElementSp.FindPropertyRelative("Code"); + string oldName = teamNameSp.stringValue; + byte oldCode = (byte)teamCodeSp.intValue; + EditorGUI.BeginChangeCheck(); + EditorGUI.PropertyField(propertyPosition, teamCodeSp, GUIContent.none); + if (EditorGUI.EndChangeCheck()) + { + byte newCode = (byte)teamCodeSp.intValue; + if (codes.Contains(newCode)) + { + Debug.LogWarningFormat("Team with the same code {0} already exists", newCode); + teamCodeSp.intValue = oldCode; + } + } + secondPropertyPosition = new Rect(elementRect.xMin + paddingLeft + codePropertyWidth, elementRect.yMin + spacingY, + namePropertyWidth, propertyHeight); + EditorGUI.BeginChangeCheck(); + EditorGUI.PropertyField(secondPropertyPosition, teamNameSp, GUIContent.none); + if (EditorGUI.EndChangeCheck()) + { + string newName = teamNameSp.stringValue; + if (string.IsNullOrEmpty(newName)) + { + Debug.LogWarning("Team name cannot be null or empty"); + teamNameSp.stringValue = oldName; + } + else if (names.Contains(newName)) + { + Debug.LogWarningFormat("Team with the same name \"{0}\" already exists", newName); + teamNameSp.stringValue = oldName; + } + } + Rect removeButtonRect = new Rect( + elementRect.xMax - PhotonGUI.DefaultRemoveButtonStyle.fixedWidth, + elementRect.yMin + 2, + PhotonGUI.DefaultRemoveButtonStyle.fixedWidth, + PhotonGUI.DefaultRemoveButtonStyle.fixedHeight); + if (GUI.Button(removeButtonRect, new GUIContent(removeTexture), PhotonGUI.DefaultRemoveButtonStyle)) + { + teamsListSp.DeleteArrayElementAtIndex(i); + } + if (i < teamsListSp.arraySize - 1) + { + Rect texturePosition = new Rect(elementRect.xMin + 2, elementRect.yMax, elementRect.width - 4, + 1); + PhotonGUI.DrawSplitter(texturePosition); + } + } + } + if (PhotonGUI.AddButton()) + { + byte c = 0; + while (codes.Contains(c) && c < byte.MaxValue) + { + c++; + } + this.teamsListSp.arraySize++; + SerializedProperty teamElementSp = this.teamsListSp.GetArrayElementAtIndex(teamsListSp.arraySize - 1); + SerializedProperty teamNameSp = teamElementSp.FindPropertyRelative("Name"); + SerializedProperty teamCodeSp = teamElementSp.FindPropertyRelative("Code"); + teamCodeSp.intValue = c; + string n = "New Team"; + int o = 1; + while (names.Contains(n)) + { + n = string.Format("New Team {0}", o); + o++; + } + teamNameSp.stringValue = n; + } + this.serializedObject.ApplyModifiedProperties(); + } + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PhotonTeamsManagerInspector.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PhotonTeamsManagerInspector.cs.meta new file mode 100644 index 0000000..4b3d3dd --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PhotonTeamsManagerInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8cb74f08e3fc52942a0d8557772bf4dc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PhotonUnityNetworking.Utilities.PhotonPlayer.Editor.asmdef b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PhotonUnityNetworking.Utilities.PhotonPlayer.Editor.asmdef new file mode 100644 index 0000000..6dcc4a0 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PhotonUnityNetworking.Utilities.PhotonPlayer.Editor.asmdef @@ -0,0 +1,15 @@ +{ + "name": "PhotonUnityNetworking.Utilities.PhotonPlayer.Editor", + "references": [ + "PhotonRealtime", + "PhotonUnityNetworking", + "PhotonUnityNetworking.Utilities", + "PhotonUnityNetworking.Editor" + ], + "optionalUnityReferences": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PhotonUnityNetworking.Utilities.PhotonPlayer.Editor.asmdef.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PhotonUnityNetworking.Utilities.PhotonPlayer.Editor.asmdef.meta new file mode 100644 index 0000000..de22c01 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PhotonUnityNetworking.Utilities.PhotonPlayer.Editor.asmdef.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7024f760fc566cf45a16d2c838e22b2d +timeCreated: 1537459565 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PlayerNumberingInspector.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PlayerNumberingInspector.cs new file mode 100644 index 0000000..f59568e --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PlayerNumberingInspector.cs @@ -0,0 +1,67 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="PlayerNumberingInspector.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// Custom inspector for PlayerNumbering +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using UnityEditor; + +using Photon.Pun; +using Photon.Realtime; + +namespace Photon.Pun.UtilityScripts +{ + [CustomEditor(typeof(PlayerNumbering))] + public class PlayerNumberingInspector : Editor { + + int localPlayerIndex; + + void OnEnable () { + PlayerNumbering.OnPlayerNumberingChanged += RefreshData; + } + + void OnDisable () { + PlayerNumbering.OnPlayerNumberingChanged -= RefreshData; + } + + public override void OnInspectorGUI() + { + DrawDefaultInspector(); + + PlayerNumbering.OnPlayerNumberingChanged += RefreshData; + + if (PhotonNetwork.InRoom) + { + EditorGUILayout.LabelField("Player Index", "Player ID"); + if (PlayerNumbering.SortedPlayers != null) + { + foreach(Player punPlayer in PlayerNumbering.SortedPlayers) + { + GUI.enabled = punPlayer.ActorNumber > 0; + EditorGUILayout.LabelField("Player " +punPlayer.GetPlayerNumber() + (punPlayer.IsLocal?" - You -":""), punPlayer.ActorNumber == 0?"n/a":punPlayer.ToStringFull()); + GUI.enabled = true; + } + } + }else{ + GUILayout.Label("PlayerNumbering only works when localPlayer is inside a room"); + } + } + + /// <summary> + /// 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 + /// </summary> + void RefreshData() + { + Repaint(); + } + + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PlayerNumberingInspector.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PlayerNumberingInspector.cs.meta new file mode 100644 index 0000000..4ed2ee0 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PlayerNumberingInspector.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d6590f39353bf4efdb3b14691166135f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PunTeamsInspector.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PunTeamsInspector.cs new file mode 100644 index 0000000..18c48a1 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PunTeamsInspector.cs @@ -0,0 +1,64 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="PunTeamsInspector.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// Custom inspector for PunTeams +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + + +using System; +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using UnityEditor; + +using Photon.Pun; +using Photon.Realtime; + +namespace Photon.Pun.UtilityScripts +{ +#pragma warning disable 0618 + [CustomEditor(typeof(PunTeams))] + public class PunTeamsInspector : Editor { + + + Dictionary<PunTeams.Team, bool> _Foldouts ; + + public override void OnInspectorGUI() + { + if (_Foldouts==null) + { + _Foldouts = new Dictionary<PunTeams.Team, bool>(); + } + + if (PunTeams.PlayersPerTeam!=null) + { + foreach (KeyValuePair<PunTeams.Team,List<Player>> _pair in PunTeams.PlayersPerTeam) + { +#pragma warning restore 0618 + 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(Player _player in _pair.Value) + { + EditorGUILayout.LabelField("",_player.ToString() + (PhotonNetwork.LocalPlayer==_player?" - You -":"")); + } + EditorGUI.indentLevel--; + } + + } + } + } + } +} + diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PunTeamsInspector.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/Editor/PunTeamsInspector.cs.meta new file mode 100644 index 0000000..ff6b7e0 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/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/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PhotonTeamsManager.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PhotonTeamsManager.cs new file mode 100644 index 0000000..792898f --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PhotonTeamsManager.cs @@ -0,0 +1,628 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="PhotonTeamsManager.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// Implements teams in a room/game with help of player properties. +// </summary> +// <remarks> +// Teams are defined by name and code. 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. +// </remarks> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using UnityEngine; + +using Photon.Realtime; +using Hashtable = ExitGames.Client.Photon.Hashtable; + +namespace Photon.Pun.UtilityScripts +{ + [Serializable] + public class PhotonTeam + { + public string Name; + public byte Code; + + public override string ToString() + { + return string.Format("{0} [{1}]", this.Name, this.Code); + } + } + + /// <summary> + /// Implements teams in a room/game with help of player properties. Access them by Player.GetTeam extension. + /// </summary> + /// <remarks> + /// 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. + /// </remarks> + [DisallowMultipleComponent] + public class PhotonTeamsManager : MonoBehaviour, IMatchmakingCallbacks, IInRoomCallbacks + { + #if UNITY_EDITOR + #pragma warning disable 0414 + [SerializeField] + private bool listFoldIsOpen = true; + #pragma warning restore 0414 + #endif + + [SerializeField] + private List<PhotonTeam> teamsList = new List<PhotonTeam> + { + new PhotonTeam { Name = "Blue", Code = 1 }, + new PhotonTeam { Name = "Red", Code = 2 } + }; + + private Dictionary<byte, PhotonTeam> teamsByCode; + private Dictionary<string, PhotonTeam> teamsByName; + + /// <summary>The main list of teams with their player-lists. Automatically kept up to date.</summary> + private Dictionary<byte, HashSet<Player>> playersPerTeam; + + /// <summary>Defines the player custom property name to use for team affinity of "this" player.</summary> + public const string TeamPlayerProp = "_pt"; + + public static event Action<Player, PhotonTeam> PlayerJoinedTeam; + public static event Action<Player, PhotonTeam> PlayerLeftTeam; + + private static PhotonTeamsManager instance; + public static PhotonTeamsManager Instance + { + get + { + if (instance == null) + { + instance = FindObjectOfType<PhotonTeamsManager>(); + if (instance == null) + { + GameObject obj = new GameObject(); + obj.name = "PhotonTeamsManager"; + instance = obj.AddComponent<PhotonTeamsManager>(); + } + instance.Init(); + } + + return instance; + } + } + + #region MonoBehaviour + + private void Awake() + { + if (instance == null || ReferenceEquals(this, instance)) + { + this.Init(); + instance = this; + } + else + { + Destroy(this); + } + } + + private void OnEnable() + { + PhotonNetwork.AddCallbackTarget(this); + } + + private void OnDisable() + { + PhotonNetwork.RemoveCallbackTarget(this); + this.ClearTeams(); + } + + private void Init() + { + teamsByCode = new Dictionary<byte, PhotonTeam>(teamsList.Count); + teamsByName = new Dictionary<string, PhotonTeam>(teamsList.Count); + playersPerTeam = new Dictionary<byte, HashSet<Player>>(teamsList.Count); + for (int i = 0; i < teamsList.Count; i++) + { + teamsByCode[teamsList[i].Code] = teamsList[i]; + teamsByName[teamsList[i].Name] = teamsList[i]; + playersPerTeam[teamsList[i].Code] = new HashSet<Player>(); + } + } + + #endregion + + #region IMatchmakingCallbacks + + void IMatchmakingCallbacks.OnJoinedRoom() + { + this.UpdateTeams(); + } + + void IMatchmakingCallbacks.OnLeftRoom() + { + this.ClearTeams(); + } + + void IInRoomCallbacks.OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps) + { + object temp; + if (changedProps.TryGetValue(TeamPlayerProp, out temp)) + { + if (temp == null) + { + foreach (byte code in playersPerTeam.Keys) + { + if (playersPerTeam[code].Remove(targetPlayer)) + { + if (PlayerLeftTeam != null) + { + PlayerLeftTeam(targetPlayer, teamsByCode[code]); + } + break; + } + } + } + else if (temp is byte) + { + byte teamCode = (byte) temp; + // check if player switched teams, remove from previous team + foreach (byte code in playersPerTeam.Keys) + { + if (code == teamCode) + { + continue; + } + if (playersPerTeam[code].Remove(targetPlayer)) + { + if (PlayerLeftTeam != null) + { + PlayerLeftTeam(targetPlayer, teamsByCode[code]); + } + break; + } + } + PhotonTeam team = teamsByCode[teamCode]; + if (!playersPerTeam[teamCode].Add(targetPlayer)) + { + Debug.LogWarningFormat("Unexpected situation while setting team {0} for player {1}, updating teams for all", team, targetPlayer); + this.UpdateTeams(); + } + if (PlayerJoinedTeam != null) + { + PlayerJoinedTeam(targetPlayer, team); + } + } + else + { + Debug.LogErrorFormat("Unexpected: custom property key {0} should have of type byte, instead we got {1} of type {2}. Player: {3}", + TeamPlayerProp, temp, temp.GetType(), targetPlayer); + } + } + } + + void IInRoomCallbacks.OnPlayerLeftRoom(Player otherPlayer) + { + if (otherPlayer.IsInactive) + { + return; + } + PhotonTeam team = otherPlayer.GetPhotonTeam(); + if (team != null && !playersPerTeam[team.Code].Remove(otherPlayer)) + { + Debug.LogWarningFormat("Unexpected situation while removing player {0} who left from team {1}, updating teams for all", otherPlayer, team); + // revert to 'brute force' in case of unexpected situation + this.UpdateTeams(); + } + } + + void IInRoomCallbacks.OnPlayerEnteredRoom(Player newPlayer) + { + PhotonTeam team = newPlayer.GetPhotonTeam(); + if (team == null) + { + return; + } + if (playersPerTeam[team.Code].Contains(newPlayer)) + { + // player rejoined w/ same team + return; + } + // check if player rejoined w/ different team, remove from previous team + foreach (var key in teamsByCode.Keys) + { + if (playersPerTeam[key].Remove(newPlayer)) + { + break; + } + } + if (!playersPerTeam[team.Code].Add(newPlayer)) + { + Debug.LogWarningFormat("Unexpected situation while adding player {0} who joined to team {1}, updating teams for all", newPlayer, team); + // revert to 'brute force' in case of unexpected situation + this.UpdateTeams(); + } + } + + #endregion + + #region Private methods + + private void UpdateTeams() + { + this.ClearTeams(); + for (int i = 0; i < PhotonNetwork.PlayerList.Length; i++) + { + Player player = PhotonNetwork.PlayerList[i]; + PhotonTeam playerTeam = player.GetPhotonTeam(); + if (playerTeam != null) + { + playersPerTeam[playerTeam.Code].Add(player); + } + } + } + + private void ClearTeams() + { + foreach (var key in playersPerTeam.Keys) + { + playersPerTeam[key].Clear(); + } + } + + #endregion + + #region Public API + + /// <summary> + /// Find a PhotonTeam using a team code. + /// </summary> + /// <param name="code">The team code.</param> + /// <param name="team">The team to be assigned if found.</param> + /// <returns>If successful or not.</returns> + public bool TryGetTeamByCode(byte code, out PhotonTeam team) + { + return teamsByCode.TryGetValue(code, out team); + } + + /// <summary> + /// Find a PhotonTeam using a team name. + /// </summary> + /// <param name="teamName">The team name.</param> + /// <param name="team">The team to be assigned if found.</param> + /// <returns>If successful or not.</returns> + public bool TryGetTeamByName(string teamName, out PhotonTeam team) + { + return teamsByName.TryGetValue(teamName, out team); + } + + /// <summary> + /// Gets all teams available. + /// </summary> + /// <returns>Returns all teams available.</returns> + public PhotonTeam[] GetAvailableTeams() + { + if (teamsList != null) + { + return teamsList.ToArray(); + } + return null; + } + + /// <summary> + /// Gets all players joined to a team using a team code. + /// </summary> + /// <param name="code">The code of the team.</param> + /// <param name="members">The array of players to be filled.</param> + /// <returns>If successful or not.</returns> + public bool TryGetTeamMembers(byte code, out Player[] members) + { + members = null; + HashSet<Player> players; + if (this.playersPerTeam.TryGetValue(code, out players)) + { + members = new Player[players.Count]; + int i = 0; + foreach (var player in players) + { + members[i] = player; + i++; + } + return true; + } + return false; + } + + /// <summary> + /// Gets all players joined to a team using a team name. + /// </summary> + /// <param name="teamName">The name of the team.</param> + /// <param name="members">The array of players to be filled.</param> + /// <returns>If successful or not.</returns> + public bool TryGetTeamMembers(string teamName, out Player[] members) + { + members = null; + PhotonTeam team; + if (this.TryGetTeamByName(teamName, out team)) + { + return this.TryGetTeamMembers(team.Code, out members); + } + return false; + } + + /// <summary> + /// Gets all players joined to a team. + /// </summary> + /// <param name="team">The team which will be used to find players.</param> + /// <param name="members">The array of players to be filled.</param> + /// <returns>If successful or not.</returns> + public bool TryGetTeamMembers(PhotonTeam team, out Player[] members) + { + members = null; + if (team != null) + { + return this.TryGetTeamMembers(team.Code, out members); + } + return false; + } + + /// <summary> + /// Gets all team mates of a player. + /// </summary> + /// <param name="player">The player whose team mates will be searched.</param> + /// <param name="teamMates">The array of players to be filled.</param> + /// <returns>If successful or not.</returns> + public bool TryGetTeamMatesOfPlayer(Player player, out Player[] teamMates) + { + teamMates = null; + if (player == null) + { + return false; + } + PhotonTeam team = player.GetPhotonTeam(); + if (team == null) + { + return false; + } + HashSet<Player> players; + if (this.playersPerTeam.TryGetValue(team.Code, out players)) + { + if (!players.Contains(player)) + { + Debug.LogWarningFormat("Unexpected situation while getting team mates of player {0} who is joined to team {1}, updating teams for all", player, team); + // revert to 'brute force' in case of unexpected situation + this.UpdateTeams(); + } + teamMates = new Player[players.Count - 1]; + int i = 0; + foreach (var p in players) + { + if (p.Equals(player)) + { + continue; + } + teamMates[i] = p; + i++; + } + return true; + } + return false; + } + + /// <summary> + /// Gets the number of players in a team by team code. + /// </summary> + /// <param name="code">Unique code of the team</param> + /// <returns>Number of players joined to the team.</returns> + public int GetTeamMembersCount(byte code) + { + PhotonTeam team; + if (this.TryGetTeamByCode(code, out team)) + { + return this.GetTeamMembersCount(team); + } + return 0; + } + + /// <summary> + /// Gets the number of players in a team by team name. + /// </summary> + /// <param name="name">Unique name of the team</param> + /// <returns>Number of players joined to the team.</returns> + public int GetTeamMembersCount(string name) + { + PhotonTeam team; + if (this.TryGetTeamByName(name, out team)) + { + return this.GetTeamMembersCount(team); + } + return 0; + } + + /// <summary> + /// Gets the number of players in a team. + /// </summary> + /// <param name="team">The team you want to know the size of</param> + /// <returns>Number of players joined to the team.</returns> + public int GetTeamMembersCount(PhotonTeam team) + { + HashSet<Player> players; + if (team != null && this.playersPerTeam.TryGetValue(team.Code, out players) && players != null) + { + return players.Count; + } + return 0; + } + + #endregion + + #region Unused methods + + void IMatchmakingCallbacks.OnFriendListUpdate(List<FriendInfo> friendList) + { + } + + void IMatchmakingCallbacks.OnCreatedRoom() + { + } + + void IMatchmakingCallbacks.OnCreateRoomFailed(short returnCode, string message) + { + } + + void IMatchmakingCallbacks.OnJoinRoomFailed(short returnCode, string message) + { + } + + void IMatchmakingCallbacks.OnJoinRandomFailed(short returnCode, string message) + { + } + + void IInRoomCallbacks.OnRoomPropertiesUpdate(Hashtable propertiesThatChanged) + { + } + + void IInRoomCallbacks.OnMasterClientSwitched(Player newMasterClient) + { + } + + #endregion + } + + /// <summary>Extension methods for the Player class that make use of PhotonTeamsManager.</summary> + public static class PhotonTeamExtensions + { + /// <summary>Gets the team the player is currently joined to. Null if none.</summary> + /// <returns>The team the player is currently joined to. Null if none.</returns> + public static PhotonTeam GetPhotonTeam(this Player player) + { + object teamId; + PhotonTeam team; + if (player.CustomProperties.TryGetValue(PhotonTeamsManager.TeamPlayerProp, out teamId) && PhotonTeamsManager.Instance.TryGetTeamByCode((byte)teamId, out team)) + { + return team; + } + return null; + } + + /// <summary> + /// Join a team. + /// </summary> + /// <param name="player">The player who will join a team.</param> + /// <param name="team">The team to be joined.</param> + /// <returns></returns> + public static bool JoinTeam(this Player player, PhotonTeam team) + { + if (team == null) + { + Debug.LogWarning("JoinTeam failed: PhotonTeam provided is null"); + return false; + } + PhotonTeam currentTeam = player.GetPhotonTeam(); + if (currentTeam != null) + { + Debug.LogWarningFormat("JoinTeam failed: player ({0}) is already joined to a team ({1}), call SwitchTeam instead", player, team); + return false; + } + return player.SetCustomProperties(new Hashtable { { PhotonTeamsManager.TeamPlayerProp, team.Code } }); + } + + /// <summary> + /// Join a team using team code. + /// </summary> + /// <param name="player">The player who will join the team.</param> + /// <param name="teamCode">The code fo the team to be joined.</param> + /// <returns></returns> + public static bool JoinTeam(this Player player, byte teamCode) + { + PhotonTeam team; + return PhotonTeamsManager.Instance.TryGetTeamByCode(teamCode, out team) && player.JoinTeam(team); + } + + /// <summary> + /// Join a team using team name. + /// </summary> + /// <param name="player">The player who will join the team.</param> + /// <param name="teamName">The name of the team to be joined.</param> + /// <returns></returns> + public static bool JoinTeam(this Player player, string teamName) + { + PhotonTeam team; + return PhotonTeamsManager.Instance.TryGetTeamByName(teamName, out team) && player.JoinTeam(team); + } + + /// <summary>Switch that player's team to the one you assign.</summary> + /// <remarks>Internally checks if this player is in that team already or not. Only team switches are actually sent.</remarks> + /// <param name="player"></param> + /// <param name="team"></param> + public static bool SwitchTeam(this Player player, PhotonTeam team) + { + if (team == null) + { + Debug.LogWarning("SwitchTeam failed: PhotonTeam provided is null"); + return false; + } + PhotonTeam currentTeam = player.GetPhotonTeam(); + if (currentTeam == null) + { + Debug.LogWarningFormat("SwitchTeam failed: player ({0}) was not joined to any team, call JoinTeam instead", player); + return false; + } + if (currentTeam.Code == team.Code) + { + Debug.LogWarningFormat("SwitchTeam failed: player ({0}) is already joined to the same team {1}", player, team); + return false; + } + return player.SetCustomProperties(new Hashtable { { PhotonTeamsManager.TeamPlayerProp, team.Code } }, + new Hashtable { { PhotonTeamsManager.TeamPlayerProp, currentTeam.Code }}); + } + + /// <summary>Switch the player's team using a team code.</summary> + /// <remarks>Internally checks if this player is in that team already or not.</remarks> + /// <param name="player">The player that will switch teams.</param> + /// <param name="teamCode">The code of the team to switch to.</param> + /// <returns>If the team switch request is queued to be sent to the server or done in case offline or not joined to a room yet.</returns> + public static bool SwitchTeam(this Player player, byte teamCode) + { + PhotonTeam team; + return PhotonTeamsManager.Instance.TryGetTeamByCode(teamCode, out team) && player.SwitchTeam(team); + } + + /// <summary>Switch the player's team using a team name.</summary> + /// <remarks>Internally checks if this player is in that team already or not.</remarks> + /// <param name="player">The player that will switch teams.</param> + /// <param name="teamName">The name of the team to switch to.</param> + /// <returns>If the team switch request is queued to be sent to the server or done in case offline or not joined to a room yet.</returns> + public static bool SwitchTeam(this Player player, string teamName) + { + PhotonTeam team; + return PhotonTeamsManager.Instance.TryGetTeamByName(teamName, out team) && player.SwitchTeam(team); + } + + /// <summary> + /// Leave the current team if any. + /// </summary> + /// <param name="player"></param> + /// <returns>If the leaving team request is queued to be sent to the server or done in case offline or not joined to a room yet.</returns> + public static bool LeaveCurrentTeam(this Player player) + { + PhotonTeam currentTeam = player.GetPhotonTeam(); + if (currentTeam == null) + { + Debug.LogWarningFormat("LeaveCurrentTeam failed: player ({0}) was not joined to any team", player); + return false; + } + return player.SetCustomProperties(new Hashtable {{PhotonTeamsManager.TeamPlayerProp, null}}, new Hashtable {{PhotonTeamsManager.TeamPlayerProp, currentTeam.Code}}); + } + + /// <summary> + /// Try to get the team mates. + /// </summary> + /// <param name="player">The player to get the team mates of.</param> + /// <param name="teamMates">The team mates array to fill.</param> + /// <returns>If successful or not.</returns> + public static bool TryGetTeamMates(this Player player, out Player[] teamMates) + { + return PhotonTeamsManager.Instance.TryGetTeamMatesOfPlayer(player, out teamMates); + } + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PhotonTeamsManager.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PhotonTeamsManager.cs.meta new file mode 100644 index 0000000..640e2d9 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PhotonTeamsManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8701526de72d8774fa165e66daf050ed +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PlayerNumbering.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PlayerNumbering.cs new file mode 100644 index 0000000..d51eccd --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PlayerNumbering.cs @@ -0,0 +1,267 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="PlayerNumbering.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// Assign numbers to Players in a room. Uses Room custom Properties +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using System.Collections.Generic; +using System.Linq; + +using UnityEngine; + +using Photon.Pun; +using Photon.Realtime; +using Hashtable = ExitGames.Client.Photon.Hashtable; + +namespace Photon.Pun.UtilityScripts +{ + /// <summary> + /// Implements consistent numbering in a room/game with help of room properties. Access them by Player.GetPlayerNumber() extension. + /// </summary> + /// <remarks> + /// indexing ranges from 0 to the maximum number of Players. + /// indexing remains for the player while in room. + /// If a Player is numbered 2 and player numbered 1 leaves, numbered 1 become vacant and will assigned to the future player joining (the first available vacant number is assigned when joining) + /// </remarks> + public class PlayerNumbering : MonoBehaviourPunCallbacks + { + //TODO: Add a "numbers available" bool, to allow easy access to this?! + + #region Public Properties + + /// <summary> + /// The instance. EntryPoint to query about Room Indexing. + /// </summary> + public static PlayerNumbering instance; + + public static Player[] SortedPlayers; + + /// <summary> + /// OnPlayerNumberingChanged delegate. Use + /// </summary> + public delegate void PlayerNumberingChanged(); + /// <summary> + /// Called everytime the room Indexing was updated. Use this for discrete updates. Always better than brute force calls every frame. + /// </summary> + public static event PlayerNumberingChanged OnPlayerNumberingChanged; + + + /// <summary>Defines the room custom property name to use for room player indexing tracking.</summary> + public const string RoomPlayerIndexedProp = "pNr"; + + /// <summary> + /// dont destroy on load flag for this Component's GameObject to survive Level Loading. + /// </summary> + public bool dontDestroyOnLoad = false; + + + #endregion + + + #region MonoBehaviours methods + + public void Awake() + { + + if (instance != null && instance != this && instance.gameObject != null) + { + GameObject.DestroyImmediate(instance.gameObject); + } + + instance = this; + if (dontDestroyOnLoad) + { + DontDestroyOnLoad(this.gameObject); + } + + this.RefreshData(); + } + + #endregion + + + #region PunBehavior Overrides + + public override void OnJoinedRoom() + { + this.RefreshData(); + } + + public override void OnLeftRoom() + { + PhotonNetwork.LocalPlayer.CustomProperties.Remove(PlayerNumbering.RoomPlayerIndexedProp); + } + + public override void OnPlayerEnteredRoom(Player newPlayer) + { + this.RefreshData(); + } + + public override void OnPlayerLeftRoom(Player otherPlayer) + { + this.RefreshData(); + } + + public override void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps) + { + if (changedProps != null && changedProps.ContainsKey(PlayerNumbering.RoomPlayerIndexedProp)) + { + this.RefreshData(); + } + } + + #endregion + + + // each player can select it's own playernumber in a room, if all "older" players already selected theirs + + + /// <summary> + /// Internal call Refresh the cached data and call the OnPlayerNumberingChanged delegate. + /// </summary> + public void RefreshData() + { + if (PhotonNetwork.CurrentRoom == null) + { + return; + } + + if (PhotonNetwork.LocalPlayer.GetPlayerNumber() >= 0) + { + SortedPlayers = PhotonNetwork.CurrentRoom.Players.Values.OrderBy((p) => p.GetPlayerNumber()).ToArray(); + if (OnPlayerNumberingChanged != null) + { + OnPlayerNumberingChanged(); + } + return; + } + + + HashSet<int> usedInts = new HashSet<int>(); + Player[] sorted = PhotonNetwork.PlayerList.OrderBy((p) => p.ActorNumber).ToArray(); + + string allPlayers = "all players: "; + foreach (Player player in sorted) + { + allPlayers += player.ActorNumber + "=pNr:"+player.GetPlayerNumber()+", "; + + int number = player.GetPlayerNumber(); + + // if it's this user, select a number and break + // else: + // check if that user has a number + // if not, break! + // else remember used numbers + + if (player.IsLocal) + { + Debug.Log ("PhotonNetwork.CurrentRoom.PlayerCount = " + PhotonNetwork.CurrentRoom.PlayerCount); + + // select a number + for (int i = 0; i < PhotonNetwork.CurrentRoom.PlayerCount; i++) + { + if (!usedInts.Contains(i)) + { + player.SetPlayerNumber(i); + break; + } + } + // then break + break; + } + else + { + if (number < 0) + { + break; + } + else + { + usedInts.Add(number); + } + } + } + + //Debug.Log(allPlayers); + //Debug.Log(PhotonNetwork.LocalPlayer.ToStringFull() + " has PhotonNetwork.player.GetPlayerNumber(): " + PhotonNetwork.LocalPlayer.GetPlayerNumber()); + + SortedPlayers = PhotonNetwork.CurrentRoom.Players.Values.OrderBy((p) => p.GetPlayerNumber()).ToArray(); + if (OnPlayerNumberingChanged != null) + { + OnPlayerNumberingChanged(); + } + } + } + + + + /// <summary>Extension used for PlayerRoomIndexing and Player class.</summary> + public static class PlayerNumberingExtensions + { + /// <summary>Extension for Player class to wrap up access to the player's custom property. + /// Make sure you use the delegate 'OnPlayerNumberingChanged' to knoiw when you can query the PlayerNumber. Numbering can changes over time or not be yet assigned during the initial phase ( when player creates a room for example) + /// </summary> + /// <returns>persistent index in room. -1 for no indexing</returns> + public static int GetPlayerNumber(this Player player) + { + if (player == null) { + return -1; + } + + if (PhotonNetwork.OfflineMode) + { + return 0; + } + if (!PhotonNetwork.IsConnectedAndReady) + { + return -1; + } + + object value; + if (player.CustomProperties.TryGetValue (PlayerNumbering.RoomPlayerIndexedProp, out value)) { + return (byte)value; + } + return -1; + } + + /// <summary> + /// Sets the player number. + /// It's not recommanded to manually interfere with the playerNumbering, but possible. + /// </summary> + /// <param name="player">Player.</param> + /// <param name="playerNumber">Player number.</param> + public static void SetPlayerNumber(this Player player, int playerNumber) + { + if (player == null) { + return; + } + + if (PhotonNetwork.OfflineMode) + { + return; + } + + if (playerNumber < 0) + { + Debug.LogWarning("Setting invalid playerNumber: " + playerNumber + " for: " + player.ToStringFull()); + } + + if (!PhotonNetwork.IsConnectedAndReady) + { + Debug.LogWarning("SetPlayerNumber was called in state: " + PhotonNetwork.NetworkClientState + ". Not IsConnectedAndReady."); + return; + } + + int current = player.GetPlayerNumber(); + if (current != playerNumber) + { + Debug.Log("PlayerNumbering: Set number "+playerNumber); + player.SetCustomProperties(new Hashtable() { { PlayerNumbering.RoomPlayerIndexedProp, (byte)playerNumber } }); + } + } + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PlayerNumbering.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PlayerNumbering.cs.meta new file mode 100644 index 0000000..39220f0 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PlayerNumbering.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b28dd60f6abf16d4094cf0f642a043e2 +timeCreated: 1512563044 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PunPlayerScores.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PunPlayerScores.cs new file mode 100644 index 0000000..8054edd --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PunPlayerScores.cs @@ -0,0 +1,62 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="PunPlayerScores.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// Scoring system for PhotonPlayer +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using System.Collections; +using System.Collections.Generic; + +using UnityEngine; + +using Photon.Pun; +using Photon.Realtime; +using Hashtable = ExitGames.Client.Photon.Hashtable; + +namespace Photon.Pun.UtilityScripts +{ + /// <summary> + /// Scoring system for PhotonPlayer + /// </summary> + public class PunPlayerScores : MonoBehaviour + { + public const string PlayerScoreProp = "score"; + } + + public static class ScoreExtensions + { + public static void SetScore(this Player 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 Player 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 Player 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/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PunPlayerScores.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PunPlayerScores.cs.meta new file mode 100644 index 0000000..5904915 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PunPlayerScores.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 6b4df3943860f1d45bfe232053a58d80 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PunTeams.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PunTeams.cs new file mode 100644 index 0000000..bc06313 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PunTeams.cs @@ -0,0 +1,156 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="PunTeams.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// Implements teams in a room/game with help of player properties. Access them by Player.GetTeam extension. +// </summary> +// <remarks> +// 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. +// </remarks> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; + +using UnityEngine; + +using Photon.Pun; +using Photon.Realtime; +using ExitGames.Client.Photon; +using Hashtable = ExitGames.Client.Photon.Hashtable; + +namespace Photon.Pun.UtilityScripts +{ + /// <summary> + /// Implements teams in a room/game with help of player properties. Access them by Player.GetTeam extension. + /// </summary> + /// <remarks> + /// 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. + /// </remarks> + [Obsolete("do not use this or add it to the scene. use PhotonTeamsManager instead")] + public class PunTeams : MonoBehaviourPunCallbacks + { + /// <summary>Enum defining the teams available. First team should be neutral (it's the default value any field of this enum gets).</summary> + [Obsolete("use custom PhotonTeam instead")] + public enum Team : byte { none, red, blue }; + + /// <summary>The main list of teams with their player-lists. Automatically kept up to date.</summary> + /// <remarks>Note that this is static. Can be accessed by PunTeam.PlayersPerTeam. You should not modify this.</remarks> + [Obsolete("use PhotonTeamsManager.Instance.TryGetTeamMembers instead")] + public static Dictionary<Team, List<Player>> PlayersPerTeam; + + /// <summary>Defines the player custom property name to use for team affinity of "this" player.</summary> + [Obsolete("do not use this. PhotonTeamsManager.TeamPlayerProp is used internally instead.")] + public const string TeamPlayerProp = "team"; + + + #region Events by Unity and Photon + + public void Start() + { + PlayersPerTeam = new Dictionary<Team, List<Player>>(); + Array enumVals = Enum.GetValues(typeof(Team)); + foreach (var enumVal in enumVals) + { + PlayersPerTeam[(Team)enumVal] = new List<Player>(); + } + } + + public override void OnDisable() + { + base.OnDisable(); + this.Start(); + } + + /// <summary>Needed to update the team lists when joining a room.</summary> + /// <remarks>Called by PUN. See enum MonoBehaviourPunCallbacks for an explanation.</remarks> + public override void OnJoinedRoom() + { + + this.UpdateTeams(); + } + + public override void OnLeftRoom() + { + Start(); + } + + /// <summary>Refreshes the team lists. It could be a non-team related property change, too.</summary> + /// <remarks>Called by PUN. See enum MonoBehaviourPunCallbacks for an explanation.</remarks> + public override void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps) + { + this.UpdateTeams(); + } + + public override void OnPlayerLeftRoom(Player otherPlayer) + { + this.UpdateTeams(); + } + + public override void OnPlayerEnteredRoom(Player newPlayer) + { + this.UpdateTeams(); + } + + #endregion + + [Obsolete("do not call this.")] + 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++) + { + Player player = PhotonNetwork.PlayerList[i]; + Team playerTeam = player.GetTeam(); + PlayersPerTeam[playerTeam].Add(player); + } + } + } + + /// <summary>Extension used for PunTeams and Player class. Wraps access to the player's custom property.</summary> + public static class TeamExtensions + { + /// <summary>Extension for Player class to wrap up access to the player's custom property.</summary> + /// <returns>PunTeam.Team.none if no team was found (yet).</returns> + [Obsolete("Use player.GetPhotonTeam")] + public static PunTeams.Team GetTeam(this Player player) + { + object teamId; + if (player.CustomProperties.TryGetValue(PunTeams.TeamPlayerProp, out teamId)) + { + return (PunTeams.Team)teamId; + } + + return PunTeams.Team.none; + } + + /// <summary>Switch that player's team to the one you assign.</summary> + /// <remarks>Internally checks if this player is in that team already or not. Only team switches are actually sent.</remarks> + /// <param name="player"></param> + /// <param name="team"></param> + [Obsolete("Use player.JoinTeam")] + public static void SetTeam(this Player player, PunTeams.Team team) + { + if (!PhotonNetwork.IsConnectedAndReady) + { + Debug.LogWarning("JoinTeam was called in state: " + PhotonNetwork.NetworkClientState + ". Not IsConnectedAndReady."); + 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/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PunTeams.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PunTeams.cs.meta new file mode 100644 index 0000000..9dffb8a --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonPlayer/PunTeams.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 6587c8104d7524f4280d0a68dd779f27 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonUnityNetworking.Utilities.asmdef b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonUnityNetworking.Utilities.asmdef new file mode 100644 index 0000000..5812232 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonUnityNetworking.Utilities.asmdef @@ -0,0 +1,11 @@ +{ + "name": "PhotonUnityNetworking.Utilities", + "references": [ + "PhotonRealtime", + "PhotonUnityNetworking" + ], + "optionalUnityReferences": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonUnityNetworking.Utilities.asmdef.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonUnityNetworking.Utilities.asmdef.meta new file mode 100644 index 0000000..7e3157c --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonUnityNetworking.Utilities.asmdef.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a738238285a7a8246af046cbf977522f +timeCreated: 1537459565 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonView.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonView.meta new file mode 100644 index 0000000..07d3ae1 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonView.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 199121930ec5d4aa9bb53d836180b74f +folderAsset: yes +timeCreated: 1529327582 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonView/SmoothSyncMovement.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonView/SmoothSyncMovement.cs new file mode 100644 index 0000000..2f3a75b --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonView/SmoothSyncMovement.cs @@ -0,0 +1,72 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="SmoothSyncMovement.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// Smoothed out movement for network gameobjects +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using UnityEngine; + +using Photon.Pun; +using Photon.Realtime; + +namespace Photon.Pun.UtilityScripts +{ + /// <summary> + /// Smoothed out movement for network gameobjects + /// </summary> + [RequireComponent(typeof(PhotonView))] + public class SmoothSyncMovement : Photon.Pun.MonoBehaviourPun, 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/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonView/SmoothSyncMovement.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonView/SmoothSyncMovement.cs.meta new file mode 100644 index 0000000..ed3764a --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/PhotonView/SmoothSyncMovement.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 35144820bcc25444bb8f0fd767d9423e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping.meta new file mode 100644 index 0000000..99561c8 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: e10fe700b1a744ec78575843923fe6d7 +folderAsset: yes +timeCreated: 1529327245 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/ConnectAndJoinRandom.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/ConnectAndJoinRandom.cs new file mode 100644 index 0000000..8cfddfe --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/ConnectAndJoinRandom.cs @@ -0,0 +1,136 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="ConnectAndJoinRandom.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// Simple component to call ConnectUsingSettings and to get into a PUN room easily. +// </summary> +// <remarks> +// A custom inspector provides a button to connect in PlayMode, should AutoConnect be false. +// </remarks> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +//#if UNITY_EDITOR +//using UnityEditor; +//#endif + +using UnityEngine; + +//using Photon.Pun; +using Photon.Realtime; + +namespace Photon.Pun.UtilityScripts +{ + /// <summary>Simple component to call ConnectUsingSettings and to get into a PUN room easily.</summary> + /// <remarks>A custom inspector provides a button to connect in PlayMode, should AutoConnect be false.</remarks> + public class ConnectAndJoinRandom : MonoBehaviourPunCallbacks + { + /// <summary>Connect automatically? If false you can set this to true later on or call ConnectUsingSettings in your own scripts.</summary> + public bool AutoConnect = true; + + /// <summary>Used as PhotonNetwork.GameVersion.</summary> + public byte Version = 1; + + /// <summary>Max number of players allowed in room. Once full, a new room will be created by the next connection attemping to join.</summary> + [Tooltip("The max number of players allowed in room. Once full, a new room will be created by the next connection attemping to join.")] + public byte MaxPlayers = 4; + + public int playerTTL = -1; + + public void Start() + { + if (this.AutoConnect) + { + this.ConnectNow(); + } + } + + public void ConnectNow() + { + Debug.Log("ConnectAndJoinRandom.ConnectNow() will now call: PhotonNetwork.ConnectUsingSettings()."); + + + PhotonNetwork.ConnectUsingSettings(); + PhotonNetwork.GameVersion = this.Version + "." + SceneManagerHelper.ActiveSceneBuildIndex; + + } + + + // below, we implement some callbacks of the Photon Realtime API. + // Being a MonoBehaviourPunCallbacks means, we can override the few methods which are needed here. + + + public override void OnConnectedToMaster() + { + Debug.Log("OnConnectedToMaster() was called by PUN. This client is now connected to Master Server in region [" + PhotonNetwork.CloudRegion + + "] and can join a room. Calling: PhotonNetwork.JoinRandomRoom();"); + PhotonNetwork.JoinRandomRoom(); + } + + public override void OnJoinedLobby() + { + Debug.Log("OnJoinedLobby(). This client is now connected to Relay in region [" + PhotonNetwork.CloudRegion + "]. This script now calls: PhotonNetwork.JoinRandomRoom();"); + PhotonNetwork.JoinRandomRoom(); + } + + public override void OnJoinRandomFailed(short returnCode, string message) + { + Debug.Log("OnJoinRandomFailed() was called by PUN. No random room available in region [" + PhotonNetwork.CloudRegion + "], so we create one. Calling: PhotonNetwork.CreateRoom(null, new RoomOptions() {maxPlayers = 4}, null);"); + + RoomOptions roomOptions = new RoomOptions() { MaxPlayers = this.MaxPlayers }; + if (playerTTL >= 0) + roomOptions.PlayerTtl = playerTTL; + + PhotonNetwork.CreateRoom(null, roomOptions, null); + } + + // the following methods are implemented to give you some context. re-implement them as needed. + public override void OnDisconnected(DisconnectCause cause) + { + Debug.Log("OnDisconnected(" + cause + ")"); + } + + public override void OnJoinedRoom() + { + Debug.Log("OnJoinedRoom() called by PUN. Now this client is in a room in region [" + PhotonNetwork.CloudRegion + "]. Game is now running."); + } + } + + + //#if UNITY_EDITOR + //[CanEditMultipleObjects] + //[CustomEditor(typeof(ConnectAndJoinRandom), true)] + //public class ConnectAndJoinRandomInspector : Editor + //{ + // void OnEnable() { EditorApplication.update += Update; } + // void OnDisable() { EditorApplication.update -= Update; } + + // bool isConnectedCache = false; + + // void Update() + // { + // if (this.isConnectedCache != PhotonNetwork.IsConnected) + // { + // this.Repaint(); + // } + // } + + // public override void OnInspectorGUI() + // { + // this.isConnectedCache = !PhotonNetwork.IsConnected; + + + // this.DrawDefaultInspector(); // Draw the normal inspector + + // if (Application.isPlaying && !PhotonNetwork.IsConnected) + // { + // if (GUILayout.Button("Connect")) + // { + // ((ConnectAndJoinRandom)this.target).ConnectNow(); + // } + // } + // } + //} + //#endif +} diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/ConnectAndJoinRandom.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/ConnectAndJoinRandom.cs.meta new file mode 100644 index 0000000..13f1494 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/ConnectAndJoinRandom.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5c1b84a427010e0469ce0df07ab64dbc +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/MoveByKeys.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/MoveByKeys.cs new file mode 100644 index 0000000..344cbe8 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/MoveByKeys.cs @@ -0,0 +1,111 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="OnJoinedInstantiate.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// Very basic component to move a GameObject by WASD and Space. +// </summary> +// <remarks> +// 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. +// </remarks> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + + +using UnityEngine; + +using Photon.Pun; +using Photon.Realtime; + +namespace Photon.Pun.UtilityScripts +{ + + /// <summary> + /// Very basic component to move a GameObject by WASD and Space. + /// </summary> + /// <remarks> + /// 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. + /// </remarks> + [RequireComponent(typeof(PhotonView))] + public class MoveByKeys : Photon.Pun.MonoBehaviourPun + { + 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<SpriteRenderer>() != null); + + this.body2d = GetComponent<Rigidbody2D>(); + this.body = GetComponent<Rigidbody>(); + } + + + // 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"); + } + } + } + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/MoveByKeys.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/MoveByKeys.cs.meta new file mode 100644 index 0000000..63447da --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/MoveByKeys.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 99b4daedc5e674a429acdf1e77da6a55 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnClickDestroy.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnClickDestroy.cs new file mode 100644 index 0000000..fcd507a --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnClickDestroy.cs @@ -0,0 +1,72 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="OnClickDestroy.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities +// </copyright> +// <summary>A compact script for prototyping.</summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + + +namespace Photon.Pun.UtilityScripts +{ + using System.Collections; + using UnityEngine; + using UnityEngine.EventSystems; + + /// <summary> + /// Destroys the networked GameObject either by PhotonNetwork.Destroy or by sending an RPC which calls Object.Destroy(). + /// </summary> + /// <remarks> + /// Using an RPC to Destroy a GameObject is typically a bad idea. + /// It allows any player to Destroy a GameObject and may cause errors. + /// + /// A client has to clean up the server's event-cache, which contains events for Instantiate and + /// buffered RPCs related to the GO. + /// + /// A buffered RPC gets cleaned up when the sending player leaves the room, so players joining later + /// won't get those buffered RPCs. This in turn, may mean they don't destroy the GO due to coming later. + /// + /// Vice versa, 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 Unity's IPointerClickHandler. Needs a PhysicsRaycaster on the camera. + /// See: https://docs.unity3d.com/ScriptReference/EventSystems.IPointerClickHandler.html + /// </remarks> + public class OnClickDestroy : MonoBehaviourPun, IPointerClickHandler + { + public PointerEventData.InputButton Button; + public KeyCode ModifierKey; + + public bool DestroyByRpc; + + + void IPointerClickHandler.OnPointerClick(PointerEventData eventData) + { + if (!PhotonNetwork.InRoom || (this.ModifierKey != KeyCode.None && !Input.GetKey(this.ModifierKey)) || eventData.button != this.Button ) + { + return; + } + + + if (this.DestroyByRpc) + { + this.photonView.RPC("DestroyRpc", RpcTarget.AllBuffered); + } + else + { + PhotonNetwork.Destroy(this.gameObject); + } + } + + + [PunRPC] + public IEnumerator DestroyRpc() + { + Destroy(this.gameObject); + yield return 0; // if you allow 1 frame to pass, the object's OnDestroy() method gets called and cleans up references. + } + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnClickDestroy.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnClickDestroy.cs.meta new file mode 100644 index 0000000..f091f18 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnClickDestroy.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9dab7328ba500e944a99d62065fba6c0 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnClickInstantiate.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnClickInstantiate.cs new file mode 100644 index 0000000..4c8f865 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnClickInstantiate.cs @@ -0,0 +1,56 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="OnClickInstantiate.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities +// </copyright> +// <summary>A compact script for prototyping.</summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + + +namespace Photon.Pun.UtilityScripts +{ + using UnityEngine; + using UnityEngine.EventSystems; + + + /// <summary> + /// Instantiates a networked GameObject on click. + /// </summary> + /// <remarks> + /// Gets OnClick() calls by Unity's IPointerClickHandler. Needs a PhysicsRaycaster on the camera. + /// See: https://docs.unity3d.com/ScriptReference/EventSystems.IPointerClickHandler.html + /// </remarks> + public class OnClickInstantiate : MonoBehaviour, IPointerClickHandler + { + public enum InstantiateOption { Mine, Scene } + + + public PointerEventData.InputButton Button; + public KeyCode ModifierKey; + + public GameObject Prefab; + + [SerializeField] + private InstantiateOption InstantiateType = InstantiateOption.Mine; + + + void IPointerClickHandler.OnPointerClick(PointerEventData eventData) + { + if (!PhotonNetwork.InRoom || (this.ModifierKey != KeyCode.None && !Input.GetKey(this.ModifierKey)) || eventData.button != this.Button) + { + return; + } + + + switch (this.InstantiateType) + { + case InstantiateOption.Mine: + PhotonNetwork.Instantiate(this.Prefab.name, eventData.pointerCurrentRaycast.worldPosition + new Vector3(0, 0.5f, 0), Quaternion.identity, 0); + break; + case InstantiateOption.Scene: + PhotonNetwork.InstantiateRoomObject(this.Prefab.name, eventData.pointerCurrentRaycast.worldPosition + new Vector3(0, 0.5f, 0), Quaternion.identity, 0, null); + break; + } + } + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnClickInstantiate.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnClickInstantiate.cs.meta new file mode 100644 index 0000000..1150759 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnClickInstantiate.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9b79a9b62449de940a073364858c3f9b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnClickRpc.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnClickRpc.cs new file mode 100644 index 0000000..c36c59c --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnClickRpc.cs @@ -0,0 +1,89 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="OnClickInstantiate.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities +// </copyright> +// <summary>A compact script for prototyping.</summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + + +using System.Collections; + + +namespace Photon.Pun.UtilityScripts +{ + using UnityEngine; + using UnityEngine.EventSystems; + + + /// <summary> + /// This component will instantiate a network GameObject when in a room and the user click on that component's GameObject. + /// Uses PhysicsRaycaster for positioning. + /// </summary> + public class OnClickRpc : MonoBehaviourPun, IPointerClickHandler + { + public PointerEventData.InputButton Button; + public KeyCode ModifierKey; + + public RpcTarget Target; + + void IPointerClickHandler.OnPointerClick(PointerEventData eventData) + { + if (!PhotonNetwork.InRoom || (this.ModifierKey != KeyCode.None && !Input.GetKey(this.ModifierKey)) || eventData.button != this.Button) + { + return; + } + + this.photonView.RPC("ClickRpc", this.Target); + } + + + #region RPC Implementation + + private Material originalMaterial; + private Color originalColor; + private bool isFlashing; + + [PunRPC] + public void ClickRpc() + { + //Debug.Log("ClickRpc Called"); + this.StartCoroutine(this.ClickFlash()); + } + + public IEnumerator ClickFlash() + { + if (isFlashing) + { + yield break; + } + isFlashing = true; + + this.originalMaterial = GetComponent<Renderer>().material; + if (!this.originalMaterial.HasProperty("_EmissionColor")) + { + Debug.LogWarning("Doesn't have emission, can't flash " + gameObject); + yield break; + } + + bool wasEmissive = this.originalMaterial.IsKeywordEnabled("_EMISSION"); + this.originalMaterial.EnableKeyword("_EMISSION"); + + this.originalColor = this.originalMaterial.GetColor("_EmissionColor"); + this.originalMaterial.SetColor("_EmissionColor", Color.white); + + for (float f = 0.0f; f <= 1.0f; f += 0.08f) + { + Color lerped = Color.Lerp(Color.white, this.originalColor, f); + this.originalMaterial.SetColor("_EmissionColor", lerped); + yield return null; + } + + this.originalMaterial.SetColor("_EmissionColor", this.originalColor); + if (!wasEmissive) this.originalMaterial.DisableKeyword("_EMISSION"); + isFlashing = false; + } + + #endregion + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnClickRpc.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnClickRpc.cs.meta new file mode 100644 index 0000000..8a7d1de --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnClickRpc.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2cd0ed7420882554fa146aab6aeb2e80 +timeCreated: 1536748184 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnEscapeQuit.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnEscapeQuit.cs new file mode 100644 index 0000000..599aec0 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnEscapeQuit.cs @@ -0,0 +1,32 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="OnJoinedInstantiate.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// This component will quit the application when escape key is pressed +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using UnityEngine; +using System.Collections; +using System.Diagnostics; + +namespace Photon.Pun.UtilityScripts +{ + /// <summary> + /// This component will quit the application when escape key is pressed + /// </summary> + public class OnEscapeQuit : MonoBehaviour + { + [Conditional("UNITY_ANDROID"), Conditional("UNITY_IOS")] + public void Update() + { + // "back" button of phone equals "Escape". quit app if that's pressed + if (Input.GetKeyDown(KeyCode.Escape)) + { + Application.Quit(); + } + } + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnEscapeQuit.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnEscapeQuit.cs.meta new file mode 100644 index 0000000..6133070 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnEscapeQuit.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1fbabafd914a48f4eb6108d8d8f43d29 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnJoinedInstantiate.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnJoinedInstantiate.cs new file mode 100644 index 0000000..14c6843 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnJoinedInstantiate.cs @@ -0,0 +1,450 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="OnJoinedInstantiate.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// This component will instantiate a network GameObject when a room is joined +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Serialization; + +using Photon.Realtime; + +#if UNITY_EDITOR +using UnityEditor; +#endif + +namespace Photon.Pun.UtilityScripts +{ + + /// <summary> + /// This component will instantiate a network GameObject when a room is joined + /// </summary> + public class OnJoinedInstantiate : MonoBehaviour + , IMatchmakingCallbacks + { + public enum SpawnSequence { Connection, Random, RoundRobin } + + #region Inspector Items + + // Old field, only here for backwards compat. Value copies over to SpawnPoints in OnValidate + [HideInInspector] private Transform SpawnPosition; + + [HideInInspector] public SpawnSequence Sequence = SpawnSequence.Connection; + + [HideInInspector] public List<Transform> SpawnPoints = new List<Transform>(1) { null }; + + [Tooltip("Add a random variance to a spawn point position. GetRandomOffset() can be overridden with your own method for producing offsets.")] + [HideInInspector] public bool UseRandomOffset = true; + + [Tooltip("Radius of the RandomOffset.")] + [FormerlySerializedAs("PositionOffset")] + [HideInInspector] public float RandomOffset = 2.0f; + + [Tooltip("Disables the Y axis of RandomOffset. The Y value of the spawn point will be used.")] + [HideInInspector] public bool ClampY = true; + + [HideInInspector] public List<GameObject> PrefabsToInstantiate = new List<GameObject>(1) { null }; // set in inspector + + [FormerlySerializedAs("autoSpawnObjects")] + [HideInInspector] public bool AutoSpawnObjects = true; + + #endregion + + // Record of spawned objects, used for Despawn All + public Stack<GameObject> SpawnedObjects = new Stack<GameObject>(); + protected int spawnedAsActorId; + + + +#if UNITY_EDITOR + + protected void OnValidate() + { + /// Check the prefab to make sure it is the actual resource, and not a scene object or other instance. + if (PrefabsToInstantiate != null) + for (int i = 0; i < PrefabsToInstantiate.Count; ++i) + { + var prefab = PrefabsToInstantiate[i]; + if (prefab) + PrefabsToInstantiate[i] = ValidatePrefab(prefab); + } + + /// Move any values from old SpawnPosition field to new SpawnPoints + if (SpawnPosition) + { + if (SpawnPoints == null) + SpawnPoints = new List<Transform>(); + + SpawnPoints.Add(SpawnPosition); + SpawnPosition = null; + } + } + + /// <summary> + /// Validate, and if valid add this prefab to the first null element of the list, or create a new element. Returns true if the object was added. + /// </summary> + /// <param name="prefab"></param> + public bool AddPrefabToList(GameObject prefab) + { + var validated = ValidatePrefab(prefab); + if (validated) + { + // Don't add to list if this prefab already is on the list + if (PrefabsToInstantiate.Contains(validated)) + return false; + + // First try to use any null array slots to keep things tidy + if (PrefabsToInstantiate.Contains(null)) + PrefabsToInstantiate[PrefabsToInstantiate.IndexOf(null)] = validated; + // Otherwise, just add this prefab. + else + PrefabsToInstantiate.Add(validated); + return true; + } + + return false; + + } + + /// <summary> + /// Determines if the supplied GameObject is an instance of a prefab, or the actual source Asset, + /// and returns a best guess at the actual resource the dev intended to use. + /// </summary> + /// <returns></returns> + protected static GameObject ValidatePrefab(GameObject unvalidated) + { + if (unvalidated == null) + return null; + + if (!unvalidated.GetComponent<PhotonView>()) + return null; + +#if UNITY_2018_3_OR_NEWER + + GameObject validated = null; + + if (unvalidated != null) + { + + if (PrefabUtility.IsPartOfPrefabAsset(unvalidated)) + return unvalidated; + + var prefabStatus = PrefabUtility.GetPrefabInstanceStatus(unvalidated); + var isValidPrefab = prefabStatus == PrefabInstanceStatus.Connected || prefabStatus == PrefabInstanceStatus.Disconnected; + + if (isValidPrefab) + validated = PrefabUtility.GetCorrespondingObjectFromSource(unvalidated) as GameObject; + else + return null; + + if (!PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(validated).Contains("/Resources")) + Debug.LogWarning("Player Prefab needs to be a Prefab in a Resource folder."); + } +#else + GameObject validated = unvalidated; + + if (unvalidated != null && PrefabUtility.GetPrefabType(unvalidated) != PrefabType.Prefab) + validated = PrefabUtility.GetPrefabParent(unvalidated) as GameObject; +#endif + return validated; + } + +#endif + + + public virtual void OnEnable() + { + PhotonNetwork.AddCallbackTarget(this); + } + + public virtual void OnDisable() + { + PhotonNetwork.RemoveCallbackTarget(this); + } + + + public virtual void OnJoinedRoom() + { + // Only AutoSpawn if we are a new ActorId. Rejoining should reproduce the objects by server instantiation. + if (AutoSpawnObjects && !PhotonNetwork.LocalPlayer.HasRejoined) + { + SpawnObjects(); + } + } + + public virtual void SpawnObjects() + { + if (this.PrefabsToInstantiate != null) + { + foreach (GameObject o in this.PrefabsToInstantiate) + { + if (o == null) + continue; +#if UNITY_EDITOR + Debug.Log("Auto-Instantiating: " + o.name); +#endif + Vector3 spawnPos; Quaternion spawnRot; + GetSpawnPoint(out spawnPos, out spawnRot); + + + var newobj = PhotonNetwork.Instantiate(o.name, spawnPos, spawnRot, 0); + SpawnedObjects.Push(newobj); + } + } + } + + /// <summary> + /// Destroy all objects that have been spawned by this component for this client. + /// </summary> + /// <param name="localOnly">Use Object.Destroy rather than PhotonNetwork.Destroy.</param> + public virtual void DespawnObjects(bool localOnly) + { + + while (SpawnedObjects.Count > 0) + { + var go = SpawnedObjects.Pop(); + if (go) + { + if (localOnly) + Object.Destroy(go); + else + PhotonNetwork.Destroy(go); + + } + } + } + + public virtual void OnFriendListUpdate(List<FriendInfo> friendList) { } + public virtual void OnCreatedRoom() { } + public virtual void OnCreateRoomFailed(short returnCode, string message) { } + public virtual void OnJoinRoomFailed(short returnCode, string message) { } + public virtual void OnJoinRandomFailed(short returnCode, string message) { } + public virtual void OnLeftRoom() { } + + protected int lastUsedSpawnPointIndex = -1; + + /// <summary> + /// Gets the next SpawnPoint from the list using the SpawnSequence, and applies RandomOffset (if used) to the transform matrix. + /// Override this method with any custom code for coming up with a spawn location. This method is used by AutoSpawn. + /// </summary> + public virtual void GetSpawnPoint(out Vector3 spawnPos, out Quaternion spawnRot) + { + + // Fetch a point using the Sequence method indicated + Transform point = GetSpawnPoint(); + + if (point != null) + { + spawnPos = point.position; + spawnRot = point.rotation; + } + else + { + spawnPos = new Vector3(0, 0, 0); + spawnRot = new Quaternion(0, 0, 0, 1); + } + + if (UseRandomOffset) + { + Random.InitState((int)(Time.time * 10000)); + spawnPos += GetRandomOffset(); + } + } + + + /// <summary> + /// Get the transform of the next SpawnPoint from the list, selected using the SpawnSequence setting. + /// RandomOffset is not applied, only the transform of the SpawnPoint is returned. + /// Override this method to change how Spawn Point transform is selected. Return the transform you want to use as a spawn point. + /// </summary> + /// <returns></returns> + protected virtual Transform GetSpawnPoint() + { + // Fetch a point using the Sequence method indicated + if (SpawnPoints == null || SpawnPoints.Count == 0) + { + return null; + } + else + { + switch (Sequence) + { + case SpawnSequence.Connection: + { + int id = PhotonNetwork.LocalPlayer.ActorNumber; + return SpawnPoints[(id == -1) ? 0 : id % SpawnPoints.Count]; + } + + case SpawnSequence.RoundRobin: + { + lastUsedSpawnPointIndex++; + if (lastUsedSpawnPointIndex >= SpawnPoints.Count) + lastUsedSpawnPointIndex = 0; + + /// Use Vector.Zero and Quaternion.Identity if we are dealing with no or a null spawnpoint. + return SpawnPoints == null || SpawnPoints.Count == 0 ? null : SpawnPoints[lastUsedSpawnPointIndex]; + } + + case SpawnSequence.Random: + { + return SpawnPoints[Random.Range(0, SpawnPoints.Count)]; + } + + default: + return null; + } + } + } + + /// <summary> + /// When UseRandomeOffset is enabled, this method is called to produce a Vector3 offset. The default implementation clamps the Y value to zero. You may override this with your own implementation. + /// </summary> + protected virtual Vector3 GetRandomOffset() + { + Vector3 random = Random.insideUnitSphere; + if (ClampY) + random.y = 0; + return RandomOffset * random.normalized; + } + + } + +#if UNITY_EDITOR + + [CustomEditor(typeof(OnJoinedInstantiate), true)] + [CanEditMultipleObjects] + public class OnJoinedInstantiateEditor : Editor + { + + SerializedProperty SpawnPoints, PrefabsToInstantiate, UseRandomOffset, ClampY, RandomOffset, Sequence, autoSpawnObjects; + GUIStyle fieldBox; + + private void OnEnable() + { + SpawnPoints = serializedObject.FindProperty("SpawnPoints"); + PrefabsToInstantiate = serializedObject.FindProperty("PrefabsToInstantiate"); + UseRandomOffset = serializedObject.FindProperty("UseRandomOffset"); + ClampY = serializedObject.FindProperty("ClampY"); + RandomOffset = serializedObject.FindProperty("RandomOffset"); + Sequence = serializedObject.FindProperty("Sequence"); + + autoSpawnObjects = serializedObject.FindProperty("AutoSpawnObjects"); + } + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + const int PAD = 6; + + if (fieldBox == null) + fieldBox = new GUIStyle("HelpBox") { padding = new RectOffset(PAD, PAD, PAD, PAD) }; + + EditorGUI.BeginChangeCheck(); + + EditableReferenceList(PrefabsToInstantiate, new GUIContent(PrefabsToInstantiate.displayName, PrefabsToInstantiate.tooltip), fieldBox); + + EditableReferenceList(SpawnPoints, new GUIContent(SpawnPoints.displayName, SpawnPoints.tooltip), fieldBox); + + /// Spawn Pattern + EditorGUILayout.BeginVertical(fieldBox); + EditorGUILayout.PropertyField(Sequence); + EditorGUILayout.PropertyField(UseRandomOffset); + if (UseRandomOffset.boolValue) + { + EditorGUILayout.PropertyField(RandomOffset); + EditorGUILayout.PropertyField(ClampY); + } + EditorGUILayout.EndVertical(); + + /// Auto/Manual Spawn + EditorGUILayout.BeginVertical(fieldBox); + EditorGUILayout.PropertyField(autoSpawnObjects); + EditorGUILayout.EndVertical(); + + if (EditorGUI.EndChangeCheck()) + { + serializedObject.ApplyModifiedProperties(); + } + } + + /// <summary> + /// Create a basic rendered list of objects from a SerializedProperty list or array, with Add/Destroy buttons. + /// </summary> + /// <param name="list"></param> + /// <param name="gc"></param> + public void EditableReferenceList(SerializedProperty list, GUIContent gc, GUIStyle style = null) + { + EditorGUILayout.LabelField(gc); + + if (style == null) + style = new GUIStyle("HelpBox") { padding = new RectOffset(6, 6, 6, 6) }; + + EditorGUILayout.BeginVertical(style); + + int count = list.arraySize; + + if (count == 0) + { + if (GUI.Button(EditorGUILayout.GetControlRect(GUILayout.MaxWidth(20)), "+", (GUIStyle)"minibutton")) + { + int newindex = list.arraySize; + list.InsertArrayElementAtIndex(0); + list.GetArrayElementAtIndex(0).objectReferenceValue = null; + } + } + else + { + // List Elements and Delete buttons + for (int i = 0; i < count; ++i) + { + EditorGUILayout.BeginHorizontal(); + bool add = (GUI.Button(EditorGUILayout.GetControlRect(GUILayout.MaxWidth(20)), "+", (GUIStyle)"minibutton")); + EditorGUILayout.PropertyField(list.GetArrayElementAtIndex(i), GUIContent.none); + bool remove = (GUI.Button(EditorGUILayout.GetControlRect(GUILayout.MaxWidth(20)), "x", (GUIStyle)"minibutton")); + + EditorGUILayout.EndHorizontal(); + + if (add) + { + Add(list, i); + break; + } + + if (remove) + { + list.DeleteArrayElementAtIndex(i); + //EditorGUILayout.EndHorizontal(); + break; + } + } + + EditorGUILayout.GetControlRect(false, 4); + + if (GUI.Button(EditorGUILayout.GetControlRect(), "Add", (GUIStyle)"minibutton")) + Add(list, count); + + } + + + EditorGUILayout.EndVertical(); + } + + private void Add(SerializedProperty list, int i) + { + { + int newindex = list.arraySize; + list.InsertArrayElementAtIndex(i); + list.GetArrayElementAtIndex(i).objectReferenceValue = null; + } + } + } + + +#endif +} diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnJoinedInstantiate.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnJoinedInstantiate.cs.meta new file mode 100644 index 0000000..5b4fba0 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnJoinedInstantiate.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ed3b5dcba7bf9114cb13fc59e0a71f55 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnStartDelete.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnStartDelete.cs new file mode 100644 index 0000000..3fd3268 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnStartDelete.cs @@ -0,0 +1,24 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="OnStartDelete.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// This component will destroy the GameObject it is attached to (in Start()). +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using UnityEngine; + +namespace Photon.Pun.UtilityScripts +{ + /// <summary>This component will destroy the GameObject it is attached to (in Start()).</summary> + public class OnStartDelete : MonoBehaviour + { + // Use this for initialization + private void Start() + { + Destroy(this.gameObject); + } + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnStartDelete.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnStartDelete.cs.meta new file mode 100644 index 0000000..4f4d47a --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Prototyping/OnStartDelete.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f8d56a54ae062da4a87516fb994f4e30 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Room.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Room.meta new file mode 100644 index 0000000..667fcfb --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Room.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 7e3b3d6025e4b41fca914dca9dcc718d +folderAsset: yes +timeCreated: 1529328285 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Room/CountdownTimer.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Room/CountdownTimer.cs new file mode 100644 index 0000000..a73da86 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Room/CountdownTimer.cs @@ -0,0 +1,176 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="CountdownTimer.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// This is a basic CountdownTimer. In order to start the timer, the MasterClient can add a certain entry to the Custom Room Properties, +// which contains the property's name 'StartTime' and the actual start time describing the moment, the timer has been started. +// To have a synchronized timer, the best practice is to use PhotonNetwork.Time. +// In order to subscribe to the CountdownTimerHasExpired event you can call CountdownTimer.OnCountdownTimerHasExpired += OnCountdownTimerIsExpired; +// from Unity's OnEnable function for example. For unsubscribing simply call CountdownTimer.OnCountdownTimerHasExpired -= OnCountdownTimerIsExpired;. +// You can do this from Unity's OnDisable function for example. +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using ExitGames.Client.Photon; +using Photon.Realtime; +using UnityEngine; +using UnityEngine.UI; + +namespace Photon.Pun.UtilityScripts +{ + /// <summary>This is a basic, network-synced CountdownTimer based on properties.</summary> + /// <remarks> + /// In order to start the timer, the MasterClient can call SetStartTime() to set the timestamp for the start. + /// The property 'StartTime' then contains the server timestamp when the timer has been started. + /// + /// In order to subscribe to the CountdownTimerHasExpired event you can call CountdownTimer.OnCountdownTimerHasExpired + /// += OnCountdownTimerIsExpired; + /// from Unity's OnEnable function for example. For unsubscribing simply call CountdownTimer.OnCountdownTimerHasExpired + /// -= OnCountdownTimerIsExpired;. + /// + /// You can do this from Unity's OnEnable and OnDisable functions. + /// </remarks> + public class CountdownTimer : MonoBehaviourPunCallbacks + { + /// <summary> + /// OnCountdownTimerHasExpired delegate. + /// </summary> + public delegate void CountdownTimerHasExpired(); + + public const string CountdownStartTime = "StartTime"; + + [Header("Countdown time in seconds")] + public float Countdown = 5.0f; + + private bool isTimerRunning; + + private int startTime; + + [Header("Reference to a Text component for visualizing the countdown")] + public Text Text; + + + /// <summary> + /// Called when the timer has expired. + /// </summary> + public static event CountdownTimerHasExpired OnCountdownTimerHasExpired; + + + public void Start() + { + if (this.Text == null) Debug.LogError("Reference to 'Text' is not set. Please set a valid reference.", this); + } + + public override void OnEnable() + { + Debug.Log("OnEnable CountdownTimer"); + base.OnEnable(); + + // the starttime may already be in the props. look it up. + Initialize(); + } + + public override void OnDisable() + { + base.OnDisable(); + Debug.Log("OnDisable CountdownTimer"); + } + + + public void Update() + { + if (!this.isTimerRunning) return; + + float countdown = TimeRemaining(); + this.Text.text = string.Format("Game starts in {0} seconds", countdown.ToString("n0")); + + if (countdown > 0.0f) return; + + OnTimerEnds(); + } + + + private void OnTimerRuns() + { + this.isTimerRunning = true; + this.enabled = true; + } + + private void OnTimerEnds() + { + this.isTimerRunning = false; + this.enabled = false; + + Debug.Log("Emptying info text.", this.Text); + this.Text.text = string.Empty; + + if (OnCountdownTimerHasExpired != null) OnCountdownTimerHasExpired(); + } + + + public override void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged) + { + Debug.Log("CountdownTimer.OnRoomPropertiesUpdate " + propertiesThatChanged.ToStringFull()); + Initialize(); + } + + + private void Initialize() + { + int propStartTime; + if (TryGetStartTime(out propStartTime)) + { + this.startTime = propStartTime; + Debug.Log("Initialize sets StartTime " + this.startTime + " server time now: " + PhotonNetwork.ServerTimestamp + " remain: " + TimeRemaining()); + + + this.isTimerRunning = TimeRemaining() > 0; + + if (this.isTimerRunning) + OnTimerRuns(); + else + OnTimerEnds(); + } + } + + + private float TimeRemaining() + { + int timer = PhotonNetwork.ServerTimestamp - this.startTime; + return this.Countdown - timer / 1000f; + } + + + public static bool TryGetStartTime(out int startTimestamp) + { + startTimestamp = PhotonNetwork.ServerTimestamp; + + object startTimeFromProps; + if (PhotonNetwork.CurrentRoom.CustomProperties.TryGetValue(CountdownStartTime, out startTimeFromProps)) + { + startTimestamp = (int)startTimeFromProps; + return true; + } + + return false; + } + + + public static void SetStartTime() + { + int startTime = 0; + bool wasSet = TryGetStartTime(out startTime); + + Hashtable props = new Hashtable + { + {CountdownTimer.CountdownStartTime, (int)PhotonNetwork.ServerTimestamp} + }; + PhotonNetwork.CurrentRoom.SetCustomProperties(props); + + + Debug.Log("Set Custom Props for Time: "+ props.ToStringFull() + " wasSet: "+wasSet); + } + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Room/CountdownTimer.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Room/CountdownTimer.cs.meta new file mode 100644 index 0000000..f37edf5 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/Room/CountdownTimer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ffc398cf76e6d458caf303b5fceea504 +timeCreated: 1529327775 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/TurnBased.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/TurnBased.meta new file mode 100644 index 0000000..2e65237 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/TurnBased.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2edc8c63e86d94f6990d3f7e7e90066a +folderAsset: yes +timeCreated: 1529327659 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/TurnBased/PunTurnManager.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/TurnBased/PunTurnManager.cs new file mode 100644 index 0000000..6b23cba --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/TurnBased/PunTurnManager.cs @@ -0,0 +1,430 @@ +// ---------------------------------------------------------------------------- +// <copyright file="PunTurnManager.cs" company="Exit Games GmbH"> +// PhotonNetwork Framework for Unity - Copyright (C) 2018 Exit Games GmbH +// </copyright> +// <summary> +// Manager for Turn Based games, using PUN +// </summary> +// <author>developer@exitgames.com</author> +// ---------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; + +using UnityEngine; + +using Photon.Realtime; + +using ExitGames.Client.Photon; +using Hashtable = ExitGames.Client.Photon.Hashtable; + +namespace Photon.Pun.UtilityScripts +{ + /// <summary> + /// Pun turnBased Game manager. + /// Provides an Interface (IPunTurnManagerCallbacks) for the typical turn flow and logic, between players + /// Provides Extensions for Player, Room and RoomInfo to feature dedicated api for TurnBased Needs + /// </summary> + public class PunTurnManager : MonoBehaviourPunCallbacks, IOnEventCallback + { + + /// <summary> + /// External definition for better garbage collection management, used in ProcessEvent. + /// </summary> + Player sender; + + /// <summary> + /// Wraps accessing the "turn" custom properties of a room. + /// </summary> + /// <value>The turn index</value> + public int Turn + { + get { return PhotonNetwork.CurrentRoom.GetTurn(); } + private set + { + + _isOverCallProcessed = false; + + PhotonNetwork.CurrentRoom.SetTurn(value, true); + } + } + + + /// <summary> + /// The duration of the turn in seconds. + /// </summary> + public float TurnDuration = 20f; + + /// <summary> + /// Gets the elapsed time in the current turn in seconds + /// </summary> + /// <value>The elapsed time in the turn.</value> + public float ElapsedTimeInTurn + { + get { return ((float) (PhotonNetwork.ServerTimestamp - PhotonNetwork.CurrentRoom.GetTurnStart())) / 1000.0f; } + } + + + /// <summary> + /// Gets the remaining seconds for the current turn. Ranges from 0 to TurnDuration + /// </summary> + /// <value>The remaining seconds fo the current turn</value> + public float RemainingSecondsInTurn + { + get { return Mathf.Max(0f, this.TurnDuration - this.ElapsedTimeInTurn); } + } + + + /// <summary> + /// Gets a value indicating whether the turn is completed by all. + /// </summary> + /// <value><c>true</c> if this turn is completed by all; otherwise, <c>false</c>.</value> + public bool IsCompletedByAll + { + get { return PhotonNetwork.CurrentRoom != null && Turn > 0 && this.finishedPlayers.Count == PhotonNetwork.CurrentRoom.PlayerCount; } + } + + /// <summary> + /// Gets a value indicating whether the current turn is finished by me. + /// </summary> + /// <value><c>true</c> if the current turn is finished by me; otherwise, <c>false</c>.</value> + public bool IsFinishedByMe + { + get { return this.finishedPlayers.Contains(PhotonNetwork.LocalPlayer); } + } + + /// <summary> + /// Gets a value indicating whether the current turn is over. That is the ElapsedTimeinTurn is greater or equal to the TurnDuration + /// </summary> + /// <value><c>true</c> if the current turn is over; otherwise, <c>false</c>.</value> + public bool IsOver + { + get { return this.RemainingSecondsInTurn <= 0f; } + } + + /// <summary> + /// The turn manager listener. Set this to your own script instance to catch Callbacks + /// </summary> + public IPunTurnManagerCallbacks TurnManagerListener; + + + /// <summary> + /// The finished players. + /// </summary> + private readonly HashSet<Player> finishedPlayers = new HashSet<Player>(); + + /// <summary> + /// The turn manager event offset event message byte. Used internaly for defining data in Room Custom Properties + /// </summary> + public const byte TurnManagerEventOffset = 0; + + /// <summary> + /// The Move event message byte. Used internaly for saving data in Room Custom Properties + /// </summary> + public const byte EvMove = 1 + TurnManagerEventOffset; + + /// <summary> + /// The Final Move event message byte. Used internaly for saving data in Room Custom Properties + /// </summary> + public const byte EvFinalMove = 2 + TurnManagerEventOffset; + + // keep track of message calls + private bool _isOverCallProcessed = false; + + #region MonoBehaviour CallBack + + + void Start(){} + + void Update() + { + if (Turn > 0 && this.IsOver && !_isOverCallProcessed) + { + _isOverCallProcessed = true; + this.TurnManagerListener.OnTurnTimeEnds(this.Turn); + } + + } + + #endregion + + + /// <summary> + /// Tells the TurnManager to begins a new turn. + /// </summary> + public void BeginTurn() + { + Turn = this.Turn + 1; // note: this will set a property in the room, which is available to the other players. + } + + + /// <summary> + /// 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. + /// </summary> + /// <param name="move"></param> + /// <param name="finished"></param> + 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, new RaiseEventOptions() {CachingOption = EventCaching.AddToRoomCache}, SendOptions.SendReliable); + if (finished) + { + PhotonNetwork.LocalPlayer.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) + ProcessOnEvent(evCode, moveHt, PhotonNetwork.LocalPlayer.ActorNumber); + } + + /// <summary> + /// Gets if the player finished the current turn. + /// </summary> + /// <returns><c>true</c>, if player finished the current turn, <c>false</c> otherwise.</returns> + /// <param name="player">The Player to check for</param> + public bool GetPlayerFinishedTurn(Player player) + { + if (player != null && this.finishedPlayers != null && this.finishedPlayers.Contains(player)) + { + return true; + } + + return false; + } + + #region Callbacks + + // called internally + void ProcessOnEvent(byte eventCode, object content, int senderId) + { + if (senderId == -1) + { + return; + } + + sender = PhotonNetwork.CurrentRoom.GetPlayer(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; + } + } + } + + /// <summary> + /// Called by PhotonNetwork.OnEventCall registration + /// </summary> + /// <param name="photonEvent">Photon event.</param> + public void OnEvent(EventData photonEvent) + { + this.ProcessOnEvent(photonEvent.Code, photonEvent.CustomData, photonEvent.Sender); + } + + /// <summary> + /// Called by PhotonNetwork + /// </summary> + /// <param name="propertiesThatChanged">Properties that changed.</param> + public override void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged) + { + + // Debug.Log("OnRoomPropertiesUpdate: "+propertiesThatChanged.ToStringFull()); + + if (propertiesThatChanged.ContainsKey("Turn")) + { + _isOverCallProcessed = false; + this.finishedPlayers.Clear(); + this.TurnManagerListener.OnTurnBegins(this.Turn); + } + } + + #endregion + } + + + public interface IPunTurnManagerCallbacks + { + /// <summary> + /// Called the turn begins event. + /// </summary> + /// <param name="turn">Turn Index</param> + void OnTurnBegins(int turn); + + /// <summary> + /// Called when a turn is completed (finished by all players) + /// </summary> + /// <param name="turn">Turn Index</param> + void OnTurnCompleted(int turn); + + /// <summary> + /// Called when a player moved (but did not finish the turn) + /// </summary> + /// <param name="player">Player reference</param> + /// <param name="turn">Turn Index</param> + /// <param name="move">Move Object data</param> + void OnPlayerMove(Player player, int turn, object move); + + /// <summary> + /// When a player finishes a turn (includes the action/move of that player) + /// </summary> + /// <param name="player">Player reference</param> + /// <param name="turn">Turn index</param> + /// <param name="move">Move Object data</param> + void OnPlayerFinished(Player player, int turn, object move); + + + /// <summary> + /// Called when a turn completes due to a time constraint (timeout for a turn) + /// </summary> + /// <param name="turn">Turn index</param> + void OnTurnTimeEnds(int turn); + } + + + public static class TurnExtensions + { + /// <summary> + /// currently ongoing turn number + /// </summary> + public static readonly string TurnPropKey = "Turn"; + + /// <summary> + /// start (server) time for currently ongoing turn (used to calculate end) + /// </summary> + public static readonly string TurnStartPropKey = "TStart"; + + /// <summary> + /// Finished Turn of Actor (followed by number) + /// </summary> + public static readonly string FinishedTurnPropKey = "FToA"; + + /// <summary> + /// Sets the turn. + /// </summary> + /// <param name="room">Room reference</param> + /// <param name="turn">Turn index</param> + /// <param name="setStartTime">If set to <c>true</c> set start time.</param> + 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); + } + + /// <summary> + /// Gets the current turn from a RoomInfo + /// </summary> + /// <returns>The turn index </returns> + /// <param name="room">RoomInfo reference</param> + public static int GetTurn(this RoomInfo room) + { + if (room == null || room.CustomProperties == null || !room.CustomProperties.ContainsKey(TurnPropKey)) + { + return 0; + } + + return (int) room.CustomProperties[TurnPropKey]; + } + + + /// <summary> + /// Returns the start time when the turn began. This can be used to calculate how long it's going on. + /// </summary> + /// <returns>The turn start.</returns> + /// <param name="room">Room.</param> + public static int GetTurnStart(this RoomInfo room) + { + if (room == null || room.CustomProperties == null || !room.CustomProperties.ContainsKey(TurnStartPropKey)) + { + return 0; + } + + return (int) room.CustomProperties[TurnStartPropKey]; + } + + /// <summary> + /// gets the player's finished turn (from the ROOM properties) + /// </summary> + /// <returns>The finished turn index</returns> + /// <param name="player">Player reference</param> + public static int GetFinishedTurn(this Player player) + { + Room room = PhotonNetwork.CurrentRoom; + if (room == null || room.CustomProperties == null || !room.CustomProperties.ContainsKey(TurnPropKey)) + { + return 0; + } + + string propKey = FinishedTurnPropKey + player.ActorNumber; + return (int) room.CustomProperties[propKey]; + } + + /// <summary> + /// Sets the player's finished turn (in the ROOM properties) + /// </summary> + /// <param name="player">Player Reference</param> + /// <param name="turn">Turn Index</param> + public static void SetFinishedTurn(this Player player, int turn) + { + Room room = PhotonNetwork.CurrentRoom; + if (room == null || room.CustomProperties == null) + { + return; + } + + string propKey = FinishedTurnPropKey + player.ActorNumber; + Hashtable finishedTurnProp = new Hashtable(); + finishedTurnProp[propKey] = turn; + + room.SetCustomProperties(finishedTurnProp); + } + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/TurnBased/PunTurnManager.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/TurnBased/PunTurnManager.cs.meta new file mode 100644 index 0000000..0076919 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/TurnBased/PunTurnManager.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1a1b3bda60e9e804f87fd1e5d20a885a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI.meta new file mode 100644 index 0000000..b1a3ce4 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 665e986f9b37c294d96c166a76e618d3 +folderAsset: yes +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/ButtonInsideScrollList.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/ButtonInsideScrollList.cs new file mode 100644 index 0000000..bb02097 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/ButtonInsideScrollList.cs @@ -0,0 +1,53 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="ButtonInsideScrollList.cs" company="Exit Games GmbH"> +// Part of: Photon Unity Utilities, +// </copyright> +// <summary> +// Used on Buttons inside UI lists to prevent scrollRect parent to scroll when down on buttons. +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using UnityEngine; +using UnityEngine.EventSystems; +using UnityEngine.UI; + +namespace Photon.Pun.UtilityScripts +{ + /// <summary> + /// 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. + /// </summary> + public class ButtonInsideScrollList : MonoBehaviour, IPointerDownHandler, IPointerUpHandler { + + ScrollRect scrollRect; + + // Use this for initialization + void Start () { + scrollRect = GetComponentInParent<ScrollRect>(); + } + + #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/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/ButtonInsideScrollList.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/ButtonInsideScrollList.cs.meta new file mode 100644 index 0000000..9e18870 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/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/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/EventSystemSpawner.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/EventSystemSpawner.cs new file mode 100644 index 0000000..3689bef --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/EventSystemSpawner.cs @@ -0,0 +1,40 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="EventSystemSpawner.cs" company="Exit Games GmbH"> +// </copyright> +// <summary> +// For additive Scene Loading context, eventSystem can't be added to each scene and instead should be instantiated only if necessary. +// https://answers.unity.com/questions/1403002/multiple-eventsystem-in-scene-this-is-not-supporte.html +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using UnityEngine; +using UnityEngine.EventSystems; + +namespace Photon.Pun.UtilityScripts +{ + /// <summary> + /// Event system spawner. Will add an EventSystem GameObject with an EventSystem component and a StandaloneInputModule component. + /// Use this in additive scene loading context where you would otherwise get a "Multiple EventSystem in scene... this is not supported" error from Unity. + /// </summary> + public class EventSystemSpawner : MonoBehaviour + { + void OnEnable() + { + #if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER + Debug.LogError("PUN Demos are not compatible with the New Input System, unless you enable \"Both\" in: Edit > Project Settings > Player > Active Input Handling. Pausing App."); + Debug.Break(); + return; + #endif + + EventSystem sceneEventSystem = FindObjectOfType<EventSystem>(); + if (sceneEventSystem == null) + { + GameObject eventSystem = new GameObject("EventSystem"); + + eventSystem.AddComponent<EventSystem>(); + eventSystem.AddComponent<StandaloneInputModule>(); + } + } + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/EventSystemSpawner.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/EventSystemSpawner.cs.meta new file mode 100644 index 0000000..a7fc376 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/EventSystemSpawner.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 68187d3cf4c8746aaa64930f1a766a38 +timeCreated: 1529319867 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/GraphicToggleIsOnTransition.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/GraphicToggleIsOnTransition.cs new file mode 100644 index 0000000..b2ee446 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/GraphicToggleIsOnTransition.cs @@ -0,0 +1,64 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="ImageToggleIsOnTransition.cs" company="Exit Games GmbH"> +// </copyright> +// <summary> +// Use this on Toggle graphics to have some color transition as well without corrupting toggle's behaviour. +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using UnityEngine; +using UnityEngine.EventSystems; +using UnityEngine.UI; + +namespace Photon.Pun.UtilityScripts +{ + /// <summary> + /// Use this on toggles texts to have some color transition on the text depending on the isOn State. + /// </summary> + [RequireComponent(typeof(Graphic))] + public class GraphicToggleIsOnTransition : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler + { + public Toggle toggle; + + private Graphic _graphic; + + public Color NormalOnColor = Color.white; + public Color NormalOffColor = Color.black; + public Color HoverOnColor = Color.black; + public Color HoverOffColor = Color.black; + + private bool isHover; + + public void OnPointerEnter(PointerEventData eventData) + { + this.isHover = true; + this._graphic.color = this.toggle.isOn ? this.HoverOnColor : this.HoverOffColor; + } + + public void OnPointerExit(PointerEventData eventData) + { + this.isHover = false; + this._graphic.color = this.toggle.isOn ? this.NormalOnColor : this.NormalOffColor; + } + + public void OnEnable() + { + this._graphic = this.GetComponent<Graphic>(); + + this.OnValueChanged(this.toggle.isOn); + + this.toggle.onValueChanged.AddListener(this.OnValueChanged); + } + + public void OnDisable() + { + this.toggle.onValueChanged.RemoveListener(this.OnValueChanged); + } + + public void OnValueChanged(bool isOn) + { + this._graphic.color = isOn ? (this.isHover ? this.HoverOnColor : this.HoverOnColor) : (this.isHover ? this.NormalOffColor : this.NormalOffColor); + } + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/GraphicToggleIsOnTransition.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/GraphicToggleIsOnTransition.cs.meta new file mode 100644 index 0000000..c8c16c9 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/GraphicToggleIsOnTransition.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 195602a009c4b42b6a62e0bdf601b70d +timeCreated: 1524059610 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/OnPointerOverTooltip.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/OnPointerOverTooltip.cs new file mode 100644 index 0000000..0f53fae --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/OnPointerOverTooltip.cs @@ -0,0 +1,45 @@ +// <copyright file="OnPointerOverTooltip.cs" company="Exit Games GmbH"> +// </copyright> +// <summary> +// Set focus to a given photonView when pointed is over +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using UnityEngine; +using UnityEngine.EventSystems; + +namespace Photon.Pun.UtilityScripts +{ + /// <summary> + /// Set focus to a given photonView when pointed is over + /// </summary> + public class OnPointerOverTooltip : MonoBehaviour,IPointerEnterHandler,IPointerExitHandler + { + + void OnDestroy() + { + PointedAtGameObjectInfo.Instance.RemoveFocus(this.GetComponent<PhotonView>()); + } + + #region IPointerExitHandler implementation + + void IPointerExitHandler.OnPointerExit (PointerEventData eventData) + { + PointedAtGameObjectInfo.Instance.RemoveFocus (this.GetComponent<PhotonView>()); + + } + + #endregion + + #region IPointerEnterHandler implementation + + void IPointerEnterHandler.OnPointerEnter (PointerEventData eventData) + { + PointedAtGameObjectInfo.Instance.SetFocus (this.GetComponent<PhotonView>()); + } + + #endregion + + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/OnPointerOverTooltip.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/OnPointerOverTooltip.cs.meta new file mode 100644 index 0000000..bf2483c --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/OnPointerOverTooltip.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ff93154db96e843fbbc5e816ec0d2b48 +timeCreated: 1495545560 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/TabViewManager.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/TabViewManager.cs new file mode 100644 index 0000000..630ab98 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/TabViewManager.cs @@ -0,0 +1,123 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="TabViewManager.cs" company="Exit Games GmbH"> +// Part of: PunCockpit +// </copyright> +// <summary> +// Simple Management for Tabs, it requires a ToggleGroup, and then for each Tab, a Unique Name, the related Toggle and its associated RectTransform View +// this manager handles Tab views activation and deactivation, and provides a Unity Event Callback when a tab was selected. +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Linq; + +using UnityEngine; +using UnityEngine.UI; +using UnityEngine.Events; + +namespace Photon.Pun.UtilityScripts +{ + /// <summary> + /// Tab view manager. Handles Tab views activation and deactivation, and provides a Unity Event Callback when a tab was selected. + /// </summary> + public class TabViewManager : MonoBehaviour + { + + /// <summary> + /// Tab change event. + /// </summary> + [System.Serializable] + public class TabChangeEvent : UnityEvent<string> { } + + [Serializable] + public class Tab + { + public string ID = ""; + public Toggle Toggle; + public RectTransform View; + } + + /// <summary> + /// The toggle group component target. + /// </summary> + public ToggleGroup ToggleGroup; + + /// <summary> + /// all the tabs for this group + /// </summary> + public Tab[] Tabs; + + /// <summary> + /// The on tab changed Event. + /// </summary> + public TabChangeEvent OnTabChanged; + + protected Tab CurrentTab; + + Dictionary<Toggle, Tab> Tab_lut; + + void Start() + { + + Tab_lut = new Dictionary<Toggle, Tab>(); + + foreach (Tab _tab in this.Tabs) + { + + Tab_lut[_tab.Toggle] = _tab; + + _tab.View.gameObject.SetActive(_tab.Toggle.isOn); + + if (_tab.Toggle.isOn) + { + CurrentTab = _tab; + } + _tab.Toggle.onValueChanged.AddListener((isSelected) => + { + if (!isSelected) + { + return; + } + OnTabSelected(_tab); + }); + } + + + } + + /// <summary> + /// Selects a given tab. + /// </summary> + /// <param name="id">Tab Id</param> + public void SelectTab(string id) + { + foreach (Tab _t in Tabs) + { + if (_t.ID == id) + { + _t.Toggle.isOn = true; + return; + } + } + } + + + /// <summary> + /// final method for a tab selection routine + /// </summary> + /// <param name="tab">Tab.</param> + void OnTabSelected(Tab tab) + { + CurrentTab.View.gameObject.SetActive(false); + + CurrentTab = Tab_lut[ToggleGroup.ActiveToggles().FirstOrDefault()]; + + CurrentTab.View.gameObject.SetActive(true); + + OnTabChanged.Invoke(CurrentTab.ID); + + } + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/TabViewManager.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/TabViewManager.cs.meta new file mode 100644 index 0000000..eae6657 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/TabViewManager.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c94485733838d40fda441b2c0fbbec10 +timeCreated: 1521118118 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/TextButtonTransition.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/TextButtonTransition.cs new file mode 100644 index 0000000..277da25 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/TextButtonTransition.cs @@ -0,0 +1,70 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="TextButtonTransition.cs" company="Exit Games GmbH"> +// </copyright> +// <summary> +// Use this on Button texts to have some color transition on the text as well without corrupting button's behaviour. +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using UnityEngine; +using UnityEngine.EventSystems; +using UnityEngine.UI; + +namespace Photon.Pun.UtilityScripts +{ + + /// <summary> + /// Use this on Button texts to have some color transition on the text as well without corrupting button's behaviour. + /// </summary> + [RequireComponent(typeof(Text))] + public class TextButtonTransition : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler + { + + Text _text; + + /// <summary> + /// The selectable Component. + /// </summary> + public Selectable Selectable; + + /// <summary> + /// The color of the normal of the transition state. + /// </summary> + public Color NormalColor= Color.white; + + /// <summary> + /// The color of the hover of the transition state. + /// </summary> + public Color HoverColor = Color.black; + + public void Awake() + { + _text = GetComponent<Text>(); + } + + public void OnEnable() + { + _text.color = NormalColor; + } + + public void OnDisable() + { + _text.color = NormalColor; + } + + public void OnPointerEnter(PointerEventData eventData) + { + if (Selectable == null || Selectable.IsInteractable()) { + _text.color = HoverColor; + } + } + + public void OnPointerExit(PointerEventData eventData) + { + if (Selectable == null || Selectable.IsInteractable()) { + _text.color = NormalColor; + } + } + } +}
\ No newline at end of file diff --git a/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/TextButtonTransition.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/TextButtonTransition.cs.meta new file mode 100644 index 0000000..43cf251 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/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/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/TextToggleIsOnTransition.cs b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/TextToggleIsOnTransition.cs new file mode 100644 index 0000000..8ffbb54 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/TextToggleIsOnTransition.cs @@ -0,0 +1,86 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="TextToggleIsOnTransition.cs" company="Exit Games GmbH"> +// </copyright> +// <summary> +// Use this on Button texts to have some color transition on the text as well without corrupting button's behaviour. +// </summary> +// <author>developer@exitgames.com</author> +// -------------------------------------------------------------------------------------------------------------------- + +using UnityEngine; +using UnityEngine.EventSystems; +using UnityEngine.UI; + +namespace Photon.Pun.UtilityScripts +{ + + /// <summary> + /// Use this on toggles texts to have some color transition on the text depending on the isOn State. + /// </summary> + [RequireComponent(typeof(Text))] + public class TextToggleIsOnTransition : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler + { + + /// <summary> + /// The toggle Component. + /// </summary> + public Toggle toggle; + + Text _text; + + /// <summary> + /// The color of the normal on transition state. + /// </summary> + public Color NormalOnColor= Color.white; + + /// <summary> + /// The color of the normal off transition state. + /// </summary> + public Color NormalOffColor = Color.black; + + /// <summary> + /// The color of the hover on transition state. + /// </summary> + public Color HoverOnColor= Color.black; + + /// <summary> + /// The color of the hover off transition state. + /// </summary> + public Color HoverOffColor = Color.black; + + bool isHover; + + public void OnEnable() + { + _text = GetComponent<Text>(); + + OnValueChanged (toggle.isOn); + + toggle.onValueChanged.AddListener(OnValueChanged); + + } + + public void OnDisable() + { + toggle.onValueChanged.RemoveListener(OnValueChanged); + } + + public void OnValueChanged(bool isOn) + { + _text.color = isOn? (isHover?HoverOnColor:HoverOnColor) : (isHover?NormalOffColor: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/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/TextToggleIsOnTransition.cs.meta b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/TextToggleIsOnTransition.cs.meta new file mode 100644 index 0000000..a2ae161 --- /dev/null +++ b/Mage/Assets/ThirdParty/Photon/PhotonUnityNetworking/UtilityScripts/UI/TextToggleIsOnTransition.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ec99d371d7c8e44899ce4b834dfd4d6a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: |