示例#1
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);
            }
        }
示例#2
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)));
        }
示例#3
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);
            }
        }
示例#4
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);
            }
        }
示例#5
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));
     }
 }
示例#6
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));
     }
 }
示例#7
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));
 }
示例#8
0
        public static void HandleLoginRequestPacket(IPacket _packet, IRemoteClient _client, IMultiplayerServer server)
        {
            var packet = (LoginRequestPacket)_packet;
            var client = (RemoteClient)_client;

            if (packet.ProtocolVersion < server.PacketReader.ProtocolVersion)
            {
                client.QueuePacket(new DisconnectPacket("Client outdated! Use beta 1.7.3."));
            }
            else if (packet.ProtocolVersion > server.PacketReader.ProtocolVersion)
            {
                client.QueuePacket(new DisconnectPacket("Server outdated! Use beta 1.7.3."));
            }
            else if (server.Worlds.Count == 0)
            {
                client.QueuePacket(new DisconnectPacket("Server has no worlds configured."));
            }
            else
            {
                client.LoggedIn    = true;
                client.Entity      = new PlayerEntity(client.Username);
                client.World       = server.Worlds[0];
                client.ChunkRadius = 2;

                if (!client.Load())
                {
                    client.Entity.Position = client.World.SpawnPoint;
                }

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

                // Start housekeeping for this client
                var entityManager = server.GetEntityManagerForWorld(client.World);
                entityManager.SpawnEntity(client.Entity);
                entityManager.SendEntitiesToClient(client);
                server.Scheduler.ScheduleEvent(DateTime.Now.AddSeconds(10), client.SendKeepAlive);
                server.Scheduler.ScheduleEvent(DateTime.Now.AddSeconds(1), client.ExpandChunkRadius);

                if (!string.IsNullOrEmpty(Program.Configuration.MOTD))
                {
                    client.SendMessage(Program.Configuration.MOTD);
                }
                server.SendMessage(ChatColor.Yellow + "{0} joined the server.", client.Username);
            }
        }
示例#9
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));
            }
        }
示例#10
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);
            }
        }
示例#11
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);
                }
            }
        }
示例#12
0
        public static void HandleClickWindowPacket(IPacket _packet, IRemoteClient _client, IMultiplayerServer server)
        {
            var packet = (ClickWindowPacket)_packet;
            var client = (RemoteClient)_client;
            var window = client.CurrentWindow;

            if (packet.SlotIndex == -999)
            {
                // Throwing item
                ItemEntity item;
                if (packet.RightClick)
                {
                    var spawned = client.ItemStaging;
                    spawned.Count = 1;
                    var inventory = client.ItemStaging;
                    inventory.Count--;
                    item = new ItemEntity(client.Entity.Position + new Vector3(0, PlayerEntity.Height, 0), spawned);
                    client.ItemStaging = inventory;
                }
                else
                {
                    item = new ItemEntity(client.Entity.Position + new Vector3(0, PlayerEntity.Height, 0), client.ItemStaging);
                    client.ItemStaging = ItemStack.EmptyStack;
                }
                item.Velocity = MathHelper.FowardVector(client.Entity.Yaw) * 0.3;
                server.GetEntityManagerForWorld(client.World).SpawnEntity(item);
                return;
            }
            var staging = (ItemStack)client.ItemStaging.Clone();

            Window.HandleClickPacket(packet, window, ref staging);
            client.ItemStaging = staging;
            if (packet.SlotIndex >= window.Length || packet.SlotIndex < 0)
            {
                return;
            }
            client.QueuePacket(new WindowItemsPacket(packet.WindowID, window.GetSlots()));
        }
示例#13
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)));
        }
