5180 fichiers 38.5 Mo 0 téléchargements 215 vues mis à jour il y a 5 heures ui
nitro-v36-with-renderer-v36 / src / api / avatar / SanitizeAvatarFigure.ts
SanitizeAvatarFigure.ts 2.9 Ko Télécharger le fichier
import { IFigurePartSet, IStructureData } from '@octane/renderer';

export interface SanitizeFigureOptions {
    gender: string;
    clubLevel: number;
    ownedSetIds: number[];
    /** Mandatory set types for the gender and club level (head, body, legs...). */
    mandatorySetTypes: string[];
}

/** Habbo's defaults when switching to a gender that has no look yet. */
export const DEFAULT_MALE_FIGURE = 'hr-100.hd-180-7.ch-215-66.lg-270-79.sh-305-62.ha-1002-70.wa-2007';
export const DEFAULT_FEMALE_FIGURE = 'hr-515-33.hd-600-1.ch-635-70.lg-716-66-62.sh-735-68';

const fitsGender = (partSet: IFigurePartSet, gender: string) => !partSet.gender || partSet.gender === 'U' || partSet.gender === gender;

const isWearable = (partSet: IFigurePartSet, options: SanitizeFigureOptions) =>
    !!partSet &&
    fitsGender(partSet, options.gender) &&
    partSet.clubLevel <= options.clubLevel &&
    !(partSet.isSellable && options.ownedSetIds.indexOf(partSet.id) === -1);

/**
 * Like Habbo's editor: drops parts the user can't wear (club level, unowned sellable, other
 * gender), puts the first wearable part back for mandatory types, and replaces club colours.
 */
export const sanitizeAvatarFigure = (figure: string, structure: IStructureData, options: SanitizeFigureOptions): string => {
    if (!figure || !structure) return figure;

    const result: string[] = [];
    const seenTypes = new Set<string>();

    for (const set of figure.split('.')) {
        const [type, idText, ...colorTexts] = set.split('-');
        const setType = type ? structure.getSetType(type) : null;

        if (!setType) continue;

        let partSet = setType.getPartSet(parseInt(idText));

        if (!isWearable(partSet, options)) {
            if (options.mandatorySetTypes.indexOf(type) === -1) continue;

            partSet = setType.partSets.getValues().find((candidate) => candidate.isSelectable && isWearable(candidate, options)) ?? null;

            if (!partSet) continue;
        }

        const palette = structure.getPalette(setType.paletteID);
        const firstColor = palette?.colors.getValues().find((color) => color.isSelectable && color.clubLevel <= options.clubLevel);
        const colors = colorTexts.map((text) => {
            const color = palette?.getColor(parseInt(text));

            return (color && color.clubLevel > options.clubLevel && firstColor) ? firstColor.id.toString() : text;
        });

        seenTypes.add(type);
        result.push([type, partSet.id.toString(), ...colors].join('-'));
    }

    // A mandatory type that was missing gets its first wearable part too.
    for (const type of options.mandatorySetTypes) {
        if (seenTypes.has(type)) continue;

        const setType = structure.getSetType(type);
        const partSet = setType?.partSets.getValues().find((candidate) => candidate.isSelectable && isWearable(candidate, options));

        if (partSet) result.push(`${type}-${partSet.id}`);
    }

    return result.join('.');
};
15Sujets
1Dépôts
20Membres
2En ligne
Profile
Inscrit
Dernière visite
Messages
0
Votes positifs
0
Votes négatifs
0

Nous utilisons des cookies pour assurer le bon fonctionnement du site et améliorer votre expérience. en savoir plus

Autoriser