Esempio n. 1
0
 private void CheckWithTerrain(IAABBEntity entity, World world)
 {
     Vector3 collisionPoint, collisionDirection;
     if (entity.Position.Y + entity.Velocity.Y >= 0 && entity.Position.Y + entity.Velocity.Y <= 255) // Don't do checks outside the map
     {
         bool fireEvent = entity.Velocity != Vector3.Zero;
         // Do terrain collisions
         if (AdjustVelocityX(entity, world, out collisionPoint, out collisionDirection))
         {
             if (fireEvent)
                 entity.TerrainCollision(this, collisionPoint, collisionDirection);
         }
         if (AdjustVelocityY(entity, world, out collisionPoint, out collisionDirection))
         {
             entity.Velocity *= new Vector3(0.2, 1, 0.2); // TODO: More sophisticated friction
             if (fireEvent)
                 entity.TerrainCollision(this, collisionPoint, collisionDirection);
         }
         if (AdjustVelocityZ(entity, world, out collisionPoint, out collisionDirection))
         {
             if (fireEvent)
                 entity.TerrainCollision(this, collisionPoint, collisionDirection);
         }
     }
 }
Esempio n. 2
0
 public PhysicsEngine(World world)
 {
     World = world;
     Entities = new List<IPhysicsEntity>();
     EntityLock = new object();
     LastUpdate = DateTime.MinValue;
 }
Esempio n. 3
0
 internal ReadOnlyWorld()
 {
     World = new World("default");
     Level = new Level();
     Level.AddWorld(World);
     UnloadChunks = true;
 }
Esempio n. 4
0
        private void ItemUsedOnBlock(World world, Coordinates3D coordinates, BlockFace face, Coordinates3D cursor, ItemInfo item)
        {
            var info = world.GetBlockInfo(coordinates);
            if (Block.GetIsSolidOnFace(info, face) == false)
                return;
            
            coordinates += MathHelper.BlockFaceToCoordinates(face);

            switch (face)
            {
                case BlockFace.NegativeZ:
                    world.SetBlockId(coordinates, item.ItemId);
                    world.SetMetadata(coordinates, (byte)Orientation.FacingNorth);
                    break;
                case BlockFace.PositiveZ:
                    world.SetBlockId(coordinates, item.ItemId);
                    world.SetMetadata(coordinates, (byte)Orientation.FacingSouth);
                    break;
                case BlockFace.NegativeX:
                    world.SetBlockId(coordinates, item.ItemId);
                    world.SetMetadata(coordinates, (byte)Orientation.FacingWest);
                    break;
                case BlockFace.PositiveX:
                    world.SetBlockId(coordinates, item.ItemId);
                    world.SetMetadata(coordinates, (byte)Orientation.FacingEast);
                    break;
                default:
                    // Ladders can't be placed lying flat.
                    break;
            }
        }
Esempio n. 5
0
 public static World LoadWorld(string baseDirectory)
 {
     if (!Directory.Exists(baseDirectory))
         throw new DirectoryNotFoundException();
     var world = new World(Path.GetFileName(baseDirectory));
     world.BaseDirectory = baseDirectory;
     return world;
 }
Esempio n. 6
0
 public static void DefaultBlockMinedHandler(BlockDescriptor block, World world, Coordinates3D destroyedBlock, ItemDescriptor? tool)
 {
     var drops = Block.GetBlockDrop(block, world, destroyedBlock);
     world.SetBlockId(destroyedBlock, 0);
     world.SetMetadata(destroyedBlock, 0);
     foreach (var drop in drops)
         world.OnSpawnEntityRequested(new ItemEntity((Vector3)destroyedBlock + new Vector3(0.5), drop));
 }
Esempio n. 7
0
 public PhysicsEngine(World world, IBlockPhysicsProvider physicsProvider, int MillisecondsBetweenUpdates)
 {
     World = world;
     Entities = new List<IPhysicsEntity>();
     EntityLock = new object();
     LastUpdate = DateTime.MinValue;
     BlockPhysicsProvider = physicsProvider;
     this.MillisecondsBetweenUpdates = MillisecondsBetweenUpdates;
 }
Esempio n. 8
0
 /// <summary>
 /// Creates a region from the given region file.
 /// </summary>
 public Region(Coordinates2D position, World world, string file) : this(position, world)
 {
     if (File.Exists(file))
         regionFile = File.Open(file, FileMode.OpenOrCreate);
     else
     {
         regionFile = File.Open(file, FileMode.OpenOrCreate);
         CreateRegionHeader();
     }
 }
