// TODO: Move a bunch of this to DataFile.cs
        private void Load()
        {
            if (!File.Exists(DataFile))
                return;

            ClientSurrogate client;
            using (FileStream rx = File.OpenRead(DataFile))
                client = (ClientSurrogate)Xml.Deserialize(rx);
            Position.X = client.X;
            Position.Y = client.Y + 1; // Players drop one block upon spawning
            Position.Z = client.Z;
            Position.Yaw = client.Yaw;
            Position.Pitch = client.Pitch;
            if (client.Inventory == null) return;
            Inventory = new Inventory {Handle = 0};
            ItemStack[] slots = new ItemStack[client.Inventory.SlotCount];
            for (short i = 0; i < client.Inventory.SlotCount; i++)
            {
                slots[i] = ItemStack.Void;
                if (!ItemStack.IsVoid(client.Inventory.Slots[i]))
                {
                    slots[i].Type = client.Inventory.Slots[i].Type;
                    slots[i].Count = client.Inventory.Slots[i].Count;
                    slots[i].Durability = client.Inventory.Slots[i].Durability;
                    slots[i].Slot = i;
                }
                // Using the default indexer on Inventory ensures all event handlers are correctly hooked up
                this.Inventory[i] = slots[i];
            }
            Inventory.Associate(this);
            GameMode = client.GameMode;
        }
示例#2
0
 internal Interface(InterfaceType type, sbyte slotCount)
 {
     Type = type;
     Handle = NextHandle;
     Slots = new ItemStack[slotCount];
     Title = "C#raft Interface";
     NextHandle = NextHandle == 127 ? (sbyte)0 : (sbyte)(NextHandle + 1);
 }
示例#3
0
 internal Interface(InterfaceType type, sbyte slotCount)
 {
     Type = type;
     Handle = NextHandle;
     Slots = new ItemStack[slotCount];
     Title = "C#raft Interface";
     NextHandle = NextHandle == 127 ? (sbyte)1 : (sbyte)(NextHandle + 1); // Handles between 1 and 127. 0 is reserved for Inventory
 }
        protected override void DoLoad()
        {
            ItemStack[] neChestItems = new ItemStack[27];
            ItemStack[] swChestItems = new ItemStack[27];

            // try..finally just to be sure we load both files - exception will be handled by caller in base
            try
            {
                DoLoadFromFile(neChestItems, NEDataFile);
            }
            finally
            {
                DoLoadFromFile(swChestItems, SWDataFile);
            }

            Slots = neChestItems.Concat(swChestItems).ToArray();
        }
示例#5
0
        // TODO: Move a bunch of this to DataFile.cs
        private void Load()
        {
            if (string.IsNullOrEmpty(Username) && string.IsNullOrEmpty(_player.DisplayName)) { return; } //we are the server ping
            if (!File.Exists(DataFile))
            {
                _player.Position = new AbsWorldCoords(Owner.World.Spawn.WorldX, Owner.World.Spawn.WorldY, Owner.World.Spawn.WorldZ);
                WaitForInitialPosAck = true;
                _player.LoginPosition = _player.Position;
                return;
            }

            ClientSurrogate client;
            using (FileStream rx = File.OpenRead(DataFile))
                client = (ClientSurrogate)Xml.Deserialize(rx);
            _player.Position = new AbsWorldCoords(client.X, client.Y, client.Z);
            _player.Yaw = client.Yaw;
            _player.Pitch = client.Pitch;
            if (client.Inventory != null)
            {
                _player.Inventory = new Inventory {Handle = 0};
                ItemStack[] slots = new ItemStack[client.Inventory.SlotCount];

                for (short i = 0; i < client.Inventory.SlotCount; i++)
                {
                    slots[i] = ItemStack.Void;
                    if (!ItemStack.IsVoid(client.Inventory.Slots[i]))
                    {
                        slots[i].Type = client.Inventory.Slots[i].Type;
                        slots[i].Count = client.Inventory.Slots[i].Count;
                        slots[i].Durability = client.Inventory.Slots[i].Durability;
                        slots[i].Slot = i;
                    }
                    // Using the default indexer on Inventory ensures all event handlers are correctly hooked up
                    _player.Inventory[i] = slots[i];
                }
                _player.Inventory.Associate(_player);
            }
            _player.GameMode = client.GameMode;
            _player.Health = client.Health;
            _player.Food = client.Food;
            _player.FoodSaturation = client.FoodSaturation;
            _player.DisplayName = client.DisplayName;
            WaitForInitialPosAck = true;
            _player.LoginPosition = _player.Position;
        }
