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;
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<NbtShort>("id").Value;
s.ID = compound.Get<NbtShort>("id").Value;
s.Metadata = compound.Get<NbtShort>("Damage").Value;
s.Count = (sbyte)compound.Get<NbtByte>("Count").Value;
s.Index = compound.Get<NbtByte>("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]

View File

@ -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<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)
{
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);

View File

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

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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
/// </summary>
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

View File

@ -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);

View File

@ -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;

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)
{
if (WindowChange != null)

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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)