Esempio n. 9
0
 public void SpawnEntity(World world, Entity entity)
 {
     entity.EntityId = NextEntityId++;
     entity.World = world;
     if (entity is IDiskEntity) // Assign chunk
     {
         var chunk = GetEntityChunk(entity.World, entity.Position);
         chunk.Entities.Add((IDiskEntity)entity);
         chunk.IsModified = true;
     }
     entity.PropertyChanged -= EntityPropertyChanged;
     entity.PropertyChanged += EntityPropertyChanged;
     Entities.Add(entity);
     SpawnOnClients(entity);
     entity.Despawn -= EntityDespawn;
     entity.Despawn += EntityDespawn;
     if (entity is IPhysicsEntity)
     {
         // Add to physics engine
         var engine = Server.GetPhysicsForWorld(world);
         engine.AddEntity((IPhysicsEntity)entity);
     }
 }
Esempio n. 10
0
 protected internal PhysicsEngine GetPhysicsForWorld(World world)
 {
     return PhysicsEngines.FirstOrDefault(p => p.World == world);
 }
Esempio n. 11
0
 public void MoveClientToWorld(RemoteClient client, World world, Vector3? spawnPoint = null)
 {
     if (client.World == world)
         return;
     lock (client.LoadedChunks)
         client.PauseChunkUpdates = true;
     EntityManager.Despawn(client.Entity);
     while (client.KnownEntities.Any())
         client.ForgetEntity(EntityManager.GetEntityById(client.KnownEntities[0]));
     EntityManager.Update();
     EntityManager.SpawnEntity(world, client.Entity);
     client.UnloadAllChunks();
     // TODO: Allow player to save their positions in each world
     if (spawnPoint == null)
         client.Entity.Position = world.WorldGenerator.SpawnPoint;
     else
         client.Entity.Position = spawnPoint.Value;
     client.UpdateChunks(true);
     client.SendPacket(new PlayerPositionAndLookPacket(client.Entity.Position.X, client.Entity.Position.Y + 0.1 + PlayerEntity.Height,
         client.Entity.Position.Z, client.Entity.Position.Y + 0.1, client.Entity.Yaw, client.Entity.Pitch, false));
     EntityManager.SendClientEntities(client);
     lock (client.LoadedChunks)
         client.PauseChunkUpdates = false;
 }
Esempio n. 12
0
 public RemoteClient[] GetClientsInWorld(World world)
 {
     return Clients.Where(c => c.IsLoggedIn && c.World == world).ToArray();
 }
Esempio n. 13
0
 /// <summary>
 /// Creates a new Region for server-side use at the given position using
 /// the provided terrain generator.
 /// </summary>
 public Region(Coordinates2D position, World world)
 {
     Chunks = new Dictionary<Coordinates2D, Chunk>();
     Position = position;
     World = world;
 }
Esempio n. 14
0
 /// <summary>
 /// Creates and adds a world to this level, with the given name.
 /// </summary>
 public void AddWorld(string name, IWorldGenerator worldGenerator = null)
 {
     if (Worlds.Any(w => w.Name.ToUpper() == name.ToUpper()))
         throw new InvalidOperationException("A world with the same name already exists in this level.");
     var world = new World(name);
     if (worldGenerator == null)
         world.WorldGenerator = WorldGenerator;
     else
         world.WorldGenerator = worldGenerator;
     Worlds.Add(world);
 }
Esempio n. 15
0
 internal static SupportDirection DefaultGetSupportDirectionHandler(BlockDescriptor block, World world, Coordinates3D coordinates)
 {
     return SupportDirection.None;
 }
Esempio n. 16
0
 internal static void DefaultBlockPlacedHandler(BlockDescriptor block, World world, Coordinates3D clickedBlock, Coordinates3D clickedSide, Coordinates3D cursorPosition)
 {
     if (world.GetBlockId(clickedBlock + clickedSide) == 0) // TODO: There are more situations than just air when a block can be overwritten
     {
         world.SetBlockId(clickedBlock + clickedSide, block.Id);
         world.SetMetadata(clickedBlock + clickedSide, block.Metadata);
     }
 }
