diff --git a/.gitignore b/.gitignore index 62e4e8f2..30547060 100644 --- a/.gitignore +++ b/.gitignore @@ -350,3 +350,4 @@ MigrationBackup/ # Ionide (cross platform F# VS Code tools) working folder .ionide/ +/todo_mv.txt diff --git a/Components/TEAbstractStorageUnit.cs b/Components/TEAbstractStorageUnit.cs index d6ba155d..809ed47c 100644 --- a/Components/TEAbstractStorageUnit.cs +++ b/Components/TEAbstractStorageUnit.cs @@ -11,88 +11,88 @@ namespace MagicStorage.Components { - public abstract class TEAbstractStorageUnit : TEStorageComponent - { - private bool inactive; - private Point16 center; + public abstract class TEAbstractStorageUnit : TEStorageComponent + { + private bool inactive; + private Point16 center; - public bool Inactive - { - get - { - return inactive; - } - set - { - inactive = value; - } - } + public bool Inactive + { + get + { + return inactive; + } + set + { + inactive = value; + } + } - public abstract bool IsFull - { - get; - } + public abstract bool IsFull + { + get; + } - public bool Link(Point16 pos) - { - bool changed = pos != center; - center = pos; - return changed; - } + public bool Link(Point16 pos) + { + bool changed = pos != center; + center = pos; + return changed; + } - public bool Unlink() - { - return Link(new Point16(-1, -1)); - } + public bool Unlink() + { + return Link(new Point16(-1, -1)); + } - public TEStorageHeart GetHeart() - { - if (center != new Point16(-1, -1) && TileEntity.ByPosition.ContainsKey(center) && TileEntity.ByPosition[center] is TEStorageCenter) - { - return ((TEStorageCenter)TileEntity.ByPosition[center]).GetHeart(); - } - return null; - } + public TEStorageHeart GetHeart() + { + if (center != new Point16(-1, -1) && TileEntity.ByPosition.ContainsKey(center) && TileEntity.ByPosition[center] is TEStorageCenter) + { + return ((TEStorageCenter)TileEntity.ByPosition[center]).GetHeart(); + } + return null; + } - public abstract bool HasSpaceInStackFor(Item check, bool locked = false); + public abstract bool HasSpaceInStackFor(Item check); - public abstract bool HasItem(Item check, bool locked = false); + public abstract bool HasItem(Item check); - public abstract IEnumerable GetItems(); + public abstract IEnumerable GetItems(); - public abstract void DepositItem(Item toDeposit, bool locked = false); + public abstract void DepositItem(Item toDeposit); - public abstract Item TryWithdraw(Item lookFor, bool locked = false); + public abstract Item TryWithdraw(Item lookFor, bool keepOneIfFavorite = false); - public override TagCompound Save() - { - TagCompound tag = new TagCompound(); - tag.Set("Inactive", inactive); - TagCompound tagCenter = new TagCompound(); - tagCenter.Set("X", center.X); - tagCenter.Set("Y", center.Y); - tag.Set("Center", tagCenter); - return tag; - } + public override TagCompound Save() + { + TagCompound tag = new TagCompound(); + tag.Set("Inactive", inactive); + TagCompound tagCenter = new TagCompound(); + tagCenter.Set("X", center.X); + tagCenter.Set("Y", center.Y); + tag.Set("Center", tagCenter); + return tag; + } - public override void Load(TagCompound tag) - { - inactive = tag.GetBool("Inactive"); - TagCompound tagCenter = tag.GetCompound("Center"); - center = new Point16(tagCenter.GetShort("X"), tagCenter.GetShort("Y")); - } + public override void Load(TagCompound tag) + { + inactive = tag.GetBool("Inactive"); + TagCompound tagCenter = tag.GetCompound("Center"); + center = new Point16(tagCenter.GetShort("X"), tagCenter.GetShort("Y")); + } - public override void NetSend(BinaryWriter writer, bool lightSend) - { - writer.Write(inactive); - writer.Write(center.X); - writer.Write(center.Y); - } + public override void NetSend(BinaryWriter writer, bool lightSend) + { + writer.Write(inactive); + writer.Write(center.X); + writer.Write(center.Y); + } - public override void NetReceive(BinaryReader reader, bool lightReceive) - { - inactive = reader.ReadBoolean(); - center = new Point16(reader.ReadInt16(), reader.ReadInt16()); - } - } + public override void NetReceive(BinaryReader reader, bool lightReceive) + { + inactive = reader.ReadBoolean(); + center = new Point16(reader.ReadInt16(), reader.ReadInt16()); + } + } } \ No newline at end of file diff --git a/Components/TECraftingAccess.cs b/Components/TECraftingAccess.cs index bafc212a..5bf7dce6 100644 --- a/Components/TECraftingAccess.cs +++ b/Components/TECraftingAccess.cs @@ -8,149 +8,253 @@ using Terraria.ID; using Terraria.ModLoader; using Terraria.ModLoader.IO; +using System.Collections.Concurrent; namespace MagicStorage.Components { - public class TECraftingAccess : TEStorageComponent - { - public Item[] stations = new Item[10]; - - public TECraftingAccess() - { - for (int k = 0; k < 10; k++) - { - stations[k] = new Item(); - } - } - - public override bool ValidTile(Tile tile) - { - return tile.type == mod.TileType("CraftingAccess") && tile.frameX == 0 && tile.frameY == 0; - } - - public void TryDepositStation(Item item) - { - if (Main.netMode == 1) - { - return; - } - foreach (Item station in stations) - { - if (station.type == item.type) - { - return; - } - } - for (int k = 0; k < stations.Length; k++) - { - if (stations[k].IsAir) - { - stations[k] = item.Clone(); - stations[k].stack = 1; - item.stack--; - if (item.stack <= 0) - { - item.SetDefaults(0); - } - NetHelper.SendTEUpdate(ID, Position); - return; - } - } - } - - public Item TryWithdrawStation(int slot) - { - if (Main.netMode == 1) - { - return new Item(); - } - if (!stations[slot].IsAir) - { - Item item = stations[slot]; - stations[slot] = new Item(); - NetHelper.SendTEUpdate(ID, Position); - return item; - } - return new Item(); - } - - public Item DoStationSwap(Item item, int slot) - { - if (Main.netMode == 1) - { - return new Item(); - } - if (!item.IsAir) - { - for (int k = 0; k < stations.Length; k++) - { - if (k != slot && stations[k].type == item.type) - { - return item; - } - } - } - if ((item.IsAir || item.stack == 1) && !stations[slot].IsAir) - { - Item temp = item; - item = stations[slot]; - stations[slot] = temp; - NetHelper.SendTEUpdate(ID, Position); - return item; - } - else if (!item.IsAir && stations[slot].IsAir) - { - stations[slot] = item.Clone(); - stations[slot].stack = 1; - item.stack--; - if (item.stack <= 0) - { - item.SetDefaults(0); - } - NetHelper.SendTEUpdate(ID, Position); - return item; - } - return item; - } - - public override TagCompound Save() - { - TagCompound tag = new TagCompound(); - IList listStations = new List(); - foreach (Item item in stations) - { - listStations.Add(ItemIO.Save(item)); - } - tag["Stations"] = listStations; - return tag; - } - - public override void Load(TagCompound tag) - { - IList listStations = tag.GetList("Stations"); - if (listStations != null && listStations.Count > 0) - { - for (int k = 0; k < stations.Length; k++) - { - stations[k] = ItemIO.Load(listStations[k]); - } - } - } - - public override void NetSend(BinaryWriter writer, bool lightSend) - { - foreach (Item item in stations) - { - ItemIO.Send(item, writer, true, false); - } - } - - public override void NetReceive(BinaryReader reader, bool lightReceive) - { - for (int k = 0; k < stations.Length; k++) - { - stations[k] = ItemIO.Receive(reader, true, false); - } - } - } + public class TECraftingAccess : TEStorageComponent + { + public enum Operation : byte + { + Withdraw, + WithdrawToInventory, + Deposit, + } + + private class NetOperation + { + public NetOperation(Operation _type, Item _item, int _client) + { + type = _type; + item = _item; + client = _client; + } + + public NetOperation(Operation _type, int _slot, int _client) + { + type = _type; + slot = _slot; + client = _client; + } + + public Operation type { get; } + public int slot { get; } + public Item item { get; } + public int client { get; } + } + ConcurrentQueue clientOpQ = new ConcurrentQueue(); + + public const int Rows = 3; + public const int Columns = 15; + public const int ItemsTotal = Rows * Columns; + + public List stations = new List(); + + public TECraftingAccess() + { + } + + public override void Update() + { + if (Main.netMode == NetmodeID.Server) + { + processClientOperations(); + } + } + + private void processClientOperations() + { + int opCount = clientOpQ.Count; + if (opCount > 0) + { + for (int i = 0; i < opCount; ++i) + { + NetOperation op; + if (clientOpQ.TryDequeue(out op)) + { + if (op.type == Operation.Withdraw || op.type == Operation.WithdrawToInventory) + { + Item item = WithdrawStation(op.slot); + if (!item.IsAir) + { + ModPacket packet = PrepareServerResult(op.type); + ItemIO.Send(item, packet, true, true); + packet.Send(op.client); + } + } + else + { + Item item = DepositStation(op.item); + if (item.stack > 0) + { + ModPacket packet = PrepareServerResult(op.type); + ItemIO.Send(item, packet, true, true); + packet.Send(op.client); + } + } + NetHelper.SendTEUpdate(ID, Position); + } + } + + Point16 pos = Position; + StorageAccess modTile = TileLoader.GetTile(Main.tile[pos.X, pos.Y].type) as StorageAccess; + TEStorageHeart heart = modTile?.GetHeart(pos.X, pos.Y); + if (heart != null) + NetHelper.SendRefreshNetworkItems(heart.ID); + } + } + + public void QClientOperation(BinaryReader reader, Operation op, int client) + { + if (op == Operation.Withdraw || op == Operation.WithdrawToInventory) + { + byte slot = reader.ReadByte(); + clientOpQ.Enqueue(new NetOperation(op, slot, client)); + } + else + { + Item item = ItemIO.Receive(reader, true, true); + clientOpQ.Enqueue(new NetOperation(op, item, client)); + } + } + + private static ModPacket PrepareServerResult(Operation op) + { + ModPacket packet = MagicStorage.Instance.GetPacket(); + packet.Write((byte)MessageType.ServerStationOperationResult); + packet.Write((byte)op); + return packet; + } + + private ModPacket PrepareClientRequest(Operation op) + { + ModPacket packet = MagicStorage.Instance.GetPacket(); + packet.Write((byte)MessageType.ClientStationOperation); + packet.Write(ID); + packet.Write((byte)op); + return packet; + } + + public override bool ValidTile(Tile tile) + { + return tile.type == mod.TileType("CraftingAccess") && tile.frameX == 0 && tile.frameY == 0; + } + + private Item DepositStation(Item item) + { + if (stations.Count < ItemsTotal) + { + bool foundSame = false; + foreach (Item station in stations) + { + if (station.type == item.type) + { + foundSame = true; + break; + } + } + + if (!foundSame) + { + Item nItem = item.Clone(); + nItem.stack = 1; + stations.Add(nItem); + item.stack--; + if (item.stack <= 0) + item.SetDefaults(); + } + } + + return item; + } + + public Item TryDepositStation(Item item) + { + if (Main.netMode == NetmodeID.MultiplayerClient) + { + ModPacket packet = PrepareClientRequest(Operation.Deposit); + ItemIO.Send(item, packet, true, true); + packet.Send(); + item.SetDefaults(0, true); + } + else + { + DepositStation(item); + } + + return item; + } + + private Item WithdrawStation(int slot) + { + Item item = new Item(); + if (slot < stations.Count) + { + item = stations[slot]; + stations.RemoveAt(slot); + } + return item; + } + + public Item TryWithdrawStation(int slot, bool toInventory = false) + { + Item item = new Item(); + if (Main.netMode == NetmodeID.MultiplayerClient) + { + ModPacket packet = PrepareClientRequest((toInventory ? Operation.WithdrawToInventory : Operation.Withdraw)); + packet.Write((byte)slot); + packet.Send(); + } + else + { + item = WithdrawStation(slot); + StoragePlayer.GetItem(item, !toInventory); + } + + return item; + } + + public override TagCompound Save() + { + TagCompound tag = new TagCompound(); + IList listStations = new List(); + foreach (Item item in stations) + { + listStations.Add(ItemIO.Save(item)); + } + tag["Stations"] = listStations; + return tag; + } + + public override void Load(TagCompound tag) + { + IList listStations = tag.GetList("Stations"); + if (listStations != null && listStations.Count > 0) + { + foreach (TagCompound stationTag in listStations) + { + Item item = ItemIO.Load(stationTag); + if (!item.IsAir) + { + stations.Add(ItemIO.Load(stationTag)); + } + } + } + } + + public override void NetSend(BinaryWriter writer, bool lightSend) + { + writer.Write(stations.Count); + foreach (Item item in stations) + ItemIO.Send(item, writer, true, true); + } + + public override void NetReceive(BinaryReader reader, bool lightReceive) + { + int stationsCount = reader.ReadInt32(); + stations = new List(); + for (int k = 0; k < stationsCount; k++) + stations.Add(ItemIO.Receive(reader, true, true)); + } + } } \ No newline at end of file diff --git a/Components/TECreativeStorageUnit.cs b/Components/TECreativeStorageUnit.cs index b241720a..77abb5e8 100644 --- a/Components/TECreativeStorageUnit.cs +++ b/Components/TECreativeStorageUnit.cs @@ -9,120 +9,120 @@ namespace MagicStorage.Components { - public class TECreativeStorageUnit : TEAbstractStorageUnit - { - public override bool IsFull - { - get - { - return true; - } - } - - public override bool ValidTile(Tile tile) - { - return tile.type == mod.TileType("CreativeStorageUnit") && tile.frameX == 0 && tile.frameY == 0; - } - - public override bool HasSpaceInStackFor(Item check, bool locked = false) - { - return false; - } - - public override bool HasItem(Item check, bool locked = false) - { - return !Inactive; - } - - public override IEnumerable GetItems() - { - return new CreativeEnumerable(Inactive); - } - - public override void DepositItem(Item toDeposit, bool locked = false) - { - } - - public override Item TryWithdraw(Item lookFor, bool locked = false) - { - if (Inactive) - { - return new Item(); - } - return lookFor.Clone(); - } - } - - class CreativeEnumerable : IEnumerable - { - private bool inactive; - - internal CreativeEnumerable(bool inactive) - { - this.inactive = inactive; - } - - public IEnumerator GetEnumerator() - { - return new CreativeEnumerator(inactive); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } - - class CreativeEnumerator : IEnumerator - { - private bool inactive; - private int id = 0; - - internal CreativeEnumerator(bool inactive) - { - this.inactive = inactive; - } - - public Item Current - { - get - { - Item item = new Item(); - item.SetDefaults(id, true); - item.stack = item.maxStack; - return item; - } - } - - object IEnumerator.Current - { - get - { - return Current; - } - } - - public bool MoveNext() - { - if (inactive) - { - return false; - } - do - { - id++; - } - while (id < ItemID.Sets.Deprecated.Length && ItemID.Sets.Deprecated[id]); - return id < ItemID.Sets.Deprecated.Length; - } - - public void Reset() - { - id = 0; - } - - public void Dispose() - { - } - } + public class TECreativeStorageUnit : TEAbstractStorageUnit + { + public override bool IsFull + { + get + { + return true; + } + } + + public override bool ValidTile(Tile tile) + { + return tile.type == mod.TileType("CreativeStorageUnit") && tile.frameX == 0 && tile.frameY == 0; + } + + public override bool HasSpaceInStackFor(Item check) + { + return false; + } + + public override bool HasItem(Item check) + { + return !Inactive; + } + + public override IEnumerable GetItems() + { + return new CreativeEnumerable(Inactive); + } + + public override void DepositItem(Item toDeposit) + { + } + + public override Item TryWithdraw(Item lookFor, bool locked = false) + { + if (Inactive) + { + return new Item(); + } + return lookFor.Clone(); + } + } + + class CreativeEnumerable : IEnumerable + { + private bool inactive; + + internal CreativeEnumerable(bool inactive) + { + this.inactive = inactive; + } + + public IEnumerator GetEnumerator() + { + return new CreativeEnumerator(inactive); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } + + class CreativeEnumerator : IEnumerator + { + private bool inactive; + private int id = 0; + + internal CreativeEnumerator(bool inactive) + { + this.inactive = inactive; + } + + public Item Current + { + get + { + Item item = new Item(); + item.SetDefaults(id, true); + item.stack = item.maxStack; + return item; + } + } + + object IEnumerator.Current + { + get + { + return Current; + } + } + + public bool MoveNext() + { + if (inactive) + { + return false; + } + do + { + id++; + } + while (id < ItemID.Sets.Deprecated.Length && ItemID.Sets.Deprecated[id]); + return id < ItemID.Sets.Deprecated.Length; + } + + public void Reset() + { + id = 0; + } + + public void Dispose() + { + } + } } \ No newline at end of file diff --git a/Components/TEStorageHeart.cs b/Components/TEStorageHeart.cs index c5f6aa46..429fb284 100644 --- a/Components/TEStorageHeart.cs +++ b/Components/TEStorageHeart.cs @@ -10,391 +10,589 @@ using Terraria.ID; using Terraria.ModLoader; using Terraria.ModLoader.IO; +using System.Collections.Concurrent; namespace MagicStorage.Components { - public class TEStorageHeart : TEStorageCenter - { - private ReaderWriterLockSlim itemsLock = new ReaderWriterLockSlim(); - public List remoteAccesses = new List(); - private int updateTimer = 60; - private int compactStage = 0; - - public override bool ValidTile(Tile tile) - { - return tile.type == mod.TileType("StorageHeart") && tile.frameX == 0 && tile.frameY == 0; - } - - public override TEStorageHeart GetHeart() - { - return this; - } - - public IEnumerable GetStorageUnits() - { - return storageUnits.Concat(remoteAccesses.Where(remoteAccess => TileEntity.ByPosition.ContainsKey(remoteAccess) && TileEntity.ByPosition[remoteAccess] is TERemoteAccess) - .SelectMany(remoteAccess => ((TERemoteAccess)TileEntity.ByPosition[remoteAccess]).storageUnits)) - .Where(storageUnit => TileEntity.ByPosition.ContainsKey(storageUnit) && TileEntity.ByPosition[storageUnit] is TEAbstractStorageUnit) - .Select(storageUnit => (TEAbstractStorageUnit)TileEntity.ByPosition[storageUnit]); - } - - public IEnumerable GetStoredItems() - { - return GetStorageUnits().SelectMany(storageUnit => storageUnit.GetItems()); - } - - public void EnterReadLock() - { - itemsLock.EnterReadLock(); - } - - public void ExitReadLock() - { - itemsLock.ExitReadLock(); - } - - public void EnterWriteLock() - { - itemsLock.EnterWriteLock(); - } - - public void ExitWriteLock() - { - itemsLock.ExitWriteLock(); - } - - public override void Update() - { - for (int k = 0; k < remoteAccesses.Count; k++) - { - if (!TileEntity.ByPosition.ContainsKey(remoteAccesses[k]) || !(TileEntity.ByPosition[remoteAccesses[k]] is TERemoteAccess)) - { - remoteAccesses.RemoveAt(k); - k--; - } - } - if (Main.netMode == 1) - { - return; - } - updateTimer++; - if (updateTimer >= 60) - { - updateTimer = 0; - if (Main.netMode != 2 || itemsLock.TryEnterWriteLock(2)) - { - try - { - CompactOne(); - } - finally - { - if (Main.netMode == 2) - { - itemsLock.ExitWriteLock(); - } - } - } - } - } - - //precondition: lock is already taken - public void CompactOne() - { - if (compactStage == 0) - { - EmptyInactive(); - } - else if (compactStage == 1) - { - Defragment(); - } - else if (compactStage == 2) - { - PackItems(); - } - } - - //precondition: lock is already taken - public bool EmptyInactive() - { - TEStorageUnit inactiveUnit = null; - foreach (TEAbstractStorageUnit abstractStorageUnit in GetStorageUnits()) - { - if (!(abstractStorageUnit is TEStorageUnit)) - { - continue; - } - TEStorageUnit storageUnit = (TEStorageUnit)abstractStorageUnit; - if (storageUnit.Inactive && !storageUnit.IsEmpty) - { - inactiveUnit = storageUnit; - } - } - if (inactiveUnit == null) - { - compactStage++; - return false; - } - foreach (TEAbstractStorageUnit abstractStorageUnit in GetStorageUnits()) - { - if (!(abstractStorageUnit is TEStorageUnit) || abstractStorageUnit.Inactive) - { - continue; - } - TEStorageUnit storageUnit = (TEStorageUnit)abstractStorageUnit; - if (storageUnit.IsEmpty && inactiveUnit.NumItems <= storageUnit.Capacity) - { - TEStorageUnit.SwapItems(inactiveUnit, storageUnit); - NetHelper.SendRefreshNetworkItems(ID); - return true; - } - } - bool hasChange = false; - NetHelper.StartUpdateQueue(); - Item tryMove = inactiveUnit.WithdrawStack(); - foreach (TEAbstractStorageUnit abstractStorageUnit in GetStorageUnits()) - { - if (!(abstractStorageUnit is TEStorageUnit) || abstractStorageUnit.Inactive) - { - continue; - } - TEStorageUnit storageUnit = (TEStorageUnit)abstractStorageUnit; - while (storageUnit.HasSpaceFor(tryMove, true) && !tryMove.IsAir) - { - storageUnit.DepositItem(tryMove, true); - if (tryMove.IsAir && !inactiveUnit.IsEmpty) - { - tryMove = inactiveUnit.WithdrawStack(); - } - hasChange = true; - } - } - if (!tryMove.IsAir) - { - inactiveUnit.DepositItem(tryMove, true); - } - NetHelper.ProcessUpdateQueue(); - if (hasChange) - { - NetHelper.SendRefreshNetworkItems(ID); - } - else - { - compactStage++; - } - return hasChange; - } - - //precondition: lock is already taken - public bool Defragment() - { - TEStorageUnit emptyUnit = null; - foreach (TEAbstractStorageUnit abstractStorageUnit in GetStorageUnits()) - { - if (!(abstractStorageUnit is TEStorageUnit)) - { - continue; - } - TEStorageUnit storageUnit = (TEStorageUnit)abstractStorageUnit; - if (emptyUnit == null && storageUnit.IsEmpty && !storageUnit.Inactive) - { - emptyUnit = storageUnit; - } - else if (emptyUnit != null && !storageUnit.IsEmpty && storageUnit.NumItems <= emptyUnit.Capacity) - { - TEStorageUnit.SwapItems(emptyUnit, storageUnit); - NetHelper.SendRefreshNetworkItems(ID); - return true; - } - } - compactStage++; - return false; - } - - //precondition: lock is already taken - public bool PackItems() - { - TEStorageUnit unitWithSpace = null; - foreach (TEAbstractStorageUnit abstractStorageUnit in GetStorageUnits()) - { - if (!(abstractStorageUnit is TEStorageUnit)) - { - continue; - } - TEStorageUnit storageUnit = (TEStorageUnit)abstractStorageUnit; - if (unitWithSpace == null && !storageUnit.IsFull && !storageUnit.Inactive) - { - unitWithSpace = storageUnit; - } - else if (unitWithSpace != null && !storageUnit.IsEmpty) - { - NetHelper.StartUpdateQueue(); - while (!unitWithSpace.IsFull && !storageUnit.IsEmpty) - { - Item item = storageUnit.WithdrawStack(); - unitWithSpace.DepositItem(item, true); - if (!item.IsAir) - { - storageUnit.DepositItem(item, true); - } - } - NetHelper.ProcessUpdateQueue(); - NetHelper.SendRefreshNetworkItems(ID); - return true; - } - } - compactStage++; - return false; - } - - public void ResetCompactStage(int stage = 0) - { - if (stage < compactStage) - { - compactStage = stage; - } - } - - public void DepositItem(Item toDeposit) - { - if (Main.netMode == 2) - { - EnterWriteLock(); - } - int oldStack = toDeposit.stack; - try - { - foreach (TEAbstractStorageUnit storageUnit in GetStorageUnits()) - { - if (!storageUnit.Inactive && storageUnit.HasSpaceInStackFor(toDeposit, true)) - { - storageUnit.DepositItem(toDeposit, true); - if (toDeposit.IsAir) - { - return; - } - } - } - foreach (TEAbstractStorageUnit storageUnit in GetStorageUnits()) - { - if (!storageUnit.Inactive && !storageUnit.IsFull) - { - storageUnit.DepositItem(toDeposit, true); - if (toDeposit.IsAir) - { - return; - } - } - } - } - finally - { - if (oldStack != toDeposit.stack) - { - ResetCompactStage(); - } - if (Main.netMode == 2) - { - ExitWriteLock(); - } - } - } - - public Item TryWithdraw(Item lookFor) - { - if (Main.netMode == 1) - { - return new Item(); - } - if (Main.netMode == 2) - { - EnterWriteLock(); - } - try - { - Item result = new Item(); - foreach (TEAbstractStorageUnit storageUnit in GetStorageUnits()) - { - if (storageUnit.HasItem(lookFor, true)) - { - Item withdrawn = storageUnit.TryWithdraw(lookFor, true); - if (!withdrawn.IsAir) - { - if (result.IsAir) - { - result = withdrawn; - } - else - { - result.stack += withdrawn.stack; - } - if (lookFor.stack <= 0) - { - ResetCompactStage(); - return result; - } - } - } - } - if (result.stack > 0) - { - ResetCompactStage(); - } - return result; - } - finally - { - if (Main.netMode == 2) - { - ExitWriteLock(); - } - } - } - - public override TagCompound Save() - { - TagCompound tag = base.Save(); - List tagRemotes = new List(); - foreach (Point16 remoteAccess in remoteAccesses) - { - TagCompound tagRemote = new TagCompound(); - tagRemote.Set("X", remoteAccess.X); - tagRemote.Set("Y", remoteAccess.Y); - tagRemotes.Add(tagRemote); - } - tag.Set("RemoteAccesses", tagRemotes); - return tag; - } - - public override void Load(TagCompound tag) - { - base.Load(tag); - foreach (TagCompound tagRemote in tag.GetList("RemoteAccesses")) - { - remoteAccesses.Add(new Point16(tagRemote.GetShort("X"), tagRemote.GetShort("Y"))); - } - } - - public override void NetSend(BinaryWriter writer, bool lightSend) - { - base.NetSend(writer, lightSend); - writer.Write((short)remoteAccesses.Count); - foreach (Point16 remoteAccess in remoteAccesses) - { - writer.Write(remoteAccess.X); - writer.Write(remoteAccess.Y); - } - } - - public override void NetReceive(BinaryReader reader, bool lightReceive) - { - base.NetReceive(reader, lightReceive); - int count = reader.ReadInt16(); - for (int k = 0; k < count; k++) - { - remoteAccesses.Add(new Point16(reader.ReadInt16(), reader.ReadInt16())); - } - } - } + public class TEStorageHeart : TEStorageCenter + { + public enum Operation : byte + { + Withdraw, + WithdrawToInventory, + Deposit, + DepositAll + } + + private class NetOperation + { + public NetOperation(Operation _type, Item _item, bool _keepOneInFavorite, int _client) + { + type = _type; + item = _item; + keepOneInFavorite = _keepOneInFavorite; + client = _client; + } + + public NetOperation(Operation _type, Item _item, int _client = -1) + { + type = _type; + item = _item; + client = _client; + } + + public NetOperation(Operation _type, List _items, int _client) + { + type = _type; + items = _items; + client = _client; + } + + public Operation type { get; } + public Item item { get; } + public List items { get; } + public bool keepOneInFavorite { get; } + public int client { get; } + } + + ConcurrentQueue clientOpQ = new ConcurrentQueue(); + bool compactCoins = false; + public List remoteAccesses = new List(); + private int updateTimer = 60; + private int compactStage = 0; + + public override bool ValidTile(Tile tile) + { + return tile.type == mod.TileType("StorageHeart") && tile.frameX == 0 && tile.frameY == 0; + } + + public override TEStorageHeart GetHeart() + { + return this; + } + + public IEnumerable GetStorageUnits() + { + return storageUnits.Concat(remoteAccesses.Where(remoteAccess => TileEntity.ByPosition.ContainsKey(remoteAccess) && TileEntity.ByPosition[remoteAccess] is TERemoteAccess) + .SelectMany(remoteAccess => ((TERemoteAccess)TileEntity.ByPosition[remoteAccess]).storageUnits)) + .Where(storageUnit => TileEntity.ByPosition.ContainsKey(storageUnit) && TileEntity.ByPosition[storageUnit] is TEAbstractStorageUnit) + .Select(storageUnit => (TEAbstractStorageUnit)TileEntity.ByPosition[storageUnit]); + } + + public IEnumerable GetStoredItems() + { + return GetStorageUnits().SelectMany(storageUnit => storageUnit.GetItems()); + } + + public override void Update() + { + for (int k = 0; k < remoteAccesses.Count; k++) + { + if (!TileEntity.ByPosition.ContainsKey(remoteAccesses[k]) || !(TileEntity.ByPosition[remoteAccesses[k]] is TERemoteAccess)) + { + remoteAccesses.RemoveAt(k); + k--; + } + } + + if (Main.netMode == NetmodeID.Server && processClientOperations()) + { + NetHelper.SendRefreshNetworkItems(ID); + } + + updateTimer++; + if (updateTimer >= 60) + { + updateTimer = 0; + if (compactCoins) + { + CompactCoins(); + compactCoins = false; + } + CompactOne(); + } + } + + private bool processClientOperations() + { + int opCount = clientOpQ.Count; + bool networkRefresh = false; + for (int i = 0; i < opCount; ++i) + { + NetOperation op; + if (clientOpQ.TryDequeue(out op)) + { + networkRefresh = true; + if (op.type == Operation.Withdraw || op.type == Operation.WithdrawToInventory) + { + Item item = Withdraw(op.item, op.keepOneInFavorite); + if (!item.IsAir) + { + ModPacket packet = PrepareServerResult(op.type); + ItemIO.Send(item, packet, true, true); + packet.Send(op.client); + } + } + else if (op.type == Operation.Deposit) + { + DepositItem(op.item); + if (!op.item.IsAir) + { + ModPacket packet = PrepareServerResult(op.type); + ItemIO.Send(op.item, packet, true, true); + packet.Send(op.client); + } + } + else if (op.type == Operation.DepositAll) + { + NetHelper.StartUpdateQueue(); + List leftOvers = new List(); + foreach (Item item in op.items) + { + DepositItem(item); + if (!item.IsAir) + { + leftOvers.Add(item); + } + } + NetHelper.ProcessUpdateQueue(); + + if (leftOvers.Count > 0) + { + ModPacket packet = PrepareServerResult(op.type); + packet.Write(leftOvers.Count); + foreach (Item item in leftOvers) + { + ItemIO.Send(item, packet, true, true); + } + packet.Send(op.client); + } + } + } + } + return networkRefresh; + } + + public void QClientOperation(BinaryReader reader, Operation op, int client) + { + if (op == Operation.Withdraw || op == Operation.WithdrawToInventory) + { + bool keepOneIfFavorite = reader.ReadBoolean(); + Item item = ItemIO.Receive(reader, true, true); + clientOpQ.Enqueue(new NetOperation(op, item, keepOneIfFavorite, client)); + } + else if (op == Operation.Deposit) + { + Item item = ItemIO.Receive(reader, true, true); + clientOpQ.Enqueue(new NetOperation(op, item, client)); + } + else if (op == Operation.DepositAll) + { + int count = reader.ReadByte(); + List items = new List(); + for (int k = 0; k < count; k++) + { + Item item = ItemIO.Receive(reader, true, true); + items.Add(item); + } + clientOpQ.Enqueue(new NetOperation(op, items, client)); + } + } + + private static ModPacket PrepareServerResult(Operation op) + { + ModPacket packet = MagicStorage.Instance.GetPacket(); + packet.Write((byte)MessageType.ServerStorageResult); + packet.Write((byte)op); + return packet; + } + + private ModPacket PrepareClientRequest(Operation op) + { + ModPacket packet = MagicStorage.Instance.GetPacket(); + packet.Write((byte)MessageType.ClinetStorageOperation); + packet.Write(ID); + packet.Write((byte)op); + return packet; + } + + public void CompactCoins() + { + Dictionary coinsQty = new Dictionary(); + coinsQty.Add(ItemID.CopperCoin, 0); + coinsQty.Add(ItemID.SilverCoin, 0); + coinsQty.Add(ItemID.GoldCoin, 0); + coinsQty.Add(ItemID.PlatinumCoin, 0); + foreach (Item item in GetStoredItems()) + { + if (isAcoin(item) && coinsQty.ContainsKey(item.type)) + { + coinsQty[item.type] += item.stack; + } + } + + int[] coinTypes = coinsQty.Keys.ToArray(); + for (int i = 0; i < coinTypes.Length - 1; i++) + { + int coin = coinTypes[i]; + int coinQty = coinsQty[coin]; + if (coinQty >= 200) + { + coinQty -= 100; + int exchangeCoin = coinTypes[i + 1]; + int exchangedQty = coinQty / 100; + coinsQty[exchangeCoin] += exchangedQty; + + Item tempCoin = new Item(); + tempCoin.SetDefaults(coin); + tempCoin.stack = exchangedQty * 100; + TryWithdraw(tempCoin, false); + + tempCoin.SetDefaults(exchangeCoin); + tempCoin.stack = exchangedQty; + DepositItem(tempCoin); + } + } + } + + public void CompactOne() + { + if (compactStage == 0) + { + EmptyInactive(); + } + else if (compactStage == 1) + { + Defragment(); + } + else if (compactStage == 2) + { + PackItems(); + } + } + + public bool EmptyInactive() + { + TEStorageUnit inactiveUnit = null; + foreach (TEAbstractStorageUnit abstractStorageUnit in GetStorageUnits()) + { + if (!(abstractStorageUnit is TEStorageUnit)) + { + continue; + } + TEStorageUnit storageUnit = (TEStorageUnit)abstractStorageUnit; + if (storageUnit.Inactive && !storageUnit.IsEmpty) + { + inactiveUnit = storageUnit; + } + } + if (inactiveUnit == null) + { + compactStage++; + return false; + } + foreach (TEAbstractStorageUnit abstractStorageUnit in GetStorageUnits()) + { + if (!(abstractStorageUnit is TEStorageUnit) || abstractStorageUnit.Inactive) + { + continue; + } + TEStorageUnit storageUnit = (TEStorageUnit)abstractStorageUnit; + if (storageUnit.IsEmpty && inactiveUnit.NumItems <= storageUnit.Capacity) + { + TEStorageUnit.SwapItems(inactiveUnit, storageUnit); + NetHelper.SendRefreshNetworkItems(ID); + return true; + } + } + bool hasChange = false; + NetHelper.StartUpdateQueue(); + Item tryMove = inactiveUnit.WithdrawStack(); + foreach (TEAbstractStorageUnit abstractStorageUnit in GetStorageUnits()) + { + if (!(abstractStorageUnit is TEStorageUnit) || abstractStorageUnit.Inactive) + { + continue; + } + TEStorageUnit storageUnit = (TEStorageUnit)abstractStorageUnit; + while (storageUnit.HasSpaceFor(tryMove) && !tryMove.IsAir) + { + storageUnit.DepositItem(tryMove); + if (tryMove.IsAir && !inactiveUnit.IsEmpty) + { + tryMove = inactiveUnit.WithdrawStack(); + } + hasChange = true; + } + } + if (!tryMove.IsAir) + { + inactiveUnit.DepositItem(tryMove); + } + NetHelper.ProcessUpdateQueue(); + if (hasChange) + { + NetHelper.SendRefreshNetworkItems(ID); + } + else + { + compactStage++; + } + return hasChange; + } + + public bool Defragment() + { + TEStorageUnit emptyUnit = null; + foreach (TEAbstractStorageUnit abstractStorageUnit in GetStorageUnits()) + { + if (!(abstractStorageUnit is TEStorageUnit)) + { + continue; + } + TEStorageUnit storageUnit = (TEStorageUnit)abstractStorageUnit; + if (emptyUnit == null && storageUnit.IsEmpty && !storageUnit.Inactive) + { + emptyUnit = storageUnit; + } + else if (emptyUnit != null && !storageUnit.IsEmpty && storageUnit.NumItems <= emptyUnit.Capacity) + { + TEStorageUnit.SwapItems(emptyUnit, storageUnit); + NetHelper.SendRefreshNetworkItems(ID); + return true; + } + } + compactStage++; + return false; + } + + public bool PackItems() + { + TEStorageUnit unitWithSpace = null; + foreach (TEAbstractStorageUnit abstractStorageUnit in GetStorageUnits()) + { + if (!(abstractStorageUnit is TEStorageUnit)) + { + continue; + } + TEStorageUnit storageUnit = (TEStorageUnit)abstractStorageUnit; + if (unitWithSpace == null && !storageUnit.IsFull && !storageUnit.Inactive) + { + unitWithSpace = storageUnit; + } + else if (unitWithSpace != null && !storageUnit.IsEmpty) + { + NetHelper.StartUpdateQueue(); + while (!unitWithSpace.IsFull && !storageUnit.IsEmpty) + { + Item item = storageUnit.WithdrawStack(); + unitWithSpace.DepositItem(item); + if (!item.IsAir) + { + storageUnit.DepositItem(item); + } + } + NetHelper.ProcessUpdateQueue(); + NetHelper.SendRefreshNetworkItems(ID); + return true; + } + } + compactStage++; + return false; + } + + public void ResetCompactStage(int stage = 0) + { + if (stage < compactStage) + { + compactStage = stage; + } + } + + public void DepositItem(Item toDeposit) + { + int oldStack = toDeposit.stack; + if (isAcoin(toDeposit)) + { + compactCoins = true; + } + + foreach (TEAbstractStorageUnit storageUnit in GetStorageUnits()) + if (!storageUnit.Inactive && storageUnit.HasSpaceInStackFor(toDeposit)) + { + storageUnit.DepositItem(toDeposit); + if (toDeposit.IsAir) + return; + } + + foreach (TEAbstractStorageUnit storageUnit in GetStorageUnits()) + if (!storageUnit.Inactive && !storageUnit.IsFull) + { + storageUnit.DepositItem(toDeposit); + if (toDeposit.IsAir) + return; + } + + if (oldStack != toDeposit.stack) + ResetCompactStage(); + } + + public void TryDeposit(Item item) + { + if (Main.netMode == NetmodeID.MultiplayerClient) + { + ModPacket packet = PrepareClientRequest(Operation.Deposit); + ItemIO.Send(item, packet, true, true); + packet.Send(); + item.SetDefaults(0, true); + } + else + { + DepositItem(item); + } + } + + public bool TryDeposit(List items) + { + bool changed = false; + if (Main.netMode == NetmodeID.MultiplayerClient) + { + int size = byte.MaxValue; + for (int i = 0; i < items.Count; i += size) + { + List _items = items.GetRange(i, (i + size) > items.Count ? items.Count - i : size); + using (ModPacket packet = PrepareClientRequest(Operation.DepositAll)) + { + packet.Write((byte)_items.Count); + for (int j = 0; j < _items.Count; ++j) + { + ItemIO.Send(_items[j], packet, true, true); + } + packet.Send(); + } + } + + foreach (Item item in items) + { + item.SetDefaults(0, true); + } + changed = true; + } + else + { + foreach (Item item in items) + { + int oldStack = item.stack; + DepositItem(item); + if (oldStack != item.stack) + changed = true; + } + } + return changed; + } + + public Item Withdraw(Item lookFor, bool keepOneIfFavorite) + { + Item result = new Item(); + foreach (TEStorageUnit storageUnit in GetStorageUnits().Reverse()) + { + if (storageUnit.HasItem(lookFor)) + { + Item withdrawn = storageUnit.TryWithdraw(lookFor, keepOneIfFavorite); + if (!withdrawn.IsAir) + { + if (result.IsAir) + result = withdrawn; + else + result.stack += withdrawn.stack; + if (lookFor.stack <= 0) + { + ResetCompactStage(); + return result; + } + } + } + } + + if (result.stack > 0) + ResetCompactStage(); + return result; + } + + public Item TryWithdraw(Item lookFor, bool keepOneIfFavorite, bool toInventory = false) + { + Item item = new Item(); + if (Main.netMode == NetmodeID.MultiplayerClient) + { + ModPacket packet = PrepareClientRequest((toInventory ? Operation.WithdrawToInventory : Operation.Withdraw)); + packet.Write(keepOneIfFavorite); + ItemIO.Send(lookFor, packet, true, true); + packet.Send(); + } + else + { + item = Withdraw(lookFor, keepOneIfFavorite); + } + return item; + } + + public bool HasItem(Item lookFor, bool ignorePrefix = false) + { + foreach (TEAbstractStorageUnit storageUnit in GetStorageUnits()) + if (storageUnit.HasItem(lookFor)) + return true; + return false; + } + + public override TagCompound Save() + { + TagCompound tag = base.Save(); + List tagRemotes = new List(); + foreach (Point16 remoteAccess in remoteAccesses) + { + TagCompound tagRemote = new TagCompound(); + tagRemote.Set("X", remoteAccess.X); + tagRemote.Set("Y", remoteAccess.Y); + tagRemotes.Add(tagRemote); + } + tag.Set("RemoteAccesses", tagRemotes); + return tag; + } + + public override void Load(TagCompound tag) + { + base.Load(tag); + foreach (TagCompound tagRemote in tag.GetList("RemoteAccesses")) + { + remoteAccesses.Add(new Point16(tagRemote.GetShort("X"), tagRemote.GetShort("Y"))); + } + compactCoins = true; + } + + private bool isAcoin(Item item) + { + return item.type == ItemID.CopperCoin || item.type == ItemID.SilverCoin || item.type == ItemID.GoldCoin || item.type == ItemID.PlatinumCoin; + } + + public override void NetSend(BinaryWriter writer, bool lightSend) + { + base.NetSend(writer, lightSend); + writer.Write((short)remoteAccesses.Count); + foreach (Point16 remoteAccess in remoteAccesses) + { + writer.Write(remoteAccess.X); + writer.Write(remoteAccess.Y); + } + } + + public override void NetReceive(BinaryReader reader, bool lightReceive) + { + base.NetReceive(reader, lightReceive); + int count = reader.ReadInt16(); + for (int k = 0; k < count; k++) + { + remoteAccesses.Add(new Point16(reader.ReadInt16(), reader.ReadInt16())); + } + } + } } \ No newline at end of file diff --git a/Components/TEStorageUnit.cs b/Components/TEStorageUnit.cs index 0f05d568..133f8bd2 100644 --- a/Components/TEStorageUnit.cs +++ b/Components/TEStorageUnit.cs @@ -13,635 +13,507 @@ namespace MagicStorage.Components { - public class TEStorageUnit : TEAbstractStorageUnit - { - private IList items = new List(); - private Queue netQueue = new Queue(); - private bool receiving = false; - - //metadata - private HashSet hasSpaceInStack = new HashSet(); - private HashSet hasItem = new HashSet(); - - public int Capacity - { - get - { - int style = Main.tile[Position.X, Position.Y].frameY / 36; - if (style == 8) - { - return 4; - } - if (style > 1) - { - style--; - } - int capacity = style + 1; - if (capacity > 4) - { - capacity++; - } - if (capacity > 6) - { - capacity++; - } - if (capacity > 8) - { - capacity += 7; - } - return 40 * capacity; - } - } - - public override bool IsFull - { - get - { - return items.Count >= Capacity; - } - } - - public bool IsEmpty - { - get - { - return items.Count == 0; - } - } - - public int NumItems - { - get - { - return items.Count; - } - } - - public override bool ValidTile(Tile tile) - { - return tile.type == mod.TileType("StorageUnit") && tile.frameX % 36 == 0 && tile.frameY % 36 == 0; - } - - public override bool HasSpaceInStackFor(Item check, bool locked = false) - { - if (Main.netMode == 2 && !locked) - { - GetHeart().EnterReadLock(); - } - try - { - ItemData data = new ItemData(check); - return hasSpaceInStack.Contains(data); - } - finally - { - if (Main.netMode == 2 && !locked) - { - GetHeart().ExitReadLock(); - } - } - } - - public bool HasSpaceFor(Item check, bool locked = false) - { - return !IsFull || HasSpaceInStackFor(check, locked); - } - - public override bool HasItem(Item check, bool locked = false) - { - if (Main.netMode == 2 && !locked) - { - GetHeart().EnterReadLock(); - } - try - { - ItemData data = new ItemData(check); - return hasItem.Contains(data); - } - finally - { - if (Main.netMode == 2 && !locked) - { - GetHeart().ExitReadLock(); - } - } - } - - public override IEnumerable GetItems() - { - return items; - } - - public override void DepositItem(Item toDeposit, bool locked = false) - { - if (Main.netMode == 1 && !receiving) - { - return; - } - if (Main.netMode == 2 && !locked) - { - GetHeart().EnterWriteLock(); - } - try - { - Item original = toDeposit.Clone(); - bool finished = false; - bool hasChange = false; - foreach (Item item in items) - { - if (ItemData.Matches(toDeposit, item) && item.stack < item.maxStack) - { - int total = item.stack + toDeposit.stack; - int newStack = total; - if (newStack > item.maxStack) - { - newStack = item.maxStack; - } - item.stack = newStack; - hasChange = true; - toDeposit.stack = total - newStack; - if (toDeposit.stack <= 0) - { - toDeposit.SetDefaults(0, true); - finished = true; - break; - } - } - } - if (!finished && !IsFull) - { - Item item = toDeposit.Clone(); - item.newAndShiny = false; - item.favorited = false; - items.Add(item); - toDeposit.SetDefaults(0, true); - hasChange = true; - finished = true; - } - if (hasChange && Main.netMode != 1) - { - if (Main.netMode == 2) - { - netQueue.Enqueue(UnitOperation.Deposit.Create(original)); - } - PostChangeContents(); - } - } - finally - { - if (Main.netMode == 2 && !locked) - { - GetHeart().ExitWriteLock(); - } - } - } - - public override Item TryWithdraw(Item lookFor, bool locked = false) - { - if (Main.netMode == 1 && !receiving) - { - return new Item(); - } - if (Main.netMode == 2 && !locked) - { - GetHeart().EnterWriteLock(); - } - try - { - Item original = lookFor.Clone(); - Item result = lookFor.Clone(); - result.stack = 0; - for (int k = 0; k < items.Count; k++) - { - Item item = items[k]; - if (ItemData.Matches(lookFor, item)) - { - int withdraw = Math.Min(lookFor.stack, item.stack); - item.stack -= withdraw; - if (item.stack <= 0) - { - items.RemoveAt(k); - k--; - } - result.stack += withdraw; - lookFor.stack -= withdraw; - if (lookFor.stack <= 0) - { - if (Main.netMode != 1) - { - if (Main.netMode == 2) - { - netQueue.Enqueue(UnitOperation.Withdraw.Create(original)); - } - PostChangeContents(); - } - return result; - } - } - } - if (result.stack == 0) - { - return new Item(); - } - if (Main.netMode != 1) - { - if (Main.netMode == 2) - { - netQueue.Enqueue(UnitOperation.Withdraw.Create(original)); - } - PostChangeContents(); - } - return result; - } - finally - { - if (Main.netMode == 2 && !locked) - { - GetHeart().ExitWriteLock(); - } - } - } - - public bool UpdateTileFrame(bool locked = false) - { - Tile topLeft = Main.tile[Position.X, Position.Y]; - int oldFrame = topLeft.frameX; - int style; - if (Main.netMode == 2 && !locked) - { - GetHeart().EnterReadLock(); - } - if (IsEmpty) - { - style = 0; - } - else if (IsFull) - { - style = 2; - } - else - { - style = 1; - } - if (Main.netMode == 2 && !locked) - { - GetHeart().ExitReadLock(); - } - if (Inactive) - { - style += 3; - } - style *= 36; - topLeft.frameX = (short)style; - Main.tile[Position.X, Position.Y + 1].frameX = (short)style; - Main.tile[Position.X + 1, Position.Y].frameX = (short)(style + 18); - Main.tile[Position.X + 1, Position.Y + 1].frameX = (short)(style + 18); - return oldFrame != style; - } - - public void UpdateTileFrameWithNetSend(bool locked = false) - { - if (UpdateTileFrame(locked)) - { - NetMessage.SendTileRange(-1, Position.X, Position.Y, 2, 2); - } - } - - //precondition: lock is already taken - internal static void SwapItems(TEStorageUnit unit1, TEStorageUnit unit2) - { - IList items = unit1.items; - unit1.items = unit2.items; - unit2.items = items; - HashSet dict = unit1.hasSpaceInStack; - unit1.hasSpaceInStack = unit2.hasSpaceInStack; - unit2.hasSpaceInStack = dict; - dict = unit1.hasItem; - unit1.hasItem = unit2.hasItem; - unit2.hasItem = dict; - if (Main.netMode == 2) - { - unit1.netQueue.Clear(); - unit2.netQueue.Clear(); - unit1.netQueue.Enqueue(UnitOperation.FullSync.Create()); - unit2.netQueue.Enqueue(UnitOperation.FullSync.Create()); - } - unit1.PostChangeContents(); - unit2.PostChangeContents(); - } - - //precondition: lock is already taken - internal Item WithdrawStack() - { - if (Main.netMode == 1 && !receiving) - { - return new Item(); - } - Item item = items[items.Count - 1]; - items.RemoveAt(items.Count - 1); - if (Main.netMode != 1) - { - if (Main.netMode == 2) - { - netQueue.Enqueue(UnitOperation.WithdrawStack.Create()); - } - PostChangeContents(); - } - return item; - } - - public override TagCompound Save() - { - TagCompound tag = base.Save(); - List tagItems = new List(); - foreach (Item item in items) - { - tagItems.Add(ItemIO.Save(item)); - } - tag.Set("Items", tagItems); - return tag; - } - - public override void Load(TagCompound tag) - { - base.Load(tag); - ClearItemsData(); - foreach (TagCompound tagItem in tag.GetList("Items")) - { - Item item = ItemIO.Load(tagItem); - items.Add(item); - ItemData data = new ItemData(item); - if (item.stack < item.maxStack) - { - hasSpaceInStack.Add(data); - } - hasItem.Add(data); - } - if (Main.netMode == 2) - { - netQueue.Enqueue(UnitOperation.FullSync.Create()); - } - } - - public override void NetSend(BinaryWriter trueWriter, bool lightSend) - { - //If the workaround is active, then the entity isn't being sent via the NetWorkaround packet or is being saved to a world file - if (EditsLoader.MessageTileEntitySyncing) - { - trueWriter.Write((byte)0); - base.NetSend(trueWriter, lightSend); - return; - } - - trueWriter.Write((byte)1); - - /* Recreate a BinaryWriter writer */ - MemoryStream buffer = new MemoryStream(65536); - DeflateStream compressor = new DeflateStream(buffer, CompressionMode.Compress, true); - BufferedStream writerBuffer = new BufferedStream(compressor, 65536); - BinaryWriter writer = new BinaryWriter(writerBuffer); - - /* Original code */ - base.NetSend(writer, lightSend); - if (netQueue.Count > Capacity / 2 || !lightSend) - { - netQueue.Clear(); - netQueue.Enqueue(UnitOperation.FullSync.Create()); - } - writer.Write((ushort)netQueue.Count); - while (netQueue.Count > 0) - { - netQueue.Dequeue().Send(writer, this); - } - - /* Forces data to be flushed into the compressed buffer */ - writerBuffer.Flush(); compressor.Close(); - - /* Sends the buffer through the network */ - trueWriter.Write((ushort)buffer.Length); - trueWriter.Write(buffer.ToArray()); - - /* Compression stats and debugging code (server side) */ - if (false) - { - MemoryStream decompressedBuffer = new MemoryStream(65536); - DeflateStream decompressor = new DeflateStream(buffer, CompressionMode.Decompress, true); - decompressor.CopyTo(decompressedBuffer); - decompressor.Close(); - - Console.WriteLine("Magic Storage Data Compression Stats: " + decompressedBuffer.Length + " => " + buffer.Length); - decompressor.Dispose(); decompressedBuffer.Dispose(); - } - - /* Dispose all objects */ - writer.Dispose(); writerBuffer.Dispose(); compressor.Dispose(); buffer.Dispose(); - } - - public override void NetReceive(BinaryReader trueReader, bool lightReceive) - { - //If the workaround is active, then the entity isn't being sent via the NetWorkaround packet - byte workaround = trueReader.ReadByte(); - - if (EditsLoader.MessageTileEntitySyncing || workaround != 1) - { - base.NetReceive(trueReader, lightReceive); - return; - } - - /* Reads the buffer off the network */ - MemoryStream buffer = new MemoryStream(65536); - BinaryWriter bufferWriter = new BinaryWriter(buffer); - - bufferWriter.Write(trueReader.ReadBytes(trueReader.ReadUInt16())); - buffer.Position = 0; - - /* Recreate the BinaryReader reader */ - DeflateStream decompressor = new DeflateStream(buffer, CompressionMode.Decompress, true); - BinaryReader reader = new BinaryReader(decompressor); - - /* Original code */ - base.NetReceive(reader, lightReceive); - if (TileEntity.ByPosition.ContainsKey(Position) && TileEntity.ByPosition[Position] is TEStorageUnit) - { - TEStorageUnit other = (TEStorageUnit)TileEntity.ByPosition[Position]; - items = other.items; - hasSpaceInStack = other.hasSpaceInStack; - hasItem = other.hasItem; - } - receiving = true; - int count = reader.ReadUInt16(); - bool flag = false; - for (int k = 0; k < count; k++) - { - if (UnitOperation.Receive(reader, this)) - { - flag = true; - } - } - if (flag) - { - RepairMetadata(); - } - receiving = false; - - /* Dispose all objects */ - reader.Dispose(); decompressor.Dispose(); bufferWriter.Dispose(); buffer.Dispose(); - } - - private void ClearItemsData() - { - items.Clear(); - hasSpaceInStack.Clear(); - hasItem.Clear(); - } - - private void RepairMetadata() - { - hasSpaceInStack.Clear(); - hasItem.Clear(); - foreach (Item item in items) - { - ItemData data = new ItemData(item); - if (item.stack < item.maxStack) - { - hasSpaceInStack.Add(data); - } - hasItem.Add(data); - } - } - - private void PostChangeContents() - { - RepairMetadata(); - UpdateTileFrameWithNetSend(true); - NetHelper.SendTEUpdate(ID, Position); - } - - abstract class UnitOperation - { - public static readonly UnitOperation FullSync = new FullSync(); - public static readonly UnitOperation Deposit = new DepositOperation(); - public static readonly UnitOperation Withdraw = new WithdrawOperation(); - public static readonly UnitOperation WithdrawStack = new WithdrawStackOperation(); - private static List types = new List(); - - static UnitOperation() - { - types.Add(FullSync); - types.Add(Deposit); - types.Add(Withdraw); - types.Add(WithdrawStack); - for (int k = 0; k < types.Count; k++) - { - types[k].id = (byte)k; - } - } - - protected byte id; - protected Item data; - - public UnitOperation Create() - { - return (UnitOperation)MemberwiseClone(); - } - - public UnitOperation Create(Item item) - { - UnitOperation clone = Create(); - clone.data = item; - return clone; - } - - public void Send(BinaryWriter writer, TEStorageUnit unit) - { - writer.Write(id); - SendData(writer, unit); - } - - protected abstract void SendData(BinaryWriter writer, TEStorageUnit unit); - - public static bool Receive(BinaryReader reader, TEStorageUnit unit) - { - byte id = reader.ReadByte(); - if (id >= 0 && id < types.Count) - { - return types[id].ReceiveData(reader, unit); - } - return false; - } - - protected abstract bool ReceiveData(BinaryReader reader, TEStorageUnit unit); - } - - class FullSync : UnitOperation - { - protected override void SendData(BinaryWriter writer, TEStorageUnit unit) - { - writer.Write(unit.items.Count); - foreach (Item item in unit.items) - { - ItemIO.Send(item, writer, true, false); - } - } - - protected override bool ReceiveData(BinaryReader reader, TEStorageUnit unit) - { - unit.ClearItemsData(); - int count = reader.ReadInt32(); - for (int k = 0; k < count; k++) - { - Item item = ItemIO.Receive(reader, true, false); - unit.items.Add(item); - ItemData data = new ItemData(item); - if (item.stack < item.maxStack) - { - unit.hasSpaceInStack.Add(data); - } - unit.hasItem.Add(data); - } - return false; - } - } - - class DepositOperation : UnitOperation - { - protected override void SendData(BinaryWriter writer, TEStorageUnit unit) - { - ItemIO.Send(data, writer, true, false); - } - - protected override bool ReceiveData(BinaryReader reader, TEStorageUnit unit) - { - unit.DepositItem(ItemIO.Receive(reader, true, false)); - return true; - } - } - - class WithdrawOperation : UnitOperation - { - protected override void SendData(BinaryWriter writer, TEStorageUnit unit) - { - ItemIO.Send(data, writer, true, false); - } - - protected override bool ReceiveData(BinaryReader reader, TEStorageUnit unit) - { - unit.TryWithdraw(ItemIO.Receive(reader, true, false)); - return true; - } - } - - class WithdrawStackOperation : UnitOperation - { - protected override void SendData(BinaryWriter writer, TEStorageUnit unit) - { - } - - protected override bool ReceiveData(BinaryReader reader, TEStorageUnit unit) - { - unit.WithdrawStack(); - return true; - } - } - } + public class TEStorageUnit : TEAbstractStorageUnit + { + internal enum NetOperations : byte + { + FullySync, + Deposit, + Withdraw, + WithdrawStack, + } + + private struct NetOperation + { + public NetOperation(NetOperations _netOPeration, Item _item = null, bool _keepOneInFavorite = false) + { + netOperation = _netOPeration; + item = _item; + keepOneInFavorite = _keepOneInFavorite; + } + + public NetOperations netOperation { get; } + public Item item { get; } + public bool keepOneInFavorite { get; } + } + + private readonly Queue netOpQueue = new Queue(); + private IList items = new List(); + private bool receiving = false; + + //metadata + private HashSet hasSpaceInStack = new HashSet(); + private HashSet hasItem = new HashSet(); + + public int Capacity + { + get + { + int style = Main.tile[Position.X, Position.Y].frameY / 36; + if (style == 8) + { + return 4; + } + if (style > 1) + { + style--; + } + int capacity = style + 1; + if (capacity > 4) + { + capacity++; + } + if (capacity > 6) + { + capacity++; + } + if (capacity > 8) + { + capacity += 7; + } + return 40 * capacity; + } + } + + public override bool IsFull + { + get + { + return items.Count >= Capacity; + } + } + + public bool IsEmpty + { + get + { + return items.Count == 0; + } + } + + public int NumItems + { + get + { + return items.Count; + } + } + + public override bool ValidTile(Tile tile) + { + return tile.type == mod.TileType("StorageUnit") && tile.frameX % 36 == 0 && tile.frameY % 36 == 0; + } + + public override bool HasSpaceInStackFor(Item check) + { + ItemData data = new ItemData(check); + return hasSpaceInStack.Contains(data); + } + + public bool HasSpaceFor(Item check) => !IsFull || HasSpaceInStackFor(check); + + public override bool HasItem(Item check) + { + ItemData data = new ItemData(check); + return hasItem.Contains(data); + } + + public override IEnumerable GetItems() + { + return items; + } + + public override void DepositItem(Item toDeposit) + { + if (Main.netMode == NetmodeID.MultiplayerClient && !receiving) + return; + + Item original = toDeposit.Clone(); + bool finished = false; + bool hasChange = false; + foreach (Item item in items) + { + if (ItemData.Matches(toDeposit, item) && item.stack < item.maxStack) + { + int total = item.stack + toDeposit.stack; + int newStack = total; + if (newStack > item.maxStack) + { + newStack = item.maxStack; + } + item.stack = newStack; + + if (toDeposit.favorited) + item.favorited = true; + + hasChange = true; + toDeposit.stack = total - newStack; + if (toDeposit.stack <= 0) + { + toDeposit.SetDefaults(0, true); + finished = true; + break; + } + } + } + if (!finished && !IsFull) + { + Item item = toDeposit.Clone(); + item.newAndShiny = false; + item.favorited = false; + items.Add(item); + toDeposit.SetDefaults(0, true); + hasChange = true; + finished = true; + } + + if (hasChange && Main.netMode != NetmodeID.MultiplayerClient) + { + if (Main.netMode == NetmodeID.Server) + { + netOpQueue.Enqueue(new NetOperation(NetOperations.Deposit, original)); + } + PostChangeContents(); + } + } + + public override Item TryWithdraw(Item lookFor, bool keepOneIfFavorite = false) + { + if (Main.netMode == NetmodeID.MultiplayerClient && !receiving) + return new Item(); + + Item original = lookFor.Clone(); + Item result = lookFor.Clone(); + result.stack = 0; + for (int k = 0; k < items.Count; k++) + { + Item item = items[k]; + if (ItemData.Matches(lookFor, item)) + { + int withdraw = Math.Min(lookFor.stack, item.stack); + item.stack -= withdraw; + if (item.stack <= 0) + { + items.RemoveAt(k); + k--; + } + result.stack += withdraw; + lookFor.stack -= withdraw; + if (lookFor.stack <= 0) + { + if (Main.netMode != NetmodeID.MultiplayerClient) + { + if (Main.netMode == NetmodeID.Server) + { + netOpQueue.Enqueue(new NetOperation(NetOperations.Withdraw, original, keepOneIfFavorite)); + } + + PostChangeContents(); + } + return result; + } + } + } + + if (result.stack == 0) + { + return new Item(); + } + if (Main.netMode != NetmodeID.MultiplayerClient) + { + if (Main.netMode == NetmodeID.Server) + { + netOpQueue.Enqueue(new NetOperation(NetOperations.Withdraw, original, keepOneIfFavorite)); + } + + PostChangeContents(); + } + return result; + } + + public bool UpdateTileFrame() + { + Tile topLeft = Main.tile[Position.X, Position.Y]; + int oldFrame = topLeft.frameX; + int style; + if (IsEmpty) + style = 0; + else if (IsFull) + style = 2; + else + style = 1; + if (Inactive) + style += 3; + style *= 36; + topLeft.frameX = (short)style; + Main.tile[Position.X, Position.Y + 1].frameX = (short)style; + Main.tile[Position.X + 1, Position.Y].frameX = (short)(style + 18); + Main.tile[Position.X + 1, Position.Y + 1].frameX = (short)(style + 18); + return oldFrame != style; + } + + public void UpdateTileFrameWithNetSend(bool locked = false) + { + if (UpdateTileFrame()) + { + NetMessage.SendTileRange(-1, Position.X, Position.Y, 2, 2); + } + } + + //precondition: lock is already taken + internal static void SwapItems(TEStorageUnit unit1, TEStorageUnit unit2) + { + IList items = unit1.items; + unit1.items = unit2.items; + unit2.items = items; + HashSet dict = unit1.hasSpaceInStack; + unit1.hasSpaceInStack = unit2.hasSpaceInStack; + unit2.hasSpaceInStack = dict; + dict = unit1.hasItem; + unit1.hasItem = unit2.hasItem; + unit2.hasItem = dict; + if (Main.netMode == NetmodeID.Server) + { + unit1.netOpQueue.Clear(); + unit2.netOpQueue.Clear(); + unit1.netOpQueue.Enqueue(new NetOperation(NetOperations.FullySync)); + unit2.netOpQueue.Enqueue(new NetOperation(NetOperations.FullySync)); + } + unit1.PostChangeContents(); + unit2.PostChangeContents(); + } + + //precondition: lock is already taken + internal Item WithdrawStack() + { + if (Main.netMode == NetmodeID.MultiplayerClient && !receiving) + return new Item(); + + Item item = items[items.Count - 1]; + items.RemoveAt(items.Count - 1); + if (Main.netMode != NetmodeID.MultiplayerClient) + { + if (Main.netMode == NetmodeID.Server) + { + netOpQueue.Enqueue(new NetOperation(NetOperations.WithdrawStack)); + } + PostChangeContents(); + } + return item; + } + + public override TagCompound Save() + { + TagCompound tag = base.Save(); + List tagItems = new List(); + foreach (Item item in items) + { + tagItems.Add(ItemIO.Save(item)); + } + tag.Set("Items", tagItems); + return tag; + } + + public override void Load(TagCompound tag) + { + base.Load(tag); + ClearItemsData(); + foreach (TagCompound tagItem in tag.GetList("Items")) + { + Item item = ItemIO.Load(tagItem); + items.Add(item); + ItemData data = new ItemData(item); + if (item.stack < item.maxStack) + { + hasSpaceInStack.Add(data); + } + hasItem.Add(data); + } + } + + public void FullySync() + { + netOpQueue.Enqueue(new NetOperation(NetOperations.FullySync)); + } + + public override void NetSend(BinaryWriter trueWriter, bool lightSend) + { + using (MemoryStream buffer = new MemoryStream(65536)) + { + using (BinaryWriter writer = new BinaryWriter(buffer)) + { + base.NetSend(writer, lightSend); + + // too many updates at this point just fully sync + if (netOpQueue.Count > Capacity / 2) + { + netOpQueue.Clear(); + netOpQueue.Enqueue(new NetOperation(NetOperations.FullySync)); + } + + writer.Write((ushort)items.Count); + writer.Write((ushort)netOpQueue.Count); + while (netOpQueue.Count > 0) + { + NetOperation netOp = netOpQueue.Dequeue(); + writer.Write((byte)netOp.netOperation); + switch (netOp.netOperation) + { + case NetOperations.FullySync: + writer.Write(items.Count); + foreach (Item item in items) + { + ItemIO.Send(item, writer, true, true); + } + break; + case NetOperations.Withdraw: + writer.Write(netOp.keepOneInFavorite); + ItemIO.Send(netOp.item, writer, true, true); + break; + case NetOperations.WithdrawStack: + break; + case NetOperations.Deposit: + ItemIO.Send(netOp.item, writer, true, true); + break; + default: + break; + } + } + + /* Forces data to be flushed into the buffer */ + writer.Flush(); + + byte[] data = null; + /* compress buffer data */ + using (MemoryStream memoryStream = new MemoryStream()) + { + using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Compress)) + { + deflateStream.Write(buffer.GetBuffer(), 0, (int)buffer.Length); + } + data = memoryStream.ToArray(); + } + + /* Sends the buffer through the network */ + trueWriter.Write((ushort)data.Length); + trueWriter.Write(data); + } + } + } + + public override void NetReceive(BinaryReader trueReader, bool lightSend) + { + /* Reads the buffer off the network */ + using (MemoryStream buffer = new MemoryStream()) + { + ushort bufferLen = trueReader.ReadUInt16(); + buffer.Write(trueReader.ReadBytes(bufferLen), 0, bufferLen); + buffer.Position = 0; + + /* Recreate the BinaryReader reader */ + using (DeflateStream decompressor = new DeflateStream(buffer, CompressionMode.Decompress, true)) + { + using (BinaryReader reader = new BinaryReader(decompressor)) + { + base.NetReceive(reader, lightSend); + + int serverItemsCount = reader.ReadUInt16(); + int opCount = reader.ReadUInt16(); + if (opCount > 0) + { + if (ByPosition.TryGetValue(Position, out TileEntity te) && te is TEStorageUnit otherUnit) + { + items = otherUnit.items; + hasSpaceInStack = otherUnit.hasSpaceInStack; + hasItem = otherUnit.hasItem; + } + + receiving = true; + bool repairMetaData = true; + for (int i = 0; i < opCount; i++) + { + byte netOp = reader.ReadByte(); + if (Enum.IsDefined(typeof(NetOperations), netOp)) + { + switch ((NetOperations)netOp) + { + case NetOperations.FullySync: + repairMetaData = false; + ClearItemsData(); + int itemsCount = reader.ReadInt32(); + for (int j = 0; j < itemsCount; j++) + { + Item item = ItemIO.Receive(reader, true, true); + items.Add(item); + ItemData data = new ItemData(item); + if (item.stack < item.maxStack) + hasSpaceInStack.Add(data); + hasItem.Add(data); + } + break; + case NetOperations.Withdraw: + bool keepOneIfFavorite = reader.ReadBoolean(); + TryWithdraw(ItemIO.Receive(reader, true, true), keepOneIfFavorite: keepOneIfFavorite); + break; + case NetOperations.WithdrawStack: + WithdrawStack(); + break; + case NetOperations.Deposit: + DepositItem(ItemIO.Receive(reader, true, true)); + break; + default: + break; + } + } + else + { + Main.NewText($"NetRecive Bad OP: {netOp}", Microsoft.Xna.Framework.Color.Red); + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine($"NetRecive Bad OP: {netOp}"); + Console.ResetColor(); + } + } + + if (repairMetaData) + RepairMetadata(); + receiving = false; + } + else if (serverItemsCount != items.Count) // if there is mismatch between the server and the client then send a sync request + { + NetHelper.SyncStorageUnit(ID); + } + } + } + } + } + + private void ClearItemsData() + { + items.Clear(); + hasSpaceInStack.Clear(); + hasItem.Clear(); + } + + private void RepairMetadata() + { + hasSpaceInStack.Clear(); + hasItem.Clear(); + foreach (Item item in items) + { + ItemData data = new ItemData(item); + if (item.stack < item.maxStack) + { + hasSpaceInStack.Add(data); + } + hasItem.Add(data); + } + } + + private void PostChangeContents() + { + RepairMetadata(); + UpdateTileFrameWithNetSend(true); + NetHelper.SendTEUpdate(ID, Position); + } + } } diff --git a/CraftingGUI.cs b/CraftingGUI.cs index 8b628d75..a0b56c11 100644 --- a/CraftingGUI.cs +++ b/CraftingGUI.cs @@ -18,1499 +18,1467 @@ namespace MagicStorage { - public static class CraftingGUI - { - private const int padding = 4; - private const int numColumns = 10; - private const int numColumns2 = 7; - private const float inventoryScale = 0.85f; - private const float smallScale = 0.7f; - - public static MouseState curMouse; - public static MouseState oldMouse; - public static bool MouseClicked - { - get - { - return curMouse.LeftButton == ButtonState.Pressed && oldMouse.LeftButton == ButtonState.Released; - } - } - - private static UIPanel basePanel; - private static float panelTop; - private static float panelLeft; - private static float panelWidth; - private static float panelHeight; - - private static UIElement topBar; - internal static UISearchBar searchBar; - private static UIButtonChoice sortButtons; - private static UIButtonChoice recipeButtons; - private static UIElement topBar2; - private static UIButtonChoice filterButtons; - internal static UISearchBar searchBar2; - - private static UIText stationText; - private static UISlotZone stationZone = new UISlotZone(HoverStation, GetStation, inventoryScale); - private static UIText recipeText; - private static UISlotZone recipeZone = new UISlotZone(HoverRecipe, GetRecipe, inventoryScale); - - internal static UIScrollbar scrollBar = new UIScrollbar(); - private static int scrollBarFocus = 0; - private static int scrollBarFocusMouseStart; - private static float scrollBarFocusPositionStart; - private static float scrollBarViewSize = 1f; - private static float scrollBarMaxViewSize = 2f; - - private static List items = new List(); - private static Dictionary itemCounts = new Dictionary(); - private static bool[] adjTiles = new bool[TileLoader.TileCount]; - private static bool adjWater = false; - private static bool adjLava = false; - private static bool adjHoney = false; - private static bool zoneSnow = false; - private static bool alchemyTable = false; - private static List recipes = new List(); - private static List recipeAvailable = new List(); - private static Recipe selectedRecipe = null; - private static int numRows; - private static int displayRows; - private static bool slotFocus = false; - - private static UIElement bottomBar = new UIElement(); - private static UIText capacityText; - - private static UIPanel recipePanel; - private static float recipeTop; - private static float recipeLeft; - private static float recipeWidth; - private static float recipeHeight; - - private static UIText recipePanelHeader; - private static UIText ingredientText; - private static UISlotZone ingredientZone = new UISlotZone(HoverItem, GetIngredient, smallScale); - private static UIText reqObjText; - private static UIText reqObjText2; - private static UIText storedItemsText; - - private static UISlotZone storageZone = new UISlotZone(HoverStorage, GetStorage, smallScale); - private static int numRows2; - private static int displayRows2; - private static List storageItems = new List(); - private static List blockStorageItems = new List(); - - internal static UIScrollbar scrollBar2 = new UIScrollbar(); - private static float scrollBar2ViewSize = 1f; - private static float scrollBar2MaxViewSize = 2f; - - internal static UITextPanel craftButton; - private static Item result = null; - private static UISlotZone resultZone = new UISlotZone(HoverResult, GetResult, inventoryScale); - private static int craftTimer = 0; - private const int startMaxCraftTimer = 20; - private static int maxCraftTimer = startMaxCraftTimer; - private static int rightClickTimer = 0; - private const int startMaxRightClickTimer = 20; - private static int maxRightClickTimer = startMaxRightClickTimer; - - private static Object threadLock = new Object(); - private static Object recipeLock = new Object(); - private static Object itemsLock = new Object(); - private static bool threadRunning = false; - internal static bool threadNeedsRestart = false; - private static SortMode threadSortMode; - private static FilterMode threadFilterMode; - private static List threadRecipes = new List(); - private static List threadRecipeAvailable = new List(); - private static List nextRecipes = new List(); - private static List nextRecipeAvailable = new List(); - - public static void Initialize() - { - lock (recipeLock) - { - recipes = nextRecipes; - recipeAvailable = nextRecipeAvailable; - } - - InitLangStuff(); - float itemSlotWidth = Main.inventoryBackTexture.Width * inventoryScale; - float itemSlotHeight = Main.inventoryBackTexture.Height * inventoryScale; - float smallSlotWidth = Main.inventoryBackTexture.Width * smallScale; - float smallSlotHeight = Main.inventoryBackTexture.Height * smallScale; - - panelTop = Main.instance.invBottom + 60; - panelLeft = 20f; - basePanel = new UIPanel(); - float innerPanelLeft = panelLeft + basePanel.PaddingLeft; - float innerPanelWidth = numColumns * (itemSlotWidth + padding) + 20f + padding; - panelWidth = basePanel.PaddingLeft + innerPanelWidth + basePanel.PaddingRight; - panelHeight = Main.screenHeight - panelTop - 40f; - basePanel.Left.Set(panelLeft, 0f); - basePanel.Top.Set(panelTop, 0f); - basePanel.Width.Set(panelWidth, 0f); - basePanel.Height.Set(panelHeight, 0f); - basePanel.Recalculate(); - - recipePanel = new UIPanel(); - recipeTop = panelTop; - recipeLeft = panelLeft + panelWidth; - recipeWidth = numColumns2 * (smallSlotWidth + padding) + 20f + padding; - recipeWidth += recipePanel.PaddingLeft + recipePanel.PaddingRight; - recipeHeight = panelHeight; - recipePanel.Left.Set(recipeLeft, 0f); - recipePanel.Top.Set(recipeTop, 0f); - recipePanel.Width.Set(recipeWidth, 0f); - recipePanel.Height.Set(recipeHeight, 0f); - recipePanel.Recalculate(); - - topBar = new UIElement(); - topBar.Width.Set(0f, 1f); - topBar.Height.Set(32f, 0f); - basePanel.Append(topBar); - - InitSortButtons(); - topBar.Append(sortButtons); - float sortButtonsRight = sortButtons.GetDimensions().Width + padding; - InitRecipeButtons(); - float recipeButtonsLeft = sortButtonsRight + 32f + 3 * padding; - recipeButtons.Left.Set(recipeButtonsLeft, 0f); - topBar.Append(recipeButtons); - float recipeButtonsRight = recipeButtonsLeft + recipeButtons.GetDimensions().Width + padding; - - searchBar.Left.Set(recipeButtonsRight + padding, 0f); - searchBar.Width.Set(-recipeButtonsRight - 2 * padding, 1f); - searchBar.Height.Set(0f, 1f); - topBar.Append(searchBar); - - topBar2 = new UIElement(); - topBar2.Width.Set(0f, 1f); - topBar2.Height.Set(32f, 0f); - topBar2.Top.Set(36f, 0f); - basePanel.Append(topBar2); - - InitFilterButtons(); - float filterButtonsRight = filterButtons.GetDimensions().Width + padding; - topBar2.Append(filterButtons); - searchBar2.Left.Set(filterButtonsRight + padding, 0f); - searchBar2.Width.Set(-filterButtonsRight - 2 * padding, 1f); - searchBar2.Height.Set(0f, 1f); - topBar2.Append(searchBar2); - - stationText.Top.Set(76f, 0f); - basePanel.Append(stationText); - - stationZone.Width.Set(0f, 1f); - stationZone.Top.Set(100f, 0f); - stationZone.Height.Set(70f, 0f); - stationZone.SetDimensions(numColumns, 1); - basePanel.Append(stationZone); - - recipeText.Top.Set(152f, 0f); - basePanel.Append(recipeText); - - recipeZone.Width.Set(0f, 1f); - recipeZone.Top.Set(176f, 0f); - recipeZone.Height.Set(-216f, 1f); - basePanel.Append(recipeZone); - - numRows = (recipes.Count + numColumns - 1) / numColumns; - displayRows = (int)recipeZone.GetDimensions().Height / ((int)itemSlotHeight + padding); - recipeZone.SetDimensions(numColumns, displayRows); - int noDisplayRows = numRows - displayRows; - if (noDisplayRows < 0) - { - noDisplayRows = 0; - } - scrollBarMaxViewSize = 1 + noDisplayRows; - scrollBar.Height.Set(displayRows * (itemSlotHeight + padding), 0f); - scrollBar.Left.Set(-20f, 1f); - scrollBar.SetView(scrollBarViewSize, scrollBarMaxViewSize); - recipeZone.Append(scrollBar); - - bottomBar.Width.Set(0f, 1f); - bottomBar.Height.Set(32f, 0f); - bottomBar.Top.Set(-32f, 1f); - basePanel.Append(bottomBar); - - capacityText.Left.Set(6f, 0f); - capacityText.Top.Set(6f, 0f); - TEStorageHeart heart = GetHeart(); - int numItems = 0; - int capacity = 0; - if (heart != null) - { - foreach (TEAbstractStorageUnit abstractStorageUnit in heart.GetStorageUnits()) - { - if (abstractStorageUnit is TEStorageUnit) - { - TEStorageUnit storageUnit = (TEStorageUnit)abstractStorageUnit; - numItems += storageUnit.NumItems; - capacity += storageUnit.Capacity; - } - } - } - capacityText.SetText(numItems + "/" + capacity + " Items"); - bottomBar.Append(capacityText); - - recipePanel.Append(recipePanelHeader); - ingredientText.Top.Set(30f, 0f); - recipePanel.Append(ingredientText); - - ingredientZone.SetDimensions(numColumns2, 2); - ingredientZone.Top.Set(54f, 0f); - ingredientZone.Width.Set(0f, 1f); - ingredientZone.Height.Set(60f, 0f); - recipePanel.Append(ingredientZone); - - reqObjText.Top.Set(136f, 0f); - recipePanel.Append(reqObjText); - reqObjText2.Top.Set(160f, 0f); - recipePanel.Append(reqObjText2); - storedItemsText.Top.Set(190f, 0f); - recipePanel.Append(storedItemsText); - - storageZone.Top.Set(214f, 0f); - storageZone.Width.Set(0f, 1f); - storageZone.Height.Set(-214f - 36, 1f); - recipePanel.Append(storageZone); - numRows2 = (storageItems.Count + numColumns2 - 1) / numColumns2; - displayRows2 = (int)storageZone.GetDimensions().Height / ((int)smallSlotHeight + padding); - storageZone.SetDimensions(numColumns2, displayRows2); - int noDisplayRows2 = numRows2 - displayRows2; - if (noDisplayRows2 < 0) - { - noDisplayRows2 = 0; - } - scrollBar2MaxViewSize = 1 + noDisplayRows2; - scrollBar2.Height.Set(displayRows2 * (smallSlotHeight + padding), 0f); - scrollBar2.Left.Set(-20f, 1f); - scrollBar2.SetView(scrollBar2ViewSize, scrollBar2MaxViewSize); - storageZone.Append(scrollBar2); - - craftButton.Top.Set(-32f, 1f); - craftButton.Width.Set(100f, 0f); - craftButton.Height.Set(24f, 0f); - craftButton.PaddingTop = 8f; - craftButton.PaddingBottom = 8f; - recipePanel.Append(craftButton); - - resultZone.SetDimensions(1, 1); - resultZone.Left.Set(-itemSlotWidth, 1f); - resultZone.Top.Set(-itemSlotHeight, 1f); - resultZone.Width.Set(itemSlotWidth, 0f); - resultZone.Height.Set(itemSlotHeight, 0f); - recipePanel.Append(resultZone); - } - - private static void InitLangStuff() - { - if (searchBar == null) - { - searchBar = new UISearchBar(Language.GetText("Mods.MagicStorage.SearchName")); - } - if (searchBar2 == null) - { - searchBar2 = new UISearchBar(Language.GetText("Mods.MagicStorage.SearchMod")); - } - if (stationText == null) - { - stationText = new UIText(Language.GetText("Mods.MagicStorage.CraftingStations")); - } - if (recipeText == null) - { - recipeText = new UIText(Language.GetText("Mods.MagicStorage.Recipes")); - } - if (capacityText == null) - { - capacityText = new UIText("Items"); - } - if (recipePanelHeader == null) - { - recipePanelHeader = new UIText(Language.GetText("Mods.MagicStorage.SelectedRecipe")); - } - if (ingredientText == null) - { - ingredientText = new UIText(Language.GetText("Mods.MagicStorage.Ingredients")); - } - if (reqObjText == null) - { - reqObjText = new UIText(Language.GetText("LegacyInterface.22")); - } - if (reqObjText2 == null) - { - reqObjText2 = new UIText(""); - } - if (storedItemsText == null) - { - storedItemsText = new UIText(Language.GetText("Mods.MagicStorage.StoredItems")); - } - if (craftButton == null) - { - craftButton = new UITextPanel(Language.GetText("LegacyMisc.72"), 1f); - } - } - - internal static void Unload() - { - sortButtons = null; - filterButtons = null; - recipeButtons = null; - } - - private static void InitSortButtons() - { - if (sortButtons == null) - { - sortButtons = new UIButtonChoice(new Texture2D[] - { - Main.inventorySortTexture[0], - MagicStorage.Instance.GetTexture("SortID"), - MagicStorage.Instance.GetTexture("SortName") - }, - new LocalizedText[] - { - Language.GetText("Mods.MagicStorage.SortDefault"), - Language.GetText("Mods.MagicStorage.SortID"), - Language.GetText("Mods.MagicStorage.SortName") - }); - } - } - - private static void InitRecipeButtons() - { - if (recipeButtons == null) - { - recipeButtons = new UIButtonChoice(new Texture2D[] - { - MagicStorage.Instance.GetTexture("RecipeAvailable"), - MagicStorage.Instance.GetTexture("RecipeAll") - }, - new LocalizedText[] - { - Language.GetText("Mods.MagicStorage.RecipeAvailable"), - Language.GetText("Mods.MagicStorage.RecipeAll") - }); - } - } - - private static void InitFilterButtons() - { - if (filterButtons == null) - { - filterButtons = new UIButtonChoice(new Texture2D[] - { - MagicStorage.Instance.GetTexture("FilterAll"), - MagicStorage.Instance.GetTexture("FilterMelee"), - MagicStorage.Instance.GetTexture("FilterPickaxe"), - MagicStorage.Instance.GetTexture("FilterArmor"), - MagicStorage.Instance.GetTexture("FilterPotion"), - MagicStorage.Instance.GetTexture("FilterTile"), - MagicStorage.Instance.GetTexture("FilterMisc"), - }, - new LocalizedText[] - { - Language.GetText("Mods.MagicStorage.FilterAll"), - Language.GetText("Mods.MagicStorage.FilterWeapons"), - Language.GetText("Mods.MagicStorage.FilterTools"), - Language.GetText("Mods.MagicStorage.FilterEquips"), - Language.GetText("Mods.MagicStorage.FilterPotions"), - Language.GetText("Mods.MagicStorage.FilterTiles"), - Language.GetText("Mods.MagicStorage.FilterMisc") - }); - } - } - - public static void Update(GameTime gameTime) - {try{ - oldMouse = StorageGUI.oldMouse; - curMouse = StorageGUI.curMouse; - if (Main.playerInventory && Main.player[Main.myPlayer].GetModPlayer().ViewingStorage().X >= 0 && StoragePlayer.IsStorageCrafting()) - { - if (curMouse.RightButton == ButtonState.Released) - { - ResetSlotFocus(); - } - if (basePanel != null) - { - basePanel.Update(gameTime); - } - if (recipePanel != null) - { - recipePanel.Update(gameTime); - } - UpdateRecipeText(); - UpdateScrollBar(); - UpdateCraftButton(); - } - else - { - scrollBarFocus = 0; - selectedRecipe = null; - craftTimer = 0; - maxCraftTimer = startMaxCraftTimer; - ResetSlotFocus(); - }}catch(Exception e){Main.NewTextMultiline(e.ToString());} - } - - public static void Draw(TEStorageHeart heart) - {try{ - Player player = Main.player[Main.myPlayer]; - StoragePlayer modPlayer = player.GetModPlayer(); - Initialize(); - if (Main.mouseX > panelLeft && Main.mouseX < recipeLeft + panelWidth && Main.mouseY > panelTop && Main.mouseY < panelTop + panelHeight) - { - player.mouseInterface = true; - player.showItemIcon = false; - InterfaceHelper.HideItemIconCache(); - } - basePanel.Draw(Main.spriteBatch); - recipePanel.Draw(Main.spriteBatch); - Vector2 pos = recipeZone.GetDimensions().Position(); - if (threadRunning) - { - Utils.DrawBorderString(Main.spriteBatch, "Loading", pos + new Vector2(8f, 8f), Color.White); - } - stationZone.DrawText(); - recipeZone.DrawText(); - ingredientZone.DrawText(); - storageZone.DrawText(); - resultZone.DrawText(); - sortButtons.DrawText(); - recipeButtons.DrawText(); - filterButtons.DrawText();}catch(Exception e){Main.NewTextMultiline(e.ToString());} - } - - private static Item GetStation(int slot, ref int context) - { - Item[] stations = GetCraftingStations(); - if (stations == null || slot >= stations.Length) - { - return new Item(); - } - return stations[slot]; - } - - private static Item GetRecipe(int slot, ref int context) - { - if (threadRunning) - { - return new Item(); - } - int index = slot + numColumns * (int)Math.Round(scrollBar.ViewPosition); - Item item = index < recipes.Count ? recipes[index].createItem : new Item(); - if (!item.IsAir && recipes[index] == selectedRecipe) - { - context = 6; - } - if (!item.IsAir && !recipeAvailable[index]) - { - context = recipes[index] == selectedRecipe ? 4 : 3; - } - return item; - } - - private static Item GetIngredient(int slot, ref int context) - { - if (selectedRecipe == null || slot >= selectedRecipe.requiredItem.Length) - { - return new Item(); - } - Item item = selectedRecipe.requiredItem[slot].Clone(); - if (selectedRecipe.anyWood && item.type == ItemID.Wood) - { - item.SetNameOverride(Lang.misc[37].Value + " " + Lang.GetItemNameValue(ItemID.Wood)); - } - if (selectedRecipe.anySand && item.type == ItemID.SandBlock) - { - item.SetNameOverride(Lang.misc[37].Value + " " + Lang.GetItemNameValue(ItemID.SandBlock)); - } - if (selectedRecipe.anyIronBar && item.type == ItemID.IronBar) - { - item.SetNameOverride(Lang.misc[37].Value + " " + Lang.GetItemNameValue(ItemID.IronBar)); - } - if (selectedRecipe.anyFragment && item.type == ItemID.FragmentSolar) - { - item.SetNameOverride(Lang.misc[37].Value + " " + Lang.misc[51].Value); - } - if (selectedRecipe.anyPressurePlate && item.type == ItemID.GrayPressurePlate) - { - item.SetNameOverride(Lang.misc[37].Value + " " + Lang.misc[38].Value); - } - string nameOverride; - if (selectedRecipe.ProcessGroupsForText(item.type, out nameOverride)) - { - item.SetNameOverride(nameOverride); - } - return item; - } - - private static Item GetStorage(int slot, ref int context) - { - int index = slot + numColumns2 * (int)Math.Round(scrollBar2.ViewPosition); - Item item = index < storageItems.Count ? storageItems[index] : new Item(); - if (blockStorageItems.Contains(new ItemData(item))) - { - context = 3; - } - return item; - } - - private static Item GetResult(int slot, ref int context) - { - return slot == 0 && result != null ? result : new Item(); - } - - private static void UpdateRecipeText() - { - if (selectedRecipe == null) - { - reqObjText2.SetText(""); - } - else - { - bool isEmpty = true; - string text = ""; - for (int k = 0; k < selectedRecipe.requiredTile.Length; k++) - { - if (selectedRecipe.requiredTile[k] == -1) - { - break; - } - if (!isEmpty) - { - text += ", "; - } - text += Lang.GetMapObjectName(MapHelper.TileToLookup(selectedRecipe.requiredTile[k], 0)); - isEmpty = false; - } - if (selectedRecipe.needWater) - { - if (!isEmpty) - { - text += ", "; - } - text += Language.GetTextValue("LegacyInterface.53"); - isEmpty = false; - } - if (selectedRecipe.needHoney) - { - if (!isEmpty) - { - text += ", "; - } - text += Language.GetTextValue("LegacyInterface.58"); - isEmpty = false; - } - if (selectedRecipe.needLava) - { - if (!isEmpty) - { - text += ", "; - } - text += Language.GetTextValue("LegacyInterface.56"); - isEmpty = false; - } - if (selectedRecipe.needSnowBiome) - { - if (!isEmpty) - { - text += ", "; - } - text += Language.GetTextValue("LegacyInterface.123"); - isEmpty = false; - } - if (isEmpty) - { - text = Language.GetTextValue("LegacyInterface.23"); - } - reqObjText2.SetText(text); - } - } - - private static void UpdateScrollBar() - { - if (slotFocus) - { - scrollBarFocus = 0; - return; - } - Rectangle dim = scrollBar.GetClippingRectangle(Main.spriteBatch); - Vector2 boxPos = new Vector2(dim.X, dim.Y + dim.Height * (scrollBar.ViewPosition / scrollBarMaxViewSize)); - float boxWidth = 20f * Main.UIScale; - float boxHeight = dim.Height * (scrollBarViewSize / scrollBarMaxViewSize); - Rectangle dim2 = scrollBar2.GetClippingRectangle(Main.spriteBatch); - Vector2 box2Pos = new Vector2(dim2.X, dim2.Y + dim2.Height * (scrollBar2.ViewPosition / scrollBar2MaxViewSize)); - float box2Height = dim2.Height * (scrollBar2ViewSize / scrollBar2MaxViewSize); - if (scrollBarFocus > 0) - { - if (curMouse.LeftButton == ButtonState.Released) - { - scrollBarFocus = 0; - } - else - { - int difference = curMouse.Y - scrollBarFocusMouseStart; - if (scrollBarFocus == 1) - { - scrollBar.ViewPosition = scrollBarFocusPositionStart + (float)difference / boxHeight; - } - else if (scrollBarFocus == 2) - { - scrollBar2.ViewPosition = scrollBarFocusPositionStart + (float)difference / box2Height; - } - } - } - else if (MouseClicked) - { - if (curMouse.X > boxPos.X && curMouse.X < boxPos.X + boxWidth && curMouse.Y > boxPos.Y - 3f && curMouse.Y < boxPos.Y + boxHeight + 4f) - { - scrollBarFocus = 1; - scrollBarFocusMouseStart = curMouse.Y; - scrollBarFocusPositionStart = scrollBar.ViewPosition; - } - else if (curMouse.X > box2Pos.X && curMouse.X < box2Pos.X + boxWidth && curMouse.Y > box2Pos.Y - 3f && curMouse.Y < box2Pos.Y + box2Height + 4f) - { - scrollBarFocus = 2; - scrollBarFocusMouseStart = curMouse.Y; - scrollBarFocusPositionStart = scrollBar2.ViewPosition; - } - } - if (scrollBarFocus == 0) - { - int difference = oldMouse.ScrollWheelValue / 250 - curMouse.ScrollWheelValue / 250; - scrollBar.ViewPosition += difference; - } - } - - private static void UpdateCraftButton() - { - Rectangle dim = InterfaceHelper.GetFullRectangle(craftButton); - bool flag = false; - if (curMouse.X > dim.X && curMouse.X < dim.X + dim.Width && curMouse.Y > dim.Y && curMouse.Y < dim.Y + dim.Height) - { - craftButton.BackgroundColor = new Color(73, 94, 171); - if (curMouse.LeftButton == ButtonState.Pressed) - { - if (selectedRecipe != null && IsAvailable(selectedRecipe) && PassesBlock(selectedRecipe)) - { - if (craftTimer <= 0) - { - craftTimer = maxCraftTimer; - maxCraftTimer = maxCraftTimer * 3 / 4; - if (maxCraftTimer <= 0) - { - maxCraftTimer = 1; - } - TryCraft(); - RefreshItems(); - Main.PlaySound(7, -1, -1, 1); - } - craftTimer--; - flag = true; - } - } - } - else - { - craftButton.BackgroundColor = new Color(63, 82, 151) * 0.7f; - } - if (selectedRecipe == null || !IsAvailable(selectedRecipe) || !PassesBlock(selectedRecipe)) - { - craftButton.BackgroundColor = new Color(30, 40, 100) * 0.7f; - } - if (!flag) - { - craftTimer = 0; - maxCraftTimer = startMaxCraftTimer; - } - } - - private static TEStorageHeart GetHeart() - { - Player player = Main.player[Main.myPlayer]; - StoragePlayer modPlayer = player.GetModPlayer(); - return modPlayer.GetStorageHeart(); - } - - private static TECraftingAccess GetCraftingEntity() - { - Player player = Main.player[Main.myPlayer]; - StoragePlayer modPlayer = player.GetModPlayer(); - return modPlayer.GetCraftingAccess(); - } - - private static Item[] GetCraftingStations() - { - TECraftingAccess ent = GetCraftingEntity(); - return ent == null ? null : ent.stations; - } - - public static void RefreshItems() - { - SortMode sortMode; - FilterMode filterMode; - - lock (itemsLock) - { - items.Clear(); - TEStorageHeart heart = GetHeart(); - if (heart == null) - { - return; - } - items.AddRange(ItemSorter.SortAndFilter(heart.GetStoredItems(), SortMode.Id, FilterMode.All, "", "")); - AnalyzeIngredients(); - InitLangStuff(); - InitSortButtons(); - InitRecipeButtons(); - InitFilterButtons(); - switch (sortButtons.Choice) - { - case 0: - sortMode = SortMode.Default; - break; - case 1: - sortMode = SortMode.Id; - break; - case 2: - sortMode = SortMode.Name; - break; - default: - sortMode = SortMode.Default; - break; - } - switch (filterButtons.Choice) - { - case 0: - filterMode = FilterMode.All; - break; - case 1: - filterMode = FilterMode.Weapons; - break; - case 2: - filterMode = FilterMode.Tools; - break; - case 3: - filterMode = FilterMode.Equipment; - break; - case 4: - filterMode = FilterMode.Potions; - break; - case 5: - filterMode = FilterMode.Placeables; - break; - case 6: - filterMode = FilterMode.Misc; - break; - default: - filterMode = FilterMode.All; - break; - } - RefreshStorageItems(); - } - - lock (threadLock) - { - threadNeedsRestart = true; - threadSortMode = sortMode; - threadFilterMode = filterMode; - if (!threadRunning) - { - threadRunning = true; - Thread thread = new Thread(RefreshRecipes); - thread.Start(); - } - } - } - - private static void RefreshRecipes() - { - while (true) - {try{ - SortMode sortMode; - FilterMode filterMode; - lock (threadLock) - { - threadNeedsRestart = false; - sortMode = threadSortMode; - filterMode = threadFilterMode; - } - var temp = ItemSorter.GetRecipes(sortMode, filterMode, searchBar2.Text, searchBar.Text); - threadRecipes.Clear(); - threadRecipeAvailable.Clear(); - try - { - if (recipeButtons.Choice == 0) - { - threadRecipes.AddRange(temp.Where(recipe => IsAvailable(recipe))); - threadRecipeAvailable.AddRange(threadRecipes.Select(recipe => true)); - } - else - { - threadRecipes.AddRange(temp); - threadRecipeAvailable.AddRange(threadRecipes.Select(recipe => IsAvailable(recipe))); - } - } - catch (InvalidOperationException) - { - } - catch (KeyNotFoundException) - { - } - lock (recipeLock) - { - nextRecipes = new List(); - nextRecipeAvailable = new List(); - nextRecipes.AddRange(threadRecipes); - nextRecipeAvailable.AddRange(threadRecipeAvailable); - - } - lock (threadLock) - { - if (!threadNeedsRestart) - { - threadRunning = false; - return; - } - }}catch(Exception e){Main.NewTextMultiline(e.ToString());} - } - } - - private static void AnalyzeIngredients() - { - Player player = Main.player[Main.myPlayer]; - - lock (itemsLock) - { - itemCounts.Clear(); - if (adjTiles.Length != player.adjTile.Length) - { - Array.Resize(ref adjTiles, player.adjTile.Length); - } - for (int k = 0; k < adjTiles.Length; k++) - { - adjTiles[k] = false; - } - adjWater = false; - adjLava = false; - adjHoney = false; - zoneSnow = false; - alchemyTable = false; - - foreach (Item item in items) - { - if (itemCounts.ContainsKey(item.netID)) - { - itemCounts[item.netID] += item.stack; - } - else - { - itemCounts[item.netID] = item.stack; - } - } - } - - foreach (Item item in GetCraftingStations()) - { - if (item.createTile >= 0) - { - adjTiles[item.createTile] = true; - if (item.createTile == TileID.GlassKiln || item.createTile == TileID.Hellforge || item.createTile == TileID.AdamantiteForge) - { - adjTiles[TileID.Furnaces] = true; - } - if (item.createTile == TileID.AdamantiteForge) - { - adjTiles[TileID.Hellforge] = true; - } - if (item.createTile == TileID.MythrilAnvil) - { - adjTiles[TileID.Anvils] = true; - } - if (item.createTile == TileID.BewitchingTable || item.createTile == TileID.Tables2) - { - adjTiles[TileID.Tables] = true; - } - if (item.createTile == TileID.AlchemyTable) - { - adjTiles[TileID.Bottles] = true; - adjTiles[TileID.Tables] = true; - alchemyTable = true; - } - bool[] oldAdjTile = player.adjTile; - bool oldAdjWater = adjWater; - bool oldAdjLava = adjLava; - bool oldAdjHoney = adjHoney; - bool oldAlchemyTable = alchemyTable; - player.adjTile = adjTiles; - player.adjWater = false; - player.adjLava = false; - player.adjHoney = false; - player.alchemyTable = false; - TileLoader.AdjTiles(player, item.createTile); - if (player.adjWater) - { - adjWater = true; - } - if (player.adjLava) - { - adjLava = true; - } - if (player.adjHoney) - { - adjHoney = true; - } - if (player.alchemyTable) - { - alchemyTable = true; - } - player.adjTile = oldAdjTile; - player.adjWater = oldAdjWater; - player.adjLava = oldAdjLava; - player.adjHoney = oldAdjHoney; - player.alchemyTable = oldAlchemyTable; - } - if (item.type == ItemID.WaterBucket || item.type == ItemID.BottomlessBucket) - { - adjWater = true; - } - if (item.type == ItemID.LavaBucket) - { - adjLava = true; - } - if (item.type == ItemID.HoneyBucket) - { - adjHoney = true; - } - if (item.type == MagicStorage.Instance.ItemType("SnowBiomeEmulator")) - { - zoneSnow = true; - } - } - adjTiles[MagicStorage.Instance.TileType("CraftingAccess")] = true; - } - - private static bool IsAvailable(Recipe recipe) - { - foreach (int tile in recipe.requiredTile) - { - if (tile == -1) - { - break; - } - if (!adjTiles[tile]) - { - return false; - } - } - - lock (itemsLock) - { - foreach (Item ingredient in recipe.requiredItem) - { - if (ingredient.type == 0) - { - break; - } - int stack = ingredient.stack; - bool useRecipeGroup = false; - foreach (int type in itemCounts.Keys) - { - if (RecipeGroupMatch(recipe, type, ingredient.type)) - { - stack -= itemCounts[type]; - useRecipeGroup = true; - } - } - if (!useRecipeGroup && itemCounts.ContainsKey(ingredient.netID)) - { - stack -= itemCounts[ingredient.netID]; - } - if (stack > 0) - { - return false; - } - } - } - - if (recipe.needWater && !adjWater && !adjTiles[TileID.Sinks]) - { - return false; - } - if (recipe.needLava && !adjLava) - { - return false; - } - if (recipe.needHoney && !adjHoney) - { - return false; - } - if (recipe.needSnowBiome && !zoneSnow) - { - return false; - } - try - { - BlockRecipes.active = false; - if (!RecipeHooks.RecipeAvailable(recipe)) - { - return false; - } - } - finally - { - BlockRecipes.active = true; - } - return true; - } - - private static bool PassesBlock(Recipe recipe) - { - foreach (Item ingredient in recipe.requiredItem) - { - if (ingredient.type == 0) - { - break; - } - int stack = ingredient.stack; - bool useRecipeGroup = false; - foreach (Item item in storageItems) - { - ItemData data = new ItemData(item); - if (!blockStorageItems.Contains(data) && RecipeGroupMatch(recipe, item.netID, ingredient.type)) - { - stack -= item.stack; - useRecipeGroup = true; - } - } - if (!useRecipeGroup) - { - foreach (Item item in storageItems) - { - ItemData data = new ItemData(item); - if (!blockStorageItems.Contains(data) && item.netID == ingredient.netID) - { - stack -= item.stack; - } - } - } - if (stack > 0) - { - return false; - } - } - return true; - } - - private static void RefreshStorageItems() - { - storageItems.Clear(); - result = null; - if (selectedRecipe != null) - { - foreach (Item item in items) - { - for (int k = 0; k < selectedRecipe.requiredItem.Length; k++) - { - if (selectedRecipe.requiredItem[k].type == 0) - { - break; - } - if (item.type == selectedRecipe.requiredItem[k].type || RecipeGroupMatch(selectedRecipe, selectedRecipe.requiredItem[k].type, item.type)) - { - storageItems.Add(item); - } - } - if (item.type == selectedRecipe.createItem.type) - { - result = item; - } - } - if (result == null) - { - result = new Item(); - result.SetDefaults(selectedRecipe.createItem.type); - result.stack = 0; - } - } - } - - private static bool RecipeGroupMatch(Recipe recipe, int type1, int type2) - { - return recipe.useWood(type1, type2) || recipe.useSand(type1, type2) || recipe.useIronBar(type1, type2) || recipe.useFragment(type1, type2) || recipe.AcceptedByItemGroups(type1, type2) || recipe.usePressurePlate(type1, type2); - } - - private static void HoverStation(int slot, ref int hoverSlot) - { - TECraftingAccess ent = GetCraftingEntity(); - if (ent == null || slot >= ent.stations.Length) - { - return; - } - - Player player = Main.player[Main.myPlayer]; - if (MouseClicked) - { - bool changed = false; - if (!ent.stations[slot].IsAir && ItemSlot.ShiftInUse) - { - Item result = player.GetItem(Main.myPlayer, DoWithdraw(slot), false, true); - if (!result.IsAir && Main.mouseItem.IsAir) - { - Main.mouseItem = result; - result = new Item(); - } - if (!result.IsAir && Main.mouseItem.type == result.type && Main.mouseItem.stack < Main.mouseItem.maxStack) - { - Main.mouseItem.stack += result.stack; - result = new Item(); - } - if (!result.IsAir) - { - player.QuickSpawnClonedItem(result); - } - changed = true; - } - else if (player.itemAnimation == 0 && player.itemTime == 0) - { - int oldType = Main.mouseItem.type; - int oldStack = Main.mouseItem.stack; - Main.mouseItem = DoStationSwap(Main.mouseItem, slot); - if (oldType != Main.mouseItem.type || oldStack != Main.mouseItem.stack) - { - changed = true; - } - } - if (changed) - { - RefreshItems(); - Main.PlaySound(7, -1, -1, 1); - } - } - - hoverSlot = slot; - } - - private static void HoverRecipe(int slot, ref int hoverSlot) - { - int visualSlot = slot; - slot += numColumns * (int)Math.Round(scrollBar.ViewPosition); - if (slot < recipes.Count) - { - if (MouseClicked) - { - selectedRecipe = recipes[slot]; - - lock (itemsLock) - { - RefreshStorageItems(); - } - - blockStorageItems.Clear(); - } - hoverSlot = visualSlot; - } - } - - private static void HoverItem(int slot, ref int hoverSlot) - { - hoverSlot = slot; - } - - private static void HoverStorage(int slot, ref int hoverSlot) - { - int visualSlot = slot; - slot += numColumns2 * (int)Math.Round(scrollBar2.ViewPosition); - if (slot < storageItems.Count) - { - if (MouseClicked) - { - ItemData data = new ItemData(storageItems[slot]); - if (blockStorageItems.Contains(data)) - { - blockStorageItems.Remove(data); - } - else - { - blockStorageItems.Add(data); - } - } - hoverSlot = visualSlot; - } - } - - private static void HoverResult(int slot, ref int hoverSlot) - { - if (slot != 0) - { - return; - } - - Player player = Main.player[Main.myPlayer]; - if (MouseClicked) - { - bool changed = false; - if (!Main.mouseItem.IsAir && player.itemAnimation == 0 && player.itemTime == 0 && result != null && Main.mouseItem.type == result.type) - { - if (TryDepositResult(Main.mouseItem)) - { - changed = true; - } - } - else if (Main.mouseItem.IsAir && result != null && !result.IsAir) - { - Item toWithdraw = result.Clone(); - if (toWithdraw.stack > toWithdraw.maxStack) - { - toWithdraw.stack = toWithdraw.maxStack; - } - Main.mouseItem = DoWithdrawResult(toWithdraw, ItemSlot.ShiftInUse); - if (ItemSlot.ShiftInUse) - { - Main.mouseItem = player.GetItem(Main.myPlayer, Main.mouseItem, false, true); - } - changed = true; - } - if (changed) - { - RefreshItems(); - Main.PlaySound(7, -1, -1, 1); - } - } - - if (curMouse.RightButton == ButtonState.Pressed && oldMouse.RightButton == ButtonState.Released && result != null && !result.IsAir && (Main.mouseItem.IsAir || ItemData.Matches(Main.mouseItem, items[slot]) && Main.mouseItem.stack < Main.mouseItem.maxStack)) - { - slotFocus = true; - } - - hoverSlot = slot; - - if (slotFocus) - { - SlotFocusLogic(); - } - } - - private static void SlotFocusLogic() - { - if (result == null || result.IsAir || (!Main.mouseItem.IsAir && (!ItemData.Matches(Main.mouseItem, result) || Main.mouseItem.stack >= Main.mouseItem.maxStack))) - { - ResetSlotFocus(); - } - else - { - if (rightClickTimer <= 0) - { - rightClickTimer = maxRightClickTimer; - maxRightClickTimer = maxRightClickTimer * 3 / 4; - if (maxRightClickTimer <= 0) - { - maxRightClickTimer = 1; - } - Item toWithdraw = result.Clone(); - toWithdraw.stack = 1; - Item withdrawn = DoWithdrawResult(toWithdraw); - if (Main.mouseItem.IsAir) - { - Main.mouseItem = withdrawn; - } - else - { - Main.mouseItem.stack += withdrawn.stack; - } - Main.soundInstanceMenuTick.Stop(); - Main.soundInstanceMenuTick = Main.soundMenuTick.CreateInstance(); - Main.PlaySound(12, -1, -1, 1); - RefreshItems(); - } - rightClickTimer--; - } - } - - private static void ResetSlotFocus() - { - slotFocus = false; - rightClickTimer = 0; - maxRightClickTimer = startMaxRightClickTimer; - } - - private static Item DoWithdraw(int slot) - { - TECraftingAccess access = GetCraftingEntity(); - if (Main.netMode == 0) - { - Item result = access.TryWithdrawStation(slot); - RefreshItems(); - return result; - } - else - { - NetHelper.SendWithdrawStation(access.ID, slot); - return new Item(); - } - } - - private static Item DoStationSwap(Item item, int slot) - { - TECraftingAccess access = GetCraftingEntity(); - if (Main.netMode == 0) - { - Item result = access.DoStationSwap(item, slot); - RefreshItems(); - return result; - } - else - { - NetHelper.SendStationSlotClick(access.ID, item, slot); - return new Item(); - } - } - - private static void TryCraft() - { - List toWithdraw; - lock (itemsLock) - { - List availableItems = new List(storageItems.Where(item => !blockStorageItems.Contains(new ItemData(item))).Select(item => item.Clone())); - toWithdraw = new List(); - for (int k = 0; k < selectedRecipe.requiredItem.Length; k++) - { - Item item = selectedRecipe.requiredItem[k]; - if (item.type == 0) - { - break; - } - int stack = item.stack; - ModRecipe modRecipe = selectedRecipe as ModRecipe; - if (modRecipe != null) - { - stack = modRecipe.ConsumeItem(item.type, item.stack); - } - if (selectedRecipe.alchemy && alchemyTable) - { - int save = 0; - for (int j = 0; j < stack; j++) - { - if (Main.rand.Next(3) == 0) - { - save++; - } - } - stack -= save; - } - if (stack > 0) - { - foreach (Item tryItem in availableItems) - { - if (item.type == tryItem.type || RecipeGroupMatch(selectedRecipe, item.type, tryItem.type)) - { - if (tryItem.stack > stack) - { - Item temp = tryItem.Clone(); - temp.stack = stack; - toWithdraw.Add(temp); - tryItem.stack -= stack; - stack = 0; - } - else - { - toWithdraw.Add(tryItem.Clone()); - stack -= tryItem.stack; - tryItem.stack = 0; - tryItem.type = 0; - } - } - } - } - } - } - - Item resultItem = selectedRecipe.createItem.Clone(); - resultItem.Prefix(-1); - - RecipeHooks.OnCraft(resultItem, selectedRecipe); - ItemLoader.OnCraft(resultItem, selectedRecipe); - - if (Main.netMode == 0) - { - foreach (Item item in DoCraft(GetHeart(), toWithdraw, resultItem)) - { - Main.player[Main.myPlayer].QuickSpawnClonedItem(item, item.stack); - } - } - else if (Main.netMode == 1) - { - NetHelper.SendCraftRequest(GetHeart().ID, toWithdraw, resultItem); - } - } - - internal static List DoCraft(TEStorageHeart heart, List toWithdraw, Item result) - { - List items = new List(); - foreach (Item tryWithdraw in toWithdraw) - { - Item withdrawn = heart.TryWithdraw(tryWithdraw); - if (!withdrawn.IsAir) - { - items.Add(withdrawn); - } - if (withdrawn.stack < tryWithdraw.stack) - { - for (int k = 0; k < items.Count; k++) - { - heart.DepositItem(items[k]); - if (items[k].IsAir) - { - items.RemoveAt(k); - k--; - } - } - return items; - } - } - items.Clear(); - heart.DepositItem(result); - if (!result.IsAir) - { - items.Add(result); - } - return items; - } - - private static bool TryDepositResult(Item item) - { - int oldStack = item.stack; - DoDepositResult(item); - return oldStack != item.stack; - } - - private static void DoDepositResult(Item item) - { - TEStorageHeart heart = GetHeart(); - if (Main.netMode == 0) - { - heart.DepositItem(item); - } - else - { - NetHelper.SendDeposit(heart.ID, item); - item.SetDefaults(0, true); - } - } - - private static Item DoWithdrawResult(Item item, bool toInventory = false) - { - TEStorageHeart heart = GetHeart(); - if (Main.netMode == 0) - { - return heart.TryWithdraw(item); - } - else - { - NetHelper.SendWithdraw(heart.ID, item, toInventory); - return new Item(); - } - } - } + public static class CraftingGUI + { + private const int padding = 4; + private const int numColumns = 10; + private const int numColumns2 = 7; + private const float inventoryScale = 0.85f; + private const float smallScale = 0.7f; + + public static MouseState curMouse; + public static MouseState oldMouse; + public static bool MouseClicked + { + get + { + return curMouse.LeftButton == ButtonState.Pressed && oldMouse.LeftButton == ButtonState.Released; + } + } + + private static UIPanel basePanel; + private static float panelTop; + private static float panelLeft; + private static float panelWidth; + private static float panelHeight; + + private static UIElement topBar; + internal static UISearchBar searchBar; + private static UIButtonChoice sortButtons; + private static UIButtonChoice recipeButtons; + private static UIElement topBar2; + private static UIButtonChoice filterButtons; + internal static UISearchBar searchBar2; + + private static UIText stationText; + private static UISlotZone stationZone = new UISlotZone(HoverStation, GetStation, inventoryScale / 1.55f); + private static UIText recipeText; + private static UISlotZone recipeZone = new UISlotZone(HoverRecipe, GetRecipe, inventoryScale); + + internal static UIScrollbar scrollBar = new UIScrollbar(); + private static int scrollBarFocus = 0; + private static int scrollBarFocusMouseStart; + private static float scrollBarFocusPositionStart; + private static float scrollBarViewSize = 1f; + private static float scrollBarMaxViewSize = 2f; + + private static List items = new List(); + private static Dictionary itemCounts = new Dictionary(); + private static bool[] adjTiles = new bool[TileLoader.TileCount]; + private static bool adjWater = false; + private static bool adjLava = false; + private static bool adjHoney = false; + private static bool zoneSnow = false; + private static bool alchemyTable = false; + private static List recipes = new List(); + private static List recipeAvailable = new List(); + private static Recipe selectedRecipe = null; + private static int numRows; + private static int displayRows; + private static bool slotFocus = false; + + private static UIElement bottomBar = new UIElement(); + private static UIText capacityText; + + private static UIPanel recipePanel; + private static float recipeTop; + private static float recipeLeft; + private static float recipeWidth; + private static float recipeHeight; + + private static UIText recipePanelHeader; + private static UIText ingredientText; + private static UISlotZone ingredientZone = new UISlotZone(HoverItem, GetIngredient, smallScale); + private static UIText reqObjText; + private static UIText reqObjText2; + private static UIText storedItemsText; + + private static UISlotZone storageZone = new UISlotZone(HoverStorage, GetStorage, smallScale); + private static int numRows2; + private static int displayRows2; + private static List storageItems = new List(); + private static List blockStorageItems = new List(); + + internal static UIScrollbar scrollBar2 = new UIScrollbar(); + private static float scrollBar2ViewSize = 1f; + private static float scrollBar2MaxViewSize = 2f; + + internal static UITextPanel craftButton; + private static Item result = null; + private static UISlotZone resultZone = new UISlotZone(HoverResult, GetResult, inventoryScale); + private static int craftTimer = 0; + private const int startMaxCraftTimer = 20; + private static int maxCraftTimer = startMaxCraftTimer; + private static int rightClickTimer = 0; + private const int startMaxRightClickTimer = 20; + private static int maxRightClickTimer = startMaxRightClickTimer; + + private static Object threadLock = new Object(); + private static Object recipeLock = new Object(); + private static Object itemsLock = new Object(); + private static bool threadRunning = false; + internal static bool threadNeedsRestart = false; + private static SortMode threadSortMode; + private static FilterMode threadFilterMode; + private static List threadRecipes = new List(); + private static List threadRecipeAvailable = new List(); + private static List nextRecipes = new List(); + private static List nextRecipeAvailable = new List(); + + public static void Initialize() + { + lock (recipeLock) + { + recipes = nextRecipes; + recipeAvailable = nextRecipeAvailable; + } + + InitLangStuff(); + float itemSlotWidth = Main.inventoryBackTexture.Width * inventoryScale; + float itemSlotHeight = Main.inventoryBackTexture.Height * inventoryScale; + float smallSlotWidth = Main.inventoryBackTexture.Width * smallScale; + float smallSlotHeight = Main.inventoryBackTexture.Height * smallScale; + + panelTop = Main.instance.invBottom + 60; + panelLeft = 20f; + basePanel = new UIPanel(); + float innerPanelLeft = panelLeft + basePanel.PaddingLeft; + float innerPanelWidth = numColumns * (itemSlotWidth + padding) + 20f + padding; + panelWidth = basePanel.PaddingLeft + innerPanelWidth + basePanel.PaddingRight; + panelHeight = Main.screenHeight - panelTop; + basePanel.Left.Set(panelLeft, 0f); + basePanel.Top.Set(panelTop, 0f); + basePanel.Width.Set(panelWidth, 0f); + basePanel.Height.Set(panelHeight, 0f); + basePanel.Recalculate(); + + recipePanel = new UIPanel(); + recipeTop = panelTop; + recipeLeft = panelLeft + panelWidth; + recipeWidth = numColumns2 * (smallSlotWidth + padding) + 20f + padding; + recipeWidth += recipePanel.PaddingLeft + recipePanel.PaddingRight; + recipeHeight = panelHeight; + recipePanel.Left.Set(recipeLeft, 0f); + recipePanel.Top.Set(recipeTop, 0f); + recipePanel.Width.Set(recipeWidth, 0f); + recipePanel.Height.Set(recipeHeight, 0f); + recipePanel.Recalculate(); + + topBar = new UIElement(); + topBar.Width.Set(0f, 1f); + topBar.Height.Set(32f, 0f); + basePanel.Append(topBar); + + InitSortButtons(); + topBar.Append(sortButtons); + float sortButtonsRight = sortButtons.GetDimensions().Width + padding; + InitRecipeButtons(); + float recipeButtonsLeft = sortButtonsRight + 32f + 3 * padding; + recipeButtons.Left.Set(recipeButtonsLeft, 0f); + topBar.Append(recipeButtons); + float recipeButtonsRight = recipeButtonsLeft + recipeButtons.GetDimensions().Width + padding; + + searchBar.Left.Set(recipeButtonsRight + padding, 0f); + searchBar.Width.Set(-recipeButtonsRight - 2 * padding, 1f); + searchBar.Height.Set(0f, 1f); + topBar.Append(searchBar); + + topBar2 = new UIElement(); + topBar2.Width.Set(0f, 1f); + topBar2.Height.Set(32f, 0f); + topBar2.Top.Set(36f, 0f); + basePanel.Append(topBar2); + + InitFilterButtons(); + float filterButtonsRight = filterButtons.GetDimensions().Width + padding; + topBar2.Append(filterButtons); + searchBar2.Left.Set(filterButtonsRight + padding, 0f); + searchBar2.Width.Set(-filterButtonsRight - 2 * padding, 1f); + searchBar2.Height.Set(0f, 1f); + topBar2.Append(searchBar2); + + stationText.Top.Set(76f, 0f); + basePanel.Append(stationText); + + stationZone.Width.Set(0f, 1f); + stationZone.Top.Set(100f, 0f); + int rows = GetCraftingStations().Count / TECraftingAccess.Columns + 1; + if (rows > TECraftingAccess.Rows) + { + rows = TECraftingAccess.Rows; + } + stationZone.SetDimensions(TECraftingAccess.Columns, rows); + stationZone.Height.Set(stationZone.getHeight(), 1f); + basePanel.Append(stationZone); + + recipeText.Top.Set(152f, 0f); + basePanel.Append(recipeText); + + recipeZone.Width.Set(0f, 1f); + recipeZone.Top.Set(100 + stationZone.getHeight(), 0f); + recipeZone.Height.Set(-(100 + stationZone.getHeight()), 1f); + basePanel.Append(recipeZone); + + numRows = (recipes.Count + numColumns - 1) / numColumns; + displayRows = (int)recipeZone.GetDimensions().Height / ((int)itemSlotHeight + padding); + recipeZone.SetDimensions(numColumns, displayRows); + int noDisplayRows = numRows - displayRows; + if (noDisplayRows < 0) + { + noDisplayRows = 0; + } + scrollBarMaxViewSize = 1 + noDisplayRows; + scrollBar.Height.Set(displayRows * (itemSlotHeight + padding), 0f); + scrollBar.Left.Set(-20f, 1f); + scrollBar.SetView(scrollBarViewSize, scrollBarMaxViewSize); + recipeZone.Append(scrollBar); + + bottomBar.Width.Set(0f, 1f); + bottomBar.Height.Set(32f, 0f); + bottomBar.Top.Set(-32f, 1f); + basePanel.Append(bottomBar); + + capacityText.Left.Set(6f, 0f); + capacityText.Top.Set(6f, 0f); + TEStorageHeart heart = GetHeart(); + int numItems = 0; + int capacity = 0; + if (heart != null) + { + foreach (TEAbstractStorageUnit abstractStorageUnit in heart.GetStorageUnits()) + { + if (abstractStorageUnit is TEStorageUnit) + { + TEStorageUnit storageUnit = (TEStorageUnit)abstractStorageUnit; + numItems += storageUnit.NumItems; + capacity += storageUnit.Capacity; + } + } + } + capacityText.SetText(numItems + "/" + capacity + " Items"); + bottomBar.Append(capacityText); + + recipePanel.Append(recipePanelHeader); + ingredientText.Top.Set(30f, 0f); + recipePanel.Append(ingredientText); + + ingredientZone.SetDimensions(numColumns2, 2); + ingredientZone.Top.Set(54f, 0f); + ingredientZone.Width.Set(0f, 1f); + ingredientZone.Height.Set(60f, 0f); + recipePanel.Append(ingredientZone); + + reqObjText.Top.Set(136f, 0f); + recipePanel.Append(reqObjText); + reqObjText2.Top.Set(160f, 0f); + recipePanel.Append(reqObjText2); + storedItemsText.Top.Set(190f, 0f); + recipePanel.Append(storedItemsText); + + storageZone.Top.Set(214f, 0f); + storageZone.Width.Set(0f, 1f); + storageZone.Height.Set(-214f - 36, 1f); + recipePanel.Append(storageZone); + numRows2 = (storageItems.Count + numColumns2 - 1) / numColumns2; + displayRows2 = (int)storageZone.GetDimensions().Height / ((int)smallSlotHeight + padding); + storageZone.SetDimensions(numColumns2, displayRows2); + int noDisplayRows2 = numRows2 - displayRows2; + if (noDisplayRows2 < 0) + { + noDisplayRows2 = 0; + } + scrollBar2MaxViewSize = 1 + noDisplayRows2; + scrollBar2.Height.Set(displayRows2 * (smallSlotHeight + padding), 0f); + scrollBar2.Left.Set(-20f, 1f); + scrollBar2.SetView(scrollBar2ViewSize, scrollBar2MaxViewSize); + storageZone.Append(scrollBar2); + + craftButton.Top.Set(-32f, 1f); + craftButton.Width.Set(100f, 0f); + craftButton.Height.Set(24f, 0f); + craftButton.PaddingTop = 8f; + craftButton.PaddingBottom = 8f; + recipePanel.Append(craftButton); + + resultZone.SetDimensions(1, 1); + resultZone.Left.Set(-itemSlotWidth, 1f); + resultZone.Top.Set(-itemSlotHeight, 1f); + resultZone.Width.Set(itemSlotWidth, 0f); + resultZone.Height.Set(itemSlotHeight, 0f); + recipePanel.Append(resultZone); + } + + private static void InitLangStuff() + { + if (searchBar == null) + { + searchBar = new UISearchBar(Language.GetText("Mods.MagicStorage.SearchName")); + } + if (searchBar2 == null) + { + searchBar2 = new UISearchBar(Language.GetText("Mods.MagicStorage.SearchMod")); + } + if (stationText == null) + { + stationText = new UIText(Language.GetText("Mods.MagicStorage.CraftingStations")); + } + if (recipeText == null) + { + recipeText = new UIText(Language.GetText("Mods.MagicStorage.Recipes")); + } + if (capacityText == null) + { + capacityText = new UIText("Items"); + } + if (recipePanelHeader == null) + { + recipePanelHeader = new UIText(Language.GetText("Mods.MagicStorage.SelectedRecipe")); + } + if (ingredientText == null) + { + ingredientText = new UIText(Language.GetText("Mods.MagicStorage.Ingredients")); + } + if (reqObjText == null) + { + reqObjText = new UIText(Language.GetText("LegacyInterface.22")); + } + if (reqObjText2 == null) + { + reqObjText2 = new UIText(""); + } + if (storedItemsText == null) + { + storedItemsText = new UIText(Language.GetText("Mods.MagicStorage.StoredItems")); + } + if (craftButton == null) + { + craftButton = new UITextPanel(Language.GetText("LegacyMisc.72"), 1f); + } + } + + internal static void Unload() + { + sortButtons = null; + filterButtons = null; + recipeButtons = null; + } + + private static void InitSortButtons() + { + if (sortButtons == null) + { + sortButtons = new UIButtonChoice(new Texture2D[] + { + Main.inventorySortTexture[0], + MagicStorage.Instance.GetTexture("SortID"), + MagicStorage.Instance.GetTexture("SortName") + }, + new LocalizedText[] + { + Language.GetText("Mods.MagicStorage.SortDefault"), + Language.GetText("Mods.MagicStorage.SortID"), + Language.GetText("Mods.MagicStorage.SortName") + }); + } + } + + private static void InitRecipeButtons() + { + if (recipeButtons == null) + { + recipeButtons = new UIButtonChoice(new Texture2D[] + { + MagicStorage.Instance.GetTexture("RecipeAvailable"), + MagicStorage.Instance.GetTexture("RecipeAll") + }, + new LocalizedText[] + { + Language.GetText("Mods.MagicStorage.RecipeAvailable"), + Language.GetText("Mods.MagicStorage.RecipeAll") + }); + } + } + + private static void InitFilterButtons() + { + if (filterButtons == null) + { + filterButtons = new UIButtonChoice(new Texture2D[] + { + MagicStorage.Instance.GetTexture("FilterAll"), + MagicStorage.Instance.GetTexture("FilterMelee"), + MagicStorage.Instance.GetTexture("FilterPickaxe"), + MagicStorage.Instance.GetTexture("FilterArmor"), + MagicStorage.Instance.GetTexture("FilterPotion"), + MagicStorage.Instance.GetTexture("FilterTile"), + MagicStorage.Instance.GetTexture("FilterMisc"), + }, + new LocalizedText[] + { + Language.GetText("Mods.MagicStorage.FilterAll"), + Language.GetText("Mods.MagicStorage.FilterWeapons"), + Language.GetText("Mods.MagicStorage.FilterTools"), + Language.GetText("Mods.MagicStorage.FilterEquips"), + Language.GetText("Mods.MagicStorage.FilterPotions"), + Language.GetText("Mods.MagicStorage.FilterTiles"), + Language.GetText("Mods.MagicStorage.FilterMisc") + }); + } + } + + public static void Update(GameTime gameTime) + { + try + { + oldMouse = StorageGUI.oldMouse; + curMouse = StorageGUI.curMouse; + if (Main.playerInventory && Main.player[Main.myPlayer].GetModPlayer().ViewingStorage().X >= 0 && StoragePlayer.IsStorageCrafting()) + { + if (curMouse.RightButton == ButtonState.Released) + { + ResetSlotFocus(); + } + if (basePanel != null) + { + basePanel.Update(gameTime); + } + if (recipePanel != null) + { + recipePanel.Update(gameTime); + } + UpdateRecipeText(); + UpdateScrollBar(); + UpdateCraftButton(); + } + else + { + scrollBarFocus = 0; + selectedRecipe = null; + craftTimer = 0; + maxCraftTimer = startMaxCraftTimer; + ResetSlotFocus(); + } + } + catch (Exception e) { Main.NewTextMultiline(e.ToString()); } + } + + public static void Draw(TEStorageHeart heart) + { + try + { + Player player = Main.player[Main.myPlayer]; + StoragePlayer modPlayer = player.GetModPlayer(); + Initialize(); + if (Main.mouseX > panelLeft && Main.mouseX < recipeLeft + panelWidth && Main.mouseY > panelTop && Main.mouseY < panelTop + panelHeight) + { + player.mouseInterface = true; + player.showItemIcon = false; + InterfaceHelper.HideItemIconCache(); + } + basePanel.Draw(Main.spriteBatch); + recipePanel.Draw(Main.spriteBatch); + Vector2 pos = recipeZone.GetDimensions().Position(); + if (threadRunning) + { + Utils.DrawBorderString(Main.spriteBatch, "Loading", pos + new Vector2(8f, 8f), Color.White); + } + stationZone.DrawText(); + recipeZone.DrawText(); + ingredientZone.DrawText(); + storageZone.DrawText(); + resultZone.DrawText(); + sortButtons.DrawText(); + recipeButtons.DrawText(); + filterButtons.DrawText(); + } + catch (Exception e) { Main.NewTextMultiline(e.ToString()); } + } + + private static Item GetStation(int slot, ref int context) + { + List stations = GetCraftingStations(); + Item station = new Item(); + if (stations.Count > 0 && slot < stations.Count) + { + station = stations[slot]; + } + return station; + } + + private static Item GetRecipe(int slot, ref int context) + { + if (threadRunning) + { + return new Item(); + } + int index = slot + numColumns * (int)Math.Round(scrollBar.ViewPosition); + Item item = index < recipes.Count ? recipes[index].createItem : new Item(); + if (!item.IsAir && recipes[index] == selectedRecipe) + { + context = 6; + } + if (!item.IsAir && !recipeAvailable[index]) + { + context = recipes[index] == selectedRecipe ? 4 : 3; + } + return item; + } + + private static Item GetIngredient(int slot, ref int context) + { + if (selectedRecipe == null || slot >= selectedRecipe.requiredItem.Length) + { + return new Item(); + } + Item item = selectedRecipe.requiredItem[slot].Clone(); + if (selectedRecipe.anyWood && item.type == ItemID.Wood) + { + item.SetNameOverride(Lang.misc[37].Value + " " + Lang.GetItemNameValue(ItemID.Wood)); + } + if (selectedRecipe.anySand && item.type == ItemID.SandBlock) + { + item.SetNameOverride(Lang.misc[37].Value + " " + Lang.GetItemNameValue(ItemID.SandBlock)); + } + if (selectedRecipe.anyIronBar && item.type == ItemID.IronBar) + { + item.SetNameOverride(Lang.misc[37].Value + " " + Lang.GetItemNameValue(ItemID.IronBar)); + } + if (selectedRecipe.anyFragment && item.type == ItemID.FragmentSolar) + { + item.SetNameOverride(Lang.misc[37].Value + " " + Lang.misc[51].Value); + } + if (selectedRecipe.anyPressurePlate && item.type == ItemID.GrayPressurePlate) + { + item.SetNameOverride(Lang.misc[37].Value + " " + Lang.misc[38].Value); + } + string nameOverride; + if (selectedRecipe.ProcessGroupsForText(item.type, out nameOverride)) + { + item.SetNameOverride(nameOverride); + } + return item; + } + + private static Item GetStorage(int slot, ref int context) + { + int index = slot + numColumns2 * (int)Math.Round(scrollBar2.ViewPosition); + Item item = index < storageItems.Count ? storageItems[index] : new Item(); + if (blockStorageItems.Contains(new ItemData(item))) + { + context = 3; + } + return item; + } + + private static Item GetResult(int slot, ref int context) + { + return slot == 0 && result != null ? result : new Item(); + } + + private static void UpdateRecipeText() + { + if (selectedRecipe == null) + { + reqObjText2.SetText(""); + } + else + { + bool isEmpty = true; + string text = ""; + for (int k = 0; k < selectedRecipe.requiredTile.Length; k++) + { + if (selectedRecipe.requiredTile[k] == -1) + { + break; + } + if (!isEmpty) + { + text += ", "; + } + text += Lang.GetMapObjectName(MapHelper.TileToLookup(selectedRecipe.requiredTile[k], 0)); + isEmpty = false; + } + if (selectedRecipe.needWater) + { + if (!isEmpty) + { + text += ", "; + } + text += Language.GetTextValue("LegacyInterface.53"); + isEmpty = false; + } + if (selectedRecipe.needHoney) + { + if (!isEmpty) + { + text += ", "; + } + text += Language.GetTextValue("LegacyInterface.58"); + isEmpty = false; + } + if (selectedRecipe.needLava) + { + if (!isEmpty) + { + text += ", "; + } + text += Language.GetTextValue("LegacyInterface.56"); + isEmpty = false; + } + if (selectedRecipe.needSnowBiome) + { + if (!isEmpty) + { + text += ", "; + } + text += Language.GetTextValue("LegacyInterface.123"); + isEmpty = false; + } + if (isEmpty) + { + text = Language.GetTextValue("LegacyInterface.23"); + } + reqObjText2.SetText(text); + } + } + + private static void UpdateScrollBar() + { + if (slotFocus) + { + scrollBarFocus = 0; + return; + } + Rectangle dim = scrollBar.GetClippingRectangle(Main.spriteBatch); + Vector2 boxPos = new Vector2(dim.X, dim.Y + dim.Height * (scrollBar.ViewPosition / scrollBarMaxViewSize)); + float boxWidth = 20f * Main.UIScale; + float boxHeight = dim.Height * (scrollBarViewSize / scrollBarMaxViewSize); + Rectangle dim2 = scrollBar2.GetClippingRectangle(Main.spriteBatch); + Vector2 box2Pos = new Vector2(dim2.X, dim2.Y + dim2.Height * (scrollBar2.ViewPosition / scrollBar2MaxViewSize)); + float box2Height = dim2.Height * (scrollBar2ViewSize / scrollBar2MaxViewSize); + if (scrollBarFocus > 0) + { + if (curMouse.LeftButton == ButtonState.Released) + { + scrollBarFocus = 0; + } + else + { + int difference = curMouse.Y - scrollBarFocusMouseStart; + if (scrollBarFocus == 1) + { + scrollBar.ViewPosition = scrollBarFocusPositionStart + (float)difference / boxHeight; + } + else if (scrollBarFocus == 2) + { + scrollBar2.ViewPosition = scrollBarFocusPositionStart + (float)difference / box2Height; + } + } + } + else if (MouseClicked) + { + if (curMouse.X > boxPos.X && curMouse.X < boxPos.X + boxWidth && curMouse.Y > boxPos.Y - 3f && curMouse.Y < boxPos.Y + boxHeight + 4f) + { + scrollBarFocus = 1; + scrollBarFocusMouseStart = curMouse.Y; + scrollBarFocusPositionStart = scrollBar.ViewPosition; + } + else if (curMouse.X > box2Pos.X && curMouse.X < box2Pos.X + boxWidth && curMouse.Y > box2Pos.Y - 3f && curMouse.Y < box2Pos.Y + box2Height + 4f) + { + scrollBarFocus = 2; + scrollBarFocusMouseStart = curMouse.Y; + scrollBarFocusPositionStart = scrollBar2.ViewPosition; + } + } + if (scrollBarFocus == 0) + { + int difference = oldMouse.ScrollWheelValue / 250 - curMouse.ScrollWheelValue / 250; + scrollBar.ViewPosition += difference; + } + } + + private static void UpdateCraftButton() + { + Rectangle dim = InterfaceHelper.GetFullRectangle(craftButton); + bool flag = false; + if (curMouse.X > dim.X && curMouse.X < dim.X + dim.Width && curMouse.Y > dim.Y && curMouse.Y < dim.Y + dim.Height) + { + craftButton.BackgroundColor = new Color(73, 94, 171); + if (curMouse.LeftButton == ButtonState.Pressed) + { + if (selectedRecipe != null && IsAvailable(selectedRecipe) && PassesBlock(selectedRecipe)) + { + if (craftTimer <= 0) + { + craftTimer = maxCraftTimer; + maxCraftTimer = maxCraftTimer * 3 / 4; + if (maxCraftTimer <= 0) + { + maxCraftTimer = 1; + } + TryCraft(); + if (Main.netMode == NetmodeID.SinglePlayer) + { + RefreshItems(); + } + Main.PlaySound(SoundID.Grab); + } + craftTimer--; + flag = true; + } + } + } + else + { + craftButton.BackgroundColor = new Color(63, 82, 151) * 0.7f; + } + if (selectedRecipe == null || !IsAvailable(selectedRecipe) || !PassesBlock(selectedRecipe)) + { + craftButton.BackgroundColor = new Color(30, 40, 100) * 0.7f; + } + if (!flag) + { + craftTimer = 0; + maxCraftTimer = startMaxCraftTimer; + } + } + + private static TEStorageHeart GetHeart() + { + Player player = Main.player[Main.myPlayer]; + StoragePlayer modPlayer = player.GetModPlayer(); + return modPlayer.GetStorageHeart(); + } + + private static TECraftingAccess GetCraftingEntity() + { + Player player = Main.player[Main.myPlayer]; + StoragePlayer modPlayer = player.GetModPlayer(); + return modPlayer.GetCraftingAccess(); + } + + private static List GetCraftingStations() + { + TECraftingAccess ent = GetCraftingEntity(); + return ent == null ? new List() : ent.stations; + } + + public static void RefreshItems() + { + SortMode sortMode; + FilterMode filterMode; + + lock (itemsLock) + { + items.Clear(); + TEStorageHeart heart = GetHeart(); + if (heart == null) + { + return; + } + items.AddRange(ItemSorter.SortAndFilter(heart.GetStoredItems(), SortMode.Id, FilterMode.All, "", "")); + AnalyzeIngredients(); + InitLangStuff(); + InitSortButtons(); + InitRecipeButtons(); + InitFilterButtons(); + switch (sortButtons.Choice) + { + case 0: + sortMode = SortMode.Default; + break; + case 1: + sortMode = SortMode.Id; + break; + case 2: + sortMode = SortMode.Name; + break; + default: + sortMode = SortMode.Default; + break; + } + switch (filterButtons.Choice) + { + case 0: + filterMode = FilterMode.All; + break; + case 1: + filterMode = FilterMode.Weapons; + break; + case 2: + filterMode = FilterMode.Tools; + break; + case 3: + filterMode = FilterMode.Equipment; + break; + case 4: + filterMode = FilterMode.Potions; + break; + case 5: + filterMode = FilterMode.Placeables; + break; + case 6: + filterMode = FilterMode.Misc; + break; + default: + filterMode = FilterMode.All; + break; + } + RefreshStorageItems(); + } + + lock (threadLock) + { + threadNeedsRestart = true; + threadSortMode = sortMode; + threadFilterMode = filterMode; + if (!threadRunning) + { + threadRunning = true; + Thread thread = new Thread(RefreshRecipes); + thread.Start(); + } + } + } + + private static void RefreshRecipes() + { + while (true) + { + try + { + SortMode sortMode; + FilterMode filterMode; + lock (threadLock) + { + threadNeedsRestart = false; + sortMode = threadSortMode; + filterMode = threadFilterMode; + } + var temp = ItemSorter.GetRecipes(sortMode, filterMode, searchBar2.Text, searchBar.Text); + threadRecipes.Clear(); + threadRecipeAvailable.Clear(); + try + { + if (recipeButtons.Choice == 0) + { + threadRecipes.AddRange(temp.Where(recipe => IsAvailable(recipe))); + threadRecipeAvailable.AddRange(threadRecipes.Select(recipe => true)); + } + else + { + threadRecipes.AddRange(temp); + threadRecipeAvailable.AddRange(threadRecipes.Select(recipe => IsAvailable(recipe))); + } + } + catch (InvalidOperationException) + { + } + catch (KeyNotFoundException) + { + } + + lock (recipeLock) + { + nextRecipes = new List(); + nextRecipeAvailable = new List(); + nextRecipes.AddRange(threadRecipes); + nextRecipeAvailable.AddRange(threadRecipeAvailable); + + } + lock (threadLock) + { + if (!threadNeedsRestart) + { + threadRunning = false; + return; + } + } + } + catch (Exception e) { Main.NewTextMultiline(e.ToString()); } + } + } + + private static void AnalyzeIngredients() + { + Player player = Main.player[Main.myPlayer]; + + lock (itemsLock) + { + itemCounts.Clear(); + if (adjTiles.Length != player.adjTile.Length) + { + Array.Resize(ref adjTiles, player.adjTile.Length); + } + for (int k = 0; k < adjTiles.Length; k++) + { + adjTiles[k] = false; + } + adjWater = false; + adjLava = false; + adjHoney = false; + zoneSnow = false; + alchemyTable = false; + + foreach (Item item in items) + { + if (itemCounts.ContainsKey(item.netID)) + { + itemCounts[item.netID] += item.stack; + } + else + { + itemCounts[item.netID] = item.stack; + } + } + } + + foreach (Item item in GetCraftingStations()) + { + if (item.createTile >= 0) + { + adjTiles[item.createTile] = true; + if (item.createTile == TileID.GlassKiln || item.createTile == TileID.Hellforge || item.createTile == TileID.AdamantiteForge) + { + adjTiles[TileID.Furnaces] = true; + } + if (item.createTile == TileID.AdamantiteForge) + { + adjTiles[TileID.Hellforge] = true; + } + if (item.createTile == TileID.MythrilAnvil) + { + adjTiles[TileID.Anvils] = true; + } + if (item.createTile == TileID.BewitchingTable || item.createTile == TileID.Tables2) + { + adjTiles[TileID.Tables] = true; + } + if (item.createTile == TileID.AlchemyTable) + { + adjTiles[TileID.Bottles] = true; + adjTiles[TileID.Tables] = true; + alchemyTable = true; + } + bool[] oldAdjTile = player.adjTile; + bool oldAdjWater = adjWater; + bool oldAdjLava = adjLava; + bool oldAdjHoney = adjHoney; + bool oldAlchemyTable = alchemyTable; + player.adjTile = adjTiles; + player.adjWater = false; + player.adjLava = false; + player.adjHoney = false; + player.alchemyTable = false; + TileLoader.AdjTiles(player, item.createTile); + if (player.adjWater) + { + adjWater = true; + } + if (player.adjLava) + { + adjLava = true; + } + if (player.adjHoney) + { + adjHoney = true; + } + if (player.alchemyTable) + { + alchemyTable = true; + } + player.adjTile = oldAdjTile; + player.adjWater = oldAdjWater; + player.adjLava = oldAdjLava; + player.adjHoney = oldAdjHoney; + player.alchemyTable = oldAlchemyTable; + } + if (item.type == ItemID.WaterBucket || item.type == ItemID.BottomlessBucket) + { + adjWater = true; + } + if (item.type == ItemID.LavaBucket) + { + adjLava = true; + } + if (item.type == ItemID.HoneyBucket) + { + adjHoney = true; + } + if (item.type == MagicStorage.Instance.ItemType("SnowBiomeEmulator")) + { + zoneSnow = true; + } + } + adjTiles[MagicStorage.Instance.TileType("CraftingAccess")] = true; + } + + private static bool IsAvailable(Recipe recipe) + { + foreach (int tile in recipe.requiredTile) + { + if (tile == -1) + { + break; + } + if (!adjTiles[tile]) + { + return false; + } + } + + lock (itemsLock) + { + foreach (Item ingredient in recipe.requiredItem) + { + if (ingredient.type == 0) + { + break; + } + int stack = ingredient.stack; + bool useRecipeGroup = false; + foreach (int type in itemCounts.Keys) + { + if (RecipeGroupMatch(recipe, type, ingredient.type)) + { + stack -= itemCounts[type]; + useRecipeGroup = true; + } + } + if (!useRecipeGroup && itemCounts.ContainsKey(ingredient.netID)) + { + stack -= itemCounts[ingredient.netID]; + } + if (stack > 0) + { + return false; + } + } + } + + if (recipe.needWater && !adjWater && !adjTiles[TileID.Sinks]) + { + return false; + } + if (recipe.needLava && !adjLava) + { + return false; + } + if (recipe.needHoney && !adjHoney) + { + return false; + } + if (recipe.needSnowBiome && !zoneSnow) + { + return false; + } + try + { + BlockRecipes.active = false; + if (!RecipeHooks.RecipeAvailable(recipe)) + { + return false; + } + } + finally + { + BlockRecipes.active = true; + } + return true; + } + + private static bool PassesBlock(Recipe recipe) + { + foreach (Item ingredient in recipe.requiredItem) + { + if (ingredient.type == 0) + { + break; + } + int stack = ingredient.stack; + bool useRecipeGroup = false; + foreach (Item item in storageItems) + { + ItemData data = new ItemData(item); + if (!blockStorageItems.Contains(data) && RecipeGroupMatch(recipe, item.netID, ingredient.type)) + { + stack -= item.stack; + useRecipeGroup = true; + } + } + if (!useRecipeGroup) + { + foreach (Item item in storageItems) + { + ItemData data = new ItemData(item); + if (!blockStorageItems.Contains(data) && item.netID == ingredient.netID) + { + stack -= item.stack; + } + } + } + if (stack > 0) + { + return false; + } + } + return true; + } + + private static void RefreshStorageItems() + { + storageItems.Clear(); + result = null; + if (selectedRecipe != null) + { + foreach (Item item in items) + { + for (int k = 0; k < selectedRecipe.requiredItem.Length; k++) + { + if (selectedRecipe.requiredItem[k].type == 0) + { + break; + } + if (item.type == selectedRecipe.requiredItem[k].type || RecipeGroupMatch(selectedRecipe, selectedRecipe.requiredItem[k].type, item.type)) + { + storageItems.Add(item); + } + } + if (item.type == selectedRecipe.createItem.type) + { + result = item; + } + } + if (result == null) + { + result = new Item(); + result.SetDefaults(selectedRecipe.createItem.type); + result.stack = 0; + } + } + } + + private static bool RecipeGroupMatch(Recipe recipe, int type1, int type2) + { + return recipe.useWood(type1, type2) || recipe.useSand(type1, type2) || recipe.useIronBar(type1, type2) || recipe.useFragment(type1, type2) || recipe.AcceptedByItemGroups(type1, type2) || recipe.usePressurePlate(type1, type2); + } + + private static void HoverStation(int slot, ref int hoverSlot) + { + TECraftingAccess access = GetCraftingEntity(); + if (access == null || slot >= TECraftingAccess.ItemsTotal) + return; + + Player player = Main.LocalPlayer; + if (MouseClicked) + { + bool changed = false; + if (slot < access.stations.Count && ItemSlot.ShiftInUse) + { + access.TryWithdrawStation(slot, true); + changed = true; + } + else if (player.itemAnimation == 0 && player.itemTime == 0) + { + if (Main.mouseItem.IsAir) + { + if (!access.TryWithdrawStation(slot).IsAir) + { + changed = true; + } + } + else + { + int oldType = Main.mouseItem.type; + int oldStack = Main.mouseItem.stack; + Main.mouseItem = access.TryDepositStation(Main.mouseItem); + if (oldType != Main.mouseItem.type || oldStack != Main.mouseItem.stack) + changed = true; + } + } + + if (changed) + { + if (Main.netMode == NetmodeID.SinglePlayer) + { + RefreshItems(); + } + Main.PlaySound(SoundID.Grab); + } + } + + hoverSlot = slot; + } + + private static void HoverRecipe(int slot, ref int hoverSlot) + { + int visualSlot = slot; + slot += numColumns * (int)Math.Round(scrollBar.ViewPosition); + if (slot < recipes.Count) + { + if (MouseClicked) + { + selectedRecipe = recipes[slot]; + + lock (itemsLock) + { + RefreshStorageItems(); + } + + blockStorageItems.Clear(); + } + hoverSlot = visualSlot; + } + } + + private static void HoverItem(int slot, ref int hoverSlot) + { + hoverSlot = slot; + } + + private static void HoverStorage(int slot, ref int hoverSlot) + { + int visualSlot = slot; + slot += numColumns2 * (int)Math.Round(scrollBar2.ViewPosition); + if (slot < storageItems.Count) + { + if (MouseClicked) + { + ItemData data = new ItemData(storageItems[slot]); + if (blockStorageItems.Contains(data)) + { + blockStorageItems.Remove(data); + } + else + { + blockStorageItems.Add(data); + } + } + hoverSlot = visualSlot; + } + } + + private static void HoverResult(int slot, ref int hoverSlot) + { + if (slot != 0) + { + return; + } + + Player player = Main.player[Main.myPlayer]; + if (MouseClicked) + { + bool changed = false; + if (!Main.mouseItem.IsAir && player.itemAnimation == 0 && player.itemTime == 0 && result != null && Main.mouseItem.type == result.type) + { + if (TryDepositResult(Main.mouseItem)) + { + changed = true; + } + } + else if (Main.mouseItem.IsAir && result != null && !result.IsAir) + { + Item toWithdraw = result.Clone(); + if (toWithdraw.stack > toWithdraw.maxStack) + { + toWithdraw.stack = toWithdraw.maxStack; + } + Main.mouseItem = DoWithdrawResult(toWithdraw, ItemSlot.ShiftInUse); + if (ItemSlot.ShiftInUse) + { + Main.mouseItem = player.GetItem(Main.myPlayer, Main.mouseItem, false, true); + } + changed = true; + } + if (changed) + { + if (Main.netMode == NetmodeID.SinglePlayer) + { + RefreshItems(); + } + Main.PlaySound(SoundID.Grab); + } + } + + if (curMouse.RightButton == ButtonState.Pressed && oldMouse.RightButton == ButtonState.Released && result != null && !result.IsAir && (Main.mouseItem.IsAir || ItemData.Matches(Main.mouseItem, items[slot]) && Main.mouseItem.stack < Main.mouseItem.maxStack)) + { + slotFocus = true; + } + + hoverSlot = slot; + + if (slotFocus) + { + SlotFocusLogic(); + } + } + + private static void SlotFocusLogic() + { + if (result == null || result.IsAir || (!Main.mouseItem.IsAir && (!ItemData.Matches(Main.mouseItem, result) || Main.mouseItem.stack >= Main.mouseItem.maxStack))) + { + ResetSlotFocus(); + } + else + { + if (rightClickTimer <= 0) + { + rightClickTimer = maxRightClickTimer; + maxRightClickTimer = maxRightClickTimer * 3 / 4; + if (maxRightClickTimer <= 0) + { + maxRightClickTimer = 1; + } + Item toWithdraw = result.Clone(); + toWithdraw.stack = 1; + Item withdrawn = DoWithdrawResult(toWithdraw); + if (Main.mouseItem.IsAir) + { + Main.mouseItem = withdrawn; + } + else + { + Main.mouseItem.stack += withdrawn.stack; + } + Main.soundInstanceMenuTick.Stop(); + Main.soundInstanceMenuTick = Main.soundMenuTick.CreateInstance(); + Main.PlaySound(SoundID.MenuTick); + RefreshItems(); + } + rightClickTimer--; + } + } + + private static void ResetSlotFocus() + { + slotFocus = false; + rightClickTimer = 0; + maxRightClickTimer = startMaxRightClickTimer; + } + + private static void TryCraft() + { + List toWithdraw; + List availableItems = new List(storageItems.Where(item => !blockStorageItems.Contains(new ItemData(item))).Select(item => item.Clone())); + toWithdraw = new List(); + for (int k = 0; k < selectedRecipe.requiredItem.Length; k++) + { + Item item = selectedRecipe.requiredItem[k]; + if (item.type == 0) + { + break; + } + int stack = item.stack; + ModRecipe modRecipe = selectedRecipe as ModRecipe; + if (modRecipe != null) + { + stack = modRecipe.ConsumeItem(item.type, item.stack); + } + if (selectedRecipe.alchemy && alchemyTable) + { + int save = 0; + for (int j = 0; j < stack; j++) + { + if (Main.rand.Next(3) == 0) + { + save++; + } + } + stack -= save; + } + if (stack > 0) + { + foreach (Item tryItem in availableItems) + { + if (item.type == tryItem.type || RecipeGroupMatch(selectedRecipe, item.type, tryItem.type)) + { + if (tryItem.stack > stack) + { + Item temp = tryItem.Clone(); + temp.stack = stack; + toWithdraw.Add(temp); + tryItem.stack -= stack; + stack = 0; + } + else + { + toWithdraw.Add(tryItem.Clone()); + stack -= tryItem.stack; + tryItem.stack = 0; + tryItem.type = ItemID.None; + } + } + } + } + } + + Item resultItem = selectedRecipe.createItem.Clone(); + resultItem.Prefix(-1); + var resultItems = new List { resultItem }; + + RecipeHooks.OnCraft(resultItem, selectedRecipe); + ItemLoader.OnCraft(resultItem, selectedRecipe); + + if (Main.netMode == NetmodeID.SinglePlayer) + { + foreach (Item item in DoCraft(GetHeart(), toWithdraw, resultItems)) + { + Main.player[Main.myPlayer].QuickSpawnClonedItem(item, item.stack); + } + } + else if (Main.netMode == NetmodeID.MultiplayerClient) + { + NetHelper.SendCraftRequest(GetHeart().ID, toWithdraw, resultItems); + } + } + + internal static List DoCraft(TEStorageHeart heart, List toWithdraw, List results) + { + var items = new List(); + foreach (Item tryWithdraw in toWithdraw) + { + Item withdrawn = heart.TryWithdraw(tryWithdraw, false); + if (!withdrawn.IsAir) + items.Add(withdrawn); + if (withdrawn.stack < tryWithdraw.stack) + { + for (int k = 0; k < items.Count; k++) + { + heart.DepositItem(items[k]); + if (items[k].IsAir) + { + items.RemoveAt(k); + k--; + } + } + + return items; + } + } + + items.Clear(); + foreach (Item result in results) + { + heart.DepositItem(result); + if (!result.IsAir) + items.Add(result); + } + + return items; + } + + private static bool TryDepositResult(Item item) + { + int oldStack = item.stack; + TEStorageHeart heart = GetHeart(); + heart.TryDeposit(item); + return oldStack != item.stack; + } + + private static Item DoWithdrawResult(Item item, bool toInventory = false) + { + TEStorageHeart heart = GetHeart(); + return heart.TryWithdraw(item, false); + } + } } \ No newline at end of file diff --git a/Edits/Detours/Vanilla.NetMessage.cs b/Edits/Detours/Vanilla.NetMessage.cs index 548c80a2..31f0006c 100644 --- a/Edits/Detours/Vanilla.NetMessage.cs +++ b/Edits/Detours/Vanilla.NetMessage.cs @@ -14,154 +14,12 @@ internal static class Vanilla { internal static void NetMessage_SendData(On.Terraria.NetMessage.orig_SendData orig, int msgType, int remoteClient, int ignoreClient, NetworkText text, int number, float number2, float number3, float number4, int number5, int number6, int number7) { - //TileSection (10) doesn't set "networkSend" to true in TileEntity.Write, so this needs to be kept track of manually - //Keeping track of this simplifies the workaround code somewhat - EditsLoader.MessageTileEntitySyncing = msgType == MessageID.TileSection; - orig(msgType, remoteClient, ignoreClient, text, number, number2, number3, number4, number5, number6, number7); - - EditsLoader.MessageTileEntitySyncing = false; - - //Catch any uses of IDs TileSection (10) and send the ModPacket message - //This is to circumvent the 65535 shorts' worth of data per-message limit and, hopefully, prevent world sections from suddenly disappearing for no reason - if (msgType == MessageID.TileSection) - { - ModPacket packet = MagicStorage.Instance.GetPacket(); - - //Get the entities in the section. Keep writing until the next entity written would make the size go over 65535 - int startX = number; - int startY = (int)number2; - short width = (short)number3; - short height = (short)number4; - - Queue ids = new Queue(); - - //Only process tile entities from Magic Storage - foreach (var item in TileEntity.ByPosition) { - Point16 pos = item.Key; - if (pos.X >= startX && pos.X < startX + width && pos.Y >= startY && pos.Y < startY + height) - if (ModTileEntity.GetTileEntity(item.Value.type)?.mod == MagicStorage.Instance) - ids.Enqueue(item.Value.ID); - } - - MemoryStream ms = new MemoryStream(); - MemoryStream ms2 = new MemoryStream(); - BinaryWriter msWriter = new BinaryWriter(ms); - BinaryWriter msWriter2 = new BinaryWriter(ms2); - int written = 0, total = 0, packetCount = 1; - - while(ids.Count > 0) - WriteNetWorkaround(msWriter, ms, msWriter2, ms2, ids, ref written, ref total, ref packetCount, ref packet, remoteClient, ignoreClient, lastSend: false); - - if(written > 0) - { - //Write the remaining information - WriteNetWorkaround(msWriter, ms, msWriter2, ms2, ids, ref written, ref total, ref packetCount, ref packet, remoteClient, ignoreClient, lastSend: true); - } - - /* - if (Main.netMode == NetmodeID.Server && total > 0) - Console.WriteLine($"Magic Storage: Wrote {packetCount} packets for {total} entities, {(packetCount - 1) * 65535 + ms.Position} bytes written"); - */ - - msWriter.Flush(); - msWriter.Close(); - msWriter.Dispose(); - - msWriter2.Flush(); - msWriter2.Close(); - msWriter2.Dispose(); - } - } - - private static void WriteNetWorkaround(BinaryWriter msWriter, MemoryStream ms, BinaryWriter msWriter2, MemoryStream ms2, Queue ids, ref int written, ref int total, ref int packetCount, ref ModPacket packet, int remoteClient, int ignoreClient, bool lastSend){ - long start = msWriter.BaseStream.Position, end = start; - - // TODO: why does the last entity in the packet have a bad ID??? also, fix the "read underflow" issues from the other packet types - - if (!lastSend) - { - //The last send won't be getting another tile, so just ignore this section - TileEntity.Write(msWriter2, TileEntity.ByID[ids.Dequeue()]); - written++; - total++; - - msWriter2.Flush(); - - end += msWriter2.BaseStream.Position; - } - - var newBytes = ms2.GetBuffer(); - - if (end > 65535 || (lastSend && written > 0)) - { - //Too much data for one net message - // TODO: handle when ONE entity sends too much data, since this assumes that at least 2 would have to be split up across messages - msWriter.Flush(); - - var bytes = ms.GetBuffer(); - - //Write the data before the "overflow" - //If this isn't the last packet, then the actual amount of entities written is "written - 1" - packet.Write((byte)MessageType.NetWorkaround); - packet.Write((ushort)(lastSend ? written : written - 1)); - packet.Write(bytes, 0, (int)start); - - packet.Send(remoteClient, ignoreClient); - - //Debugging purposes - /* - if (Main.netMode == NetmodeID.Server) - { - string path = Path.Combine(Main.SavePath, "MagicStorage Logging"); - Directory.CreateDirectory(path); - - path = Path.Combine(path, $"packet - {DateTime.Now.Ticks}t - {start}b.dat"); - - using (BinaryWriter fileWriter = new BinaryWriter(File.Open(path, FileMode.Create))) - fileWriter.Write(bytes, 0, (int)start); - } - - if (Main.netMode == NetmodeID.Server) - Console.WriteLine($" [written: {written}, total: {total}, packets: {packetCount}, length: {start}]"); - */ - - written = 0; - - if (!lastSend) - { - //Reset the packet - packet = MagicStorage.Instance.GetPacket(); - - packetCount++; - - //Reset the stream - ms.Position = 0; - ms.SetLength(0); - ms.Capacity = 0; - - //Still need to write data for one more entity - written = 1; - } - } - - if (!lastSend) - { - //Copy over the new bytes - msWriter.Write(newBytes, 0, (int)(end - start)); - - ms2.Position = 0; - ms2.SetLength(0); - ms2.Capacity = 0; - } } internal static void MessageBuffer_GetData(On.Terraria.MessageBuffer.orig_GetData orig, MessageBuffer self, int start, int length, out int messageType) { orig(self, start, length, out messageType); - - //Set to true in Mod.HijackGetData if the message ID is TileSection (10) - EditsLoader.MessageTileEntitySyncing = false; } } } diff --git a/Edits/EditsLoader.cs b/Edits/EditsLoader.cs index c4dff6bf..4cbb6db5 100644 --- a/Edits/EditsLoader.cs +++ b/Edits/EditsLoader.cs @@ -7,9 +7,7 @@ internal static class EditsLoader public static void Load() { - On.Terraria.NetMessage.SendData += Detours.Vanilla.NetMessage_SendData; - - On.Terraria.MessageBuffer.GetData += Detours.Vanilla.MessageBuffer_GetData; + // 1.4 have Recipe.FindRecipes += Vanilla.Recipe_FindRecipes; } } } diff --git a/Items/StorageDeactivator.cs b/Items/StorageDeactivator.cs index 6ff3285a..43544a7f 100644 --- a/Items/StorageDeactivator.cs +++ b/Items/StorageDeactivator.cs @@ -8,83 +8,87 @@ namespace MagicStorage.Items { - public class StorageDeactivator : ModItem - { - public override void SetStaticDefaults() - { - DisplayName.SetDefault("Storage Unit Wand"); - DisplayName.AddTranslation(GameCulture.Russian, "Жезл Ячейки Хранилища"); - DisplayName.AddTranslation(GameCulture.Polish, "Różdżka jednostki magazynującej"); - DisplayName.AddTranslation(GameCulture.French, "Baguette d'unité de stockage"); - DisplayName.AddTranslation(GameCulture.Spanish, "Varita de unidad de almacenamiento"); - DisplayName.AddTranslation(GameCulture.French, "Baguetter d'unité de stockage"); - DisplayName.AddTranslation(GameCulture.Chinese, "存储单元魔杖"); + public class StorageDeactivator : ModItem + { + public override void SetStaticDefaults() + { + DisplayName.SetDefault("Storage Unit Wand"); + DisplayName.AddTranslation(GameCulture.Russian, "Жезл Ячейки Хранилища"); + DisplayName.AddTranslation(GameCulture.Polish, "Różdżka jednostki magazynującej"); + DisplayName.AddTranslation(GameCulture.French, "Baguette d'unité de stockage"); + DisplayName.AddTranslation(GameCulture.Spanish, "Varita de unidad de almacenamiento"); + DisplayName.AddTranslation(GameCulture.French, "Baguetter d'unité de stockage"); + DisplayName.AddTranslation(GameCulture.Chinese, "存储单元魔杖"); - Tooltip.SetDefault(" Storage Unit to toggle between Active/Inactive"); - Tooltip.AddTranslation(GameCulture.Russian, " на Ячейке Хранилища что бы активировать/деактивировать ее"); - Tooltip.AddTranslation(GameCulture.Polish, " aby przełączyć Jednostkę Magazynującą (wł./wył.)"); - Tooltip.AddTranslation(GameCulture.French, " pour changer l'unité de stockage actif/inactif"); - Tooltip.AddTranslation(GameCulture.Spanish, " para cambiar el unidad de almacenamiento activo/inactivo"); - Tooltip.AddTranslation(GameCulture.Chinese, "存储单元使其切换启用/禁用"); - } + Tooltip.SetDefault(" Storage Unit to toggle between Active/Inactive"); + Tooltip.AddTranslation(GameCulture.Russian, " на Ячейке Хранилища что бы активировать/деактивировать ее"); + Tooltip.AddTranslation(GameCulture.Polish, " aby przełączyć Jednostkę Magazynującą (wł./wył.)"); + Tooltip.AddTranslation(GameCulture.French, " pour changer l'unité de stockage actif/inactif"); + Tooltip.AddTranslation(GameCulture.Spanish, " para cambiar el unidad de almacenamiento activo/inactivo"); + Tooltip.AddTranslation(GameCulture.Chinese, "存储单元使其切换启用/禁用"); + } - public override void SetDefaults() - { - item.width = 24; - item.height = 28; - item.useTurn = true; - item.autoReuse = true; - item.useAnimation = 15; - item.useTime = 15; - item.useStyle = 1; - item.tileBoost = 20; - item.rare = 1; - item.value = Item.sellPrice(0, 0, 40, 0); - } + public override void SetDefaults() + { + item.width = 24; + item.height = 28; + item.useTurn = true; + item.autoReuse = true; + item.useAnimation = 15; + item.useTime = 15; + item.useStyle = 1; + item.tileBoost = 20; + item.rare = 1; + item.value = Item.sellPrice(0, 0, 40, 0); + } - public override bool UseItem(Player player) - { - if (player.whoAmI == Main.myPlayer && player.itemAnimation > 0 && player.itemTime == 0 && player.controlUseItem) - { - int i = Player.tileTargetX; - int j = Player.tileTargetY; - if (Main.tile[i, j].frameX % 36 == 18) - { - i--; - } - if (Main.tile[i, j].frameY % 36 == 18) - { - j--; - } - Point16 point = new Point16(i, j); - if (TileEntity.ByPosition.ContainsKey(point) && TileEntity.ByPosition[point] is TEAbstractStorageUnit) - { - TEAbstractStorageUnit storageUnit = (TEAbstractStorageUnit)TileEntity.ByPosition[point]; - storageUnit.Inactive = !storageUnit.Inactive; - string activeText = storageUnit.Inactive ? "Deactivated" : "Activated"; - Main.NewText("Storage Unit has been " + activeText); - NetHelper.ClientSendTEUpdate(storageUnit.ID); - if (storageUnit is TEStorageUnit) - { - ((TEStorageUnit)storageUnit).UpdateTileFrameWithNetSend(); - if (Main.netMode == 0) - { - storageUnit.GetHeart().ResetCompactStage(); - } - } - } - } - return true; - } + public override bool UseItem(Player player) + { + if (player.whoAmI == Main.myPlayer && player.itemAnimation > 0 && player.itemTime == 0 && player.controlUseItem) + { + int i = Player.tileTargetX; + int j = Player.tileTargetY; + if (Main.tile[i, j].frameX % 36 == 18) + { + i--; + } + if (Main.tile[i, j].frameY % 36 == 18) + { + j--; + } + Point16 point = new Point16(i, j); + if (TileEntity.ByPosition.ContainsKey(point) && TileEntity.ByPosition[point] is TEAbstractStorageUnit) + { + TEAbstractStorageUnit storage = (TEAbstractStorageUnit)TileEntity.ByPosition[point]; + storage.Inactive = !storage.Inactive; + string activeText = storage.Inactive ? "Deactivated" : "Activated"; + Main.NewText("Storage Unit has been " + activeText); + if (storage is TEStorageUnit) + { + TEStorageUnit storageUnit = (TEStorageUnit)storage; + if (Main.netMode == NetmodeID.MultiplayerClient) + { + NetHelper.ClientSendDeactivate(storageUnit.ID, storageUnit.Inactive); + } + else + { + storageUnit.UpdateTileFrameWithNetSend(); + storageUnit.GetHeart().ResetCompactStage(); + } + } + } + } + return true; + } - public override void AddRecipes() - { - ModRecipe recipe = new ModRecipe(mod); - recipe.AddIngredient(ItemID.ActuationRod); - recipe.AddIngredient(null, "StorageComponent"); - recipe.AddTile(TileID.Anvils); - recipe.SetResult(this); - recipe.AddRecipe(); - } - } + public override void AddRecipes() + { + ModRecipe recipe = new ModRecipe(mod); + recipe.AddIngredient(ItemID.ActuationRod); + recipe.AddIngredient(null, "StorageComponent"); + recipe.AddTile(TileID.Anvils); + recipe.SetResult(this); + recipe.AddRecipe(); + } + } } diff --git a/MagicStorage.csproj b/MagicStorage.csproj index 07c44503..cab16c60 100644 --- a/MagicStorage.csproj +++ b/MagicStorage.csproj @@ -1,16 +1,16 @@ - - - MagicStorage - net45 - x86 - 7.3 - - - - - - - + + + MagicStorage + net45 + x86 + 7.3 + + + + + + + \ No newline at end of file diff --git a/NetHelper.cs b/NetHelper.cs index 546a73e5..a4ff1036 100644 --- a/NetHelper.cs +++ b/NetHelper.cs @@ -11,689 +11,526 @@ namespace MagicStorage { - public static class NetHelper - { - private static bool queueUpdates = false; - private static Queue updateQueue = new Queue(); - private static HashSet updateQueueContains = new HashSet(); - - public static void HandlePacket(BinaryReader reader, int sender) - { - MessageType type = (MessageType)reader.ReadByte(); - - /* - if (Main.netMode == NetmodeID.MultiplayerClient) - Main.NewText($"Receiving Message Type \"{Enum.GetName(typeof(MessageType), type)}\""); - else if(Main.netMode == NetmodeID.Server) - Console.WriteLine($"Receiving Message Type \"{Enum.GetName(typeof(MessageType), type)}\""); - */ - - if (type == MessageType.SearchAndRefreshNetwork) - { - ReceiveSearchAndRefresh(reader); - } - else if (type == MessageType.TryStorageOperation) - { - ReceiveStorageOperation(reader, sender); - } - else if (type == MessageType.StorageOperationResult) - { - ReceiveOperationResult(reader); - } - else if (type == MessageType.RefreshNetworkItems) - { - ReceiveRefreshNetworkItems(reader); - } - else if (type == MessageType.ClientSendTEUpdate) - { - ReceiveClientSendTEUpdate(reader, sender); - } - else if (type == MessageType.TryStationOperation) - { - ReceiveStationOperation(reader, sender); - } - else if (type == MessageType.StationOperationResult) - { - ReceiveStationResult(reader); - } - else if (type == MessageType.ResetCompactStage) - { - ReceiveResetCompactStage(reader); - } - else if (type == MessageType.CraftRequest) - { - ReceiveCraftRequest(reader, sender); - } - else if (type == MessageType.CraftResult) - { - ReceiveCraftResult(reader); - } - else if (type == MessageType.NetWorkaround) - { - ReceiveNetWorkaround(reader); - } - } - - public static void SendComponentPlace(int i, int j, int type) - { - if (Main.netMode == 1) - { - NetMessage.SendTileRange(Main.myPlayer, i, j, 2, 2); - NetMessage.SendData(MessageID.TileEntityPlacement, -1, -1, null, i, j, type); - } - } - - public static void StartUpdateQueue() - { - queueUpdates = true; - } - - public static void SendTEUpdate(int id, Point16 position) - { - if (Main.netMode != 2) - { - return; - } - if (queueUpdates) - { - if (!updateQueueContains.Contains(id)) - { - updateQueue.Enqueue(id); - updateQueueContains.Add(id); - } - } - else - { - NetMessage.SendData(MessageID.TileEntitySharing, -1, -1, null, id, position.X, position.Y); - } - } - - public static void ProcessUpdateQueue() - { - if (queueUpdates) - { - queueUpdates = false; - while (updateQueue.Count > 0) - { - NetMessage.SendData(MessageID.TileEntitySharing, -1, -1, null, updateQueue.Dequeue()); - } - updateQueueContains.Clear(); - } - } - - public static void SendSearchAndRefresh(int i, int j) - { - if (Main.netMode == 1) - { - ModPacket packet = MagicStorage.Instance.GetPacket(); - packet.Write((byte)MessageType.SearchAndRefreshNetwork); - packet.Write((short)i); - packet.Write((short)j); - packet.Send(); - } - } - - private static void ReceiveSearchAndRefresh(BinaryReader reader) - { - Point16 point = new Point16(reader.ReadInt16(), reader.ReadInt16()); - TEStorageComponent.SearchAndRefreshNetwork(point); - } - - private static ModPacket PrepareStorageOperation(int ent, byte op) - { - ModPacket packet = MagicStorage.Instance.GetPacket(); - packet.Write((byte)MessageType.TryStorageOperation); - packet.Write(ent); - packet.Write(op); - return packet; - } - - private static ModPacket PrepareOperationResult(byte op) - { - ModPacket packet = MagicStorage.Instance.GetPacket(); - packet.Write((byte)MessageType.StorageOperationResult); - packet.Write(op); - return packet; - } - - public static void SendDeposit(int ent, Item item) - { - if (Main.netMode == 1) - { - ModPacket packet = PrepareStorageOperation(ent, 0); - ItemIO.Send(item, packet, true); - packet.Send(); - } - } - - public static void SendWithdraw(int ent, Item item, bool toInventory = false) - { - if (Main.netMode == 1) - { - ModPacket packet = PrepareStorageOperation(ent, (byte)(toInventory ? 3 : 1)); - ItemIO.Send(item, packet, true); - packet.Send(); - } - } - - public static void SendDepositAll(int ent, List items) - { - if (Main.netMode == 1) - { - ModPacket packet = PrepareStorageOperation(ent, 2); - packet.Write((byte)items.Count); - foreach (Item item in items) - { - ItemIO.Send(item, packet, true); - } - packet.Send(); - } - } - - public static void ReceiveStorageOperation(BinaryReader reader, int sender) - { - int ent = reader.ReadInt32(); - byte op = reader.ReadByte(); - - /* - if (Main.netMode == NetmodeID.Server) - Console.WriteLine($"Receiving Storage Operation {op} from entity {ent}"); - else - Main.NewText($"Receiving Storage Operation {op} from entity {ent}"); - */ - - if (Main.netMode != 2) - { - //The data still needs to be read for exceptions to not be thrown... - if (op == 0 || op == 1 || op == 3) - { - ItemIO.Receive(reader, true); - } - else if (op == 3) - { - int count = reader.ReadByte(); - for (int i = 0; i < count; i++) - ItemIO.Receive(reader, true); - } - - return; - } - if (!TileEntity.ByID.ContainsKey(ent) || !(TileEntity.ByID[ent] is TEStorageHeart)) - { - return; - } - TEStorageHeart heart = (TEStorageHeart)TileEntity.ByID[ent]; - if (op == 0) - { - Item item = ItemIO.Receive(reader, true); - heart.DepositItem(item); - if (!item.IsAir) - { - ModPacket packet = PrepareOperationResult(op); - ItemIO.Send(item, packet, true); - packet.Send(sender); - } - } - else if (op == 1 || op == 3) - { - Item item = ItemIO.Receive(reader, true); - item = heart.TryWithdraw(item); - if (!item.IsAir) - { - ModPacket packet = PrepareOperationResult(op); - ItemIO.Send(item, packet, true); - packet.Send(sender); - } - } - else if (op == 2) - { - int count = reader.ReadByte(); - List items = new List(); - StartUpdateQueue(); - for (int k = 0; k < count; k++) - { - Item item = ItemIO.Receive(reader, true); - heart.DepositItem(item); - if (!item.IsAir) - { - items.Add(item); - } - } - ProcessUpdateQueue(); - if (items.Count > 0) - { - ModPacket packet = PrepareOperationResult(op); - packet.Write((byte)items.Count); - foreach (Item item in items) - { - ItemIO.Send(item, packet, true); - } - packet.Send(sender); - } - } - SendRefreshNetworkItems(ent); - } - - public static void ReceiveOperationResult(BinaryReader reader) - { - byte op = reader.ReadByte(); - - /* - if (Main.netMode == NetmodeID.Server) - Console.WriteLine($"Receiving Operation Result {op}"); - else - Main.NewText($"Receiving Operation Result {op}"); - */ - - if (Main.netMode != 1) - { - //The data still needs to be read for exceptions to not be thrown... - if (op == 0 || op == 1 || op == 3) - { - ItemIO.Receive(reader, true); - } - else if (op == 2) - { - int count = reader.ReadByte(); - for (int i = 0; i < count; i++) - ItemIO.Receive(reader, true); - } - - return; - } - if (op == 0 || op == 1 || op == 3) - { - Item item = ItemIO.Receive(reader, true); - - /* - Main.NewText($"Item Read: [type: {item.type}, prefix: {item.prefix}, stack: {item.stack}]"); - Main.NewText($"Reader Position: {reader.BaseStream.Position}"); - */ - - StoragePlayer.GetItem(item, op != 3); - } - else if (op == 2) - { - int count = reader.ReadByte(); - for (int k = 0; k < count; k++) - { - Item item = ItemIO.Receive(reader, true); - - /* - Main.NewText($"Item Read: [type: {item.type}, prefix: {item.prefix}, stack: {item.stack}]"); - Main.NewText($"Reader Position: {reader.BaseStream.Position}"); - */ - - StoragePlayer.GetItem(item, false); - } - } - } - - public static void SendRefreshNetworkItems(int ent) - { - if (Main.netMode == 2) - { - ModPacket packet = MagicStorage.Instance.GetPacket(); - packet.Write((byte)MessageType.RefreshNetworkItems); - packet.Write(ent); - packet.Send(); - } - } - - private static void ReceiveRefreshNetworkItems(BinaryReader reader) - { - int ent = reader.ReadInt32(); - if (Main.netMode == 2) - { - return; - } - - if (!TileEntity.ByID.TryGetValue(ent, out _)) - { - //Nothing would've happened anyway - return; - } - - StorageGUI.RefreshItems(); - } - - public static void ClientSendTEUpdate(int id) - { - if (Main.netMode == 1) - { - ModPacket packet = MagicStorage.Instance.GetPacket(); - packet.Write((byte)MessageType.ClientSendTEUpdate); - packet.Write(id); - TileEntity.Write(packet, TileEntity.ByID[id], true); - packet.Send(); - } - } - - public static void ReceiveClientSendTEUpdate(BinaryReader reader, int sender) - { - if (Main.netMode == 2) - { - int id = reader.ReadInt32(); - TileEntity ent = TileEntity.Read(reader, true); - ent.ID = id; - TileEntity.ByID[id] = ent; - TileEntity.ByPosition[ent.Position] = ent; - if (ent is TEStorageUnit) - { - TEStorageHeart heart = ((TEStorageUnit)ent).GetHeart(); - if (heart != null) - { - heart.ResetCompactStage(); - } - } - NetMessage.SendData(MessageID.TileEntitySharing, -1, sender, null, id, ent.Position.X, ent.Position.Y); - } - else if (Main.netMode == 1) - { - //Still need to read the data - reader.ReadInt32(); - } - } - - private static ModPacket PrepareStationOperation(int ent, byte op) - { - ModPacket packet = MagicStorage.Instance.GetPacket(); - packet.Write((byte)MessageType.TryStationOperation); - packet.Write(ent); - packet.Write(op); - return packet; - } - - private static ModPacket PrepareStationResult(byte op) - { - ModPacket packet = MagicStorage.Instance.GetPacket(); - packet.Write((byte)MessageType.StationOperationResult); - packet.Write(op); - return packet; - } - - public static void SendDepositStation(int ent, Item item) - { - if (Main.netMode == 1) - { - ModPacket packet = PrepareStationOperation(ent, 0); - ItemIO.Send(item, packet, true); - packet.Send(); - } - } - - public static void SendWithdrawStation(int ent, int slot) - { - if (Main.netMode == 1) - { - ModPacket packet = PrepareStationOperation(ent, 1); - packet.Write((byte)slot); - packet.Send(); - } - } - - public static void SendStationSlotClick(int ent, Item item, int slot) - { - if (Main.netMode == 1) - { - ModPacket packet = PrepareStationOperation(ent, 2); - ItemIO.Send(item, packet, true); - packet.Write((byte)slot); - packet.Send(); - } - } - - public static void ReceiveStationOperation(BinaryReader reader, int sender) - { - int ent = reader.ReadInt32(); - byte op = reader.ReadByte(); - if (Main.netMode != 2) - { - //Still need to read the data for exceptions to not be thrown... - if (op == 0) - { - ItemIO.Receive(reader, true); - } - else if(op == 1) - { - reader.ReadByte(); - } - else if(op == 2) - { - ItemIO.Receive(reader, true); - reader.ReadByte(); - } - return; - } - if (!TileEntity.ByID.ContainsKey(ent) || !(TileEntity.ByID[ent] is TECraftingAccess)) - { - return; - } - TECraftingAccess access = (TECraftingAccess)TileEntity.ByID[ent]; - Item[] stations = access.stations; - if (op == 0) - { - Item item = ItemIO.Receive(reader, true); - access.TryDepositStation(item); - if (item.stack > 0) - { - ModPacket packet = PrepareStationResult(op); - ItemIO.Send(item, packet, true); - packet.Send(sender); - } - } - else if (op == 1) - { - int slot = reader.ReadByte(); - Item item = access.TryWithdrawStation(slot); - if (!item.IsAir) - { - ModPacket packet = PrepareStationResult(op); - ItemIO.Send(item, packet, true); - packet.Send(sender); - } - } - else if (op == 2) - { - Item item = ItemIO.Receive(reader, true); - int slot = reader.ReadByte(); - item = access.DoStationSwap(item, slot); - if (!item.IsAir) - { - ModPacket packet = PrepareStationResult(op); - ItemIO.Send(item, packet, true); - packet.Send(sender); - } - } - Point16 pos = access.Position; - StorageAccess modTile = TileLoader.GetTile(Main.tile[pos.X, pos.Y].type) as StorageAccess; - if (modTile != null) - { - TEStorageHeart heart = modTile.GetHeart(pos.X, pos.Y); - if (heart != null) - { - SendRefreshNetworkItems(heart.ID); - } - } - } - - public static void ReceiveStationResult(BinaryReader reader) - { - //Still need to read the data for exceptions to not be thrown... - byte op = reader.ReadByte(); - Item item = ItemIO.Receive(reader, true); - if (Main.netMode != 1) - { - return; - } - Player player = Main.player[Main.myPlayer]; - if (op == 2 && Main.playerInventory && Main.mouseItem.IsAir) - { - Main.mouseItem = item; - item = new Item(); - } - else if (op == 2 && Main.playerInventory && Main.mouseItem.type == item.type) - { - int total = Main.mouseItem.stack + item.stack; - if (total > Main.mouseItem.maxStack) - { - total = Main.mouseItem.maxStack; - } - int difference = total - Main.mouseItem.stack; - Main.mouseItem.stack = total; - item.stack -= total; - } - if (item.stack > 0) - { - item = player.GetItem(Main.myPlayer, item, false, true); - if (!item.IsAir) - { - player.QuickSpawnClonedItem(item, item.stack); - } - } - } - - public static void SendResetCompactStage(int ent) - { - if (Main.netMode == 1) - { - ModPacket packet = MagicStorage.Instance.GetPacket(); - packet.Write((byte)MessageType.ResetCompactStage); - packet.Write(ent); - packet.Send(); - } - } - - public static void ReceiveResetCompactStage(BinaryReader reader) - { - if (Main.netMode == 2) - { - int ent = reader.ReadInt32(); - if (TileEntity.ByID[ent] is TEStorageHeart) - { - ((TEStorageHeart)TileEntity.ByID[ent]).ResetCompactStage(); - } - } - else if (Main.netMode == 1) - { - reader.ReadInt32(); - } - } - - public static void SendCraftRequest(int heart, List toWithdraw, Item result) - { - if (Main.netMode == 1) - { - ModPacket packet = MagicStorage.Instance.GetPacket(); - packet.Write((byte)MessageType.CraftRequest); - packet.Write(heart); - packet.Write(toWithdraw.Count); - foreach (Item item in toWithdraw) - { - ItemIO.Send(item, packet, true); - } - ItemIO.Send(result, packet, true); - packet.Send(); - } - } - - public static void ReceiveCraftRequest(BinaryReader reader, int sender) - { - int ent = reader.ReadInt32(); - int count = reader.ReadInt32(); - if (Main.netMode != 2) - { - //Still need to read the data for exceptions to not be thrown - for (int i = 0; i < count; i++) - ItemIO.Receive(reader, true); - - ItemIO.Receive(reader, true); - return; - } - if (!TileEntity.ByID.ContainsKey(ent) || !(TileEntity.ByID[ent] is TEStorageHeart)) - { - return; - } - TEStorageHeart heart = (TEStorageHeart)TileEntity.ByID[ent]; - List toWithdraw = new List(); - for (int k = 0; k < count; k++) - { - toWithdraw.Add(ItemIO.Receive(reader, true)); - } - Item result = ItemIO.Receive(reader, true); - List items = CraftingGUI.DoCraft(heart, toWithdraw, result); - if (items.Count > 0) - { - ModPacket packet = MagicStorage.Instance.GetPacket(); - packet.Write((byte)MessageType.CraftResult); - packet.Write(items.Count); - foreach (Item item in items) - { - ItemIO.Send(item, packet, true); - } - packet.Send(sender); - } - SendRefreshNetworkItems(ent); - } - - public static void ReceiveCraftResult(BinaryReader reader) - { - Player player = Main.player[Main.myPlayer]; - int count = reader.ReadInt32(); - for (int k = 0; k < count; k++) - { - Item item = ItemIO.Receive(reader, true); - player.QuickSpawnClonedItem(item, item.stack); - } - } - - public static void ReceiveNetWorkaround(BinaryReader reader) - { - EditsLoader.MessageTileEntitySyncing = false; - - int entityCount = reader.ReadUInt16(); - for (int i = 0; i < entityCount; i++) - { - /* - long entStart = reader.BaseStream.Position; - - if (Main.netMode == NetmodeID.MultiplayerClient) - { - byte type = reader.ReadByte(); - reader.BaseStream.Seek(-1, SeekOrigin.Current); - MagicStorage.Instance.Logger.Debug($"Reading entity data of type {type}"); - } - */ - - TileEntity.Read(reader); - - /* - if (Main.netMode == NetmodeID.MultiplayerClient) - MagicStorage.Instance.Logger.Debug($"Bytes read (#{i + 1}): {reader.BaseStream.Position - entStart} (total: {reader.BaseStream.Position})"); - */ - } - - /* - long end = reader.BaseStream.Position; - - if (Main.netMode == NetmodeID.MultiplayerClient && entityCount > 0) - MagicStorage.Instance.Logger.Debug($"Received netmessage workaround - {entityCount} entities read, {end} bytes read"); - */ - } - } - - enum MessageType : byte - { - SearchAndRefreshNetwork, - TryStorageOperation, - StorageOperationResult, - RefreshNetworkItems, - ClientSendTEUpdate, - TryStationOperation, - StationOperationResult, - ResetCompactStage, - CraftRequest, - CraftResult, - NetWorkaround - } + public static class NetHelper + { + private static bool queueUpdates = false; + private static Queue updateQueue = new Queue(); + private static HashSet updateQueueContains = new HashSet(); + + public static void HandlePacket(BinaryReader reader, int sender) + { + MessageType type = (MessageType)reader.ReadByte(); + + /* + if (Main.netMode == NetmodeID.MultiplayerClient) + Main.NewText($"Receiving Message Type \"{Enum.GetName(type)}\""); + else if(Main.netMode == NetmodeID.Server) + Console.WriteLine($"Receiving Message Type \"{Enum.GetName(type)}\""); + */ + + switch (type) + { + case MessageType.SearchAndRefreshNetwork: + ReceiveSearchAndRefresh(reader); + break; + case MessageType.ClinetStorageOperation: + ReciveClientStorageOperation(reader, sender); + break; + case MessageType.ServerStorageResult: + ReciveServerStorageResult(reader); + break; + case MessageType.RefreshNetworkItems: + ReceiveRefreshNetworkItems(reader); + break; + case MessageType.ClientSendTEUpdate: + ReceiveClientSendTEUpdate(reader, sender); + break; + case MessageType.ClientSendDeactivate: + ReceiveClientDeactivate(reader, sender); + break; + case MessageType.ClientStationOperation: + ReceiveClientStationOperation(reader, sender); + break; + case MessageType.ServerStationOperationResult: + ReceiveServerStationResult(reader); + break; + case MessageType.ResetCompactStage: + ReceiveResetCompactStage(reader); + break; + case MessageType.CraftRequest: + ReceiveCraftRequest(reader, sender); + break; + case MessageType.CraftResult: + ReceiveCraftResult(reader); + break; + case MessageType.SectionRequest: + ReceiveClientRequestSection(reader, sender); + break; + case MessageType.SyncStorageUnitToClinet: + ClientReciveStorageSync(reader); + break; + case MessageType.SyncStorageUnit: + ServerReciveSyncStorageUnit(reader, sender); + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + + public static void SyncStorageUnit(int storageUnitId) + { + if (Main.netMode == NetmodeID.MultiplayerClient) + { + ModPacket packet = MagicStorage.Instance.GetPacket(); + packet.Write((byte)MessageType.SyncStorageUnit); + packet.Write(storageUnitId); + packet.Send(); + } + } + + public static void ServerReciveSyncStorageUnit(BinaryReader reader, int remoteClient) + { + if (Main.netMode == NetmodeID.Server) + { + int storageUnitId = reader.ReadInt32(); + TileEntity tileEntity = TileEntity.ByID[storageUnitId]; + TEStorageUnit storageUnit = (TEStorageUnit)TileEntity.ByID[storageUnitId]; + storageUnit.FullySync(); + + using (MemoryStream packetStream = new MemoryStream(65536)) + using (BinaryWriter BWriter = new BinaryWriter(packetStream)) + { + TileEntity.Write(BWriter, tileEntity, true); + BWriter.Flush(); + + ModPacket packet = MagicStorage.Instance.GetPacket(); + packet.Write((byte)MessageType.SyncStorageUnitToClinet); + packet.Write(packetStream.GetBuffer(), 0, (int)packetStream.Length); + packet.Send(remoteClient); + } + } + } + + public static void SendComponentPlace(int i, int j, int type) + { + if (Main.netMode == 1) + { + NetMessage.SendTileRange(Main.myPlayer, i, j, 2, 2); + NetMessage.SendData(MessageID.TileEntityPlacement, -1, -1, null, i, j, type); + } + } + + public static void StartUpdateQueue() + { + queueUpdates = true; + } + + public static void SendTEUpdate(int id, Point16 position) + { + if (Main.netMode != 2) + { + return; + } + if (queueUpdates) + { + if (!updateQueueContains.Contains(id)) + { + updateQueue.Enqueue(id); + updateQueueContains.Add(id); + } + } + else + { + NetMessage.SendData(MessageID.TileEntitySharing, -1, -1, null, id, position.X, position.Y); + } + } + + public static void ProcessUpdateQueue() + { + if (queueUpdates) + { + queueUpdates = false; + while (updateQueue.Count > 0) + { + NetMessage.SendData(MessageID.TileEntitySharing, -1, -1, null, updateQueue.Dequeue()); + } + updateQueueContains.Clear(); + } + } + + public static void SendSearchAndRefresh(int i, int j) + { + if (Main.netMode == 1) + { + ModPacket packet = MagicStorage.Instance.GetPacket(); + packet.Write((byte)MessageType.SearchAndRefreshNetwork); + packet.Write((short)i); + packet.Write((short)j); + packet.Send(); + } + } + + private static void ReceiveSearchAndRefresh(BinaryReader reader) + { + Point16 point = new Point16(reader.ReadInt16(), reader.ReadInt16()); + TEStorageComponent.SearchAndRefreshNetwork(point); + } + + public static void ReciveClientStorageOperation(BinaryReader reader, int sender) + { + int ent = reader.ReadInt32(); + TEStorageHeart.Operation op = (TEStorageHeart.Operation)reader.ReadByte(); + + if (Main.netMode != NetmodeID.Server) + { + //The data still needs to be read for exceptions to not be thrown... + if (op == TEStorageHeart.Operation.Deposit) + { + _ = ItemIO.Receive(reader, true, true); + } + else if (op == TEStorageHeart.Operation.Withdraw || op == TEStorageHeart.Operation.WithdrawToInventory) + { + _ = reader.ReadBoolean(); + _ = ItemIO.Receive(reader, true, true); + } + else if (op == TEStorageHeart.Operation.DepositAll) + { + int count = reader.ReadByte(); + for (int i = 0; i < count; i++) + _ = ItemIO.Receive(reader, true, true); + } + + return; + } + + if (!TileEntity.ByID.TryGetValue(ent, out TileEntity te) || !(te is TEStorageHeart heart)) + return; + + heart.QClientOperation(reader, op, sender); + } + + public static void ReciveServerStorageResult(BinaryReader reader) + { + TEStorageHeart.Operation op = (TEStorageHeart.Operation)reader.ReadByte(); + + if (Main.netMode != NetmodeID.MultiplayerClient) + { + //The data still needs to be read for exceptions to not be thrown... + if (op == TEStorageHeart.Operation.Withdraw || op == TEStorageHeart.Operation.WithdrawToInventory || op == TEStorageHeart.Operation.Deposit) + { + _ = ItemIO.Receive(reader, true, true); + } + else if (op == TEStorageHeart.Operation.DepositAll) + { + int count = reader.ReadByte(); + for (int i = 0; i < count; i++) + _ = ItemIO.Receive(reader, true, true); + } + } + else if (op == TEStorageHeart.Operation.Withdraw || op == TEStorageHeart.Operation.WithdrawToInventory || op == TEStorageHeart.Operation.Deposit) + { + Item item = ItemIO.Receive(reader, true, true); + StoragePlayer.GetItem(item, op != TEStorageHeart.Operation.WithdrawToInventory); + } + else if (op == TEStorageHeart.Operation.DepositAll) + { + int count = reader.ReadInt32(); + for (int k = 0; k < count; k++) + { + Item item = ItemIO.Receive(reader, true, true); + StoragePlayer.GetItem(item, false); + } + } + } + + public static void SendRefreshNetworkItems(int ent) + { + if (Main.netMode == NetmodeID.Server) + { + ModPacket packet = MagicStorage.Instance.GetPacket(); + packet.Write((byte)MessageType.RefreshNetworkItems); + packet.Write(ent); + packet.Send(); + } + } + + private static void ReceiveRefreshNetworkItems(BinaryReader reader) + { + int ent = reader.ReadInt32(); + if (Main.netMode == NetmodeID.Server) + { + return; + } + + if (TileEntity.ByID.ContainsKey(ent)) + StorageGUI.RefreshItems(); + } + + public static void ClientSendDeactivate(int id, bool inActive) + { + if (Main.netMode == NetmodeID.MultiplayerClient) + { + ModPacket packet = MagicStorage.Instance.GetPacket(); + packet.Write((byte)MessageType.ClientSendDeactivate); + packet.Write(id); + packet.Write(inActive); + packet.Send(); + } + } + + public static void ReceiveClientDeactivate(BinaryReader reader, int sender) + { + if (Main.netMode == NetmodeID.Server) + { + int id = reader.ReadInt32(); + bool inActive = reader.ReadBoolean(); + TileEntity ent = TileEntity.ByID[id]; + if (ent is TEStorageUnit storageUnit) + { + storageUnit.Inactive = inActive; + storageUnit.UpdateTileFrameWithNetSend(); + TEStorageHeart heart = storageUnit.GetHeart(); + if (heart != null) + { + heart.ResetCompactStage(); + } + } + } + else if (Main.netMode == NetmodeID.MultiplayerClient) + { + //Still need to read the data + _ = reader.ReadInt32(); + // TODO does TileEntity need to be read? + //_ = TileEntity.Read(reader, true); + } + } + + public static void ClientSendTEUpdate(int id) + { + if (Main.netMode == 1) + { + ModPacket packet = MagicStorage.Instance.GetPacket(); + packet.Write((byte)MessageType.ClientSendTEUpdate); + packet.Write(id); + TileEntity.Write(packet, TileEntity.ByID[id], true); + packet.Send(); + } + } + + public static void ReceiveClientSendTEUpdate(BinaryReader reader, int sender) + { + if (Main.netMode == 2) + { + int id = reader.ReadInt32(); + TileEntity ent = TileEntity.Read(reader, true); + ent.ID = id; + TileEntity.ByID[id] = ent; + TileEntity.ByPosition[ent.Position] = ent; + if (ent is TEStorageUnit) + { + TEStorageHeart heart = ((TEStorageUnit)ent).GetHeart(); + if (heart != null) + { + heart.ResetCompactStage(); + } + } + NetMessage.SendData(MessageID.TileEntitySharing, -1, sender, null, id, ent.Position.X, ent.Position.Y); + } + else if (Main.netMode == 1) + { + //Still need to read the data + reader.ReadInt32(); + } + } + + + public static void ReceiveClientStationOperation(BinaryReader reader, int sender) + { + int ent = reader.ReadInt32(); + TECraftingAccess.Operation op = (TECraftingAccess.Operation)reader.ReadByte(); + + if (Main.netMode != NetmodeID.Server) + { + //The data still needs to be read for exceptions to not be thrown... + if (op == TECraftingAccess.Operation.Withdraw || op == TECraftingAccess.Operation.WithdrawToInventory) + { + _ = reader.ReadByte(); + } + else if (op == TECraftingAccess.Operation.Deposit) + { + _ = ItemIO.Receive(reader, true, true); + } + return; + } + + if (!TileEntity.ByID.TryGetValue(ent, out TileEntity te) || !(te is TECraftingAccess craftingAccess)) + return; + + craftingAccess.QClientOperation(reader, op, sender); + } + + public static void ReceiveServerStationResult(BinaryReader reader) + { + //Still need to read the data for exceptions to not be thrown... + TECraftingAccess.Operation op = (TECraftingAccess.Operation)reader.ReadByte(); + Item item = ItemIO.Receive(reader, true, true); + + if (Main.netMode == NetmodeID.MultiplayerClient) + { + if (op == TECraftingAccess.Operation.Withdraw || op == TECraftingAccess.Operation.WithdrawToInventory) + { + StoragePlayer.GetItem(item, op == TECraftingAccess.Operation.Withdraw); + } + else // deposit operation + { + Main.mouseItem = item; + } + } + } + + public static void SendResetCompactStage(int ent) + { + if (Main.netMode == 1) + { + ModPacket packet = MagicStorage.Instance.GetPacket(); + packet.Write((byte)MessageType.ResetCompactStage); + packet.Write(ent); + packet.Send(); + } + } + + public static void ReceiveResetCompactStage(BinaryReader reader) + { + if (Main.netMode == 2) + { + int ent = reader.ReadInt32(); + if (TileEntity.ByID[ent] is TEStorageHeart) + { + ((TEStorageHeart)TileEntity.ByID[ent]).ResetCompactStage(); + } + } + else if (Main.netMode == 1) + { + reader.ReadInt32(); + } + } + + public static void SendCraftRequest(int heart, List toWithdraw, List results) + { + if (Main.netMode == NetmodeID.MultiplayerClient) + { + ModPacket packet = MagicStorage.Instance.GetPacket(); + packet.Write((byte)MessageType.CraftRequest); + packet.Write(heart); + packet.Write(toWithdraw.Count); + foreach (Item item in toWithdraw) + ItemIO.Send(item, packet, true, true); + packet.Write(results.Count); + foreach (Item result in results) + ItemIO.Send(result, packet, true, true); + packet.Send(); + } + } + + public static void ReceiveCraftRequest(BinaryReader reader, int sender) + { + int ent = reader.ReadInt32(); + int withdrawCount = reader.ReadInt32(); + if (Main.netMode != NetmodeID.Server) + { + //Still need to read the data for exceptions to not be thrown + for (int i = 0; i < withdrawCount; i++) + _ = ItemIO.Receive(reader, true, true); + + + int count = reader.ReadInt32(); + for (int i = 0; i < count; i++) + _ = ItemIO.Receive(reader, true, true); + + return; + } + if (!TileEntity.ByID.ContainsKey(ent) || !(TileEntity.ByID[ent] is TEStorageHeart)) + { + return; + } + TEStorageHeart heart = (TEStorageHeart)TileEntity.ByID[ent]; + List toWithdraw = new List(); + for (int k = 0; k < withdrawCount; k++) + toWithdraw.Add(ItemIO.Receive(reader, true, true)); + + int resultsCount = reader.ReadInt32(); + List results = new List(); + for (int k = 0; k < resultsCount; k++) + results.Add(ItemIO.Receive(reader, true, true)); + + List items = CraftingGUI.DoCraft(heart, toWithdraw, results); + if (items.Count > 0) + { + ModPacket packet = MagicStorage.Instance.GetPacket(); + packet.Write((byte)MessageType.CraftResult); + packet.Write(items.Count); + foreach (Item item in items) + ItemIO.Send(item, packet, true, true); + packet.Send(sender); + } + + SendRefreshNetworkItems(ent); + } + + public static void ReceiveCraftResult(BinaryReader reader) + { + Player player = Main.player[Main.myPlayer]; + int count = reader.ReadInt32(); + for (int k = 0; k < count; k++) + { + Item item = ItemIO.Receive(reader, true); + player.QuickSpawnClonedItem(item, item.stack); + } + } + public static void ClientRequestSection(Point16 coords) + { + if (Main.netMode == NetmodeID.MultiplayerClient) + { + ModPacket packet = MagicStorage.Instance.GetPacket(); + packet.Write((byte)MessageType.SectionRequest); + + packet.Write(coords.X); + packet.Write(coords.Y); + + packet.Send(); + } + } + + public static void ReceiveClientRequestSection(BinaryReader reader, int sender) + { + if (Main.netMode == NetmodeID.Server) + { + Point16 coords = new Point16(reader.ReadInt16(), reader.ReadInt16()); + RemoteClient.CheckSection(sender, coords.ToWorldCoordinates()); + } + } + + public static void ClientReciveStorageSync(BinaryReader reader) + { + TileEntity.Read(reader, true); + } + } + + internal enum MessageType : byte + { + SearchAndRefreshNetwork, + ClinetStorageOperation, + ServerStorageResult, + RefreshNetworkItems, + ClientSendTEUpdate, + ClientSendDeactivate, + ClientStationOperation, + ServerStationOperationResult, + ResetCompactStage, + CraftRequest, + CraftResult, + SectionRequest, + SyncStorageUnitToClinet, + SyncStorageUnit + } } \ No newline at end of file diff --git a/Sorting/ItemSorter.cs b/Sorting/ItemSorter.cs index 0966acaa..776fac8a 100644 --- a/Sorting/ItemSorter.cs +++ b/Sorting/ItemSorter.cs @@ -2,143 +2,484 @@ using System.Collections.Generic; using System.Linq; using Terraria; +using Terraria.ID; +using System.Diagnostics; +using System.Reflection; namespace MagicStorage.Sorting { - public static class ItemSorter - { - public static IEnumerable SortAndFilter(IEnumerable items, SortMode sortMode, FilterMode filterMode, string modFilter, string nameFilter) - { - ItemFilter filter; - switch (filterMode) - { - case FilterMode.All: - filter = new FilterAll(); - break; - case FilterMode.Weapons: - filter = new FilterWeapon(); - break; - case FilterMode.Tools: - filter = new FilterTool(); - break; - case FilterMode.Equipment: - filter = new FilterEquipment(); - break; - case FilterMode.Potions: - filter = new FilterPotion(); - break; - case FilterMode.Placeables: - filter = new FilterPlaceable(); - break; - case FilterMode.Misc: - filter = new FilterMisc(); - break; - default: - filter = new FilterAll(); - break; - } - IEnumerable filteredItems = items.Where((item) => filter.Passes(item) && FilterName(item, modFilter, nameFilter)); - CompareFunction func; - switch (sortMode) - { - case SortMode.Default: - func = new CompareDefault(); - break; - case SortMode.Id: - func = new CompareID(); - break; - case SortMode.Name: - func = new CompareName(); - break; - case SortMode.Quantity: - func = new CompareID(); - break; - default: - return filteredItems; - } - BTree sortedTree = new BTree(func); - foreach (Item item in filteredItems) - { - sortedTree.Insert(item); - } - if (sortMode == SortMode.Quantity) - { - BTree oldTree = sortedTree; - sortedTree = new BTree(new CompareQuantity()); - foreach (Item item in oldTree.GetSortedItems()) - { - sortedTree.Insert(item); - } - } - return sortedTree.GetSortedItems(); - } - - public static IEnumerable GetRecipes(SortMode sortMode, FilterMode filterMode, string modFilter, string nameFilter) - { - ItemFilter filter; - switch (filterMode) - { - case FilterMode.All: - filter = new FilterAll(); - break; - case FilterMode.Weapons: - filter = new FilterWeapon(); - break; - case FilterMode.Tools: - filter = new FilterTool(); - break; - case FilterMode.Equipment: - filter = new FilterEquipment(); - break; - case FilterMode.Potions: - filter = new FilterPotion(); - break; - case FilterMode.Placeables: - filter = new FilterPlaceable(); - break; - case FilterMode.Misc: - filter = new FilterMisc(); - break; - default: - filter = new FilterAll(); - break; - } - IEnumerable filteredRecipes = Main.recipe.Where((recipe, index) => index < Recipe.numRecipes && filter.Passes(recipe) && FilterName(recipe.createItem, modFilter, nameFilter)); - CompareFunction func; - switch (sortMode) - { - case SortMode.Default: - func = new CompareDefault(); - break; - case SortMode.Id: - func = new CompareID(); - break; - case SortMode.Name: - func = new CompareName(); - break; - default: - return filteredRecipes; - } - BTree sortedTree = new BTree(func); - foreach (Recipe recipe in filteredRecipes) - { - sortedTree.Insert(recipe); - if (CraftingGUI.threadNeedsRestart) - { - return new List(); - } - } - return sortedTree.GetSortedItems(); - } - - private static bool FilterName(Item item, string modFilter, string filter) - { - string modName = "Terraria"; - if (item.modItem != null) - { - modName = item.modItem.mod.DisplayName; - } - return modName.ToLowerInvariant().IndexOf(modFilter.ToLowerInvariant()) >= 0 && item.Name.ToLowerInvariant().IndexOf(filter.ToLowerInvariant()) >= 0; - } - } + public static class ItemSorter + { + private enum itemType + { + Unknown, + MeleeWeapon, + RangedWeapon, + MagicWeapon, + SummonWeapon, + ThrownWeapon, + Weapon, + Ammo, + Picksaw, + Hamaxe, + Pickaxe, + Axe, + Hammer, + TerraformingTool, + AmmoTool, + Armor, + VanityArmor, + Accessory, + Grapple, + Mount, + Cart, + LightPet, + VanityPet, + Dye, + HairDye, + HealthPotion, + ManaPotion, + Elixir, + BuffPotion, + BossSpawn, + Painting, + Wiring, + Material, + Rope, + Extractible, + Misc, + FrameImportantTile, + CommonTile + } + + private static Dictionary> chcekType = new Dictionary>(); + + static ItemSorter() + { + foreach (int i in Enum.GetValues(typeof(itemType))) + { + if (i != (int)itemType.Unknown) + { + MethodInfo methodInfo = typeof(ItemSorter).GetMethod(Enum.GetName(typeof(itemType), i), BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new[] { typeof(Item) }, null); + Func delegateMethod = (Func)Delegate.CreateDelegate(typeof(Func), methodInfo); + chcekType.Add((itemType)i, delegateMethod); + } + } + } + + private static bool MeleeWeapon(Item item) + { + return item.maxStack == 1 && item.damage > 0 && item.ammo == 0 && item.melee && item.pick < 1 && item.hammer < 1 && item.axe < 1; + } + + private static bool RangedWeapon(Item item) + { + return item.maxStack == 1 && item.damage > 0 && item.ammo == 0 && item.ranged; + } + + private static bool MagicWeapon(Item item) + { + return item.maxStack == 1 && item.damage > 0 && item.ammo == 0 && item.magic; + } + + private static bool SummonWeapon(Item item) + { + return item.maxStack == 1 && item.damage > 0 && item.summon; + } + + private static bool ThrownWeapon(Item item) + { + return item.damage > 0 && (item.ammo == 0 || item.notAmmo) && item.shoot > 0 && item.thrown; + } + + private static bool Weapon(Item item) + { + return item.damage > 0 && item.ammo == 0 && item.pick == 0 && item.axe == 0 && item.hammer == 0; + } + + private static bool Ammo(Item item) + { + return item.ammo > 0 && item.damage > 0; + } + + private static bool Picksaw(Item item) + { + return item.pick > 0 && item.axe > 0; + } + + private static bool Hamaxe(Item item) + { + return item.hammer > 0 && item.axe > 0; + } + + private static bool Pickaxe(Item item) + { + return item.pick > 0; + } + + private static bool Axe(Item item) + { + return item.axe > 0; + } + + private static bool Hammer(Item item) + { + return item.hammer > 0; + } + + private static bool TerraformingTool(Item item) + { + return ItemID.Sets.SortingPriorityTerraforming[item.type] >= 0; + } + + private static bool AmmoTool(Item item) + { + return item.ammo > 0; + } + + private static bool Armor(Item item) + { + return (item.headSlot >= 0 || item.bodySlot >= 0 || item.legSlot >= 0) && !item.vanity; + } + + private static bool VanityArmor(Item item) + { + return (item.headSlot >= 0 || item.bodySlot >= 0 || item.legSlot >= 0) && item.vanity; + } + + private static bool Accessory(Item item) + { + return item.accessory; + } + + private static bool Grapple(Item item) + { + return Main.projHook[item.shoot]; + } + + private static bool Mount(Item item) + { + return item.mountType != -1 && !MountID.Sets.Cart[item.mountType]; + } + + private static bool Cart(Item item) + { + return item.mountType != -1 && MountID.Sets.Cart[item.mountType]; + } + + private static bool LightPet(Item item) + { + return item.buffType > 0 && Main.lightPet[item.buffType]; + } + + private static bool VanityPet(Item item) + { + return item.buffType > 0 && Main.vanityPet[item.buffType]; + } + + private static bool Dye(Item item) + { + return item.dye > 0; + } + + private static bool HairDye(Item item) + { + return item.hairDye >= 0; + } + + private static bool HealthPotion(Item item) + { + return item.consumable && item.healLife > 0 && item.healMana < 1; + } + + private static bool ManaPotion(Item item) + { + return item.consumable && item.healLife < 1 && item.healMana > 0; + } + + private static bool Elixir(Item item) + { + return item.consumable && item.healLife > 0 && item.healMana > 0; + } + + private static bool BuffPotion(Item item) + { + return item.consumable && item.buffType > 0; + } + + private static bool BossSpawn(Item item) + { + return ItemID.Sets.SortingPriorityBossSpawns[item.type] >= 0; + } + + private static bool Painting(Item item) + { + return ItemID.Sets.SortingPriorityPainting[item.type] >= 0 || item.paint > 0; + } + + private static bool Wiring(Item item) + { + return ItemID.Sets.SortingPriorityWiring[item.type] >= 0 || item.mech; + } + + private static bool Material(Item item) + { + return ItemID.Sets.SortingPriorityMaterials[item.type] >= 0; + } + + private static bool Rope(Item item) + { + return ItemID.Sets.SortingPriorityRopes[item.type] >= 0; + } + + private static bool Extractible(Item item) + { + return ItemID.Sets.SortingPriorityExtractibles[item.type] >= 0; + } + + private static bool Misc(Item item) + { + return item.createTile < 0 && item.createWall < 1; + } + + private static bool FrameImportantTile(Item item) + { + return item.createTile >= 0 && Main.tileFrameImportant[item.createTile]; + } + + private static bool CommonTile(Item item) + { + return item.createTile >= 0 || item.createWall > 0; + } + + private static itemType getItemType(Item item) + { + itemType result = itemType.Unknown; + + foreach (var kv in chcekType) + { + if (kv.Value(item)) + { + result = kv.Key; + break; + } + } + + return result; + } + + private static Stopwatch watch = Stopwatch.StartNew(); + public static IEnumerable SortAndFilter(IEnumerable items, SortMode sortMode, FilterMode filterMode, string modFilter, string nameFilter) + { + //long ticks = watch.ElapsedTicks; + ItemFilter filter; + switch (filterMode) + { + case FilterMode.All: + filter = new FilterAll(); + break; + case FilterMode.Weapons: + filter = new FilterWeapon(); + break; + case FilterMode.Tools: + filter = new FilterTool(); + break; + case FilterMode.Equipment: + filter = new FilterEquipment(); + break; + case FilterMode.Potions: + filter = new FilterPotion(); + break; + case FilterMode.Placeables: + filter = new FilterPlaceable(); + break; + case FilterMode.Misc: + filter = new FilterMisc(); + break; + default: + filter = new FilterAll(); + break; + } + + List filteredItems; + if (sortMode == SortMode.Default) + { + Dictionary> dic = new Dictionary>(); + foreach (itemType itemType in chcekType.Keys) + { + dic.Add(itemType, new SortedDictionary()); + } + dic.Add(itemType.Unknown, new SortedDictionary()); + foreach (Item item in items) + { + if (!item.IsAir && filter.Passes(item) && FilterName(item, modFilter, nameFilter)) + { + itemType iType = getItemType(item); + long hash = 1000 * item.type + item.prefix; + if (!dic[iType].ContainsKey(hash)) + { + dic[iType].Add(hash, item.Clone()); + } + else + { + dic[iType][hash].stack += item.stack; + } + } + } + + filteredItems = new List(); + foreach (var itemGroup in dic.Values) + { + foreach (Item item in itemGroup.Values) + { + filteredItems.Add(item); + } + } + } + else + { + Dictionary dic = new Dictionary(); + foreach (Item item in items) + { + if (!item.IsAir && filter.Passes(item) && FilterName(item, modFilter, nameFilter)) + { + long hash = 1000 * item.type + item.prefix; + if (!dic.ContainsKey(hash)) + { + dic.Add(hash, item.Clone()); + } + else + { + dic[hash].stack += item.stack; + } + } + } + + filteredItems = dic.Values.ToList(); + CompareFunction func; + switch (sortMode) + { + case SortMode.Id: + func = new CompareID(); + break; + case SortMode.Name: + func = new CompareName(); + break; + case SortMode.Quantity: + func = new CompareQuantity(); + break; + default: + return filteredItems; + } + filteredItems.Sort((i1, i2) => func.Compare(i1, i2)); + } + //Main.NewText($"Item Sorting took: {watch.ElapsedTicks - ticks} ticks, items count: {items.Count()}, filtered count: {filteredItems.Count()}"); + return filteredItems; + } + + public static IEnumerable GetRecipes(SortMode sortMode, FilterMode filterMode, string modFilter, string nameFilter) + { + //long ticks = watch.ElapsedTicks; + ItemFilter filter; + switch (filterMode) + { + case FilterMode.All: + filter = new FilterAll(); + break; + case FilterMode.Weapons: + filter = new FilterWeapon(); + break; + case FilterMode.Tools: + filter = new FilterTool(); + break; + case FilterMode.Equipment: + filter = new FilterEquipment(); + break; + case FilterMode.Potions: + filter = new FilterPotion(); + break; + case FilterMode.Placeables: + filter = new FilterPlaceable(); + break; + case FilterMode.Misc: + filter = new FilterMisc(); + break; + default: + filter = new FilterAll(); + break; + } + List filteredRecipes = new List(); + + if (sortMode == SortMode.Default) + { + Dictionary> dic = new Dictionary>(); + foreach (itemType itemType in chcekType.Keys) + { + dic.Add(itemType, new SortedDictionary()); + } + dic.Add(itemType.Unknown, new SortedDictionary()); + for (int i = 0; i < Main.recipe.Length; ++i) + { + Recipe recipe = Main.recipe[i]; + Item item = recipe.createItem; + if (!item.IsAir && filter.Passes(recipe) && FilterName(item, modFilter, nameFilter)) + { + itemType iType = getItemType(item); + long hash = 1000 * item.type + i; + dic[iType].Add(hash, recipe); + } + } + + filteredRecipes = new List(); + foreach (var recipeGroup in dic.Values) + { + foreach (Recipe recipe in recipeGroup.Values) + { + filteredRecipes.Add(recipe); + } + } + } + else + { + for (int i = 0; i < Main.recipe.Length; ++i) + { + Recipe recipe = Main.recipe[i]; + Item item = recipe.createItem; + if (!item.IsAir && filter.Passes(recipe) && FilterName(item, modFilter, nameFilter)) + { + filteredRecipes.Add(recipe); + } + } + + CompareFunction func; + switch (sortMode) + { + case SortMode.Id: + func = new CompareID(); + break; + case SortMode.Name: + func = new CompareName(); + break; + case SortMode.Quantity: + func = new CompareQuantity(); + break; + default: + return filteredRecipes; + } + filteredRecipes.Sort((i1, i2) => func.Compare(i1, i2)); + } + //Main.NewText($"Recipe Sorting took: {watch.ElapsedTicks - ticks} ticks, recipe count: {Main.recipe.Length}"); + return filteredRecipes; + } + + private static bool FilterName(Item item, string modFilter, string filter) + { + string modName = "Terraria"; + if (item.modItem != null) + { + modName = item.modItem.mod.DisplayName; + } + return modName.ToLowerInvariant().IndexOf(modFilter.ToLowerInvariant()) >= 0 && item.Name.ToLowerInvariant().IndexOf(filter.ToLowerInvariant()) >= 0; + } + } } diff --git a/StorageGUI.cs b/StorageGUI.cs index d1d74c31..0c8aaa22 100644 --- a/StorageGUI.cs +++ b/StorageGUI.cs @@ -11,546 +11,507 @@ using Terraria.UI; using MagicStorage.Components; using MagicStorage.Sorting; +using Terraria.ID; namespace MagicStorage { - public static class StorageGUI - { - private const int padding = 4; - private const int numColumns = 10; - public const float inventoryScale = 0.85f; - - public static MouseState curMouse; - public static MouseState oldMouse; - public static bool MouseClicked - { - get - { - return curMouse.LeftButton == ButtonState.Pressed && oldMouse.LeftButton == ButtonState.Released; - } - } - - private static UIPanel basePanel; - private static float panelTop; - private static float panelLeft; - private static float panelWidth; - private static float panelHeight; - - private static UIElement topBar; - internal static UISearchBar searchBar; - private static UIButtonChoice sortButtons; - internal static UITextPanel depositButton; - private static UIElement topBar2; - private static UIButtonChoice filterButtons; - internal static UISearchBar searchBar2; - - private static UISlotZone slotZone = new UISlotZone(HoverItemSlot, GetItem, inventoryScale); - private static int slotFocus = -1; - private static int rightClickTimer = 0; - private const int startMaxRightClickTimer = 20; - private static int maxRightClickTimer = startMaxRightClickTimer; - - internal static UIScrollbar scrollBar = new UIScrollbar(); - private static bool scrollBarFocus = false; - private static int scrollBarFocusMouseStart; - private static float scrollBarFocusPositionStart; - private static float scrollBarViewSize = 1f; - private static float scrollBarMaxViewSize = 2f; - - private static List items = new List(); - private static List didMatCheck = new List(); - private static int numRows; - private static int displayRows; - - private static UIElement bottomBar = new UIElement(); - private static UIText capacityText; - - public static void Initialize() - { - InitLangStuff(); - float itemSlotWidth = Main.inventoryBackTexture.Width * inventoryScale; - float itemSlotHeight = Main.inventoryBackTexture.Height * inventoryScale; - - panelTop = Main.instance.invBottom + 60; - panelLeft = 20f; - basePanel = new UIPanel(); - float innerPanelLeft = panelLeft + basePanel.PaddingLeft; - float innerPanelWidth = numColumns * (itemSlotWidth + padding) + 20f + padding; - panelWidth = basePanel.PaddingLeft + innerPanelWidth + basePanel.PaddingRight; - panelHeight = Main.screenHeight - panelTop - 40f; - basePanel.Left.Set(panelLeft, 0f); - basePanel.Top.Set(panelTop, 0f); - basePanel.Width.Set(panelWidth, 0f); - basePanel.Height.Set(panelHeight, 0f); - basePanel.Recalculate(); - - topBar = new UIElement(); - topBar.Width.Set(0f, 1f); - topBar.Height.Set(32f, 0f); - basePanel.Append(topBar); - - InitSortButtons(); - topBar.Append(sortButtons); - - depositButton.Left.Set(sortButtons.GetDimensions().Width + 2 * padding, 0f); - depositButton.Width.Set(128f, 0f); - depositButton.Height.Set(-2 * padding, 1f); - depositButton.PaddingTop = 8f; - depositButton.PaddingBottom = 8f; - topBar.Append(depositButton); - - float depositButtonRight = sortButtons.GetDimensions().Width + 2 * padding + depositButton.GetDimensions().Width; - searchBar.Left.Set(depositButtonRight + padding, 0f); - searchBar.Width.Set(-depositButtonRight - 2 * padding, 1f); - searchBar.Height.Set(0f, 1f); - topBar.Append(searchBar); - - topBar2 = new UIElement(); - topBar2.Width.Set(0f, 1f); - topBar2.Height.Set(32f, 0f); - topBar2.Top.Set(36f, 0f); - basePanel.Append(topBar2); - - InitFilterButtons(); - topBar2.Append(filterButtons); - searchBar2.Left.Set(depositButtonRight + padding, 0f); - searchBar2.Width.Set(-depositButtonRight - 2 * padding, 1f); - searchBar2.Height.Set(0f, 1f); - topBar2.Append(searchBar2); - - slotZone.Width.Set(0f, 1f); - slotZone.Top.Set(76f, 0f); - slotZone.Height.Set(-116f, 1f); - basePanel.Append(slotZone); - - numRows = (items.Count + numColumns - 1) / numColumns; - displayRows = (int)slotZone.GetDimensions().Height / ((int)itemSlotHeight + padding); - slotZone.SetDimensions(numColumns, displayRows); - int noDisplayRows = numRows - displayRows; - if (noDisplayRows < 0) - { - noDisplayRows = 0; - } - scrollBarMaxViewSize = 1 + noDisplayRows; - scrollBar.Height.Set(displayRows * (itemSlotHeight + padding), 0f); - scrollBar.Left.Set(-20f, 1f); - scrollBar.SetView(scrollBarViewSize, scrollBarMaxViewSize); - slotZone.Append(scrollBar); - - bottomBar.Width.Set(0f, 1f); - bottomBar.Height.Set(32f, 0f); - bottomBar.Top.Set(-32f, 1f); - basePanel.Append(bottomBar); - - capacityText.Left.Set(6f, 0f); - capacityText.Top.Set(6f, 0f); - TEStorageHeart heart = GetHeart(); - int numItems = 0; - int capacity = 0; - if (heart != null) - { - foreach (TEAbstractStorageUnit abstractStorageUnit in heart.GetStorageUnits()) - { - if (abstractStorageUnit is TEStorageUnit) - { - TEStorageUnit storageUnit = (TEStorageUnit)abstractStorageUnit; - numItems += storageUnit.NumItems; - capacity += storageUnit.Capacity; - } - } - } - capacityText.SetText(numItems + "/" + capacity + " Items"); - bottomBar.Append(capacityText); - } - - private static void InitLangStuff() - { - if (depositButton == null) - { - depositButton = new UITextPanel(Language.GetText("Mods.MagicStorage.DepositAll"), 1f); - } - if (searchBar == null) - { - searchBar = new UISearchBar(Language.GetText("Mods.MagicStorage.SearchName")); - } - if (searchBar2 == null) - { - searchBar2 = new UISearchBar(Language.GetText("Mods.MagicStorage.SearchMod")); - } - if (capacityText == null) - { - capacityText = new UIText("Items"); - } - } - - internal static void Unload() - { - sortButtons = null; - filterButtons = null; - } - - private static void InitSortButtons() - { - if (sortButtons == null) - { - sortButtons = new UIButtonChoice(new Texture2D[] - { - Main.inventorySortTexture[0], - MagicStorage.Instance.GetTexture("SortID"), - MagicStorage.Instance.GetTexture("SortName"), - MagicStorage.Instance.GetTexture("SortNumber") - }, - new LocalizedText[] - { - Language.GetText("Mods.MagicStorage.SortDefault"), - Language.GetText("Mods.MagicStorage.SortID"), - Language.GetText("Mods.MagicStorage.SortName"), - Language.GetText("Mods.MagicStorage.SortStack") - }); - } - } - - private static void InitFilterButtons() - { - if (filterButtons == null) - { - filterButtons = new UIButtonChoice(new Texture2D[] - { - MagicStorage.Instance.GetTexture("FilterAll"), - MagicStorage.Instance.GetTexture("FilterMelee"), - MagicStorage.Instance.GetTexture("FilterPickaxe"), - MagicStorage.Instance.GetTexture("FilterArmor"), - MagicStorage.Instance.GetTexture("FilterPotion"), - MagicStorage.Instance.GetTexture("FilterTile"), - MagicStorage.Instance.GetTexture("FilterMisc"), - }, - new LocalizedText[] - { - Language.GetText("Mods.MagicStorage.FilterAll"), - Language.GetText("Mods.MagicStorage.FilterWeapons"), - Language.GetText("Mods.MagicStorage.FilterTools"), - Language.GetText("Mods.MagicStorage.FilterEquips"), - Language.GetText("Mods.MagicStorage.FilterPotions"), - Language.GetText("Mods.MagicStorage.FilterTiles"), - Language.GetText("Mods.MagicStorage.FilterMisc") - }); - } - } - - public static void Update(GameTime gameTime) - { - oldMouse = curMouse; - curMouse = Mouse.GetState(); - if (Main.playerInventory && Main.player[Main.myPlayer].GetModPlayer().ViewingStorage().X >= 0 && !StoragePlayer.IsStorageCrafting()) - { - if (StorageGUI.curMouse.RightButton == ButtonState.Released) - { - ResetSlotFocus(); - } - if(basePanel != null) - basePanel.Update(gameTime); - UpdateScrollBar(); - UpdateDepositButton(); - } - else - { - scrollBarFocus = false; - scrollBar.ViewPosition = 0f; - ResetSlotFocus(); - } - } - - public static void Draw(TEStorageHeart heart) - { - Player player = Main.player[Main.myPlayer]; - StoragePlayer modPlayer = player.GetModPlayer(); - Initialize(); - if (Main.mouseX > panelLeft && Main.mouseX < panelLeft + panelWidth && Main.mouseY > panelTop && Main.mouseY < panelTop + panelHeight) - { - player.mouseInterface = true; - player.showItemIcon = false; - InterfaceHelper.HideItemIconCache(); - } - basePanel.Draw(Main.spriteBatch); - slotZone.DrawText(); - sortButtons.DrawText(); - filterButtons.DrawText(); - } - - private static Item GetItem(int slot, ref int context) - { - int index = slot + numColumns * (int)Math.Round(scrollBar.ViewPosition); - Item item = index < items.Count ? items[index] : new Item(); - if (!item.IsAir && !didMatCheck[index]) - { - item.checkMat(); - didMatCheck[index] = true; - } - return item; - } - - private static void UpdateScrollBar() - { - if (slotFocus >= 0) - { - scrollBarFocus = false; - return; - } - Rectangle dim = scrollBar.GetClippingRectangle(Main.spriteBatch); - Vector2 boxPos = new Vector2(dim.X, dim.Y + dim.Height * (scrollBar.ViewPosition / scrollBarMaxViewSize)); - float boxWidth = 20f * Main.UIScale; - float boxHeight = dim.Height * (scrollBarViewSize / scrollBarMaxViewSize); - if (scrollBarFocus) - { - if (curMouse.LeftButton == ButtonState.Released) - { - scrollBarFocus = false; - } - else - { - int difference = curMouse.Y - scrollBarFocusMouseStart; - scrollBar.ViewPosition = scrollBarFocusPositionStart + (float)difference / boxHeight; - } - } - else if (MouseClicked) - { - if (curMouse.X > boxPos.X && curMouse.X < boxPos.X + boxWidth && curMouse.Y > boxPos.Y - 3f && curMouse.Y < boxPos.Y + boxHeight + 4f) - { - scrollBarFocus = true; - scrollBarFocusMouseStart = curMouse.Y; - scrollBarFocusPositionStart = scrollBar.ViewPosition; - } - } - if (!scrollBarFocus) - { - int difference = oldMouse.ScrollWheelValue / 250 - curMouse.ScrollWheelValue / 250; - scrollBar.ViewPosition += difference; - } - } - - private static TEStorageHeart GetHeart() - { - Player player = Main.player[Main.myPlayer]; - StoragePlayer modPlayer = player.GetModPlayer(); - return modPlayer.GetStorageHeart(); - } - - public static void RefreshItems() - { - if (StoragePlayer.IsStorageCrafting()) - { - CraftingGUI.RefreshItems(); - return; - } - items.Clear(); - didMatCheck.Clear(); - TEStorageHeart heart = GetHeart(); - if (heart == null) - { - return; - } - InitLangStuff(); - InitSortButtons(); - InitFilterButtons(); - SortMode sortMode = (SortMode)sortButtons.Choice; - FilterMode filterMode = (FilterMode)filterButtons.Choice; - - items.AddRange(ItemSorter.SortAndFilter(heart.GetStoredItems(), sortMode, filterMode, searchBar2.Text, searchBar.Text)); - for (int k = 0; k < items.Count; k++) - { - didMatCheck.Add(false); - } - } - - private static void UpdateDepositButton() - { - Rectangle dim = InterfaceHelper.GetFullRectangle(depositButton); - if (curMouse.X > dim.X && curMouse.X < dim.X + dim.Width && curMouse.Y > dim.Y && curMouse.Y < dim.Y + dim.Height) - { - depositButton.BackgroundColor = new Color(73, 94, 171); - if (MouseClicked) - { - if (TryDepositAll()) - { - RefreshItems(); - Main.PlaySound(7, -1, -1, 1); - } - } - } - else - { - depositButton.BackgroundColor = new Color(63, 82, 151) * 0.7f; - } - } - - private static void ResetSlotFocus() - { - slotFocus = -1; - rightClickTimer = 0; - maxRightClickTimer = startMaxRightClickTimer; - } - - private static void HoverItemSlot(int slot, ref int hoverSlot) - { - Player player = Main.player[Main.myPlayer]; - int visualSlot = slot; - slot += numColumns * (int)Math.Round(scrollBar.ViewPosition); - if (MouseClicked) - { - bool changed = false; - if (!Main.mouseItem.IsAir && (player.itemAnimation == 0 && player.itemTime == 0)) - { - if (TryDeposit(Main.mouseItem)) - { - changed = true; - } - } - else if (Main.mouseItem.IsAir && slot < items.Count && !items[slot].IsAir) - { - Item toWithdraw = items[slot].Clone(); - if (toWithdraw.stack > toWithdraw.maxStack) - { - toWithdraw.stack = toWithdraw.maxStack; - } - Main.mouseItem = DoWithdraw(toWithdraw, ItemSlot.ShiftInUse); - if (ItemSlot.ShiftInUse) - { - Main.mouseItem = player.GetItem(Main.myPlayer, Main.mouseItem, false, true); - } - changed = true; - } - if (changed) - { - RefreshItems(); - Main.PlaySound(7, -1, -1, 1); - } - } - - if (curMouse.RightButton == ButtonState.Pressed && oldMouse.RightButton == ButtonState.Released && slot < items.Count && (Main.mouseItem.IsAir || ItemData.Matches(Main.mouseItem, items[slot]) && Main.mouseItem.stack < Main.mouseItem.maxStack)) - { - slotFocus = slot; - } - - if (slot < items.Count && !items[slot].IsAir) - { - hoverSlot = visualSlot; - } - - if (slotFocus >= 0) - { - SlotFocusLogic(); - } - } - - private static void SlotFocusLogic() - { - if (slotFocus >= items.Count || (!Main.mouseItem.IsAir && (!ItemData.Matches(Main.mouseItem, items[slotFocus]) || Main.mouseItem.stack >= Main.mouseItem.maxStack))) - { - ResetSlotFocus(); - } - else - { - if (rightClickTimer <= 0) - { - rightClickTimer = maxRightClickTimer; - maxRightClickTimer = maxRightClickTimer * 3 / 4; - if (maxRightClickTimer <= 0) - { - maxRightClickTimer = 1; - } - Item toWithdraw = items[slotFocus].Clone(); - toWithdraw.stack = 1; - Item result = DoWithdraw(toWithdraw); - if (Main.mouseItem.IsAir) - { - Main.mouseItem = result; - } - else - { - Main.mouseItem.stack += result.stack; - } - Main.soundInstanceMenuTick.Stop(); - Main.soundInstanceMenuTick = Main.soundMenuTick.CreateInstance(); - Main.PlaySound(12, -1, -1, 1); - RefreshItems(); - } - rightClickTimer--; - } - } - - private static bool TryDeposit(Item item) - { - int oldStack = item.stack; - DoDeposit(item); - return oldStack != item.stack; - } - - private static void DoDeposit(Item item) - { - TEStorageHeart heart = GetHeart(); - if (Main.netMode == 0) - { - heart.DepositItem(item); - } - else - { - NetHelper.SendDeposit(heart.ID, item); - item.SetDefaults(0, true); - } - } - - private static bool TryDepositAll() - { - Player player = Main.player[Main.myPlayer]; - TEStorageHeart heart = GetHeart(); - bool changed = false; - if (Main.netMode == 0) - { - for (int k = 10; k < 50; k++) - { - if (!player.inventory[k].IsAir && !player.inventory[k].favorited) - { - int oldStack = player.inventory[k].stack; - heart.DepositItem(player.inventory[k]); - if (oldStack != player.inventory[k].stack) - { - changed = true; - } - } - } - } - else - { - List items = new List(); - for (int k = 10; k < 50; k++) - { - if (!player.inventory[k].IsAir && !player.inventory[k].favorited) - { - items.Add(player.inventory[k]); - } - } - NetHelper.SendDepositAll(heart.ID, items); - foreach (Item item in items) - { - item.SetDefaults(0, true); - } - changed = true; - } - return changed; - } - - private static Item DoWithdraw(Item item, bool toInventory = false) - { - TEStorageHeart heart = GetHeart(); - if (Main.netMode == 0) - { - return heart.TryWithdraw(item); - } - else - { - NetHelper.SendWithdraw(heart.ID, item, toInventory); - return new Item(); - } - } - } + public static class StorageGUI + { + private const int padding = 4; + private const int numColumns = 10; + public const float inventoryScale = 0.85f; + + public static MouseState curMouse; + public static MouseState oldMouse; + public static bool MouseClicked + { + get + { + return curMouse.LeftButton == ButtonState.Pressed && oldMouse.LeftButton == ButtonState.Released; + } + } + + private static UIPanel basePanel; + private static float panelTop; + private static float panelLeft; + private static float panelWidth; + private static float panelHeight; + + private static UIElement topBar; + internal static UISearchBar searchBar; + private static UIButtonChoice sortButtons; + internal static UITextPanel depositButton; + private static UIElement topBar2; + private static UIButtonChoice filterButtons; + internal static UISearchBar searchBar2; + + private static UISlotZone slotZone = new UISlotZone(HoverItemSlot, GetItem, inventoryScale); + private static int slotFocus = -1; + private static int rightClickTimer = 0; + private const int startMaxRightClickTimer = 20; + private static int maxRightClickTimer = startMaxRightClickTimer; + + internal static UIScrollbar scrollBar = new UIScrollbar(); + private static bool scrollBarFocus = false; + private static int scrollBarFocusMouseStart; + private static float scrollBarFocusPositionStart; + private static float scrollBarViewSize = 1f; + private static float scrollBarMaxViewSize = 2f; + + private static List items = new List(); + private static List didMatCheck = new List(); + private static int numRows; + private static int displayRows; + + private static UIElement bottomBar = new UIElement(); + private static UIText capacityText; + + public static void Initialize() + { + InitLangStuff(); + float itemSlotWidth = Main.inventoryBackTexture.Width * inventoryScale; + float itemSlotHeight = Main.inventoryBackTexture.Height * inventoryScale; + + panelTop = Main.instance.invBottom + 60; + panelLeft = 20f; + basePanel = new UIPanel(); + float innerPanelLeft = panelLeft + basePanel.PaddingLeft; + float innerPanelWidth = numColumns * (itemSlotWidth + padding) + 20f + padding; + panelWidth = basePanel.PaddingLeft + innerPanelWidth + basePanel.PaddingRight; + panelHeight = Main.screenHeight - panelTop - 40f; + basePanel.Left.Set(panelLeft, 0f); + basePanel.Top.Set(panelTop, 0f); + basePanel.Width.Set(panelWidth, 0f); + basePanel.Height.Set(panelHeight, 0f); + basePanel.Recalculate(); + + topBar = new UIElement(); + topBar.Width.Set(0f, 1f); + topBar.Height.Set(32f, 0f); + basePanel.Append(topBar); + + InitSortButtons(); + topBar.Append(sortButtons); + + depositButton.Left.Set(sortButtons.GetDimensions().Width + 2 * padding, 0f); + depositButton.Width.Set(128f, 0f); + depositButton.Height.Set(-2 * padding, 1f); + depositButton.PaddingTop = 8f; + depositButton.PaddingBottom = 8f; + topBar.Append(depositButton); + + float depositButtonRight = sortButtons.GetDimensions().Width + 2 * padding + depositButton.GetDimensions().Width; + searchBar.Left.Set(depositButtonRight + padding, 0f); + searchBar.Width.Set(-depositButtonRight - 2 * padding, 1f); + searchBar.Height.Set(0f, 1f); + topBar.Append(searchBar); + + topBar2 = new UIElement(); + topBar2.Width.Set(0f, 1f); + topBar2.Height.Set(32f, 0f); + topBar2.Top.Set(36f, 0f); + basePanel.Append(topBar2); + + InitFilterButtons(); + topBar2.Append(filterButtons); + searchBar2.Left.Set(depositButtonRight + padding, 0f); + searchBar2.Width.Set(-depositButtonRight - 2 * padding, 1f); + searchBar2.Height.Set(0f, 1f); + topBar2.Append(searchBar2); + + slotZone.Width.Set(0f, 1f); + slotZone.Top.Set(76f, 0f); + slotZone.Height.Set(-116f, 1f); + basePanel.Append(slotZone); + + numRows = (items.Count + numColumns - 1) / numColumns; + displayRows = (int)slotZone.GetDimensions().Height / ((int)itemSlotHeight + padding); + slotZone.SetDimensions(numColumns, displayRows); + int noDisplayRows = numRows - displayRows; + if (noDisplayRows < 0) + { + noDisplayRows = 0; + } + scrollBarMaxViewSize = 1 + noDisplayRows; + scrollBar.Height.Set(displayRows * (itemSlotHeight + padding), 0f); + scrollBar.Left.Set(-20f, 1f); + scrollBar.SetView(scrollBarViewSize, scrollBarMaxViewSize); + slotZone.Append(scrollBar); + + bottomBar.Width.Set(0f, 1f); + bottomBar.Height.Set(32f, 0f); + bottomBar.Top.Set(-32f, 1f); + basePanel.Append(bottomBar); + + capacityText.Left.Set(6f, 0f); + capacityText.Top.Set(6f, 0f); + TEStorageHeart heart = GetHeart(); + int numItems = 0; + int capacity = 0; + if (heart != null) + { + foreach (TEAbstractStorageUnit abstractStorageUnit in heart.GetStorageUnits()) + { + if (abstractStorageUnit is TEStorageUnit) + { + TEStorageUnit storageUnit = (TEStorageUnit)abstractStorageUnit; + numItems += storageUnit.NumItems; + capacity += storageUnit.Capacity; + } + } + } + capacityText.SetText(numItems + "/" + capacity + " Items"); + bottomBar.Append(capacityText); + } + + private static void InitLangStuff() + { + if (depositButton == null) + { + depositButton = new UITextPanel(Language.GetText("Mods.MagicStorage.DepositAll"), 1f); + } + if (searchBar == null) + { + searchBar = new UISearchBar(Language.GetText("Mods.MagicStorage.SearchName")); + } + if (searchBar2 == null) + { + searchBar2 = new UISearchBar(Language.GetText("Mods.MagicStorage.SearchMod")); + } + if (capacityText == null) + { + capacityText = new UIText("Items"); + } + } + + internal static void Unload() + { + sortButtons = null; + filterButtons = null; + } + + private static void InitSortButtons() + { + if (sortButtons == null) + { + sortButtons = new UIButtonChoice(new Texture2D[] + { + Main.inventorySortTexture[0], + MagicStorage.Instance.GetTexture("SortID"), + MagicStorage.Instance.GetTexture("SortName"), + MagicStorage.Instance.GetTexture("SortNumber") + }, + new LocalizedText[] + { + Language.GetText("Mods.MagicStorage.SortDefault"), + Language.GetText("Mods.MagicStorage.SortID"), + Language.GetText("Mods.MagicStorage.SortName"), + Language.GetText("Mods.MagicStorage.SortStack") + }); + } + } + + private static void InitFilterButtons() + { + if (filterButtons == null) + { + filterButtons = new UIButtonChoice(new Texture2D[] + { + MagicStorage.Instance.GetTexture("FilterAll"), + MagicStorage.Instance.GetTexture("FilterMelee"), + MagicStorage.Instance.GetTexture("FilterPickaxe"), + MagicStorage.Instance.GetTexture("FilterArmor"), + MagicStorage.Instance.GetTexture("FilterPotion"), + MagicStorage.Instance.GetTexture("FilterTile"), + MagicStorage.Instance.GetTexture("FilterMisc"), + }, + new LocalizedText[] + { + Language.GetText("Mods.MagicStorage.FilterAll"), + Language.GetText("Mods.MagicStorage.FilterWeapons"), + Language.GetText("Mods.MagicStorage.FilterTools"), + Language.GetText("Mods.MagicStorage.FilterEquips"), + Language.GetText("Mods.MagicStorage.FilterPotions"), + Language.GetText("Mods.MagicStorage.FilterTiles"), + Language.GetText("Mods.MagicStorage.FilterMisc") + }); + } + } + + public static void Update(GameTime gameTime) + { + oldMouse = curMouse; + curMouse = Mouse.GetState(); + if (Main.playerInventory && Main.player[Main.myPlayer].GetModPlayer().ViewingStorage().X >= 0 && !StoragePlayer.IsStorageCrafting()) + { + if (StorageGUI.curMouse.RightButton == ButtonState.Released) + { + ResetSlotFocus(); + } + if (basePanel != null) + basePanel.Update(gameTime); + UpdateScrollBar(); + UpdateDepositButton(); + } + else + { + scrollBarFocus = false; + scrollBar.ViewPosition = 0f; + ResetSlotFocus(); + } + } + + public static void Draw(TEStorageHeart heart) + { + Player player = Main.player[Main.myPlayer]; + StoragePlayer modPlayer = player.GetModPlayer(); + Initialize(); + if (Main.mouseX > panelLeft && Main.mouseX < panelLeft + panelWidth && Main.mouseY > panelTop && Main.mouseY < panelTop + panelHeight) + { + player.mouseInterface = true; + player.showItemIcon = false; + InterfaceHelper.HideItemIconCache(); + } + basePanel.Draw(Main.spriteBatch); + slotZone.DrawText(); + sortButtons.DrawText(); + filterButtons.DrawText(); + } + + private static Item GetItem(int slot, ref int context) + { + int index = slot + numColumns * (int)Math.Round(scrollBar.ViewPosition); + Item item = index < items.Count ? items[index] : new Item(); + if (!item.IsAir && !didMatCheck[index]) + { + item.checkMat(); + didMatCheck[index] = true; + } + return item; + } + + private static void UpdateScrollBar() + { + if (slotFocus >= 0) + { + scrollBarFocus = false; + return; + } + Rectangle dim = scrollBar.GetClippingRectangle(Main.spriteBatch); + Vector2 boxPos = new Vector2(dim.X, dim.Y + dim.Height * (scrollBar.ViewPosition / scrollBarMaxViewSize)); + float boxWidth = 20f * Main.UIScale; + float boxHeight = dim.Height * (scrollBarViewSize / scrollBarMaxViewSize); + if (scrollBarFocus) + { + if (curMouse.LeftButton == ButtonState.Released) + { + scrollBarFocus = false; + } + else + { + int difference = curMouse.Y - scrollBarFocusMouseStart; + scrollBar.ViewPosition = scrollBarFocusPositionStart + (float)difference / boxHeight; + } + } + else if (MouseClicked) + { + if (curMouse.X > boxPos.X && curMouse.X < boxPos.X + boxWidth && curMouse.Y > boxPos.Y - 3f && curMouse.Y < boxPos.Y + boxHeight + 4f) + { + scrollBarFocus = true; + scrollBarFocusMouseStart = curMouse.Y; + scrollBarFocusPositionStart = scrollBar.ViewPosition; + } + } + if (!scrollBarFocus) + { + int difference = oldMouse.ScrollWheelValue / 250 - curMouse.ScrollWheelValue / 250; + scrollBar.ViewPosition += difference; + } + } + + private static TEStorageHeart GetHeart() + { + Player player = Main.player[Main.myPlayer]; + StoragePlayer modPlayer = player.GetModPlayer(); + return modPlayer.GetStorageHeart(); + } + + public static void RefreshItems() + { + if (StoragePlayer.IsStorageCrafting()) + { + CraftingGUI.RefreshItems(); + return; + } + items.Clear(); + didMatCheck.Clear(); + TEStorageHeart heart = GetHeart(); + if (heart == null) + { + return; + } + InitLangStuff(); + InitSortButtons(); + InitFilterButtons(); + SortMode sortMode = (SortMode)sortButtons.Choice; + FilterMode filterMode = (FilterMode)filterButtons.Choice; + + items.AddRange(ItemSorter.SortAndFilter(heart.GetStoredItems(), sortMode, filterMode, searchBar2.Text, searchBar.Text)); + for (int k = 0; k < items.Count; k++) + { + didMatCheck.Add(false); + } + } + + private static void UpdateDepositButton() + { + Rectangle dim = InterfaceHelper.GetFullRectangle(depositButton); + if (curMouse.X > dim.X && curMouse.X < dim.X + dim.Width && curMouse.Y > dim.Y && curMouse.Y < dim.Y + dim.Height) + { + depositButton.BackgroundColor = new Color(73, 94, 171); + if (MouseClicked) + { + if (TryDepositAll()) + { + RefreshItems(); + Main.PlaySound(7, -1, -1, 1); + } + } + } + else + { + depositButton.BackgroundColor = new Color(63, 82, 151) * 0.7f; + } + } + + private static void ResetSlotFocus() + { + slotFocus = -1; + rightClickTimer = 0; + maxRightClickTimer = startMaxRightClickTimer; + } + + private static void HoverItemSlot(int slot, ref int hoverSlot) + { + Player player = Main.player[Main.myPlayer]; + int visualSlot = slot; + slot += numColumns * (int)Math.Round(scrollBar.ViewPosition); + if (MouseClicked) + { + bool changed = false; + if (!Main.mouseItem.IsAir && (player.itemAnimation == 0 && player.itemTime == 0)) + { + if (TryDeposit(Main.mouseItem)) + { + changed = true; + } + } + else if (Main.mouseItem.IsAir && slot < items.Count && !items[slot].IsAir) + { + Item toWithdraw = items[slot].Clone(); + if (toWithdraw.stack > toWithdraw.maxStack) + { + toWithdraw.stack = toWithdraw.maxStack; + } + Main.mouseItem = DoWithdraw(toWithdraw, ItemSlot.ShiftInUse); + if (ItemSlot.ShiftInUse) + { + Main.mouseItem = player.GetItem(Main.myPlayer, Main.mouseItem, false, true); + } + changed = true; + } + if (changed) + { + if (Main.netMode == NetmodeID.SinglePlayer) + { + RefreshItems(); + } + Main.PlaySound(7, -1, -1, 1); + } + } + + if (curMouse.RightButton == ButtonState.Pressed && oldMouse.RightButton == ButtonState.Released && slot < items.Count && (Main.mouseItem.IsAir || ItemData.Matches(Main.mouseItem, items[slot]) && Main.mouseItem.stack < Main.mouseItem.maxStack)) + { + slotFocus = slot; + } + + if (slot < items.Count && !items[slot].IsAir) + { + hoverSlot = visualSlot; + } + + if (slotFocus >= 0) + { + SlotFocusLogic(); + } + } + + private static void SlotFocusLogic() + { + if (slotFocus >= items.Count || (!Main.mouseItem.IsAir && (!ItemData.Matches(Main.mouseItem, items[slotFocus]) || Main.mouseItem.stack >= Main.mouseItem.maxStack))) + { + ResetSlotFocus(); + } + else + { + if (rightClickTimer <= 0) + { + rightClickTimer = maxRightClickTimer; + maxRightClickTimer = maxRightClickTimer * 3 / 4; + if (maxRightClickTimer <= 0) + { + maxRightClickTimer = 1; + } + Item toWithdraw = items[slotFocus].Clone(); + toWithdraw.stack = 1; + Item result = DoWithdraw(toWithdraw); + if (Main.mouseItem.IsAir) + { + Main.mouseItem = result; + } + else + { + Main.mouseItem.stack += result.stack; + } + Main.soundInstanceMenuTick.Stop(); + Main.soundInstanceMenuTick = Main.soundMenuTick.CreateInstance(); + Main.PlaySound(12, -1, -1, 1); + RefreshItems(); + } + rightClickTimer--; + } + } + + private static bool TryDeposit(Item item) + { + int oldStack = item.stack; + TEStorageHeart heart = GetHeart(); + heart.TryDeposit(item); + return oldStack != item.stack; + } + + private static bool TryDepositAll(bool quickStack = false) + { + Player player = Main.LocalPlayer; + TEStorageHeart heart = GetHeart(); + + bool filter(Item item) => !item.IsAir && !item.favorited && (!quickStack || heart.HasItem(item, true)); + int inventorySize = player.inventory.Length; + var items = new List(); + for (int k = 10; k < inventorySize; k++) + { + Item item = player.inventory[k]; + if (filter(item)) + items.Add(item); + } + + return heart.TryDeposit(items); + } + + private static Item DoWithdraw(Item item, bool toInventory = false, bool keepOneIfFavorite = false) + { + TEStorageHeart heart = GetHeart(); + return heart.TryWithdraw(item, keepOneIfFavorite, toInventory); + } + } } \ No newline at end of file diff --git a/StoragePlayer.cs b/StoragePlayer.cs index 23c37d23..b5dbe892 100644 --- a/StoragePlayer.cs +++ b/StoragePlayer.cs @@ -114,6 +114,18 @@ public static void GetItem(Item item, bool toMouse) if (!item.IsAir) { item = player.GetItem(Main.myPlayer, item, false, true); + if (!item.IsAir && Main.mouseItem.IsAir) + { + Main.mouseItem = item; + item = new Item(); + } + + if (!item.IsAir && Main.mouseItem.type == item.type && Main.mouseItem.stack < Main.mouseItem.maxStack) + { + Main.mouseItem.stack += item.stack; + item = new Item(); + } + if (!item.IsAir) { player.QuickSpawnClonedItem(item, item.stack); @@ -140,27 +152,11 @@ public override bool ShiftClickSlot(Item[] inventory, int context, int slot) int oldStack = item.stack; if (StorageCrafting()) { - if (Main.netMode == 0) - { - GetCraftingAccess().TryDepositStation(item); - } - else - { - NetHelper.SendDepositStation(GetCraftingAccess().ID, item); - item.SetDefaults(0, true); - } + GetCraftingAccess().TryDepositStation(item); } else { - if (Main.netMode == 0) - { - GetStorageHeart().DepositItem(item); - } - else - { - NetHelper.SendDeposit(GetStorageHeart().ID, item); - item.SetDefaults(0, true); - } + GetStorageHeart().TryDeposit(item); } if (item.type != oldType || item.stack != oldStack) { diff --git a/UISlotZone.cs b/UISlotZone.cs index e6da1a4c..0b0f01de 100644 --- a/UISlotZone.cs +++ b/UISlotZone.cs @@ -9,89 +9,100 @@ namespace MagicStorage { - public class UISlotZone : UIElement - { - public delegate void HoverItemSlot(int slot, ref int hoverSlot); - public delegate Item GetItem(int slot, ref int context); + public class UISlotZone : UIElement + { + public delegate Item GetItem(int slot, ref int context); - private const int padding = 4; - private int numColumns = 10; - private int numRows = 4; - private int hoverSlot = -1; - private HoverItemSlot onHover; - private GetItem getItem; - private float inventoryScale; + public delegate void HoverItemSlot(int slot, ref int hoverSlot); - private static Item[] temp = new Item[11]; + private const int Padding = 4; - public UISlotZone(HoverItemSlot onHover, GetItem getItem, float scale) - { - this.onHover = onHover; - this.getItem = getItem; - this.inventoryScale = scale; - } + private readonly GetItem getItem; + private readonly float inventoryScale; + private readonly HoverItemSlot onHover; + private int hoverSlot = -1; + private int numColumns = 10; + private int numRows = 4; + private int height; - public void SetDimensions(int columns, int rows) - { - this.numColumns = columns; - this.numRows = rows; - } + public UISlotZone(HoverItemSlot onHover, GetItem getItem, float scale) + { + this.onHover = onHover; + this.getItem = getItem; + inventoryScale = scale; + } - public override void Update(GameTime gameTime) - { - hoverSlot = -1; - Vector2 origin = InterfaceHelper.GetFullRectangle(this).TopLeft(); - MouseState curMouse = StorageGUI.curMouse; - if (curMouse.X <= origin.X || curMouse.Y <= origin.Y) - { - return; - } - int slotWidth = (int)(Main.inventoryBackTexture.Width * inventoryScale * Main.UIScale); - int slotHeight = (int)(Main.inventoryBackTexture.Height * inventoryScale * Main.UIScale); - int slotX = (curMouse.X - (int)origin.X) / (slotWidth + padding); - int slotY = (curMouse.Y - (int)origin.Y) / (slotHeight + padding); - if (slotX < 0 || slotX >= numColumns || slotY < 0 || slotY >= numRows) - { - return; - } - Vector2 slotPos = origin + new Vector2(slotX * (slotWidth + padding * Main.UIScale), slotY * (slotHeight + padding * Main.UIScale)); - if (curMouse.X > slotPos.X && curMouse.X < slotPos.X + slotWidth && curMouse.Y > slotPos.Y && curMouse.Y < slotPos.Y + slotHeight) - { - onHover(slotX + numColumns * slotY, ref hoverSlot); - } - } + public void SetDimensions(int columns, int rows) + { + numColumns = columns; + numRows = rows; + height = (int)(Main.inventoryBackTexture.Width * inventoryScale * Main.UIScale) * rows + Padding; + } - protected override void DrawSelf(SpriteBatch spriteBatch) - { - float slotWidth = Main.inventoryBackTexture.Width * inventoryScale; - float slotHeight = Main.inventoryBackTexture.Height * inventoryScale; - Vector2 origin = GetDimensions().Position(); - float oldScale = Main.inventoryScale; - Main.inventoryScale = inventoryScale; - Item[] temp = new Item[11]; - for (int k = 0; k < numColumns * numRows; k++) - { - int context = 0; - Item item = getItem(k, ref context); - Vector2 drawPos = origin + new Vector2((slotWidth + padding) * (k % numColumns), (slotHeight + padding) * (k / numColumns)); - temp[10] = item; - ItemSlot.Draw(Main.spriteBatch, temp, context, 10, drawPos); - } - Main.inventoryScale = oldScale; - } + public override void Update(GameTime gameTime) + { + hoverSlot = -1; + Vector2 origin = InterfaceHelper.GetFullRectangle(this).TopLeft(); + MouseState curMouse = StorageGUI.curMouse; + if (curMouse.X <= origin.X || curMouse.Y <= origin.Y) + { + return; + } + int slotWidth = (int)(Main.inventoryBackTexture.Width * inventoryScale * Main.UIScale); + int slotHeight = (int)(Main.inventoryBackTexture.Height * inventoryScale * Main.UIScale); + int slotX = (curMouse.X - (int)origin.X) / (slotWidth + Padding); + int slotY = (curMouse.Y - (int)origin.Y) / (slotHeight + Padding); + if (slotX < 0 || slotX >= numColumns || slotY < 0 || slotY >= numRows) + { + return; + } + Vector2 slotPos = origin + new Vector2(slotX * (slotWidth + Padding * Main.UIScale), slotY * (slotHeight + Padding * Main.UIScale)); + if (curMouse.X > slotPos.X && curMouse.X < slotPos.X + slotWidth && curMouse.Y > slotPos.Y && curMouse.Y < slotPos.Y + slotHeight) + { + onHover(slotX + numColumns * slotY, ref hoverSlot); + } + } - public void DrawText() - { - if (hoverSlot >= 0) - { - int context = 0; - Item hoverItem = getItem(hoverSlot, ref context); - if (!hoverItem.IsAir) - { - Main.HoverItem = hoverItem.Clone(); - Main.instance.MouseText(string.Empty); - } - } - } - } + protected override void DrawSelf(SpriteBatch spriteBatch) + { + float slotWidth = Main.inventoryBackTexture.Width * inventoryScale; + float slotHeight = Main.inventoryBackTexture.Height * inventoryScale; + Vector2 origin = GetDimensions().Position(); + float oldScale = Main.inventoryScale; + Main.inventoryScale = inventoryScale; + Item[] temp = new Item[11]; + for (int k = 0; k < numColumns * numRows; k++) + { + int context = 0; + Item item = getItem(k, ref context); + int col = k % numColumns; + int row = k / numColumns; + float x = (slotWidth + Padding) * col; + float y = (slotHeight + Padding) * row; + Vector2 drawPos = origin + new Vector2(x, y); + temp[10] = item; + ItemSlot.Draw(Main.spriteBatch, temp, context, 10, drawPos); + } + Main.inventoryScale = oldScale; + } + + public void DrawText() + { + if (hoverSlot >= 0) + { + int context = 0; + Item hoverItem = getItem(hoverSlot, ref context); + if (!hoverItem.IsAir) + { + Main.HoverItem = hoverItem.Clone(); + Main.instance.MouseText(string.Empty); + } + } + } + + public int getHeight() + { + return height; + } + } } \ No newline at end of file diff --git a/build.txt b/build.txt index 8467174f..4b053f23 100644 --- a/build.txt +++ b/build.txt @@ -1,5 +1,5 @@ author = blushiemagic -version = 0.4.3.6 +version = 0.4.6.0 displayName = Magic Storage homepage = https://forums.terraria.org/index.php?threads/magic-storage.56294/ hideCode = false