示例#14
0
        public static void HandlePlayerDiggingPacket(IPacket _packet, IRemoteClient _client, IMultiplayerServer server)
        {
            var   packet     = (PlayerDiggingPacket)_packet;
            var   client     = (RemoteClient)_client;
            var   world      = _client.World;
            var   position   = new Coordinates3D(packet.X, packet.Y, packet.Z);
            var   descriptor = world.GetBlockData(position);
            var   provider   = server.BlockRepository.GetBlockProvider(descriptor.ID);
            short damage;
            int   time;

            switch (packet.PlayerAction)
            {
            case PlayerDiggingPacket.Action.DropItem:
                // Throwing item
                if (client.SelectedItem.Empty)
                {
                    break;
                }
                var spawned = client.SelectedItem;
                spawned.Count = 1;
                var inventory = client.SelectedItem;
                inventory.Count--;
                var item = new ItemEntity(client.Entity.Position + new Vector3(0, PlayerEntity.Height, 0), spawned);
                item.Velocity = MathHelper.FowardVector(client.Entity.Yaw) * 0.3;
                client.Inventory[client.SelectedSlot] = inventory;
                server.GetEntityManagerForWorld(client.World).SpawnEntity(item);
                break;

            case PlayerDiggingPacket.Action.StartDigging:
                foreach (var nearbyClient in server.Clients)     // TODO: Send this repeatedly during the course of the digging
                {
                    var c = (RemoteClient)nearbyClient;
                    if (c.KnownEntities.Contains(client.Entity))
                    {
                        c.QueuePacket(new AnimationPacket(client.Entity.EntityID, AnimationPacket.PlayerAnimation.SwingArm));
                    }
                }
                if (provider == null)
                {
                    server.SendMessage(ChatColor.Red + "WARNING: block provider for ID {0} is null (player digging)", descriptor.ID);
                }
                else
                {
                    provider.BlockLeftClicked(descriptor, packet.Face, world, client);
                }

                // "But why on Earth does this behavior change if you use shears on leaves?"
                // "This is poor seperation of concerns"
                // "Let me do a git blame and flame whoever wrote the next line"
                // To answer all of those questions, here:
                // Minecraft sends a player digging packet when the player starts and stops digging a block (two packets)
                // However, it only sends ONE packet if the block would be mined immediately - which usually is only the case
                // for blocks that have a hardness equal to zero.
                // The exception to this rule is shears on leaves. Leaves normally have a hardness of 0.2, but when you mine them
                // using shears the client only sends the start digging packet and expects them to be mined immediately.
                // So if you want to blame anyone, send flames to Notch for the stupid idea of not sending "stop digging" packets
                // for hardness == 0 blocks.

                time = BlockProvider.GetHarvestTime(descriptor.ID, client.SelectedItem.ID, out damage);
                if (time <= 20)
                {
                    provider.BlockMined(descriptor, packet.Face, world, client);
                    break;
                }
                client.ExpectedDigComplete = DateTime.UtcNow.AddMilliseconds(time);
                break;

            case PlayerDiggingPacket.Action.StopDigging:
                foreach (var nearbyClient in server.Clients)
                {
                    var c = (RemoteClient)nearbyClient;
                    if (c.KnownEntities.Contains(client.Entity))
                    {
                        c.QueuePacket(new AnimationPacket(client.Entity.EntityID, AnimationPacket.PlayerAnimation.None));
                    }
                }
                if (provider != null && descriptor.ID != 0)
                {
                    time = BlockProvider.GetHarvestTime(descriptor.ID, client.SelectedItem.ID, out damage);
                    if (time <= 20)
                    {
                        break;     // Already handled earlier
                    }
                    var diff = (DateTime.UtcNow - client.ExpectedDigComplete).TotalMilliseconds;
                    if (diff > -100)     // Allow a small tolerance
                    {
                        provider.BlockMined(descriptor, packet.Face, world, client);
                        // Damage the item
                        if (damage != 0)
                        {
                            var tool = server.ItemRepository.GetItemProvider(client.SelectedItem.ID) as ToolItem;
                            if (tool != null && tool.Uses != -1)
                            {
                                var slot = client.SelectedItem;
                                slot.Metadata += damage;
                                if (slot.Metadata >= tool.Uses)
                                {
                                    slot.Count = 0;     // Destroy item
                                }
                                client.Inventory[client.SelectedSlot] = slot;
                            }
                        }
                    }
                }
                break;
            }
        }
