diff --git a/ContainerAdapters/CannonAdapter.cs b/ContainerAdapters/CannonAdapter.cs index 5d91c8e..84e98d6 100644 --- a/ContainerAdapters/CannonAdapter.cs +++ b/ContainerAdapters/CannonAdapter.cs @@ -52,6 +52,8 @@ public bool InjectItem(int x, int y, Item item) WorldGen.ShootFromCannon(originX, originY, angle, ammotype, item.damage, item.knockBack, Main.myPlayer); + item.stack--; + return true; } } diff --git a/ContainerAdapters/ChestAdapter.cs b/ContainerAdapters/ChestAdapter.cs index ac219d3..fcb1266 100644 --- a/ContainerAdapters/ChestAdapter.cs +++ b/ContainerAdapters/ChestAdapter.cs @@ -1,13 +1,19 @@ using System; using System.Collections.Generic; using Terraria; -using Terraria.ID; using Terraria.ModLoader; namespace MechTransfer.ContainerAdapters { internal class ChestAdapter { + private Mod mod; + + public ChestAdapter(Mod mod) + { + this.mod = mod; + } + private int FindChest(int x, int y) { Tile tile = Main.tile[x, y]; @@ -30,15 +36,16 @@ private int FindChest(int x, int y) return -1; } - private void HandleChestItemChange(int chest, int slot) + private void HandleChestItemChange(int chest) { int targetPlayer = WhichPlayerInChest(chest); if (targetPlayer != -1) { if (Main.netMode == 2) { - Item item = Main.chest[chest].item[slot]; - NetMessage.SendData(MessageID.SyncChestItem, targetPlayer, -1, null, chest, slot, item.stack, item.prefix, item.type); + ModPacket packet = mod.GetPacket(); + packet.Write((byte)MechTransfer.ModMessageID.KickFromChest); + packet.Send(targetPlayer); } else if (Main.netMode == 0) Recipe.FindRecipes(); @@ -64,6 +71,8 @@ public bool InjectItem(int x, int y, Item item) if (c == -1) return false; + bool injectedPartial = false; + if (item.maxStack > 1) { for (int i = 0; i < Main.chest[c].item.Length; i++) @@ -71,9 +80,21 @@ public bool InjectItem(int x, int y, Item item) Item chestItem = Main.chest[c].item[i]; if (item.IsTheSameAs(chestItem) && chestItem.stack < chestItem.maxStack) { - chestItem.stack++; - HandleChestItemChange(c, i); - return true; + int spaceLeft = chestItem.maxStack - chestItem.stack; + if (spaceLeft >= item.stack) + { + chestItem.stack += item.stack; + item.stack = 0; + HandleChestItemChange(c); + return true; + } + else + { + item.stack -= spaceLeft; + chestItem.stack = chestItem.maxStack; + HandleChestItemChange(c); + injectedPartial = true; + } } } } @@ -82,13 +103,14 @@ public bool InjectItem(int x, int y, Item item) { if (Main.chest[c].item[i].IsAir) { - Main.chest[c].item[i] = item; - HandleChestItemChange(c, i); + Main.chest[c].item[i] = item.Clone(); + item.stack = 0; + HandleChestItemChange(c); return true; } } - return false; + return injectedPartial; } public IEnumerable> EnumerateItems(int x, int y) @@ -111,8 +133,11 @@ public void TakeItem(int x, int y, object slot, int amount) if (c == -1) return; - TransferUtils.EatItem(ref Main.chest[c].item[(int)slot], amount); - HandleChestItemChange(c, (int)slot); + Main.chest[c].item[(int)slot].stack -= amount; + if (Main.chest[c].item[(int)slot].stack < 1) + Main.chest[c].item[(int)slot] = new Item(); + + HandleChestItemChange(c); } } } \ No newline at end of file diff --git a/ContainerAdapters/CrystalStandAdapter.cs b/ContainerAdapters/CrystalStandAdapter.cs index 1f226e2..9fcb4eb 100644 --- a/ContainerAdapters/CrystalStandAdapter.cs +++ b/ContainerAdapters/CrystalStandAdapter.cs @@ -29,16 +29,15 @@ public bool InjectItem(int x, int y, Item item) if (tile == null || !tile.active()) return false; - int originY = y - tile.frameY % 18; - - if (DD2Event.WouldFailSpawningHere(x, originY)) + if (DD2Event.WouldFailSpawningHere(x, y)) { DD2Event.FailureMessage(-1); return false; } else { - DD2Event.SummonCrystal(x, originY); + DD2Event.SummonCrystal(x, y); + item.stack--; return true; } } diff --git a/ContainerAdapters/ItemFrameAdapter.cs b/ContainerAdapters/ItemFrameAdapter.cs index 7d3c09a..9bea670 100644 --- a/ContainerAdapters/ItemFrameAdapter.cs +++ b/ContainerAdapters/ItemFrameAdapter.cs @@ -15,12 +15,8 @@ private TEItemFrame FindItemFrame(int x, int y) if (tile == null || !tile.active()) return null; - int originX = x; - int originY = y; - if (tile.frameX % 36 != 0) - originX--; - if (tile.frameY != 0) - originY--; + int originX = x - tile.frameX % 36 / 18; + int originY = y - tile.frameY / 18; int id = TEItemFrame.Find(originX, originY); if (id == -1) @@ -42,7 +38,9 @@ public bool InjectItem(int x, int y, Item item) if (!frame.item.IsAir) return false; - frame.item = item; + frame.item = item.Clone(); + frame.item.stack = 1; + item.stack--; HandleItemFrameChange(x, y, frame.ID); return true; } diff --git a/ContainerAdapters/MagicStorageInterfaceAdapter.cs b/ContainerAdapters/MagicStorageInterfaceAdapter.cs new file mode 100644 index 0000000..ab5c99f --- /dev/null +++ b/ContainerAdapters/MagicStorageInterfaceAdapter.cs @@ -0,0 +1,77 @@ +using MagicStorage; +using MagicStorage.Components; +using System; +using System.Collections.Generic; +using Terraria; +using Terraria.DataStructures; + +namespace MechTransfer.ContainerAdapters +{ + internal class MagicStorageInterfaceAdapter + { + private TEStorageHeart FindHeart(int x, int y) + { + Point16 center = TEStorageComponent.FindStorageCenter(new Point16(x, y)); + if (center.X == -1 && center.Y == -1) + return null; + + TEStorageHeart heart = ((TEStorageCenter)TileEntity.ByPosition[center]).GetHeart(); + + return heart; + } + + private void HandleStorageItemChange(TEStorageHeart heart) + { + if (Main.netMode == 2) + { + NetHelper.SendRefreshNetworkItems(heart.ID); + } + else if (Main.netMode == 0) + { + StorageGUI.RefreshItems(); + } + } + + public void KickMe() + { + Main.LocalPlayer.GetModPlayer().CloseStorage(); + } + + public bool InjectItem(int x, int y, Item item) + { + int oldstack = item.stack; + + TEStorageHeart targetHeart = FindHeart(x, y); + targetHeart.DepositItem(item); + + if (oldstack != item.stack) + { + HandleStorageItemChange(targetHeart); + return true; + } + return false; + } + + public IEnumerable> EnumerateItems(int x, int y) + { + TEStorageHeart targetHeart = FindHeart(x, y); + foreach (var item in targetHeart.GetStoredItems()) + { + yield return new Tuple(item, item.type); + } + } + + public void TakeItem(int x, int y, object slot, int amount) + { + TEStorageHeart targetHeart = FindHeart(x, y); + + Item toWithdraw = new Item(); + toWithdraw.SetDefaults((int)slot); + toWithdraw.stack = amount; + + targetHeart.TryWithdraw(toWithdraw); + + HandleStorageItemChange(targetHeart); + } + } +} \ No newline at end of file diff --git a/ContainerAdapters/OmniTurretAdapter.cs b/ContainerAdapters/OmniTurretAdapter.cs index 49b0950..863ee7f 100644 --- a/ContainerAdapters/OmniTurretAdapter.cs +++ b/ContainerAdapters/OmniTurretAdapter.cs @@ -15,9 +15,9 @@ internal class OmniTurretAdapter private int[] fireRate = new int[] { 11, 7, 0 }; private int[] shootSpeed = new int[] { 10, 10, 20 }; - public OmniTurretAdapter(Mod m) + public OmniTurretAdapter(Mod mod) { - mod = m; + this.mod = mod; } public void TakeItem(int x, int y, object slot, int amount) @@ -31,7 +31,7 @@ public IEnumerable> EnumerateItems(int x, int y) public bool InjectItem(int x, int y, Item item) { - if (!item.consumable || item.ammo == 0 || item.shoot == 0) + if (item.ammo == 0 || item.shoot == 0 || item.ammo == AmmoID.Rocket) return false; Tile tile = Main.tile[x, y]; @@ -76,6 +76,9 @@ public bool InjectItem(int x, int y, Item item) packet.Send(); } + if (item.consumable) + item.stack--; + return true; } } diff --git a/ContainerAdapters/SnowballLauncherAdapter.cs b/ContainerAdapters/SnowballLauncherAdapter.cs index 6ec8e88..e774cf3 100644 --- a/ContainerAdapters/SnowballLauncherAdapter.cs +++ b/ContainerAdapters/SnowballLauncherAdapter.cs @@ -54,6 +54,8 @@ public bool InjectItem(int x, int y, Item item) velocityY *= velocity; Projectile.NewProjectile(position.X, position.Y, velocityX, velocityY, ProjectileID.SnowBallFriendly, 35, 3.5f, Main.myPlayer, 0, 0); + + item.stack--; return true; } } diff --git a/ContainerAdapters/WeaponRackAdapter.cs b/ContainerAdapters/WeaponRackAdapter.cs index fb50a37..419ebf6 100644 --- a/ContainerAdapters/WeaponRackAdapter.cs +++ b/ContainerAdapters/WeaponRackAdapter.cs @@ -10,11 +10,11 @@ internal class WeaponRackAdapter { //By god, this weapon rack thing is a complete mess... - public Point16 FindOrigin(int x, int y, out bool something) + public Point16 FindOrigin(int x, int y, out bool facingRight) { Tile tile = Main.tile[x, y]; - int originY = y - tile.frameY % 36 / 18 + 1; + int originY = y - tile.frameY / 18 + 1; int realFrameX = 0; int temp = Math.DivRem(tile.frameX, 5000, out realFrameX); @@ -23,11 +23,11 @@ public Point16 FindOrigin(int x, int y, out bool something) realFrameX = (temp - 1) * 18; } - something = false; + facingRight = false; if (realFrameX >= 54) { realFrameX -= 54; - something = true; + facingRight = true; } int originX = x - realFrameX / 18; @@ -46,26 +46,34 @@ public void HandleRackItemChange(int x, int y) public void TakeItem(int x, int y, object slot, int amount) { - bool something; - Point16 origin = FindOrigin(x, y, out something); + bool facingRight; + Point16 origin = FindOrigin(x, y, out facingRight); - Main.tile[origin.X, origin.Y].frameX = 0; - Main.tile[origin.X + 1, origin.Y].frameX = 18; + if (facingRight) + { + Main.tile[origin.X, origin.Y].frameX = 54; + Main.tile[origin.X + 1, origin.Y].frameX = 72; + } + else + { + Main.tile[origin.X, origin.Y].frameX = 0; + Main.tile[origin.X + 1, origin.Y].frameX = 18; + } HandleRackItemChange(origin.X, origin.Y); } public IEnumerable> EnumerateItems(int x, int y) { - bool something; - Point16 origin = FindOrigin(x, y, out something); + bool facingRight; + Point16 origin = FindOrigin(x, y, out facingRight); if (Main.tile[origin.X, origin.Y].frameX < 5000) yield break; //Empty Item item = new Item(); - if (something) + if (facingRight) { item.netDefaults(Main.tile[origin.X, origin.Y].frameX - 20100); item.prefix = (byte)(Main.tile[origin.X + 1, origin.Y].frameX - 25000); @@ -84,13 +92,13 @@ public bool InjectItem(int x, int y, Item item) if (!Main.LocalPlayer.ItemFitsWeaponRack(item)) return false; - bool something; - Point16 origin = FindOrigin(x, y, out something); + bool facingRight; + Point16 origin = FindOrigin(x, y, out facingRight); if (Main.tile[origin.X, origin.Y].frameX >= 5000) return false; //Already has item - if (something) + if (facingRight) { Main.tile[origin.X, origin.Y].frameX = (short)(item.netID + 20100); Main.tile[origin.X + 1, origin.Y].frameX = (short)(item.prefix + 25000); @@ -103,6 +111,7 @@ public bool InjectItem(int x, int y, Item item) HandleRackItemChange(origin.X, origin.Y); + item.stack--; return true; } } diff --git a/Interfaces.cs b/Interfaces.cs new file mode 100644 index 0000000..b160522 --- /dev/null +++ b/Interfaces.cs @@ -0,0 +1,19 @@ +using Terraria; +using Terraria.DataStructures; + +namespace MechTransfer +{ + public interface ITransferTarget + { + ushort Type { get; } + + bool Receive(TransferUtils agent, Point16 location, Item item); + } + + public interface ITransferPassthrough + { + ushort Type { get; } + + bool ShouldPassthrough(TransferUtils agent, Point16 location, Item item); + } +} \ No newline at end of file diff --git a/Items/InverseTransferFilterItem.png b/Items/InverseTransferFilterItem.png new file mode 100644 index 0000000..837afd7 Binary files /dev/null and b/Items/InverseTransferFilterItem.png differ diff --git a/Items/InverseTransferFilterItem.xcf b/Items/InverseTransferFilterItem.xcf new file mode 100644 index 0000000..6d13d5c Binary files /dev/null and b/Items/InverseTransferFilterItem.xcf differ diff --git a/Items/MagicStorageInterfaceItem.png b/Items/MagicStorageInterfaceItem.png new file mode 100644 index 0000000..42de4e0 Binary files /dev/null and b/Items/MagicStorageInterfaceItem.png differ diff --git a/Items/MagicStorageInterfaceItem.xcf b/Items/MagicStorageInterfaceItem.xcf new file mode 100644 index 0000000..8021dd7 Binary files /dev/null and b/Items/MagicStorageInterfaceItem.xcf differ diff --git a/Items/PneumaticActuatorItem.cs b/Items/PneumaticActuatorItem.cs index 2ba2bf7..64d99fb 100644 --- a/Items/PneumaticActuatorItem.cs +++ b/Items/PneumaticActuatorItem.cs @@ -1,4 +1,5 @@ -using Terraria.ModLoader; +using Terraria; +using Terraria.ModLoader; namespace MechTransfer.Items { @@ -15,7 +16,7 @@ public override void SetDefaults() item.width = 26; item.height = 26; item.maxStack = 999; - item.value = 5000; + item.value = Item.buyPrice(0, 0, 50, 0); } } } \ No newline at end of file diff --git a/Items/SimplePlaceableItem.cs b/Items/SimplePlaceableItem.cs index b462758..795e586 100644 --- a/Items/SimplePlaceableItem.cs +++ b/Items/SimplePlaceableItem.cs @@ -7,12 +7,8 @@ public class SimplePlaceableItem : ModItem { public int placeType; public int style = 0; - public ModTranslation name; public int value = Item.sellPrice(0, 0, 50, 0); - public ModTranslation DName { get { return DisplayName; } } - public ModTranslation TTip { get { return Tooltip; } } - public override bool CloneNewInstances { get { return true; } } public override void SetDefaults() @@ -37,6 +33,7 @@ public override bool Autoload(ref string name) return false; } + //Needed to stop ModLoader from assigning a default display name public override void AutoStaticDefaults() { Main.itemTexture[item.type] = ModLoader.GetTexture(Texture); diff --git a/Items/StackExtractorItem.png b/Items/StackExtractorItem.png new file mode 100644 index 0000000..44be48e Binary files /dev/null and b/Items/StackExtractorItem.png differ diff --git a/Items/StackExtractorItem.xcf b/Items/StackExtractorItem.xcf new file mode 100644 index 0000000..e687bce Binary files /dev/null and b/Items/StackExtractorItem.xcf differ diff --git a/MechTransfer.cs b/MechTransfer.cs index 744bccd..26c1c54 100644 --- a/MechTransfer.cs +++ b/MechTransfer.cs @@ -1,6 +1,7 @@ using MechTransfer.ContainerAdapters; using MechTransfer.Items; using MechTransfer.Tiles; +using MechTransfer.UI; using System; using System.Collections.Generic; using System.IO; @@ -10,6 +11,7 @@ using Terraria.DataStructures; using Terraria.ID; using Terraria.ModLoader; +using Terraria.UI; using EnumerateItemsDelegate = System.Func>>; using InjectItemDelegate = System.Func; using TakeItemDelegate = System.Action; @@ -18,14 +20,21 @@ namespace MechTransfer { public class MechTransfer : Mod { - public enum ModMessageID { FilterSyncing, CreateDust, RotateTurret, ProjectileMakeHostile } + public enum ModMessageID { FilterSyncing, CreateDust, RotateTurret, ProjectileMakeHostile, KickFromChest } + + public TransferUtils transferAgent = new TransferUtils(); - internal Dictionary ContainerAdapters = new Dictionary(); internal HashSet PickupBlacklist = new HashSet(); + private const string callErorPrefix = "MechTransfer Call() error: "; private const string registerAdapter = "RegisterAdapter"; private const string registerAdapterReflection = "RegisterAdapterReflection"; + private GameInterfaceLayer interfaceLayer; + public FilterHoverUI filterHoverUI; + + private Mod modMagicStorage = null; + public MechTransfer() { Properties = new ModProperties() @@ -34,7 +43,6 @@ public MechTransfer() AutoloadGores = true, AutoloadSounds = true }; - TransferUtils.mod = this; } public override object Call(params object[] args) @@ -81,8 +89,8 @@ public override object Call(params object[] args) foreach (var type in (int[])args[4]) { - if (!ContainerAdapters.ContainsKey(type)) - ContainerAdapters.Add(type, definition); + if (!transferAgent.ContainerAdapters.ContainsKey(type)) + transferAgent.ContainerAdapters.Add(type, definition); } return definition; } @@ -127,8 +135,8 @@ public override object Call(params object[] args) foreach (var t in (int[])args[2]) { - if (!ContainerAdapters.ContainsKey(t)) - ContainerAdapters.Add(t, definition); + if (!transferAgent.ContainerAdapters.ContainsKey(t)) + transferAgent.ContainerAdapters.Add(t, definition); } return definition; } @@ -143,50 +151,68 @@ public override object Call(params object[] args) return null; } - public override bool HijackGetData(ref byte messageType, ref BinaryReader reader, int playerNumber) - { - if (Main.netMode == 1 && messageType == MessageID.SyncChestItem && Main.LocalPlayer.chest == reader.ReadInt16()) - { - //This a temporary fix for multiplayer item duplication - Main.LocalPlayer.chest = -1; - Recipe.FindRecipes(); - Main.PlaySound(SoundID.MenuClose); - } - return false; - } - public override void HandlePacket(BinaryReader reader, int whoAmI) { ModMessageID id = (ModMessageID)reader.ReadByte(); - if (id == ModMessageID.FilterSyncing) - { - if (Main.netMode != 2) - return; - TransferFilterTileEntity entity = (TransferFilterTileEntity)TileEntity.ByID[reader.ReadInt32()]; - entity.ItemId = reader.ReadInt32(); - NetMessage.SendData(MessageID.TileEntitySharing, -1, whoAmI, null, entity.ID, entity.Position.X, entity.Position.Y); - } - else if (id == ModMessageID.CreateDust) + switch (id) { - if (Main.netMode != 1) - return; + case ModMessageID.FilterSyncing: - Dust.NewDustPerfect(reader.ReadVector2(), DustID.Silver, reader.ReadVector2()).noGravity = true; - } - else if (id == ModMessageID.RotateTurret) - { - GetTile().Rotate(reader.ReadInt16(), reader.ReadInt16(), false); - } - else if (id == ModMessageID.ProjectileMakeHostile) - { - Main.projectile[reader.ReadInt16()].hostile = true; + if (Main.netMode != 2) + return; + + TransferFilterTileEntity FilterEntity = (TransferFilterTileEntity)TileEntity.ByID[reader.ReadInt32()]; + FilterEntity.ItemId = reader.ReadInt32(); + NetMessage.SendData(MessageID.TileEntitySharing, -1, whoAmI, null, FilterEntity.ID, FilterEntity.Position.X, FilterEntity.Position.Y); + + break; + + case ModMessageID.CreateDust: + + if (Main.netMode != 1) + return; + + VisualUtils.CreateVisual(reader.ReadPackedVector2().ToPoint16(), (TransferUtils.Direction)reader.ReadByte()); + break; + + case ModMessageID.RotateTurret: + + GetTile().Rotate(reader.ReadInt16(), reader.ReadInt16(), false); + break; + + case ModMessageID.ProjectileMakeHostile: + + Main.projectile[reader.ReadInt16()].hostile = true; + break; + + case ModMessageID.KickFromChest: + + Main.LocalPlayer.chest = -1; + Recipe.FindRecipes(); + Main.PlaySound(SoundID.MenuClose); + break; } } public override void Load() { + modMagicStorage = ModLoader.GetMod("MagicStorage"); + LoadItems(); + if (!Main.dedServ) + LoadUI(); + } + + public override void ModifyInterfaceLayers(List layers) + { + int index = layers.FindIndex(x => x.Name == "Vanilla: Mouse Text") + 1; + layers.Insert(index, interfaceLayer); + + if (filterHoverUI.visible) + { + layers.Find(x => x.Name == "Vanilla: Interact Item Icon").Active = false; + } } public override void PostSetupContent() @@ -195,6 +221,20 @@ public override void PostSetupContent() LoadBlacklist(); } + private void LoadUI() + { + filterHoverUI = new FilterHoverUI(); + filterHoverUI.Activate(); + + interfaceLayer = new LegacyGameInterfaceLayer("MechTransfer: UI", + delegate + { + filterHoverUI.Draw(Main.spriteBatch); + return true; + }, + InterfaceScaleType.UI); + } + private void LoadAdapters() { //Item frame @@ -220,12 +260,19 @@ private void LoadAdapters() //Omni turret OmniTurretAdapter omniTurretAdapter = new OmniTurretAdapter(this); Call(registerAdapterReflection, omniTurretAdapter, new int[] { TileType() }); + + if (modMagicStorage != null) + { + //Magic storage interface + MagicStorageInterfaceAdapter magicStorageInterfaceAdapter = new MagicStorageInterfaceAdapter(); + Call(registerAdapterReflection, magicStorageInterfaceAdapter, new int[] { TileType() }); + } } //This needs to be called from SetupRecipies, because chests are made in SetupContent. private void LoadChestAdapters() { - ChestAdapter chestAdapter = new ChestAdapter(); + ChestAdapter chestAdapter = new ChestAdapter(this); List chestTypes = new List(); for (int i = 0; i < TileLoader.TileCount; i++) { @@ -256,6 +303,14 @@ public override void AddRecipes() r.AddTile(TileID.WorkBenches); r.AddRecipe(); + //StackExtractor + r = new ModRecipe(this); + r.AddIngredient(ItemType("TransferExtractorItem"), 1); + r.AddIngredient(ItemID.Nanites, 10); + r.SetResult(ItemType("StackExtractorItem"), 1); + r.AddTile(TileID.WorkBenches); + r.AddRecipe(); + //Injector r = new ModRecipe(this); r.AddIngredient(ItemType(), 1); @@ -274,6 +329,15 @@ public override void AddRecipes() r.SetResult(ItemType("TransferFilterItem"), 1); r.AddRecipe(); + //InverseFilter + r = new ModRecipe(this); + r.AddIngredient(ItemType(), 1); + r.AddIngredient(ItemID.Actuator, 1); + r.AddIngredient(ItemID.ItemFrame, 1); + r.AddTile(TileID.WorkBenches); + r.SetResult(ItemType("InverseTransferFilterItem"), 1); + r.AddRecipe(); + //Gate r = new ModRecipe(this); r.AddIngredient(ItemType(), 1); @@ -342,6 +406,18 @@ public override void AddRecipes() r.SetResult(ItemType("MatterProjectorItem"), 1); r.AddRecipe(); + if (modMagicStorage != null) + { + //Magic storage interface + r = new ModRecipe(this); + r.AddIngredient(modMagicStorage.ItemType("StorageComponent")); + r.AddRecipeGroup("MagicStorage:AnyDiamond", 1); + r.AddIngredient(ItemType(), 1); + r.AddTile(TileID.WorkBenches); + r.SetResult(ItemType("MagicStorageInterfaceItem")); + r.AddRecipe(); + } + LoadChestAdapters(); } @@ -356,11 +432,19 @@ private void LoadItems() i.Tooltip.AddTranslation(LangID.English, "WIP\nCrafts items automatically\nRight click with item in hand to set filter"); //Extractor - SimplePlaceableItem j = new SimplePlaceableItem(); - j.placeType = TileType(); - AddItem("TransferExtractorItem", j); - j.DisplayName.AddTranslation(LangID.English, "Transfer extractor"); - j.Tooltip.AddTranslation(LangID.English, "Extracts items from adjacent chests"); + i = new SimplePlaceableItem(); + i.placeType = TileType(); + AddItem("TransferExtractorItem", i); + i.DisplayName.AddTranslation(LangID.English, "Transfer extractor"); + i.Tooltip.AddTranslation(LangID.English, "Extracts items from adjacent chests"); + + //StackExtractor + i = new SimplePlaceableItem(); + i.placeType = TileType(); + i.value = Item.sellPrice(0, 1, 0, 0); + AddItem("StackExtractorItem", i); + i.DisplayName.AddTranslation(LangID.English, "Stack extractor"); + i.Tooltip.AddTranslation(LangID.English, "Extracts a whole stack at once"); //Injector i = new SimplePlaceableItem(); @@ -373,7 +457,15 @@ private void LoadItems() i = new SimplePlaceableItem(); i.placeType = TileType(); AddItem("TransferFilterItem", i); - i.DisplayName.AddTranslation(LangID.English, "Transfer filter"); + i.DisplayName.AddTranslation(LangID.English, "Transfer filter (whitelist)"); + i.Tooltip.AddTranslation(LangID.English, "Place in line with Transfer pipe\nRight click with item in hand to set filter"); + + //InverseFilter + i = new SimplePlaceableItem(); + i.placeType = TileType(); + i.style = 1; + AddItem("InverseTransferFilterItem", i); + i.DisplayName.AddTranslation(LangID.English, "Transfer filter (blacklist)"); i.Tooltip.AddTranslation(LangID.English, "Place in line with Transfer pipe\nRight click with item in hand to set filter"); //Gate @@ -436,6 +528,14 @@ private void LoadItems() AddItem("MatterProjectorItem", i); i.DisplayName.AddTranslation(LangID.English, "Matter projector"); i.Tooltip.AddTranslation(LangID.English, "Shoots any standard ammo really, really fast"); + + + //Magic storage interface + i = new SimplePlaceableItem(); + i.placeType = TileType(); + AddItem("MagicStorageInterfaceItem", i); + i.DisplayName.AddTranslation(LangID.English, "Magic storage interface"); + i.Tooltip.AddTranslation(LangID.English, "Allows you to inject and extract items from storage systems"); } private void LoadBlacklist() diff --git a/MechTransfer.csproj b/MechTransfer.csproj index c05ed55..16d73cb 100644 --- a/MechTransfer.csproj +++ b/MechTransfer.csproj @@ -14,7 +14,7 @@ true - AnyCPU + x86 true full false @@ -38,20 +38,22 @@ + + + + + - - - @@ -64,8 +66,13 @@ + + + + C:\Users\kwinc\Documents\My Games\Terraria\ModLoader\Mods\MagicStorage.All.dll + False C:\Windows\Microsoft.NET\assembly\GAC_32\Microsoft.Xna.Framework\v4.0_4.0.0.0__842cf8be1de50553\Microsoft.Xna.Framework.dll diff --git a/Tiles/FilterableTile.cs b/Tiles/FilterableTile.cs new file mode 100644 index 0000000..bc4eefd --- /dev/null +++ b/Tiles/FilterableTile.cs @@ -0,0 +1,50 @@ +using Microsoft.Xna.Framework; +using Terraria; +using Terraria.DataStructures; +using Terraria.ModLoader; + +namespace MechTransfer.Tiles +{ + public abstract class FilterableTile : ModTile + { + protected string hoverText = "Filter:"; + + public override void RightClick(int i, int j) + { + if (!Main.LocalPlayer.HeldItem.IsAir) + { + TileEntity tileEntity; + if (TileEntity.ByPosition.TryGetValue(new Point16(i, j), out tileEntity)) + { + TransferFilterTileEntity transferFilter = tileEntity as TransferFilterTileEntity; + if (transferFilter != null) + { + transferFilter.ItemId = Main.LocalPlayer.HeldItem.type; + transferFilter.SyncData(); + } + } + } + } + + public override void MouseOverFar(int i, int j) + { + DisplayTooltip(i, j); + } + + public override void MouseOver(int i, int j) + { + DisplayTooltip(i, j); + Main.LocalPlayer.noThrow = 2; + } + + public virtual void DisplayTooltip(int i, int j) + { + int id = mod.GetTileEntity().Find(i, j); + if (id == -1) + return; + TransferFilterTileEntity entity = (TransferFilterTileEntity)TileEntity.ByID[id]; + + ((MechTransfer)mod).filterHoverUI.Display(entity.ItemId, hoverText, Color.White); + } + } +} \ No newline at end of file diff --git a/Tiles/MagicStorageInterfaceTile.cs b/Tiles/MagicStorageInterfaceTile.cs new file mode 100644 index 0000000..5424619 --- /dev/null +++ b/Tiles/MagicStorageInterfaceTile.cs @@ -0,0 +1,33 @@ +using Microsoft.Xna.Framework; +using Terraria; +using Terraria.DataStructures; +using Terraria.Enums; +using Terraria.ModLoader; +using Terraria.ObjectData; + +namespace MechTransfer.Tiles +{ + public class MagicStorageInterfaceTile : ModTile + { + public override void SetDefaults() + { + Main.tileFrameImportant[Type] = true; + Main.tileNoFail[Type] = true; + dustType = 1; + + TileObjectData.newTile.CopyFrom(TileObjectData.Style2x2); + TileObjectData.newTile.LavaDeath = false; + TileObjectData.newTile.StyleHorizontal = true; + TileObjectData.newTile.AnchorBottom = new AnchorData(AnchorType.None, 0, 0); + TileObjectData.newTile.CoordinateHeights = new int[] { 16, 16 }; + TileObjectData.addTile(Type); + + AddMapEntry(new Color(200, 200, 200)); + } + + public override void KillMultiTile(int i, int j, int frameX, int frameY) + { + Item.NewItem(i * 16, j * 16, 16, 16, mod.ItemType("MagicStorageInterfaceItem")); + } + } +} \ No newline at end of file diff --git a/Tiles/MagicStorageInterfaceTile.png b/Tiles/MagicStorageInterfaceTile.png new file mode 100644 index 0000000..8970fed Binary files /dev/null and b/Tiles/MagicStorageInterfaceTile.png differ diff --git a/Tiles/MagicStorageInterfaceTile.xcf b/Tiles/MagicStorageInterfaceTile.xcf new file mode 100644 index 0000000..87a9ab7 Binary files /dev/null and b/Tiles/MagicStorageInterfaceTile.xcf differ diff --git a/Tiles/OmniTurretTile.cs b/Tiles/OmniTurretTile.cs index 2b20340..3d053fa 100644 --- a/Tiles/OmniTurretTile.cs +++ b/Tiles/OmniTurretTile.cs @@ -110,7 +110,6 @@ public void Rotate(int i, int j, bool skipWies) Wiring.SkipWire(originX + 1, originY + 1); } - if (Main.netMode == 2) { NetMessage.SendTileSquare(-1, originX, originY, 2, TileChangeType.None); diff --git a/Tiles/StackExtractorTile.cs b/Tiles/StackExtractorTile.cs new file mode 100644 index 0000000..2e1637d --- /dev/null +++ b/Tiles/StackExtractorTile.cs @@ -0,0 +1,50 @@ +using Microsoft.Xna.Framework; +using Terraria; +using Terraria.DataStructures; +using Terraria.Enums; +using Terraria.ModLoader; +using Terraria.ObjectData; + +namespace MechTransfer.Tiles +{ + public class StackExtractorTile : ModTile + { + public override void SetDefaults() + { + Main.tileFrameImportant[Type] = true; + Main.tileNoFail[Type] = true; + dustType = 1; + + TileObjectData.newTile.CopyFrom(TileObjectData.Style1x1); + TileObjectData.newTile.LavaDeath = false; + TileObjectData.newTile.AnchorBottom = new AnchorData(AnchorType.None, 0, 0); + TileObjectData.addTile(Type); + + drop = mod.ItemType("StackExtractorItem"); + AddMapEntry(new Color(200, 200, 200)); + } + + public override void HitWire(int i, int j) + { + if (Main.netMode == 1) + return; + + foreach (var c in ((MechTransfer)mod).transferAgent.FindContainerAdjacent(i, j)) + { + foreach (var item in c.EnumerateItems()) + { + if (!item.Item1.IsAir) + { + Item clone = item.Item1.Clone(); + int numTook = ((MechTransfer)mod).transferAgent.StartTransfer(i, j, clone); + if (numTook > 0) + { + c.TakeItem(item.Item2, numTook); + return; + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Tiles/StackExtractorTile.png b/Tiles/StackExtractorTile.png new file mode 100644 index 0000000..998f7ca Binary files /dev/null and b/Tiles/StackExtractorTile.png differ diff --git a/Tiles/StackExtractorTile.xcf b/Tiles/StackExtractorTile.xcf new file mode 100644 index 0000000..547fa02 Binary files /dev/null and b/Tiles/StackExtractorTile.xcf differ diff --git a/Tiles/TransferAssemblerTile.cs b/Tiles/TransferAssemblerTile.cs index 0c7a76b..756e894 100644 --- a/Tiles/TransferAssemblerTile.cs +++ b/Tiles/TransferAssemblerTile.cs @@ -5,15 +5,15 @@ using Terraria.DataStructures; using Terraria.Enums; using Terraria.ID; +using Terraria.Localization; using Terraria.ModLoader; using Terraria.ObjectData; namespace MechTransfer.Tiles { - public class TransferAssemblerTile : ModTile + public class TransferAssemblerTile : FilterableTile { private ItemInventory inventory = new ItemInventory(); - private Item stockpile = new Item(); private Dictionary tileRemap = new Dictionary() { { 302, new int[]{ 17 } }, @@ -44,40 +44,46 @@ public override void HitWire(int i, int j) if (Main.netMode == 1) return; - inventory.Clear(); - foreach (var c in TransferUtils.FindContainerAdjacent(i, j)) - { - inventory.RegisterContainer(c); - } - int filterId = mod.GetTileEntity().Find(i, j); if (filterId == -1) return; TransferAssemblerTileEntity entity = (TransferAssemblerTileEntity)TileEntity.ByID[filterId]; - List candidates = new List(); + if (entity.ItemId == 0 || entity.stock.stack > 0) + return; + + inventory.Clear(); + foreach (var c in ((MechTransfer)mod).transferAgent.FindContainerAdjacent(i, j)) + { + inventory.RegisterContainer(c); + } + + bool foundRecipe = false; for (int r = 0; r < Recipe.maxRecipes && !Main.recipe[r].createItem.IsAir; r++) { - if (Main.recipe[r].createItem.type == entity.ItemId && TryMakeRecipe(Main.recipe[r], entity)) + if (Main.recipe[r].createItem.type == entity.ItemId) { - break; + foundRecipe = true; + if (TryMakeRecipe(Main.recipe[r], entity)) + break; } } + + if (!foundRecipe) + entity.Status = TransferAssemblerTileEntity.StatusKind.NoRecipe; + inventory.Clear(); + + NetMessage.SendData(MessageID.TileEntitySharing, -1, -1, null, entity.ID, entity.Position.X, entity.Position.Y); } private bool TryMakeRecipe(Recipe recipe, TransferAssemblerTileEntity entity) { - - while (stockpile.stack > 0) + bool alchemy; + if (!SearchStation(recipe, entity.Position.X, entity.Position.Y, out alchemy)) { - Item safeCLone = stockpile.Clone(); - safeCLone.stack = 1; - if(!TransferUtils.InjectItem(entity.Position.X, entity.Position.Y, safeCLone)) - { - return true; - } - stockpile.stack--; + entity.Status = TransferAssemblerTileEntity.StatusKind.MissingStation; + return false; } for (int i = 0; i < Recipe.maxRequirements && !recipe.requiredItem[i].IsAir; i++) @@ -90,13 +96,6 @@ private bool TryMakeRecipe(Recipe recipe, TransferAssemblerTileEntity entity) } } - bool alchemy = false; - if (!SearchStation(recipe, entity.Position.X, entity.Position.Y, ref alchemy)) - { - entity.Status = TransferAssemblerTileEntity.StatusKind.MissingStation; - return false; - } - Item clone = recipe.createItem.Clone(); if (!clone.IsAir) @@ -106,37 +105,17 @@ private bool TryMakeRecipe(Recipe recipe, TransferAssemblerTileEntity entity) ItemLoader.OnCraft(clone, recipe); } - if (clone.stack == 1) - { - if (!TransferUtils.InjectItem(entity.Position.X, entity.Position.Y, clone)) - { - entity.Status = TransferAssemblerTileEntity.StatusKind.MissingSpace; - return true; //returning with success, so we don't try alternate recipes - } - } - else - { - stockpile = clone; - while (stockpile.stack > 0) - { - Item safeCLone = stockpile.Clone(); - safeCLone.stack = 1; - if (!TransferUtils.InjectItem(entity.Position.X, entity.Position.Y, safeCLone)) - { - break; - } - stockpile.stack--; - } - } - - inventory.Commit(alchemy); + entity.stock = clone; entity.Status = TransferAssemblerTileEntity.StatusKind.Success; + inventory.Commit(alchemy); return true; } - private bool SearchStation(Recipe recipe, int x, int y, ref bool alchemy) + private bool SearchStation(Recipe recipe, int x, int y, out bool alchemy) { + alchemy = false; + bool[] tileOk = new bool[Recipe.maxRequirements]; bool waterOk = !recipe.needWater; bool honeyOk = !recipe.needHoney; @@ -152,15 +131,14 @@ private bool SearchStation(Recipe recipe, int x, int y, ref bool alchemy) { for (int z = 0; z < Recipe.maxRequirements && recipe.requiredTile[z] != -1; z++) { - if (recipe.requiredTile[z] == tile.type) - tileOk[z] = true; - - if (tileRemap.ContainsKey(tile.type) && tileRemap[tile.type].Contains(recipe.requiredTile[z])) - tileOk[z] = true; - ModTile modTile = TileLoader.GetTile(tile.type); - if (modTile != null && modTile.adjTiles.Contains(recipe.requiredTile[z])) + + if ((recipe.requiredTile[z] == tile.type) || + (tileRemap.ContainsKey(tile.type) && tileRemap[tile.type].Contains(recipe.requiredTile[z])) || + (modTile != null && modTile.adjTiles.Contains(recipe.requiredTile[z]))) + { tileOk[z] = true; + } //easier than reimplementing the zone finding logic if (tile.type == TileID.SnowBlock || tile.type == TileID.IceBlock || tile.type == TileID.HallowedIce || tile.type == TileID.FleshIce || tile.type == TileID.CorruptIce) @@ -175,12 +153,12 @@ private bool SearchStation(Recipe recipe, int x, int y, ref bool alchemy) if (tile != null && tile.liquid > 200) { - if (tile.liquidType() == 0) - waterOk = true; - if (tile.liquidType() == 2) - honeyOk = true; - if (tile.liquidType() == 1) - lavaOk = true; + switch (tile.liquidType()) + { + case 0: waterOk = true; break; + case 2: honeyOk = true; break; + case 1: lavaOk = true; break; + } } } } @@ -202,31 +180,7 @@ public override void KillTile(int i, int j, ref bool fail, ref bool effectOnly, mod.GetTileEntity().Kill(i, j); } - public override void RightClick(int i, int j) - { - if (!Main.LocalPlayer.HeldItem.IsAir) - { - int id = mod.GetTileEntity().Find(i, j); - if (id != -1) - { - TransferAssemblerTileEntity tileEntity = (TransferAssemblerTileEntity)TileEntity.ByID[id]; - tileEntity.ItemId = Main.LocalPlayer.HeldItem.type; - tileEntity.SyncData(); - } - } - } - - public override void MouseOverFar(int i, int j) - { - DisplayTooltip(i, j); - } - - public override void MouseOver(int i, int j) - { - DisplayTooltip(i, j); - } - - public void DisplayTooltip(int i, int j) + public override void DisplayTooltip(int i, int j) { int id = mod.GetTileEntity().Find(i, j); if (id == -1) @@ -234,34 +188,35 @@ public void DisplayTooltip(int i, int j) TransferAssemblerTileEntity entity = (TransferAssemblerTileEntity)TileEntity.ByID[id]; string statusText = ""; + Color statusColor = Color.White; switch (entity.Status) { case TransferAssemblerTileEntity.StatusKind.Ready: - statusText = "[c/FFFF00:Ready]"; break; + statusText = "Ready"; statusColor = Color.Yellow; break; case TransferAssemblerTileEntity.StatusKind.Success: - statusText = "[c/00FF00:Success]"; break; + statusText = "Success"; statusColor = Color.Green; break; case TransferAssemblerTileEntity.StatusKind.MissingItem: - statusText = string.Format("[c/FF0000:Missing ingredient ({0})]", TransferUtils.ItemNameById(entity.MissingItemType)); break; + statusText = string.Format("Missing ingredient ({0})", ItemNameById(entity.MissingItemType)); statusColor = Color.Red; break; case TransferAssemblerTileEntity.StatusKind.MissingStation: - statusText = "[c/FF0000:Missing crafting station]"; break; + statusText = "Missing crafting station"; statusColor = Color.Red; break; case TransferAssemblerTileEntity.StatusKind.MissingSpace: - statusText = "[c/FF0000:Inventory full]"; break; + statusText = string.Format("Cant deposit ({0} x{1})", entity.stock.Name, entity.stock.stack); statusColor = Color.Red; break; + case TransferAssemblerTileEntity.StatusKind.NoRecipe: + statusText = "No recipe found"; statusColor = Color.Red; break; } - string itemText = ""; - if (entity.ItemId == 0) - { - itemText = "Not set"; - Main.LocalPlayer.showItemIcon2 = drop; - } - else - { - itemText = TransferUtils.ItemNameById(entity.ItemId); - Main.LocalPlayer.showItemIcon2 = entity.ItemId; - } + ((MechTransfer)mod).filterHoverUI.Display(entity.ItemId, "Crafting: " + statusText, statusColor); + } + + public static string ItemNameById(int id) + { + if (id == 0) + return ""; - Main.LocalPlayer.showItemIconText = string.Format(" Crafting: {0}\n{1}", itemText, statusText); - Main.LocalPlayer.showItemIcon = true; + LocalizedText name = Lang.GetItemName(id); + if (name == LocalizedText.Empty) + return string.Format("Unknown item #{0}", id); + return name.Value; } } } \ No newline at end of file diff --git a/Tiles/TransferAssemblerTileEntity.cs b/Tiles/TransferAssemblerTileEntity.cs index 012d550..2d7b7ea 100644 --- a/Tiles/TransferAssemblerTileEntity.cs +++ b/Tiles/TransferAssemblerTileEntity.cs @@ -1,17 +1,85 @@ -using Terraria; +using System.IO; +using Terraria; +using Terraria.ID; +using Terraria.ModLoader.IO; namespace MechTransfer.Tiles { public class TransferAssemblerTileEntity : TransferFilterTileEntity { - public enum StatusKind { Ready, Success, MissingItem, MissingStation, MissingSpace } + public enum StatusKind { Ready, Success, MissingItem, MissingStation, MissingSpace, NoRecipe } public StatusKind Status = StatusKind.Ready; public int MissingItemType = 0; + public Item stock = new Item(); + + private int timer = 0; public override bool ValidTile(int i, int j) { return Main.tile[i, j].active() && (Main.tile[i, j].type == mod.TileType()); } + + public override void Update() + { + if (timer > 0) + { + timer--; + return; + } + + if (stock.stack > 0) + { + foreach (var container in ((MechTransfer)mod).transferAgent.FindContainerAdjacent(Position.X, Position.Y)) + { + container.InjectItem(stock); + + if (stock.stack < 1) + { + Status = StatusKind.Success; + break; + } + } + + if (stock.stack > 0) + { + timer = 60; + Status = StatusKind.MissingSpace; + } + + if (Main.netMode == 2) + NetMessage.SendData(MessageID.TileEntitySharing, -1, -1, null, ID, Position.X, Position.Y); + } + } + + public override TagCompound Save() + { + TagCompound tags = base.Save(); + tags.Add("stck", ItemIO.Save(stock)); + return tags; + } + + public override void Load(TagCompound tag) + { + if (tag.ContainsKey("stck")) + stock = ItemIO.Load((TagCompound)tag["stck"]); + base.Load(tag); + } + + public override void NetSend(BinaryWriter writer, bool lightSend) + { + base.NetSend(writer, lightSend); + writer.Write((byte)Status); + writer.Write(MissingItemType); + writer.WriteItem(stock, true); + } + + public override void NetReceive(BinaryReader reader, bool lightReceive) + { + base.NetReceive(reader, lightReceive); + Status = (StatusKind)reader.ReadByte(); + MissingItemType = reader.ReadInt32(); + stock = reader.ReadItem(true); + } } } \ No newline at end of file diff --git a/Tiles/TransferExtractorTile.cs b/Tiles/TransferExtractorTile.cs index a5d3312..fa57860 100644 --- a/Tiles/TransferExtractorTile.cs +++ b/Tiles/TransferExtractorTile.cs @@ -29,14 +29,19 @@ public override void HitWire(int i, int j) if (Main.netMode == 1) return; - foreach (var c in TransferUtils.FindContainerAdjacent(i, j)) + foreach (var c in ((MechTransfer)mod).transferAgent.FindContainerAdjacent(i, j)) { foreach (var item in c.EnumerateItems()) { - if (!item.Item1.IsAir && TransferUtils.StartTransfer(i, j, item.Item1)) + if (!item.Item1.IsAir) { - c.TakeItem(item.Item2, 1); - return; + Item clone = item.Item1.Clone(); + clone.stack = 1; + if (((MechTransfer)mod).transferAgent.StartTransfer(i, j, clone) > 0) + { + c.TakeItem(item.Item2, 1); + return; + } } } } diff --git a/Tiles/TransferFilterTile.cs b/Tiles/TransferFilterTile.cs index f8a65be..a569843 100644 --- a/Tiles/TransferFilterTile.cs +++ b/Tiles/TransferFilterTile.cs @@ -1,14 +1,12 @@ using Microsoft.Xna.Framework; -using System; using Terraria; using Terraria.DataStructures; using Terraria.Enums; -using Terraria.ModLoader; using Terraria.ObjectData; namespace MechTransfer.Tiles { - public class TransferFilterTile : ModTile + public class TransferFilterTile : FilterableTile, ITransferPassthrough { public override void SetDefaults() { @@ -22,58 +20,39 @@ public override void SetDefaults() TileObjectData.newTile.AnchorBottom = new AnchorData(AnchorType.None, 0, 0); TileObjectData.addTile(Type); - drop = mod.ItemType("TransferFilterItem"); AddMapEntry(new Color(200, 200, 200)); - } - public override void KillTile(int i, int j, ref bool fail, ref bool effectOnly, ref bool noItem) - { - mod.GetTileEntity().Kill(i, j); + hoverText = "Item allowed:"; + + ((MechTransfer)mod).transferAgent.passthroughs.Add(Type, this); } - public override void RightClick(int i, int j) + public override void KillTile(int i, int j, ref bool fail, ref bool effectOnly, ref bool noItem) { - if (!Main.LocalPlayer.HeldItem.IsAir) + if (!effectOnly) { - int id = mod.GetTileEntity().Find(i, j); - if (id != -1) + mod.GetTileEntity().Kill(i, j); + if (!noItem) { - TransferFilterTileEntity tileEntity = (TransferFilterTileEntity)TileEntity.ByID[id]; - tileEntity.ItemId = Main.LocalPlayer.HeldItem.type; - tileEntity.SyncData(); + if (Main.tile[i, j].frameY == 0) + Item.NewItem(i * 16, j * 16, 16, 16, mod.ItemType("TransferFilterItem")); + else + Item.NewItem(i * 16, j * 16, 16, 16, mod.ItemType("InverseTransferFilterItem")); } } } - public override void MouseOverFar(int i, int j) - { - DisplayTooltip(i, j); - } - - public override void MouseOver(int i, int j) + public bool ShouldPassthrough(TransferUtils agent, Point16 location, Item item) { - DisplayTooltip(i, j); - } - - public void DisplayTooltip(int i, int j) - { - int id = mod.GetTileEntity().Find(i, j); + int id = mod.GetTileEntity().Find(location.X, location.Y); if (id == -1) - return; + return false; TransferFilterTileEntity entity = (TransferFilterTileEntity)TileEntity.ByID[id]; - if (entity.ItemId == 0) - { - Main.LocalPlayer.showItemIconText = " Filter: Empty"; - Main.LocalPlayer.showItemIcon2 = drop; - } + if (Main.tile[location.X, location.Y].frameY == 0) + return entity.ItemId == item.type; else - { - Main.LocalPlayer.showItemIconText = String.Format(" Filter: {0}", TransferUtils.ItemNameById(entity.ItemId)); - Main.LocalPlayer.showItemIcon2 = entity.ItemId; - } - - Main.LocalPlayer.showItemIcon = true; + return entity.ItemId != item.type; } } } \ No newline at end of file diff --git a/Tiles/TransferFilterTile.png b/Tiles/TransferFilterTile.png index da3988d..8c4da64 100644 Binary files a/Tiles/TransferFilterTile.png and b/Tiles/TransferFilterTile.png differ diff --git a/Tiles/TransferFilterTile.xcf b/Tiles/TransferFilterTile.xcf index e426c81..1083fd7 100644 Binary files a/Tiles/TransferFilterTile.xcf and b/Tiles/TransferFilterTile.xcf differ diff --git a/Tiles/TransferFilterTileEntity.cs b/Tiles/TransferFilterTileEntity.cs index 13ea5cb..ea7a306 100644 --- a/Tiles/TransferFilterTileEntity.cs +++ b/Tiles/TransferFilterTileEntity.cs @@ -25,7 +25,7 @@ public void SyncData() public override bool ValidTile(int i, int j) { - return Main.tile[i, j].active() && (Main.tile[i, j].type == mod.TileType()); + return Main.tile[i, j].active() && (TileLoader.GetTile(Main.tile[i, j].type) is FilterableTile); } public override TagCompound Save() diff --git a/Tiles/TransferGateTile.cs b/Tiles/TransferGateTile.cs index fe96274..8e82ce8 100644 --- a/Tiles/TransferGateTile.cs +++ b/Tiles/TransferGateTile.cs @@ -8,7 +8,7 @@ namespace MechTransfer.Tiles { - public class TransferGateTile : ModTile + public class TransferGateTile : ModTile, ITransferPassthrough { public override void SetDefaults() { @@ -23,6 +23,8 @@ public override void SetDefaults() drop = mod.ItemType("TransferGateItem"); AddMapEntry(new Color(200, 200, 200)); + + ((MechTransfer)mod).transferAgent.passthroughs.Add(Type, this); } public override void HitWire(int i, int j) @@ -39,5 +41,10 @@ public override void HitWire(int i, int j) if (Main.netMode == 2) NetMessage.SendTileSquare(-1, i, j, 1, TileChangeType.None); } + + public bool ShouldPassthrough(TransferUtils agent, Point16 location, Item item) + { + return Main.tile[location.X, location.Y].frameY == 0; + } } } \ No newline at end of file diff --git a/Tiles/TransferInjectorTile.cs b/Tiles/TransferInjectorTile.cs index d22e364..2a629a3 100644 --- a/Tiles/TransferInjectorTile.cs +++ b/Tiles/TransferInjectorTile.cs @@ -7,7 +7,7 @@ namespace MechTransfer.Tiles { - public class TransferInjectorTile : ModTile + public class TransferInjectorTile : ModTile, ITransferTarget { public override void SetDefaults() { @@ -22,6 +22,27 @@ public override void SetDefaults() drop = mod.ItemType("TransferInjectorItem"); AddMapEntry(new Color(200, 200, 200)); + + ((MechTransfer)mod).transferAgent.targets.Add(Type, this); + } + + public bool Receive(TransferUtils agent, Point16 location, Item item) + { + bool success = false; + + foreach (var container in agent.FindContainerAdjacent(location.X, location.Y)) + { + if (container.InjectItem(item)) + success = true; + + if (item.stack < 1) + break; + } + + if (success) + mod.GetModWorld().TripWireDelayed(location.X, location.Y, 1, 1); + + return success; } } } \ No newline at end of file diff --git a/Tiles/TransferInletTile.cs b/Tiles/TransferInletTile.cs index 381adcc..9b4a68b 100644 --- a/Tiles/TransferInletTile.cs +++ b/Tiles/TransferInletTile.cs @@ -2,13 +2,12 @@ using Terraria; using Terraria.DataStructures; using Terraria.Enums; -using Terraria.ID; using Terraria.ModLoader; using Terraria.ObjectData; namespace MechTransfer.Tiles { - public class TransferInletTile : ModTile + public class TransferInletTile : ModTile, ITransferPassthrough { public override void SetDefaults() { @@ -30,25 +29,21 @@ public override void SetDefaults() TileObjectData.addTile(Type); AddMapEntry(new Color(200, 200, 200)); + + ((MechTransfer)mod).transferAgent.passthroughs.Add(Type, this); } public override void KillMultiTile(int i, int j, int frameX, int frameY) { - Item.NewItem(i * 16, j * 16, 16, 16, mod.ItemType("TransferInletItem")); - mod.GetTileEntity().Kill(i, j); + int originX = (i - frameX / 18) + 1; + Item.NewItem(originX * 16, j * 16, 16, 16, mod.ItemType("TransferInletItem")); + mod.GetTileEntity().Kill(originX, j); } - public override bool CanKillTile(int i, int j, ref bool blockDamaged) + public bool ShouldPassthrough(TransferUtils agent, Point16 location, Item item) { - Tile tile = Main.tile[i, j]; - int originX = i - (tile.frameX / 18 - 1); - tile = Main.tile[originX, j - 1]; - if (tile != null && tile.active() && (TileID.Sets.BasicChest[tile.type] || TileID.Sets.BasicChestFake[tile.type])) - { - blockDamaged = true; - return false; - } - return true; + Tile tile = Main.tile[location.X, location.Y]; + return (tile.frameX == 0 || tile.frameX == 36); } } } \ No newline at end of file diff --git a/Tiles/TransferInletTileEntity.cs b/Tiles/TransferInletTileEntity.cs index 80ae5b5..1959953 100644 --- a/Tiles/TransferInletTileEntity.cs +++ b/Tiles/TransferInletTileEntity.cs @@ -33,10 +33,12 @@ public override void Update() if (!((MechTransfer)mod).PickupBlacklist.Contains(item.type) && new Rectangle((Position.X - 1) * 16, (Position.Y - 1) * 16, 48, 16).Intersects(item.getRect())) { - if (TransferUtils.StartTransfer(Position.X, Position.Y, item)) - { - TransferUtils.EatWorldItem(i); - } + item.stack -= ((MechTransfer)mod).transferAgent.StartTransfer(Position.X, Position.Y, item); + if (item.stack < 1) + Main.item[i] = new Item(); + + if (Main.netMode == 2) + NetMessage.SendData(MessageID.SyncItem, -1, -1, null, i); } } } diff --git a/Tiles/TransferOutletTile.cs b/Tiles/TransferOutletTile.cs index 50afee3..373daf4 100644 --- a/Tiles/TransferOutletTile.cs +++ b/Tiles/TransferOutletTile.cs @@ -7,7 +7,7 @@ namespace MechTransfer.Tiles { - public class TransferOutletTile : ModTile + public class TransferOutletTile : ModTile, ITransferTarget { public override void SetDefaults() { @@ -22,6 +22,16 @@ public override void SetDefaults() drop = mod.ItemType("TransferOutletItem"); AddMapEntry(new Color(200, 200, 200)); + + ((MechTransfer)mod).transferAgent.targets.Add(Type, this); + } + + public bool Receive(TransferUtils agent, Point16 location, Item item) + { + int dropTarget = Item.NewItem(location.X * 16, location.Y * 16, 16, 16, item.type, item.stack, false, item.prefix); + Main.item[dropTarget].velocity = Vector2.Zero; + item.stack = 0; + return true; } } } \ No newline at end of file diff --git a/Tiles/TransferPipeTile.cs b/Tiles/TransferPipeTile.cs index 9133d39..e9dde9f 100644 --- a/Tiles/TransferPipeTile.cs +++ b/Tiles/TransferPipeTile.cs @@ -19,6 +19,8 @@ public override void SetDefaults() TileObjectData.newTile.AnchorBottom = new AnchorData(AnchorType.None, 0, 0); TileObjectData.addTile(Type); + ((MechTransfer)mod).transferAgent.unconditionalPassthroughType = Type; + drop = mod.ItemType("TransferPipeItem"); AddMapEntry(new Color(200, 200, 200)); } diff --git a/Tiles/TransferRelayTile.cs b/Tiles/TransferRelayTile.cs index e62ba89..f6833e5 100644 --- a/Tiles/TransferRelayTile.cs +++ b/Tiles/TransferRelayTile.cs @@ -7,7 +7,7 @@ namespace MechTransfer.Tiles { - public class TransferRelayTile : ModTile + public class TransferRelayTile : ModTile, ITransferTarget { public override void SetDefaults() { @@ -25,11 +25,41 @@ public override void SetDefaults() TileObjectData.addTile(Type); AddMapEntry(new Color(200, 200, 200)); + + ((MechTransfer)mod).transferAgent.targets.Add(Type, this); } public override void KillMultiTile(int i, int j, int frameX, int frameY) { Item.NewItem(i * 16, j * 16, 16, 16, mod.ItemType("TransferRelayItem")); } + + public bool Receive(TransferUtils agent, Point16 location, Item item) + { + Tile tile = Main.tile[location.X, location.Y]; + + if (tile.frameX == 0) + { + int decrement = agent.StartTransfer(location.X + 1, location.Y, item); + item.stack -= decrement; + if (decrement != 0) + { + mod.GetModWorld().TripWireDelayed(location.X, location.Y, 2, 1); + return true; + } + } + else if (tile.frameX == 54) + { + int decrement = agent.StartTransfer(location.X - 1, location.Y, item); + item.stack -= decrement; + if (decrement != 0) + { + mod.GetModWorld().TripWireDelayed(location.X - 1, location.Y, 2, 1); + return true; + } + } + + return false; + } } } \ No newline at end of file diff --git a/TransferUtils.cs b/TransferUtils.cs index 8c76b92..cff2942 100644 --- a/TransferUtils.cs +++ b/TransferUtils.cs @@ -1,53 +1,41 @@ using MechTransfer.ContainerAdapters; -using MechTransfer.Tiles; -using Microsoft.Xna.Framework; using System.Collections.Generic; using Terraria; using Terraria.DataStructures; -using Terraria.ID; -using Terraria.Localization; -using Terraria.ModLoader; namespace MechTransfer { - public static class TransferUtils + public class TransferUtils { public enum Direction { up, down, left, right, stop } - private const float dustVelocity = 1.5f; + private HashSet TargetTriggered = new HashSet(); //stops infinite recursion + private int running = 0; - public static MechTransfer mod; - private static List relayTriggered = new List(); //stops infinite recursion + public Dictionary ContainerAdapters = new Dictionary(); + public int unconditionalPassthroughType = 0; + public Dictionary targets = new Dictionary(); + public Dictionary passthroughs = new Dictionary(); - public static void EatWorldItem(int id, int eatNumber = 1) + public int StartTransfer(int startX, int startY, Item item) { - EatItem(ref Main.item[id], eatNumber); + running++; - if (Main.netMode == 2) - NetMessage.SendData(MessageID.SyncItem, -1, -1, null, id); - } - - public static void EatItem(ref Item item, int eatNumber) - { - if (item.stack > eatNumber) - item.stack -= eatNumber; - else - item = new Item(); - } + int olstack = item.stack; + Item clone = item.Clone(); + SearchForTarget(startX, startY, clone); - public static bool StartTransfer(int startX, int startY, Item item) - { - relayTriggered.Clear(); + running--; - Item clone = item.Clone(); - clone.stack = 1; - bool result = SearchForTarget(startX, startY, clone); + if (running == 0) + { + TargetTriggered.Clear(); + } - relayTriggered.Clear(); - return result; + return olstack - clone.stack; } - private static bool SearchForTarget(int startX, int startY, Item IToTransfer) + private void SearchForTarget(int startX, int startY, Item IToTransfer) { Queue searchQ = new Queue(); Dictionary visited = new Dictionary(); @@ -74,172 +62,68 @@ private static bool SearchForTarget(int startX, int startY, Item IToTransfer) if (visited.ContainsKey(searchP)) continue; - visited.Add(searchP, (byte)dir); + visited.Add(searchP, (byte)dir);// 00000VDD Tile tile = Main.tile[searchP.X, searchP.Y]; if (tile == null || !tile.active()) continue; - bool addToQ = false; - //checking for targets - if (tile.type == mod.TileType() && !relayTriggered.Contains(searchP)) + ITransferTarget target; + if (!TargetTriggered.Contains(searchP) && targets.TryGetValue(tile.type, out target)) { - if (tile.frameX == 0) - { - relayTriggered.Add(searchP); - if (SearchForTarget(searchP.X + 1, searchP.Y, IToTransfer)) - { - mod.GetModWorld().TripWireDelayed(searchP.X, searchP.Y, 2, 1); - UnwindVisuals(visited, searchP); - return true; - } - } - if (tile.frameX == 54) - { - relayTriggered.Add(searchP); - if (SearchForTarget(searchP.X - 1, searchP.Y, IToTransfer)) - { - mod.GetModWorld().TripWireDelayed(searchP.X - 1, searchP.Y, 2, 1); - UnwindVisuals(visited, searchP); - return true; - } - } - } - else if (tile.type == mod.TileType() && InjectItem(searchP.X, searchP.Y, IToTransfer)) - { - mod.GetModWorld().TripWireDelayed(searchP.X, searchP.Y, 1, 1); - UnwindVisuals(visited, searchP); - return true; - } - else if (tile.type == mod.TileType()) - { - DropItem(searchP.X, searchP.Y, IToTransfer); - mod.GetModWorld().TripWireDelayed(searchP.X, searchP.Y, 1, 1); - UnwindVisuals(visited, searchP); - return true; + TargetTriggered.Add(searchP); + if (target.Receive(this, searchP, IToTransfer)) + VisualUtils.UnwindVisuals(visited, searchP); } + if (IToTransfer.stack == 0) + return; + //checking for pipes - else if (tile.type == mod.TileType()) - addToQ = true; - else if (tile.type == mod.TileType() && (tile.frameX == 0 || tile.frameX == 36)) - addToQ = true; - else if (tile.type == mod.TileType() && tile.frameY == 0) - addToQ = true; - else if (tile.type == mod.TileType()) + if (tile.type == unconditionalPassthroughType) { - int id = mod.GetTileEntity().Find(searchP.X, searchP.Y); - if (id != -1 && (((TransferFilterTileEntity)TileEntity.ByID[id]).ItemId == 0 || IToTransfer.type == ((TransferFilterTileEntity)TileEntity.ByID[id]).ItemId)) - addToQ = true; - } - - if (addToQ) searchQ.Enqueue(searchP); - } - } - return false; - } - - private static void UnwindVisuals(Dictionary visited, Point16 startPoint) - { - MechTransferWorld world = mod.GetModWorld(); - - Point16 p = startPoint; - - while (visited.ContainsKey(p)) - { - Direction dir = (Direction)visited[p]; - - Vector2 velocity = Vector2.Zero; - - switch (dir) - { - case Direction.up: p = new Point16(p.X, p.Y - 1); velocity.Y = dustVelocity; break; - case Direction.down: p = new Point16(p.X, p.Y + 1); velocity.Y = -dustVelocity; break; - case Direction.left: p = new Point16(p.X - 1, p.Y); velocity.X = dustVelocity; break; - case Direction.right: p = new Point16(p.X + 1, p.Y); velocity.X = -dustVelocity; break; - case Direction.stop: return; - } - - Vector2 location = new Vector2(p.X * 16 + 8, p.Y * 16 + 8); - - if (Main.netMode == 0) - { - Dust.NewDustPerfect(location, DustID.Silver, velocity).noGravity = true; - } - else - { - ModPacket packet = mod.GetPacket(); - packet.Write((byte)MechTransfer.ModMessageID.CreateDust); - packet.WriteVector2(location); - packet.WriteVector2(velocity); - packet.Send(); + } + else + { + ITransferPassthrough passthrough; + if (passthroughs.TryGetValue(tile.type, out passthrough)) + { + if (passthrough.ShouldPassthrough(this, searchP, IToTransfer)) + searchQ.Enqueue(searchP); + } + } } } } - public static bool InjectItem(int x, int y, Item item) - { - List found = FindContainerAdjacent(x, y); - - foreach (var container in found) - { - if (container.InjectItem(item)) - return true; - } - return false; - } - - public static void DropItem(int x, int y, Item item) - { - int dropTarget = Item.NewItem(x * 16, y * 16, item.width, item.height, item.type); - item.position = Main.item[dropTarget].position; - item.velocity.X = 0; - item.velocity.Y = 0; - Main.item[dropTarget] = item; - } - //search order: Up, Down, Left, Right - public static List FindContainerAdjacent(int x, int y) + public IEnumerable FindContainerAdjacent(int x, int y) { - List found = new List(); ContainerAdapter c; c = FindContainer(x, y - 1); if (c != null) - found.Add(c); + yield return c; c = FindContainer(x, y + 1); if (c != null) - found.Add(c); + yield return c; c = FindContainer(x - 1, y); if (c != null) - found.Add(c); + yield return c; c = FindContainer(x + 1, y); if (c != null) - found.Add(c); - - return found; + yield return c; } - public static ContainerAdapter FindContainer(int x, int y) + public ContainerAdapter FindContainer(int x, int y) { ContainerAdapterDefinition c; Tile tile = Main.tile[x, y]; - if (tile != null && tile.active() && mod.ContainerAdapters.TryGetValue(tile.type, out c)) + if (tile != null && tile.active() && ContainerAdapters.TryGetValue(tile.type, out c)) return c.GetAdapter(x, y); return null; } - - public static string ItemNameById(int id) - { - if (id == 0) - return ""; - - LocalizedText name = Lang.GetItemName(id); - if (name == LocalizedText.Empty) - return string.Format("Unknown item #{0}", id); - return name.Value; - } } } \ No newline at end of file diff --git a/UI/FilterHoverUI.cs b/UI/FilterHoverUI.cs new file mode 100644 index 0000000..ee82d25 --- /dev/null +++ b/UI/FilterHoverUI.cs @@ -0,0 +1,75 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Terraria; +using Terraria.GameContent.UI; +using Terraria.GameContent.UI.Elements; +using Terraria.UI; + +namespace MechTransfer.UI +{ + public class FilterHoverUI : UIState + { + public bool visible = false; + + private UIPanel panel; + private UIText itemText; + private UIText titleText; + private Item[] fakeInv = new Item[11]; + + public override void OnInitialize() + { + fakeInv[10] = new Item(); + + titleText = new UIText("Not set"); + titleText.Left.Set(5, 0); + titleText.Top.Set(5, 0); + Append(titleText); + + panel = new UIPanel(); + panel.Left.Set(0, 0); + panel.Top.Set(25, 0); + panel.Width.Set(200, 0); + panel.Height.Set(Main.inventoryBackTexture.Height * 0.5f * Main.UIScale + 10, 0); + + itemText = new UIText("N/A"); + itemText.Left.Set(Main.inventoryBackTexture.Width * 0.5f * Main.UIScale, 0); + itemText.Top.Set(0, 0); + panel.Append(itemText); + + Append(panel); + } + + public void Display(int type, string text, Color textColor) + { + visible = true; + + titleText.SetText(text); + titleText.TextColor = textColor; + + fakeInv[10].SetDefaults(type); + itemText.SetText(type == 0 ? "Not set" : fakeInv[10].Name); + itemText.TextColor = type == 0 ? Color.Red : ItemRarity.GetColor(fakeInv[10].rare); + panel.Width.Pixels = itemText.MinWidth.Pixels + Main.inventoryBackTexture.Width * 0.5f * Main.UIScale + 20; + + Left.Pixels = Main.mouseX + 10; + Top.Pixels = Main.mouseY + 10; + + Recalculate(); + } + + public override void Draw(SpriteBatch spriteBatch) + { + if (!visible) + return; + + base.Draw(spriteBatch); + + float oldScale = Main.inventoryScale; + Main.inventoryScale = 0.5f; + ItemSlot.Draw(spriteBatch, fakeInv, ItemSlot.Context.InventoryItem, 10, new Vector2(Left.Pixels + 5, Top.Pixels + 30)); + Main.inventoryScale = oldScale; + + visible = false; + } + } +} \ No newline at end of file diff --git a/VisualUtils.cs b/VisualUtils.cs new file mode 100644 index 0000000..d9f6a9f --- /dev/null +++ b/VisualUtils.cs @@ -0,0 +1,83 @@ +using Microsoft.Xna.Framework; +using System.Collections.Generic; +using Terraria; +using Terraria.DataStructures; +using Terraria.ID; +using Terraria.ModLoader; + +namespace MechTransfer +{ + public static class VisualUtils + { + private const float dustVelocity = 1.5f; + + private static MechTransfer mod = (MechTransfer)ModLoader.GetMod("MechTransfer"); + + public static void UnwindVisuals(Dictionary visited, Point16 startPoint) + { + Point16 p = startPoint; + + while (visited.ContainsKey(p)) + { + TransferUtils.Direction dir = (TransferUtils.Direction)visited[p]; + visited[p] = (byte)TransferUtils.Direction.stop; //Stops multiple particles, if multiple containers receive + + switch (dir) + { + case TransferUtils.Direction.up: p = new Point16(p.X, p.Y - 1); break; + case TransferUtils.Direction.down: p = new Point16(p.X, p.Y + 1); break; + case TransferUtils.Direction.left: p = new Point16(p.X - 1, p.Y); break; + case TransferUtils.Direction.right: p = new Point16(p.X + 1, p.Y); break; + case TransferUtils.Direction.stop: return; + } + + if (Main.netMode == 0) + { + CreateVisual(p, dir); + } + else + { + ModPacket packet = mod.GetPacket(); + packet.Write((byte)MechTransfer.ModMessageID.CreateDust); + packet.WritePackedVector2(p.ToVector2()); + packet.Write((byte)dir); + packet.Send(); + } + } + } + + public static void CreateVisual(Point16 point, TransferUtils.Direction dir) + { + Vector2 location = new Vector2(point.X * 16 + 8, point.Y * 16 + 8); + Vector2 velocity = Vector2.Zero; + + switch (dir) + { + case TransferUtils.Direction.up: velocity.Y = dustVelocity; break; + case TransferUtils.Direction.down: velocity.Y = -dustVelocity; break; + case TransferUtils.Direction.left: velocity.X = dustVelocity; break; + case TransferUtils.Direction.right: velocity.X = -dustVelocity; break; + case TransferUtils.Direction.stop: return; + } + + Dust dust = Dust.NewDustPerfect(location, DustID.Silver, velocity); + dust.noGravity = true; + + if (Main.xMas) + { + if (point.X % 2 == point.Y % 2) + dust.color = Color.Red; + else + dust.color = Color.LightGreen; + } + + if (Main.halloween) + { + if (point.X % 2 == point.Y % 2) + dust.color = Color.MediumPurple; + else + dust.color = Color.Orange; + } + } + } +} \ No newline at end of file diff --git a/build.txt b/build.txt index 0a2b82b..1395ade 100644 --- a/build.txt +++ b/build.txt @@ -1,7 +1,8 @@ author = DRKV -version = 1.4.2 +version = 1.5 displayName = MechTransfer includePDB = false +weakReferences = MagicStorage@0.4.3.1 buildIgnore = .gitignore, description.txt, *.csproj*, *.sln, .git/*, .vs/*, bin/*, obj/*, *.xcf hideCode = false hideResources = false diff --git a/description.txt b/description.txt index 6aefc77..82b1394 100644 --- a/description.txt +++ b/description.txt @@ -45,4 +45,10 @@ v1.4.1 - Fixed modded chest support v1.4.2 -- Quick fix to stop assembler from eating items \ No newline at end of file +- Quick fix to stop assembler from eating items + +v1.5 +- New tool-tip +- Added Magic Storage Interface +- Added blacklist filter +- Added Stack extractor \ No newline at end of file diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..0fdcadf Binary files /dev/null and b/icon.png differ diff --git a/icon.xcf b/icon.xcf new file mode 100644 index 0000000..773ae95 Binary files /dev/null and b/icon.xcf differ