Esempio n. 17
0
        public static void DoBlockUpdates(World world, Coordinates3D coordinates)
        {
            OnBlockUpdate(world.GetBlock(coordinates), world, coordinates);

            if ((coordinates + Coordinates3D.Up).Y < Chunk.Height)
                OnBlockUpdate(world.GetBlock(coordinates + Coordinates3D.Up), world, coordinates + Coordinates3D.Up);
            if ((coordinates + Coordinates3D.Down).Y >= 0)
                OnBlockUpdate(world.GetBlock(coordinates + Coordinates3D.Down), world, coordinates + Coordinates3D.Down);

            OnBlockUpdate(world.GetBlock(coordinates + Coordinates3D.North), world, coordinates + Coordinates3D.North);
            OnBlockUpdate(world.GetBlock(coordinates + Coordinates3D.South), world, coordinates + Coordinates3D.South);
            OnBlockUpdate(world.GetBlock(coordinates + Coordinates3D.East), world, coordinates + Coordinates3D.East);
            OnBlockUpdate(world.GetBlock(coordinates + Coordinates3D.West), world, coordinates + Coordinates3D.West);
        }
Esempio n. 18
0
 public static void OnItemUsedOnBlock(ItemDescriptor item, World world, Coordinates3D clickedBlock, Coordinates3D clickedSide, Coordinates3D cursorPosition)
 {
     GetLogicDescriptor(item).ItemUsedOnBlock(item, world, clickedBlock, clickedSide, cursorPosition);
 }
Esempio n. 19
0
 internal static void DefaultItemUsedOnBlockHandler(ItemDescriptor item, World world, Coordinates3D clickedBlock, Coordinates3D clickedSide, Coordinates3D cursorPosition)
 {
 }
Esempio n. 20
0
 public static void OnItemUsedOnBlock(ItemDescriptor item, World world, Coordinates3D clickedBlock, Coordinates3D clickedSide, Coordinates3D cursorPosition)
 {
     if (world.GetBlockId(clickedBlock + clickedSide) == 0)
         world.SetBlockId(clickedBlock + clickedSide, CakeBlock.BlockId);
 }
Esempio n. 21
0
 public static ItemStack[] DefaultGetDropHandler(BlockDescriptor block, World world, Coordinates3D minedBlock)
 {
     return new[] { new ItemStack(block.Id, 1, block.Metadata) };
 }
Esempio n. 22
0
 internal static void DefaultBlockUpdateHandler(BlockDescriptor block, World world, Coordinates3D updatedBlock)
 {
     var logic = GetLogicDescriptor(block);
     var support = logic.GetSupportDirection(block, world, updatedBlock);
     var supportingBlock = updatedBlock;
     switch (support)
     {
         case SupportDirection.Down:
             supportingBlock = updatedBlock + Coordinates3D.Down;
             break;
         case SupportDirection.Up:
             supportingBlock = updatedBlock + Coordinates3D.Up;
             break;
         case SupportDirection.East:
             supportingBlock = updatedBlock + Coordinates3D.East;
             break;
         case SupportDirection.West:
             supportingBlock = updatedBlock + Coordinates3D.West;
             break;
         case SupportDirection.North:
             supportingBlock = updatedBlock + Coordinates3D.North;
             break;
         case SupportDirection.South:
             supportingBlock = updatedBlock + Coordinates3D.South;
             break;
         default:
             return;
     }
     if (!World.IsValidPosition(supportingBlock))
         return;
     if (world.GetBlockId(supportingBlock) == 0) // TODO: Air isn't the only thing that can't support some blocks
         OnBlockMined(block, world, updatedBlock, null); // TODO: Consider using a seperate delegate for blocks destroyed through non-player actions
 }
Esempio n. 23
0
 /// <summary>
 /// Adds a world to this level.
 /// </summary>
 public void AddWorld(World world)
 {
     if (Worlds.Any(w => w.Name.ToUpper() == world.Name.ToUpper()))
         throw new InvalidOperationException("A world with the same name already exists in this level.");
     Worlds.Add(world);
 }
Esempio n. 24
0
 internal static bool DefaultBlockRightClickedHandler(BlockDescriptor block, World world, Coordinates3D clickedBlock, Coordinates3D clickedSide, Coordinates3D cursorPosition)
 {
     return true;
 }
Esempio n. 25
0
 public static ItemStack[] GetBlockDrop (BlockDescriptor block, World world, Coordinates3D minedBlock)
 {
     if (!BlockLogicDescriptors.ContainsKey(block.Id))
         throw new KeyNotFoundException("The given block does not exist.");
     return BlockLogicDescriptors[block.Id].GetDrop(block, world, minedBlock);
 }
Esempio n. 26
0
 internal static void DefaultBlockMinedHandler(BlockDescriptor block, World world, Coordinates3D destroyedBlock, ItemDescriptor? tool)
 {
     if (GlobalDefaultBlockMinedHandler == null)
     {
         world.SetBlockId(destroyedBlock, 0);
         world.SetMetadata(destroyedBlock, 0);
     }
     else
         GlobalDefaultBlockMinedHandler(block, world, destroyedBlock, tool);
 }
