Unify server and client implementations of windows

This commit is contained in:
Drew DeVault 2015-10-09 07:42:37 -04:00
parent 77f000ad2b
commit 0c6a973a69
8 changed files with 140 additions and 159 deletions

View File

@ -16,6 +16,7 @@ namespace TrueCraft.API.Windows
int MinecraftWasWrittenByFuckingIdiotsLength { get; } int MinecraftWasWrittenByFuckingIdiotsLength { get; }
ItemStack this[int index] { get; set; } ItemStack this[int index] { get; set; }
bool Empty { get; } bool Empty { get; }
short[] ReadOnlySlots { get; }
/// <summary> /// <summary>
/// Call this to "shift+click" an item from one area to another. /// Call this to "shift+click" an item from one area to another.

View File

@ -138,69 +138,17 @@ namespace TrueCraft.Client.Modules
var packet = new ClickWindowPacket(id, SelectedSlot, e.Button == MouseButton.Right, var packet = new ClickWindowPacket(id, SelectedSlot, e.Button == MouseButton.Right,
0, Keyboard.GetState().IsKeyDown(Keys.LeftShift) || Keyboard.GetState().IsKeyDown(Keys.RightShift), 0, Keyboard.GetState().IsKeyDown(Keys.LeftShift) || Keyboard.GetState().IsKeyDown(Keys.RightShift),
item.ID, item.Count, item.Metadata); item.ID, item.Count, item.Metadata);
// Special cases (TODO: make this more abstract? Read-only slots?) if (packet.SlotIndex == -999)
if ((Game.Client.CurrentWindow is InventoryWindow && SelectedSlot == InventoryWindow.CraftingOutputIndex)
|| (Game.Client.CurrentWindow is CraftingBenchWindow && SelectedSlot == CraftingBenchWindow.CraftingOutputIndex)
|| (Game.Client.CurrentWindow is FurnaceWindow && SelectedSlot == FurnaceWindow.OutputIndex))
{ {
if (HeldItem.Empty) // Special case (throwing item) TODO
HeldItem = (ItemStack)item.Clone();
else
{
if (item.CanMerge(HeldItem))
{
var held = HeldItem;
held.Count += item.Count;
HeldItem = held;
}
}
} }
else else
{ {
if (HeldItem.Empty) // See InteractionHandler.cs (in the server) for an explanation var backup = Game.Client.CurrentWindow.GetSlots();
{ var staging = (ItemStack)HeldItem.Clone();
if (!packet.Shift) Window.HandleClickPacket(packet, Game.Client.CurrentWindow, ref staging); // just for updating staging
{ HeldItem = staging;
if (packet.RightClick) Game.Client.CurrentWindow.SetSlots(backup);
{
var held = (ItemStack)item.Clone();
held.Count = (sbyte)((held.Count / 2) + (item.Count % 2));
HeldItem = held;
}
else
HeldItem = (ItemStack)item.Clone();
}
}
else
{
if (item.Empty)
{
if (packet.RightClick)
{
var held = HeldItem;
held.Count--;
HeldItem = held;
}
else
HeldItem = ItemStack.EmptyStack;
}
else
{
if (item.CanMerge(HeldItem))
{
if (packet.RightClick)
{
var held = HeldItem;
held.Count--;
HeldItem = held;
}
else
HeldItem = ItemStack.EmptyStack;
}
else
HeldItem = (ItemStack)item.Clone();
}
}
} }
Game.Client.QueuePacket(packet); Game.Client.QueuePacket(packet);
return true; return true;

View File

@ -140,6 +140,7 @@ namespace TrueCraft.Client
GraphicalModules.Add(DebugInfoModule); GraphicalModules.Add(DebugInfoModule);
InputModules.Add(windowModule); InputModules.Add(windowModule);
InputModules.Add(DebugInfoModule);
InputModules.Add(ChatModule); InputModules.Add(ChatModule);
InputModules.Add(new HUDModule(this, Pixel)); InputModules.Add(new HUDModule(this, Pixel));
InputModules.Add(new PlayerControlModule(this)); InputModules.Add(new PlayerControlModule(this));

