├── icon.jpg ├── README.md ├── src ├── MemoryOperators.cpp ├── Entry.h ├── Entry.cpp ├── Global.h ├── LegacyServerApi.cpp ├── BinaryStreamApi.cpp ├── LegacyModApi.cpp ├── PlaceholderApi.cpp ├── FormAPI.cpp └── EventAPI.cpp ├── .gitignore ├── .clangd ├── manifest.json ├── .github ├── PULL_REQUEST_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── feature_request_zh.yml │ ├── feature_request.yml │ ├── bug_report_zh.yml │ └── bug_report.yml └── workflows │ ├── build.yml │ └── release.yml ├── lib ├── PlaceholderAPI.d.ts ├── BEPlaceholderAPI-JS.d.ts ├── PlaceholderAPI.js ├── BEPlaceholderAPI-JS.js ├── FormAPI-JS.js ├── EventAPI-JS.js ├── EventAPI-JS.d.ts └── GMLIB_API-JS.d.ts ├── .clang-format ├── xmake.lua ├── tooth.json ├── .clang-tidy └── LICENSE /icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GroupMountain/GMLIB-LegacyRemoteCallApi/HEAD/icon.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GMLIB-LegacyRemoteCallApi 2 | Legacy RemoteCall API for GMLIB. Only for legacy LSE plugin compatibility. 3 | 4 | # 模块简介 5 | - 本模块是 `GMLIB` 的 `Legacy RemoteCall API` 模块,是为LL2的LLSE插件的兼容性保留。 6 | - 通过本模块,可以使LSE插件调用 `GMLIB` 内部的API。 7 | 8 | # 开发文档 9 | - https://groupmountain.github.io/Documentation/ 10 | -------------------------------------------------------------------------------- /src/MemoryOperators.cpp: -------------------------------------------------------------------------------- 1 | // This file will make your plugin use LeviLamina's memory operators by default. 2 | // This improves the memory management of your plugin and is recommended to use. 3 | // You should not modify anything in this file. 4 | 5 | #define LL_MEMORY_OPERATORS 6 | 7 | #include -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | CMakeLists.txt.user 2 | CMakeCache.txt 3 | CMakeFiles 4 | CMakeScripts 5 | Testing 6 | Makefile 7 | cmake_install.cmake 8 | install_manifest.txt 9 | compile_commands.json 10 | CTestTestfile.cmake 11 | _deps 12 | CMakeSettings.json 13 | .vscode/ 14 | build/ 15 | /.xmake 16 | /CMakeLists.txt 17 | /bin 18 | .cache/clangd/index 19 | -------------------------------------------------------------------------------- /.clangd: -------------------------------------------------------------------------------- 1 | Diagnostics: 2 | Suppress: 3 | - "-Wmicrosoft-enum-forward-reference" 4 | - "-Wc++11-narrowing" 5 | - "-Wc++2b-extensions" 6 | - "-Wmicrosoft-cast" 7 | CompileFlags: 8 | Add: 9 | - "-ferror-limit=0" 10 | - "-D__FUNCTION__=\"dummy\"" 11 | - "-Yumc/_HeaderOutputPredefine.h" 12 | - "-FImc/_HeaderOutputPredefine.h" # clangd bug can't find pch file 13 | Remove: 14 | - "/Yu_HeaderOutputPredefine.h" 15 | - "/FI_HeaderOutputPredefine.h" 16 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "${modName}", 3 | "entry": "${modFile}", 4 | "version": "${modVersion}", 5 | "author": "GroupMountain", 6 | "type": "native", 7 | "passive": true, 8 | "dependencies": [ 9 | { 10 | "name": "GMLIB" 11 | }, 12 | { 13 | "name": "LegacyRemoteCall" 14 | }, 15 | { 16 | "name": "iListenAttentively" 17 | }, 18 | { 19 | "name": "ModAPI" 20 | } 21 | ] 22 | } -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## What does this PR do? 2 | 3 | 4 | 5 | ## Which issues does this PR resolve? 6 | 7 | 8 | 9 | ## Checklist before merging 10 | 11 | Thank you for your contribution to the repository. 12 | Before submitting this PR, please make sure: 13 | 14 | - [ ] Your code builds clean without any errors or warnings 15 | - [ ] Your code follows [LeviLamina C++ Style Guide](https://github.com/LiteLDev/LeviLamina/wiki/CPP-Style-Guide) 16 | - [ ] You have tested all functions 17 | - [ ] You have not used code without license 18 | - [ ] You have added statement for third-party code 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request_zh.yml: -------------------------------------------------------------------------------- 1 | name: 新功能建议 2 | description: 如果需要更多API,请给出你的建议。 3 | title: "标题:新功能建议" 4 | labels: ["type: enhancement"] 5 | body: 6 | - type: textarea 7 | attributes: 8 | label: 您的新功能建议是否与问题有关?请描述。 9 | description: 简述你在开发过程中遇到了什么问题? 10 | validations: 11 | required: true 12 | 13 | - type: textarea 14 | attributes: 15 | label: 你想要的接口 16 | description: 简述你需要的API,以及具体功能。 17 | validations: 18 | required: true 19 | 20 | - type: textarea 21 | attributes: 22 | label: 你曾经使用过的替代方案 23 | description: 简述你对于此问题使用过的替代方案。 24 | 25 | - type: textarea 26 | attributes: 27 | label: 更多信息 28 | description: 给出更多信息帮助我们解决你的问题。 29 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | on: 2 | pull_request: 3 | push: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | build: 8 | runs-on: windows-latest 9 | steps: 10 | - name: Checkout repository 11 | uses: actions/checkout@v2 12 | 13 | - uses: xmake-io/github-action-setup-xmake@v1 14 | with: 15 | xmake-version: 3.0.0 16 | 17 | - run: | 18 | xmake repo -u 19 | 20 | - run: | 21 | xmake f -a x64 -m release -p windows -y 22 | 23 | - run: | 24 | xmake -w -y 25 | 26 | - uses: actions/upload-artifact@v4 27 | with: 28 | name: ${{ github.event.repository.name }}-windows-x64-${{ github.sha }} 29 | path: | 30 | bin/ -------------------------------------------------------------------------------- /lib/PlaceholderAPI.d.ts: -------------------------------------------------------------------------------- 1 | /** 翻译带PAPI变量文本 */ 2 | export function translate( 3 | /** 要翻译的文本 */ 4 | value: String, 5 | /** 实体对象 */ 6 | actor?: Entity, 7 | /** 目标翻译语言 */ 8 | language?: String 9 | ): String; 10 | 11 | /** 注册PAPI变量 */ 12 | export function registerPlaceholder( 13 | /** papi变量 */ 14 | placeholder: String, 15 | /** 回调 */ 16 | callback: ( 17 | /** 实体对象 */ actor: Entity, 18 | /** 参数 */ params: String[], 19 | /** 目标翻译语言 */language: String 20 | ) => String | undefined 21 | ): void; 22 | 23 | /** 注销PAPI变量 */ 24 | export function unregisterPlaceholder( 25 | /** papi变量 */ 26 | placeholder: String 27 | ): Boolean; 28 | 29 | /** 根据模组名注销PAPI变量 */ 30 | export function unregisterPlaceholderFromModName( 31 | /** 模组名 */ 32 | modName: String 33 | ): Boolean; 34 | 35 | /** 获取一个papi变量的值 */ 36 | export function getValue( 37 | /** papi变量名 */ 38 | placeholder: String, 39 | actor?: Entity, 40 | params?: Record, 41 | language?: string 42 | ): Boolean; -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Suggest an idea for this project 3 | title: "[Feature]: " 4 | labels: ["enhancement"] 5 | body: 6 | - type: textarea 7 | attributes: 8 | label: Is your feature request related to a problem? Please describe. 9 | description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 10 | validations: 11 | required: true 12 | 13 | - type: textarea 14 | attributes: 15 | label: Describe the solution you'd like 16 | description: A clear and concise description of what you want to happen. 17 | validations: 18 | required: true 19 | 20 | - type: textarea 21 | attributes: 22 | label: Describe alternatives you've considered 23 | description: A clear and concise description of any alternative solutions or features you've considered. 24 | 25 | - type: textarea 26 | attributes: 27 | label: Additional context 28 | description: Add any other context or screenshots about the feature request here. 29 | -------------------------------------------------------------------------------- /src/Entry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | namespace gmlib { 7 | 8 | class LegacyRemoteCallApi { 9 | 10 | public: 11 | static LegacyRemoteCallApi& getInstance(); 12 | 13 | LegacyRemoteCallApi() : mSelf(*ll::mod::NativeMod::current()), mThreadPoolExecutor(getSelf().getName()) {} 14 | 15 | [[nodiscard]] ll::mod::NativeMod& getSelf() const { return mSelf; } 16 | 17 | /// @return True if the plugin is loaded successfully. 18 | bool load(); 19 | 20 | /// @return True if the plugin is enabled successfully. 21 | bool enable(); 22 | 23 | /// @return True if the plugin is disabled successfully. 24 | bool disable(); 25 | 26 | // TODO: Implement this method if you need to unload the plugin. 27 | // /// @return True if the plugin is unloaded successfully. 28 | // bool unload(); 29 | 30 | ll::thread::ThreadPoolExecutor& getThreadPoolExecutor() { return mThreadPoolExecutor; } 31 | 32 | private: 33 | ll::mod::NativeMod& mSelf; 34 | ll::thread::ThreadPoolExecutor mThreadPoolExecutor; 35 | }; 36 | 37 | } // namespace gmlib 38 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report_zh.yml: -------------------------------------------------------------------------------- 1 | name: 漏洞反馈 2 | description: 如果插件存在漏洞,请在此反馈。 3 | title: "标题:漏洞反馈" 4 | labels: ["type: bug"] 5 | body: 6 | - type: textarea 7 | attributes: 8 | label: 简述漏洞 9 | description: 发生了什么问题? 10 | validations: 11 | required: true 12 | 13 | - type: textarea 14 | attributes: 15 | label: 复现方案 16 | description: 给出具体的复现步骤。 17 | validations: 18 | required: true 19 | 20 | - type: textarea 21 | attributes: 22 | label: 预期结果 23 | description: 简述预期结果是什么! 24 | validations: 25 | required: true 26 | 27 | - type: textarea 28 | attributes: 29 | label: 日志或截图 30 | description: 如果有条件请给出日志或截图来帮助我们修复漏洞 31 | 32 | - type: input 33 | attributes: 34 | label: 操作系统 35 | description: 你所使用的操作系统 (例如: Windows 10) 36 | 37 | - type: input 38 | attributes: 39 | label: BDS 版本 40 | description: 你所使用的 BDS 版本 (例如: 1.20.32.1) 41 | 42 | - type: input 43 | attributes: 44 | label: LeviLamina 版本 45 | description: 你所使用的 LeviLamina 版本 (例如: 1.0.0) 46 | 47 | - type: input 48 | attributes: 49 | label: GMLIB 版本 50 | description: 你所使用的 GMLIB 版本 (例如: 1.0.0) 51 | 52 | - type: textarea 53 | attributes: 54 | label: 更多信息 55 | description: 如果还有更多相关信息,请提供。 56 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | AccessModifierOffset: -4 3 | AlignAfterOpenBracket: BlockIndent 4 | AlignArrayOfStructures: Left 5 | AlignConsecutiveDeclarations: 6 | Enabled: true 7 | AcrossEmptyLines: false 8 | AcrossComments: false 9 | AlignConsecutiveAssignments: 10 | Enabled: true 11 | AcrossEmptyLines: false 12 | AcrossComments: false 13 | AlignCompound: true 14 | PadOperators: true 15 | AlignConsecutiveMacros: 16 | Enabled: true 17 | AcrossEmptyLines: false 18 | AcrossComments: false 19 | AllowAllParametersOfDeclarationOnNextLine: false 20 | AllowAllArgumentsOnNextLine: false 21 | AlignOperands: AlignAfterOperator 22 | AlignConsecutiveBitFields: 23 | Enabled: true 24 | AcrossEmptyLines: false 25 | AcrossComments: false 26 | AllowShortLambdasOnASingleLine: All 27 | AllowShortBlocksOnASingleLine: Empty 28 | AllowShortIfStatementsOnASingleLine: AllIfsAndElse 29 | AllowShortLoopsOnASingleLine: true 30 | AlwaysBreakAfterDefinitionReturnType: None 31 | AlwaysBreakTemplateDeclarations: 'Yes' 32 | BinPackArguments: false 33 | BinPackParameters: false 34 | BreakBeforeBraces: Custom 35 | BreakBeforeBinaryOperators: NonAssignment 36 | ColumnLimit: 120 37 | CommentPragmas: '^ IWYU pragma:' 38 | ConstructorInitializerIndentWidth: 0 39 | IndentWidth: 4 40 | Language: Cpp 41 | MaxEmptyLinesToKeep: 2 42 | PackConstructorInitializers: CurrentLine 43 | PointerAlignment: Left 44 | TabWidth: 4 45 | UseTab: Never 46 | SortIncludes: CaseSensitive 47 | -------------------------------------------------------------------------------- /src/Entry.cpp: -------------------------------------------------------------------------------- 1 | #include "Entry.h" 2 | #include "Global.h" 3 | 4 | namespace gmlib { 5 | 6 | LegacyRemoteCallApi& LegacyRemoteCallApi::getInstance() { 7 | static LegacyRemoteCallApi instance; 8 | return instance; 9 | } 10 | 11 | bool LegacyRemoteCallApi::load() { 12 | (void)CustomRecipeRegistry::getInstance(); 13 | Export_Legacy_GMLib_ModAPI(); 14 | Export_Legacy_GMLib_ServerAPI(); 15 | Export_Compatibility_API(); 16 | ExportPAPI(); 17 | Export_Event_API(); 18 | Export_BinaryStream_API(); 19 | // Export_Form_API(); 20 | auto logger = ll::io::LoggerRegistry::getInstance().getOrCreate(PLUGIN_NAME); 21 | logger->info("GMLIB-LegacyRemoteCallApi Loaded!"); 22 | logger->info( 23 | "Loaded Version: {} with {}", 24 | fmt::format(fg(fmt::color::pink), "GMLIB-" GMLIB_FILE_VERSION_STRING), 25 | fmt::format(fg(fmt::color::light_green), "GMLIB-LegacyRemoteCallApi-{}", LIB_VERSION.to_string()) 26 | ); 27 | logger->info("Author: GroupMountain"); 28 | logger->info("Repository: https://github.com/GroupMountain/GMLIB-LegacyRemoteCallApi"); 29 | return true; 30 | } 31 | 32 | bool LegacyRemoteCallApi::enable() { return true; } 33 | 34 | bool LegacyRemoteCallApi::disable() { return true; } 35 | 36 | } // namespace gmlib 37 | 38 | LL_REGISTER_MOD(gmlib::LegacyRemoteCallApi, gmlib::LegacyRemoteCallApi::getInstance()); 39 | 40 | 41 | ll::thread::ThreadPoolExecutor const& getThreadPoolExecutor() { 42 | return gmlib::LegacyRemoteCallApi::getInstance().getThreadPoolExecutor(); 43 | } 44 | 45 | ll::io::Logger& getLogger() { return gmlib::LegacyRemoteCallApi::getInstance().getSelf().getLogger(); } -------------------------------------------------------------------------------- /xmake.lua: -------------------------------------------------------------------------------- 1 | add_rules("mode.debug", "mode.release") 2 | 3 | add_repositories("liteldev-repo https://github.com/LiteLDev/xmake-repo.git") 4 | add_repositories("groupmountain-repo https://github.com/GroupMountain/xmake-repo.git") 5 | add_repositories("miracleforest-repo https://github.com/MiracleForest/xmake-repo.git") 6 | 7 | if not has_config("vs_runtime") then 8 | set_runtimes("MD") 9 | end 10 | 11 | add_requires("levilamina 1.7.3", {configs = {target_type = "server"}}) 12 | add_requires("legacyremotecall") 13 | add_requires("levibuildscript 0.5.2") 14 | add_requires("ilistenattentively 0.10.0") 15 | add_requires("gmlib 1.7.0") 16 | add_requires("modapi 0.3.0") 17 | 18 | target("GMLIB-LegacyRemoteCallApi") 19 | add_cxflags( 20 | "/EHa", 21 | "/utf-8", 22 | "/bigobj" 23 | ) 24 | add_defines( 25 | "NOMINMAX", 26 | "UNICODE", 27 | "_HAS_CXX23=1" 28 | ) 29 | add_files( 30 | "src/**.cpp" 31 | ) 32 | add_includedirs( 33 | "src" 34 | ) 35 | add_packages( 36 | "levilamina", 37 | "legacyremotecall", 38 | "ilistenattentively", 39 | "gmlib", 40 | "modapi" 41 | ) 42 | add_rules("@levibuildscript/linkrule") 43 | add_rules("@levibuildscript/modpacker") 44 | set_exceptions("none") 45 | set_kind("shared") 46 | set_languages("cxx20") 47 | set_symbols("debug") 48 | after_build(function (target) 49 | local target_path = path.join("bin", target:name(), "lib") 50 | if os.exists(target_path) then 51 | os.rm(target_path) 52 | end 53 | os.cp("lib", target_path) 54 | end) -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: Create a report to help us improve 3 | title: "[Bug]: " 4 | labels: ["bug"] 5 | body: 6 | - type: textarea 7 | attributes: 8 | label: Describe the bug 9 | description: A clear and concise description of what the bug is. 10 | validations: 11 | required: true 12 | 13 | - type: textarea 14 | attributes: 15 | label: To Reproduce 16 | description: Steps to reproduce the behavior. 17 | validations: 18 | required: true 19 | 20 | - type: textarea 21 | attributes: 22 | label: Expected behavior 23 | description: A clear and concise description of what you expected to happen. 24 | validations: 25 | required: true 26 | 27 | - type: textarea 28 | attributes: 29 | label: Screenshots 30 | description: If applicable, add screenshots to help explain your problem. 31 | 32 | - type: input 33 | attributes: 34 | label: Platform 35 | description: The platform you are using. (e.g. Windows 10) 36 | 37 | - type: input 38 | attributes: 39 | label: BDS Version 40 | description: The version of BDS you are using. (e.g. 1.20.32.1) 41 | 42 | - type: input 43 | attributes: 44 | label: LeviLamina Version 45 | description: The version of LeviLamina you are using. (e.g. 1.0.0) 46 | 47 | - type: input 48 | attributes: 49 | label: Version 50 | description: The version of the plugin you are using. (e.g. 1.0.0) 51 | 52 | - type: textarea 53 | attributes: 54 | label: Additional context 55 | description: Add any other context about the problem here. 56 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | on: 2 | release: 3 | types: 4 | - published 5 | 6 | jobs: 7 | build: 8 | runs-on: windows-latest 9 | steps: 10 | - name: Checkout repository 11 | uses: actions/checkout@v2 12 | 13 | - uses: xmake-io/github-action-setup-xmake@v1 14 | with: 15 | xmake-version: 3.0.0 16 | 17 | - run: | 18 | xmake repo -u 19 | 20 | - run: | 21 | xmake f -a x64 -m release -p windows -y 22 | 23 | - run: | 24 | xmake -w -y 25 | 26 | - uses: actions/upload-artifact@v4 27 | with: 28 | name: ${{ github.event.repository.name }}-windows-x64-${{ github.sha }} 29 | path: | 30 | bin/ 31 | 32 | upload-to-release: 33 | needs: 34 | - build 35 | permissions: 36 | contents: write 37 | runs-on: ubuntu-latest 38 | steps: 39 | - name: Checkout code 40 | uses: actions/checkout@v4 41 | 42 | - name: Download Mod 43 | uses: actions/download-artifact@v4 44 | with: 45 | name: ${{ github.event.repository.name }}-windows-x64-${{ github.sha }} 46 | path: artifact 47 | 48 | - name: Copy additional files 49 | run: | 50 | cp -v LICENSE README.md artifact/ 51 | 52 | - name: Archive release 53 | run: | 54 | zip -r ../${{ github.event.repository.name }}-windows-x64.zip * 55 | working-directory: artifact 56 | 57 | - name: Create GitHub Release 58 | uses: softprops/action-gh-release@v1 59 | with: 60 | files: | 61 | ${{ github.event.repository.name }}-windows-x64.zip -------------------------------------------------------------------------------- /tooth.json: -------------------------------------------------------------------------------- 1 | { 2 | "format_version": 3, 3 | "format_uuid": "289f771f-2c9a-4d73-9f3f-8492495a924d", 4 | "tooth": "github.com/GroupMountain/GMLIB-LegacyRemoteCallApi", 5 | "version": "1.7.1", 6 | "info": { 7 | "name": "GMLIB-LegacyRemoteCallApi", 8 | "description": "Legacy RemoteCall API for GMLIB", 9 | "tags": [ 10 | "platform:levilamina", 11 | "type:mod", 12 | "gmlib", 13 | "lse", 14 | "library" 15 | ], 16 | "avatar_url": "https://raw.githubusercontent.com/GroupMountain/GMLIB-LegacyRemoteCallApi/refs/heads/main/icon.jpg" 17 | }, 18 | "variants": [ 19 | { 20 | "platform": "win-x64", 21 | "dependencies": { 22 | "github.com/LiteLDev/LeviLamina": ">=1.7.0", 23 | "github.com/GroupMountain/GMLIB-Release": ">=1.7.0", 24 | "github.com/GroupMountain/ModAPI-Release": ">=0.3.0", 25 | "github.com/MiracleForest/iListenAttentively-Release": ">=0.10.0" 26 | }, 27 | "assets": [ 28 | { 29 | "type": "zip", 30 | "urls": [ 31 | "https://{{tooth}}/releases/download/v{{version}}/GMLIB-LegacyRemoteCallApi-windows-x64.zip" 32 | ], 33 | "placements": [ 34 | { 35 | "type": "dir", 36 | "src": "GMLIB-LegacyRemoteCallApi", 37 | "dest": "plugins/GMLIB-LegacyRemoteCallApi/" 38 | } 39 | ] 40 | } 41 | ], 42 | "remove_files": [ 43 | "plugins/GMLIB-LegacyRemoteCallApi" 44 | ] 45 | } 46 | ] 47 | } -------------------------------------------------------------------------------- /lib/BEPlaceholderAPI-JS.d.ts: -------------------------------------------------------------------------------- 1 | export class PAPI { 2 | /** 注册一个玩家PAPI变量 */ 3 | static registerPlayerPlaceholder( 4 | /** PAPI调用函数 */ 5 | func: ( 6 | /** 玩家对象 */ 7 | player: Player, 8 | /** 变量参数 */ 9 | param: null | object. 10 | ) => string, 11 | /** 插件名字 */ 12 | pluginsName: string, 13 | /** PAPI变量 */ 14 | PAPIName: string 15 | ): void; 16 | 17 | /** 注册一个服务器PAPI变量 */ 18 | static registerServerPlaceholder( 19 | /** PAPI调用函数 */ 20 | func: ( 21 | /** 变量参数 */ 22 | param: null | object. 23 | ) => string, 24 | /** 插件名字 */ 25 | pluginsName: string, 26 | /** PAPI变量 */ 27 | PAPIName: string 28 | ): void; 29 | 30 | /** 注册一个静态PAPI变量 */ 31 | static registerStaticPlaceholder( 32 | /** PAPI调用函数 */ 33 | func: () => string, 34 | /** 插件名字 */ 35 | pluginsName: string, 36 | /** PAPI变量 */ 37 | PAPIName: string, 38 | /** 更新时间 */ 39 | UpdateInterval: number 40 | ): void; 41 | 42 | /** 获取一个服务器变量的值 */ 43 | static getValue( 44 | /** PAPI名 */ 45 | key: string 46 | ): string; 47 | 48 | /** 获取一个玩家变量的值 */ 49 | static getValueByPlayer( 50 | /** PAPI名 */ 51 | key: string, 52 | /** 玩家对象 */ 53 | pl: Player 54 | ): string; 55 | 56 | /** 翻译带PAPI变量的字符串 */ 57 | static translateString( 58 | /** 要翻译的字符串 */ 59 | str: string, 60 | /** 玩家对象 */ 61 | pl: Player | undefined 62 | ): string; 63 | 64 | /** 注销一个PAPI变量 */ 65 | static unRegisterPlaceholder( 66 | /** PAPI名 */ 67 | str: string 68 | ): boolean; 69 | 70 | /** 获取所有已注册的PAPI变量 */ 71 | static getAllPAPI(): string[]; 72 | } 73 | -------------------------------------------------------------------------------- /src/Global.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // clang-format off 3 | #pragma warning(push) 4 | #pragma warning(disable : 4996) 5 | #pragma include_alias("mc/world/item/HumanoidArmorItem.h", "modapi/item/types/mc/HumanoidArmorItem.h") 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | using namespace gmlib; 15 | using namespace gmlib::ui; 16 | using namespace gmlib::i18n; 17 | using namespace gmlib::memory; 18 | using namespace modapi; 19 | #pragma warning(pop) 20 | // clang-format on 21 | 22 | #define PLUGIN_NAME fmt::format(fg(fmt::color::light_green), "GMLIB-LRCA") 23 | 24 | #define LIB_VERSION_MAJOR 1 25 | #define LIB_VERSION_MINOR 7 26 | #define LIB_VERSION_PATCH 1 27 | #define LIB_VERSION_PRERELEASE std::nullopt 28 | 29 | #ifdef LIB_VERSION_PRERELEASE 30 | #define LIB_VERSION ll::data::Version(LIB_VERSION_MAJOR, LIB_VERSION_MINOR, LIB_VERSION_PATCH, LIB_VERSION_PRERELEASE) 31 | #else 32 | #define LIB_VERSION ll::data::Version(LIB_VERSION_MAJOR, LIB_VERSION_MINOR, LIB_VERSION_PATCH) 33 | #endif 34 | 35 | extern void Export_Legacy_GMLib_ModAPI(); 36 | extern void Export_Legacy_GMLib_ServerAPI(); 37 | extern void Export_Compatibility_API(); 38 | extern void ExportPAPI(); 39 | extern void Export_Event_API(); 40 | extern void Export_BinaryStream_API(); 41 | extern ll::thread::ThreadPoolExecutor const& getThreadPoolExecutor(); 42 | extern ll::io::Logger& getLogger(); 43 | // extern void Export_Form_API(); 44 | 45 | 46 | template <> 47 | struct fmt::formatter : fmt::formatter { 48 | template 49 | auto format(ActorUniqueID const& t, FormatContext& ctx) const { 50 | return formatter::format(t.rawID, ctx); 51 | } 52 | }; 53 | template <> 54 | struct fmt::formatter : fmt::formatter { 55 | template 56 | auto format(mce::UUID const& t, FormatContext& ctx) const { 57 | return formatter::format(t.asString(), ctx); 58 | } 59 | }; -------------------------------------------------------------------------------- /lib/PlaceholderAPI.js: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | const getPluginName = () => { 4 | if (getPluginName.PluginNameCache) return getPluginName.PluginNameCache; 5 | 6 | return getPluginName.PluginNameCache = (() => { 7 | if (ll.getCurrentPluginInfo) return ll.getCurrentPluginInfo().name; 8 | 9 | const error = new Error("getPluginName"); 10 | switch (ll.scriptEngineVersion) { 11 | case "QuickJS": { 12 | if (!error.stack) break; 13 | const /** @type {string} */ line = error.stack.trim().split("\n").pop().trim(); 14 | if (line.includes("")) { 15 | return line.slice( 16 | line.indexOf("(") + 1, 17 | line.indexOf("\\") 18 | ); 19 | } 20 | if (line.includes("")) { 21 | return line.slice( 22 | line.indexOf("/", line.indexOf("/") + 1) + 1, 23 | line.indexOf("\\") 24 | ); 25 | } 26 | break; 27 | } 28 | case "V8 12.4.254.21-node.21": { 29 | try { 30 | const selfFileName = require('path').basename(__filename); 31 | const pluginDirectory = Object.entries( 32 | require('module')._pathCache 33 | ).find( 34 | ([key, _]) => key.includes(selfFileName) 35 | )[0].split("\u0000")[1]; 36 | const directories = pluginDirectory.split("\\"); 37 | const pluginName = directories[directories.findIndex(value => value === "plugins") + 1].trim(); 38 | if (pluginName) return pluginName; 39 | } catch { } 40 | 41 | if (!error.stack) break; 42 | const /** @type {string} */ line = error.stack.trim().split("\n").pop().trim(); 43 | if (line.includes(".js") && /:\d+:\d+$/.test(line)) { 44 | const directories = line.split("\\"); 45 | const pluginName = directories[directories.findIndex(value => value === "plugins") + 1].trim(); 46 | if (pluginName) return pluginName; 47 | } 48 | break; 49 | } 50 | default: break; 51 | } 52 | return "Unknown"; 53 | })(); 54 | }; 55 | 56 | module.exports = { 57 | translate(value, actor = undefined, language = "") { 58 | return actor instanceof LLSE_Entity 59 | ? ll.imports("PlaceholderAPI", "translateFromActor")(value, actor, language) 60 | : ll.imports("PlaceholderAPI", "translate")(value, language); 61 | }, 62 | registerPlaceholder(placeholder, callback) { 63 | const pluginName = getPluginName(); 64 | ll.exports((...args) => { 65 | if(!args[0].uniqueId) args[0] = undefined; 66 | return callback(...args) ?? ""; 67 | }, pluginName, `Placeholder_${placeholder}`); 68 | ll.imports("PlaceholderAPI", "registerPlaceholder")(placeholder, `Placeholder_${placeholder}`, pluginName); 69 | }, 70 | unregisterPlaceholder(placeholder) { 71 | return ll.imports("PlaceholderAPI", "unregisterPlaceholder")(placeholder); 72 | }, 73 | unregisterPlaceholderFromModName(placeholder) { 74 | return ll.imports("PlaceholderAPI", "unregisterPlaceholderFromModName")(placeholder); 75 | }, 76 | getValue(placeholder, actor = undefined, params = {}, language = "") { 77 | if (actor instanceof LLSE_Player) actor = ll.imports("GMLib_ServerAPI", "PlayerToEntity")(actor); 78 | const result = actor instanceof LLSE_Entity 79 | ? ll.imports("PlaceholderAPI", "getValueFromActor")(placeholder, actor, params, language) 80 | : ll.imports("PlaceholderAPI", "getValue")(placeholder, params, language); 81 | return result !== "" ? result : undefined; 82 | } 83 | }; -------------------------------------------------------------------------------- /src/LegacyServerApi.cpp: -------------------------------------------------------------------------------- 1 | #include "Global.h" 2 | 3 | void Export_Legacy_GMLib_ServerAPI() { 4 | RemoteCall::exportAs("GMLib_ServerAPI", "setEducationFeatureEnabled", []() -> void { 5 | getLogger().error("GMLib_ServerAPI::setEducationFeatureEnabled is not implemented"); 6 | }); 7 | RemoteCall::exportAs("GMLib_ServerAPI", "registerAbilityCommand", []() -> void { 8 | getLogger().error("GMLib_ServerAPI::registerAbilityCommand is not implemented"); 9 | }); 10 | RemoteCall::exportAs("GMLib_ServerAPI", "setEnableAchievement", []() -> void { 11 | getLogger().error("GMLib_ServerAPI::setEnableAchievement is not implemented"); 12 | }); 13 | RemoteCall::exportAs("GMLib_ServerAPI", "setForceTrustSkins", []() -> void { 14 | getLogger().error("GMLib_ServerAPI::setForceTrustSkins is not implemented"); 15 | }); 16 | RemoteCall::exportAs("GMLib_ServerAPI", "enableCoResourcePack", []() -> void { 17 | getLogger().error("GMLib_ServerAPI::enableCoResourcePack is not implemented"); 18 | }); 19 | RemoteCall::exportAs("GMLib_ServerAPI", "getLevelName", []() -> std::string { 20 | return GMLevel::getInstance().transform( 21 | [](GMLevel& level) -> std::string { return level.getLevelName(); } 22 | ).value_or(""); 23 | }); 24 | RemoteCall::exportAs("GMLib_ServerAPI", "setLevelName", [](std::string const& name) -> void { 25 | if (auto level = GMLevel::getInstance()) { 26 | level->setLevelName(name); 27 | } 28 | }); 29 | RemoteCall::exportAs("GMLib_ServerAPI", "getLevelSeed", []() -> std::string { 30 | return GMLevel::getInstance() 31 | .transform([](GMLevel& level) -> std::string { return std::to_string(level.getSeed()); }) 32 | .value_or(""); 33 | }); 34 | RemoteCall::exportAs("GMLib_ServerAPI", "setFakeSeed", [](int64_t seed) -> void { 35 | getLogger().error("GMLib_ServerAPI::setFakeSeed is not implemented"); 36 | }); 37 | RemoteCall::exportAs( 38 | "GMLib_ServerAPI", 39 | "spawnEntity", 40 | [](std::pair pos, std::string const& name) -> Actor* { 41 | return GMSpawner::spawnEntity(pos.first, pos.second, name).as_ptr(); 42 | } 43 | ); 44 | RemoteCall::exportAs( 45 | "GMLib_ServerAPI", 46 | "shootProjectile", 47 | [](Actor* owner, std::string const& name, float speed, float offset) -> Actor* { 48 | auto actor = GMSpawner::spawnEntity(owner->getPosition(), owner->getDimensionId(), name); 49 | if (!actor) return nullptr; 50 | ((GMActor*)owner)->setProjectile((GMActor&)*actor, speed, offset); 51 | return actor.as_ptr(); 52 | } 53 | ); 54 | RemoteCall::exportAs( 55 | "GMLib_ServerAPI", 56 | "throwEntity", 57 | [](Actor* owner, Actor* actor, float speed, float offset) -> bool { 58 | auto ac = (GMActor*)owner; 59 | ac->setProjectile((GMActor&)*actor, speed, offset); 60 | return true; 61 | } 62 | ); 63 | RemoteCall::exportAs("GMLib_ServerAPI", "PlayerToEntity", [](Player* player) -> Actor* { return (Actor*)player; }); 64 | RemoteCall::exportAs( 65 | "GMLib_ServerAPI", 66 | "addFakeList", 67 | [](const std::string& name, const std::string& xuid) -> bool { 68 | PlayerListAPI::push_back(name, xuid); 69 | return true; 70 | } 71 | ); 72 | RemoteCall::exportAs("GMLib_ServerAPI", "removeFakeList", [](const std::string& nameOrXuid) -> bool { 73 | PlayerListAPI::erase(nameOrXuid); 74 | return true; 75 | }); 76 | RemoteCall::exportAs("GMLib_ServerAPI", "removeAllFakeList", []() -> void { PlayerListAPI::clear(); }); 77 | RemoteCall::exportAs("GMLib_ServerAPI", "getMaxPlayers", []() -> int { 78 | return GMLevel::getInstance().transform( 79 | [](GMLevel& level) -> int { return level.getMaxPlayerCount(); } 80 | ).value_or(0); 81 | }); 82 | RemoteCall::exportAs("GMLib_ServerAPI", "setMaxPlayers", [&](int count, bool ignoreVanillaLimit) { 83 | if (auto level = GMLevel::getInstance(); level) { 84 | level->setMaxPlayerCount(count, ignoreVanillaLimit); 85 | } 86 | }); 87 | } 88 | -------------------------------------------------------------------------------- /src/BinaryStreamApi.cpp: -------------------------------------------------------------------------------- 1 | #include "Global.h" 2 | 3 | class LegacyScriptBinaryStreamManager { 4 | private: 5 | int64 mNextBinaryStreamId = 0; 6 | std::unordered_map> mBinaryStream; 7 | 8 | public: 9 | uint getNextId() { return mNextBinaryStreamId++; } 10 | 11 | void cretateBinaryStream(uint id) { mBinaryStream[id] = std::make_shared(); } 12 | 13 | uint64 copyBinaryStream(uint id) { 14 | auto nextId = getNextId(); 15 | cretateBinaryStream(nextId); 16 | if (auto bs = getBinaryStream(nextId); bs != nullptr) { 17 | getBinaryStream(nextId)->mBuffer = getBinaryStream(id)->mBuffer; 18 | } 19 | return nextId; 20 | } 21 | 22 | void removeBinaryStream(uint64 id) { mBinaryStream.erase(id); } 23 | 24 | std::shared_ptr getBinaryStream(uint64 id) { 25 | return mBinaryStream.contains(id) ? mBinaryStream.at(id) : nullptr; 26 | } 27 | 28 | public: 29 | static LegacyScriptBinaryStreamManager& getInstance() { 30 | static std::unique_ptr instance; 31 | if (!instance) instance = std::make_unique(); 32 | return *instance; 33 | } 34 | }; 35 | 36 | #define BinaryStreamManager LegacyScriptBinaryStreamManager::getInstance() 37 | #define EXPORTAPI(funcName, type, fuc) \ 38 | RemoteCall::exportAs("GMLIB_BinaryStream_API", funcName, [](uint64 id, type value) -> void { \ 39 | auto bs = BinaryStreamManager.getBinaryStream(id); \ 40 | if (bs != nullptr) fuc; \ 41 | }) 42 | 43 | template 44 | struct Info; 45 | template 46 | struct Info { 47 | using ArgT = A; 48 | }; 49 | #define EXPORTAPI2(T) EXPORTAPI(#T, Info::ArgT, bs->T(value)) 50 | 51 | void Export_BinaryStream_API() { 52 | RemoteCall::exportAs("GMLIB_BinaryStream_API", "create", []() -> uint64 { 53 | auto id = BinaryStreamManager.getNextId(); 54 | BinaryStreamManager.cretateBinaryStream(id); 55 | return id; 56 | }); 57 | RemoteCall::exportAs("GMLIB_BinaryStream_API", "copy", [](uint64 id) -> uint64 { 58 | return BinaryStreamManager.copyBinaryStream(id); 59 | }); 60 | RemoteCall::exportAs("GMLIB_BinaryStream_API", "reset", [](uint64 id) -> void { 61 | if (BinaryStreamManager.getBinaryStream(id) == nullptr) BinaryStreamManager.cretateBinaryStream(id); 62 | else { 63 | auto bs = BinaryStreamManager.getBinaryStream(id); 64 | bs->mBuffer.clear(); 65 | bs->mReadPointer = 0; 66 | bs->mHasOverflowed = false; 67 | } 68 | }); 69 | RemoteCall::exportAs("GMLIB_BinaryStream_API", "sendTo", [](uint64 id, Player* player) -> void { 70 | if (auto bs = BinaryStreamManager.getBinaryStream(id); bs != nullptr) 71 | bs->sendTo(static_cast(*player)); 72 | }); 73 | RemoteCall::exportAs("GMLIB_BinaryStream_API", "destroy", [](uint64 id) -> void { 74 | BinaryStreamManager.removeBinaryStream(id); 75 | }); 76 | EXPORTAPI("writePacketHeader", int, bs->writePacketHeader((MinecraftPacketIds)value)); 77 | EXPORTAPI("writeUuid", std::string const&, bs->writeUuid(mce::UUID::fromString(value))); 78 | EXPORTAPI("writeItem", ItemStack*, bs->writeNetworkItemStackDescriptor(NetworkItemStackDescriptor(*value))); 79 | EXPORTAPI("writeString", std::string const&, bs->writeString(value)); 80 | EXPORTAPI("writeCompoundTag", CompoundTag*, bs->writeCompoundTag(*value)); 81 | EXPORTAPI("writeUnsignedChar", uchar, bs->writeUnsignedChar(value)); 82 | EXPORTAPI2(writeBool); 83 | EXPORTAPI2(writeByte); 84 | EXPORTAPI2(writeDouble); 85 | EXPORTAPI2(writeFloat); 86 | EXPORTAPI2(writeSignedBigEndianInt); 87 | EXPORTAPI2(writeSignedInt); 88 | EXPORTAPI2(writeSignedInt64); 89 | EXPORTAPI2(writeSignedShort); 90 | EXPORTAPI2(writeUnsignedInt); 91 | EXPORTAPI2(writeUnsignedInt64); 92 | EXPORTAPI2(writeUnsignedShort); 93 | EXPORTAPI2(writeUnsignedVarInt); 94 | EXPORTAPI2(writeUnsignedVarInt64); 95 | EXPORTAPI2(writeVarInt); 96 | EXPORTAPI2(writeVarInt64); 97 | } -------------------------------------------------------------------------------- /lib/BEPlaceholderAPI-JS.js: -------------------------------------------------------------------------------- 1 | const PlaceholderAPI = { 2 | /** 获取一个服务器变量的值 @type {function(string):string} */ 3 | getValueAPI: ll.imports("BEPlaceholderAPI", "GetValue"), 4 | /** 获取一个玩家变量的值 @type {function(string,Player):string} */ 5 | getValueByPlayerAPI: ll.imports("BEPlaceholderAPI", "GetValueWithPlayer"), 6 | /** 注册一个玩家变量 @type {function(string,string,string):boolean} */ 7 | registerPlayerPlaceholderAPI: ll.imports("BEPlaceholderAPI", "registerPlayerPlaceholder"), 8 | /** 注册一个服务器变量 @type {function(string,string,string):boolean} */ 9 | registerServerPlaceholderAPI: ll.imports("BEPlaceholderAPI", "registerServerPlaceholder"), 10 | /** 注册一个静态变量 @type {function(string,string,string,number):boolean} */ 11 | registerStaticPlaceholderAPI: ll.imports("BEPlaceholderAPI", "registerStaticPlaceholder"), 12 | /** 翻译包含PAPI服务器变量的字符串 @type {function(string):string} */ 13 | translateStringAPI: ll.imports("BEPlaceholderAPI", "translateString"), 14 | /** 翻译包含PAPI玩家变量的字符串 @type {function(string,Player):string} */ 15 | translateStringWithPlayerAPI: ll.imports("BEPlaceholderAPI", "translateStringWithPlayer"), 16 | /** 注销PAPI变量 @type {function(string):boolean} */ 17 | unRegisterPlaceholderAPI: ll.imports("BEPlaceholderAPI", "unRegisterPlaceholder"), 18 | /** 获取所有已注册的PAPI变量 @type {function():Array.} */ 19 | getAllPAPI: ll.imports("BEPlaceholderAPI", "getAllPAPI") 20 | } 21 | 22 | /** PAPI变量类 */ 23 | class PAPI { 24 | constructor() { 25 | throw new Error("Static class cannot be instantiated"); 26 | } 27 | 28 | /** 29 | * 注册一个玩家PAPI变量 30 | * @param {function} func 变量调用的函数 31 | * @param {string} PluginName 插件名字 32 | * @param {string} PAPIName PAPI变量名 33 | * @returns {boolean} 是否注册成功 34 | */ 35 | static registerPlayerPlaceholder(func, PluginName, PAPIName) { 36 | ll.export(func, PluginName, `Placeholder_${PAPIName}`); 37 | PlaceholderAPI.registerPlayerPlaceholderAPI(PluginName, `Placeholder_${PAPIName}`, PAPIName); 38 | } 39 | 40 | /** 41 | * 注册一个服务器PAPI变量 42 | * @param {function} func 变量调用的函数 43 | * @param {string} PluginName 插件名字 44 | * @param {string} PAPIName PAPI变量名 45 | * @returns {boolean} 是否注册成功 46 | */ 47 | static registerServerPlaceholder(func, PluginName, PAPIName) { 48 | ll.export(func, PluginName, `Placeholder_${PAPIName}`); 49 | PlaceholderAPI.registerServerPlaceholderAPI(PluginName, `Placeholder_${PAPIName}`, PAPIName); 50 | } 51 | 52 | /** 53 | * 注册一个静态PAPI变量 54 | * @param {function} func 变量调用的函数 55 | * @param {string} PluginName 插件名字 56 | * @param {string} PAPIName PAPI变量名 57 | * @param {number} [UpdateInterval=50] 更新间隔 58 | * @returns {boolean} 是否注册成功 59 | */ 60 | static registerStaticPlaceholder(func, PluginName, PAPIName, UpdateInterval = 50) { 61 | ll.export(func, PluginName, `Placeholder_${PAPIName}`); 62 | PlaceholderAPI.registerStaticPlaceholderAPI(PluginName, `Placeholder_${PAPIName}`, PAPIName, UpdateInterval); 63 | } 64 | 65 | /** 66 | * 获取一个服务器变量的值 67 | * @param {string} key PAPI变量名 68 | * @returns {string} 值 69 | */ 70 | static getValue(key) { 71 | return PlaceholderAPI.getValueAPI(key); 72 | } 73 | 74 | /** 75 | * 获取一个玩家变量的值 76 | * @param {string} key PAPI变量名 77 | * @param {Player} pl 玩家对象 78 | * @returns {string} 值 79 | */ 80 | static getValueByPlayer(key, pl) { 81 | return PlaceholderAPI.getValueByPlayerAPI(key, pl); 82 | } 83 | 84 | /** 85 | * 翻译带PAPI变量的字符串 86 | * @param {string} str 字符串 87 | * @param {Player} pl 玩家对象 88 | * @returns {string} 翻译结果 89 | */ 90 | static translateString(str, pl = null) { 91 | if (pl) { 92 | return PlaceholderAPI.translateStringWithPlayerAPI(str, pl); 93 | } 94 | return PlaceholderAPI.translateStringAPI(str); 95 | } 96 | 97 | /** 98 | * 注销一个PAPI变量 99 | * @param {string} str PAPI变量名 100 | * @returns {boolean} 是否注销成功 101 | */ 102 | static unRegisterPlaceholder(str) { 103 | return PlaceholderAPI.unRegisterPlaceholderAPI(str); 104 | } 105 | 106 | /** 107 | * 获取所有已注册的PAPI变量 108 | * @returns {Array.} 已注册的PAPI变量数组 109 | */ 110 | static getAllPAPI() { 111 | return PlaceholderAPI.getAllPAPI(); 112 | } 113 | 114 | } 115 | 116 | module.exports = { 117 | PAPI 118 | }; -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | # Generated from CLion Inspection settings 2 | --- 3 | Checks: '-*, 4 | bugprone-argument-comment, 5 | bugprone-assert-side-effect, 6 | bugprone-bad-signal-to-kill-thread, 7 | bugprone-branch-clone, 8 | bugprone-copy-constructor-init, 9 | bugprone-dangling-handle, 10 | bugprone-dynamic-static-initializers, 11 | bugprone-fold-init-type, 12 | bugprone-forward-declaration-namespace, 13 | bugprone-forwarding-reference-overload, 14 | bugprone-inaccurate-erase, 15 | bugprone-incorrect-roundings, 16 | bugprone-integer-division, 17 | bugprone-lambda-function-name, 18 | bugprone-macro-parentheses, 19 | bugprone-macro-repeated-side-effects, 20 | bugprone-misplaced-operator-in-strlen-in-alloc, 21 | bugprone-misplaced-pointer-arithmetic-in-alloc, 22 | bugprone-misplaced-widening-cast, 23 | bugprone-move-forwarding-reference, 24 | bugprone-multiple-statement-macro, 25 | bugprone-no-escape, 26 | bugprone-not-null-terminated-result, 27 | bugprone-parent-virtual-call, 28 | bugprone-posix-return, 29 | bugprone-reserved-identifier, 30 | bugprone-sizeof-container, 31 | bugprone-sizeof-expression, 32 | bugprone-spuriously-wake-up-functions, 33 | bugprone-string-constructor, 34 | bugprone-string-integer-assignment, 35 | bugprone-string-literal-with-embedded-nul, 36 | bugprone-suspicious-enum-usage, 37 | bugprone-suspicious-include, 38 | bugprone-suspicious-memory-comparison, 39 | bugprone-suspicious-memset-usage, 40 | bugprone-suspicious-missing-comma, 41 | bugprone-suspicious-semicolon, 42 | bugprone-suspicious-string-compare, 43 | bugprone-swapped-arguments, 44 | bugprone-terminating-continue, 45 | bugprone-throw-keyword-missing, 46 | bugprone-too-small-loop-variable, 47 | bugprone-undefined-memory-manipulation, 48 | bugprone-undelegated-constructor, 49 | bugprone-unhandled-self-assignment, 50 | bugprone-unused-raii, 51 | bugprone-unused-return-value, 52 | bugprone-use-after-move, 53 | bugprone-virtual-near-miss, 54 | cert-dcl21-cpp, 55 | cert-dcl58-cpp, 56 | cert-err34-c, 57 | cert-err52-cpp, 58 | cert-err60-cpp, 59 | cert-flp30-c, 60 | cert-msc50-cpp, 61 | cert-msc51-cpp, 62 | cert-str34-c, 63 | cppcoreguidelines-interfaces-global-init, 64 | cppcoreguidelines-narrowing-conversions, 65 | cppcoreguidelines-pro-type-member-init, 66 | cppcoreguidelines-slicing, 67 | google-default-arguments, 68 | google-explicit-constructor, 69 | google-runtime-operator, 70 | hicpp-exception-baseclass, 71 | hicpp-multiway-paths-covered, 72 | misc-misplaced-const, 73 | misc-new-delete-overloads, 74 | misc-non-copyable-objects, 75 | misc-throw-by-value-catch-by-reference, 76 | misc-unconventional-assign-operator, 77 | misc-uniqueptr-reset-release, 78 | modernize-avoid-bind, 79 | modernize-concat-nested-namespaces, 80 | modernize-deprecated-headers, 81 | modernize-deprecated-ios-base-aliases, 82 | modernize-loop-convert, 83 | modernize-make-shared, 84 | modernize-make-unique, 85 | modernize-pass-by-value, 86 | modernize-raw-string-literal, 87 | modernize-redundant-void-arg, 88 | modernize-replace-auto-ptr, 89 | modernize-replace-disallow-copy-and-assign-macro, 90 | modernize-replace-random-shuffle, 91 | modernize-return-braced-init-list, 92 | modernize-shrink-to-fit, 93 | modernize-unary-static-assert, 94 | modernize-use-auto, 95 | modernize-use-bool-literals, 96 | modernize-use-emplace, 97 | modernize-use-equals-default, 98 | modernize-use-equals-delete, 99 | modernize-use-nodiscard, 100 | modernize-use-noexcept, 101 | modernize-use-nullptr, 102 | modernize-use-override, 103 | modernize-use-transparent-functors, 104 | modernize-use-uncaught-exceptions, 105 | mpi-buffer-deref, 106 | mpi-type-mismatch, 107 | openmp-use-default-none, 108 | performance-faster-string-find, 109 | performance-for-range-copy, 110 | performance-implicit-conversion-in-loop, 111 | performance-inefficient-algorithm, 112 | performance-inefficient-string-concatenation, 113 | performance-inefficient-vector-operation, 114 | performance-move-const-arg, 115 | performance-move-constructor-init, 116 | performance-no-automatic-move, 117 | performance-noexcept-move-constructor, 118 | performance-trivially-destructible, 119 | performance-type-promotion-in-math-fn, 120 | performance-unnecessary-copy-initialization, 121 | performance-unnecessary-value-param, 122 | portability-simd-intrinsics, 123 | readability-avoid-const-params-in-decls, 124 | readability-const-return-type, 125 | readability-container-size-empty, 126 | readability-convert-member-functions-to-static, 127 | readability-delete-null-pointer, 128 | readability-deleted-default, 129 | readability-inconsistent-declaration-parameter-name, 130 | readability-make-member-function-const, 131 | readability-misleading-indentation, 132 | readability-misplaced-array-index, 133 | readability-non-const-parameter, 134 | readability-redundant-control-flow, 135 | readability-redundant-declaration, 136 | readability-redundant-function-ptr-dereference, 137 | readability-redundant-smartptr-get, 138 | readability-redundant-string-cstr, 139 | readability-redundant-string-init, 140 | readability-simplify-subscript-expr, 141 | readability-static-accessed-through-instance, 142 | readability-static-definition-in-anonymous-namespace, 143 | readability-string-compare, 144 | readability-uniqueptr-delete-release, 145 | readability-use-anyofallof' 146 | -------------------------------------------------------------------------------- /lib/FormAPI-JS.js: -------------------------------------------------------------------------------- 1 | // // const getNextCallbackId = ll.imports("GMLIB_FormAPI", "getNextFormCallbackId"); 2 | 3 | // class ServerSettingForm { 4 | // constructor() { 5 | // throw new Error("Static class cannot be instantiated"); 6 | // } 7 | 8 | // static getDefaultPriority() { 9 | // return ll.imports("GMLIB_ServerSettingForm", "getDefaultPriority")(); 10 | // } 11 | 12 | // static hasTitle() { 13 | // return ll.imports("GMLIB_ServerSettingForm", "hasTitle")(); 14 | // } 15 | 16 | // static getTitle() { 17 | // return ll.imports("GMLIB_ServerSettingForm", "getTitle")(); 18 | // } 19 | 20 | // static setTitle(title, forceModify = false) { 21 | // return ll.imports("GMLIB_ServerSettingForm", "setTitle")(title, forceModify); 22 | // } 23 | 24 | // static hasIcon() { 25 | // return ll.imports("GMLIB_ServerSettingForm", "hasIcon")(); 26 | // } 27 | 28 | // static getIconData() { 29 | // return hasIcon() ? ll.imports("GMLIB_ServerSettingForm", "getIconData")() : null; 30 | // } 31 | 32 | // static getIconType() { 33 | // return ll.imports("GMLIB_ServerSettingForm", "getIconType")(); 34 | // } 35 | 36 | // static setIcon(data, type = 0, forceModify = false) { 37 | // return ll.imports("GMLIB_ServerSettingForm", "setIcon")(data, type, forceModify); 38 | // } 39 | 40 | // static addLabel( 41 | // text, 42 | // playerDetector = (pl) => { return true; }, 43 | // priority = this.getDefaultPriority() 44 | // ) { 45 | // let detectorId = getNextCallbackId(); 46 | // ll.export(playerDetector, "GMLIB_FORM_CALLBACK", detectorId); 47 | // return ll.imports("GMLIB_ServerSettingForm", "addLabel")(text, detectorId, priority); 48 | // } 49 | 50 | 51 | // static addInput( 52 | // text, 53 | // placeholder, 54 | // defaultVal, 55 | // callback = (pl, input) => { }, 56 | // playerDetector = (pl) => { return true; }, 57 | // priority = this.getDefaultPriority() 58 | // ) { 59 | // let callbackId = getNextCallbackId(); 60 | // ll.export(callback, "GMLIB_FORM_CALLBACK", callbackId); 61 | // let detectorId = getNextCallbackId(); 62 | // ll.export(playerDetector, "GMLIB_FORM_CALLBACK", detectorId); 63 | // return ll.imports("GMLIB_ServerSettingForm", "addInput")(text, placeholder, defaultVal, callbackId, detectorId, priority); 64 | // } 65 | 66 | // static addToggle( 67 | // text, 68 | // defaultVal = false, 69 | // callback = (pl, input) => { }, 70 | // playerDetector = (pl) => { return true; }, 71 | // priority = this.getDefaultPriority() 72 | // ) { 73 | // let callbackId = getNextCallbackId(); 74 | // ll.export(callback, "GMLIB_FORM_CALLBACK", callbackId); 75 | // let detectorId = getNextCallbackId(); 76 | // ll.export(playerDetector, "GMLIB_FORM_CALLBACK", detectorId); 77 | // return ll.imports("GMLIB_ServerSettingForm", "addToggle")(text, defaultVal, callbackId, detectorId, priority); 78 | // } 79 | 80 | // static addDropdown( 81 | // text, 82 | // options, 83 | // defaultVal = 0, 84 | // callback = (pl, input) => { }, 85 | // playerDetector = (pl) => { return true; }, 86 | // priority = this.getDefaultPriority() 87 | // ) { 88 | // let callbackId = getNextCallbackId(); 89 | // ll.export(callback, "GMLIB_FORM_CALLBACK", callbackId); 90 | // let detectorId = getNextCallbackId(); 91 | // ll.export(playerDetector, "GMLIB_FORM_CALLBACK", detectorId); 92 | // return ll.imports("GMLIB_ServerSettingForm", "addDropdown")(text, options, defaultVal, callbackId, detectorId, priority); 93 | // } 94 | 95 | // static addSlider( 96 | // text, 97 | // min, 98 | // max, 99 | // step = 0.0, 100 | // defaultVal = 0.0, 101 | // callback = (pl, input) => { }, 102 | // playerDetector = (pl) => { return true; }, 103 | // priority = this.getDefaultPriority() 104 | // ) { 105 | // let callbackId = getNextCallbackId(); 106 | // ll.export(callback, "GMLIB_FORM_CALLBACK", callbackId); 107 | // let detectorId = getNextCallbackId(); 108 | // ll.export(playerDetector, "GMLIB_FORM_CALLBACK", detectorId); 109 | // return ll.imports("GMLIB_ServerSettingForm", "addSlider")(text, min, max, step, defaultVal, callbackId, detectorId, priority); 110 | // } 111 | 112 | // static addStepSlider( 113 | // text, 114 | // steps, 115 | // defaultVal = 0, 116 | // callback = (pl, input) => { }, 117 | // playerDetector = (pl) => { return true; }, 118 | // priority = this.getDefaultPriority() 119 | // ) { 120 | // let callbackId = getNextCallbackId(); 121 | // ll.export(callback, "GMLIB_FORM_CALLBACK", callbackId); 122 | // let detectorId = getNextCallbackId(); 123 | // ll.export(playerDetector, "GMLIB_FORM_CALLBACK", detectorId); 124 | // return ll.imports("GMLIB_ServerSettingForm", "addStepSlider")(text, steps, defaultVal, callbackId, detectorId, priority); 125 | // } 126 | 127 | // static removeElement(id) { 128 | // return ll.imports("GMLIB_ServerSettingForm", "removeElement")(id); 129 | // } 130 | // } 131 | 132 | // class NpcDialogueForm { 133 | // constructor(npcName, sceneName, dialogue) { 134 | // this.mFormId = ll.imports("GMLIB_NpcDialogueForm", "createForm")(npcName, sceneName, dialogue); 135 | // } 136 | 137 | // addButton(button) { 138 | // return ll.imports("GMLIB_NpcDialogueForm", "addButton")(this.mFormId, button); 139 | // } 140 | 141 | // sendTo(pl, callback = (pl, index, type) => { }, free = true) { 142 | // let callbackId = getNextCallbackId(); 143 | // ll.export(callback, "GMLIB_FORM_CALLBACK", callbackId); 144 | // ll.imports("GMLIB_NpcDialogueForm", "sendTo")(this.mFormId, pl, callbackId); 145 | // if (free) { 146 | // this.destroy(); 147 | // } 148 | // } 149 | 150 | // destroy() { 151 | // ll.imports("GMLIB_NpcDialogueForm", "destroyForm")(this.mFormId); 152 | // } 153 | // } 154 | 155 | // class ChestForm { 156 | // constructor(npcName, sceneName, dialogue) { 157 | // this.mFormId = ll.imports("GMLIB_NpcDialogueForm", "createForm")(npcName, sceneName, dialogue); 158 | // } 159 | 160 | // addButton(button) { 161 | // return ll.imports("GMLIB_NpcDialogueForm", "addButton")(this.mFormId, button); 162 | // } 163 | 164 | // sendTo(pl, free = true) { 165 | // //let callbackId = getNextCallbackId(); 166 | // //ll.export(callback, "GMLIB_FORM_CALLBACK", callbackId); 167 | // //ll.imports("GMLIB_NpcDialogueForm", "sendTo")(this.mFormId, pl, callbackId); 168 | // //if (free) { 169 | // // this.destroy(); 170 | // //} 171 | // } 172 | 173 | // destroy() { 174 | // //ll.imports("GMLIB_NpcDialogueForm", "destroyForm")(this.mFormId); 175 | // } 176 | // } 177 | 178 | // module.exports = { 179 | // ServerSettingForm, 180 | // NpcDialogueForm, 181 | // ChestForm 182 | // }; -------------------------------------------------------------------------------- /src/LegacyModApi.cpp: -------------------------------------------------------------------------------- 1 | #include "Global.h" 2 | 3 | ICustomRecipe::UnlockingRequirement makeRecipeUnlockingKey(std::string const& key) { 4 | if (auto context = magic_enum::enum_cast(key)) { 5 | return ICustomRecipe::UnlockingRequirement(*context); 6 | } 7 | return ICustomRecipe::UnlockingRequirement({ICustomRecipe::Ingredient(key)}); 8 | } 9 | 10 | void Export_Legacy_GMLib_ModAPI() { 11 | // 合成表部分 12 | RemoteCall::exportAs( 13 | "GMLib_ModAPI", 14 | "registerShapelessRecipe", 15 | [](std::string const& recipe_id, 16 | std::vector ingredients, 17 | std::string const& result, 18 | int count, 19 | std::string const& unlock) -> void { 20 | if (!GMLevel::getInstance().has_value()) return; 21 | std::vector types; 22 | for (auto& ing : ingredients) { 23 | types.emplace_back(ICustomRecipe::Ingredient{ing, 1}); 24 | } 25 | CustomRecipeRegistry::getInstance() 26 | .registerShapelessRecipe(recipe_id, types, ItemInstance(result, count), makeRecipeUnlockingKey(unlock)); 27 | } 28 | ); 29 | RemoteCall::exportAs( 30 | "GMLib_ModAPI", 31 | "registerShapedRecipe", 32 | [](std::string const& recipe_id, 33 | std::vector shape, 34 | std::vector ingredients, 35 | std::string const& result, 36 | int count, 37 | std::string const& unlock) -> void { 38 | if (!GMLevel::getInstance().has_value()) return; 39 | ICustomShapedRecipe::ShapedIngredients types; 40 | char index = 'A'; 41 | for (auto& ing : ingredients) { 42 | types.add(std::string(1, index++), ICustomRecipe::Ingredient{ing}); 43 | } 44 | CustomRecipeRegistry::getInstance().registerShapedRecipe( 45 | recipe_id, 46 | shape, 47 | types, 48 | ItemInstance(result, count), 49 | makeRecipeUnlockingKey(unlock) 50 | ); 51 | } 52 | ); 53 | RemoteCall::exportAs( 54 | "GMLib_ModAPI", 55 | "registerFurnaceRecipe", 56 | [](std::string const& recipe_id, 57 | std::string const& input, 58 | std::string const& output, 59 | std::vector tags) -> void { 60 | if (!GMLevel::getInstance().has_value()) return; 61 | CustomRecipeRegistry::getInstance() 62 | .registerFurnaceRecipe(ICustomRecipe::Ingredient{input}, ItemInstance{output}, tags); 63 | } 64 | ); 65 | RemoteCall::exportAs( 66 | "GMLib_ModAPI", 67 | "registerBrewingMixRecipe", 68 | [](std::string const& recipe_id, std::string const& input, std::string const& output, std::string const& reagent 69 | ) -> void { 70 | if (!GMLevel::getInstance().has_value()) return; 71 | CustomRecipeRegistry::getInstance().registerBrewingRecipe( 72 | ICustomRecipe::Ingredient{input}, 73 | ICustomRecipe::Ingredient{reagent}, 74 | ICustomRecipe::Ingredient{output} 75 | ); 76 | } 77 | ); 78 | RemoteCall::exportAs( 79 | "GMLib_ModAPI", 80 | "registerBrewingContainerRecipe", 81 | [](std::string const& recipe_id, std::string const& input, std::string const& output, std::string const& reagent 82 | ) -> void { 83 | if (!GMLevel::getInstance().has_value()) return; 84 | CustomRecipeRegistry::getInstance().registerBrewingRecipe( 85 | ICustomRecipe::Ingredient{input}, 86 | ICustomRecipe::Ingredient{reagent}, 87 | ICustomRecipe::Ingredient{output} 88 | ); 89 | } 90 | ); 91 | RemoteCall::exportAs( 92 | "GMLib_ModAPI", 93 | "registerSmithingTransformRecipe", 94 | [](std::string const& recipe_id, 95 | std::string const& smithing_template, 96 | std::string const& base, 97 | std::string const& addition, 98 | std::string const& result) -> void { 99 | if (!GMLevel::getInstance().has_value()) return; 100 | CustomRecipeRegistry::getInstance().registerSmithingTransformRecipe( 101 | recipe_id, 102 | ICustomRecipe::Ingredient{smithing_template}, 103 | ICustomRecipe::Ingredient{base}, 104 | ICustomRecipe::Ingredient{addition}, 105 | ItemInstance{result} 106 | ); 107 | } 108 | ); 109 | RemoteCall::exportAs( 110 | "GMLib_ModAPI", 111 | "registerSmithingTrimRecipe", 112 | [](std::string const& recipe_id, 113 | std::string const& smithing_template, 114 | std::string const& base, 115 | std::string const& addition) -> void { 116 | if (!GMLevel::getInstance().has_value()) return; 117 | CustomRecipeRegistry::getInstance().registerSmithingTrimRecipe( 118 | recipe_id, 119 | ICustomRecipe::Ingredient{smithing_template}, 120 | ICustomRecipe::Ingredient{base}, 121 | ICustomRecipe::Ingredient{addition} 122 | ); 123 | } 124 | ); 125 | RemoteCall::exportAs( 126 | "GMLib_ModAPI", 127 | "registerStoneCutterRecipe", 128 | [](std::string const& recipe_id, 129 | std::string const& input, 130 | int input_data, 131 | std::string const& output, 132 | int output_data, 133 | int output_count) -> void { 134 | if (!GMLevel::getInstance().has_value()) return; 135 | CustomRecipeRegistry::getInstance().registerStoneCutterRecipe( 136 | recipe_id, 137 | ICustomRecipe::Ingredient{input, 1, input_data}, 138 | {output, output_count, output_data} 139 | ); 140 | } 141 | ); 142 | // 错误方块清理 143 | RemoteCall::exportAs("GMLib_ModAPI", "setUnknownBlockCleaner", []() -> void { 144 | getLogger().error("setUnknownBlockCleaner is not implemented"); 145 | }); 146 | // 实验性 147 | RemoteCall::exportAs("GMLib_ModAPI", "registerExperimentsRequire", [](int experiment_id) -> void { 148 | GMLevel::getInstance().and_then([&](GMLevel& level) { 149 | level.setExperimentEnabled((AllExperiments)experiment_id); 150 | return true; 151 | }); 152 | }); 153 | RemoteCall::exportAs("GMLib_ModAPI", "setExperimentEnabled", [](int experiment_id, bool value) -> void { 154 | GMLevel::getInstance().and_then([&](GMLevel& level) { 155 | level.setExperimentEnabled((AllExperiments)experiment_id, value); 156 | return true; 157 | }); 158 | }); 159 | RemoteCall::exportAs("GMLib_ModAPI", "getExperimentEnabled", [](int experiment_id) -> bool { 160 | return GMLevel::getInstance() 161 | .transform([&](GMLevel& level) { return level.getExperimentEnabled((AllExperiments)experiment_id); }) 162 | .value_or(false); 163 | }); 164 | RemoteCall::exportAs("GMLib_ModAPI", "setFixI18nEnabled", []() -> void {}); 165 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. -------------------------------------------------------------------------------- /lib/EventAPI-JS.js: -------------------------------------------------------------------------------- 1 | const getPluginName = () => { 2 | if (getPluginName.PluginNameCache) return getPluginName.PluginNameCache; 3 | 4 | return getPluginName.PluginNameCache = (() => { 5 | if (ll.getCurrentPluginInfo) return ll.getCurrentPluginInfo().name; 6 | 7 | const error = new Error("getPluginName"); 8 | switch (ll.scriptEngineVersion) { 9 | case "QuickJS": { 10 | if (!error.stack) break; 11 | const /** @type {string} */ line = error.stack.trim().split("\n").pop().trim(); 12 | if (line.includes("")) { 13 | return line.slice( 14 | line.indexOf("(") + 1, 15 | line.indexOf("\\") 16 | ); 17 | } 18 | if (line.includes("")) { 19 | return line.slice( 20 | line.indexOf("/", line.indexOf("/") + 1) + 1, 21 | line.indexOf("\\") 22 | ); 23 | } 24 | break; 25 | } 26 | case "V8 12.4.254.21-node.21": { 27 | try { 28 | const selfFileName = require('path').basename(__filename); 29 | const pluginDirectory = Object.entries( 30 | require('module')._pathCache 31 | ).find( 32 | ([key, _]) => key.includes(selfFileName) 33 | )[0].split("\u0000")[1]; 34 | const directories = pluginDirectory.split("\\"); 35 | const pluginName = directories[directories.findIndex(value => value === "plugins") + 1].trim(); 36 | if (pluginName) return pluginName; 37 | } catch { } 38 | 39 | if (!error.stack) break; 40 | const /** @type {string} */ line = error.stack.trim().split("\n").pop().trim(); 41 | if (line.includes(".js") && /:\d+:\d+$/.test(line)) { 42 | const directories = line.split("\\"); 43 | const pluginName = directories[directories.findIndex(value => value === "plugins") + 1].trim(); 44 | if (pluginName) return pluginName; 45 | } 46 | break; 47 | } 48 | default: break; 49 | } 50 | return "Unknown"; 51 | })(); 52 | }; 53 | 54 | module.exports = { 55 | Event: { 56 | /** 57 | * 事件订阅记录 58 | * 例如: {事件名: [事件ID, ...], ...} 59 | * @type {Object.} 60 | */ 61 | mEventData: {}, 62 | /** 63 | * 事件异常处理回调 64 | * @param {Error} error 65 | * @param {string} eventName 66 | * @param {number} eventID 67 | * @param {string} pluginName 68 | * @returns {void} 69 | */ 70 | mErrorHanlerCallback: (error, eventName, eventID, pluginName) => { 71 | logger.error(`Info: ${pluginName}-${eventName}-${eventID} Exception: ${error.message}\n${error.stack}`); 72 | }, 73 | 74 | /** 75 | * 监听事件(兼容旧版) 76 | * @param {string} eventName 77 | * @param {function} callback 78 | * @param {boolean} 79 | */ 80 | listen: function (eventName, callback) { 81 | try { 82 | if (typeof callback !== "function") return false; 83 | const eventReflection = { 84 | onServerStopping: "ll::ServerStoppingEvent", 85 | onClientLogin: "gmlib::ClientLoginAfterEvent", 86 | onWeatherChange: "gmlib::WeatherUpdateBeforeEvent", 87 | onMobPick: "gmlib::MobPickupItemBeforeEvent", 88 | onItemTrySpawn: "gmlib::ItemActorSpawnBeforeEvent", 89 | onItemSpawned: "gmlib::ItemActorSpawnAfterEvent", 90 | onEntityTryChangeDim: "gmlib::ActorChangeDimensionBeforeEvent", 91 | onLeaveBed: "gmlib::PlayerStopSleepBeforeEvent", 92 | onDeathMessage: "gmlib::DeathMessageAfterEvent", 93 | onMobHurted: "gmlib::MobHurtAfterEvent", 94 | onEndermanTake: "gmlib::EndermanTakeBlockBeforeEvent", 95 | onEntityChangeDim: "gmlib::ActorChangeDimensionAfterEvent", 96 | onDragonRespawn: "gmlib::DragonRespawnBeforeEvent", 97 | onProjectileTryCreate: "gmlib::ProjectileCreateBeforeEvent", 98 | onProjectileCreate: "gmlib::ProjectileCreateAfterEvent", 99 | onSpawnWanderingTrader: "gmlib::SpawnWanderingTraderBeforeEvent", 100 | onHandleRequestAction: "gmlib::HandleRequestActionBeforeEvent", 101 | onSendContainerClosePacket: "gmlib::ContainerClosePacketSendAfterEvent" 102 | }; 103 | this.emplaceListener(eventReflection[eventName] ?? eventName, event => { 104 | const result = callback(...event.params); 105 | if (typeof (result) === "boolean" && !result) event.cancel(); 106 | }); 107 | return true; 108 | } catch { } 109 | return false; 110 | }, 111 | 112 | /** 113 | * 订阅事件 114 | * @param {string} eventName 115 | * @param {function} callback 116 | * @param {number?} priority 117 | * @param {string?} pluginName 118 | * @returns {number} 119 | */ 120 | emplaceListener: function (eventName, callback, priority = this.EventPriority.Normal, pluginName = getPluginName()) { 121 | if (typeof callback !== "function") throw new Error("callback must be a function!"); 122 | const /** @type {number} */ eventId = ll.imports("GMLIB_Event_API", "emplaceListener")(pluginName, eventName, priority); 123 | if (eventId === -1) throw new Error(`Event ${eventName} creation failed!`); 124 | ll.exports((...data) => { 125 | let /** @type {boolean} */ result = typeof (data.slice(-1)[0]) === "boolean" ? data.pop() : false; 126 | try { 127 | callback({ 128 | params: data, 129 | cancel: () => result = true, 130 | setCancelled: (/** @type {boolean} */value) => { result = value; }, 131 | isCancelled: () => result, 132 | getId: () => eventId, 133 | getEventType: () => eventName 134 | }); 135 | } catch (error) { 136 | try { 137 | this.mErrorHanlerCallback(error, eventName, eventId, pluginName); 138 | } catch { } 139 | } 140 | return result; 141 | }, pluginName, eventName + "_" + eventId); 142 | (this.mEventData[eventName] ??= []).push(eventId); 143 | return eventId; 144 | }, 145 | 146 | /** 147 | * 取消事件订阅 148 | * @param {number} eventId 149 | * @param {boolean} 150 | */ 151 | removeListener: function (eventId) { 152 | const result = ll.imports("GMLIB_Event_API", "removeListener")(eventId); 153 | if (result) { 154 | for (let [eventName, eventIds] of Object.entries(this.mEventData)) { 155 | this.mEventData[eventName] = eventIds.filter(id => id !== eventId); 156 | if (this.mEventData[eventName].length === 0) delete this.mEventData[eventName]; 157 | } 158 | } 159 | return result; 160 | }, 161 | 162 | /** 163 | * 判断事件订阅是否存在 164 | * @param {number} eventId 165 | * @returns {boolean} 166 | */ 167 | hasListener: function (eventId) { 168 | return ll.imports("GMLIB_Event_API", "hasListener")(eventId); 169 | }, 170 | 171 | /** 172 | * 获取订阅事件优先级 173 | * @param {number} eventId 174 | * @returns {number?} 175 | */ 176 | getListenerPriority: function (eventId) { 177 | const priority = ll.imports("GMLIB_Event_API", "getListenerPriority")(eventId); 178 | return priority === -1 ? undefined : priority; 179 | }, 180 | 181 | /** 182 | * 获取订阅事件列表 183 | * @param {string | undefined} eventName 184 | * @returns {number[] | Object.} 185 | */ 186 | getListener: function (eventName) { 187 | return eventName === undefined ? this.mEventData : this.mEventData[eventName] ?? []; 188 | }, 189 | 190 | /** 191 | * 设置异常处理回调 192 | * @param {function(Error, string, number, string): void} callback 193 | * @returns {boolean} 194 | */ 195 | setErrorHanlerCallback: function (callback) { 196 | if (callback === undefined || typeof callback !== "function") return false; 197 | this.mErrorHanlerCallback = callback; 198 | return true; 199 | }, 200 | 201 | /** 202 | * 事件优先级 203 | */ 204 | EventPriority: { 205 | Highest: 0, 206 | High: 100, 207 | Normal: 200, 208 | Low: 300, 209 | Lowest: 400 210 | } 211 | } 212 | }; -------------------------------------------------------------------------------- /src/PlaceholderApi.cpp: -------------------------------------------------------------------------------- 1 | #include "Global.h" 2 | #include 3 | 4 | namespace PAPIRemoteCall { 5 | std::string GetValue(std::string const& from) { 6 | return PlaceholderAPI::getInstance().getValue(from, std::nullopt).value_or(""); 7 | } 8 | 9 | std::string GetValueWithPlayer(std::string const& key, Player* player) { 10 | return PlaceholderAPI::getInstance().getValue(key, (GMActor*)player).value_or(""); 11 | } 12 | 13 | void registerPlayerPlaceholder( 14 | std::string const& PluginName, 15 | std::string const& FuncName, 16 | std::string const& PAPIName 17 | ) { 18 | if (!RemoteCall::hasFunc(PluginName, FuncName)) return; 19 | auto func = [=]() -> void { 20 | PlaceholderAPI::getInstance().unregisterPlaceholder(PAPIName); 21 | std::weak_ptr mod = ll::mod::ModManagerRegistry::getInstance().getMod(PluginName); 22 | if (mod.expired()) return; 23 | PlaceholderAPI::getInstance().registerPlaceholder( 24 | PAPIName, 25 | [Call = RemoteCall::importAs)>( 26 | PluginName, 27 | FuncName 28 | )](optional_ref actor, ll::SmallStringMap const& params, auto&&... 29 | ) -> std::optional { 30 | if (actor.has_value() && ((Actor*)actor.as_ptr())->isPlayer()) { 31 | std::unordered_map paramMap; 32 | for (auto& [key, val] : params) { 33 | paramMap[key] = val; 34 | } 35 | return Call((Player*)actor.as_ptr(), paramMap); 36 | } 37 | return std::nullopt; 38 | }, 39 | false, 40 | mod 41 | ); 42 | }; 43 | if (ll::mod::ModManagerRegistry::getInstance().hasMod(PluginName)) { 44 | func(); 45 | } else { 46 | getThreadPoolExecutor().execute(func); 47 | } 48 | } 49 | 50 | void registerServerPlaceholder( 51 | std::string const& PluginName, 52 | std::string const& FuncName, 53 | std::string const& PAPIName 54 | ) { 55 | if (!RemoteCall::hasFunc(PluginName, FuncName)) return; 56 | auto func = [=]() -> void { 57 | PlaceholderAPI::getInstance().unregisterPlaceholder(PAPIName); 58 | std::weak_ptr mod = ll::mod::ModManagerRegistry::getInstance().getMod(PluginName); 59 | if (mod.expired()) return; 60 | PlaceholderAPI::getInstance().registerPlaceholder( 61 | PAPIName, 62 | [Call = RemoteCall::importAs)>( 63 | PluginName, 64 | FuncName 65 | )](auto, ll::SmallStringMap const& params, auto&&...) -> std::optional { 66 | std::unordered_map paramMap; 67 | for (auto& [key, val] : params) { 68 | paramMap[key] = val; 69 | } 70 | return Call(paramMap); 71 | }, 72 | false, 73 | mod 74 | ); 75 | }; 76 | if (ll::mod::ModManagerRegistry::getInstance().hasMod(PluginName)) { 77 | func(); 78 | } else { 79 | getThreadPoolExecutor().execute(func); 80 | } 81 | } 82 | 83 | void registerStaticPlaceholder( 84 | std::string const& PluginName, 85 | std::string const& FuncName, 86 | std::string const& PAPIName, 87 | int num 88 | ) { 89 | if (!RemoteCall::hasFunc(PluginName, FuncName)) return; 90 | auto func = [=]() -> void { 91 | PlaceholderAPI::getInstance().unregisterPlaceholder(PAPIName); 92 | std::weak_ptr mod = ll::mod::ModManagerRegistry::getInstance().getMod(PluginName); 93 | if (mod.expired()) return; 94 | PlaceholderAPI::getInstance().registerPlaceholder( 95 | PAPIName, 96 | [Call = RemoteCall::importAs(PluginName, FuncName)](auto&&... 97 | ) -> std::optional { return Call(); }, 98 | false, 99 | mod 100 | ); 101 | }; 102 | if (ll::mod::ModManagerRegistry::getInstance().hasMod(PluginName)) { 103 | func(); 104 | } else { 105 | getThreadPoolExecutor().execute(func); 106 | } 107 | } 108 | 109 | std::string translateStringWithPlayer(std::string const& str, Player* pl) { 110 | return PlaceholderAPI::getInstance().translate(str, (GMActor*)pl); 111 | } 112 | 113 | std::string translateString(std::string const& str) { 114 | return PlaceholderAPI::getInstance().translate(str, std::nullopt); 115 | } 116 | 117 | bool unRegisterPlaceholder(std::string const& str) { return PlaceholderAPI::getInstance().unregisterPlaceholder(str); } 118 | 119 | std::vector getAllPAPI() { 120 | std::vector result; 121 | for (auto& papi : PlaceholderAPI::getInstance().getAllPlaceholderData()) { 122 | result.push_back(papi.first); 123 | } 124 | return result; 125 | } 126 | 127 | } // namespace PAPIRemoteCall 128 | 129 | namespace NewPapiRemoteCall { 130 | std::string translate(std::string const& value, std::string const& language) { 131 | return PlaceholderAPI::getInstance().translate(value, std::nullopt, language); 132 | } 133 | std::string translateFromActor(std::string const& value, Actor* actor, std::string const& language) { 134 | return PlaceholderAPI::getInstance().translate(value, (GMActor*)actor, language); 135 | } 136 | void registerPlaceholder(std::string const& placeholder, std::string const& funcName, std::string const& pluginName) { 137 | if (!RemoteCall::hasFunc(pluginName, funcName)) return; 138 | auto func = [=]() -> void { 139 | if (std::weak_ptr mod = ll::mod::ModManagerRegistry::getInstance().getMod(pluginName); !mod.expired()) { 140 | PlaceholderAPI::getInstance().unregisterPlaceholder(placeholder); 141 | PlaceholderAPI::getInstance().registerPlaceholder( 142 | placeholder, 143 | [Call = RemoteCall::importAs< 144 | std::string(Actor*, std::unordered_map, std::string)>( 145 | pluginName, 146 | funcName 147 | )](optional_ref actor, ll::SmallStringMap const& params, std::string const& language 148 | ) -> std::optional { 149 | std::unordered_map paramMap; 150 | for (auto& [key, val] : params) { 151 | paramMap[key] = val; 152 | } 153 | auto result = Call((Actor*)actor.as_ptr(), paramMap, language); 154 | return result == "" ? std::nullopt : std::optional(result); 155 | }, 156 | false, 157 | mod 158 | ); 159 | } 160 | }; 161 | if (ll::mod::ModManagerRegistry::getInstance().hasMod(pluginName)) { 162 | func(); 163 | } else { 164 | getThreadPoolExecutor().execute(func); 165 | } 166 | } 167 | bool unregisterPlaceholder(std::string const& placeholder) { 168 | return PlaceholderAPI::getInstance().unregisterPlaceholder(placeholder); 169 | } 170 | bool unregisterPlaceholderFromModName(std::string const& pluginName) { 171 | std::weak_ptr plugin = ll::mod::ModManagerRegistry::getInstance().getMod(pluginName); 172 | if (plugin.expired()) return false; 173 | return PlaceholderAPI::getInstance().unregisterPlaceholder(plugin); 174 | } 175 | std::string getValue( 176 | std::string const& placeholder, 177 | std::unordered_map params, 178 | std::string const& language 179 | ) { 180 | ll::SmallStringMap paramMap; 181 | for (auto& [key, val] : params) { 182 | paramMap[key] = val; 183 | } 184 | return PlaceholderAPI::getInstance() 185 | .getValue(placeholder, std::nullopt, paramMap, language) 186 | .value_or(""); 187 | } 188 | std::string getValueFromActor( 189 | std::string const& placeholder, 190 | Actor* actor, 191 | std::unordered_map params, 192 | std::string const& language 193 | ) { 194 | ll::SmallStringMap paramMap; 195 | for (auto& [key, val] : params) { 196 | paramMap[key] = val; 197 | } 198 | return PlaceholderAPI::getInstance() 199 | .getValue(placeholder, (GMActor*)actor, paramMap, language) 200 | .value_or(""); 201 | } 202 | } // namespace NewPapiRemoteCall 203 | 204 | #define EXPORTAPI(T) \ 205 | RemoteCall::exportAs("BEPlaceholderAPI", ll::utils::string_utils::replaceAll(#T, "PAPIRemoteCall::", ""), T); 206 | 207 | #define EXPORTAPI2(T) RemoteCall::exportAs("PlaceholderAPI", #T, NewPapiRemoteCall::T); 208 | 209 | void ExportPAPI() { 210 | EXPORTAPI(PAPIRemoteCall::registerPlayerPlaceholder); 211 | EXPORTAPI(PAPIRemoteCall::registerServerPlaceholder); 212 | EXPORTAPI(PAPIRemoteCall::registerStaticPlaceholder); 213 | EXPORTAPI(PAPIRemoteCall::GetValue); 214 | EXPORTAPI(PAPIRemoteCall::GetValueWithPlayer); 215 | EXPORTAPI(PAPIRemoteCall::translateString); 216 | EXPORTAPI(PAPIRemoteCall::translateStringWithPlayer); 217 | EXPORTAPI(PAPIRemoteCall::unRegisterPlaceholder); 218 | EXPORTAPI(PAPIRemoteCall::getAllPAPI); 219 | 220 | EXPORTAPI2(translate); 221 | EXPORTAPI2(translateFromActor); 222 | EXPORTAPI2(registerPlaceholder); 223 | EXPORTAPI2(unregisterPlaceholder); 224 | EXPORTAPI2(unregisterPlaceholderFromModName); 225 | EXPORTAPI2(getValue); 226 | EXPORTAPI2(getValueFromActor); 227 | } -------------------------------------------------------------------------------- /src/FormAPI.cpp: -------------------------------------------------------------------------------- 1 | // #include "Global.h" 2 | 3 | // using namespace ll::hash_utils; 4 | 5 | // class LegacyScriptFormManager { 6 | // private: 7 | // int64 mNextFormCallbackId = 0; 8 | // int64 mNextFormId = 0; 9 | // std::unordered_map> mNpcDialogueForms; 10 | // // std::unordered_map> mChestForms; 11 | 12 | // public: 13 | // // std::string getNextFormCallbackId() { 14 | // // return "GMLIB_FormApi_" + std::to_string(mNextFormCallbackId++); 15 | // // } 16 | 17 | // int64 getNextFormId() { 18 | // mNextFormId++; 19 | // return mNextFormId; 20 | // } 21 | 22 | // int64 createNpcDialogueForm(std::string const& npcName, std::string const& sceneName, std::string const& dialogue) { 23 | // auto formId = LegacyScriptFormManager::getInstance().getNextFormId(); 24 | // auto formPtr = std::make_unique(npcName, sceneName, dialogue); 25 | // mNpcDialogueForms[formId] = std::move(formPtr); 26 | // return formId; 27 | // } 28 | 29 | // bool destroyNpcDialogueForm(int64 formId) { 30 | // if (mNpcDialogueForms.contains(formId)) { 31 | // mNpcDialogueForms.erase(formId); 32 | // return true; 33 | // } 34 | // return false; 35 | // } 36 | 37 | // optional_ref getNpcDialogueForm(int64 formId) { 38 | // if (mNpcDialogueForms.contains(formId)) { 39 | // return mNpcDialogueForms[formId].get(); 40 | // } 41 | // return {}; 42 | // } 43 | 44 | // /* 45 | // int64 createChestForm(std::string const& npcName, std::string const& sceneName, std::string const& dialogue) { 46 | // auto formId = LegacyScriptFormManager::getInstance().getNextFormId(); 47 | // auto formPtr = std::make_unique(npcName, sceneName, dialogue); 48 | // mChestForms[formId] = std::move(formPtr); 49 | // return formId; 50 | // } 51 | 52 | // bool destroyChestForm(int64 formId) { 53 | // if (mChestForms.contains(formId)) { 54 | // mChestForms.erase(formId); 55 | // return true; 56 | // } 57 | // return false; 58 | // } 59 | 60 | // optional_ref getChestForm(int64 formId) { 61 | // if (mChestForms.contains(formId)) { 62 | // return mChestForms[formId].get(); 63 | // } 64 | // return {}; 65 | // } 66 | 67 | // */ 68 | // public: 69 | // static LegacyScriptFormManager& getInstance() { 70 | // static std::unique_ptr instance; 71 | // if (!instance) { 72 | // instance = std::make_unique(); 73 | // } 74 | // return *instance; 75 | // } 76 | // }; 77 | 78 | // #define PLAYER_DETECROR \ 79 | // [detectorId, result](::Player& pl) -> bool { \ 80 | // try { \ 81 | // if (RemoteCall::hasFunc("GMLIB_FORM_CALLBACK", detectorId)) { \ 82 | // auto const& detector = RemoteCall::importAs("GMLIB_FORM_CALLBACK", detectorId); \ 83 | // return detector(&pl); \ 84 | // } else { \ 85 | // gmlib::form::ServerSettingForm::removeElement(result); \ 86 | // } \ 87 | // } catch (...) {} \ 88 | // return false; \ 89 | // } 90 | 91 | // #define CALLBACK_TYPE(type) \ 92 | // [callbackId, result](Player& pl, type data) { \ 93 | // try { \ 94 | // if (RemoteCall::hasFunc("GMLIB_FORM_CALLBACK", callbackId)) { \ 95 | // auto const& callback = RemoteCall::importAs("GMLIB_FORM_CALLBACK", callbackId); \ 96 | // callback(&pl, data); \ 97 | // } else { \ 98 | // gmlib::form::ServerSettingForm::removeElement(result); \ 99 | // } \ 100 | // } catch (...) {} \ 101 | // } 102 | 103 | // #define CALLBACK_TYPE_NORMAL \ 104 | // [callbackId](::Player& pl) { \ 105 | // try { \ 106 | // if (RemoteCall::hasFunc("GMLIB_FORM_CALLBACK", callbackId)) { \ 107 | // auto const& callback = RemoteCall::importAs("GMLIB_FORM_CALLBACK", callbackId); \ 108 | // callback(&pl); \ 109 | // } \ 110 | // } catch (...) {} \ 111 | // } 112 | 113 | 114 | // void Export_Form_API() { 115 | // //////////////////////////////// Form Manager ///////////////////////////////// 116 | // // RemoteCall::exportAs("GMLIB_FormAPI", "getNextFormCallbackId", []() -> std::string { 117 | // // return LegacyScriptFormManager::getInstance().getNextFormCallbackId(); 118 | // // }); 119 | // ////////////////////////////// ServerSettingForm ////////////////////////////// 120 | // RemoteCall::exportAs("GMLIB_ServerSettingForm", "getDefaultPriority", []() -> int { 121 | // return gmlib::form::ServerSettingForm::getDefaultPriority(); 122 | // }); 123 | // RemoteCall::exportAs("GMLIB_ServerSettingForm", "hasTitle", []() -> bool { return gmlib::form::ServerSettingForm::hasTitle(); }); 124 | // RemoteCall::exportAs("GMLIB_ServerSettingForm", "getTitle", []() -> std::string { 125 | // return gmlib::form::ServerSettingForm::getTitle(); 126 | // }); 127 | // RemoteCall::exportAs("GMLIB_gmlib::form::ServerSettingForm", "setTitle", [](std::string const& title, bool forceModify) -> bool { 128 | // return gmlib::form::ServerSettingForm::setTitle(title, forceModify); 129 | // }); 130 | // RemoteCall::exportAs("GMLIB_gmlib::form::ServerSettingForm", "hasIcon", []() -> bool { return gmlib::form::ServerSettingForm::hasIcon(); }); 131 | // RemoteCall::exportAs("GMLIB_gmlib::form::ServerSettingForm", "getIconData", []() -> std::string { 132 | // return gmlib::form::ServerSettingForm::getIconData().value_or(""); 133 | // }); 134 | // RemoteCall::exportAs("GMLIB_gmlib::form::ServerSettingForm", "getIconType", []() -> int { 135 | // return gmlib::form::ServerSettingForm::getIconType() 136 | // .transform([](gmlib::form::IconType&& type) -> int { return (int)type; }) 137 | // .value_or(-1); 138 | // }); 139 | // RemoteCall::exportAs( 140 | // "GMLIB_gmlib::form::ServerSettingForm", 141 | // "setIcon", 142 | // [](std::string const& title, uchar type, bool forceModify) -> bool { 143 | // return gmlib::form::ServerSettingForm::setIcon(title, gmlib::form::IconType(type), forceModify); 144 | // } 145 | // ); 146 | // RemoteCall::exportAs( 147 | // "GMLIB_gmlib::form::ServerSettingForm", 148 | // "addLabel", 149 | // [](std::string const& text, std::string const& detectorId, int priority) -> uint { 150 | // uint result = gmlib::form::ServerSettingForm::addLabel(text, PLAYER_DETECROR, priority); 151 | // return result; 152 | // } 153 | // ); 154 | // RemoteCall::exportAs( 155 | // "GMLIB_gmlib::form::ServerSettingForm", 156 | // "addInput", 157 | // [](std::string const& text, 158 | // std::string const& placeholder, 159 | // std::string const& defaultVal, 160 | // std::string const& callbackId, 161 | // std::string const& detectorId, 162 | // int priority) -> uint { 163 | // uint result = gmlib::form::ServerSettingForm::addInput( 164 | // text, 165 | // placeholder, 166 | // defaultVal, 167 | // CALLBACK_TYPE(std::string const&), 168 | // PLAYER_DETECROR, 169 | // priority 170 | // ); 171 | // return result; 172 | // } 173 | // ); 174 | // RemoteCall::exportAs( 175 | // "GMLIB_gmlib::form::ServerSettingForm", 176 | // "addToggle", 177 | // [](std::string const& text, 178 | // bool defaultVal, 179 | // std::string const& callbackId, 180 | // std::string const& detectorId, 181 | // int priority) -> uint { 182 | // uint result = gmlib::form::ServerSettingForm::addToggle(text, defaultVal, CALLBACK_TYPE(bool), PLAYER_DETECROR, priority); 183 | // return result; 184 | // } 185 | // ); 186 | // RemoteCall::exportAs( 187 | // "GMLIB_gmlib::form::ServerSettingForm", 188 | // "addDropdown", 189 | // [](std::string const& text, 190 | // std::vector options, 191 | // int64 defaultVal, 192 | // std::string const& callbackId, 193 | // std::string const& detectorId, 194 | // int priority) -> uint { 195 | // uint result = gmlib::form::ServerSettingForm::addDropdown( 196 | // text, 197 | // options, 198 | // defaultVal, 199 | // CALLBACK_TYPE(int64), 200 | // PLAYER_DETECROR, 201 | // priority 202 | // ); 203 | // return result; 204 | // } 205 | // ); 206 | // RemoteCall::exportAs( 207 | // "GMLIB_gmlib::form::ServerSettingForm", 208 | // "addSlider", 209 | // [](std::string const& text, 210 | // double min, 211 | // double max, 212 | // double step, 213 | // double defaultVal, 214 | // std::string const& callbackId, 215 | // std::string const& detectorId, 216 | // int priority) -> uint { 217 | // uint result = gmlib::form::ServerSettingForm::addSlider( 218 | // text, 219 | // min, 220 | // max, 221 | // step, 222 | // defaultVal, 223 | // CALLBACK_TYPE(double), 224 | // PLAYER_DETECROR, 225 | // priority 226 | // ); 227 | // return result; 228 | // } 229 | // ); 230 | // RemoteCall::exportAs( 231 | // "GMLIB_gmlib::form::ServerSettingForm", 232 | // "addStepSlider", 233 | // [](std::string const& text, 234 | // std::vector steps, 235 | // int64 defaultVal, 236 | // std::string const& callbackId, 237 | // std::string const& detectorId, 238 | // int priority) -> uint { 239 | // uint result = gmlib::form::ServerSettingForm::addStepSlider( 240 | // text, 241 | // steps, 242 | // defaultVal, 243 | // CALLBACK_TYPE(int64), 244 | // PLAYER_DETECROR, 245 | // priority 246 | // ); 247 | // return result; 248 | // } 249 | // ); 250 | // RemoteCall::exportAs("GMLIB_gmlib::form::ServerSettingForm", "removeElement", [](uint id) -> bool { 251 | // return gmlib::form::ServerSettingForm::removeElement(id); 252 | // }); 253 | // ////////////////////////////// NpcDialogueForm ////////////////////////////// 254 | // RemoteCall::exportAs( 255 | // "GMLIB_NpcDialogueForm", 256 | // "createForm", 257 | // [](std::string const& npcName, std::string const& sceneName, std::string const& dialogue) -> int64 { 258 | // return LegacyScriptFormManager::getInstance().createNpcDialogueForm(npcName, sceneName, dialogue); 259 | // } 260 | // ); 261 | // RemoteCall::exportAs("GMLIB_NpcDialogueForm", "destroyForm", [](int64 formId) -> bool { 262 | // return LegacyScriptFormManager::getInstance().destroyNpcDialogueForm(formId); 263 | // }); 264 | // RemoteCall::exportAs( 265 | // "GMLIB_NpcDialogueForm", 266 | // "addButton", 267 | // [](int64 formId, std::string const& button, std::string const& callbackId) -> void { 268 | // if (auto formPtr = LegacyScriptFormManager::getInstance().getNpcDialogueForm(formId)) { 269 | // formPtr->addButton(button, CALLBACK_TYPE_NORMAL); 270 | // } 271 | // } 272 | // ); 273 | // RemoteCall::exportAs( 274 | // "GMLIB_NpcDialogueForm", 275 | // "onPlayerClose", 276 | // [](int64 formId, std::string const& callbackId) -> void { 277 | // if (auto formPtr = LegacyScriptFormManager::getInstance().getNpcDialogueForm(formId)) { 278 | // formPtr->onPlayerClose(CALLBACK_TYPE_NORMAL); 279 | // } 280 | // } 281 | // ); 282 | // RemoteCall::exportAs("GMLIB_NpcDialogueForm", "sendTo", [](int64 formId, ::Player* pl) -> void { 283 | // if (auto formPtr = LegacyScriptFormManager::getInstance().getNpcDialogueForm(formId)) { 284 | // formPtr->sendTo(*pl); 285 | // } 286 | // }); 287 | // ////////////////////////////// ChestForm ////////////////////////////// 288 | // } -------------------------------------------------------------------------------- /src/EventAPI.cpp: -------------------------------------------------------------------------------- 1 | #include "Global.h" 2 | using namespace ll::hash_utils; 3 | 4 | class EventManager { 5 | private: 6 | std::unordered_map mEventIds; 7 | 8 | public: 9 | static EventManager& getInstance() { 10 | static std::unique_ptr instance; 11 | if (!instance) instance = std::make_unique(); 12 | return *instance; 13 | } 14 | 15 | ullong getNextId() { 16 | auto id = mEventIds.size(); 17 | mEventIds.emplace(id, nullptr); 18 | return id; 19 | } 20 | 21 | bool addListener(ullong id, ll::event::ListenerPtr const& listener) { 22 | if (mEventIds.contains(id) && mEventIds[id]) return false; 23 | mEventIds[id] = listener; 24 | return true; 25 | } 26 | 27 | bool removeListener(ullong id) { 28 | if (ll::event::EventBus::getInstance().removeListener(mEventIds[id])) { 29 | mEventIds[id] = nullptr; 30 | return true; 31 | } 32 | return false; 33 | } 34 | 35 | bool hasListener(ullong id) { return mEventIds.contains(id) && mEventIds[id]; } 36 | 37 | ll::event::ListenerPtr getListener(ullong id) { return mEventIds.contains(id) ? mEventIds[id] : nullptr; } 38 | }; 39 | 40 | #define REGISTER_EVENT_LISTEN(eventType, paramType, params, cancelFun, ...) \ 41 | auto eventPtr = ll::event::EventBus::getInstance().emplaceListener( \ 42 | [pluginName, eventName, eventId](eventType& event) -> void { \ 43 | if (!RemoteCall::hasFunc(pluginName, eventName + "_" + std::to_string(eventId))) { \ 44 | EventManager::getInstance().removeListener(eventId); \ 45 | return; \ 46 | } \ 47 | try { \ 48 | __VA_ARGS__ \ 49 | auto result = \ 50 | RemoteCall::importAs(pluginName, eventName + "_" + std::to_string(eventId)) \ 51 | params; \ 52 | cancelFun \ 53 | } catch (...) {} \ 54 | }, \ 55 | ll::event::EventPriority(priority) \ 56 | ); \ 57 | return eventId 58 | 59 | void Export_Event_API() { 60 | RemoteCall::exportAs("GMLIB_Event_API", "removeListener", [](ll::event::ListenerId eventId) -> bool { 61 | return EventManager::getInstance().removeListener(eventId); 62 | }); 63 | 64 | RemoteCall::exportAs("GMLIB_Event_API", "hasListener", [](ll::event::ListenerId eventId) -> bool { 65 | return EventManager::getInstance().hasListener(eventId); 66 | }); 67 | 68 | RemoteCall::exportAs("GMLIB_Event_API", "getListenerPriority", [](ll::event::ListenerId eventId) -> int { 69 | if (auto event = EventManager::getInstance().getListener(eventId); event != nullptr) { 70 | return (int)event->getPriority(); 71 | } 72 | return -1; 73 | }); 74 | 75 | RemoteCall::exportAs( 76 | "GMLIB_Event_API", 77 | "emplaceListener", 78 | [](std::string const& pluginName, std::string const& eventName, int priority) -> llong { 79 | auto eventId = EventManager::getInstance().getNextId(); 80 | switch (doHash(eventName)) { 81 | case doHash("ll::ServerStoppingEvent"): { 82 | REGISTER_EVENT_LISTEN(ll::event::ServerStoppingEvent, (), (), , ); 83 | } 84 | case doHash("gmlib::ClientLoginAfterEvent"): { 85 | REGISTER_EVENT_LISTEN( 86 | ila::mc::ClientLoginAfterEvent, 87 | (std::string const& realName, 88 | std::string const& uuid, 89 | std::string const& serverXuid, 90 | std::string const& clientXuid), 91 | (event.realName(), event.uuid().asString(), event.serverAuthXuid(), event.clientAuthXuid()), 92 | if (result) event.disConnectClient(); 93 | ); 94 | } 95 | case doHash("gmlib::WeatherUpdateBeforeEvent"): { 96 | REGISTER_EVENT_LISTEN( 97 | ila::mc::WeatherUpdateBeforeEvent, 98 | (float rainLevel, int rainTime, float lightningLevel, int lightningTime, bool isCancelled), 99 | (event.rainLevel(), 100 | event.rainTime(), 101 | event.lightningLevel(), 102 | event.lightningTime(), 103 | event.isCancelled()), 104 | event.setCancelled(result); 105 | ); 106 | } 107 | case doHash("gmlib::WeatherUpdateAfterEvent"): { 108 | REGISTER_EVENT_LISTEN( 109 | ila::mc::WeatherUpdateAfterEvent, 110 | (float rainLevel, int rainTime, float lightningLevel, int lightningTime), 111 | (event.rainLevel(), event.rainTime(), event.lightningLevel(), event.lightningTime()), 112 | , 113 | ); 114 | } 115 | case doHash("gmlib::MobPickupItemBeforeEvent"): { 116 | REGISTER_EVENT_LISTEN(ila::mc::ActorPickupItemBeforeEvent, 117 | (Actor * mob, Actor * item, bool isCancelled), 118 | (&event.self(), (Actor*)&event.itemActor(), event.isCancelled()), 119 | event.setCancelled(result);); 120 | } 121 | case doHash("gmlib::MobPickupItemAfterEvent"): { 122 | REGISTER_EVENT_LISTEN( 123 | ila::mc::ActorPickupItemAfterEvent, 124 | (Actor * mob, Actor * item), 125 | (&event.self(), (Actor*)&event.itemActor()), 126 | , 127 | ); 128 | } 129 | case doHash("gmlib::ItemActorSpawnBeforeEvent"): { 130 | REGISTER_EVENT_LISTEN( 131 | ila::mc::SpawnItemActorBeforeEvent, 132 | (ItemStack * item, std::pair position, int64 spawnerUniqueId, bool isCancelled), 133 | (&event.item(), 134 | {event.pos(), event.blockSource().getDimensionId().id}, 135 | event.spawner() ? event.spawner()->getOrCreateUniqueID().rawID : -1, 136 | event.isCancelled()), 137 | event.setCancelled(result); 138 | ); 139 | } 140 | case doHash("gmlib::ItemActorSpawnAfterEvent"): { 141 | REGISTER_EVENT_LISTEN( 142 | ila::mc::SpawnItemActorAfterEvent, 143 | (Actor * item, std::pair position, int64 spawnerUniqueId), 144 | (&event.itemActor(), 145 | {event.pos(), event.blockSource().getDimensionId().id}, 146 | event.spawner() ? event.spawner()->getOrCreateUniqueID().rawID : -1), 147 | , 148 | ); 149 | } 150 | case doHash("gmlib::ActorChangeDimensionBeforeEvent"): { 151 | REGISTER_EVENT_LISTEN(ila::mc::ActorChangeDimensionBeforeEvent, 152 | (Actor * entity, int toDimId, bool isCancelled), 153 | (&event.self(), event.toDimensionId(), event.isCancelled()), 154 | event.setCancelled(result);); 155 | } 156 | case doHash("gmlib::ActorChangeDimensionAfterEvent"): { 157 | REGISTER_EVENT_LISTEN( 158 | ila::mc::ActorChangeDimensionAfterEvent, 159 | (Actor * entity, int fromDimId, int toDimId), 160 | (&event.self(), event.fromDimensionId(), event.toDimensionId()), 161 | , 162 | ); 163 | } 164 | case doHash("gmlib::PlayerStartSleepBeforeEvent"): { 165 | REGISTER_EVENT_LISTEN(ila::mc::PlayerStartSleepBeforeEvent, 166 | (Player * entity, BlockPos pos, bool isCancelled), 167 | (&event.self(), event.pos(), event.isCancelled()), 168 | event.setCancelled(result);); 169 | } 170 | case doHash("gmlib::PlayerStartSleepAfterEvent"): { 171 | REGISTER_EVENT_LISTEN( 172 | ila::mc::PlayerStartSleepAfterEvent, 173 | (Player * entity, BlockPos pos, int result), 174 | (&event.self(), event.pos(), (int)event.result()), 175 | , 176 | ); 177 | } 178 | case doHash("gmlib::PlayerStopSleepBeforeEvent"): { 179 | REGISTER_EVENT_LISTEN( 180 | ila::mc::PlayerStopSleepBeforeEvent, 181 | (Player * entity, bool forcefulWakeUp, bool updateLevelList, bool isCancelled), 182 | (&event.self(), event.forcefulWakeUp(), event.updateLevelList(), false), 183 | 184 | ); 185 | } 186 | case doHash("gmlib::PlayerStopSleepAfterEvent"): { 187 | REGISTER_EVENT_LISTEN( 188 | ila::mc::PlayerStopSleepAfterEvent, 189 | (Player * entity, bool forcefulWakeUp, bool updateLevelList, bool), 190 | (&event.self(), event.forcefulWakeUp(), event.updateLevelList(), false), 191 | , 192 | ); 193 | } 194 | case doHash("gmlib::DeathMessageAfterEvent"): { 195 | REGISTER_EVENT_LISTEN( 196 | ila::mc::DeathMessageAfterEvent, 197 | (std::string const& message, std::vector, Actor* dead), 198 | (event.result().first, event.result().second, &event.self()), 199 | , 200 | ); 201 | } 202 | case doHash("gmlib::MobHurtAfterEvent"): { 203 | REGISTER_EVENT_LISTEN( 204 | ila::mc::MobHealthChangeAfterEvent, 205 | (Actor * mob, Actor * source, float damage, int cause), 206 | (&event.self(), source, event.oldValue() - event.newValue(), (int)damageSource->mCause), 207 | , 208 | if (event.newValue() > event.oldValue()) return; 209 | auto& damageSource = event.buff().mSource; 210 | Actor* source = nullptr; 211 | if (damageSource->isEntitySource()) { 212 | auto uniqueId = damageSource->getDamagingEntityUniqueID(); 213 | source = ll::service::getLevel()->fetchEntity(uniqueId, false); 214 | if (source->getOwner()) source = source->getOwner(); 215 | } 216 | ); 217 | } 218 | case doHash("gmlib::EndermanTakeBlockBeforeEvent"): { 219 | REGISTER_EVENT_LISTEN(ila::mc::MobTakeBlockBeforeEvent, 220 | (Actor * mob, bool isCancelled), 221 | (&event.self(), event.isCancelled()), 222 | event.setCancelled(result); 223 | , if (!event.self().isType(ActorType::EnderMan)) return;); 224 | } 225 | case doHash("gmlib::DragonRespawnBeforeEvent"): { 226 | REGISTER_EVENT_LISTEN(ila::mc::DragonRespawnBeforeEvent, 227 | (bool isCancelled), 228 | (event.isCancelled()), 229 | event.setCancelled(result);); 230 | } 231 | case doHash("gmlib::DragonRespawnAfterEvent"): { 232 | REGISTER_EVENT_LISTEN(ila::mc::DragonRespawnAfterEvent, (Actor * mob), (&event.self()), ); 233 | } 234 | case doHash("gmlib::ProjectileCreateBeforeEvent"): { 235 | REGISTER_EVENT_LISTEN(ila::mc::ProjectileCreateBeforeEvent, 236 | (Actor * mob, int64 uniqueId, bool isCancelled), 237 | (&event.self(), event.self().getOwnerId().rawID, event.isCancelled()), 238 | event.setCancelled(result);); 239 | } 240 | case doHash("gmlib::ProjectileCreateAfterEvent"): { 241 | REGISTER_EVENT_LISTEN( 242 | ila::mc::ProjectileCreateAfterEvent, 243 | (Actor * mob, int64 uniqueId), 244 | (&event.self(), event.self().getOwnerId().rawID), 245 | ); 246 | } 247 | case doHash("gmlib::SpawnWanderingTraderBeforeEvent"): { 248 | REGISTER_EVENT_LISTEN(ila::mc::SpawnWanderingTraderBeforeEvent, 249 | (std::pair pos, bool isCancelled), 250 | ({event.pos(), event.blockSource().getDimensionId()}, event.isCancelled()), 251 | event.setCancelled(result);); 252 | } 253 | case doHash("gmlib::HandleRequestActionBeforeEvent"): { 254 | // clang-format off 255 | REGISTER_EVENT_LISTEN( 256 | ila::mc::PlayerRequestItemActionBeforeEvent, 257 | ( 258 | Player * player, 259 | std::string const& actionType, 260 | int count, 261 | std::string const& sourceContainerNetId, 262 | int sourceSlot, 263 | std::string const& destinationContainerNetId, 264 | int destinationSlot, 265 | bool isCancelled 266 | ), 267 | ( 268 | (Player*)&event.self(), 269 | magic_enum::enum_name(event.actionType()).data(), 270 | event.amount(), 271 | magic_enum::enum_name(event.src().mFullContainerName.mName).data(), 272 | (int)event.src().mSlot, 273 | magic_enum::enum_name(event.dst().mFullContainerName.mName).data(), 274 | (int)event.dst().mSlot, 275 | event.isCancelled() 276 | ), 277 | event.setCancelled(result);, 278 | ); 279 | // clang-format on 280 | } 281 | case doHash("gmlib::HandleRequestActionAfterEvent"): { 282 | // clang-format off 283 | REGISTER_EVENT_LISTEN( 284 | ila::mc::PlayerRequestItemActionAfterEvent, 285 | ( 286 | Player * player, 287 | std::string const& actionType, 288 | int count, 289 | std::string const& sourceContainerNetId, 290 | int sourceSlot, 291 | std::string const& destinationContainerNetId, 292 | int destinationSlot 293 | ), 294 | ( 295 | (Player*)&event.self(), 296 | magic_enum::enum_name(event.actionType()).data(), 297 | event.amount(), 298 | magic_enum::enum_name(event.src().mFullContainerName.mName).data(), 299 | (int)event.src().mSlot, 300 | magic_enum::enum_name(event.dst().mFullContainerName.mName).data(), 301 | (int)event.dst().mSlot 302 | ), 303 | , 304 | ); 305 | // clang-format on 306 | } 307 | case doHash("gmlib::ContainerClosePacketSendAfterEvent"): { 308 | REGISTER_EVENT_LISTEN( 309 | ila::mc::PlayerCloseContainerAfterEvent, 310 | (Player * player, int containerId, bool serverInitiatedClose, bool), 311 | (&event.self(), (int)event.containerId(), event.serverInitiatedClose(), false), 312 | , 313 | ); 314 | } 315 | } 316 | return -1; 317 | } 318 | ); 319 | } -------------------------------------------------------------------------------- /lib/EventAPI-JS.d.ts: -------------------------------------------------------------------------------- 1 | export namespace Event { 2 | /** 事件优先级 */ 3 | export enum EventPriority { 4 | /** 最高 */ 5 | Highest = 0, 6 | /** 高 */ 7 | High = 100, 8 | /** 正常(推荐) */ 9 | Normal = 200, 10 | /** 低 */ 11 | Low = 300, 12 | /** 最低 */ 13 | Lowest = 400 14 | } 15 | 16 | /** 获取所有事件订阅 */ 17 | export function getListener(): Record; 18 | 19 | /** 获取事件订阅列表 */ 20 | export function getListener( 21 | /** 事件名 */ 22 | eventName: 23 | "ll::ServerStoppingEvent" 24 | | "gmlib::ClientLoginAfterEvent" 25 | | "gmlib::WeatherUpdateBeforeEvent" 26 | | "gmlib::MobPickupItemBeforeEvent" 27 | | "gmlib::ItemActorSpawnBeforeEvent" 28 | | "gmlib::ItemActorSpawnAfterEvent" 29 | | "gmlib::ActorChangeDimensionBeforeEvent" 30 | | "gmlib::PlayerStopSleepBeforeEvent" 31 | | "gmlib::DeathMessageAfterEvent" 32 | | "gmlib::MobHurtAfterEvent" 33 | | "gmlib::EndermanTakeBlockBeforeEvent" 34 | | "gmlib::ActorChangeDimensionAfterEvent" 35 | | "gmlib::DragonRespawnBeforeEvent" 36 | | "gmlib::ProjectileCreateBeforeEvent" 37 | | "gmlib::ProjectileCreateAfterEvent" 38 | | "gmlib::SpawnWanderingTraderBeforeEvent" 39 | | "gmlib::HandleRequestActionBeforeEvent" 40 | | "gmlib::ContainerClosePacketSendAfterEvent" 41 | ): number[]; 42 | 43 | /** 订阅事件是否存在 */ 44 | export function hasListener( 45 | /** 事件ID */ 46 | eventId: number 47 | ): boolean; 48 | 49 | /** 取消事件订阅 */ 50 | export function removeListener( 51 | /** 事件ID */ 52 | eventId: number 53 | ): boolean; 54 | 55 | /** 获取订阅事件优先级 */ 56 | export function getListenerPriority( 57 | /** 事件ID */ 58 | eventId: number 59 | ): EventPriority | undefined; 60 | 61 | /** 设置事件异常处理回调 */ 62 | export function setErrorHanlerCallback( 63 | /** 回调 */ 64 | callback: ( 65 | /** 错误 */ 66 | error: Error, 67 | /** 事件名 */ 68 | eventName: string, 69 | /** 事件ID */ 70 | eventId: number, 71 | /** 插件名 */ 72 | pluginName: string 73 | ) => void 74 | ): boolean; 75 | 76 | /** 监听事件(兼容旧版) */ 77 | export function listen( 78 | /** 事件名 */ 79 | eventName: "onServerStopping" 80 | | "onClientLogin" 81 | | "onWeatherChange" 82 | | "onMobPick" 83 | | "onItemTrySpawn" 84 | | "onItemSpawned" 85 | | "onEntityTryChangeDim" 86 | | "onLeaveBed" 87 | | "onDeathMessage" 88 | | "onMobHurted" 89 | | "onEndermanTake" 90 | | "onEntityChangeDim" 91 | | "onDragonRespawn" 92 | | "onProjectileTryCreate" 93 | | "onProjectileCreate" 94 | | "onSpawnWanderingTrader" 95 | | "onHandleRequestAction" 96 | | "onSendContainerClosePacket", 97 | /** 回调 */ 98 | callback: Function 99 | ): boolean; 100 | 101 | /** 订阅事件 */ 102 | export function emplaceListener( 103 | /** 事件名 */ 104 | eventName: string, 105 | /** 回调 */ 106 | callback: (event: { 107 | /** 事件参数 */ 108 | params: any[], 109 | /** 拦截事件 */ 110 | cancel: () => void, 111 | /** 设置拦截状态 */ 112 | setCancelled: ( 113 | /** 是否拦截 */ 114 | value: boolean 115 | ) => void, 116 | /** 是否被拦截 */ 117 | isCancelled: () => boolean, 118 | /** 获取事件ID */ 119 | getId: () => number, 120 | /** 获取事件类型 */ 121 | getEventType: () => string 122 | }) => void, 123 | /** 优先级 */ 124 | priority?: Event.EventPriority, 125 | /** 插件名 */ 126 | pluginName?: string 127 | ): number; 128 | 129 | /** 订阅事件(服务器关闭事件) */ 130 | export function emplaceListener( 131 | /** 事件名 */ 132 | eventName: "ll::ServerStoppingEvent", 133 | /** 回调 */ 134 | callback: (event: { 135 | /** 事件参数 */ 136 | params: {}, 137 | /** 获取事件ID */ 138 | getId: () => number, 139 | /** 获取事件类型 */ 140 | getEventType: () => string 141 | }) => void, 142 | /** 优先级 */ 143 | priority?: Event.EventPriority, 144 | /** 插件名 */ 145 | pluginName?: string 146 | ): number; 147 | 148 | /** 订阅事件(客户端登录后事件) */ 149 | export function emplaceListener( 150 | /** 事件名 */ 151 | eventName: "gmlib::ClientLoginAfterEvent", 152 | /** 回调 */ 153 | callback: (event: { 154 | /** 事件参数 */ 155 | params: { 156 | /** 玩家名 */ 157 | 0: string, 158 | /** 玩家uuid */ 159 | 1: string, 160 | /** 玩家服务端xuid */ 161 | 2: string, 162 | /** 玩家客户端xuid */ 163 | 3: string, 164 | }, 165 | /** 拦截事件 */ 166 | cancel: () => void, 167 | /** 设置拦截状态 */ 168 | setCancelled: ( 169 | /** 是否拦截 */ 170 | value: boolean 171 | ) => void, 172 | /** 是否被拦截 */ 173 | isCancelled: () => boolean, 174 | /** 获取事件ID */ 175 | getId: () => number, 176 | /** 获取事件类型 */ 177 | getEventType: () => string 178 | }) => void, 179 | /** 优先级 */ 180 | priority?: Event.EventPriority, 181 | /** 插件名 */ 182 | pluginName?: string 183 | ): number; 184 | 185 | /** 订阅事件(天气更新前事件) */ 186 | export function emplaceListener( 187 | /** 事件名 */ 188 | eventName: "gmlib::WeatherUpdateBeforeEvent", 189 | /** 回调 */ 190 | callback: (event: { 191 | /** 事件参数 */ 192 | params: { 193 | /** 雨天等级 */ 194 | 0: number, 195 | /** 雨天时间(tick) */ 196 | 1: number, 197 | /** 暴雨等级 */ 198 | 2: number, 199 | /** 暴雨时间(tick) */ 200 | 3: number, 201 | }, 202 | /** 拦截事件 */ 203 | cancel: () => void, 204 | /** 设置拦截状态 */ 205 | setCancelled: ( 206 | /** 是否拦截 */ 207 | value: boolean 208 | ) => void, 209 | /** 是否被拦截 */ 210 | isCancelled: () => boolean, 211 | /** 获取事件ID */ 212 | getId: () => number, 213 | /** 获取事件类型 */ 214 | getEventType: () => string 215 | }) => void, 216 | /** 优先级 */ 217 | priority?: Event.EventPriority, 218 | /** 插件名 */ 219 | pluginName?: string 220 | ): number; 221 | 222 | /** 订阅事件(天气更新后事件) */ 223 | export function emplaceListener( 224 | /** 事件名 */ 225 | eventName: "gmlib::WeatherUpdateAfterEvent", 226 | /** 回调 */ 227 | callback: (event: { 228 | /** 事件参数 */ 229 | params: { 230 | /** 雨天等级 */ 231 | 0: number, 232 | /** 雨天时间(tick) */ 233 | 1: number, 234 | /** 暴雨等级 */ 235 | 2: number, 236 | /** 暴雨时间(tick) */ 237 | 3: number, 238 | }, 239 | /** 获取事件ID */ 240 | getId: () => number, 241 | /** 获取事件类型 */ 242 | getEventType: () => string 243 | }) => void, 244 | /** 优先级 */ 245 | priority?: Event.EventPriority, 246 | /** 插件名 */ 247 | pluginName?: string 248 | ): number; 249 | 250 | /** 订阅事件(实体捡起物品前事件) */ 251 | export function emplaceListener( 252 | /** 事件名 */ 253 | eventName: "gmlib::MobPickupItemBeforeEvent", 254 | /** 回调 */ 255 | callback: (event: { 256 | /** 事件参数 */ 257 | params: { 258 | /** 捡起物品的实体 */ 259 | 0: Entity, 260 | /** 掉落物 */ 261 | 1: Entity 262 | }, 263 | /** 拦截事件 */ 264 | cancel: () => void, 265 | /** 设置拦截状态 */ 266 | setCancelled: ( 267 | /** 是否拦截 */ 268 | value: boolean 269 | ) => void, 270 | /** 是否被拦截 */ 271 | isCancelled: () => boolean, 272 | /** 获取事件ID */ 273 | getId: () => number, 274 | /** 获取事件类型 */ 275 | getEventType: () => string 276 | }) => void, 277 | /** 优先级 */ 278 | priority?: Event.EventPriority, 279 | /** 插件名 */ 280 | pluginName?: string 281 | ): number; 282 | 283 | /** 订阅事件(实体捡起物品后事件) */ 284 | export function emplaceListener( 285 | /** 事件名 */ 286 | eventName: "gmlib::MobPickupItemAfterEvent", 287 | /** 回调 */ 288 | callback: (event: { 289 | /** 事件参数 */ 290 | params: { 291 | /** 捡起物品的实体 */ 292 | 0: Entity, 293 | /** 掉落物 */ 294 | 1: Entity 295 | }, 296 | /** 获取事件ID */ 297 | getId: () => number, 298 | /** 获取事件类型 */ 299 | getEventType: () => string 300 | }) => void, 301 | /** 优先级 */ 302 | priority?: Event.EventPriority, 303 | /** 插件名 */ 304 | pluginName?: string 305 | ): number; 306 | 307 | /** 订阅事件(掉落物生成前事件) */ 308 | export function emplaceListener( 309 | /** 事件名 */ 310 | eventName: "gmlib::ItemActorSpawnBeforeEvent", 311 | /** 回调 */ 312 | callback: (event: { 313 | /** 事件参数 */ 314 | params: { 315 | /** 物品 */ 316 | 0: Item, 317 | /** 生成坐标坐标 */ 318 | 1: FloatPos, 319 | /** 生成此物品主人的uniqueId (-1为不存在) */ 320 | 2: number 321 | }, 322 | /** 拦截事件 */ 323 | cancel: () => void, 324 | /** 设置拦截状态 */ 325 | setCancelled: ( 326 | /** 是否拦截 */ 327 | value: boolean 328 | ) => void, 329 | /** 是否被拦截 */ 330 | isCancelled: () => boolean, 331 | /** 获取事件ID */ 332 | getId: () => number, 333 | /** 获取事件类型 */ 334 | getEventType: () => string 335 | }) => void, 336 | /** 优先级 */ 337 | priority?: Event.EventPriority, 338 | /** 插件名 */ 339 | pluginName?: string 340 | ): number; 341 | 342 | /** 订阅事件(掉落物生成后事件) */ 343 | export function emplaceListener( 344 | /** 事件名 */ 345 | eventName: "gmlib::ItemActorSpawnAfterEvent", 346 | /** 回调 */ 347 | callback: (event: { 348 | /** 事件参数 */ 349 | params: { 350 | /** 物品实体对象 */ 351 | 0: Entity, 352 | /** 生成坐标坐标 */ 353 | 1: FloatPos, 354 | /** 生成此物品主人的uniqueId (-1为不存在) */ 355 | 2: number 356 | }, 357 | /** 获取事件ID */ 358 | getId: () => number, 359 | /** 获取事件类型 */ 360 | getEventType: () => string 361 | }) => void, 362 | /** 优先级 */ 363 | priority?: Event.EventPriority, 364 | /** 插件名 */ 365 | pluginName?: string 366 | ): number; 367 | 368 | /** 订阅事件(实体切换维度前事件) */ 369 | export function emplaceListener( 370 | /** 事件名 */ 371 | eventName: "gmlib::ActorChangeDimensionBeforeEvent", 372 | /** 回调 */ 373 | callback: (event: { 374 | /** 事件参数 */ 375 | params: { 376 | /** 切换维度的实体 */ 377 | 0: Entity, 378 | /** 前往的维度ID */ 379 | 1: number 380 | }, 381 | /** 拦截事件 */ 382 | cancel: () => void, 383 | /** 设置拦截状态 */ 384 | setCancelled: ( 385 | /** 是否拦截 */ 386 | value: boolean 387 | ) => void, 388 | /** 是否被拦截 */ 389 | isCancelled: () => boolean, 390 | /** 获取事件ID */ 391 | getId: () => number, 392 | /** 获取事件类型 */ 393 | getEventType: () => string 394 | }) => void, 395 | /** 优先级 */ 396 | priority?: Event.EventPriority, 397 | /** 插件名 */ 398 | pluginName?: string 399 | ): number; 400 | 401 | /** 订阅事件(事件切换维度后事件) */ 402 | export function emplaceListener( 403 | /** 事件名 */ 404 | eventName: "gmlib::ActorChangeDimensionAfterEvent", 405 | /** 回调 */ 406 | callback: (event: { 407 | /** 事件参数 */ 408 | params: { 409 | /** 切换维度的实体 */ 410 | 0: Entity, 411 | /** 原来的维度ID */ 412 | 1: number, 413 | /** 前往的维度ID */ 414 | 2: number 415 | }, 416 | /** 获取事件ID */ 417 | getId: () => number, 418 | /** 获取事件类型 */ 419 | getEventType: () => string 420 | }) => void, 421 | /** 优先级 */ 422 | priority?: Event.EventPriority, 423 | /** 插件名 */ 424 | pluginName?: string 425 | ): number; 426 | 427 | /** 订阅事件(玩家开始睡觉前事件) */ 428 | export function emplaceListener( 429 | /** 事件名 */ 430 | eventName: "gmlib::PlayerStartSleepBeforeEvent", 431 | /** 回调 */ 432 | callback: (event: { 433 | /** 事件参数 */ 434 | params: { 435 | /** 睡觉的玩家 */ 436 | 0: Player, 437 | /** 床的坐标 */ 438 | 1: IntPos 439 | }, 440 | /** 拦截事件 */ 441 | cancel: () => void, 442 | /** 设置拦截状态 */ 443 | setCancelled: ( 444 | /** 是否拦截 */ 445 | value: boolean 446 | ) => void, 447 | /** 是否被拦截 */ 448 | isCancelled: () => boolean, 449 | /** 获取事件ID */ 450 | getId: () => number, 451 | /** 获取事件类型 */ 452 | getEventType: () => string 453 | }) => void, 454 | /** 优先级 */ 455 | priority?: Event.EventPriority, 456 | /** 插件名 */ 457 | pluginName?: string 458 | ): number; 459 | 460 | /** 订阅事件(玩家开始睡觉后事件) */ 461 | export function emplaceListener( 462 | /** 事件名 */ 463 | eventName: "gmlib::PlayerStartSleepAfterEvent", 464 | /** 回调 */ 465 | callback: (event: { 466 | /** 事件参数 */ 467 | params: { 468 | /** 睡觉的玩家 */ 469 | 0: Player, 470 | /** 床的坐标 */ 471 | 1: IntPos, 472 | /** 睡觉的结果 */ 473 | 2: number 474 | }, 475 | /** 获取事件ID */ 476 | getId: () => number, 477 | /** 获取事件类型 */ 478 | getEventType: () => string 479 | }) => void, 480 | /** 优先级 */ 481 | priority?: Event.EventPriority, 482 | /** 插件名 */ 483 | pluginName?: string 484 | ): number; 485 | 486 | /** 订阅事件(玩家停止睡觉前事件) */ 487 | export function emplaceListener( 488 | /** 事件名 */ 489 | eventName: "gmlib::PlayerStopSleepBeforeEvent", 490 | /** 回调 */ 491 | callback: (event: { 492 | /** 事件参数 */ 493 | params: { 494 | /** 睡觉的玩家 */ 495 | 0: Player, 496 | /** forcefulWakeUp */ 497 | 1: boolean, 498 | /** updateLevelList */ 499 | 2: boolean 500 | }, 501 | /** 拦截事件 */ 502 | cancel: () => void, 503 | /** 设置拦截状态 */ 504 | setCancelled: ( 505 | /** 是否拦截 */ 506 | value: boolean 507 | ) => void, 508 | /** 是否被拦截 */ 509 | isCancelled: () => boolean, 510 | /** 获取事件ID */ 511 | getId: () => number, 512 | /** 获取事件类型 */ 513 | getEventType: () => string 514 | }) => void, 515 | /** 优先级 */ 516 | priority?: Event.EventPriority, 517 | /** 插件名 */ 518 | pluginName?: string 519 | ): number; 520 | 521 | /** 订阅事件(玩家停止睡觉后事件) */ 522 | export function emplaceListener( 523 | /** 事件名 */ 524 | eventName: "gmlib::PlayerStopSleepAfterEvent", 525 | /** 回调 */ 526 | callback: (event: { 527 | /** 事件参数 */ 528 | params: { 529 | /** 睡觉的玩家 */ 530 | 0: Player, 531 | /** forcefulWakeUp */ 532 | 1: boolean, 533 | /** updateLevelList */ 534 | 2: boolean 535 | }, 536 | /** 获取事件ID */ 537 | getId: () => number, 538 | /** 获取事件类型 */ 539 | getEventType: () => string 540 | }) => void, 541 | /** 优先级 */ 542 | priority?: Event.EventPriority, 543 | /** 插件名 */ 544 | pluginName?: string 545 | ): number; 546 | 547 | /** 订阅事件(生成死亡消息后事件) */ 548 | export function emplaceListener( 549 | /** 事件名 */ 550 | eventName: "gmlib::DeathMessageAfterEvent", 551 | /** 回调 */ 552 | callback: (event: { 553 | /** 事件参数 */ 554 | params: { 555 | /** 键名 */ 556 | 0: string, 557 | /** 翻译参数 */ 558 | 1: string[], 559 | /** 死亡的实体 */ 560 | 2: Entity 561 | }, 562 | /** 获取事件ID */ 563 | getId: () => number, 564 | /** 获取事件类型 */ 565 | getEventType: () => string 566 | }) => void, 567 | /** 优先级 */ 568 | priority?: Event.EventPriority, 569 | /** 插件名 */ 570 | pluginName?: string 571 | ): number; 572 | 573 | /** 订阅事件(实体受伤后事件) */ 574 | export function emplaceListener( 575 | /** 事件名 */ 576 | eventName: "gmlib::MobHurtAfterEvent", 577 | /** 回调 */ 578 | callback: (event: { 579 | /** 事件参数 */ 580 | params: { 581 | /** 受伤的实体 */ 582 | 0: Entity, 583 | /** 伤害来源 */ 584 | 1: Entity, 585 | /** 伤害值 */ 586 | 2: number, 587 | /** 伤害类型 */ 588 | 3: DamageCause 589 | }, 590 | /** 获取事件ID */ 591 | getId: () => number, 592 | /** 获取事件类型 */ 593 | getEventType: () => string 594 | }) => void, 595 | /** 优先级 */ 596 | priority?: Event.EventPriority, 597 | /** 插件名 */ 598 | pluginName?: string 599 | ): number; 600 | 601 | /** 订阅事件(末影人搬运方块前事件) */ 602 | export function emplaceListener( 603 | /** 事件名 */ 604 | eventName: "gmlib::EndermanTakeBlockBeforeEvent", 605 | /** 回调 */ 606 | callback: (event: { 607 | /** 事件参数 */ 608 | params: { 609 | /** 末影人实体 */ 610 | 0: Entity 611 | }, 612 | /** 拦截事件 */ 613 | cancel: () => void, 614 | /** 设置拦截状态 */ 615 | setCancelled: ( 616 | /** 是否拦截 */ 617 | value: boolean 618 | ) => void, 619 | /** 是否被拦截 */ 620 | isCancelled: () => boolean, 621 | /** 获取事件ID */ 622 | getId: () => number, 623 | /** 获取事件类型 */ 624 | getEventType: () => string 625 | }) => void, 626 | /** 优先级 */ 627 | priority?: Event.EventPriority, 628 | /** 插件名 */ 629 | pluginName?: string 630 | ): number; 631 | 632 | /** 订阅事件(末影龙复活前事件) */ 633 | export function emplaceListener( 634 | /** 事件名 */ 635 | eventName: "gmlib::DragonRespawnBeforeEvent", 636 | /** 回调 */ 637 | callback: (event: { 638 | /** 事件参数 */ 639 | params: {}, 640 | /** 拦截事件 */ 641 | cancel: () => void, 642 | /** 设置拦截状态 */ 643 | setCancelled: ( 644 | /** 是否拦截 */ 645 | value: boolean 646 | ) => void, 647 | /** 是否被拦截 */ 648 | isCancelled: () => boolean, 649 | /** 获取事件ID */ 650 | getId: () => number, 651 | /** 获取事件类型 */ 652 | getEventType: () => string 653 | }) => void, 654 | /** 优先级 */ 655 | priority?: Event.EventPriority, 656 | /** 插件名 */ 657 | pluginName?: string 658 | ): number; 659 | 660 | /** 订阅事件(末影龙复活后事件) */ 661 | export function emplaceListener( 662 | /** 事件名 */ 663 | eventName: "gmlib::DragonRespawnAfterEvent", 664 | /** 回调 */ 665 | callback: (event: { 666 | /** 事件参数 */ 667 | params: { 668 | /** 末影龙实体 */ 669 | 0: Entity 670 | }, 671 | /** 获取事件ID */ 672 | getId: () => number, 673 | /** 获取事件类型 */ 674 | getEventType: () => string 675 | }) => void, 676 | /** 优先级 */ 677 | priority?: Event.EventPriority, 678 | /** 插件名 */ 679 | pluginName?: string 680 | ): number; 681 | 682 | /** 订阅事件(投射物创建前事件) */ 683 | export function emplaceListener( 684 | /** 事件名 */ 685 | eventName: "gmlib::ProjectileCreateBeforeEvent", 686 | /** 回调 */ 687 | callback: (event: { 688 | /** 事件参数 */ 689 | params: { 690 | /** 投射物实体 */ 691 | 0: Entity, 692 | /** 创建投射物实体的uniqueId */ 693 | 1: number 694 | }, 695 | /** 拦截事件 */ 696 | cancel: () => void, 697 | /** 设置拦截状态 */ 698 | setCancelled: ( 699 | /** 是否拦截 */ 700 | value: boolean 701 | ) => void, 702 | /** 是否被拦截 */ 703 | isCancelled: () => boolean, 704 | /** 获取事件ID */ 705 | getId: () => number, 706 | /** 获取事件类型 */ 707 | getEventType: () => string 708 | }) => void, 709 | /** 优先级 */ 710 | priority?: Event.EventPriority, 711 | /** 插件名 */ 712 | pluginName?: string 713 | ): number; 714 | 715 | /** 订阅事件(投射物创建后事件) */ 716 | export function emplaceListener( 717 | /** 事件名 */ 718 | eventName: "gmlib::ProjectileCreateAfterEvent", 719 | /** 回调 */ 720 | callback: (event: { 721 | /** 事件参数 */ 722 | params: { 723 | /** 投射物实体 */ 724 | 0: Entity, 725 | /** 创建投射物实体的uniqueId */ 726 | 1: number 727 | }, 728 | /** 获取事件ID */ 729 | getId: () => number, 730 | /** 获取事件类型 */ 731 | getEventType: () => string 732 | }) => void, 733 | /** 优先级 */ 734 | priority?: Event.EventPriority, 735 | /** 插件名 */ 736 | pluginName?: string 737 | ): number; 738 | 739 | /** 订阅事件(生成流浪商人前事件) */ 740 | export function emplaceListener( 741 | /** 事件名 */ 742 | eventName: "gmlib::SpawnWanderingTraderBeforeEvent", 743 | /** 回调 */ 744 | callback: (event: { 745 | /** 事件参数 */ 746 | params: { 747 | /** 出现的坐标 */ 748 | 0: IntPos 749 | }, 750 | /** 拦截事件 */ 751 | cancel: () => void, 752 | /** 设置拦截状态 */ 753 | setCancelled: ( 754 | /** 是否拦截 */ 755 | value: boolean 756 | ) => void, 757 | /** 是否被拦截 */ 758 | isCancelled: () => boolean, 759 | /** 获取事件ID */ 760 | getId: () => number, 761 | /** 获取事件类型 */ 762 | getEventType: () => string 763 | }) => void, 764 | /** 优先级 */ 765 | priority?: Event.EventPriority, 766 | /** 插件名 */ 767 | pluginName?: string 768 | ): number; 769 | 770 | /** 订阅事件(生成流浪商人后事件) */ 771 | export function emplaceListener( 772 | /** 事件名 */ 773 | eventName: "gmlib::SpawnWanderingTraderAfterEvent", 774 | /** 回调 */ 775 | callback: (event: { 776 | /** 事件参数 */ 777 | params: { 778 | /** 出现的坐标 */ 779 | 0: IntPos 780 | }, 781 | /** 获取事件ID */ 782 | getId: () => number, 783 | /** 获取事件类型 */ 784 | getEventType: () => string 785 | }) => void, 786 | /** 优先级 */ 787 | priority?: Event.EventPriority, 788 | /** 插件名 */ 789 | pluginName?: string 790 | ): number; 791 | 792 | /** 订阅事件(处理物品请求前事件) */ 793 | export function emplaceListener( 794 | /** 事件名 */ 795 | eventName: "gmlib::HandleRequestActionBeforeEvent", 796 | /** 回调 */ 797 | callback: (event: { 798 | /** 事件参数 */ 799 | params: { 800 | /** 请求的玩家 */ 801 | 0: Player, 802 | /** 请求类型 */ 803 | 1: string, 804 | /** 请求数量 */ 805 | 2: number, 806 | /** 请求原容器类型 */ 807 | 3: string, 808 | /** 请求原容器槽位 */ 809 | 4: number, 810 | /** 请求前往的容器类型 */ 811 | 5: string, 812 | /** 请求前往的槽位 */ 813 | 6: number 814 | }, 815 | /** 拦截事件 */ 816 | cancel: () => void, 817 | /** 设置拦截状态 */ 818 | setCancelled: ( 819 | /** 是否拦截 */ 820 | value: boolean 821 | ) => void, 822 | /** 是否被拦截 */ 823 | isCancelled: () => boolean, 824 | /** 获取事件ID */ 825 | getId: () => number, 826 | /** 获取事件类型 */ 827 | getEventType: () => string 828 | }) => void, 829 | /** 优先级 */ 830 | priority?: Event.EventPriority, 831 | /** 插件名 */ 832 | pluginName?: string 833 | ): number; 834 | 835 | /** 订阅事件(处理物品请求后事件) */ 836 | export function emplaceListener( 837 | /** 事件名 */ 838 | eventName: "gmlib::HandleRequestActionAfterEvent", 839 | /** 回调 */ 840 | callback: (event: { 841 | /** 事件参数 */ 842 | params: { 843 | /** 请求的玩家 */ 844 | 0: Player, 845 | /** 请求类型 */ 846 | 1: string, 847 | /** 请求数量 */ 848 | 2: number, 849 | /** 请求原容器类型 */ 850 | 3: string, 851 | /** 请求原容器槽位 */ 852 | 4: number, 853 | /** 请求前往的容器类型 */ 854 | 5: string, 855 | /** 请求前往的槽位 */ 856 | 6: number 857 | }, 858 | /** 获取事件ID */ 859 | getId: () => number, 860 | /** 获取事件类型 */ 861 | getEventType: () => string 862 | }) => void, 863 | /** 优先级 */ 864 | priority?: Event.EventPriority, 865 | /** 插件名 */ 866 | pluginName?: string 867 | ): number; 868 | 869 | /** 订阅事件(玩家关闭容器后事件) */ 870 | export function emplaceListener( 871 | /** 事件名 */ 872 | eventName: "gmlib::ContainerClosePacketSendAfterEvent", 873 | /** 回调 */ 874 | callback: (event: { 875 | /** 事件参数 */ 876 | params: { 877 | /** 关闭的玩家 */ 878 | 0: Player, 879 | /** 容器会话ID */ 880 | 1: number, 881 | /** 由服务器关闭 */ 882 | 2: boolean 883 | }, 884 | /** 获取事件ID */ 885 | getId: () => number, 886 | /** 获取事件类型 */ 887 | getEventType: () => string 888 | }) => void, 889 | /** 优先级 */ 890 | priority?: Event.EventPriority, 891 | /** 插件名 */ 892 | pluginName?: string 893 | ): number; 894 | } -------------------------------------------------------------------------------- /lib/GMLIB_API-JS.d.ts: -------------------------------------------------------------------------------- 1 | /** 静态悬浮字类 */ 2 | export class StaticFloatingText { 3 | constructor( 4 | /** 生成的坐标 */ 5 | pos: FloatPos, 6 | /** 显示的文本 */ 7 | text: string, 8 | /** 是否启用papi变量 */ 9 | papi: boolean | undefined 10 | ); 11 | 12 | /** 发送悬浮字给玩家 */ 13 | sendToClient( 14 | /** 要发送的玩家对象 */ 15 | player: Player 16 | ): boolean; 17 | 18 | /** 发送悬浮字给所有玩家 */ 19 | sendToClients(): boolean; 20 | 21 | /** 删除玩家的悬浮字 */ 22 | removeFromClient( 23 | /** 要删除的玩家的玩家对象 */ 24 | player: Player 25 | ): boolean; 26 | 27 | /** 删除所有玩家悬浮字 */ 28 | removeFromClients(): boolean; 29 | 30 | /** 更新玩家的悬浮字 */ 31 | updateClient( 32 | player: Player 33 | ): boolean; 34 | 35 | /** 更新所有玩家的悬浮字 */ 36 | updateClients(): boolean; 37 | 38 | /** 获取悬浮字的RuntimeId */ 39 | getRuntimeId(): number; 40 | 41 | /** 获取悬浮字显示的文本 */ 42 | getText(): string; 43 | 44 | /** 设置悬浮字显示的文本 */ 45 | setText( 46 | /** 要显示的文本 */ 47 | text: string 48 | ): void; 49 | 50 | /** 更新所有玩家的悬浮字 */ 51 | update(): boolean; 52 | 53 | /** 更新悬浮字文本 */ 54 | updateText( 55 | /** 要显示的文本 */ 56 | text: string 57 | ): boolean; 58 | 59 | /** 获取悬浮字的坐标 */ 60 | getPos(): FloatPos; 61 | 62 | /** 删除悬浮字 */ 63 | destroy(): boolean 64 | 65 | /** 根据RuntimeId获取静态悬浮字 */ 66 | static getFloatingText( 67 | /** 悬浮字的RuntimeId */ 68 | runtimeId: number 69 | ): StaticFloatingText | null; 70 | 71 | /** 获取所有静态悬浮字 */ 72 | static getAllFloatingTexts(): Array; 73 | } 74 | 75 | /** 动态悬浮字类 */ 76 | export class DynamicFloatingText extends StaticFloatingText { 77 | constructor( 78 | /** 生成的坐标 */ 79 | pos: FloatPos, 80 | /** 显示的文本 */ 81 | text: string, 82 | /** 更新频率(秒) */ 83 | updateRate: number | undefined, 84 | /** 是否使用PAPI变量 */ 85 | papi: boolean | undefined 86 | ); 87 | 88 | /** 获取悬浮字更新频率 */ 89 | getUpdateRate(): number 90 | 91 | /** 设置悬浮字更新频率 */ 92 | setUpdateRate( 93 | updateRate: number | undefined 94 | ): void; 95 | 96 | /** 开始更新悬浮字 */ 97 | startUpdate(): boolean; 98 | 99 | /** 停止更新悬浮字 */ 100 | stopUpdate(): boolean; 101 | 102 | /** 删除悬浮字 */ 103 | destroy(): boolean; 104 | 105 | /** 根据RuntimeId获取动态悬浮字 */ 106 | static getFloatingText( 107 | /** 悬浮字的RuntimeId */ 108 | runtimeId: number 109 | ): StaticFloatingText | null; 110 | 111 | /** 获取所有动态悬浮字 */ 112 | static getAllFloatingTexts(): Array; 113 | } 114 | 115 | /** 基础游戏API类 */ 116 | export class Minecraft { 117 | private constructor(); 118 | 119 | /** 获取服务器平均tps */ 120 | static getServerAverageTps(): number; 121 | 122 | /** 获取服务器当前tps */ 123 | static getServerCurrentTps(): number; 124 | 125 | /** 获取服务器mspt */ 126 | static getServerMspt(): number; 127 | 128 | /** 获取所有玩家uuid */ 129 | static getAllPlayerUuids(): Array; 130 | 131 | /** 获取玩家NBT */ 132 | static getPlayerNbt( 133 | /** 玩家uuid */ 134 | uuid: string 135 | ): NbtCompound; 136 | 137 | /** 写入玩家NBT */ 138 | static setPlayerNbt( 139 | /** 玩家uuid */ 140 | uuid: string, 141 | /** 要设置的NBT数据 */ 142 | nbt: NbtCompound, 143 | /** 不存在是否创建 */ 144 | forceCreate: boolean | undefined 145 | ): boolean; 146 | 147 | /** 覆盖玩家NBT的特定Tags */ 148 | static setPlayerNbtTags( 149 | /** 玩家uuid */ 150 | uuid: string, 151 | /** 要设置的NBT数据 */ 152 | nbt: NbtCompound, 153 | /** 要覆盖的NBT标签 */ 154 | tags: string[] 155 | ): boolean; 156 | 157 | /** 删除玩家NBT */ 158 | static deletePlayerNbt( 159 | /** 玩家uuid */ 160 | uuid: string, 161 | ): boolean; 162 | 163 | /** 获取玩家坐标 */ 164 | static getPlayerPosition( 165 | /** 玩家uuid */ 166 | uuid: string 167 | ): IntPos | null; 168 | 169 | /** 设置玩家坐标 */ 170 | static setPlayerPosition( 171 | /** 玩家uuid */ 172 | uuid: string, 173 | /** 玩家坐标 */ 174 | pos: IntPos 175 | ): boolean; 176 | 177 | /** 获取世界出生点 */ 178 | static getWorldSpawn(): IntPos; 179 | 180 | /** 设置世界出生点 */ 181 | static setWorldSpawn( 182 | /** 要设置的出生点坐标对象 */ 183 | pos: IntPos 184 | ): void; 185 | 186 | /** 187 | * @deprecated 已删 188 | * 启用教育版内容 189 | */ 190 | static setEducationFeatureEnabled(): void; 191 | 192 | /** 193 | * @deprecated 已删 194 | * 注册Ability命令 195 | */ 196 | static registerAbilityCommand(): void; 197 | 198 | /** 199 | * @deprecated 已删 200 | * 启用Xbox成就 201 | */ 202 | static setEnableAchievement(): void; 203 | 204 | /** 205 | * @deprecated 已删 206 | * 信任所有玩家皮肤 207 | */ 208 | static setForceTrustSkins(): void; 209 | 210 | /** 211 | * @deprecated 已删 212 | * 启用资源包双端共存 213 | */ 214 | static enableCoResourcePack(): void; 215 | 216 | /** 获取存档名称 */ 217 | static getWorldName(): string; 218 | 219 | /** 设置存档名称 */ 220 | static setWorldName( 221 | name: string 222 | ): boolean; 223 | 224 | /** 225 | * @deprecated 已删 226 | * 设置假种子 227 | */ 228 | static setFakeSeed( 229 | /** 要设置的假种子 */ 230 | seed: number | undefined 231 | ): void; 232 | 233 | /** 234 | * @deprecated 已删 235 | * 启用错误方块清理 236 | */ 237 | static setUnknownBlockCleaner(): void; 238 | 239 | /** 强制生成实体 */ 240 | static spawnEntity( 241 | /** 生成坐标 */ 242 | pos: FloatPos, 243 | /** 实体命名空间ID */ 244 | name: string 245 | ): Entity; 246 | 247 | /** 射弹投射物 */ 248 | static shootProjectile( 249 | /** 实体对象 */ 250 | entity: Entity, 251 | /** 投射物命名空间ID */ 252 | proj: string, 253 | /** 速度 */ 254 | speed: number, 255 | /** 偏移量 */ 256 | offset: number 257 | ): boolean; 258 | 259 | /** 投掷实体 */ 260 | static throwEntity( 261 | /** 实体对象 */ 262 | entity: Entity, 263 | /** 被投掷的实体 */ 264 | proj: Entity, 265 | /** 速度 */ 266 | speed: number, 267 | /** 偏移量 */ 268 | offset: number 269 | ): boolean; 270 | 271 | /** 获取服务器使用的语言 */ 272 | static getServerLanguage(): string; 273 | 274 | /** 设置服务器使用的语言 */ 275 | static setServerLanguage( 276 | language: string 277 | ): boolean; 278 | 279 | /** 设置资源包路径 */ 280 | static setCustomPackPath( 281 | /** 要设置的路径 */ 282 | path: string 283 | ): void; 284 | 285 | /** 翻译资源包文本 */ 286 | static resourcePackTranslate( 287 | /** 键名 */ 288 | key: string, 289 | /** 参数 */ 290 | params: string[] | undefined 291 | ): string; 292 | 293 | /** 根据uuid获取玩家对象 */ 294 | static getPlayerFromUuid( 295 | uuid: string 296 | ): Player; 297 | 298 | /** 根据UniqueId获取玩家对象 */ 299 | static getPlayerFromUniqueId( 300 | uniqueId: string | number 301 | ): Player; 302 | 303 | /** 根据UniqueId获取实体对象 */ 304 | static getEntityFromUniqueId( 305 | uniqueId: string | number 306 | ): Entity; 307 | 308 | /** 获取方块runtimeId */ 309 | static getBlockRuntimeId( 310 | /** 方块命名空间ID */ 311 | block: string, 312 | /** 方块的特殊值 */ 313 | legacyData: Number | undefined 314 | ): number; 315 | 316 | /** 添加虚假列表玩家 */ 317 | static addFakeList( 318 | /** 虚假玩家的名字 */ 319 | name: string, 320 | /** 虚假玩家的xuid */ 321 | xuid: string 322 | ): boolean; 323 | 324 | /** 移除虚假列表玩家 */ 325 | static removeFakeList( 326 | /** 虚假的玩家名字或xuid */ 327 | nameOrXuid: string 328 | ): boolean; 329 | 330 | /** 移除所有虚假列表玩家 */ 331 | static removeAllFakeLists(): boolean; 332 | 333 | /** 334 | * @deprecated 已删 335 | * 启用I18n修复 336 | */ 337 | static setFixI18nEnabled(): void; 338 | 339 | /** 保存NBT至文件 */ 340 | static saveNbtToFile( 341 | /** 文件路径 */ 342 | path: string, 343 | /** NBT对象 */ 344 | nbt: NbtCompound, 345 | /** 是否写入为二进制 */ 346 | isBinary: boolean | undefined 347 | ): boolean; 348 | 349 | /** 从文件读取NBT */ 350 | static readNbtFromFile( 351 | /** 文件路径 */ 352 | path: string, 353 | /** 是否以二进制方式读取 */ 354 | isBinary: boolean | undefined 355 | ): NbtCompound; 356 | 357 | /** 根据命名空间ID获取翻译键名 */ 358 | static getBlockTranslateKeyFromName( 359 | /** 方块命名空间ID */ 360 | name: string 361 | ): string; 362 | 363 | /** 获取存档种子 */ 364 | static getLevelSeed(): string; 365 | 366 | /** 获取方块亮度 */ 367 | static getBlockLightEmission( 368 | /** 方块的命名空间ID */ 369 | block: string, 370 | /** 方块的特殊值 */ 371 | legacyData: number 372 | ): number; 373 | 374 | /** 获取游戏规则列表 */ 375 | static getGameRules(): { Name: string; Value: boolean | number; }[]; 376 | 377 | /** 获取附魔名字和等级 */ 378 | static getEnchantNameAndLevel( 379 | /** 附魔命名空间ID */ 380 | typeName: string, 381 | /** 附魔的等级 */ 382 | level: number 383 | ): string; 384 | 385 | /** 通过附魔ID获取附魔命名空间ID */ 386 | static getEnchantTypeNameFromId( 387 | /** 附魔ID */ 388 | id: number 389 | ): string | null; 390 | 391 | /** 获取最大玩家数 */ 392 | static getMaxPlayers(): number; 393 | 394 | /** 设置最大玩家数 */ 395 | static setMaxPlayers( 396 | /** 最大玩家数 */ 397 | count: number, 398 | /** 是否忽略原版限制 */ 399 | ignoreVanillaLimit?: boolean 400 | ): void; 401 | 402 | /** 玩家是否拥有NBT */ 403 | static hasPlayerNbt( 404 | /** 玩家的uuid */ 405 | uuid: string 406 | ): boolean; 407 | 408 | /** 获取游戏难度 */ 409 | static getGameDifficulty(): -1 | 0 | 1 | 2 | 3; 410 | 411 | /** 设置游戏难度 */ 412 | static setGameDifficulty( 413 | /** 游戏难度 */ 414 | difficulty: 0 | 1 | 2 | 3 415 | ): void; 416 | 417 | /** 获取默认游戏模式 */ 418 | static getDefaultGameMode(): -1 | 0 | 1 | 2 | 5 | 6; 419 | 420 | /** 设置默认游戏模式 */ 421 | static setDefaultGameMode( 422 | /** 游戏模式 */ 423 | gameMode: 0 | 1 | 2 | 5 | 6 424 | ): void; 425 | } 426 | 427 | /** 合成表类 */ 428 | export class Recipes { 429 | private constructor(); 430 | 431 | /** 注销合成表 */ 432 | static unregisterRecipe( 433 | /** 合成表唯一标识符 */ 434 | recipeId: string 435 | ): boolean; 436 | 437 | /** 注册切石机合成表 */ 438 | static registerStoneCutterRecipe( 439 | /** 合成表唯一标识符 */ 440 | recipeId: string, 441 | /** 输入物品 */ 442 | inputName: string, 443 | /** 输入物品额外数据 */ 444 | inputAux: number, 445 | /** 合成结果 */ 446 | outputName: string, 447 | /** 合成结果额外数据 */ 448 | outputAux: number, 449 | /** 合成数量 */ 450 | outputCount: number 451 | ): boolean; 452 | 453 | /** 注册锻造纹饰合成表 */ 454 | static registerSmithingTrimRecipe( 455 | /** 合成表唯一标识符 */ 456 | recipeId: string, 457 | /** 锻造模板 */ 458 | template: string, 459 | /** 基础材料 */ 460 | base: string, 461 | /** 纹饰材料 */ 462 | addition: string 463 | ): boolean; 464 | 465 | /** 注册锻造配方合成表 */ 466 | static registerSmithingTransformRecipe( 467 | /** 合成表唯一标识符 */ 468 | recipeId: string, 469 | /** 锻造模板 */ 470 | template: string, 471 | /** 基础材料 */ 472 | base: string, 473 | /** 升级材料 */ 474 | addition: string, 475 | /** 合成结果 */ 476 | result: string 477 | ): boolean; 478 | 479 | /** 注册酿造容器表 */ 480 | static registerBrewingContainerRecipe( 481 | /** 合成表唯一标识符 */ 482 | recipeId: string, 483 | /** 输入物品 */ 484 | input: string, 485 | /** 合成结果 */ 486 | output: string, 487 | /** 酿造物品 */ 488 | reagent: string 489 | ): boolean; 490 | 491 | /** 注册酿造混合表 */ 492 | static registerBrewingMixRecipe( 493 | /** 合成表唯一标识符 */ 494 | recipeId: string, 495 | /** 输入物品 */ 496 | input: string, 497 | /** 合成结果 */ 498 | output: string, 499 | /** 酿造物品 */ 500 | reagent: string 501 | ): boolean; 502 | 503 | /** 注册熔炼合成表 */ 504 | static registerFurnaceRecipe( 505 | /** 合成表唯一标识符 */ 506 | recipeId: string, 507 | /** 输入物品 */ 508 | input: string, 509 | /** 合成结果 */ 510 | output: string, 511 | /** 材料的标签数组 */ 512 | tags: ("furnace" | "blast_furnace" | "smoker" | "campfire" | "soul_campfire")[] | undefined 513 | ): boolean; 514 | 515 | /** 注册有序合成表 */ 516 | static registerShapedRecipe( 517 | /** 合成表唯一标识符 */ 518 | recipeId: string, 519 | /** 合成表摆放方式,数组元素为字符串 */ 520 | shape: [string, string, string], 521 | /** 材料数组 */ 522 | ingredients: string[], 523 | /** 合成结果 */ 524 | result: string, 525 | /** 合成结果的数量 */ 526 | count: number | undefined, 527 | /** 解锁条件(也可以填物品命名空间ID) */ 528 | unlock: "AlwaysUnlocked" | "PlayerHasManyItems" | "PlayerInWater" | "None" | undefined 529 | ): boolean; 530 | 531 | /** 注册无序合成表 */ 532 | static registerShapelessRecipe( 533 | /** 合成表唯一标识符 */ 534 | recipeId: string, 535 | /** 合成材料 */ 536 | ingredients: string[], 537 | /** 合成结果 */ 538 | result: string, 539 | /** 合成结果的数量 */ 540 | count: number | undefined, 541 | /** 解锁条件(也可以填物品命名空间ID) */ 542 | unlock: "AlwaysUnlocked" | "PlayerHasManyItems" | "PlayerInWater" | "None" | undefined 543 | ): boolean; 544 | 545 | /** 注册自定义有序合成表 */ 546 | static registerCustomShapedRecipe( 547 | /** 合成表唯一标识符 */ 548 | recipeId: string, 549 | /** 合成表摆放方式,数组元素为字符串 */ 550 | shape: [string, string, string], 551 | /** 材料数组 */ 552 | ingredients: string[], 553 | /** 合成结果 */ 554 | result: Item 555 | ): boolean; 556 | 557 | /** 注册自定义无序合成表 */ 558 | static registerCustomShapelessRecipe( 559 | /** 合成表唯一标识符 */ 560 | recipeId: string, 561 | /** 合成材料 */ 562 | ingredients: string[], 563 | /** 合成结果 */ 564 | result: Item 565 | ): boolean; 566 | } 567 | 568 | /** 实验性功能类 */ 569 | export class Experiments { 570 | private constructor(); 571 | 572 | /** 获取所有实验的id */ 573 | static getAllExperimentIds(): number[]; 574 | 575 | /** 获取实验性功能文本的键名 */ 576 | static getExperimentTranslateKey( 577 | /** 实验性功能的id */ 578 | id: number 579 | ): string; 580 | 581 | /** 获取实验性功能启用状态 */ 582 | static getExperimentEnabled( 583 | /** 实验性功能的id */ 584 | id: number 585 | ): boolean; 586 | 587 | /** 设置实验性功能启用状态 */ 588 | static setExperimentEnabled( 589 | /** 实验性功能的id */ 590 | id: number, 591 | /** 实验性功能是否开启 */ 592 | value: boolean | undefined 593 | ): void; 594 | 595 | /** 设置实验性依赖 */ 596 | static registerExperimentsRequire( 597 | /** 实验性功能的id */ 598 | id: number, 599 | ): void 600 | } 601 | 602 | /** 计分板类 */ 603 | export class Scoreboard { 604 | private constructor(); 605 | 606 | /** 获取所有跟踪实体 */ 607 | static getAllTrackedEntities(): string[]; 608 | 609 | /** 获取所有跟踪的玩家 */ 610 | static getAllTrackedPlayers(): string[]; 611 | 612 | /** 获取所有跟踪的字符串 */ 613 | static getAllTrackedFakePlayers(): string[]; 614 | 615 | /** 获取所有跟踪目标 */ 616 | static getAllTrackedTargets(): ({ Type: "Player"; Uuid: string; } | { Type: "FakePlayer"; Name: string; } | { Type: "Entity"; UniqueId: string; })[] 617 | 618 | /** 创建计分板 */ 619 | static addObjective( 620 | /** 计分板名字 */ 621 | name: string, 622 | /** 显示名称 */ 623 | displayName: string, 624 | ): boolean; 625 | 626 | /** 移除计分板 */ 627 | static removeObjective( 628 | /** 计分板名字 */ 629 | name: string 630 | ): boolean; 631 | 632 | /** 获取所有计分板名字 */ 633 | static getAllObjectives(): string[]; 634 | 635 | /** 获取计分板显示名称 */ 636 | static getDisplayName( 637 | /** 计分板名字 */ 638 | objective: string 639 | ): string; 640 | 641 | /** 设置计分板显示名称 */ 642 | static setDisplayName( 643 | /** 计分板名字 */ 644 | objective: string, 645 | /** 显示名称 */ 646 | displayName: string 647 | ): boolean; 648 | 649 | /** 设置计分板显示 */ 650 | static setDisplay( 651 | /** 计分板名字 */ 652 | objective: string, 653 | /** 显示位置 */ 654 | slot: "sidebar" | "list" | "belowName", 655 | /** 排序方式 */ 656 | order: 0 | 1 657 | ): void; 658 | 659 | /** 清除计分板显示 */ 660 | static clearDisplay( 661 | /** 计分板名字 */ 662 | objective: string 663 | ): void; 664 | 665 | /** 获取玩家在计分板中的值 */ 666 | static getPlayerScore( 667 | /** 玩家的uuid */ 668 | uuid: string, 669 | /** 计分板名字 */ 670 | objective: string 671 | ): number | null; 672 | 673 | /** 增加玩家在计分板中的值 */ 674 | static addPlayerScore( 675 | /** 玩家的uuid */ 676 | uuid: string, 677 | /** 计分板名字 */ 678 | objective: string, 679 | /** 增加的值 */ 680 | value: number 681 | ): boolean; 682 | 683 | /** 减少玩家在计分板中的值 */ 684 | static reducePlayerScore( 685 | /** 玩家的uuid */ 686 | uuid: string, 687 | /** 计分板名字 */ 688 | objective: string, 689 | /** 减少的值 */ 690 | value: number 691 | ): boolean; 692 | 693 | /** 设置玩家在计分板中的值 */ 694 | static setPlayerScore( 695 | /** 玩家的uuid */ 696 | uuid: string, 697 | /** 计分板名字 */ 698 | objective: string, 699 | /** 设置的值 */ 700 | value: number 701 | ): boolean; 702 | 703 | /** 重载玩家在计分板中的数据 */ 704 | static resetPlayerScore( 705 | /** 玩家的uuid */ 706 | uuid: string, 707 | /** 计分板名字 */ 708 | objective: string 709 | ): boolean; 710 | 711 | /** 重置玩家所有计分板的数据 */ 712 | static resetPlayerScores( 713 | /** 玩家的uuid */ 714 | uuid: string 715 | ): boolean; 716 | 717 | /** 获取字符串在计分板中的值 */ 718 | static getFakePlayerScore( 719 | /** 字符串名字 */ 720 | name: string, 721 | /** 计分板名字 */ 722 | objective: string 723 | ): number | null; 724 | 725 | /** 增加字符串在计分板中的值 */ 726 | static addFakePlayerScore( 727 | /** 字符串名字 */ 728 | name: string, 729 | /** 计分板名字 */ 730 | objective: string, 731 | /** 增加的值 */ 732 | value: number 733 | ): boolean; 734 | 735 | /** 减少字符串在计分板中的值 */ 736 | static reduceFakePlayerScore( 737 | /** 字符串名字 */ 738 | name: string, 739 | /** 计分板名字 */ 740 | objective: string, 741 | /** 减少的值 */ 742 | value: number 743 | ): boolean; 744 | 745 | /** 设置字符串在计分板中的值 */ 746 | static setFakePlayerScore( 747 | /** 字符串名字 */ 748 | name: string, 749 | /** 计分板名字 */ 750 | objective: string, 751 | /** 设置的值 */ 752 | value: number 753 | ): boolean; 754 | 755 | /** 重载字符串在计分板中的数据 */ 756 | static resetFakePlayerScore( 757 | /** 字符串名字 */ 758 | name: string, 759 | /** 计分板名字 */ 760 | objective: string 761 | ): boolean; 762 | 763 | /** 重载字符串所有计分板数据 */ 764 | static resetAllFakePlayerScores( 765 | /** 字符串名字 */ 766 | name: string 767 | ): boolean; 768 | 769 | /** 获取实体在计分板中的值 */ 770 | static getEntityScore( 771 | /** 实体的uniqueId */ 772 | uniqueId: string, 773 | /** 计分板名字 */ 774 | objective: string 775 | ): number | null; 776 | 777 | /** 增加实体在计分板中的值 */ 778 | static addEntityScore( 779 | /** 实体的uniqueId */ 780 | uniqueId: string, 781 | /** 计分板名字 */ 782 | objective: string, 783 | /** 增加的值 */ 784 | value: number 785 | ): boolean; 786 | 787 | /** 减少实体在计分板中的值 */ 788 | static reduceEntityScore( 789 | /** 实体的uniqueId */ 790 | uniqueId: string, 791 | /** 计分板名字 */ 792 | objective: string, 793 | /** 减少的值 */ 794 | value: number 795 | ): boolean; 796 | 797 | /** 设置实体在计分板中的值 */ 798 | static setEntityScore( 799 | /** 实体的uniqueId */ 800 | uniqueId: string, 801 | /** 计分板名字 */ 802 | objective: string, 803 | /** 设置的值 */ 804 | value: number 805 | ): boolean; 806 | 807 | /** 重载实体在计分板中的数据 */ 808 | static resetEntityScore( 809 | /** 实体的uniqueId */ 810 | uniqueId: string, 811 | /** 计分板名字 */ 812 | objective: string 813 | ): boolean; 814 | 815 | /** 重载实体所有计分板数据 */ 816 | static resetAllEntityScores( 817 | /** 实体的uniqueId */ 818 | uniqueId: string 819 | ): boolean; 820 | } 821 | 822 | /** 仿LSE的JsonConfigFile类 */ 823 | export class JsonConfig { 824 | constructor( 825 | /** 文件路径 */ 826 | path: string, 827 | /** 默认数据 */ 828 | defaultData: object | undefined 829 | ); 830 | 831 | /** 初始化文件 */ 832 | init(): void; 833 | 834 | /** 保存文件 */ 835 | save( 836 | /** 缩进 */ 837 | format: number | undefined 838 | ): void; 839 | 840 | /** 获取所有数据 */ 841 | getData(): Record; 842 | 843 | /** 读取数据 */ 844 | get( 845 | /** 键名 */ 846 | key: string, 847 | /** 不存在返回值 */ 848 | defaultValue: T 849 | ): T; 850 | 851 | /** 设置数据 */ 852 | set( 853 | /** 键名 */ 854 | key: string, 855 | /** 值 */ 856 | value: any 857 | ): void; 858 | 859 | /** 删除数据 */ 860 | delete( 861 | /** 键名 */ 862 | key: string 863 | ): void; 864 | } 865 | 866 | /** JSON语言文件 */ 867 | export class JsonLanguage extends JsonConfig { 868 | /** 创建或打开一个 Json 语言文件 */ 869 | constructor( 870 | /** 文件路径 */ 871 | path: string, 872 | /** 默认数据 */ 873 | defaultData: object | undefined 874 | ); 875 | 876 | /** 翻译键名 */ 877 | translate( 878 | /** 键名 */ 879 | key: string, 880 | /** 替换参数 */ 881 | data: string[] 882 | ): string; 883 | } 884 | 885 | /** JSON版翻译类 */ 886 | export class JsonI18n { 887 | /** 加载翻译数据目录 */ 888 | constructor( 889 | /** 目录 */ 890 | path: string, 891 | /** 默认语言 */ 892 | localLangCode: string | undefined 893 | ); 894 | 895 | /** 加载所有语言 */ 896 | loadAllLanguage(): void; 897 | 898 | /** 加载语言 */ 899 | loadLanguage( 900 | /** 语言标识符 */ 901 | langCode: string, 902 | /** 默认数据 */ 903 | defaultData: object | undefined 904 | ): void; 905 | 906 | /** 设置语言 */ 907 | chooseLanguage( 908 | /** 语言标识符 */ 909 | langCode: string 910 | ): void; 911 | 912 | /** 设置默认语言 */ 913 | setDefaultLanguage( 914 | /** 语言标识符 */ 915 | langCode: string 916 | ): void; 917 | 918 | /** 翻译键名 */ 919 | translate( 920 | /** 键名 */ 921 | key: string, 922 | /** 替换参数 */ 923 | data: string[], 924 | /** 语言标识符 */ 925 | langCode: string | undefined 926 | ): string; 927 | } 928 | 929 | /** 版本类 */ 930 | export class Version { 931 | /** 创建版本对象 */ 932 | constructor( 933 | /** 主版本号 */ 934 | major: number, 935 | /** 次版本号 */ 936 | minor: number, 937 | /** 修订版本号 */ 938 | revision: number, 939 | ); 940 | 941 | /** 转换成字符串 */ 942 | toString( 943 | /** 是否添加前缀"v" */ 944 | prefix: boolean | undefined 945 | ): string; 946 | 947 | /** 转换成数组 */ 948 | toArray(): [number, number, number]; 949 | 950 | /** 转换成数字 */ 951 | valueOf(): number; 952 | 953 | /** 从字符串中创建版本对象 */ 954 | static fromString( 955 | /** 字符串 */ 956 | version: string 957 | ): Version; 958 | 959 | /** 从数组中创建版本对象 */ 960 | static fromArray( 961 | /** 数组 */ 962 | version: [number, number, number] 963 | ): Version; 964 | 965 | /** 检测LRCA版本是否大于或等于此版本 */ 966 | static isPluginVersionMatched( 967 | /** 比较版本号 */ 968 | version: Version 969 | ); 970 | 971 | /** 获取LRCA版本对象 */ 972 | static getLrcaVersion(): Version; 973 | 974 | /** 获取GMLIB版本对象 */ 975 | static getGmlibVersion(): Version; 976 | } 977 | 978 | /** 翻译API类 */ 979 | export class I18nAPI { 980 | private constructor(); 981 | 982 | /** 获取键翻译 */ 983 | static get( 984 | /** 键名 */ 985 | key: string, 986 | /** 翻译参数 */ 987 | params: string[] | undefined, 988 | /** 语言标识符 */ 989 | langCode: string | undefined 990 | ): string; 991 | 992 | /** 获取键翻译 */ 993 | static translate( 994 | /** 键名 */ 995 | key: string, 996 | /** 翻译参数 */ 997 | params: string[] | undefined, 998 | /** 语言标识符 */ 999 | langCode: string | undefined 1000 | ): string; 1001 | 1002 | /** 获取支持的语言标识符 */ 1003 | static getSupportedLanguages(): string[]; 1004 | 1005 | /** 获取资源包默认语言 */ 1006 | static getCurrentLanguage(): string; 1007 | 1008 | /** 设置资源包默认语言 */ 1009 | static chooseLanguage( 1010 | /** 要设置的语言标识符 */ 1011 | language: string 1012 | ): void; 1013 | 1014 | /** 加载语言数据 */ 1015 | static loadLanguage( 1016 | /** 语言数据 */ 1017 | code: string, 1018 | /** 语言标识符 */ 1019 | language: string 1020 | ): void; 1021 | 1022 | /** 更新或创建语言文件 */ 1023 | static updateOrCreateLanguageFile( 1024 | /** 语言数据 */ 1025 | code: string, 1026 | /** 语言标识符 */ 1027 | language: string, 1028 | /** 文件路径 */ 1029 | path: string 1030 | ): void; 1031 | 1032 | /** 加载语言目录 */ 1033 | static loadLanguageDirectory( 1034 | /** 语言数据目录 */ 1035 | path: string 1036 | ): void; 1037 | } 1038 | 1039 | /** 玩家信息存储类 */ 1040 | export class UserCache { 1041 | private constructor(); 1042 | 1043 | /** 根据uuid查xuid */ 1044 | static getXuidByUuid( 1045 | /** uuid */ 1046 | uuid: string 1047 | ): string; 1048 | 1049 | /** 根据xuid查uuid */ 1050 | static getUuidByXuid( 1051 | /** xuid */ 1052 | xuid: string 1053 | ): string; 1054 | 1055 | /** 根据xuid查玩家名 */ 1056 | static getNameByUuid( 1057 | /** xuid */ 1058 | xuid: string 1059 | ): string; 1060 | 1061 | /** 根据xuid查玩家名 */ 1062 | static getNameByXuid( 1063 | /** xuid */ 1064 | xuid: string 1065 | ): string; 1066 | 1067 | /** 根据玩家名查xuid */ 1068 | static getXuidByName( 1069 | /** 玩家名 */ 1070 | name: string 1071 | ): string; 1072 | 1073 | /** 根据玩家名查uuid */ 1074 | static getUuidByName( 1075 | /** 玩家名 */ 1076 | name: string 1077 | ): string; 1078 | 1079 | /** 获取玩家信息 */ 1080 | static getPlayerInfo( 1081 | /** 玩家名 或 xuid 或 uuid 或 serverId 或 uniqueId */ 1082 | playerIdentifier: string 1083 | ): { Xuid: string, Uuid: string, Name: string, ServerId: string, ActorUniqueID: string } | null; 1084 | 1085 | /** 获取所有玩家信息 */ 1086 | static getAllPlayerInfo(): { Xuid: string, Uuid: string, Name: string, ServerId: string, ActorUniqueID: string }[] 1087 | } 1088 | 1089 | type PacketDataItem = ( 1090 | { 1091 | id: number, 1092 | type: 0x0 | 0x1 | 0x2 | 0x3 | 0x7, 1093 | value: number 1094 | } 1095 | | { 1096 | id: number, 1097 | type: 0x4, 1098 | value: string 1099 | } 1100 | | { 1101 | id: number, 1102 | type: 0x5, 1103 | value: NbtCompound 1104 | } 1105 | | { 1106 | id: number, 1107 | type: 0x6 | 0x8, 1108 | value: IntPos | FloatPos 1109 | } 1110 | ); 1111 | 1112 | type PacketData = ( 1113 | | { type: "", value: PacketData | PacketData[] } 1114 | | { type: "Item", value: Item } 1115 | | { type: "CompoundTag", value: NbtCompound } 1116 | | { 1117 | type: "DataItem", 1118 | value: PacketDataItem[], 1119 | } 1120 | | { 1121 | type: "ActorLink", 1122 | value: { 1123 | mA: number, 1124 | mB: number, 1125 | mType: number, 1126 | mImmediate: boolean, 1127 | mPassengerInitiated: boolean, 1128 | }, 1129 | } 1130 | | { type: "Vec3" | "BlockPos", value: FloatPos | IntPos } 1131 | | { type: "Vec2", value: DirectionAngle } 1132 | | { type: "String" | "Uuid", value: string } 1133 | | { type: "Bool", value: boolean } 1134 | | { 1135 | type: 1136 | "PacketHeader" 1137 | | "Byte" 1138 | | "Double" 1139 | | "Float" 1140 | | "SignedBigEndianInt" 1141 | | "SignedInt" 1142 | | "SignedInt64" 1143 | | "SignedShort" 1144 | | "UnsignedChar" 1145 | | "UnsignedInt" 1146 | | "UnsignedInt64" 1147 | | "UnsignedShort" 1148 | | "UnsignedVarInt" 1149 | | "UnsignedVarInt64" 1150 | | "VarInt" 1151 | | "VarInt64", 1152 | value: number, 1153 | } 1154 | ); 1155 | 1156 | /** 二进制流数据包类 */ 1157 | export class GMLIB_BinaryStream { 1158 | /** 数据包ID */ 1159 | #id: number; 1160 | /** 数据包是否被销毁 */ 1161 | #destroy: boolean; 1162 | 1163 | /** 构造二进流数据包 */ 1164 | constructor( 1165 | /** 数据包数据 */ 1166 | data: PacketData[]? 1167 | ); 1168 | 1169 | /** 拷贝二进制流数据包 */ 1170 | constructor( 1171 | /** 要拷贝的二进制流数据包 */ 1172 | stream: GMLIB_BinaryStream 1173 | ); 1174 | 1175 | /** 获取数据包的ID */ 1176 | getId(): number; 1177 | 1178 | /** 发送数据包 */ 1179 | sendTo( 1180 | /** 要发送数据包的玩家对象 */ 1181 | player: Player | Entity, 1182 | /** 数据包发送后是否销毁 */ 1183 | free: boolean = true 1184 | ): GMLIB_BinaryStream; 1185 | 1186 | /** 发送数据包到玩家数组 */ 1187 | sendToPlayers( 1188 | /** 要发送数据包的玩家对象数组 */ 1189 | players: Player[] | Entity[], 1190 | /** 数据包发送后是否销毁 */ 1191 | free: boolean = true 1192 | ): GMLIB_BinaryStream; 1193 | 1194 | /** 发送数据包到所有玩家 */ 1195 | sendToAll( 1196 | /** 数据包发送后是否销毁 */ 1197 | free: boolean = true 1198 | ): GMLIB_BinaryStream; 1199 | 1200 | /** 发送数据包到维度 */ 1201 | sendToDimension( 1202 | /** 维度ID */ 1203 | dimid: number, 1204 | /** 数据包发送后是否销毁 */ 1205 | free: boolean = true 1206 | ): GMLIB_BinaryStream; 1207 | 1208 | /** 销毁数据包 */ 1209 | destroy(): GMLIB_BinaryStream; 1210 | 1211 | /** 数据包是否已被销毁 */ 1212 | isDestroy(): boolean; 1213 | 1214 | /** 重置数据包 */ 1215 | reset(): GMLIB_BinaryStream; 1216 | 1217 | /** 转换成字符串 */ 1218 | toString(): string; 1219 | 1220 | /** 写入数据 */ 1221 | write( 1222 | /** 数据 */ 1223 | data: PacketData | PacketData[]? 1224 | ): GMLIB_BinaryStream; 1225 | 1226 | /** 写入数据包头部 */ 1227 | writePacketHeader( 1228 | /** 数据包ID */ 1229 | id: number 1230 | ): GMLIB_BinaryStream; 1231 | 1232 | /** 写入UUID */ 1233 | writeUuid( 1234 | /** UUID */ 1235 | value: string 1236 | ): GMLIB_BinaryStream; 1237 | 1238 | /** 写入物品 */ 1239 | writeItem( 1240 | /** 物品对象 */ 1241 | value: Item 1242 | ): GMLIB_BinaryStream; 1243 | 1244 | /** 写入NBT */ 1245 | writeCompoundTag( 1246 | /** NBT */ 1247 | value: NbtCompound 1248 | ): GMLIB_BinaryStream; 1249 | 1250 | /** */ 1251 | writeDataItem( 1252 | /** 数据项 */ 1253 | value: PacketDataItem[] 1254 | ): GMLIB_BinaryStream; 1255 | 1256 | writeActorLink( 1257 | /** 数据项 */ 1258 | value: { "mA": number, "mB": number, "mType": number, "mImmediate": boolean, "mPassengerInitiated": boolean } 1259 | ): GMLIB_BinaryStream; 1260 | 1261 | /** 写入浮点数坐标对象 */ 1262 | writeVec3( 1263 | /** 浮点数坐标对象 */ 1264 | value: FloatPos 1265 | ): GMLIB_BinaryStream; 1266 | 1267 | /** 写入整数坐标对象 */ 1268 | writeBlockPos( 1269 | /** 整数坐标对象 */ 1270 | value: IntPos 1271 | ): GMLIB_BinaryStream; 1272 | 1273 | /** */ 1274 | writeVec2( 1275 | /** 数据 */ 1276 | value: { "x": number, "z": number } 1277 | ): GMLIB_BinaryStream; 1278 | 1279 | /** 写入字符串 */ 1280 | writeString( 1281 | /** 字符串 */ 1282 | value: string 1283 | ): GMLIB_BinaryStream; 1284 | 1285 | /** 写入布尔值 */ 1286 | writeBool( 1287 | /** 布尔值 */ 1288 | value: boolean 1289 | ): GMLIB_BinaryStream; 1290 | 1291 | /** 写入字节 */ 1292 | writeByte( 1293 | /** 字节 */ 1294 | value: number 1295 | ): GMLIB_BinaryStream; 1296 | 1297 | /** 写入(双精度)浮点数 */ 1298 | writeDouble( 1299 | /** 浮点数 */ 1300 | value: number 1301 | ): GMLIB_BinaryStream; 1302 | 1303 | /** 写入(单精度)浮点数 */ 1304 | writeFloat( 1305 | /** 浮点数 */ 1306 | value: number 1307 | ): GMLIB_BinaryStream; 1308 | 1309 | /** */ 1310 | writeSignedBigEndianInt( 1311 | /** 数值 */ 1312 | value: number 1313 | ): GMLIB_BinaryStream; 1314 | 1315 | /** */ 1316 | writeSignedInt( 1317 | /** 数值 */ 1318 | value: number 1319 | ): GMLIB_BinaryStream; 1320 | 1321 | /** 写入 */ 1322 | writeSignedInt64( 1323 | /** 数值 */ 1324 | value: number 1325 | ): GMLIB_BinaryStream; 1326 | 1327 | /** */ 1328 | writeSignedShort( 1329 | /** 数值 */ 1330 | value: number 1331 | ): GMLIB_BinaryStream; 1332 | 1333 | /** */ 1334 | writeUnsignedChar( 1335 | /** 数值 */ 1336 | value: number 1337 | ): GMLIB_BinaryStream; 1338 | 1339 | /** */ 1340 | writeUnsignedInt( 1341 | /** 数值 */ 1342 | value: number 1343 | ): GMLIB_BinaryStream; 1344 | 1345 | /** */ 1346 | writeUnsignedInt64( 1347 | /** 数值 */ 1348 | value: number 1349 | ): GMLIB_BinaryStream; 1350 | 1351 | /** */ 1352 | writeUnsignedShort( 1353 | /** 数值 */ 1354 | value: number 1355 | ): GMLIB_BinaryStream; 1356 | 1357 | /** */ 1358 | writeUnsignedVarInt( 1359 | /** 数值 */ 1360 | value: number 1361 | ): GMLIB_BinaryStream; 1362 | 1363 | /** */ 1364 | writeUnsignedVarInt64( 1365 | /** 数值 */ 1366 | value: number 1367 | ): GMLIB_BinaryStream; 1368 | 1369 | /** */ 1370 | writeVarInt( 1371 | /** 数值 */ 1372 | value: number 1373 | ): GMLIB_BinaryStream; 1374 | 1375 | /** */ 1376 | writeVarInt64( 1377 | /** 数值 */ 1378 | value: number 1379 | ): GMLIB_BinaryStream; 1380 | } 1381 | 1382 | export enum ActorType { 1383 | Undefined = 1, 1384 | TypeMask = 255, 1385 | Mob = 256, 1386 | PathfinderMob = 768, 1387 | Monster = 2816, 1388 | Animal = 4864, 1389 | TamableAnimal = 21248, 1390 | Ambient = 33024, 1391 | UndeadMob = 68352, 1392 | ZombieMonster = 199424, 1393 | Arthropod = 264960, 1394 | Minecart = 524288, 1395 | SkeletonMonster = 1116928, 1396 | EquineAnimal = 2118400, 1397 | Projectile = 4194304, 1398 | AbstractArrow = 8388608, 1399 | WaterAnimal = 8960, 1400 | VillagerBase = 16777984, 1401 | Chicken = 4874, 1402 | Cow = 4875, 1403 | Pig = 4876, 1404 | Sheep = 4877, 1405 | Wolf = 21262, 1406 | Villager = 16777999, 1407 | MushroomCow = 4880, 1408 | Squid = 8977, 1409 | Rabbit = 4882, 1410 | Bat = 33043, 1411 | IronGolem = 788, 1412 | SnowGolem = 789, 1413 | Ocelot = 21270, 1414 | Horse = 2118423, 1415 | PolarBear = 4892, 1416 | Llama = 4893, 1417 | Parrot = 21278, 1418 | Dolphin = 8991, 1419 | Donkey = 2118424, 1420 | Mule = 2118425, 1421 | SkeletonHorse = 2186010, 1422 | ZombieHorse = 2186011, 1423 | Zombie = 199456, 1424 | Creeper = 2849, 1425 | Skeleton = 1116962, 1426 | Spider = 264995, 1427 | PigZombie = 68388, 1428 | Slime = 2853, 1429 | EnderMan = 2854, 1430 | Silverfish = 264999, 1431 | CaveSpider = 265000, 1432 | Ghast = 2857, 1433 | LavaSlime = 2858, 1434 | Blaze = 2859, 1435 | ZombieVillager = 199468, 1436 | Witch = 2861, 1437 | Stray = 1116974, 1438 | Husk = 199471, 1439 | WitherSkeleton = 1116976, 1440 | Guardian = 2865, 1441 | ElderGuardian = 2866, 1442 | Npc = 307, 1443 | WitherBoss = 68404, 1444 | Dragon = 2869, 1445 | Shulker = 2870, 1446 | Endermite = 265015, 1447 | Agent = 312, 1448 | Vindicator = 2873, 1449 | Phantom = 68410, 1450 | IllagerBeast = 2875, 1451 | ArmorStand = 317, 1452 | TripodCamera = 318, 1453 | Player = 319, 1454 | ItemEntity = 64, 1455 | PrimedTnt = 65, 1456 | FallingBlock = 66, 1457 | MovingBlock = 67, 1458 | ExperiencePotion = 4194372, 1459 | Experience = 69, 1460 | EyeOfEnder = 70, 1461 | EnderCrystal = 71, 1462 | FireworksRocket = 72, 1463 | Trident = 12582985, 1464 | Turtle = 4938, 1465 | Cat = 21323, 1466 | ShulkerBullet = 4194380, 1467 | FishingHook = 77, 1468 | Chalkboard = 78, 1469 | DragonFireball = 4194383, 1470 | Arrow = 12582992, 1471 | Snowball = 4194385, 1472 | ThrownEgg = 4194386, 1473 | Painting = 83, 1474 | LargeFireball = 4194389, 1475 | ThrownPotion = 4194390, 1476 | Enderpearl = 4194391, 1477 | LeashKnot = 88, 1478 | WitherSkull = 4194393, 1479 | BoatRideable = 90, 1480 | WitherSkullDangerous = 4194395, 1481 | LightningBolt = 93, 1482 | SmallFireball = 4194398, 1483 | AreaEffectCloud = 95, 1484 | LingeringPotion = 4194405, 1485 | LlamaSpit = 4194406, 1486 | EvocationFang = 4194407, 1487 | EvocationIllager = 2920, 1488 | Vex = 2921, 1489 | MinecartRideable = 524372, 1490 | MinecartHopper = 524384, 1491 | MinecartTNT = 524385, 1492 | MinecartChest = 524386, 1493 | MinecartFurnace = 524387, 1494 | MinecartCommandBlock = 524388, 1495 | IceBomb = 4194410, 1496 | Balloon = 107, 1497 | Pufferfish = 9068, 1498 | Salmon = 9069, 1499 | Drowned = 199534, 1500 | Tropicalfish = 9071, 1501 | Fish = 9072, 1502 | Panda = 4977, 1503 | Pillager = 2930, 1504 | VillagerV2 = 16778099, 1505 | ZombieVillagerV2 = 199540, 1506 | Shield = 117, 1507 | WanderingTrader = 886, 1508 | Lectern = 119, 1509 | ElderGuardianGhost = 2936, 1510 | Fox = 4985, 1511 | Bee = 378, 1512 | Piglin = 379, 1513 | Hoglin = 4988, 1514 | Strider = 4989, 1515 | Zoglin = 68478, 1516 | PiglinBrute = 383, 1517 | Goat = 4992, 1518 | GlowSquid = 9089, 1519 | Axolotl = 4994, 1520 | Warden = 2947, 1521 | Frog = 4996, 1522 | Tadpole = 9093, 1523 | Allay = 390, 1524 | ChestBoatRideable = 218, 1525 | TraderLlama = 5021, 1526 | Camel = 5002, 1527 | Sniffer = 5003, 1528 | Breeze = 2956, 1529 | BreezeWindChargeProjectile = 4194445, 1530 | Armadillo = 5006, 1531 | WindChargeProjectile = 4194447, 1532 | Bogged = 1117072, 1533 | OminousItemSpawner = 145, 1534 | Creaking = 2962, 1535 | HappyGhast = 5011, 1536 | } 1537 | 1538 | interface Player { 1539 | /** (GMLIB)转换成实体对象 */ 1540 | toEntity(): Entity; 1541 | 1542 | /** (GMLIB)获取玩家重生坐标 */ 1543 | getSpawnPoint(): IntPos; 1544 | 1545 | /** (GMLIB)设置玩家重生坐标 */ 1546 | setSpawnPoint( 1547 | /** 要设置的坐标对象 */ 1548 | pos: IntPos 1549 | ): void; 1550 | 1551 | /** (GMLIB)清除玩家重生点 */ 1552 | clearSpawnPoint(): void; 1553 | 1554 | /** (GMLIB)丢出玩家物品 */ 1555 | dropItem( 1556 | /** 物品对象 */ 1557 | item: Item, 1558 | /** 随机丢出位置 */ 1559 | randomly: boolean | undefined 1560 | ): boolean; 1561 | 1562 | /** (GMLIB)获取玩家的rumtimeId */ 1563 | getRuntimeId(): number; 1564 | 1565 | /** (GMLIB)获取玩家饥饿值 */ 1566 | getHungry(): number; 1567 | 1568 | /** (GMLIB)获取玩家盔甲覆盖百分比 */ 1569 | getArmorCoverPercentage(): number; 1570 | 1571 | /** (GMLIB)获取玩家盔甲值 */ 1572 | getArmorValue(): number; 1573 | 1574 | /** (GMLIB)设置玩家UI栏物品 */ 1575 | setPlayerUIItem( 1576 | /** 槽位 */ 1577 | slot: number, 1578 | /** 物品 */ 1579 | item: Item 1580 | ): void; 1581 | 1582 | /** (GMLIB)获取玩家UI栏物品 */ 1583 | getPlayerUIItem( 1584 | /** 槽位 */ 1585 | slot: number 1586 | ): Item; 1587 | 1588 | /** (GMLIB & Glacie)获取客户端版本协议*/ 1589 | getNetworkProtocolVersion(): number 1590 | 1591 | /** (GMLIB)发送更新更新物品数据包 */ 1592 | sendInventorySlotPacket( 1593 | /** 容器ID */ 1594 | containerId: number, 1595 | /** 槽位 */ 1596 | slot: number, 1597 | /** 物品 */ 1598 | item: Item 1599 | ): void; 1600 | 1601 | /** (GMLIB)获取玩家破坏方块所需时间 */ 1602 | getDestroyProgress( 1603 | /** 方块对象 */ 1604 | block: Block 1605 | ): number; 1606 | } 1607 | 1608 | interface Entity { 1609 | /** (GMLIB)射弹投射物 */ 1610 | shootProjectile( 1611 | /** 投射物命名空间ID */ 1612 | proj: string, 1613 | /** 速度 */ 1614 | speed: number | undefined, 1615 | /** 偏移量 */ 1616 | offset: number | undefined 1617 | ): boolean; 1618 | 1619 | /** (GMLIB)投掷实体 */ 1620 | throwEntity( 1621 | /** 投掷的实体对象 */ 1622 | proj: Entity, 1623 | /** 速度 */ 1624 | speed: number | undefined, 1625 | /** 偏移量 */ 1626 | offset: number | undefined 1627 | ): boolean; 1628 | 1629 | /** (GMLIB)获取实体翻译键名 */ 1630 | getTranslateKey(): string; 1631 | 1632 | /** (GMLIB)获取实体名字翻译 */ 1633 | getTranslateName( 1634 | /** 要翻译的语言 */ 1635 | langCode: string 1636 | ): string; 1637 | 1638 | /** (GMLIB)使玩家攻击实体 */ 1639 | attack( 1640 | /** 攻击的实体对象 */ 1641 | entity: Entity 1642 | ): boolean; 1643 | 1644 | /** (GMLIB) */ 1645 | pullInEntity( 1646 | /** 实体对象 */ 1647 | entity: Entity 1648 | ): boolean; 1649 | 1650 | /** (GMLIB)获取实体的rumtimeId */ 1651 | getRuntimeId(): number; 1652 | 1653 | /** (GMLIB)获取实体的命名 */ 1654 | getNameTag(): string; 1655 | 1656 | /** (GMLIB)获取实体的主人 */ 1657 | getEntityOwner(): Entity | null; 1658 | 1659 | /** (GMLIB)实体是否包含在某类里 */ 1660 | hasFamily( 1661 | /** 实体族 */ 1662 | family: string 1663 | ): boolean; 1664 | 1665 | /** (GMLIB)实体是否拥有buff效果 */ 1666 | hasEffect( 1667 | /** 效果ID */ 1668 | effectId: number 1669 | ): boolean; 1670 | 1671 | /** (GMLIB)获取buff信息 */ 1672 | getEffectInfo( 1673 | /** 效果ID */ 1674 | effectId: number 1675 | ): { 1676 | /** 效果ID */ 1677 | Id: number, 1678 | /** 效果等级 */ 1679 | Amplifier: number, 1680 | /** 持续时间 */ 1681 | Duration: number, 1682 | /** 简单难度下的持续时间 */ 1683 | DurationEasy: number, 1684 | /** 普通难度下的持续时间 */ 1685 | DurationNormal: number, 1686 | /** 困难难度下的持续时间 */ 1687 | DurationHard: number, 1688 | /** 是否为信标给予 */ 1689 | Ambient: boolean, 1690 | /** 是否显示粒子效果 */ 1691 | ShowParticles: boolean 1692 | } | null; 1693 | 1694 | /** (GMLIB)获取所有buff信息 */ 1695 | getAllEffectsInfo(): { 1696 | /** 效果ID */ 1697 | Id: number, 1698 | /** 效果等级 */ 1699 | Amplifier: number, 1700 | /** 持续时间 */ 1701 | Duration: number, 1702 | /** 简单难度下的持续时间 */ 1703 | DurationEasy: number, 1704 | /** 普通难度下的持续时间 */ 1705 | DurationNormal: number, 1706 | /** 困难难度下的持续时间 */ 1707 | DurationHard: number, 1708 | /** 是否为信标给予 */ 1709 | Ambient: boolean, 1710 | /** 是否显示粒子效果 */ 1711 | ShowParticles: boolean 1712 | }[]; 1713 | 1714 | /** 实体是否为某类型 */ 1715 | isType( 1716 | /** 实体类型 */ 1717 | type: ActorType 1718 | ): boolean; 1719 | 1720 | /** 实体是否包含某类型 */ 1721 | hasType( 1722 | /** 实体类型 */ 1723 | type: ActorType 1724 | ): boolean; 1725 | 1726 | /** 获取实体类型ID */ 1727 | getEntityTypeId(): ActorType; 1728 | } 1729 | 1730 | interface Block { 1731 | /** (GMLIB)获取方块翻译键名 */ 1732 | getTranslateKey(): string; 1733 | 1734 | /** (GMLIB)获取方块名字翻译 */ 1735 | getTranslateName( 1736 | /** 要翻译的语言 */ 1737 | langCode: string 1738 | ): string; 1739 | 1740 | /** (GMLIB)获取方块硬度 */ 1741 | getBlockDestroySpeed(): number; 1742 | 1743 | /** (GMLIB)使方块被玩家挖掘 */ 1744 | playerDestroy( 1745 | /** 挖掘的玩家对象 */ 1746 | player: Player 1747 | ): void; 1748 | 1749 | /** (GMLIB) */ 1750 | canDropWithAnyTool(): boolean; 1751 | 1752 | /** (GMLIB)检测方块是否能被玩家挖掘(比如插件拦截) */ 1753 | playerWillDestroy( 1754 | /** 挖掘的玩家对象 */ 1755 | player: Player 1756 | ): boolean; 1757 | } 1758 | 1759 | interface Item { 1760 | /** (GMLIB)获取方块翻译键名 */ 1761 | getTranslateKey(): string; 1762 | 1763 | /** (GMLIB)获取方块名字翻译 */ 1764 | getTranslateName( 1765 | /** 要翻译的语言 */ 1766 | langCode: string 1767 | ): string; 1768 | 1769 | /** (GMLIB)获取物品挖掘方块速度 */ 1770 | getDestroyBlockSpeed( 1771 | /** 挖掘的方块对象 */ 1772 | block: Block 1773 | ): number; 1774 | 1775 | /** (GMLIB)物品冒险模式下是否可以挖掘方块 */ 1776 | canDestroy( 1777 | /** 挖掘的方块对象 */ 1778 | block: Block 1779 | ): boolean; 1780 | 1781 | /** (GMLIB)物品是否能破坏方块 */ 1782 | canDestroyInCreative(): boolean; 1783 | 1784 | /** (GMLIB)物品是否可以采集方块 */ 1785 | canDestroySpecial( 1786 | /** 挖掘的方块对象 */ 1787 | block: Block 1788 | ): boolean; 1789 | 1790 | /** (GMLIB)添加附魔 */ 1791 | applyEnchant( 1792 | /** 附魔的命名空间ID */ 1793 | typeName: string, 1794 | /** 附魔等级 */ 1795 | level: number, 1796 | /** 允许非原版附魔 */ 1797 | allowNonVanilla: boolean | null 1798 | ): boolean; 1799 | 1800 | /** (GMLIB)删除所有附魔 */ 1801 | removeEnchants(): void; 1802 | 1803 | /** (GMLIB)判断是否拥有附魔 */ 1804 | hasEnchant( 1805 | /** 附魔的命名空间ID */ 1806 | typeName: string 1807 | ): boolean; 1808 | 1809 | /** (GMLIB)获取附魔等级 */ 1810 | getEnchantLevel( 1811 | /** 附魔的命名空间ID */ 1812 | typeName: string 1813 | ): number; 1814 | 1815 | /** (GMLIB)物品是否拥有不可破坏标签 */ 1816 | isUnbreakable(): boolean; 1817 | 1818 | /** (GMLIB)设置物品不可破坏标签 */ 1819 | setUnbreakable( 1820 | /** 是否不可破坏 */ 1821 | unbreakable: boolean 1822 | ): void; 1823 | 1824 | /** (GMLIB)物品是否拥有死亡不掉落标签 */ 1825 | getShouldKeepOnDeath(): boolean; 1826 | 1827 | /** (GMLIB)设置物品死亡不掉落标签 */ 1828 | setShouldKeepOnDeath( 1829 | /** 物品是否死亡不掉落 */ 1830 | value: boolean 1831 | ): void; 1832 | 1833 | /** (GMLIB)获取物品的锁定模式 0:无 1:锁定在格子里 2:锁定在背包里 */ 1834 | getItemLockMode(): 0 | 1 | 2; 1835 | 1836 | /** (GMLIB)设置物品的锁定模式 0:无 1:锁定在格子里 2:锁定在背包里 */ 1837 | setItemLockMode( 1838 | /** 锁定模式 */ 1839 | mode: 0 | 1 | 2 1840 | ): void; 1841 | 1842 | /** (GMLIB)获取物品的惩罚等级 */ 1843 | getRepairCost(): number; 1844 | 1845 | /** (GMLIB)设置物品的惩罚等级 */ 1846 | setRepairCost( 1847 | /** 要设置的惩罚等级 */ 1848 | cost: number 1849 | ): void; 1850 | 1851 | /** (GMLIB)获取冒险模式下能破坏的方块 */ 1852 | getCanDestroy(): string[]; 1853 | 1854 | /** (GMLIB)设置冒险模式下能破坏的方块 */ 1855 | setCanDestroy( 1856 | /** 能破坏的方块 */ 1857 | blocks: string[] 1858 | ): void; 1859 | 1860 | /** (GMLIB)获取冒险模式下能放置在什么方块上 */ 1861 | getCanPlaceOn(): string[]; 1862 | 1863 | /** (GMLIB)设置冒险模式下能放置在什么方块上 */ 1864 | getCanPlaceOn( 1865 | /** 能放置的方块 */ 1866 | blocks: string[] 1867 | ): void; 1868 | 1869 | /** (GMLIB)获取物品分类名称 */ 1870 | getCategoryName(): string; 1871 | 1872 | /** (GMLIB)获取物品的命名 */ 1873 | getCustomName(): string; 1874 | 1875 | /** (GMLIB)获取物品的BUFF效果名称 */ 1876 | getEffecName(): string; 1877 | 1878 | /** (GMLIB)物品是否为食物 */ 1879 | isFood(): boolean; 1880 | 1881 | /** (GMLIB)获取物品最大堆叠数量 */ 1882 | getMaxCount(): number; 1883 | } 1884 | 1885 | interface Container { 1886 | /** (GMLIB)获取容器类型 */ 1887 | getContainerType(): string 1888 | } --------------------------------------------------------------------------------