Partially implement furnace blocks

This commit is contained in:
Drew DeVault 2015-10-04 15:46:43 -04:00
parent 6bfa813d54
commit 11489e7f95
12 changed files with 330 additions and 3 deletions

View File

@ -0,0 +1,15 @@
using System;
namespace TrueCraft.API.Logic
{
/// <summary>
/// Describes an item that can be burnt as fuel in a furnace.
/// </summary>
public interface IBurnableItem
{
/// <summary>
/// The duration of time this item can act as fuel.
/// </summary>
TimeSpan BurnTime { get; }
}
}

View File

@ -0,0 +1,15 @@
using System;
namespace TrueCraft.API.Logic
{
/// <summary>
/// Describes an item that can be smelted in a furnace to produce a new item.
/// </summary>
public interface ISmeltableItem
{
/// <summary>
/// The item this becomes when smelted.
/// </summary>
ItemStack SmeltingOutput { get; }
}
}

View File

@ -122,6 +122,8 @@
<Compile Include="Physics\IPhysicsEngine.cs" />
<Compile Include="Physics\IPhysicsEntity.cs" />
<Compile Include="Physics\IAABBEntity.cs" />
<Compile Include="Logic\ISmeltableItem.cs" />
<Compile Include="Logic\IBurnableItem.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup />

View File