示例#15
0
        public static void HandleClickWindowPacket(IPacket _packet, IRemoteClient _client, IMultiplayerServer server)
        {
            var packet = (ClickWindowPacket)_packet;
            var client = (RemoteClient)_client;
            var window = client.CurrentWindow;

            if (packet.SlotIndex == -999)
            {
                // Throwing item
                ItemEntity item;
                if (packet.RightClick)
                {
                    var spawned = client.ItemStaging;
                    spawned.Count = 1;
                    var inventory = client.ItemStaging;
                    inventory.Count--;
                    item = new ItemEntity(client.Entity.Position + new Vector3(0, PlayerEntity.Height, 0), spawned);
                    client.ItemStaging = inventory;
                }
                else
                {
                    item = new ItemEntity(client.Entity.Position + new Vector3(0, PlayerEntity.Height, 0), client.ItemStaging);
                    client.ItemStaging = ItemStack.EmptyStack;
                }
                item.Velocity = MathHelper.FowardVector(client.Entity.Yaw) * 0.3;
                server.GetEntityManagerForWorld(client.World).SpawnEntity(item);
                return;
            }
            if (packet.SlotIndex >= window.Length || packet.SlotIndex < 0)
            {
                return;
            }
            ItemStack existing = window[packet.SlotIndex];
            ItemStack held     = client.ItemStaging;

            if (packet.SlotIndex == InventoryWindow.CraftingOutputIndex &&
                (window is InventoryWindow || window is CraftingBenchWindow))
            {
                // Stupid special case because Minecraft was written by morons
                if (held.ID == existing.ID || held.Empty)
                {
                    if (held.Empty)
                    {
                        held = existing;
                    }
                    else
                    {
                        held.Count += existing.Count;
                    }
                    client.ItemStaging       = held;
                    window[packet.SlotIndex] = ItemStack.EmptyStack;
                }
                client.QueuePacket(new WindowItemsPacket(packet.WindowID, window.GetSlots()));
                return;
            }
            if (client.ItemStaging.Empty) // Picking up something
            {
                if (packet.Shift)
                {
                    window.MoveToAlternateArea(packet.SlotIndex);
                }
                else
                {
                    if (packet.RightClick)
                    {
                        sbyte mod = (sbyte)(existing.Count % 2);
                        existing.Count          /= 2;
                        held                     = existing;
                        held.Count              += mod;
                        client.ItemStaging       = held;
                        window[packet.SlotIndex] = existing;
                    }
                    else
                    {
                        client.ItemStaging       = window[packet.SlotIndex];
                        window[packet.SlotIndex] = ItemStack.EmptyStack;
                    }
                }
            }
            else // Setting something down
            {
                if (existing.Empty) // Replace empty slot
                {
                    if (packet.RightClick)
                    {
                        var newItem = (ItemStack)client.ItemStaging.Clone();
                        newItem.Count = 1;
                        held.Count--;
                        window[packet.SlotIndex] = newItem;
                        client.ItemStaging       = held;
                    }
                    else
                    {
                        window[packet.SlotIndex] = client.ItemStaging;
                        client.ItemStaging       = ItemStack.EmptyStack;
                    }
                }
                else
                {
                    if (existing.CanMerge(client.ItemStaging)) // Merge items
                    {
                        // TODO: Consider the maximum stack size
                        if (packet.RightClick)
                        {
                            existing.Count++;
                            held.Count--;
                            window[packet.SlotIndex] = existing;
                            client.ItemStaging       = held;
                        }
                        else
                        {
                            existing.Count          += client.ItemStaging.Count;
                            window[packet.SlotIndex] = existing;
                            client.ItemStaging       = ItemStack.EmptyStack;
                        }
                    }
                    else // Swap items
                    {
                        window[packet.SlotIndex] = client.ItemStaging;
                        client.ItemStaging       = existing;
                    }
                }
            }
            client.QueuePacket(new WindowItemsPacket(packet.WindowID, window.GetSlots()));
        }
示例#16
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);
     }
 }
示例#17
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;
                }

                var entityManager = server.GetEntityManagerForWorld(remoteClient.World);
                entityManager.SpawnEntity(remoteClient.Entity);

                // Send setup packets
                remoteClient.QueuePacket(new LoginResponsePacket(client.Entity.EntityID, 0, Dimension.Overworld));
                remoteClient.UpdateChunks();
                remoteClient.QueuePacket(new WindowItemsPacket(0, remoteClient.Inventory.GetSlots()));
                remoteClient.QueuePacket(new UpdateHealthPacket((remoteClient.Entity as PlayerEntity).Health));
                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
                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);
                }
            }
        }
