Compare commits
9 Commits
v1.0.0-alp
...
v1.0.1-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de81f9bcac | ||
|
|
3aeacad28c | ||
|
|
27cbd4705b | ||
|
|
24c578b411 | ||
|
|
a6a33a9886 | ||
|
|
17ea745e23 | ||
|
|
98a948d377 | ||
|
|
eaa3a4299b | ||
|
|
bbf4c7033a |
@@ -1,9 +1,14 @@
|
||||
# Troubleshooting
|
||||
A guide dedicated for trying to troubleshoot Cultivation.
|
||||
|
||||
## The launcher doesn't appear to open.
|
||||
Try running the launcher with **administrative privileges**.\
|
||||
If this fixes your issue, you can force enable it in the **Compatability**\
|
||||
tab for the launcher's executable.
|
||||
|
||||
## Unable to play on `localhost`.
|
||||
Make sure your server is running with **encryption disabled**.\
|
||||
Additionally, make sure Cultivation **is not using HTTPS**.
|
||||
Make sure your server is running with **encryption disabled** and `useInRouting` to **false**.\
|
||||
Additionally, make sure Cultivation **is set to not use HTTPS**.
|
||||
|
||||
## "I can't do anything requiring the internet after closing Cultivation!"
|
||||
You probably didn't close Cultivation properly.\
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cultivation",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^1.0.0-rc.5",
|
||||
|
||||
9
src-tauri/Cargo.lock
generated
@@ -2104,12 +2104,6 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "minisign-verify"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "933dca44d65cdd53b355d0b73d380a2ff5da71f87f036053188bf1eab6a19881"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.5.1"
|
||||
@@ -3893,7 +3887,6 @@ checksum = "a34cef4a0ebee0230baaa319b1709c4336f4add550149d2b005a9a5dc5d33617"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"attohttpc",
|
||||
"base64",
|
||||
"bincode",
|
||||
"cocoa",
|
||||
"dirs-next",
|
||||
@@ -3907,7 +3900,6 @@ dependencies = [
|
||||
"heck 0.4.0",
|
||||
"http",
|
||||
"ignore",
|
||||
"minisign-verify",
|
||||
"notify-rust",
|
||||
"objc",
|
||||
"once_cell",
|
||||
@@ -3939,7 +3931,6 @@ dependencies = [
|
||||
"webkit2gtk",
|
||||
"webview2-com",
|
||||
"windows 0.30.0",
|
||||
"zip 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -16,7 +16,7 @@ tauri-build = { version = "1.0.0-rc.8", features = [] }
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tauri = { version = "1.0.0-rc.9", features = ["api-all", "updater"] }
|
||||
tauri = { version = "1.0.0-rc.9", features = ["api-all"] }
|
||||
|
||||
# Access system process info.
|
||||
sysinfo = "0.23.12"
|
||||
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 974 B After Width: | Height: | Size: 954 B |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 903 B After Width: | Height: | Size: 902 B |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 279 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 35 KiB |
@@ -11,8 +11,11 @@
|
||||
"files_extracting": "Files Extracting: "
|
||||
},
|
||||
"options": {
|
||||
"enabled": "Enabled",
|
||||
"disabled": "Disabled",
|
||||
"game_exec": "Set Game Executable",
|
||||
"grasscutter_jar": "Set Grasscutter JAR",
|
||||
"toggle_encryption": "Toggle Encryption",
|
||||
"java_path": "Set Custom Java Path",
|
||||
"grasscutter_with_game": "Automatically launch Grasscutter with game",
|
||||
"language": "Select Language",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
},
|
||||
"package": {
|
||||
"productName": "Cultivation",
|
||||
"version": "1.0.0"
|
||||
"version": "1.0.1"
|
||||
},
|
||||
"tauri": {
|
||||
"allowlist": {
|
||||
@@ -72,7 +72,7 @@
|
||||
"csp": "default-src 'self' https://asset.localhost; img-src 'self'; img-src https://* asset: https://asset.localhost"
|
||||
},
|
||||
"updater": {
|
||||
"active": true,
|
||||
"active": false,
|
||||
"dialog": true,
|
||||
"endpoints": [
|
||||
"https://api.grasscutter.io/cultivation/updater?version={{current_version}}",
|
||||
|
||||
@@ -79,7 +79,6 @@ class App extends React.Component<IProps, IState> {
|
||||
async componentDidMount() {
|
||||
const cert_generated = await getConfigOption('cert_generated')
|
||||
const game_exe = await getConfigOption('game_install_path')
|
||||
const custom_bg = await getConfigOption('customBackground')
|
||||
const game_path = game_exe?.substring(0, game_exe.replace(/\\/g, '/').lastIndexOf('/')) || ''
|
||||
const root_path = game_path?.substring(0, game_path.replace(/\\/g, '/').lastIndexOf('/')) || ''
|
||||
|
||||
@@ -90,6 +89,9 @@ class App extends React.Component<IProps, IState> {
|
||||
await loadTheme(themeObj, document)
|
||||
}
|
||||
|
||||
// Get custom bg AFTER theme is loaded !! important !!
|
||||
const custom_bg = await getConfigOption('customBackground')
|
||||
|
||||
if(!custom_bg || !/png|jpg|jpeg$/.test(custom_bg)) {
|
||||
if(game_path) {
|
||||
// Get the bg by invoking, then set the background to that bg.
|
||||
|
||||
@@ -6,4 +6,13 @@
|
||||
|
||||
margin-bottom: 8px;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.OptionSection .BigButton {
|
||||
height: 100%;
|
||||
min-height: 30px;
|
||||
}
|
||||
|
||||
.OptionSection .BigButtonText {
|
||||
font-size: 12px;
|
||||
}
|
||||
@@ -3,13 +3,15 @@ import { invoke } from '@tauri-apps/api'
|
||||
import { dataDir } from '@tauri-apps/api/path'
|
||||
import DirInput from '../common/DirInput'
|
||||
import Menu from './Menu'
|
||||
import Tr, { getLanguages } from '../../../utils/language'
|
||||
import Tr, { getLanguages, translate } from '../../../utils/language'
|
||||
import { setConfigOption, getConfig, getConfigOption } from '../../../utils/configuration'
|
||||
import Checkbox from '../common/Checkbox'
|
||||
import Divider from './Divider'
|
||||
import { getThemeList } from '../../../utils/themes'
|
||||
import * as server from '../../../utils/server'
|
||||
|
||||
import './Options.css'
|
||||
import BigButton from '../common/BigButton'
|
||||
|
||||
interface IProps {
|
||||
closeFn: () => void;
|
||||
@@ -25,6 +27,7 @@ interface IState {
|
||||
bg_url_or_path: string
|
||||
themes: string[]
|
||||
theme: string
|
||||
encryption: boolean
|
||||
}
|
||||
|
||||
export default class Options extends React.Component<IProps, IState> {
|
||||
@@ -40,7 +43,8 @@ export default class Options extends React.Component<IProps, IState> {
|
||||
current_language: 'en',
|
||||
bg_url_or_path: '',
|
||||
themes: ['default'],
|
||||
theme: ''
|
||||
theme: '',
|
||||
encryption: false
|
||||
}
|
||||
|
||||
this.setGameExec = this.setGameExec.bind(this)
|
||||
@@ -48,11 +52,17 @@ export default class Options extends React.Component<IProps, IState> {
|
||||
this.setJavaPath = this.setJavaPath.bind(this)
|
||||
this.toggleGrasscutterWithGame = this.toggleGrasscutterWithGame.bind(this)
|
||||
this.setCustomBackground = this.setCustomBackground.bind(this)
|
||||
this.toggleEncryption = this.toggleEncryption.bind(this)
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const config = await getConfig()
|
||||
const languages = await getLanguages()
|
||||
|
||||
// Remove jar from path
|
||||
const path = config.grasscutter_path.replace(/\\/g, '/')
|
||||
const folderPath = path.substring(0, path.lastIndexOf('/'))
|
||||
const encEnabled = await server.encryptionEnabled(folderPath + '/config.json')
|
||||
|
||||
this.setState({
|
||||
game_install_path: config.game_install_path || '',
|
||||
@@ -63,7 +73,8 @@ export default class Options extends React.Component<IProps, IState> {
|
||||
current_language: config.language || 'en',
|
||||
bg_url_or_path: config.customBackground || '',
|
||||
themes: (await getThemeList()).map(t => t.name),
|
||||
theme: config.theme || 'default'
|
||||
theme: config.theme || 'default',
|
||||
encryption: await translate(encEnabled ? 'options.enabled' : 'options.disabled')
|
||||
})
|
||||
|
||||
this.forceUpdate()
|
||||
@@ -136,6 +147,26 @@ export default class Options extends React.Component<IProps, IState> {
|
||||
}
|
||||
}
|
||||
|
||||
async toggleEncryption() {
|
||||
const config = await getConfig()
|
||||
|
||||
// Check if grasscutter path is set
|
||||
if (!config.grasscutter_path) {
|
||||
alert('Grasscutter not set!')
|
||||
return
|
||||
}
|
||||
|
||||
// Remove jar from path
|
||||
const path = config.grasscutter_path.replace(/\\/g, '/')
|
||||
const folderPath = path.substring(0, path.lastIndexOf('/'))
|
||||
|
||||
await server.toggleEncryption(folderPath + '/config.json')
|
||||
|
||||
this.setState({
|
||||
encryption: await translate(await server.encryptionEnabled(folderPath + '/config.json') ? 'options.enabled' : 'options.disabled')
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Menu closeFn={this.props.closeFn} className="Options" heading="Options">
|
||||
@@ -155,6 +186,18 @@ export default class Options extends React.Component<IProps, IState> {
|
||||
<DirInput onChange={this.setGrasscutterJar} value={this.state?.grasscutter_path} extensions={['jar']} />
|
||||
</div>
|
||||
</div>
|
||||
<div className='OptionSection'>
|
||||
<div className='OptionLabel'>
|
||||
<Tr text="options.toggle_encryption" />
|
||||
</div>
|
||||
<div className='OptionValue'>
|
||||
<BigButton onClick={this.toggleEncryption} id="toggleEnc">
|
||||
{
|
||||
this.state.encryption
|
||||
}
|
||||
</BigButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Divider />
|
||||
|
||||
|
||||
36
src/utils/server.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { fs } from '@tauri-apps/api'
|
||||
|
||||
export async function toggleEncryption(path: string) {
|
||||
let serverConf
|
||||
|
||||
try {
|
||||
serverConf = JSON.parse(await fs.readTextFile(path))
|
||||
} catch(e) {
|
||||
console.log(`Server config at ${path} not found or invalid`)
|
||||
return
|
||||
}
|
||||
|
||||
const enabled = serverConf.server.http.encryption.useEncryption
|
||||
|
||||
serverConf.server.http.encryption.useEncryption = !enabled
|
||||
serverConf.server.http.encryption.useInRouting = !enabled
|
||||
|
||||
// Write file
|
||||
await fs.writeFile({
|
||||
path,
|
||||
contents: JSON.stringify(serverConf)
|
||||
})
|
||||
}
|
||||
|
||||
export async function encryptionEnabled(path: string) {
|
||||
let serverConf
|
||||
|
||||
try {
|
||||
serverConf = JSON.parse(await fs.readTextFile(path))
|
||||
} catch(e) {
|
||||
console.log(`Server config at ${path} not found or invalid`)
|
||||
return false
|
||||
}
|
||||
|
||||
return serverConf.server.http.encryption.useEncryption
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { invoke } from '@tauri-apps/api'
|
||||
import { dataDir } from '@tauri-apps/api/path'
|
||||
import { convertFileSrc } from '@tauri-apps/api/tauri'
|
||||
import { getConfig, setConfigOption } from './configuration'
|
||||
|
||||
interface Theme {
|
||||
name: string
|
||||
@@ -77,6 +78,9 @@ export async function getTheme(name: string) {
|
||||
}
|
||||
|
||||
export async function loadTheme(theme: ThemeList, document: Document) {
|
||||
// Get config, since we will set the custom background in there
|
||||
const config = await getConfig()
|
||||
|
||||
// We are going to dynamically load stylesheets into the document
|
||||
const head = document.head
|
||||
|
||||
@@ -107,22 +111,32 @@ export async function loadTheme(theme: ThemeList, document: Document) {
|
||||
|
||||
// Set custom background
|
||||
if (theme.customBackgroundURL) {
|
||||
document.body.style.backgroundImage = `url('${theme.customBackgroundURL}')`
|
||||
// If the custom bg is already set don't overwrite
|
||||
if (config.customBackground === '') {
|
||||
config.customBackground = theme.customBackgroundURL
|
||||
}
|
||||
}
|
||||
|
||||
// Set custom background
|
||||
if (theme.customBackgroundPath) {
|
||||
const bgPath = await dataDir() + 'cultivation/grasscutter/theme.png'
|
||||
const bgPath = (await dataDir()).replace(/\\/g, '/') + 'cultivation/bg/'
|
||||
const imageName = theme.customBackgroundPath.split('/').pop()
|
||||
|
||||
// Save the background to our data dir
|
||||
await invoke('copy_file', {
|
||||
path: theme.path + '/' + theme.customBackgroundPath,
|
||||
new_path: bgPath
|
||||
newPath: bgPath
|
||||
})
|
||||
|
||||
// Set the background
|
||||
document.body.style.backgroundImage = `url('${bgPath}')`
|
||||
// If the custom bg is already set don't overwrite
|
||||
if (config.customBackground === '') {
|
||||
config.customBackground = bgPath + imageName
|
||||
}
|
||||
}
|
||||
|
||||
// Write config
|
||||
await setConfigOption('customBackground', config.customBackground)
|
||||
|
||||
return
|
||||
}
|
||||