@ -1,4 +1,5 @@
using System;
using TrueCraft.API.Networking;
namespace TrueCraft.API.Windows
{
@ -6,6 +7,7 @@ namespace TrueCraft.API.Windows
{
event EventHandler<WindowChangeEventArgs> WindowChange;
IRemoteClient Client { get; set; }
IWindowArea[] WindowAreas { get; }
sbyte ID { get; set; }
string Name { get; }

View File

@ -3,6 +3,13 @@ using TrueCraft.API.Logic;
using TrueCraft.API;
using TrueCraft.API.Networking;
using TrueCraft.API.World;
using TrueCraft.Core.Windows;
using TrueCraft.API.Windows;
using System.Collections.Generic;
using fNbt;
using TrueCraft.API.Server;
using TrueCraft.Core.Networking.Packets;
using TrueCraft.Core.Entities;
namespace TrueCraft.Core.Logic.Blocks
{
@ -20,6 +27,123 @@ namespace TrueCraft.Core.Logic.Blocks
public override string DisplayName { get { return "Furnace"; } }
protected override ItemStack[] GetDrop(BlockDescriptor descriptor, ItemStack item)
{
return new ItemStack[] { new ItemStack(BlockID) };
}
public override void BlockMined(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user)
{
var entity = world.GetTileEntity(descriptor.Coordinates);
if (entity != null)
{
foreach (var item in (NbtList)entity["Items"])
{
var manager = user.Server.GetEntityManagerForWorld(world);
var slot = ItemStack.FromNbt((NbtCompound)item);
manager.SpawnEntity(new ItemEntity(descriptor.Coordinates + new Vector3(0.5), slot));
}
world.SetTileEntity(descriptor.Coordinates, null);
}
base.BlockMined(descriptor, face, world, user);
}
public override bool BlockRightClicked(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user)
{
var window = new FurnaceWindow(user.Server.Scheduler, descriptor.Coordinates,
user.Server.ItemRepository, (InventoryWindow)user.Inventory);
var entity = world.GetTileEntity(descriptor.Coordinates);
if (entity != null)
{
int i = 0;
foreach (var item in (NbtList)entity["Items"])
{
var slot = ItemStack.FromNbt((NbtCompound)item);
window[i++] = slot;
}
}
user.OpenWindow(window);
if (entity != null)
{
var burnTime = entity["BurnTime"].ShortValue;
var burnTotal = entity["BurnTotal"].ShortValue;
var cookTime = entity["CookTime"].ShortValue;
var burnProgress = (short)(((double)burnTime / burnTotal) * 250);
if (burnTime == 0)
burnProgress = 0;
if (cookTime != 0)
window.Client.QueuePacket(new UpdateProgressPacket(window.ID,
UpdateProgressPacket.ProgressTarget.ItemCompletion, cookTime));
if (burnProgress != 0)
window.Client.QueuePacket(new UpdateProgressPacket(window.ID,
UpdateProgressPacket.ProgressTarget.AvailableHeat, burnProgress));
}
window.WindowChange += (sender, e) => FurnaceWindowChanged(sender, e, world);
return false;
}
private bool Handling = false;
private NbtCompound CreateTileEntity()
{
return new NbtCompound(new NbtTag[]
{
new NbtShort("BurnTime", 0),
new NbtShort("BurnTotal", 0),
new NbtShort("CookTime", 20),
new NbtList("Items", new[]
{
ItemStack.EmptyStack.ToNbt(),
ItemStack.EmptyStack.ToNbt(),
ItemStack.EmptyStack.ToNbt()
}, NbtTagType.Compound)
});
}
protected void FurnaceWindowChanged(object sender, WindowChangeEventArgs e, IWorld world)
{
if (Handling)
return;
var window = sender as FurnaceWindow;
var index = e.SlotIndex;
if (index >= FurnaceWindow.MainIndex)
return;
Handling = true;
window[index] = e.Value;
var entity = world.GetTileEntity(window.Coordinates);
if (entity == null)
entity = CreateTileEntity();
entity["Items"] = new NbtList("Items", new NbtTag[]
{
window[0].ToNbt(), window[1].ToNbt(), window[2].ToNbt()
}, NbtTagType.Compound);
world.SetTileEntity(window.Coordinates, entity);
UpdateFurnaceState(window.EventScheduler, world, entity, window.ItemRepository, window.Coordinates, window, TimeSpan.Zero);
Handling = false;
}
private void UpdateFurnaceState(IEventScheduler scheduler, IWorld world, NbtCompound tileEntity,
IItemRepository itemRepository, Coordinates3D coords, FurnaceWindow window, TimeSpan elapsed)
{
if (world.GetBlockID(coords) != FurnaceBlock.BlockID && world.GetBlockID(coords) != LitFurnaceBlock.BlockID)
{
if (window != null && !window.IsDisposed)
window.Dispose();
return;
}
// TODO
}
public override Tuple<int, int> GetTextureMap(byte metadata)
{
return new Tuple<int, int>(13, 2);

View File

@ -1,10 +1,11 @@
using System;
using TrueCraft.API.Logic;
using TrueCraft.API;
using TrueCraft.Core.Logic.Items;
namespace TrueCraft.Core.Logic.Blocks
{
public class IronOreBlock : BlockProvider
public class IronOreBlock : BlockProvider, ISmeltableItem
{
public static readonly byte BlockID = 0x0F;
@ -38,5 +39,7 @@ namespace TrueCraft.Core.Logic.Blocks
return ToolType.Pickaxe;
}
}
public ItemStack SmeltingOutput { get { return new ItemStack(IronIngotItem.ItemID); } }
}
}

View File

@ -3,7 +3,7 @@ using TrueCraft.API.Logic;
namespace TrueCraft.Core.Logic.Items
{
public class CoalItem : ItemProvider
public class CoalItem : ItemProvider, IBurnableItem
{
public static readonly short ItemID = 0x107;
@ -15,5 +15,7 @@ namespace TrueCraft.Core.Logic.Items
}
public override string DisplayName { get { return "Coal"; } }
public TimeSpan BurnTime { get { return TimeSpan.FromSeconds(80); } }
}
}

View File

@ -16,6 +16,13 @@ namespace TrueCraft.Core.Networking.Packets
public byte ID { get { return 0x69; } }
public UpdateProgressPacket(sbyte windowID, ProgressTarget target, short value)
{
WindowID = windowID;
Target = target;
Value = value;
}
public sbyte WindowID;
public ProgressTarget Target;
/// <summary>

View File

@ -352,6 +352,7 @@
<Compile Include="AI\WanderState.cs" />
<Compile Include="Physics\PhysicsEngine.cs" />
<Compile Include="Entities\WolfEntity.cs" />
<Compile Include="Windows\FurnaceWindow.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>

View File

@ -0,0 +1,144 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TrueCraft.API.Windows;
using TrueCraft.API.Logic;
using TrueCraft.API;
using TrueCraft.API.Server;
namespace TrueCraft.Core.Windows
{
public class FurnaceWindow : Window
{
public IItemRepository ItemRepository { get; set; }
public IEventScheduler EventScheduler { get; set; }
public Coordinates3D Coordinates { get; set; }
public FurnaceWindow(IEventScheduler scheduler, Coordinates3D coordinates,
IItemRepository itemRepository, InventoryWindow inventory)
{
ItemRepository = itemRepository;
EventScheduler = scheduler;
Coordinates = coordinates;
WindowAreas = new[]
{
new WindowArea(IngredientIndex, 1, 1, 1),
new WindowArea(FuelIndex, 1, 1, 1),
new WindowArea(OutputIndex, 1, 1, 1),
new WindowArea(MainIndex, 27, 9, 3),
new WindowArea(HotbarIndex, 9, 9, 1)
};
inventory.MainInventory.CopyTo(MainInventory);
inventory.Hotbar.CopyTo(Hotbar);
foreach (var area in WindowAreas)
area.WindowChange += (s, e) => OnWindowChange(new WindowChangeEventArgs(
(s as WindowArea).StartIndex + e.SlotIndex, e.Value));
Copying = false;
inventory.WindowChange += (sender, e) =>
{
if (Copying) return;
if ((e.SlotIndex >= InventoryWindow.MainIndex && e.SlotIndex < InventoryWindow.MainIndex + inventory.MainInventory.Length)
|| (e.SlotIndex >= InventoryWindow.HotbarIndex && e.SlotIndex < InventoryWindow.HotbarIndex + inventory.Hotbar.Length))
{
inventory.MainInventory.CopyTo(MainInventory);
inventory.Hotbar.CopyTo(Hotbar);
}
};
}
private bool Copying { get; set; }
public const int IngredientIndex = 0;
public const int FuelIndex = 1;
public const int OutputIndex = 2;
public const int MainIndex = 3;
public const int HotbarIndex = 30;
public override string Name
{
get
{
return "Furnace";
}
}
public override sbyte Type
{
get
{
return 2;
}
}
public override IWindowArea[] WindowAreas { get; protected set; }
public IWindowArea Ingredient
{
get { return WindowAreas[0]; }
}
public IWindowArea Fuel
{
get { return WindowAreas[1]; }
}
public IWindowArea Output
{
get { return WindowAreas[2]; }
}
public IWindowArea MainInventory
{
get { return WindowAreas[3]; }
}
public IWindowArea Hotbar
{
get { return WindowAreas[4]; }
}
public override ItemStack[] GetSlots()
{
var relevantAreas = new[] { Ingredient, Fuel, Output };
int length = relevantAreas.Sum(area => area.Length);
var slots = new ItemStack[length];
foreach (var windowArea in relevantAreas)
Array.Copy(windowArea.Items, 0, slots, windowArea.StartIndex, windowArea.Length);
return slots;
}
public override void CopyToInventory(IWindow inventoryWindow)
{
var window = (InventoryWindow)inventoryWindow;
Copying = true;
MainInventory.CopyTo(window.MainInventory);
Hotbar.CopyTo(window.Hotbar);
Copying = false;
}
protected override IWindowArea GetLinkedArea(int index, ItemStack slot)
{
if (index < MainIndex)
return MainInventory;
return Hotbar;
}
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))
//&& item.Count + slot.Count < Item.GetMaximumStackSize(new ItemDescriptor(item.Id, item.Metadata)))) // TODO
{
area = Hotbar;
break;
}
}
int index = area.MoveOrMergeItem(-1, slot, null);
return index != -1;
}
}
}

