예제 #1
0
        public void DestroyCactus(BlockDescriptor descriptor, IMultiplayerServer server, IWorld world)
        {
            var toDrop = 0;

            // Search upwards
            for (int y = descriptor.Coordinates.Y; y < 127; y++)
            {
                var coordinates = new Coordinates3D(descriptor.Coordinates.X, y, descriptor.Coordinates.Z);
                if (world.GetBlockID(coordinates) == CactusBlock.BlockID)
                {
                    world.SetBlockID(coordinates, AirBlock.BlockID);
                    toDrop++;
                }
            }

            // Search downwards.
            for (int y = descriptor.Coordinates.Y - 1; y > 0; y--)
            {
                var coordinates = new Coordinates3D(descriptor.Coordinates.X, y, descriptor.Coordinates.Z);
                if (world.GetBlockID(coordinates) == CactusBlock.BlockID)
                {
                    world.SetBlockID(coordinates, AirBlock.BlockID);
                    toDrop++;
                }
            }

            var manager = server.GetEntityManagerForWorld(world);

            manager.SpawnEntity(
                new ItemEntity(descriptor.Coordinates + Coordinates3D.Up,
                               new ItemStack(CactusBlock.BlockID, (sbyte)toDrop)));
        }
예제 #2
0
        public void DoSpread(IMultiplayerServer server, IWorld world, BlockDescriptor descriptor)
        {
            foreach (var coord in SpreadableBlocks)
            {
                var check = descriptor.Coordinates + coord;
                if (world.GetBlockID(check) == AirBlock.BlockID)
                {
                    // Check if this is adjacent to a flammable block
                    foreach (var adj in AdjacentBlocks)
                    {
                        var provider = BlockRepository.GetBlockProvider(
                            world.GetBlockID(check + adj));
                        if (provider.Flammable)
                        {
                            if (provider.Hardness == 0)
                            {
                                check = check + adj;
                            }

                            // Spread to this block
                            world.SetBlockID(check, FireBlock.BlockID);
                            ScheduleUpdate(server, world, world.GetBlockData(check));
                            break;
                        }
                    }
                }
            }
        }
예제 #3
0
        public void DestroyCactus(BlockDescriptor descriptor, IMultiplayerServer server, IWorld world)
        {
            var toDrop = 0;

            // Search upwards
            for (int y = descriptor.Coordinates.Y; y < 127; y++)
            {
                var coordinates = new Coordinates3D(descriptor.Coordinates.X, y, descriptor.Coordinates.Z);
                if (world.GetBlockID(coordinates) == CactusBlock.BlockID)
                {
                    world.SetBlockID(coordinates, AirBlock.BlockID);
                    toDrop++;
                }
            }

            // Search downwards.
            for (int y = descriptor.Coordinates.Y - 1; y > 0; y--)
            {
                var coordinates = new Coordinates3D(descriptor.Coordinates.X, y, descriptor.Coordinates.Z);
                if (world.GetBlockID(coordinates) == CactusBlock.BlockID)
                {
                    world.SetBlockID(coordinates, AirBlock.BlockID);
                    toDrop++;
                }
            }

            var manager = server.GetEntityManagerForWorld(world);
            manager.SpawnEntity(
                new ItemEntity(descriptor.Coordinates + Coordinates3D.Up,
                    new ItemStack(CactusBlock.BlockID, (sbyte)toDrop)));
        }
예제 #4
0
        public void DoSpread(IMultiplayerServer server, IWorld world, BlockDescriptor descriptor)
        {
            foreach (var coord in SpreadableBlocks)
            {
                var check = descriptor.Coordinates + coord;
                if (world.GetBlockID(check) == AirBlock.BlockID)
                {
                    // Check if this is adjacent to a flammable block
                    foreach (var adj in AdjacentBlocks)
                    {
                        var provider = BlockRepository.GetBlockProvider(
                           world.GetBlockID(check + adj));
                        if (provider.Flammable)
                        {
                            if (provider.Hardness == 0)
                                check = check + adj;

                            // Spread to this block
                            world.SetBlockID(check, FireBlock.BlockID);
                            ScheduleUpdate(server, world, world.GetBlockData(check));
                            break;
                        }
                    }
                }
            }
        }
예제 #5
0
        public void GenerateDropEntity(BlockDescriptor descriptor, IWorld world, IMultiplayerServer server, ItemStack item)
        {
            var entityManager = server.GetEntityManagerForWorld(world);
            var items         = new ItemStack[0];
            var type          = ToolType.None;
            var material      = ToolMaterial.None;
            var held          = ItemRepository.GetItemProvider(item.ID);

            if (held is ToolItem)
            {
                var tool = held as ToolItem;
                material = tool.Material;
                type     = tool.ToolType;
            }

            if ((EffectiveTools & type) > 0)
            {
                if ((EffectiveToolMaterials & material) > 0)
                {
                    items = GetDrop(descriptor, item);
                }
            }

            foreach (var i in items)
            {
                if (i.Empty)
                {
                    continue;
                }
                var entity = new ItemEntity(new Vector3(descriptor.Coordinates) + new Vector3(0.5), i);
                entityManager.SpawnEntity(entity);
            }
        }
