Skip to content

Instantly share code, notes, and snippets.

@gptlang
Last active February 17, 2025 21:35
Show Gist options
  • Save gptlang/9c424da866e52f506bc3f65701e41f53 to your computer and use it in GitHub Desktop.
Save gptlang/9c424da866e52f506bc3f65701e41f53 to your computer and use it in GitHub Desktop.
Getting Grasscutter and Genshin working on Linux (5.2)
{
"folderStructure": {
"resources": "./resources.zip",
"data": "./data/",
"packets": "./packets/",
"scripts": "resources:Scripts/",
"plugins": "./plugins/",
"cache": "./cache/"
},
"databaseInfo": {
"server": {
"connectionUri": "mongodb://localhost:27017",
"collection": "grasscutter"
},
"game": {
"connectionUri": "mongodb://localhost:27017",
"collection": "grasscutter"
}
},
"language": {
"language": "en_US",
"fallback": "en_US",
"document": "EN"
},
"account": {
"autoCreate": false,
"EXPERIMENTAL_RealPassword": false,
"defaultPermissions": [],
"playerEmail": "GuraGC.io",
"maxPlayer": -1
},
"server": {
"debugWhitelist": [],
"debugBlacklist": [],
"runMode": "HYBRID",
"logCommands": false,
"fastRequire": true,
"http": {
"startImmediately": false,
"bindAddress": "127.0.0.1",
"bindPort": 21000,
"accessAddress": "127.0.0.1",
"accessPort": 0,
"encryption": {
"useEncryption": true,
"useInRouting": true,
"keystore": "./keystore.p12",
"keystorePassword": "123456"
},
"policies": {
"cors": {
"enabled": true,
"allowedOrigins": ["*"]
}
},
"files": {
"indexFile": "./index.html",
"errorFile": "./404.html"
}
},
"game": {
"bindAddress": "127.0.0.1",
"bindPort": 22102,
"accessAddress": "127.0.0.1",
"accessPort": 0,
"useUniquePacketKey": true,
"useXorEncryption": true,
"loadEntitiesForPlayerRange": 300,
"enableScriptInBigWorld": true,
"enableConsole": true,
"kcpInterval": 20,
"logPackets": "NONE",
"isShowPacketPayload": false,
"isShowLoopPackets": false,
"cacheSceneEntitiesEveryRun": false,
"gameOptions": {
"inventoryLimits": {
"weapons": 2000,
"relics": 2000,
"materials": 2000,
"furniture": 2000,
"all": 30000
},
"avatarLimits": {
"singlePlayerTeam": 4,
"multiplayerTeam": 4
},
"sceneEntityLimit": 1000,
"watchGachaConfig": false,
"enableShopItems": true,
"staminaUsage": true,
"energyUsage": true,
"fishhookTeleport": true,
"trialCostumes": false,
"questing": {
"enabled": true
},
"resinOptions": {
"resinUsage": false,
"cap": 200,
"rechargeTime": 480
},
"rates": {
"adventureExp": 1.0,
"mora": 1.0,
"leyLines": 1.0
},
"handbook": {
"enable": false,
"allowCommands": true,
"limits": {
"enabled": false,
"interval": 3,
"maxRequests": 10,
"maxEntities": 25
},
"server": {
"enforced": false,
"address": "127.0.0.1",
"port": 443,
"canChange": true
}
}
},
"joinOptions": {
"welcomeEmotes": [2007, 1002, 4010],
"welcomeMessage": "Welcome to a GuraGC 5.0.0!",
"welcomeMail": {
"title": "Welcome to GuraGC!",
"content": "Hi there!\r\nFirst of all, welcome to GuraGC. If you have any issues, please let us know so that Lawnmower can help you! \r\n\r\nCheck out our:\r\n<type=\"browser\" text=\"Discord\" href=\"https://discord.gg/miHoYo\"/>\n",
"sender": "Lawnmower",
"items": [
{
"itemId": 13509,
"itemCount": 1,
"itemLevel": 1
},
{
"itemId": 201,
"itemCount": 99999,
"itemLevel": 1
}
]
}
},
"serverAccount": {
"avatarId": 10000095,
"nameCardId": 210180,
"adventureRank": 1,
"worldLevel": 0,
"nickName": "GuraGC",
"signature": "Welcome to GuraGC!"
},
"visionOptions": [
{
"name": "VISION_LEVEL_NORMAL",
"visionRange": 80,
"gridWidth": 20
},
{
"name": "VISION_LEVEL_LITTLE_REMOTE",
"visionRange": 16,
"gridWidth": 40
},
{
"name": "VISION_LEVEL_REMOTE",
"visionRange": 1000,
"gridWidth": 250
},
{
"name": "VISION_LEVEL_SUPER",
"visionRange": 4000,
"gridWidth": 1000
},
{
"name": "VISION_LEVEL_NEARBY",
"visionRange": 40,
"gridWidth": 20
},
{
"name": "VISION_LEVEL_SUPER_NEARBY",
"visionRange": 20,
"gridWidth": 20
}
]
},
"dispatch": {
"regions": [],
"dispatchUrl": "ws://127.0.0.1:1111",
"encryptionKey": "6FJ1jsWvg6KTuQai6qiCU3BiGAs+UTO+VyLVZzAo2cI=",
"dispatchKey": "AB3sh8IeAK9fiqXwjWGeurFqMM4RoV6DwjZW78vLnIU=",
"defaultName": "Grasscutter",
"logRequests": "NONE"
},
"debugMode": {
"serverLoggerLevel": {
"levelInt": 10000,
"levelStr": "DEBUG"
},
"servicesLoggersLevel": {
"levelInt": 20000,
"levelStr": "INFO"
},
"logPackets": "ALL",
"isShowPacketPayload": false,
"isShowLoopPackets": false,
"logRequests": "ALL"
}
},
"version": 13
}
##
#
# Copyright (C) 2002-2022 MlgmXyysd All Rights Reserved.
#
##
##
#
# Anime game script for mitmproxy
#
# https://github.com/MlgmXyysd/
#
# *Original fiddler script from https://github.lunatic.moe/fiddlerscript
#
# Environment requirement:
# - mitmdump from mitmproxy
#
# @author MlgmXyysd
# @version 1.0
#
##
import string
from mitmproxy import ctx
from mitmproxy import http
class MlgmXyysd_Anime_Game_Proxy:
def load(self, loader):
loader.add_option(
name="ip",
typespec=str,
default="127.0.0.1",
help="IP address to replace",
)
loader.add_option(
name="port",
typespec=int,
default=21000,
help="Port to replace",
)
loader.add_option(
name="use_https",
typespec=bool,
default=True,
help="Use HTTPS",
)
loader.add_option(
name="dispatch",
typespec=str,
default="",
help="IP address to replace",
)
loader.add_option(
name="dispatch_port",
typespec=int,
default=0,
help="Port to replace",
)
loader.add_option(
name="dispatch_use_https",
typespec=bool,
default=True,
help="Use HTTPS",
)
def request(self, flow: http.HTTPFlow) -> None:
# This can also be replaced with another IP address.
REMOTE_HOST = ctx.options.ip
REMOTE_PORT = ctx.options.port
REMOTE_DISPATCH_HOST = ctx.options.dispatch
REMOTE_DISPATCH_PORT = ctx.options.dispatch_port
REMOTE_DISPATCH_HTTPS = ctx.options.dispatch_use_https
if REMOTE_DISPATCH_HOST == "":
REMOTE_DISPATCH_HOST = REMOTE_HOST
REMOTE_DISPATCH_HTTPS = ctx.options.use_https
if REMOTE_DISPATCH_PORT == 0:
REMOTE_DISPATCH_PORT = REMOTE_PORT
DISPATCH_LIST_DOMAINS = [
"dispatchosglobal.yuanshen.com",
"osusadispatch.yuanshen.com",
"osasiadispatch.yuanshen.com",
"dispatchcntest.yuanshen.com",
"cnbeta01dispatch.yuanshen.com",
"dispatchcnglobal.yuanshen.com",
"cnbeta02dispatch.yuanshen.com",
]
LIST_DOMAINS = [
"api-os-takumi.mihoyo.com",
"hk4e-api-os-static.mihoyo.com",
"hk4e-sdk-os.mihoyo.com",
"account.mihoyo.com",
"log-upload-os.mihoyo.com",
"devlog-upload.mihoyo.com",
"webstatic.mihoyo.com",
"log-upload.mihoyo.com",
"hk4e-sdk.mihoyo.com",
"api-beta-sdk.mihoyo.com",
"api-beta-sdk-os.mihoyo.com",
"sdk-os-static.mihoyo.com",
"webstatic-sea.mihoyo.com",
"webstatic-sea.hoyoverse.com",
"hk4e-sdk-os-static.hoyoverse.com",
"sdk-os-static.hoyoverse.com",
"api-account-os.hoyoverse.com",
"hk4e-sdk-os.hoyoverse.com",
"overseauspider.yuanshen.com",
"gameapi-account.mihoyo.com",
"minor-api.mihoyo.com",
"public-data-api.mihoyo.com",
"uspider.yuanshen.com",
"sdk-static.mihoyo.com",
"abtest-api-data-sg.hoyoverse.com",
"log-upload-os.hoyoverse.com",
"webapi-os.account.hoyoverse.com",
]
if flow.request.host in LIST_DOMAINS:
if ctx.options.use_https:
flow.request.scheme = "https"
else:
flow.request.scheme = "http"
flow.request.host = REMOTE_HOST
flow.request.port = REMOTE_PORT
if flow.request.host in DISPATCH_LIST_DOMAINS:
if REMOTE_DISPATCH_HTTPS:
flow.request.scheme = "https"
else:
flow.request.scheme = "http"
flow.request.host = REMOTE_DISPATCH_HOST
flow.request.port = REMOTE_DISPATCH_PORT
addons = [MlgmXyysd_Anime_Game_Proxy()]

