chore: Start work on creating instances (MC Manifest argument deserializing needs to be fixed)

This commit is contained in:
LynithDev 2024-03-24 22:09:04 +01:00
parent ec0590bc49
commit 750ecd414e
4 changed files with 116 additions and 10 deletions

View file

@ -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)]

View file

@ -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?;

View file

@ -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');
}

View file

@ -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>