diff --git a/TrueCraft.API/ItemStack.cs b/TrueCraft.API/ItemStack.cs index 406bc7a..397a742 100644 --- a/TrueCraft.API/ItemStack.cs +++ b/TrueCraft.API/ItemStack.cs @@ -59,7 +59,7 @@ namespace TrueCraft.API Nbt = nbt; if (Count == 0) { - Id = -1; + ID = -1; Metadata = 0; Nbt = null; } @@ -68,7 +68,7 @@ namespace TrueCraft.API public static ItemStack FromStream(IMinecraftStream stream) { var slot = ItemStack.EmptyStack; - slot.Id = stream.ReadInt16(); + slot.ID = stream.ReadInt16(); if (slot.Empty) return slot; slot.Count = stream.ReadInt8(); @@ -86,7 +86,7 @@ namespace TrueCraft.API public void WriteTo(IMinecraftStream stream) { - stream.WriteInt16(Id); + stream.WriteInt16(ID); if (Empty) return; stream.WriteInt8(Count); @@ -106,7 +106,7 @@ namespace TrueCraft.API public static ItemStack FromNbt(NbtCompound compound) { var s = ItemStack.EmptyStack; - s.Id = compound.Get("id").Value; + s.ID = compound.Get("id").Value; s.Metadata = compound.Get("Damage").Value; s.Count = (sbyte)compound.Get("Count").Value; s.Index = compound.Get("Slot").Value; @@ -118,7 +118,7 @@ namespace TrueCraft.API public NbtCompound ToNbt() { var c = new NbtCompound(); - c.Add(new NbtShort("id", Id)); + c.Add(new NbtShort("id", ID)); c.Add(new NbtShort("Damage", Metadata)); c.Add(new NbtByte("Count", (byte)Count)); c.Add(new NbtByte("Slot", (byte)Index)); @@ -130,10 +130,10 @@ namespace TrueCraft.API [NbtIgnore] public bool Empty { - get { return Id == -1; } + get { return ID == -1; } } - public short Id + public short ID { get { return _Id; } set @@ -181,7 +181,7 @@ namespace TrueCraft.API { if (Empty) return "(Empty)"; - string result = "ID: " + Id; + string result = "ID: " + ID; if (Count != 1) result += "; Count: " + Count; if (Metadata != 0) result += "; Metadata: " + Metadata; if (Nbt != null) result += Environment.NewLine + Nbt.ToString(); @@ -190,7 +190,7 @@ namespace TrueCraft.API public object Clone() { - return new ItemStack(Id, Count, Metadata, Nbt); + return new ItemStack(ID, Count, Metadata, Nbt); } [NbtIgnore] diff --git a/TrueCraft.API/Logic/IBlockProvider.cs b/TrueCraft.API/Logic/IBlockProvider.cs index 551190d..988623b 100644 --- a/TrueCraft.API/Logic/IBlockProvider.cs +++ b/TrueCraft.API/Logic/IBlockProvider.cs @@ -1,4 +1,6 @@ using System; +using TrueCraft.API.World; +using TrueCraft.API.Networking; namespace TrueCraft.API.Logic { @@ -12,5 +14,10 @@ namespace TrueCraft.API.Logic byte LightModifier { get; } string DisplayName { get; } Tuple GetTextureMap(byte metadata); + bool BlockRightClicked(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user); + bool BlockPlaced(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user); + void BlockMined(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user); + void BlockUpdate(BlockDescriptor descriptor, IWorld world); + void BlockScheduledEvent(BlockDescriptor descriptor, IWorld world, object data); } } \ No newline at end of file diff --git a/TrueCraft.API/MetadataSlot.cs b/TrueCraft.API/MetadataSlot.cs index 0227555..51ed167 100644 --- a/TrueCraft.API/MetadataSlot.cs +++ b/TrueCraft.API/MetadataSlot.cs @@ -34,8 +34,8 @@ namespace TrueCraft.API public override void WriteTo(IMinecraftStream stream, byte index) { stream.WriteUInt8(GetKey(index)); - stream.WriteInt16(Value.Id); - if (Value.Id != -1) + stream.WriteInt16(Value.ID); + if (Value.ID != -1) { stream.WriteInt8(Value.Count); stream.WriteInt16(Value.Metadata); diff --git a/TrueCraft.API/TrueCraft.API.csproj b/TrueCraft.API/TrueCraft.API.csproj index 73f39ac..ac52d7a 100644 --- a/TrueCraft.API/TrueCraft.API.csproj +++ b/TrueCraft.API/TrueCraft.API.csproj @@ -68,7 +68,6 @@ - @@ -80,6 +79,7 @@ + diff --git a/TrueCraft.API/Windows/IWindow.cs b/TrueCraft.API/Windows/IWindow.cs index 14341ba..c12e4a8 100644 --- a/TrueCraft.API/Windows/IWindow.cs +++ b/TrueCraft.API/Windows/IWindow.cs @@ -19,5 +19,9 @@ namespace TrueCraft.API.Windows /// Gets an array of all slots in this window. Suitable for sending to clients over the network. /// ItemStack[] GetSlots(); + /// + /// Adds the specified item stack to this window, merging with established slots as neccessary. + /// + bool PickUpStack(ItemStack slot); } } \ No newline at end of file diff --git a/TrueCraft.API/World/BlockChangeEventArgs.cs b/TrueCraft.API/World/BlockChangeEventArgs.cs index e212746..f527347 100644 --- a/TrueCraft.API/World/BlockChangeEventArgs.cs +++ b/TrueCraft.API/World/BlockChangeEventArgs.cs @@ -4,7 +4,7 @@ namespace TrueCraft.API.World { public class BlockChangeEventArgs : EventArgs { - public BlockChangeEventArgs(Coordinates3D position, BlockData oldBlock, BlockData newBlock) + public BlockChangeEventArgs(Coordinates3D position, BlockDescriptor oldBlock, BlockDescriptor newBlock) { Position = position; OldBlock = oldBlock; @@ -12,7 +12,7 @@ namespace TrueCraft.API.World } public Coordinates3D Position; - public BlockData OldBlock; - public BlockData NewBlock; + public BlockDescriptor OldBlock; + public BlockDescriptor NewBlock; } } \ No newline at end of file diff --git a/TrueCraft.API/World/BlockData.cs b/TrueCraft.API/World/BlockDescriptor.cs similarity index 70% rename from TrueCraft.API/World/BlockData.cs rename to TrueCraft.API/World/BlockDescriptor.cs index 1f553a1..f524a19 100644 --- a/TrueCraft.API/World/BlockData.cs +++ b/TrueCraft.API/World/BlockDescriptor.cs @@ -2,11 +2,12 @@ namespace TrueCraft.API.World { - public struct BlockData + public struct BlockDescriptor { public byte ID; public byte Metadata; public byte BlockLight; public byte SkyLight; + public Coordinates3D Coordinates; } } \ No newline at end of file diff --git a/TrueCraft.API/World/IWorld.cs b/TrueCraft.API/World/IWorld.cs index f6b74eb..1b1bd13 100644 --- a/TrueCraft.API/World/IWorld.cs +++ b/TrueCraft.API/World/IWorld.cs @@ -18,7 +18,7 @@ namespace TrueCraft.API.World byte GetBlockID(Coordinates3D coordinates); byte GetMetadata(Coordinates3D coordinates); byte GetSkyLight(Coordinates3D coordinates); - BlockData GetBlockData(Coordinates3D coordinates); + BlockDescriptor GetBlockData(Coordinates3D coordinates); void SetBlockID(Coordinates3D coordinates, byte value); void SetMetadata(Coordinates3D coordinates, byte value); void SetSkyLight(Coordinates3D coordinates, byte value); diff --git a/TrueCraft.Core/Logic/BlockProvider.cs b/TrueCraft.Core/Logic/BlockProvider.cs index 33764cb..cbc76ce 100644 --- a/TrueCraft.Core/Logic/BlockProvider.cs +++ b/TrueCraft.Core/Logic/BlockProvider.cs @@ -1,5 +1,8 @@ using System; using TrueCraft.API.Logic; +using TrueCraft.API.World; +using TrueCraft.API; +using TrueCraft.API.Networking; namespace TrueCraft.Core.Logic { @@ -8,6 +11,34 @@ namespace TrueCraft.Core.Logic /// public abstract class BlockProvider : IBlockProvider, IItemProvider { + public virtual bool BlockRightClicked(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user) + { + return true; + } + + public virtual bool BlockPlaced(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user) + { + throw new NotImplementedException(); + } + + public virtual void BlockMined(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user) + { + // TODO: Spawn item entity + var stack = new ItemStack(descriptor.ID, 1, descriptor.Metadata); + user.Inventory.PickUpStack(stack); + world.SetBlockID(descriptor.Coordinates, 0); + } + + public virtual void BlockUpdate(BlockDescriptor descriptor, IWorld world) + { + // This space intentionally left blank + } + + public virtual void BlockScheduledEvent(BlockDescriptor descriptor, IWorld world, object data) + { + // This space intentionally left blank + } + short IItemProvider.ID { get diff --git a/TrueCraft.Core/Networking/Packets/WindowItemsPacket.cs b/TrueCraft.Core/Networking/Packets/WindowItemsPacket.cs index b7175b8..813021e 100644 --- a/TrueCraft.Core/Networking/Packets/WindowItemsPacket.cs +++ b/TrueCraft.Core/Networking/Packets/WindowItemsPacket.cs @@ -45,7 +45,7 @@ namespace TrueCraft.Core.Networking.Packets stream.WriteInt16((short)Items.Length); for (int i = 0; i < Items.Length; i++) { - stream.WriteInt16(Items[i].Id); + stream.WriteInt16(Items[i].ID); if (!Items[i].Empty) { stream.WriteInt8(Items[i].Count); diff --git a/TrueCraft.Core/Windows/InventoryWindow.cs b/TrueCraft.Core/Windows/InventoryWindow.cs index 9073069..8e92c7c 100644 --- a/TrueCraft.Core/Windows/InventoryWindow.cs +++ b/TrueCraft.Core/Windows/InventoryWindow.cs @@ -69,12 +69,12 @@ namespace TrueCraft.Core.Windows return Hotbar; } - public bool PickUpStack(ItemStack slot) + public override bool PickUpStack(ItemStack slot) { var area = MainInventory; foreach (var item in Hotbar.Items) { - if (item.Empty || (slot.Id == item.Id && slot.Metadata == item.Metadata)) + if (item.Empty || (slot.ID == item.ID && slot.Metadata == item.Metadata)) //&& item.Count + slot.Count < Item.GetMaximumStackSize(new ItemDescriptor(item.Id, item.Metadata)))) // TODO { area = Hotbar; diff --git a/TrueCraft.Core/Windows/Window.cs b/TrueCraft.Core/Windows/Window.cs index 4ff3d33..03511be 100644 --- a/TrueCraft.Core/Windows/Window.cs +++ b/TrueCraft.Core/Windows/Window.cs @@ -118,6 +118,11 @@ namespace TrueCraft.Core.Windows } } + public virtual bool PickUpStack(ItemStack slot) + { + throw new NotSupportedException(); + } + protected internal virtual void OnWindowChange(WindowChangeEventArgs e) { if (WindowChange != null) diff --git a/TrueCraft.Core/Windows/WindowArea.cs b/TrueCraft.Core/Windows/WindowArea.cs index 4fc91c4..1135586 100644 --- a/TrueCraft.Core/Windows/WindowArea.cs +++ b/TrueCraft.Core/Windows/WindowArea.cs @@ -44,7 +44,7 @@ namespace TrueCraft.Core.Windows { if (this[i].Empty && emptyIndex == -1) emptyIndex = i; - else if (this[i].Id == item.Id && + else if (this[i].ID == item.ID && this[i].Metadata == item.Metadata && this[i].Count < maximumStackSize) { @@ -54,12 +54,12 @@ namespace TrueCraft.Core.Windows from[index] = ItemStack.EmptyStack; if (this[i].Count + item.Count > maximumStackSize) { - item = new ItemStack(item.Id, (sbyte)(item.Count - (maximumStackSize - this[i].Count)), + item = new ItemStack(item.ID, (sbyte)(item.Count - (maximumStackSize - this[i].Count)), item.Metadata, item.Nbt); - this[i] = new ItemStack(item.Id, (sbyte)maximumStackSize, item.Metadata, item.Nbt); + this[i] = new ItemStack(item.ID, (sbyte)maximumStackSize, item.Metadata, item.Nbt); continue; } - this[i] = new ItemStack(item.Id, (sbyte)(this[i].Count + item.Count), item.Metadata); + this[i] = new ItemStack(item.ID, (sbyte)(this[i].Count + item.Count), item.Metadata); return i; } } diff --git a/TrueCraft.Core/World/World.cs b/TrueCraft.Core/World/World.cs index bcb66f6..b7f8370 100644 --- a/TrueCraft.Core/World/World.cs +++ b/TrueCraft.Core/World/World.cs @@ -152,21 +152,22 @@ namespace TrueCraft.Core.World return chunk.GetBlockLight(coordinates); } - public BlockData GetBlockData(Coordinates3D coordinates) + public BlockDescriptor GetBlockData(Coordinates3D coordinates) { IChunk chunk; - coordinates = FindBlockPosition(coordinates, out chunk); - return GetBlockDataFromChunk(coordinates, chunk); + var adjustedCoordinates = FindBlockPosition(coordinates, out chunk); + return GetBlockDataFromChunk(adjustedCoordinates, chunk, coordinates); } - private BlockData GetBlockDataFromChunk(Coordinates3D adjustedCoordinates, IChunk chunk) + private BlockDescriptor GetBlockDataFromChunk(Coordinates3D adjustedCoordinates, IChunk chunk, Coordinates3D coordinates) { - return new BlockData + return new BlockDescriptor { ID = chunk.GetBlockID(adjustedCoordinates), Metadata = chunk.GetMetadata(adjustedCoordinates), BlockLight = chunk.GetBlockLight(adjustedCoordinates), - SkyLight = chunk.GetSkyLight(adjustedCoordinates) + SkyLight = chunk.GetSkyLight(adjustedCoordinates), + Coordinates = coordinates }; } @@ -174,24 +175,24 @@ namespace TrueCraft.Core.World { IChunk chunk; var adjustedCoordinates = FindBlockPosition(coordinates, out chunk); - BlockData old = new BlockData(); + BlockDescriptor old = new BlockDescriptor(); if (BlockChanged != null) - old = GetBlockDataFromChunk(adjustedCoordinates, chunk); + old = GetBlockDataFromChunk(adjustedCoordinates, chunk, coordinates); chunk.SetBlockID(adjustedCoordinates, value); if (BlockChanged != null) - BlockChanged(this, new BlockChangeEventArgs(coordinates, old, GetBlockDataFromChunk(adjustedCoordinates, chunk))); + BlockChanged(this, new BlockChangeEventArgs(coordinates, old, GetBlockDataFromChunk(adjustedCoordinates, chunk, coordinates))); } public void SetMetadata(Coordinates3D coordinates, byte value) { IChunk chunk; var adjustedCoordinates = FindBlockPosition(coordinates, out chunk); - BlockData old = new BlockData(); + BlockDescriptor old = new BlockDescriptor(); if (BlockChanged != null) - old = GetBlockDataFromChunk(adjustedCoordinates, chunk); + old = GetBlockDataFromChunk(adjustedCoordinates, chunk, coordinates); chunk.SetMetadata(adjustedCoordinates, value); if (BlockChanged != null) - BlockChanged(this, new BlockChangeEventArgs(coordinates, old, GetBlockDataFromChunk(adjustedCoordinates, chunk))); + BlockChanged(this, new BlockChangeEventArgs(coordinates, old, GetBlockDataFromChunk(adjustedCoordinates, chunk, coordinates))); } public void SetSkyLight(Coordinates3D coordinates, byte value) diff --git a/TrueCraft/Handlers/InteractionHandlers.cs b/TrueCraft/Handlers/InteractionHandlers.cs index f212ef7..0e90993 100644 --- a/TrueCraft/Handlers/InteractionHandlers.cs +++ b/TrueCraft/Handlers/InteractionHandlers.cs @@ -17,6 +17,7 @@ namespace TrueCraft.Handlers var client = (RemoteClient)_client; var world = _client.World; var position = new Coordinates3D(packet.X, packet.Y, packet.Z); + var descriptor = world.GetBlockData(position); switch (packet.PlayerAction) { case PlayerDiggingPacket.Action.DropItem: @@ -26,10 +27,8 @@ namespace TrueCraft.Handlers // TODO break; case PlayerDiggingPacket.Action.StopDigging: - // TODO: Do this properly - var stack = new ItemStack(world.GetBlockID(position), 1, world.GetMetadata(position)); - client.InventoryWindow.PickUpStack(stack); - world.SetBlockID(position, 0); + var provider = server.BlockRepository.GetBlockProvider(descriptor.ID); + provider.BlockMined(descriptor, packet.Face, world, client); break; } } @@ -41,7 +40,7 @@ namespace TrueCraft.Handlers var slot = client.SelectedItem; var position = new Coordinates3D(packet.X, packet.Y, packet.Z); - BlockData? block = null; + BlockDescriptor? block = null; if (position != -Coordinates3D.One) { if (position.DistanceTo((Coordinates3D)client.Entity.Position) > 10 /* TODO: Reach */) @@ -56,7 +55,16 @@ namespace TrueCraft.Handlers bool use = true; if (block != null) { - // TODO: Call the handler for the block being clicked on and possible cancel use + var provider = server.BlockRepository.GetBlockProvider(block.Value.ID); + if (!provider.BlockRightClicked(block.Value, packet.Face, client.World, client)) + { + position += MathHelper.BlockFaceToCoordinates(packet.Face); + var oldID = client.World.GetBlockID(position); + var oldMeta = client.World.GetMetadata(position); + client.QueuePacket(new BlockChangePacket(position.X, (sbyte)position.Y, position.Z, (sbyte)oldID, (sbyte)oldMeta)); + client.QueuePacket(new SetSlotPacket(0, client.SelectedSlot, client.SelectedItem.ID, client.SelectedItem.Count, client.SelectedItem.Metadata)); + return; + } } if (!slot.Empty) { @@ -64,7 +72,7 @@ namespace TrueCraft.Handlers { // Temporary: just place the damn thing position += MathHelper.BlockFaceToCoordinates(packet.Face); - client.World.SetBlockID(position, (byte)slot.Id); + client.World.SetBlockID(position, (byte)slot.ID); client.World.SetMetadata(position, (byte)slot.Metadata); slot.Count--; client.Inventory[client.SelectedSlot] = slot; diff --git a/TrueCraft/MultiplayerServer.cs b/TrueCraft/MultiplayerServer.cs index 2b7fde5..54e0315 100644 --- a/TrueCraft/MultiplayerServer.cs +++ b/TrueCraft/MultiplayerServer.cs @@ -173,7 +173,7 @@ namespace TrueCraft if (ExecutingTick) return; // TODO: Warn about skipped updates? ExecutingTick = true; - for (int i = 0; i < Clients.Count; i++) + for (int i = 0; i < Clients.Count && i >= 0; i++) { var client = Clients[i] as RemoteClient; var sendTimeout = DateTime.Now.AddMilliseconds(50); diff --git a/TrueCraft/Program.cs b/TrueCraft/Program.cs index 3a51d62..6eccf90 100644 --- a/TrueCraft/Program.cs +++ b/TrueCraft/Program.cs @@ -21,7 +21,7 @@ namespace TrueCraft // TODO: Make this more flexible var server = new MultiplayerServer(); server.AddWorld(new World("default", new StandardGenerator())); - server.AddLogProvider(new ConsoleLogProvider()); + server.AddLogProvider(new ConsoleLogProvider(LogCategory.Notice | LogCategory.Warning | LogCategory.Error | LogCategory.Debug)); #if DEBUG server.AddLogProvider(new FileLogProvider(new StreamWriter("packets.log", false), LogCategory.Packets)); #endif diff --git a/TrueCraft/RemoteClient.cs b/TrueCraft/RemoteClient.cs index 72ca13d..06ef563 100644 --- a/TrueCraft/RemoteClient.cs +++ b/TrueCraft/RemoteClient.cs @@ -158,7 +158,7 @@ namespace TrueCraft void HandleWindowChange(object sender, WindowChangeEventArgs e) { - QueuePacket(new SetSlotPacket(0, (short)e.SlotIndex, e.Value.Id, e.Value.Count, e.Value.Metadata)); + QueuePacket(new SetSlotPacket(0, (short)e.SlotIndex, e.Value.ID, e.Value.Count, e.Value.Metadata)); } private static ChunkDataPacket CreatePacket(IChunk chunk)