Getting Grasscutter and Genshin working on Linux

Getting Grasscutter up and running

Get the files in place

Clone the UnknownAnimeGamePS fork of grasscutter.

git clone https://github.com/XeonSucksLAB/UnknownAnimeGamePS

Make sure java 17 is installed.

./gradlew jar

Boom. UnknownAnimeGamePS-1.7.4.jar popped into existence.

Now for the resources, do

wget https://github.com/pmagixc/5.2-res/archive/refs/heads/main.zip -O resources.zip

Do not unzip it.

MongoDB

Containers make life easier. I use podman, you can use docker if you want. Same command.

podman run --name mongodb -p 27017:27017 -d mongodb/mongodb-community-server:latest

You only need to run this the first time. If you stop the container or restart your computer and need to start mongodb again, just

podman start mongodb

Running the server

To make sure you don't need root, you need to modify the config.

In the UnknownAnimeGamePS directory, create config.json. Copy the contents of my config. It should use port 21000 instead of 443.

My config also makes sure resources.zip is used rather than the ./resources directory (recommended)

Now it's easy:

java -jar UnknownAnimeGamePS-1.7.4.jar

Wait a few seconds for it to start up. Warnings are expected.

Once you see the prompt (>), create an account: account create username.

Patching Genshin

First you obviously need Genshin 5.2 installed. A new update is coming out on new years so you will need to download the correct game version when the time comes.