View File

@ -4,15 +4,20 @@ using System.Linq;
using System.Text;
using TrueCraft.API.Windows;
using TrueCraft.API;
using TrueCraft.API.Networking;
namespace TrueCraft.Core.Windows
{
public abstract class Window : IWindow, IDisposable
public abstract class Window : IWindow, IDisposable, IEventSubject
{
public abstract IWindowArea[] WindowAreas { get; protected set; }
public event EventHandler<WindowChangeEventArgs> WindowChange;
public bool IsDisposed { get; private set; }
public IRemoteClient Client { get; set; }
public virtual void MoveToAlternateArea(int index)
{
int fromIndex = GetAreaIndex(index);
@ -142,6 +147,8 @@ namespace TrueCraft.Core.Windows
WindowChange(this, e);
}
public event EventHandler Disposed;
public virtual void Dispose()
{
for (int i = 0; i < WindowAreas.Length; i++)
@ -149,6 +156,10 @@ namespace TrueCraft.Core.Windows
WindowAreas[i].Dispose();
}
WindowChange = null;
if (Disposed != null)
Disposed(this, null);
Client = null;
IsDisposed = true;
}
}
}

View File

@ -208,6 +208,7 @@ namespace TrueCraft
public void OpenWindow(IWindow window)
{
CurrentWindow = window;
window.Client = this;
window.ID = NextWindowID++;
if (NextWindowID < 0) NextWindowID = 1;
QueuePacket(new OpenWindowPacket(window.ID, window.Type, window.Name, (sbyte)window.MinecraftWasWrittenByFuckingIdiotsLength));