示例#18
0
 public static void HandleClickWindowPacket(IPacket _packet, IRemoteClient _client, IMultiplayerServer server)
 {
     var packet = (ClickWindowPacket)_packet;
     var client = (RemoteClient)_client;
     var window = client.CurrentWindow;
     if (packet.SlotIndex == -999)
     {
         // Throwing item
         ItemEntity item;
         if (packet.RightClick)
         {
             var spawned = client.ItemStaging;
             spawned.Count = 1;
             var inventory = client.ItemStaging;
             inventory.Count--;
             item = new ItemEntity(client.Entity.Position + new Vector3(0, PlayerEntity.Height, 0), spawned);
             client.ItemStaging = inventory;
         }
         else
         {
             item = new ItemEntity(client.Entity.Position + new Vector3(0, PlayerEntity.Height, 0), client.ItemStaging);
             client.ItemStaging = ItemStack.EmptyStack;
         }
         item.Velocity = MathHelper.FowardVector(client.Entity.Yaw) * 0.3;
         server.GetEntityManagerForWorld(client.World).SpawnEntity(item);
         return;
     }
     var staging = (ItemStack)client.ItemStaging.Clone();
     Window.HandleClickPacket(packet, window, ref staging);
     client.ItemStaging = staging;
     if (packet.SlotIndex >= window.Length || packet.SlotIndex < 0)
         return;
     client.QueuePacket(new WindowItemsPacket(packet.WindowID, window.GetSlots()));
 }
示例#19
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);
     }
 }
示例#20
0
        public static void HandlePlayerDiggingPacket(IPacket _packet, IRemoteClient _client, IMultiplayerServer server)
        {
            var packet     = (PlayerDiggingPacket)_packet;
            var client     = (RemoteClient)_client;
            var world      = _client.World;
            var position   = new Coordinates3D(packet.X, packet.Y, packet.Z);
            var descriptor = world.GetBlockData(position);
            var provider   = server.BlockRepository.GetBlockProvider(descriptor.ID);

            switch (packet.PlayerAction)
            {
            case PlayerDiggingPacket.Action.DropItem:
                // Throwing item
                if (client.SelectedItem.Empty)
                {
                    break;
                }
                var spawned = client.SelectedItem;
                spawned.Count = 1;
                var inventory = client.SelectedItem;
                inventory.Count--;
                var item = new ItemEntity(client.Entity.Position + new Vector3(0, PlayerEntity.Height, 0), spawned);
                item.Velocity = MathHelper.FowardVector(client.Entity.Yaw) * 0.3;
                client.Inventory[client.SelectedSlot] = inventory;
                server.GetEntityManagerForWorld(client.World).SpawnEntity(item);
                break;

            case PlayerDiggingPacket.Action.StartDigging:
                foreach (var nearbyClient in server.Clients)     // TODO: Send this repeatedly during the course of the digging
                {
                    var c = (RemoteClient)nearbyClient;
                    if (c.KnownEntities.Contains(client.Entity))
                    {
                        c.QueuePacket(new AnimationPacket(client.Entity.EntityID, AnimationPacket.PlayerAnimation.SwingArm));
                    }
                }
                if (provider == null)
                {
                    server.SendMessage(ChatColor.Red + "WARNING: block provider for ID {0} is null (player digging)", descriptor.ID);
                }
                else
                {
                    provider.BlockLeftClicked(descriptor, packet.Face, world, client);
                }
                if (provider != null && provider.Hardness == 0)
                {
                    provider.BlockMined(descriptor, packet.Face, world, client);
                }
                break;

            case PlayerDiggingPacket.Action.StopDigging:
                foreach (var nearbyClient in server.Clients)
                {
                    var c = (RemoteClient)nearbyClient;
                    if (c.KnownEntities.Contains(client.Entity))
                    {
                        c.QueuePacket(new AnimationPacket(client.Entity.EntityID, AnimationPacket.PlayerAnimation.None));
                    }
                }
                if (provider != null && descriptor.ID != 0)
                {
                    provider.BlockMined(descriptor, packet.Face, world, client);
                }
                break;
            }
        }