예제 #6
0
 private void TryGrowth(IMultiplayerServer server, Coordinates3D coords, IWorld world)
 {
     if (world.GetBlockID(coords) != BlockID)
         return;
     // Find current height of stalk
     int height = 0;
     for (int y = -MaxGrowHeight; y <= MaxGrowHeight; y++)
     {
         if (world.GetBlockID(coords + (Coordinates3D.Down * y)) == BlockID)
             height++;
     }
     if (height < MaxGrowHeight)
     {
         var meta = world.GetMetadata(coords);
         meta++;
         world.SetMetadata(coords, meta);
         var chunk = world.FindChunk(coords);
         if (meta == 15)
         {
             if (world.GetBlockID(coords + Coordinates3D.Up) == 0)
             {
                 world.SetBlockID(coords + Coordinates3D.Up, BlockID);
                 server.Scheduler.ScheduleEvent("cactus", chunk,
                     TimeSpan.FromSeconds(MathHelper.Random.Next(MinGrowthSeconds, MaxGrowthSeconds)),
                     (_server) => TryGrowth(_server, coords + Coordinates3D.Up, world));
             }
         }
         else
         {
             server.Scheduler.ScheduleEvent("cactus", chunk,
                 TimeSpan.FromSeconds(MathHelper.Random.Next(MinGrowthSeconds, MaxGrowthSeconds)),
                 (_server) => TryGrowth(_server, coords, world));
         }
     }
 }
예제 #7
0
 public override void BlockLoadedFromChunk(Coordinates3D coords, IMultiplayerServer server, IWorld world)
 {
     var chunk = world.FindChunk(coords);
     server.Scheduler.ScheduleEvent("crops", chunk,
         TimeSpan.FromSeconds(MathHelper.Random.Next(30, 60)),
         (s) => GrowBlock(s, world, coords));
 }
예제 #8
0
 void HydrationCheckEvent(IMultiplayerServer server, Coordinates3D coords, IWorld world)
 {
     if (world.GetBlockID(coords) != BlockID)
         return;
     if (MathHelper.Random.Next(3) == 0)
     {
         var meta = world.GetMetadata(coords);
         if (IsHydrated(coords, world) && meta != 15)
             meta++;
         else
         {
             meta--;
             if (meta == 0)
             {
                 world.SetBlockID(coords, BlockID);
                 return;
             }
         }
         world.SetMetadata(coords, meta);
     }
     var chunk = world.FindChunk(coords);
     server.Scheduler.ScheduleEvent("farmland", chunk,
         TimeSpan.FromSeconds(UpdateIntervalSeconds),
         _server => HydrationCheckEvent(_server, coords, world));
 }
예제 #9
0
        void HydrationCheckEvent(IMultiplayerServer server, Coordinates3D coords, IWorld world)
        {
            if (world.GetBlockID(coords) != BlockID)
            {
                return;
            }
            if (MathHelper.Random.Next(3) == 0)
            {
                var meta = world.GetMetadata(coords);
                if (IsHydrated(coords, world) && meta != 15)
                {
                    meta++;
                }
                else
                {
                    meta--;
                    if (meta == 0)
                    {
                        world.SetBlockID(coords, BlockID);
                        return;
                    }
                }
                world.SetMetadata(coords, meta);
            }
            var chunk = world.FindChunk(coords);

            server.Scheduler.ScheduleEvent("farmland", chunk,
                                           TimeSpan.FromSeconds(UpdateIntervalSeconds),
                                           _server => HydrationCheckEvent(_server, coords, world));
        }
예제 #10
0
        public static void HandleLoginRequestPacket(IPacket packet, IRemoteClient client, IMultiplayerServer server)
        {
            var loginRequestPacket = (LoginRequestPacket)packet;
            var remoteClient = (RemoteClient)client;
            if (loginRequestPacket.ProtocolVersion < server.PacketReader.ProtocolVersion)
                remoteClient.QueuePacket(new DisconnectPacket("Client outdated! Use beta 1.7.3."));
            else if (loginRequestPacket.ProtocolVersion > server.PacketReader.ProtocolVersion)
                remoteClient.QueuePacket(new DisconnectPacket("Server outdated! Use beta 1.7.3."));
            else if (server.Worlds.Count == 0)
                remoteClient.QueuePacket(new DisconnectPacket("Server has no worlds configured."));
            else if (!server.PlayerIsWhitelisted(remoteClient.Username) && server.PlayerIsBlacklisted(remoteClient.Username))
                remoteClient.QueuePacket(new DisconnectPacket("You're banned from this server"));
            else if (server.Clients.Count(c => c.Username == client.Username) > 1)
                remoteClient.QueuePacket(new DisconnectPacket("The player with this username is already logged in"));
            else
            {
                remoteClient.LoggedIn = true;
                remoteClient.Entity = new PlayerEntity(remoteClient.Username);
                remoteClient.World = server.Worlds[0];
                remoteClient.ChunkRadius = 2;

                if (!remoteClient.Load())
                    remoteClient.Entity.Position = remoteClient.World.SpawnPoint;
                // Make sure they don't spawn in the ground
                var collision = new Func<bool>(() =>
                {
                    var feet = client.World.GetBlockID((Coordinates3D)client.Entity.Position);
                    var head = client.World.GetBlockID((Coordinates3D)(client.Entity.Position + Vector3.Up));
                    var feetBox = server.BlockRepository.GetBlockProvider(feet).BoundingBox;
                    var headBox = server.BlockRepository.GetBlockProvider(head).BoundingBox;
                    return feetBox != null || headBox != null;
                });
                while (collision())
                    client.Entity.Position += Vector3.Up;

                // Send setup packets
                remoteClient.QueuePacket(new LoginResponsePacket(0, 0, Dimension.Overworld));
                remoteClient.UpdateChunks();
                remoteClient.QueuePacket(new WindowItemsPacket(0, remoteClient.Inventory.GetSlots()));
                remoteClient.QueuePacket(new SpawnPositionPacket((int)remoteClient.Entity.Position.X,
                        (int)remoteClient.Entity.Position.Y, (int)remoteClient.Entity.Position.Z));
                remoteClient.QueuePacket(new SetPlayerPositionPacket(remoteClient.Entity.Position.X,
                        remoteClient.Entity.Position.Y + 1,
                        remoteClient.Entity.Position.Y + remoteClient.Entity.Size.Height + 1,
                        remoteClient.Entity.Position.Z, remoteClient.Entity.Yaw, remoteClient.Entity.Pitch, true));
                remoteClient.QueuePacket(new TimeUpdatePacket(remoteClient.World.Time));

                // Start housekeeping for this client
                var entityManager = server.GetEntityManagerForWorld(remoteClient.World);
                entityManager.SpawnEntity(remoteClient.Entity);
                entityManager.SendEntitiesToClient(remoteClient);
                server.Scheduler.ScheduleEvent("remote.keepalive", remoteClient, TimeSpan.FromSeconds(10), remoteClient.SendKeepAlive);
                server.Scheduler.ScheduleEvent("remote.chunks", remoteClient, TimeSpan.FromSeconds(1), remoteClient.ExpandChunkRadius);

                if (!string.IsNullOrEmpty(Program.ServerConfiguration.MOTD))
                    remoteClient.SendMessage(Program.ServerConfiguration.MOTD);
                if (!Program.ServerConfiguration.Singleplayer)
                    server.SendMessage(ChatColor.Yellow + "{0} joined the server.", remoteClient.Username);
            }
        }
