├── Logging ├── app.config ├── Logging.csproj └── Program.cs ├── BDSBaseLib ├── C#插件开发指南.txt ├── MyClass.cs ├── BDS │ ├── Plugin.cs │ ├── Component.cs │ └── MCCSAPI.cs ├── ConfigReader.cs └── BDSBaseLib.csproj ├── README.md ├── NoAutoCompactionTip ├── BDS │ ├── Plugin.cs │ └── MCCSAPI.cs ├── NoAutoCompactionTip.cs └── NoAutoCompactionTip.csproj ├── AntiWsCmd ├── BDS │ ├── Plugin.cs │ └── MCCSAPI.cs ├── AntiWsCmd.cs └── AntiWsCmd.csproj ├── HideSeed ├── Hook.cs ├── Program5.cs └── HideSeed.csproj ├── AlwaysNoCheat ├── Program2.cs ├── Hook.cs └── AlwaysNoCheat.csproj ├── Vbtest ├── NewClass.vb └── Vbtest.vbproj ├── Visitor ├── Visitor.csproj └── Program4.cs ├── Testcase ├── Testcase.csproj ├── SimpleGUI.cs └── Program3.cs ├── CSRMods.sln └── LICENSE /Logging/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /BDSBaseLib/C#插件开发指南.txt: -------------------------------------------------------------------------------- 1 | 本插件开发采用启动器加载framework并调用指定入口方法启动。基本运作机制同JSRunner。 2 | 3 | 1. 创建.net framework类库工程; 4 | 2. 复制模板工程中的BDS文件夹至工程目录; 5 | 3. 在自己的主类里实现 CSR.Plugin.onStart 方法; 6 | 4. 修改工程生成的dll文件后缀名为.csr.dll,放置插件到BDS服务端下的CSR文件夹下即可被插件平台加载运行。 7 | 8 | 自由发挥创意吧! 9 | 10 | 构建注意:建议设置目标框架版本 4 以上,生成目标平台强制为 x64(AMD/Intel 64位处理器)。 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSRMods 2 | 构建基于BDSNetRunner的插件示例 3 | 4 | 注:由于github官方策略限制,本项目源码将迁移至 5 | 6 | https://mzgl.coding.net/public/csrmods/CSRMods/git/files 7 | 8 | ### BDSBaseLib 9 | 10 | 提供公共方法的CSR通用的BDS API接口,动态更新时只需更新此处 11 | 12 | #### Logging 13 | 14 | 基本监控信息输出,可通过配置文件修改路径或选择是否保存LOG 15 | 16 | #### AlwaysNoCheat 17 | 18 | 解锁所有指令为非作弊模式,hook方式调用,需随版本更新 19 | 20 | #### Testcase 21 | 22 | 提供一个启动API测试用例的指令(社区版) 23 | 24 | #### Visitor 25 | 26 | 提供后台降级访客的命令 27 | 28 | #### HideSeed 29 | 30 | 隐藏种子,hook方式调用,需随版本更新 31 | 32 | #### Vbtest 33 | 34 | 提供一个 VB.Net 的开发用例(一次性监听) 35 | 36 | #### NoAutoCompactionTip 37 | 38 | 隐藏 “Running AutoCompaction ...” 这个提示,hook方式调用,需随版本更新 39 | -------------------------------------------------------------------------------- /BDSBaseLib/MyClass.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * 由SharpDevelop创建。 3 | * 用户: BDSNetRunner 4 | * 日期: 2020/7/28 5 | * 时间: 0:45 6 | * 7 | * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 8 | */ 9 | using System; 10 | using System.Collections.Generic; 11 | 12 | namespace BDSBaseLib 13 | { 14 | /// 15 | /// Template 16 | /// 17 | public class MyClass 18 | { 19 | } 20 | } 21 | 22 | namespace CSR { 23 | partial class Plugin { 24 | // TODO 25 | //public static int onServerStart(string pathandversion) { 26 | // Console.WriteLine("----Base CSR api is loaded----"); 27 | // return -1; 28 | //} 29 | // TODO 30 | //public static void onStart(MCCSAPI api) { 31 | //} 32 | } 33 | } -------------------------------------------------------------------------------- /NoAutoCompactionTip/BDS/Plugin.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * 由SharpDevelop创建。 3 | * 用户: BDSNetRunner 4 | * 日期: 2020/7/18 5 | * 时间: 12:32 6 | * 7 | * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 8 | */ 9 | using System; 10 | 11 | namespace CSR 12 | { 13 | partial class Plugin 14 | { 15 | #region 插件统一调用接口,请勿随意更改 16 | // 采用第三方引用时候,全部由用户实现 17 | public static int onServerStart(string pathandversion) { 18 | string path = null, version = null; 19 | bool commercial = false; 20 | string [] pav = pathandversion.Split(','); 21 | if (pav.Length > 1) { 22 | path = pav[0]; 23 | version = pav[1]; 24 | commercial = (pav[pav.Length - 1] == "1"); 25 | var api = new MCCSAPI(path, version, commercial); 26 | if (api != null) { 27 | onStart(api); 28 | return 0; 29 | } 30 | } 31 | Console.WriteLine("Load failed."); 32 | return -1; 33 | } 34 | #endregion 35 | 36 | #region 必要接口 onStart ,由用户实现 37 | // public static void onStart(MCCSAPI api) 38 | #endregion 39 | } 40 | } -------------------------------------------------------------------------------- /AntiWsCmd/BDS/Plugin.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * 由SharpDevelop创建。 3 | * 用户: BDSNetRunner 4 | * 日期: 2020/7/18 5 | * 时间: 12:32 6 | * 7 | * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 8 | */ 9 | using System; 10 | 11 | namespace CSR 12 | { 13 | partial class Plugin 14 | { 15 | private static MCCSAPI mapi = null; 16 | /// 17 | /// 静态api对象 18 | /// 19 | public static MCCSAPI api { get { return mapi; } } 20 | #region 插件统一调用接口,请勿随意更改 21 | public static int onServerStart(string pathandversion) { 22 | string path = null, version = null; 23 | bool commercial = false; 24 | string [] pav = pathandversion.Split(','); 25 | if (pav.Length > 1) { 26 | path = pav[0]; 27 | version = pav[1]; 28 | commercial = (pav[pav.Length - 1] == "1"); 29 | mapi = new MCCSAPI(path, version, commercial); 30 | if (mapi != null) { 31 | onStart(mapi); 32 | GC.KeepAlive(mapi); 33 | return 0; 34 | } 35 | } 36 | Console.WriteLine("Load failed."); 37 | return -1; 38 | } 39 | #endregion 40 | 41 | ~Plugin() 42 | { 43 | //Console.WriteLine("[CSR Plugin] Ref released."); 44 | } 45 | 46 | #region 必要接口 onStart ,由用户实现 47 | // public static void onStart(MCCSAPI api) 48 | #endregion 49 | } 50 | } -------------------------------------------------------------------------------- /BDSBaseLib/BDS/Plugin.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * 由SharpDevelop创建。 3 | * 用户: BDSNetRunner 4 | * 日期: 2020/7/18 5 | * 时间: 12:32 6 | * 7 | * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 8 | */ 9 | using System; 10 | 11 | namespace CSR 12 | { 13 | partial class Plugin 14 | { 15 | private static MCCSAPI mapi = null; 16 | /// 17 | /// 静态api对象 18 | /// 19 | public static MCCSAPI api { get { return mapi; } } 20 | #region 插件统一调用接口,请勿随意更改 21 | // public static int onServerStart(string pathandversion) { 22 | // string path = null, version = null; 23 | // bool commercial = false; 24 | // string [] pav = pathandversion.Split(','); 25 | // if (pav.Length > 1) { 26 | // path = pav[0]; 27 | // version = pav[1]; 28 | // commercial = (pav[pav.Length - 1] == "1"); 29 | // mapi = new MCCSAPI(path, version, commercial); 30 | // if (mapi != null) { 31 | // onStart(mapi); 32 | // GC.KeepAlive(mapi); 33 | // return 0; 34 | // } 35 | // } 36 | // Console.WriteLine("Load failed."); 37 | // return -1; 38 | // } 39 | #endregion 40 | 41 | ~Plugin() 42 | { 43 | //Console.WriteLine("[CSR Plugin] Ref released."); 44 | } 45 | 46 | #region 必要接口 onStart ,由用户实现 47 | // public static void onStart(MCCSAPI api) 48 | #endregion 49 | } 50 | } -------------------------------------------------------------------------------- /HideSeed/Hook.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using CSR; 4 | 5 | namespace HideSeed 6 | { 7 | /// 8 | /// 隐藏种子 9 | /// 10 | public class Hook 11 | { 12 | static int fakeseed; 13 | 14 | delegate ulong HIDESEEDPACKET(IntPtr a1, ulong a2); 15 | static IntPtr hideorg = IntPtr.Zero; 16 | /// 17 | /// 新方法,hook方式修改数据包,隐藏种子 18 | /// 19 | /// StartGamePacket指针 20 | /// BinaryStream引用 21 | /// 22 | private static readonly HIDESEEDPACKET hide = (a1, a2) => { 23 | Marshal.WriteInt32(a1 + 40, fakeseed); 24 | var org = Marshal.GetDelegateForFunctionPointer(hideorg); 25 | return org(a1, a2); 26 | }; 27 | 28 | // 注册hook 29 | public static void init(MCCSAPI api, int seed) { 30 | fakeseed = seed; 31 | int rva = 0; 32 | switch(api.VERSION) { // 版本适配 33 | case "1.16.1.2": 34 | rva = 0x00380010; 35 | break; 36 | case "1.16.10.2": 37 | rva = 0x0037FFE0; 38 | break; 39 | case "1.16.20.3": 40 | rva = 0x00386260; 41 | break; 42 | case "1.16.40.2": 43 | rva = 0x00386270; 44 | break; 45 | case "1.16.100.4": 46 | case "1.16.101.1": 47 | rva = 0x00972F80; 48 | break; 49 | } 50 | if (rva != 0) { 51 | bool ret = api.cshook(rva, // IDA StartGamePacket::write 52 | Marshal.GetFunctionPointerForDelegate(hide), 53 | out hideorg); 54 | if (ret) 55 | Console.WriteLine("[HideSeed] 种子已隐藏。"); 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /AlwaysNoCheat/Program2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CSR; 3 | 4 | namespace AlwaysNoCheat 5 | { 6 | /// 7 | /// 实现解锁全部命令为无需作弊状态可使用 8 | /// 9 | public class Program 10 | { 11 | public static readonly string LOGCONFIG = @"CSR\configs\logconfig.txt"; 12 | 13 | // 主入口实现 14 | public static void init(MCCSAPI api) { 15 | // 读取配置 根据配置设置hook 16 | ConfigReader cf = new ConfigReader(LOGCONFIG); 17 | 18 | bool nocheatable = cf.getValue("AlwaysNoCheat").ToLower() == "true"; 19 | string nocheatablestr = ("" + nocheatable).ToLower(); 20 | cf.setValue("AlwaysNoCheat", nocheatablestr); 21 | cf.save(); 22 | if (nocheatable) { 23 | Hook.init(api); 24 | } 25 | } 26 | } 27 | } 28 | 29 | namespace CSR { 30 | partial class Plugin { 31 | // 用户主实现 32 | public static void onStart(MCCSAPI api) { 33 | AlwaysNoCheat.Program.init(api); 34 | } 35 | 36 | private static MCCSAPI mapi = null; 37 | /// 38 | /// 静态api对象 39 | /// 40 | public static MCCSAPI api { get { return mapi; } } 41 | public static int onServerStart(string pathandversion) { 42 | string path = null, version = null; 43 | bool commercial = false; 44 | string [] pav = pathandversion.Split(','); 45 | if (pav.Length > 1) { 46 | path = pav[0]; 47 | version = pav[1]; 48 | commercial = (pav[pav.Length - 1] == "1"); 49 | mapi = new MCCSAPI(path, version, commercial); 50 | if (mapi != null) { 51 | onStart(mapi); 52 | GC.KeepAlive(mapi); 53 | return 0; 54 | } 55 | } 56 | Console.WriteLine("Load failed."); 57 | return -1; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /AntiWsCmd/AntiWsCmd.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * 由SharpDevelop创建。 3 | * 用户: classmates 4 | * 日期: 2021/8/6 5 | * 时间: 15:04 6 | * 7 | * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 8 | */ 9 | using System; 10 | using System.Runtime.InteropServices; 11 | using CSR; 12 | 13 | namespace AntiWsCmd 14 | { 15 | /// 16 | /// ws指令显形 17 | /// 18 | public class MyClass 19 | { 20 | static MCCSAPI mapi; 21 | static IntPtr org; 22 | 23 | public delegate long ClientAutomationCommandOrigin_getName(long a, long b); 24 | 25 | static readonly ClientAutomationCommandOrigin_getName wsf = (a, b) => { 26 | IntPtr func_PlayerCommandOrigin_getName = IntPtr.Zero; 27 | switch(mapi.VERSION) { 28 | case "1.17.10.04": // IDA PlayerCommandOrigin::getName 29 | func_PlayerCommandOrigin_getName = mapi.dlsym(0x00786150); 30 | break; 31 | } 32 | if (func_PlayerCommandOrigin_getName != IntPtr.Zero) { 33 | ClientAutomationCommandOrigin_getName pgname = Marshal.GetDelegateForFunctionPointer( 34 | func_PlayerCommandOrigin_getName); 35 | return pgname(a, b); 36 | } 37 | return 0; 38 | }; 39 | 40 | public static void init(MCCSAPI api) { 41 | mapi = api; 42 | switch (api.VERSION) { 43 | case "1.17.10.04": // IDA ClientAutomationCommandOrigin::getName 44 | if (api.cshook(0x00786020, Marshal.GetFunctionPointerForDelegate(wsf), out org)) { 45 | Console.WriteLine("[AntiWsCmd] ws指令显形已加载。"); 46 | } 47 | break; 48 | } 49 | } 50 | } 51 | } 52 | 53 | namespace CSR { 54 | partial class Plugin { 55 | public static void onStart(MCCSAPI api) { 56 | AntiWsCmd.MyClass.init(api); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /HideSeed/Program5.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CSR; 3 | 4 | namespace HideSeed 5 | { 6 | /// 7 | /// 隐藏种子 8 | /// 9 | public class Program 10 | { 11 | static MCCSAPI mapi; 12 | 13 | /// 14 | /// 固定配置文件所在路径 15 | /// 16 | static readonly string LOGCONFIG = @"CSR\configs\logconfig.txt"; 17 | 18 | public static void init(MCCSAPI api) { 19 | mapi = api; 20 | 21 | var cf = new ConfigReader(LOGCONFIG); 22 | 23 | var seedstr = cf.getValue("fakeseed"); 24 | if (!string.IsNullOrEmpty(seedstr)) { 25 | // 此处隐藏种子 26 | try { 27 | int fakeseed = Convert.ToInt32(seedstr); 28 | Hook.init(api, fakeseed); 29 | } catch(Exception e) {Console.WriteLine(e.StackTrace);} 30 | } else { 31 | Console.WriteLine("[HideSeed] 默认值为空,不予隐藏。"); 32 | cf.setValue("fakeseed", null); 33 | cf.save(); 34 | } 35 | } 36 | } 37 | } 38 | 39 | namespace CSR 40 | { 41 | partial class Plugin 42 | { 43 | private static MCCSAPI mapi = null; 44 | /// 45 | /// 静态api对象 46 | /// 47 | public static MCCSAPI api { get { return mapi; } } 48 | public static int onServerStart(string pathandversion) { 49 | string path = null, version = null; 50 | bool commercial = false; 51 | string [] pav = pathandversion.Split(','); 52 | if (pav.Length > 1) { 53 | path = pav[0]; 54 | version = pav[1]; 55 | commercial = (pav[pav.Length - 1] == "1"); 56 | mapi = new MCCSAPI(path, version, commercial); 57 | if (mapi != null) { 58 | onStart(mapi); 59 | GC.KeepAlive(mapi); 60 | return 0; 61 | } 62 | } 63 | Console.WriteLine("Load failed."); 64 | return -1; 65 | } 66 | 67 | /// 68 | /// 通用调用接口,需用户自行实现 69 | /// 70 | /// MC相关调用方法 71 | public static void onStart(MCCSAPI api) { 72 | Console.WriteLine("[HideSeed] 已装载。请等待版本适配..."); 73 | // TODO 此接口为必要实现 74 | HideSeed.Program.init(api); 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /AlwaysNoCheat/Hook.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Runtime.InteropServices; 4 | using CSR; 5 | 6 | namespace AlwaysNoCheat 7 | { 8 | /// 9 | /// 解锁所有指令为无作弊即可使用状态 10 | /// 11 | public class Hook 12 | { 13 | delegate ulong CMD_REG_Func(ulong a1, ulong a2, ulong a3, byte level, byte f1, byte f2); 14 | private static IntPtr _CS_REGISTERCOMMAND_org = IntPtr.Zero; 15 | /// 16 | /// 新方法,修改注册的命令标识,所有指令全部增加一个无需作弊可用的flag 17 | /// 18 | /// CommandRegistry句柄 19 | /// 指令原型 20 | /// 指令描述 21 | /// 需求op等级 22 | /// 指令属性flag1 23 | /// 指令属性flag2 24 | /// 25 | private static ulong _cshook_registerCommand(ulong a1, ulong a2, ulong a3, byte level, byte f1, byte f2) { 26 | f1 |= (byte)MCCSAPI.CommandCheatFlag.NotCheat; 27 | var org = Marshal.GetDelegateForFunctionPointer(_CS_REGISTERCOMMAND_org, typeof(CMD_REG_Func)) as CMD_REG_Func; 28 | return org(a1, a2, a3, level, f1, f2); 29 | } 30 | private static readonly CMD_REG_Func cs_reghookptr = _cshook_registerCommand; 31 | 32 | // 注册hook 33 | public static void init(MCCSAPI api) { 34 | int rva = 0; 35 | switch(api.VERSION) { // 版本适配 36 | case "1.16.1.2": 37 | rva = 0x00429850; 38 | break; 39 | case "1.16.10.2": 40 | rva = 0x00429820; 41 | break; 42 | case "1.16.20.3": 43 | rva = 0x0042D250; 44 | break; 45 | case "1.16.40.2": 46 | rva = 0x0042D260; 47 | break; 48 | case "1.16.100.4": 49 | case "1.16.101.1": 50 | rva = 0x00A1E8E0; 51 | break; 52 | } 53 | if (rva != 0) { 54 | bool ret = api.cshook(rva, // IDA CommandRegistry::registerCommand 55 | Marshal.GetFunctionPointerForDelegate(cs_reghookptr), 56 | out _CS_REGISTERCOMMAND_org); 57 | if (ret) 58 | Console.WriteLine("作弊指令已解锁。"); 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Vbtest/NewClass.vb: -------------------------------------------------------------------------------- 1 | ' 2 | ' 由SharpDevelop创建。 3 | ' 用户: BDSNetRunner 4 | ' 日期: 2020/8/4 5 | ' 时间: 17:34 6 | ' 7 | ' 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 8 | ' 9 | Imports CSR 10 | 11 | REM 本测试程序提供一个VB.Net调用范例,监听一次破坏方块 12 | Public Class MyVBClass 13 | 14 | Shared cb As MCCSAPI.EventCab 15 | 16 | Public Shared Sub init(api As MCCSAPI) 17 | cb = Function(x As Events) 18 | Dim e As DestroyBlockEvent = CType(BaseEvent.getFrom(x), DestroyBlockEvent) 19 | If (Not IsNothing(e)) Then 20 | Console.WriteLine("[vbtest] 玩家" + e.playername + " 在 " + e.dimension + " (" + e.XYZ.x.ToString() + 21 | "," + e.XYZ.y.ToString() + "," + e.XYZ.z.ToString() + ")处破坏 " + e.blockname + " 方块。") 22 | REM 此处卸载监听器 23 | api.removeAfterActListener(EventKey.onDestroyBlock, cb) 24 | End If 25 | Return False 26 | End Function 27 | api.addAfterActListener(EventKey.onDestroyBlock, cb) 28 | 29 | api.logout("这是一个vb测试插件。" + "api version=" + api.VERSION) 30 | End Sub 31 | 32 | End Class 33 | 34 | 35 | REM 注意工程根命名空间为CSR,保证接口可被调用 36 | namespace Global.CSR 37 | 38 | Public Class Plugin 39 | Shared mapi as MCCSAPI 40 | #Region "初始化通用接口,请勿随意更改" 41 | Public Shared Function onServerStart(pathandversion As String) As Int32 42 | Dim path as string, Version as string 43 | Dim commercial = False 44 | Dim pav() = pathandversion.Split(",".ToCharArray()) 45 | If pav.Length > 1 Then 46 | path = pav.GetValue(0).ToString() 47 | Version = pav.GetValue(1).ToString() 48 | commercial = pav.GetValue(pav.Length - 1).Equals("1") 49 | mapi = New MCCSAPI(path, Version, commercial) 50 | If Not IsNothing(mapi) Then 51 | onStart(mapi) 52 | GC.KeepAlive(mapi) 53 | Return 0 54 | End If 55 | End If 56 | Console.WriteLine("Load failed.") 57 | Return -1 58 | End Function 59 | #End Region 60 | 61 | Private Shared Sub onStart(api As MCCSAPI) 62 | REM TODO 此处需要自行实现 63 | Vbtest.MyVBClass.init(api) 64 | End Sub 65 | End Class 66 | 67 | end namespace -------------------------------------------------------------------------------- /BDSBaseLib/ConfigReader.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * 由SharpDevelop创建。 3 | * 用户: BDSNetRunner 4 | * 日期: 2020/7/27 5 | * 时间: 23:47 6 | * 7 | * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 8 | */ 9 | using System; 10 | using System.Collections; 11 | using System.IO; 12 | 13 | namespace CSR 14 | { 15 | /// 16 | /// 等号分割符用的配置文件 17 | /// 18 | public class ConfigReader 19 | { 20 | public string configpath; 21 | private Hashtable mconfigs; 22 | 23 | public ConfigReader(string filepath) 24 | { 25 | configpath = filepath; 26 | reload(); 27 | } 28 | 29 | /// 30 | /// 保存配置 31 | /// 32 | public void save() { 33 | var al = new ArrayList(); 34 | foreach(string k in mconfigs.Keys) { 35 | string pair = k + "=" + mconfigs[k]; 36 | al.Add(pair); 37 | } 38 | try { 39 | string dir = Path.GetDirectoryName(configpath); 40 | if (!Directory.Exists(dir)) 41 | Directory.CreateDirectory(dir); 42 | File.WriteAllLines(configpath, (string[])al.ToArray(typeof(string))); 43 | }catch(Exception e){Console.WriteLine(e.StackTrace);} 44 | } 45 | 46 | /// 47 | /// 重载配置文件 48 | /// 49 | public void reload() { 50 | mconfigs = new Hashtable(); 51 | string [] datas = null; 52 | try { 53 | datas = File.ReadAllLines(configpath); 54 | } catch {} 55 | if (datas != null && datas.Length > 0) { 56 | // 读取配置文件 57 | foreach(string s in datas) { 58 | var sec = s.Split('='); 59 | if (sec.Length == 2) { 60 | string k = sec[0].Trim(); 61 | string v = sec[1].Trim(); 62 | mconfigs[k] = v; 63 | } 64 | } 65 | } else { 66 | Console.WriteLine("[Base] 读取配置失败,使用默认配置。配置文件位于 {0}", configpath); 67 | } 68 | } 69 | 70 | /// 71 | /// 添加一个配置项 72 | /// 73 | /// 74 | /// 75 | /// 76 | public bool setValue(string k, string v) { 77 | if (mconfigs == null || string.IsNullOrEmpty(configpath)) 78 | return false; 79 | mconfigs[k] = v; 80 | return true; 81 | } 82 | 83 | /// 84 | /// 获取一个配置项 85 | /// 86 | /// 87 | /// 88 | public string getValue(string k) { 89 | string ret = string.Empty; 90 | if (mconfigs != null) { 91 | object o = mconfigs[k]; 92 | if (o != null) 93 | ret = o.ToString(); 94 | } 95 | return ret; 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /NoAutoCompactionTip/NoAutoCompactionTip.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Runtime.InteropServices; 4 | using CSR; 5 | 6 | namespace NoAutoCompactionTip 7 | { 8 | /// 9 | /// 隐藏 “Running AutoCompaction ...” 这个提示 10 | /// 11 | public class Program 12 | { 13 | public static MCCSAPI mapi; 14 | 15 | public static Hashtable rva_bedlogs = new Hashtable(); 16 | public static Hashtable rva_docalls = new Hashtable(); 17 | 18 | static IntPtr f_bed_log; 19 | static IntPtr f_do_call; 20 | 21 | public delegate long TASK_DO_CALL(long a, long b); 22 | public delegate void BED_LOG(int a1, int a2, long a3, int a4, int a5, long a6, int a7, long a8); 23 | 24 | // 隐藏输出,直接返回 25 | static readonly BED_LOG hidelog = (a1, a2, a3, a4, a5, a6, a7, a8) => {}; // Console.WriteLine("[NoAutoCompactionTip] 此处隐藏自动压缩提示。"); 26 | 27 | // 压缩任务期间,输出前截断LOG,完成任务后恢复log功能 28 | static readonly TASK_DO_CALL hook_task_do_call = (a, b) => { 29 | int rva = (int)rva_bedlogs[mapi.VERSION]; 30 | mapi.cshook(rva, Marshal.GetFunctionPointerForDelegate(hidelog), out f_bed_log); 31 | TASK_DO_CALL org = Marshal.GetDelegateForFunctionPointer(f_do_call); 32 | long ret = org(a, b); 33 | mapi.csunhook(Marshal.GetFunctionPointerForDelegate(hidelog), ref f_bed_log); 34 | return ret; 35 | }; 36 | 37 | 38 | 39 | public static void init(MCCSAPI api) { 40 | mapi = api; 41 | 42 | rva_bedlogs["1.16.220.02"] = 0x01051430; // IDA BedrockLog::log 43 | rva_bedlogs["1.16.221.01"] = 0x01051590; 44 | rva_bedlogs["1.17.0.03"] = 0x0134F520; 45 | rva_bedlogs["1.17.2.01"] = 0x0134EFF0; 46 | rva_bedlogs["1.17.10.04"] = 0x0137BF70; 47 | rva_docalls["1.16.220.02"] = 0xD50380; // IDA "Running AutoCompaction..." 48 | rva_docalls["1.16.221.01"] = 0xD50510; 49 | rva_docalls["1.17.2.01"] = 0xFC19D0; 50 | rva_docalls["1.17.10.04"] = 0xFAE630; 51 | int rva = (int)rva_docalls[api.VERSION]; 52 | if (rva != 0) 53 | if (api.cshook(rva, Marshal.GetFunctionPointerForDelegate(hook_task_do_call), out f_do_call)) { 54 | Console.WriteLine("[NoAutoCompactionTip] 隐藏AutoCompaction提示已加载。适配版本:" + api.VERSION); 55 | } 56 | } 57 | } 58 | } 59 | 60 | namespace CSR 61 | { 62 | partial class Plugin 63 | { 64 | 65 | /// 66 | /// 通用调用接口,需用户自行实现 67 | /// 68 | /// MC相关调用方法 69 | public static void onStart(MCCSAPI api) { 70 | Console.WriteLine("[NoAutoCompactionTip] 已装载。请等待版本适配..."); 71 | // TODO 此接口为必要实现 72 | NoAutoCompactionTip.Program.init(api); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /NoAutoCompactionTip/NoAutoCompactionTip.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {B31F56C3-CA13-42BA-8B6D-ACEA726E277E} 5 | {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 6 | Debug 7 | AnyCPU 8 | Library 9 | NoAutoCompactionTip 10 | NoAutoCompactionTip.csr 11 | v4.5.1 12 | Properties 13 | 14 | False 15 | False 16 | False 17 | False 18 | obj\$(Configuration)\ 19 | 4 20 | 21 | 22 | x64 23 | 4194304 24 | False 25 | Auto 26 | 4096 27 | 28 | 29 | bin\Debug\ 30 | True 31 | Full 32 | False 33 | True 34 | DEBUG;TRACE 35 | obj\ 36 | 37 | 38 | bin\Release\ 39 | False 40 | None 41 | True 42 | False 43 | TRACE 44 | 45 | 46 | 47 | 4.0 48 | 49 | 50 | 51 | 3.5 52 | 53 | 54 | 55 | 3.5 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /HideSeed/HideSeed.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {4029AB3A-B7C0-4BED-BA29-75B6A11DB545} 5 | {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 6 | Debug 7 | AnyCPU 8 | Library 9 | HideSeed 10 | HideSeed.csr 11 | v4.5.1 12 | Properties 13 | False 14 | False 15 | False 16 | False 17 | obj\$(Configuration)\ 18 | 4 19 | 20 | 21 | x64 22 | 4194304 23 | False 24 | Auto 25 | 4096 26 | 27 | 28 | bin\Debug\ 29 | True 30 | Full 31 | False 32 | True 33 | DEBUG;TRACE 34 | obj\ 35 | 36 | 37 | bin\Release\ 38 | False 39 | None 40 | True 41 | False 42 | TRACE 43 | 44 | 45 | 46 | 4.0 47 | 48 | 49 | 50 | 3.5 51 | 52 | 53 | 54 | 3.5 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | {cd9cca4e-2796-401a-9fc5-5e21165957c5} 64 | BDSBaseLib 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /AlwaysNoCheat/AlwaysNoCheat.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {ABD35EC4-F8D6-4AFD-B2ED-2296ADF1CD1F} 5 | {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 6 | Debug 7 | AnyCPU 8 | Library 9 | AlwaysNoCheat 10 | AlwaysNoCheat.csr 11 | v4.5.1 12 | Properties 13 | False 14 | False 15 | False 16 | False 17 | obj\$(Configuration)\ 18 | 4 19 | 20 | 21 | x64 22 | 4194304 23 | False 24 | Auto 25 | 4096 26 | 27 | 28 | bin\Debug\ 29 | True 30 | Full 31 | False 32 | True 33 | DEBUG;TRACE 34 | obj\ 35 | 36 | 37 | bin\Release\ 38 | False 39 | None 40 | True 41 | False 42 | TRACE 43 | 44 | 45 | 46 | 4.0 47 | 48 | 49 | 50 | 3.5 51 | 52 | 53 | 54 | 3.5 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | {cd9cca4e-2796-401a-9fc5-5e21165957c5} 64 | BDSBaseLib 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /AntiWsCmd/AntiWsCmd.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {BC9D245C-2C25-4AA8-B0AC-C1E6462CA585} 5 | {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 6 | Debug 7 | AnyCPU 8 | Library 9 | AntiWsCmd 10 | AntiWsCmd.csr 11 | v4.5.1 12 | Properties 13 | 14 | False 15 | False 16 | False 17 | OnBuildSuccess 18 | False 19 | False 20 | False 21 | obj\$(Configuration)\ 22 | 4 23 | 24 | 25 | AnyCPU 26 | 4194304 27 | False 28 | Auto 29 | 4096 30 | 31 | 32 | bin\Debug\ 33 | True 34 | Full 35 | False 36 | True 37 | DEBUG;TRACE 38 | obj\ 39 | Project 40 | 41 | 42 | bin\Release\ 43 | False 44 | None 45 | True 46 | False 47 | TRACE 48 | 49 | 50 | 51 | 4.0 52 | 53 | 54 | 55 | 3.5 56 | 57 | 58 | 59 | 3.5 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /Visitor/Visitor.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {EF71BE68-EB03-4529-8D30-5BCE06939166} 5 | {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 6 | Debug 7 | AnyCPU 8 | Library 9 | Visitor 10 | Visitor.csr 11 | v4.5.1 12 | Properties 13 | False 14 | False 15 | False 16 | False 17 | obj\$(Configuration)\ 18 | 4 19 | 20 | 21 | x64 22 | 4194304 23 | False 24 | Auto 25 | 4096 26 | 27 | 28 | bin\Debug\ 29 | True 30 | Full 31 | False 32 | True 33 | DEBUG;TRACE 34 | obj\ 35 | 36 | 37 | bin\Release\ 38 | False 39 | None 40 | True 41 | False 42 | TRACE 43 | 44 | 45 | 46 | 4.0 47 | 48 | 49 | 50 | 3.5 51 | 52 | 53 | 3.5 54 | 55 | 56 | 57 | 3.5 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | {cd9cca4e-2796-401a-9fc5-5e21165957c5} 66 | BDSBaseLib 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /Testcase/Testcase.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {E45B1153-ED6C-4188-8402-542629847203} 5 | {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 6 | Debug 7 | AnyCPU 8 | Library 9 | Testcase 10 | Testcase.csr 11 | v4.5.1 12 | Properties 13 | False 14 | False 15 | False 16 | False 17 | obj\$(Configuration)\ 18 | 4 19 | 20 | 21 | x64 22 | 4194304 23 | False 24 | Auto 25 | 4096 26 | 27 | 28 | bin\Debug\ 29 | True 30 | Full 31 | False 32 | True 33 | DEBUG;TRACE 34 | obj\ 35 | 36 | 37 | bin\Release\ 38 | False 39 | None 40 | True 41 | False 42 | TRACE 43 | 44 | 45 | 46 | 4.0 47 | 48 | 49 | 50 | 3.5 51 | 52 | 53 | 3.5 54 | 55 | 56 | 57 | 3.5 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | {cd9cca4e-2796-401a-9fc5-5e21165957c5} 67 | BDSBaseLib 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /BDSBaseLib/BDSBaseLib.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {CD9CCA4E-2796-401A-9FC5-5E21165957C5} 5 | {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 6 | Debug 7 | AnyCPU 8 | Library 9 | BDSBaseLib 10 | BDSBaseLib.csr 11 | v4.5.1 12 | Properties 13 | False 14 | OnBuildSuccess 15 | False 16 | False 17 | False 18 | obj\$(Configuration)\ 19 | 4 20 | 21 | 22 | x64 23 | 4194304 24 | False 25 | Auto 26 | 4096 27 | 28 | 29 | bin\Debug\ 30 | True 31 | Full 32 | False 33 | True 34 | DEBUG;TRACE 35 | obj\ 36 | 37 | 38 | bin\Release\ 39 | False 40 | None 41 | True 42 | False 43 | TRACE 44 | 45 | 46 | 47 | 4.0 48 | 49 | 50 | 51 | 3.5 52 | 53 | 54 | 55 | 3.5 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /Vbtest/Vbtest.vbproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {493FBFDD-1AB0-4578-B4FF-ED1DDE4C3576} 5 | {F184B08F-C81C-45F6-A57F-5ABD9991F28F} 6 | Debug 7 | AnyCPU 8 | Library 9 | Windows 10 | Vbtest 11 | Vbtest.csr 12 | v4.5.1 13 | Properties 14 | On 15 | False 16 | Off 17 | Binary 18 | False 19 | obj\$(Configuration)\ 20 | 4 21 | 22 | 23 | x64 24 | 4194304 25 | False 26 | Auto 27 | 4096 28 | 29 | 30 | bin\Debug\ 31 | True 32 | Full 33 | False 34 | DEBUG=1,TRACE=1 35 | obj\ 36 | 37 | 38 | bin\Release\ 39 | False 40 | None 41 | True 42 | TRACE=1 43 | 44 | 45 | 46 | 4.0 47 | 48 | 49 | 50 | 3.5 51 | 52 | 53 | 54 | 3.5 55 | 56 | 57 | 58 | 3.5 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | {cd9cca4e-2796-401a-9fc5-5e21165957c5} 75 | BDSBaseLib 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /Logging/Logging.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {517728DB-1EF1-4845-A678-CE1001492856} 5 | {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 6 | Debug 7 | AnyCPU 8 | Library 9 | CSR 10 | Logging.csr 11 | v4.5.1 12 | Properties 13 | False 14 | False 15 | False 16 | obj\$(Configuration)\ 17 | 4 18 | False 19 | False 20 | False 21 | OnBuildSuccess 22 | 23 | 24 | 25 | x64 26 | 4194304 27 | False 28 | Auto 29 | 4096 30 | 31 | 32 | bin\Debug\ 33 | True 34 | Full 35 | False 36 | True 37 | DEBUG;TRACE 38 | obj\ 39 | 40 | 41 | bin\Release\ 42 | False 43 | None 44 | True 45 | False 46 | TRACE 47 | obj\ 48 | 49 | 50 | 51 | 4.0 52 | 53 | 54 | 55 | 3.5 56 | 57 | 58 | 59 | 3.5 60 | 61 | 62 | 63 | 3.5 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | {cd9cca4e-2796-401a-9fc5-5e21165957c5} 75 | BDSBaseLib 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /Testcase/SimpleGUI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Threading; 4 | using System.Web.Script.Serialization; 5 | using CSR; 6 | 7 | namespace Testcase 8 | { 9 | /// 10 | /// 简易表单处理程序 11 | /// 12 | public class SimpleGUI { 13 | private MCCSAPI mapi; 14 | 15 | public delegate void ONSELECT(string selected); 16 | public delegate void ONTIMEOUT(); 17 | /// 18 | /// 表单id 19 | /// 20 | public uint id; 21 | /// 22 | /// 玩家uuid 23 | /// 24 | public string uuid; 25 | /// 26 | /// 返回的选项 27 | /// 28 | public string selected; 29 | /// 30 | /// 表单标题 31 | /// 32 | public string title; 33 | /// 34 | /// 内容 35 | /// 36 | public string content; 37 | /// 38 | /// 按钮内容 39 | /// 40 | public ArrayList buttons; 41 | /// 42 | /// 处理选择程序 43 | /// 44 | public ONSELECT onselected; 45 | /// 46 | /// 超时处理程序 47 | /// 48 | public ONTIMEOUT ontimeout; 49 | /// 50 | /// 超时毫秒数 51 | /// 52 | public int timeout; 53 | /// 54 | /// 注册回调 55 | /// 56 | public MCCSAPI.EventCab fmcb; 57 | /// 58 | /// 是否取消 59 | /// 60 | public bool canceled; 61 | /// 62 | /// 创建一个简单表单 63 | /// 64 | /// 65 | /// 玩家uuid 66 | /// 标题 67 | /// 内容 68 | /// 按钮列表 69 | public SimpleGUI(MCCSAPI api, string u, string t, string c, ArrayList b) { 70 | mapi = api; 71 | uuid = u; 72 | title = t; 73 | content = c; 74 | buttons = (b ?? new ArrayList()); 75 | } 76 | /// 77 | /// 开始超时监听 78 | /// 79 | public void startTimeout() { 80 | Thread t = new Thread(()=>{ 81 | Thread.Sleep(timeout); 82 | if (!canceled) { 83 | mapi.releaseForm(id); 84 | mapi.removeBeforeActListener(EventKey.onFormSelect, fmcb); 85 | if (ontimeout != null) 86 | ontimeout(); 87 | } 88 | }); 89 | t.Start(); 90 | } 91 | /// 92 | /// 取消一个超时监听 93 | /// 94 | public void cancelTimeout() { 95 | canceled = true; 96 | } 97 | /// 98 | /// 发送一个简易表单 99 | /// 100 | /// 超时时间 101 | /// 主选择处理函数 102 | /// 超时处理函数 103 | /// 104 | public bool send(int tout, ONSELECT func, ONTIMEOUT tofunc) { 105 | timeout = tout; 106 | onselected = func; 107 | ontimeout = tofunc; 108 | fmcb = (x) => { 109 | var e = BaseEvent.getFrom(x) as FormSelectEvent; 110 | if (e.formid == id) { // 确定是当前表单 111 | mapi.removeBeforeActListener(EventKey.onFormSelect, fmcb); 112 | cancelTimeout(); 113 | onselected(e.selected); 114 | } 115 | return true; 116 | }; 117 | mapi.addBeforeActListener(EventKey.onFormSelect, fmcb); 118 | string bts = "[]"; 119 | if (buttons != null && buttons.Count > 0) { 120 | var ser = new JavaScriptSerializer(); 121 | bts = ser.Serialize(buttons); 122 | } 123 | id = mapi.sendSimpleForm(uuid, title, content, bts); 124 | bool ret = (id != 0); 125 | if (timeout > 0) { 126 | startTimeout(); 127 | } 128 | return ret; 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /NoAutoCompactionTip/BDS/MCCSAPI.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * 由SharpDevelop创建。 3 | * 用户: BDSNetRunner 4 | * 日期: 2020/7/17 5 | * 时间: 16:27 6 | * 7 | * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 8 | */ 9 | using System; 10 | using System.Runtime.InteropServices; 11 | using System.Text; 12 | 13 | namespace CSR 14 | { 15 | /// 16 | /// API接口定义 17 | /// 18 | public class MCCSAPI 19 | { 20 | [DllImport("kernel32.dll")] 21 | private extern static IntPtr LoadLibrary(String path); 22 | [DllImport("kernel32.dll")] 23 | private extern static IntPtr GetProcAddress(IntPtr lib, String funcName); 24 | [DllImport("kernel32.dll")] 25 | private extern static bool FreeLibrary(IntPtr lib); 26 | 27 | private readonly string mVersion; 28 | /// 29 | /// 插件版本 30 | /// 31 | public string VERSION {get{return mVersion;}} 32 | private readonly bool mcommercial; 33 | /// 34 | /// 平台类型 35 | /// 36 | public bool COMMERCIAL {get{return mcommercial;}} 37 | 38 | private IntPtr hLib; 39 | public MCCSAPI(String DLLPath, string ver, bool commercial) 40 | { 41 | mVersion = ver; 42 | mcommercial = commercial; 43 | hLib = LoadLibrary(DLLPath); 44 | if (hLib != IntPtr.Zero) { 45 | initApis(); 46 | } 47 | } 48 | ~MCCSAPI() 49 | { 50 | FreeLibrary(hLib); 51 | } 52 | //将要执行的函数转换为委托 53 | private T Invoke(String APIName) 54 | { 55 | IntPtr api = GetProcAddress(hLib, APIName); 56 | if (api != IntPtr.Zero) 57 | //return (T)Marshal.GetDelegateForFunctionPointer(api, typeof(T)); 58 | //若.net framework版本高于4.5.1可用以下替换以上 59 | return Marshal.GetDelegateForFunctionPointer(api); 60 | Console.WriteLine("Get Api {0} failed.", APIName); 61 | return default(T); 62 | } 63 | 64 | private delegate bool CSHOOKFUNC(int rva, IntPtr hook, out IntPtr org); 65 | private CSHOOKFUNC ccshook; 66 | private delegate bool CSUNHOOKFUNC(IntPtr hook, out IntPtr org); 67 | private CSUNHOOKFUNC ccsunhook; 68 | private delegate IntPtr DLSYMFUNC(int rva); 69 | private DLSYMFUNC cdlsym; 70 | private delegate bool READHARDMEMORY(int rva, byte[] odata, int size); 71 | private READHARDMEMORY creadHardMemory, cwriteHardMemory; 72 | 73 | // 初始化所有api函数 74 | void initApis() 75 | { 76 | ccshook = Invoke("cshook"); 77 | ccsunhook = Invoke("csunhook"); 78 | cdlsym = Invoke("dlsym"); 79 | creadHardMemory = Invoke("readHardMemory"); 80 | cwriteHardMemory = Invoke("writeHardMemory"); 81 | } 82 | 83 | // 底层相关 84 | 85 | /// 86 | /// 设置一个钩子 87 | /// 88 | /// 原型函数相对地址 89 | /// 新函数 90 | /// 待保存原型函数的指针 91 | /// 92 | public bool cshook(int rva, IntPtr hook, out IntPtr org) 93 | { 94 | IntPtr sorg = IntPtr.Zero; 95 | var ret = ccshook != null && ccshook(rva, hook, out sorg); 96 | org = sorg; 97 | return ret; 98 | } 99 | /// 100 | /// 卸载一个钩子 101 | /// 102 | /// 待卸载的函数 103 | /// 已保存了原型函数的指针 104 | /// 105 | public bool csunhook(IntPtr hook, ref IntPtr org) { 106 | IntPtr sorg = org; 107 | var ret = ccsunhook != null && ccsunhook(hook, out sorg); 108 | org = sorg; 109 | return ret; 110 | } 111 | /// 112 | /// 取相对地址对应的实际指针 113 | /// 114 | /// 115 | /// 116 | public IntPtr dlsym(int rva) { 117 | return cdlsym != null ? cdlsym(rva) : 118 | IntPtr.Zero; 119 | } 120 | /// 121 | /// 读特定段内存硬编码 122 | /// 123 | /// 函数片段起始位置相对地址 124 | /// 内存长度 125 | /// 126 | public byte[] readHardMemory(int rva, int size) { 127 | byte[] x = new byte[size]; 128 | if (creadHardMemory != null) 129 | if (creadHardMemory(rva, x, size)) 130 | return x; 131 | return null; 132 | } 133 | /// 134 | /// 写特定段内存硬编码 135 | /// 136 | /// 函数片段起始位置相对地址 137 | /// 新数据内容 138 | /// 内存长度 139 | /// 140 | public bool writeHardMemory(int rva, byte[] data, int size) { 141 | return (cwriteHardMemory != null) && cwriteHardMemory(rva, data, size); 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /CSRMods.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | # SharpDevelop 5.1 5 | VisualStudioVersion = 12.0.20827.3 6 | MinimumVisualStudioVersion = 10.0.40219.1 7 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Logging", "Logging\Logging.csproj", "{517728DB-1EF1-4845-A678-CE1001492856}" 8 | EndProject 9 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AlwaysNoCheat", "AlwaysNoCheat\AlwaysNoCheat.csproj", "{ABD35EC4-F8D6-4AFD-B2ED-2296ADF1CD1F}" 10 | EndProject 11 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BDSBaseLib", "BDSBaseLib\BDSBaseLib.csproj", "{CD9CCA4E-2796-401A-9FC5-5E21165957C5}" 12 | EndProject 13 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcase", "Testcase\Testcase.csproj", "{E45B1153-ED6C-4188-8402-542629847203}" 14 | EndProject 15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Visitor", "Visitor\Visitor.csproj", "{EF71BE68-EB03-4529-8D30-5BCE06939166}" 16 | EndProject 17 | Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Vbtest", "Vbtest\Vbtest.vbproj", "{493FBFDD-1AB0-4578-B4FF-ED1DDE4C3576}" 18 | EndProject 19 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HideSeed", "HideSeed\HideSeed.csproj", "{4029AB3A-B7C0-4BED-BA29-75B6A11DB545}" 20 | EndProject 21 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NoAutoCompactionTip", "NoAutoCompactionTip\NoAutoCompactionTip.csproj", "{B31F56C3-CA13-42BA-8B6D-ACEA726E277E}" 22 | EndProject 23 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AntiWsCmd", "AntiWsCmd\AntiWsCmd.csproj", "{BC9D245C-2C25-4AA8-B0AC-C1E6462CA585}" 24 | EndProject 25 | Global 26 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 27 | Debug|Any CPU = Debug|Any CPU 28 | Release|Any CPU = Release|Any CPU 29 | EndGlobalSection 30 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 31 | {517728DB-1EF1-4845-A678-CE1001492856}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 32 | {517728DB-1EF1-4845-A678-CE1001492856}.Debug|Any CPU.Build.0 = Debug|Any CPU 33 | {517728DB-1EF1-4845-A678-CE1001492856}.Release|Any CPU.ActiveCfg = Release|Any CPU 34 | {517728DB-1EF1-4845-A678-CE1001492856}.Release|Any CPU.Build.0 = Release|Any CPU 35 | {ABD35EC4-F8D6-4AFD-B2ED-2296ADF1CD1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 36 | {ABD35EC4-F8D6-4AFD-B2ED-2296ADF1CD1F}.Debug|Any CPU.Build.0 = Debug|Any CPU 37 | {ABD35EC4-F8D6-4AFD-B2ED-2296ADF1CD1F}.Release|Any CPU.ActiveCfg = Release|Any CPU 38 | {ABD35EC4-F8D6-4AFD-B2ED-2296ADF1CD1F}.Release|Any CPU.Build.0 = Release|Any CPU 39 | {CD9CCA4E-2796-401A-9FC5-5E21165957C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 40 | {CD9CCA4E-2796-401A-9FC5-5E21165957C5}.Debug|Any CPU.Build.0 = Debug|Any CPU 41 | {CD9CCA4E-2796-401A-9FC5-5E21165957C5}.Release|Any CPU.ActiveCfg = Release|Any CPU 42 | {CD9CCA4E-2796-401A-9FC5-5E21165957C5}.Release|Any CPU.Build.0 = Release|Any CPU 43 | {E45B1153-ED6C-4188-8402-542629847203}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 44 | {E45B1153-ED6C-4188-8402-542629847203}.Debug|Any CPU.Build.0 = Debug|Any CPU 45 | {E45B1153-ED6C-4188-8402-542629847203}.Release|Any CPU.ActiveCfg = Release|Any CPU 46 | {E45B1153-ED6C-4188-8402-542629847203}.Release|Any CPU.Build.0 = Release|Any CPU 47 | {EF71BE68-EB03-4529-8D30-5BCE06939166}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 48 | {EF71BE68-EB03-4529-8D30-5BCE06939166}.Debug|Any CPU.Build.0 = Debug|Any CPU 49 | {EF71BE68-EB03-4529-8D30-5BCE06939166}.Release|Any CPU.ActiveCfg = Release|Any CPU 50 | {EF71BE68-EB03-4529-8D30-5BCE06939166}.Release|Any CPU.Build.0 = Release|Any CPU 51 | {493FBFDD-1AB0-4578-B4FF-ED1DDE4C3576}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 52 | {493FBFDD-1AB0-4578-B4FF-ED1DDE4C3576}.Debug|Any CPU.Build.0 = Debug|Any CPU 53 | {493FBFDD-1AB0-4578-B4FF-ED1DDE4C3576}.Release|Any CPU.ActiveCfg = Release|Any CPU 54 | {493FBFDD-1AB0-4578-B4FF-ED1DDE4C3576}.Release|Any CPU.Build.0 = Release|Any CPU 55 | {4029AB3A-B7C0-4BED-BA29-75B6A11DB545}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 56 | {4029AB3A-B7C0-4BED-BA29-75B6A11DB545}.Debug|Any CPU.Build.0 = Debug|Any CPU 57 | {4029AB3A-B7C0-4BED-BA29-75B6A11DB545}.Release|Any CPU.ActiveCfg = Release|Any CPU 58 | {4029AB3A-B7C0-4BED-BA29-75B6A11DB545}.Release|Any CPU.Build.0 = Release|Any CPU 59 | {B31F56C3-CA13-42BA-8B6D-ACEA726E277E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 60 | {B31F56C3-CA13-42BA-8B6D-ACEA726E277E}.Debug|Any CPU.Build.0 = Debug|Any CPU 61 | {B31F56C3-CA13-42BA-8B6D-ACEA726E277E}.Release|Any CPU.ActiveCfg = Release|Any CPU 62 | {B31F56C3-CA13-42BA-8B6D-ACEA726E277E}.Release|Any CPU.Build.0 = Release|Any CPU 63 | {BC9D245C-2C25-4AA8-B0AC-C1E6462CA585}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 64 | {BC9D245C-2C25-4AA8-B0AC-C1E6462CA585}.Debug|Any CPU.Build.0 = Debug|Any CPU 65 | {BC9D245C-2C25-4AA8-B0AC-C1E6462CA585}.Release|Any CPU.ActiveCfg = Release|Any CPU 66 | {BC9D245C-2C25-4AA8-B0AC-C1E6462CA585}.Release|Any CPU.Build.0 = Release|Any CPU 67 | EndGlobalSection 68 | EndGlobal 69 | -------------------------------------------------------------------------------- /AntiWsCmd/BDS/MCCSAPI.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * 由SharpDevelop创建。 3 | * 用户: BDSNetRunner 4 | * 日期: 2020/7/17 5 | * 时间: 16:27 6 | * 7 | * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 8 | */ 9 | using System; 10 | using System.Collections; 11 | using System.Collections.Generic; 12 | using System.Runtime.InteropServices; 13 | 14 | namespace CSR 15 | { 16 | /// 17 | /// API接口定义 18 | /// 19 | public class MCCSAPI 20 | { 21 | [DllImport("kernel32.dll")] 22 | private extern static IntPtr LoadLibrary(String path); 23 | [DllImport("kernel32.dll")] 24 | private extern static IntPtr GetProcAddress(IntPtr lib, String funcName); 25 | [DllImport("kernel32.dll")] 26 | private extern static bool FreeLibrary(IntPtr lib); 27 | 28 | private readonly string mVersion; 29 | /// 30 | /// 插件版本 31 | /// 32 | public string VERSION {get{return mVersion;}} 33 | private readonly bool mcommercial; 34 | /// 35 | /// 平台类型 36 | /// 37 | public bool COMMERCIAL {get{return mcommercial;}} 38 | 39 | // 注册事件回调管理,避免回收 40 | private Dictionary callbks = new Dictionary(); 41 | // 发送tick方法管理,避免回收 42 | private Dictionary ticks = new Dictionary(); 43 | 44 | private IntPtr hLib; 45 | public MCCSAPI(String DLLPath, string ver, bool commercial) 46 | { 47 | mVersion = ver; 48 | mcommercial = commercial; 49 | hLib = LoadLibrary(DLLPath); 50 | if (hLib != IntPtr.Zero) { 51 | initApis(); 52 | } 53 | } 54 | ~MCCSAPI() 55 | { 56 | FreeLibrary(hLib); 57 | } 58 | //将要执行的函数转换为委托 59 | private T Invoke(String APIName) 60 | { 61 | IntPtr api = GetProcAddress(hLib, APIName); 62 | if (api != IntPtr.Zero) 63 | //return (T)Marshal.GetDelegateForFunctionPointer(api, typeof(T)); 64 | //若.net framework版本高于4.5.1可用以下替换以上 65 | return Marshal.GetDelegateForFunctionPointer(api); 66 | Console.WriteLine("Get Api {0} failed.", APIName); 67 | return default(T); 68 | } 69 | 70 | private delegate bool CSHOOKFUNC(int rva, IntPtr hook, out IntPtr org); 71 | private CSHOOKFUNC ccshook; 72 | private delegate bool CSUNHOOKFUNC(IntPtr hook, out IntPtr org); 73 | private CSUNHOOKFUNC ccsunhook; 74 | private delegate IntPtr DLSYMFUNC(int rva); 75 | private DLSYMFUNC cdlsym; 76 | private delegate bool READHARDMEMORY(int rva, byte[] odata, int size); 77 | private READHARDMEMORY creadHardMemory, cwriteHardMemory; 78 | 79 | // 初始化所有api函数 80 | void initApis() 81 | { 82 | ccshook = Invoke("cshook"); 83 | ccsunhook = Invoke("csunhook"); 84 | cdlsym = Invoke("dlsym"); 85 | creadHardMemory = Invoke("readHardMemory"); 86 | cwriteHardMemory = Invoke("writeHardMemory"); 87 | } 88 | 89 | // 底层相关 90 | 91 | /// 92 | /// 设置一个钩子 93 | /// 94 | /// 原型函数相对地址 95 | /// 新函数 96 | /// 待保存原型函数的指针 97 | /// 98 | public bool cshook(int rva, IntPtr hook, out IntPtr org) 99 | { 100 | IntPtr sorg = IntPtr.Zero; 101 | var ret = ccshook != null && ccshook(rva, hook, out sorg); 102 | org = sorg; 103 | return ret; 104 | } 105 | /// 106 | /// 卸载一个钩子 107 | /// 108 | /// 待卸载的函数 109 | /// 已保存了原型函数的指针 110 | /// 111 | public bool csunhook(IntPtr hook, ref IntPtr org) { 112 | IntPtr sorg = org; 113 | var ret = ccsunhook != null && ccsunhook(hook, out sorg); 114 | org = sorg; 115 | return ret; 116 | } 117 | /// 118 | /// 取相对地址对应的实际指针 119 | /// 120 | /// 121 | /// 122 | public IntPtr dlsym(int rva) { 123 | return cdlsym != null ? cdlsym(rva) : 124 | IntPtr.Zero; 125 | } 126 | 127 | /// 128 | /// 读特定段内存硬编码 129 | /// 130 | /// 函数片段起始位置相对地址 131 | /// 内存长度 132 | /// 133 | public byte[] readHardMemory(int rva, int size) { 134 | byte[] x = new byte[size]; 135 | if (creadHardMemory != null) 136 | if (creadHardMemory(rva, x, size)) 137 | return x; 138 | return null; 139 | } 140 | 141 | /// 142 | /// 写特定段内存硬编码 143 | /// 144 | /// 函数片段起始位置相对地址 145 | /// 新数据内容 146 | /// 内存长度 147 | /// 148 | public bool writeHardMemory(int rva, byte[] data, int size) 149 | { 150 | return (cwriteHardMemory != null) && cwriteHardMemory(rva, data, size); 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /Visitor/Program4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Web.Script.Serialization; 6 | using CSR; 7 | 8 | namespace Visitor 9 | { 10 | /// 11 | /// 实现后台访客 12 | /// 13 | public class Program 14 | { 15 | static MCCSAPI mapi; 16 | 17 | static Dictionary namexuids = new Dictionary(); 18 | static Dictionary nameuuids = new Dictionary(); 19 | 20 | // 从在线列表中获取xuid 21 | public static string getXUID(string name) 22 | { 23 | string xuid = null; 24 | if (namexuids.TryGetValue(name, out xuid)) { 25 | return xuid; 26 | } 27 | // 重载在线列表 28 | namexuids.Clear(); 29 | nameuuids.Clear(); 30 | string ols = mapi.getOnLinePlayers(); 31 | if (!string.IsNullOrEmpty(ols)) { 32 | var ser = new JavaScriptSerializer(); 33 | ArrayList ol = ser.Deserialize(ols); 34 | foreach (Dictionary d in ol) { 35 | object tname, txuid, tuuid; 36 | if (d.TryGetValue("playername", out tname)) { 37 | if (d.TryGetValue("xuid", out txuid)) { 38 | namexuids[tname.ToString()] = txuid.ToString(); 39 | if (tname.ToString() == name) { 40 | xuid = txuid.ToString(); 41 | } 42 | } 43 | if (d.TryGetValue("uuid", out tuuid)) { 44 | nameuuids[tname.ToString()] = tuuid.ToString(); 45 | } 46 | } 47 | } 48 | } 49 | return xuid; 50 | } 51 | // 获取uuid 52 | public static string getUUUD(string name) 53 | { 54 | string uuid; 55 | if (nameuuids.TryGetValue(name, out uuid)) { 56 | return uuid; 57 | } 58 | // 重载在线列表 59 | nameuuids.Clear(); 60 | namexuids.Clear(); 61 | string ols = mapi.getOnLinePlayers(); 62 | if (!string.IsNullOrEmpty(ols)) { 63 | try { 64 | var ser = new JavaScriptSerializer(); 65 | ArrayList ol = ser.Deserialize(ols); 66 | foreach (Dictionary d in ol) { 67 | object tname, tuuid, txuid; 68 | if (d.TryGetValue("playername", out tname)) { 69 | if (d.TryGetValue("uuid", out tuuid)) { 70 | nameuuids[tname.ToString()] = tuuid.ToString(); 71 | if (tname.ToString() == name) { 72 | uuid = tuuid.ToString(); 73 | } 74 | } 75 | if (d.TryGetValue("xuid", out txuid)) { 76 | namexuids[tname.ToString()] = txuid.ToString(); 77 | } 78 | } 79 | } 80 | } catch(Exception e){Console.WriteLine(e.StackTrace);} 81 | } 82 | return uuid; 83 | } 84 | 85 | // 从白名单中获取xuid 86 | public static string getLeftXUID(string name) { 87 | string wl = string.Empty; 88 | try { 89 | wl = File.ReadAllText("whitelist.json"); 90 | } catch{} 91 | var ser = new JavaScriptSerializer(); 92 | if (!string.IsNullOrEmpty(wl)) { 93 | try { 94 | var wlal = ser.Deserialize(wl); 95 | if (wlal != null && wlal.Count > 0) { 96 | foreach (Dictionary d in wlal) { 97 | object dname; 98 | if (d.TryGetValue("name", out dname)) { 99 | if (dname.ToString() == name) { // 找到 100 | object dxuid; 101 | if (d.TryGetValue("xuid", out dxuid)) { 102 | return dxuid.ToString(); 103 | } 104 | } 105 | } 106 | } 107 | } 108 | }catch(Exception e){Console.WriteLine(e.StackTrace);} 109 | } 110 | return null; 111 | } 112 | 113 | // 将玩家加入权限列表 114 | public static bool visitorPlayer(string xuid) { 115 | if (!string.IsNullOrEmpty(xuid)) { 116 | var ser = new JavaScriptSerializer(); 117 | string sops = string.Empty; 118 | try { 119 | sops = File.ReadAllText("permissions.json"); 120 | } catch{} 121 | var opl = new ArrayList(); 122 | bool finded = false; 123 | if (!string.IsNullOrEmpty(sops)) { 124 | var vis = ser.Deserialize(sops); 125 | vis = vis ?? new ArrayList(); 126 | opl = vis; 127 | foreach (Dictionary d in opl) { 128 | object dxuid; 129 | if (d.TryGetValue("xuid", out dxuid)) { 130 | if (dxuid.ToString() == xuid) { // 找到 131 | d["permission"] = "visitor"; 132 | finded = true; 133 | break; 134 | } 135 | } 136 | } 137 | } 138 | if (!finded) { // 装入新权限 139 | var nd = new Dictionary(); 140 | nd["permission"] = "visitor"; 141 | nd["xuid"] = xuid; 142 | opl.Add(nd); 143 | } 144 | try { 145 | File.WriteAllText("permissions.json", ser.Serialize(opl)); 146 | mapi.runcmd("permission reload"); // 重载权限配置 147 | return true; 148 | } catch{} 149 | } 150 | return false; 151 | } 152 | // 发送一个tellraw 153 | public static void tellraw(string pname, string msg) { 154 | var ser = new JavaScriptSerializer(); 155 | var rawtxt = new Dictionary(); 156 | var rawtext = new ArrayList(); 157 | var text = new Dictionary(); 158 | text["text"] = msg; 159 | rawtext.Add(text); 160 | rawtxt["rawtext"] = rawtext; 161 | mapi.runcmd("tellraw \"" + pname + "\" " + ser.Serialize(rawtxt)); 162 | } 163 | 164 | // 主入口实现 165 | public static void init(MCCSAPI api) { 166 | mapi = api; 167 | 168 | // 监听后台指令 169 | api.addBeforeActListener(EventKey.onServerCmd, x => { 170 | var e = BaseEvent.getFrom(x) as ServerCmdEvent; 171 | string scmd = e.cmd.Trim(); 172 | if (scmd.ToLower().IndexOf("visitor") == 0) { // 可能找到 173 | string[] cmds = scmd.Split(' '); 174 | if (cmds[0].ToLower() == "visitor") { // 找到 175 | if (cmds.Length > 1) { 176 | string pname = scmd.Substring(7).Trim().Trim('"'); 177 | string xuid = null; 178 | if (!string.IsNullOrEmpty(xuid = getXUID(pname))) { 179 | // 在线降权 180 | if (visitorPlayer(xuid)) { 181 | tellraw(pname, "您已被降级权限为访客。"); 182 | api.logout("Visited : " + pname); 183 | return false; 184 | } 185 | } else if (!string.IsNullOrEmpty(xuid = getLeftXUID(pname))) { 186 | // 离线降权 187 | if (visitorPlayer(xuid)) { 188 | api.logout("玩家 " + pname + " 已被降级权限为访客。"); 189 | return false; 190 | } 191 | } else { 192 | api.logout("未能找到对应玩家。"); 193 | } 194 | } else { 195 | api.logout("[vistor] 参数过少。用法:visitor [playername]"); 196 | } 197 | return false; 198 | } 199 | } 200 | return true; 201 | }); 202 | 203 | // 离开监听 204 | api.addAfterActListener(EventKey.onPlayerLeft, x => { 205 | var e = BaseEvent.getFrom(x) as PlayerLeftEvent; 206 | string uuid, xuid; 207 | if (nameuuids.TryGetValue(e.playername, out uuid)) { 208 | nameuuids.Remove(e.playername); 209 | } 210 | if (namexuids.TryGetValue(e.playername, out xuid)) { 211 | namexuids.Remove(e.playername); 212 | } 213 | return true; 214 | }); 215 | } 216 | } 217 | } 218 | 219 | namespace CSR 220 | { 221 | partial class Plugin 222 | { 223 | private static MCCSAPI mapi = null; 224 | /// 225 | /// 静态api对象 226 | /// 227 | public static MCCSAPI api { get { return mapi; } } 228 | public static int onServerStart(string pathandversion) { 229 | string path = null, version = null; 230 | bool commercial = false; 231 | string [] pav = pathandversion.Split(','); 232 | if (pav.Length > 1) { 233 | path = pav[0]; 234 | version = pav[1]; 235 | commercial = (pav[pav.Length - 1] == "1"); 236 | mapi = new MCCSAPI(path, version, commercial); 237 | if (mapi != null) { 238 | onStart(mapi); 239 | GC.KeepAlive(mapi); 240 | return 0; 241 | } 242 | } 243 | Console.WriteLine("Load failed."); 244 | return -1; 245 | } 246 | 247 | /// 248 | /// 通用调用接口,需用户自行实现 249 | /// 250 | /// MC相关调用方法 251 | public static void onStart(MCCSAPI api) { 252 | // TODO 此接口为必要实现 253 | Visitor.Program.init(api); 254 | Console.WriteLine("[visitor] 访客命令已装载(仅限后台)。用法:visitor [playername]"); 255 | } 256 | } 257 | } -------------------------------------------------------------------------------- /Logging/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Text; 6 | using System.Threading; 7 | using CSR; 8 | namespace Logging 9 | { 10 | public class Logger { 11 | private const string AUTOSAVEKEY = "autoSave"; 12 | private const string LOGPATHKEY = "logpath"; 13 | 14 | private readonly bool mautoSave; 15 | /// 16 | /// 是否自动保存log 17 | /// 18 | public bool autoSave {get{return mautoSave;}} 19 | private readonly string mpath; 20 | /// 21 | /// log保存所在路径 22 | /// 23 | public string filepath {get{return mpath;}} 24 | public Logger(string path) { 25 | var cf = new ConfigReader(path); 26 | string extsave = cf.getValue(AUTOSAVEKEY), extpath = cf.getValue(LOGPATHKEY); 27 | if (!string.IsNullOrEmpty(extsave)) { 28 | mautoSave = (extsave.ToLower() == "true"); 29 | } else 30 | mautoSave = false; 31 | if (!string.IsNullOrEmpty(extpath)) { 32 | mpath = extpath; 33 | } else 34 | mpath = ""; 35 | // 写回原数据 36 | cf.setValue(AUTOSAVEKEY, ("" + mautoSave).ToLower()); 37 | cf.setValue(LOGPATHKEY, mpath); 38 | cf.save(); 39 | try { 40 | if (!string.IsNullOrEmpty(mpath)) { 41 | string mdir = Path.GetDirectoryName(mpath); 42 | if (!Directory.Exists(mdir)) 43 | Directory.CreateDirectory(mdir); 44 | } 45 | }catch(Exception e){Console.WriteLine(e.StackTrace);} 46 | } 47 | // 写入一行日志 48 | public void saveLine(string l) { 49 | if (autoSave) { 50 | if (!string.IsNullOrEmpty(filepath)) 51 | try { 52 | File.AppendAllLines(filepath, new string[]{ l }); 53 | } catch { 54 | } 55 | } 56 | } 57 | } 58 | 59 | class Program { 60 | private static MCCSAPI mapi = null; 61 | 62 | /// 63 | /// 固定配置文件所在路径 64 | /// 65 | static readonly string LOGCONFIG = @"CSR\configs\logconfig.txt"; 66 | 67 | // 返回一个时间前缀 68 | public static string title(string content) { 69 | DateTime t = DateTime.Now; 70 | return "[" + t.ToString("yyyy-MM-dd hh:mm:ss") + " " + content + "]"; 71 | } 72 | // 打印坐标 73 | public static string Coordinator(BPos3 b) { 74 | return "(" + b.x + ", " + b.y + ", " + b.z + ")"; 75 | } 76 | public static string Coordinator(Vec3 b) { 77 | return "(" + (int)b.x + ", " + (int)b.y + ", " + (int)b.z + ")"; 78 | } 79 | // 维度ID转换为中文字符 80 | public static string toDimenStr(int dimensionId) { 81 | switch (dimensionId) { 82 | case 0: 83 | return "主世界"; 84 | case 1: 85 | return "地狱"; 86 | case 2: 87 | return "末地"; 88 | default: 89 | break; 90 | } 91 | return "未知维度"; 92 | } 93 | 94 | // 主入口实现 95 | public static void init(MCCSAPI api) { 96 | mapi = api; 97 | Console.OutputEncoding = Encoding.UTF8; 98 | // 从固定路径读取配置文件 99 | var logsetting = new Logger(LOGCONFIG); 100 | 101 | // 放置方块监听 102 | api.addAfterActListener(EventKey.onPlacedBlock, x => { 103 | var e = BaseEvent.getFrom(x) as PlacedBlockEvent; 104 | if(e == null) return true; 105 | string str = string.Format("{0} 玩家 {1} {2}在 {3} {4} 放置 {5} 方块。", 106 | title(EventKey.onPlacedBlock), e.playername, 107 | !e.isstand ? "悬空地":"", 108 | e.dimension, 109 | Coordinator(e.position), 110 | e.blockname); 111 | Console.WriteLine("{" + str); 112 | if (logsetting.autoSave) { 113 | var t = new Thread(() => logsetting.saveLine(str)); 114 | t.Start(); 115 | } 116 | return true; 117 | }); 118 | // 使用物品监听 119 | api.addAfterActListener(EventKey.onUseItem, x => { 120 | var e = BaseEvent.getFrom(x) as UseItemEvent; 121 | if(e == null) return true; 122 | if (e.RESULT) { 123 | string str = string.Format("{0} 玩家 {1} {2}对 {3} {4} 处的 {5} 方块使用 {6} 物品。", 124 | title(EventKey.onUseItem), e.playername, 125 | !e.isstand ? "悬空地":"", 126 | e.dimension, 127 | Coordinator(e.position), 128 | e.blockname, 129 | e.itemname); 130 | Console.WriteLine("{" + str); 131 | if (logsetting.autoSave) { 132 | var t = new Thread(() => logsetting.saveLine(str)); 133 | t.Start(); 134 | } 135 | } 136 | return true; 137 | }); 138 | // 破坏方块监听 139 | api.addAfterActListener(EventKey.onDestroyBlock, x => { 140 | var e = BaseEvent.getFrom(x) as DestroyBlockEvent; 141 | if(e == null) return true; 142 | string str = string.Format("{0} 玩家 {1} {2}在 {3} {4} 破坏 {5} 方块。", 143 | title(EventKey.onDestroyBlock), e.playername, 144 | !e.isstand ? "悬空地":"", 145 | e.dimension, 146 | Coordinator(e.position), 147 | e.blockname); 148 | Console.WriteLine("{" + str); 149 | if (logsetting.autoSave) { 150 | var t = new Thread(() => logsetting.saveLine(str)); 151 | t.Start(); 152 | } 153 | return true; 154 | }); 155 | // 玩家打开箱子 156 | api.addAfterActListener(EventKey.onStartOpenChest, x => { 157 | var e = BaseEvent.getFrom(x) as StartOpenChestEvent; 158 | if(e == null) return true; 159 | string str = string.Format("{0} 玩家 {1} {2}在 {3} {4} 打开 {5} 箱子。", 160 | title(EventKey.onDestroyBlock), e.playername, 161 | !e.isstand ? "悬空地":"", 162 | e.dimension, 163 | Coordinator(e.position), 164 | e.blockname); 165 | Console.WriteLine("{" + str); 166 | if (logsetting.autoSave) { 167 | var t = new Thread(() => logsetting.saveLine(str)); 168 | t.Start(); 169 | } 170 | return true; 171 | }); 172 | // 玩家打开木桶 173 | api.addAfterActListener(EventKey.onStartOpenBarrel, x => { 174 | var e = BaseEvent.getFrom(x) as StartOpenBarrelEvent; 175 | if(e == null) return true; 176 | string str = string.Format("{0} 玩家 {1} {2}在 {3} {4} 打开 {5} 木桶。", 177 | title(EventKey.onDestroyBlock), e.playername, 178 | !e.isstand ? "悬空地":"", 179 | e.dimension, 180 | Coordinator(e.position), 181 | e.blockname); 182 | Console.WriteLine("{" + str); 183 | if (logsetting.autoSave) { 184 | var t = new Thread(() => logsetting.saveLine(str)); 185 | t.Start(); 186 | } 187 | return true; 188 | }); 189 | // 玩家关闭箱子 190 | api.addAfterActListener(EventKey.onStopOpenChest, x => { 191 | var e = BaseEvent.getFrom(x) as StopOpenChestEvent; 192 | if(e == null) return true; 193 | string str = string.Format("{0} 玩家 {1} {2}在 {3} {4} 关闭 {5} 箱子。", 194 | title(EventKey.onDestroyBlock), e.playername, 195 | !e.isstand ? "悬空地":"", 196 | e.dimension, 197 | Coordinator(e.position), 198 | e.blockname); 199 | Console.WriteLine("{" + str); 200 | if (logsetting.autoSave) { 201 | var t = new Thread(() => logsetting.saveLine(str)); 202 | t.Start(); 203 | } 204 | return true; 205 | }); 206 | // 玩家关闭木桶 207 | api.addAfterActListener(EventKey.onStopOpenBarrel, x => { 208 | var e = BaseEvent.getFrom(x) as StopOpenBarrelEvent; 209 | if (e == null) return true; 210 | string str = string.Format("{0} 玩家 {1} {2}在 {3} {4} 关闭 {5} 木桶。", 211 | title(EventKey.onDestroyBlock), e.playername, 212 | !e.isstand ? "悬空地" : "", 213 | e.dimension, 214 | Coordinator(e.position), 215 | e.blockname); 216 | Console.WriteLine("{" + str); 217 | if (logsetting.autoSave) { 218 | var t = new Thread(() => logsetting.saveLine(str)); 219 | t.Start(); 220 | } 221 | return true; 222 | }); 223 | // 放入取出物品 224 | api.addAfterActListener(EventKey.onSetSlot, x => { 225 | var e = BaseEvent.getFrom(x) as SetSlotEvent; 226 | if(e == null) return true; 227 | string str, str1, str2; 228 | str1 = string.Format("{0} 玩家 {1} {2}在 {3} {4} 的 {5} 里的第 {6} 格", 229 | title(EventKey.onSetSlot), e.playername, 230 | !e.isstand ? "悬空地" : "", 231 | e.dimension, 232 | Coordinator(e.position), 233 | e.blockname, 234 | e.slot); 235 | str2 = (e.itemcount > 0) ? string.Format(" 放入 {0} 个 {1} 物品。", 236 | e.itemcount, 237 | e.itemname) : 238 | " 取出物品。"; 239 | str = str1 + str2; 240 | Console.WriteLine("{" + str); 241 | if (logsetting.autoSave) { 242 | var t = new Thread(() => logsetting.saveLine(str)); 243 | t.Start(); 244 | } 245 | return true; 246 | }); 247 | // 玩家切换维度 248 | api.addAfterActListener(EventKey.onChangeDimension, x => { 249 | var e = BaseEvent.getFrom(x) as ChangeDimensionEvent; 250 | if(e == null) return true; 251 | if (e.RESULT) { 252 | string str = string.Format("{0} 玩家 {1} {2}切换维度至 {3} {4}。", 253 | title(EventKey.onChangeDimension), e.playername, 254 | !e.isstand ? "悬空地" : "", 255 | e.dimension, 256 | Coordinator(e.XYZ)); 257 | Console.WriteLine("{" + str); 258 | if (logsetting.autoSave) { 259 | var t = new Thread(() => logsetting.saveLine(str)); 260 | t.Start(); 261 | } 262 | } 263 | return true; 264 | }); 265 | // 命名生物死亡 266 | api.addAfterActListener(EventKey.onMobDie, x => { 267 | var e = BaseEvent.getFrom(x) as MobDieEvent; 268 | if(e == null) return true; 269 | if (!string.IsNullOrEmpty(e.mobname)) { 270 | string str = string.Format("{0} {1} {2} 在 {3} {4} 被 {5} 杀死了。", 271 | title(EventKey.onMobDie), 272 | string.IsNullOrEmpty(e.playername) ? "实体" : "玩家", 273 | e.mobname, 274 | toDimenStr(e.dimensionid), 275 | Coordinator(e.XYZ), 276 | e.srcname); 277 | Console.WriteLine("{" + str); 278 | if (logsetting.autoSave) { 279 | var t = new Thread(() => logsetting.saveLine(str)); 280 | t.Start(); 281 | } 282 | } 283 | return true; 284 | }); 285 | // 聊天消息 286 | api.addAfterActListener(EventKey.onChat, x => { 287 | var e = BaseEvent.getFrom(x) as ChatEvent; 288 | if(e == null) return true; 289 | if (e.chatstyle != "title") { 290 | string str = string.Format("{0} {1} 说:{2}", 291 | e.playername, 292 | string.IsNullOrEmpty(e.target) ? "" : "悄悄地对 " + e.target, 293 | e.msg); 294 | Console.WriteLine("{" + str); 295 | if (logsetting.autoSave) { 296 | var t = new Thread(() => logsetting.saveLine(str)); 297 | t.Start(); 298 | } 299 | } 300 | return true; 301 | }); 302 | } 303 | } 304 | } 305 | 306 | namespace CSR 307 | { 308 | partial class Plugin 309 | { 310 | private static MCCSAPI mapi = null; 311 | /// 312 | /// 静态api对象 313 | /// 314 | public static MCCSAPI api { get { return mapi; } } 315 | public static int onServerStart(string pathandversion) { 316 | string path = null, version = null; 317 | bool commercial = false; 318 | string [] pav = pathandversion.Split(','); 319 | if (pav.Length > 1) { 320 | path = pav[0]; 321 | version = pav[1]; 322 | commercial = (pav[pav.Length - 1] == "1"); 323 | mapi = new MCCSAPI(path, version, commercial); 324 | if (mapi != null) { 325 | onStart(mapi); 326 | GC.KeepAlive(mapi); 327 | return 0; 328 | } 329 | } 330 | Console.WriteLine("Load failed."); 331 | return -1; 332 | } 333 | 334 | /// 335 | /// 通用调用接口,需用户自行实现 336 | /// 337 | /// MC相关调用方法 338 | public static void onStart(MCCSAPI api) { 339 | // TODO 此接口为必要实现 340 | Logging.Program.init(api); 341 | Console.WriteLine("[Logging] 日志记录插件已装载。"); 342 | } 343 | } 344 | } -------------------------------------------------------------------------------- /Testcase/Program3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Web.Script.Serialization; 6 | using CSR; 7 | 8 | namespace Testcase 9 | { 10 | /// 11 | /// 进行一个测试命令 12 | /// 13 | public class Program 14 | { 15 | static MCCSAPI mapi; 16 | 17 | static Dictionary nameuuids = new Dictionary(); 18 | 19 | // 临时效果 20 | static string tmpeff; 21 | // 记录侧边栏打开次数 22 | static Dictionary sidecount = new Dictionary(); 23 | 24 | // 获取uuid 25 | public static string getUUUD(string name) 26 | { 27 | string uuid; 28 | if (nameuuids.TryGetValue(name, out uuid)) { 29 | return uuid; 30 | } 31 | // 重载在线列表 32 | nameuuids.Clear(); 33 | string ols = mapi.getOnLinePlayers(); 34 | if (!string.IsNullOrEmpty(ols)) { 35 | var ser = new JavaScriptSerializer(); 36 | ArrayList ol = ser.Deserialize(ols); 37 | foreach (Dictionary d in ol) { 38 | object tname, tuuid; 39 | if (d.TryGetValue("playername", out tname)) { 40 | if (d.TryGetValue("uuid", out tuuid)) { 41 | nameuuids[tname.ToString()] = tuuid.ToString(); 42 | if (tname.ToString() == name) { 43 | uuid = tuuid.ToString(); 44 | } 45 | } 46 | } 47 | } 48 | } 49 | return uuid; 50 | } 51 | 52 | // 主入口实现 53 | public static void init(MCCSAPI api) 54 | { 55 | mapi = api; 56 | 57 | string[] bts = null; 58 | if (!api.COMMERCIAL) { 59 | bts = new string[] { 60 | "后台指令tell", 61 | "前缀/去前缀名", 62 | "模拟喊话", 63 | "模拟执行me指令", 64 | "后台指令输出hello", 65 | "查询当前状态至后台", 66 | "给32个白桦木", 67 | "断开自身连接", 68 | "发送一条原始文本至玩家聊天框", 69 | "获取玩家计分板项money的值", 70 | "设置玩家计分板项money的值+1" 71 | }; 72 | } else { 73 | bts = new string[] { 74 | "后台指令tell", 75 | "前缀/去前缀名", 76 | "模拟喊话", 77 | "模拟执行me指令", 78 | "后台指令输出hello", 79 | "查询当前状态至后台", 80 | "给32个白桦木", 81 | "断开自身连接", 82 | "发送一条原始文本至玩家聊天框", 83 | "获取玩家计分板项money的值", 84 | "设置玩家计分板项money的值+1", // 以下是非社区版内容 85 | "穿墙能力开/关", 86 | "传送至梦之故里大厅", 87 | "跨维传送至末地祭坛", 88 | "读当前属性值至后台", 89 | "临时攻击+10,生命+2,附命+2,抗飞+1,等级+5,食物+2", 90 | "读属性上限值至后台", 91 | "攻限+10,命限+10,食限+10", 92 | "读当前选中物品至后台", 93 | "给1个附魔叉", 94 | "替换副手为一个叉子", 95 | "保存玩家所有物品列表至pit.json并清空", 96 | "读pit.json到当前玩家", 97 | "读玩家当前效果列表到后台", 98 | "设置玩家临时存储的效果列表", 99 | "显示欢迎一个血条", 100 | "清除欢迎血条", 101 | "显示一个带统计的自定义侧边栏", 102 | "移除自定义侧边栏", 103 | "读当前权限与游戏模式至后台", 104 | "切换op/visitor,生存/创造模式", 105 | "导出当前位置+长宽高x10的结构到st1.json", 106 | "读结构st1.json到当前位置", 107 | "导出世界所有计分板分数至sc1.json", 108 | "导入计分板分数sc1.json至世界", 109 | "读本玩家周边3x3区块所有像素点至map.json", 110 | "导出世界所有玩家数据至players.json", 111 | "导入玩家数据players.json至本世界" 112 | }; 113 | } 114 | 115 | var a = new ArrayList(bts); 116 | // 设置指令描述 117 | api.setCommandDescribeEx("testcase", "开始一个测试用例", MCCSAPI.CommandPermissionLevel.GameMasters, 118 | (byte)MCCSAPI.CommandCheatFlag.NotCheat, 0); 119 | // 添加测试指令监听 120 | api.addBeforeActListener(EventKey.onInputCommand, x => { 121 | var e = BaseEvent.getFrom(x) as InputCommandEvent; 122 | if (e.cmd.Trim() == "/testcase") { 123 | // 此处执行拦截操作 124 | string uuid = getUUUD(e.playername); 125 | var gui = new SimpleGUI(api, uuid, "测试用例", "请于30秒内选择测试用例进行测试:", 126 | a); 127 | gui.send(30000, selected => { 128 | switch (selected) { 129 | case "0": 130 | api.runcmd("tell \"" + e.playername + "\" 你好 c# !"); 131 | break; 132 | case "1": 133 | { 134 | string r = e.playername; 135 | r = (r.IndexOf("[前缀]") >= 0 ? r.Substring(4) : "[前缀]" + r); 136 | api.reNameByUuid(uuid, r); 137 | } 138 | break; 139 | case "2": 140 | api.talkAs(uuid, "你好 c# !"); 141 | break; 142 | case "3": 143 | api.runcmdAs(uuid, "/me 你好 c# !"); 144 | break; 145 | case "4": 146 | api.logout("logout: 你好 c# !"); 147 | break; 148 | case "5": 149 | Console.WriteLine(api.selectPlayer(uuid)); 150 | break; 151 | case "6": 152 | api.addPlayerItem(uuid, 17, 2, 32); 153 | break; 154 | case "7": 155 | api.disconnectClient(uuid, "这个消息来自测试"); 156 | break; 157 | case "8": 158 | api.sendText(uuid, "这个文本来自测试"); 159 | break; 160 | case "9": 161 | Console.WriteLine("玩家{0}计分板money项数值为:{1}", e.playername, api.getscoreboard(uuid, "money")); 162 | break; 163 | case "10": 164 | if (api.setscoreboard(uuid, "money", api.getscoreboard(uuid, "money") + 1)) 165 | Console.WriteLine("[setscoreboard] 已成功设置计分板项。"); 166 | break; 167 | #region 以下部分为非社区版内容 168 | 169 | case "11": 170 | { 171 | string sa = api.getPlayerAbilities(uuid); 172 | if (!string.IsNullOrEmpty(sa)) { 173 | var ser = new JavaScriptSerializer(); 174 | var ja = ser.Deserialize>(sa); 175 | var cja = new Dictionary(); 176 | object nnoclip; 177 | if (ja.TryGetValue("noclip", out nnoclip)) { 178 | cja["noclip"] = !((bool)nnoclip); 179 | } 180 | api.setPlayerAbilities(uuid, ser.Serialize(cja)); 181 | } 182 | } 183 | break; 184 | case "12": 185 | api.transferserver(uuid, "www.xiafox.com", 19132); 186 | break; 187 | case "13": 188 | api.teleport(uuid, 10, 99, 10, 2); 189 | break; 190 | case "14": 191 | api.logout(api.getPlayerAttributes(uuid)); 192 | break; 193 | case "15": 194 | { 195 | var sa = api.getPlayerAttributes(uuid); 196 | if (!string.IsNullOrEmpty(sa)) { 197 | var ser = new JavaScriptSerializer(); 198 | var ja = ser.Deserialize>(sa); 199 | var cja = new Dictionary(); 200 | object atdmg; 201 | if (ja.TryGetValue("attack_damage", out atdmg)) { 202 | cja["attack_damage"] = Convert.ToSingle(atdmg) + 10; 203 | } 204 | if (ja.TryGetValue("absorption", out atdmg)) { 205 | cja["absorption"] = Convert.ToSingle(atdmg) + 2; 206 | } 207 | if (ja.TryGetValue("health", out atdmg)) { 208 | cja["health"] = Convert.ToSingle(atdmg) + 2; 209 | } 210 | if (ja.TryGetValue("knockback_resistance", out atdmg)) { 211 | cja["knockback_resistance"] = Convert.ToSingle(atdmg) + 1; 212 | } 213 | if (ja.TryGetValue("level", out atdmg)) { 214 | cja["level"] = Convert.ToSingle(atdmg) + 5; 215 | } 216 | if (ja.TryGetValue("hunger", out atdmg)) { 217 | cja["hunger"] = Convert.ToSingle(atdmg) + 2; 218 | } 219 | api.setPlayerTempAttributes(uuid, ser.Serialize(cja)); 220 | } 221 | } 222 | break; 223 | case "16": 224 | api.logout(api.getPlayerMaxAttributes(uuid)); 225 | break; 226 | case "17": 227 | { 228 | var sa = api.getPlayerMaxAttributes(uuid); 229 | if (!string.IsNullOrEmpty(sa)) { 230 | var ser = new JavaScriptSerializer(); 231 | var ja = ser.Deserialize>(sa); 232 | var cja = new Dictionary(); 233 | object dmg; 234 | if (ja.TryGetValue("maxattack_damage", out dmg)) { 235 | cja["maxattack_damage"] = Convert.ToSingle(dmg) + 10; 236 | } 237 | if (ja.TryGetValue("maxhealth", out dmg)) { 238 | cja["maxhealth"] = Convert.ToSingle(dmg) + 10; 239 | } 240 | if (ja.TryGetValue("maxhunger", out dmg)) { 241 | cja["maxhunger"] = Convert.ToSingle(dmg) + 10; 242 | } 243 | api.setPlayerMaxAttributes(uuid, ser.Serialize(cja)); 244 | } 245 | } 246 | break; 247 | case "18": 248 | api.logout(api.getPlayerSelectedItem(uuid)); 249 | break; 250 | case "19": 251 | { 252 | // tt - TAG_TYPE 标签数据类型,总计11种类型 253 | // tv - TAG_VALUE 标签值,由类型决定 254 | // ck - Compound_KEY nbt关键字,字符串类型 255 | // cv - Compound_VALUE nbt值,总是为一个TAG 256 | var jitem = "{" + 257 | "\"tt\": 10, \"tv\": [" + 258 | "{ \"ck\": \"Count\", \"cv\": { \"tt\": 1, \"tv\": 1 } }," + 259 | "{ \"ck\": \"Damage\", \"cv\": { \"tt\": 2, \"tv\": 0 } }," + 260 | "{ \"ck\": \"Name\", \"cv\": { \"tt\": 8, \"tv\": \"minecraft:trident\" } }," + 261 | "{ \"ck\": \"tag\", \"cv\": { \"tt\": 10, \"tv\": [" + 262 | "{ \"ck\": \"ench\", \"cv\": { \"tt\": 9, \"tv\": [" + 263 | "{ \"tt\": 10, \"tv\": [" + 264 | "{ \"ck\": \"id\", \"cv\": { \"tt\": 2, \"tv\": 10 } }," + 265 | "{ \"ck\": \"lvl\", \"cv\": { \"tt\": 2, \"tv\": 9999 } }]" + 266 | "}]}" + 267 | "}]}" + 268 | "}]" + 269 | "}"; 270 | api.addPlayerItemEx(uuid, jitem); 271 | } 272 | break; 273 | case "20": 274 | { 275 | var jtem = "{" + 276 | "\"Offhand\": { \"tt\": 9, \"tv\": [" + 277 | "{ \"tt\": 10, \"tv\": [" + 278 | "{ \"ck\": \"Count\", \"cv\": { \"tt\": 1, \"tv\": 1 } }," + 279 | "{ \"ck\": \"Damage\", \"cv\": { \"tt\": 2, \"tv\": 0 } }," + 280 | "{ \"ck\": \"Name\", \"cv\": { \"tt\": 8, \"tv\": \"minecraft:trident\" } }," + 281 | "{ \"ck\": \"tag\", \"cv\": { \"tt\": 10, \"tv\": [" + 282 | "{ \"ck\": \"ench\", \"cv\": {" + 283 | "\"tt\": 9, \"tv\": [" + 284 | "{ \"tt\": 10, \"tv\": [" + 285 | "{ \"ck\": \"id\", \"cv\": { \"tt\": 2, \"tv\": 7 } }," + 286 | "{ \"ck\": \"lvl\", \"cv\": { \"tt\": 2, \"tv\": 8888 } }]" + 287 | "}]}" + 288 | "}]}" + 289 | "}]" + 290 | "}]}" + 291 | "}"; 292 | api.setPlayerItems(uuid, jtem); 293 | } 294 | break; 295 | case "21": 296 | { 297 | var its = api.getPlayerItems(uuid); 298 | File.WriteAllText("pit.json", its); 299 | // 此处使用空气填充末影箱 300 | var sair = "{\"tt\":10,\"tv\":[{\"ck\":\"Count\",\"cv\":{\"tt\":1,\"tv\":0}},{\"ck\":\"Damage\",\"cv\":{\"tt\":2,\"tv\":0}},{\"ck\":\"Name\"" + ",\"cv\":{\"tt\":8,\"tv\":\"\"}},{\"ck\":\"Slot\",\"cv\":{\"tt\":1,\"tv\":0}}]}"; 301 | //let air = { "tt": 10, "tv": [{ "ck": "Count", "cv": { "tt": 1, "tv": 0 } }, { "ck": "Damage", "cv": { "tt": 2, "tv": 0 } }, { "ck": "Name", "cv": { "tt": 8, "tv": "" } }, { "ck": "Slot", "cv": { "tt": 1, "tv": 0 } }] }; 302 | 303 | var endc = new Dictionary(); 304 | var eci = new Dictionary(); 305 | var edclist = new ArrayList(); 306 | eci["tt"] = 9; 307 | var ser = new JavaScriptSerializer(); 308 | for (int i = 0; i < 27; i++) { 309 | var mair = ser.Deserialize>(sair); 310 | if (((Dictionary)(((ArrayList)(mair["tv"]))[3]))["ck"].ToString() == "Slot") { // 此处需修改并应用 311 | ((Dictionary)(((Dictionary)(((ArrayList)(mair["tv"]))[3]))["cv"]))["tv"] = i; 312 | } 313 | edclist.Add(mair); 314 | } 315 | eci["tv"] = edclist; 316 | endc["EnderChestInventory"] = eci; 317 | api.setPlayerItems(uuid, ser.Serialize(endc)); 318 | api.runcmd("clear \"" + e.playername + "\""); 319 | } 320 | break; 321 | case "22": 322 | { 323 | try { 324 | var its = File.ReadAllText("pit.json"); 325 | if (its != null) { 326 | api.setPlayerItems(uuid, its); 327 | } 328 | } catch { 329 | } 330 | } 331 | break; 332 | case "23": 333 | { 334 | var efs = api.getPlayerEffects(uuid); 335 | tmpeff = efs; 336 | Console.WriteLine(efs); 337 | } 338 | break; 339 | case "24": 340 | api.setPlayerEffects(uuid, tmpeff); 341 | break; 342 | case "25": 343 | api.setPlayerBossBar(uuid, "欢迎使用NetRunner自定义血条!", ((float)(new Random().Next() % 1001)) / 1000.0f); 344 | break; 345 | case "26": 346 | api.removePlayerBossBar(uuid); 347 | break; 348 | case "27": 349 | { 350 | int count = 0; 351 | if (!sidecount.TryGetValue(uuid, out count)) { 352 | sidecount[uuid] = 0; 353 | } 354 | ++sidecount[uuid]; 355 | var ser = new JavaScriptSerializer(); 356 | var list = new List(); 357 | list.Add("第" + sidecount[uuid] + "次打开侧边栏 "); 358 | list.Add("这是第二行 "); 359 | list.Add("这是下一行 "); 360 | list.Add("属性:[待填写] "); 361 | list.Add("§e颜色自拟 "); 362 | api.setPlayerSidebar(uuid, e.playername + "的侧边栏", ser.Serialize(list)); 363 | } 364 | break; 365 | case "28": 366 | api.removePlayerSidebar(uuid); 367 | break; 368 | case "29": 369 | Console.WriteLine(api.getPlayerPermissionAndGametype(uuid)); 370 | break; 371 | case "30": 372 | { 373 | var st = api.getPlayerPermissionAndGametype(uuid); 374 | var ser = new JavaScriptSerializer(); 375 | var t = ser.Deserialize>(st); 376 | if (t != null) { 377 | t["gametype"] = (int)(t["gametype"]) == 0 ? 1 : 0; 378 | t["permission"] = (int)(t["permission"]) == 0 ? 2 : 0; 379 | api.setPlayerPermissionAndGametype(uuid, ser.Serialize(t)); 380 | } 381 | } 382 | break; 383 | case "31": 384 | { 385 | var posa = e.XYZ; 386 | var ser = new JavaScriptSerializer(); 387 | var posb = new Vec3(); 388 | posb.x = posa.x + 10; 389 | posb.y = posa.y + 10; 390 | posb.z = posa.z + 10; 391 | var data = api.getStructure(e.dimensionid, ser.Serialize(posa), ser.Serialize(posb), false, true); 392 | File.WriteAllText("st1.json", data); 393 | } 394 | break; 395 | case "32": 396 | try { 397 | var data = File.ReadAllText("st1.json"); 398 | var ser = new JavaScriptSerializer(); 399 | api.setStructure(data, e.dimensionid, ser.Serialize(e.XYZ), 0, true, true); 400 | } catch { 401 | } 402 | break; 403 | case "33": 404 | try { 405 | File.WriteAllText("sc1.json", api.getAllScore()); 406 | } catch{} 407 | break; 408 | case "34": 409 | try { 410 | var data = File.ReadAllText("sc1.json"); 411 | api.setAllScore(data); 412 | } catch{} 413 | break; 414 | case "35": 415 | try { 416 | var d = "["; 417 | for (int dx = -1; dx < 2; dx++) { 418 | for (int dy = -1; dy < 2; dy++) { 419 | int px = (int)(e.XYZ.x + dx * (16)); 420 | int py = (int)e.XYZ.y; 421 | int pz = (int)(e.XYZ.y + dy * 16); 422 | var data = api.getMapColors(px, py, pz, e.dimensionid); 423 | d += data; 424 | d += ","; 425 | } 426 | } 427 | d = d.Substring(0, d.Length - 1) + "]"; 428 | File.WriteAllText("map.json", d); 429 | } catch{} 430 | break; 431 | case "36": 432 | try { 433 | File.WriteAllText("players.json", api.exportPlayersData()); 434 | } catch{} 435 | break; 436 | case "37": 437 | try { 438 | var data = File.ReadAllText("players.json"); 439 | api.importPlayersData(data); 440 | } catch{} 441 | break; 442 | #endregion 443 | case "null": 444 | Console.WriteLine("玩家 " + e.playername + " 主动取消了一个表单项。", gui.id); 445 | break; 446 | } 447 | }, 448 | () => Console.WriteLine("[testcase] 玩家 " + e.playername + " 表单已超时,id={0}", gui.id)); 449 | return false; 450 | } 451 | return true; 452 | }); 453 | // 离开监听 454 | api.addAfterActListener(EventKey.onPlayerLeft, x => { 455 | var e = BaseEvent.getFrom(x) as PlayerLeftEvent; 456 | string uuid; 457 | if (nameuuids.TryGetValue(e.playername, out uuid)) { 458 | nameuuids.Remove(e.playername); 459 | } 460 | return true; 461 | }); 462 | } 463 | } 464 | } 465 | 466 | namespace CSR 467 | { 468 | partial class Plugin 469 | { 470 | private static MCCSAPI mapi = null; 471 | /// 472 | /// 静态api对象 473 | /// 474 | public static MCCSAPI api { get { return mapi; } } 475 | public static int onServerStart(string pathandversion) { 476 | string path = null, version = null; 477 | bool commercial = false; 478 | string [] pav = pathandversion.Split(','); 479 | if (pav.Length > 1) { 480 | path = pav[0]; 481 | version = pav[1]; 482 | commercial = (pav[pav.Length - 1] == "1"); 483 | mapi = new MCCSAPI(path, version, commercial); 484 | if (mapi != null) { 485 | onStart(mapi); 486 | GC.KeepAlive(mapi); 487 | return 0; 488 | } 489 | } 490 | Console.WriteLine("Load failed."); 491 | return -1; 492 | } 493 | 494 | /// 495 | /// 通用调用接口,需用户自行实现 496 | /// 497 | /// MC相关调用方法 498 | public static void onStart(MCCSAPI api) { 499 | // TODO 此接口为必要实现 500 | Testcase.Program.init(api); 501 | Console.WriteLine("[testcase] 测试命令已装载。用法:/testcase"); 502 | } 503 | } 504 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 489 | USA 490 | 491 | Also add information on how to contact you by electronic and paper mail. 492 | 493 | You should also get your employer (if you work as a programmer) or your 494 | school, if any, to sign a "copyright disclaimer" for the library, if 495 | necessary. Here is a sample; alter the names: 496 | 497 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 498 | library `Frob' (a library for tweaking knobs) written by James Random 499 | Hacker. 500 | 501 | , 1 April 1990 502 | Ty Coon, President of Vice 503 | 504 | That's all there is to it! 505 | -------------------------------------------------------------------------------- /BDSBaseLib/BDS/Component.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace CSR 6 | { 7 | public enum ActorDamageCause : int 8 | { 9 | Override = 0x0, 10 | Contact = 0x1, 11 | EntityAttack = 0x2, 12 | Projectile = 0x3, 13 | Suffocation = 0x4, 14 | Fall = 0x5, 15 | Fire = 0x6, 16 | FireTick = 0x7, 17 | Lava = 0x8, 18 | Drowning = 0x9, 19 | BlockExplosion = 0x0A, 20 | EntityExplosion = 0x0B, 21 | Void = 0x0C, 22 | Suicide = 0x0D, 23 | Magic = 0x0E, 24 | Wither = 0x0F, 25 | Starve = 0x10, 26 | Anvil = 0x11, 27 | Thorns = 0x12, 28 | FallingBlock = 0x13, 29 | Piston = 0x14, 30 | FlyIntoWall = 0x15, 31 | Magma = 0x16, 32 | Fireworks = 0x17, 33 | Lightning = 0x18, 34 | Charging = 0x19, 35 | Temperature = 0x1A, 36 | All = 0x1F, 37 | None = -0x01 38 | } 39 | 40 | /// 41 | /// 实体类 42 | /// 43 | public class CsActor 44 | { 45 | const string ENTITY_GET_ARMOR_CONTAINER = "entity.get_armor_container"; 46 | const string ENTITY_GET_ATTACK = "entity.get_attack"; 47 | const string ENTITY_SET_ATTACK = "entity.set_attack"; 48 | const string ENTITY_GET_COLLISION_BOX = "entity.get_collision_box"; 49 | const string ENTITY_SET_COLLISION_BOX = "entity.set_collision_box"; 50 | const string ENTITY_GET_HAND_CONTAINER = "entity.get_hand_container"; 51 | const string ENTITY_GET_HEALTH = "entity.get_health"; 52 | const string ENTITY_SET_HEALTH = "entity.set_health"; 53 | const string ENTITY_GET_INVENTORY_CONTAINER = "entity.get_inventory_container"; 54 | const string ENTITY_GET_NAME = "entity.get_name"; 55 | const string ENTITY_SET_NAME = "entity.set_name"; 56 | const string ENTITY_GET_POSITION = "entity.get_position"; 57 | const string ENTITY_SET_POSITION = "entity.set_position"; 58 | const string ENTITY_GET_ROTATION = "entity.get_rotation"; 59 | const string ENTITY_SET_ROTATION = "entity.set_rotation"; 60 | const string ENTITY_GET_DIMENSIONID = "entity.get_dimensionid"; 61 | const string ENTITY_GET_TYPEID = "entity.get_typeid"; 62 | const string ENTITY_GET_UNIQUEID = "entity.get_uniqueid"; 63 | const string ENTITY_REMOVE = "entity.remove"; 64 | const string ENTITY_HURT = "entity.hurt"; 65 | #region 非社区内容 66 | const string ENTITY_GET_ABILITIES = "entity.get_abilities"; 67 | const string ENTITY_SET_ABILITIES = "entity.set_abilities"; 68 | const string ENTITY_GET_ATTRIBUTES = "entity.get_attributes"; 69 | const string ENTITY_SET_ATTRIBUTES = "entity.set_attributes"; 70 | const string ENTITY_GET_MAXATTRIBUTES = "entity.get_maxattributes"; 71 | const string ENTITY_SET_MAXATTRIBUTES = "entity.set_maxattributes"; 72 | const string ENTITY_GET_EFFECTS = "entity.get_effects"; 73 | const string ENTITY_SET_EFFECTS = "entity.set_effects"; 74 | #endregion 75 | const string LEVEL_GETFROM_UNIQUEID = "level.getfrom_uniqueid"; 76 | const string LEVEL_GETSFROM_AABB = "level.getsfrom_aabb"; 77 | 78 | protected delegate Std_String AGET(IntPtr p); 79 | protected delegate int AGETDIMENSIONID(IntPtr p); 80 | protected delegate bool ASET(IntPtr p, string s); 81 | protected delegate bool ASETNAME(IntPtr p, string n, bool a); 82 | protected delegate ulong AGETUNIQUEID(IntPtr p); 83 | protected delegate bool AREMOVE(IntPtr p); 84 | protected delegate bool AHURT(IntPtr p, IntPtr sp, ActorDamageCause cause, int count, bool knock, bool ignite); 85 | protected delegate IntPtr AGETFROMUNIQUEID(ulong i); 86 | protected delegate IntPtr AGETSFROMAABB(int did, float x1, float y1, float z1, float x2, float y2, float z2); 87 | static protected AGET egetArmorContainer; 88 | static protected AGET egetAttack; 89 | static protected ASET esetAttack; 90 | static protected AGET egetCollisionBox; 91 | static protected ASET esetCollisionBox; 92 | static protected AGET egetHandContainer; 93 | static protected AGET egetHealth; 94 | static protected ASET esetHealth; 95 | static protected AGET egetInventoryContainer; 96 | static protected AGET egetName; 97 | static protected ASETNAME esetName; 98 | static protected AGET egetPosition; 99 | static protected ASET esetPosition; 100 | static protected AGET egetRotation; 101 | static protected ASET esetRotation; 102 | static protected AGETDIMENSIONID egetDimensionId; 103 | static protected AGETDIMENSIONID egetTypeId; 104 | static protected AGETUNIQUEID egetUniqueId; 105 | static protected AREMOVE eremove; 106 | static protected AHURT ehurt; 107 | #region 非社区内容 108 | static protected AGET egetAbilities; 109 | static protected ASET esetAbilities; 110 | static protected AGET egetAttributes; 111 | static protected ASET esetAttributes; 112 | static protected AGET egetMaxAttributes; 113 | static protected ASET esetMaxAttributes; 114 | static protected AGET egetEffects; 115 | static protected ASET esetEffects; 116 | #endregion 117 | static protected AGETFROMUNIQUEID egetFromUniqueId; 118 | static protected AGETSFROMAABB egetsFromAABB; 119 | static bool entityApiInited = false; 120 | 121 | static protected bool initEntityAPI(MCCSAPI api) 122 | { 123 | if (!entityApiInited) 124 | { 125 | if (api != null) 126 | { 127 | egetArmorContainer = api.ConvertComponentFunc(ENTITY_GET_ARMOR_CONTAINER); 128 | egetAttack = api.ConvertComponentFunc(ENTITY_GET_ATTACK); 129 | esetAttack = api.ConvertComponentFunc(ENTITY_SET_ATTACK); 130 | egetCollisionBox = api.ConvertComponentFunc(ENTITY_GET_COLLISION_BOX); 131 | esetCollisionBox = api.ConvertComponentFunc(ENTITY_SET_COLLISION_BOX); 132 | egetHandContainer = api.ConvertComponentFunc(ENTITY_GET_HAND_CONTAINER); 133 | egetHealth = api.ConvertComponentFunc(ENTITY_GET_HEALTH); 134 | esetHealth = api.ConvertComponentFunc(ENTITY_SET_HEALTH); 135 | egetInventoryContainer = api.ConvertComponentFunc(ENTITY_GET_INVENTORY_CONTAINER); 136 | egetName = api.ConvertComponentFunc(ENTITY_GET_NAME); 137 | esetName = api.ConvertComponentFunc(ENTITY_SET_NAME); 138 | egetPosition = api.ConvertComponentFunc(ENTITY_GET_POSITION); 139 | esetPosition = api.ConvertComponentFunc(ENTITY_SET_POSITION); 140 | egetRotation = api.ConvertComponentFunc(ENTITY_GET_ROTATION); 141 | esetRotation = api.ConvertComponentFunc(ENTITY_SET_ROTATION); 142 | egetDimensionId = api.ConvertComponentFunc(ENTITY_GET_DIMENSIONID); 143 | egetTypeId = api.ConvertComponentFunc(ENTITY_GET_TYPEID); 144 | egetUniqueId = api.ConvertComponentFunc(ENTITY_GET_UNIQUEID); 145 | eremove = api.ConvertComponentFunc(ENTITY_REMOVE); 146 | ehurt = api.ConvertComponentFunc(ENTITY_HURT); 147 | if (api.COMMERCIAL) 148 | { // 非社区内容 149 | egetAbilities = api.ConvertComponentFunc(ENTITY_GET_ABILITIES); 150 | esetAbilities = api.ConvertComponentFunc(ENTITY_SET_ABILITIES); 151 | egetAttributes = api.ConvertComponentFunc(ENTITY_GET_ATTRIBUTES); 152 | esetAttributes = api.ConvertComponentFunc(ENTITY_SET_ATTRIBUTES); 153 | egetMaxAttributes = api.ConvertComponentFunc(ENTITY_GET_MAXATTRIBUTES); 154 | esetMaxAttributes = api.ConvertComponentFunc(ENTITY_SET_MAXATTRIBUTES); 155 | egetEffects = api.ConvertComponentFunc(ENTITY_GET_EFFECTS); 156 | esetEffects = api.ConvertComponentFunc(ENTITY_SET_EFFECTS); 157 | } 158 | egetFromUniqueId = api.ConvertComponentFunc(LEVEL_GETFROM_UNIQUEID); 159 | egetsFromAABB = api.ConvertComponentFunc(LEVEL_GETSFROM_AABB); 160 | entityApiInited = true; 161 | } else 162 | { 163 | return false; 164 | } 165 | } 166 | return true; 167 | } 168 | 169 | static protected MCCSAPI mapi; 170 | protected IntPtr ptr; 171 | 172 | public CsActor(MCCSAPI api, IntPtr e) 173 | { 174 | if (mapi == null) 175 | mapi = api; 176 | ptr = e; 177 | initEntityAPI(api); 178 | } 179 | 180 | /// 181 | /// 装备栏 182 | /// 183 | public string ArmorContainer { get 184 | { 185 | if (ptr != null && ptr != IntPtr.Zero) 186 | { 187 | Std_String s = egetArmorContainer(ptr); 188 | return StrTool.c_str(s); 189 | } 190 | return null; 191 | } } 192 | /// 193 | /// 攻击力 194 | /// 195 | public string Attack { get 196 | { 197 | if (ptr != null && ptr != IntPtr.Zero) 198 | { 199 | Std_String s = egetAttack(ptr); 200 | return StrTool.c_str(s); 201 | } 202 | return null; 203 | } set { 204 | if (ptr != null && ptr != IntPtr.Zero) 205 | { 206 | esetAttack(ptr, value); 207 | } 208 | } 209 | } 210 | /// 211 | /// 碰撞箱 212 | /// 213 | public string CollisionBox { get 214 | { 215 | if (ptr != null && ptr != IntPtr.Zero) 216 | { 217 | Std_String s = egetCollisionBox(ptr); 218 | return StrTool.c_str(s); 219 | } 220 | return null; 221 | } set 222 | { 223 | if (ptr != null && ptr != IntPtr.Zero) 224 | { 225 | esetCollisionBox(ptr, value); 226 | } 227 | } 228 | } 229 | /// 230 | /// 主副手栏 231 | /// 232 | public string HandContainer 233 | { 234 | get 235 | { 236 | if (ptr != null && ptr != IntPtr.Zero) 237 | { 238 | Std_String s = egetHandContainer(ptr); 239 | return StrTool.c_str(s); 240 | } 241 | return null; 242 | } 243 | } 244 | /// 245 | /// 生命值 246 | /// 247 | public string Health { get 248 | { 249 | if (ptr != null && ptr != IntPtr.Zero) 250 | { 251 | Std_String s = egetHealth(ptr); 252 | return StrTool.c_str(s); 253 | } 254 | return null; 255 | } 256 | set 257 | { 258 | if (ptr != null && ptr != IntPtr.Zero) 259 | { 260 | esetHealth(ptr, value); 261 | } 262 | } 263 | } 264 | /// 265 | /// 背包列表 266 | /// 267 | public string InventoryContainer 268 | { 269 | get 270 | { 271 | if (ptr != null && ptr != IntPtr.Zero) 272 | { 273 | Std_String s = egetInventoryContainer(ptr); 274 | return StrTool.c_str(s); 275 | } 276 | return null; 277 | } 278 | } 279 | /// 280 | /// 获取名字 281 | /// 282 | /// 283 | public string getName() 284 | { 285 | if (ptr != null && ptr != IntPtr.Zero) 286 | { 287 | Std_String s = egetName(ptr); 288 | return StrTool.c_str(s); 289 | } 290 | return null; 291 | } 292 | /// 293 | /// 设置名字及显示属性 294 | /// 295 | /// 名字 296 | /// 是否常显示 297 | /// 298 | public bool setName(string nname, bool alwaysShow) 299 | { 300 | if (ptr != null && ptr != IntPtr.Zero) 301 | { 302 | return esetName(ptr, nname, alwaysShow); 303 | } 304 | return false; 305 | } 306 | /// 307 | /// 实体所在坐标 308 | /// 309 | public string Position 310 | { 311 | get 312 | { 313 | if (ptr != null && ptr != IntPtr.Zero) 314 | { 315 | Std_String s = egetPosition(ptr); 316 | return StrTool.c_str(s); 317 | } 318 | return null; 319 | } 320 | set 321 | { 322 | if (ptr != null && ptr != IntPtr.Zero) 323 | { 324 | esetPosition(ptr, value); 325 | } 326 | } 327 | } 328 | /// 329 | /// 实体转角属性 330 | /// 331 | public string Rotation 332 | { 333 | get 334 | { 335 | if (ptr != null && ptr != IntPtr.Zero) 336 | { 337 | Std_String s = egetRotation(ptr); 338 | return StrTool.c_str(s); 339 | } 340 | return null; 341 | } 342 | set 343 | { 344 | if (ptr != null && ptr != IntPtr.Zero) 345 | { 346 | esetRotation(ptr, value); 347 | } 348 | } 349 | } 350 | /// 351 | /// 维度ID 352 | /// 353 | public int DimensionId { get 354 | { 355 | if (ptr != null && ptr != IntPtr.Zero) 356 | { 357 | return egetDimensionId(ptr); 358 | } 359 | return -1; 360 | } } 361 | /// 362 | /// 实体类型ID 363 | /// 364 | public int TypeId 365 | { 366 | get 367 | { 368 | if (ptr != null && ptr != IntPtr.Zero) 369 | { 370 | return egetTypeId(ptr); 371 | } 372 | return 1; 373 | } 374 | } 375 | /// 376 | /// 查询ID 377 | /// 378 | public ulong UniqueId { get 379 | { 380 | if (ptr != null && ptr != IntPtr.Zero) 381 | { 382 | return egetUniqueId(ptr); 383 | } 384 | return 0; 385 | } } 386 | /// 387 | /// 从地图中移除该实体 388 | /// 389 | /// 是否移除成功 390 | public bool remove() 391 | { 392 | if (ptr != null && ptr != IntPtr.Zero) 393 | { 394 | bool ret = eremove(ptr); 395 | if (ret) 396 | { 397 | ptr = IntPtr.Zero; 398 | return ret; 399 | } 400 | } 401 | return false; 402 | } 403 | /// 404 | /// 模拟产生一个由源实体发出的伤害 405 | /// 406 | /// 源实体 407 | /// 伤害类型 408 | /// 具体伤害数值 409 | /// 是否产生击退 410 | /// 是否产生火焰附加 411 | /// 是否伤害成功 412 | public bool hurt(IntPtr sourceActor, ActorDamageCause cause, int count, bool knock, bool ignite) 413 | { 414 | if (ptr != null && ptr != IntPtr.Zero) 415 | { 416 | return ehurt != null && ehurt(ptr, sourceActor, cause, count, knock, ignite); 417 | } 418 | return false; 419 | } 420 | 421 | #region 非社区内容 422 | /// 423 | /// 实体能力值列表 424 | /// 425 | public string Abilities 426 | { 427 | get 428 | { 429 | if (ptr != null && ptr != IntPtr.Zero) 430 | { 431 | if (egetAbilities != null) 432 | { 433 | Std_String str = egetAbilities(ptr); 434 | return StrTool.c_str(str); 435 | } 436 | } 437 | return ""; 438 | } 439 | set 440 | { 441 | if (ptr != null && ptr != IntPtr.Zero) 442 | { 443 | if (esetAbilities != null) 444 | esetAbilities(ptr, value); 445 | } 446 | } 447 | } 448 | /// 449 | /// 实体属性列表 450 | /// 451 | public string Attributes 452 | { 453 | get 454 | { 455 | if (ptr != null && ptr != IntPtr.Zero) 456 | { 457 | if (egetAttributes != null) 458 | { 459 | Std_String str = egetAttributes(ptr); 460 | return StrTool.c_str(str); 461 | } 462 | } 463 | return ""; 464 | } 465 | set 466 | { 467 | if (ptr != null && ptr != IntPtr.Zero) 468 | { 469 | if (esetAttributes != null) 470 | esetAttributes(ptr, value); 471 | } 472 | } 473 | } 474 | /// 475 | /// 实体属性最大值列表 476 | /// 477 | public string MaxAttributes 478 | { 479 | get 480 | { 481 | if (ptr != null && ptr != IntPtr.Zero) 482 | { 483 | if (egetMaxAttributes != null) 484 | { 485 | Std_String str = egetMaxAttributes(ptr); 486 | return StrTool.c_str(str); 487 | } 488 | } 489 | return ""; 490 | } 491 | set 492 | { 493 | if (ptr != null && ptr != IntPtr.Zero) 494 | { 495 | if (esetMaxAttributes != null) 496 | esetMaxAttributes(ptr, value); 497 | } 498 | } 499 | } 500 | /// 501 | /// 实体所有效果状态列表 502 | /// 503 | public string Effects 504 | { 505 | get 506 | { 507 | if (ptr != null && ptr != IntPtr.Zero) 508 | { 509 | if (egetEffects != null) 510 | { 511 | Std_String str = egetEffects(ptr); 512 | return StrTool.c_str(str); 513 | } 514 | } 515 | return ""; 516 | } 517 | set 518 | { 519 | if (ptr != null && ptr != IntPtr.Zero) 520 | { 521 | if (esetEffects != null) 522 | esetEffects(ptr, value); 523 | } 524 | } 525 | } 526 | #endregion 527 | 528 | /// 529 | /// 从查询ID处反查一个实体(或玩家) 530 | /// 531 | /// 532 | /// 533 | public static CsActor getFromUniqueId(MCCSAPI api, ulong id) 534 | { 535 | if (egetFromUniqueId == null) 536 | initEntityAPI(api); 537 | IntPtr p = egetFromUniqueId(id); 538 | if (p != null && p != IntPtr.Zero) 539 | { 540 | if (egetTypeId != null && egetTypeId(p) == 319) 541 | return new CsPlayer(api, p); 542 | else 543 | return new CsActor(api, p); 544 | } 545 | return null; 546 | } 547 | /// 548 | /// 从指定地图位置查询实体指针列表(不含玩家) 549 | /// 550 | /// 551 | /// 维度ID 552 | /// 553 | /// 554 | /// 555 | /// 556 | /// 557 | /// 558 | /// 实体指针列表 559 | public static ArrayList getsFromAABB(MCCSAPI api, int did, float x1, float y1, float z1, float x2, float y2, float z2) { 560 | if (egetsFromAABB == null) 561 | initEntityAPI(api); 562 | IntPtr pv = egetsFromAABB(did, x1, y1, z1, x2, y2, z2); 563 | if (pv != null && pv != IntPtr.Zero) { 564 | try { 565 | return ((Std_Vector)Marshal.PtrToStructure(pv, typeof(Std_Vector))).toList(); 566 | } 567 | catch { } 568 | } 569 | return null; 570 | } 571 | } 572 | 573 | /// 574 | /// 玩家类 575 | /// 576 | public class CsPlayer : CsActor 577 | { 578 | const string PLAYER_GET_HOTBAR_CONTAINER = "player.get_hotbar_container"; 579 | const string PLAYER_GET_UUID = "player.get_uuid"; 580 | const string PLAYER_GET_IPPORT = "player.get_ipport"; 581 | const string PLAYER_ADD_LEVEL = "player.add_level"; 582 | const string PLAYER_GET_SCOREID = "player.get_scoreboardid"; 583 | const string PLAYER_CREATE_SCOREID = "player.create_scoreboardid"; 584 | const string LEVEL_GETPLFROM_AABB = "level.getplfrom_aabb"; 585 | #region 非社区内容 586 | const string PLAYER_GET_STORAGEID = "player.get_storageid"; 587 | #endregion 588 | 589 | protected delegate bool PADDLEVEL(IntPtr p, int lv); 590 | protected delegate long PGETSCOREID(IntPtr p); 591 | static AGET pgetHotbarContainer, pgetServerStorageID; 592 | static AGET pgetUuid; 593 | static AGET pgetIPPort; 594 | static PADDLEVEL paddLevel; 595 | static AGETSFROMAABB pgetplFromAABB; 596 | static PGETSCOREID pgetScoreboardId, pcreateScoreboardId; 597 | static bool playerApiInited = false; 598 | 599 | static private bool initPlayerAPI(MCCSAPI api) 600 | { 601 | if (!playerApiInited) 602 | { 603 | if (api != null) 604 | { 605 | pgetHotbarContainer = api.ConvertComponentFunc(PLAYER_GET_HOTBAR_CONTAINER); 606 | pgetUuid = api.ConvertComponentFunc(PLAYER_GET_UUID); 607 | pgetIPPort = api.ConvertComponentFunc(PLAYER_GET_IPPORT); 608 | paddLevel = api.ConvertComponentFunc(PLAYER_ADD_LEVEL); 609 | pgetScoreboardId = api.ConvertComponentFunc(PLAYER_GET_SCOREID); 610 | pcreateScoreboardId = api.ConvertComponentFunc(PLAYER_CREATE_SCOREID); 611 | pgetplFromAABB = api.ConvertComponentFunc(LEVEL_GETPLFROM_AABB); 612 | if (api.COMMERCIAL) 613 | { // 非社区内容 614 | pgetServerStorageID = api.ConvertComponentFunc(PLAYER_GET_STORAGEID); 615 | } 616 | playerApiInited = true; 617 | } 618 | else 619 | { 620 | return false; 621 | } 622 | } 623 | return true; 624 | } 625 | 626 | public CsPlayer(MCCSAPI api, IntPtr p) : base(api, p) 627 | { 628 | initPlayerAPI(api); 629 | } 630 | /// 631 | /// 获取玩家热键栏 632 | /// 633 | public string HotbarContainer { get 634 | { 635 | if (ptr != null && ptr != IntPtr.Zero) 636 | { 637 | Std_String s = pgetHotbarContainer(ptr); 638 | return StrTool.c_str(s); 639 | } 640 | return null; 641 | } } 642 | /// 643 | /// 获取玩家uuid 644 | /// 645 | public string Uuid { get 646 | { 647 | if (ptr != null && ptr != IntPtr.Zero) 648 | { 649 | Std_String s = pgetUuid(ptr); 650 | return StrTool.c_str(s); 651 | } 652 | return null; 653 | } } 654 | /// 655 | /// 获取玩家IP和端口 656 | /// 657 | public string IpPort { get 658 | { 659 | if (ptr != null && ptr != IntPtr.Zero) 660 | { 661 | Std_String s = pgetIPPort(ptr); 662 | return StrTool.c_str(s); 663 | } 664 | return null; 665 | } } 666 | /// 667 | /// 增加玩家等级 668 | /// 669 | /// 670 | public void addLevel(int lv) 671 | { 672 | if (ptr != null && ptr != IntPtr.Zero) 673 | { 674 | paddLevel(ptr, lv); 675 | } 676 | } 677 | /// 678 | /// 获取玩家对应计分板ID数值 679 | /// 680 | /// 计分板ID值 681 | public long getScoreboardId() 682 | { 683 | return (ptr != null && ptr != IntPtr.Zero) ? 684 | pgetScoreboardId(ptr) : -1; 685 | } 686 | /// 687 | /// 创建玩家对应计分板ID并获取其值 688 | /// 689 | /// 计分板ID值 690 | public long createScoreboardId() 691 | { 692 | return (ptr != null && ptr != IntPtr.Zero) ? 693 | pcreateScoreboardId(ptr) : -1; 694 | } 695 | #region 非社区内容 696 | public string StorageID 697 | { 698 | get 699 | { 700 | return (ptr != null && ptr != IntPtr.Zero) ? 701 | StrTool.c_str(pgetServerStorageID(ptr)) : string.Empty; 702 | } 703 | } 704 | #endregion 705 | /// 706 | /// 从指定地图位置查询玩家指针列表 707 | /// 708 | /// 709 | /// 维度ID 710 | /// 711 | /// 712 | /// 713 | /// 714 | /// 715 | /// 716 | /// 玩家指针列表 717 | public static ArrayList getplFromAABB(MCCSAPI api, int did, float x1, float y1, float z1, float x2, float y2, float z2) 718 | { 719 | if (pgetplFromAABB == null) 720 | initEntityAPI(api); 721 | IntPtr pv = pgetplFromAABB(did, x1, y1, z1, x2, y2, z2); 722 | if (pv != null && pv != IntPtr.Zero) 723 | { 724 | try 725 | { 726 | return ((Std_Vector)Marshal.PtrToStructure(pv, typeof(Std_Vector))).toList(); 727 | } 728 | catch { } 729 | } 730 | return null; 731 | } 732 | } 733 | } 734 | -------------------------------------------------------------------------------- /BDSBaseLib/BDS/MCCSAPI.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * 由SharpDevelop创建。 3 | * 用户: BDSNetRunner 4 | * 日期: 2020/7/17 5 | * 时间: 16:27 6 | * 7 | * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 8 | */ 9 | using System; 10 | using System.Collections; 11 | using System.Collections.Generic; 12 | using System.Runtime.InteropServices; 13 | using System.Text; 14 | 15 | namespace CSR 16 | { 17 | /// 18 | /// API接口定义 19 | /// 20 | public class MCCSAPI 21 | { 22 | [DllImport("kernel32.dll")] 23 | private extern static IntPtr LoadLibrary(String path); 24 | [DllImport("kernel32.dll")] 25 | private extern static IntPtr GetProcAddress(IntPtr lib, String funcName); 26 | [DllImport("kernel32.dll")] 27 | private extern static bool FreeLibrary(IntPtr lib); 28 | 29 | private readonly string mVersion; 30 | /// 31 | /// 插件版本 32 | /// 33 | public string VERSION {get{return mVersion;}} 34 | private readonly bool mcommercial; 35 | /// 36 | /// 平台类型 37 | /// 38 | public bool COMMERCIAL {get{return mcommercial;}} 39 | 40 | // 注册事件回调管理,避免回收 41 | private Dictionary callbks = new Dictionary(); 42 | // 发送tick方法管理,避免回收 43 | private Dictionary ticks = new Dictionary(); 44 | 45 | private IntPtr hLib; 46 | public MCCSAPI(String DLLPath, string ver, bool commercial) 47 | { 48 | mVersion = ver; 49 | mcommercial = commercial; 50 | hLib = LoadLibrary(DLLPath); 51 | if (hLib != IntPtr.Zero) { 52 | initApis(); 53 | } 54 | } 55 | ~MCCSAPI() 56 | { 57 | FreeLibrary(hLib); 58 | } 59 | //将要执行的函数转换为委托 60 | private T Invoke(String APIName) 61 | { 62 | IntPtr api = GetProcAddress(hLib, APIName); 63 | if (api != IntPtr.Zero) 64 | //return (T)Marshal.GetDelegateForFunctionPointer(api, typeof(T)); 65 | //若.net framework版本高于4.5.1可用以下替换以上 66 | return Marshal.GetDelegateForFunctionPointer(api); 67 | Console.WriteLine("Get Api {0} failed.", APIName); 68 | return default(T); 69 | } 70 | 71 | /// 72 | /// 事件处理函数类型 73 | /// 74 | /// 原始数据 75 | /// 是否继续/拦截(before事件有效) 76 | public delegate bool EventCab(Events e); 77 | private delegate bool ADDACTEVENTFUNC(string key, EventCab cb); 78 | private ADDACTEVENTFUNC caddBeforeActEvent, caddAfterActEvent, cremoveBeforeAct, cremoveAfterAct; 79 | /// 80 | /// 置入tick所需的无参方法 81 | /// 82 | public delegate void TickFunc(); 83 | private delegate void POSTTICK(TickFunc f); 84 | private POSTTICK cpostTick; 85 | private delegate bool CSHOOKFUNC(int rva, IntPtr hook, out IntPtr org); 86 | private CSHOOKFUNC ccshook; 87 | private delegate bool CSUNHOOKFUNC(IntPtr hook, out IntPtr org); 88 | private CSUNHOOKFUNC ccsunhook; 89 | private delegate IntPtr DLSYMFUNC(int rva); 90 | private DLSYMFUNC cdlsym; 91 | private delegate bool READHARDMEMORY(int rva, byte[] odata, int size); 92 | private READHARDMEMORY creadHardMemory, cwriteHardMemory; 93 | private delegate void SETSHAREPTRFUNC(string key, IntPtr sdata); 94 | private SETSHAREPTRFUNC csetshareptr; 95 | private delegate IntPtr GETSHAREPTRFUNC(string key); 96 | private GETSHAREPTRFUNC cgetSharePtr, cremoveSharePtr; 97 | public enum CommandPermissionLevel { 98 | Any = 0, 99 | GameMasters = 1, 100 | Admin = 2, 101 | Host = 3, 102 | Owner = 4, 103 | Internal = 5 104 | } 105 | public enum CommandVisibilityFlag : byte { 106 | Visible = 0, 107 | HiddenFromCommandBlockOrigin = 2, 108 | HiddenFromPlayerOrigin = 4, 109 | Hidden = 6 110 | } 111 | public enum CommandUsageFlag : byte { 112 | Normal = 0, 113 | Test = 1 114 | } 115 | public enum CommandSyncFlag : byte { 116 | Synced = 0, 117 | Local = 8 118 | } 119 | public enum CommandExecuteFlag : byte { 120 | Allowed = 0, 121 | Disallowed = 0x10 122 | } 123 | public enum CommandTypeFlag : byte { 124 | None = 0, 125 | Message = 0x20 126 | } 127 | public enum CommandCheatFlag : byte { 128 | Cheat = 0, 129 | NotCheat = 0x80 130 | } 131 | private delegate void SETCOMMANDDESCRIBEFUNC(string key, string description, CommandPermissionLevel level, short flag1, short flag2); 132 | private SETCOMMANDDESCRIBEFUNC csetCommandDescribe; 133 | private delegate bool RUNCMDFUNC(string cmd); 134 | private RUNCMDFUNC cruncmd, cremovePlayerBossBar, cremovePlayerSidebar, csetAllScore, cimportPlayersData; 135 | private delegate void LOGOUTFUNC(string cmdout); 136 | private LOGOUTFUNC clogout; 137 | private delegate Std_String GETONLINEPLAYERSFUNC(); 138 | private GETONLINEPLAYERSFUNC cgetOnLinePlayers, cgetAllScore, cexportPlayersData; 139 | private delegate Std_String GETSTRUCTUREFUNC(int did, string jsonposa, string jsonposb, bool exent, bool exblk); 140 | private GETSTRUCTUREFUNC cgetStructure; 141 | private delegate bool SETSTRUCTUREFUNC(string jdata, int did, string jsonposa, byte rot, bool exent, bool exblk); 142 | private SETSTRUCTUREFUNC csetStructure; 143 | private delegate bool RENAMEBYUUIDFUNC(string uuid, string newName); 144 | private RENAMEBYUUIDFUNC creNameByUuid, csetPlayerAbilities, csetPlayerTempAttributes, 145 | csetPlayerMaxAttributes, csetPlayerItems, caddPlayerItemEx, csetPlayerEffects, 146 | ctalkAs, cruncmdAs, cdisconnectClient, csendText, csetPlayerPermissionAndGametype; 147 | private delegate Std_String GETPLAYERABILITIESFUNC(string uuid); 148 | private GETPLAYERABILITIESFUNC cgetPlayerAbilities, cgetPlayerAttributes, cgetPlayerMaxAttributes, 149 | cgetPlayerItems, cgetPlayerSelectedItem, cgetPlayerEffects, cselectPlayer, cgetPlayerPermissionAndGametype; 150 | private delegate bool ADDPLAYERITEMFUNC(string uuid, int id, short aux, byte count); 151 | private ADDPLAYERITEMFUNC caddPlayerItem; 152 | private delegate bool SETPLAYERBOSSBARFUNC(string uuid, string title, float percent); 153 | private SETPLAYERBOSSBARFUNC csetPlayerBossBar; 154 | private delegate bool TRANSFERSERVERFUNC(string uuid, string addr, int port); 155 | private TRANSFERSERVERFUNC ctransferserver; 156 | private delegate bool TELEPORTFUNC(string uuid, float x, float y, float z, int did); 157 | private TELEPORTFUNC cteleport; 158 | private delegate Std_String GETMAPCOLORS(int x, int y, int z, int did); 159 | private GETMAPCOLORS cgetMapColors; 160 | private delegate uint SENDSIMPLEFORMFUNC(string uuid, string title, string content, string buttons); 161 | private SENDSIMPLEFORMFUNC csendSimpleForm; 162 | private delegate uint SENDMODALFORMFUNC(string uuid, string title, string content, string button1, string button2); 163 | private SENDMODALFORMFUNC csendModalForm; 164 | private delegate uint SENDCUSTOMFORMFUNC(string uuid, string json); 165 | private SENDCUSTOMFORMFUNC csendCustomForm; 166 | private delegate bool RELEASEFORMFUNC(uint fid); 167 | private RELEASEFORMFUNC creleaseForm; 168 | private delegate bool SETPLAYERSIDEBARFUNC(string uuid, string title, string list); 169 | private SETPLAYERSIDEBARFUNC csetPlayerSidebar; 170 | private delegate int GETSCOREBOARDVALUEFUNC(string uuid, string objname); 171 | private GETSCOREBOARDVALUEFUNC cgetscoreboardValue; 172 | private delegate bool SETSCOREBOARDVALUEFUNC(string uuid, string objname, int count); 173 | private SETSCOREBOARDVALUEFUNC csetscoreboardValue; 174 | private delegate bool SETSERVERMOTD(string motd, bool isShow); 175 | private SETSERVERMOTD csetServerMotd; 176 | private delegate Std_String GETITEMRAWNAME(int id); 177 | private GETITEMRAWNAME cgetItemRawname; 178 | /// 179 | /// 脚本引擎执行功能结果回调 180 | /// 181 | /// 是否执行成功 182 | public delegate void JSECab(bool r); 183 | private delegate void JSERUNSCRIPT(string js, JSECab cb); 184 | private JSERUNSCRIPT cJSErunScript; 185 | private delegate void JSEFIRECUSTOMEVENT(string ename, string jdata, JSECab cb); 186 | private JSEFIRECUSTOMEVENT cJSEfireCustomEvent; 187 | private delegate int GETSCOREBYID(long id, string objname); 188 | private GETSCOREBYID cgetscoreById; 189 | private delegate int SETSCOREBYID(long id, string objname, int count); 190 | private SETSCOREBYID csetscoreById; 191 | private delegate IntPtr GETEXTRAAPI(string apiname); 192 | private GETEXTRAAPI cgetExtraAPI; 193 | 194 | // 转换附加函数指针 195 | private T ConvertExtraFunc(string apiname) 196 | { 197 | if (cgetExtraAPI != null) { 198 | IntPtr f = cgetExtraAPI(apiname); 199 | if (f != IntPtr.Zero) { 200 | //return (T)Marshal.GetDelegateForFunctionPointer(f, typeof(T)); 201 | //若.net framework版本高于4.5.1可用以下替换以上 202 | return Marshal.GetDelegateForFunctionPointer(f); 203 | } 204 | } 205 | Console.WriteLine("Get ExtraApi {0} failed.", apiname); 206 | return default(T); 207 | } 208 | 209 | private delegate IntPtr MCCOMPONENTAPI(string apiname); 210 | private MCCOMPONENTAPI cmcComponentAPI; 211 | // 获取组件相关API 212 | public T ConvertComponentFunc(string apiname) 213 | { 214 | if (cmcComponentAPI != null) 215 | { 216 | IntPtr f = cmcComponentAPI(apiname); 217 | if (f != IntPtr.Zero) 218 | { 219 | //return (T)Marshal.GetDelegateForFunctionPointer(f, typeof(T)); 220 | //若.net framework版本高于4.5.1可用以下替换以上 221 | return Marshal.GetDelegateForFunctionPointer(f); 222 | } 223 | } 224 | Console.WriteLine("Get ComponentApi {0} failed.", apiname); 225 | return default(T); 226 | } 227 | 228 | // 初始化所有api函数 229 | void initApis() 230 | { 231 | caddBeforeActEvent = Invoke("addBeforeActListener"); 232 | caddAfterActEvent = Invoke("addAfterActListener"); 233 | cremoveBeforeAct = Invoke("removeBeforeActListener"); 234 | cremoveAfterAct = Invoke("removeAfterActListener"); 235 | csetshareptr = Invoke("setSharePtr"); 236 | cgetSharePtr = Invoke("getSharePtr"); 237 | cremoveSharePtr = Invoke("removeSharePtr"); 238 | csetCommandDescribe = Invoke("setCommandDescribeEx"); 239 | cruncmd = Invoke("runcmd"); 240 | clogout = Invoke("logout"); 241 | cgetOnLinePlayers = Invoke("getOnLinePlayers"); 242 | cgetExtraAPI = Invoke("getExtraAPI"); 243 | cmcComponentAPI = Invoke("mcComponentAPI"); 244 | creNameByUuid = Invoke("reNameByUuid"); 245 | ctalkAs = Invoke("talkAs"); 246 | cruncmdAs = Invoke("runcmdAs"); 247 | cdisconnectClient = Invoke("disconnectClient"); 248 | csendText = Invoke("sendText"); 249 | cJSErunScript = Invoke("JSErunScript"); 250 | cJSEfireCustomEvent = Invoke("JSEfireCustomEvent"); 251 | csendSimpleForm = Invoke("sendSimpleForm"); 252 | csendModalForm = Invoke("sendModalForm"); 253 | csendCustomForm = Invoke("sendCustomForm"); 254 | creleaseForm = Invoke("releaseForm"); 255 | cselectPlayer = Invoke("selectPlayer"); 256 | caddPlayerItem = Invoke("addPlayerItem"); 257 | cgetscoreboardValue = Invoke("getscoreboardValue"); 258 | csetscoreboardValue = Invoke("setscoreboardValue"); 259 | csetServerMotd = Invoke("setServerMotd"); 260 | cgetscoreById = Invoke("getscoreById"); 261 | csetscoreById = Invoke("setscoreById"); 262 | cpostTick = Invoke("postTick"); 263 | cgetItemRawname = Invoke("getItemRawname"); 264 | ccshook = Invoke("cshook"); 265 | ccsunhook = Invoke("csunhook"); 266 | cdlsym = Invoke("dlsym"); 267 | creadHardMemory = Invoke("readHardMemory"); 268 | cwriteHardMemory = Invoke("writeHardMemory"); 269 | 270 | #region 非社区部分内容 271 | if (COMMERCIAL) { 272 | cgetStructure = ConvertExtraFunc("getStructure"); 273 | csetStructure = ConvertExtraFunc("setStructure"); 274 | cgetPlayerAbilities = ConvertExtraFunc("getPlayerAbilities"); 275 | csetPlayerAbilities = ConvertExtraFunc("setPlayerAbilities"); 276 | cgetPlayerAttributes = ConvertExtraFunc("getPlayerAttributes"); 277 | csetPlayerTempAttributes = ConvertExtraFunc("setPlayerTempAttributes"); 278 | cgetPlayerMaxAttributes = ConvertExtraFunc("getPlayerMaxAttributes"); 279 | csetPlayerMaxAttributes = ConvertExtraFunc("setPlayerMaxAttributes"); 280 | cgetPlayerItems = ConvertExtraFunc("getPlayerItems"); 281 | csetPlayerItems = ConvertExtraFunc("setPlayerItems"); 282 | cgetPlayerSelectedItem = ConvertExtraFunc("getPlayerSelectedItem"); 283 | caddPlayerItemEx = ConvertExtraFunc("addPlayerItemEx"); 284 | cgetPlayerEffects = ConvertExtraFunc("getPlayerEffects"); 285 | csetPlayerEffects = ConvertExtraFunc("setPlayerEffects"); 286 | csetPlayerBossBar = ConvertExtraFunc("setPlayerBossBar"); 287 | cremovePlayerBossBar = ConvertExtraFunc("removePlayerBossBar"); 288 | ctransferserver = ConvertExtraFunc("transferserver"); 289 | cteleport = ConvertExtraFunc("teleport"); 290 | csetPlayerSidebar = ConvertExtraFunc("setPlayerSidebar"); 291 | cremovePlayerSidebar = ConvertExtraFunc("removePlayerSidebar"); 292 | cgetPlayerPermissionAndGametype = ConvertExtraFunc("getPlayerPermissionAndGametype"); 293 | csetPlayerPermissionAndGametype = ConvertExtraFunc("setPlayerPermissionAndGametype"); 294 | cgetAllScore = ConvertExtraFunc("getAllScore"); 295 | csetAllScore = ConvertExtraFunc("setAllScore"); 296 | cgetMapColors = ConvertExtraFunc("getMapColors"); 297 | cexportPlayersData = ConvertExtraFunc("exportPlayersData"); 298 | cimportPlayersData = ConvertExtraFunc("importPlayersData"); 299 | } 300 | #endregion 301 | } 302 | 303 | // 保管一个事件 304 | private void addcb(string k, EventCab cb) 305 | { 306 | ArrayList al; 307 | if (callbks.TryGetValue(k, out al)) 308 | { 309 | if (al != null) 310 | al.Add(cb); 311 | else 312 | { 313 | al = new ArrayList(); 314 | al.Add(cb); 315 | callbks[k] = al; 316 | } 317 | } 318 | else 319 | { 320 | al = new ArrayList(); 321 | al.Add(cb); 322 | callbks[k] = al; 323 | } 324 | } 325 | // 移除一个事件处理 326 | private void removecb(string k, EventCab cb) 327 | { 328 | ArrayList al; 329 | if (callbks.TryGetValue(k, out al)) 330 | { 331 | if (al != null) 332 | al.Remove(cb); 333 | } 334 | } 335 | 336 | /// 337 | /// 设置事件发生前监听 338 | /// 339 | /// 340 | /// 341 | /// 342 | public bool addBeforeActListener(string key, EventCab cb) { 343 | bool r = caddBeforeActEvent != null && caddBeforeActEvent(key, cb); 344 | if (r) 345 | { 346 | string k = "Before" + key; 347 | addcb(k, cb); 348 | } 349 | return r; 350 | } 351 | 352 | /// 353 | /// 设置事件发生后监听 354 | /// 355 | /// 356 | /// 357 | /// 358 | public bool addAfterActListener(string key, EventCab cb) { 359 | bool r = caddAfterActEvent != null && caddAfterActEvent(key, cb); 360 | if (r) 361 | { 362 | string k = "After" + key; 363 | addcb(k, cb); 364 | } 365 | return r; 366 | } 367 | 368 | /// 369 | /// 移除事件发生前监听 370 | /// 371 | /// 372 | /// 373 | /// 374 | public bool removeBeforeActListener(string key, EventCab cb) { 375 | bool r = cremoveBeforeAct != null && cremoveBeforeAct(key, cb); 376 | if (r) 377 | { 378 | string k = "Before" + key; 379 | removecb(k, cb); 380 | } 381 | return r; 382 | } 383 | 384 | /// 385 | /// 移除事件发生后监听 386 | /// 387 | /// 388 | /// 389 | /// 390 | public bool removeAfterActListener(string key, EventCab cb) { 391 | bool r = cremoveAfterAct != null && cremoveAfterAct(key, cb); 392 | if (r) 393 | { 394 | string k = "After" + key; 395 | removecb(k, cb); 396 | } 397 | return r; 398 | } 399 | 400 | /// 401 | /// 发送一个方法至tick 402 | /// 403 | /// 待置入下一tick的无参方法 404 | public void postTick(TickFunc f) 405 | { 406 | if (cpostTick != null) 407 | { 408 | TickFunc tmp = null; 409 | tmp = () => 410 | { 411 | f(); 412 | ticks.Remove(tmp); 413 | }; 414 | ticks[tmp] = f; 415 | cpostTick(tmp); 416 | } 417 | } 418 | 419 | /// 420 | /// 设置共享数据(指针)
421 | /// 注:会替换掉旧数据 422 | ///
423 | /// 关键字 424 | /// 数据/函数指针 425 | public void setSharePtr(string key, IntPtr data) { 426 | if (csetshareptr != null) 427 | csetshareptr(key, data); 428 | } 429 | /// 430 | /// 获取共享数据(指针) 431 | /// 432 | /// 关键字 433 | /// 434 | public IntPtr getSharePtr(string key) { 435 | return (cgetSharePtr != null) ? cgetSharePtr(key) : 436 | IntPtr.Zero; 437 | } 438 | /// 439 | /// 移除共享数据(指针) 440 | /// 441 | /// 关键字 442 | /// 443 | public IntPtr removeSharePtr(string key) { 444 | return (cremoveSharePtr != null) ? cremoveSharePtr(key) : 445 | IntPtr.Zero; 446 | } 447 | /// 448 | /// 设置一个指令说明
449 | /// 备注:延期注册的情况,可能不会改变客户端界面 450 | ///
451 | /// 命令 452 | /// 描述 453 | /// 执行要求等级 454 | /// 命令类型1 455 | /// 命令类型2 456 | public void setCommandDescribeEx(string key, string description, CommandPermissionLevel level, short flag1, short flag2) { 457 | if (csetCommandDescribe != null) 458 | csetCommandDescribe(key, description, level, flag1, flag2); 459 | } 460 | /// 461 | /// 设置一个全局指令描述 462 | /// 463 | /// 命令 464 | /// 描述 465 | public void setCommandDescribe(string key, string description) { 466 | setCommandDescribeEx(key, description, CommandPermissionLevel.Any, (short)CommandCheatFlag.NotCheat, (short)CommandVisibilityFlag.Visible); 467 | } 468 | 469 | /// 470 | /// 执行后台指令 471 | /// 472 | /// 语法正确的MC指令 473 | /// 是否正常执行 474 | public bool runcmd(string cmd) { 475 | return (cruncmd != null) && cruncmd(cmd); 476 | } 477 | 478 | /// 479 | /// 发送一条命令输出消息(可被拦截)
480 | /// 注:末尾附带换行符 481 | ///
482 | /// 待发送的命令输出字符串 483 | public void logout(string cmdout) { 484 | if (clogout != null) 485 | clogout(cmdout); 486 | } 487 | 488 | /// 489 | /// 获取在线玩家列表 490 | /// 491 | /// 492 | public string getOnLinePlayers() { 493 | try 494 | { 495 | return (cgetOnLinePlayers != null) ? StrTool.c_str(cgetOnLinePlayers()) : 496 | string.Empty; 497 | } catch(Exception e) { Console.WriteLine(e.StackTrace); } 498 | return string.Empty; 499 | } 500 | 501 | /// 502 | /// 获取一个结构 503 | /// 504 | /// 地图维度 505 | /// 坐标JSON字符串 506 | /// 坐标JSON字符串 507 | /// 是否导出实体 508 | /// 是否导出方块 509 | /// 结构json字符串 510 | public string getStructure(int did, string jsonposa, string jsonposb, bool exent, bool exblk) { 511 | try 512 | { 513 | return (cgetStructure != null) ? StrTool.c_str(cgetStructure(did, jsonposa, jsonposb, exent, exblk)) : 514 | string.Empty; 515 | }catch (Exception e) { Console.WriteLine(e.StackTrace); } 516 | return string.Empty; 517 | } 518 | /// 519 | /// 设置一个结构到指定位置
520 | /// 注:旋转类型包含4种有效旋转类型 521 | ///
522 | /// 结构JSON字符串 523 | /// 地图维度 524 | /// 起始点坐标JSON字符串 525 | /// 旋转类型 526 | /// 是否导入实体 527 | /// 是否导入方块 528 | /// 是否设置成功 529 | public bool setStructure(string jdata, int did, string jsonposa, byte rot, bool exent, bool exblk) { 530 | return (csetStructure != null) && csetStructure(jdata, did, jsonposa, rot, exent, exblk); 531 | } 532 | 533 | /// 534 | /// 获取所有计分板计分项 535 | /// 536 | /// 计分板json字符串 537 | public string getAllScore() 538 | { 539 | try 540 | { 541 | return (cgetAllScore != null) ? StrTool.c_str(cgetAllScore()) : 542 | string.Empty; 543 | } 544 | catch (Exception e) { Console.WriteLine(e.StackTrace); } 545 | return string.Empty; 546 | } 547 | /// 548 | /// 设置所有计分板计分项
549 | /// 注:设置过程会清空原有数据 550 | ///
551 | /// 计分板json字符串 552 | /// 是否设置成功 553 | public bool setAllScore(string jdata) 554 | { 555 | return (csetAllScore != null) && csetAllScore(jdata); 556 | } 557 | /// 558 | /// 导出地图所有离线玩家数据
559 | /// 注:调用时机在地图初始化完成之后生效 560 | ///
561 | /// 562 | public string exportPlayersData() 563 | { 564 | return (cexportPlayersData != null) ? StrTool.c_str(cexportPlayersData()) : 565 | string.Empty; 566 | } 567 | /// 568 | /// 导入玩家数据至地图 569 | /// 570 | /// 待导入的玩家信息集json字符串 571 | /// 是否导入成功 572 | public bool importPlayersData(string jdata) 573 | { 574 | return (cimportPlayersData != null) && cimportPlayersData(jdata); 575 | } 576 | 577 | /// 578 | /// 重命名一个指定的玩家名
579 | /// 注:该函数可能不会变更客户端实际显示名 580 | ///
581 | /// 在线玩家的uuid字符串 582 | /// 新的名称 583 | /// 是否命名成功 584 | public bool reNameByUuid(string uuid, string newName) { 585 | return (creNameByUuid != null) && creNameByUuid(uuid, newName); 586 | } 587 | 588 | /// 589 | /// 获取玩家能力表
590 | /// 注:含总计18种能力值 591 | ///
592 | /// 在线玩家的uuid字符串 593 | /// 能力json字符串 594 | public string getPlayerAbilities(string uuid) { 595 | try 596 | { 597 | return (cgetPlayerAbilities != null) ? StrTool.c_str(cgetPlayerAbilities(uuid)) : 598 | string.Empty; 599 | } 600 | catch(Exception e) { Console.WriteLine(e.StackTrace); } 601 | return string.Empty; 602 | } 603 | /// 604 | /// 设置玩家能力表
605 | /// 注:该函数可能不会变更客户端实际显示能力 606 | ///
607 | /// 在线玩家的uuid字符串 608 | /// 新能力json数据字符串 609 | /// 是否设置成功 610 | public bool setPlayerAbilities(string uuid, string abdata) { 611 | return (csetPlayerAbilities != null) && csetPlayerAbilities(uuid, abdata); 612 | } 613 | 614 | /// 615 | /// 获取玩家属性表
616 | /// 注:总计14种生物属性,含部分有效玩家属性 617 | ///
618 | /// 在线玩家的uuid字符串 619 | /// 属性json字符串 620 | public string getPlayerAttributes(string uuid) { 621 | try 622 | { 623 | return (cgetPlayerAttributes != null) ? StrTool.c_str(cgetPlayerAttributes(uuid)) : 624 | string.Empty; 625 | } catch (Exception e) { Console.WriteLine(e.StackTrace); } 626 | return string.Empty; 627 | 628 | } 629 | /// 630 | /// 设置玩家属性临时值表
631 | /// 注:该函数可能不会变更客户端实际显示值 632 | ///
633 | /// 在线玩家的uuid字符串 634 | /// 新属性临时值json数据字符串 635 | /// 是否设置成功 636 | public bool setPlayerTempAttributes(string uuid, string newTempAttributes) { 637 | return (csetPlayerTempAttributes != null) && csetPlayerTempAttributes(uuid, newTempAttributes); 638 | } 639 | /// 640 | /// 获取玩家属性上限值表 641 | /// 642 | /// 在线玩家的uuid字符串 643 | /// 属性上限值json字符串 644 | public string getPlayerMaxAttributes(string uuid) { 645 | try 646 | { 647 | return (cgetPlayerMaxAttributes != null) ? StrTool.c_str(cgetPlayerMaxAttributes(uuid)) : 648 | string.Empty; 649 | } catch (Exception e) { Console.WriteLine(e.StackTrace); } 650 | return string.Empty; 651 | } 652 | /// 653 | /// 设置玩家属性上限值表
654 | /// 注:该函数可能不会变更客户端实际显示值 655 | ///
656 | /// 在线玩家的uuid字符串 657 | /// 新属性上限值json数据字符串 658 | /// 是否设置成功 659 | public bool setPlayerMaxAttributes(string uuid, string newMaxAttributes) { 660 | return (csetPlayerMaxAttributes != null) && csetPlayerMaxAttributes(uuid, newMaxAttributes); 661 | } 662 | 663 | /// 664 | /// 获取玩家所有物品列表
665 | /// 注:玩家物品包括末影箱、装备、副手和背包四项物品的nbt描述型数据列表。nbt被序列化数据类型的tag所描述,总计12种有效tag,所对应值可序列化为json数据,亦可反序列化为nbt 666 | ///
667 | /// 在线玩家的uuid字符串 668 | /// 物品列表json字符串 669 | public string getPlayerItems(string uuid) { 670 | try 671 | { 672 | return (cgetPlayerItems != null) ? StrTool.c_str(cgetPlayerItems(uuid)) : 673 | string.Empty; 674 | } catch(Exception e) { Console.WriteLine(e.StackTrace); } 675 | return string.Empty; 676 | } 677 | /// 678 | /// 设置玩家所有物品列表
679 | /// 注:特定条件下可能不会变更游戏内实际物品 680 | ///
681 | /// 在线玩家的uuid字符串 682 | /// 新物品列表json数据字符串 683 | /// 是否设置成功 684 | public bool setPlayerItems(string uuid, string newItems) { 685 | return (csetPlayerItems != null) && csetPlayerItems(uuid, newItems); 686 | } 687 | /// 688 | /// 获取玩家当前选中项信息
689 | /// 注:选中项包含选中框所处位置,以及选中物品的nbt描述型数据 690 | ///
691 | /// 在线玩家的uuid字符串 692 | /// 当前选中项信息json字符串 693 | public string getPlayerSelectedItem(string uuid) { 694 | try 695 | { 696 | return (cgetPlayerSelectedItem != null) ? StrTool.c_str(cgetPlayerSelectedItem(uuid)) : 697 | string.Empty; 698 | } catch (Exception e) { Console.WriteLine(e.StackTrace); } 699 | return string.Empty; 700 | } 701 | /// 702 | /// 增加玩家一个物品
703 | /// 注:特定条件下可能不会变更游戏内实际物品 704 | ///
705 | /// 在线玩家的uuid字符串 706 | /// 物品json数据字符串 707 | /// 是否添加成功 708 | public bool addPlayerItemEx(string uuid, string item) { 709 | return (caddPlayerItemEx != null) && caddPlayerItemEx(uuid, item); 710 | } 711 | /// 712 | /// 增加玩家一个物品
713 | /// 注:特定条件下可能不会变更游戏内实际物品 714 | ///
715 | /// 在线玩家的uuid字符串 716 | /// 物品id值 717 | /// 物品特殊值 718 | /// 数量 719 | /// 是否增加成功 720 | public bool addPlayerItem(string uuid, int id, short aux, byte count) { 721 | return (caddPlayerItem != null) && caddPlayerItem(uuid, id, aux, count); 722 | } 723 | /// 724 | /// 获取玩家所有效果列表 725 | /// 726 | /// 在线玩家的uuid字符串 727 | /// 效果列表json字符串 728 | public string getPlayerEffects(string uuid) { 729 | try 730 | { 731 | return (cgetPlayerEffects != null) ? StrTool.c_str(cgetPlayerEffects(uuid)) : 732 | string.Empty; 733 | } catch (Exception e) { Console.WriteLine(e.StackTrace); } 734 | return string.Empty; 735 | } 736 | /// 737 | /// 设置玩家所有效果列表
738 | /// 注:特定条件下可能不会变更游戏内实际界面 739 | ///
740 | /// 在线玩家的uuid字符串 741 | /// 新效果列表json数据字符串 742 | /// 是否设置成功 743 | public bool setPlayerEffects(string uuid, string newEffects) { 744 | return (csetPlayerEffects != null) && csetPlayerEffects(uuid, newEffects); 745 | } 746 | 747 | /// 748 | /// 设置玩家自定义血条 749 | /// 750 | /// 在线玩家的uuid字符串 751 | /// 血条标题 752 | /// 血条百分比 753 | /// 754 | public bool setPlayerBossBar(string uuid, string title, float percent) { 755 | return (csetPlayerBossBar != null) && csetPlayerBossBar(uuid, title, percent); 756 | } 757 | /// 758 | /// 清除玩家自定义血条 759 | /// 760 | /// 在线玩家的uuid字符串 761 | /// 是否清除成功 762 | public bool removePlayerBossBar(string uuid) { 763 | return (cremovePlayerBossBar != null) && cremovePlayerBossBar(uuid); 764 | } 765 | 766 | /// 767 | /// 查询在线玩家基本信息 768 | /// 769 | /// 在线玩家的uuid字符串 770 | /// 玩家基本信息json字符串 771 | public string selectPlayer(string uuid) { 772 | try 773 | { 774 | return (cselectPlayer != null) ? StrTool.c_str(cselectPlayer(uuid)) : 775 | string.Empty; 776 | } catch (Exception e) { Console.WriteLine(e); } 777 | return string.Empty; 778 | } 779 | 780 | /// 781 | /// 传送玩家至指定服务器 782 | /// 783 | /// 在线玩家的uuid字符串 784 | /// 待传服务器 785 | /// 端口 786 | /// 是否传送成功 787 | public bool transferserver(string uuid, string addr, int port) { 788 | return (ctransferserver != null) && ctransferserver(uuid, addr, port); 789 | } 790 | /// 791 | /// 传送玩家至指定坐标和维度 792 | /// 793 | /// 在线玩家的uuid字符串 794 | /// 795 | /// 796 | /// 797 | /// 维度ID 798 | /// 是否传送成功 799 | public bool teleport(string uuid, float x, float y, float z, int did) { 800 | return (cteleport != null) && cteleport(uuid, x, y, z, did); 801 | } 802 | /// 803 | /// 模拟玩家发送一个文本 804 | /// 805 | /// 在线玩家的uuid字符串 806 | /// 待模拟发送的文本 807 | /// 是否发送成功 808 | public bool talkAs(string uuid, string msg) { 809 | return (ctalkAs != null) && ctalkAs(uuid, msg); 810 | } 811 | /// 812 | /// 模拟玩家执行一个指令 813 | /// 814 | /// 在线玩家的uuid字符串 815 | /// 待模拟执行的指令 816 | /// 是否发送成功 817 | public bool runcmdAs(string uuid, string cmd) { 818 | return (cruncmdAs != null) && cruncmdAs(uuid, cmd); 819 | } 820 | 821 | /// 822 | /// 断开一个玩家的连接 823 | /// 824 | /// 在线玩家的uuid字符串 825 | /// 断开提示(设空值则为默认值) 826 | /// 827 | public bool disconnectClient(string uuid, string tips) { 828 | return (cdisconnectClient != null) && cdisconnectClient(uuid, tips); 829 | } 830 | 831 | /// 832 | /// 发送一个原始显示文本给玩家 833 | /// 834 | /// 在线玩家的uuid字符串 835 | /// 文本内容,空白内容则不予发送 836 | /// 是否发送成功 837 | public bool sendText(string uuid, string msg) 838 | { 839 | return (csendText != null) && csendText(uuid, msg); 840 | } 841 | 842 | /// 843 | /// 使用官方脚本引擎新增一段行为包脚本并执行
844 | /// (注:每次调用都会新增脚本环境,请避免多次重复调用此方法) 845 | ///
846 | /// 脚本文本 847 | /// 结果回调 848 | public void JSErunScript(string js, JSECab cb) 849 | { 850 | if (cJSErunScript != null) 851 | cJSErunScript(js, cb); 852 | } 853 | 854 | /// 855 | /// 使用官方脚本引擎发送一个自定义事件广播 856 | /// 857 | /// 自定义事件名称(不能以minecraft:开头) 858 | /// 事件内容JSON文本 859 | /// 结果回调 860 | public void JSEfireCustomEvent(string ename, string jdata, JSECab cb) 861 | { 862 | if (cJSEfireCustomEvent != null) 863 | cJSEfireCustomEvent(ename, jdata, cb); 864 | } 865 | 866 | /// 867 | /// 向指定的玩家发送一个简单表单 868 | /// 869 | /// 在线玩家的uuid字符串 870 | /// 表单标题 871 | /// 内容 872 | /// 按钮文本数组字符串 873 | /// 创建的表单id,为 0 表示发送失败 874 | public uint sendSimpleForm(string uuid, string title, string content, string buttons) { 875 | return (csendSimpleForm != null) ? csendSimpleForm(uuid, title, content, buttons) : 876 | 0; 877 | } 878 | /// 879 | /// 向指定的玩家发送一个模式对话框 880 | /// 881 | /// 在线玩家的uuid字符串 882 | /// 表单标题 883 | /// 内容 884 | /// 按钮1标题(点击该按钮selected为true) 885 | /// 按钮2标题(点击该按钮selected为false) 886 | /// 创建的表单id,为 0 表示发送失败 887 | public uint sendModalForm(string uuid, string title, string content, string button1, string button2) { 888 | return (csendModalForm != null) ? csendModalForm(uuid, title, content, button1, button2) : 889 | 0; 890 | } 891 | /// 892 | /// 向指定的玩家发送一个自定义表单 893 | /// 894 | /// 在线玩家的uuid字符串 895 | /// 自定义表单的json字符串
896 | /// (要使用自定义表单类型,参考nk、pm格式或minebbs专栏) 897 | /// 创建的表单id,为 0 表示发送失败 898 | public uint sendCustomForm(string uuid, string json) { 899 | return (csendCustomForm != null) ? csendCustomForm(uuid, json) : 900 | 0; 901 | } 902 | /// 903 | /// 放弃一个表单
904 | /// 注:已被接收到的表单会被自动释放 905 | ///
906 | /// 表单id 907 | /// 是否释放成功 908 | public bool releaseForm(uint formid) { 909 | return (creleaseForm != null) && creleaseForm(formid); 910 | } 911 | 912 | /// 913 | /// 设置玩家自定义侧边栏临时计分板
914 | /// 注:列表总是从第1行开始,总计不超过15行 915 | ///
916 | /// 在线玩家的uuid字符串 917 | /// 侧边栏标题 918 | /// 列表字符串数组 919 | /// 是否设置成功 920 | public bool setPlayerSidebar(string uuid, string title, string list) { 921 | return (csetPlayerSidebar != null) && csetPlayerSidebar(uuid, title, list); 922 | } 923 | /// 924 | /// 清除玩家自定义侧边栏 925 | /// 926 | /// 在线玩家的uuid字符串 927 | /// 是否清除成功 928 | public bool removePlayerSidebar(string uuid) { 929 | return (cremovePlayerSidebar != null) && cremovePlayerSidebar(uuid); 930 | } 931 | 932 | /// 933 | /// 获取玩家权限与游戏模式
934 | /// 注:OP命令等级包含6个有效等级[op-permission-level],权限包含3种有效权限[permissions.json],游戏模式包含5种有效模式[gamemode] 935 | ///
936 | /// 在线玩家的uuid字符串 937 | /// 权限与模式的json字符串 938 | public string getPlayerPermissionAndGametype(string uuid) { 939 | try 940 | { 941 | return (cgetPlayerPermissionAndGametype != null) ? StrTool.c_str(cgetPlayerPermissionAndGametype(uuid)) : 942 | string.Empty; 943 | } catch (Exception e) { Console.WriteLine(e.StackTrace); } 944 | return string.Empty; 945 | } 946 | /// 947 | /// 设置玩家权限与游戏模式
948 | /// 注:特定条件下可能不会变更游戏内实际能力 949 | ///
950 | /// 在线玩家的uuid字符串 951 | /// 新权限或模式json数据字符串 952 | /// 是否设置成功 953 | public bool setPlayerPermissionAndGametype(string uuid, string newModes) { 954 | return (csetPlayerPermissionAndGametype != null) && csetPlayerPermissionAndGametype(uuid, newModes); 955 | } 956 | 957 | /// 958 | /// 获取一个指定位置处区块的颜色数据
959 | /// 注:如区块未处于活动状态,可能返回无效颜色数据 960 | ///
961 | /// 962 | /// 963 | /// 964 | /// 待读取的维度 965 | /// 区块位置及颜色数据内容 966 | public string getMapColors(int x, int y, int z, int did) 967 | { 968 | return (cgetMapColors != null) ? StrTool.c_str(cgetMapColors(x, y, z, did)) : 969 | string.Empty; 970 | } 971 | 972 | // 社区贡献 973 | 974 | /// 975 | /// 获取指定玩家指定计分板上的数值
976 | /// 注:特定情况下会自动创建计分板 977 | ///
978 | /// 在线玩家的uuid字符串 979 | /// 计分板登记的名称 980 | /// 获取的目标值,若目标不存在则返回0 981 | public int getscoreboard(string uuid, string objname) 982 | { 983 | return (cgetscoreboardValue != null) ? cgetscoreboardValue(uuid, objname) : 984 | 0; 985 | } 986 | /// 987 | /// 设置指定玩家指定计分板上的数值 988 | /// 989 | /// 在线玩家的uuid字符串 990 | /// 计分板登记的名称,若不存在则自动添加 991 | /// 待设定的目标值 992 | /// 是否设置成功 993 | public bool setscoreboard(string uuid, string objname, int count) 994 | { 995 | return csetscoreboardValue != null && csetscoreboardValue(uuid, objname, count); 996 | } 997 | /// 998 | /// 设置服务器的显示名信息
999 | /// (注:服务器名称加载时机在地图完成载入之后) 1000 | ///
1001 | /// 新服务器显示名信息 1002 | /// 是否公开显示 1003 | /// 是否设置成功 1004 | public bool setServerMotd(string motd, bool isShow) 1005 | { 1006 | return csetServerMotd != null && csetServerMotd(motd, isShow); 1007 | } 1008 | /// 1009 | /// 获取指定ID对应于计分板上的数值 1010 | /// 1011 | /// 离线计分板的id 1012 | /// 计分板登记的名称,若不存在则自动添加 1013 | /// 获取的目标值,若目标不存在则返回0 1014 | public int getscoreById(long id, string objname) 1015 | { 1016 | return (cgetscoreById != null) ? cgetscoreById(id, objname) : 1017 | 0; 1018 | } 1019 | /// 1020 | /// 设置指定id对应于计分板上的数值 1021 | /// 1022 | /// 离线计分板的id 1023 | /// 计分板登记的名称,若不存在则自动添加 1024 | /// 待设置的值 1025 | /// 设置后的目标值,若未成功则返回0 1026 | public int setscoreById(long id, string objname, int count) 1027 | { 1028 | return (csetscoreById != null) ? csetscoreById(id, objname, count) : 1029 | 0; 1030 | } 1031 | /// 1032 | /// 获取物品原始标识字符 1033 | /// 1034 | /// 物品id 1035 | /// 物品原始标识字符 1036 | public string getItemRawname(int id) 1037 | { 1038 | return (cgetItemRawname != null) ? StrTool.c_str(cgetItemRawname(id)) : 1039 | "unknow"; 1040 | } 1041 | // 底层相关 1042 | 1043 | /// 1044 | /// 设置一个钩子 1045 | /// 1046 | /// 原型函数相对地址 1047 | /// 新函数 1048 | /// 待保存原型函数的指针 1049 | /// 1050 | public bool cshook(int rva, IntPtr hook, out IntPtr org) 1051 | { 1052 | IntPtr sorg = IntPtr.Zero; 1053 | var ret = ccshook != null && ccshook(rva, hook, out sorg); 1054 | org = sorg; 1055 | return ret; 1056 | } 1057 | /// 1058 | /// 卸载一个钩子 1059 | /// 1060 | /// 待卸载的函数 1061 | /// 已保存了原型函数的指针 1062 | /// 1063 | public bool csunhook(IntPtr hook, ref IntPtr org) { 1064 | IntPtr sorg = org; 1065 | var ret = ccsunhook != null && ccsunhook(hook, out sorg); 1066 | org = sorg; 1067 | return ret; 1068 | } 1069 | /// 1070 | /// 取相对地址对应的实际指针 1071 | /// 1072 | /// 1073 | /// 1074 | public IntPtr dlsym(int rva) { 1075 | return cdlsym != null ? cdlsym(rva) : 1076 | IntPtr.Zero; 1077 | } 1078 | 1079 | /// 1080 | /// 读特定段内存硬编码 1081 | /// 1082 | /// 函数片段起始位置相对地址 1083 | /// 内存长度 1084 | /// 1085 | public byte[] readHardMemory(int rva, int size) { 1086 | byte[] x = new byte[size]; 1087 | if (creadHardMemory != null) 1088 | if (creadHardMemory(rva, x, size)) 1089 | return x; 1090 | return null; 1091 | } 1092 | 1093 | /// 1094 | /// 写特定段内存硬编码 1095 | /// 1096 | /// 函数片段起始位置相对地址 1097 | /// 新数据内容 1098 | /// 内存长度 1099 | /// 1100 | public bool writeHardMemory(int rva, byte[] data, int size) 1101 | { 1102 | return (cwriteHardMemory != null) && cwriteHardMemory(rva, data, size); 1103 | } 1104 | } 1105 | } 1106 | --------------------------------------------------------------------------------