diff --git a/.gitignore b/.gitignore index 8d4a6c0..8350d77 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ bin -obj \ No newline at end of file +obj +*.sln +*.vs \ No newline at end of file diff --git a/Config.cs b/Config.cs new file mode 100644 index 0000000..d86cc95 --- /dev/null +++ b/Config.cs @@ -0,0 +1,228 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using Terraria; +using Terraria.ID; +using Terraria.Localization; +using Terraria.ModLoader; + +namespace OmniSwing +{ + //so I spent like half a day coding this + //tML says they'll add ModConfig soon, what do I do? + static class Config + { + public static List BlacklistedItemIDs = new List(); + public static List WhitelistedItemIDs = new List(); + + static List ErrorLines = new List(); + + static string ConfigFolderPath = Path.Combine(Main.SavePath, "Mod Configs"); + static string ConfigPath = Path.Combine(ConfigFolderPath, "OmniSwing.txt"); + + public static void Load() + { + if(!Directory.Exists(ConfigFolderPath)) + { + OmniSwing.Log("Mod Config directory not found, creating..."); + Directory.CreateDirectory(ConfigFolderPath); + } + + if(File.Exists(ConfigPath)) + { + Reset(); + ReadConfig(); + } + else + { + OmniSwing.Log("Config file not found, creating default..."); + SetDefaults(); + SaveConfig(); + } + } + + static void ReadConfig() + { + int lineNumber = 0; + using(var reader = new StreamReader(ConfigPath)) + { + while(!reader.EndOfStream) + { + lineNumber++; + string line = reader.ReadLine().Split('#')[0].Trim(); + if(line.Length == 0) + continue; + + if(line[0] == '!') + { + line = line.Remove(0, 1).Trim(); + ParseConfigLine(line, lineNumber, WhitelistedItemIDs); + } + else + { + ParseConfigLine(line, lineNumber, BlacklistedItemIDs); + } + } + } + } + + static void ParseConfigLine(string line, int lineNumber, List idList) + { + int id = 0; + if(Int32.TryParse(line, out id)) + { + if(id <= 0 || id >= ItemID.Count) + throw new Exception(id + " is not a valid Vanilla Item ID!"); + idList.Add(id); + } + else + { + string[] splitLine = line.Split(':'); + if(splitLine.Length < 2) + throw new Exception("Wrong config file format at line " + lineNumber); + + var mod = ModLoader.GetMod(splitLine[0]); + if(mod == null) + { + ErrorLines.Add(line); + return; + } + id = mod.ItemType(splitLine[1]); + if(id == 0) + { + ErrorLines.Add(line); + return; + } + idList.Add(id); + } + } + + public static void SetDefaults() + { + Reset(); + BlacklistedItemIDs = new List(new int[] + { + ItemID.MagicDagger, + ItemID.PhoenixBlaster + }); + } + + static void Reset() + { + ErrorLines.Clear(); + BlacklistedItemIDs.Clear(); + WhitelistedItemIDs.Clear(); + } + + public static void SaveConfig() + { + File.WriteAllLines(ConfigPath, new string[] + { + "# This is the OmniSwing configuration file. Please use the /omniSwing command to modify this.", + "# (or edit this manually if you know what you're doing)", + "# Each line is a new blacklisted item.", + "# If it's a Vanilla item, add the item ID directly.", + "# If it's a modded item, specify its name in this format:", + "# InternalModName:InternalItemName", + "# (use WMITF's Internal Name button to see the internal names)", + "# Any item that starts with an exclamation mark ! will auto-swing even if it's not a weapon (whitelist)", + "# Anything that comes after a # sign will be ignored (like these comments)", + }); + foreach(int id in BlacklistedItemIDs) + { + if(id < ItemID.Count) + { + File.AppendAllLines(ConfigPath, new string[] { id + " # " + Lang.GetItemNameValue(id) }); + } + else if(id < ItemLoader.ItemCount) + { + var item = new Item(); + item.SetDefaults(); + if(item.modItem != null) + { + string modName = item.modItem.mod.Name; + string itemName = item.modItem.Name; + File.AppendAllLines(ConfigPath, new string[] { modName + ':' + itemName + " # " + Lang.GetItemNameValue(id) }); + } + } + } + foreach(int id in WhitelistedItemIDs) + { + if(id < ItemID.Count) + { + File.AppendAllLines(ConfigPath, new string[] { "! " + id + " # " + Lang.GetItemNameValue(id) }); + } + else if(id < ItemLoader.ItemCount) + { + var item = new Item(); + item.SetDefaults(); + if(item.modItem != null) + { + string modName = item.modItem.mod.Name; + string itemName = item.modItem.Name; + File.AppendAllLines(ConfigPath, new string[] { "! " + modName + ':' + itemName + " # " + Lang.GetItemNameValue(id) }); + } + } + } + } + + public static void PrintErrors() + { + if(ErrorLines.Count == 0) + return; + Main.NewText(Language.GetTextValue("Mods.OmniSwing.ConfigLineError1"), Colors.RarityRed); + Main.NewText(Language.GetTextValue("Mods.OmniSwing.ConfigLineError2"), Colors.RarityRed); + Main.NewText(Language.GetTextValue("Mods.OmniSwing.ConfigLineError3"), Colors.RarityRed); + foreach(var line in ErrorLines) + Main.NewText(line, Colors.RarityRed); + Main.NewText(Language.GetTextValue("Mods.OmniSwing.ConfigLineError4"), Colors.RarityRed); + } + + public class MultiplayerSyncWorld : ModWorld + { + public override void NetSend(BinaryWriter writer) + { + writer.Write(BlacklistedItemIDs.Count); + foreach(int id in BlacklistedItemIDs) + writer.Write(id); + + writer.Write(WhitelistedItemIDs.Count); + foreach(int id in WhitelistedItemIDs) + writer.Write(id); + } + + public override void NetReceive(BinaryReader reader) + { + ErrorLines.Clear(); + + int count = reader.ReadInt32(); + BlacklistedItemIDs = new List(count); + for(int i = 0; i < count; i++) + BlacklistedItemIDs.Add(reader.ReadInt32()); + + count = reader.ReadInt32(); + WhitelistedItemIDs = new List(count); + for(int i = 0; i < count; i++) + WhitelistedItemIDs.Add(reader.ReadInt32()); + } + } + + public class MultiplayerSyncPlayer : ModPlayer + { + public override void OnEnterWorld(Player player) + { + if(ErrorLines.Count > 0) + { + PrintErrors(); + } + } + + public override void PlayerDisconnect(Player player) + { + Config.Load(); + } + } + } +} diff --git a/Localization/en-US.lang b/Localization/en-US.lang new file mode 100644 index 0000000..b0e4ee3 --- /dev/null +++ b/Localization/en-US.lang @@ -0,0 +1,12 @@ +ConfigLineError1=[OmniSwing configuration] +ConfigLineError2=There was an error while loading the OmniSwing configuration file. +ConfigLineError3=These items weren't loaded: +ConfigLineError4=Either the mods are disabled, or the names are incorrect. + +CommandDescription=Allows disabling or enabling OmniSwing on an item you hold in your hand. +CommandWhitelistAdded={0} added to OmniSwing whitelist. +CommandWhitelistRemoved={0} removed from OmniSwing whitelist. +CommandBlacklistAdded={0} added to OmniSwing blacklist. +CommandBlacklistRemoved={0} removed from OmniSwing blacklist. +CommandUsage=You're not holding any item! +CommandServerOnly=This command can only be executed by the server owner. \ No newline at end of file diff --git a/Localization/ru-RU.lang b/Localization/ru-RU.lang new file mode 100644 index 0000000..58c3ad0 --- /dev/null +++ b/Localization/ru-RU.lang @@ -0,0 +1,12 @@ +ConfigLineError1=[конфигурация OmniSwing] +ConfigLineError2=Во время загрузки конфигурации OmniSwing произошла ошибка. +ConfigLineError3=Эти предметы не были найдены в игре: +ConfigLineError4=Либо эти моды выключены, либо вы неправильно указали имена предметов. + +CommandDescription=Позволяет включать/выключать авто-использование предмета, который вы держите руке. +CommandWhitelistAdded=OmniSwing включен для предмета: {0} +CommandWhitelistRemoved=OmniSwing выключен для предмета: {0} +CommandBlacklistAdded=OmniSwing выключен для предмета: {0} +CommandBlacklistRemoved=OmniSwing включен для предмета: {0} +CommandUsage=У вас в руке нет предмета! +CommandServerOnly=Эту команду может исользовать только владелец сервера. \ No newline at end of file diff --git a/OmniSwing.cs b/OmniSwing.cs index 37e7ba6..dccfdb7 100644 --- a/OmniSwing.cs +++ b/OmniSwing.cs @@ -1,68 +1,83 @@  using System; using System.Collections.Generic; +using System.IO; using System.Reflection; using Terraria; using Terraria.ID; +using Terraria.Localization; using Terraria.ModLoader; namespace OmniSwing { public class OmniSwing : Mod { - //Hamstar's Mod Helpers integration + public override void PostSetupContent() + { + Config.Load(); + } + + public override void HandlePacket(BinaryReader reader, int whoAmI) + { + if(Main.netMode == NetmodeID.Server) + return; + + var messageType = (MessageType)reader.ReadByte(); + int itemID = reader.ReadInt32(); + switch(messageType) + { + case MessageType.BlacklistItemAdd: + Config.BlacklistedItemIDs.Add(itemID); + break; + case MessageType.WhitelistItemAdd: + Config.WhitelistedItemIDs.Add(itemID); + break; + case MessageType.BlacklistItemRemove: + Config.BlacklistedItemIDs.Remove(itemID); + break; + case MessageType.WhitelistItemRemove: + Config.WhitelistedItemIDs.Add(itemID); + break; + } + } + + public enum MessageType : byte + { + BlacklistItemAdd = 0, + WhitelistItemAdd = 1, + BlacklistItemRemove = 2, + WhitelistItemRemove = 3 + } + + #region Hamstar's Mod Helpers integration + public static string GithubUserName { get { return "goldenapple3"; } } public static string GithubProjectName { get { return "OmniSwing"; } } - } - - class SwingGlobalItem : GlobalItem - { - public override void SetDefaults(Item item) + + public static string ConfigFileRelativePath { get { return "Mod Configs/OmniSwing.txt"; } } + + public static void ReloadConfigFromFile() { - if(ShouldAutoSwing(item)) - item.autoReuse = true; + Config.Load(); + Config.PrintErrors(); } - - public override bool CanUseItem(Item item, Player player) + + public static void ResetConfigFromDefaults() { - if(ShouldAutoSwing(item)) - item.autoReuse = true; - return base.CanUseItem(item, player); + Config.SetDefaults(); + Config.SaveConfig(); } - - static bool ShouldAutoSwing(Item item) + + #endregion + + public static void Log(object message) { - try - { - if(item.damage <= 0 || item.summon || item.sentry) - return false; - - if(item.shoot > 0) - { - var projectile = new Projectile(); - projectile.SetDefaults(item.shoot); - //Magic Missile-type projectiles get buggy with auto-swing - return projectile.aiStyle != 9; - } - return true; - } - catch(NullReferenceException e) - { - return false; - } + ErrorLogger.Log(String.Format("[OmniSwing][{0}] {1}", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"), message)); } - } - - //spear fix by CrimsHallowHero - class SwingGlobalProjectile : GlobalProjectile - { - public override void AI(Projectile projectile) + + public static void Log(string message, params object[] formatData) { - if((projectile.aiStyle == 19 || projectile.aiStyle == 699) && projectile.timeLeft > Main.player[projectile.owner].itemAnimation) - { - projectile.timeLeft = Main.player[projectile.owner].itemAnimation; - projectile.netUpdate = true; - } + ErrorLogger.Log(String.Format("[OmniSwing][{0}] {1}", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"), String.Format(message, formatData))); } } -} +} \ No newline at end of file diff --git a/OmniSwing.csproj b/OmniSwing.csproj index 08920b5..9982cfc 100644 --- a/OmniSwing.csproj +++ b/OmniSwing.csproj @@ -1,7 +1,7 @@  - {EFE25AFF-85C2-424F-A145-9195309B4205} + {7C86A562-70DF-405F-811C-C62C4B4C3CFF} {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} Debug AnyCPU @@ -44,16 +44,21 @@ 3.5 - - ..\..\..\..\..\..\..\Yurik\Steam\SteamApps\common\Terraria\tModLoader.exe + + ..\..\..\..\Steam\SteamApps\common\Terraria\Terraria.exe + + + + + \ No newline at end of file diff --git a/OmniSwingCommand.cs b/OmniSwingCommand.cs new file mode 100644 index 0000000..361620c --- /dev/null +++ b/OmniSwingCommand.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Terraria; +using Terraria.ID; +using Terraria.Localization; +using Terraria.ModLoader; + +namespace OmniSwing +{ + public class BlacklistCommand : ModCommand + { + public override string Command { get { return "omniSwing"; } } + + public override CommandType Type { get { return CommandType.World; } } + + public override string Description { get { return Language.GetTextValue("Mods.OmniSwing.CommandDescription"); } } + + public override string Usage { get { return "/omniSwing"; } } + + public override void Action(CommandCaller caller, string input, string[] args) + { + if(Main.netMode == NetmodeID.MultiplayerClient || caller.Player == null) + { + caller.Reply(Language.GetTextValue("Mods.OmniSwing.CommandServerOnly")); + } + if(caller.Player.HeldItem != null && caller.Player.HeldItem.stack > 0 && caller.Player.HeldItem.type > 0) + { + var item = caller.Player.HeldItem; + if(SwingHandler.ShouldAutoSwingDefault(item)) + { + if(Config.BlacklistedItemIDs.Contains(item.type)) + { + Config.BlacklistedItemIDs.Remove(item.type); + caller.Reply(Language.GetTextValue("Mods.OmniSwing.CommandBlacklistRemoved", item.Name)); + if(Main.netMode != NetmodeID.SinglePlayer) + { + var message = mod.GetPacket(); + message.Write((byte)OmniSwing.MessageType.BlacklistItemRemove); + message.Write(item.type); + message.Send(); + } + } + else + { + Config.BlacklistedItemIDs.Add(item.type); + caller.Reply(Language.GetTextValue("Mods.OmniSwing.CommandBlacklistAdded", item.Name)); + if(Main.netMode != NetmodeID.SinglePlayer) + { + var message = mod.GetPacket(); + message.Write((byte)OmniSwing.MessageType.BlacklistItemAdd); + message.Write(item.type); + message.Send(); + } + } + } + else + { + if(Config.WhitelistedItemIDs.Contains(item.type)) + { + Config.WhitelistedItemIDs.Remove(item.type); + caller.Reply(Language.GetTextValue("Mods.OmniSwing.CommandWhitelistRemoved", item.Name)); + if(Main.netMode != NetmodeID.SinglePlayer) + { + var message = mod.GetPacket(); + message.Write((byte)OmniSwing.MessageType.WhitelistItemRemove); + message.Write(item.type); + message.Send(); + } + } + else + { + Config.WhitelistedItemIDs.Add(item.type); + caller.Reply(Language.GetTextValue("Mods.OmniSwing.CommandWhitelistAdded", item.Name)); + if(Main.netMode != NetmodeID.SinglePlayer) + { + var message = mod.GetPacket(); + message.Write((byte)OmniSwing.MessageType.WhitelistItemAdd); + message.Write(item.type); + message.Send(); + } + } + } + Config.SaveConfig(); + } + else + { + caller.Reply(Language.GetTextValue("Mods.OmniSwing.CommandUsage"), Colors.RarityRed); + } + } + } +} diff --git a/SwingHandler.cs b/SwingHandler.cs new file mode 100644 index 0000000..a7e4ed1 --- /dev/null +++ b/SwingHandler.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Terraria; +using Terraria.ModLoader; + +namespace OmniSwing +{ + public static class SwingHandler + { + public static bool ShouldAutoSwing(Item item) + { + return Config.WhitelistedItemIDs.Contains(item.type) || + (ShouldAutoSwingDefault(item) && !Config.BlacklistedItemIDs.Contains(item.type)); + } + + public static bool ShouldAutoSwingDefault(Item item) + { + if(item.damage <= 0 || item.summon || item.sentry) + return false; + + if(item.shoot > 0) + { + var projectile = new Projectile(); + projectile.SetDefaults(item.shoot); + return projectile.aiStyle != 9; + } + + return true; + } + + class SwingGlobalItem : GlobalItem + { + public override bool InstancePerEntity { get { return true; } } + + //public override void SetDefaults(Item item) + //{ + // if(ShouldAutoSwing(item)) + // item.autoReuse = true; + //} + + bool RealAutoReuseValue = false; + bool FakeAutoReuse = false; + + public override bool CanUseItem(Item item, Player player) + { + if(ShouldAutoSwing(item)) + { + if(!FakeAutoReuse) + { + RealAutoReuseValue = item.autoReuse; + FakeAutoReuse = true; + } + item.autoReuse = true; + } + else + { + if(FakeAutoReuse) + { + item.autoReuse = RealAutoReuseValue; + FakeAutoReuse = false; + } + } + return base.CanUseItem(item, player); + } + + public override GlobalItem NewInstance(Item item) + { + return new SwingGlobalItem(); + } + + public override GlobalItem Clone(Item item, Item itemClone) + { + return new SwingGlobalItem(); + } + } + + //spear fix by CrimsHallowHero + class SwingGlobalProjectile : GlobalProjectile + { + public override void AI(Projectile projectile) + { + if((projectile.aiStyle == 19 || projectile.aiStyle == 699) && + ShouldAutoSwing(Main.player[projectile.owner].HeldItem) && + projectile.timeLeft > Main.player[projectile.owner].itemAnimation) + { + projectile.timeLeft = Main.player[projectile.owner].itemAnimation; + projectile.netUpdate = true; + } + } + } + } +} diff --git a/build.txt b/build.txt index 028c537..c8837fb 100644 --- a/build.txt +++ b/build.txt @@ -1,8 +1,8 @@ displayName = OmniSwing author = goldenapple -version = 1.10 +version = 2.0 homepage = http://forums.terraria.org/index.php?threads/vanilla-tweaks-other-little-tweak-mods.37443/#OmniSwing hideResources = false -hideCode = false includeSource = true -buildIgnore = obj\*, bin\*, *.csproj, .git\* \ No newline at end of file +buildIgnore = obj\*, bin\*, *.csproj, *.sln, .git\* +includePDB = true \ No newline at end of file diff --git a/description.txt b/description.txt index 7b2c959..fc805fd 100644 --- a/description.txt +++ b/description.txt @@ -1,5 +1,7 @@ -Makes every weapon in the game auto-swing/auto-shoot. +Makes every weapon in the game auto-swing/auto-shoot. Because why the heck not? +NEW IN V2.0: Configurable via /omniSwing command! + Thanks to CrimsHallowHero for fixing spears. \ No newline at end of file