Esempio n. 27
0
        /// <summary>
        /// Performs terrain collision tests and adjusts the Y-axis velocity accordingly
        /// </summary>
        /// <returns>True if the entity collides with the terrain</returns>
        private bool AdjustVelocityY(IAABBEntity entity, World world, out Vector3 collision, out Vector3 collisionDirection)
        {
            collision = Vector3.Zero;
            collisionDirection = Vector3.Zero;
            if (entity.Velocity.Y == 0)
                return false;
            // Do some enviornment guessing to improve speed
            int minX = (int)entity.Position.X - (entity.Position.X < 0 ? 1 : 0);
            int maxX = (int)(entity.Position.X + entity.Size.Width) - (entity.Position.X < 0 ? 1 : 0);
            int minZ = (int)entity.Position.Z - (entity.Position.Z < 0 ? 1 : 0);
            int maxZ = (int)(entity.Position.Z + entity.Size.Depth) - (entity.Position.Z < 0 ? 1 : 0);
            int minY, maxY;

            // Expand bounding box to include area to be tested
            if (entity.Velocity.Y < 0)
            {
                TempBoundingBox = new BoundingBox(
                    new Vector3(entity.BoundingBox.Min.X, entity.BoundingBox.Min.Y + entity.Velocity.Y, entity.BoundingBox.Min.Z) - (entity.Size / 2),
                    new Vector3(entity.BoundingBox.Max.X, entity.BoundingBox.Max.Y, entity.BoundingBox.Max.Z) - (entity.Size / 2)
                );

                maxY = (int)(TempBoundingBox.Max.Y);
                minY = (int)(TempBoundingBox.Min.Y + entity.Velocity.Y);
            }
            else
            {
                TempBoundingBox = new BoundingBox(
                    entity.BoundingBox.Min - (entity.Size / 2),
                    new Vector3(
                    entity.BoundingBox.Max.X, entity.BoundingBox.Max.Y + entity.Velocity.Y, entity.BoundingBox.Max.Z) - (entity.Size / 2)
                );
                minY = (int)(entity.BoundingBox.Min.Y);
                maxY = (int)(entity.BoundingBox.Max.Y + entity.Velocity.Y);
            }

            // Clamp Y into map boundaries
            if (minY < 0)
                minY = 0;
            if (minY >= World.Height)
                minY = World.Height - 1;
            if (maxY < 0)
                maxY = 0;
            if (maxY >= World.Height)
                maxY = World.Height - 1;

            // Do terrain checks
            double? collisionPoint = null;
            BoundingBox blockBox;
            for (int x = minX; x <= maxX; x++)
            {
                for (int y = minY; y <= maxY; y++)
                {
                    for (int z = minZ; z <= maxZ; z++)
                    {
                        var position = new Vector3(x, y, z);
                        var boundingBox = BlockPhysicsProvider.GetBoundingBox(world, (Coordinates3D)position);
                        if (boundingBox == null)
                            continue;
                        blockBox = boundingBox.Value.OffsetBy(position);
                        if (TempBoundingBox.Intersects(blockBox))
                        {
                            if (entity.Velocity.Y < 0)
                            {
                                if (!collisionPoint.HasValue)
                                    collisionPoint = blockBox.Max.Y;
                                else if (collisionPoint.Value < blockBox.Max.Y)
                                    collisionPoint = blockBox.Max.Y;
                            }
                            else
                            {
                                if (!collisionPoint.HasValue)
                                    collisionPoint = blockBox.Min.Y;
                                else if (collisionPoint.Value > blockBox.Min.Y)
                                    collisionPoint = blockBox.Min.Y;
                            }
                            collision = position;
                        }
                    }
                }
            }

            if (collisionPoint != null)
            {
                if (entity.Velocity.Y < 0)
                {
                    // TODO: Do block event
                    //var block = world.GetBlock(collision);
                    //block.OnBlockWalkedOn(world, collision, this);
                    entity.Velocity = new Vector3(entity.Velocity.X,
                        entity.Velocity.Y + (collisionPoint.Value - TempBoundingBox.Min.Y),
                        entity.Velocity.Z);
                    collisionDirection = Vector3.Down;
                }
                else if (entity.Velocity.Y > 0)
                {
                    entity.Velocity = new Vector3(entity.Velocity.X,
                        entity.Velocity.Y - (TempBoundingBox.Max.Y - collisionPoint.Value),
                        entity.Velocity.Z);
                    collisionDirection = Vector3.Up;
                }
                return true;
            }

            return false;
        }
