/// <summary> /// Make connection by request /// </summary> /// <param name="targetNode"></param> /// <param name="character"></param> public void MakeConnection(IPBSObject targetNode, Character character) { //source pbsObject access check _pbsObject.CheckAccessAndThrowIfFailed(character); //--- transmit radius check targetNode.ThrowIfEqual(_pbsObject, ErrorCodes.WTFErrorMedicalAttentionSuggested); var targetUnit = ((Unit)targetNode); targetUnit.CurrentPosition.IsInRangeOf2D(_pbsObject.CurrentPosition, _pbsObject.GetTransmitRadius()).ThrowIfFalse(ErrorCodes.TargetOutOfTransmitRadius); //check pair-------------------------- _pbsObject.ConnectionHandler.CheckNewConnection(targetNode, true); targetNode.ConnectionHandler.CheckNewConnection(_pbsObject, false); //-------check networks and owners var changeOwner = false; long newOwner = 0L; var sourceNetwork = NetworkNodes.ToArray(); IPBSObject[] targetNetwork = null; var dockingBaseInSourceNetwork = false; var dockingBaseInTargetNetwork = false; var isSameNetwork = sourceNetwork.Any(p => p.GetHashCode() == targetNode.GetHashCode()); if (!isSameNetwork) { //they are in different networks targetNetwork = targetNode.ConnectionHandler.NetworkNodes.ToArray(); var sourceDockingBase = sourceNetwork.FirstOrDefault(n => n is PBSDockingBase) as PBSDockingBase; var targetDockingBase = targetNetwork.FirstOrDefault(n => n is PBSDockingBase) as PBSDockingBase; dockingBaseInSourceNetwork = sourceDockingBase != null; dockingBaseInTargetNetwork = targetDockingBase != null; //check nodes in networks if (dockingBaseInSourceNetwork) { IsAnyNodeOutsideOfNetworkRange(sourceNetwork, sourceDockingBase).ThrowIfTrue(ErrorCodes.SomeNodeAreOutsideOfNetworkRange); IsAnyNodeOutsideOfNetworkRange(targetNetwork, sourceDockingBase).ThrowIfTrue(ErrorCodes.SomeNodeAreOutsideOfNetworkRange); } var sumUsage = sourceNetwork.Concat(targetNetwork).Where(n => !(n is PBSDockingBase)).Sum(n => n.GetBandwidthUsage()); //both networks have docking bases -> nono (dockingBaseInSourceNetwork && dockingBaseInTargetNetwork).ThrowIfTrue(ErrorCodes.BasesInBothNetworks); if (dockingBaseInSourceNetwork || dockingBaseInTargetNetwork) { //there must be a docking base in one of the two changeOwner = true; //-------------------------------------- number of nodes check int bandwidthCapacity; if (dockingBaseInSourceNetwork) { bandwidthCapacity = sourceDockingBase.GetBandwidthCapacity; } else { bandwidthCapacity = targetDockingBase.GetBandwidthCapacity; } sumUsage.ThrowIfGreater(bandwidthCapacity, ErrorCodes.TooManyNodesOutOfCpu); //------------------------------------------ new owner select if (dockingBaseInSourceNetwork) { newOwner = _pbsObject.Owner; } else { newOwner = targetUnit.Owner; } } else { //no docking base sumUsage.ThrowIfGreater(CPU_POWER_IN_NETWORK_WITHOUT_BASE, ErrorCodes.TooManyNodesOutOfCpu); _pbsObject.Owner.ThrowIfNotEqual(targetUnit.Owner, ErrorCodes.OwnerMismatch); } } if (changeOwner) { if (newOwner == 0) { //lekezeletlen resz %%% Debug.Assert(false, " nincs megirva"); } else { if (dockingBaseInSourceNetwork) { foreach (var n in targetNetwork) { n.TakeOver(newOwner); } } if (dockingBaseInTargetNetwork) { foreach (var n in sourceNetwork) { n.TakeOver(newOwner); } } } } //-----------------------------do actual work var outConnection = new PBSConnection(targetNode, _pbsObject, true); AttachConnection(outConnection); var inConnection = new PBSConnection(_pbsObject, targetNode, false); targetNode.ConnectionHandler.AttachConnection(inConnection); Transaction.Current.OnCommited(() => { var pbsBase = NetworkNodes.FirstOrDefault(o => o is PBSDockingBase); if (pbsBase == null) { return; } _pbsObject.ReinforceHandler.ForceDailyOffset(pbsBase.ReinforceHandler.ReinforceOffsetHours); //this node foreach (var node in NetworkNodes) { if (node.Equals(_pbsObject)) { continue; } if (node.Equals(pbsBase)) { continue; } //all reinforcable nodes in the network node.ReinforceHandler.ForceDailyOffset(pbsBase.ReinforceHandler.ReinforceOffsetHours); } }); }