🆙 Init V3

This commit is contained in:
DuckieTM
2026-01-31 09:10:52 +01:00
commit 7feb10ab15
1733 changed files with 53405 additions and 0 deletions
+14
View File
@@ -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;
};
+65
View File
@@ -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(',') + ')';
}
}
+9
View File
@@ -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');
};
+65
View File
@@ -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;
}
}
+47
View File
@@ -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() ]);
}
}
+11
View File
@@ -0,0 +1,11 @@
export const GetLocalStorage = <T>(key: string) =>
{
try
{
JSON.parse(window.localStorage.getItem(key)) as T ?? null;
}
catch (e)
{
return null;
}
};
+5
View File
@@ -0,0 +1,5 @@
export class LocalStorageKeys
{
public static CATALOG_PLACE_MULTIPLE_OBJECTS: string = 'catalogPlaceMultipleObjects';
public static CATALOG_SKIP_PURCHASE_CONFIRMATION: string = 'catalogSkipPurchaseConfirmation';
}
+10
View File
@@ -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;
};
+10
View File
@@ -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;
};
+6
View File
@@ -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, ' ');
};
+36
View File
@@ -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);
}
+6
View File
@@ -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);
}
+24
View File
@@ -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();
+58
View File
@@ -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;
}
}
+28
View File
@@ -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;
}
}
+75
View File
@@ -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;
};
+1
View File
@@ -0,0 +1 @@
export const SetLocalStorage = <T>(key: string, value: T) => window.localStorage.setItem(key, JSON.stringify(value));
+9
View File
@@ -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';
}
+5
View File
@@ -0,0 +1,5 @@
export interface WindowSaveOptions
{
offset: { x: number, y: number };
size: { width: number, height: number };
}
+19
View File
@@ -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';