Implement crafting benches
This commit is contained in:
parent
a070e7498e
commit
7c4c2ef5fc
@ -22,5 +22,6 @@ namespace TrueCraft.API.Networking
|
||||
void QueuePacket(IPacket packet);
|
||||
void SendMessage(string message);
|
||||
void Log(string message, params object[] parameters);
|
||||
void OpenWindow(IWindow window);
|
||||
}
|
||||
}
|
@ -7,6 +7,9 @@ namespace TrueCraft.API.Windows
|
||||
event EventHandler<WindowChangeEventArgs> WindowChange;
|
||||
|
||||
IWindowArea[] WindowAreas { get; }
|
||||
sbyte ID { get; set; }
|
||||
string Name { get; }
|
||||
sbyte Type { get; }
|
||||
int Length { get; }
|
||||
ItemStack this[int index] { get; set; }
|
||||
bool Empty { get; }
|
||||
@ -23,5 +26,9 @@ namespace TrueCraft.API.Windows
|
||||
/// Adds the specified item stack to this window, merging with established slots as neccessary.
|
||||
/// </summary>
|
||||
bool PickUpStack(ItemStack slot);
|
||||
/// <summary>
|
||||
/// Copy the contents of this window back into an inventory window after changes have been made.
|
||||
/// </summary>
|
||||
void CopyToInventory(IWindow inventoryWindow);
|
||||
}
|
||||
}
|
@ -1,6 +1,9 @@
|
||||
using System;
|
||||
using TrueCraft.API.Logic;
|
||||
using TrueCraft.API;
|
||||
using TrueCraft.API.World;
|
||||
using TrueCraft.API.Networking;
|
||||
using TrueCraft.Core.Windows;
|
||||
|
||||
namespace TrueCraft.Core.Logic.Blocks
|
||||
{
|
||||
@ -18,6 +21,13 @@ namespace TrueCraft.Core.Logic.Blocks
|
||||
|
||||
public override string DisplayName { get { return "Crafting Table"; } }
|
||||
|
||||
public override bool BlockRightClicked(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user)
|
||||
{
|
||||
var window = new CraftingBenchWindow(user.Server.CraftingRepository, (InventoryWindow)user.Inventory);
|
||||
user.OpenWindow(window);
|
||||
return false;
|
||||
}
|
||||
|
||||
public override Tuple<int, int> GetTextureMap(byte metadata)
|
||||
{
|
||||
return new Tuple<int, int>(11, 3);
|
||||
|
@ -7,7 +7,7 @@ using TrueCraft.Core.Logic.Blocks;
|
||||
|
||||
namespace TrueCraft.Core.Logic.Items
|
||||
{
|
||||
public class BedItem : ItemProvider
|
||||
public class BedItem : ItemProvider, ICraftingRecipe
|
||||
{
|
||||
public static readonly short ItemID = 0x163;
|
||||
|
||||
@ -59,5 +59,33 @@ namespace TrueCraft.Core.Logic.Items
|
||||
item.Count--;
|
||||
user.Inventory[user.SelectedSlot] = item;
|
||||
}
|
||||
|
||||
public ItemStack[,] Pattern
|
||||
{
|
||||
get
|
||||
{
|
||||
return new[,]
|
||||
{
|
||||
{
|
||||
new ItemStack(WoolBlock.BlockID),
|
||||
new ItemStack(WoolBlock.BlockID),
|
||||
new ItemStack(WoolBlock.BlockID),
|
||||
},
|
||||
{
|
||||
new ItemStack(WoodenPlanksBlock.BlockID),
|
||||
new ItemStack(WoodenPlanksBlock.BlockID),
|
||||
new ItemStack(WoodenPlanksBlock.BlockID),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public ItemStack Output
|
||||
{
|
||||
get
|
||||
{
|
||||
return new ItemStack(ItemID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -72,7 +72,7 @@ namespace TrueCraft.Core.Networking
|
||||
RegisterPacketType<LightningPacket>(serverbound: false, clientbound: true); // 0x47
|
||||
|
||||
RegisterPacketType<OpenWindowPacket>(serverbound: false, clientbound: true); // 0x64
|
||||
RegisterPacketType<CloseWindow>(); // 0x65
|
||||
RegisterPacketType<CloseWindowPacket>(); // 0x65
|
||||
RegisterPacketType<ClickWindowPacket>(serverbound: true, clientbound: false); // 0x66
|
||||
RegisterPacketType<SetSlotPacket>(serverbound: false, clientbound: true); // 0x67
|
||||
RegisterPacketType<WindowItemsPacket>(serverbound: false, clientbound: true); // 0x68
|
||||
|
@ -6,10 +6,15 @@ namespace TrueCraft.Core.Networking.Packets
|
||||
/// <summary>
|
||||
/// Sent by the server to forcibly close an inventory window, or from the client when naturally closed.
|
||||
/// </summary>
|
||||
public struct CloseWindow : IPacket
|
||||
public struct CloseWindowPacket : IPacket
|
||||
{
|
||||
public byte ID { get { return 0x65; } }
|
||||
|
||||
public CloseWindowPacket(sbyte windowID)
|
||||
{
|
||||
WindowID = windowID;
|
||||
}
|
||||
|
||||
public sbyte WindowID;
|
||||
|
||||
public void ReadPacket(IMinecraftStream stream)
|
@ -8,25 +8,25 @@ namespace TrueCraft.Core.Networking.Packets
|
||||
/// </summary>
|
||||
public struct OpenWindowPacket : IPacket
|
||||
{
|
||||
public enum WindowType
|
||||
{
|
||||
Chest = 0,
|
||||
Workbench = 1,
|
||||
Furnace = 2,
|
||||
Dispenser = 3
|
||||
}
|
||||
|
||||
public byte ID { get { return 0x64; } }
|
||||
|
||||
public OpenWindowPacket(sbyte windowID, sbyte type, string title, sbyte totalSlots)
|
||||
{
|
||||
WindowID = windowID;
|
||||
Type = type;
|
||||
Title = title;
|
||||
TotalSlots = totalSlots;
|
||||
}
|
||||
|
||||
public sbyte WindowID;
|
||||
public WindowType Type;
|
||||
public sbyte Type;
|
||||
public string Title;
|
||||
public sbyte TotalSlots;
|
||||
|
||||
public void ReadPacket(IMinecraftStream stream)
|
||||
{
|
||||
WindowID = stream.ReadInt8();
|
||||
Type = (WindowType)stream.ReadInt8();
|
||||
Type = stream.ReadInt8();
|
||||
Title = stream.ReadString8();
|
||||
TotalSlots = stream.ReadInt8();
|
||||
}
|
||||
@ -34,7 +34,7 @@ namespace TrueCraft.Core.Networking.Packets
|
||||
public void WritePacket(IMinecraftStream stream)
|
||||
{
|
||||
stream.WriteInt8(WindowID);
|
||||
stream.WriteInt8((sbyte)Type);
|
||||
stream.WriteInt8(Type);
|
||||
stream.WriteString8(Title);
|
||||
stream.WriteInt8(TotalSlots);
|
||||
}
|
||||
|
@ -153,7 +153,6 @@
|
||||
<Compile Include="Networking\Packets\EnvironmentStatePacket.cs" />
|
||||
<Compile Include="Networking\Packets\LightningPacket.cs" />
|
||||
<Compile Include="Networking\Packets\OpenWindowPacket.cs" />
|
||||
<Compile Include="Networking\Packets\CloseWindow.cs" />
|
||||
<Compile Include="Networking\Packets\ClickWindowPacket.cs" />
|
||||
<Compile Include="Networking\Packets\SetSlotPacket.cs" />
|
||||
<Compile Include="Networking\Packets\WindowItemsPacket.cs" />
|
||||
@ -270,6 +269,8 @@
|
||||
<Compile Include="Entities\PlayerEntity.cs" />
|
||||
<Compile Include="Logic\Blocks\AirBlock.cs" />
|
||||
<Compile Include="Entities\EntityFlags.cs" />
|
||||
<Compile Include="Windows\CraftingBenchWindow.cs" />
|
||||
<Compile Include="Networking\Packets\CloseWindowPacket.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
|
129
TrueCraft.Core/Windows/CraftingBenchWindow.cs
Normal file
129
TrueCraft.Core/Windows/CraftingBenchWindow.cs
Normal file
@ -0,0 +1,129 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using TrueCraft.API.Windows;
|
||||
using TrueCraft.API.Logic;
|
||||
using TrueCraft.API;
|
||||
|
||||
namespace TrueCraft.Core.Windows
|
||||
{
|
||||
public class CraftingBenchWindow : Window
|
||||
{
|
||||
public CraftingBenchWindow(ICraftingRepository craftingRepository, InventoryWindow inventory)
|
||||
{
|
||||
WindowAreas = new[]
|
||||
{
|
||||
new CraftingWindowArea(craftingRepository, CraftingOutputIndex, 3, 3),
|
||||
new WindowArea(MainIndex, 27, 9, 3), // Main inventory
|
||||
new WindowArea(HotbarIndex, 9, 9, 1) // Hotbar
|
||||
};
|
||||
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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#region Variables
|
||||
|
||||
private bool Copying { get; set; }
|
||||
|
||||
public const int HotbarIndex = 37;
|
||||
public const int CraftingGridIndex = 1;
|
||||
public const int CraftingOutputIndex = 0;
|
||||
public const int MainIndex = 10;
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Workbench";
|
||||
}
|
||||
}
|
||||
|
||||
public override sbyte Type
|
||||
{
|
||||
get
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public override IWindowArea[] WindowAreas { get; protected set; }
|
||||
|
||||
#region Properties
|
||||
|
||||
public IWindowArea CraftingGrid
|
||||
{
|
||||
get { return WindowAreas[0]; }
|
||||
}
|
||||
|
||||
public IWindowArea MainInventory
|
||||
{
|
||||
get { return WindowAreas[1]; }
|
||||
}
|
||||
|
||||
public IWindowArea Hotbar
|
||||
{
|
||||
get { return WindowAreas[2]; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
public override ItemStack[] GetSlots()
|
||||
{
|
||||
var relevantAreas = new[] { CraftingGrid };
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -9,7 +9,8 @@ namespace TrueCraft.Core.Windows
|
||||
public static readonly int CraftingOutput = 0;
|
||||
public ICraftingRepository Repository { get; set; }
|
||||
|
||||
public CraftingWindowArea(ICraftingRepository repository, int startIndex) : base(startIndex, 5, 2, 2)
|
||||
public CraftingWindowArea(ICraftingRepository repository, int startIndex, int width = 2, int height = 2)
|
||||
: base(startIndex, width * height + 1, width, height)
|
||||
{
|
||||
Repository = repository;
|
||||
WindowChange += HandleWindowChange;
|
||||
@ -50,12 +51,12 @@ namespace TrueCraft.Core.Windows
|
||||
if (found) break;
|
||||
}
|
||||
// Remove items
|
||||
for (int _x = 0; _x < recipe.Pattern.GetLength(0); _x++)
|
||||
for (int _x = 0; _x < recipe.Pattern.GetLength(1); _x++)
|
||||
{
|
||||
for (int _y = 0; _y < recipe.Pattern.GetLength(1); _y++)
|
||||
for (int _y = 0; _y < recipe.Pattern.GetLength(0); _y++)
|
||||
{
|
||||
var item = Items[(y + _y) * Width + (x + _x) + 1];
|
||||
item.Count -= recipe.Pattern[_x, _y].Count;
|
||||
item.Count -= recipe.Pattern[_y, _x].Count;
|
||||
Items[(y + _y) * Width + (x + _x) + 1] = item;
|
||||
}
|
||||
}
|
||||
@ -65,7 +66,7 @@ namespace TrueCraft.Core.Windows
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = new WindowArea(1, 4, 2, 2);
|
||||
var result = new WindowArea(1, Width * Height, Width, Height);
|
||||
for (var i = 1; i < Items.Length; i++)
|
||||
result.Items[i - 1] = Items[i];
|
||||
return result;
|
||||
|
@ -32,6 +32,22 @@ namespace TrueCraft.Core.Windows
|
||||
public const int ArmorIndex = 5;
|
||||
public const int MainIndex = 9;
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Inventory";
|
||||
}
|
||||
}
|
||||
|
||||
public override sbyte Type
|
||||
{
|
||||
get
|
||||
{
|
||||
return -1; // NOTE: This window does not have a type
|
||||
}
|
||||
}
|
||||
|
||||
public override IWindowArea[] WindowAreas { get; protected set; }
|
||||
|
||||
#region Properties
|
||||
@ -60,11 +76,13 @@ namespace TrueCraft.Core.Windows
|
||||
|
||||
#endregion
|
||||
|
||||
public override void CopyToInventory(IWindow inventoryWindow)
|
||||
{
|
||||
// This space intentionally left blank
|
||||
}
|
||||
|
||||
protected override IWindowArea GetLinkedArea(int index, ItemStack slot)
|
||||
{
|
||||
// TODO: Link armor
|
||||
//if (!slot.Empty && slot.AsItem() is IArmorItem && (index == 2 || index == 3))
|
||||
// return Armor;
|
||||
if (index == 0 || index == 1 || index == 3)
|
||||
return MainInventory;
|
||||
return Hotbar;
|
||||
|
@ -25,6 +25,10 @@ namespace TrueCraft.Core.Windows
|
||||
if (WindowChange != null && destination != -1)
|
||||
WindowChange(this, new WindowChangeEventArgs(destination + to.StartIndex, slot));
|
||||
}
|
||||
|
||||
public sbyte ID { get; set; }
|
||||
public abstract string Name { get; }
|
||||
public abstract sbyte Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// When shift-clicking items between areas, this method is used
|
||||
@ -34,6 +38,7 @@ namespace TrueCraft.Core.Windows
|
||||
/// <param name="slot">The item being moved</param>
|
||||
/// <returns>The area to place the item into</returns>
|
||||
protected abstract IWindowArea GetLinkedArea(int index, ItemStack slot);
|
||||
public abstract void CopyToInventory(IWindow inventoryWindow);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the window area to handle this index and adjust index accordingly
|
||||
@ -81,7 +86,7 @@ namespace TrueCraft.Core.Windows
|
||||
}
|
||||
}
|
||||
|
||||
public ItemStack[] GetSlots()
|
||||
public virtual ItemStack[] GetSlots()
|
||||
{
|
||||
int length = WindowAreas.Sum(area => area.Length);
|
||||
var slots = new ItemStack[length];
|
||||
|
@ -47,14 +47,14 @@ namespace TrueCraft
|
||||
|
||||
public bool TestRecipe(IWindowArea craftingArea, ICraftingRecipe recipe, int x, int y)
|
||||
{
|
||||
if (x + recipe.Pattern.GetLength(0) > craftingArea.Width || y + recipe.Pattern.GetLength(1) > craftingArea.Height)
|
||||
if (x + recipe.Pattern.GetLength(1) > craftingArea.Width || y + recipe.Pattern.GetLength(0) > craftingArea.Height)
|
||||
return false;
|
||||
for (int _x = 0; _x < recipe.Pattern.GetLength(0); _x++)
|
||||
for (int _x = 0; _x < recipe.Pattern.GetLength(1); _x++)
|
||||
{
|
||||
for (int _y = 0; _y < recipe.Pattern.GetLength(1); _y++)
|
||||
for (int _y = 0; _y < recipe.Pattern.GetLength(0); _y++)
|
||||
{
|
||||
var supplied = craftingArea[(y + _y) * craftingArea.Width + (x + _x)];
|
||||
var required = recipe.Pattern[_x, _y];
|
||||
var required = recipe.Pattern[_y, _x];
|
||||
if (supplied.ID != required.ID || supplied.Count < required.Count)
|
||||
{
|
||||
return false;
|
||||
@ -70,14 +70,29 @@ namespace TrueCraft
|
||||
{
|
||||
for (int y = 0; y < craftingArea.Height; y++)
|
||||
{
|
||||
var item = craftingArea[y * craftingArea.Width + x];
|
||||
if (item.ID == recipe.Pattern[0, 0].ID &&
|
||||
item.Count >= recipe.Pattern[0, 0].Count)
|
||||
if (TestRecipe(craftingArea, recipe, x, y))
|
||||
{
|
||||
return TestRecipe(craftingArea, recipe, x, y);
|
||||
// Check to make sure there aren't any sneaky unused items in the grid
|
||||
for (int _x = 0; _x < x; x++)
|
||||
{
|
||||
for (int _y = 0; _y < y; _y++)
|
||||
{
|
||||
var supplied = craftingArea[(y + _y) * craftingArea.Width + (x + _x)];
|
||||
if (!supplied.Empty)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int _y = 0; _y < y; _y++)
|
||||
{
|
||||
for (int _x = 0; _x < x; x++)
|
||||
{
|
||||
var supplied = craftingArea[(y + _y) * craftingArea.Width + (x + _x)];
|
||||
if (!supplied.Empty)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!item.Empty)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -124,7 +124,8 @@ namespace TrueCraft.Handlers
|
||||
return;
|
||||
ItemStack existing = window[packet.SlotIndex];
|
||||
ItemStack held = client.ItemStaging;
|
||||
if (packet.SlotIndex == InventoryWindow.CraftingOutputIndex)
|
||||
if (packet.SlotIndex == InventoryWindow.CraftingOutputIndex
|
||||
&& (window is InventoryWindow || window is CraftingBenchWindow))
|
||||
{
|
||||
// Stupid special case because Minecraft was written by morons
|
||||
if (held.ID == existing.ID || held.Empty)
|
||||
@ -208,6 +209,13 @@ namespace TrueCraft.Handlers
|
||||
}
|
||||
}
|
||||
|
||||
public static void HandleCloseWindowPacket(IPacket _packet, IRemoteClient _client, IMultiplayerServer server)
|
||||
{
|
||||
var packet = (CloseWindowPacket)_packet;
|
||||
if (packet.WindowID != 0)
|
||||
(_client as RemoteClient).CloseWindow(true);
|
||||
}
|
||||
|
||||
public static void HandleChangeHeldItem(IPacket _packet, IRemoteClient _client, IMultiplayerServer server)
|
||||
{
|
||||
var packet = (ChangeHeldItemPacket)_packet;
|
||||
|
@ -29,6 +29,7 @@ namespace TrueCraft.Handlers
|
||||
server.RegisterPacketHandler(new ChangeHeldItemPacket().ID, InteractionHandlers.HandleChangeHeldItem);
|
||||
server.RegisterPacketHandler(new PlayerActionPacket().ID, InteractionHandlers.HandlePlayerAction);
|
||||
server.RegisterPacketHandler(new ClickWindowPacket().ID, InteractionHandlers.HandleClickWindowPacket);
|
||||
server.RegisterPacketHandler(new CloseWindowPacket().ID, InteractionHandlers.HandleCloseWindowPacket);
|
||||
}
|
||||
|
||||
internal static void HandleKeepAlive(IPacket _packet, IRemoteClient _client, IMultiplayerServer server)
|
||||
|
@ -37,6 +37,7 @@ namespace TrueCraft
|
||||
KnownEntities = new List<IEntity>();
|
||||
Disconnected = false;
|
||||
EnableLogging = server.EnableClientLogging;
|
||||
NextWindowID = 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -44,6 +45,7 @@ namespace TrueCraft
|
||||
/// </summary>
|
||||
internal List<IEntity> KnownEntities { get; set; }
|
||||
internal bool Disconnected { get; set; }
|
||||
internal sbyte NextWindowID { get; set; }
|
||||
|
||||
public NetworkStream NetworkStream { get; set; }
|
||||
public IMinecraftStream MinecraftStream { get; internal set; }
|
||||
@ -55,7 +57,7 @@ namespace TrueCraft
|
||||
public IWindow Inventory { get; private set; }
|
||||
public short SelectedSlot { get; internal set; }
|
||||
public ItemStack ItemStaging { get; set; }
|
||||
public IWindow CurrentWindow { get; set; }
|
||||
public IWindow CurrentWindow { get; internal set; }
|
||||
public bool EnableLogging { get; set; }
|
||||
|
||||
private IEntity _Entity;
|
||||
@ -114,6 +116,23 @@ namespace TrueCraft
|
||||
}
|
||||
}
|
||||
|
||||
public void OpenWindow(IWindow window)
|
||||
{
|
||||
CurrentWindow = window;
|
||||
window.ID = NextWindowID++;
|
||||
if (NextWindowID < 0) NextWindowID = 1;
|
||||
QueuePacket(new OpenWindowPacket(window.ID, window.Type, window.Name, (sbyte)window.Length));
|
||||
QueuePacket(new WindowItemsPacket(window.ID, window.GetSlots()));
|
||||
}
|
||||
|
||||
public void CloseWindow(bool clientInitiated = false)
|
||||
{
|
||||
if (!clientInitiated)
|
||||
QueuePacket(new CloseWindowPacket(CurrentWindow.ID));
|
||||
CurrentWindow.CopyToInventory(Inventory);
|
||||
CurrentWindow = InventoryWindow;
|
||||
}
|
||||
|
||||
public void Log(string message, params object[] parameters)
|
||||
{
|
||||
if (EnableLogging)
|
||||
|
Loading…
x
Reference in New Issue
Block a user