Enforce digging time and damage items when used
Closes #11 Partially addresses #12
This commit is contained in:
parent
a77822950b
commit
fa8c4a6877
@ -8,27 +8,86 @@ namespace TrueCraft.API.Networking
|
|||||||
{
|
{
|
||||||
public interface IRemoteClient
|
public interface IRemoteClient
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Minecraft stream used to communicate with this client.
|
||||||
|
/// </summary>
|
||||||
IMinecraftStream MinecraftStream { get; }
|
IMinecraftStream MinecraftStream { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if this client has data pending in the network stream.
|
||||||
|
/// </summary>
|
||||||
bool DataAvailable { get; }
|
bool DataAvailable { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// The world this client is present in.
|
||||||
|
/// </summary>
|
||||||
IWorld World { get; }
|
IWorld World { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// The entity associated with this client.
|
||||||
|
/// </summary>
|
||||||
IEntity Entity { get; }
|
IEntity Entity { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// This client's inventory.
|
||||||
|
/// </summary>
|
||||||
IWindow Inventory { get; }
|
IWindow Inventory { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// The username of the connected client. May be null if not yet ascertained.
|
||||||
|
/// </summary>
|
||||||
string Username { get; }
|
string Username { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// The slot index this user has selected in their hotbar.
|
||||||
|
/// </summary>
|
||||||
short SelectedSlot { get; }
|
short SelectedSlot { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// The item stack at the slot the user has selected in their hotbar.
|
||||||
|
/// </summary>
|
||||||
ItemStack SelectedItem { get; }
|
ItemStack SelectedItem { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// The server this user is playing on.
|
||||||
|
/// </summary>
|
||||||
IMultiplayerServer Server { get; }
|
IMultiplayerServer Server { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// If true, this client will be sent logging information as chat messages.
|
||||||
|
/// </summary>
|
||||||
bool EnableLogging { get; set; }
|
bool EnableLogging { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// The time the user is expected to complete the active digging operation,
|
||||||
|
/// depending on what kind of block they are mining and what tool they're using
|
||||||
|
/// to do it with.
|
||||||
|
/// </summary>
|
||||||
|
DateTime ExpectedDigComplete { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// True if this client has been disconnected. You should cease sending packets and
|
||||||
|
/// so on, this client is just waiting to be reaped.
|
||||||
|
/// </summary>
|
||||||
bool Disconnected { get; }
|
bool Disconnected { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads player data from disk for this client.
|
||||||
|
/// </summary>
|
||||||
bool Load();
|
bool Load();
|
||||||
|
/// <summary>
|
||||||
|
/// Saves player data to disk for this client.
|
||||||
|
/// </summary>
|
||||||
void Save();
|
void Save();
|
||||||
|
/// <summary>
|
||||||
|
/// Queues a packet to be sent to this client.
|
||||||
|
/// </summary>
|
||||||
void QueuePacket(IPacket packet);
|
void QueuePacket(IPacket packet);
|
||||||
|
/// <summary>
|
||||||
|
/// Disconnects this client from the server.
|
||||||
|
/// </summary>
|
||||||
void Disconnect();
|
void Disconnect();
|
||||||
|
/// <summary>
|
||||||
|
/// Sends a chat message to this client.
|
||||||
|
/// </summary>
|
||||||
void SendMessage(string message);
|
void SendMessage(string message);
|
||||||
|
/// <summary>
|
||||||
|
/// If logging is enabled, sends your message to the client as chat.
|
||||||
|
/// </summary>
|
||||||
void Log(string message, params object[] parameters);
|
void Log(string message, params object[] parameters);
|
||||||
|
/// <summary>
|
||||||
|
/// Opens a window on the client. This sends the appropriate packets and tracks
|
||||||
|
/// this window as the currently open window.
|
||||||
|
/// </summary>
|
||||||
void OpenWindow(IWindow window);
|
void OpenWindow(IWindow window);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,6 +9,7 @@ using TrueCraft.API.Server;
|
|||||||
using TrueCraft.Core.Logic.Blocks;
|
using TrueCraft.Core.Logic.Blocks;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using fNbt;
|
using fNbt;
|
||||||
|
using TrueCraft.Core.Logic.Items;
|
||||||
|
|
||||||
namespace TrueCraft.Core.Logic
|
namespace TrueCraft.Core.Logic
|
||||||
{
|
{
|
||||||
@ -242,5 +243,91 @@ namespace TrueCraft.Core.Logic
|
|||||||
return new BoundingBox(Vector3.Zero, Vector3.One);
|
return new BoundingBox(Vector3.Zero, Vector3.One);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the time required to mine the given block with the given item.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The harvest time in milliseconds.</returns>
|
||||||
|
/// <param name="blockId">Block identifier.</param>
|
||||||
|
/// <param name="itemId">Item identifier.</param>
|
||||||
|
/// <param name="damage">Damage sustained by the item.</param>
|
||||||
|
public static int GetHarvestTime(byte blockId, short itemId, out short damage)
|
||||||
|
{
|
||||||
|
// Reference:
|
||||||
|
// http://minecraft.gamepedia.com/index.php?title=Breaking&oldid=138286
|
||||||
|
|
||||||
|
damage = 0;
|
||||||
|
|
||||||
|
var block = BlockRepository.GetBlockProvider(blockId);
|
||||||
|
var item = ItemRepository.GetItemProvider(itemId);
|
||||||
|
|
||||||
|
double hardness = block.Hardness;
|
||||||
|
if (hardness == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
double time = hardness * 1.5;
|
||||||
|
|
||||||
|
var tool = ToolType.None;
|
||||||
|
var material = ToolMaterial.None;
|
||||||
|
|
||||||
|
if (item is ToolItem)
|
||||||
|
{
|
||||||
|
var _ = item as ToolItem;
|
||||||
|
tool = _.ToolType;
|
||||||
|
material = _.Material;
|
||||||
|
|
||||||
|
if ((block.EffectiveTools & tool) == 0 || (block.EffectiveToolMaterials & material) == 0)
|
||||||
|
{
|
||||||
|
time *= 3.33; // Add time for ineffective tools
|
||||||
|
}
|
||||||
|
if (material != ToolMaterial.None)
|
||||||
|
{
|
||||||
|
switch (material)
|
||||||
|
{
|
||||||
|
case ToolMaterial.Wood:
|
||||||
|
time /= 2;
|
||||||
|
break;
|
||||||
|
case ToolMaterial.Stone:
|
||||||
|
time /= 4;
|
||||||
|
break;
|
||||||
|
case ToolMaterial.Iron:
|
||||||
|
time /= 6;
|
||||||
|
break;
|
||||||
|
case ToolMaterial.Diamond:
|
||||||
|
time /= 8;
|
||||||
|
break;
|
||||||
|
case ToolMaterial.Gold:
|
||||||
|
time /= 12;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
damage = 1;
|
||||||
|
if (tool == ToolType.Shovel || tool == ToolType.Axe || tool == ToolType.Pickaxe)
|
||||||
|
{
|
||||||
|
damage = (short)(hardness != 0 ? 1 : 0);
|
||||||
|
}
|
||||||
|
else if (tool == ToolType.Sword)
|
||||||
|
{
|
||||||
|
damage = (short)(hardness != 0 ? 2 : 0);
|
||||||
|
time /= 1.5;
|
||||||
|
if (block is CobwebBlock)
|
||||||
|
time /= 1.5;
|
||||||
|
}
|
||||||
|
else if (tool == ToolType.Hoe)
|
||||||
|
damage = 0; // What? This doesn't seem right
|
||||||
|
else if (item is ShearsItem)
|
||||||
|
{
|
||||||
|
if (block is WoolBlock)
|
||||||
|
time /= 5;
|
||||||
|
else if (block is LeavesBlock || block is CobwebBlock)
|
||||||
|
time /= 15;
|
||||||
|
if (block is LeavesBlock || block is CobwebBlock || block is TallGrassBlock)
|
||||||
|
damage = 1;
|
||||||
|
else
|
||||||
|
damage = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (int)(time * 1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,6 +30,11 @@ namespace TrueCraft.Core.Logic.Blocks
|
|||||||
|
|
||||||
public override BoundingBox? BoundingBox { get { return null; } }
|
public override BoundingBox? BoundingBox { get { return null; } }
|
||||||
|
|
||||||
|
public override Coordinates3D GetSupportDirection(BlockDescriptor descriptor)
|
||||||
|
{
|
||||||
|
return Coordinates3D.Down;
|
||||||
|
}
|
||||||
|
|
||||||
public override Tuple<int, int> GetTextureMap(byte metadata)
|
public override Tuple<int, int> GetTextureMap(byte metadata)
|
||||||
{
|
{
|
||||||
return new Tuple<int, int>(7, 2);
|
return new Tuple<int, int>(7, 2);
|
||||||
|
@ -15,5 +15,27 @@ namespace TrueCraft.Core.Logic
|
|||||||
public virtual short BaseDurability { get { return 0; } }
|
public virtual short BaseDurability { get { return 0; } }
|
||||||
|
|
||||||
public override sbyte MaximumStack { get { return 1; } }
|
public override sbyte MaximumStack { get { return 1; } }
|
||||||
|
|
||||||
|
public virtual int Uses
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (Material)
|
||||||
|
{
|
||||||
|
case ToolMaterial.Gold:
|
||||||
|
return 33;
|
||||||
|
case ToolMaterial.Wood:
|
||||||
|
return 60;
|
||||||
|
case ToolMaterial.Stone:
|
||||||
|
return 132;
|
||||||
|
case ToolMaterial.Iron:
|
||||||
|
return 251;
|
||||||
|
case ToolMaterial.Diamond:
|
||||||
|
return 1562;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -36,7 +36,7 @@
|
|||||||
<HintPath>..\lib\Ionic.Zip.Reduced.dll</HintPath>
|
<HintPath>..\lib\Ionic.Zip.Reduced.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Newtonsoft.Json">
|
<Reference Include="Newtonsoft.Json">
|
||||||
<HintPath>..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
|
<HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" />
|
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -34,12 +34,12 @@
|
|||||||
<Reference Include="Xwt">
|
<Reference Include="Xwt">
|
||||||
<HintPath>..\lib\Xwt.dll</HintPath>
|
<HintPath>..\lib\Xwt.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Newtonsoft.Json">
|
|
||||||
<HintPath>..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Ionic.Zip.Reduced">
|
<Reference Include="Ionic.Zip.Reduced">
|
||||||
<HintPath>..\lib\Ionic.Zip.Reduced.dll</HintPath>
|
<HintPath>..\lib\Ionic.Zip.Reduced.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Newtonsoft.Json">
|
||||||
|
<HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
@ -96,10 +96,10 @@
|
|||||||
<None Include="Xwt.WPF.dll">
|
<None Include="Xwt.WPF.dll">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<None Include="packages.config" />
|
|
||||||
<None Include="truecraft">
|
<None Include="truecraft">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Content\truecraft-logo.png" />
|
<EmbeddedResource Include="Content\truecraft-logo.png" />
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" />
|
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -12,6 +12,7 @@ using fNbt;
|
|||||||
using TrueCraft.Core.Logic.Blocks;
|
using TrueCraft.Core.Logic.Blocks;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using TrueCraft.Core.Logic.Items;
|
using TrueCraft.Core.Logic.Items;
|
||||||
|
using TrueCraft.Core.Logic;
|
||||||
|
|
||||||
namespace TrueCraft.Handlers
|
namespace TrueCraft.Handlers
|
||||||
{
|
{
|
||||||
@ -25,6 +26,8 @@ namespace TrueCraft.Handlers
|
|||||||
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);
|
var descriptor = world.GetBlockData(position);
|
||||||
var provider = server.BlockRepository.GetBlockProvider(descriptor.ID);
|
var provider = server.BlockRepository.GetBlockProvider(descriptor.ID);
|
||||||
|
short damage;
|
||||||
|
int time;
|
||||||
switch (packet.PlayerAction)
|
switch (packet.PlayerAction)
|
||||||
{
|
{
|
||||||
case PlayerDiggingPacket.Action.DropItem:
|
case PlayerDiggingPacket.Action.DropItem:
|
||||||
@ -64,9 +67,13 @@ namespace TrueCraft.Handlers
|
|||||||
// So if you want to blame anyone, send flames to Notch for the stupid idea of not sending "stop digging" packets
|
// So if you want to blame anyone, send flames to Notch for the stupid idea of not sending "stop digging" packets
|
||||||
// for hardness == 0 blocks.
|
// for hardness == 0 blocks.
|
||||||
|
|
||||||
if (provider != null && provider.Hardness == 0
|
time = BlockProvider.GetHarvestTime(descriptor.ID, client.SelectedItem.ID, out damage);
|
||||||
|| (client.SelectedItem.ID == ShearsItem.ItemID && provider is LeavesBlock))
|
if (time <= 20)
|
||||||
|
{
|
||||||
provider.BlockMined(descriptor, packet.Face, world, client);
|
provider.BlockMined(descriptor, packet.Face, world, client);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
client.ExpectedDigComplete = DateTime.UtcNow.AddMilliseconds(time);
|
||||||
break;
|
break;
|
||||||
case PlayerDiggingPacket.Action.StopDigging:
|
case PlayerDiggingPacket.Action.StopDigging:
|
||||||
foreach (var nearbyClient in server.Clients)
|
foreach (var nearbyClient in server.Clients)
|
||||||
@ -76,7 +83,29 @@ namespace TrueCraft.Handlers
|
|||||||
c.QueuePacket(new AnimationPacket(client.Entity.EntityID, AnimationPacket.PlayerAnimation.None));
|
c.QueuePacket(new AnimationPacket(client.Entity.EntityID, AnimationPacket.PlayerAnimation.None));
|
||||||
}
|
}
|
||||||
if (provider != null && descriptor.ID != 0)
|
if (provider != null && descriptor.ID != 0)
|
||||||
provider.BlockMined(descriptor, packet.Face, world, client);
|
{
|
||||||
|
time = BlockProvider.GetHarvestTime(descriptor.ID, client.SelectedItem.ID, out damage);
|
||||||
|
if (time <= 20)
|
||||||
|
break; // Already handled earlier
|
||||||
|
var diff = (DateTime.UtcNow - client.ExpectedDigComplete).TotalMilliseconds;
|
||||||
|
if (diff > -100) // Allow a small tolerance
|
||||||
|
{
|
||||||
|
provider.BlockMined(descriptor, packet.Face, world, client);
|
||||||
|
// Damage the item
|
||||||
|
if (damage != 0)
|
||||||
|
{
|
||||||
|
var tool = server.ItemRepository.GetItemProvider(client.SelectedItem.ID) as ToolItem;
|
||||||
|
if (tool != null && tool.Uses != -1)
|
||||||
|
{
|
||||||
|
var slot = client.SelectedItem;
|
||||||
|
slot.Metadata += damage;
|
||||||
|
if (slot.Metadata >= tool.Uses)
|
||||||
|
slot.Count = 0; // Destroy item
|
||||||
|
client.Inventory[client.SelectedSlot] = slot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,7 @@ namespace TrueCraft
|
|||||||
public IWindow CurrentWindow { get; internal set; }
|
public IWindow CurrentWindow { get; internal set; }
|
||||||
public bool EnableLogging { get; set; }
|
public bool EnableLogging { get; set; }
|
||||||
public IPacket LastSuccessfulPacket { get; set; }
|
public IPacket LastSuccessfulPacket { get; set; }
|
||||||
|
public DateTime ExpectedDigComplete { get; set; }
|
||||||
|
|
||||||
public Socket Connection { get; private set; }
|
public Socket Connection { get; private set; }
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user