jjzjj

grasscutter 使用指南——Android/Windows/IOS端均已支持

Echidna_ 2023-11-08 原文

grasscutter 使用指南——Android/Windows/IOS端均已支持

前言

grasscutter是某二次元手游的开源后端,目前功能并不完整,但正在contributers正在全速开发中,未来可期。可以部署在linux和windows下,通过代理与各种平台的客户端进行交互。本文提供grasscutter的linux端部署(windows端比较简单)、windows/andriod/ios端的客户端连接指导,其中安卓提供机器root和非root两种情况下的解决方案。本文需要有一定的计算机基础,不面向小白,尽量说的详细,说明部分可能包含简单的shell命令,自行执行,不提供一键安装脚本,不提供已搭建完成的服务器,适合爱折腾的玩家,不希望任何人以此盈利,欢迎进行技术交流,有问题可以问。

关键突破点为mitmproxy在安卓客户端的ca证书安装,安卓可以使用vmos获得一个root过的虚拟机(vmos不要在应用商店下载,有关键功能阉割,去官网下载。root功能需要vip,有慈禧预付费版本,不想花钱的可以自己动手找一下)

更新

目前dev版本已更新秘境和深渊,大世界支持联机。

关键词

SSL、CA证书、grasscutter、某二次元游戏、代理转发、http注入、安卓、IOS、windows

环境准备

  1. java se 17
  2. mongodb 4.0+
  3. mitmproxy

环境准备请自行度娘解决

linux服务端搭建(centos7)

1.git拉取 或 直接下载源代码,并上传到服务器,tar -xzf解压缩

git clone -b development https://github.com/Grasscutters/Grasscutter.git

注意下载的dev版本(如果编译不通过,又不想调试,可以改下stable版本)

1.关闭防火墙或配置放行策略(注意除了常规端口外,要放行TCP和UDP的22102端口)

systemctl stop firewalld

我就比较直接,23333。如果是云服务器,记得去控制台配置一下安全组策略,服务端90%的问题来自这里。

2. 启动mongodb,自行百度linux下如何启动mongodb,这个基本上没啥问题,后续出现27017端口问题或mongodb类似的报错,多半是mongo服务没起或者挂了。

  • 这里提供一个教程,执行到启动mongodb服务并验证即可。

3. 编译,需要java17环境自带gradle全自动编译脚本,执行就完事了。

sh gradlew jar

执行时间视服务器配置而定,如有报错,请检查你的java环境和网络环境,善用度娘

编译成功后会在grasscutter的主目录下 生成一个grasscutter开头(加版本号)的jar文件,直接运行

java -jar grasscutter-1.1.0.jar #1.1.0是我下载的版本

会提示缺少资源文件,并给你创好了资源文件的目录(resources,没创的话自行创一下),里面的内容需要你自己下载。

4. 下载资源文件

github地址

注:此仓库被github停掉的概率较高,注意备份,原因不多说了,dddd。

git clone https://github.com/memetrollsXD/Grasscutter_Resources.git

将Resources下的文件全部复制到grasscutter根目录下的resources文件夹中,包括BinOutput、ExcelBinOutput、Readable、Scripts、Subtitle、TextMap

5. 启动服务器

修改配置文件config.json

