Skip to content

Commit

Permalink
Merge pull request #237 from Controllerdestiny/main
Browse files Browse the repository at this point in the history
添加插件:AutoUpdatePlugin (插件更新)
  • Loading branch information
Controllerdestiny authored Jun 19, 2024
2 parents aa35d8b + 3231998 commit 56b8855
Show file tree
Hide file tree
Showing 10 changed files with 279 additions and 57 deletions.
5 changes: 5 additions & 0 deletions AutoUpdatePlugin/AutoUpdatePlugin.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">

<Import Project="..\template.targets" />

</Project>
157 changes: 157 additions & 0 deletions AutoUpdatePlugin/Plugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
using Newtonsoft.Json;
using System.IO.Compression;
using Terraria;
using TerrariaApi.Server;
using TShockAPI;

namespace AutoUpdatePlugin;

[ApiVersion(2, 1)]
public class Plugin : TerrariaPlugin
{
public override string Name => "AutoUpdatePlugin";

public override Version Version => new(1, 6, 0, 2);

public override string Author => "少司命,Cai";

public override string Description => "自动更新你的插件!";

private const string ReleaseUrl = "https://github.com/Controllerdestiny/TShockPlugin/releases/download/V1.0.0.0/Plugins.zip";

private const string PUrl = "https://github.moeyy.xyz/";

private const string PluginsUrl = "https://raw.githubusercontent.com/Controllerdestiny/TShockPlugin/master/Plugins.json";

private static readonly HttpClient _httpClient = new();

private const string TempSaveDir = "TempFile";

private const string TempZipName = "Plugins.zip";

public Plugin(Main game) : base(game)
{

}

public override void Initialize()
{
Commands.ChatCommands.Add(new("AutoUpdatePlugin", CheckCmd, "cplugin"));
Commands.ChatCommands.Add(new("AutoUpdatePlugin", UpdateCmd, "uplugin"));
}

private void UpdateCmd(CommandArgs args)
{
try
{
var updates = GetUpdate();
if (updates.Count == 0)
{
args.Player.SendSuccessMessage("你的插件全是最新版本,无需更新哦~");
return;
}
args.Player.SendInfoMessage("正在下载最新插件包...");
DownLoadPlugin();
args.Player.SendInfoMessage("正在解压插件包...");
ExtractDirectoryZip();
args.Player.SendInfoMessage("正在升级插件...");
UpdatePlugin(updates);
args.Player.SendSuccessMessage("[更新完成]\n" + string.Join("\n", updates.Select(i => $"[{i.Name}] V{i.OldVersion} >>> V{i.NewVersion}")));
args.Player.SendSuccessMessage("重启服务器后插件生效!");
}
catch (Exception ex)
{
args.Player.SendErrorMessage("自动更新出现错误:" + ex.Message);
return;
}
}

private void CheckCmd(CommandArgs args)
{
try
{
var updates = GetUpdate();
if (updates.Count == 0)
{
args.Player.SendSuccessMessage("你的插件全是最新版本,无需更新哦~");
return;
}
args.Player.SendInfoMessage("[以下插件有新的版本更新]\n" + string.Join("\n", updates.Select(i => $"[{i.Name}] V{i.OldVersion} >>> V{i.NewVersion}")));
}
catch (Exception ex)
{
args.Player.SendErrorMessage("无法获取更新:" + ex.Message);
return;
}
}

#region 工具方法
private static List<PluginUpdateInfo> GetUpdate()
{
var plugins = GetPlugins();
HttpClient httpClient = new();
var response = httpClient.GetAsync(PUrl + PluginsUrl).Result;

if (!response.IsSuccessStatusCode)
throw new Exception("无法连接服务器");
var json = response.Content.ReadAsStringAsync().Result;
var latestPluginList = JsonConvert.DeserializeObject<List<PluginVersionInfo>>(json) ?? new();
List<PluginUpdateInfo> pluginUpdateList = new();
foreach (var latestPluginInfo in latestPluginList)
foreach (var plugin in plugins)
if (plugin.Name == latestPluginInfo.Name && plugin.Version != latestPluginInfo.Version)
pluginUpdateList.Add(new PluginUpdateInfo(plugin.Name, plugin.Author, latestPluginInfo.Version, plugin.Version, plugin.Path, latestPluginInfo.Path));
return pluginUpdateList;
}

private static List<PluginVersionInfo> GetPlugins()
{
List<PluginVersionInfo> plugins = new();
foreach (var plugin in ServerApi.Plugins)
{
plugins.Add(new PluginVersionInfo()
{
AssemblyName = plugin.Plugin.GetType().Assembly.GetName().Name!,
Path = Path.Combine(ServerApi.ServerPluginsDirectoryPath, plugin.Plugin.GetType().Assembly.GetName().Name! + ".dll"),
Author = plugin.Plugin.Author,
Name = plugin.Plugin.Name,
Description = plugin.Plugin.Description,
Version = plugin.Plugin.Version.ToString()
});
}
return plugins;
}


private static void DownLoadPlugin()
{
DirectoryInfo directoryInfo = new(TempSaveDir);
if (!directoryInfo.Exists)
directoryInfo.Create();
HttpClient httpClient = new();
var zipBytes = httpClient.GetByteArrayAsync(PUrl + ReleaseUrl).Result;
File.WriteAllBytes(Path.Combine(directoryInfo.FullName, TempZipName), zipBytes);
}

private static void ExtractDirectoryZip()
{
DirectoryInfo directoryInfo = new(TempSaveDir);
ZipFile.ExtractToDirectory(Path.Combine(directoryInfo.FullName, TempZipName), Path.Combine(directoryInfo.FullName, "Plugins"), true);
}

private static void UpdatePlugin(List<PluginUpdateInfo> pluginUpdateInfos)
{
foreach (var pluginUpdateInfo in pluginUpdateInfos)
{
string sourcePath = Path.Combine(TempSaveDir, "Plugins", pluginUpdateInfo.RemotePath);
string destinationPath = Path.Combine(ServerApi.ServerPluginsDirectoryPath, pluginUpdateInfo.LocalPath);
// 确保目标目录存在
string destinationDirectory = Path.GetDirectoryName(destinationPath)!;
// 复制并覆盖文件
File.Copy(sourcePath, destinationPath, true);
}
if (Directory.Exists(TempSaveDir))
Directory.Delete(TempSaveDir, true);
}
#endregion
}
21 changes: 21 additions & 0 deletions AutoUpdatePlugin/PluginUpdateInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace AutoUpdatePlugin;