Download link Package size Decompressed package size MD5 checksum
GenshinImpact_5.2.0.zip.001 10.0 GB 20.0 GB 651a72b1adb3bb5be28dcffded9ee7ec
GenshinImpact_5.2.0.zip.002 10.0 GB 20.0 GB ecfcb0aa4b403608aa0089e8cbc0c618
GenshinImpact_5.2.0.zip.003 10.0 GB 20.0 GB 5bac8cd01f87d13dd3e20cbf897731d9
GenshinImpact_5.2.0.zip.004 10.0 GB 20.0 GB 84501620dded6000f758bfc4bde68d50
GenshinImpact_5.2.0.zip.005 10.0 GB 20.0 GB 2d47ee68d07fd698c02001311998498f
GenshinImpact_5.2.0.zip.006 10.0 GB 20.0 GB 8246d93ee1f93ed787bf87314220ed4e
GenshinImpact_5.2.0.zip.007 7.24 GB 14.49 GB fda38b6c9a5f746829abd8b561f51f54
Audio_Chinese_5.2.0.zip 13.42 GB 26.84 GB 10dd6595c3687dec572afdc329c47eec
Audio_English(US)_5.2.0.zip 15.46 GB 30.93 GB c67d7e98f823afce67fe662f76d27388
Audio_Korean_5.2.0.zip 13.17 GB 26.35 GB 071cfaab116ac1578fb6d755c34634e0
Audio_Japanese_5.2.0.zip 17.41 GB 34.84 GB 285fba0cf723fc0ec033944caa1ada5c

Now from the game directory, go to GenshinImpact_Data/Plugins. Back up Astrolabe.dll to a location of your choice, then delete it.

If you trust me, download my build: wget https://github.com/gptlang/hk4e-patch-universal/releases/download/v5.2/Astrolabe.dll

If not, you can build it yourself with Rust cross cross build --target x86_64-pc-windows-gnu --release It will show up in target/x86_64-pc-windows-gnu/release/ext.dll

mitmproxy

Make sure mitmproxy is installed. Do pip install mitmproxy

Download genshin_proxy.py and run mitmproxy -s genshin_proxy.py -k

That's it. Pretty simple. You can change ports around if you modified the config.

Set proxy in wine

Now you need to trust the mitmproxy certificate in wine. Make sure you have set your wine prefixes correctly before doing this.

wine rundll32.exe shell32.dll,Control_RunDLL inetcpl.cpl

Go to content -> certificates -> import.

This should pop up a wizard. Choose ~/.mitmproxy/mitmproxy-ca-cert.cer. Because it's in a hidden directory, it may be hard to find. Copy the file to ~/Downloads/ or somewhere more accessible if so. Usually your Linux files are in the Z: drive in wine.

Now go to connections -> proxy server. Set the address as 127.0.0.1 and port as 8080. Make sure "Use a proxy server" is checked.

You're done!

Run GenshinImpact.exe and log in with the username you created in grasscutter.

It might take a few tries with "Connection timed out". Just try again.

Connecting back to official servers

wine rundll32.exe shell32.dll,Control_RunDLL inetcpl.cpl

Disable proxy connections.

Delete Astrolabe.dll from GenshinImpact_Data/Plugins and put back the backup of the original Astrolabe.dll.

Now you can run Genshin safely again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment