private static void OnReserveVoxelPositionRequest(ref ReserveVoxelPositionMsg msg, MyNetworkClient sender) { if (!Sync.IsServer) { return; } MyTransportMessageEnum responseState = MyTransportMessageEnum.Success; ReservedEntityData entityData; MyVoxelBase voxelMap = null; if (!MySession.Static.VoxelMaps.Instances.TryGetValue(msg.EntityId, out voxelMap)) { return; } Vector3I voxelMapSize = voxelMap.StorageMax - voxelMap.StorageMin; Debug.Assert(voxelMapSize.AbsMax() < 2 * 10E6, "Voxel map size too large to reserve unique voxel position"); // Integer overflow won't even happen on the next line for voxel maps smaller than roughly (2.5M)^3, and most Vector3I member functions have broken down way before that var entityId = new KeyValuePair <long, long>(msg.EntityId, msg.VoxelPos.X + msg.VoxelPos.Y * voxelMapSize.X + msg.VoxelPos.Z * voxelMapSize.X * voxelMapSize.Y); if (m_reservedEntities.TryGetValue(entityId, out entityData)) { if (entityData.ReserverId == new MyPlayer.PlayerId(sender.SteamUserId, msg.SenderSerialId)) { entityData.ReservationTimer = Stopwatch.GetTimestamp() + Stopwatch.Frequency * msg.ReservationTimeMs / 1000; } else { responseState = MyTransportMessageEnum.Failure; } } else { m_reservedEntities.Add(entityId, new ReservedEntityData() { EntityId = msg.EntityId, GridPos = msg.VoxelPos, ReservationTimer = Stopwatch.GetTimestamp() + Stopwatch.Frequency * msg.ReservationTimeMs / 1000, ReserverId = new MyPlayer.PlayerId(sender.SteamUserId, msg.SenderSerialId) }); } Sync.Layer.SendMessage(ref msg, sender.SteamUserId, responseState); }
private bool IsFaceTriangle(MyNavigationTriangle triangle, Vector3I cubePosition, Vector3I direction) { var e = triangle.GetVertexEnumerator(); // Quantize the point positions to 1/256ths inside each cube (but multiplied by 256 :-) ) e.MoveNext(); Vector3I positionA = Vector3I.Round(e.Current * 256); e.MoveNext(); Vector3I positionB = Vector3I.Round(e.Current * 256); e.MoveNext(); Vector3I positionC = Vector3I.Round(e.Current * 256); cubePosition = cubePosition * 256; // Change the point coordinates to be relative to the face center Vector3I faceCenter = cubePosition + direction * 128; positionA -= faceCenter; positionB -= faceCenter; positionC -= faceCenter; // Discard all triangles whose points are not on the plane of the face if (positionA * direction != Vector3I.Zero) { return(false); } if (positionB * direction != Vector3I.Zero) { return(false); } if (positionC * direction != Vector3I.Zero) { return(false); } // Discard all triangles that are not contained inside the face's square return(positionA.AbsMax() <= 128 && positionB.AbsMax() <= 128 && positionC.AbsMax() <= 128); }
private static void OnReserveVoxelPositionRequest(long entityId, Vector3I voxelPosition, long reservationTimeMs, int senderSerialId) { EndpointId sender; if (MyEventContext.Current.IsLocallyInvoked) { sender = new EndpointId(Sync.MyId); } else { sender = MyEventContext.Current.Sender; } bool success = true; ReservedEntityData entityData; MyVoxelBase voxelMap = null; if (!MySession.Static.VoxelMaps.Instances.TryGetValue(entityId, out voxelMap)) { return; } Vector3I voxelMapSize = voxelMap.StorageMax - voxelMap.StorageMin; Debug.Assert(voxelMapSize.AbsMax() < 2 * 10E6, "Voxel map size too large to reserve unique voxel position"); // Integer overflow won't even happen on the next line for voxel maps smaller than roughly (2.5M)^3, and most Vector3I member functions have broken down way before that var entityIdPair = new KeyValuePair <long, long>(entityId, voxelPosition.X + voxelPosition.Y * voxelMapSize.X + voxelPosition.Z * voxelMapSize.X * voxelMapSize.Y); if (m_reservedEntities.TryGetValue(entityIdPair, out entityData)) { if (entityData.ReserverId == new MyPlayer.PlayerId(sender.Value, senderSerialId)) { entityData.ReservationTimer = Stopwatch.GetTimestamp() + Stopwatch.Frequency * reservationTimeMs / 1000; } else { success = false; } } else { m_reservedEntities.Add(entityIdPair, new ReservedEntityData() { EntityId = entityId, GridPos = voxelPosition, ReservationTimer = Stopwatch.GetTimestamp() + Stopwatch.Frequency * reservationTimeMs / 1000, ReserverId = new MyPlayer.PlayerId(sender.Value, senderSerialId) }); } if (MyEventContext.Current.IsLocallyInvoked) { if (success) { OnReserveVoxelPositionSuccess(entityId, voxelPosition, senderSerialId); } else { OnReserveVoxelPositionFailure(entityId, voxelPosition, senderSerialId); } } else { if (success) { MyMultiplayer.RaiseStaticEvent(s => MyAiTargetManager.OnReserveVoxelPositionSuccess, entityId, voxelPosition, senderSerialId, sender); } else { MyMultiplayer.RaiseStaticEvent(s => MyAiTargetManager.OnReserveVoxelPositionFailure, entityId, voxelPosition, senderSerialId, sender); } } }
// Math magic by Whiplash internal static void BresenhamLineDraw(Vector3I start, Vector3I end, List <Vector3I> points) { points.Clear(); points.Add(start); Vector3I delta = end - start; Vector3I step = Vector3I.Sign(delta); delta *= step; int max = delta.AbsMax(); if (max == delta.X) { int p1 = 2 * delta.Y - delta.X; int p2 = 2 * delta.Z - delta.X; while (start.X != end.X) { start.X += step.X; if (p1 >= 0) { start.Y += step.Y; p1 -= 2 * delta.X; } if (p2 >= 0) { start.Z += step.Z; p2 -= 2 * delta.X; } p1 += 2 * delta.Y; p2 += 2 * delta.Z; points.Add(start); } } else if (max == delta.Y) { int p1 = 2 * delta.X - delta.Y; int p2 = 2 * delta.Z - delta.Y; while (start.Y != end.Y) { start.Y += step.Y; if (p1 >= 0) { start.X += step.X; p1 -= 2 * delta.Y; } if (p2 >= 0) { start.Z += step.Z; p2 -= 2 * delta.Y; } p1 += 2 * delta.X; p2 += 2 * delta.Z; points.Add(start); } } else { int p1 = 2 * delta.X - delta.Z; int p2 = 2 * delta.Y - delta.Z; while (start.Z != end.Z) { start.Z += step.Z; if (p1 >= 0) { start.X += step.X; p1 -= 2 * delta.Z; } if (p2 >= 0) { start.Y += step.Y; p2 -= 2 * delta.Z; } p1 += 2 * delta.X; p2 += 2 * delta.Y; points.Add(start); } } }
internal static bool BresenhamGridIntersection(MyCubeGrid grid, ref Vector3D worldStart, ref Vector3D worldEnd, out Vector3D?hitPos, MyCubeBlock weapon = null, GridAi ai = null) { var start = grid.WorldToGridInteger(worldStart); var end = grid.WorldToGridInteger(worldEnd); Vector3I delta = end - start; Vector3I step = Vector3I.Sign(delta); delta *= step; int max = delta.AbsMax(); hitPos = null; var gMinX = grid.Min.X; var gMinY = grid.Min.Y; var gMinZ = grid.Min.Z; var gMaxX = grid.Max.X; var gMaxY = grid.Max.Y; var gMaxZ = grid.Max.Z; if (ai != null) { var dir = (worldEnd - worldStart); var ray = new RayD(ref worldStart, ref dir); var gridMatrix = ai.MyGrid.PositionComp.WorldMatrixRef; foreach (var sub in ai.SubGrids) { if (sub == grid) { continue; } var subDist = sub.PositionComp.WorldVolume.Intersects(ray); if (subDist.HasValue) { //var rotMatrix = Quaternion.CreateFromRotationMatrix(ai.MyGrid.WorldMatrix); //var obb = new MyOrientedBoundingBoxD(ai.MyGrid.PositionComp.WorldAABB.Center, ai.MyGrid.PositionComp.LocalAABB.HalfExtents, rotMatrix); var box = ai.MyGrid.PositionComp.LocalAABB; var obb = new MyOrientedBoundingBoxD(box, gridMatrix); Vector3D?ignoreHit; if (obb.Intersects(ref ray) != null && BresenhamGridIntersection(sub, ref worldStart, ref worldEnd, out ignoreHit, weapon)) { return(true); } } } } if (max == delta.X) { int p1 = 2 * delta.Y - delta.X; int p2 = 2 * delta.Z - delta.X; while (start.X != end.X) { start.X += step.X; if (p1 >= 0) { start.Y += step.Y; p1 -= 2 * delta.X; } if (p2 >= 0) { start.Z += step.Z; p2 -= 2 * delta.X; } p1 += 2 * delta.Y; p2 += 2 * delta.Z; var contained = gMinX <= start.X && start.X <= gMaxX && (gMinY <= start.Y && start.Y <= gMaxY) && (gMinZ <= start.Z && start.Z <= gMaxZ); if (!contained) { return(false); } MyCube cube; if (grid.TryGetCube(start, out cube) && cube.CubeBlock != weapon?.SlimBlock) { return(true); } } } else if (max == delta.Y) { int p1 = 2 * delta.X - delta.Y; int p2 = 2 * delta.Z - delta.Y; while (start.Y != end.Y) { start.Y += step.Y; if (p1 >= 0) { start.X += step.X; p1 -= 2 * delta.Y; } if (p2 >= 0) { start.Z += step.Z; p2 -= 2 * delta.Y; } p1 += 2 * delta.X; p2 += 2 * delta.Z; var contained = gMinX <= start.X && start.X <= gMaxX && (gMinY <= start.Y && start.Y <= gMaxY) && (gMinZ <= start.Z && start.Z <= gMaxZ); if (!contained) { return(false); } MyCube cube; if (grid.TryGetCube(start, out cube) && cube.CubeBlock != weapon?.SlimBlock) { return(true); } } } else { int p1 = 2 * delta.X - delta.Z; int p2 = 2 * delta.Y - delta.Z; while (start.Z != end.Z) { start.Z += step.Z; if (p1 >= 0) { start.X += step.X; p1 -= 2 * delta.Z; } if (p2 >= 0) { start.Y += step.Y; p2 -= 2 * delta.Z; } p1 += 2 * delta.X; p2 += 2 * delta.Y; var contained = gMinX <= start.X && start.X <= gMaxX && (gMinY <= start.Y && start.Y <= gMaxY) && (gMinZ <= start.Z && start.Z <= gMaxZ); if (!contained) { return(false); } MyCube cube; if (grid.TryGetCube(start, out cube) && cube.CubeBlock != weapon?.SlimBlock) { return(true); } } } return(false); }
private bool IsFaceTriangle(MyNavigationTriangle triangle, Vector3I cubePosition, Vector3I direction) { MyWingedEdgeMesh.FaceVertexEnumerator vertexEnumerator = triangle.GetVertexEnumerator(); vertexEnumerator.MoveNext(); vertexEnumerator.MoveNext(); vertexEnumerator.MoveNext(); cubePosition *= 0x100; Vector3I vectori4 = (Vector3I)(cubePosition + (direction * 0x80)); Vector3I vectori = Vector3I.Round(vertexEnumerator.Current * 256f) - vectori4; Vector3I vectori2 = Vector3I.Round(vertexEnumerator.Current * 256f) - vectori4; Vector3I vectori3 = Vector3I.Round(vertexEnumerator.Current * 256f) - vectori4; return(!((vectori * direction) != Vector3I.Zero) ? (!((vectori2 * direction) != Vector3I.Zero) ? (!((vectori3 * direction) != Vector3I.Zero) ? ((vectori.AbsMax() <= 0x80) && ((vectori2.AbsMax() <= 0x80) && (vectori3.AbsMax() <= 0x80))) : false) : false) : false); }