{
  "DatabaseUrl": "mongodb://localhost:27017",
  "DatabaseCollection": "grasscutter",
  "RESOURCE_FOLDER": "./resources/",
  "DATA_FOLDER": "./data/",
  "PACKETS_FOLDER": "./packets/",
  "DUMPS_FOLDER": "./dumps/",
  "KEY_FOLDER": "./keys/",
  "SCRIPTS_FOLDER": "./resources/Scripts/",
  "PLUGINS_FOLDER": "./plugins/",
  "DebugMode": "NONE",
  "RunMode": "HYBRID",
  "GameServer": {
    "Name": "Test",
    "Ip": "0.0.0.0",
    "PublicIp": "your public ip",
    "Port": 22102,
    "PublicPort": 0,
    "DispatchServerDatabaseUrl": "mongodb://localhost:27017",
    "DispatchServerDatabaseCollection": "grasscutter",
    "InventoryLimitWeapon": 2000,
    "InventoryLimitRelic": 2000,
    "InventoryLimitMaterial": 2000,
    "InventoryLimitFurniture": 2000,
    "InventoryLimitAll": 30000,
    "MaxAvatarsInTeam": 4,
    "MaxAvatarsInTeamMultiplayer": 4,
    "MaxEntityLimit": 1000,
    "WatchGacha": false,
    "ServerNickname": "Server",
    "ServerAvatarId": 10000007,
    "ServerNameCardId": 210001,
    "ServerLevel": 1,
    "ServerWorldLevel": 1,
    "ServerSignature": "Server Signature",
    "WelcomeEmotes": [
      2007,
      1002,
      4010
    ],
    "WelcomeMotd": "Welcome to Grasscutter emu",
    "WelcomeMailTitle": "Welcome to Grasscutter!",
    "WelcomeMailSender": "Lawnmower",
    "WelcomeMailContent": "Hi there!\r\nFirst of all, welcome to Grasscutter. If you have any issues, please let us know so that Lawnmower can help you! \r\n\r\nCheck out our:\r\n\u003ctype\u003d\"browser\" text\u003d\"Discord\" href\u003d\"https://discord.gg/T5vZU6UyeG\"/\u003e",
    "WelcomeMailItems": [
      {
        "itemId": 13509,
        "itemCount": 1,
        "itemLevel": 1
      },
      {
        "itemId": 201,
        "itemCount": 10000,
        "itemLevel": 1
      }
    ],
    "EnableOfficialShop": true,
    "Game": {
      "ADVENTURE_EXP_RATE": 1.0,
      "MORA_RATE": 1.0,
      "DOMAIN_DROP_RATE": 1.0
    }
  },
  "DispatchServer": {
    "Ip": "0.0.0.0",
    "PublicIp": "your public ip",
    "Port": 14514,
    "PublicPort": 0,
    "KeystorePath": "./keystore.p12",
    "KeystorePassword": "123456",
    "UseSSL": true,
    "FrontHTTPS": true,
    "CORS": false,
    "CORSAllowedOrigins": [
      "*"
    ],
    "AutomaticallyCreateAccounts": false,
    "defaultPermissions": [
      ""
    ],
    "GameServers": []
  },
  "LocaleLanguage": "en_US",
  "DefaultLanguage": "en",
  "OpenStamina": true
}

其实只需要修改两处publicip为你的公网ip,以及如果你不想用443端口,修改一下DispatchServer.port即可,注意这里修改的话,下面的mitmdump的配置也需要同步修改。其他的不涉及网络的选项,你自己看着改。

(我开的端口有点臭,23333)

再执行一次启动命令

java -jar grasscutter-1.1.0.jar

显示游戏服务器在22102端口运行,转发服务器在14514端口运行,即为成功。

此时参照命令表,在该shell窗口输入账号创建命令

account create echidna 114514233

会提示账号创建成功。

QA

  1. java编译失败

列出我遇到的几种可能原因,

    1. java环境没配好,这属于最不太可能的错误,但还是检测一下,输入java --version,看是不是17点几版本的,不是赶紧换。
    1. 网络问题,编译过程会给你安装gradle和一系列jar依赖,看看卡在哪里了自行下载后导入。
    1. 内存问题,编译需要占用较多内存,实测内存512MB失败,2G成功,运行时最低需要1G内存,(本来想用vps服务器的,但vps配置较差,没编过去,哈哈哈)
    1. 程序问题,dev版本编译建失败实属正常现象,要么自己调一下,要么换stable版本。
    1. 上述是我实际遇到过的问题,如依然不能解决,自行百度,本人C++工程师,java属实有点专业盲区。
  1. 程序运行失败
    1. 确认你的resources目录正常存在于编译生成的入口jar文件的同级目录下,并内容齐全。
    1. 确认你config.json文件的json格式没有被破坏,比如手滑多删了个引号(还真有人这么蠢,是谁呢,不会是我吧?)
    1. 确认你的mongodb的守护进程正常,ps -aux | grep mongod
    1. 确认没有程序占用你的端口,netstat -tunlp | grep <你设置的端口,默认是443>,linux下的常见犯人叫ngnix,windows下的常见犯人叫vmware,重点检查。
    1. 确认你的可用内存大于1G
    1. 提示密码错误的,可以把config.json中的DispatchServer.KeystorePassword改为空(原本是空的改为123456,每个版本的key可能放的不一样,反正两个总有一个是对的)。

