Implement mining via block providers

This commit is contained in:
Drew DeVault 2015-01-26 17:05:26 -07:00
parent 61bd2d32d3
commit c0585fc714
18 changed files with 103 additions and 46 deletions

View File

@ -59,7 +59,7 @@ namespace TrueCraft.API
Nbt = nbt; Nbt = nbt;
if (Count == 0) if (Count == 0)
{ {
Id = -1; ID = -1;
Metadata = 0; Metadata = 0;
Nbt = null; Nbt = null;
} }
@ -68,7 +68,7 @@ namespace TrueCraft.API
public static ItemStack FromStream(IMinecraftStream stream) public static ItemStack FromStream(IMinecraftStream stream)
{ {
var slot = ItemStack.EmptyStack; var slot = ItemStack.EmptyStack;
slot.Id = stream.ReadInt16(); slot.ID = stream.ReadInt16();
if (slot.Empty) if (slot.Empty)
return slot; return slot;
slot.Count = stream.ReadInt8(); slot.Count = stream.ReadInt8();
@ -86,7 +86,7 @@ namespace TrueCraft.API
public void WriteTo(IMinecraftStream stream) public void WriteTo(IMinecraftStream stream)
{ {
stream.WriteInt16(Id); stream.WriteInt16(ID);
if (Empty) if (Empty)
return; return;
stream.WriteInt8(Count); stream.WriteInt8(Count);
@ -106,7 +106,7 @@ namespace TrueCraft.API
public static ItemStack FromNbt(NbtCompound compound) public static ItemStack FromNbt(NbtCompound compound)
{ {
var s = ItemStack.EmptyStack; var s = ItemStack.EmptyStack;
s.Id = compound.Get<NbtShort>("id").Value; s.ID = compound.Get<NbtShort>("id").Value;
s.Metadata = compound.Get<NbtShort>("Damage").Value; s.Metadata = compound.Get<NbtShort>("Damage").Value;
s.Count = (sbyte)compound.Get<NbtByte>("Count").Value; s.Count = (sbyte)compound.Get<NbtByte>("Count").Value;
s.Index = compound.Get<NbtByte>("Slot").Value; s.Index = compound.Get<NbtByte>("Slot").Value;
@ -118,7 +118,7 @@ namespace TrueCraft.API
public NbtCompound ToNbt() public NbtCompound ToNbt()
{ {
var c = new NbtCompound(); 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 NbtShort("Damage", Metadata));
c.Add(new NbtByte("Count", (byte)Count)); c.Add(new NbtByte("Count", (byte)Count));
c.Add(new NbtByte("Slot", (byte)Index)); c.Add(new NbtByte("Slot", (byte)Index));
@ -130,10 +130,10 @@ namespace TrueCraft.API
[NbtIgnore] [NbtIgnore]
public bool Empty public bool Empty
{ {
get { return Id == -1; } get { return ID == -1; }
} }
public short Id public short ID
{ {
get { return _Id; } get { return _Id; }
set set
@ -181,7 +181,7 @@ namespace TrueCraft.API
{ {
if (Empty) if (Empty)
return "(Empty)"; return "(Empty)";
string result = "ID: " + Id; string result = "ID: " + ID;
if (Count != 1) result += "; Count: " + Count; if (Count != 1) result += "; Count: " + Count;
if (Metadata != 0) result += "; Metadata: " + Metadata; if (Metadata != 0) result += "; Metadata: " + Metadata;
if (Nbt != null) result += Environment.NewLine + Nbt.ToString(); if (Nbt != null) result += Environment.NewLine + Nbt.ToString();
@ -190,7 +190,7 @@ namespace TrueCraft.API
public object Clone() public object Clone()
{ {
return new ItemStack(Id, Count, Metadata, Nbt); return new ItemStack(ID, Count, Metadata, Nbt);
} }
[NbtIgnore] [NbtIgnore]

View File

@ -1,4 +1,6 @@
using System; using System;
using TrueCraft.API.World;
using TrueCraft.API.Networking;
namespace TrueCraft.API.Logic namespace TrueCraft.API.Logic
{ {
@ -12,5 +14,10 @@ namespace TrueCraft.API.Logic
byte LightModifier { get; } byte LightModifier { get; }
string DisplayName { get; } string DisplayName { get; }
Tuple<int, int> GetTextureMap(byte metadata); Tuple<int, int> 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);
} }
} }

View File

@ -34,8 +34,8 @@ namespace TrueCraft.API
public override void WriteTo(IMinecraftStream stream, byte index) public override void WriteTo(IMinecraftStream stream, byte index)
{ {
stream.WriteUInt8(GetKey(index)); stream.WriteUInt8(GetKey(index));
stream.WriteInt16(Value.Id); stream.WriteInt16(Value.ID);
if (Value.Id != -1) if (Value.ID != -1)
{ {
stream.WriteInt8(Value.Count); stream.WriteInt8(Value.Count);
stream.WriteInt16(Value.Metadata); stream.WriteInt16(Value.Metadata);

View File

@ -68,7 +68,6 @@
<Compile Include="Server\IEventScheduler.cs" /> <Compile Include="Server\IEventScheduler.cs" />
<Compile Include="Server\IEntityManager.cs" /> <Compile Include="Server\IEntityManager.cs" />
<Compile Include="Entities\IEntity.cs" /> <Compile Include="Entities\IEntity.cs" />
<Compile Include="World\BlockData.cs" />
<Compile Include="World\BlockChangeEventArgs.cs" /> <Compile Include="World\BlockChangeEventArgs.cs" />
<Compile Include="Windows\IWindow.cs" /> <Compile Include="Windows\IWindow.cs" />
<Compile Include="Windows\IWindowArea.cs" /> <Compile Include="Windows\IWindowArea.cs" />
@ -80,6 +79,7 @@
<Compile Include="BlockFace.cs" /> <Compile Include="BlockFace.cs" />
<Compile Include="Server\PlayerJoinedEventArgs.cs" /> <Compile Include="Server\PlayerJoinedEventArgs.cs" />
<Compile Include="Logic\IBlockRepository.cs" /> <Compile Include="Logic\IBlockRepository.cs" />
<Compile Include="World\BlockDescriptor.cs" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup /> <ItemGroup />

View File

@ -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. /// Gets an array of all slots in this window. Suitable for sending to clients over the network.
/// </summary> /// </summary>
ItemStack[] GetSlots(); ItemStack[] GetSlots();
/// <summary>
/// Adds the specified item stack to this window, merging with established slots as neccessary.
/// </summary>
bool PickUpStack(ItemStack slot);
} }
} }

View File

@ -4,7 +4,7 @@ namespace TrueCraft.API.World
{ {
public class BlockChangeEventArgs : EventArgs public class BlockChangeEventArgs : EventArgs
{ {
public BlockChangeEventArgs(Coordinates3D position, BlockData oldBlock, BlockData newBlock) public BlockChangeEventArgs(Coordinates3D position, BlockDescriptor oldBlock, BlockDescriptor newBlock)
{ {
Position = position; Position = position;
OldBlock = oldBlock; OldBlock = oldBlock;
@ -12,7 +12,7 @@ namespace TrueCraft.API.World
} }
public Coordinates3D Position; public Coordinates3D Position;
public BlockData OldBlock; public BlockDescriptor OldBlock;
public BlockData NewBlock; public BlockDescriptor NewBlock;
} }
} }

View File

@ -2,11 +2,12 @@
namespace TrueCraft.API.World namespace TrueCraft.API.World
{ {
public struct BlockData public struct BlockDescriptor
{ {
public byte ID; public byte ID;
public byte Metadata; public byte Metadata;
public byte BlockLight; public byte BlockLight;
public byte SkyLight; public byte SkyLight;
public Coordinates3D Coordinates;
} }
} }

View File

@ -18,7 +18,7 @@ namespace TrueCraft.API.World
byte GetBlockID(Coordinates3D coordinates); byte GetBlockID(Coordinates3D coordinates);
byte GetMetadata(Coordinates3D coordinates); byte GetMetadata(Coordinates3D coordinates);
byte GetSkyLight(Coordinates3D coordinates); byte GetSkyLight(Coordinates3D coordinates);
BlockData GetBlockData(Coordinates3D coordinates); BlockDescriptor GetBlockData(Coordinates3D coordinates);
void SetBlockID(Coordinates3D coordinates, byte value); void SetBlockID(Coordinates3D coordinates, byte value);
void SetMetadata(Coordinates3D coordinates, byte value); void SetMetadata(Coordinates3D coordinates, byte value);
void SetSkyLight(Coordinates3D coordinates, byte value); void SetSkyLight(Coordinates3D coordinates, byte value);

View File

@ -1,5 +1,8 @@
using System; using System;
using TrueCraft.API.Logic; using TrueCraft.API.Logic;
using TrueCraft.API.World;
using TrueCraft.API;
using TrueCraft.API.Networking;
namespace TrueCraft.Core.Logic namespace TrueCraft.Core.Logic
{ {
@ -8,6 +11,34 @@ namespace TrueCraft.Core.Logic
/// </summary> /// </summary>
public abstract class BlockProvider : IBlockProvider, IItemProvider 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 short IItemProvider.ID
{ {
get get

View File

@ -45,7 +45,7 @@ namespace TrueCraft.Core.Networking.Packets
stream.WriteInt16((short)Items.Length); stream.WriteInt16((short)Items.Length);
for (int i = 0; i < Items.Length; i++) for (int i = 0; i < Items.Length; i++)
{ {
stream.WriteInt16(Items[i].Id); stream.WriteInt16(Items[i].ID);
if (!Items[i].Empty) if (!Items[i].Empty)
{ {
stream.WriteInt8(Items[i].Count); stream.WriteInt8(Items[i].Count);

View File

@ -69,12 +69,12 @@ namespace TrueCraft.Core.Windows
return Hotbar; return Hotbar;
} }
public bool PickUpStack(ItemStack slot) public override bool PickUpStack(ItemStack slot)
{ {
var area = MainInventory; var area = MainInventory;
foreach (var item in Hotbar.Items) 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 //&& item.Count + slot.Count < Item.GetMaximumStackSize(new ItemDescriptor(item.Id, item.Metadata)))) // TODO
{ {
area = Hotbar; area = Hotbar;

View File

@ -118,6 +118,11 @@ namespace TrueCraft.Core.Windows
} }
} }
public virtual bool PickUpStack(ItemStack slot)
{
throw new NotSupportedException();
}
protected internal virtual void OnWindowChange(WindowChangeEventArgs e) protected internal virtual void OnWindowChange(WindowChangeEventArgs e)
{ {
if (WindowChange != null) if (WindowChange != null)

View File

@ -44,7 +44,7 @@ namespace TrueCraft.Core.Windows
{ {
if (this[i].Empty && emptyIndex == -1) if (this[i].Empty && emptyIndex == -1)
emptyIndex = i; emptyIndex = i;
else if (this[i].Id == item.Id && else if (this[i].ID == item.ID &&
this[i].Metadata == item.Metadata && this[i].Metadata == item.Metadata &&
this[i].Count < maximumStackSize) this[i].Count < maximumStackSize)
{ {
@ -54,12 +54,12 @@ namespace TrueCraft.Core.Windows
from[index] = ItemStack.EmptyStack; from[index] = ItemStack.EmptyStack;
if (this[i].Count + item.Count > maximumStackSize) 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); 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; 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; return i;
} }
} }

View File

@ -152,21 +152,22 @@ namespace TrueCraft.Core.World
return chunk.GetBlockLight(coordinates); return chunk.GetBlockLight(coordinates);
} }
public BlockData GetBlockData(Coordinates3D coordinates) public BlockDescriptor GetBlockData(Coordinates3D coordinates)
{ {
IChunk chunk; IChunk chunk;
coordinates = FindBlockPosition(coordinates, out chunk); var adjustedCoordinates = FindBlockPosition(coordinates, out chunk);
return GetBlockDataFromChunk(coordinates, 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), ID = chunk.GetBlockID(adjustedCoordinates),
Metadata = chunk.GetMetadata(adjustedCoordinates), Metadata = chunk.GetMetadata(adjustedCoordinates),
BlockLight = chunk.GetBlockLight(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; IChunk chunk;
var adjustedCoordinates = FindBlockPosition(coordinates, out chunk); var adjustedCoordinates = FindBlockPosition(coordinates, out chunk);
BlockData old = new BlockData(); BlockDescriptor old = new BlockDescriptor();
if (BlockChanged != null) if (BlockChanged != null)
old = GetBlockDataFromChunk(adjustedCoordinates, chunk); old = GetBlockDataFromChunk(adjustedCoordinates, chunk, coordinates);
chunk.SetBlockID(adjustedCoordinates, value); chunk.SetBlockID(adjustedCoordinates, value);
if (BlockChanged != null) 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) public void SetMetadata(Coordinates3D coordinates, byte value)
{ {
IChunk chunk; IChunk chunk;
var adjustedCoordinates = FindBlockPosition(coordinates, out chunk); var adjustedCoordinates = FindBlockPosition(coordinates, out chunk);
BlockData old = new BlockData(); BlockDescriptor old = new BlockDescriptor();
if (BlockChanged != null) if (BlockChanged != null)
old = GetBlockDataFromChunk(adjustedCoordinates, chunk); old = GetBlockDataFromChunk(adjustedCoordinates, chunk, coordinates);
chunk.SetMetadata(adjustedCoordinates, value); chunk.SetMetadata(adjustedCoordinates, value);
if (BlockChanged != null) 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) public void SetSkyLight(Coordinates3D coordinates, byte value)

View File

@ -17,6 +17,7 @@ namespace TrueCraft.Handlers
var client = (RemoteClient)_client; var client = (RemoteClient)_client;
var world = _client.World; var world = _client.World;
var position = new Coordinates3D(packet.X, packet.Y, packet.Z); var position = new Coordinates3D(packet.X, packet.Y, packet.Z);
var descriptor = world.GetBlockData(position);
switch (packet.PlayerAction) switch (packet.PlayerAction)
{ {
case PlayerDiggingPacket.Action.DropItem: case PlayerDiggingPacket.Action.DropItem:
@ -26,10 +27,8 @@ namespace TrueCraft.Handlers
// TODO // TODO
break; break;
case PlayerDiggingPacket.Action.StopDigging: case PlayerDiggingPacket.Action.StopDigging:
// TODO: Do this properly var provider = server.BlockRepository.GetBlockProvider(descriptor.ID);
var stack = new ItemStack(world.GetBlockID(position), 1, world.GetMetadata(position)); provider.BlockMined(descriptor, packet.Face, world, client);
client.InventoryWindow.PickUpStack(stack);
world.SetBlockID(position, 0);
break; break;
} }
} }
@ -41,7 +40,7 @@ namespace TrueCraft.Handlers
var slot = client.SelectedItem; var slot = client.SelectedItem;
var position = new Coordinates3D(packet.X, packet.Y, packet.Z); var position = new Coordinates3D(packet.X, packet.Y, packet.Z);
BlockData? block = null; BlockDescriptor? block = null;
if (position != -Coordinates3D.One) if (position != -Coordinates3D.One)
{ {
if (position.DistanceTo((Coordinates3D)client.Entity.Position) > 10 /* TODO: Reach */) if (position.DistanceTo((Coordinates3D)client.Entity.Position) > 10 /* TODO: Reach */)
@ -56,7 +55,16 @@ namespace TrueCraft.Handlers
bool use = true; bool use = true;
if (block != null) 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) if (!slot.Empty)
{ {
@ -64,7 +72,7 @@ namespace TrueCraft.Handlers
{ {
// Temporary: just place the damn thing // Temporary: just place the damn thing
position += MathHelper.BlockFaceToCoordinates(packet.Face); 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); client.World.SetMetadata(position, (byte)slot.Metadata);
slot.Count--; slot.Count--;
client.Inventory[client.SelectedSlot] = slot; client.Inventory[client.SelectedSlot] = slot;

View File

@ -173,7 +173,7 @@ namespace TrueCraft
if (ExecutingTick) if (ExecutingTick)
return; // TODO: Warn about skipped updates? return; // TODO: Warn about skipped updates?
ExecutingTick = true; 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 client = Clients[i] as RemoteClient;
var sendTimeout = DateTime.Now.AddMilliseconds(50); var sendTimeout = DateTime.Now.AddMilliseconds(50);

View File

@ -21,7 +21,7 @@ namespace TrueCraft
// TODO: Make this more flexible // TODO: Make this more flexible
var server = new MultiplayerServer(); var server = new MultiplayerServer();
server.AddWorld(new World("default", new StandardGenerator())); 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 #if DEBUG
server.AddLogProvider(new FileLogProvider(new StreamWriter("packets.log", false), LogCategory.Packets)); server.AddLogProvider(new FileLogProvider(new StreamWriter("packets.log", false), LogCategory.Packets));
#endif #endif

View File

@ -158,7 +158,7 @@ namespace TrueCraft
void HandleWindowChange(object sender, WindowChangeEventArgs e) 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) private static ChunkDataPacket CreatePacket(IChunk chunk)