Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

添加插件:AutoUpdatePlugin (插件更新) #237

Merged
merged 7 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}
Loading