Esempio n. 28
0
 private Chunk GetEntityChunk(World world, Vector3 position)
 {
     return world.FindChunk(position);
 }
Esempio n. 29
0
        // TODO: There's a lot of code replication here, perhaps it can be consolidated
        /// <summary>
        /// Performs terrain collision tests and adjusts the X-axis velocity accordingly
        /// </summary>
        /// <returns>True if the entity collides with the terrain</returns>
        private bool AdjustVelocityX(IAABBEntity entity, World world, out Vector3 collision, out Vector3 collisionDirection)
        {
            collision = Vector3.Zero;
            collisionDirection = Vector3.Zero;
            if (entity.Velocity.X == 0)
                return false;
            // Do some enviornment guessing to improve speed
            int minY = (int)entity.Position.Y - (entity.Position.Y < 0 ? 1 : 0);
            int maxY = (int)(entity.Position.Y + entity.Size.Width) - (entity.Position.Y < 0 ? 1 : 0);
            int minZ = (int)entity.Position.Z - (entity.Position.Z < 0 ? 1 : 0);
            int maxZ = (int)(entity.Position.Z + entity.Size.Depth) - (entity.Position.Z < 0 ? 1 : 0);
            int minX, maxX;

            // Expand bounding box to include area to be tested
            if (entity.Velocity.X < 0)
            {
                TempBoundingBox = new BoundingBox(
                    new Vector3(entity.BoundingBox.Min.X + entity.Velocity.X, entity.BoundingBox.Min.Y, entity.BoundingBox.Min.Z) - (entity.Size / 2),
                    new Vector3(entity.BoundingBox.Max.X, entity.BoundingBox.Max.Y, entity.BoundingBox.Max.Z) - (entity.Size / 2)
                );

                maxX = (int)(TempBoundingBox.Max.X);
                minX = (int)(TempBoundingBox.Min.X + entity.Velocity.X);
            }
            else
            {
                TempBoundingBox = new BoundingBox(
                    entity.BoundingBox.Min - (entity.Size / 2),
                    new Vector3(
                    entity.BoundingBox.Max.X + entity.Velocity.X, entity.BoundingBox.Max.Y, entity.BoundingBox.Max.Z) - (entity.Size / 2)
                );
                minX = (int)(entity.BoundingBox.Min.X);
                maxX = (int)(entity.BoundingBox.Max.X + entity.Velocity.X);
            }

            // Do terrain checks
            double? collisionPoint = null;
            BoundingBox blockBox;
            for (int x = minX; x <= maxX; x++)
            {
                for (int y = minY; y <= maxY; y++)
                {
                    for (int z = minZ; z <= maxZ; z++)
                    {
                        var position = new Vector3(x, y, z);
                        var boundingBox = BlockPhysicsProvider.GetBoundingBox(world, (Coordinates3D)position);
                        if (boundingBox == null)
                            continue;
                        blockBox = boundingBox.Value.OffsetBy(position);
                        if (TempBoundingBox.Intersects(blockBox))
                        {
                            if (entity.Velocity.X < 0)
                            {
                                if (!collisionPoint.HasValue)
                                    collisionPoint = blockBox.Max.X;
                                else if (collisionPoint.Value < blockBox.Max.X)
                                    collisionPoint = blockBox.Max.X;
                            }
                            else
                            {
                                if (!collisionPoint.HasValue)
                                    collisionPoint = blockBox.Min.X;
                                else if (collisionPoint.Value > blockBox.Min.X)
                                    collisionPoint = blockBox.Min.X;
                            }
                            collision = position;
                        }
                    }
                }
            }

            if (collisionPoint != null)
            {
                if (entity.Velocity.X < 0)
                {
                    entity.Velocity = new Vector3(
                        entity.Velocity.X - (TempBoundingBox.Min.X - collisionPoint.Value),
                        entity.Velocity.Y,
                        entity.Velocity.Z);
                    collisionDirection = Vector3.Left;
                }
                else if (entity.Velocity.X > 0)
                {
                    entity.Velocity = new Vector3(
                        entity.Velocity.X - (TempBoundingBox.Max.X - collisionPoint.Value),
                        entity.Velocity.Y,
                        entity.Velocity.Z);
                    collisionDirection = Vector3.Right;
                }
                return true;
            }

            return false;
        }
Esempio n. 30
0
 public static void OnBlockUpdate(BlockDescriptor block, World world, Coordinates3D updatedBlock)
 {
     if (!BlockLogicDescriptors.ContainsKey(block.Id))
         throw new KeyNotFoundException("The given block does not exist.");
     BlockLogicDescriptors[block.Id].BlockUpdated(block, world, updatedBlock);
 }