예제 #11
0
        public void GenerateDropEntity(BlockDescriptor descriptor, IWorld world, IMultiplayerServer server, ItemStack item)
        {
            var entityManager = server.GetEntityManagerForWorld(world);
            var items = new ItemStack[0];
            var type = ToolType.None;
            var material = ToolMaterial.None;
            var held = ItemRepository.GetItemProvider(item.ID);

            if (held is ToolItem)
            {
                var tool = held as ToolItem;
                material = tool.Material;
                type = tool.ToolType;
            }

            if ((EffectiveTools & type) > 0)
            {
                if ((EffectiveToolMaterials & material) > 0)
                    items = GetDrop(descriptor, item);
            }

            foreach (var i in items)
            {
                if (i.Empty) continue;
                var entity = new ItemEntity(new Vector3(descriptor.Coordinates) + new Vector3(0.5), i);
                entityManager.SpawnEntity(entity);
            }
        }
예제 #12
0
        public override void BlockLoadedFromChunk(Coordinates3D coords, IMultiplayerServer server, IWorld world)
        {
            var chunk = world.FindChunk(coords);

            server.Scheduler.ScheduleEvent(chunk, DateTime.UtcNow.AddSeconds(MathHelper.Random.Next(30, 60)),
                                           (s) => GrowBlock(s, world, coords));
        }
예제 #13
0
 public override void BlockLoadedFromChunk(Coordinates3D coords, IMultiplayerServer server, IWorld world)
 {
     var chunk = world.FindChunk(coords);
     server.Scheduler.ScheduleEvent("cactus", chunk,
         TimeSpan.FromSeconds(MathHelper.Random.Next(MinGrowthSeconds, MaxGrowthSeconds)),
         s => TryGrowth(s, coords, world));
 }
예제 #14
0
 public override void BlockLoadedFromChunk(Coordinates3D coords, IMultiplayerServer server, IWorld world)
 {
     var chunk = world.FindChunk(coords);
     server.Scheduler.ScheduleEvent(chunk,
         DateTime.UtcNow.AddSeconds(MathHelper.Random.Next(MinGrowthTime, MaxGrowthTime)),
         s => TrySpread(coords, world, server));
 }
예제 #15
0
 public override void BlockLoadedFromChunk(Coordinates3D coords, IMultiplayerServer server, IWorld world)
 {
     var chunk = world.FindChunk(coords);
     server.Scheduler.ScheduleEvent("farmland", chunk,
         TimeSpan.FromSeconds(UpdateIntervalSeconds),
         s => HydrationCheckEvent(s, coords, world));
 }
예제 #16
0
 void HydrationCheckEvent(IMultiplayerServer server, Coordinates3D coords, IWorld world)
 {
     if (world.GetBlockID(coords) != BlockID)
     {
         return;
     }
     if (MathHelper.Random.Next(3) == 0)
     {
         var meta = world.GetMetadata(coords);
         if (IsHydrated(coords, world) && meta != 15)
         {
             meta++;
         }
         else
         {
             meta--;
             if (meta == 0)
             {
                 world.SetBlockID(coords, BlockID);
                 return;
             }
         }
         world.SetMetadata(coords, meta);
     }
     server.Scheduler.ScheduleEvent(DateTime.Now.AddSeconds(UpdateIntervalSeconds), (_server) => HydrationCheckEvent(_server, coords, world));
 }
예제 #17
0
 public static void HandleHandshakePacket(IPacket packet, IRemoteClient client, IMultiplayerServer server)
 {
     var handshakePacket = (HandshakePacket) packet;
     var remoteClient = (RemoteClient)client;
     remoteClient.Username = handshakePacket.Username;
     remoteClient.QueuePacket(new HandshakeResponsePacket("-")); // TODO: Implement some form of authentication
 }
예제 #18
0
 public override void BlockUpdate(BlockDescriptor descriptor, BlockDescriptor source, IMultiplayerServer server, IWorld world)
 {
     bool upper = ((DoorItem.DoorFlags)descriptor.Metadata & DoorItem.DoorFlags.Upper) == DoorItem.DoorFlags.Upper;
     var other = upper ? Coordinates3D.Down : Coordinates3D.Up;
     if (world.GetBlockID(descriptor.Coordinates + other) != ID)
         world.SetBlockID(descriptor.Coordinates, 0);
 }
