public override async Task <GetRandomPointResponse> GetRandomPoint(GetRandomPointRequest request, ServerCallContext context) { Navmesh mesh; if (!Navmeshes.TryGetValue(request.Navmesh, out mesh)) { Metrics.QPSByResult["NavmeshUnavailable"].Increment(); return(new GetRandomPointResponse()); } var onDequeue = Metrics.Record("RandomPoint", request.Navmesh); return(await Task.Factory.StartNew(() => { lock (mesh) { onDequeue(); var center = ToRecastFloats(request.Position.X, request.Position.Y, request.Position.Z + 8); var cradius = request.Radius *CONVERSION_FACTOR; var outVec = new float[3]; var defaultInclude = dtPolyFlags.ALL ^ dtPolyFlags.DISABLED; var defaultExclude = (dtPolyFlags)0; var filter = new[] { defaultInclude, defaultExclude }; var polyPickEx = new float[3] { 2.0f, 4.0f, 2.0f }; var status = FindRandomPointAroundCircle(mesh.QueryPtr, center, cradius, polyPickEx, filter, outVec, () => (float)mesh.Random.NextDouble()); if ((status & dtStatus.DT_SUCCESS) == 0) { Metrics.QPSByResult["NoRandomPointFound"].Increment(); return new GetRandomPointResponse(); } Metrics.QPSByResult["RandomPointFound"].Increment(); return new GetRandomPointResponse { Point = new Vec3 { X = outVec[0] * INV_FACTOR, Y = outVec[2] * INV_FACTOR, Z = outVec[1] * INV_FACTOR } }; } }, TaskCreationOptions.LongRunning)); }
public override async Task <PathingResponse> GetPathStraight(PathingRequest request, ServerCallContext context) { // NOTE: Consider using GetPathStreamed instead Navmesh mesh; if (!Navmeshes.TryGetValue(request.Navmesh, out mesh)) { Metrics.QPSByResult["NavmeshUnavailable"].Increment(); return(new PathingResponse { ResultCode = PathingResult.NavmeshUnavailable }); } var onDequeue = Metrics.Record("Path", request.Navmesh); return(await Task.Factory.StartNew(() => { lock (mesh) { onDequeue(); var startFloats = ToRecastFloats(request.StartingPoint.X, request.StartingPoint.Y, request.StartingPoint.Z + 8); var endFloats = ToRecastFloats(request.DestinationPoint.X, request.DestinationPoint.Y, request.DestinationPoint.Z + 8); var numNodes = 0; var buffer = new float[MAX_POLY * 3]; var flags = new dtPolyFlags[MAX_POLY]; var includeFilter = dtPolyFlags.ALL ^ dtPolyFlags.DISABLED; var excludeFilter = (dtPolyFlags)0; var filter = new[] { includeFilter, excludeFilter }; var polyExt = ToRecastFloats(64f, 64f, 256f); var options = dtStraightPathOptions.DT_STRAIGHTPATH_ALL_CROSSINGS; var status = PathStraight(mesh.QueryPtr, startFloats, endFloats, polyExt, filter, options, ref numNodes, buffer, flags); if ((status & dtStatus.DT_SUCCESS) == 0) { Metrics.QPSByResult["NoPathFound"].Increment(); return new PathingResponse { ResultCode = PathingResult.NoPathFound }; } var points = new PathPoint[numNodes]; var positions = Vector3ArrayFromRecastFloats(buffer, numNodes); for (var i = 0; i < numNodes; i++) { points[i] = new PathPoint { Flags = (uint)flags[i], Position = positions[i] }; } if ((status & dtStatus.DT_PARTIAL_RESULT) == 0) { Metrics.QPSByResult["PathFound"].Increment(); return new PathingResponse { ResultCode = PathingResult.PathFound, Path = { points } }; } Metrics.QPSByResult["PartialPathFound"].Increment(); return new PathingResponse { ResultCode = PathingResult.PartialPathFound, Path = { points } }; } }, TaskCreationOptions.LongRunning)); }
private unsafe PathingResponse GetPathForStreaming(PathingRequest request) { Navmesh mesh; if (!Navmeshes.TryGetValue(request.Navmesh, out mesh)) { Metrics.QPSByResult["NavmeshUnavailable"].Increment(); return(new PathingResponse() { SequenceID = request.SequenceID, ResultCode = PathingResult.NavmeshUnavailable, }); } var onDequeue = Metrics.Record("PathStreamed", request.Navmesh); lock (mesh) { onDequeue(); var startFloats = ToRecastFloats(request.StartingPoint.X, request.StartingPoint.Y, request.StartingPoint.Z + 8); var endFloats = ToRecastFloats(request.DestinationPoint.X, request.DestinationPoint.Y, request.DestinationPoint.Z + 8); var numNodes = 0; var buffer = new float[MAX_POLY * 3]; var flags = new dtPolyFlags[MAX_POLY]; var includeFilter = dtPolyFlags.ALL ^ dtPolyFlags.DISABLED; var excludeFilter = (dtPolyFlags)0; var filter = new[] { includeFilter, excludeFilter }; var polyExt = ToRecastFloats(64f, 64f, 256f); var options = dtStraightPathOptions.DT_STRAIGHTPATH_ALL_CROSSINGS; var status = PathStraight(mesh.QueryPtr, startFloats, endFloats, polyExt, filter, options, ref numNodes, buffer, flags); if ((status & dtStatus.DT_SUCCESS) == 0) { Metrics.QPSByResult["NoPathFound"].Increment(); return(new PathingResponse() { SequenceID = request.SequenceID, ResultCode = PathingResult.NoPathFound, }); } var code = PathingResult.PathFound; if ((status & dtStatus.DT_PARTIAL_RESULT) != 0) { Metrics.QPSByResult["PartialPathFound"].Increment(); code = PathingResult.PartialPathFound; } else { Metrics.QPSByResult["PathFound"].Increment(); } // Create nodes var positions = Vector3ArrayFromRecastFloats(buffer, numNodes); var oneStructSize = Marshal.SizeOf <PathPointStruct>(); var oneStruct = Marshal.AllocHGlobal(oneStructSize); byte[] buf = new byte[oneStructSize * numNodes]; for (int i = 0; i < numNodes; i++) { var vec = positions[i]; var pp = new PathPointStruct { Flags = flags[i], X = (float)vec.X, Y = (float)vec.Y, Z = (float)vec.Z, }; Marshal.StructureToPtr(pp, oneStruct, false); Marshal.Copy(oneStruct, buf, i * oneStructSize, oneStructSize); } return(new PathingResponse() { SequenceID = request.SequenceID, PathNodes = (uint)numNodes, ResultCode = code, SerializedNodes = ByteString.CopyFrom(buf, 0, buf.Length) }); } }