Skip to content

Commit

Permalink
made generation more "minecrafty" | finish rp merging
Browse files Browse the repository at this point in the history
  • Loading branch information
spartacus04 committed Mar 21, 2024
1 parent e5a78e1 commit df3c2fe
Show file tree
Hide file tree
Showing 25 changed files with 448 additions and 129 deletions.
Binary file modified bun.lockb
Binary file not shown.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@tailwindcss/typography": "0.5.10",
"@tauri-apps/cli": "^1.5.10",
"@types/node": "20.11.5",
"@types/three": "^0.162.0",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"autoprefixer": "10.4.17",
Expand Down Expand Up @@ -52,6 +53,7 @@
"jszip": "^3.10.1",
"marked": "latest",
"minecraft-text-js": "^1.1.3",
"svelte-gestures": "^4.0.0"
"svelte-gestures": "^4.0.0",
"three": "^0.162.0"
}
}
5 changes: 5 additions & 0 deletions src/app.postcss
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ a {
font-weight: 700;
src: url('/fonts/minecraft_ten.ttf') format('truetype')
}
@font-face {
font-family: 'Minecraft Title';
font-weight: 700;
src: url('/fonts/Minecrafter.Reg.ttf') format('truetype')
}
}

::selection {
Expand Down
Binary file removed src/lib/assets/geyser_logo.png
Binary file not shown.
Binary file removed src/lib/assets/loading.webp
Binary file not shown.
Binary file removed src/lib/assets/minecraft_logo.webp
Binary file not shown.
Binary file added src/lib/assets/panorama_0.webp
Binary file not shown.
Binary file added src/lib/assets/panorama_1.webp
Binary file not shown.
Binary file added src/lib/assets/panorama_2.webp
Binary file not shown.
Binary file added src/lib/assets/panorama_3.webp
Binary file not shown.
Binary file added src/lib/assets/panorama_4.webp
Binary file not shown.
Binary file added src/lib/assets/panorama_5.webp
Binary file not shown.
14 changes: 13 additions & 1 deletion src/lib/components/EditDiscModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,17 @@
modalStore.close();
}
}
const deleteDisc = () => {
discsStore.update(discs => {
return discs.filter(disc => !discNamespaces.includes(disc["disc-namespace"]));
})
if($modalStore[0]) {
$modalStore[0].response!!(true);
modalStore.close();
}
}
</script>

<main class="bg-surface-500 rounded-md p-2 h-[50%] overflow-y-auto w-[90%] sm:w-[80%] lg:w-[50%]">
Expand Down Expand Up @@ -269,8 +280,9 @@
</div>
{/if}

<div class="flex w-full items-center justify-center mt-4">
<div class="flex w-full items-center justify-center mt-4 gap-4">
<button class="btn variant-filled-secondary text-white" on:click={exit}>Save</button>
<button class="btn variant-filled-error text-white" on:click={deleteDisc}>Delete disc{multiple ? 's' : ''}</button>
</div>

{/await}
Expand Down
14 changes: 14 additions & 0 deletions src/lib/components/ForgeProgressBar.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script lang="ts">
export let max: number;
export let value: number;
export let invisible: boolean = false;
</script>

