public virtual void ItemUsedOnBlock(Coordinates3D coordinates, ItemStack item, BlockFace face, IWorld world, IRemoteClient user) { var old = world.GetBlockData(coordinates); if (!Overwritable.Any(b => b == old.Id)) { coordinates += MathHelper.BlockFaceToCoordinates(face); old = world.GetBlockData(coordinates); if (!Overwritable.Any(b => b == old.Id)) { return; } } // Test for entities if (BoundingBox.HasValue) { var em = user.Server.GetEntityManagerForWorld(world); var entities = em.EntitiesInRange(coordinates.AsVector3(), 3); var box = new BoundingBox(BoundingBox.Value.Min + (Vector3)coordinates.AsVector3(), BoundingBox.Value.Max + (Vector3)coordinates.AsVector3()); foreach (var entity in entities) { var aabb = entity as IAABBEntity; if (aabb != null && !(entity is ItemEntity)) { if (aabb.BoundingBox.Intersects(box)) { return; } } var player = entity as PlayerEntity; // Players do not implement IAABBEntity if (player != null) { if (new BoundingBox(player.Position, player.Position + player.Size.AsVector3()) .Intersects(box)) { return; } } } } // Place block world.SetBlockId(coordinates, Id); world.SetMetadata(coordinates, (byte)item.Metadata); BlockPlaced(world.GetBlockData(coordinates), face, world, user); if (!IsSupported(world.GetBlockData(coordinates), user.Server, world)) { world.SetBlockData(coordinates, old); } else { item.Count--; user.Inventory[user.SelectedSlot] = item; } }
public bool TestTerrainCollisionCylinder(IAABBEntity entity, out Vector3 collisionPoint) { collisionPoint = Vector3.Zero; var testBox = GetAABBVelocityBox(entity); var testCylinder = new BoundingCylinder(testBox.Min, testBox.Max, entity.BoundingBox.Min.DistanceTo(entity.BoundingBox.Max)); var collision = false; for (var x = (int)Math.Floor(testBox.Min.X); x <= (int)Math.Ceiling(testBox.Max.X); x++) { for (var z = (int)Math.Floor(testBox.Min.Z); z <= (int)Math.Ceiling(testBox.Max.Z); z++) { for (var y = (int)Math.Floor(testBox.Min.Y); y <= (int)Math.Ceiling(testBox.Max.Y); y++) { var coords = new Coordinates3D(x, y, z); if (!World.IsValidPosition(coords)) { continue; } var _box = BlockPhysicsProvider.GetBoundingBox(World, coords); if (_box == null) { continue; } var box = _box.Value.OffsetBy(coords.AsVector3()); if (testCylinder.Intersects(box)) { if (testBox.Intersects(box)) { collision = true; AdjustVelocityForCollision(entity, box); testBox = GetAABBVelocityBox(entity); testCylinder = new BoundingCylinder(testBox.Min, testBox.Max, entity.BoundingBox.Min.DistanceTo(entity.BoundingBox.Max)); collisionPoint = coords.AsVector3(); } } } } } return(collision); }
public static void HandleUpdateSignPacket(IPacket _packet, IRemoteClient _client, IMultiPlayerServer server) { var packet = (UpdateSignPacket)_packet; var client = (RemoteClient)_client; var coords = new Coordinates3D(packet.X, packet.Y, packet.Z); if (client.Entity.Position.DistanceTo(coords.AsVector3()) < 10) // TODO: Reach { var block = client.World.GetBlockId(coords); if (block == UprightSignBlock.BlockId || block == WallSignBlock.BlockId) { client.World.SetTileEntity(coords, new NbtCompound(new[] { new NbtString("Text1", packet.Text[0]), new NbtString("Text2", packet.Text[1]), new NbtString("Text3", packet.Text[2]), new NbtString("Text4", packet.Text[3]) })); // TODO: Some utility methods for things like "clients with given chunk loaded" server.Clients.Where(c => ((RemoteClient)c).LoggedIn && c.World == _client.World).ToList() .ForEach(c => c.QueuePacket(packet)); } } }
public bool TestTerrainCollisionZ(IAABBEntity entity, out Vector3 collisionPoint) { // Things we need to do: // 1 - expand bounding box to include the destination and everything within // 2 - collect all blocks within that area // 3 - test bounding boxes in direction of motion collisionPoint = Vector3.Zero; if (entity.Velocity.Z == 0) { return(false); } bool negative; BoundingBox testBox; if (entity.Velocity.Z < 0) { testBox = new BoundingBox( new Vector3( entity.BoundingBox.Min.X, entity.BoundingBox.Min.Y, entity.BoundingBox.Min.Z + entity.Velocity.Z), entity.BoundingBox.Max); negative = true; } else { testBox = new BoundingBox( entity.BoundingBox.Min, new Vector3( entity.BoundingBox.Max.X, entity.BoundingBox.Max.Y, entity.BoundingBox.Max.Z + entity.Velocity.Z)); negative = false; } double?collisionExtent = null; for (var x = (int)Math.Floor(testBox.Min.X); x <= (int)Math.Ceiling(testBox.Max.X); x++) { for (var z = (int)Math.Floor(testBox.Min.Z); z <= (int)Math.Ceiling(testBox.Max.Z); z++) { for (var y = (int)Math.Floor(testBox.Min.Y); y <= (int)Math.Ceiling(testBox.Max.Y); y++) { var coords = new Coordinates3D(x, y, z); if (!World.IsValidPosition(coords)) { continue; } var _box = BlockPhysicsProvider.GetBoundingBox(World, coords); if (_box == null) { continue; } var box = _box.Value.OffsetBy(coords.AsVector3()); if (testBox.Intersects(box)) { if (negative) { if (collisionExtent == null || collisionExtent.Value < box.Max.Z) { collisionExtent = box.Max.Z; collisionPoint = coords.AsVector3(); } } else { if (collisionExtent == null || collisionExtent.Value > box.Min.Z) { collisionExtent = box.Min.Z; collisionPoint = coords.AsVector3(); } } } } } } if (collisionExtent != null) // Collision detected, adjust accordingly { var extent = collisionExtent.Value; double diff; if (negative) { diff = -(entity.BoundingBox.Min.Z - extent); } else { diff = extent - entity.BoundingBox.Max.Z; } entity.Velocity = new Vector3(entity.Velocity.X, entity.Velocity.Y, (float)diff); return(true); } return(false); }