예제 #19
0
        private void TryGrowth(IMultiplayerServer server, Coordinates3D coords, IWorld world)
        {
            if (world.GetBlockID(coords) != BlockID)
            {
                return;
            }
            // Find current height of stalk
            int height = 0;

            for (int y = -3; y <= 3; y++)
            {
                if (world.GetBlockID(coords + (Coordinates3D.Down * y)) == BlockID)
                {
                    height++;
                }
            }
            if (height < 3)
            {
                var meta = world.GetMetadata(coords);
                meta++;
                world.SetMetadata(coords, meta);
                if (meta == 15)
                {
                    world.SetBlockID(coords + Coordinates3D.Up, BlockID);
                    server.Scheduler.ScheduleEvent(DateTime.Now.AddSeconds(MathHelper.Random.Next(MinGrowthSeconds, MaxGrowthSeconds)),
                                                   (_server) => TryGrowth(_server, coords + Coordinates3D.Up, world));
                }
                else
                {
                    server.Scheduler.ScheduleEvent(DateTime.Now.AddSeconds(MathHelper.Random.Next(MinGrowthSeconds, MaxGrowthSeconds)),
                                                   (_server) => TryGrowth(_server, coords, world));
                }
            }
        }
예제 #20
0
        public void ScheduleUpdate(IMultiplayerServer server, IWorld world, BlockDescriptor descriptor)
        {
            var chunk = world.FindChunk(descriptor.Coordinates);

            server.Scheduler.ScheduleEvent("fire.spread", chunk,
                                           TimeSpan.FromSeconds(MathHelper.Random.Next(MinSpreadTime, MaxSpreadTime)),
                                           s => DoUpdate(s, world, descriptor));
        }
예제 #21
0
        public override void BlockLoadedFromChunk(Coordinates3D coords, IMultiplayerServer server, IWorld world)
        {
            var chunk = world.FindChunk(coords);

            server.Scheduler.ScheduleEvent("grass", chunk,
                                           TimeSpan.FromSeconds(MathHelper.Random.Next(MinGrowthTime, MaxGrowthTime)),
                                           s => TrySpread(coords, world, server));
        }
예제 #22
0
 public override void BlockUpdate(BlockDescriptor descriptor, BlockDescriptor source, IMultiplayerServer server, IWorld world)
 {
     if (world.GetBlockID(descriptor.Coordinates + Coordinates3D.Down) != FarmlandBlock.BlockID)
     {
         GenerateDropEntity(descriptor, world, server);
         world.SetBlockID(descriptor.Coordinates, 0);
     }
 }
예제 #23
0
 public override void BlockUpdate(BlockDescriptor descriptor, BlockDescriptor source, IMultiplayerServer server, IWorld world)
 {
     if (world.GetBlockID(descriptor.Coordinates + Coordinates3D.Down) == AirBlock.BlockID)
     {
         world.SetBlockID(descriptor.Coordinates, AirBlock.BlockID);
         server.GetEntityManagerForWorld(world).SpawnEntity(new FallingGravelEntity(descriptor.Coordinates));
     }
 }
예제 #24
0
        public override void BlockLoadedFromChunk(Coordinates3D coords, IMultiplayerServer server, IWorld world)
        {
            var chunk = world.FindChunk(coords);

            server.Scheduler.ScheduleEvent("farmland", chunk,
                                           TimeSpan.FromSeconds(UpdateIntervalSeconds),
                                           s => HydrationCheckEvent(s, coords, world));
        }
예제 #25
0
 public EventScheduler(IMultiplayerServer server)
 {
     Events    = new List <ScheduledEvent>();
     Server    = server;
     Subjects  = new HashSet <IEventSubject>();
     Stopwatch = new Stopwatch();
     Stopwatch.Start();
 }
예제 #26
0
        public void ScheduleNextEvent(Coordinates3D coords, IWorld world, IMultiplayerServer server)
        {
            var chunk = world.FindChunk(coords);

            server.Scheduler.ScheduleEvent(chunk,
                                           DateTime.UtcNow.AddSeconds(SecondsBetweenUpdates), (_server) =>
                                           AutomataUpdate(_server, world, coords));
        }
예제 #27
0
 public EventScheduler(IMultiplayerServer server)
 {
     Events = new List<ScheduledEvent>();
     Server = server;
     Subjects = new HashSet<IEventSubject>();
     Stopwatch = new Stopwatch();
     Stopwatch.Start();
 }
예제 #28
0
 public void ScheduleNextEvent(Coordinates3D coords, IWorld world, IMultiplayerServer server)
 {
     if (world.GetBlockID(coords) == StillID)
         return;
     var chunk = world.FindChunk(coords);
     server.Scheduler.ScheduleEvent("fluid", chunk,
         TimeSpan.FromSeconds(SecondsBetweenUpdates), (_server) =>
         AutomataUpdate(_server, world, coords));
 }
예제 #29
0
 internal static void HandleChatMessage(IPacket _packet, IRemoteClient _client, IMultiplayerServer _server)
 {
     // TODO: Abstract this to support things like commands
     // TODO: Sanitize messages
     var packet = (ChatMessagePacket)_packet;
     var server = (MultiplayerServer)_server;
     var args = new ChatMessageEventArgs(_client, packet.Message);
     server.OnChatMessageReceived(args);
 }
예제 #30
0
 public static void HandleChangeHeldItem(IPacket _packet, IRemoteClient _client, IMultiplayerServer server)
 {
     var packet = (ChangeHeldItemPacket)_packet;
     var client = (RemoteClient)_client;
     client.SelectedSlot = (short)(packet.Slot + InventoryWindow.HotbarIndex);
     var notified = server.GetEntityManagerForWorld(client.World).ClientsForEntity(client.Entity);
     foreach (var c in notified)
         c.QueuePacket(new EntityEquipmentPacket(client.Entity.EntityID, 0, client.SelectedItem.ID, client.SelectedItem.Metadata));
 }
예제 #31
0
 public virtual bool IsSupported(BlockDescriptor descriptor, IMultiplayerServer server, IWorld world)
 {
     var support = GetSupportDirection(descriptor);
     if (support != Coordinates3D.Zero)
     {
         var supportingBlock = server.BlockRepository.GetBlockProvider(world.GetBlockID(descriptor.Coordinates + support));
         if (!supportingBlock.Opaque)
             return false;
     }
     return true;
 }
