// 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; }
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); }
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(); }
// 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; }
/// <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; }
/// <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); }
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; }
/// <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; }
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)); } }
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; } } }
/// <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; }
/// <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); }
/// <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); } } }
protected virtual void OnItemStackChanged(ItemStack stack) { SendUpdate(stack.Slot); }
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(); } }
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); } }
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); }
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); } } } } }
/// <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; }
protected virtual void DoInteraction(Client client, ItemStack item) { }
/// <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; }
/// <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); }
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; }
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); }
public static bool IsVoid(ItemStack stack) { return stack == null || stack.Count < 1 || stack.Type <= 0; }
private SmeltingRecipe GetSmeltingRecipe(ItemStack item) { SmeltingRecipe recipe = null; if (!ItemStack.IsVoid(item)) recipe = SmeltingRecipe.GetRecipe(Server.GetSmeltingRecipes(), item); return recipe; }
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(); }