6. 配置抓包以及http注入

  • 这里我们用到mitmproxy,我看到不少人使用fiddler,但fiddler是基于.net开发的程序,移植到linux并不方便。

  • 可以直接使用pip3安装,没装python3的yum装一下。

pip3 install mitmproxy
  • 会给你安装mitmproxy及其命令行版本,即mitmdump,还有其多版本的ca证书

  • 也可以去官网下载二进制版本,但不带ca证书,需要你自行部署完成后开启代理并访问mitm.it下载,但国内的云服务器不允许域名转发到未备案域名,所以会比较麻烦。

  • 安装完成后,我们回到grasscutter的主目录

      vim proxy_config.py
    

    修改配置文件,如下:

      import os
    
      # This can also be replaced with another IP address.
      USE_SSL = True
      REMOTE_HOST = "your public ip"
      REMOTE_PORT = 14514
    
      if os.getenv('MITM_REMOTE_HOST') != None:
          REMOTE_HOST = os.getenv('MITM_REMOTE_HOST')
      if os.getenv('MITM_REMOTE_PORT') != None:
          REMOTE_PORT = int(os.getenv('MITM_REMOTE_PORT'))
      if os.getenv('MITM_USE_SSL') != None:
          USE_SSL = bool(os.getenv('MITM_USE_SSL'))
    
      print('MITM Remote Host: ' + REMOTE_HOST)
      print('MITM Remote Port: ' + str(REMOTE_PORT))
      print('MITM Use SSL ' + str(USE_SSL))
    

    注意此处的REMOTE_PORT要与上面你修改的dispatchsever的port一致。

    • 配置ca证书
    cp ~/.mitmproxy/mitmproxy-ca-cert.crt /etc/ssl/certs # 这句是安装为根证书,未必需要
    cp ~/.mitmproxy/mitmproxy-ca-cert.pem /etc/pki/ca-trust/source/anchors
    update-ca-trust extract
    
    • 执行转发。重点来了,mitmproxy的安卓代理存在诸多问题,需要添加一系列参数进行规避,而这部分,大部分教程并未提及

      mitmdump -s proxy.py --ssl-insecure --set block_global=false --no-http2
      

      允许不安全的ssl连接,禁用http2连接,以及禁用internet对mitmproxy的直接访问,。

此时,代理服务器会在默认的8080端口启动,同样请确保端口不会冲突。

windows端登陆

  • 配置ca证书

    将服务器端~/.mitmproxy文件夹下的mitmproxy-ca-cert.p12文件拿到windows机器上,直接双击,选择给本地计算机安装,要密码直接空过,自动选择目录即可,重启机器。

  • windows端支持国服和国际服客户端登录,方法非常简单,打开网络和Internet设置,选择代理,打开手动设置代理选项,填写地址和端口,即为你上面设置的publicip和mitmdump的端口(默认8080那个)。

  • 打开客户端,直接用你创建的账号密码登录即可。