public class PluginUpdateInfo
{
public PluginUpdateInfo(string name, string author, string newVersion, string oldVersion, string localPath, string remotePath)
{
NewVersion = newVersion;
OldVersion = oldVersion;
Author = author;
Name = name;
LocalPath = localPath;
RemotePath = remotePath;
}
public string NewVersion { get; set; }
public string OldVersion { get; set; }
public string Author { get; set; }
public string Name { get; set; }
public string LocalPath { get; set; }
public string RemotePath { get; set; }

}
16 changes: 16 additions & 0 deletions AutoUpdatePlugin/PluginVersionInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace AutoUpdatePlugin;

public class PluginVersionInfo
{
public string Version { get; set; } = string.Empty;

public string Author { get; set; } = string.Empty;

public string Name { get; set; } = string.Empty;

public string Description { get; set; } = string.Empty;

public string Path { get; set; } = string.Empty;

public string AssemblyName { get; set; } = string.Empty;
}
26 changes: 26 additions & 0 deletions AutoUpdatePlugin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# AutoUpdatePlugin 自动更新插件

- 作者: 少司命,Cai
- 出处: 本仓库
- 使用指令自动更新服务器的插件(仅本仓库)

## 更新日志

```
暂无
```

## 指令

| 语法 | 权限 | 说明 |
| -------------- | :-----------------: | :------: |
| /cplugin | AutoUpdatePlugin | 检查插件更新|
| /uplugin | AutoUpdatePlugin | 一键升级插件(需要重启服务器)|
## 配置

