mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-19 23:16:21 +00:00
🆙 Init V3
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
export const CloneObject = <T>(object: T): T =>
|
||||
{
|
||||
if((object == null) || ('object' != typeof object)) return object;
|
||||
|
||||
// @ts-ignore
|
||||
const copy = new object.constructor();
|
||||
|
||||
for(const attr in object)
|
||||
{
|
||||
if(object.hasOwnProperty(attr)) copy[attr] = object[attr];
|
||||
}
|
||||
|
||||
return copy;
|
||||
};
|
||||
@@ -0,0 +1,65 @@
|
||||
export class ColorUtils
|
||||
{
|
||||
public static makeColorHex(color: string): string
|
||||
{
|
||||
return ('#' + color);
|
||||
}
|
||||
|
||||
public static makeColorNumberHex(color: number): string
|
||||
{
|
||||
let val = color.toString(16);
|
||||
return ( '#' + val.padStart(6, '0'));
|
||||
}
|
||||
|
||||
public static convertFromHex(color: string): number
|
||||
{
|
||||
return parseInt(color.replace('#', ''), 16);
|
||||
}
|
||||
|
||||
public static uintHexColor(color: number): string
|
||||
{
|
||||
const realColor = color >>>0;
|
||||
|
||||
return ColorUtils.makeColorHex(realColor.toString(16).substring(2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an integer format into an array of 8-bit values
|
||||
* @param {number} value value in integer format
|
||||
* @returns {Array} 8-bit values
|
||||
*/
|
||||
public static int_to_8BitVals(value: number): [number, number, number, number]
|
||||
{
|
||||
const val1 = ((value >> 24) & 0xFF);
|
||||
const val2 = ((value >> 16) & 0xFF);
|
||||
const val3 = ((value >> 8) & 0xFF);
|
||||
const val4 = (value & 0xFF);
|
||||
|
||||
return [ val1, val2, val3, val4 ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines 4 8-bit values into a 32-bit integer. Values are combined in
|
||||
* in the order of the parameters
|
||||
* @param val1
|
||||
* @param val2
|
||||
* @param val3
|
||||
* @param val4
|
||||
* @returns 32-bit integer of combined values
|
||||
*/
|
||||
public static eight_bitVals_to_int(val1: number, val2: number, val3: number, val4: number): number
|
||||
{
|
||||
return (((val1) << 24) + ((val2) << 16) + ((val3) << 8) + (val4| 0));
|
||||
}
|
||||
|
||||
public static int2rgb(color: number): string
|
||||
{
|
||||
color >>>= 0;
|
||||
const b = color & 0xFF;
|
||||
const g = (color & 0xFF00) >>> 8;
|
||||
const r = (color & 0xFF0000) >>> 16;
|
||||
const a = ((color & 0xFF000000) >>> 24) / 255;
|
||||
|
||||
return 'rgba(' + [ r, g, b, 1 ].join(',') + ')';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export const ConvertSeconds = (seconds: number) =>
|
||||
{
|
||||
let numDays = Math.floor(seconds / 86400);
|
||||
let numHours = Math.floor((seconds % 86400) / 3600);
|
||||
let numMinutes = Math.floor(((seconds % 86400) % 3600) / 60);
|
||||
let numSeconds = ((seconds % 86400) % 3600) % 60;
|
||||
|
||||
return numDays.toString().padStart(2, '0') + ':' + numHours.toString().padStart(2, '0') + ':' + numMinutes.toString().padStart(2, '0') + ':' + numSeconds.toString().padStart(2, '0');
|
||||
};
|
||||
@@ -0,0 +1,65 @@
|
||||
export class FixedSizeStack
|
||||
{
|
||||
private _data: number[];
|
||||
private _maxSize: number;
|
||||
private _index: number;
|
||||
|
||||
constructor(k: number)
|
||||
{
|
||||
this._data = [];
|
||||
this._maxSize = k;
|
||||
this._index = 0;
|
||||
}
|
||||
|
||||
public reset(): void
|
||||
{
|
||||
this._data = [];
|
||||
this._index = 0;
|
||||
}
|
||||
|
||||
public addValue(k: number): void
|
||||
{
|
||||
if(this._data.length < this._maxSize)
|
||||
{
|
||||
this._data.push(k);
|
||||
}
|
||||
else
|
||||
{
|
||||
this._data[this._index] = k;
|
||||
}
|
||||
|
||||
this._index = ((this._index + 1) % this._maxSize);
|
||||
}
|
||||
|
||||
public getMax(): number
|
||||
{
|
||||
let k = Number.MIN_VALUE;
|
||||
|
||||
let _local_2 = 0;
|
||||
|
||||
while(_local_2 < this._maxSize)
|
||||
{
|
||||
if(this._data[_local_2] > k) k = this._data[_local_2];
|
||||
|
||||
_local_2++;
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
public getMin(): number
|
||||
{
|
||||
let k = Number.MAX_VALUE;
|
||||
|
||||
let _local_2 = 0;
|
||||
|
||||
while(_local_2 < this._maxSize)
|
||||
{
|
||||
if(this._data[_local_2] < k) k = this._data[_local_2];
|
||||
|
||||
_local_2++;
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import { LocalizeText } from './LocalizeText';
|
||||
|
||||
export class FriendlyTime
|
||||
{
|
||||
private static MINUTE: number = 60;
|
||||
private static HOUR: number = (60 * FriendlyTime.MINUTE);
|
||||
private static DAY: number = (24 * FriendlyTime.HOUR);
|
||||
private static WEEK: number = (7 * FriendlyTime.DAY);
|
||||
private static MONTH: number = (30 * FriendlyTime.DAY);
|
||||
private static YEAR: number = (365 * FriendlyTime.DAY);
|
||||
|
||||
|
||||
public static format(seconds: number, key: string = '', threshold: number = 3): string
|
||||
{
|
||||
if(seconds > (threshold * FriendlyTime.YEAR)) return FriendlyTime.getLocalization(('friendlytime.years' + key), Math.round((seconds / FriendlyTime.YEAR)));
|
||||
|
||||
if(seconds > (threshold * FriendlyTime.MONTH)) return FriendlyTime.getLocalization(('friendlytime.months' + key), Math.round((seconds / FriendlyTime.MONTH)));
|
||||
|
||||
if(seconds > (threshold * FriendlyTime.DAY)) return FriendlyTime.getLocalization(('friendlytime.days' + key), Math.round((seconds / FriendlyTime.DAY)));
|
||||
|
||||
if(seconds > (threshold * FriendlyTime.HOUR)) return FriendlyTime.getLocalization(('friendlytime.hours' + key), Math.round((seconds / FriendlyTime.HOUR)));
|
||||
|
||||
if(seconds > (threshold * FriendlyTime.MINUTE)) return FriendlyTime.getLocalization(('friendlytime.minutes' + key), Math.round((seconds / FriendlyTime.MINUTE)));
|
||||
|
||||
return FriendlyTime.getLocalization(('friendlytime.seconds' + key), Math.round(seconds));
|
||||
}
|
||||
|
||||
public static shortFormat(seconds: number, key: string = '', threshold: number = 3): string
|
||||
{
|
||||
if(seconds > (threshold * FriendlyTime.YEAR)) return FriendlyTime.getLocalization(('friendlytime.years.short' + key), Math.round((seconds / FriendlyTime.YEAR)));
|
||||
|
||||
if(seconds > (threshold * FriendlyTime.MONTH)) return FriendlyTime.getLocalization(('friendlytime.months.short' + key), Math.round((seconds / FriendlyTime.MONTH)));
|
||||
|
||||
if(seconds > (threshold * FriendlyTime.DAY)) return FriendlyTime.getLocalization(('friendlytime.days.short' + key), Math.round((seconds / FriendlyTime.DAY)));
|
||||
|
||||
if(seconds > (threshold * FriendlyTime.HOUR)) return FriendlyTime.getLocalization(('friendlytime.hours.short' + key), Math.round((seconds / FriendlyTime.HOUR)));
|
||||
|
||||
if(seconds > (threshold * FriendlyTime.MINUTE)) return FriendlyTime.getLocalization(('friendlytime.minutes.short' + key), Math.round((seconds / FriendlyTime.MINUTE)));
|
||||
|
||||
return FriendlyTime.getLocalization(('friendlytime.seconds.short' + key), Math.round(seconds));
|
||||
}
|
||||
|
||||
public static getLocalization(key: string, amount: number): string
|
||||
{
|
||||
return LocalizeText(key, [ 'amount' ], [ amount.toString() ]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
export const GetLocalStorage = <T>(key: string) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
JSON.parse(window.localStorage.getItem(key)) as T ?? null;
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
export class LocalStorageKeys
|
||||
{
|
||||
public static CATALOG_PLACE_MULTIPLE_OBJECTS: string = 'catalogPlaceMultipleObjects';
|
||||
public static CATALOG_SKIP_PURCHASE_CONFIRMATION: string = 'catalogSkipPurchaseConfirmation';
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { GetLocalizationManager } from '@nitrots/nitro-renderer';
|
||||
|
||||
export const LocalizeBadgeDescription = (key: string) =>
|
||||
{
|
||||
let badgeDesc = GetLocalizationManager().getBadgeDesc(key);
|
||||
|
||||
if(!badgeDesc || !badgeDesc.length) badgeDesc = `badge_desc_${ key }`;
|
||||
|
||||
return badgeDesc;
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
import { GetLocalizationManager } from '@nitrots/nitro-renderer';
|
||||
|
||||
export const LocalizeBadgeName = (key: string) =>
|
||||
{
|
||||
let badgeName = GetLocalizationManager().getBadgeName(key);
|
||||
|
||||
if(!badgeName || !badgeName.length) badgeName = `badge_name_${ key }`;
|
||||
|
||||
return badgeName;
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
export function LocalizeFormattedNumber(number: number): string
|
||||
{
|
||||
if(!number || isNaN(number)) return '0';
|
||||
|
||||
return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
export function LocalizeShortNumber(number: number): string
|
||||
{
|
||||
if(!number || isNaN(number)) return '0';
|
||||
|
||||
let abs = Math.abs(number);
|
||||
|
||||
const rounder = Math.pow(10, 1);
|
||||
const isNegative = (number < 0);
|
||||
|
||||
let key = '';
|
||||
|
||||
const powers = [
|
||||
{ key: 'Q', value: Math.pow(10, 15) },
|
||||
{ key: 'T', value: Math.pow(10, 12) },
|
||||
{ key: 'B', value: Math.pow(10, 9) },
|
||||
{ key: 'M', value: Math.pow(10, 6) },
|
||||
{ key: 'K', value: 1000 }
|
||||
];
|
||||
|
||||
for(const power of powers)
|
||||
{
|
||||
let reduced = abs / power.value;
|
||||
|
||||
reduced = Math.round(reduced * rounder) / rounder;
|
||||
|
||||
if(reduced >= 1)
|
||||
{
|
||||
abs = reduced;
|
||||
key = power.key;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ((isNegative ? '-' : '') + abs + key);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { GetLocalizationManager } from '@nitrots/nitro-renderer';
|
||||
|
||||
export function LocalizeText(key: string, parameters: string[] = null, replacements: string[] = null): string
|
||||
{
|
||||
return GetLocalizationManager().getValueWithParameters(key, parameters, replacements);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { MouseEventType, NitroSoundEvent } from '@nitrots/nitro-renderer';
|
||||
import { DispatchMainEvent } from '../events';
|
||||
|
||||
let canPlaySound = false;
|
||||
|
||||
export const PlaySound = (sampleCode: string) =>
|
||||
{
|
||||
if(!canPlaySound) return;
|
||||
|
||||
DispatchMainEvent(new NitroSoundEvent(NitroSoundEvent.PLAY_SOUND, sampleCode));
|
||||
};
|
||||
|
||||
const eventTypes = [ MouseEventType.MOUSE_CLICK ];
|
||||
|
||||
const startListening = () =>
|
||||
{
|
||||
const stopListening = () => eventTypes.forEach(type => window.removeEventListener(type, onEvent));
|
||||
|
||||
const onEvent = (event: Event) => ((canPlaySound = true) && stopListening());
|
||||
|
||||
eventTypes.forEach(type => window.addEventListener(type, onEvent));
|
||||
};
|
||||
|
||||
startListening();
|
||||
@@ -0,0 +1,58 @@
|
||||
import { FurnitureType, GetRoomEngine } from '@nitrots/nitro-renderer';
|
||||
import { FurniCategory } from '../inventory';
|
||||
|
||||
export class ProductImageUtility
|
||||
{
|
||||
public static getProductImageUrl(productType: FurnitureType, furniClassId: number, extraParam: string): string
|
||||
{
|
||||
let imageUrl: string = null;
|
||||
|
||||
switch(productType)
|
||||
{
|
||||
case FurnitureType.FLOOR:
|
||||
imageUrl = GetRoomEngine().getFurnitureFloorIconUrl(furniClassId);
|
||||
break;
|
||||
case FurnitureType.WALL:
|
||||
const productCategory = this.getProductCategory(CatalogPageMessageProductData.I, furniClassId);
|
||||
|
||||
if(productCategory === 1)
|
||||
{
|
||||
imageUrl = GetRoomEngine().getFurnitureWallIconUrl(furniClassId, extraParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(productCategory)
|
||||
{
|
||||
case FurniCategory.WALL_PAPER:
|
||||
break;
|
||||
case FurniCategory.LANDSCAPE:
|
||||
break;
|
||||
case FurniCategory.FLOOR:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FurnitureType.EFFECT:
|
||||
// fx_icon_furniClassId_png
|
||||
break;
|
||||
}
|
||||
|
||||
return imageUrl;
|
||||
}
|
||||
|
||||
public static getProductCategory(productType: FurnitureType, furniClassId: number): number
|
||||
{
|
||||
if(productType === FurnitureType.FLOOR) return 1;
|
||||
|
||||
if(productType === FurnitureType.WALL)
|
||||
{
|
||||
if(furniClassId === 3001) return FurniCategory.WALL_PAPER;
|
||||
|
||||
if(furniClassId === 3002) return FurniCategory.FLOOR;
|
||||
|
||||
if(furniClassId === 4057) return FurniCategory.LANDSCAPE;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
export class Randomizer
|
||||
{
|
||||
public static getRandomNumber(count: number): number
|
||||
{
|
||||
return Math.floor(Math.random() * count);
|
||||
}
|
||||
|
||||
public static getRandomElement<T>(elements: T[]): T
|
||||
{
|
||||
return elements[this.getRandomNumber(elements.length)];
|
||||
}
|
||||
|
||||
public static getRandomElements<T>(elements: T[], count: number): T[]
|
||||
{
|
||||
const result: T[] = new Array(count);
|
||||
let len = elements.length;
|
||||
const taken = new Array(len);
|
||||
|
||||
while(count--)
|
||||
{
|
||||
var x = this.getRandomNumber(len);
|
||||
result[count] = elements[x in taken ? taken[x] : x];
|
||||
taken[x] = --len in taken ? taken[len] : len;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
const allowedColours: Map<string, string> = new Map();
|
||||
|
||||
allowedColours.set('r', 'red');
|
||||
allowedColours.set('b', 'blue');
|
||||
allowedColours.set('g', 'green');
|
||||
allowedColours.set('y', 'yellow');
|
||||
allowedColours.set('w', 'white');
|
||||
allowedColours.set('o', 'orange');
|
||||
allowedColours.set('c', 'cyan');
|
||||
allowedColours.set('br', 'brown');
|
||||
allowedColours.set('pr', 'purple');
|
||||
allowedColours.set('pk', 'pink');
|
||||
|
||||
allowedColours.set('red', 'red');
|
||||
allowedColours.set('blue', 'blue');
|
||||
allowedColours.set('green', 'green');
|
||||
allowedColours.set('yellow', 'yellow');
|
||||
allowedColours.set('white', 'white');
|
||||
allowedColours.set('orange', 'orange');
|
||||
allowedColours.set('cyan', 'cyan');
|
||||
allowedColours.set('brown', 'brown');
|
||||
allowedColours.set('purple', 'purple');
|
||||
allowedColours.set('pink', 'pink');
|
||||
|
||||
const encodeHTML = (str: string) =>
|
||||
{
|
||||
return str.replace(/([\u00A0-\u9999<>&])(.|$)/g, (full, char, next) =>
|
||||
{
|
||||
if(char !== '&' || next !== '#')
|
||||
{
|
||||
if(/[\u00A0-\u9999<>&]/.test(next)) next = '&#' + next.charCodeAt(0) + ';';
|
||||
|
||||
return '&#' + char.charCodeAt(0) + ';' + next;
|
||||
}
|
||||
|
||||
return full;
|
||||
});
|
||||
};
|
||||
|
||||
export const RoomChatFormatter = (content: string) =>
|
||||
{
|
||||
let result = '';
|
||||
|
||||
content = encodeHTML(content);
|
||||
//content = (joypixels.shortnameToUnicode(content) as string)
|
||||
|
||||
if(content.startsWith('@') && content.indexOf('@', 1) > -1)
|
||||
{
|
||||
let match = null;
|
||||
|
||||
while((match = /@[a-zA-Z]+@/g.exec(content)) !== null)
|
||||
{
|
||||
const colorTag = match[0].toString();
|
||||
const colorName = colorTag.substr(1, colorTag.length - 2);
|
||||
const text = content.replace(colorTag, '');
|
||||
|
||||
if(!allowedColours.has(colorName))
|
||||
{
|
||||
result = text;
|
||||
}
|
||||
else
|
||||
{
|
||||
const color = allowedColours.get(colorName);
|
||||
result = '<span style="color: ' + color + '">' + text + '</span>';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = content;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export const SetLocalStorage = <T>(key: string, value: T) => window.localStorage.setItem(key, JSON.stringify(value));
|
||||
@@ -0,0 +1,9 @@
|
||||
export class SoundNames
|
||||
{
|
||||
public static CAMERA_SHUTTER = 'camera_shutter';
|
||||
public static CREDITS = 'credits';
|
||||
public static DUCKETS = 'duckets';
|
||||
public static MESSENGER_NEW_THREAD = 'messenger_new_thread';
|
||||
public static MESSENGER_MESSAGE_RECEIVED = 'messenger_message_received';
|
||||
public static MODTOOLS_NEW_TICKET = 'modtools_new_ticket';
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export interface WindowSaveOptions
|
||||
{
|
||||
offset: { x: number, y: number };
|
||||
size: { width: number, height: number };
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
export * from './CloneObject';
|
||||
export * from './ColorUtils';
|
||||
export * from './ConvertSeconds';
|
||||
export * from './FixedSizeStack';
|
||||
export * from './FriendlyTime';
|
||||
export * from './GetLocalStorage';
|
||||
export * from './LocalStorageKeys';
|
||||
export * from './LocalizeBadgeDescription';
|
||||
export * from './LocalizeBageName';
|
||||
export * from './LocalizeFormattedNumber';
|
||||
export * from './LocalizeShortNumber';
|
||||
export * from './LocalizeText';
|
||||
export * from './PlaySound';
|
||||
export * from './ProductImageUtility';
|
||||
export * from './Randomizer';
|
||||
export * from './RoomChatFormatter';
|
||||
export * from './SetLocalStorage';
|
||||
export * from './SoundNames';
|
||||
export * from './WindowSaveOptions';
|
||||
Reference in New Issue
Block a user