Skip to content

Commit

Permalink
Add resourcepack generation
Browse files Browse the repository at this point in the history
  • Loading branch information
spartacus04 committed Mar 20, 2024
1 parent b08d0ad commit e5a78e1
Show file tree
Hide file tree
Showing 23 changed files with 606 additions and 48 deletions.
26 changes: 18 additions & 8 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

use base64::{engine::general_purpose::{self, STANDARD}, Engine};
use ffmpeg_sidecar::event::{FfmpegEvent, FfmpegProgress};
use ffmpeg_sidecar::event::FfmpegEvent;
use tauri::{api::dialog, Manager};
use std::{fs, io::{Read, Write}};

Expand All @@ -26,7 +26,7 @@ fn download_ffmpeg(app_handle: tauri::AppHandle) -> bool {
}
}

#[tauri::command]
#[tauri::command(async)]
fn ffmpeg(input: String, args: Vec<String>, app_handle: tauri::AppHandle) -> String {
let binary = STANDARD.decode(input).unwrap();

Expand Down Expand Up @@ -62,9 +62,8 @@ fn ffmpeg(input: String, args: Vec<String>, app_handle: tauri::AppHandle) -> Str
return String::from("");
}
}

// run the ffmpeg command with the args and the temporary file

let mut ffmpeg = ffmpeg_sidecar::command::FfmpegCommand::new()
.input(input_file_path)
.args(args)
Expand All @@ -75,10 +74,21 @@ fn ffmpeg(input: String, args: Vec<String>, app_handle: tauri::AppHandle) -> Str
ffmpeg.iter().unwrap()
.for_each(|e| {
match e {
FfmpegEvent::Progress(FfmpegProgress { frame, .. }) =>
println!("Current frame: {frame}"),
FfmpegEvent::Log(_level, msg) =>
println!("[ffmpeg] {msg}"),
FfmpegEvent::Log(_level, msg) => {
println!("[ffmpeg] {msg}");

if !msg.contains("time=") || !msg.contains("speed=") {
return;
}

let time = msg.split("time=").collect::<Vec<&str>>()[1].split(" ").collect::<Vec<&str>>()[0];

if time.starts_with("-") {
return;
}

app_handle.emit_all("ffmpeg-progress", time).unwrap();
}
_ => {}
}
});
Expand Down
5 changes: 5 additions & 0 deletions src/app.postcss
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ a {
font-weight: 400;
src: url('/fonts/MinecraftRegular.ttf') format('truetype')
}
@font-face {
font-family: 'Minecraft Launcher';
font-weight: 700;
src: url('/fonts/minecraft_ten.ttf') format('truetype')
}
}

::selection {
Expand Down
Binary file added src/lib/assets/default_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/lib/assets/generate_btn.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/lib/assets/geyser_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/lib/assets/loading.webp
Binary file not shown.
Binary file added src/lib/assets/minecraft_logo.webp
Binary file not shown.
5 changes: 4 additions & 1 deletion src/lib/components/ConfigNode.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
}
$: can_reset = type === 'enumSource' ? JSON.stringify(node.value) !== JSON.stringify(node.defaultValue) : node.value !== node.defaultValue;
// I hate this, but it's the only way to make the compiler happy
const notypecheck = (x : any) => x;
</script>