```json
暂无
```
## 反馈
- 共同维护的插件库:https://github.com/Controllerdestiny/TShockPlugin
- 国内社区trhub.cn 或 TShock官方群等
10 changes: 10 additions & 0 deletions Plugin.sln
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TimerKeeper", "TimerKeeper\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Chameleon", "Chameleon\Chameleon.csproj", "{53CD6498-27DE-4C8C-A706-3CD2BD106D9E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoUpdatePlugin", "AutoUpdatePlugin\AutoUpdatePlugin.csproj", "{9B88AC5E-E11C-4424-A5DC-5C1D094860B9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -896,6 +898,14 @@ Global
{53CD6498-27DE-4C8C-A706-3CD2BD106D9E}.Release|Any CPU.Build.0 = Release|Any CPU
{53CD6498-27DE-4C8C-A706-3CD2BD106D9E}.Release|x64.ActiveCfg = Release|Any CPU
{53CD6498-27DE-4C8C-A706-3CD2BD106D9E}.Release|x64.Build.0 = Release|Any CPU
{9B88AC5E-E11C-4424-A5DC-5C1D094860B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9B88AC5E-E11C-4424-A5DC-5C1D094860B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9B88AC5E-E11C-4424-A5DC-5C1D094860B9}.Debug|x64.ActiveCfg = Debug|Any CPU
{9B88AC5E-E11C-4424-A5DC-5C1D094860B9}.Debug|x64.Build.0 = Debug|Any CPU
{9B88AC5E-E11C-4424-A5DC-5C1D094860B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9B88AC5E-E11C-4424-A5DC-5C1D094860B9}.Release|Any CPU.Build.0 = Release|Any CPU
{9B88AC5E-E11C-4424-A5DC-5C1D094860B9}.Release|x64.ActiveCfg = Release|Any CPU
{9B88AC5E-E11C-4424-A5DC-5C1D094860B9}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@
| [Musicplayer](Musicplayer/README.md) | 简易音乐播放器 ||
| [TimerKeeper](TimerKeeper/README.md) | 保存计时器状态 ||
| [Chameleon](Chameleon/README.md) | 进服前登录 ||

| [AutoUpdatePlugin](AutoUpdatePlugin/README.md) | 一键自动更新插件 ||
</Details>

## 代码贡献
Expand Down
26 changes: 0 additions & 26 deletions ServerTools/ClearPlayersItem.cs

This file was deleted.

35 changes: 5 additions & 30 deletions ServerTools/Plugin.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
using Microsoft.Xna.Framework;
using MonoMod.RuntimeDetour;
using Newtonsoft.Json;
using NuGet.Configuration;
using NuGet.Protocol.Plugins;
using System.Linq;
using Terraria.DataStructures;
using Terraria;
using Terraria.GameContent.Creative;
using TerrariaApi.Server;
Expand All @@ -22,7 +18,7 @@ public partial class Plugin : TerrariaPlugin

public override string Name => "ServerTools";// 插件名字

public override Version Version => new(1, 1, 7, 0);// 插件版本
public override Version Version => new(1, 1, 7, 1);// 插件版本

private static Config Config = new();

Expand All @@ -38,8 +34,6 @@ public partial class Plugin : TerrariaPlugin

public static Hook CmdHook;

private static ClearPlayersItem clear = new();

public Plugin(Main game) : base(game)
{

Expand Down Expand Up @@ -112,30 +106,11 @@ private void OnUpdate(object? sender, GetDataHandlers.PlayerUpdateEventArgs e)
e.Player.SetBuff(156, 180, true);
TShock.Utils.Broadcast($"[ServerTools] 玩家 [{e.Player.Name}] 因多饰品被冻结3秒,自动施行清理多饰品装备[i:{keepArmor.netID}]", Color.DarkRed);
}
if (ArmorGroup.Any() && TimerCount % 20 == 0)
clear.ClearItem(ArmorGroup.ToArray(), e.Player);

if (Config.KeepArmor2 && !Main.hardMode) { Clear7Item(e.Player); }
}
if (ArmorGroup.Any())
Utils.ClearItem(ArmorGroup.ToArray(), e.Player);

private static void Clear7Item(TSPlayer args)
{
if (!args.TPlayer.armor[8].IsAir && TimerCount % 20 == 0)
{
Item i = args.TPlayer.armor[8];
GiveItem(args, i.type, i.stack, i.prefix);
args.TPlayer.armor[8].TurnToAir();
args.SendData(PacketTypes.PlayerSlot, "", args.Index, Terraria.ID.PlayerItemSlotID.Armor0 + 8);
TShock.Utils.Broadcast($"[ServerTools] 世界未开启困难模式,禁止玩家 [{args.Name}]使用恶魔心饰品栏", Color.DarkRed);
}
}

private static void GiveItem(TSPlayer p, int type, int stack, int prefix = 0)
{
int num = Item.NewItem(new EntitySource_DebugCommand(), (int)p.TPlayer.Center.X, (int)p.TPlayer.Center.Y, p.TPlayer.width, p.TPlayer.height, type, stack, true, prefix, true, false);
Main.item[num].playerIndexTheItemIsReservedFor = p.Index;
p.SendData(PacketTypes.ItemDrop, "", num, 1f, 0f, 0f, 0);
p.SendData(PacketTypes.ItemOwner, null, num, 0f, 0f, 0f, 0);
if (Config.KeepArmor2 && !Main.hardMode)
Utils.Clear7Item(e.Player);
}

#endregion
Expand Down
38 changes: 38 additions & 0 deletions ServerTools/Utils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Terraria;
using Microsoft.Xna.Framework;
using TShockAPI;

namespace ServerTools;

internal class Utils
{
public static void Clear7Item(TSPlayer Player)
{
if (!Player.TPlayer.armor[8].IsAir)
{
Item item = Player.TPlayer.armor[8];
Player.GiveItem(item.type, item.stack, item.prefix);
Player.TPlayer.armor[8].TurnToAir();
Player.SendData(PacketTypes.PlayerSlot, "", Player.Index, Terraria.ID.PlayerItemSlotID.Armor0 + 8);
TShock.Utils.Broadcast($"[ServerTools] 世界未开启困难模式,禁止玩家 [{Player.Name}]使用恶魔心饰品栏", Color.DarkRed);
}
}


#region 清理盔甲组逻辑
public static void ClearItem(Item[] items, TSPlayer tSPlayer)
{
for (int i = 0; i < 10; i++)
{
foreach (Item item in items)
{
if (!tSPlayer.TPlayer.armor[i].IsAir && tSPlayer.TPlayer.armor[i].type == item.type)
{
tSPlayer.TPlayer.armor[i].TurnToAir();
tSPlayer.SendData(PacketTypes.PlayerSlot, "", tSPlayer.Index, Terraria.ID.PlayerItemSlotID.Armor0 + i);
}
}
}
}
#endregion
}

0 comments on commit 56b8855

Please sign in to comment.