View File

@ -40,10 +40,10 @@ namespace TrueCraft.Core.Windows
private bool Copying { get; set; } private bool Copying { get; set; }
public const int HotbarIndex = 37; public const short HotbarIndex = 37;
public const int CraftingGridIndex = 1; public const short CraftingGridIndex = 1;
public const int CraftingOutputIndex = 0; public const short CraftingOutputIndex = 0;
public const int MainIndex = 10; public const short MainIndex = 10;
public override string Name public override string Name
{ {
@ -61,6 +61,14 @@ namespace TrueCraft.Core.Windows
} }
} }
public override short[] ReadOnlySlots
{
get
{
return new[] { CraftingOutputIndex };
}
}
public override IWindowArea[] WindowAreas { get; protected set; } public override IWindowArea[] WindowAreas { get; protected set; }
#region Properties #region Properties

View File

@ -50,11 +50,11 @@ namespace TrueCraft.Core.Windows
private bool Copying { get; set; } private bool Copying { get; set; }
public const int IngredientIndex = 0; public const short IngredientIndex = 0;
public const int FuelIndex = 1; public const short FuelIndex = 1;
public const int OutputIndex = 2; public const short OutputIndex = 2;
public const int MainIndex = 3; public const short MainIndex = 3;
public const int HotbarIndex = 30; public const short HotbarIndex = 30;
public override string Name public override string Name
{ {
@ -72,6 +72,14 @@ namespace TrueCraft.Core.Windows
} }
} }
public override short[] ReadOnlySlots
{
get
{
return new[] { OutputIndex };
}
}
public override IWindowArea[] WindowAreas { get; protected set; } public override IWindowArea[] WindowAreas { get; protected set; }
public IWindowArea Ingredient public IWindowArea Ingredient

View File

@ -26,11 +26,11 @@ namespace TrueCraft.Core.Windows
#region Variables #region Variables
public const int HotbarIndex = 36; public const short HotbarIndex = 36;
public const int CraftingGridIndex = 1; public const short CraftingGridIndex = 1;
public const int CraftingOutputIndex = 0; public const short CraftingOutputIndex = 0;
public const int ArmorIndex = 5; public const short ArmorIndex = 5;
public const int MainIndex = 9; public const short MainIndex = 9;
public override string Name public override string Name
{ {
@ -48,6 +48,14 @@ namespace TrueCraft.Core.Windows
} }
} }
public override short[] ReadOnlySlots
{
get
{
return new[] { CraftingOutputIndex };
}
}
public override IWindowArea[] WindowAreas { get; protected set; } public override IWindowArea[] WindowAreas { get; protected set; }
#region Properties #region Properties

View File

@ -5,6 +5,7 @@ using System.Text;
using TrueCraft.API.Windows; using TrueCraft.API.Windows;
using TrueCraft.API; using TrueCraft.API;
using TrueCraft.API.Networking; using TrueCraft.API.Networking;
using TrueCraft.Core.Networking.Packets;
namespace TrueCraft.Core.Windows namespace TrueCraft.Core.Windows
{ {
@ -161,5 +162,94 @@ namespace TrueCraft.Core.Windows
Client = null; Client = null;
IsDisposed = true; IsDisposed = true;
} }
public virtual short[] ReadOnlySlots
{
get { return new short[0]; }
}
public static void HandleClickPacket(ClickWindowPacket packet, IWindow window, ref ItemStack itemStaging)
{
if (packet.SlotIndex >= window.Length || packet.SlotIndex < 0)
return;
var existing = window[packet.SlotIndex];
if (window.ReadOnlySlots.Contains(packet.SlotIndex))
{
if (itemStaging.ID == existing.ID || itemStaging.Empty)
{
if (itemStaging.Empty)
itemStaging = existing;
else
itemStaging.Count += existing.Count;
window[packet.SlotIndex] = ItemStack.EmptyStack;
}
return;
}
if (itemStaging.Empty) // Picking up something
{
if (packet.Shift)
{
window.MoveToAlternateArea(packet.SlotIndex);
}
else
{
if (packet.RightClick)
{
sbyte mod = (sbyte)(existing.Count % 2);
existing.Count /= 2;
itemStaging = existing;
itemStaging.Count += mod;
window[packet.SlotIndex] = existing;
}
else
{
itemStaging = window[packet.SlotIndex];
window[packet.SlotIndex] = ItemStack.EmptyStack;
}
}
}
else // Setting something down
{
if (existing.Empty) // Replace empty slot
{
if (packet.RightClick)
{
var newItem = (ItemStack)itemStaging.Clone();
newItem.Count = 1;
itemStaging.Count--;
window[packet.SlotIndex] = newItem;
}
else
{
window[packet.SlotIndex] = itemStaging;
itemStaging = ItemStack.EmptyStack;
}
}
else
{
if (existing.CanMerge(itemStaging)) // Merge items
{
// TODO: Consider the maximum stack size
if (packet.RightClick)
{
existing.Count++;
itemStaging.Count--;
window[packet.SlotIndex] = existing;
}
else
{
existing.Count += itemStaging.Count;
window[packet.SlotIndex] = existing;
itemStaging = ItemStack.EmptyStack;
}
}
else // Swap items
{
window[packet.SlotIndex] = itemStaging;
itemStaging = existing;
}
}
}
}
} }
} }