示例#6
0
 /// <summary>
 /// Drops an item at the given location.
 /// </summary>
 /// <param name="world">The world in which the coordinates reside.</param>
 /// <param name="x">The target X coordinate.</param>
 /// <param name="y">The target Y coordinate.</param>
 /// <param name="z">The target Z coordinate.</param>
 /// <param name="stack">The stack to be dropped</param>
 /// <returns>The entity ID of the item drop.</returns>
 public int DropItem(WorldManager world, int x, int y, int z, ItemStack stack)
 {
     int entityId = AllocateEntity();
     AddEntity(new ItemEntity(this, entityId)
     {
         World = world,
         Position = new Location(new Vector3(x + 0.5, y, z + 0.5)), // Put in the middle of the block (ignoring Y)
         ItemId = stack.Type,
         Count = stack.Count,
         Durability = stack.Durability
     });
     return entityId;
 }
示例#7
0
 /// <summary>
 /// Drops an item based on the given player's position and rotation.
 /// </summary>
 /// <param name="client">The client to be used for position calculations.</param>
 /// <param name="stack">The stack to be dropped.</param>
 /// <returns>The entity ID of the item drop.</returns>
 public int DropItem(Client client, ItemStack stack)
 {
     return DropItem(client.World, (int)client.Position.X, (int)client.Position.Y, (int)client.Position.Z, stack);
 }
示例#8
0
 internal static ItemStack Read(PacketReader stream)
 {
     ItemStack retval = new ItemStack(stream.ReadShort());
     if (retval.Type >= 0)
     {
         retval.Count = stream.ReadSByte();
         retval.Durability = stream.ReadShort();
     }
     return retval;
 }
示例#9
0
 /// <summary>
 /// Determines whether the durability and type of two stacks are identical.
 /// </summary>
 /// <param name="stack">The stack to be compared with the current object.</param>
 /// <returns>True if the objects stack; otherwise false.</returns>
 /// <remarks>
 /// <para>This method does not take into consideration whether or not the item type can be stacked (e.g. pork).</para>
 /// <para>This method is used under this assumption throughout the server.</para>
 /// </remarks>
 public bool StacksWith(ItemStack stack)
 {
     return Type == stack.Type && stack.Durability == Durability;
 }
示例#10
0
 public void InitSlots(ItemStack input, ItemStack fuel, ItemStack output)
 {
     lock (_instanceLock)
     {
         InputSlot = (ItemStack.IsVoid(input) ? ItemStack.Void : new ItemStack(input.Type, input.Count, input.Durability));
         FuelSlot = (ItemStack.IsVoid(fuel) ? ItemStack.Void : new ItemStack(fuel.Type, fuel.Count, fuel.Durability));
         OutputSlot = (ItemStack.IsVoid(output) ? ItemStack.Void : new ItemStack(output.Type, output.Count, output.Durability));
     }
 }
示例#11
0
        internal void AddItem(short id, sbyte count, short durability)
        {
            // Quickslots, stacking
            for (short i = (short)InventorySlots.QuickSlotFirst; i <= (short)InventorySlots.QuickSlotLast; i++)
            {
                if (!ItemStack.IsVoid(Slots[i]) && Slots[i].Type == id && Slots[i].Durability == durability)
                {
                    if (Slots[i].Count + count <= 64)
                    {
                        Slots[i].Count += count;
                        return;
                    }
                    count -= (sbyte)(64 - Slots[i].Count);
                    Slots[i].Count = 64;
                }
            }

            // Inventory, stacking
            for (short i = (short)InventorySlots.InventoryFirst; i <= (short)InventorySlots.InventoryLast; i++)
            {
                if (!ItemStack.IsVoid(Slots[i]) && Slots[i].Type == id && Slots[i].Durability == durability)
                {
                    if (Slots[i].Count + count <= 64)
                    {
                        Slots[i].Count += count;
                        return;
                    }
                    count -= (sbyte)(64 - Slots[i].Count);
                    Slots[i].Count = 64;
                }
            }

            // Quickslots, not stacking
            for (short i = (short)InventorySlots.QuickSlotFirst; i <= (short)InventorySlots.QuickSlotLast; i++)
            {
                if (ItemStack.IsVoid(Slots[i]))
                {
                    Owner.Client.SendPacket(new ChatMessagePacket { Message = "Placing in slot " + i });
                    this[i] = new ItemStack(id, count, durability) { Slot = i };
                    return;
                }
            }

            // Inventory, not stacking
            for (short i = (short)InventorySlots.InventoryFirst; i <= (short)InventorySlots.InventoryLast; i++)
            {
                if (ItemStack.IsVoid(Slots[i]))
                {
                    this[i] = new ItemStack(id, count, durability) { Slot = i };
                    return;
                }
            }
        }
