mirror of
https://github.com/Grasscutters/Cultivation.git
synced 2025-12-14 16:14:48 +01:00
split main launcher into seperate file
This commit is contained in:
18
src-tauri/src/gamebanana.rs
Normal file
18
src-tauri/src/gamebanana.rs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
use crate::web;
|
||||||
|
|
||||||
|
static API_URL: &str = "https://api.gamebanana.com";
|
||||||
|
static SITE_URL: &str = "https://gamebanana.com";
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn list_submissions(mode: String) -> String {
|
||||||
|
let res = web::query(
|
||||||
|
format!(
|
||||||
|
"{}/apiv9/Util/Game/Submissions?_idGameRow=8552&_nPage=1&_nPerpage=50&_sMode={}",
|
||||||
|
SITE_URL, mode
|
||||||
|
)
|
||||||
|
.as_str(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ use sysinfo::{System, SystemExt};
|
|||||||
|
|
||||||
mod downloader;
|
mod downloader;
|
||||||
mod file_helpers;
|
mod file_helpers;
|
||||||
|
mod gamebanana;
|
||||||
mod lang;
|
mod lang;
|
||||||
mod metadata_patcher;
|
mod metadata_patcher;
|
||||||
mod proxy;
|
mod proxy;
|
||||||
@@ -59,6 +60,7 @@ fn main() {
|
|||||||
lang::get_languages,
|
lang::get_languages,
|
||||||
web::valid_url,
|
web::valid_url,
|
||||||
web::web_get,
|
web::web_get,
|
||||||
|
gamebanana::list_submissions,
|
||||||
metadata_patcher::patch_metadata
|
metadata_patcher::patch_metadata
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use reqwest::header::USER_AGENT;
|
use reqwest::header::{CONTENT_TYPE, USER_AGENT};
|
||||||
|
|
||||||
pub(crate) async fn query(site: &str) -> String {
|
pub(crate) async fn query(site: &str) -> String {
|
||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
@@ -6,6 +6,7 @@ pub(crate) async fn query(site: &str) -> String {
|
|||||||
let response = client
|
let response = client
|
||||||
.get(site)
|
.get(site)
|
||||||
.header(USER_AGENT, "cultivation")
|
.header(USER_AGENT, "cultivation")
|
||||||
|
.header(CONTENT_TYPE, "application/json")
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
173
src/ui/App.tsx
173
src/ui/App.tsx
@@ -1,101 +1,32 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { listen } from '@tauri-apps/api/event'
|
|
||||||
import './App.css'
|
import './App.css'
|
||||||
|
|
||||||
import DownloadHandler from '../utils/download'
|
import DownloadHandler from '../utils/download'
|
||||||
|
import { getConfigOption } from '../utils/configuration'
|
||||||
// Major Components
|
|
||||||
import TopBar from './components/TopBar'
|
|
||||||
import ServerLaunchSection from './components/ServerLaunchSection'
|
|
||||||
import MainProgressBar from './components/common/MainProgressBar'
|
|
||||||
import Options from './components/menu/Options'
|
|
||||||
import MiniDialog from './components/MiniDialog'
|
|
||||||
import DownloadList from './components/common/DownloadList'
|
|
||||||
import Downloads from './components/menu/Downloads'
|
|
||||||
import NewsSection from './components/news/NewsSection'
|
|
||||||
import Game from './components/menu/Game'
|
|
||||||
|
|
||||||
import RightBar from './components/RightBar'
|
|
||||||
import { getConfigOption, setConfigOption } from '../utils/configuration'
|
|
||||||
import { invoke } from '@tauri-apps/api'
|
|
||||||
import { dataDir } from '@tauri-apps/api/path'
|
|
||||||
import { appWindow } from '@tauri-apps/api/window'
|
|
||||||
import { convertFileSrc } from '@tauri-apps/api/tauri'
|
|
||||||
import { getTheme, loadTheme } from '../utils/themes'
|
import { getTheme, loadTheme } from '../utils/themes'
|
||||||
import { unpatchGame } from '../utils/metadata'
|
import { convertFileSrc, invoke } from '@tauri-apps/api/tauri'
|
||||||
|
import { dataDir } from '@tauri-apps/api/path'
|
||||||
interface IProps {
|
import { Main } from './Main'
|
||||||
[key: string]: never
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
isDownloading: boolean
|
moddingOpen: boolean
|
||||||
optionsOpen: boolean
|
|
||||||
miniDownloadsOpen: boolean
|
|
||||||
downloadsOpen: boolean
|
|
||||||
gameDownloadsOpen: boolean
|
|
||||||
bgFile: string
|
bgFile: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const downloadHandler = new DownloadHandler()
|
||||||
const DEFAULT_BG = 'https://api.grasscutter.io/cultivation/bgfile'
|
const DEFAULT_BG = 'https://api.grasscutter.io/cultivation/bgfile'
|
||||||
|
|
||||||
const downloadHandler = new DownloadHandler()
|
class App extends React.Component<Readonly<unknown>, IState> {
|
||||||
|
constructor(props: Readonly<unknown>) {
|
||||||
class App extends React.Component<IProps, IState> {
|
|
||||||
constructor(props: IProps) {
|
|
||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
isDownloading: false,
|
moddingOpen: false,
|
||||||
optionsOpen: false,
|
|
||||||
miniDownloadsOpen: false,
|
|
||||||
downloadsOpen: false,
|
|
||||||
gameDownloadsOpen: false,
|
|
||||||
bgFile: DEFAULT_BG,
|
bgFile: DEFAULT_BG,
|
||||||
}
|
}
|
||||||
|
|
||||||
listen('lang_error', (payload) => {
|
|
||||||
console.log(payload)
|
|
||||||
})
|
|
||||||
|
|
||||||
listen('jar_extracted', ({ payload }: { payload: string }) => {
|
|
||||||
setConfigOption('grasscutter_path', payload)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Emitted for metadata replacing-purposes
|
|
||||||
listen('game_closed', async () => {
|
|
||||||
const wasPatched = await getConfigOption('patch_metadata')
|
|
||||||
|
|
||||||
if (wasPatched) {
|
|
||||||
const unpatched = await unpatchGame()
|
|
||||||
|
|
||||||
console.log(`unpatched game? ${unpatched}`)
|
|
||||||
|
|
||||||
if (!unpatched) {
|
|
||||||
alert(
|
|
||||||
`Could not unpatch game! (You should be able to find your metadata backup in ${await dataDir()}\\cultivation\\)`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
let min = false
|
|
||||||
|
|
||||||
// periodically check if we need to min/max based on whether the game is open
|
|
||||||
setInterval(async () => {
|
|
||||||
const gameOpen = await invoke('is_game_running')
|
|
||||||
|
|
||||||
if (gameOpen && !min) {
|
|
||||||
appWindow.minimize()
|
|
||||||
min = true
|
|
||||||
} else if (!gameOpen && min) {
|
|
||||||
appWindow.unminimize()
|
|
||||||
min = false
|
|
||||||
}
|
|
||||||
}, 1000)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
const cert_generated = await getConfigOption('cert_generated')
|
|
||||||
const game_exe = await getConfigOption('game_install_path')
|
const game_exe = await getConfigOption('game_install_path')
|
||||||
const game_path = game_exe?.substring(0, game_exe.replace(/\\/g, '/').lastIndexOf('/')) || ''
|
const game_path = game_exe?.substring(0, game_exe.replace(/\\/g, '/').lastIndexOf('/')) || ''
|
||||||
const root_path = game_path?.substring(0, game_path.replace(/\\/g, '/').lastIndexOf('/')) || ''
|
const root_path = game_path?.substring(0, game_path.replace(/\\/g, '/').lastIndexOf('/')) || ''
|
||||||
@@ -154,22 +85,6 @@ class App extends React.Component<IProps, IState> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cert_generated) {
|
|
||||||
// Generate the certificate
|
|
||||||
await invoke('generate_ca_files', {
|
|
||||||
path: (await dataDir()) + 'cultivation',
|
|
||||||
})
|
|
||||||
|
|
||||||
await setConfigOption('cert_generated', true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Period check to only show progress bar when downloading files
|
|
||||||
setInterval(() => {
|
|
||||||
this.setState({
|
|
||||||
isDownloading: downloadHandler.getDownloads().filter((d) => d.status !== 'finished')?.length > 0,
|
|
||||||
})
|
|
||||||
}, 1000)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -184,69 +99,11 @@ class App extends React.Component<IProps, IState> {
|
|||||||
: {}
|
: {}
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<TopBar
|
{this.state.moddingOpen ? null : (
|
||||||
optFunc={() => {
|
<>
|
||||||
this.setState({ optionsOpen: !this.state.optionsOpen })
|
<Main downloadHandler={downloadHandler} />
|
||||||
}}
|
</>
|
||||||
downFunc={() => this.setState({ downloadsOpen: !this.state.downloadsOpen })}
|
)}
|
||||||
gameFunc={() => this.setState({ gameDownloadsOpen: !this.state.gameDownloadsOpen })}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<RightBar />
|
|
||||||
|
|
||||||
<NewsSection />
|
|
||||||
|
|
||||||
{
|
|
||||||
// Mini downloads section
|
|
||||||
this.state.miniDownloadsOpen ? (
|
|
||||||
<div className="MiniDownloads" id="miniDownloadContainer">
|
|
||||||
<MiniDialog
|
|
||||||
title="Downloads"
|
|
||||||
closeFn={() => {
|
|
||||||
this.setState({ miniDownloadsOpen: false })
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<DownloadList downloadManager={downloadHandler} />
|
|
||||||
</MiniDialog>
|
|
||||||
<div className="arrow-down"></div>
|
|
||||||
</div>
|
|
||||||
) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// Download menu
|
|
||||||
this.state.downloadsOpen ? (
|
|
||||||
<Downloads downloadManager={downloadHandler} closeFn={() => this.setState({ downloadsOpen: false })} />
|
|
||||||
) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// Options menu
|
|
||||||
this.state.optionsOpen ? (
|
|
||||||
<Options
|
|
||||||
downloadManager={downloadHandler}
|
|
||||||
closeFn={() => this.setState({ optionsOpen: !this.state.optionsOpen })}
|
|
||||||
/>
|
|
||||||
) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// Game downloads menu
|
|
||||||
this.state.gameDownloadsOpen ? (
|
|
||||||
<Game downloadManager={downloadHandler} closeFn={() => this.setState({ gameDownloadsOpen: false })} />
|
|
||||||
) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
<div className="BottomSection" id="bottomSectionContainer">
|
|
||||||
<ServerLaunchSection />
|
|
||||||
|
|
||||||
<div
|
|
||||||
id="DownloadProgress"
|
|
||||||
onClick={() => this.setState({ miniDownloadsOpen: !this.state.miniDownloadsOpen })}
|
|
||||||
>
|
|
||||||
{this.state.isDownloading ? <MainProgressBar downloadManager={downloadHandler} /> : null}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class Debug extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<TopBar optFunc={none} downFunc={none} gameFunc={none} />
|
<TopBar optFunc={none} downFunc={none} gameFunc={none} modFunc={none} />
|
||||||
<TextInput readOnly={false} initalValue={'change to set proxy address'} onChange={setProxyAddress} />
|
<TextInput readOnly={false} initalValue={'change to set proxy address'} onChange={setProxyAddress} />
|
||||||
<button onClick={startProxy}>start proxy</button>
|
<button onClick={startProxy}>start proxy</button>
|
||||||
<button onClick={stopProxy}>stop proxy</button>
|
<button onClick={stopProxy}>stop proxy</button>
|
||||||
|
|||||||
187
src/ui/Main.tsx
Normal file
187
src/ui/Main.tsx
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
// Major Components
|
||||||
|
import TopBar from './components/TopBar'
|
||||||
|
import ServerLaunchSection from './components/ServerLaunchSection'
|
||||||
|
import MainProgressBar from './components/common/MainProgressBar'
|
||||||
|
import Options from './components/menu/Options'
|
||||||
|
import MiniDialog from './components/MiniDialog'
|
||||||
|
import DownloadList from './components/common/DownloadList'
|
||||||
|
import Downloads from './components/menu/Downloads'
|
||||||
|
import NewsSection from './components/news/NewsSection'
|
||||||
|
import Game from './components/menu/Game'
|
||||||
|
import RightBar from './components/RightBar'
|
||||||
|
|
||||||
|
import { getConfigOption, setConfigOption } from '../utils/configuration'
|
||||||
|
import { invoke } from '@tauri-apps/api'
|
||||||
|
import { listen } from '@tauri-apps/api/event'
|
||||||
|
import { dataDir } from '@tauri-apps/api/path'
|
||||||
|
import { appWindow } from '@tauri-apps/api/window'
|
||||||
|
import { unpatchGame } from '../utils/metadata'
|
||||||
|
import DownloadHandler from '../utils/download'
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
downloadHandler: DownloadHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IState {
|
||||||
|
isDownloading: boolean
|
||||||
|
optionsOpen: boolean
|
||||||
|
miniDownloadsOpen: boolean
|
||||||
|
downloadsOpen: boolean
|
||||||
|
gameDownloadsOpen: boolean
|
||||||
|
moddingOpen: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Main extends React.Component<IProps, IState> {
|
||||||
|
constructor(props: IProps) {
|
||||||
|
super(props)
|
||||||
|
this.state = {
|
||||||
|
isDownloading: false,
|
||||||
|
optionsOpen: false,
|
||||||
|
miniDownloadsOpen: false,
|
||||||
|
downloadsOpen: false,
|
||||||
|
gameDownloadsOpen: false,
|
||||||
|
moddingOpen: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
invoke('list_submissions')
|
||||||
|
|
||||||
|
listen('lang_error', (payload) => {
|
||||||
|
console.log(payload)
|
||||||
|
})
|
||||||
|
|
||||||
|
listen('jar_extracted', ({ payload }: { payload: string }) => {
|
||||||
|
setConfigOption('grasscutter_path', payload)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Emitted for metadata replacing-purposes
|
||||||
|
listen('game_closed', async () => {
|
||||||
|
const wasPatched = await getConfigOption('patch_metadata')
|
||||||
|
|
||||||
|
if (wasPatched) {
|
||||||
|
const unpatched = await unpatchGame()
|
||||||
|
|
||||||
|
console.log(`unpatched game? ${unpatched}`)
|
||||||
|
|
||||||
|
if (!unpatched) {
|
||||||
|
alert(
|
||||||
|
`Could not unpatch game! (You should be able to find your metadata backup in ${await dataDir()}\\cultivation\\)`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
let min = false
|
||||||
|
|
||||||
|
// periodically check if we need to min/max based on whether the game is open
|
||||||
|
setInterval(async () => {
|
||||||
|
const gameOpen = await invoke('is_game_running')
|
||||||
|
|
||||||
|
if (gameOpen && !min) {
|
||||||
|
appWindow.minimize()
|
||||||
|
min = true
|
||||||
|
} else if (!gameOpen && min) {
|
||||||
|
appWindow.unminimize()
|
||||||
|
min = false
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
async componentDidMount() {
|
||||||
|
const cert_generated = await getConfigOption('cert_generated')
|
||||||
|
|
||||||
|
if (!cert_generated) {
|
||||||
|
// Generate the certificate
|
||||||
|
await invoke('generate_ca_files', {
|
||||||
|
path: (await dataDir()) + 'cultivation',
|
||||||
|
})
|
||||||
|
|
||||||
|
await setConfigOption('cert_generated', true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Period check to only show progress bar when downloading files
|
||||||
|
setInterval(() => {
|
||||||
|
this.setState({
|
||||||
|
isDownloading: this.props.downloadHandler.getDownloads().filter((d) => d.status !== 'finished')?.length > 0,
|
||||||
|
})
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TopBar
|
||||||
|
optFunc={() => {
|
||||||
|
this.setState({ optionsOpen: !this.state.optionsOpen })
|
||||||
|
}}
|
||||||
|
downFunc={() => this.setState({ downloadsOpen: !this.state.downloadsOpen })}
|
||||||
|
gameFunc={() => this.setState({ gameDownloadsOpen: !this.state.gameDownloadsOpen })}
|
||||||
|
modFunc={() => this.setState({ moddingOpen: !this.state.moddingOpen })}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<RightBar />
|
||||||
|
|
||||||
|
<NewsSection />
|
||||||
|
|
||||||
|
{
|
||||||
|
// Mini downloads section
|
||||||
|
this.state.miniDownloadsOpen ? (
|
||||||
|
<div className="MiniDownloads" id="miniDownloadContainer">
|
||||||
|
<MiniDialog
|
||||||
|
title="Downloads"
|
||||||
|
closeFn={() => {
|
||||||
|
this.setState({ miniDownloadsOpen: false })
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DownloadList downloadManager={this.props.downloadHandler} />
|
||||||
|
</MiniDialog>
|
||||||
|
<div className="arrow-down"></div>
|
||||||
|
</div>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Download menu
|
||||||
|
this.state.downloadsOpen ? (
|
||||||
|
<Downloads
|
||||||
|
downloadManager={this.props.downloadHandler}
|
||||||
|
closeFn={() => this.setState({ downloadsOpen: false })}
|
||||||
|
/>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Options menu
|
||||||
|
this.state.optionsOpen ? (
|
||||||
|
<Options
|
||||||
|
downloadManager={this.props.downloadHandler}
|
||||||
|
closeFn={() => this.setState({ optionsOpen: !this.state.optionsOpen })}
|
||||||
|
/>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Game downloads menu
|
||||||
|
this.state.gameDownloadsOpen ? (
|
||||||
|
<Game
|
||||||
|
downloadManager={this.props.downloadHandler}
|
||||||
|
closeFn={() => this.setState({ gameDownloadsOpen: false })}
|
||||||
|
/>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
|
||||||
|
<div className="BottomSection" id="bottomSectionContainer">
|
||||||
|
<ServerLaunchSection />
|
||||||
|
|
||||||
|
<div
|
||||||
|
id="DownloadProgress"
|
||||||
|
onClick={() => this.setState({ miniDownloadsOpen: !this.state.miniDownloadsOpen })}
|
||||||
|
>
|
||||||
|
{this.state.isDownloading ? <MainProgressBar downloadManager={this.props.downloadHandler} /> : null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@ interface IProps {
|
|||||||
optFunc: () => void
|
optFunc: () => void
|
||||||
downFunc: () => void
|
downFunc: () => void
|
||||||
gameFunc: () => void
|
gameFunc: () => void
|
||||||
|
modFunc: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
@@ -116,6 +117,9 @@ export default class TopBar extends React.Component<IProps, IState> {
|
|||||||
<div id="downloadsBtn" className="TopButton" onClick={this.props.downFunc}>
|
<div id="downloadsBtn" className="TopButton" onClick={this.props.downFunc}>
|
||||||
<img src={downBtn} alt="downloads" />
|
<img src={downBtn} alt="downloads" />
|
||||||
</div>
|
</div>
|
||||||
|
<div id="modsBtn" onClick={this.props.modFunc} className="TopButton">
|
||||||
|
MODS
|
||||||
|
</div>
|
||||||
{/* <div id="gameBtn" className="TopButton" onClick={this.props.gameFunc}>
|
{/* <div id="gameBtn" className="TopButton" onClick={this.props.gameFunc}>
|
||||||
<img src={gameBtn} alt="game" />
|
<img src={gameBtn} alt="game" />
|
||||||
</div> */}
|
</div> */}
|
||||||
|
|||||||
Reference in New Issue
Block a user