예제 #32
0
 public EntityManager(IMultiplayerServer server, IWorld world)
 {
     Server = server;
     World = world;
     PhysicsEngine = new PhysicsEngine(world, (BlockRepository)server.BlockRepository);
     PendingDespawns = new ConcurrentBag<IEntity>();
     Entities = new List<IEntity>();
     // TODO: Handle loading worlds that already have entities
     // Note: probably not the concern of EntityManager. The server could manually set this?
     NextEntityID = 1;
 }
예제 #33
0
 public EntityManager(IMultiplayerServer server, IWorld world)
 {
     Server          = server;
     World           = world;
     PhysicsEngine   = new PhysicsEngine(world, (BlockRepository)server.BlockRepository);
     PendingDespawns = new ConcurrentBag <IEntity>();
     Entities        = new List <IEntity>();
     // TODO: Handle loading worlds that already have entities
     // Note: probably not the concern of EntityManager. The server could manually set this?
     NextEntityID = 1;
 }
예제 #34
0
 static void SaveWorlds(IMultiplayerServer server)
 {
     Server.Log(LogCategory.Notice, "Saving world...");
     foreach (var w in Server.Worlds)
     {
         w.Save();
     }
     Server.Log(LogCategory.Notice, "Done.");
     server.Scheduler.ScheduleEvent("world.save", null,
                                    TimeSpan.FromSeconds(ServerConfiguration.WorldSaveInterval), SaveWorlds);
 }
예제 #35
0
        public void TrySpread(Coordinates3D coords, IWorld world, IMultiplayerServer server)
        {
            if (!world.IsValidPosition(coords + Coordinates3D.Up))
            {
                return;
            }
            var sky   = world.GetSkyLight(coords + Coordinates3D.Up);
            var block = world.GetBlockLight(coords + Coordinates3D.Up);

            if (sky < 9 && block < 9)
            {
                return;
            }
            for (int i = 0, j = MathHelper.Random.Next(GrowthCandidates.Length); i < GrowthCandidates.Length; i++, j++)
            {
                var candidate = GrowthCandidates[j % GrowthCandidates.Length] + coords;
                if (!world.IsValidPosition(candidate) || !world.IsValidPosition(candidate + Coordinates3D.Up))
                {
                    continue;
                }
                var id = world.GetBlockID(candidate);
                if (id == DirtBlock.BlockID)
                {
                    var _sky   = world.GetSkyLight(candidate + Coordinates3D.Up);
                    var _block = world.GetBlockLight(candidate + Coordinates3D.Up);
                    if (_sky < 4 && _block < 4)
                    {
                        continue;
                    }
                    IChunk chunk;
                    var    _candidate = world.FindBlockPosition(candidate, out chunk);
                    bool   grow       = true;
                    for (int y = candidate.Y; y < chunk.GetHeight((byte)_candidate.X, (byte)_candidate.Z); y++)
                    {
                        var b = world.GetBlockID(new Coordinates3D(candidate.X, y, candidate.Z));
                        var p = world.BlockRepository.GetBlockProvider(b);
                        if (p.LightOpacity >= 2)
                        {
                            grow = false;
                            break;
                        }
                    }
                    if (grow)
                    {
                        world.SetBlockID(candidate, GrassBlock.BlockID);
                        server.Scheduler.ScheduleEvent("grass", chunk,
                                                       TimeSpan.FromSeconds(MathHelper.Random.Next(MinGrowthTime, MaxGrowthTime)),
                                                       s => TrySpread(candidate, world, server));
                    }
                    break;
                }
            }
        }
예제 #36
0
 public EventScheduler(IMultiplayerServer server)
 {
     Events = new List <ScheduledEvent>();
     ImmediateEventQueue = new ConcurrentQueue <ScheduledEvent>();
     LaterEventQueue     = new ConcurrentQueue <ScheduledEvent>();
     DisposedSubjects    = new ConcurrentQueue <IEventSubject>();
     Server         = server;
     Subjects       = new HashSet <IEventSubject>();
     Stopwatch      = new Stopwatch();
     DisabledEvents = new HashSet <string>();
     Stopwatch.Start();
 }
예제 #37
0
        public void ScheduleNextEvent(Coordinates3D coords, IWorld world, IMultiplayerServer server)
        {
            if (world.GetBlockID(coords) == StillID)
            {
                return;
            }
            var chunk = world.FindChunk(coords);

            server.Scheduler.ScheduleEvent("fluid", chunk,
                                           TimeSpan.FromSeconds(SecondsBetweenUpdates), (_server) =>
                                           AutomataUpdate(_server, world, coords));
        }
예제 #38
0
        private void FlowOutward(IWorld world, LiquidFlow target, IMultiplayerServer server)
        {
            // For each block we can flow into, generate an item entity if appropriate
            var provider = world.BlockRepository.GetBlockProvider(world.GetBlockID(target.TargetBlock));

            provider.GenerateDropEntity(new BlockDescriptor {
                Coordinates = target.TargetBlock, ID = provider.ID
            }, world, server);
            // And overwrite the block with a new fluid block.
            world.SetBlockID(target.TargetBlock, FlowingID);
            world.SetMetadata(target.TargetBlock, target.Level);
            server.Scheduler.ScheduleEvent(DateTime.Now.AddSeconds(SecondsBetweenUpdates), s => AutomataUpdate(s, world, target.TargetBlock));
        }
예제 #39
0
 public override void BlockUpdate(BlockDescriptor descriptor, BlockDescriptor source, IMultiplayerServer server, IWorld world)
 {
     if (ID == StillID)
     {
         var outward = DetermineOutwardFlow(world, descriptor.Coordinates);
         var inward = DetermineInwardFlow(world, descriptor.Coordinates);
         if (outward.Length != 0 || inward != descriptor.Metadata)
         {
             world.SetBlockID(descriptor.Coordinates, FlowingID);
             ScheduleNextEvent(descriptor.Coordinates, world, server);
         }
     }
 }