示例#12
0
文件: Server.cs 项目: IdentErr/c-raft
 /// <summary>
 /// Drops an item at the given location.
 /// </summary>
 /// <param name="world">The world in which the coordinates reside.</param>
 /// <param name="x">The target X coordinate.</param>
 /// <param name="y">The target Y coordinate.</param>
 /// <param name="z">The target Z coordinate.</param>
 /// <param name="stack">The stack to be dropped</param>
 /// <returns>The entity ID of the item drop.</returns>
 public int DropItem(WorldManager world, UniversalCoords coords, ItemStack stack)
 {
     int entityId = AllocateEntity();
     AddEntity(new ItemEntity(this, entityId)
     {
         World = world,
         Position = new AbsWorldCoords(new Vector3(coords.WorldX + 0.5, coords.WorldY, coords.WorldZ + 0.5)), // Put in the middle of the block (ignoring Y)
         ItemId = stack.Type,
         Count = stack.Count,
         Durability = stack.Durability
     });
     return entityId;
 }
示例#13
0
文件: Server.cs 项目: IdentErr/c-raft
 /// <summary>
 /// Drops an item based on the given player's position and rotation.
 /// </summary>
 /// <param name="client">The client to be used for position calculations.</param>
 /// <param name="stack">The stack to be dropped.</param>
 /// <returns>The entity ID of the item drop.</returns>
 public int DropItem(Client client, ItemStack stack)
 {
     return DropItem(client.Owner.World, UniversalCoords.FromAbsWorld(client.Owner.Position.X, client.Owner.Position.Y, client.Owner.Position.Z), stack);
 }
示例#14
0
文件: Mob.cs 项目: dekema2/c-raft
        /// <summary>
        /// When a player interacts with a mob (right-click) with an item / hand
        /// </summary>
        /// <param name="client">The client that is interacting</param>
        /// <param name="item">The item being used (could be Void e.g. Hand)</param>
        public void InteractWith(Client client, ItemStack item)
        {
            // TODO: create a plugin event for this action

            DoInteraction(client, item);
        }
 protected virtual void DoSaveToFile(ItemStack[] itemStack, string file)
 {
     if (this.IsEmpty())
     {
         File.Delete(file);
     }
     else
     {
         try
         {
             using (FileStream fileStream = File.Create(file + ".tmp"))
             {
                 using (BigEndianStream bigEndian = new BigEndianStream(fileStream, StreamRole.Server))
                 {
                     foreach (ItemStack stack in itemStack)
                     {
                         if (stack != null)
                         {
                             stack.Write(bigEndian);
                         }
                         else
                         {
                             ItemStack.Void.Write(bigEndian);
                         }
                     }
                 }
             }
         }
         finally
         {
             File.Delete(file);
             File.Move(file + ".tmp", file);
         }
     }
 }
示例#16
0
 protected virtual void OnItemStackChanged(ItemStack stack)
 {
     SendUpdate(stack.Slot);
 }