<div class="flex-col flex mx-3 justify-between sm:flex-row">
Expand All @@ -62,7 +65,7 @@
{:else if type == 'string'}
<MinecraftTextbox bind:value={node.value} placeholder={node.defaultValue} />
{:else if type == 'enum'}
<MinecraftComboBox bind:value={node.value} values={node.enumValues} />
<MinecraftComboBox bind:value={node.value} values={notypecheck(node.enumValues)} />
{:else if type == 'enumSource'}
<MinecraftButton on:click={open} flex={true}>Open editor</MinecraftButton>
{/if}
Expand Down
11 changes: 6 additions & 5 deletions src/lib/components/EditDiscModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import DungeonSelectModal from "./DungeonSelectModal.svelte";
import MinecraftComboBox from "./MinecraftComboBox.svelte";
import { inputFile, dropFile } from "$lib/directives";
import { processImage } from "$lib/resourcepack/utils";
export let discNamespaces: string[];
let multiple: boolean;
Expand Down Expand Up @@ -71,7 +72,7 @@
initalText = tempDisc.lores.value.join('\n');
})();
const setTexture = (files?: File[]) => {
const setTexture = async (files?: File[]) => {
if(files && files.length > 0 && files[0]) {
tempDisc.texture.value = files[0];
tempDisc.texture.edited = true;
Expand Down Expand Up @@ -153,10 +154,10 @@
const exit = () => {
// apply tempDisc to namespaces
discsStore.update((discs) => {
discs.forEach(disc => {
discs.forEach(async disc => {
if(discNamespaces.includes(disc["disc-namespace"])) {
for(const [key, value] of Object.entries(tempDisc)) {
if(value.edited) {
if(value != undefined && value.edited) {
switch(key) {
case 'mono':
case 'normalize':
Expand All @@ -166,14 +167,14 @@
break;
case 'texture':
if(disc.packData) {
disc.packData.texture = value.value as Blob;
disc.packData.texture = await processImage(value.value as Blob);
} else {
disc.uploadData!.uploadedTexture = value.value as Blob;
}
break;
case 'fragment_texture':
if(disc.packData) {
disc.packData.fragmentTexture = value.value as Blob;
disc.packData.fragmentTexture = await processImage(value.value as Blob);
} else {
disc.uploadData!.uploadedFragmentTexture = value.value as Blob;
}
Expand Down
13 changes: 6 additions & 7 deletions src/lib/components/MinecraftComboBox.svelte
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
<script lang="ts">
export let value: unknown = '';
export let values: unknown = [];
<script lang="ts" generics="T">
export let value: T;
export let values: T[] = [];
export let labels: string[] = [];
export let fontsize: string = '1em';
const vals = (values as string[]).map((v) => v.toString());
</script>

<select class="w-full text-white p-2 h-min font-minecraft bg-[#303030] hover:bg-[#404040] border-[3px] border-black appearance-none hover:border-white" bind:value={value} style:font-size={fontsize} on:input>
{#each vals as option}
<option value={option}>{option}</option>
{#each values as option, i}
<option value={option}>{labels.length > i ? labels[i] : option}</option>
{/each}
</select>

Expand Down
64 changes: 64 additions & 0 deletions src/lib/components/OutputModal.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<script lang="ts">
import { outputEverything } from "$lib/resourcepack/exporter";
import { ProgressBar, ProgressRadial } from '@skeletonlabs/skeleton';
import { writable } from "svelte/store";
import loading from '$lib/assets/loading.webp';
import { resourcePackStore } from "$lib/config";
import MinecraftButton from "./MinecraftButton.svelte";
import { saveAs } from "$lib/utils";
import minecraft_logo from '$lib/assets/minecraft_logo.webp';
import geyser_logo from '$lib/assets/geyser_logo.png';
const progressStore = writable<{
total?: number,
current?: number
}>({
total: undefined,
current: undefined
});
let javaRp: Blob|undefined = undefined;
let bedrockRp: Blob|undefined = undefined;
outputEverything(rp => {
setTimeout(() => {
javaRp = rp;
}, 500);
}, (total, current) => {
console.log(total, current)
progressStore.set({ total, current })
}, rp => {
bedrockRp = rp;
});
</script>

<main class="bg-surface-500 rounded-md p-2 h-[50%] overflow-y-auto w-[90%] sm:w-[80%] lg:w-[50%] flex items-center justify-center gap-4 flex-col">
{#if javaRp}
<h4 class="h4 mt-2 font-minecraft">Your resourcepack is ready!</h4>
<div class="flex gap-4">
<div class="card flex flex-col gap-4 p-4 rounded-lg">
<div class="card-header w-full p-0">
<img src={minecraft_logo} alt="resourcepackicon" class="aspect-square object-contain w-52" style="image-rendering: optimizeQuality;">
</div>
<MinecraftButton on:click={() => saveAs(javaRp, 'resourcepack.zip')}>Download for<br>Minecraft: Java Edition</MinecraftButton>
</div>

<div class="card flex flex-col gap-4 p-4 rounded-lg">
<div class="card-header w-full p-0">
<img src={geyser_logo} alt="resourcepackicon" class="w-52 aspect-square object-contain" style="image-rendering: optimizeQuality;">
</div>
<MinecraftButton enabled={bedrockRp != undefined} on:click={() => saveAs(bedrockRp, 'resourcepack-geysermc.mcpack')}>
{#if bedrockRp == undefined}
Generating for<br>GeyserMC...
{:else}
Download for<br>GeyserMC
{/if}
</MinecraftButton>
</div>
</div>
{:else}
<h4 class="h4 mt-2 font-minecraft">Generating your assets...</h4>
<img src={loading} alt="loading">
<ProgressBar bind:max={$progressStore.total} bind:value={$progressStore.current} />
{/if}
</main>
33 changes: 33 additions & 0 deletions src/lib/components/ResourcePackManager.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<script lang="ts">
import { resourcePackStore, versions } from "$lib/config";
import { inputFile, dropFile } from "$lib/directives";
import MinecraftComboBox from "./MinecraftComboBox.svelte";
import MinecraftTextbox from "./MinecraftTextbox.svelte";
const setTexture = async (files?: File[]) => {
if(files && files.length > 0 && files[0]) {
$resourcePackStore.icon = files[0];
}
}
</script>

<!-- TODO: continue working on this -->

<main class="flex p-5">
<img class="bg-[#202020] p-3 cursor-pointer h-28 sm:h-32 h-max-32 aspect-square border border-transparent hover:border-white" src={URL.createObjectURL($resourcePackStore.icon)} alt="disc icon" use:inputFile={{
accept: 'image/*',
cb: setTexture
}} use:dropFile={{
accept: 'image/*',
cb: setTexture
}} />

<MinecraftComboBox bind:value={$resourcePackStore.version} values={Array.from(versions.keys())} labels={Array.from(versions.values())} />

<MinecraftTextbox placeholder="The resource pack description" bind:value={$resourcePackStore.description} />

<div class="flex">
{#each $resourcePackStore.packs as pack}
{/each}
</div>
</main>
21 changes: 20 additions & 1 deletion src/lib/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { writable } from "svelte/store";
import type { Disc } from "./types";
import type { Disc, ResourcePackData } from "./types";
import default_icon from './assets/default_icon.png';

export const versions = new Map([
[4, '1.14 - 1.14.4'],
Expand All @@ -16,3 +17,21 @@ export const versions = new Map([
]);

export const discsStore = writable<Disc[]>([]);

export const resourcePackStore = writable<ResourcePackData>({
icon: new Blob(),
version: Math.max(...Array.from(versions.keys())),
description: "Adds custom music discs!",
packs: []
})

fetch(default_icon).then(
async (res) => {
const blob = await res.blob();

resourcePackStore.update((store) => {
store.icon = blob;
return store;
})
}
);
15 changes: 12 additions & 3 deletions src/lib/ffmpeg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { FFmpeg } from "@ffmpeg/ffmpeg";
import { arrayBufferToBase64, base64ToArrayBuffer, blobToArraBuffer } from "./utils";
import { invoke } from '@tauri-apps/api/tauri'
import { get, writable } from "svelte/store";
import { listen } from "@tauri-apps/api/event";
import { getDuration } from "./resourcepack/utils";

const baseURL = 'https://unpkg.com/@ffmpeg/[email protected]/dist/esm';
const baseMTURL = 'https://unpkg.com/@ffmpeg/[email protected]/dist/esm';
Expand All @@ -17,7 +19,6 @@ const qualityArgs = {
export const localFFmpegStore = writable(false);

export const prepareAudio = async (blob: Blob, data: FFmpegData, onProgress?: (percent: number) => unknown) : Promise<Blob|null> => {

const args = ['-vn', '-acodec', 'libvorbis'];

if (data.mono) args.push('-ac', '1');
Expand All @@ -27,19 +28,27 @@ export const prepareAudio = async (blob: Blob, data: FFmpegData, onProgress?: (p
args.push(...qualityArgs[data.quality]);

if (window.__TAURI__ && get(localFFmpegStore)) {
const duration = await getDuration(blob);

const unregister = await listen<string>('ffmpeg-progress', async event => {
const [hours, minutes, seconds] = event.payload.split(':').map(Number);

onProgress?.((hours * 3600 + minutes * 60 + seconds) / duration * 100);
})

const result = <string>(await invoke('ffmpeg', {
input: arrayBufferToBase64(await blob.arrayBuffer()),
args
}))

unregister();

if(result === "") return null;

return new Blob([base64ToArrayBuffer(result)], { type: 'audio/ogg' });
} else {
const ffmpeg = new FFmpeg();

// import file from node modules

if(!ffmpeg.loaded) await ffmpeg.load(crossOriginIsolated ? {
coreURL: `${baseMTURL}/ffmpeg-core.js`,
wasmURL: `${baseMTURL}/ffmpeg-core.wasm`,
Expand Down
9 changes: 0 additions & 9 deletions src/lib/loottables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,6 @@ export const loottables : Loottables = {
},
},
"archaeology/*": {
/*
"archaeology/trail_ruins_rare" to 12,
"archaeology/trail_ruins_common" to 45,
"archaeology/ocean_ruin_cold" to 15,
"archaeology/ocean_ruin_warm" to 15,
"archaeology/desert_pyramid" to 8,
"archaeology/desert_well" to 8,
*/

"Trail ruins": {
version: 15,
img: 'loottable_icons/Trail_Ruins.webp',
Expand Down
Loading

0 comments on commit e5a78e1

Please sign in to comment.