예제 #40
0
        public virtual bool IsSupported(BlockDescriptor descriptor, IMultiplayerServer server, IWorld world)
        {
            var support = GetSupportDirection(descriptor);

            if (support != Coordinates3D.Zero)
            {
                var supportingBlock = server.BlockRepository.GetBlockProvider(world.GetBlockID(descriptor.Coordinates + support));
                if (!supportingBlock.Opaque)
                {
                    return(false);
                }
            }
            return(true);
        }
예제 #41
0
        public static void HandleAnimation(IPacket _packet, IRemoteClient _client, IMultiplayerServer server)
        {
            var packet = (AnimationPacket)_packet;
            var client = (RemoteClient)_client;

            if (packet.EntityID == client.Entity.EntityID)
            {
                var nearby = server.GetEntityManagerForWorld(client.World)
                             .ClientsForEntity(client.Entity);
                foreach (var player in nearby)
                {
                    player.QueuePacket(packet);
                }
            }
        }
예제 #42
0
 private void GrowBlock(IMultiplayerServer server, IWorld world, Coordinates3D coords)
 {
     if (world.GetBlockID(coords) != BlockID)
         return;
     var meta = world.GetMetadata(coords);
     meta++;
     world.SetMetadata(coords, meta);
     if (meta < 7)
     {
         var chunk = world.FindChunk(coords);
         server.Scheduler.ScheduleEvent("crops",
             chunk, TimeSpan.FromSeconds(MathHelper.Random.Next(30, 60)),
            (_server) => GrowBlock(_server, world, coords));
     }
 }
예제 #43
0
        public void GenerateDropEntity(BlockDescriptor descriptor, IWorld world, IMultiplayerServer server)
        {
            var entityManager = server.GetEntityManagerForWorld(world);
            var items         = GetDrop(descriptor);

            foreach (var item in items)
            {
                if (item.Empty)
                {
                    continue;
                }
                var entity = new ItemEntity(new Vector3(descriptor.Coordinates) + new Vector3(0.5), item);
                entityManager.SpawnEntity(entity);
            }
        }
예제 #44
0
 public override void BlockUpdate(BlockDescriptor descriptor, BlockDescriptor source, IMultiplayerServer server, IWorld world)
 {
     if (source.Coordinates == descriptor.Coordinates + Coordinates3D.Up)
     {
         var provider = world.BlockRepository.GetBlockProvider(source.ID);
         if (provider.Opaque)
         {
             var chunk = world.FindChunk(descriptor.Coordinates, generate: false);
             server.Scheduler.ScheduleEvent("grass", chunk,
             TimeSpan.FromSeconds(MathHelper.Random.Next(MinDecayTime, MaxDecayTime)), s =>
             {
                 ScheduledUpdate(world, descriptor.Coordinates);
             });
         }
     }
 }
예제 #45
0
        private void AutomataUpdate(IMultiplayerServer server, IWorld world, Coordinates3D coords)
        {
            if (world.GetBlockID(coords) != FlowingID && world.GetBlockID(coords) != StillID)
            {
                return;
            }
            server.BlockUpdatesEnabled = false;
            var again = DoAutomata(server, world, coords);

            server.BlockUpdatesEnabled = true;
            if (again)
            {
                server.Scheduler.ScheduleEvent(DateTime.Now.AddSeconds(SecondsBetweenUpdates), (_server) =>
                                               AutomataUpdate(_server, world, coords));
            }
        }
예제 #46
0
        private void GrowBlock(IMultiplayerServer server, IWorld world, Coordinates3D coords)
        {
            if (world.GetBlockID(coords) != BlockID)
            {
                return;
            }
            var meta = world.GetMetadata(coords);

            meta++;
            world.SetMetadata(coords, meta);
            if (meta < 7)
            {
                server.Scheduler.ScheduleEvent(DateTime.Now.AddSeconds(MathHelper.Random.Next(30, 60)),
                                               (_server) => GrowBlock(_server, world, coords));
            }
        }
예제 #47
0
 internal void ExpandChunkRadius(IMultiplayerServer server)
 {
     if (this.Disconnected)
     {
         return;
     }
     Task.Factory.StartNew(() =>
     {
         if (ChunkRadius < 8) // TODO: Allow customization of this number
         {
             ChunkRadius++;
             UpdateChunks();
             server.Scheduler.ScheduleEvent("remote.chunks", this, TimeSpan.FromSeconds(1), ExpandChunkRadius);
         }
     });
 }
예제 #48
0
 public RemoteClient(IMultiplayerServer server, NetworkStream stream)
 {
     NetworkStream   = stream;
     MinecraftStream = new MinecraftStream(new TrueCraft.Core.Networking.BufferedStream(NetworkStream));
     PacketQueue     = new ConcurrentQueue <IPacket>();
     LoadedChunks    = new List <Coordinates2D>();
     Server          = server;
     Inventory       = new InventoryWindow(server.CraftingRepository);
     InventoryWindow.WindowChange += HandleWindowChange;
     SelectedSlot  = InventoryWindow.HotbarIndex;
     CurrentWindow = InventoryWindow;
     ItemStaging   = ItemStack.EmptyStack;
     KnownEntities = new List <IEntity>();
     Disconnected  = false;
     EnableLogging = server.EnableClientLogging;
     NextWindowID  = 1;
 }
예제 #49
0
        private void GrowBlock(IMultiplayerServer server, IWorld world, Coordinates3D coords)
        {
            if (world.GetBlockID(coords) != BlockID)
            {
                return;
            }
            var meta = world.GetMetadata(coords);

            meta++;
            world.SetMetadata(coords, meta);
            if (meta < 7)
            {
                var chunk = world.FindChunk(coords);
                server.Scheduler.ScheduleEvent("crops",
                                               chunk, TimeSpan.FromSeconds(MathHelper.Random.Next(30, 60)),
                                               (_server) => GrowBlock(_server, world, coords));
            }
        }