示例#17
0
        internal virtual void OnClicked(WindowClickPacket packet)
        {
            InterfaceClickedEventArgs e = new InterfaceClickedEventArgs(this, packet);
            if (Clicked != null)
                Clicked.Invoke(this, e);

            StartTransaction(); // Don't send update packets while we process this transaction, as that would be redundant.
            try
            {
                Interface target = null;
                switch (e.Location)
                {
                case ClickLocation.Void:
                    if (ItemStack.IsVoid(Cursor))
                    {	// Empty click in void: ignore
                        e.Cancel();
                    }
                    else if (e.RightClick)
                    {	// Right-click in void: drop item
                        Client.Server.DropItem(Client, new ItemStack(Cursor.Type, 1, Cursor.Durability));
                        Cursor.Count--;
                    }
                    else
                    {	// Left-click in void: drop stack
                        Client.Server.DropItem(Client, Cursor);
                        Cursor = ItemStack.Void;
                    }
                    return;

                case ClickLocation.Interface:
                    target = e.Interface;
                    break;

                case ClickLocation.Inventory:
                    target = Client.Inventory;
                    break;
                }

                // Ensure a true void stack for our calculations
                if (ItemStack.IsVoid(Cursor))
                    Cursor = ItemStack.Void;
                if (ItemStack.IsVoid(target.Slots[e.Slot]))
                    target[e.Slot] = ItemStack.Void;

                // The fun begins.
                if (target.Slots[e.Slot].StacksWith(Cursor))
                {
                    if (ItemStack.IsVoid(Cursor))
                    {	// Useless click
                        e.Cancel();
                    }
                    else if (e.RightClick)
                    {	// Right-click on same item
                        if (target.Slots[e.Slot].Count >= 64)
                        {	// Stack is already full: ignore
                            e.Cancel();
                        }
                        else
                        {	// Increment stack
                            target.Slots[e.Slot].Count++;
                            Cursor.Count--;
                        }
                    }
                    else
                    {	// Left-click on same item
                        int total = target.Slots[e.Slot].Count + Cursor.Count;
                        if (total <= 64)
                        {	// Move all items to stack
                            target.Slots[e.Slot].Count = unchecked((sbyte)total);
                            Cursor.Count = 0;
                        }
                        else
                        {	// Make stack 64, and put remainder in cursor
                            target.Slots[e.Slot].Count = 64;
                            Cursor.Count = unchecked((sbyte)(total - 64));
                        }
                    }
                }
                else if (!ItemStack.IsVoid(Cursor) && e.RightClick && ItemStack.IsVoid(target.Slots[e.Slot]))
                {
                    // Right-click on empty slot with items in cursor: drop one item from Cursor into slot
                    target.Slots[e.Slot].Type = Cursor.Type;
                    target.Slots[e.Slot].Durability = Cursor.Durability;
                    target.Slots[e.Slot].Count = 1;
                    Cursor.Count--;
                    if (Cursor.Count == 0)
                        Cursor = ItemStack.Void;
                }
                else if (e.RightClick && ItemStack.IsVoid(Cursor))
                {	// Right-click with empty cursor: split stack in half
                    int count = target.Slots[e.Slot].Count;
                    target.Slots[e.Slot].Count /= 2;
                    count -= target.Slots[e.Slot].Count;
                    Cursor = new ItemStack(target.Slots[e.Slot].Type, (sbyte)count, target.Slots[e.Slot].Durability);
                }
                else if (e.RightClick)
                {	// Right-click on different type: ignored click
                    e.Cancel();
                }
                else
                {	// Left-click on different type: swap stacks
                    ItemStack swap = target[e.Slot];
                    target[e.Slot] = Cursor;
                    Cursor = swap;
                }
            }
            catch (Exception ex)
            {
                e.Cancel();
                Client.SendMessage("§cInventory Error: " + ex.Message);
                Client.Logger.Log(ex);
            }
            finally
            {
                PacketHandler.SendPacket(new TransactionPacket
                {
                    Accepted = !e.Cancelled,
                    Transaction = e.Transaction,
                    WindowId = e.Interface.Handle
                });
                EndTransaction();
            }
        }
示例#18
0
 private void RemoveFuel()
 {
     FuelSlot.Count--;
     if (FuelSlot.Count == 0)
         FuelSlot = ItemStack.Void;
     foreach (var fInterface in Interfaces)
     {
         fInterface[(short)FurnaceSlots.Fuel] = new ItemStack(FuelSlot.Type, FuelSlot.Count, FuelSlot.Durability);
         fInterface.SendUpdate((short)FurnaceSlots.Fuel);
     }
 }
