├── .gitignore ├── README.md ├── assets ├── 1.png ├── docsify-plugins │ ├── docsify-auto-title.js │ ├── docsify-edit-on-github.js │ └── docsify-github-repo-contributors.js ├── jsdelivr-auto-fallback.index.js └── rule-editor-preview.png ├── check-logs.md ├── client ├── forge-mod-client-manual.md ├── jar-client-android.md ├── jar-client-desktop.md └── jar-client-manual.md ├── faq.md ├── faqs ├── exe-client.md ├── jar-client.md ├── little-server.md └── universal.md ├── index.html ├── mcversioning └── mcversioning.md ├── navbar.md ├── package.json ├── server ├── balloon-server-manual.md ├── balloon-server-reference.md ├── filter-rules-reference.md ├── little-server-manual.md ├── little-server-reference.md ├── rule-editor-tool-manaual.md ├── static-server-manual.md └── static-server-reference.md └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 文件更新助手帮助文档(版本4) 2 | 3 | —— 更新客户端小程序,Mod服好帮手 4 | 5 | 官方企鹅群,欢迎过来聊天,讨论,和提出建议: 6 | 7 | + [【更新助手官方群】](https://jq.qq.com/?_wv=1027&k=PqAEtn39) 925057600 8 | 9 | !> 这是新版的文档,如果你在找旧文档(Exe客户端、旧版PHP服务端等),点击[这里](https://github.com/BalloonUpdate/Docs/tree/old-servers)跳转到GitHub仓库查阅历史分支。更早的文档,请从[此处](https://github.com/BalloonUpdate/Docs/branches)查阅 10 | 11 | 如果访问页面出现 404 - not found,请清理缓存后再试 12 | 13 | ## 新闻 14 | 15 | !> 更新助手的独立衍生版本[Mc Versioning](https://balloonupdate.github.io/McVersioningDocs)有文件漏更新的严重bug,请勿再使用。 16 | 17 | 更新助手的全新重写系列 [McPatch](https://balloonupdate.github.io/McPatchDocs) 已经发布,相比原版更新助手,优点如下: 18 | 19 | 1. 更新大文件时会计算文件差异,仅打包文件中有变动的部分,更新大体积文件时非常节省流量和带宽 20 | 2. 静态部署更加友好,更新包为一个json文件和一个bin文件,方便自己手动上传,不再需要静态工具 21 | 3. 除了HTTP以外,还支持SFTP更新源(SFTP更新源操作不当会有安全风险,使用之前请三思) 22 | 4. 检测文件速度快,基于版本号的更新速度更快。磁盘IO开销更小,对移动端设备更加友好 23 | 5. 不用写更新规则,发布新版本时会自动检测到哪些文件改变,并自动生成差异记录 24 | 6. 不删玩家的模组文件,玩家可以自由添加自己的mod而不用担心被误更新删除 25 | 26 | ## 介绍 27 | 28 | 文件更新助手是一个使用HTTP协议的服务端/客户端架构的程序,需要两者都安装才能正常使用。服务端程序和客户端程序有不同的发行版可选择,且通信协议互相兼容,可以自由混搭。 29 | 30 | 在使用之前务必确保你了解这些内容:YAML语法、JSON语法、IP、端口、域名、端口、超文本传输协议中常见的错误代码等,了解这些内容会极大地增加诊断问题的效率。 31 | 32 | 如果你遇到任何问题,在问人之前,请首先查阅[常见问题解答FAQ](faq.md),这个页面能解决你遇到的绝大部分问题,如果仍然无法解决,再考虑向他人求助。 33 | 34 | ## 安装教程 35 | 36 | 文档分两部分,**手册 Manual** 和 **参考 Reference**、手册是教你快速上手的教程。参考是解锁高级玩法的说明书。 37 | 38 | 如果你是第一次用这个软件,那么只看手册部分就好了。当然一些过于简单的功能仅有手册页面,没有对应的参考页面。 39 | 40 | 服务端发行版: 41 | 42 | 1. [BalloonServer 服务端(手册)](server/balloon-server-manual.md)(**小白推荐**。Jar格式的单文件**图形化**服务端,开箱即用 + 99.9% 可视化操作 + 多线程优化!) 43 | 2. [单文件服务端(手册)](server/little-server-manual.md)(**小白推荐**。Jar格式的单文件**命令行**服务端,无其它依赖库,小体积打包,稳定可靠,适配桌面和命令行环境) 44 | 3. [静态服务端(手册)](server/static-server-manual.md)(略有门槛,适合对象存储等纯静态环境、也可用于PHP网站主机或者宝塔环境) 45 | 46 | 客户端发行版: 47 | 48 | 1. [Jar客户端(手册)](client/jar-client-manual.md)(独立软件并非模组。支持PC端、安卓端平台。以及任意启动器的一键启动) 49 | 2. [Forge模组客户端(手册)](client/forge-mod-client-manual.md)(基于Jar客户端开发,支持任意平台运行,猫反友好) 50 | 51 | 小工具(新!): 52 | 53 | 1. [更新规则编辑器(手册)](server/rule-editor-tool-manaual.md)(以可视化点击的方式代替手写更新规则。规则尽量亲自手写,不要过度依赖编辑器) 54 | 55 | ## 版本升级 56 | 57 | 同一行区间内的版本号,客户端是可以和服务端兼容的,如果你的客户端和服务端不在同一个区间内,就无法一起使用 58 | 59 | | 版本区间 | Jar版客户端 | 服务端 | 60 | | -------- | ------------ | -------- | 61 | | 区间一 | 0.0.1\~0.0.4 | 3.2\~3.6 | 62 | | 区间二 | 1.0 | 3.7 | 63 | | 区间三 | 4.x | 4.x | 64 | 65 | ## 参与贡献 66 | 67 | 由于个人精力有限,代码中难免会出现错误、疏忽、遗漏,还需要在大家的帮助下不断完善 68 | 69 | 如果你发现了问题,欢迎前来GitHub仓库提交Issue、PullRequest,或者亲自告诉我,我会不断改进 70 | 71 | 如果帮助文档中出现了错误或者是不适合的地方,同样欢迎大家进行修改,提交PR! 72 | 73 | ## 仓库地址 74 | 75 | 如果需要查阅更新记录和历史,请访问对应仓库的Release页面(部分仓库因为架构过于简单,没有更新记录) 76 | 77 | + [帮助文档](https://github.com/BalloonUpdate/Docs):项目的帮助文档仓库,包含手册和参考 78 | + [ForgeMod客户端](https://github.com/BalloonUpdate/ModClient)(由[KasumiNova](https://github.com/KasumiNova)大佬开发):Forge模组版本的客户端,支持任意平台,猫反友好 79 | + [Jar客户端](https://github.com/BalloonUpdate/JarClient):普通客户端,是一个独立软件,支持多平台和任意三方启动器 80 | + [BalloonServer 服务端](https://github.com/BalloonUpdate/BalloonServer)(由[KasumiNova](https://github.com/KasumiNova)大佬开发):图形化单文件服务端,可视化操作 + 多线程优化 81 | + [单文件服务端](https://github.com/BalloonUpdate/LittleServer):命令行单文件服务端,适配大部分无桌面场景 82 | 83 | 不再维护: 84 | 85 | + ~~[WindowsExe文件打包器](https://github.com/BalloonUpdate/LittleWrapper)~~(不再维护):Exe客户端打包工具 86 | + [~~Exe客户端~~](https://github.com/BalloonUpdate/ExeClient)~~(不再有新特性):Electron版本客户端,支持自定义全部界面,但仅支持Windows平台 87 | + [~~静态服务端小工具(旧)~~](https://github.com/BalloonUpdate/Tool)~~(已被其它功能替代):第一版的静态服务端上传工具,操作不当有误删文件的风险,不再建议使用 88 | + [~~PHP服务端~~](https://github.com/BalloonUpdate/PhpServer)~~(已集成进静态服务端):PHP编写的服务端,但因为性能问题不再更新,已由静态服务端承担PHP服务端所有的功能 89 | + [~~静态服务端结构文件工具~~](https://github.com/BalloonUpdate/StructureTool)~~(已被其它功能替代):第二版的静态服务端生成工具。已由最新版静态服务端整合包替代 90 | + [~~静态服务端对象存储工具~~](https://github.com/BalloonUpdate/ObjectStorageServiceUtility)~~(已被其它功能替代):第二版的静态服务端上传工具。已由最新版静态服务端整合包替代 91 | + [~~Jar客户端一键启动工具~~](https://github.com/BalloonUpdate/BatchRunner)~~(已被其它功能替代):初代Jar客户端的一键启动方案,因为配置复杂容易出错,已由更简单方便的新启动方式替代 92 | -------------------------------------------------------------------------------- /assets/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BalloonUpdate/Docs/afbb3e64a0cec5cc6757e506602794686e95cbf5/assets/1.png -------------------------------------------------------------------------------- /assets/docsify-plugins/docsify-auto-title.js: -------------------------------------------------------------------------------- 1 | // 自动将第一个标题作为网页Title 2 | (function(){ 3 | var plugin = function(hook) { 4 | hook.afterEach(function(html) { 5 | var parser = new DOMParser() 6 | var root = parser.parseFromString(html, 'text/html') 7 | var dom = root.querySelectorAll('h1,h2,h3,h4,h5,h6') 8 | if(dom.length > 0) { 9 | setTimeout(() => { 10 | document.querySelector('title').innerHTML = dom[0].innerText 11 | }, 5); 12 | } else { 13 | document.querySelector('title').innerHTML = window.DocsifyAutoTitle.defaultTitle 14 | } 15 | return html; 16 | }); 17 | } 18 | 19 | window.DocsifyAutoTitle = { 20 | defaultTitle: '', 21 | create: function(defaultTitle) { 22 | // 获取默认标题 23 | var title = defaultTitle ?? document.querySelector('title').innerHTML 24 | window.DocsifyAutoTitle.defaultTitle = title 25 | 26 | return plugin 27 | } 28 | } 29 | })(); -------------------------------------------------------------------------------- /assets/docsify-plugins/docsify-edit-on-github.js: -------------------------------------------------------------------------------- 1 | ;(function() { 2 | function isFunction(functionToCheck) { 3 | return functionToCheck && {}.toString.call(functionToCheck) === '[object Function]' 4 | } 5 | 6 | window.EditOnGithubPlugin = {} 7 | 8 | function create(docBase, docEditBase, title) { 9 | title = title || 'Edit on GitHub' 10 | docEditBase = docEditBase || docBase.replace(/\/blob\//, '/edit/') 11 | 12 | function editDoc(event, vm) { 13 | var docName = vm.route.file 14 | 15 | if (docName) { 16 | var editLink = docEditBase + docName 17 | window.open(editLink) 18 | event.preventDefault() 19 | return false 20 | } else { 21 | return true 22 | } 23 | } 24 | 25 | window.EditOnGithubPlugin.editDoc = editDoc 26 | 27 | function generateHeader(title) { 28 | return header = [ 29 | '
', 30 | '

', 32 | title, 33 | '

', 34 | '
' 35 | ].join('') 36 | } 37 | 38 | return function(hook, vm) { 39 | window.EditOnGithubPlugin.onClick = function(event) { 40 | EditOnGithubPlugin.editDoc(event, vm) 41 | } 42 | 43 | if (isFunction(title)) { 44 | 45 | hook.afterEach(function (html) { 46 | return generateHeader(title(vm.route.file)) + html 47 | }) 48 | } else { 49 | var header = generateHeader(title) 50 | 51 | hook.afterEach(function (html) { 52 | return header + html 53 | }) 54 | } 55 | 56 | 57 | } 58 | } 59 | 60 | window.EditOnGithubPlugin.create = create 61 | }) (window); -------------------------------------------------------------------------------- /assets/docsify-plugins/docsify-github-repo-contributors.js: -------------------------------------------------------------------------------- 1 | // 在页脚显示版权文字和贡献者信息 2 | (function(){ 3 | var plugin = function(hook) { 4 | hook.afterEach(function(html) { 5 | 6 | setTimeout(() => { 7 | let githubContributors = { 8 | data: () => ({ 9 | contributors: [] 10 | }) 11 | } 12 | 13 | let vue = new (Vue.extend(githubContributors))().$mount('#github-contributors') 14 | let repos = [ 15 | 'https://api.github.com/repos/balloonupdate/Docs/contributors', 16 | 'https://api.github.com/repos/balloonupdate/Tool/contributors', 17 | 'https://api.github.com/repos/balloonupdate/JarClient/contributors', 18 | 'https://api.github.com/repos/balloonupdate/LittleServer/contributors', 19 | 'https://api.github.com/repos/balloonupdate/ExeClient/contributors', 20 | 'https://api.github.com/repos/balloonupdate/ModClient/contributors', 21 | 'https://api.github.com/repos/balloonupdate/BalloonServer/contributors', 22 | ] 23 | 24 | vue.contributors = [] 25 | 26 | for (const repo of repos) 27 | fetch(repo).then((r) => r.json()).then((data) => { 28 | 29 | for (let i = 0;i < data.length;i++) 30 | { 31 | let idx = findIndex(data[i], vue.contributors) 32 | if(idx != -1) 33 | { 34 | if(data[i]['contributions'] > vue.contributors[idx]['contributions']) 35 | vue.contributors[idx] = data[i] 36 | } else { 37 | vue.contributors.push(data[i]) 38 | } 39 | } 40 | 41 | vue.contributors = vue.contributors.sort((a, b) => b['contributions'] - a['contributions']) 42 | 43 | console.log(vue.contributors) 44 | }) 45 | }, 150); 46 | 47 | return html+` 48 |
49 |
50 |
Copyleft © 2021 - 2022 BalloonUpdate
51 |
|
52 |
Contributors:
53 |
54 | 55 | 56 |
57 |
58 | 95 | `; 96 | 97 | function findIndex(el, array) 98 | { 99 | let index = -1 100 | for (let i = 0;i < array.length;i++) 101 | if(array[i]['id'] == el['id']) 102 | index = i 103 | return index 104 | } 105 | }); 106 | } 107 | 108 | window.DocsifyGithubRepoContributors = { 109 | create: function(defaultTitle) { 110 | 111 | return plugin 112 | } 113 | } 114 | })(); -------------------------------------------------------------------------------- /assets/jsdelivr-auto-fallback.index.js: -------------------------------------------------------------------------------- 1 | (function (document) { 2 | const SOURCE = 'https://cdn.jsdelivr.net'; 3 | const DEST = 'https://gcore.jsdelivr.net'; 4 | const $ = document.querySelectorAll.bind(document); 5 | const checkAvailable = (callback) => { 6 | let timeoutId; 7 | const newNode = document.createElement('link'); 8 | newNode.rel = 'stylesheet'; 9 | newNode.text = 'text/css'; 10 | const onError = () => { 11 | if (!timeoutId) { 12 | return; 13 | } 14 | 15 | clearTimeout(timeoutId); 16 | timeoutId = 0; 17 | newNode.href = 'about:blank'; 18 | newNode.remove(); 19 | callback(false); 20 | }; 21 | 22 | timeoutId = setTimeout(onError, 2000); 23 | newNode.addEventListener('error', onError); 24 | newNode.addEventListener('load', function () { 25 | newNode.remove(); 26 | clearTimeout(timeoutId); 27 | callback(true); 28 | }); 29 | 30 | newNode.href = 31 | SOURCE + 32 | '/gh/PipecraftNet/jsdelivr-auto-fallback@main/empty.css?' + 33 | Date.now(); 34 | document.head.insertAdjacentElement('afterbegin', newNode); 35 | }; 36 | 37 | const replaceElementSrc = () => { 38 | for (const element of $('link[rel="stylesheet"]')) { 39 | if (element.href && element.href.includes(SOURCE)) { 40 | element.href = element.href.replace(SOURCE, DEST); 41 | } 42 | } 43 | 44 | for (const element of $('script')) { 45 | if (element.src && element.src.includes(SOURCE)) { 46 | const newNode = document.createElement('script'); 47 | newNode.src = element.src.replace(SOURCE, DEST); 48 | element.defer = true; 49 | element.src = ''; 50 | element.before(newNode); 51 | element.remove(); 52 | } 53 | } 54 | 55 | for (const element of $('img')) { 56 | if (element.src && element.src.includes(SOURCE)) { 57 | const source = element.src; 58 | // Used to cancel loading. Without this line it will remain pending status. 59 | element.src = ''; 60 | element.src = source.replace(SOURCE, DEST); 61 | } 62 | } 63 | }; 64 | 65 | checkAvailable(function (isAvailable) { 66 | if (isAvailable) { 67 | return; 68 | } 69 | 70 | console.warn(SOURCE + ' is not available.'); 71 | 72 | replaceElementSrc(); 73 | // Replace dynamically added elements 74 | setInterval(replaceElementSrc, 500); 75 | }); 76 | })(document); 77 | -------------------------------------------------------------------------------- /assets/rule-editor-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BalloonUpdate/Docs/afbb3e64a0cec5cc6757e506602794686e95cbf5/assets/rule-editor-preview.png -------------------------------------------------------------------------------- /check-logs.md: -------------------------------------------------------------------------------- 1 | ## 通过日志排查问题 2 | 3 | 本章节教你如何通过日志来排查遇到的各种问题(覆盖率100%) 4 | 5 | 日志一般在客户端程序的旁边,文件名:`updater.log`/`balloon_update.log`/`balloon_update.txt` 6 | 7 | 首先使用任何文本编辑器打开日志文件(推荐使用等宽字体显示) 8 | 9 | 然后使用搜索功能,定位到`更新路径匹配信息`所在位置(如果是Jar客户端,则就在开头部分,不用定位) 10 | 11 | 关键部分的日志,大概的结构是这样的(Jar客户端的日志结构稍有不同,但总体上八九不离十) 12 | 13 | ``` 14 | -----更新路径匹配信息(CommonMode)------ 15 | N: - .minecraft 16 | N: + mods 17 | N: + [3D声效]Sound-Physics-1.12.2.jar 18 | N: + [JEI本体]jei_1.12.2-4.15.0.281.jar 19 | N: + [JEI附属NEI风格]justenoughbuttons-1.12.2-1.2.3.jar 20 | N: + [JEI附属拼音搜索]JustEnoughCharacters-1.12.0-3.4.3.jar 21 | N: + [吸血鬼]Vampirism-1.12.2-1.5.2.jar.disabled 22 | N: + [吸血鬼前置]Guide-API-1.12-2.1.8-63.jar.disabled 23 | N: + [家具][1.12.2]MrCrayfish's+Furniture+-+6.3.1.jar 24 | N: + [工业2]industrialcraft-2-2.8.188-ex112.jar 25 | N: + [手柄支持]controllable-1.12.2-0.3.1.jar.disabled 26 | N: + [旅行地图]journeymap-1.12.2-5.5.5.jar 27 | N: + [星系]Galacticraft-Planets-1.12.2-4.0.2.244.jar.disabled 28 | N: + [星系]GalacticraftCore-1.12.2-4.0.2.244.jar.disabled 29 | N: + [星系]MicdoodleCore-1.12.2-4.0.2.244.jar.disabled 30 | N: b46da38920daaed19d912cbcc54c5054_2714005653360072542.gif 31 | ------------------- 32 | O: - .minecraft 33 | O: + mods 34 | O: + [3D声效]Sound-Physics-1.12.2.jar 35 | O: + [JEI本体]jei_1.12.2-4.15.0.281.jar 36 | O: + [JEI附属NEI风格]justenoughbuttons-1.12.2-1.2.3.jar 37 | O: + [JEI附属拼音搜索]JustEnoughCharacters-1.12.0-3.4.3.jar 38 | O: + [吸血鬼]Vampirism-1.12.2-1.5.2.jar.disabled 39 | O: + [吸血鬼前置]Guide-API-1.12-2.1.8-63.jar.disabled 40 | O: + [家具][1.12.2]MrCrayfish's+Furniture+-+6.3.1.jar 41 | O: + [工业2]industrialcraft-2-2.8.188-ex112.jar 42 | O: + [手柄支持]controllable-1.12.2-0.3.1.jar.disabled 43 | O: + [旅行地图]journeymap-1.12.2-5.5.5.jar 44 | O: + [星系]Galacticraft-Planets-1.12.2-4.0.2.244.jar.disabled 45 | O: + [星系]GalacticraftCore-1.12.2-4.0.2.244.jar.disabled 46 | O: + [星系]MicdoodleCore-1.12.2-4.0.2.244.jar.disabled 47 | O: b46da38920daaed19d912cbcc54c5054_2714005653360072542.gif 48 | ``` 49 | 50 | 这样的日志会先后显示两次,首先是CommonMode(普通对比)的日志,其次是OnceMode(补全对比)的日志 51 | 52 | 测试阶段的日志分两部分: 53 | 54 | + 上部分以`N:`开头,用来寻找需要`下载`的文件(`N`是`new`是首字母) 55 | + 下部分以`O:`开头,用来寻找需要`删除`的文件(`O`是`old`是首字母) 56 | 57 | N部分和O会分别遍历所有路径,如果路径被匹配为要参与更新的路径(命中更新规则),那么在路径的前面会用一个加号`+`或者减号`-`来表示,如果未能匹配,则是空白 58 | 59 | + `+`表示能直接匹配更新规则(能够被更新规则直接命中),通常是`文件` 60 | + `-`表示自己本身不能匹配更新规则,但是有某个子目录却能命中更新规则(间接匹配),通常是`目录` 61 | + **只要出现`+`或者`-`的任意一种,就算命中了更新规则,就会参与更新** 62 | 63 | 如果你希望更新的文件没有这些字样,或者根本找不到你要更新的文件名,那么请检查更新规则是否填写正确,检查服务端上的文件位置是否和更新规则里写的路径是一致的 64 | -------------------------------------------------------------------------------- /client/forge-mod-client-manual.md: -------------------------------------------------------------------------------- 1 | ## ForgeMod客户端 2 | 3 | ForgeMod客户端是由[KasumiNova](https://github.com/KasumiNova)大佬基于 Jar 客户端开发的 Forge 模组版本的客户端,可作为一个模组被游戏加载。 4 | 5 | 下载地址:https://github.com/BalloonUpdate/ModClient/releases 6 | 7 | 1. 首先配置好一个可用的 JarClient 客户端(指独立启动没问题) 8 | 2. 下载 ForgeMod 客户端并放到游戏的 `mods` 目录下 9 | 3. 将 JarClient 客户端复制到游戏目录下,模组会自动检测文件并载入。注意:如果你修改了 JarClient 的名称,请在游戏目录下新建名为 `BalloonUpdateFileName.txt` 的文本文件,并输入你修改后的名称。(此处游戏目录均指 `.minecraft`,配置文件使用 JarClient 文件内部的配置) 10 | 4. 启动 Minecraft 测试效果 11 | 12 | ## 工作流程 13 | - 1.12.2 版本的 BalloonUpdateModLoader 被作为 CoreMod 来加载,但是它比大部分的 CoreMod 要更早加载,以实现更新除猫反作弊之外的所有模组的功能。 14 | - 1.13.2 - 1.16.5 版本的 BalloonUpdateModLoader 被作为 Service 来加载,但是它比大部分的 CoreMod 要更早加载,以实现更新所有模组的功能。 15 | 16 | ## 猫反作弊注意事项: 17 | 猫反作弊模组必须在本模组之前加载,否则会发生报错 18 | 19 | 解决方案: 20 | 1. 将猫反作弊文件名名称前添加 `!!` 21 | 2. 举例:`CatAntiCheat.jar` -> `!!CatAntiCheat.jar` 22 | 因 Forge 读取模组的顺序是按照名称读取的,因此此方法可以让 Forge 优先加载猫反,然后再加载 BaloonUpdateModLoader。 23 | 24 | ## 额外功能 25 | 26 | 要更新并删除旧版 JarClient,请在游戏目录下创建名为 `OldBalloonUpdateFileName.txt` 的文本文件,并输入旧版 JarClient 的文件名。 27 | 28 | 例如: 29 | 30 | `JarClient 4.1.16.jar` 31 | 32 | 如果有多个客户端需要删除,请逐行输入。 33 | 34 | 例如: 35 | ``` 36 | JarClient 4.1.16.jar 37 | JarClient 4.1.15.jar 38 | ``` 39 | -------------------------------------------------------------------------------- /client/jar-client-android.md: -------------------------------------------------------------------------------- 1 | ## Android平台一键启动 2 | 3 | 运行环境要求:Java 8或更高 4 | 5 | 此更新方案整体配置过程和配置`authlib`外置登录非常像,如果你有类似的经验,则很容易上手。教程这里以澪作为示例,其它启动器大同小异 6 | 7 | ### 1.准备工作 8 | 9 | 首先PC机上配置好一个可用的Jar客户端(指独立启动没问题) 10 | 11 | 注意Jar客户端的版本需要大于等于4.1,只有4.1版本开始才支持作为`javaagent`参数启动 12 | 13 | 在PC端调试完毕后,从PC上将Jar客户端和配置文件(如果有)复制到手机的`/sdcard/MioLauncher/JarClient.jar`路径下(实际文件名如果包含中文,请删掉中文部分) 14 | 15 | ### 2.移除签名证书 16 | 17 | 接着启动澪。如果你还没有下载一个游戏版本,请下载一个游戏版本 18 | 19 | 将游戏核心Jar文件(只有一个),比如`/sdcard/MioLauncher/.minecraft/versions/1.12.2/1.12.2.jar`导出到电脑上 20 | 21 | 用压缩软件打开,删除`META-INF/`目录下的`MOJANGCS.RSA`和`MOJANGCS.SF`文件,然后保存并导回到手机上覆盖对应的文件(某些特殊情况下,此步骤不是必须的。但为保险起见,还是删掉比较稳妥,毕竟安卓端调试比较麻烦) 22 | 23 | ### 3.配置JVM参数 24 | 25 | 打开澪,切换到`游戏配置`页面,在游戏参数的最前面插入一段JVM参数`-javaagent:/sdcard/MioLauncher/JarClient.jar`(`JarClient.jar`文件名记得换成实际的文件名) 26 | 27 | 输入完毕后记得点击保存按钮 28 | 29 | 上面一步非常重要,请再输入完成后务必仔细检查,不能打错一个字,否则游戏直接闪退 30 | 31 | 如果你有多个`javaagent`参数,请确保位于所有参数的最前面 32 | 33 | ### 4.启动测试 34 | 35 | 接着重启澪,并启动游戏测试效果。如果你希望看到详细的日志输出过程,可以打开澪的开发者模式,启动游戏之后,点击“日志”按钮就可以看到详细更新过程了 36 | 37 | 如果希望看到完整的日志,可以查看`JarClient.jar`文件旁边的`balloon_update.txt`文件 38 | 39 | ## 更新性能优化 40 | 41 | 手机上的ARM处理器性能不及PC上的x86处理器那么强大,过多的文件更新会导致游戏启动速度变的非常慢 42 | 43 | 如果你的游戏启动非常慢,请查看日志窗口,判断是不是更新助手检查文件时间过长导致的,如果是,请往下阅读 44 | 45 | 手机上硬件资源有限,有些地方必须做出取舍,为此Jar客户端提供了部分可配置的参数来优化更新过程的性能: 46 | 47 | 1. 减少参与更新文件的总大小,文件总大小越大,检查更新花费的时间就越长,尽量缩减一些不必要的模组和文件,尤其是文件大小超过50Mb以上的模组,不光手机可能带不动,更新所花费的时间也会更长 48 | 2. 打开配置文件中的`check-modified`选项,大多数时候可以极大地提升文件检查效率,尤其是大文件场景下非常明显。具体说明请参考配置文件内的注释 49 | 3. 打开配置文件中的`version-cache`选项,开启后客户端每次更新完成后会把服务端的文件结构计算一个校验存起来,待下次更新时,服务端没有任何文件变动,则直接跳过本地文件检查过程。具体说明请参考配置文件内的注释 50 | 51 | 52 | 53 | ## 游戏闪退/崩溃 54 | 55 | 在移动端更新时无法像电脑端一样弹窗显示进度条,所以当出现问题后,只能以使Minecraft进程主动崩溃的方式告诉你更新失败了,所以如果发生了游戏闪退,请首先判断是不是因为更新失败造成的 56 | 57 | 你可以直接查看澪的`日志`页面,然后滑到底部。如果是因为更新导致的游戏主动崩溃,会有中文消息告诉你具体是什么原因,是网络问题,还是配置问题。如果是因为其它原因闪退,那么一般会出现大量的英文 58 | 59 | 如果你不希望在更新出现问题时直接闪退这种简单粗暴的机制,你可以在配置文件开启`no-throwing`选项。开启后如果遇到网络原因无法更新,就不会闪退,而是继续启动Minecraft。虽然不会闪退,但也可能因为服务器新增了模组而导致进不去服务器的情况,所以此选项请自行决定是否开启 60 | 61 | --- 62 | 63 | 如果配置完毕后,启动立即闪退,而且也没有看到任何Jar客户端输出的内容(内容一般是中文,很显眼),那么请检查你的参数是否填写正确,或者文件是否放到了正确的位置的上 64 | 65 | 如果仍然不能解决,那么使用Pojav后端启动,闪退后查看澪的日志文件`/sdcard/MioLauncher/latestlog.txt` 66 | 67 | 如果文件末尾提示这样的话,那多半就是指定路径找不到jar文件,你就需要检查文件是否放到位了没有 68 | 69 | ``` 70 | Error opening zip file or JAR manifest missing : /sdcard/MioLauncher/LittleClient-0.0.0.jar 71 | Error occurred during initialization of VM 72 | agent library failed to init 73 | : instrument 74 | --------- beginning of system 75 | ``` 76 | 77 | 如果出现其它报错,请联系我 78 | -------------------------------------------------------------------------------- /client/jar-client-desktop.md: -------------------------------------------------------------------------------- 1 | ## Windows平台一键启动 2 | 3 | 运行环境要求:Java 8或更高 4 | 5 | 得益于新的JavaAgent启动方式,Jar客户端可以任意启动器的热更新功能,不再依赖启动器的`启动前指令`功能。因此此方法可以适用于任何启动器! 6 | 7 | ### 1.准备工作 8 | 9 | 首先配置好一个可用的Jar客户端(指独立启动没问题) 10 | 11 | 注意Jar客户端的版本需要大于等于4.1,只有4.1版本开始才支持作为`javaagent`参数启动 12 | 13 | 将Jar客户端和配置文件(如果有)移动到`.minecraft/`目录下(如果是XMCL,请移动到对应的实例目录下,Windows下一般位于`~/.xmcl/instances/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/`) 14 | 15 | ### 2.移除签名证书 16 | 17 | 将游戏核心Jar文件,比如`.minecraft/versions/1.12.2/1.12.2.jar`用压缩软件打开,删除`META-INF/`目录下的`MOJANGCS.RSA`和`MOJANGCS.SF`文件并保存(某些特殊情况下,此步骤不是必须的。如果你因为一些原因不能修改核心文件,可以尝试跳过这一步,如果游戏因为Jar签名的Security原因不能正常启动,那么还是删掉签名证书的好)作者注:如果你不知道括号里说的是什么,请老老实实做完这一步,不要跳过去 18 | 19 | ### 3.配置JVM参数 20 | 21 | 打开启动器,找到JVM(Java虚拟机)参数,在现有内容的最前面插入一段`-javaagent:JarClient.jar`(`JarClient.jar`文件名记得换成实际的文件名) 22 | 23 | 如果你的`JarClient.jar`不在此处,请自行修改路径,此相对路径的起始路径是`.minecraft`目录 24 | 25 | 上面一步非常重要,请再输入完成后务必仔细检查,不能打错一个字,否则游戏直接闪退 26 | 27 | 如果你有多个`javaagent`参数,请确保位于所有参数的最前面 28 | 29 | ### 4.启动测试 30 | 31 | 接着启动游戏,测试效果。如果你希望看到详细的日志输出过程,可以打开启动器的日志窗口。如果希望看到完整的日志,可以查看`JarClient.jar`文件旁边的`balloon_update.txt`文件 32 | 33 | ## 无窗口模式(静默更新) 34 | 35 | 当Jar客户端在PC机上运行时,会自动检测是否是桌面环境,如果是,则会显示包含进度条的窗口 36 | 37 | 如果你不希望显示窗口,而是希望像[安卓端更新方案](onekey-start-ja-mobile.md)那样全程以无窗口方式运行(也叫静默更新),你可以添加一个javaagent参数`windowless`,来开启**无窗口模式**,比如这样配置JVM参数:`-javaagent:JarClient-0.0.0.jar=windowless`。则即使是桌面环境,也不会显示更新进度条,所有更新过程将完全在后台运行(全程无任何窗口显示) 38 | 39 | ## 游戏崩溃 40 | 41 | 当Jar客户端遇到网络问题,配置文件问题,或者其它原因出现错误的时候,会主动崩溃Minecraft进程,以此来告诉你更新失败了,所以如果发生了游戏闪退,请首先查看日志,判断是不是因为更新失败造成的。当然一般出现错误的时候,都会有弹框显示告诉你,避免手动查日志这个繁琐的工作(如果你开了无窗口模式,则没有任何错误弹窗显示) 42 | 43 | 如果你不希望在更新出现问题时直接闪退这种简单粗暴的机制,你可以在配置文件开启`no-throwing`选项。开启后如果遇到网络原因无法更新,就不会闪退,而是继续启动Minecraft。虽然不会闪退,但也可能因为服务器新增了模组而导致进不去服务器的情况,所以此选项请自行决定是否开启 -------------------------------------------------------------------------------- /client/jar-client-manual.md: -------------------------------------------------------------------------------- 1 | ## Jar客户端Manual 2 | 3 | Jar客户端运行环境要求:Java 8或更高 4 | 5 | 1. 把Jar客户端移动到启动器旁边,把里面的`config.yml`解压到Jar的旁边,并用文本编辑器打开 6 | 2. 修改`server`选项 7 | 1. 如果是单文件服务端:将单文件服务端的API地址复制粘贴过来(注意外网的话要复制外网地址) 8 | 2. 如果是静态服务端:将`index.json`的URL复制粘贴过来 9 | 3. 打开`check-modified`选项,将其设置为`true`,可以检查资源的速度 10 | 4. 其它选项保持默认,或者按照文档的注释进行修改,最后保存并关闭文件 11 | 3. 双击启动Jar测试效果 12 | 13 | ## 注意事项 14 | 15 | Jar客户端独立启动时,其只能设置为默认双击启动(`javaw.exe`或者`java.exe`),而不能使用`打开方式`选择Java启动,这样可能会提示找不到`.minecraft`目录。设置默认打开方式为Java后,软件的图标应该是一个Java的咖啡杯的样子 16 | 17 | ## 优化建议 18 | 19 | 如果检查更新的过程很慢,可以考虑调整配置文件中的这几个参数: 20 | 21 | 1. 首先打开`check-modified`选项,将其设置为`true`,会先检查文件修改时间,如果时间不一致再检查文件hash,开启后检测过程会快得多,尤其是当大文件特别多的时候,性能提升特别明显 22 | 2. 如果仍然很慢,可以考虑开启`version-cache`选项,此选项仅推荐在线上环境开启,具体可以参考配置文件里的说明 23 | 24 | ## 配置一键启动 25 | 26 | 一键启动可以在Minecraft启动时更新文件,更新自动进行且全程无需手动操作,用户体验非常好。 27 | 28 | + [Windows平台](jar-client-desktop.md)(新的一键启动方案,支持所有三方启动器) 29 | + [Android平台](jar-client-android.md)(适用于澪,以及任何基于Boat的移动端启动方案) 30 | -------------------------------------------------------------------------------- /faq.md: -------------------------------------------------------------------------------- 1 | # 常见问题解答 2 | 3 | 一些常见的问题都列举在这里了,希望对你有帮助。 4 | 5 | 6 | 7 | ## **Jar版客户端** 8 | 9 | [jar-client.md](faqs/jar-client.md ':include') 10 | 11 | ## **单文件服务端** 12 | 13 | [little-server.md](faqs/little-server.md ':include') 14 | 15 | ## **通用问题** 16 | 17 | [universal.md](faqs/universal.md ':include') 18 | 19 | ## **Exe客户端** 20 | 21 | [exe-client.md](faqs/exe-client.md ':include') 22 | 23 | 24 | -------------------------------------------------------------------------------- /faqs/exe-client.md: -------------------------------------------------------------------------------- 1 | ### Duplicate Content-Length 2 | 3 | `影响范围`:4.x全版本 4 | 5 | `问题原因`:单文件服务端返回的数据中HTTP头重复,冲突 6 | 7 | `解决办法`:升级到单文件服务端4.0.7或者更高版本 8 | 9 | ### 找不到VCRUNTIME140_1.dll 10 | 11 | `影响范围`:3.x全版本 12 | 13 | `问题原因`:缺少VC运行库2015 14 | 15 | `解决办法`:1.安装VC++2015 2.升级到3.0.13或者以上版本 16 | 17 | ### 360卫士报毒/拦截 18 | 19 | `影响范围`:2.x全版本\~3.x全版本 20 | 21 | `问题原因`:360误报危险文件,本程序相关所有代码均开源,请自行审查 22 | 23 | `解决办法`:此问题无解,目前只能手动加入白名单 24 | 25 | ### HTTP请求/连接失败 26 | 27 | ``` 28 | HTTPResponseException(HTTP请求/连接失败(通常是网络原因)) 29 | ``` 30 | 31 | `影响范围`:3.x全版本 32 | 33 | `问题原因`:网络原因导致请求超时,从而判定为连接失败 34 | 35 | `解决办法`:多次尝试启动,或者等网好一点时再试。如果实在不能解决,请手动在浏览器里打开对话框中以`http(s)://`开头的那个URL,如果出现文件下载对话框或者显示内容为yaml格式,则正常工作,其它情况请根据报错信息自行解决。 36 | 37 | ### The .minecraft directory not found 38 | 39 | ``` 40 | MCDirectoryNotFoundException: The .minecraft directory not found. 41 | ``` 42 | 43 | `影响范围`:3.x全版本 44 | 45 | `问题原因`:未将主程序放到相应的位置上,正确的位置: 46 | 47 | + `.minecraft`同级目录下 48 | + `.minecraft/`目录下 49 | + `.minecraft/updater/`目录下 50 | 51 | 主程序只能放在这几个位置,否则无法正常启动 52 | 53 | 注:配置文件只能放在`.minecraft/updater/updater.yml`,请不要随主程序移动 54 | 55 | `解决办法`:将主程序移动到上面任意路径之一,都可以正常识别 56 | 57 | ### 找不到配置文件 58 | 59 | ``` 60 | ConfigFileNotFoundException(找不到配置文件) 61 | ``` 62 | 63 | `影响范围`:3.x全版本 64 | 65 | `问题原因`:未将配置文件`updater.yml`放到`.minecraft/updater/updater.yml` 66 | 67 | `解决办法`:将配置文件移动到正确的位置 68 | 69 | ### 服务端返回了无法解码的数据 70 | 71 | ``` 72 | UnableToDecodeException服务端返回了无法解码的数据(非yaml格式) 73 | ``` 74 | 75 | `影响范围`:3.x全版本 76 | 77 | `问题原因`:服务端的配置不正确 78 | 79 | `解决办法`:请手动在浏览器里打开对话框中以`http(s)://`开头的那个URL,如果出现文件下载对话框或者显示内容为yaml格式,则正常工作,其它情况请根据报错信息自行解决。 80 | 81 | 注:对话框中只会显示一小部分返回的内容,而且位置标记因为不是等宽字体的原因也无法准确反映错误位置,你可以打开日志文件`.minecraft/updater/updater.log`并滑到最下面或者搜索`RAWDATA`关键字,就能看到详细报错的行和列的位置 82 | 83 | ### 连接关闭/传输中断 84 | 85 | ``` 86 | ConnectionClosedException连接关闭/传输中断(通常是网络原因) 87 | ``` 88 | 89 | `影响范围`:3.x全版本 90 | 91 | `问题原因`:网络原因导致传输中断 92 | 93 | `解决办法`:请等待5\~10分钟网络稳定以后再试 94 | 95 | > 此报错和程序本身无关,通常是网络原因,不是程序BUG。 96 | 97 | ### 不正确的HTTP状态码 98 | 99 | ``` 100 | UnexpectedHttpCodeExcepetion不正确的HTTP状态码(未处于2xx-3xx之间) 101 | ``` 102 | 103 | `影响范围`:3.x全版本 104 | 105 | `问题原因`:服务端并未返回正常的200状态码(即使是301或者302也不行) 106 | 107 | `解决办法`:请手动在浏览器里打开对话框中以`http(s)://`开头的那个URL,并根据具体情况自行解决。 108 | 109 | > 此报错和程序本身无关,而是HTTP服务器的问题,不是本程序的BUG。 110 | 111 | ### 未知的工作模式 112 | 113 | ``` 114 | UnknownWorkModeException未知的工作模式 115 | ``` 116 | 117 | `影响范围`:3.1全版本 118 | 119 | `问题原因`:服务端配置文件里的`mode`设置不正确 120 | 121 | `解决办法`:将服务端配置文件里的`mode`设置为下列值之一:`common`、`exist` 122 | 123 | ### 重定向次数过多 124 | 125 | ``` 126 | MaxRedirectionReachedException重定向次数过多 127 | ``` 128 | 129 | `影响范围`:3.x全版本 130 | 131 | `问题原因`:HTTP3xx跳转次数过多(超过10次以上)此问题为HTTP服务器的技术性问题,与本软件无关! 132 | 133 | `解决办法`:减少跳转次数 134 | 135 | ### 重定向出错 136 | 137 | ``` 138 | RedirectionFailedException重定向出错 139 | ``` 140 | 141 | `影响范围`:3.x全版本 142 | 143 | `问题原因`:HTTP3xx响应头中找不到Location属性,无法完整此次跳转。此问题为HTTP服务器的技术性问题,与本软件无关! 144 | 145 | `解决办法`:请寻求HTTP服务器管理员的帮助 146 | 147 | ### 更新规则带-号时不更新任何文件 148 | 149 | `详情`:没有更新任何文件,而且日志里显示,带`-`符号的路径末尾出现一个`\n` 150 | 151 | `影响范围`:服务端3.x(仅php服务端) 152 | 153 | `问题原因`:php服务端的yaml解析程序的bug所导致 154 | 155 | `解决方法`:(任选其一) 156 | 157 | + 避免更新路径里带有`-`符号, 158 | + 升级php服务端版本到3.1(客户端不用做任何改动) 159 | 160 | ### 有歧义的文件类型 161 | 162 | ``` 163 | AmbiguousFileTypeEeception(有歧义的文件类型(内部错误)) 164 | ``` 165 | 166 | `影响范围`:3.x全版本 167 | 168 | `问题原因`:小工具的bug所导致 169 | 170 | `解决办法`:升级小工具的版本到v3.0.1 171 | 172 | ### 找不到res.yml(404问题) 173 | 174 | `影响范围`:3.x全版本 175 | 176 | 1.当使用PHP服务端时 177 | 178 | `问题原因`:客户端配置错误 179 | 180 | `解决方法`:将客户端配置文件里的`api`选项,从`.yml`结尾换成`.php`结尾(前提是没有使用URLrewrite) 181 | 182 | 2.当使用静态服务端时 183 | 184 | `问题原因`:自己使用后台或者COSBrowser手动管理了文件 185 | 186 | `解决方法`:改为全程使用小工具上传 187 | 188 | ### The "path" argument must be type string 189 | 190 | `The "path" argument must be type string, Received type number(1)` 191 | 192 | `影响范围`:Exe客户端全版本 193 | 194 | `问题原因`:当遇到文件名是纯数字的文件时会触发这个问题,具体原因与YAML规范有关 195 | 196 | `解决方案`:参考[这里](#YAML规范导致的Int和String的问题) 197 | 198 | ### EPERM: operation not permitted, opendir xxx 199 | 200 | `EPERM: operation not permitted, opendir 'c:\Documents and Settings'` 201 | 202 | `影响范围`:Exe客户端3.x 203 | 204 | `问题原因`:把程序误放到了C盘根目录执行,因为尝试读取了系统保护的目录,没有权限,因此报错 205 | 206 | `解决方法`:把程序放到子目录里运行,不要放到盘符的根目录下执行 207 | 208 | ### EPERM: operation not permitted, open 'xxxxx/updater.log' 209 | 210 | `影响范围`:Exe客户端3.x 211 | 212 | `问题原因`:误把日志文件设置了只读属性或者隐藏属性 213 | 214 | `解决方法`:取消日志文件的只读属性或者隐藏属性。如果需要,可以配置文件里禁用日志或者修改生成位置 215 | 216 | ### EPERM: operation not permitted, lstat 'xxxxx/updater.log' 217 | 218 | `影响范围`:Exe客户端4.x 219 | 220 | `问题原因`:日志文件被包含进了更新规则里 221 | 222 | `解决方法`:从更新规则里排除日志文件,或者将日志文件移动位置,或者禁用日志文件输出 223 | 224 | ### EBUSY: resource busy or locked, unlink 'xxxxx/xxx.xxx' 225 | 226 | `影响范围`:Exe客户端3.x/4.x 227 | 228 | `问题原因`:对应文件被锁定/占用 229 | 230 | `解决方法`:关闭占用的进程。或者检查Minecraft进程是否退出 231 | 232 | ### .minecraft目录更新误在了程序所在目录 233 | 234 | `影响范围`:Exe客户端3.x/4.0.0 235 | 236 | `问题原因`:当程序没有放在`.minecraft`同级目录时会出现这个问题,这个是程序BUG 237 | 238 | `解决方法`:升级到4.0.1或者更高版本 239 | 240 | ### 启动失败出现LittleWrapper Error occurred 241 | 242 | 倒数第二/三行为:`cause: failed to open the file: xxx.exe` 243 | 244 | 倒数第一行为:`probable reason: xxxx (123)`(注意这个123) 245 | 246 | `影响范围`:Exe客户端全版本 247 | 248 | `问题原因`:程序运行路径包含无效的字符 249 | 250 | `解决方法`:检查路径里是否存在特殊符号,或者尝试在英文路径下运行 -------------------------------------------------------------------------------- /faqs/jar-client.md: -------------------------------------------------------------------------------- 1 | ### 更新时窗口无响应卡死或者内容丢失 2 | 3 | `影响范围`:Jar客户端4.1.10及更高 4 | 5 | `问题原因`:目前未知 6 | 7 | `解决方法`:升级到4.1.14版本或更高。然后在配置文件里把主题禁用即可`disable-theme: true` 8 | 9 | ### 连接中断 10 | 11 | `影响范围`:Jar客户端4.1.10及更高 12 | 13 | `问题原因`:由于网络原因,已建立的TCP连接被意外断开 14 | 15 | `解决方法`:这不是程序bug,请检查客户端与服务器之间的网络是否流畅 16 | 17 | ### 连接被拒绝 18 | 19 | `影响范围`:Jar客户端4.1.10及更高 20 | 21 | `问题原因`:由于网络原因,服务器拒绝了客户端的TCP请求 22 | 23 | `解决方法`:这不是程序bug,请排查与服务器直接的网络是否通常,是否需要放开安全组规则,配置端口映射,放行服务器防火墙规则,也请检查客户端配置文件中的地址是否填写错误等 24 | 25 | ### 连接超时 26 | 27 | `影响范围`:Jar客户端4.1.10及更高 28 | 29 | `问题原因`:由于网络原因,服务器未能在指定时间内及时应答客户端的TCP数据包。 30 | 31 | `解决方法`:这不是程序bug,请检查客户端与服务器之间的网络是否稳定 32 | 33 | 一个特例是:如果超时的请求文件为`res.json`并且你使用的是单文件服务端,请检查你的`res`目录体积是不是过大(300mb以上),如果是,请开启单文件服务端的高性能模式。如果你使用的是php服务端,请更换为静态服务端或者单文件服务端。 34 | 35 | ### 配置文件中的选项(xxx)无效 36 | 37 | `影响范围`:Jar客户端4.1.10及更高 38 | 39 | `问题原因`:配置文件`config.yml`中找不到名为xxx的配置项,或者配置项的数据类型不正确 40 | 41 | `解决方法`:删除配置文件并重新从文件内部解压重新配置一次 42 | 43 | ### xxx无法解码为xxx格式 44 | 45 | 可能的情况: 46 | 47 | + `配置文件config.yml`无法解码为`yaml`格式 48 | + `语言配置文件lang.yml`无法解码为`yaml`格式 49 | + `元数据文件请求`无法解码为`json`格式 50 | + `结构文件请求`无法解码为`json`格式 51 | 52 | `影响范围`:Jar客户端4.1.10及更高 53 | 54 | `问题原因`:对应的数据无法解析到对应的格式,比如json格式或者yaml格式 55 | 56 | `解决方法`:如下 57 | 58 | + `配置文件config.yml`无法解码为`yaml`格式:自行检查配置文件的格式是否符合yaml规范 59 | + `语言配置文件lang.yml`无法解码为`yaml`格式:自行检查配置文件的格式是否符合yaml规范 60 | + `元数据文件请求`无法解码为`json`格式:自行检查服务端返回的`index.json`或者`index.php`文件的格式是否符合yaml规范 61 | + `结构文件请求`无法解码为`json`格式:向我报告此问题 62 | 63 | ### Http状态码(xxx)不在2xx-3xx之间 64 | 65 | `影响范围`:Jar客户端4.1.10及更高 66 | 67 | `问题原因`:访问对应URL时,服务端返回了一个表示错误的HTTP状态码(即不在2xx-3xx之间) 68 | 69 | `解决方法`:参考[HTTP状态码不正确](#HTTP状态码不正确) 70 | 71 | ### 由于安全机制或者IO错误,无法访问目录 72 | 73 | `影响范围`:Jar客户端4.1.10及更高 74 | 75 | `问题原因`:参考[安全机制导致操作失败](#安全机制导致操作失败) 76 | 77 | `解决方法`:参考[安全机制导致操作失败](#安全机制导致操作失败) 78 | 79 | ## java.io.IOException 80 | 81 | `java.io.IOException: unexpected end of stream on http://xxx.com...` 82 | 83 | `影响范围`:Jar客户端4.x全版本+单文件服务端全版本 84 | 85 | `问题原因`:暂未找到问题原因 86 | 87 | `解决方法`:重启单文件服务端 88 | 89 | --- 90 | 91 | ### 配置文件读取失败 92 | 93 | `影响范围`:Jar客户端4.1.9及更低 94 | 95 | `问题原因`:配置文件格式不正确,无法按YAML规范读取 96 | 97 | `解决方案`:检查配置文件文件中server选项是否存在,是否拼写错误,以及是否一个字符串 98 | 99 | ### 找不到配置文件 100 | 101 | `影响范围`:Jar客户端全版本 102 | 103 | `问题原因`:找不到配置文件(在Jar文件旁边找不到`config.yml`,同时Jar文件内部也找不到这个问题) 104 | 105 | `解决方案`:检查Jar包内是否有config.yml文件存在,或者检查Jar文件旁是否存在config.yml 106 | 107 | ### 无法连接到更新服务器 108 | 109 | `影响范围`:Jar客户端4.1.9及更低 110 | 111 | `问题原因`:无法与服务器的建立TCP连接 112 | 113 | `解决方案`:检查服务端是否启动成功,是否需要放开安全组,防火墙,或者设置端口映射,并检查与服务端的网络通断 114 | 115 | ### 连接关闭 116 | 117 | `影响范围`:Jar客户端4.1.9及更低 118 | 119 | `问题原因`:成功与服务器的建立TCP连接,但是连接意外断开了 120 | 121 | `解决方案`:请检查网络质量,当文件下载到一半时如果网络闪断,会弹出这个问题 122 | 123 | ### HTTP状态码不正确 124 | 125 | ``` 126 | http状态码不正确(不在2xx-3xx之间) 127 | http://xx.com/xxx.yml with httpcode(404) 128 | Error 404, file not found: /res.yml 129 | ``` 130 | 131 | 例外情况A:错误信息里的URL指向了`res.yml`文件,且状态码为404 132 | 133 | `影响范围`:Jar客户端4.0.0至4.0.9 134 | 135 | `问题原因`:程序bug导致访问到了不存在的文件`res.yml`,正确应该为`res.json` 136 | 137 | `解决方案`:升级到Jar客户端4.0.2版本或者更高 138 | 139 | --- 140 | 141 | 例外情况B:错误信息里的URL指向了`index.php/index.json/index.yml`文件,且状态码为404 142 | 143 | `影响范围`:Jar客户端全版本 144 | 145 | `问题原因`:服务器响应的`index`文件的的HTTP状态码不再3xx-4xx之间 146 | 147 | `解决方案`:请将`config.yml`中的`server`处填写的地址复制粘贴到浏览器打开,正常情况下服务器会返回json格式或者yaml格式的数据,如果不是,请按实际返回的数据进行问题排查 148 | 149 | --- 150 | 151 | 其它情况:对某个`res`目录下的资源返回了非3xx-4xx之间的状态码(比如:`res/.minecraft/mods/[工业2]industrialcraft-2-2.8.188-ex112.jar`等模组文件) 152 | 153 | `影响范围`:Jar客户端全版本+静态服务端(尤其是使用静态服务端) 154 | 155 | `问题原因`:元信息文件`res.yml`报告的文件结构和实际文件结构不一致,导致下载到了一个不存在的文件(404),或者因为权限问题无法访问(403,检查文件访问权限或者存储桶的权限) 156 | 157 | `解决方案`:如果你在使用静态服务端,请严格确保`res.yml`文件内容与实际文件内容一致(如果你看不懂这句话在说什么,请从新阅读一遍静态服务端的教程) 158 | 159 | 如果能确保`res.yml`文件内容与实际文件内容一致,请转到程序日志文件,找到出问题的URL,复制粘贴到浏览器打开。如果能不能打开,说明通过HTTP获取到的`res.yml`文件内容与实际文件内容不一致!如果能打开,请联系我反馈问题。 160 | 161 | 如果你在使用PHP服务端或者单文件服务端时遇到了这个问题,请联系我反馈问题。 162 | 163 | ### 服务器未能响应正确的数据 164 | 165 | 参考问题:[HTTP状态码不正确](#HTTP状态码不正确) 166 | 167 | ### 数据无法解码 168 | 169 | Json无法解码 170 | 171 | `影响范围`:Jar客户端4.1.9及更低 172 | 173 | `问题原因`:客户端配置文件或者服务端返回的数据不是严格的JSON格式 174 | 175 | `解决方案`:首先检查客户端配置文件是否严格符合JSON语法要求。如果客户端配置文件没问题,请将config.yml中的server所填写的地址复制粘贴到浏览器打开,正常情况下服务器会返回json格式或者yaml格式的数据,如果不是,请按实际返回的数据进行问题排查 176 | 177 | ### 找不到.minecraft目录 178 | 179 | 即使把Jar客户端放到`.minecraft`目录旁也提示找不到的问题 180 | 181 | `影响范围`:Jar客户端全版本 182 | 183 | `问题原因`:启动Jar文件时,在`打开方式`中选择了以Java启动打开,而非默认Java启动 184 | 185 | `解决方案`:将Jar文件设置为默认使用Java运行,然后使用双击方式启动 186 | 187 | ### HMCL启动时程序卡死 188 | 189 | 使用HMCL的“启动前指令”启动时Jar客户端程序运行到一半卡死,而单独运行则不会 190 | 191 | `影响范围`:Jar客户端全版本 192 | 193 | `问题原因`:可能是HMCL启动子进程时的stdout缓冲区太小导致(测试大概2kbyes左右) 194 | 195 | `解决方案`:在`java -jar xxx.jar`的后面增加` > nul`语句 196 | 197 | ### ClassCastException(1) 198 | 199 | 完整错误信息:`java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer` 200 | 201 | `影响范围`:Jar客户端4.x 202 | 203 | `问题原因`:代码对服务端获取到的数据进行解析时未判断数据类型导致 204 | 205 | `解决方案`:升级到Jar客户端4.0.3版本或者更高 206 | 207 | ### ClassCastException(2) 208 | 209 | 完整错误信息:`java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String` 210 | 211 | `影响范围`:Jar客户端3.x 212 | 213 | `问题原因`:当遇到文件名是纯数字的文件时会触发这个问题,具体原因与YAML规范有关 214 | 215 | `解决方案`:参考通用问题里的:YAML规范导致的Int和String的问题 216 | 217 | ### _file.listFiles() must not be null 218 | 219 | `影响范围`:Jar客户端4.1.6或更低 220 | 221 | `问题原因`:1.把游戏客户端解压到了某个盘的根目录。2.需要更新的目录中包含无权限访问的目录 222 | 223 | `解决方法`:不要解压到根目录上。放到有权限的目录中或者使用管理员权限运行 224 | 225 | ### org.json.JSON.Exception 226 | 227 | `A JsonArray text must start with xxx` 228 | 229 | `影响范围`:Jar客户端4.1.4 及更早 230 | 231 | `问题原因`:程序内部异常捕获错误(实际报错是JSON无法正常解析,检查服务端`index.json`是否符合JSON规范) 232 | 233 | `解决方法`:更新到Jar客户端4.1.5版本或更高 234 | 235 | ### SocketTimeoutException 236 | 237 | connect timed out 238 | 239 | `影响范围`:Jar客户端4.1.5及更早 240 | 241 | `问题原因`:与服务器建立连接的过程超时 242 | 243 | `解决方法`:检查客户端与服务端的网络通断 244 | 245 | ### 配置文件base-path选项没有效果 246 | 247 | 配置文件中的`base-path`选项设置了之后还是没有效果,还是会提示找不到`.minecraft`文件 248 | 249 | `影响范围`:Jar客户端4.1.5及更早 250 | 251 | `问题原因`:读取配置文件的代码有误,本应该读取`base-path`,实际却读取了`basedir`(重命名后遗留的问题) 252 | 253 | `解决方法`:1.升级到Jar客户端4.1.6或更高版本。2.新增加一个配置项`basedir`,再把基本更新目录写到这个选项后面(此方法不推荐) 254 | 255 | ### 安全机制导致操作失败 256 | 257 | 由于安全机制或者IO错误,无法访问目录: xxx/xxx/xxx.xx 258 | 259 | `影响范围`:Jar客户端4.1.7至4.1.9 260 | 261 | `问题原因`:1.把游戏客户端解压到了某个盘的根目录或者放到了某些系统文件夹里(比如AppData里)。2.需要更新的目录中包含无权限访问的目录 262 | 263 | `解决方法`:1.不要解压到根目录上。2.放到有权限的目录中或者使用管理员权限运行。3.使用`base-path`选项避开访问无权限的目录其是使用静态服务端 264 | -------------------------------------------------------------------------------- /faqs/little-server.md: -------------------------------------------------------------------------------- 1 | ### 配置文件读取出错 2 | 3 | 配置文件读取出错(格式不正确),位置和原因:null 4 | 5 | `影响范围`:单文件服务端全版本 6 | 7 | `问题原因`:配置文件格式不正确,无法按YAML规范读取,可能是反斜线转义导致 8 | 9 | `解决方案`:检查配置文件格式是否符合YAML规范,另外所有单反斜线需要改成双反斜线(`\`改成`\\`) 10 | 11 | ### 高性能模式无法关闭 12 | 13 | 在配置文件里关闭`高性能模式`模式后,启动单文件服务端时仍然会显示`高性能模式已开启` 14 | 15 | `影响范围`:单文件服务端4.0.1 16 | 17 | `问题原因`:代码bug导致无论是否开关高性能模式,都会显示`高性能模式已开启`。但实际高性能模式已经被关闭了,仅仅是显示上出bugl 18 | 19 | `解决方案`:暂无 -------------------------------------------------------------------------------- /faqs/universal.md: -------------------------------------------------------------------------------- 1 | ### 下载大文件时进度条卡住 2 | 3 | 如果你在使用PHP服务端,请尝试使用其它类型的服务端。 4 | 5 | 如果你在使用其它服务端,请确认是否为网络原因 6 | 7 | ### YAML规范导致的Int和String的问题 8 | 9 | yaml规范会默认把纯数字字符串以字符串的形式保存,在读取的时候读取到的就是整形,而不是字符串。对一些强类型语言来说,这会引发错误 10 | 11 | 解决方法: 12 | 13 | 1. 临时解决方法:检查所有参与更新的文件,将所有纯数字的文件名改成非纯数字,需要注意的是,纯数字文件名没有后缀,如果是`1.txt`之类的文件,则不算是纯数字文件名 14 | 2. 如果使用静态服务端:升级小工具到3.1.4或者以上版本 15 | 3. 如果使用PHP服务端:暂无彻底解决的方法,请使用上方的临时解决 16 | 4. 如果使用单文件服务端:升级到0.0.3或者以上的版本 17 | 18 | ### 服务端里找不到index.json文件 19 | 20 | 服务端里找不到`index.json`文件,只有一个`index.yml`文件 21 | 22 | 此问题是由于我打包失误照成的,这个问题仅出现在服务端4.1版本上。 23 | 24 | 如果你遇到这个问题,请重新下载服务端4.1版本的zip包,最新的zip包已经修好了这个问题,或者下载更高版本服务端zip包 25 | 26 | ### 未更新任何文件 27 | 28 | `影响范围`:Jar客户端全版本、Exe客户端全版本 29 | 30 | `问题原因`:所有文件已是最新,或者更新规则和实际文件结构不一致导致检测不到 31 | 32 | `解决办法`:(二选一) 33 | 34 | 1. 完整地重新按文档配置一次(注意不要遗漏任何步骤!) 35 | 2. 通过程序日志排查问题([跳转链接](/check-logs.md)) 36 | 37 | ### 所有文件被意外清空 38 | 39 | 程序误将Minecraft客户端mods等文件夹下的内容全部清空,即使放新文件进去也会被清空 40 | 41 | `影响范围`:Jar客户端全版本、Exe客户端全版本 42 | 43 | `问题原因`:更新规则里列出的目录为空。如果对应目录为空,客户端就会将对应目录下的文件清空 44 | 45 | `解决办法`:将需要被更新的文件放到服务端上**正确**的目录结构下 46 | 47 | ### 忽略文件失效 48 | 49 | `影响范围`:Exe客户端全版本和Jar客户端全版本 50 | 51 | `问题原因`:当你尝试更新mods文件夹或者其它文件夹里所有`.jar`时,如果客户端`mods`文件夹不存在,就会直接下载所有服务端mods里的所有文件 52 | 53 | `解决方法`:此问题影响不大,只需要在客户端创建一个空的对应文件夹即可,比如上面的例子中就需要创建一个空的`mods`文件夹(其它目录同理) -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 文件更新助手帮助文档 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 58 | 59 |
60 | 页面正在加载...
61 | 如果卡在此页面超过10s。请尝试直接访问文档仓库链接:
62 | GitHub源仓库:
https://github.com/BalloonUpdate/Docs 63 |
64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 238 | 239 | 240 | -------------------------------------------------------------------------------- /mcversioning/mcversioning.md: -------------------------------------------------------------------------------- 1 | ## Mc Versioning 2 | 3 | Mc Versioning是新版的更新助手,但使用不同的更新方式,与更新助手使用方式有很大不一样,尤其是服务端部分,所以单独取名为Mc Versioning 4 | 5 | Mc Versioning相比更新助手,有这些优点: 6 | 7 | 1. **检测文件速度快**:Mc Versioning使用基于版本号的更新,而非基于同步的更新。基于版本号的更新速度更快。磁盘IO开销更小,对移动端设备更加友好 8 | 9 | 2. **不用再写更新规则**:更新规则是个很巧妙的设计,但却又是个很反人类的功能,在Mc Versioning中会直接去掉这个辣鸡玩意,程序会自动检测到文件改变,不再需要用更新规则去标明更新范围 10 | 11 | 3. **玩家可以自行添加模组文件**:更新助手中,玩家自行添加的文件,只要命中更新规则的,都会被客户端无情地删除掉。如果要避免这种情况,只能编写复杂又头疼的更新规则,或者模组文件名加前缀,或者使用规则编辑器。但Mc Versioning不会自作主张删掉这些文件,甚至连在更新的时候,玩家自己添加的文件也能得以保留 12 | 13 | 14 | Mc Versioning相比更新助手,有这些缺点: 15 | 16 | 1. 无法检测到玩家对客户端做的修改,具体参考优点三,这个缺点也是更新助手的优点 17 | 2. Mc Versioning服务端以命令行为主,图形界面支持暂时为零 18 | 19 | Mc Versioning和更新助手共同的优点: 20 | 21 | 1. 最小化更新策略,即使落下多个版本,也只下载实际需要更新的文件 22 | 2. 支持移动端Java版和PC端任意三方启动器 23 | 24 | ## 使用教程 25 | 26 | 使用之前需要说明,Mc Versioning的更新方式不同于更新助手,Mc Versioning是采用版本号进行更新的,如果一个客户端的版本是1.7,当服务端发布1.8版本之后,运行客户端程序,客户端会自动更新到1.8版本。如果落后多个版本,客户端程序会依次更新到最新版。 27 | 28 | Mc Versioning有3个可执行文件,其中两个是给服务端用的,另外一个是给客户端用的 29 | 30 | 1. McVersioning.jar:服务端软件,用来管理和打出新的版本包 31 | 2. MiniHttpServer.jar:服务端软件:用来开启一个HttpServer供客户端下载 32 | 3. McVersioningClient.jar:客户端软件,用来更新客户端文件 33 | 34 | ### 创建第一个版本 35 | 36 | 1. 首先在任意位置新建一个文件夹,名字随意,用来存放服务端程序,我这里就叫mvserver 37 | 2. 将McVersioning.jar和MiniHttpServer.jar复制到mvserver目录下 38 | 3. 双击运行McVersioning.jar程序,程序启动后先最小化到任务栏 39 | 4. 可以看到mvserver目录下新增了两个目录client和public 40 | 1. client目录用来存放你要更新的文件,这里也是服主日常维护客户端文件的地方 41 | 2. public目录用来存放你曾经创建的版本,以供给客户端下载。这个目录不要手动修改 42 | 5. 将服务端客户端的模组文件复制到mvserver/client/.minecraft/mods/目录下 43 | 1. 注意并不需要复制所有的文件(这点有别于更新助手),你只需要复制你未来可能会更新的文件就好,如果你能非常确定某个模组文件一万年都不需要更新,那么这种文件你就不用复制过去了。当然,一些会自动下载/生成的文件(一般是模组的一些依赖库,某些模组启动时会自动下载,并不需要手动安装)也不需要复制过去。 44 | 2. 这里仅仅拿.minecraft/mods/目录下的模组文件举例子,如果你有其它文件需要更新,也请同样按照上一条步骤进行操作,复制到你想要的路径上就好。请尽量在第一次配置的时候就把需要更新的文件都复制过去,如果忘了复制,后面再发新版本的时候,你是没办法删掉这些忘记加进client里面的文件的。 45 | 6. 复制好要更新的文件以后,回到McVersioning窗口,点击`扫描更改`按钮,可以看到下面已经显示你新增了一些文件 46 | 7. 点击`版本列表`按钮,在输入框里输入一个版本号比如`1.0`,然后点击`创建版本`按钮,就可以创建出第一个版本了。(版本号可以由任何文字组成,不一定要纯数字,但中文和空格除外!) 47 | 8. 版本创建成功之后点击返回,可以看到窗口又显示"没有任何文件修改了",意思是说client目录现在是干净的 48 | 9. 此时你已经发布了第一个版本。接着我们需要开启一个http服务器以供客户端检查更新 49 | 10. 在命令行窗口里输入`java -jar MiniHttpServer-0.0.0.jar`可以启动MiniHttpServer这个httpserver 50 | 11. 启动成功之后复制API地址后面的链接,粘贴到浏览器打开,如果一切顺利浏览器会显示1.0这个版本号 51 | 12. 把McVersioningClient.jar复制到你即将要发布给玩家的服务器客户端文件夹里,放在启动器旁边也就是.minecraft目录的旁边 52 | 13. 用压缩软件打开McVersioningClient.jar,把config.yml文件解压到McVersioningClient.jar的旁边,打开config.yml文件进行编辑 53 | 14. 将刚刚复制好的API地址粘贴到config.yml中的server选项后面,然后保存关闭 54 | 15. 双击运行McVersioningClient.jar,如果一切正常,就会开始更新第一个版本,更新完成后客户端的版本号会保存在mv-version.txt里面,默认放在程序旁边,如果要调整文件位置,可以修改配置文件 55 | 56 | ### 创建第二第三个版本 57 | 58 | 有别于初次创建第一个版本,创建第二第三个版本要容易的多。如果你的客户端要更新文件了,只需要很简单的几个步骤就能轻松完成 59 | 60 | 1. 在给client目录更换新的文件或者进行修改之前,首先需要确认一下client目录是干净的,也就是client目录没有被改过的,因为你也不想在打新版本时,打进一些奇奇怪怪的东西进去对吧? 61 | 2. 双击运行McVersioning.jar程序,程序启动后会自动检查client目录的修改情况,如果你不放心,可以再手动点一次`扫描更改`来确认一遍 62 | 3. 理想情况下,client目录不应该有任何文件修改。如果要丢弃这些修改,可以点击`还原更改`按钮来使client目录恢复原状,请注意这个命令可能会丢弃你对client目录的一切更改,使用前请十分注意! 63 | 64 | 1. 确保client目录是干净的以后,你就可以对client目录下的文件做替换了,该换新版的文件换新版,该修改的文件修改,该新增的新增,该删除的删除 65 | 66 | 2. 完成之后,点击`版本列表`然后重新打一个新的版本就完成了。这样,一个新的版本就创建好了 67 | 68 | 注意版本号一旦发布就不能撤回了,因为撤回会导致文件状态混乱。你应该额外发布一个更新的版本来替代撤回以修补你的过错 69 | 70 | ## 文件用途介绍 71 | 72 | Mc Versioning在运行时会创建许多文件,本章节会主要介绍这些文件的用途,尤其是public目录下的文件 73 | 74 | public目录下的文件一般不建议手动修改,如特殊情况确实要手动修改,请在修改之前详细阅读本章节的文件说明。如果你在使用软件的时候出现了一些不可逆转的错误,请尽量直接删除整个public目录重头来过,而非进来手动修改文件 75 | 76 | ### public/snapshot目录 77 | 78 | 这个目录用来存储client目录的最新快照。有两个用途:一是用来给客户端提供文件更新下载,二是用来丢弃你对client目录的更改的。此目录由程序自动维护,非特殊情况请勿手动修改 79 | 80 | ### public/snapshot.json文件 81 | 82 | 这个文件用来存储snapshot目录下的文件结构信息,正常情况下此文件内容应该和snapshot目录的文件结构保持一致。此外这个文件也被用来计算与client目录的差异,以此来得知你对client目录都做了哪些修改。此文件由程序自动维护,非特殊情况请勿手动修改 83 | 84 | ### public/all-versions.txt文件 85 | 86 | 这个文件存储着迄今为止你创建的所有版本号,用来给客户端判断落后服务端多少个版本。此文件由程序自动维护,非特殊情况请勿手动修改 87 | 88 | ### public/current-version.txt文件 89 | 90 | 这个文件存储着最新的版本号,用来给客户端快速判断客户端是否需要更新,如果需要更新,则客户端会再次获取all-versions.txt文件判断具体落下了哪些更新。此文件由程序自动维护,非特殊情况请勿手动修改 91 | 92 | ### v-x.x.x.json文件 93 | 94 | x.x.x代表一个实际的版本号。这是一个版本记录文件,是存储每个版本里的文件变化的文件,也就是每个版本你都新增了哪些文件,修改了哪些文件,删除了哪些文件之类的,每一个版本都是一个单独的文件。此文件由程序自动维护,非特殊情况请勿手动修改 95 | 96 | ## 凭空删除文件 97 | 98 | 如果某些文件在你打包第一个版本的时候,忘记复制进client目录了,那么这个这个文件就不能通过删除client目录里的这个文件来实现在客户端也删掉这个文件了。因为client目录里面根本就没有这个文件,所以删不了。 99 | 100 | 如果你要删除某个在客户端有,但在client目录里没有的文件。首先需要打一个新的版本。然后编辑对应的版本记录文件,也就是public/v-xxx.json 101 | 102 | 打开文件后,在old_files字段下手动添加上你要删除的文件的相对路径就可以了。如果要删除目录,请添加在old_folders下。等到客户端更新到这个版本的时候,就会自动删除这些old_files下的文件和old_folders下的目录了 103 | 104 | ## 一些使用提示 105 | 106 | 版本号不强制需要往高迭代,也可以往低迭代,就是说你甚至可以1.5版本更新到1.4版本,这都被允许的。因为版本的前后关系并不是直接判断版本号文字计算出来的,而是按照你打每个版本的时间顺序,后打的版本总是比先打的版本要新(存储在public/all-versions.txt里)版本号文字只是个标签罢了,不作为任何判断版本前后的依据 107 | -------------------------------------------------------------------------------- /navbar.md: -------------------------------------------------------------------------------- 1 | - [首页 Home](/) 2 | - 手册 Manual 3 | - [BalloonServer 服务端](/server/balloon-server-manual.md) 4 | - [单文件服务端](/server/little-server-manual.md) 5 | - [静态服务端](/server/static-server-manual.md) 6 | - [Jar客户端](/client/jar-client-manual.md) 7 | - [ForgeMod客户端](/client/forge-mod-client-manual.md) 8 | - [Jar客户端一键启动(Windows平台)](/client/jar-client-desktop.md) 9 | - [Jar客户端一键启动(Android平台)](/client/jar-client-android.md) 10 | - [更新规则编辑器](/server/rule-editor-tool-manaual.md) 11 | - 参考 Reference 12 | - [编写更新规则](/server/filter-rules-reference.md) 13 | - [单文件服务端](/server/little-server-reference.md) 14 | - [BalloonServer 服务端](/server/balloon-server-reference.md) 15 | - [静态服务端](/server/static-server-reference.md) 16 | - [常见问题解答 FAQ](/faq.md) 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "balloon-update-docs", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "author": "asforest ", 6 | "license": "MIT", 7 | "dependencies": { 8 | "http-server": "^14.1.1" 9 | }, 10 | "scripts": { 11 | "serve": "yarn http-server . -d -c-1 -o" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /server/balloon-server-manual.md: -------------------------------------------------------------------------------- 1 | ## BalloonServer 服务端 Manual 2 | BalloonServer 是由[KasumiNova](https://github.com/KasumiNova)大佬制作的一个完全图形化的单文件服务端,底层基于高性能的 Netty-IO,性能更佳。 3 | 4 | [点击这里](balloon-server-reference.md)跳转到 BalloonServer 服务端的参考页面,了解更多用法和技术细节 5 | 6 | **注意:从 1.0.6-BETA 版本起,程序的最低 JAVA 版本要求提高到了 17。** 7 | 8 | ## 优点 9 | - 99.9% 可视化操作,上手简单便捷 10 | - 开箱即用,无需手动编辑配置文件 11 | - 支持双击启动和 Shell 启动 12 | - 支持配置重载 13 | - 支持 SSL 证书 14 | - 支持实时文件监听,实现全自动服务端维护 15 | - 支持最小化到任务栏托盘(需要系统支持) 16 | - 支持跨平台(Linux, Windows, MacOS) 17 | - 高性能多线程处理,最大化利用服务器资源,减少卡顿 18 | ## 窗口介绍 19 | 20 | ![](../assets/1.png) 21 | 22 | 控制面板将会是你后期最经常接触的面板,每个部分都有不同的功能: 23 | 24 | - 橙色箭头所指的为程序日志,这里将输出程序的普通日志 25 | - 红色箭头所指的为标签页窗口 26 | - 黄色箭头所指的为控制面板,用于控制服务器 启动/关闭,以及配置服务器 27 | - 蓝色箭头所指的为上传列表,当玩家向服务器获取文件时,会在此处显示传输进度 28 | 29 | ***提示:如果操作系统支持系统托盘,则关闭窗口的时候不会关闭程序,而是会最小化到任务栏。*** 30 | ***左击托盘图标即可打开程序,右击托盘图标可打开菜单以退出程序。*** 31 | 32 | ## 使用教程 33 | 1. 下载**单文件图形化增强**目录内的Jar文件(无特殊需求选择最新版即可)并放到一个新建的文件夹里,这个文件夹可以放到任意位置(建议使用纯英文路径) 34 | 2. 双击 JAR 文件或执行命令 `java -jar BalloonServer-1.x.x-BETA.jar` 启动程序 35 | 3. 待软件启动后,就可以看到主窗口了 36 | 4. 在JAR文件的旁边新建一个目录,叫`res` 37 | 5. 如果你要更新模组文件,复制Minecraft客户端中所有的模组文件到`res/.minecraft/mods/`里(目录请自行创建),注意是所有文件。如果你要更新其它文件,同样按上面的方法,复制到`res`目录里对应的路径的目录上(比如vexview的贴图复制到`res/.minecraft/vexview/textures/`下,其它文件同理) 38 | 6. 然后在右侧`控制面板`->`普通更新模式`的列表中点击右键`添加更新规则`,更新规则就是一个路径+通配符,表示哪些需要更新`res`目录下的哪些文件。比如要更新模组文件和vexview的贴图文件可以添加这两条规则,更新其它文件可以模仿这个照葫芦画瓢: 39 | 1. `.minecraft/mods/*.jar` 40 | 2. `.minecraft/vexview/textures/**` 41 | 42 | 43 | 7. 需要注意的是,路径分隔符只能使用正斜线(即使是在Windows上),且避免在更新规则中包含`[]`方括号,会导致更新失败([更新规则示例、参考链接](filter-rules-reference.md)) 44 | 8. 其它参数无需改动,保持默认即可 45 | 9. 点击`控制面板`下方的`保存配置并重置`按钮,然后再点击`重载配置并启动服务器`按钮即可启动服务器。如果你看到`服务器已启动,地址:127.0.0.1:8080`(如果显示`0.0.0.0`请务必替换成`127.0.0.1`访问)的字样,说明启动成功。如果启动失败请换个端口再试试 46 | 10. 复制程序输出的`API地址`后面的链接,到浏览器粘贴并打开,如果显示大串`json`格式的英文(不是json格式就是有问题),那么恭喜,服务端配置无误! 47 | 11. 若你有外网IP或者域名,请将链接中的`127.0.0.1`(或者`0.0.0.0`)替换为对应的外网IP域名再访问一次,再次确认无误后,安装过程就结束了。 48 | 49 | ## 文件管理 50 | 51 | 得益于软件的同步式更新架构,后续对客户端的文件管理其实是非常简单的: 52 | 53 | + 给客户端新增文件:在服务端**添加**对应的文件,客户端那边下次启动时,就会同步更新(开启`实时文件监听`时可以即时生效) 54 | + 删除客户端的文件:在服务端**删除**对应的文件,客户端那边下次启动时,就会同步更新(开启`实时文件监听`时可以即时生效) 55 | + 更新客户端的文件:在服务端**替换**对应的文件,客户端那边下次启动时,就会同步更新(开启`实时文件监听`时可以即时生效) 56 | 57 | 不仅仅是文件,文件夹也是和上面一样的更新逻辑。这样,服务端的内容,就会自动同步到客户端那边。如果没有按预期更新,请检查一下对应的文件/目录是否忘了添加更新规则 58 | 59 | ## 配置SSL证书 60 | 61 | 配置好SSL证书之后,BalloonServer的服务协议会从监听http请求转变为监听https请求。 62 | 63 | 配置过程很简单,点击`控制面板`中`JKS证书文件`后面的`选择按钮`选择你的SSL证书文件(格式必须为Java的JKS格式),然后`JKS证书密码`中输入证书文件的密钥,然后保存配置并重启服务器即可生效 64 | 65 | ## 控制面板按钮 66 | ### 重载配置 67 | 68 | 点击后,服务端会将当前的程序配置应用到程序内,但是不会应用到服务器内。 69 | 70 | ### 保存配置并重载 71 | 点击后,服务端会将当前的程序配置应用到程序内,并保存当前的配置文件至磁盘,但是不会应用到服务器内。 72 | 73 | ### 重新生成资源文件夹缓存 74 | 点击后,服务端会主动生成资源文件夹的缓存,并保存至磁盘。并且会重载服务器的资源文件夹缓存。 75 | ***即使服务器正在运行,程序也可以重载服务器的缓存*** 76 | 77 | ### 重载配置并启动服务器 78 | 点击后,服务端会将当前的程序配置应用到程序内,并应用到服务器内,然后生成资源文件夹缓存,最后启动服务器。如果启用了 `实时文件监听` 功能,程序还会启动实时文件监听器。 79 | 80 | ### 关闭服务器 81 | 点击后,服务端将会在完成最后任务后停止监听端口,如果启用了 `实时文件监听` 功能,程序也会关闭实时文件监听器。 82 | 83 | *Enjoy it~* 84 | -------------------------------------------------------------------------------- /server/balloon-server-reference.md: -------------------------------------------------------------------------------- 1 | ## BalloonServer 服务端 Reference 2 | 3 | ## 监听 IP 和端口 4 | 5 | 点击 `重载配置并启动服务器` 按钮时,程序将会监听此 `IP`和 `端口`传入的请求。 6 | 7 | 监听IP默认是`0.0.0.0`也就是监听所有网卡流量,监听端口默认是8080,如果和其它服务有冲突导致启动失败,可以更换一个别的端口再试 8 | 9 | ## 资源文件夹 10 | 11 | 程序将会 扫描/监听 的文件夹,默认为 `/res`,**如果无特殊需求,请不要动它。** 12 | 13 | 资源文件夹是所有客户端的入口,以如果玩家访问除 `res.json` `index.json` `/res` 之外的路径,将会返回 403 错误。 14 | 15 | ## 最小化更新模式 16 | 17 | 此选项开启后,程序如果在生成缓存后变动文件,则不需要重新生成缓存文件,程序将会最小化检查差异更新,适合服务器 IO 性能较弱的情况下使用。 18 | 19 | 关闭后,程序每次更新缓存文件都会完整计算一次资源文件夹。 20 | 21 | 通常情况下推荐启用,除非在出现了 BUG 的情况下无法正常生成缓存时需要关闭以重新生成缓存。 22 | 23 | *此功能以**多线程**方式计算文件差异,相比 LittleServer, 性能**更加优秀**。* 24 | *此功能会在未来的版本内成为程序的一部分,不再提供 启用/关闭 功能* 25 | 26 | ## 实时文件监听 27 | 28 | 此选项开启后,启动服务器的同时会启动文件监听服务。 29 | 30 | 文件监听服务会每隔 5 - 7 秒会统计一次资源文件夹的变化,如果资源一有变化就会**立即**重新生成资源缓存。 31 | 32 | 此功能使用最小化更新模式的方法生成缓存,并且**不需要**重启服务端。 33 | 34 | 适合在频繁变动文件的情况下使用此功能。 -------------------------------------------------------------------------------- /server/filter-rules-reference.md: -------------------------------------------------------------------------------- 1 | ## 更新规则Reference 2 | 3 | 更新规则也叫文件过滤器,是用来告诉客户端更新哪些文件,不更新哪些的文件的。通常以`json`或者`yaml`格式出现,而且包含2个模式:`common_mode`和`once_mode`。这是两种不同的更新模式。把同一个更新路径写在不同的更新模式下,会有不同的更新策略。通常来说,`common_mode`使用的比较多。 4 | 5 | > 所有的路径分隔符请使用正斜线,不要使用反斜线,即使是在Windows上 6 | 7 | ```yaml 8 | # 此模式适合用来更新常规文件 9 | common_mode: 10 | - .minecraft/mods/*.jar # 只更新一级子目录下的.jar文件 11 | - .minecraft/vexview/textures/* # 只更新一级子目录下的任意后缀文件 12 | - .minecraft/vexview/textures/** # 更新任意级子目录下的任意后缀文件 13 | - .minecraft/vexview/textures/**/*.jar # 更新任意级子目录下的.jar文件 14 | 15 | # 此模式适合用来补全配置文件 16 | once_mode: [] 17 | ``` 18 | 19 | ## 更新模式 20 | 21 | + 写在`common_mode`下是最常用的做法,`common_mode`下所有的文件会被**更新**,这是我们最通俗的更新做法。一般用来更新模组,资源包,贴图等文件 22 | + 写在`once_mode`下时,仅当首次文件/文件夹不存在时会进行一次下载,如果后续文件存在,就会跳过更新不会覆盖已有内容。一般用来补全一些配置文件 23 | 24 | 注意,`common_mode`和`once_mode`的范围不要有重叠,否则会按`common_mode`模式进行更新 25 | 26 | ## 更新规则 27 | 28 | 更新规则类似一个相对路径,所以写起来很简单。如果要匹配一个目录下的所有文件,你可以使用星号来替代文件名,这种写法叫Glob表达式,星号叫通配符(wildcard),也是默认的写法。 29 | 30 | 如果Glob表达式不能实现你的需求,你可以在最前面加上一个`@`符号来转换成一个正则表达式。正则表达式支持更多的玩法,但也更加复杂。 31 | 32 | ### Glob表达式 33 | 34 | Glob表达式虽然简单易用,但并非完美。当你的Glob表达式里包含了`[]`方括号的时候,会导致识别混乱,这是因为方括号在Glob表达式里有特别的含义,且无法转义 35 | 36 | 如果一定要包含方括号,请考虑使用中文括号`【】`或者使用正则表达式(方括号在正则里仍然有特殊含义,但是相比Glob表达式,正则里的方括号可以通过`\`反斜线转义来避免) 37 | 38 | 如果你对Glob表达式感兴趣,可以前往[wikipedia的页面](https://en.wikipedia.org/wiki/Glob_(programming))了解更多内容 39 | 40 | ### 正则表达式 41 | 42 | 相比使用Glob表达式,正则表达式能更精准地控制更新的文件,比如实现高级通配符操作或者排除指定文件/目录。当然也比Glob表达式复杂的多。 43 | 44 | 如果你之前从未接触过正则表达式,同时又对其非常感兴趣,可以参考这篇[正则表达式30分钟入门教程](https://deerchao.cn/tutorials/regex/regex.htm)来快速学习正则表达式的基本用法。 45 | 46 | 使用正则表达式写很简单,只需要在路径最前面加上一个`@`符号就好了,加上`@`符号表明这是一条正则表达式,而不是Glob表达式 47 | 48 | 下面是一个栗子,它只更新mods下的所有.jar文件(非.jar结尾的文件通常是某个模组的依赖库,并不需要参与到更新当中)(这里和Glob表达式的`.minecraft/mods/*.jar`功能一模一样) 49 | 50 | ```yaml 51 | common_mode: 52 | - '@\.minecraft/mods/[^/]+\.jar' 53 | once_mode: [] 54 | ``` 55 | 56 | 如果你喜欢,正则写法也可以和Glob表达式混合使用 57 | 58 | ```yaml 59 | common_mode: 60 | - '@\.minecraft/mods/[^/]+\.jar' 61 | - .minecraft/config/*.conf 62 | once_mode: [] 63 | ``` 64 | 65 | 这里推荐一个在线正则表达式调试工具:https://tool.lu/regex/ 66 | 67 | 需要注意的地方: 68 | 69 | 1. 请注意半角点`.` 的转义和正则本身的一些转义字符的影响 70 | 2. 路径不要以`./`开头,也不要以`/`结尾 71 | 3. 加上@后,记得使用单引号或者双引号包裹当前的值(不然会出现解析错误) 72 | 73 | ## 配置文件示例 74 | 75 | > 还是不太会吗,来看看配置文件示例吧 76 | 77 | ### 示例1 78 | 79 | 需求:更新模组和资源包。更新`.minecraft/mods`和`.minecraft/resourcepacks`文件夹 80 | 81 | Glob写法: 82 | 83 | ```yaml 84 | common_mode: 85 | - .minecraft/mods/* 86 | - .minecraft/resourcepacks/* 87 | once_mode: [] 88 | ``` 89 | 90 | 正则写法: 91 | 92 | ```yaml 93 | common_mode: 94 | - "@\.minecraft/mods" 95 | - "@\.minecraft/resourcepacks" 96 | once_mode: [] 97 | ``` 98 | 99 | ### 示例2 100 | 101 | 需求:只更新服务器提供的模组。同时不会更新玩家自己添加的模组 102 | 103 | 实现此需求的私聊是给所有服务器提供的模组的文件名统一加上一个前缀或者后缀,用来和区分玩家的Mod进行区分。个人比较推荐在所有服务器提供的模组的文件名的后面加上一个英文感叹号`!`作为后缀 104 | 105 | 如果需要批量重命名工具,可以加入交流群,在群文件中的`更新助手——辅助软件`文件夹里找到 106 | 107 | Glob写法: 108 | 109 | ```yaml 110 | common_mode: 111 | - .minecraft/mods/*!.jar 112 | once_mode: [] 113 | ``` 114 | 115 | 正则写法: 116 | 117 | ```yaml 118 | common_mode: 119 | - "@\.minecraft/mods/[^/]\!*\.jar" 120 | once_mode: [] 121 | ``` 122 | 123 | ### 示例3 124 | 125 | 需求:更新mods文件夹里所有.jar结尾文件。只更新.jar结尾的模组 126 | 127 | 有些模组会在mods文件夹里释放依赖库或者保存配置文件,为了避免误删,只需要更新.jar结尾的文件就好,其它类型的文件一律忽略 128 | 129 | Glob写法: 130 | 131 | ```yaml 132 | common_mode: 133 | - .minecraft/mods/*.jar 134 | once_mode: [] 135 | ``` 136 | 137 | 正则写法: 138 | 139 | ```yaml 140 | common_mode: 141 | - "@\.minecraft/mods/[^/]+\.jar" 142 | once_mode: [] 143 | ``` 144 | 145 | ### 示例4 146 | 147 | 需求:更新启动器背景图片、模组文件。更新启动器背景图片、模组文件(以HMCL为例) 148 | 149 | 仅Glob写法: 150 | 151 | ```yaml 152 | common_mode: 153 | - bg/* 154 | - .minecraft/mods/*.jar 155 | once_mode: [] 156 | ``` 157 | 158 | Glob写法和正则写法混合使用: 159 | 160 | ```yaml 161 | common_mode: 162 | - bg/* 163 | - "@\.minecraft/mods" 164 | once_mode: [] 165 | ``` 166 | 167 | ### 示例5 168 | 169 | 需求:只更新除`exclude1.jar`和`exclude2.jar`以外的其它模组文件 170 | 171 | 仅正则写法: 172 | 173 | ```yaml 174 | common_mode: 175 | // 多个忽略的文件之间用竖线|隔开 176 | - "@\.minecraft/mods/(?!exclude1\.jar|exclude2\.jar).*\.jar" 177 | once_mode: [] 178 | ``` 179 | -------------------------------------------------------------------------------- /server/little-server-manual.md: -------------------------------------------------------------------------------- 1 | ## 单文件服务端 Manual 2 | 3 | JVM版本要求:Java8 - Java11 4 | 5 | 单文件服务端是一种开箱即用的更新助手服务端,使用起来最简单。编写语言为大名鼎鼎的Jvav语言,没有任何外部依赖,可以在任何JVM平台上运行。适合小服务器和调试环境使用。 6 | 7 | 最新版的单文件服务端已经可以模拟静态服务端工作了(需开启高性能模式),可以极大减小CPU的计算压力。如果你的服务器规模比较大,同时res目录也比较大,推荐开启高性能模式。 8 | 9 | [点击这里](little-server-reference.md)跳转到单文件服务端的参考页面,了解更多用法和技术细节 10 | 11 | ## 使用教程 12 | 13 | 1. 首先下载服务端zip包,将`单文件服务端`解压到任意位置(建议使用纯英文路径) 14 | 2. 如果你要更新模组文件,复制Minecraft客户端中所有的模组文件到`res/.minecraft/mods/`里(目录请自行创建),注意是所有文件。如果你要更新其它文件,同样按上面的方法,复制到`res`目录里对应的路径的目录上(比如vexview的贴图复制到`res/.minecraft/vexview/textures/`下,其它文件同理) 15 | 3. 编辑配置文件`config.yml`,在`common_mode`下写上所有要进行更新的目录的路径,比如要更新模组文件和vexview的贴图文件可以这样写。需要注意的是,路径分隔符只能使用正斜线(即使是在Windows上),且避免在更新规则中包含`[]`方括号,会导致更新失败(允许玩家自己添加mod可以参考:[更新规则示例、参考链接](filter-rules-reference.md)中的示例2) 16 | 17 | ```yaml 18 | common_mode: 19 | - .minecraft/mods/*.jar 20 | - .minecraft/vexview/textures/** 21 | ``` 22 | 23 | 4. 其它参数无需改动,保持默认即可,保存并关闭配置文件`config.yml`(如果对`config.yml`进行了修改需要重启程序,注意是重启) 24 | 5. 双击`启动.cmd`启动服务端,如果你看到了`启动成功!`的字样,说明启动成功。如果失败请换个端口再试试 25 | 6. 复制程序输出的`API地址`后面的链接,到浏览器粘贴并打开,如果显示大串`json`格式的英文(不是json格式就是有问题),那么恭喜,服务端配置无误! 26 | 7. 若你有外网IP或者域名,请将链接中的`127.0.0.1`(或者`0.0.0.0`)替换为对应的外网IP域名再访问一次,再次确认无误后,安装过程就结束了。 27 | 28 | ## 注意事项 29 | 30 | 注意所有参与更新文件的文件名中请不要包含下列字符,否则会导致更新出错:半角感叹号`!`、波浪号`~`、反引号、星号`*`、Et(And)`&`、Caret`^`、百分号`$`、At`@`、半角冒号`:`、半角分号`;`、半角双引号`"`、反斜线`\` 31 | 32 | ## 文件管理 33 | 34 | 得益于软件的同步式更新架构,后续对客户端的文件管理其实是非常简单的: 35 | 36 | + 给客户端新增文件:在服务端**添加**对应的文件,客户端那边下次启动时,就会同步更新(未开启高性能模式时可以即时生效) 37 | + 删除客户端的文件:在服务端**删除**对应的文件,客户端那边下次启动时,就会同步更新(未开启高性能模式时可以即时生效) 38 | + 更新客户端的文件:在服务端**替换**对应的文件,客户端那边下次启动时,就会同步更新(未开启高性能模式时可以即时生效) 39 | 40 | > 在单文件服务端v4.0.6和更新的版本中,高性能模式选项已经被删除,且功能会默认开启,无需再手动配置 41 | 42 | 不仅仅是文件,文件夹也是和上面一样的更新逻辑。这样,服务端的内容,就会自动同步到客户端那边。如果没有按预期更新,请检查一下对应的文件/目录是否忘了添加更新规则 43 | 44 | ## 加载SSL证书 45 | 46 | 单文件服务端支持加载SSL证书从而提供https协议的服务。SSL证书必须为jks格式,且必须设置一个密码。 47 | 48 | 将jks文件放置到单文件服务端旁边之后,使用`jks-certificate-file`选项来配置证书文件名,使用`jks-certificate-pass`选项来配置证书密码。 49 | 50 | 一切无误之后,重启程序,如果SSL证书加载成功,程序会在启动阶段输出`SSL证书已加载`的信息。 -------------------------------------------------------------------------------- /server/little-server-reference.md: -------------------------------------------------------------------------------- 1 | ## 单文件服务端Reference 2 | 3 | 配置文件参考 4 | 5 | ```yaml 6 | # 监听地址,支持IPV6,默认是0.0.0.0也就是监听本机的所有网卡,一般无需修改此选项 7 | address: 0.0.0.0 8 | 9 | # 监听端口,默认是8000,如果冲突了请换一个别的端口 10 | port: 8000 11 | 12 | # ssl证书路径(jks格式) 13 | jks-certificate-file: 14 | 15 | # ssl证书密码 16 | jks-certificate-pass: 17 | 18 | # 普通更新模式 19 | common_mode: 20 | - .minecraft/** 21 | 22 | # 补全更新模式 23 | once_mode: [] 24 | ``` 25 | 26 | ## 运行时命令 27 | 28 | > 在单文件服务端v4.0.6和更新的版本中,不再支持reload指令,因为高性能模式选项已经被删除,且默认开启,无需再手动刷新缓存 29 | 30 | 单文件服务端在运行时可以输入一部分指令来执行一些功能,目前仅支持2个指令: 31 | 32 | + ~~reload:简写r,用来在开启高性能模式之后,在不重启程序的情况下重新生成**资源目录缓存**~~ 33 | + stop:简写s,用来退出程序。当然也可以用Ctrl+C退出程序或者直接点右上角的叉也是可以的 34 | 35 | ## 高性能模式 36 | 37 | > 在单文件服务端v4.0.6和更新的版本中,高性能模式选项已经被删除,此功能会默认开启,无需再手动配置。且不需要再手动刷新缓存,程序会处理好各种情况。 38 | 39 | ~~单文件服务端开启高性能模式之后,会变成一个静态服务端,也就是会预先生成**资源目录缓存**并缓存到内存里,而不是每次都实时生成,可以节省CPU压力,提升性能。开启后,如果对res目录下的文件做了改动,是需要主动打命令来重新生成一次的,不然客户端可能会报错文件找不到。~~ 40 | 41 | + ~~开启后,修改res目录下的文件之后,需要打指令reload来重新生成**资源目录缓存**~~ 42 | + ~~关闭时,修改res目录下的文件之后,会自动重新生成**资源目录缓存**,不需要打指令~~ 43 | 44 | ~~如果需要手动删除缓存文件强制重新生成,删除cache.json即可。~~ 45 | 46 | -------------------------------------------------------------------------------- /server/rule-editor-tool-manaual.md: -------------------------------------------------------------------------------- 1 | ## 更新规则编辑器 Manual 2 | 3 | **更新规则编辑器**目前支持所有服务端:单文件服务端、静态服务端、BalloonServer 4 | 5 | **更新规则编辑器**是一个独立的小工具,可以以鼠标点击的方式代替编写简单的更新规则。并以颜色标记的方式清晰明了地显示出哪些文件需要更新哪些文件被忽略不更新。 6 | 7 | 更新规则编辑器只能生成很简单的更新规则,并不适用于所有情况。一些复杂的更新规则仍然需要亲自编写。不要过度依赖编辑器,有条件的用户请尽量手写更新规则。 8 | 9 | ![规则编辑器.png](../assets/rule-editor-preview.png) 10 | 11 | ## 已知问题 12 | 13 | 简短版本: 14 | 15 | 如果一个文件你发布新版本之后,新版和旧版本文件名有任何变化,请勿删除旧文件名的更新规则,即使是无效的规则也要保留,永远不能删除。以避免客户端同时出现新旧两个版本文件导致冲突 16 | 17 | 详细版本: 18 | 19 | 确保文件更新前后都使用同一个文件名,如果文件名有变化(尤其是升级mod版本的时候),新文件默认是忽略更新状态的,而旧文件会成为一条无效更新规则。 20 | 21 | 此时我们通常的做法是把新文件加入更新规则,然后把旧文件的更新规则删掉。 22 | 23 | 请注意千万不要这样操作,因为无效的更新并非真的无效,而仅仅是更新规则存,但找不到对应的文件而已。 24 | 25 | 如果你这样操作,会导致旧文件被设置为了忽略更新,无法从客户端删除,而新文件又会被下载。然后就出现了新旧版本共存的问题,如果是模组文件,一定会加载冲突! 26 | 27 | 正确的做法是:将新文件标记为需要更新,然后不要删除旧的文件更新规则。 28 | 29 | 这可能有会有一个问题,就是旧规则会越来越多,列表会越来越占空间。这个问题无解,也是使用编辑器的弊端。最理想的方式是不使用编辑器,而是手写更新规则,并参考更新规则实例里面的“允许玩家添加自己的Mod”章节去编写更新规则,这样可以一劳永逸 30 | 31 | 如果要更新的文件前后文件名并没有发生变化,就不会出现上面的问题。所以规则编辑器适合用来更新文件名不会发生变化的文件,如果文件名会发生变化,比如模组文件名新版本通常就和旧版本不一样,那么是不推荐使用规则编辑器的 32 | 33 | ## 使用教程 34 | 35 | 0. 在使用规则编辑器之前,可以不用清空现有规则,这些规则会以**无效规则**显示在编辑器中,注意不是真的是无效的,只是编辑器无法识别而已,千万不要看都不看就给删掉了!确定不需要再删除! 36 | 1. 将 "规则编辑器" 文件夹复制到 37 | 1. a.单文件服务端根目录下(LittleServer.jar 旁) 38 | 2. b.或者静态服务端的根目录下(run.bat 旁) 39 | 3. c.或者BalloonServer的根目录下(BalloonServer.exe 旁)注意编辑规则期间请完全退出BalloonServer否则不会生效 40 | 2. 根据不同的服务端变体,双击对应的 `启动规则编辑器.cmd` 文件来启动编辑器 41 | 3. 规则编辑器启动成功会输出两个链接,并会自动打开你的浏览器 42 | 如果浏览器没有自动打开,请随意复制其中一个链接到浏览器里手动打开 43 | 4. 点击文件夹可以展示里面的文件。文件夹后面括号里的数字表示文件夹下的更新规则数量 44 | 5. 点击文件可以标记为需要更新或者忽略更新 45 | 将需要更新的文件标记为"普通"更新模式,或者"补全"更新模式即可 46 | 将需要忽略的文件标记为"忽略"(默认所有文件都是忽略状态) 47 | 6. 无效的更新规则会显示在文件的最下方,无效的更新规则并非是真的无效,而是编辑器本身无法直接识别而已,比如带有通配符或者使用了一些正则的高级语法的规则都是无法直接识别的。还有一种可能是文件在更新规则里存在,但实际文件已被删除。无效的更新规则请按需要删除(鼠标悬浮上去可以显示完整的规则) 48 | 7. 所有标记完成后,点击上方的"保存规则"即可保存。如果想丢弃更改,按F5刷新页面即可 49 | 8. 更新规则修改完成后,可以直接关闭黑色窗口来退出规则编辑器,然后关闭浏览器页面 50 | 1. 如果是单文件服务端,重新启动单文件服务端程序 51 | 2. 如果是静态服务端,重新运行 run.bat 上传 52 | 3. 如果是BalloonServer,注意编辑规则期间请完全退出BalloonServer否则不会生效。编辑完成后再次启动BalloonServer程序 53 | 54 | ## 常见问题 55 | 56 | Q:服务端目录下找不到res目录 57 | A:规则编辑器未放置到正确的位置上,请参考教程重新复制一次。同时请检查是否运行了错误的启动脚本(服务端类型选错了) 58 | 59 | Q:Address already in use: JVM_Bind 60 | A:端口冲突,请检查是否同时打开了两个规则编辑器。如果不是请确保6700端口可用 61 | -------------------------------------------------------------------------------- /server/static-server-manual.md: -------------------------------------------------------------------------------- 1 | ## 静态服务端 Manual 2 | 3 | 静态服务端是为没法执行PHP脚本或者Java程序的环境所制作的一种服务端(当然可以执行PHP脚本的主机也同样可以使用静态服务端),比如对象存储上。当然不仅限于对象存储,PHP网站主机和自己搭建的宝塔环境也都是可以使用的。 4 | 5 | 与单文件服务端不同的是,**资源目录缓存**(也就是`res.json`)会提前预先计算好,而不是做实时计算。这样不仅可以部署在纯静态HTTP环境,也能极大提升CPU的处理效率,提高并发的上限。 6 | 7 | 静态服务端适合那些文件存储的物理位置不在本地的场景,比如对象存储,网站主机,GitPages服务等。如果你的文件都是存储在本地或者说自己电脑上的话,建议使用单文件服务端,体验会比静态服务端更友好 8 | 9 | > PHP服务端已经合并到了静态服务端里,相比旧版的PHP服务端,静态服务端的性能更好,而且不依赖任何脚本执行环境(比如JSP,PHP,ASP)。无论是内存占用,还是CPU占用,都比PHP服务端要好的多。 10 | 11 | [点击这里](static-server-reference.md)跳转到单文件服务端的参考页面,了解更多用法和技术细节 12 | 13 | ## 使用教程 14 | 15 | 1. 首先下载服务端zip包,将`静态服务端`解压到任意位置(建议使用纯英文路径) 16 | 2. 如果你要更新模组文件,复制Minecraft客户端中所有的模组文件到`res/.minecraft/mods/`里(目录请自行创建),注意是所有文件。如果你要更新其它文件,同样按上面的方法,复制到`res`目录里对应的路径的目录上(比如vexview的贴图复制到`res/.minecraft/vexview/textures/`下,其它文件同理) 17 | 3. 编辑配置文件`updater/index.json`,在`common_mode`下写上所有要进行更新的目录的路径,比如要更新模组文件和vexview的贴图文件可以这样写。需要注意的是,路径分隔符只能使用正斜线(即使是在Windows上),且避免在更新规则中包含`[]`方括号,会导致更新失败(允许玩家自己添加mod可以参考:[更新规则示例、参考链接](filter-rules-reference.md)中的示例2) 18 | 19 | ```json 20 | { 21 | "update": "res", 22 | "common_mode": [ 23 | ".minecraft/mods/*.jar", 24 | ".minecraft/vexview/textures/**" 25 | ], 26 | "once_mode": [] 27 | } 28 | ``` 29 | 30 | 4. 其它参数无需改动,保持默认即可,保存并关闭配置文件`updater/index.json` 31 | 5. 然后需要将所有文件上传到对象存储或者FTP(PHP主机),这里的上传并不需要每次都手动一个个操作。而是使用静态服务端里自带的增量上传工具。目前自带了4个服务商支持:阿里云对象存储、腾讯云对象存储、七牛云对象存储、FTP协议(适用于网站主机) 32 | 6. 使用静态服务端里自带的增量上传工具上传不会删除现有文件,没有误删文件的风险。但如果有同名文件,仍然会被覆盖 33 | 7. 然后根据你选择的服务商的不同,执行下面不同的步骤 34 | 35 | ## a.腾讯云对象存储 36 | 37 | 1. 编辑`tools/tencent/tencent.cos.yaml`文件 38 | 1. 将`cos.base.secretid`修改为你的腾讯云账号的Secret Id(具体方法请查看腾讯云文档) 39 | 2. 将`cos.base.secretkey`修改为你的腾讯云账号的Secret Key(具体方法请查看腾讯云文档) 40 | 3. 将`cos.buckets[0].name`修改为你的桶名(一般是aaa-bbbbb格式,aaa是桶名,bbbbbb是账号id) 41 | 4. 将`cos.buckets[0].endpoint`修改为你桶的地域(一般是cos.ap-xxxxxx.myqcloud.com格式,xxxxxx是地域的拼音) 42 | 5. 其它选项不需要修改,保存并关闭配置文件 43 | 2. 运行`静态服务端/run.bat`,然后选择3按回车,即可执行上传操作 44 | 3. 将桶的权限设置为**公有读私有写** 45 | 46 | ## b.阿里云对象存储 47 | 48 | 1. 编辑`tools/aliyun/aliyun.oos.ini`文件 49 | 1. 将`accessKeyID`修改为你的阿里云账号的accesskey id(具体方法请查看阿里云文档) 50 | 2. 将`accessKeySecret`修改为你的阿里云账号的accesskey secret(具体方法请查看阿里云文档) 51 | 3. 将`endpoint`修改为你桶的地域(一般是oss-cn-xxxxx.aliyuncs.com格式,xxxxx是地域的拼音) 52 | 4. 其它选项不需要修改,保存并关闭配置文件 53 | 2. 编辑`tools/aliyun/config.yml`文件 54 | 1. 修改`variables.bucket-name`为你的桶名 55 | 3. 运行`静态服务端/run.bat`,然后选择1按回车,即可执行上传操作 56 | 4. 将桶的权限设置为**公有读私有写** 57 | 58 | ## c.七牛云对象存储 59 | 60 | 1. 在`静态服务端/tools/qiniuyun`目录下打开终端(在目录空白处按Shift+右键,然后点击*启动命令提示符*) 61 | 2. 在终端输入`qshell.exe account -L -w -- ak sk name`来配置七牛云工具 62 | 1. `ak`请替换成你七牛云的ak信息 63 | 2. `sk`请替换成你七牛云的sk信息 64 | 3. `name`请替换成你七牛云的账号名(一般是手机号) 65 | 4. 输入`exit`关闭终端 66 | 3. 编辑`tools/qiniuyun/config.yml`文件 67 | 1. 修改`variables.bucket`为你的桶名(另外七牛云的桶不区分地域) 68 | 2. 其它选项不需要修改,保存并关闭配置文件 69 | 4. 运行`静态服务端/run.bat`,然后选择2按回车,即可执行上传操作 70 | 71 | ## d.FTP协议 72 | 73 | FTP并不是一个具体的服务商,而是指的FTP协议,可以把文件上传到所有支持FTP协议的服务器上,通常我们购买的PHP网站主机都是使用的FTP协议去后台管理文件的 74 | 75 | 使用ftp协议需要额外安装Java环境,最低Java8,并能在终端中使用java目录访问即可 76 | 77 | 1. 编辑`tools/ftp/config.yml`文件 78 | 1. 修改`variables.user`为你的FTP用户名 79 | 2. 修改`variables.pass`为你的FTP用户密码 80 | 3. 修改`variables.base-path`为你要将文件上传到哪个目录上(如果未填写路径就是根目录,支持填写子目录(子目录需要自行创建)。另外末尾没有正斜线`/`) 81 | 4. 其它选项不需要修改,保存并关闭配置文件 82 | 2. 运行`静态服务端/run.bat`,然后选择4按回车,即可执行上传操作 83 | 84 | ## 注意事项 85 | 86 | 增量上传文件之后,就不要再手动修改对应的远端目录,因为这样很容易会造成两边文件对不上,从而上传报错。建议全程使用增量上传工具来维护远端目录的内容。 87 | 88 | 因为程序为了IO效率,不会真的去索引远端目录有哪些文件,而是将远端目录结构保存到一个**状态文件**(可以理解为单文件服务端的**资源目录缓存**),这个文件叫`remote-structure.json`,存放在`tools`目录下,每次程序执行对远端目录的修改的时候,都会去更新这个状态文件。如果你不小心手动修改了远端文件,从而打乱了两边文件状态的一致性,请先删除远端对应的整个目录,然后删除本地的状态文件`tools/remote-structure.json`,之后重新上传,这样就可以重建两边文件的状态了。 89 | 90 | 另外`updater/res.json`文件请不要手动编辑,此文件是旁边的`res`目录生成的**资源目录缓存**,是由脚本自动生成并维护的,无需手动管理 91 | 92 | 注意所有参与更新文件的文件名中请不要包含下列字符,否则会导致更新出错:半角感叹号`!`、波浪号`~`、反引号、星号`*`、Et(And)`&`、Caret`^`、百分号`$`、At`@`、半角冒号`:`、半角分号`;`、半角双引号`"`、反斜线`\` 93 | 94 | ## 文件管理 95 | 96 | 得益于软件的同步式更新架构,后续对客户端的文件管理其实是非常简单的: 97 | 98 | + 给客户端新增文件:在服务端**添加**对应的文件,然后进行一次上传,客户端那边就会同步更新 99 | + 删除客户端的文件:在服务端**删除**对应的文件,然后进行一次上传,客户端那边就会同步更新 100 | + 更新客户端的文件:在服务端**替换**对应的文件,然后进行一次上传,客户端那边就会同步更新 101 | 102 | 不仅仅是文件,文件夹也是和上面一样的更新逻辑。这样,服务端的内容,就会自动同步到客户端那边。如果没有按预期更新,请检查一下对应的文件/目录是否忘了添加更新规则。 103 | 104 | -------------------------------------------------------------------------------- /server/static-server-reference.md: -------------------------------------------------------------------------------- 1 | ## 静态服务端Reference 2 | 3 | 静态服务端是由一些脚本文件和一些可执行文件缝合而成的一个整合包(你没看错),这样的模块化设计对扩展和定制方面特别友好。静态服务端的核心文件是一个叫`incremental-upload.exe`的文件。这是一个工具软件,可以将本地有修改的文件增量地上传到各个地方(对象存储或是FTP),未修改的文件不会上传,可以节省带宽和时间。具体的上传过程会由`incremental-upload.exe`调用具体命令行来完成。这个命令行可以自由配置,也就是说只要写好了调用命令行,那么`incremental-upload.exe`可以将文件上传到任何地方!包括私有的服务器。 4 | 5 | 静态服务端目前仅提供了Windows x64平台的整合,如果你需要在Linux平台下使用,请过来催更一下。 6 | 7 | ## incremental-upload工具 8 | 9 | `incremental-upload`工具是一个开源命令行工具程序,用rust语言编写,拥有较高的执行性能和较少的内存BUG(源代码也会随可执行文件一起附赠)。同时也是静态整合包里面最核心的一个工具,负责计算文件差异,然后将新文件上传到远端,然后将旧文件删除掉。 10 | 11 | 加载不同的配置文件之后,可以实现不同服务商/协议的上传效果,目前自带了4个服务商/协议支持: 12 | 13 | + 阿里云对象存储 14 | + 腾讯云对象存储 15 | + 七牛云对象存储 16 | + FTP协议(适用于网站主机) 17 | 18 | 如果你需要增加一个新的协议或者是服务商的支持,请阅读[添加服务商支持(自由化部署)](#添加服务商支持)章节 19 | 20 | ## 工作流程 21 | 22 | `incremental-upload`工具的工作流程如下,先读取远端的文件结构(当然不会真的去索引远端文件,而是从一个存在于本地的**状态文件**(通常是`tools/remote-structure.json`)里读取,`incremental-upload`会维护这个文件的内容使其与远端一致)。在知道了远端目录的结构之后,就会与本地的目录进行对比,计算出文件差异。文件差异分4个部分: 23 | 24 | + 旧文件:本地不存在但远端存在的文件。需要将远端的这个文件删除,以和本地保持同步 25 | + 旧目录:本地不存在但远端存在的目录。需要将远端的这个目录删除,以和本地保持同步 26 | + 新文件:本地存在但远端不存在的文件。需要将这个文件上传到远端,以和本地保持同步 27 | + 新目录:本地存在但远端不存在的目录。需要在远端新建这个空目录,以和本地保持同步 28 | 29 | 这4个部分会按上面的顺序依次执行,已确保先删除目录下的文件,再删除父目录,然后先创建文件夹,再上传文件。此为,每个部分都会调用一个具体的外部命令行,若干次,去执行实际的操作。至于若干次是多少次,那就要看旧文件或者旧目录部分下有多少个新文件/旧文件了。100个新文件会调用100次上传文件的命令行。1000个旧文件会调用1000此删除文件的命令行,以此类推。 30 | 31 | 所有外部命令行调用完成之后,`incremental-upload`工具就会再次遍历这些文件差异,以对**状态文件**(也叫远端目录结构文件)进行更新(这些操作都是在程序内部的内存里完成的,此时就不会调用外部命令行了)。此时状态文件就又能和远端结构保持同步了。然后程序就执行完毕了。 32 | 33 | 其实这里面有个问题:一旦使用`incremental-upload`工具进行第一次上传之后,就再也不能对远端文件进行手动管理了,不然会造成状态文件里的远端文件结构和实际对不上,在执行命令行时出现文件找不到的问题,或者目录不存在的问题。如果不小心破坏这个一致性,那么就需要删除本地的`tools/remote-structure.json`文件和清空对应的远端目录再进行上传,以重建状态文件。 34 | 35 | ## 配置文件 36 | 37 | 基本功能配置 38 | 39 | ```yaml 40 | # 源目录路径(支持使用自定义变量) 41 | # 源目录就是要上传的文件都存放所在的那个目录,通常是updater目录,这里从变量里进行读取 42 | source-dir: $source 43 | 44 | # 状态文件路径(支持使用自定义变量) 45 | # 状态文件就是存储远端目录结构的文件,有了这个文件,程序就不用去实际索引远端文件了,而是直接从这个文件里进行读取,这里从变量里进行读取 46 | state-file: $state 47 | 48 | # 是否开启覆盖模式,开启后需要先删除后上传的文件会跳过删除步骤,仅进行上传 49 | # 覆盖模式就是,如果文件被修改了,通常的做法是先将远端的这个文件删除,然后再上传这个文件。 50 | # 开启覆盖模式之后,就不会删除了,而是直接走上传流程。如果你的服务商/协议不支持覆盖这种操作,请关闭这个选项 51 | overlay-mode: true 52 | 53 | # 是否开启快速对比模式,开启后优先对比文件修改时间,然后才是文件hash 54 | # 开启后在计算本地文件差异时,会先看文件的修改时间,如果与远端一致,就不再检测hash。如果不一致则再检查hash判断文件是否相同 55 | # 开启后可以极大加快检查文件差异的过程,节省不必要的IO操作,通常推荐开启 56 | fast-comparison: true 57 | 58 | # 是否使用本地状态文件,若与use-remote-state同时开启,则download-state不会被执行 59 | # 用于存储远端目录结构的状态文件,是否保存到本地。推荐保存到本地,这样读取起来比较快,如果需要同时也保存到远端一份,可以开启use-remote-state。 60 | use-local-state: true 61 | 62 | # 是否使用远程状态文件,若与use-local-state同时开启,则download-state不会被执行 63 | # 用于存储远端目录结构的状态文件,是否保存到远端。开启后每次更新状态文件之后,都会调用专门的命令行将状态文件上传到远端一份。 64 | # 此选项通常是不开启的,因为每次上传消耗额外的时间和流量,除非你特别特别担心位于本地的状态文件丢失后会打破状态文件与远端实际文件结构的一致性。此时可以考虑开启此选项 65 | use-remote-state: false 66 | 67 | # 状态文件缩进数量 68 | # 状态文件是以Json格式保存的,此选项用来调整Json文本的缩进数量,设置为0可以缩减文件大小,节省流量。 69 | # 设置为2或者4会增大状态文件大小,但文件内容的可读性会提升。生产环境建议设置为0 70 | state-indent: 0 71 | 72 | # 命令执行时使用的并发数,有效指令:delete-file, upload-file 73 | threads: 1 74 | 75 | # commands节点下所有的命令执行时的工作目录,默认继承自父进程 76 | # 此选项用来配置在执行commands节点下的目录时,子进程的工作目录,如果留空则会继承父进程的工作目录 77 | command-workdir: tools/tencent 78 | 79 | # 文件过滤器,使用正则表达式语法,匹配的文件才会被执行到delete-file, delete-dir, upload-file, making-dir命令中 80 | # 若有多个过滤器,文件路径需要全部匹配才会执行delete-file, delete-dir, upload-file, making-dir命令 81 | # 如果过滤器以!开头,则过滤器的匹配条件会被翻转。未匹配时返回true,匹配时返回false 82 | # 文件过滤器可以过滤掉一些Logs文件或者Cache文件,这些文件不会被上传到远端,可以节省流量。如果过滤器为空,则任何文件都会被上传到远端 83 | # 使用小提示:此选项配置好之后,可以直接打开命令行终端,在incremental-upload.exe的后面传入--test-filter参数 84 | # 此时incremental-upload会进入过滤器测试模式,会列出所有匹配的文件路径,匹配的文件都会上传。此方法可以用于快速调试file-filters选项 85 | file-filters: [] 86 | ``` 87 | 88 | 自定义变量配置。这里的变量仅仅是会进行简单文本替换的变量,并不是指环境变量,也不会从环境变量进行继承。 89 | 90 | ```yaml 91 | # 自定义变量定义,变量之间可以互相嵌套使用。注意不要出现环形嵌套,程序会陷入死循环的 92 | variables: 93 | source: updater 94 | state: tools/remote-structure.json 95 | cli: coscli-windows.exe -c tencent.cos.yaml 96 | bucket: 'cos://my-default-bucket' 97 | ``` 98 | 99 | 文件操作命令用于执行实际的远端文件管理操作:上传文件、删除文件、新建目录、删除目录等。 100 | 101 | 所有捕获的子进程(命令行)输出都是使用utf-8进行解码的,如果你的程序不是使用utf-8,则输出的文字可能是乱码(乱码不会影响程序正常运行,仅会影响人类阅读)。 102 | 103 | 子命令可以写成列表的形式来指定多个命令顺序执行,如果其中有一个命令的返回值不是0,则整个程序中断运行,并打印相关的报错信息。可以利用整个机制在`start-up`里检查一些python环境或者是java环境有没有安装,如果没有安装则不会执行后面的代码 104 | 105 | ```yaml 106 | # 文件操作命令 107 | # 所有命令可用的全局变量: 108 | # $source:源目录的绝对路径(路径分隔符为正斜线/) 109 | # $workdir:工作目录的绝对路径(路径分隔符为正斜线/) 110 | # $source_:源目录的绝对路径(路径分隔符为反斜线\) 111 | # $workdir_:工作目录的绝对路径(路径分隔符为反斜线\) 112 | # $last-stdout:同一个子指令下面,前一个命令执行结果所捕获的标准输出流内容,首个指令无此变量 113 | # $last-stderr:同一个子指令下面,前一个命令执行结果所捕获的标准错误流内容,首个指令无此变量 114 | # 每个子指令都可以写成列表的形式来执行多个步骤,比如 115 | # start-up: 116 | # - echo step one now 117 | # - echo step two now 118 | # 如果子命令写成上面那样的单行单行的列表,每一行的字符串都会被按空格拆分成程序名+应用程序参数的形式 119 | # 如果写成子列表的形式,则直接使用你指定的拆分顺序,而不是由程序自动按空格拆分(多数情况下你并不需要用到该功能) 120 | # 也可以将子命令写成列表和单行混用的形式。如果你的命令行就是单行,且不希望被自动拆分,可以在字符串最前面加一个+来避免 121 | # start-up: # 演示混合风格 122 | # - echo step one now # 使用自动命令行拆分(按空格):[echo, step, one, now],其中echo是程序名,step和one是参数 123 | # - - echo # 使用手动命令行拆分:[echo, step one, now],其中echo是程序名,step one是参数1。now是参数2 124 | # - step two 125 | # - now 126 | # - +echo step three now # 禁用自动命令行拆分:[echo step three now],其中echo step three now是一个完整的文件名,后面无任何参数 127 | commands: 128 | # 传输初始化命令,在有文件差异存在时,此命令最先被执行。若无文件差异,则不会被执行 129 | start-up: 130 | 131 | # 传输清理命令,在有文件差异存在时,此命令最后被执行。若无文件差异,则不会被执行 132 | clean-up: 133 | 134 | # 将远程状态文件下载到本地的命令,仅当开启use-remote-state且use-local-state未被开启时会被执行 135 | download-state: $cli cp "$bucket/$state" "$state" 136 | 137 | # 将本地状态文件上传到远程的命令,仅当开启use-remote-state时会被执行 138 | upload-state: $cli cp "$state" "$bucket/$state" 139 | 140 | # 删除远程文件的命令 141 | # 可用局部变量:$path:文件的相对路径、$path_:路径分隔符为反斜线版本的$path 142 | delete-file: $cli rm "$bucket/$path" --force 143 | 144 | # 删除远程目录的命令 145 | # 可用局部变量:$path:文件的相对路径、$path_:路径分隔符为反斜线版本的$path 146 | delete-dir: 147 | 148 | # 将本地文件上传到远程的命令 149 | # 可用局部变量:$path:文件的相对路径、$path_:路径分隔符为反斜线版本的$path 150 | upload-file: $cli sync "$source/$path" "$bucket/$path" 151 | 152 | # 创建一个远程目录的命令 153 | # 可用局部变量:$path:文件的相对路径、$path_:路径分隔符为反斜线版本的$path 154 | making-dir: 155 | ``` 156 | 157 | ## 添加服务商支持 158 | 159 | 要添加新的服务商支持,只需要修改YAML格式的配置文件就好了,完全无需编写代码,这也是`incremental-upload`最大的优势。 160 | 161 | 1. 复制腾讯云对象存储的配置文件作为模板,然后在上面进行修改:复制`tools/tencent`目录到`tools/custom`目录(只能叫`custom`) 162 | 2. 进入`tools/custom`目录,删除除了`config.yml`以外的其它文件。然后打开`config.yml`编辑配置文件 163 | 3. 修改`commands`节点下的子命令,以实现对远端文件的操作 164 | 1. `start-up`:执行一些初始化工作,一般留空即可 165 | 2. `clean-up`:执行一些清理工作,一般留空即可 166 | 3. `download-state`:下载远端的状态文件到本地,如果`use-remote-state`没有开启,此选项可以留空 167 | 4. `upload-state`:上传本地的状态文件到远端,如果`use-remote-state`没有开启,此选项可以留空 168 | 5. `delete-file`:删除远端文件的命令,可以使用变量`$path`来替换具体文件相对路径 169 | 6. `delete-dir`:删除远端目录的目录,可以使用变量`$path`来替换具体文件相对路径 170 | 7. `upload-file`:上传一个本地文件到远端,可以使用变量`$path`来替换具体文件相对路径 171 | 8. `making-dir`:在远端创建一个空目录,可以使用变量`$path`来替换具体文件相对路径 172 | 4. 其它选项可以按需修改,完成后保存关闭 173 | 5. 删除`tools/service-provider.txt`文件 174 | 6. 重新启动`run.bat`,然后会多出来一个叫`custom`的选项,输入custom的序号按下回车,此时`incremental-upload`就会执行你自己的上传逻辑了 175 | 7. 当然,一般切换上传目标之后,建议一并删除`tools/remote-structure.json`文件,使其重建远端目录结构数据 176 | 8. 如果你需要添加多个服务商的支持,可以在`tools`目录下除了添加`custom`目录以外的目录,并修改`run.bat`文件,在这个脚本照葫芦画瓢,根据前面的代码复制并修改,添加上你自己的服务商名字和选项,再次删除`tools/remote-structure.json`文件并启动`run.bat`就可以看到效果了 177 | 178 | ## 自由化部署 179 | 180 | 如果你不喜欢用`incremental-upload`一键上传。而是偏好生成好状态文件`res.json`之后自己处理。你可以将`incremental-upload`切换为仅生成状态文件的模式。 181 | 182 | 你可以将下面的代码保存到一个`bat`文件里,可以叫它`gen.bat`,然后保存关闭。 183 | 184 | ``` 185 | @echo off 186 | if exist updater\res.json move /Y updater\res.json res.json > nul 187 | tools\incremental-upload-0.0.0-windows-x64.exe --config tools\calculate-res-dot-json.yml 188 | if exist res.json move /Y res.json updater\res.json > nul 189 | pause 190 | ``` 191 | 192 | 双击运行这个文件,就会仅刷新`updater\res.json`这个状态文件而不会执行任何上传操作了。之后你就可以把`updater`目录下的文件做自行处理了,无论是上传到私有服务器,还是存储空间都是没问题的。 -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | ansi-styles@^4.1.0: 6 | version "4.3.0" 7 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 8 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 9 | dependencies: 10 | color-convert "^2.0.1" 11 | 12 | async@^2.6.2: 13 | version "2.6.4" 14 | resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" 15 | integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== 16 | dependencies: 17 | lodash "^4.17.14" 18 | 19 | basic-auth@^2.0.1: 20 | version "2.0.1" 21 | resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" 22 | integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== 23 | dependencies: 24 | safe-buffer "5.1.2" 25 | 26 | call-bind@^1.0.0: 27 | version "1.0.2" 28 | resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" 29 | integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== 30 | dependencies: 31 | function-bind "^1.1.1" 32 | get-intrinsic "^1.0.2" 33 | 34 | chalk@^4.1.2: 35 | version "4.1.2" 36 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 37 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 38 | dependencies: 39 | ansi-styles "^4.1.0" 40 | supports-color "^7.1.0" 41 | 42 | color-convert@^2.0.1: 43 | version "2.0.1" 44 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 45 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 46 | dependencies: 47 | color-name "~1.1.4" 48 | 49 | color-name@~1.1.4: 50 | version "1.1.4" 51 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 52 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 53 | 54 | corser@^2.0.1: 55 | version "2.0.1" 56 | resolved "https://registry.yarnpkg.com/corser/-/corser-2.0.1.tgz#8eda252ecaab5840dcd975ceb90d9370c819ff87" 57 | integrity sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ== 58 | 59 | debug@^3.1.1: 60 | version "3.2.7" 61 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" 62 | integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== 63 | dependencies: 64 | ms "^2.1.1" 65 | 66 | eventemitter3@^4.0.0: 67 | version "4.0.7" 68 | resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" 69 | integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== 70 | 71 | follow-redirects@^1.0.0: 72 | version "1.15.1" 73 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" 74 | integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== 75 | 76 | function-bind@^1.1.1: 77 | version "1.1.1" 78 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 79 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 80 | 81 | get-intrinsic@^1.0.2: 82 | version "1.1.2" 83 | resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598" 84 | integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA== 85 | dependencies: 86 | function-bind "^1.1.1" 87 | has "^1.0.3" 88 | has-symbols "^1.0.3" 89 | 90 | has-flag@^4.0.0: 91 | version "4.0.0" 92 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 93 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 94 | 95 | has-symbols@^1.0.3: 96 | version "1.0.3" 97 | resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" 98 | integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== 99 | 100 | has@^1.0.3: 101 | version "1.0.3" 102 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 103 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 104 | dependencies: 105 | function-bind "^1.1.1" 106 | 107 | he@^1.2.0: 108 | version "1.2.0" 109 | resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" 110 | integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== 111 | 112 | html-encoding-sniffer@^3.0.0: 113 | version "3.0.0" 114 | resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9" 115 | integrity sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA== 116 | dependencies: 117 | whatwg-encoding "^2.0.0" 118 | 119 | http-proxy@^1.18.1: 120 | version "1.18.1" 121 | resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" 122 | integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== 123 | dependencies: 124 | eventemitter3 "^4.0.0" 125 | follow-redirects "^1.0.0" 126 | requires-port "^1.0.0" 127 | 128 | http-server@^14.1.1: 129 | version "14.1.1" 130 | resolved "https://registry.yarnpkg.com/http-server/-/http-server-14.1.1.tgz#d60fbb37d7c2fdff0f0fbff0d0ee6670bd285e2e" 131 | integrity sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A== 132 | dependencies: 133 | basic-auth "^2.0.1" 134 | chalk "^4.1.2" 135 | corser "^2.0.1" 136 | he "^1.2.0" 137 | html-encoding-sniffer "^3.0.0" 138 | http-proxy "^1.18.1" 139 | mime "^1.6.0" 140 | minimist "^1.2.6" 141 | opener "^1.5.1" 142 | portfinder "^1.0.28" 143 | secure-compare "3.0.1" 144 | union "~0.5.0" 145 | url-join "^4.0.1" 146 | 147 | iconv-lite@0.6.3: 148 | version "0.6.3" 149 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" 150 | integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== 151 | dependencies: 152 | safer-buffer ">= 2.1.2 < 3.0.0" 153 | 154 | lodash@^4.17.14: 155 | version "4.17.21" 156 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 157 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 158 | 159 | mime@^1.6.0: 160 | version "1.6.0" 161 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" 162 | integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== 163 | 164 | minimist@^1.2.6: 165 | version "1.2.6" 166 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" 167 | integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== 168 | 169 | mkdirp@^0.5.5: 170 | version "0.5.6" 171 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" 172 | integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== 173 | dependencies: 174 | minimist "^1.2.6" 175 | 176 | ms@^2.1.1: 177 | version "2.1.3" 178 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 179 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 180 | 181 | object-inspect@^1.9.0: 182 | version "1.12.2" 183 | resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" 184 | integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== 185 | 186 | opener@^1.5.1: 187 | version "1.5.2" 188 | resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" 189 | integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== 190 | 191 | portfinder@^1.0.28: 192 | version "1.0.28" 193 | resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" 194 | integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== 195 | dependencies: 196 | async "^2.6.2" 197 | debug "^3.1.1" 198 | mkdirp "^0.5.5" 199 | 200 | qs@^6.4.0: 201 | version "6.10.5" 202 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.5.tgz#974715920a80ff6a262264acd2c7e6c2a53282b4" 203 | integrity sha512-O5RlPh0VFtR78y79rgcgKK4wbAI0C5zGVLztOIdpWX6ep368q5Hv6XRxDvXuZ9q3C6v+e3n8UfZZJw7IIG27eQ== 204 | dependencies: 205 | side-channel "^1.0.4" 206 | 207 | requires-port@^1.0.0: 208 | version "1.0.0" 209 | resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" 210 | integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== 211 | 212 | safe-buffer@5.1.2: 213 | version "5.1.2" 214 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 215 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 216 | 217 | "safer-buffer@>= 2.1.2 < 3.0.0": 218 | version "2.1.2" 219 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 220 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 221 | 222 | secure-compare@3.0.1: 223 | version "3.0.1" 224 | resolved "https://registry.yarnpkg.com/secure-compare/-/secure-compare-3.0.1.tgz#f1a0329b308b221fae37b9974f3d578d0ca999e3" 225 | integrity sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw== 226 | 227 | side-channel@^1.0.4: 228 | version "1.0.4" 229 | resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" 230 | integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== 231 | dependencies: 232 | call-bind "^1.0.0" 233 | get-intrinsic "^1.0.2" 234 | object-inspect "^1.9.0" 235 | 236 | supports-color@^7.1.0: 237 | version "7.2.0" 238 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 239 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 240 | dependencies: 241 | has-flag "^4.0.0" 242 | 243 | union@~0.5.0: 244 | version "0.5.0" 245 | resolved "https://registry.yarnpkg.com/union/-/union-0.5.0.tgz#b2c11be84f60538537b846edb9ba266ba0090075" 246 | integrity sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA== 247 | dependencies: 248 | qs "^6.4.0" 249 | 250 | url-join@^4.0.1: 251 | version "4.0.1" 252 | resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7" 253 | integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA== 254 | 255 | whatwg-encoding@^2.0.0: 256 | version "2.0.0" 257 | resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz#e7635f597fd87020858626805a2729fa7698ac53" 258 | integrity sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg== 259 | dependencies: 260 | iconv-lite "0.6.3" 261 | --------------------------------------------------------------------------------