예제 #50
0
        private void AutomataUpdate(IMultiplayerServer server, IWorld world, Coordinates3D coords)
        {
            if (world.GetBlockID(coords) != FlowingID && world.GetBlockID(coords) != StillID)
            {
                return;
            }
            server.BlockUpdatesEnabled = false;
            var again = DoAutomata(server, world, coords);

            server.BlockUpdatesEnabled = true;
            if (again)
            {
                var chunk = world.FindChunk(coords);
                server.Scheduler.ScheduleEvent("fluid", chunk,
                                               TimeSpan.FromSeconds(SecondsBetweenUpdates), (_server) =>
                                               AutomataUpdate(_server, world, coords));
            }
        }
예제 #51
0
        public bool DoAutomata(IMultiplayerServer server, IWorld world, Coordinates3D coords)
        {
            var previousLevel = world.GetMetadata(coords);

            var inward  = DetermineInwardFlow(world, coords);
            var outward = DetermineOutwardFlow(world, coords);

            if (outward.Length == 1 && outward[0].TargetBlock == coords + Coordinates3D.Down)
            {
                // Exit early if we have placed a fluid block beneath us (and we aren't a source block)
                FlowOutward(world, outward[0], server);
                if (previousLevel != 0)
                {
                    return(true);
                }
            }

            // Process inward flow
            if (inward > MaximumFluidDepletion)
            {
                world.SetBlockID(coords, 0);
                return(true);
            }
            world.SetMetadata(coords, inward);
            if (inward == 0 && previousLevel != 0)
            {
                // Exit early if we have become a source block
                return(true);
            }

            // Process outward flow
            for (int i = 0; i < outward.Length; i++)
            {
                FlowOutward(world, outward[i], server);
            }
            // Set our block to still fluid if we are done spreading.
            if (outward.Length == 0 && inward == previousLevel)
            {
                world.SetBlockID(coords, StillID);
                return(false);
            }
            return(true);
        }
예제 #52
0
        public void DoUpdate(IMultiplayerServer server, IWorld world, BlockDescriptor descriptor)
        {
            var down = descriptor.Coordinates + Coordinates3D.Down;

            var current = world.GetBlockID(descriptor.Coordinates);

            if (current != FireBlock.BlockID && current != LavaBlock.BlockID && current != StationaryLavaBlock.BlockID)
            {
                return;
            }

            // Decay
            var meta = world.GetMetadata(descriptor.Coordinates);

            meta++;
            if (meta == 0xE)
            {
                if (!world.IsValidPosition(down) || world.GetBlockID(down) != NetherrackBlock.BlockID)
                {
                    world.SetBlockID(descriptor.Coordinates, AirBlock.BlockID);
                    return;
                }
            }
            world.SetMetadata(descriptor.Coordinates, meta);

            if (meta > 9)
            {
                var pick     = AdjacentBlocks[meta % AdjacentBlocks.Length];
                var provider = BlockRepository
                               .GetBlockProvider(world.GetBlockID(pick + descriptor.Coordinates));
                if (provider.Flammable)
                {
                    world.SetBlockID(pick + descriptor.Coordinates, AirBlock.BlockID);
                }
            }

            // Spread
            DoSpread(server, world, descriptor);

            // Schedule next event
            ScheduleUpdate(server, world, descriptor);
        }
예제 #53
0
        private void TryGrowth(IMultiplayerServer server, Coordinates3D coords, IWorld world)
        {
            if (world.GetBlockID(coords) != BlockID)
            {
                return;
            }
            // Find current height of stalk
            int height = 0;

            for (int y = -MaxGrowHeight; y <= MaxGrowHeight; y++)
            {
                if (world.GetBlockID(coords + (Coordinates3D.Down * y)) == BlockID)
                {
                    height++;
                }
            }
            if (height < MaxGrowHeight)
            {
                var meta = world.GetMetadata(coords);
                meta++;
                world.SetMetadata(coords, meta);
                var chunk = world.FindChunk(coords);
                if (meta == 15)
                {
                    if (world.GetBlockID(coords + Coordinates3D.Up) == 0)
                    {
                        world.SetBlockID(coords + Coordinates3D.Up, BlockID);
                        server.Scheduler.ScheduleEvent("sugarcane", chunk,
                                                       TimeSpan.FromSeconds(MathHelper.Random.Next(MinGrowthSeconds, MaxGrowthSeconds)),
                                                       (_server) => TryGrowth(_server, coords + Coordinates3D.Up, world));
                    }
                }
                else
                {
                    server.Scheduler.ScheduleEvent("sugarcane", chunk,
                                                   TimeSpan.FromSeconds(MathHelper.Random.Next(MinGrowthSeconds, MaxGrowthSeconds)),
                                                   (_server) => TryGrowth(_server, coords, world));
                }
            }
        }