View File

@ -201,94 +201,11 @@ namespace TrueCraft.Handlers
server.GetEntityManagerForWorld(client.World).SpawnEntity(item); server.GetEntityManagerForWorld(client.World).SpawnEntity(item);
return; return;
} }
var staging = (ItemStack)client.ItemStaging.Clone();
Window.HandleClickPacket(packet, window, ref staging);
client.ItemStaging = staging;
if (packet.SlotIndex >= window.Length || packet.SlotIndex < 0) if (packet.SlotIndex >= window.Length || packet.SlotIndex < 0)
return; return;
ItemStack existing = window[packet.SlotIndex];
ItemStack held = client.ItemStaging;
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)
{
if (held.Empty)
held = existing;
else
held.Count += existing.Count;
client.ItemStaging = held;
window[packet.SlotIndex] = ItemStack.EmptyStack;
}
client.QueuePacket(new WindowItemsPacket(packet.WindowID, window.GetSlots()));
return;
}
if (client.ItemStaging.Empty) // Picking up something
{
if (packet.Shift)
{
window.MoveToAlternateArea(packet.SlotIndex);
}
else
{
if (packet.RightClick)
{
sbyte mod = (sbyte)(existing.Count % 2);
existing.Count /= 2;
held = existing;
held.Count += mod;
client.ItemStaging = held;
window[packet.SlotIndex] = existing;
}
else
{
client.ItemStaging = window[packet.SlotIndex];
window[packet.SlotIndex] = ItemStack.EmptyStack;
}
}
}
else // Setting something down
{
if (existing.Empty) // Replace empty slot
{
if (packet.RightClick)
{
var newItem = (ItemStack)client.ItemStaging.Clone();
newItem.Count = 1;
held.Count--;
window[packet.SlotIndex] = newItem;
client.ItemStaging = held;
}
else
{
window[packet.SlotIndex] = client.ItemStaging;
client.ItemStaging = ItemStack.EmptyStack;
}
}
else
{
if (existing.CanMerge(client.ItemStaging)) // Merge items
{
// TODO: Consider the maximum stack size
if (packet.RightClick)
{
existing.Count++;
held.Count--;
window[packet.SlotIndex] = existing;
client.ItemStaging = held;
}
else
{
existing.Count += client.ItemStaging.Count;
window[packet.SlotIndex] = existing;
client.ItemStaging = ItemStack.EmptyStack;
}
}
else // Swap items
{
window[packet.SlotIndex] = client.ItemStaging;
client.ItemStaging = existing;
}
}
}
client.QueuePacket(new WindowItemsPacket(packet.WindowID, window.GetSlots())); client.QueuePacket(new WindowItemsPacket(packet.WindowID, window.GetSlots()));
} }