using System.Collections; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using UnityEngine; public class SocketContainer : MonoBehaviour { [Header("Socket Management")] [SerializeField] private List sockets = new List(); // This list will now control the order and availability of manual iteration [SerializeField] private List iterativeSockets = new List(); [SerializeField] private bool autoDetectSockets = true; [Header("Cycling Behavior")] [SerializeField] private bool allowCycling = true; [SerializeField] private bool wrapAround = true; private BlockContainerInit containerInit; private int currentSocketIndex = 0; private SocketPoint currentActiveSocket; void Awake() { InitializeSockets(); } private void InitializeSockets() { if (autoDetectSockets) { sockets.Clear(); SocketPoint[] foundSockets = GetComponentsInChildren(); sockets.AddRange(foundSockets); if (sockets.Count > 0) { Debug.Log($"{gameObject.name} detected {sockets.Count} total sockets"); } } // Initialize iteration state using iterativeSockets list if (iterativeSockets.Count > 0) { currentSocketIndex = 0; currentActiveSocket = iterativeSockets[0]; } else if (sockets.Count > 0) { containerInit = gameObject.GetComponent(); if (containerInit == null) return; iterativeSockets = containerInit.InitBlockContainer(sockets); currentSocketIndex = 0; currentActiveSocket = iterativeSockets[0]; } } /// /// Updated: Returns the active socket from the ITERATIVE list /// public SocketPoint GetActiveSocket() { if (iterativeSockets.Count == 0) return null; return iterativeSockets[currentSocketIndex]; } /// /// Updated: Cycles through iterativeSockets /// public void CycleToNextSocket() { if (!allowCycling || iterativeSockets.Count <= 1) return; if (iterativeSockets[currentSocketIndex] != null) iterativeSockets[currentSocketIndex].Highlight(HighlightState.Default); currentSocketIndex++; if (currentSocketIndex >= iterativeSockets.Count) currentSocketIndex = wrapAround ? 0 : iterativeSockets.Count - 1; currentActiveSocket = iterativeSockets[currentSocketIndex]; if (currentActiveSocket != null) currentActiveSocket.Highlight(HighlightState.Active); } /// /// Updated: Cycles through iterativeSockets /// public void CycleToPreviousSocket() { if (!allowCycling || iterativeSockets.Count <= 1) return; if (iterativeSockets[currentSocketIndex] != null) iterativeSockets[currentSocketIndex].Highlight(HighlightState.Default); currentSocketIndex--; if (currentSocketIndex < 0) currentSocketIndex = wrapAround ? iterativeSockets.Count - 1 : 0; currentActiveSocket = iterativeSockets[currentSocketIndex]; if (currentActiveSocket != null) currentActiveSocket.Highlight(HighlightState.Active); } /// /// Updated: Targets iterativeSockets /// public void SetActiveSocketByIndex(int index) { if (index < 0 || index >= iterativeSockets.Count) return; if (iterativeSockets[currentSocketIndex] != null) iterativeSockets[currentSocketIndex].Highlight(HighlightState.Default); currentSocketIndex = index; currentActiveSocket = iterativeSockets[currentSocketIndex]; if (currentActiveSocket != null) currentActiveSocket.Highlight(HighlightState.Active); } /// /// Updated: Finds the index within the iterativeSockets list /// public void SetActiveSocket(SocketPoint socket) { int index = iterativeSockets.IndexOf(socket); if (index >= 0) SetActiveSocketByIndex(index); } public void ResetToFirstSocket() { if (iterativeSockets.Count == 0) return; ClearAllHighlights(); currentSocketIndex = 0; currentActiveSocket = iterativeSockets[0]; if (currentActiveSocket != null) currentActiveSocket.Highlight(HighlightState.Active); } /// /// Get all sockets in this container /// public List GetAllSockets() { return new List(sockets); } /// /// Get all unoccupied sockets /// public List GetAvailableSockets() { List available = new List(); foreach (SocketPoint socket in sockets) { if (socket != null && !socket.IsOccupied()) { available.Add(socket); } } return available; } /// /// Get all occupied sockets /// public List GetOccupiedSockets() { List occupied = new List(); foreach (SocketPoint socket in sockets) { if (socket != null && socket.IsOccupied()) { occupied.Add(socket); } } return occupied; } /// /// Find the nearest compatible socket to a given world position /// public SocketPoint FindNearestCompatibleSocket(Vector3 worldPosition, SocketPoint sourceSocket) { SocketPoint nearest = null; float minDistance = float.MaxValue; foreach (SocketPoint socket in sockets) { // Skip occupied sockets if (socket.IsOccupied()) continue; // Check compatibility if (sourceSocket != null && !socket.CanAccept(sourceSocket)) continue; // Calculate distance float distance = Vector3.Distance(socket.GetTransform().position, worldPosition); if (distance < minDistance) { minDistance = distance; nearest = socket; } } return nearest; } /// /// Find all sockets within a certain radius of a position /// public List FindSocketsInRadius(Vector3 worldPosition, float radius, bool onlyAvailable = true) { List socketsInRadius = new List(); foreach (SocketPoint socket in sockets) { if (onlyAvailable && socket.IsOccupied()) continue; float distance = Vector3.Distance(socket.GetTransform().position, worldPosition); if (distance <= radius) { socketsInRadius.Add(socket); } } return socketsInRadius; } /// /// Get sockets by type /// public List GetSocketsByType(SocketType type) { List filtered = new List(); foreach (SocketPoint socket in sockets) { if (socket.GetSocketType() == type) { filtered.Add(socket); } } return filtered; } /// /// Highlight all sockets with a specific state /// public void HighlightAllSockets(HighlightState state) { foreach (SocketPoint socket in sockets) { if (socket != null) { socket.Highlight(state); } } } /// /// Clear all socket highlights /// public void ClearAllHighlights() { foreach (SocketPoint socket in sockets) { if (socket != null) { socket.Highlight(HighlightState.Default); } } } /// /// Manually add a socket to the container /// public void AddSocket(SocketPoint socket) { if (!sockets.Contains(socket)) { sockets.Add(socket); Debug.Log($"Added socket {socket.name} to container"); } } /// /// Remove a socket from the container /// public void RemoveSocket(SocketPoint socket) { if (sockets.Contains(socket)) { sockets.Remove(socket); // If we removed the active socket, reset to first if (socket == currentActiveSocket && sockets.Count > 0) { currentSocketIndex = 0; currentActiveSocket = sockets[0]; } } } /// /// Get count of total sockets /// public int GetSocketCount() { return sockets.Count; } /// /// Check if container has any sockets /// public bool HasSockets() { return sockets.Count > 0; } /// /// Get the current socket index /// public int GetCurrentSocketIndex() { return currentSocketIndex; } /// /// Find sockets that can connect to a specific joint block /// public List FindSocketsCompatibleWithJoint(JointBlock jointBlock) { List compatible = new List(); SocketPoint jointEnd1 = jointBlock.GetSocketEnd1(); SocketPoint jointEnd2 = jointBlock.GetSocketEnd2(); foreach (SocketPoint socket in sockets) { if (socket.IsOccupied()) continue; if (jointEnd1 != null && socket.CanAccept(jointEnd1)) { compatible.Add(socket); } else if (jointEnd2 != null && socket.CanAccept(jointEnd2)) { compatible.Add(socket); } } return compatible; } #if UNITY_EDITOR /// /// Visualize sockets in editor /// private void OnDrawGizmos() { if (sockets.Count == 0) return; foreach (SocketPoint socket in sockets) { if (socket == null) continue; // Draw sphere at socket position Gizmos.color = socket.IsOccupied() ? Color.red : Color.green; Gizmos.DrawWireSphere(socket.GetTransform().position, socket.GetSocketRadius()); // Draw normal direction Gizmos.color = Color.blue; Gizmos.DrawRay(socket.GetTransform().position, socket.GetNormal() * 0.2f); } // Highlight active socket if (currentActiveSocket != null) { Gizmos.color = Color.yellow; Gizmos.DrawWireSphere(currentActiveSocket.GetTransform().position, currentActiveSocket.GetSocketRadius() * 1.2f); } } /// /// Editor button to refresh socket list /// [ContextMenu("Refresh Sockets")] private void EditorRefreshSockets() { InitializeSockets(); } #endif }