示例#21
0
 public static void HandleClickWindowPacket(IPacket _packet, IRemoteClient _client, IMultiplayerServer server)
 {
     var packet = (ClickWindowPacket)_packet;
     var client = (RemoteClient)_client;
     var window = client.CurrentWindow;
     if (packet.SlotIndex == -999)
     {
         // Throwing item
         ItemEntity item;
         if (packet.RightClick)
         {
             var spawned = client.ItemStaging;
             spawned.Count = 1;
             var inventory = client.ItemStaging;
             inventory.Count--;
             item = new ItemEntity(client.Entity.Position + new Vector3(0, PlayerEntity.Height, 0), spawned);
             client.ItemStaging = inventory;
         }
         else
         {
             item = new ItemEntity(client.Entity.Position + new Vector3(0, PlayerEntity.Height, 0), client.ItemStaging);
             client.ItemStaging = ItemStack.EmptyStack;
         }
         item.Velocity = MathHelper.FowardVector(client.Entity.Yaw) * 0.3;
         server.GetEntityManagerForWorld(client.World).SpawnEntity(item);
         return;
     }
     if (packet.SlotIndex >= window.Length || packet.SlotIndex < 0)
         return;
     ItemStack existing = window[packet.SlotIndex];
     ItemStack held = client.ItemStaging;
     if (packet.SlotIndex == InventoryWindow.CraftingOutputIndex
         && (window is InventoryWindow || window is CraftingBenchWindow))
     {
         // Stupid special case because Minecraft was written by morons
         if (held.ID == existing.ID || held.Empty)
         {
             if (held.Empty)
                 held = existing;
             else
                 held.Count += existing.Count;
             client.ItemStaging = held;
             window[packet.SlotIndex] = ItemStack.EmptyStack;
         }
         client.QueuePacket(new WindowItemsPacket(packet.WindowID, window.GetSlots()));
         return;
     }
     if (client.ItemStaging.Empty) // Picking up something
     {
         if (packet.Shift)
         {
             window.MoveToAlternateArea(packet.SlotIndex);
         }
         else
         {
             if (packet.RightClick)
             {
                 sbyte mod = (sbyte)(existing.Count % 2);
                 existing.Count /= 2;
                 held = existing;
                 held.Count += mod;
                 client.ItemStaging = held;
                 window[packet.SlotIndex] = existing;
             }
             else
             {
                 client.ItemStaging = window[packet.SlotIndex];
                 window[packet.SlotIndex] = ItemStack.EmptyStack;
             }
         }
     }
     else // Setting something down
     {
         if (existing.Empty) // Replace empty slot
         {
             if (packet.RightClick)
             {
                 var newItem = (ItemStack)client.ItemStaging.Clone();
                 newItem.Count = 1;
                 held.Count--;
                 window[packet.SlotIndex] = newItem;
                 client.ItemStaging = held;
             }
             else
             {
                 window[packet.SlotIndex] = client.ItemStaging;
                 client.ItemStaging = ItemStack.EmptyStack;
             }
         }
         else
         {
             if (existing.CanMerge(client.ItemStaging)) // Merge items
             {
                 // TODO: Consider the maximum stack size
                 if (packet.RightClick)
                 {
                     existing.Count++;
                     held.Count--;
                     window[packet.SlotIndex] = existing;
                     client.ItemStaging = held;
                 }
                 else
                 {
                     existing.Count += client.ItemStaging.Count;
                     window[packet.SlotIndex] = existing;
                     client.ItemStaging = ItemStack.EmptyStack;
                 }
             }
             else // Swap items
             {
                 window[packet.SlotIndex] = client.ItemStaging;
                 client.ItemStaging = existing;
             }
         }
     }
     client.QueuePacket(new WindowItemsPacket(packet.WindowID, window.GetSlots()));
 }
