//-- Creates a spherical crater where the meteor made contact with the ground --// private void CreateCrater(Vec3d meteorDirection, Vec3d shrapnelDirection) { List <LandClaim> claims = serverAPI.World.Claims.All; List <BlockPos> ashPositions = new List <BlockPos>(); blockAccessor = serverAPI.World.GetBlockAccessorBulkUpdate(true, true); Vec3i centerPos = this.entity.ServerPos.XYZInt; BlockPos craterPos = new BlockPos(); //-- Initial scan to see if the meteor crater should fill with liquid instead of air --// blockAccessor.SearchFluidBlocks(new BlockPos(centerPos.X - explosionRadius, centerPos.Y - explosionRadius, centerPos.Z - explosionRadius), new BlockPos(centerPos.X + explosionRadius, centerPos.Y + explosionRadius, centerPos.Z + explosionRadius), (block, bPos) => { if (block.DrawType == EnumDrawType.Liquid) { liquidAsset = new AssetLocation(block.Code.Domain, block.Code.Path); fillWithLiquid = true; fillHeight = bPos.Y; return(true); } return(false); }); //-- Scans every block in a cube determined by the explosion radius and determines whether that block fits within the explosion sphere --// blockAccessor.WalkBlocks(new BlockPos(centerPos.X - explosionRadius, centerPos.Y - explosionRadius, centerPos.Z - explosionRadius), new BlockPos(centerPos.X + explosionRadius, centerPos.Y + explosionRadius, centerPos.Z + explosionRadius), (block, xPos, yPos, zPos) => { BlockPos blockPos = new BlockPos(xPos, yPos, zPos); float distanceToCenter = blockPos.DistanceTo(centerPos.ToBlockPos()); if (distanceToCenter < explosionRadius) { if (serverAPI.World.Config.GetBool("ClaimsProtected") == true) { bool isClaimed = false; foreach (LandClaim claim in claims) { if (claim.PositionInside(blockPos)) { isClaimed = true; } } if (isClaimed == false) { ExplodeBlock(block, blockPos, shrapnelDirection); if (fillWithLiquid == false) { if (centerPos.Y - blockPos.Y == explosionRadius - 1) { if (explosionRand.Next(0, 100) < ashBlockChance) { ashPositions.Add(blockPos + new BlockPos(0, 1, 0)); } } } } } else { ExplodeBlock(block, blockPos, shrapnelDirection); if (fillWithLiquid == false) { if (centerPos.Y - blockPos.Y == explosionRadius - 1) { if (explosionRand.Next(0, 100) < ashBlockChance) { ashPositions.Add(blockPos.Copy() + new BlockPos(0, 1, 0)); } } } } } }); PlaceMeteor(meteorDirection, shrapnelDirection, centerPos, explosionRadius, claims); PlaceAsh(ashPositions); blockAccessor.Commit(); }
/// <summary> /// Updates the velocity vector according to the amount of passed time, gravity and terrain collision. /// </summary> /// <param name="pos"></param> /// <param name="motion"></param> /// <param name="blockAccessor"></param> /// <param name="gravityStrength"></param> /// <param name="deltatime"></param> /// <returns></returns> public EnumCollideFlags UpdateMotion(Vec3d pos, Vec3d motion, float height) { particleCollBox.Set( pos.X - height / 2, pos.Y - 0 / 2, pos.Z - height / 2, pos.X + height / 2, pos.Y + height / 2, pos.Z + height / 2 ); motion.X = Math.Min(2, Math.Abs(motion.X)) * Math.Sign(motion.X); motion.Y = Math.Min(2, Math.Abs(motion.Y)) * Math.Sign(motion.Y); motion.Z = Math.Min(2, Math.Abs(motion.Z)) * Math.Sign(motion.Z); EnumCollideFlags flags = 0; BlockPos minPos = new BlockPos(); BlockPos maxPos = new BlockPos(); minPos.Set( (int)(particleCollBox.X1 + Math.Min(0, motion.X)), (int)(particleCollBox.Y1 + Math.Min(0, motion.Y) - 1), // -1 for the extra high collision box of fences (int)(particleCollBox.Z1 + Math.Min(0, motion.Z)) ); maxPos.Set( (int)(particleCollBox.X2 + Math.Max(0, motion.X)), (int)(particleCollBox.Y2 + Math.Max(0, motion.Y)), (int)(particleCollBox.Z2 + Math.Max(0, motion.Z)) ); CollisionBoxList.Clear(); BlockAccess.WalkBlocks(minPos, maxPos, (cblock, bpos) => { Cuboidf[] collisionBoxes = cblock.GetCollisionBoxes(BlockAccess, bpos); for (int i = 0; collisionBoxes != null && i < collisionBoxes.Length; i++) { CollisionBoxList.Add(collisionBoxes[i], bpos, cblock); } }, false); // Y - Collision (Vertical) EnumPushDirection pushDirection = EnumPushDirection.None; for (int i = 0; i < CollisionBoxList.Count; i++) { blockCollBox = CollisionBoxList.cuboids[i]; motion.Y = blockCollBox.pushOutY(particleCollBox, motion.Y, ref pushDirection); if (pushDirection != EnumPushDirection.None) { flags |= EnumCollideFlags.CollideY; } } particleCollBox.Translate(0, motion.Y, 0); // X - Collision (Horizontal) for (int i = 0; i < CollisionBoxList.Count; i++) { blockCollBox = CollisionBoxList.cuboids[i]; motion.X = (float)blockCollBox.pushOutX(particleCollBox, motion.X, ref pushDirection); if (pushDirection != EnumPushDirection.None) { flags |= EnumCollideFlags.CollideX; } } particleCollBox.Translate(motion.X, 0, 0); // Z - Collision (Horizontal) for (int i = 0; i < CollisionBoxList.Count; i++) { blockCollBox = CollisionBoxList.cuboids[i]; motion.Z = (float)blockCollBox.pushOutZ(particleCollBox, motion.Z, ref pushDirection); if (pushDirection != EnumPushDirection.None) { flags |= EnumCollideFlags.CollideZ; } } return(flags); }