QA

  • 为啥我客户端提示网络异常?

    代理端口不对,建议检查你的mitmproxy是否活着,端口号是否正确。

  • 为啥4206了?

    大抵是证书装的有问题罢,要么你没有全局安装,要么可以把上面那个mitmproxy目录下的另外一个p12文件也拉出装一下,目前未验证grasscutter下的证书是否需要安装,可以尝试一下安装那个grasscutter下的keystore.p12文件。

  • 连上去后网络非常不稳定

    你服务器带宽问题。

  • 登录进去显示12-4301

    建议切换美服通道登录

  • 为啥我发现我nohup后台运行程序的服务器炸了?

    硬盘炸了,ssh连不上的话,先去控制台重启一下。首先,必须重定向nohup到dev/null,而且目前grasscutter有bug,会往主目录的log文件夹里疯狂写入latest.log,目前config.json中未发现相关选择,本人是懒得去代码里找,直接选择删除latest.log。

  • 其他问题

    检查你的有没有科学上网啥的,关了。

IOS端登录

  • 自行搜索ios如何安装ca证书,我们要安装的ca证书是~/.mitmproxy目录下的mitmproxy-ca-cert.pem,注意下载完成后要去找到这个文件,点一下,然后再执行证书安装的两个步骤(先安装再信任)。
  • 不要使用小火箭,会有bug,原因很简单,小火箭不会转发udp报文,但我们的grasscuter是依赖于kcp这种udp协议的。
  • IOS端一把成功,没遇到啥问题,有问题应该和上述windows端差不多的解决方法。

Android端登录

比上面的都要复杂,问题主要出在,Android7.0往后,应用可以选择不信任用户证书,而很遗憾该手游app就是设置为不信任的那种,基于此,我想出3条解决方案。

  • magisk,就是俗称的面具root,不过没有备用机,不打算刷掉我的正常使用的手机,并不考虑。
  • 改包,设置为接受用户证书,然后重新打包,值得一试。
  • 使用虚拟机,也就是安卓模拟器。

乍一看,第三点是一个非常抽象的想法,这意味着要在安卓机上装安卓模拟器,这不搞笑吗。但找了一下,真的有这种东西,vmos pro。

至于这玩意咋整,应该没啥技术难度,注意我之前说的关于vmos pro的注意事项即可,剩下的百度解决。

当我们有了一个root过的虚拟机的时候,我需要将ca证书安装到系统目录下,为此需要openssl进行安卓系统ca证书的制作。


yum install openssl
openssl x509 -inform PEM -subject_hash_old -in mitmproxy-ca-cert.pem -noout
cp mitmproxy-ca-cert.pem c8750f0d.0 # 这边的c8750f0d是上一条命令的输出。

将这个文件放入/system/etc/security/cacerts/下,并修改权限为644

设置中长按你所连接的wifi,选择修改网络,设置代理,和上面的其他客户端一样的要求。

连接即可,注意需要国际服客户端。

结语

本人网络方向C++工程师,本来以为可以一晚上解决的,但其实还是研究了不少时间的,毕竟要跑dev版本的java的代码(我跑的那个版本编译都有问题2333),以及一堆ca证书问题,终于全客户端搞定了这玩意,搭建了一个服务器和朋友一起玩玩。为防止一切侵权隐患,以及屏蔽正义游侠,文章概不放图,但该讲到的节点都讲到了,有需要技术支持的请评论区留言,技术支持不收费,三言两语能解决的我都会回答(只要你不是小白,大部分问题属于这种),想以此盈利的请勿打扰(之前看到一个群友截图,大致说是有个卖家某宝98出售私服,结果买家进群,卖家说windows和ios都解决了,让大家等等安卓端的解决方案,笑死)。

关于私服问题,我是持摆烂态度的,只要不借此盈利即可,盈利那是纯纯的收割冤种。毕竟这是一个主打大世界探索的游戏,私服缺少你的核心玩法,注定就该只是自娱自乐。如果说只有单纯抽卡和副本的私服真的能把你干爆了,你是不是该想想自己游戏的问题呢(非指你游)?显然这种私服激不起什么浪花。

有关grasscutter 使用指南——Android/Windows/IOS端均已支持的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  8. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  9. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  10. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

随机推荐