예제 #54
0
        public static void RegisterHandlers(IMultiplayerServer server)
        {
            server.RegisterPacketHandler(new KeepAlivePacket().ID, HandleKeepAlive);
            server.RegisterPacketHandler(new ChatMessagePacket().ID, HandleChatMessage);
            server.RegisterPacketHandler(new DisconnectPacket().ID, HandleDisconnect);

            server.RegisterPacketHandler(new HandshakePacket().ID, LoginHandlers.HandleHandshakePacket);
            server.RegisterPacketHandler(new LoginRequestPacket().ID, LoginHandlers.HandleLoginRequestPacket);

            server.RegisterPacketHandler(new PlayerGroundedPacket().ID, (a, b, c) => { /* no-op */ });
            server.RegisterPacketHandler(new PlayerPositionPacket().ID, EntityHandlers.HandlePlayerPositionPacket);
            server.RegisterPacketHandler(new PlayerLookPacket().ID, EntityHandlers.HandlePlayerLookPacket);
            server.RegisterPacketHandler(new PlayerPositionAndLookPacket().ID, EntityHandlers.HandlePlayerPositionAndLookPacket);

            server.RegisterPacketHandler(new PlayerDiggingPacket().ID, InteractionHandlers.HandlePlayerDiggingPacket);
            server.RegisterPacketHandler(new PlayerBlockPlacementPacket().ID, InteractionHandlers.HandlePlayerBlockPlacementPacket);
            server.RegisterPacketHandler(new ChangeHeldItemPacket().ID, InteractionHandlers.HandleChangeHeldItem);
            server.RegisterPacketHandler(new PlayerActionPacket().ID, InteractionHandlers.HandlePlayerAction);
            server.RegisterPacketHandler(new ClickWindowPacket().ID, InteractionHandlers.HandleClickWindowPacket);
            server.RegisterPacketHandler(new CloseWindowPacket().ID, InteractionHandlers.HandleCloseWindowPacket);
            server.RegisterPacketHandler(new UpdateSignPacket().ID, InteractionHandlers.HandleUpdateSignPacket);
        }
예제 #55
0
        public RemoteClient(IMultiplayerServer server, IPacketReader packetReader, PacketHandler[] packetHandlers, Socket connection)
        {
            LoadedChunks = new List<Coordinates2D>();
            Server = server;
            Inventory = new InventoryWindow(server.CraftingRepository);
            InventoryWindow.WindowChange += HandleWindowChange;
            SelectedSlot = InventoryWindow.HotbarIndex;
            CurrentWindow = InventoryWindow;
            ItemStaging = ItemStack.EmptyStack;
            KnownEntities = new List<IEntity>();
            Disconnected = false;
            EnableLogging = server.EnableClientLogging;
            NextWindowID = 1;
            Connection = connection;
            SocketPool = new SocketAsyncEventArgsPool(100, 200, 65536);
            PacketReader = packetReader;
            PacketHandlers = packetHandlers;

            cancel = new CancellationTokenSource();

            StartReceive();
        }
예제 #56
0
        public void DoUpdate(IMultiplayerServer server, IWorld world, BlockDescriptor descriptor)
        {
            var down = descriptor.Coordinates + Coordinates3D.Down;

            var current = world.GetBlockID(descriptor.Coordinates);
            if (current != FireBlock.BlockID && current != LavaBlock.BlockID && current != StationaryLavaBlock.BlockID)
                return;

            // Decay
            var meta = world.GetMetadata(descriptor.Coordinates);
            meta++;
            if (meta == 0xE)
            {
                if (!world.IsValidPosition(down) || world.GetBlockID(down) != NetherrackBlock.BlockID)
                {
                    world.SetBlockID(descriptor.Coordinates, AirBlock.BlockID);
                    return;
                }
            }
            world.SetMetadata(descriptor.Coordinates, meta);

            if (meta > 9)
            {
                var pick = AdjacentBlocks[meta % AdjacentBlocks.Length];
                var provider = BlockRepository
                    .GetBlockProvider(world.GetBlockID(pick + descriptor.Coordinates));
                if (provider.Flammable)
                    world.SetBlockID(pick + descriptor.Coordinates, AirBlock.BlockID);
            }

            // Spread
            DoSpread(server, world, descriptor);

            // Schedule next event
            ScheduleUpdate(server, world, descriptor);
        }
예제 #57
0
 void HydrationCheckEvent(IMultiplayerServer server, Coordinates3D coords, IWorld world)
 {
     if (world.GetBlockID(coords) != BlockID)
         return;
     if (MathHelper.Random.Next(3) == 0)
     {
         var meta = world.GetMetadata(coords);
         if (IsHydrated(coords, world) && meta != 15)
             meta++;
         else
         {
             meta--;
             if (meta == 0)
             {
                 world.SetBlockID(coords, BlockID);
                 return;
             }
         }
         world.SetMetadata(coords, meta);
     }
     server.Scheduler.ScheduleEvent(DateTime.Now.AddSeconds(UpdateIntervalSeconds), (_server) => HydrationCheckEvent(_server, coords, world));
 }
예제 #58
0
 private void TryGrowth(IMultiplayerServer server, Coordinates3D coords, IWorld world)
 {
     if (world.GetBlockID(coords) != BlockID)
         return;
     // Find current height of stalk
     int height = 0;
     for (int y = -3; y <= 3; y++)
     {
         if (world.GetBlockID(coords + (Coordinates3D.Down * y)) == BlockID)
             height++;
     }
     if (height < 3)
     {
         var meta = world.GetMetadata(coords);
         meta++;
         world.SetMetadata(coords, meta);
         if (meta == 15)
         {
             world.SetBlockID(coords + Coordinates3D.Up, BlockID);
             server.Scheduler.ScheduleEvent(DateTime.Now.AddSeconds(MathHelper.Random.Next(MinGrowthSeconds, MaxGrowthSeconds)),
                 (_server) => TryGrowth(_server, coords + Coordinates3D.Up, world));
         }
         else
         {
             server.Scheduler.ScheduleEvent(DateTime.Now.AddSeconds(MathHelper.Random.Next(MinGrowthSeconds, MaxGrowthSeconds)),
                 (_server) => TryGrowth(_server, coords, world));
         }
     }
 }
예제 #59
0
 public override void BlockLoadedFromChunk(Coordinates3D coords, IMultiplayerServer server, IWorld world)
 {
     var state = GetState(world, coords);
     TryInitializeFurnace(state, server.Scheduler, world, coords, server.ItemRepository);
 }
예제 #60
0
 public override void BlockUpdate(BlockDescriptor descriptor, BlockDescriptor source, IMultiplayerServer server, IWorld world)
 {
     if (!ValidPlacement(descriptor, world))
     {
         // Destroy self
         world.SetBlockID(descriptor.Coordinates, 0);
         GenerateDropEntity(descriptor, world, server);
     }
 }