Skip to content

Commit

Permalink
aquabox improvements (#99)
Browse files Browse the repository at this point in the history
  • Loading branch information
hykilpikonna authored Jan 5, 2025
2 parents 8b1fe94 + 3a69717 commit 574e885
Show file tree
Hide file tree
Showing 12 changed files with 445 additions and 97 deletions.
2 changes: 2 additions & 0 deletions AquaNet/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,5 @@ dist-ssr
!.yarn/releases
!.yarn/sdks
!.yarn/versions

public/chu3
128 changes: 79 additions & 49 deletions AquaNet/src/components/settings/ChuniSettings.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
} from "../../libs/generalTypes";
import { DATA, USER, USERBOX } from "../../libs/sdk";
import { t, ts } from "../../libs/i18n";
import { DATA_HOST, FADE_IN, FADE_OUT, HAS_USERBOX_ASSETS } from "../../libs/config";
import { DATA_HOST, FADE_IN, FADE_OUT, USERBOX_DEFAULT_URL } from "../../libs/config";
import { fade, slide } from "svelte/transition";
import StatusOverlays from "../StatusOverlays.svelte";
import Icon from "@iconify/svelte";
Expand Down Expand Up @@ -97,9 +97,11 @@
let USERBOX_PROGRESS = 0;
let USERBOX_SETUP_RUN = false;
let USERBOX_SETUP_MODE = false;
let USERBOX_SETUP_TEXT = t("userbox.new.setup");
let USERBOX_ENABLED = useLocalStorage("userboxNew", false);
let USERBOX_PROFILE_ENABLED = useLocalStorage("userboxNewProfile", false);
let USERBOX_INSTALLED = false;
let USERBOX_SUPPORT = "webkitGetAsEntry" in DataTransferItem.prototype;
Expand All @@ -117,12 +119,37 @@
}) ?? "";
}
let USERBOX_URL_STATE = useLocalStorage("userboxURL", USERBOX_DEFAULT_URL);
function userboxHandleInput(baseURL: string, isSetByServer: boolean = false) {
if (baseURL != "")
try {
// validate url
new URL(baseURL, location.href);
} catch(err) {
if (isSetByServer)
return;
return error = t("userbox.new.error.invalidUrl")
}
USERBOX_URL_STATE.value = baseURL;
USERBOX_ENABLED.value = true;
USERBOX_PROFILE_ENABLED.value = true;
location.reload();
}
if (USERBOX_DEFAULT_URL && !USERBOX_URL_STATE.value)
userboxHandleInput(USERBOX_DEFAULT_URL, true);
indexedDB.databases().then(async (dbi) => {
let databaseExists = dbi.some(db => db.name == "userboxChusanDDS");
if (USERBOX_URL_STATE.value && databaseExists) {
indexedDB.deleteDatabase("userboxChusanDDS")
}
if (databaseExists) {
await initializeDb();
}
if (databaseExists || USERBOX_URL_STATE.value) {
DDSreader = new DDS(ddsDB);
USERBOX_INSTALLED = databaseExists;
USERBOX_INSTALLED = databaseExists || USERBOX_URL_STATE.value != "";
}
})
Expand Down Expand Up @@ -156,9 +183,9 @@
</div>
{:else}
<div class="chuni-userbox-container">
<ChuniUserplateComponent on:click={() => userboxSelected = "nameplateId"} chuniCharacter={userbox.characterId} chuniLevel={userbox.level} chuniRating={userbox.playerRating / 100}
<ChuniUserplateComponent chuniIsUserbox={true} on:click={() => userboxSelected = "nameplateId"} chuniCharacter={userbox.characterId} chuniLevel={userbox.level.toString()} chuniRating={userbox.playerRating / 100}
chuniNameplate={userbox.nameplateId} chuniName={userbox.userName} chuniTrophyName={allItems.trophy[userbox.trophyId].name}></ChuniUserplateComponent>
<ChuniPenguinComponent classPassthrough="chuni-penguin-float" chuniWear={userbox.avatarWear} chuniHead={userbox.avatarHead} chuniBack={userbox.avatarBack}
<ChuniPenguinComponent chuniWear={userbox.avatarWear} chuniHead={userbox.avatarHead} chuniBack={userbox.avatarBack}
chuniFront={userbox.avatarFront} chuniFace={userbox.avatarFace} chuniItem={userbox.avatarItem}
chuniSkin={userbox.avatarSkin}></ChuniPenguinComponent>
</div>
Expand Down Expand Up @@ -210,39 +237,28 @@
{/each}
</div>
{/if}
{#if HAS_USERBOX_ASSETS}
{#if USERBOX_INSTALLED}
<!-- god this is a mess but idgaf atp -->
<div class="field boolean" style:margin-top="1em">
<input type="checkbox" bind:checked={USERBOX_ENABLED.value} id="newUserbox">
<label for="newUserbox">
<span class="name">{t("userbox.new.activate")}</span>
<span class="desc">{t(`userbox.new.activate_desc`)}</span>
</label>
</div>
{/if}
{#if USERBOX_SUPPORT}
<p>
<button on:click={() => USERBOX_SETUP_RUN = !USERBOX_SETUP_RUN}>{t(!USERBOX_INSTALLED ? `userbox.new.activate_first` : `userbox.new.activate_update`)}</button>
</p>
{/if}
{#if !USERBOX_SUPPORT || !USERBOX_INSTALLED || !USERBOX_ENABLED.value}
<h2>{t("userbox.header.preview")}</h2>
<p class="notice">{t("userbox.preview.notice")}</p>
<input bind:value={preview} placeholder={t("userbox.preview.url")}/>
{#if preview}
<div class="preview">
{#each userItems.filter(v => v.iKey != 'trophy' && v.iKey != 'systemVoice') as { iKey, ubKey, items }, i}
<div>
<span>{ts(`userbox.${ubKey}`)}</span>
<img src={`${preview}/${iKey}/${userbox[ubKey].toString().padStart(8, '0')}.png`} alt="" on:error={coverNotFound} />
</div>
{/each}
</div>
{/if}
{/if}
{#if USERBOX_INSTALLED}
<!-- god this is a mess but idgaf atp -->
<div class="field boolean" style:margin-top="1em">
<input type="checkbox" bind:checked={USERBOX_ENABLED.value} id="newUserbox">
<label for="newUserbox">
<span class="name">{t("userbox.new.activate")}</span>
<span class="desc">{t(`userbox.new.activate_desc`)}</span>
</label>
</div>
<div class="field boolean" style:margin-top="1em">
<input type="checkbox" bind:checked={USERBOX_PROFILE_ENABLED.value} id="newUserboxProfile">
<label for="newUserboxProfile">
<span class="name">{t("userbox.new.activate_profile")}</span>
<span class="desc">{t(`userbox.new.activate_profile_desc`)}</span>
</label>
</div>
{/if}
{#if USERBOX_SUPPORT && !USERBOX_DEFAULT_URL}
<p>
<button on:click={() => USERBOX_SETUP_RUN = !USERBOX_SETUP_RUN}>{t(!USERBOX_INSTALLED ? `userbox.new.activate_first` : `userbox.new.activate_update`)}</button>
</p>
{/if}

<ChuniMatchingSettings/>
</div>
{/if}
Expand All @@ -251,20 +267,32 @@
<div class="overlay" transition:fade>
<div>
<h2>{t('userbox.new.name')}</h2>
<span>{USERBOX_SETUP_TEXT}</span>
<span>{USERBOX_SETUP_MODE ? t('userbox.new.url_warning') : USERBOX_SETUP_TEXT}</span>
<div class="actions">
{#if USERBOX_PROGRESS != 0}
<div class="progress">
<div class="progress-bar" style="width: {USERBOX_PROGRESS}%"></div>
</div>
{#if USERBOX_SETUP_MODE}
<input type="text" on:keyup={e => {if (e.key == "Enter") userboxHandleInput((e.target as HTMLInputElement).value)}} class="add-margin" placeholder="Base URL">
{:else}
<button class="drop-btn">
<input type="file" on:input={userboxSafeDrop} on:click={e => e.preventDefault()}>
{t('userbox.new.drop')}
</button>
<button on:click={() => USERBOX_SETUP_RUN = false}>
{t('back')}
</button>
{#if USERBOX_PROGRESS != 0}
<div class="progress">
<div class="progress-bar" style="width: {USERBOX_PROGRESS}%"></div>
</div>
{:else}
<p class="notice add-margin">
{t('userbox.new.setup.notice')}
</p>
<button class="drop-btn">
<input type="file" on:input={userboxSafeDrop} on:click={e => e.preventDefault()}>
{t('userbox.new.drop')}
</button>
{/if}
{/if}
{#if USERBOX_PROGRESS == 0}
<button on:click={() => USERBOX_SETUP_RUN = false}>
{t('back')}
</button>
<button on:click={() => USERBOX_SETUP_MODE = !USERBOX_SETUP_MODE}>
{t(USERBOX_SETUP_MODE ? 'userbox.new.switch.to_drop' : 'userbox.new.switch.to_url')}
</button>
{/if}
</div>
</div>
Expand Down Expand Up @@ -299,13 +327,15 @@ p.notice
border-radius: 25px
.add-margin, .drop-btn
margin-bottom: 1em
.drop-btn
position: relative
width: 100%
aspect-ratio: 3
background: transparent
box-shadow: 0 0 1px 1px vars.$ov-lighter
margin-bottom: 1em
> input
position: absolute
Expand Down
116 changes: 88 additions & 28 deletions AquaNet/src/components/settings/userbox/ChuniPenguin.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
export var chuniItem = 1500001;
export var chuniFront = 1600001;
export var chuniBack = 1700001;
export var classPassthrough: string = ``
export var classPassthrough: string = ``;
</script>
<div class="chuni-penguin {classPassthrough}">
<div class="chuni-penguin-body">
Expand All @@ -28,13 +28,33 @@
<img class="chuni-penguin-beak chuni-penguin-accessory" src={imageURL} alt="Beak">
{/await}

<!-- Arms (surfboard) -->
{#await DDSreader.getFileFromSheet("surfboard:CHU_UI_Common_Avatar_body_00.dds", 0, 0, 85, 160, 0.75) then imageURL}
<img class="chuni-penguin-arm-left chuni-penguin-arm" src={imageURL} alt="Left Arm">
{/await}
{#await DDSreader.getFileFromSheet("surfboard:CHU_UI_Common_Avatar_body_00.dds", 0, 0, 85, 160, 0.75) then imageURL}
<img class="chuni-penguin-arm-right chuni-penguin-arm" src={imageURL} alt="Right Arm">
{/await}
{#if chuniItem != 1500001}
<!-- Arms (straight) -->
{#await DDSreader.getFileFromSheet("surfboard:CHU_UI_Common_Avatar_body_00.dds", 0, 0, 85, 160, 0.75) then imageURL}
<img class="chuni-penguin-arm-left chuni-penguin-arm" src={imageURL} alt="Left Arm">
<div class="chuni-penguin-arm-left chuni-penguin-arm-type-1 chuni-penguin-arm">
{#await DDSreader.getFileFromSheet(`avatarAccessory:${chuniItem.toString().padStart(8, "0")}`, 0, 0, 200, 544, 0.75) then imageURL}
<img class="chuni-penguin-item chuni-penguin-accessory chuni-penguin-item-left" src={imageURL} alt="Item">
{/await}
</div>
{/await}
{#await DDSreader.getFileFromSheet("surfboard:CHU_UI_Common_Avatar_body_00.dds", 0, 0, 85, 160, 0.75) then imageURL}
<img class="chuni-penguin-arm-right chuni-penguin-arm" src={imageURL} alt="Right Arm">
<div class="chuni-penguin-arm-right chuni-penguin-arm-type-1 chuni-penguin-arm">
{#await DDSreader.getFileFromSheet(`avatarAccessory:${chuniItem.toString().padStart(8, "0")}`, 200, 0, 200, 544, 0.75) then imageURL}
<img class="chuni-penguin-item chuni-penguin-accessory chuni-penguin-item-right" src={imageURL} alt="Item">
{/await}
</div>
{/await}
{:else}
<!-- Arms (bent) -->
{#await DDSreader.getFileFromSheet("surfboard:CHU_UI_Common_Avatar_body_00.dds", 80, 0, 110, 100, 0.75) then imageURL}
<img class="chuni-penguin-arm-left chuni-penguin-arm chuni-penguin-arm-type-2" src={imageURL} alt="Left Arm">
{/await}
{#await DDSreader.getFileFromSheet("surfboard:CHU_UI_Common_Avatar_body_00.dds", 80, 0, 110, 100, 0.75) then imageURL}
<img class="chuni-penguin-arm-right chuni-penguin-arm chuni-penguin-arm-type-2" src={imageURL} alt="Right Arm">
{/await}
{/if}

<!-- Wear -->
{#await DDSreader.getFileScaled(`avatarAccessory:${chuniWear.toString().padStart(8, "0")}`, 0.75, `avatarAccessory:01100001`) then imageURL}
Expand All @@ -60,11 +80,6 @@
<img class="chuni-penguin-face-accessory chuni-penguin-accessory" src={imageURL} alt="Face (Accessory)">
{/await}

<!-- Item -->
{#await DDSreader.getFileScaled(`avatarAccessory:${chuniItem.toString().padStart(8, "0")}`, 0.75, `avatarAccessory:01500001`) then imageURL}
<img class="chuni-penguin-item chuni-penguin-accessory" src={imageURL} alt="Item">
{/await}

<!-- Front -->
{#await DDSreader.getFileScaled(`avatarAccessory:${chuniFront.toString().padStart(8, "0")}`, 0.75) then imageURL}
<img class="chuni-penguin-front chuni-penguin-accessory" src={imageURL} alt="Front">
Expand All @@ -77,20 +92,23 @@
</div>
<div class="chuni-penguin-feet">
<!-- Feet -->
{#await DDSreader.getFileFromSheet(`avatarAccessory:${chuniSkin.toString().padStart(8, "0")}`, 0, 410, 167, 80, 0.75) then imageURL}
<img src={imageURL} alt="Feet">
{#await DDSreader.getFileFromSheet(`avatarAccessory:${chuniSkin.toString().padStart(8, "0")}`, 0, 410, 85, 80, 0.75) then imageURL}
<img src={imageURL} alt="Foot">
{/await}
{#await DDSreader.getFileFromSheet(`avatarAccessory:${chuniSkin.toString().padStart(8, "0")}`, 85, 410, 85, 80, 0.75) then imageURL}
<img src={imageURL} alt="Foot">
{/await}
</div>
</div>
<!-- Truly sorry for the horrors below -->
<style lang="sass">
@keyframes chuniPenguinBodyBob
0%
transform: translate(-50%, 0%) translate(0%, -50%)
transform: translate(-50%, 5px) translate(0%, -50%)
50%
transform: translate(-50%, 10px) translate(0%, -50%)
100%
transform: translate(-50%, 0%) translate(0%, -50%)
100%
transform: translate(-50%, 5px) translate(0%, -50%)
@keyframes chuniPenguinArmLeft
0%
transform: translate(-50%, 0) rotate(-2deg)
Expand All @@ -108,11 +126,21 @@
img
-webkit-user-drag: none
user-select: none
.chuni-penguin
height: 512px
aspect-ratio: 1/2
position: relative
pointer-events: none
z-index: 1
&.chuni-penguin-float
position: absolute
top: 50%
left: 50%
transform: translate(-50%, -50%)
.chuni-penguin-body, .chuni-penguin-feet
transform: translate(-50%, -50%)
Expand All @@ -122,34 +150,66 @@
.chuni-penguin-body
top: 50%
z-index: 1
animation: chuniPenguinBodyBob 2s infinite cubic-bezier(0.45, 0, 0.55, 1)
animation: chuniPenguinBodyBob 1s infinite cubic-bezier(0.45, 0, 0.55, 1)
.chuni-penguin-feet
top: 82.5%
top: 80%
z-index: 0
width: 175px
display: flex
justify-content: center
img
margin-left: auto
margin-right: auto
.chuni-penguin-arm
transform-origin: 95% 10%
transform-origin: 90% 10%
position: absolute
top: 40%
.chuni-penguin-arm-left
left: 0%
animation: chuniPenguinArmLeft 1.5s infinite cubic-bezier(0.45, 0, 0.55, 1)
.chuni-penguin-arm-right
left: 70%
animation: chuniPenguinArmRight 1.5s infinite cubic-bezier(0.45, 0, 0.55, 1)
z-index: 0
&.chuni-penguin-arm-type-1
width: calc(85px * 0.75)
height: calc(160px * 0.75)
z-index: 2
&.chuni-penguin-arm-type-2
transform-origin: 40% 10%
z-index: 2
&.chuni-penguin-arm-left
left: 0%
transform: translate(-50%, 0)
animation: chuniPenguinArmLeft 1s infinite cubic-bezier(0.45, 0, 0.55, 1)
&.chuni-penguin-arm-type-2
left: 15%
&.chuni-penguin-arm-right
left: 72.5%
transform: translate(-50%, 0) scaleX(-1)
animation: chuniPenguinArmRight 1s infinite cubic-bezier(0.45, 0, 0.55, 1)
&.chuni-penguin-arm-type-2
left: 95%
.chuni-penguin-accessory
transform: translate(-50%, -50%)
position: absolute
top: 50%
left: 50%
.chuni-penguin-item
z-index: 1
top: 25%
left: 0
&.chuni-penguin-item-left
transform: translate(-50%, -50%) rotate(-15deg)
&.chuni-penguin-item-right
transform: translate(-50%, -50%) scaleX(-1) rotate(15deg)
.chuni-penguin-eyes
top: 22.5%
.chuni-penguin-beak
top: 29.5%
.chuni-penguin-wear
top: 57.5%
top: 60%
.chuni-penguin-head
top: 7.5%
z-index: 10
Expand Down
Loading

0 comments on commit 574e885

Please sign in to comment.