diff --git a/AdditionalPylons/AdditionalPylons.csproj b/AdditionalPylons/AdditionalPylons.csproj new file mode 100644 index 000000000..639adc026 --- /dev/null +++ b/AdditionalPylons/AdditionalPylons.csproj @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/AdditionalPylons/AdditionalPylonsPlugin.cs b/AdditionalPylons/AdditionalPylonsPlugin.cs new file mode 100644 index 000000000..567342a61 --- /dev/null +++ b/AdditionalPylons/AdditionalPylonsPlugin.cs @@ -0,0 +1,304 @@ +using Terraria; +using Terraria.GameContent; +using Terraria.GameContent.NetModules; +using TerrariaApi.Server; +using TShockAPI; +using TShockAPI.Hooks; +using TShockAPI.Net; + +namespace AdditionalPylons +{ + [ApiVersion(2, 1)] + public class AdditionalPylonsPlugin : TerrariaPlugin + { + + + #region Plugin Properties + public override string Name => "[放置更多晶塔] AdditionalPylons"; + + public override Version Version => System.Reflection.Assembly.GetAssembly(typeof(AdditionalPylonsPlugin)).GetName().Version; + + public override string Author => "Stealownz,肝帝熙恩优化1449"; + + public override string Description => "晶塔环境不受限制,数量可提升"; + + + public AdditionalPylonsPlugin(Main game) : base(game) + { + LoadConfig(); + } + #endregion // Plugin Properties + + private const string permission_infiniteplace = "AdditionalPylons"; + + private readonly HashSet pylonItemIDList = new HashSet() { 4875, 4876, 4916, 4917, 4918, 4919, 4920, 4921, 4951 }; + private readonly HashSet playersHoldingPylon = new HashSet(); + internal static Configuration Config; + private static void LoadConfig() + { + + Config = Configuration.Read(Configuration.FilePath); + Config.Write(Configuration.FilePath); + + } + private static void ReloadConfig(ReloadEventArgs args) + { + LoadConfig(); + args.Player?.SendSuccessMessage("[{0}]重新加载配置完毕。", typeof(AdditionalPylonsPlugin).Name); + } + + #region Plugin Overrides + public override void Initialize() + { + GetDataHandlers.PlayerUpdate.Register(OnPlayerUpdate); + GetDataHandlers.PlaceTileEntity.Register(OnPlaceTileEntity, HandlerPriority.High); + GetDataHandlers.SendTileRect.Register(OnSendTileRect, HandlerPriority.High); + GeneralHooks.ReloadEvent += ReloadConfig; + } + #endregion // Plugin overrides + + #region Plugin Hooks + private void OnSendTileRect(object sender, GetDataHandlers.SendTileRectEventArgs e) + { + // 如果有更高优先级的插件需要处理,就尊重它们的决定... + if (this.isDisposed || e.Handled) + return; + + // 如果玩家没有权限,就没有必要检查数据 + if (!e.Player.HasPermission(permission_infiniteplace)) + return; + + // 最小的合理检查,这个STR很可能是晶塔 + if (e.Width != 3 || e.Length != 4) + return; + + long savePosition = e.Data.Position; + NetTile[,] tiles = new NetTile[e.Width, e.Length]; + + for (int x = 0; x < e.Width; x++) + { + for (int y = 0; y < e.Length; y++) + { + tiles[x, y] = new NetTile(e.Data); + if (tiles[x, y].Type != Terraria.ID.TileID.TeleportationPylon) + { + e.Data.Seek(savePosition, System.IO.SeekOrigin.Begin); + return; + } + } + } + + // 重置数据回到原始位置 + e.Data.Seek(savePosition, System.IO.SeekOrigin.Begin); + + // 简单地清除主系统的晶塔网络,以欺骗服务器 >:DD + // 这样做之所以有效,是因为当晶塔系统被放置时,它无论如何都会被刷新。 + // 这个部分是必需的,因为TShock重新实现了带有反弹器的STR, + // 然后调用PlaceEntityNet,由于在Main.PylonSystem内部已经包含了这种类型的晶塔,所以它会拒绝这个晶塔。 + Main.PylonSystem._pylons.Clear(); + } + + private void OnPlayerUpdate(object sender, TShockAPI.GetDataHandlers.PlayerUpdateEventArgs e) + { + if (this.isDisposed || e.Handled) + return; + + if (!e.Player.HasPermission(permission_infiniteplace)) + return; + + int holdingItem = e.Player.TPlayer.inventory[e.SelectedItem].netID; + bool alreadyHoldingPylon = playersHoldingPylon.Contains(e.PlayerId); + bool isHoldingPylon = pylonItemIDList.Contains(holdingItem); + + if (alreadyHoldingPylon) + { + if (!isHoldingPylon) + { + // 停止持有晶塔 + playersHoldingPylon.Remove(e.PlayerId); + + // 为玩家客户端重新加载晶塔系统 + SendPlayerPylonSystem(e.PlayerId, true); + } + } + else + { + if (isHoldingPylon) + { + // 开始持有晶塔 + playersHoldingPylon.Add(e.PlayerId); + + // 清除玩家客户端的晶塔系统 + SendPlayerPylonSystem(e.PlayerId, false); + } + } + } + + private void OnPlaceTileEntity(object sender, TShockAPI.GetDataHandlers.PlaceTileEntityEventArgs e) + { + // 如果插件已被销毁或事件已被处理,则返回 + if (this.isDisposed || e.Handled) + return; + + // 如果实体类型不是7(晶塔),则返回 + if (e.Type != 7) + return; + + // 如果玩家没有无限放置晶塔的权限,则向所有客户端发送STR以更新非无限晶塔玩家的第一个晶塔放置 + if (!e.Player.HasPermission(permission_infiniteplace)) + { + TShockAPI.TSPlayer.All.SendTileRect((short)e.X, (short)e.Y, 3, 4); + return; + } + + // 在指定位置放置晶塔 + Terraria.GameContent.Tile_Entities.TETeleportationPylon.Place(e.X, e.Y); + + // 这是为了更新服务器上的晶塔列表。 + // 注意:重置将向所有玩家广播更改。 + Main.PylonSystem.Reset(); + + // 由于其他客户端不知道这个晶塔,所以在手动执行TETeleportationPylon.Place()之后发送STR + TShockAPI.TSPlayer.All.SendTileRect((short)e.X, (short)e.Y, 3, 4); + + // 从持有晶塔的玩家列表中移除当前玩家 + playersHoldingPylon.Remove(e.Player.Index); + + //e.Handled = true; // 这行代码被注释掉了,如果需要设置事件已处理,可以取消注释 + } + #endregion // Plugin Hooks + + private void SendPlayerPylonSystem(int playerId, bool addPylons) + { + // 检测每种晶塔的数量是否达到指定值 + foreach (int pylonItemId in pylonItemIDList) + { + int count = Main.PylonSystem.Pylons.Count(pylon => pylon.TypeOfPylon == GetPylonTypeFromItemId(pylonItemId)); + + // 根据晶塔类型进行不同的处理 + switch (pylonItemId) + { + case 4875: + if (count >= Config.JungleTowerLimit) + { + TShock.Players[playerId].SendErrorMessage("丛林晶塔数量已达到上限。"); + return; + } + break; + + case 4876: + if (count >= Config.ForestTowerLimit) + { + TShock.Players[playerId].SendErrorMessage("森林晶塔数量已达到上限。"); + return; + } + break; + case 4916: + if (count >= Config.HolyTowerLimit) + { + TShock.Players[playerId].SendErrorMessage("神圣晶塔数量已达到上限。"); + return; + } + break; + case 4917: + if (count >= Config.CaveTowerLimit) + { + TShock.Players[playerId].SendErrorMessage("洞穴晶塔数量已达到上限。"); + return; + } + break; + case 4918: + if (count >= Config.OceanTowerLimit) + { + TShock.Players[playerId].SendErrorMessage("海洋晶塔数量已达到上限。"); + return; + } + break; + case 4919: + if (count >= Config.DesertTowerLimit) + { + TShock.Players[playerId].SendErrorMessage("沙漠晶塔数量已达到上限。"); + return; + } + break; + case 4920: + if (count >= Config.SnowTowerLimit) + { + TShock.Players[playerId].SendErrorMessage("雪原晶塔数量已达到上限。"); + return; + } + break; + case 4921: + if (count >= Config.MushroomTowerLimit) + { + TShock.Players[playerId].SendErrorMessage("蘑菇晶塔数量已达到上限。"); + return; + } + break; + case 4951: + if (count >= Config.UniversalTowerLimit) + { + TShock.Players[playerId].SendErrorMessage("万能晶塔数量已达到上限。"); + return; + } + break; + } + } + + // 如果未中断,继续发送晶塔信息 + foreach (TeleportPylonInfo pylon in Main.PylonSystem.Pylons) + { + Terraria.Net.NetManager.Instance.SendToClient( + NetTeleportPylonModule.SerializePylonWasAddedOrRemoved( + pylon, + addPylons ? NetTeleportPylonModule.SubPacketType.PylonWasAdded : NetTeleportPylonModule.SubPacketType.PylonWasRemoved + ), + playerId + ); + } + } + + // 根据晶塔物品ID获取对应的晶塔类型 + private TeleportPylonType GetPylonTypeFromItemId(int pylonItemId) + { + switch (pylonItemId) + { + case 4875: return TeleportPylonType.Jungle; + case 4876: return TeleportPylonType.SurfacePurity; + case 4916: return TeleportPylonType.Hallow; + case 4917: return TeleportPylonType.Underground; + case 4918: return TeleportPylonType.Beach; + case 4919: return TeleportPylonType.Desert; + case 4920: return TeleportPylonType.Snow; + case 4921: return TeleportPylonType.GlowingMushroom; + case 4951: return TeleportPylonType.Victory; + default: return TeleportPylonType.Count; // 或者根据实际情况返回一个默认值 + } + } + + #region [IDisposable Implementation] + private bool isDisposed = false; + + public bool IsDisposed + { + get { return this.isDisposed; } + } + + protected override void Dispose(bool isDisposing) + { + if (this.IsDisposed) + return; + + if (isDisposing) + { + GetDataHandlers.PlayerUpdate.UnRegister(OnPlayerUpdate); + GetDataHandlers.PlaceTileEntity.UnRegister(OnPlaceTileEntity); + GetDataHandlers.SendTileRect.UnRegister(OnSendTileRect); + } + + base.Dispose(isDisposing); + this.isDisposed = true; + } + #endregion // [IDisposable Implementation] + } +} diff --git a/AdditionalPylons/Configuration.cs b/AdditionalPylons/Configuration.cs new file mode 100644 index 000000000..8befea0c8 --- /dev/null +++ b/AdditionalPylons/Configuration.cs @@ -0,0 +1,58 @@ +using Newtonsoft.Json; +using System; +using System.IO; +using TShockAPI; + +namespace AdditionalPylons +{ + internal class Configuration + { + public static readonly string FilePath = Path.Combine(TShock.SavePath, "无限晶塔.json"); + + [JsonProperty("丛林晶塔数量上限")] + public int JungleTowerLimit = 2; + [JsonProperty("森林晶塔数量上限")] + public int ForestTowerLimit = 2; + [JsonProperty("神圣晶塔数量上限")] + public int HolyTowerLimit = 2; + [JsonProperty("洞穴晶塔数量上限")] + public int CaveTowerLimit = 2; + [JsonProperty("海洋晶塔数量上限")] + public int OceanTowerLimit = 2; + [JsonProperty("沙漠晶塔数量上限")] + public int DesertTowerLimit = 2; + [JsonProperty("雪原晶塔数量上限")] + public int SnowTowerLimit = 2; + [JsonProperty("蘑菇晶塔数量上限")] + public int MushroomTowerLimit = 2; + [JsonProperty("万能晶塔数量上限")] + public int UniversalTowerLimit = 2; + + + public void Write(string path) + { + using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Write)) + { + var str = JsonConvert.SerializeObject(this, Formatting.Indented); + using (var sw = new StreamWriter(fs)) + { + sw.Write(str); + } + } + } + + 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/AdditionalPylons/README.md b/AdditionalPylons/README.md new file mode 100644 index 000000000..9a198854c --- /dev/null +++ b/AdditionalPylons/README.md @@ -0,0 +1,35 @@ +# AdditionalPylons 放置更多晶塔权 + +- 作者: Stealownz,肝帝熙恩优化1449 +- 出处: github +- 晶塔环境不受限制,数量可提升 +- 所有晶塔都无视环境 +- 所有晶塔都至少可以放一个 + +## 更新日志 + +``` +暂无 +``` + +## 指令 + +| 语法 | 权限 | 说明 | +| -------------- | :-----------------: | :------: | +| 无 | AdditionalPylons | 放置更多晶塔权限| + +## 配置 + +```json +{ + "丛林晶塔数量上限": 2, + "森林晶塔数量上限": 2, + "神圣晶塔数量上限": 2, + "洞穴晶塔数量上限": 2, + "海洋晶塔数量上限": 2, + "沙漠晶塔数量上限": 2, + "雪原晶塔数量上限": 2, + "蘑菇晶塔数量上限": 2, + "万能晶塔数量上限": 2 +} +``` diff --git a/LifemaxExtra/PluginContainer.cs b/LifemaxExtra/PluginContainer.cs index 419842416..75e851c84 100644 --- a/LifemaxExtra/PluginContainer.cs +++ b/LifemaxExtra/PluginContainer.cs @@ -34,6 +34,10 @@ private static void ReloadConfig(ReloadEventArgs args) { LoadConfig(); args.Player?.SendSuccessMessage("[{0}] 重新加载配置完毕。", typeof(LifemaxExtra).Name); + if(Config.LifeCrystalMaxLife> Config.LifeFruitMaxLife) + { + + } } public override void Initialize() diff --git a/Plugin.sln b/Plugin.sln index 2d98a9991..18cd7da66 100644 --- a/Plugin.sln +++ b/Plugin.sln @@ -86,6 +86,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DamageStatistic", "DamageSt EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DumpTerrariaID", "DumpTerrariaID\DumpTerrariaID.csproj", "{11865290-2C16-44F3-885B-35C01F8EB7B6}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AdditionalPylons", "AdditionalPylons\AdditionalPylons.csproj", "{A86130C5-D9DD-4B60-9D60-666B7E8593D3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -406,6 +408,14 @@ Global {11865290-2C16-44F3-885B-35C01F8EB7B6}.Release|Any CPU.Build.0 = Release|Any CPU {11865290-2C16-44F3-885B-35C01F8EB7B6}.Release|x64.ActiveCfg = Release|Any CPU {11865290-2C16-44F3-885B-35C01F8EB7B6}.Release|x64.Build.0 = Release|Any CPU + {A86130C5-D9DD-4B60-9D60-666B7E8593D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A86130C5-D9DD-4B60-9D60-666B7E8593D3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A86130C5-D9DD-4B60-9D60-666B7E8593D3}.Debug|x64.ActiveCfg = Debug|Any CPU + {A86130C5-D9DD-4B60-9D60-666B7E8593D3}.Debug|x64.Build.0 = Debug|Any CPU + {A86130C5-D9DD-4B60-9D60-666B7E8593D3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A86130C5-D9DD-4B60-9D60-666B7E8593D3}.Release|Any CPU.Build.0 = Release|Any CPU + {A86130C5-D9DD-4B60-9D60-666B7E8593D3}.Release|x64.ActiveCfg = Release|Any CPU + {A86130C5-D9DD-4B60-9D60-666B7E8593D3}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/README.md b/README.md index 4203bafbd..b723d9d72 100644 --- a/README.md +++ b/README.md @@ -61,3 +61,4 @@ | [PvPer](PvPer/README.md) | 决斗系统 | 无 | | [DumpTerrariaID](DumpTerrariaID/README.md) | 输出 ID | 无 | | [DamageStatistic](DamageStatistic/README.md) | 伤害统计 | 无 | +| [AdditionalPylons](AdditionalPylons/README.md) | 放置更多晶塔 | 无 |