From 0b20396ef1cceda571e7461810d855aff24c6593 Mon Sep 17 00:00:00 2001 From: xien <2383759126@qq.com> Date: Sun, 14 Apr 2024 20:34:38 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=EF=BC=9ADeathDrop=20=E6=80=AA=E7=89=A9=E6=AD=BB=E9=9A=8F?= =?UTF-8?q?=E6=9C=BA=E5=92=8C=E8=87=AA=E5=AE=9A=E4=B9=89=E7=89=A9=E5=93=81?= =?UTF-8?q?=E6=8E=89=E8=90=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DeathDrop/DeathDrop.cs | 154 +++++++++++++++++++++++++++++++++++ DeathDrop/DeathDrop.csproj | 3 + DeathDrop/DeathDropConfig.cs | 62 ++++++++++++++ Plugin.sln | 10 +++ 4 files changed, 229 insertions(+) create mode 100644 DeathDrop/DeathDrop.cs create mode 100644 DeathDrop/DeathDrop.csproj create mode 100644 DeathDrop/DeathDropConfig.cs diff --git a/DeathDrop/DeathDrop.cs b/DeathDrop/DeathDrop.cs new file mode 100644 index 000000000..1ef59d837 --- /dev/null +++ b/DeathDrop/DeathDrop.cs @@ -0,0 +1,154 @@ +using System; +using System.IO; +using Microsoft.Xna.Framework; +using Newtonsoft.Json; +using Terraria; +using TerrariaApi.Server; +using TShockAPI; + +namespace DeathDrop +{ + [ApiVersion(2, 1)] + public class DeathDrop : TerrariaPlugin + { + public static Random RandomGenerator = new Random(); + + public override string Author => "大豆子,肝帝熙恩更新优化"; + public override string Description => "自定义怪物死亡随机掉落物"; + public override string Name => "死亡随机掉落"; + public override Version Version => new Version(1, 0, 1); + + public DeathDrop(Main game) : base(game) { } + + public override void Initialize() + { + ServerApi.Hooks.NpcKilled.Register(this, NPCDead); + } + + private void NPCDead(NpcKilledEventArgs args) + { + int npcNetID = args.npc.netID; + Vector2 npcPosition = args.npc.position; + + // 获取击杀者玩家(可能为 null) + TSPlayer player = args.npc.lastInteraction != 255 && args.npc.lastInteraction >= 0 + ? TShock.Players[args.npc.lastInteraction] + : null; + + try + { + DeathDropConfig config = DeathDropConfig.GetConfig(); + + if (config.EnableRandomDrops) + { + int itemId = GetRandomItemIdFromGlobalConfig(config); + + if (Candorp(config.RandomDropChance)) + { + Item item = TShock.Utils.GetItemById(itemId); + int dropAmount = RandomGenerator.Next(config.MinRandomDropAmount, config.MaxRandomDropAmount + 1); + + int itemNumber = Item.NewItem( + null, + (int)args.npc.position.X, + (int)args.npc.position.Y, + item.width, + item.height, + item.type, + dropAmount + ); + + // 只有当玩家不为 null 时才发送数据包 + if (player != null) + { + player.SendData(PacketTypes.SyncExtraValue, null, itemNumber); + player.SendData(PacketTypes.ItemOwner, null, itemNumber); + player.SendData(PacketTypes.TweakItem, null, itemNumber, 255f, 63f); + } + } + } + + if (config.EnableCustomDrops) + { + foreach (DeathDropConfig.Monster monster in config.DeathDropSet) + { + if (monster.NPCID == npcNetID && Candorp(monster.DropChance)) + { + int dropItemId = GetRandomItemIdFromMonsterConfig(monster); + + Item dropItem = TShock.Utils.GetItemById(dropItemId); + int dropAmount = RandomGenerator.Next(monster.RandomDropMinAmount, monster.RandomDropMaxAmount + 1); + + int dropItemNumber = Item.NewItem( + null, + (int)npcPosition.X, + (int)npcPosition.Y, + dropItem.width, + dropItem.height, + dropItem.type, + dropAmount + ); + + // 只有当玩家不为 null 时才发送数据包 + if (player != null) + { + player.SendData(PacketTypes.SyncExtraValue, null, dropItemNumber); + player.SendData(PacketTypes.ItemOwner, null, dropItemNumber); + player.SendData(PacketTypes.TweakItem, null, dropItemNumber, 255f, 63f); + } + } + } + } + } + catch (Exception ex) + { + Console.WriteLine($"死亡掉落插件发生异常:{ex.Message}"); + } + } + + private int GetRandomItemIdFromGlobalConfig(DeathDropConfig config) + { + if (config.FullRandomDrops) + { + int itemId = RandomGenerator.Next(1, 5453); + + while (config.FullRandomExcludedItems.Contains(itemId)) + { + itemId = RandomGenerator.Next(1, 5453); + } + + return itemId; + } + else + { + int randomIndex = RandomGenerator.Next(config.CommonRandomDrops.Count); + return config.CommonRandomDrops[randomIndex]; + } + } + + private int GetRandomItemIdFromMonsterConfig(DeathDropConfig.Monster monster) + { + if (monster.FullRandomDrops) + { + int itemId = RandomGenerator.Next(1, 5453); + + while (monster.FullRandomExcludedItems.Contains(itemId)) + { + itemId = RandomGenerator.Next(1, 5453); + } + + return itemId; + } + else + { + int randomIndex = RandomGenerator.Next(monster.CommonRandomDrops.Count); + return monster.CommonRandomDrops[randomIndex]; + } + } + + private static bool Candorp(int probability) + { + return RandomGenerator.Next(100) <= probability; + } + } +} \ No newline at end of file diff --git a/DeathDrop/DeathDrop.csproj b/DeathDrop/DeathDrop.csproj new file mode 100644 index 000000000..11a03c671 --- /dev/null +++ b/DeathDrop/DeathDrop.csproj @@ -0,0 +1,3 @@ + + + diff --git a/DeathDrop/DeathDropConfig.cs b/DeathDrop/DeathDropConfig.cs new file mode 100644 index 000000000..ab38cef08 --- /dev/null +++ b/DeathDrop/DeathDropConfig.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; +using System.IO; +using Newtonsoft.Json; +using TShockAPI; + +namespace DeathDrop +{ + internal class DeathDropConfig + { + public class Monster + { + [JsonProperty("生物id")] + public int NPCID { get; set; } = 0; + [JsonProperty("完全随机掉落")] + public bool FullRandomDrops { get; set; } = false; + [JsonProperty("完全随机掉落排除物品ID")] + public List FullRandomExcludedItems { get; set; } = new List(); + [JsonProperty("普通随机掉落物")] + public List CommonRandomDrops { get; set; } = new List(); + [JsonProperty("随机掉落数量最小值")] + public int RandomDropMinAmount { get; set; } = 1; + [JsonProperty("随机掉落数量最大值")] + public int RandomDropMaxAmount { get; set; } = 1; + [JsonProperty("掉落概率")] + public int DropChance { get; set; } = 100; + } + + [JsonProperty("是否开启随机掉落")] + public bool EnableRandomDrops { get; set; } = false; + [JsonProperty("完全随机掉落")] + public bool FullRandomDrops { get; set; } = false; + [JsonProperty("完全随机掉落排除物品ID")] + public List FullRandomExcludedItems { get; set; } = new List(); + [JsonProperty("普通随机掉落物")] + public List CommonRandomDrops { get; set; } = new List(); + [JsonProperty("随机掉落概率")] + public int RandomDropChance { get; set; } = 100; + [JsonProperty("随机掉落数量最小值")] + public int MinRandomDropAmount { get; set; } = 1; + [JsonProperty("随机掉落数量最大值")] + public int MaxRandomDropAmount { get; set; } = 1; + [JsonProperty("是否开启自定义掉落")] + public bool EnableCustomDrops { get; set; } = false; + [JsonProperty("自定义掉落设置")] + public Monster[] DeathDropSet { get; set; } = new Monster[1] + { + new Monster() + }; + + public static readonly string ConfigFilePath = Path.Combine(TShock.SavePath, "死亡掉落配置表.json"); + + public static DeathDropConfig GetConfig() + { + if (!File.Exists(ConfigFilePath)) + { + File.WriteAllText(ConfigFilePath, JsonConvert.SerializeObject(new DeathDropConfig(), Formatting.Indented)); + } + + return JsonConvert.DeserializeObject(File.ReadAllText(ConfigFilePath)); + } + } +} \ No newline at end of file diff --git a/Plugin.sln b/Plugin.sln index 5808aefc9..3a1337e22 100644 --- a/Plugin.sln +++ b/Plugin.sln @@ -76,6 +76,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CriticalHit", "CriticalHit\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PacketsStop", "PacketsStop\PacketsStop.csproj", "{852705B7-607D-4591-8359-860D3DD2B6A9}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeathDrop", "DeathDrop\DeathDrop.csproj", "{7901BF97-3A58-4D80-B99F-FE9D41AB4729}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -356,6 +358,14 @@ Global {852705B7-607D-4591-8359-860D3DD2B6A9}.Release|Any CPU.Build.0 = Release|Any CPU {852705B7-607D-4591-8359-860D3DD2B6A9}.Release|x64.ActiveCfg = Release|Any CPU {852705B7-607D-4591-8359-860D3DD2B6A9}.Release|x64.Build.0 = Release|Any CPU + {7901BF97-3A58-4D80-B99F-FE9D41AB4729}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7901BF97-3A58-4D80-B99F-FE9D41AB4729}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7901BF97-3A58-4D80-B99F-FE9D41AB4729}.Debug|x64.ActiveCfg = Debug|Any CPU + {7901BF97-3A58-4D80-B99F-FE9D41AB4729}.Debug|x64.Build.0 = Debug|Any CPU + {7901BF97-3A58-4D80-B99F-FE9D41AB4729}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7901BF97-3A58-4D80-B99F-FE9D41AB4729}.Release|Any CPU.Build.0 = Release|Any CPU + {7901BF97-3A58-4D80-B99F-FE9D41AB4729}.Release|x64.ActiveCfg = Release|Any CPU + {7901BF97-3A58-4D80-B99F-FE9D41AB4729}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 1c5b611b904ebf3996bd691728a7fd99f8b77bac Mon Sep 17 00:00:00 2001 From: xien <2383759126@qq.com> Date: Sun, 14 Apr 2024 21:26:40 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=87=8D=E8=BD=BD?= =?UTF-8?q?=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{DeathDropConfig.cs => Configuration.cs} | 29 +++- DeathDrop/DeathDrop.cs | 134 ++++++++++-------- DeathDrop/README.md | 47 ++++++ 3 files changed, 145 insertions(+), 65 deletions(-) rename DeathDrop/{DeathDropConfig.cs => Configuration.cs} (68%) create mode 100644 DeathDrop/README.md diff --git a/DeathDrop/DeathDropConfig.cs b/DeathDrop/Configuration.cs similarity index 68% rename from DeathDrop/DeathDropConfig.cs rename to DeathDrop/Configuration.cs index ab38cef08..4805366f9 100644 --- a/DeathDrop/DeathDropConfig.cs +++ b/DeathDrop/Configuration.cs @@ -5,7 +5,7 @@ namespace DeathDrop { - internal class DeathDropConfig + public class Configuration { public class Monster { @@ -47,16 +47,31 @@ public class Monster new Monster() }; - public static readonly string ConfigFilePath = Path.Combine(TShock.SavePath, "死亡掉落配置表.json"); - - public static DeathDropConfig GetConfig() + public static readonly string FilePath = Path.Combine(TShock.SavePath, "死亡掉落配置表.json"); + public void Write(string path) { - if (!File.Exists(ConfigFilePath)) + using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Write)) { - File.WriteAllText(ConfigFilePath, JsonConvert.SerializeObject(new DeathDropConfig(), Formatting.Indented)); + var str = JsonConvert.SerializeObject(this, Formatting.Indented); + using (var sw = new StreamWriter(fs)) + { + sw.Write(str); + } } + } - return JsonConvert.DeserializeObject(File.ReadAllText(ConfigFilePath)); + public static Configuration Read(string path) + { + if (!File.Exists(path)) + return new Configuration(); + using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + using (var sr = new StreamReader(fs)) + { + var cf = JsonConvert.DeserializeObject(sr.ReadToEnd()); + return cf; + } + } } } } \ No newline at end of file diff --git a/DeathDrop/DeathDrop.cs b/DeathDrop/DeathDrop.cs index 1ef59d837..a808f3ab8 100644 --- a/DeathDrop/DeathDrop.cs +++ b/DeathDrop/DeathDrop.cs @@ -5,6 +5,7 @@ using Terraria; using TerrariaApi.Server; using TShockAPI; +using TShockAPI.Hooks; namespace DeathDrop { @@ -12,19 +13,45 @@ namespace DeathDrop public class DeathDrop : TerrariaPlugin { public static Random RandomGenerator = new Random(); + public static Configuration Config; public override string Author => "大豆子,肝帝熙恩更新优化"; - public override string Description => "自定义怪物死亡随机掉落物"; - public override string Name => "死亡随机掉落"; - public override Version Version => new Version(1, 0, 1); + public override string Description => "怪物死亡随机和自定义掉落物品"; + public override string Name => "死亡掉落"; + public override Version Version => new Version(1, 0, 3); - public DeathDrop(Main game) : base(game) { } + public DeathDrop(Main game) : base(game) + { + LoadConfig(); + } public override void Initialize() { + GeneralHooks.ReloadEvent += ReloadConfig; ServerApi.Hooks.NpcKilled.Register(this, NPCDead); } + protected override void Dispose(bool disposing) + { + if (disposing) + { + GeneralHooks.ReloadEvent -= ReloadConfig; + ServerApi.Hooks.NpcKilled.Deregister(this, NPCDead); + } + base.Dispose(disposing); + } + private static void LoadConfig() + { + Config = Configuration.Read(Configuration.FilePath); + Config.Write(Configuration.FilePath); + } + + private static void ReloadConfig(ReloadEventArgs args) + { + LoadConfig(); + args.Player?.SendSuccessMessage("[死亡掉落] 重新加载配置完毕。"); + } + private void NPCDead(NpcKilledEventArgs args) { int npcNetID = args.npc.netID; @@ -35,78 +62,69 @@ private void NPCDead(NpcKilledEventArgs args) ? TShock.Players[args.npc.lastInteraction] : null; - try + if (Config.EnableRandomDrops) { - DeathDropConfig config = DeathDropConfig.GetConfig(); + int itemId = GetRandomItemIdFromGlobalConfig(Config); - if (config.EnableRandomDrops) + if (Candorp(Config.RandomDropChance)) { - int itemId = GetRandomItemIdFromGlobalConfig(config); + Item item = TShock.Utils.GetItemById(itemId); + int dropAmount = RandomGenerator.Next(Config.MinRandomDropAmount, Config.MaxRandomDropAmount + 1); + + int itemNumber = Item.NewItem( + null, + (int)args.npc.position.X, + (int)args.npc.position.Y, + item.width, + item.height, + item.type, + dropAmount + ); + + // 只有当玩家不为 null 时才发送数据包 + if (player != null) + { + player.SendData(PacketTypes.SyncExtraValue, null, itemNumber); + player.SendData(PacketTypes.ItemOwner, null, itemNumber); + player.SendData(PacketTypes.TweakItem, null, itemNumber, 255f, 63f); + } + } + } - if (Candorp(config.RandomDropChance)) + if (Config.EnableCustomDrops) + { + foreach (Configuration.Monster monster in Config.DeathDropSet) + { + if (monster.NPCID == npcNetID && Candorp(monster.DropChance)) { - Item item = TShock.Utils.GetItemById(itemId); - int dropAmount = RandomGenerator.Next(config.MinRandomDropAmount, config.MaxRandomDropAmount + 1); + int dropItemId = GetRandomItemIdFromMonsterConfig(monster); - int itemNumber = Item.NewItem( + Item dropItem = TShock.Utils.GetItemById(dropItemId); + int dropAmount = RandomGenerator.Next(monster.RandomDropMinAmount, monster.RandomDropMaxAmount + 1); + + int dropItemNumber = Item.NewItem( null, - (int)args.npc.position.X, - (int)args.npc.position.Y, - item.width, - item.height, - item.type, + (int)npcPosition.X, + (int)npcPosition.Y, + dropItem.width, + dropItem.height, + dropItem.type, dropAmount ); // 只有当玩家不为 null 时才发送数据包 if (player != null) { - player.SendData(PacketTypes.SyncExtraValue, null, itemNumber); - player.SendData(PacketTypes.ItemOwner, null, itemNumber); - player.SendData(PacketTypes.TweakItem, null, itemNumber, 255f, 63f); - } - } - } - - if (config.EnableCustomDrops) - { - foreach (DeathDropConfig.Monster monster in config.DeathDropSet) - { - if (monster.NPCID == npcNetID && Candorp(monster.DropChance)) - { - int dropItemId = GetRandomItemIdFromMonsterConfig(monster); - - Item dropItem = TShock.Utils.GetItemById(dropItemId); - int dropAmount = RandomGenerator.Next(monster.RandomDropMinAmount, monster.RandomDropMaxAmount + 1); - - int dropItemNumber = Item.NewItem( - null, - (int)npcPosition.X, - (int)npcPosition.Y, - dropItem.width, - dropItem.height, - dropItem.type, - dropAmount - ); - - // 只有当玩家不为 null 时才发送数据包 - if (player != null) - { - player.SendData(PacketTypes.SyncExtraValue, null, dropItemNumber); - player.SendData(PacketTypes.ItemOwner, null, dropItemNumber); - player.SendData(PacketTypes.TweakItem, null, dropItemNumber, 255f, 63f); - } + player.SendData(PacketTypes.SyncExtraValue, null, dropItemNumber); + player.SendData(PacketTypes.ItemOwner, null, dropItemNumber); + player.SendData(PacketTypes.TweakItem, null, dropItemNumber, 255f, 63f); } } } } - catch (Exception ex) - { - Console.WriteLine($"死亡掉落插件发生异常:{ex.Message}"); - } } - private int GetRandomItemIdFromGlobalConfig(DeathDropConfig config) + private int GetRandomItemIdFromGlobalConfig(Configuration config) { if (config.FullRandomDrops) { @@ -126,7 +144,7 @@ private int GetRandomItemIdFromGlobalConfig(DeathDropConfig config) } } - private int GetRandomItemIdFromMonsterConfig(DeathDropConfig.Monster monster) + private int GetRandomItemIdFromMonsterConfig(Configuration.Monster monster) { if (monster.FullRandomDrops) { diff --git a/DeathDrop/README.md b/DeathDrop/README.md new file mode 100644 index 000000000..d6378aa00 --- /dev/null +++ b/DeathDrop/README.md @@ -0,0 +1,47 @@ +# DeathDrop 死亡掉落 + +- 作者: 大豆子,肝帝熙恩更新优化 +- 出处: TShock中文官方群 +- 允许自定义怪物死亡时的掉落物。 +- 随机or自定义,互不影响 + +## 更新日志 + +``` +- v1.0.3 使用reload来重载配置,原先是杀一只怪就重载一次,感觉会爆 +``` + +## 指令 + +``` +暂无 +``` + +## 配置 + +```json +{ + "是否开启随机掉落": false,//随机掉落的总开关,必须设置这个为true能设置除了自定义以外的内容 + "完全随机掉落": false,//完全随机掉落,从1-5452里面选一个或多个物品 + "完全随机掉落排除物品ID": [],//不会选择这里面的物品 + "普通随机掉落物": [],//如果完全随机掉落为false,你可以在这里面自定义所有怪物一起的随机掉落物,随机掉落物从这里面选取 + "随机掉落概率": 100,//概率,同时影响完全随机掉落和普通随机掉落 + "随机掉落数量最小值": 1,//随机掉落数量最小值,同时影响完全随机掉落和普通随机掉落 + "随机掉落数量最大值": 1,//随机掉落数量最小值,同时影响完全随机掉落和普通随机掉落 + "是否开启自定义掉落": false,//自定义掉落,不受上面所有设置的影响,独立作用 + "自定义掉落设置": [ + { + "生物id": 0, + "完全随机掉落": false, + "完全随机掉落排除物品ID": [], + "普通随机掉落物": [], + "随机掉落数量最小值": 1, + "随机掉落数量最大值": 1, + "掉落概率": 100 + } + ] +} +``` +## 反馈 +- 共同维护的插件库:https://github.com/THEXN/TShockPlugin/ +- 国内社区trhub.cn 或 TShock官方群等 \ No newline at end of file From 3ee3fd61c96baf3662efd3ae374d73d8eab25594 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=82=9D=E5=B8=9D=E7=86=99=E6=81=A9?= <111548550+THEXN@users.noreply.github.com> Date: Sun, 14 Apr 2024 21:28:23 +0800 Subject: [PATCH 3/3] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7d3563b3d..8273dd726 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,8 @@ | [RegionView](RegionView/README.md) | 显示区域边界 | 无 | | [Noagent](Noagent/README.md) | 禁止代理 ip 进入 | 无 | | [SwitchCommands](SwitchCommands/README.md) | 区域执行指令 | 无 | -| [GolfRewards](GolfRewards/README.md) | 高尔夫奖励 | 无 | +| [GolfRewards](GolfRewards/README.md) | 高尔夫奖励 | 无 | | [DataSync](DataSync/README.md) | 进度同步 | 无 | | [ProgressRestrict](ProgressRestrict/README.md) | 超进度检测 | DataSync | -| [PacketsStop](PacketsStop/README.md) | 数据包拦截 | 无 | +| [PacketsStop](PacketsStop/README.md) | 数据包拦截 | 无 | +| [DeathDrop](DeathDrop/README.md) |怪物死亡随机和自定义掉落物品 | 无 |