Implement bed placement and supported blocks
This commit is contained in:
parent
91fdf59532
commit
eda5dd2f82
@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace TrueCraft.API.World
|
namespace TrueCraft.API.Logic
|
||||||
{
|
{
|
||||||
public struct BlockDescriptor
|
public struct BlockDescriptor
|
||||||
{
|
{
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using TrueCraft.API.World;
|
using TrueCraft.API.World;
|
||||||
using TrueCraft.API.Networking;
|
using TrueCraft.API.Networking;
|
||||||
|
using TrueCraft.API.Server;
|
||||||
|
|
||||||
namespace TrueCraft.API.Logic
|
namespace TrueCraft.API.Logic
|
||||||
{
|
{
|
||||||
@ -17,7 +18,7 @@ namespace TrueCraft.API.Logic
|
|||||||
bool BlockRightClicked(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user);
|
bool BlockRightClicked(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user);
|
||||||
bool BlockPlaced(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 BlockMined(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user);
|
||||||
void BlockUpdate(BlockDescriptor descriptor, IWorld world);
|
void BlockUpdate(BlockDescriptor descriptor, IMultiplayerServer server, IWorld world);
|
||||||
void BlockScheduledEvent(BlockDescriptor descriptor, IWorld world, object data);
|
void BlockScheduledEvent(BlockDescriptor descriptor, IWorld world, object data);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using TrueCraft.API.World;
|
||||||
|
using TrueCraft.API.Networking;
|
||||||
|
using TrueCraft.API.Entities;
|
||||||
|
|
||||||
namespace TrueCraft.API.Logic
|
namespace TrueCraft.API.Logic
|
||||||
{
|
{
|
||||||
@ -7,6 +10,8 @@ namespace TrueCraft.API.Logic
|
|||||||
short ID { get; }
|
short ID { get; }
|
||||||
sbyte MaximumStack { get; }
|
sbyte MaximumStack { get; }
|
||||||
string DisplayName { get; }
|
string DisplayName { get; }
|
||||||
//bool ItemUsedOnBlock(ItemDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user);
|
void ItemUsedOnNothing(ItemStack item, IWorld world, IRemoteClient user);
|
||||||
|
void ItemUsedOnEntity(ItemStack item, IEntity usedOn, IWorld world, IRemoteClient user);
|
||||||
|
void ItemUsedOnBlock(Coordinates3D coordinates, ItemStack item, BlockFace face, IWorld world, IRemoteClient user);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -25,6 +25,7 @@ namespace TrueCraft.API.Server
|
|||||||
IEventScheduler Scheduler { get; }
|
IEventScheduler Scheduler { get; }
|
||||||
IBlockRepository BlockRepository { get; }
|
IBlockRepository BlockRepository { get; }
|
||||||
IItemRepository ItemRepository { get; }
|
IItemRepository ItemRepository { get; }
|
||||||
|
bool BlockUpdatesEnabled { get; set; }
|
||||||
|
|
||||||
void Start(IPEndPoint endPoint);
|
void Start(IPEndPoint endPoint);
|
||||||
void RegisterPacketHandler(byte packetId, PacketHandler handler);
|
void RegisterPacketHandler(byte packetId, PacketHandler handler);
|
||||||
|
@ -79,11 +79,11 @@
|
|||||||
<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" />
|
|
||||||
<Compile Include="Entities\IAABBEntity.cs" />
|
<Compile Include="Entities\IAABBEntity.cs" />
|
||||||
<Compile Include="Entities\IBlockPhysicsProvider.cs" />
|
<Compile Include="Entities\IBlockPhysicsProvider.cs" />
|
||||||
<Compile Include="Entities\IPhysicsEntity.cs" />
|
<Compile Include="Entities\IPhysicsEntity.cs" />
|
||||||
<Compile Include="Logic\IItemRepository.cs" />
|
<Compile Include="Logic\IItemRepository.cs" />
|
||||||
|
<Compile Include="Logic\BlockDescriptor.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<ItemGroup />
|
<ItemGroup />
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using TrueCraft.API.Logic;
|
||||||
|
|
||||||
namespace TrueCraft.API.World
|
namespace TrueCraft.API.World
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using TrueCraft.API.Logic;
|
||||||
|
|
||||||
namespace TrueCraft.API.World
|
namespace TrueCraft.API.World
|
||||||
{
|
{
|
||||||
@ -19,6 +20,7 @@ namespace TrueCraft.API.World
|
|||||||
byte GetMetadata(Coordinates3D coordinates);
|
byte GetMetadata(Coordinates3D coordinates);
|
||||||
byte GetSkyLight(Coordinates3D coordinates);
|
byte GetSkyLight(Coordinates3D coordinates);
|
||||||
BlockDescriptor GetBlockData(Coordinates3D coordinates);
|
BlockDescriptor GetBlockData(Coordinates3D coordinates);
|
||||||
|
void SetBlockData(Coordinates3D coordinates, BlockDescriptor block);
|
||||||
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);
|
||||||
|
@ -19,6 +19,8 @@ namespace TrueCraft.Core.Entities
|
|||||||
{
|
{
|
||||||
Position = position;
|
Position = position;
|
||||||
Item = item;
|
Item = item;
|
||||||
|
if (Item.ID == 0)
|
||||||
|
System.Diagnostics.Debugger.Break();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemStack Item { get; set; }
|
public ItemStack Item { get; set; }
|
||||||
|
@ -4,13 +4,15 @@ using TrueCraft.API.World;
|
|||||||
using TrueCraft.API;
|
using TrueCraft.API;
|
||||||
using TrueCraft.API.Networking;
|
using TrueCraft.API.Networking;
|
||||||
using TrueCraft.Core.Entities;
|
using TrueCraft.Core.Entities;
|
||||||
|
using TrueCraft.API.Entities;
|
||||||
|
using TrueCraft.API.Server;
|
||||||
|
|
||||||
namespace TrueCraft.Core.Logic
|
namespace TrueCraft.Core.Logic
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides common implementations of block logic.
|
/// Provides common implementations of block logic.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class BlockProvider : IBlockProvider, IItemProvider
|
public abstract class BlockProvider : IItemProvider, IBlockProvider
|
||||||
{
|
{
|
||||||
public virtual bool BlockRightClicked(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user)
|
public virtual bool BlockRightClicked(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user)
|
||||||
{
|
{
|
||||||
@ -24,18 +26,38 @@ namespace TrueCraft.Core.Logic
|
|||||||
|
|
||||||
public virtual void BlockMined(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user)
|
public virtual void BlockMined(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user)
|
||||||
{
|
{
|
||||||
var entityManager = user.Server.GetEntityManagerForWorld(world);
|
GenerateDropEntity(descriptor, world, user.Server);
|
||||||
var items = GetDrop(descriptor);
|
|
||||||
foreach (var item in items)
|
|
||||||
{
|
|
||||||
entityManager.SpawnEntity(new ItemEntity(new Vector3(descriptor.Coordinates) + new Vector3(0.5), item));
|
|
||||||
}
|
|
||||||
world.SetBlockID(descriptor.Coordinates, 0);
|
world.SetBlockID(descriptor.Coordinates, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void BlockUpdate(BlockDescriptor descriptor, IWorld world)
|
private void GenerateDropEntity(BlockDescriptor descriptor, IWorld world, IMultiplayerServer server)
|
||||||
{
|
{
|
||||||
// This space intentionally left blank
|
var entityManager = server.GetEntityManagerForWorld(world);
|
||||||
|
var items = GetDrop(descriptor);
|
||||||
|
foreach (var item in items)
|
||||||
|
entityManager.SpawnEntity(new ItemEntity(new Vector3(descriptor.Coordinates) + new Vector3(0.5), item));
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool IsSupported(BlockDescriptor descriptor, IMultiplayerServer server, IWorld world)
|
||||||
|
{
|
||||||
|
var support = GetSupportDirection(descriptor);
|
||||||
|
if (support != Coordinates3D.Zero)
|
||||||
|
{
|
||||||
|
var supportingBlock = server.BlockRepository.GetBlockProvider(world.GetBlockID(descriptor.Coordinates + support));
|
||||||
|
if (!supportingBlock.Opaque)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void BlockUpdate(BlockDescriptor descriptor, IMultiplayerServer server, IWorld world)
|
||||||
|
{
|
||||||
|
if (!IsSupported(descriptor, server, world))
|
||||||
|
{
|
||||||
|
server.SendMessage(ChatColor.Red + "Removing block due to insufficient opaque support blocks");
|
||||||
|
GenerateDropEntity(descriptor, world, server);
|
||||||
|
world.SetBlockID(descriptor.Coordinates, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void BlockScheduledEvent(BlockDescriptor descriptor, IWorld world, object data)
|
public virtual void BlockScheduledEvent(BlockDescriptor descriptor, IWorld world, object data)
|
||||||
@ -48,6 +70,25 @@ namespace TrueCraft.Core.Logic
|
|||||||
return new[] { new ItemStack(descriptor.ID, 1, descriptor.Metadata) };
|
return new[] { new ItemStack(descriptor.ID, 1, descriptor.Metadata) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void ItemUsedOnEntity(ItemStack item, IEntity usedOn, IWorld world, IRemoteClient user)
|
||||||
|
{
|
||||||
|
// This space intentionally left blank
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void ItemUsedOnNothing(ItemStack item, IWorld world, IRemoteClient user)
|
||||||
|
{
|
||||||
|
// This space intentionally left blank
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void ItemUsedOnBlock(Coordinates3D coordinates, ItemStack item, BlockFace face, IWorld world, IRemoteClient user)
|
||||||
|
{
|
||||||
|
coordinates += MathHelper.BlockFaceToCoordinates(face);
|
||||||
|
world.SetBlockID(coordinates, (byte)item.ID);
|
||||||
|
world.SetMetadata(coordinates, (byte)item.Metadata);
|
||||||
|
item.Count--;
|
||||||
|
user.Inventory[user.SelectedSlot] = item;
|
||||||
|
}
|
||||||
|
|
||||||
short IItemProvider.ID
|
short IItemProvider.ID
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -61,6 +102,11 @@ namespace TrueCraft.Core.Logic
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract byte ID { get; }
|
public abstract byte ID { get; }
|
||||||
|
|
||||||
|
public virtual Coordinates3D GetSupportDirection(BlockDescriptor descriptor)
|
||||||
|
{
|
||||||
|
return Coordinates3D.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The maximum amount that can be in a single stack of this block.
|
/// The maximum amount that can be in a single stack of this block.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
26
TrueCraft.Core/Logic/Blocks/AirBlock.cs
Normal file
26
TrueCraft.Core/Logic/Blocks/AirBlock.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TrueCraft.Core.Logic.Blocks
|
||||||
|
{
|
||||||
|
public class AirBlock : BlockProvider
|
||||||
|
{
|
||||||
|
public static readonly byte BlockID = 0x00;
|
||||||
|
|
||||||
|
public override byte ID { get { return 0x00; } }
|
||||||
|
|
||||||
|
public override double BlastResistance { get { return 0; } }
|
||||||
|
|
||||||
|
public override double Hardness { get { return 100000; } }
|
||||||
|
|
||||||
|
public override bool Opaque { get { return false; } }
|
||||||
|
|
||||||
|
public override byte Luminance { get { return 0; } }
|
||||||
|
|
||||||
|
public override string DisplayName { get { return "Air"; } }
|
||||||
|
|
||||||
|
public override Tuple<int, int> GetTextureMap(byte metadata)
|
||||||
|
{
|
||||||
|
return new Tuple<int, int>(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,30 @@
|
|||||||
using System;
|
using System;
|
||||||
using TrueCraft.API.Logic;
|
using TrueCraft.API.Logic;
|
||||||
|
using TrueCraft.API;
|
||||||
|
using TrueCraft.Core.Logic.Items;
|
||||||
|
using TrueCraft.API.World;
|
||||||
|
using TrueCraft.API.Server;
|
||||||
|
|
||||||
namespace TrueCraft.Core.Logic.Blocks
|
namespace TrueCraft.Core.Logic.Blocks
|
||||||
{
|
{
|
||||||
public class BedBlock : BlockProvider
|
public class BedBlock : BlockProvider
|
||||||
{
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum BedDirection : byte
|
||||||
|
{
|
||||||
|
South = 0x0,
|
||||||
|
West = 0x1,
|
||||||
|
North = 0x2,
|
||||||
|
East = 0x3,
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum BedType : byte
|
||||||
|
{
|
||||||
|
Foot = 0x0,
|
||||||
|
Head = 0x8,
|
||||||
|
}
|
||||||
|
|
||||||
public static readonly byte BlockID = 0x1A;
|
public static readonly byte BlockID = 0x1A;
|
||||||
|
|
||||||
public override byte ID { get { return 0x1A; } }
|
public override byte ID { get { return 0x1A; } }
|
||||||
@ -23,5 +43,54 @@ namespace TrueCraft.Core.Logic.Blocks
|
|||||||
{
|
{
|
||||||
return new Tuple<int, int>(6, 8);
|
return new Tuple<int, int>(6, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override ItemStack[] GetDrop(BlockDescriptor descriptor)
|
||||||
|
{
|
||||||
|
return new[] { new ItemStack(BedItem.ItemID) };
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ValidBedPosition(BlockDescriptor descriptor, IBlockRepository repository, IWorld world, bool checkNeighbor = true, bool checkSupport = false)
|
||||||
|
{
|
||||||
|
if (checkNeighbor)
|
||||||
|
{
|
||||||
|
var other = Coordinates3D.Zero;
|
||||||
|
switch ((BedDirection)(descriptor.Metadata & 0x3))
|
||||||
|
{
|
||||||
|
case BedDirection.East:
|
||||||
|
other = Coordinates3D.East;
|
||||||
|
break;
|
||||||
|
case BedDirection.West:
|
||||||
|
other = Coordinates3D.West;
|
||||||
|
break;
|
||||||
|
case BedDirection.North:
|
||||||
|
other = Coordinates3D.North;
|
||||||
|
break;
|
||||||
|
case BedDirection.South:
|
||||||
|
other = Coordinates3D.South;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((descriptor.Metadata & (byte)BedType.Head) == (byte)BedType.Head)
|
||||||
|
other = -other;
|
||||||
|
if (world.GetBlockID(descriptor.Coordinates + other) != BedBlock.BlockID)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (checkSupport)
|
||||||
|
{
|
||||||
|
var supportingBlock = repository.GetBlockProvider(world.GetBlockID(descriptor.Coordinates + Coordinates3D.Down));
|
||||||
|
if (!supportingBlock.Opaque)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void BlockUpdate(BlockDescriptor descriptor, IMultiplayerServer server, IWorld world)
|
||||||
|
{
|
||||||
|
if (!ValidBedPosition(descriptor, server.BlockRepository, world))
|
||||||
|
{
|
||||||
|
world.SetBlockID(descriptor.Coordinates, 0);
|
||||||
|
server.SendMessage(ChatColor.Red + "Removing block due to insufficient neighboring bed blocks");
|
||||||
|
}
|
||||||
|
base.BlockUpdate(descriptor, server, world);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,8 +17,6 @@ namespace TrueCraft.Core.Logic.Blocks
|
|||||||
|
|
||||||
public override byte Luminance { get { return 0; } }
|
public override byte Luminance { get { return 0; } }
|
||||||
|
|
||||||
public override bool Opaque { get { return false; } }
|
|
||||||
|
|
||||||
public override string DisplayName { get { return "Grass"; } }
|
public override string DisplayName { get { return "Grass"; } }
|
||||||
|
|
||||||
public override Tuple<int, int> GetTextureMap(byte metadata)
|
public override Tuple<int, int> GetTextureMap(byte metadata)
|
||||||
|
@ -4,6 +4,9 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using TrueCraft.API.Logic;
|
using TrueCraft.API.Logic;
|
||||||
using TrueCraft.API;
|
using TrueCraft.API;
|
||||||
|
using TrueCraft.API.Entities;
|
||||||
|
using TrueCraft.API.World;
|
||||||
|
using TrueCraft.API.Networking;
|
||||||
|
|
||||||
namespace TrueCraft.Core.Logic
|
namespace TrueCraft.Core.Logic
|
||||||
{
|
{
|
||||||
@ -14,5 +17,20 @@ namespace TrueCraft.Core.Logic
|
|||||||
public virtual sbyte MaximumStack { get { return 64; } }
|
public virtual sbyte MaximumStack { get { return 64; } }
|
||||||
|
|
||||||
public virtual string DisplayName { get { return string.Empty; } }
|
public virtual string DisplayName { get { return string.Empty; } }
|
||||||
|
|
||||||
|
public virtual void ItemUsedOnEntity(ItemStack item, IEntity usedOn, IWorld world, IRemoteClient user)
|
||||||
|
{
|
||||||
|
// This space intentionally left blank
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void ItemUsedOnBlock(Coordinates3D coordinates, ItemStack item, BlockFace face, IWorld world, IRemoteClient user)
|
||||||
|
{
|
||||||
|
// This space intentionally left blank
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void ItemUsedOnNothing(ItemStack item, IWorld world, IRemoteClient user)
|
||||||
|
{
|
||||||
|
// This space intentionally left blank
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using TrueCraft.API.Logic;
|
using TrueCraft.API.Logic;
|
||||||
|
using TrueCraft.API;
|
||||||
|
using TrueCraft.API.World;
|
||||||
|
using TrueCraft.API.Networking;
|
||||||
|
using TrueCraft.Core.Logic.Blocks;
|
||||||
|
|
||||||
namespace TrueCraft.Core.Logic.Items
|
namespace TrueCraft.Core.Logic.Items
|
||||||
{
|
{
|
||||||
@ -12,5 +16,48 @@ namespace TrueCraft.Core.Logic.Items
|
|||||||
public override sbyte MaximumStack { get { return 1; } }
|
public override sbyte MaximumStack { get { return 1; } }
|
||||||
|
|
||||||
public override string DisplayName { get { return "Bed"; } }
|
public override string DisplayName { get { return "Bed"; } }
|
||||||
|
|
||||||
|
public override void ItemUsedOnBlock(Coordinates3D coordinates, ItemStack item, BlockFace face, IWorld world, IRemoteClient user)
|
||||||
|
{
|
||||||
|
coordinates += MathHelper.BlockFaceToCoordinates(face);
|
||||||
|
var head = coordinates;
|
||||||
|
var foot = coordinates;
|
||||||
|
BedBlock.BedDirection direction = BedBlock.BedDirection.North;
|
||||||
|
switch (MathHelper.DirectionByRotationFlat(user.Entity.Yaw))
|
||||||
|
{
|
||||||
|
case Direction.North:
|
||||||
|
head += Coordinates3D.North;
|
||||||
|
direction = BedBlock.BedDirection.North;
|
||||||
|
break;
|
||||||
|
case Direction.South:
|
||||||
|
head += Coordinates3D.South;
|
||||||
|
direction = BedBlock.BedDirection.South;
|
||||||
|
break;
|
||||||
|
case Direction.East:
|
||||||
|
head += Coordinates3D.East;
|
||||||
|
direction = BedBlock.BedDirection.East;
|
||||||
|
break;
|
||||||
|
case Direction.West:
|
||||||
|
head += Coordinates3D.West;
|
||||||
|
direction = BedBlock.BedDirection.West;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var bedProvider = (BedBlock)user.Server.BlockRepository.GetBlockProvider(BedBlock.BlockID);
|
||||||
|
if (!bedProvider.ValidBedPosition(new BlockDescriptor { Coordinates = head },
|
||||||
|
user.Server.BlockRepository, user.World, false, true) ||
|
||||||
|
!bedProvider.ValidBedPosition(new BlockDescriptor { Coordinates = foot },
|
||||||
|
user.Server.BlockRepository, user.World, false, true))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
user.Server.BlockUpdatesEnabled = false;
|
||||||
|
world.SetBlockData(head, new BlockDescriptor
|
||||||
|
{ ID = BedBlock.BlockID, Metadata = (byte)((byte)direction | (byte)BedBlock.BedType.Head) });
|
||||||
|
world.SetBlockData(foot, new BlockDescriptor
|
||||||
|
{ ID = BedBlock.BlockID, Metadata = (byte)((byte)direction | (byte)BedBlock.BedType.Foot) });
|
||||||
|
user.Server.BlockUpdatesEnabled = true;
|
||||||
|
item.Count--;
|
||||||
|
user.Inventory[user.SelectedSlot] = item;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -267,6 +267,7 @@
|
|||||||
<Compile Include="Entities\LivingEntity.cs" />
|
<Compile Include="Entities\LivingEntity.cs" />
|
||||||
<Compile Include="Entities\ObjectEntity.cs" />
|
<Compile Include="Entities\ObjectEntity.cs" />
|
||||||
<Compile Include="Entities\PlayerEntity.cs" />
|
<Compile Include="Entities\PlayerEntity.cs" />
|
||||||
|
<Compile Include="Logic\Blocks\AirBlock.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -5,6 +5,7 @@ using System.IO;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using TrueCraft.API;
|
using TrueCraft.API;
|
||||||
using TrueCraft.API.World;
|
using TrueCraft.API.World;
|
||||||
|
using TrueCraft.API.Logic;
|
||||||
|
|
||||||
namespace TrueCraft.Core.World
|
namespace TrueCraft.Core.World
|
||||||
{
|
{
|
||||||
@ -159,6 +160,18 @@ namespace TrueCraft.Core.World
|
|||||||
return GetBlockDataFromChunk(adjustedCoordinates, chunk, coordinates);
|
return GetBlockDataFromChunk(adjustedCoordinates, chunk, coordinates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetBlockData(Coordinates3D coordinates, BlockDescriptor descriptor)
|
||||||
|
{
|
||||||
|
// TODO: Figure out the best way to handle light in this scenario
|
||||||
|
IChunk chunk;
|
||||||
|
var adjustedCoordinates = FindBlockPosition(coordinates, out chunk);
|
||||||
|
var old = GetBlockDataFromChunk(adjustedCoordinates, chunk, coordinates);
|
||||||
|
chunk.SetBlockID(adjustedCoordinates, descriptor.ID);
|
||||||
|
chunk.SetMetadata(adjustedCoordinates,descriptor.Metadata);
|
||||||
|
if (BlockChanged != null)
|
||||||
|
BlockChanged(this, new BlockChangeEventArgs(coordinates, old, GetBlockDataFromChunk(adjustedCoordinates, chunk, coordinates)));
|
||||||
|
}
|
||||||
|
|
||||||
private BlockDescriptor GetBlockDataFromChunk(Coordinates3D adjustedCoordinates, IChunk chunk, Coordinates3D coordinates)
|
private BlockDescriptor GetBlockDataFromChunk(Coordinates3D adjustedCoordinates, IChunk chunk, Coordinates3D coordinates)
|
||||||
{
|
{
|
||||||
return new BlockDescriptor
|
return new BlockDescriptor
|
||||||
|
@ -6,6 +6,7 @@ using TrueCraft.API;
|
|||||||
using TrueCraft.API.World;
|
using TrueCraft.API.World;
|
||||||
using TrueCraft.Core;
|
using TrueCraft.Core;
|
||||||
using TrueCraft.Core.Windows;
|
using TrueCraft.Core.Windows;
|
||||||
|
using TrueCraft.API.Logic;
|
||||||
|
|
||||||
namespace TrueCraft.Handlers
|
namespace TrueCraft.Handlers
|
||||||
{
|
{
|
||||||
@ -43,7 +44,7 @@ namespace TrueCraft.Handlers
|
|||||||
if (c.KnownEntities.Contains(client.Entity))
|
if (c.KnownEntities.Contains(client.Entity))
|
||||||
c.QueuePacket(new AnimationPacket(client.Entity.EntityID, AnimationPacket.PlayerAnimation.None));
|
c.QueuePacket(new AnimationPacket(client.Entity.EntityID, AnimationPacket.PlayerAnimation.None));
|
||||||
}
|
}
|
||||||
if (provider != null)
|
if (provider != null && descriptor.ID != 0)
|
||||||
provider.BlockMined(descriptor, packet.Face, world, client);
|
provider.BlockMined(descriptor, packet.Face, world, client);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -93,16 +94,17 @@ namespace TrueCraft.Handlers
|
|||||||
{
|
{
|
||||||
if (use)
|
if (use)
|
||||||
{
|
{
|
||||||
// Temporary: just place the damn thing
|
var itemProvider = server.ItemRepository.GetItemProvider(slot.ID);
|
||||||
position += MathHelper.BlockFaceToCoordinates(packet.Face);
|
if (itemProvider == null)
|
||||||
client.World.SetBlockID(position, (byte)slot.ID);
|
{
|
||||||
client.World.SetMetadata(position, (byte)slot.Metadata);
|
server.SendMessage(ChatColor.Red + "WARNING: item provider for ID {0} is null (player placing)", block.Value.ID);
|
||||||
slot.Count--;
|
server.SendMessage(ChatColor.Red + "Error occured from client {0} at coordinates {1}", client.Username, block.Value.Coordinates);
|
||||||
client.Inventory[client.SelectedSlot] = slot;
|
server.SendMessage(ChatColor.Red + "Packet logged at {0}, please report upstream", DateTime.Now);
|
||||||
// End temporary
|
}
|
||||||
if (block != null)
|
if (block != null)
|
||||||
{
|
{
|
||||||
// TODO: Use item on block
|
if (itemProvider != null)
|
||||||
|
itemProvider.ItemUsedOnBlock(position, slot, packet.Face, client.World, client);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -19,16 +19,11 @@ namespace TrueCraft
|
|||||||
|
|
||||||
public IItemProvider GetItemProvider(short id)
|
public IItemProvider GetItemProvider(short id)
|
||||||
{
|
{
|
||||||
int max = ItemProviders.Count - 1, min = 0;
|
// TODO: Binary search
|
||||||
while (max >= min)
|
for (int i = 0; i < ItemProviders.Count; i++)
|
||||||
{
|
{
|
||||||
int mid = (max - min / 2) + min;
|
if (ItemProviders[i].ID == id)
|
||||||
if (ItemProviders[mid].ID == id)
|
return ItemProviders[i];
|
||||||
return ItemProviders[mid];
|
|
||||||
else if(ItemProviders[mid].ID < id)
|
|
||||||
min = mid + 1;
|
|
||||||
else
|
|
||||||
max = min - 1;
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -29,11 +29,35 @@ namespace TrueCraft
|
|||||||
public IBlockRepository BlockRepository { get; private set; }
|
public IBlockRepository BlockRepository { get; private set; }
|
||||||
public IItemRepository ItemRepository { get; private set; }
|
public IItemRepository ItemRepository { get; private set; }
|
||||||
|
|
||||||
|
private bool _BlockUpdatesEnabled = true;
|
||||||
|
private struct BlockUpdate
|
||||||
|
{
|
||||||
|
public Coordinates3D Coordinates;
|
||||||
|
public IWorld World;
|
||||||
|
}
|
||||||
|
private Queue<BlockUpdate> PendingBlockUpdates { get; set; }
|
||||||
|
public bool BlockUpdatesEnabled
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _BlockUpdatesEnabled;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_BlockUpdatesEnabled = value;
|
||||||
|
if (_BlockUpdatesEnabled)
|
||||||
|
{
|
||||||
|
ProcessBlockUpdates();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Timer EnvironmentWorker;
|
private Timer EnvironmentWorker;
|
||||||
private Thread NetworkWorker;
|
private Thread NetworkWorker;
|
||||||
private TcpListener Listener;
|
private TcpListener Listener;
|
||||||
private readonly PacketHandler[] PacketHandlers;
|
private readonly PacketHandler[] PacketHandlers;
|
||||||
private IList<ILogProvider> LogProviders;
|
private IList<ILogProvider> LogProviders;
|
||||||
|
private object ClientLock = new object();
|
||||||
|
|
||||||
public MultiplayerServer()
|
public MultiplayerServer()
|
||||||
{
|
{
|
||||||
@ -53,6 +77,7 @@ namespace TrueCraft
|
|||||||
var itemRepository = new ItemRepository();
|
var itemRepository = new ItemRepository();
|
||||||
itemRepository.DiscoverItemProviders();
|
itemRepository.DiscoverItemProviders();
|
||||||
ItemRepository = itemRepository;
|
ItemRepository = itemRepository;
|
||||||
|
PendingBlockUpdates = new Queue<BlockUpdate>();
|
||||||
|
|
||||||
reader.RegisterCorePackets();
|
reader.RegisterCorePackets();
|
||||||
Handlers.PacketHandlers.RegisterHandlers(this);
|
Handlers.PacketHandlers.RegisterHandlers(this);
|
||||||
@ -90,7 +115,32 @@ namespace TrueCraft
|
|||||||
if (client.LoggedIn && client.World == sender)
|
if (client.LoggedIn && client.World == sender)
|
||||||
{
|
{
|
||||||
client.QueuePacket(new BlockChangePacket(e.Position.X, (sbyte)e.Position.Y, e.Position.Z,
|
client.QueuePacket(new BlockChangePacket(e.Position.X, (sbyte)e.Position.Y, e.Position.Z,
|
||||||
(sbyte)e.NewBlock.ID, (sbyte)e.NewBlock.Metadata));
|
(sbyte)e.NewBlock.ID, (sbyte)e.NewBlock.Metadata));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PendingBlockUpdates.Enqueue(new BlockUpdate { Coordinates = e.Position, World = sender as IWorld });
|
||||||
|
ProcessBlockUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessBlockUpdates()
|
||||||
|
{
|
||||||
|
if (!BlockUpdatesEnabled)
|
||||||
|
return;
|
||||||
|
var adjacent = new[]
|
||||||
|
{
|
||||||
|
Coordinates3D.Up, Coordinates3D.Down,
|
||||||
|
Coordinates3D.Left, Coordinates3D.Right,
|
||||||
|
Coordinates3D.Forwards, Coordinates3D.Backwards
|
||||||
|
};
|
||||||
|
while (PendingBlockUpdates.Count != 0)
|
||||||
|
{
|
||||||
|
var update = PendingBlockUpdates.Dequeue();
|
||||||
|
foreach (var offset in adjacent)
|
||||||
|
{
|
||||||
|
var descriptor = update.World.GetBlockData(update.Coordinates + offset);
|
||||||
|
var provider = BlockRepository.GetBlockProvider(descriptor.ID);
|
||||||
|
if (provider != null)
|
||||||
|
provider.BlockUpdate(descriptor, this, update.World);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,7 +214,8 @@ namespace TrueCraft
|
|||||||
{
|
{
|
||||||
var tcpClient = Listener.EndAcceptTcpClient(result);
|
var tcpClient = Listener.EndAcceptTcpClient(result);
|
||||||
var client = new RemoteClient(this, tcpClient.GetStream());
|
var client = new RemoteClient(this, tcpClient.GetStream());
|
||||||
Clients.Add(client);
|
lock (ClientLock)
|
||||||
|
Clients.Add(client);
|
||||||
Listener.BeginAcceptTcpClient(AcceptClient, null);
|
Listener.BeginAcceptTcpClient(AcceptClient, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,11 +235,17 @@ namespace TrueCraft
|
|||||||
bool idle = true;
|
bool idle = true;
|
||||||
for (int i = 0; i < Clients.Count && i >= 0; i++)
|
for (int i = 0; i < Clients.Count && i >= 0; i++)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Running update " + DateTime.Now);
|
RemoteClient client;
|
||||||
var client = Clients[i] as RemoteClient;
|
lock (ClientLock)
|
||||||
var sendTimeout = DateTime.Now.AddMilliseconds(50);
|
client = Clients[i] as RemoteClient;
|
||||||
while (client.PacketQueue.Count != 0 && DateTime.Now < sendTimeout)
|
var sendTimeout = DateTime.Now.AddMilliseconds(100);
|
||||||
|
while (client.PacketQueue.Count != 0)
|
||||||
{
|
{
|
||||||
|
if (DateTime.Now > sendTimeout)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Send timeout" + DateTime.Now);
|
||||||
|
break;
|
||||||
|
}
|
||||||
idle = false;
|
idle = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -225,9 +282,14 @@ namespace TrueCraft
|
|||||||
Clients.RemoveAt(i);
|
Clients.RemoveAt(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var receiveTimeout = DateTime.Now.AddMilliseconds(50);
|
var receiveTimeout = DateTime.Now.AddMilliseconds(100);
|
||||||
while (client.DataAvailable && DateTime.Now < receiveTimeout)
|
while (client.DataAvailable)
|
||||||
{
|
{
|
||||||
|
if (DateTime.Now > receiveTimeout)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Receive timeout" + DateTime.Now);
|
||||||
|
break;
|
||||||
|
}
|
||||||
idle = false;
|
idle = false;
|
||||||
var packet = PacketReader.ReadPacket(client.MinecraftStream);
|
var packet = PacketReader.ReadPacket(client.MinecraftStream);
|
||||||
LogPacket(packet, true);
|
LogPacket(packet, true);
|
||||||
@ -268,7 +330,8 @@ namespace TrueCraft
|
|||||||
Thread.Sleep(100);
|
Thread.Sleep(100);
|
||||||
if (client.Disconnected)
|
if (client.Disconnected)
|
||||||
{
|
{
|
||||||
Clients.RemoveAt(i);
|
lock (ClientLock)
|
||||||
|
Clients.RemoveAt(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user