示例#19
0
        protected override bool SharedSlotClicked(WindowClickPacket packet)
        {
            if (packet.Slot == (short)FurnaceSlots.Output)
            {
                if (Container[packet.Slot].IsVoid())
                {
                    Owner.Client.SendPacket(new TransactionPacket
                    {
                        Accepted = false,
                        Transaction = packet.Transaction,
                        WindowId = packet.WindowId
                    });
                    return false;
                }
                ItemStack output = Container[packet.Slot];
                if (!Cursor.IsVoid())
                {
                    if (!Cursor.StacksWith(output) || (Cursor.StacksWith(output) && Cursor.Count >= 64))
                    {
                        Owner.Client.SendPacket(new TransactionPacket
                        {
                            Accepted = false,
                            Transaction = packet.Transaction,
                            WindowId = packet.WindowId
                        });
                        return false;
                    }
                }
                ItemStack newOutput = ItemStack.Void;
                if (Cursor.IsVoid())
                {
                    Cursor = new ItemStack(output.Type, output.Count, output.Durability);
                    Cursor.Slot = -1;
                }
                else
                {
                    int freeSpaceInCursor = 64 - Cursor.Count;
                    int takeFromOutput = (output.Count > freeSpaceInCursor ? freeSpaceInCursor : output.Count);
                    Cursor.Count += (sbyte)takeFromOutput;
                    if (takeFromOutput < output.Count)
                        newOutput = new ItemStack(output.Type, (sbyte)(output.Count - takeFromOutput), output.Durability);
                }
                Container.ChangeSlot(Handle, packet.Slot, newOutput);
                this[(short)FurnaceSlots.Output] = newOutput;
                return false;
            }

            return base.SharedSlotClicked(packet);
        }
示例#20
0
文件: Inventory.cs 项目: Nirad/c-raft
        public void AddItem(short id, sbyte count, short durability, bool isInGame =true)
        {
            // Quickslots, stacking
            for (short i = (short)InventorySlots.QuickSlotFirst; i <= (short)InventorySlots.QuickSlotLast; i++)
            {
                if (!Slots[i].IsVoid() && Slots[i].Type == id && Slots[i].Durability == durability)
                {
                    if (Slots[i].Count + count <= 64)
                    {
                        Slots[i].Count += count;
                        return;
                    }
                    count -= (sbyte)(64 - Slots[i].Count);
                    Slots[i].Count = 64;
                }
            }

            // Inventory, stacking
            for (short i = (short)InventorySlots.InventoryFirst; i <= (short)InventorySlots.InventoryLast; i++)
            {
                if (!Slots[i].IsVoid() && Slots[i].Type == id && Slots[i].Durability == durability)
                {
                    if (Slots[i].Count + count <= 64)
                    {
                        Slots[i].Count += count;
                        return;
                    }
                    count -= (sbyte)(64 - Slots[i].Count);
                    Slots[i].Count = 64;
                }
            }

            // Quickslots, not stacking
            for (short i = (short)InventorySlots.QuickSlotFirst; i <= (short)InventorySlots.QuickSlotLast; i++)
            {
                if (Slots[i].IsVoid())
                {
                    if (isInGame)
                    {
                        Owner.Client.SendPacket(new ChatMessagePacket {Message = "Placing in slot " + i});
                    }
                    this[i] = new ItemStack(id, count, durability) { Slot = i };
                    return;
                }
            }

            // Inventory, not stacking
            for (short i = (short)InventorySlots.InventoryFirst; i <= (short)InventorySlots.InventoryLast; i++)
            {
                if (Slots[i].IsVoid())
                {
                    this[i] = new ItemStack(id, count, durability) { Slot = i };
                    return;
                }
            }

            Owner.MarkToSave();
        }
 protected virtual void DoLoadFromFile(ItemStack[] itemStack, string file)
 {
     if (File.Exists(file))
     {
         using (FileStream containerStream = File.Open(file, FileMode.Open, FileAccess.Read))
         {
             using (Net.BigEndianStream bigEndian = new Net.BigEndianStream(containerStream, StreamRole.Server))
             {
                 for (int i = 0; i < itemStack.Length; i++)
                 {
                     itemStack[i] = new ItemStack(bigEndian);
                 }
             }
         }
     }
 }
示例#22
0
 /// <summary>
 /// Drops an item at the given location.
 /// </summary>
 /// <param name="world">The world in which the coordinates reside.</param>
 /// <param name="x">The target X coordinate.</param>
 /// <param name="y">The target Y coordinate.</param>
 /// <param name="z">The target Z coordinate.</param>
 /// <param name="stack">The stack to be dropped</param>
 /// <returns>The entity ID of the item drop.</returns>
 public int DropItem(WorldManager world, int x, int y, int z, ItemStack stack)
 {
     int entityId = AllocateEntity();
     AddEntity(new ItemEntity(this, entityId)
     {
         World = world,
         Position = new World.Vector3(x + 0.5, y, z + 0.5),
         ItemId = stack.Type,
         Count = stack.Count,
         Durability = stack.Durability
     });
     return entityId;
 }
