1- import type { Loader , VersionType } from '@onelauncher/client/bindings' ;
1+ import type { CreateCluster , Loader , VersionType } from '@onelauncher/client/bindings' ;
22import { TextInputIcon } from '@untitled-theme/icons-solid' ;
33import { bridge } from '~imports' ;
44import Checkbox from '~ui/components/base/Checkbox' ;
@@ -8,32 +8,79 @@ import TextField from '~ui/components/base/TextField';
88import LoaderIcon from '~ui/components/game/LoaderIcon' ;
99import useCommand from '~ui/hooks/useCommand' ;
1010import { formatVersionRelease , LOADERS } from '~utils' ;
11- import { createEffect , createSignal , For , Index , type JSX , onMount , Show , splitProps , untrack } from 'solid-js' ;
11+ import { createEffect , createMemo , createSignal , For , Index , type JSX , onMount , Show , splitProps , untrack } from 'solid-js' ;
1212import { type ClusterStepProps , createClusterStep } from './ClusterCreationModal' ;
1313
14+ type PartialCluster = Partial < CreateCluster > ;
15+ type PartialClusterUpdateFunc = < K extends keyof PartialCluster > ( key : K , value : PartialCluster [ K ] ) => void ;
16+
1417export default createClusterStep ( {
1518 message : 'Game Setup' ,
1619 buttonType : 'create' ,
1720 Component : ClusterGameSetup ,
1821} ) ;
1922
23+ function _epicHardcodedLoaderVersionFilter ( loader : Loader , version : string ) : boolean {
24+ if ( loader === 'vanilla' )
25+ return true ;
26+
27+ const split = version . split ( '.' ) [ 1 ] ;
28+ if ( split === undefined )
29+ return true ;
30+
31+ const minor = Number . parseInt ( split ) ;
32+ if ( minor < 13 )
33+ return loader === 'forge' || loader === 'legacyfabric' ;
34+ else
35+ return loader === 'forge' || loader === 'fabric' || loader === 'neoforge' || loader === 'quilt' ;
36+ }
37+
2038function ClusterGameSetup ( props : ClusterStepProps ) {
21- const check = ( ) => {
22- const hasName = ( props . controller . partialCluster ( ) . name ?. length ?? 0 ) > 0 ;
23- const hasVersion = ( props . controller . partialCluster ( ) . mc_version ?. length ?? 0 ) > 0 ;
24- const hasLoader = ( props . controller . partialCluster ( ) . mod_loader ?. length ?? 0 ) > 0 ;
39+ const [ partialCluster , setPartialCluster ] = createSignal < PartialCluster > ( {
40+ mod_loader : 'vanilla' ,
41+ } ) ;
2542
26- props . setCanGoForward ( hasName && hasVersion && hasLoader ) ;
27- } ;
43+ const requiredProps : ( keyof PartialCluster ) [ ] = [ 'name' , 'mc_version' , 'mod_loader' ] ;
2844
29- createEffect ( check ) ;
45+ const updatePartialCluster : PartialClusterUpdateFunc = ( key , value ) => setPartialCluster ( prev => ( { ...prev , [ key ] : value } ) ) ;
46+ const setName = ( name : string ) => updatePartialCluster ( 'name' , name ) ;
47+ const setVersion = ( version : string ) => updatePartialCluster ( 'mc_version' , version ) ;
48+ const setLoader = ( loader : Loader | string ) => updatePartialCluster ( 'mod_loader' , loader . toLowerCase ( ) as Loader ) ;
3049
31- const setName = ( name : string ) => props . controller . updatePartialCluster ( 'name' , name ) ;
32- const setVersion = ( version : string ) => props . controller . updatePartialCluster ( 'mc_version' , version ) ;
33- const setLoader = ( loader : Loader | string ) => props . controller . updatePartialCluster ( 'mod_loader' , loader . toLowerCase ( ) as Loader ) ;
50+ const getLoaders = createMemo ( ( ) => {
51+ const version = partialCluster ( ) . mc_version ?? '' ;
52+
53+ return LOADERS . filter ( loader => _epicHardcodedLoaderVersionFilter ( loader , version ) ) ;
54+ } ) ;
55+
56+ createEffect ( ( ) => {
57+ const hasName = ( partialCluster ( ) . name ?. length ?? 0 ) > 0 ;
58+ const hasVersion = ( partialCluster ( ) . mc_version ?. length ?? 0 ) > 0 ;
59+ const hasLoader = ( partialCluster ( ) . mod_loader ?. length ?? 0 ) > 0 ;
60+
61+ props . setCanGoForward ( hasName && hasVersion && hasLoader ) ;
62+ } ) ;
3463
3564 onMount ( ( ) => {
36- setLoader ( 'vanilla' ) ;
65+ props . controller . setFinishFunction ( ( ) => async ( ) => {
66+ const untracked = untrack ( partialCluster ) ;
67+
68+ for ( const prop of requiredProps )
69+ if ( ! untracked [ prop ] )
70+ throw new Error ( `Missing required property ${ prop } ` ) ;
71+
72+ await bridge . commands . createCluster ( {
73+ icon : null ,
74+ icon_url : null ,
75+ loader_version : null ,
76+ package_data : null ,
77+ skip : null ,
78+ skip_watch : null ,
79+ ...untracked ,
80+ } as CreateCluster ) ;
81+
82+ return true ;
83+ } ) ;
3784 } ) ;
3885
3986 return (
@@ -51,8 +98,8 @@ function ClusterGameSetup(props: ClusterStepProps) {
5198 </ Option >
5299
53100 < Option header = "Loader" >
54- < Dropdown onChange = { index => setLoader ( LOADERS [ index ] || 'vanilla' ) } >
55- < For each = { LOADERS } >
101+ < Dropdown onChange = { index => setLoader ( getLoaders ( ) [ index ] || 'vanilla' ) } >
102+ < For each = { getLoaders ( ) } >
56103 { loader => (
57104 < Dropdown . Row >
58105 < div class = "flex flex-row gap-x-2" >
0 commit comments