Partially implement furnace blocks
This commit is contained in:
parent
6bfa813d54
commit
11489e7f95
15
TrueCraft.API/Logic/IBurnableItem.cs
Normal file
15
TrueCraft.API/Logic/IBurnableItem.cs
Normal 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; }
|
||||||
|
}
|
||||||
|
}
|
15
TrueCraft.API/Logic/ISmeltableItem.cs
Normal file
15
TrueCraft.API/Logic/ISmeltableItem.cs
Normal 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; }
|
||||||
|
}
|
||||||
|
}
|
@ -122,6 +122,8 @@
|
|||||||
<Compile Include="Physics\IPhysicsEngine.cs" />
|
<Compile Include="Physics\IPhysicsEngine.cs" />
|
||||||
<Compile Include="Physics\IPhysicsEntity.cs" />
|
<Compile Include="Physics\IPhysicsEntity.cs" />
|
||||||
<Compile Include="Physics\IAABBEntity.cs" />
|
<Compile Include="Physics\IAABBEntity.cs" />
|
||||||
|
<Compile Include="Logic\ISmeltableItem.cs" />
|
||||||
|
<Compile Include="Logic\IBurnableItem.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.Networking;
|
||||||
|
|
||||||
namespace TrueCraft.API.Windows
|
namespace TrueCraft.API.Windows
|
||||||
{
|
{
|
||||||
@ -6,6 +7,7 @@ namespace TrueCraft.API.Windows
|
|||||||
{
|
{
|
||||||
event EventHandler<WindowChangeEventArgs> WindowChange;
|
event EventHandler<WindowChangeEventArgs> WindowChange;
|
||||||
|
|
||||||
|
IRemoteClient Client { get; set; }
|
||||||
IWindowArea[] WindowAreas { get; }
|
IWindowArea[] WindowAreas { get; }
|
||||||
sbyte ID { get; set; }
|
sbyte ID { get; set; }
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
|
@ -3,6 +3,13 @@ using TrueCraft.API.Logic;
|
|||||||
using TrueCraft.API;
|
using TrueCraft.API;
|
||||||
using TrueCraft.API.Networking;
|
using TrueCraft.API.Networking;
|
||||||
using TrueCraft.API.World;
|
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
|
namespace TrueCraft.Core.Logic.Blocks
|
||||||
{
|
{
|
||||||
@ -20,6 +27,123 @@ namespace TrueCraft.Core.Logic.Blocks
|
|||||||
|
|
||||||
public override string DisplayName { get { return "Furnace"; } }
|
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)
|
public override Tuple<int, int> GetTextureMap(byte metadata)
|
||||||
{
|
{
|
||||||
return new Tuple<int, int>(13, 2);
|
return new Tuple<int, int>(13, 2);
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using TrueCraft.API.Logic;
|
using TrueCraft.API.Logic;
|
||||||
using TrueCraft.API;
|
using TrueCraft.API;
|
||||||
|
using TrueCraft.Core.Logic.Items;
|
||||||
|
|
||||||
namespace TrueCraft.Core.Logic.Blocks
|
namespace TrueCraft.Core.Logic.Blocks
|
||||||
{
|
{
|
||||||
public class IronOreBlock : BlockProvider
|
public class IronOreBlock : BlockProvider, ISmeltableItem
|
||||||
{
|
{
|
||||||
public static readonly byte BlockID = 0x0F;
|
public static readonly byte BlockID = 0x0F;
|
||||||
|
|
||||||
@ -38,5 +39,7 @@ namespace TrueCraft.Core.Logic.Blocks
|
|||||||
return ToolType.Pickaxe;
|
return ToolType.Pickaxe;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ItemStack SmeltingOutput { get { return new ItemStack(IronIngotItem.ItemID); } }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,7 +3,7 @@ using TrueCraft.API.Logic;
|
|||||||
|
|
||||||
namespace TrueCraft.Core.Logic.Items
|
namespace TrueCraft.Core.Logic.Items
|
||||||
{
|
{
|
||||||
public class CoalItem : ItemProvider
|
public class CoalItem : ItemProvider, IBurnableItem
|
||||||
{
|
{
|
||||||
public static readonly short ItemID = 0x107;
|
public static readonly short ItemID = 0x107;
|
||||||
|
|
||||||
@ -15,5 +15,7 @@ namespace TrueCraft.Core.Logic.Items
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override string DisplayName { get { return "Coal"; } }
|
public override string DisplayName { get { return "Coal"; } }
|
||||||
|
|
||||||
|
public TimeSpan BurnTime { get { return TimeSpan.FromSeconds(80); } }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,6 +16,13 @@ namespace TrueCraft.Core.Networking.Packets
|
|||||||
|
|
||||||
public byte ID { get { return 0x69; } }
|
public byte ID { get { return 0x69; } }
|
||||||
|
|
||||||
|
public UpdateProgressPacket(sbyte windowID, ProgressTarget target, short value)
|
||||||
|
{
|
||||||
|
WindowID = windowID;
|
||||||
|
Target = target;
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
public sbyte WindowID;
|
public sbyte WindowID;
|
||||||
public ProgressTarget Target;
|
public ProgressTarget Target;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -352,6 +352,7 @@
|
|||||||
<Compile Include="AI\WanderState.cs" />
|
<Compile Include="AI\WanderState.cs" />
|
||||||
<Compile Include="Physics\PhysicsEngine.cs" />
|
<Compile Include="Physics\PhysicsEngine.cs" />
|
||||||
<Compile Include="Entities\WolfEntity.cs" />
|
<Compile Include="Entities\WolfEntity.cs" />
|
||||||
|
<Compile Include="Windows\FurnaceWindow.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
144
TrueCraft.Core/Windows/FurnaceWindow.cs
Normal file
144
TrueCraft.Core/Windows/FurnaceWindow.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,15 +4,20 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using TrueCraft.API.Windows;
|
using TrueCraft.API.Windows;
|
||||||
using TrueCraft.API;
|
using TrueCraft.API;
|
||||||
|
using TrueCraft.API.Networking;
|
||||||
|
|
||||||
namespace TrueCraft.Core.Windows
|
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 abstract IWindowArea[] WindowAreas { get; protected set; }
|
||||||
|
|
||||||
public event EventHandler<WindowChangeEventArgs> WindowChange;
|
public event EventHandler<WindowChangeEventArgs> WindowChange;
|
||||||
|
|
||||||
|
public bool IsDisposed { get; private set; }
|
||||||
|
|
||||||
|
public IRemoteClient Client { get; set; }
|
||||||
|
|
||||||
public virtual void MoveToAlternateArea(int index)
|
public virtual void MoveToAlternateArea(int index)
|
||||||
{
|
{
|
||||||
int fromIndex = GetAreaIndex(index);
|
int fromIndex = GetAreaIndex(index);
|
||||||
@ -142,6 +147,8 @@ namespace TrueCraft.Core.Windows
|
|||||||
WindowChange(this, e);
|
WindowChange(this, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public event EventHandler Disposed;
|
||||||
|
|
||||||
public virtual void Dispose()
|
public virtual void Dispose()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < WindowAreas.Length; i++)
|
for (int i = 0; i < WindowAreas.Length; i++)
|
||||||
@ -149,6 +156,10 @@ namespace TrueCraft.Core.Windows
|
|||||||
WindowAreas[i].Dispose();
|
WindowAreas[i].Dispose();
|
||||||
}
|
}
|
||||||
WindowChange = null;
|
WindowChange = null;
|
||||||
|
if (Disposed != null)
|
||||||
|
Disposed(this, null);
|
||||||
|
Client = null;
|
||||||
|
IsDisposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,6 +208,7 @@ namespace TrueCraft
|
|||||||
public void OpenWindow(IWindow window)
|
public void OpenWindow(IWindow window)
|
||||||
{
|
{
|
||||||
CurrentWindow = window;
|
CurrentWindow = window;
|
||||||
|
window.Client = this;
|
||||||
window.ID = NextWindowID++;
|
window.ID = NextWindowID++;
|
||||||
if (NextWindowID < 0) NextWindowID = 1;
|
if (NextWindowID < 0) NextWindowID = 1;
|
||||||
QueuePacket(new OpenWindowPacket(window.ID, window.Type, window.Name, (sbyte)window.MinecraftWasWrittenByFuckingIdiotsLength));
|
QueuePacket(new OpenWindowPacket(window.ID, window.Type, window.Name, (sbyte)window.MinecraftWasWrittenByFuckingIdiotsLength));
|
||||||
|
Reference in New Issue
Block a user