示例#23
0
文件: Mob.cs 项目: dekema2/c-raft
 protected virtual void DoInteraction(Client client, ItemStack item)
 {
 }
示例#24
0
文件: Server.cs 项目: dekema2/c-raft
        /// <summary>
        /// Drops an item at the given location.
        /// </summary>
        /// <param name="world">The world in which the coordinates reside.</param>
        /// <param name="coords">The target coordinate</param>
        /// <param name="stack">The stack to be dropped</param>
        /// <param name="velocity">An optional velocity (the velocity will be clamped to -0.4 and 0.4 on each axis)</param>
        /// <returns>The entity ID of the item drop.</returns>
        public int DropItem(WorldManager world, UniversalCoords coords, ItemStack stack, Vector3 velocity = new Vector3())
        {
            int entityId = AllocateEntity();

            bool sendVelocity = false;
            if (velocity != Vector3.Origin)
            {
                velocity = new Vector3(velocity.X.Clamp(-0.4, 0.4), velocity.Y.Clamp(-0.4, 0.4), velocity.Z.Clamp(-0.4, 0.4));
                sendVelocity = true;
            }

            AddEntity(new ItemEntity(this, entityId)
            {
                World = world,
                Position = new AbsWorldCoords(new Vector3(coords.WorldX + 0.5, coords.WorldY, coords.WorldZ + 0.5)), // Put in the middle of the block (ignoring Y)
                ItemId = stack.Type,
                Count = stack.Count,
                Velocity = velocity,
                Durability = stack.Durability
            });

            if (sendVelocity)
                SendPacketToNearbyPlayers(world, coords, new EntityVelocityPacket { EntityId = entityId, VelocityX = (short)(velocity.X * 8000), VelocityY = (short)(velocity.Y * 8000), VelocityZ = (short)(velocity.Z * 8000) });

            return entityId;
        }
示例#25
0
文件: Server.cs 项目: IdentErr/c-raft
 /// <summary>
 /// Drops an item based on the given player's position and rotation.
 /// </summary>
 /// <param name="player">The player to be used for position calculations.</param>
 /// <param name="stack">The stack to be dropped.</param>
 /// <returns>The entity ID of the item drop.</returns>
 public int DropItem(Player player, ItemStack stack)
 {
     //todo - proper drop
     return DropItem(player.World, UniversalCoords.FromAbsWorld(player.Position.X + 4, player.Position.Y, player.Position.Z), stack);
 }
示例#26
0
        internal static ItemStack Read(PacketReader stream)
        {
            ItemStack retval = new ItemStack(stream.ReadShort());
            if (retval.Type >= 0)
            {
                retval.Count = stream.ReadSByte();
                retval.Durability = stream.ReadShort();

                // TODO: Implement extra data read (enchantment) and items

                if (retval.Durability > 0 || retval.IsEnchantable())
                    stream.ReadShort();
            }
            return retval;
        }
示例#27
0
 public override void Read(BigEndianStream stream)
 {
     WindowId = stream.ReadSByte();
     Items = new ItemStack[stream.ReadShort()];
     for (int i = 0; i < Items.Length; i++)
         Items[i] = ItemStack.Read(stream);
 }
示例#28
0
 public static bool IsVoid(ItemStack stack)
 {
     return stack == null || stack.Count < 1 || stack.Type <= 0;
 }
示例#29
0
 private SmeltingRecipe GetSmeltingRecipe(ItemStack item)
 {
     SmeltingRecipe recipe = null;
     if (!ItemStack.IsVoid(item))
         recipe = SmeltingRecipe.GetRecipe(Server.GetSmeltingRecipes(), item);
     return recipe;
 }
示例#30
0
 public void ChangeOutput(ItemStack newItem)
 {
     lock (_instanceLock)
     {
         if (ItemStack.IsVoid(newItem))
             OutputSlot = ItemStack.Void;
         else
         {
             OutputSlot.Type = newItem.Type;
             OutputSlot.Count = newItem.Count;
             OutputSlot.Durability = newItem.Durability;
         }
         foreach (var fInterface in Interfaces)
         {
             fInterface[(short)FurnaceSlots.Output] = OutputSlot;
             fInterface.SendUpdate((short)FurnaceSlots.Output);
         }
     }
     TryBurn();
 }