示例#22
0
        public static void HandlePlayerDiggingPacket(IPacket _packet, IRemoteClient _client, IMultiplayerServer server)
        {
            var packet = (PlayerDiggingPacket)_packet;
            var client = (RemoteClient)_client;
            var world = _client.World;
            var position = new Coordinates3D(packet.X, packet.Y, packet.Z);
            var descriptor = world.GetBlockData(position);
            var provider = server.BlockRepository.GetBlockProvider(descriptor.ID);
            short damage;
            int time;
            switch (packet.PlayerAction)
            {
                case PlayerDiggingPacket.Action.DropItem:
                    // Throwing item
                    if (client.SelectedItem.Empty)
                        break;
                    var spawned = client.SelectedItem;
                    spawned.Count = 1;
                    var inventory = client.SelectedItem;
                    inventory.Count--;
                    var item = new ItemEntity(client.Entity.Position + new Vector3(0, PlayerEntity.Height, 0), spawned);
                    item.Velocity = MathHelper.FowardVector(client.Entity.Yaw) * 0.3;
                    client.Inventory[client.SelectedSlot] = inventory;
                    server.GetEntityManagerForWorld(client.World).SpawnEntity(item);
                    break;
                case PlayerDiggingPacket.Action.StartDigging:
                    foreach (var nearbyClient in server.Clients) // TODO: Send this repeatedly during the course of the digging
                    {
                        var c = (RemoteClient)nearbyClient;
                        if (c.KnownEntities.Contains(client.Entity))
                            c.QueuePacket(new AnimationPacket(client.Entity.EntityID, AnimationPacket.PlayerAnimation.SwingArm));
                    }
                    if (provider == null)
                        server.SendMessage(ChatColor.Red + "WARNING: block provider for ID {0} is null (player digging)", descriptor.ID);
                    else
                        provider.BlockLeftClicked(descriptor, packet.Face, world, client);

                    // "But why on Earth does this behavior change if you use shears on leaves?"
                    // "This is poor seperation of concerns"
                    // "Let me do a git blame and flame whoever wrote the next line"
                    // To answer all of those questions, here:
                    // Minecraft sends a player digging packet when the player starts and stops digging a block (two packets)
                    // However, it only sends ONE packet if the block would be mined immediately - which usually is only the case
                    // for blocks that have a hardness equal to zero.
                    // The exception to this rule is shears on leaves. Leaves normally have a hardness of 0.2, but when you mine them
                    // using shears the client only sends the start digging packet and expects them to be mined immediately.
                    // So if you want to blame anyone, send flames to Notch for the stupid idea of not sending "stop digging" packets
                    // for hardness == 0 blocks.

                    time = BlockProvider.GetHarvestTime(descriptor.ID, client.SelectedItem.ID, out damage);
                    if (time <= 20)
                    {
                        provider.BlockMined(descriptor, packet.Face, world, client);
                        break;
                    }
                    client.ExpectedDigComplete = DateTime.UtcNow.AddMilliseconds(time);
                    break;
                case PlayerDiggingPacket.Action.StopDigging:
                    foreach (var nearbyClient in server.Clients)
                    {
                        var c = (RemoteClient)nearbyClient;
                        if (c.KnownEntities.Contains(client.Entity))
                            c.QueuePacket(new AnimationPacket(client.Entity.EntityID, AnimationPacket.PlayerAnimation.None));
                    }
                    if (provider != null && descriptor.ID != 0)
                    {
                        time = BlockProvider.GetHarvestTime(descriptor.ID, client.SelectedItem.ID, out damage);
                        if (time <= 20)
                            break; // Already handled earlier
                        var diff = (DateTime.UtcNow - client.ExpectedDigComplete).TotalMilliseconds;
                        if (diff > -100) // Allow a small tolerance
                        {
                            provider.BlockMined(descriptor, packet.Face, world, client);
                            // Damage the item
                            if (damage != 0)
                            {
                                var tool = server.ItemRepository.GetItemProvider(client.SelectedItem.ID) as ToolItem;
                                if (tool != null && tool.Uses != -1)
                                {
                                    var slot = client.SelectedItem;
                                    slot.Metadata += damage;
                                    if (slot.Metadata >= tool.Uses)
                                        slot.Count = 0; // Destroy item
                                    client.Inventory[client.SelectedSlot] = slot;
                                }
                            }
                        }
                    }
                    break;
            }
        }