chore: Start work on creating instances (MC Manifest argument deserializing needs to be fixed)
This commit is contained in:
parent
ec0590bc49
commit
750ecd414e
4 changed files with 116 additions and 10 deletions
|
|
@ -1,4 +1,5 @@
|
|||
use serde::{Serialize, Deserialize};
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
|
@ -11,12 +12,47 @@ pub struct MinecraftManifest {
|
|||
pub libraries: Vec<Library>,
|
||||
pub logging: Logging,
|
||||
pub main_class: String,
|
||||
pub minecraft_arguments: String,
|
||||
pub arguments: Arguments,
|
||||
pub release_time: String,
|
||||
#[serde(rename = "type")]
|
||||
pub release_type: ReleaseType,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(untagged)]
|
||||
pub enum Arguments {
|
||||
// TODO: https://serde.rs/string-or-struct.html
|
||||
MinecraftArguments(String),
|
||||
Arguments {
|
||||
game: Vec<ModernArgumentsItem>,
|
||||
jvm: Vec<ModernArgumentsItem>,
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Arguments {
|
||||
fn default() -> Self { Arguments::MinecraftArguments(String::new()) }
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(untagged)]
|
||||
pub enum ModernArgumentsItem {
|
||||
Simple(String),
|
||||
Rule {
|
||||
rules: Vec<Rule>,
|
||||
value: ArgumentRuleValue,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(untagged)]
|
||||
pub enum ArgumentRuleValue {
|
||||
String(String),
|
||||
List(Vec<String>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum ReleaseType {
|
||||
|
|
@ -109,19 +145,32 @@ pub struct Native {
|
|||
pub url: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Rule {
|
||||
pub action: String,
|
||||
pub action: RuleAction,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub os: Option<Os>,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub features: Option<Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(untagged)]
|
||||
pub enum RuleAction {
|
||||
Allow,
|
||||
Disallow,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Os {
|
||||
pub name: String,
|
||||
pub name: Option<String>,
|
||||
pub arch: Option<String>,
|
||||
pub version: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ pub async fn create_instance(
|
|||
state: State<'_, Mutex<GameManagerState>>,
|
||||
name: String,
|
||||
version: String,
|
||||
client: ClientType,
|
||||
cover: Option<String>,
|
||||
group: Option<Uuid>,
|
||||
client: ClientType
|
||||
) -> Result<Uuid, String> {
|
||||
let manager = &mut state.lock().await.client_manager;
|
||||
let uuid = manager.create_instance(name, version, cover, group, client).await?;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,24 @@ export async function getInstances(): Promise<Core.Instance[]> {
|
|||
return await invoke<Core.Instance[]>('plugin:launcher-core|get_instances');
|
||||
}
|
||||
|
||||
export async function createInstance(instance: Omit<Core.Instance, 'id' | 'createdAt'> & { version: string }): Promise<void> {
|
||||
return await invoke(
|
||||
'plugin:launcher-core|create_instance',
|
||||
{
|
||||
name: instance.name,
|
||||
version: instance.version,
|
||||
client: instance.client,
|
||||
// cover: instance.cover,
|
||||
// group: instance.group,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Accept: 'text/plain',
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export async function refreshClientManager(): Promise<void> {
|
||||
return await invoke('plugin:launcher-core|refresh_client_manager');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import Tag from '../components/base/Tag';
|
|||
import TextField from '../components/base/TextField';
|
||||
import defaultCover from '../../assets/images/default_instance_cover.jpg';
|
||||
import ContextMenu from '../components/overlay/ContextMenu';
|
||||
import { getInstancesWithManifests, refreshClientManager } from '../../bridge/game';
|
||||
import { createInstance, getInstancesWithManifests, refreshClientManager } from '../../bridge/game';
|
||||
|
||||
// TODO: Replace this into it's own component
|
||||
function OneConfigLogo() {
|
||||
|
|
@ -261,13 +261,37 @@ function InstanceGroup(props: InstanceGroupProps) {
|
|||
|
||||
const Instances = lazy(async () => {
|
||||
const instances = await getInstancesWithManifests();
|
||||
const map = new Map<string, Core.InstanceWithManifest[]>();
|
||||
|
||||
instances.forEach((instance) => {
|
||||
const groupName = instance.instance.group || 'Unnamed';
|
||||
|
||||
if (map.has(groupName))
|
||||
map.get(groupName)!.push(instance);
|
||||
else
|
||||
map.set(groupName, [instance]);
|
||||
});
|
||||
|
||||
return {
|
||||
default: () => <InstanceGroup title="Unnamed" instances={instances} />,
|
||||
default: () => Array.from(map.entries()).map(([title, instances]) => (
|
||||
<InstanceGroup title={title} instances={instances} />
|
||||
)),
|
||||
};
|
||||
});
|
||||
|
||||
function HomePage() {
|
||||
function newInstance() {
|
||||
createInstance({
|
||||
name: 'New Instance',
|
||||
version: '1.19.2',
|
||||
client: {
|
||||
type: 'Vanilla',
|
||||
},
|
||||
cover: null,
|
||||
group: null,
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="flex flex-col gap-y-4 text-fg-primary">
|
||||
<Banner />
|
||||
|
|
@ -277,9 +301,24 @@ function HomePage() {
|
|||
<TextField iconLeft={<SearchMdIcon />} placeholder="Search for something..." />
|
||||
</div>
|
||||
<div class="flex flex-row gap-x-4">
|
||||
<Button styleType="primary" iconLeft={<PlusIcon class="!w-5 stroke-[2.2]" />}>New Instance</Button>
|
||||
<Button styleType="secondary" iconLeft={<Download01Icon />}>From URL</Button>
|
||||
<Button styleType="secondary" iconLeft={<RefreshCw01Icon />} onClick={() => refreshClientManager()} />
|
||||
<Button
|
||||
styleType="primary"
|
||||
iconLeft={<PlusIcon class="!w-5 stroke-[2.2]" />}
|
||||
children="New Instance"
|
||||
onClick={() => newInstance()}
|
||||
/>
|
||||
|
||||
<Button
|
||||
styleType="secondary"
|
||||
iconLeft={<Download01Icon />}
|
||||
children="From URL"
|
||||
/>
|
||||
|
||||
<Button
|
||||
styleType="secondary"
|
||||
iconLeft={<RefreshCw01Icon />}
|
||||
onClick={() => refreshClientManager()}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue