WarpAttemptResult CanWarp(IShip warpingShip, Player warpingPlayer, IArea currentArea, int destinationAreaID, int warpholeIndex, out string denialString) { if (currentArea == null) { denialString = ""; return(WarpAttemptResult.CurrentAreaNotFound); } if (currentArea.Warpholes[warpholeIndex].DestinationAreaID != destinationAreaID) { denialString = ""; return(WarpAttemptResult.DestinationAreaIDMismatch);//Packet corruption or hacking attempt? Also potential multiple warp requests recieved and processed for the same warphole } if (TimeKeeper.MsSinceInitialization - warpingShip.LastWarpTime < ServerConfig.MinWarpPeriod) { denialString = "";//Probably better to fail silently return(WarpAttemptResult.StillInWarpCooldown); } if (!currentArea.IsAreaConnected(destinationAreaID)) //Fixes a bug where a ship might send a second warp request before the first is complete, since we send warp indices instead of destination areas from the client { denialString = ""; //Clients will only get here if they are hacking or if there's a weird latency-caused pseudo-bug. Probably better to fail silently. return(WarpAttemptResult.NotConnectedArea); } if (warpingShip.CurrentEnergy != warpingShip.MaxEnergy)//Do we want to allow [some] ships to warp without full energy? { denialString = "Warp failed: not enough energy."; return(WarpAttemptResult.NotEnoughEnergy); } if (warpingShip.DistanceTo(currentArea.Warpholes[warpholeIndex]) > 2) { denialString = "";//Probably better to fail silently return(WarpAttemptResult.NotNearWarp); } if (warpingPlayer.IsTrading) { denialString = "Can't warp while trading!"; return(WarpAttemptResult.Trading); } denialString = ""; return(WarpAttemptResult.Success); }