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
|
||||
{
|
||||
/// <summary>
|
||||
/// Minecraft stream used to communicate with this client.
|
||||
/// </summary>
|
||||
IMinecraftStream MinecraftStream { get; }
|
||||
/// <summary>
|
||||
/// Returns true if this client has data pending in the network stream.
|
||||
/// </summary>
|
||||
bool DataAvailable { get; }
|
||||
/// <summary>
|
||||
/// The world this client is present in.
|
||||
/// </summary>
|
||||
IWorld World { get; }
|
||||
/// <summary>
|
||||
/// The entity associated with this client.
|
||||
/// </summary>
|
||||
IEntity Entity { get; }
|
||||
/// <summary>
|
||||
/// This client's inventory.
|
||||
/// </summary>
|
||||
IWindow Inventory { get; }
|
||||
/// <summary>
|
||||
/// The username of the connected client. May be null if not yet ascertained.
|
||||
/// </summary>
|
||||
string Username { get; }
|
||||
/// <summary>
|
||||
/// The slot index this user has selected in their hotbar.
|
||||
/// </summary>
|
||||
short SelectedSlot { get; }
|
||||
/// <summary>
|
||||
/// The item stack at the slot the user has selected in their hotbar.
|
||||
/// </summary>
|
||||
ItemStack SelectedItem { get; }
|
||||
/// <summary>
|
||||
/// The server this user is playing on.
|
||||
/// </summary>
|
||||
IMultiplayerServer Server { get; }
|
||||
/// <summary>
|
||||
/// If true, this client will be sent logging information as chat messages.
|
||||
/// </summary>
|
||||
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; }
|
||||
|
||||
/// <summary>
|
||||
/// Loads player data from disk for this client.
|
||||
/// </summary>
|
||||
bool Load();
|
||||
/// <summary>
|
||||
/// Saves player data to disk for this client.
|
||||
/// </summary>
|
||||
void Save();
|
||||
/// <summary>
|
||||
/// Queues a packet to be sent to this client.
|
||||
/// </summary>
|
||||
void QueuePacket(IPacket packet);
|
||||
|
||||
/// <summary>
|
||||
/// Disconnects this client from the server.
|
||||
/// </summary>
|
||||
void Disconnect();
|
||||
|
||||
/// <summary>
|
||||
/// Sends a chat message to this client.
|
||||
/// </summary>
|
||||
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);
|
||||
/// <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);
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ using TrueCraft.API.Server;
|
||||
using TrueCraft.Core.Logic.Blocks;
|
||||
using System.Linq;
|
||||
using fNbt;
|
||||
using TrueCraft.Core.Logic.Items;
|
||||
|
||||
namespace TrueCraft.Core.Logic
|
||||
{
|
||||
@ -242,5 +243,91 @@ namespace TrueCraft.Core.Logic
|
||||
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 Coordinates3D GetSupportDirection(BlockDescriptor descriptor)
|
||||
{
|
||||
return Coordinates3D.Down;
|
||||
}
|
||||
|
||||
public override Tuple<int, int> GetTextureMap(byte metadata)
|
||||
{
|
||||
return new Tuple<int, int>(7, 2);
|
||||
|
@ -15,5 +15,27 @@ namespace TrueCraft.Core.Logic
|
||||
public virtual short BaseDurability { get { return 0; } }
|
||||
|
||||
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>
|
||||
</Reference>
|
||||
<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>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
|
||||
</packages>
|
@ -34,12 +34,12 @@
|
||||
<Reference Include="Xwt">
|
||||
<HintPath>..\lib\Xwt.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Ionic.Zip.Reduced">
|
||||
<HintPath>..\lib\Ionic.Zip.Reduced.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
@ -96,10 +96,10 @@
|
||||
<None Include="Xwt.WPF.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
<None Include="truecraft">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Content\truecraft-logo.png" />
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
|
||||
</packages>
|
@ -12,6 +12,7 @@ using fNbt;
|
||||
using TrueCraft.Core.Logic.Blocks;
|
||||
using System.Linq;
|
||||
using TrueCraft.Core.Logic.Items;
|
||||
using TrueCraft.Core.Logic;
|
||||
|
||||
namespace TrueCraft.Handlers
|
||||
{
|
||||
@ -25,6 +26,8 @@ namespace TrueCraft.Handlers
|
||||
var position = new Coordinates3D(packet.X, packet.Y, packet.Z);
|
||||
var descriptor = world.GetBlockData(position);
|
||||
var provider = server.BlockRepository.GetBlockProvider(descriptor.ID);
|
||||
short damage;
|
||||
int time;
|
||||
switch (packet.PlayerAction)
|
||||
{
|
||||
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
|
||||
// for hardness == 0 blocks.
|
||||
|
||||
if (provider != null && provider.Hardness == 0
|
||||
|| (client.SelectedItem.ID == ShearsItem.ItemID && provider is LeavesBlock))
|
||||
time = BlockProvider.GetHarvestTime(descriptor.ID, client.SelectedItem.ID, out damage);
|
||||
if (time <= 20)
|
||||
{
|
||||
provider.BlockMined(descriptor, packet.Face, world, client);
|
||||
break;
|
||||
}
|
||||
client.ExpectedDigComplete = DateTime.UtcNow.AddMilliseconds(time);
|
||||
break;
|
||||
case PlayerDiggingPacket.Action.StopDigging:
|
||||
foreach (var nearbyClient in server.Clients)
|
||||
@ -76,7 +83,29 @@ namespace TrueCraft.Handlers
|
||||
c.QueuePacket(new AnimationPacket(client.Entity.EntityID, AnimationPacket.PlayerAnimation.None));
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -70,6 +70,7 @@ namespace TrueCraft
|
||||
public IWindow CurrentWindow { get; internal set; }
|
||||
public bool EnableLogging { get; set; }
|
||||
public IPacket LastSuccessfulPacket { get; set; }
|
||||
public DateTime ExpectedDigComplete { get; set; }
|
||||
|
||||
public Socket Connection { get; private set; }
|
||||
|
||||
|
Reference in New Issue
Block a user