{#if !invisible}
<div class="w-full h-8 bg-gray-200 relative border-mc-light-gray border {invisible ? 'border-transparent' : ''}">
<div class="h-full bg-[#cb3d35]" style="width: {value / max * 100}%"></div>
<div class="absolute top-0 left-0 w-full h-full flex items-center justify-center text-black font-minecraft text-2xl">{value}/{max}</div>
</div>
{:else}
<div class="h-8" />
{/if}
168 changes: 131 additions & 37 deletions src/lib/components/OutputModal.svelte
Original file line number Diff line number Diff line change
@@ -1,64 +1,158 @@
<script lang="ts">
import { outputEverything } from "$lib/resourcepack/exporter";
import { ProgressBar, ProgressRadial } from '@skeletonlabs/skeleton';
import { ProgressBar, getModalStore } 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
});
import * as THREE from 'three';
import panorama_top from '$lib/assets/panorama_4.webp';
import panorama_bottom from '$lib/assets/panorama_5.webp';
import panorama_left from '$lib/assets/panorama_3.webp';
import panorama_right from '$lib/assets/panorama_1.webp';
import panorama_front from '$lib/assets/panorama_0.webp';
import panorama_back from '$lib/assets/panorama_2.webp';
import { fade } from 'svelte/transition';
import default_icon from '$lib/assets/default_icon.png';
import ForgeProgressBar from "./ForgeProgressBar.svelte";
const modalStore = getModalStore();
let canvas: HTMLDivElement;
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(85, window.innerWidth / window.innerHeight, 0.1, 50);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
// render 6 sides forming a cube, each side should have a panorama_* texture, backside
const geometry = new THREE.BoxGeometry(10, 10, 10);
const materials = [
new THREE.MeshBasicMaterial({ map: new THREE.TextureLoader().load(panorama_right), side: THREE.BackSide }),
new THREE.MeshBasicMaterial({ map: new THREE.TextureLoader().load(panorama_left), side: THREE.BackSide }),
new THREE.MeshBasicMaterial({ map: new THREE.TextureLoader().load(panorama_top), side: THREE.BackSide }),
new THREE.MeshBasicMaterial({ map: new THREE.TextureLoader().load(panorama_bottom), side: THREE.BackSide }),
new THREE.MeshBasicMaterial({ map: new THREE.TextureLoader().load(panorama_front), side: THREE.BackSide }),
new THREE.MeshBasicMaterial({ map: new THREE.TextureLoader().load(panorama_back), side: THREE.BackSide })
];
const cube = new THREE.Mesh( geometry, materials );
cube.position.set(0, 0, 0)
scene.add(cube);
const animate = () => {
if(!canvas) return;
setTimeout(() => {
requestAnimationFrame(animate);
}, 1000 / 60);
cube.rotation.y += 0.0005;
renderer.render(scene, camera);
};
const loadPanorama = () => {
canvas.appendChild(renderer.domElement);
animate();
}
const progressStore = writable([
{
total: 3,
current: 0,
status: 'Loading FFmpeg'
},
undefined,
undefined
]);
let javaRp: Blob|undefined = undefined;
let bedrockRp: Blob|undefined = undefined;
outputEverything(rp => {
setTimeout(() => {
javaRp = rp;
setTimeout(() => {
loadPanorama();
}, 1)
}, 500);
}, (total, current) => {
console.log(total, current)
progressStore.set({ total, current })
}, (total, current, status, index) => {
progressStore.update(store => {
if(total == undefined || current == undefined || status == undefined) store[index] = undefined;
else store[index] = { total, current, status };
return store;
})
}, rp => {
bedrockRp = rp;
});
window.onresize = () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
</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">
<main in:fade class="bg-white h-screen overflow-y-auto w-screen flex items-center justify-center gap-4 flex-col p-4 {javaRp ? 'z-10' : ''}">
{#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>
<div in:fade={{ duration: 500 }} bind:this={canvas} class="w-full fixed h-full z-20" />
<div in:fade={{ duration: 500 }} class="w-full fixed h-full z-30 flex items-center justify-center gap-4 flex-col">
<h1 class="h1 sm:text-7xl mt-2 font-minecraft-title text-center shadow-lg" style="text-shadow:
3px 3px 0 #000,
-3px 3px 0 #000,
-3px -3px 0 #000,
3px -3px 0 #000;">Your resourcepack is ready</h1>
<div class="flex gap-4 flex-col w-[75%] sm:w-[50%]">
<MinecraftButton on:click={() => saveAs(javaRp, 'resourcepack.zip')}>Download Resource Pack for Minecraft: Java Edition</MinecraftButton>
<MinecraftButton enabled={bedrockRp != undefined} on:click={() => saveAs(bedrockRp, 'resourcepack-geysermc.mcpack')}>
{#if bedrockRp == undefined}
Generating for<br>GeyserMC...
Generating Resource Pack for GeyserMC...
{:else}
Download for<br>GeyserMC
Download Resource Pack for GeyserMC
{/if}
</MinecraftButton>
<MinecraftButton on:click={() => modalStore.close()}>Back to disc generation</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>
<div class="w-full fixed h-full flex flex-col items-center justify-center p-2">
<div class="xl:w-[50%] lg:w-[60%] w-[100%] flex flex-col items-center justify-center p-2">
<div class="flex items-center justify-center gap-4 flex-col sm:flex-row mb-4">
<img src={default_icon} alt="jext-icon" class="aspect-square h-32 sm:h-full">
<h1 class="font-minecraft-launcher text-black h1 text-6xl {window.__TAURI__ ? 'text-nowrap' : ''} md:text-7xl sm:text-nowrap sm:text-8xl text-center">JEXT Reborn</h1>
</div>
{#if !window.__TAURI__}
<h4 class="h4 bg-red-800 p-2 rounded-lg font-minecraft">Warning! The website may take a while to generate the resourcepack!<br>Consider using the desktop app</h4>
{/if}

{#if $progressStore[0] != undefined}
<p class="font-minecraft text-2xl text-black text-left w-full">{$progressStore[0].status}</p>
<ForgeProgressBar bind:max={$progressStore[0].total} bind:value={$progressStore[0].current} />
{:else}
<p class="font-minecraft text-2xl text-white text-left w-full select-none">&nbsp;</p>
<ForgeProgressBar max={0} value={0} invisible={true} />
{/if}

{#if $progressStore[1] != undefined}
<p class="font-minecraft text-2xl text-black text-left w-full">{$progressStore[1].status}</p>
<ForgeProgressBar bind:max={$progressStore[1].total} bind:value={$progressStore[1].current} />
{:else}
<p class="font-minecraft text-2xl text-white text-left w-full select-none">&nbsp;</p>
<ForgeProgressBar max={0} value={0} invisible={true} />
{/if}

{#if $progressStore[2] != undefined}
<p class="font-minecraft text-2xl text-black text-left w-full">{$progressStore[2].status}</p>
<ForgeProgressBar bind:max={$progressStore[2].total} bind:value={$progressStore[2].current} />
{:else}
<p class="font-minecraft text-2xl text-white text-left w-full select-none">&nbsp;</p>
<ForgeProgressBar max={0} value={0} invisible={true} />
{/if}
</div>
</div>
</main>
100 changes: 87 additions & 13 deletions src/lib/components/ResourcePackManager.svelte
Original file line number Diff line number Diff line change
@@ -1,33 +1,107 @@
<script lang="ts">
import { resourcePackStore, versions } from "$lib/config";
import { inputFile, dropFile } from "$lib/directives";
import JSZip from "jszip";
import MinecraftComboBox from "./MinecraftComboBox.svelte";
import MinecraftTextbox from "./MinecraftTextbox.svelte";
import { randomDiscTexture } from "$lib/resourcepack/discs";
const setTexture = async (files?: File[]) => {
if(files && files.length > 0 && files[0]) {
$resourcePackStore.icon = files[0];
}
}
const addRP = async (files?: File[]) => {
if(files && files.length > 0 && files[0]) {
$resourcePackStore.packs = [...$resourcePackStore.packs, {
name: files[0].name,
value: files[0],
icon: await new JSZip().loadAsync(files[0]).then(async zip => {
const icon = zip.file('pack.png');
return icon ? icon.async("blob") : (await randomDiscTexture())!;
})
}];
}
}
const shiftRp = (index: number, shift: number) => {
const packs = $resourcePackStore.packs;
const temp = packs[index];
packs[index] = packs[index + shift];
packs[index + shift] = temp;
$resourcePackStore.packs = packs;
}
</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
}} />
<main class="flex flex-col p-5">
<div class="flex gap-4 flex-col sm:flex-row items-center">
<img class="bg-[#202020] p-3 cursor-pointer w-28 sm:w-32 max-w-32 h-28 sm:h-32 max-h-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
}} />

<div class="flex h-28 sm:h-32 h-max-32 justify-around flex-col w-full">
<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>

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

<MinecraftTextbox placeholder="The resource pack description" bind:value={$resourcePackStore.description} />
<h4 class="h4 text-center font-minecraft">Merge with other resourcepacks</h4>

<div class="flex">
{#each $resourcePackStore.packs as pack}
<div class="grid grid-cols-1 sm:grid-cols-3 lg:grid-cols-5 xl:grid-cols-7 mt-4 p-2 gap-4 border-white rounded-md border">
<div class="card p-4 rounded-lg">
<div class="card-header">
<img src={URL.createObjectURL($resourcePackStore.icon)} alt="icon" class="w-full aspect-square">
</div>
<section class="p-4 font-minecraft text-center w-[calc(100%)]">JEXT Resources</section>
<footer class="card-footer flex items-center justify-center">
<button class="cursor-not-allowed">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-lock"><rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
</button>
</footer>
</div>
{#each $resourcePackStore.packs as pack, i}
<div class="card p-4 rounded-lg">
<div class="card-header">
<img src={URL.createObjectURL(pack.icon)} alt="icon" class="w-full aspect-square">
</div>
<section class="p-4 font-minecraft text-center text-ellipsis w-[calc(100%)] whitespace-nowrap overflow-hidden">{pack.name}</section>
<footer class="card-footer flex items-center justify-center gap-4">
<button class="card-hover" disabled={i == 0} on:click={() => shiftRp(i, -1)}>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-left rotate-90 sm:rotate-0 {i == 0 ? 'stroke-gray-600 cursor-not-allowed' : ''}"><path d="m15 18-6-6 6-6"/></svg>
</button>
<button class="card-hover" disabled={i == $resourcePackStore.packs.length - 1} on:click={() => shiftRp(i, 1)}>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-right rotate-90 sm:rotate-0 {i == $resourcePackStore.packs.length - 1 ? 'stroke-gray-600 cursor-not-allowed' : ''}"><path d="m9 18 6-6-6-6"/></svg>
</button>
</footer>
</div>
{/each}
<button class="card p-4 rounded-lg card-hover cursor-pointer [&>*]:pointer-events-none" use:inputFile={{
accept: '.zip',
cb: addRP
}} use:dropFile={{
accept: '.zip',
cb: addRP
}}>
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-full aspect-square text-[d3d3d3] "
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"><path d="M5 12h14" /><path d="M12 5v14" /></svg
>
</button>
</div>
</main>
Loading

0 comments on commit df3c2fe

Please sign in to comment.