2024-05-27 09:39:18 +01:00
|
|
|
import i18next from "i18next";
|
2024-06-13 23:44:23 +01:00
|
|
|
import { MoneyFormat } from "#enums/money-format";
|
2024-05-27 09:39:18 +01:00
|
|
|
|
2024-05-23 16:03:10 +01:00
|
|
|
export const MissingTextureKey = "__MISSING";
|
2024-02-25 02:16:19 +00:00
|
|
|
|
2023-10-18 23:01:15 +01:00
|
|
|
export function toReadableString(str: string): string {
|
2024-05-23 16:03:10 +01:00
|
|
|
return str.replace(/\_/g, " ").split(" ").map(s => `${s.slice(0, 1)}${s.slice(1).toLowerCase()}`).join(" ");
|
2023-10-18 23:01:15 +01:00
|
|
|
}
|
|
|
|
|
2024-01-03 02:31:59 +00:00
|
|
|
export function randomString(length: integer, seeded: boolean = false) {
|
2024-05-23 16:03:10 +01:00
|
|
|
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
|
|
let result = "";
|
2024-05-24 00:45:04 +01:00
|
|
|
|
2023-10-18 23:01:15 +01:00
|
|
|
for (let i = 0; i < length; i++) {
|
2024-01-03 02:31:59 +00:00
|
|
|
const randomIndex = seeded ? randSeedInt(characters.length) : Math.floor(Math.random() * characters.length);
|
2023-10-18 23:01:15 +01:00
|
|
|
result += characters[randomIndex];
|
|
|
|
}
|
2024-05-24 00:45:04 +01:00
|
|
|
|
2023-10-18 23:01:15 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function shiftCharCodes(str: string, shiftCount: integer) {
|
2024-05-23 16:03:10 +01:00
|
|
|
if (!shiftCount) {
|
2023-10-18 23:01:15 +01:00
|
|
|
shiftCount = 0;
|
2024-05-23 16:03:10 +01:00
|
|
|
}
|
2024-05-24 00:45:04 +01:00
|
|
|
|
2024-05-23 16:03:10 +01:00
|
|
|
let newStr = "";
|
2023-10-18 23:01:15 +01:00
|
|
|
|
|
|
|
for (let i = 0; i < str.length; i++) {
|
2024-05-23 16:03:10 +01:00
|
|
|
const charCode = str.charCodeAt(i);
|
|
|
|
const newCharCode = charCode + shiftCount;
|
|
|
|
newStr += String.fromCharCode(newCharCode);
|
2023-10-18 23:01:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return newStr;
|
2023-03-28 19:54:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export function clampInt(value: integer, min: integer, max: integer): integer {
|
|
|
|
return Math.min(Math.max(value, min), max);
|
|
|
|
}
|
|
|
|
|
2024-01-05 04:57:21 +00:00
|
|
|
export function randGauss(stdev: number, mean: number = 0): number {
|
2024-05-23 16:03:10 +01:00
|
|
|
if (!stdev) {
|
2024-03-19 23:52:27 +00:00
|
|
|
return 0;
|
2024-05-23 16:03:10 +01:00
|
|
|
}
|
2024-01-05 04:57:21 +00:00
|
|
|
const u = 1 - Math.random();
|
|
|
|
const v = Math.random();
|
|
|
|
const z = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v);
|
|
|
|
return z * stdev + mean;
|
2023-03-28 19:54:52 +01:00
|
|
|
}
|
|
|
|
|
2024-01-05 04:57:21 +00:00
|
|
|
export function randSeedGauss(stdev: number, mean: number = 0): number {
|
2024-05-23 16:03:10 +01:00
|
|
|
if (!stdev) {
|
2024-03-19 23:52:27 +00:00
|
|
|
return 0;
|
2024-05-23 16:03:10 +01:00
|
|
|
}
|
2024-01-05 04:57:21 +00:00
|
|
|
const u = 1 - Phaser.Math.RND.realInRange(0, 1);
|
|
|
|
const v = Phaser.Math.RND.realInRange(0, 1);
|
|
|
|
const z = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v);
|
|
|
|
return z * stdev + mean;
|
2023-10-27 02:42:53 +01:00
|
|
|
}
|
|
|
|
|
2023-03-28 19:54:52 +01:00
|
|
|
export function padInt(value: integer, length: integer, padWith?: string): string {
|
2024-05-23 16:03:10 +01:00
|
|
|
if (!padWith) {
|
|
|
|
padWith = "0";
|
|
|
|
}
|
2023-03-28 19:54:52 +01:00
|
|
|
let valueStr = value.toString();
|
2024-05-23 16:03:10 +01:00
|
|
|
while (valueStr.length < length) {
|
2023-03-28 19:54:52 +01:00
|
|
|
valueStr = `${padWith}${valueStr}`;
|
2024-05-23 16:03:10 +01:00
|
|
|
}
|
2023-03-28 19:54:52 +01:00
|
|
|
return valueStr;
|
|
|
|
}
|
|
|
|
|
2024-05-05 04:16:59 +01:00
|
|
|
/**
|
|
|
|
* Returns a random integer between min and min + range
|
|
|
|
* @param range The amount of possible numbers
|
|
|
|
* @param min The starting number
|
|
|
|
*/
|
2024-01-03 02:31:59 +00:00
|
|
|
export function randInt(range: integer, min: integer = 0): integer {
|
2024-05-23 16:03:10 +01:00
|
|
|
if (range === 1) {
|
2023-05-18 16:11:06 +01:00
|
|
|
return min;
|
2024-05-23 16:03:10 +01:00
|
|
|
}
|
2023-03-28 19:54:52 +01:00
|
|
|
return Math.floor(Math.random() * range) + min;
|
|
|
|
}
|
|
|
|
|
2024-01-03 02:31:59 +00:00
|
|
|
export function randSeedInt(range: integer, min: integer = 0): integer {
|
2024-05-23 16:03:10 +01:00
|
|
|
if (range <= 1) {
|
2023-10-18 23:01:15 +01:00
|
|
|
return min;
|
2024-05-23 16:03:10 +01:00
|
|
|
}
|
2023-10-18 23:01:15 +01:00
|
|
|
return Phaser.Math.RND.integerInRange(min, (range - 1) + min);
|
|
|
|
}
|
|
|
|
|
2024-05-05 04:16:59 +01:00
|
|
|
/**
|
|
|
|
* Returns a random integer between min and max (non-inclusive)
|
|
|
|
* @param min The lowest number
|
|
|
|
* @param max The highest number
|
|
|
|
*/
|
2023-10-04 22:24:28 +01:00
|
|
|
export function randIntRange(min: integer, max: integer): integer {
|
|
|
|
return randInt(max - min, min);
|
|
|
|
}
|
|
|
|
|
2024-03-21 18:53:35 +00:00
|
|
|
export function randItem<T>(items: T[]): T {
|
|
|
|
return items.length === 1
|
|
|
|
? items[0]
|
|
|
|
: items[randInt(items.length)];
|
|
|
|
}
|
|
|
|
|
2024-02-17 05:40:03 +00:00
|
|
|
export function randSeedItem<T>(items: T[]): T {
|
|
|
|
return items.length === 1
|
|
|
|
? items[0]
|
|
|
|
: Phaser.Math.RND.pick(items);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function randSeedWeightedItem<T>(items: T[]): T {
|
|
|
|
return items.length === 1
|
|
|
|
? items[0]
|
|
|
|
: Phaser.Math.RND.weightedPick(items);
|
|
|
|
}
|
|
|
|
|
2024-05-23 16:03:10 +01:00
|
|
|
export function randSeedEasedWeightedItem<T>(items: T[], easingFunction: string = "Sine.easeIn"): T {
|
|
|
|
if (!items.length) {
|
2024-04-02 05:48:13 +01:00
|
|
|
return null;
|
2024-05-23 16:03:10 +01:00
|
|
|
}
|
|
|
|
if (items.length === 1) {
|
2024-04-02 05:48:13 +01:00
|
|
|
return items[0];
|
2024-05-23 16:03:10 +01:00
|
|
|
}
|
2024-04-02 05:48:13 +01:00
|
|
|
const value = Phaser.Math.RND.realInRange(0, 1);
|
|
|
|
const easedValue = Phaser.Tweens.Builders.GetEaseFunction(easingFunction)(value);
|
|
|
|
return items[Math.floor(easedValue * items.length)];
|
|
|
|
}
|
|
|
|
|
2024-06-07 04:01:13 +01:00
|
|
|
/**
|
|
|
|
* Shuffle a list using the seeded rng. Utilises the Fisher-Yates algorithm.
|
|
|
|
* @param {Array} items An array of items.
|
|
|
|
* @returns {Array} A new shuffled array of items.
|
|
|
|
*/
|
|
|
|
export function randSeedShuffle<T>(items: T[]): T[] {
|
|
|
|
if (items.length <= 1) {
|
|
|
|
return items;
|
|
|
|
}
|
|
|
|
const newArray = items.slice(0);
|
|
|
|
for (let i = items.length - 1; i > 0; i--) {
|
|
|
|
const j = Phaser.Math.RND.integerInRange(0, i);
|
|
|
|
[newArray[i], newArray[j]] = [newArray[j], newArray[i]];
|
|
|
|
}
|
|
|
|
return newArray;
|
|
|
|
}
|
|
|
|
|
2023-06-05 02:47:43 +01:00
|
|
|
export function getFrameMs(frameCount: integer): integer {
|
|
|
|
return Math.floor((1 / 60) * 1000 * frameCount);
|
|
|
|
}
|
|
|
|
|
2023-12-30 02:04:40 +00:00
|
|
|
export function getCurrentTime(): number {
|
|
|
|
const date = new Date();
|
|
|
|
return (((date.getHours() * 60 + date.getMinutes()) / 1440) + 0.675) % 1;
|
|
|
|
}
|
|
|
|
|
2024-01-12 01:27:50 +00:00
|
|
|
const secondsInHour = 3600;
|
|
|
|
|
|
|
|
export function getPlayTimeString(totalSeconds: integer): string {
|
|
|
|
const days = `${Math.floor(totalSeconds / (secondsInHour * 24))}`;
|
|
|
|
const hours = `${Math.floor(totalSeconds % (secondsInHour * 24) / secondsInHour)}`;
|
|
|
|
const minutes = `${Math.floor(totalSeconds % secondsInHour / 60)}`;
|
|
|
|
const seconds = `${Math.floor(totalSeconds % 60)}`;
|
|
|
|
|
2024-05-23 16:03:10 +01:00
|
|
|
return `${days.padStart(2, "0")}:${hours.padStart(2, "0")}:${minutes.padStart(2, "0")}:${seconds.padStart(2, "0")}`;
|
2024-01-12 01:27:50 +00:00
|
|
|
}
|
|
|
|
|
2023-03-28 19:54:52 +01:00
|
|
|
export function binToDec(input: string): integer {
|
2024-05-24 00:45:04 +01:00
|
|
|
const place: integer[] = [];
|
2024-05-23 16:03:10 +01:00
|
|
|
const binary: string[] = [];
|
2024-05-24 00:45:04 +01:00
|
|
|
|
2023-03-28 19:54:52 +01:00
|
|
|
let decimalNum = 0;
|
2024-05-24 00:45:04 +01:00
|
|
|
|
2023-03-28 19:54:52 +01:00
|
|
|
for (let i = 0; i < input.length; i++) {
|
|
|
|
binary.push(input[i]);
|
|
|
|
place.push(Math.pow(2, i));
|
|
|
|
decimalNum += place[i] * parseInt(binary[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return decimalNum;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function decToBin(input: integer): string {
|
2024-05-23 16:03:10 +01:00
|
|
|
let bin = "";
|
2023-03-28 19:54:52 +01:00
|
|
|
let intNum = input;
|
|
|
|
while (intNum > 0) {
|
|
|
|
bin = intNum % 2 ? `1${bin}` : `0${bin}`;
|
|
|
|
intNum = Math.floor(intNum * 0.5);
|
|
|
|
}
|
|
|
|
|
|
|
|
return bin;
|
|
|
|
}
|
|
|
|
|
2024-03-29 04:03:54 +00:00
|
|
|
export function getIvsFromId(id: integer): integer[] {
|
|
|
|
return [
|
|
|
|
binToDec(decToBin(id).substring(0, 5)),
|
|
|
|
binToDec(decToBin(id).substring(5, 10)),
|
|
|
|
binToDec(decToBin(id).substring(10, 15)),
|
|
|
|
binToDec(decToBin(id).substring(15, 20)),
|
|
|
|
binToDec(decToBin(id).substring(20, 25)),
|
|
|
|
binToDec(decToBin(id).substring(25, 30))
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2024-03-15 19:13:32 +00:00
|
|
|
export function formatLargeNumber(count: integer, threshold: integer): string {
|
2024-05-23 16:03:10 +01:00
|
|
|
if (count < threshold) {
|
2024-03-15 19:13:32 +00:00
|
|
|
return count.toString();
|
2024-05-23 16:03:10 +01:00
|
|
|
}
|
|
|
|
const ret = count.toString();
|
|
|
|
let suffix = "";
|
2024-02-29 20:25:15 +00:00
|
|
|
switch (Math.ceil(ret.length / 3) - 1) {
|
2024-05-23 16:03:10 +01:00
|
|
|
case 1:
|
|
|
|
suffix = "K";
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
suffix = "M";
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
suffix = "B";
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
suffix = "T";
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
suffix = "q";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return "?";
|
2024-02-29 20:25:15 +00:00
|
|
|
}
|
|
|
|
const digits = ((ret.length + 2) % 3) + 1;
|
2024-05-14 21:12:31 +01:00
|
|
|
let decimalNumber = ret.slice(digits, digits + 2);
|
2024-05-23 16:03:10 +01:00
|
|
|
while (decimalNumber.endsWith("0")) {
|
|
|
|
decimalNumber = decimalNumber.slice(0, -1);
|
|
|
|
}
|
|
|
|
return `${ret.slice(0, digits)}${decimalNumber ? `.${decimalNumber}` : ""}${suffix}`;
|
2024-02-29 20:25:15 +00:00
|
|
|
}
|
|
|
|
|
2024-05-27 12:58:20 +01:00
|
|
|
// Abbreviations from 10^0 to 10^33
|
|
|
|
const AbbreviationsLargeNumber: string[] = ["", "K", "M", "B", "t", "q", "Q", "s", "S", "o", "n", "d"];
|
|
|
|
|
2024-06-08 02:09:12 +01:00
|
|
|
export function formatFancyLargeNumber(number: number, rounded: number = 3): string {
|
2024-05-27 12:58:20 +01:00
|
|
|
let exponent: number;
|
|
|
|
|
|
|
|
if (number < 1000) {
|
|
|
|
exponent = 0;
|
|
|
|
} else {
|
|
|
|
const maxExp = AbbreviationsLargeNumber.length - 1;
|
|
|
|
|
|
|
|
exponent = Math.floor(Math.log(number) / Math.log(1000));
|
|
|
|
exponent = Math.min(exponent, maxExp);
|
|
|
|
|
|
|
|
number /= Math.pow(1000, exponent);
|
|
|
|
}
|
|
|
|
|
2024-06-08 02:09:12 +01:00
|
|
|
return `${(exponent === 0) || number % 1 === 0 ? number : number.toFixed(rounded)}${AbbreviationsLargeNumber[exponent]}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function formatMoney(format: MoneyFormat, amount: number) {
|
|
|
|
if (format === MoneyFormat.ABBREVIATED) {
|
|
|
|
return formatFancyLargeNumber(amount);
|
|
|
|
}
|
|
|
|
return amount.toLocaleString();
|
2024-05-27 12:58:20 +01:00
|
|
|
}
|
|
|
|
|
2024-03-15 19:13:32 +00:00
|
|
|
export function formatStat(stat: integer, forHp: boolean = false): string {
|
|
|
|
return formatLargeNumber(stat, forHp ? 100000 : 1000000);
|
|
|
|
}
|
|
|
|
|
2023-04-11 18:00:04 +01:00
|
|
|
export function getEnumKeys(enumType): string[] {
|
|
|
|
return Object.values(enumType).filter(v => isNaN(parseInt(v.toString()))).map(v => v.toString());
|
|
|
|
}
|
|
|
|
|
|
|
|
export function getEnumValues(enumType): integer[] {
|
2023-03-28 19:54:52 +01:00
|
|
|
return Object.values(enumType).filter(v => !isNaN(parseInt(v.toString()))).map(v => parseInt(v.toString()));
|
|
|
|
}
|
|
|
|
|
2023-10-31 18:09:33 +00:00
|
|
|
export function executeIf<T>(condition: boolean, promiseFunc: () => Promise<T>): Promise<T> {
|
|
|
|
return condition ? promiseFunc() : new Promise<T>(resolve => resolve(null));
|
|
|
|
}
|
|
|
|
|
2024-05-23 16:03:10 +01:00
|
|
|
export const sessionIdKey = "pokerogue_sessionId";
|
2024-05-27 16:20:25 +01:00
|
|
|
// Check if the current hostname is 'localhost' or an IP address, and ensure a port is specified
|
|
|
|
export const isLocal = (
|
|
|
|
(window.location.hostname === "localhost" ||
|
|
|
|
/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/.test(window.location.hostname)) &&
|
|
|
|
window.location.port !== "") || window.location.hostname === "";
|
|
|
|
|
2024-06-07 21:43:32 +01:00
|
|
|
export const localServerUrl = import.meta.env.VITE_SERVER_URL ?? `http://${window.location.hostname}:${window.location.port+1}`;
|
|
|
|
|
2024-05-27 16:20:25 +01:00
|
|
|
// Set the server URL based on whether it's local or not
|
2024-06-07 21:43:32 +01:00
|
|
|
export const serverUrl = isLocal ? localServerUrl : "";
|
2024-05-23 16:03:10 +01:00
|
|
|
export const apiUrl = isLocal ? serverUrl : "https://api.pokerogue.net";
|
2024-06-06 02:24:47 +01:00
|
|
|
// used to disable api calls when isLocal is true and a server is not found
|
2024-06-08 00:43:21 +01:00
|
|
|
export let isLocalServerConnected = true;
|
2023-12-30 23:41:25 +00:00
|
|
|
|
|
|
|
export function setCookie(cName: string, cValue: string): void {
|
2024-04-10 05:29:03 +01:00
|
|
|
const expiration = new Date();
|
2024-05-05 23:13:19 +01:00
|
|
|
expiration.setTime(new Date().getTime() + 3600000 * 24 * 30 * 3/*7*/);
|
2024-06-09 02:03:33 +01:00
|
|
|
document.cookie = `${cName}=${cValue};Secure;SameSite=Strict;Path=/;Expires=${expiration.toUTCString()}`;
|
2023-12-30 23:41:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export function getCookie(cName: string): string {
|
|
|
|
const name = `${cName}=`;
|
2024-05-23 16:03:10 +01:00
|
|
|
const ca = document.cookie.split(";");
|
2023-12-30 23:41:25 +00:00
|
|
|
for (let i = 0; i < ca.length; i++) {
|
|
|
|
let c = ca[i];
|
2024-05-23 16:03:10 +01:00
|
|
|
while (c.charAt(0) === " ") {
|
2023-12-30 23:41:25 +00:00
|
|
|
c = c.substring(1);
|
2024-05-23 16:03:10 +01:00
|
|
|
}
|
|
|
|
if (c.indexOf(name) === 0) {
|
2023-12-30 23:41:25 +00:00
|
|
|
return c.substring(name.length, c.length);
|
2024-05-23 16:03:10 +01:00
|
|
|
}
|
2023-12-30 23:41:25 +00:00
|
|
|
}
|
2024-05-23 16:03:10 +01:00
|
|
|
return "";
|
2023-12-30 23:41:25 +00:00
|
|
|
}
|
|
|
|
|
2024-06-06 02:24:47 +01:00
|
|
|
/**
|
|
|
|
* When locally running the game, "pings" the local server
|
|
|
|
* with a GET request to verify if a server is running,
|
|
|
|
* sets isLocalServerConnected based on results
|
|
|
|
*/
|
|
|
|
export function localPing() {
|
|
|
|
if (isLocal) {
|
|
|
|
apiFetch("game/titlestats")
|
|
|
|
.then(resolved => isLocalServerConnected = true,
|
|
|
|
rejected => isLocalServerConnected = false
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-10 04:44:09 +01:00
|
|
|
export function apiFetch(path: string, authed: boolean = false): Promise<Response> {
|
2024-06-06 02:24:47 +01:00
|
|
|
return (isLocal && isLocalServerConnected) || !isLocal ? new Promise((resolve, reject) => {
|
2024-04-19 22:35:49 +01:00
|
|
|
const request = {};
|
|
|
|
if (authed) {
|
|
|
|
const sId = getCookie(sessionIdKey);
|
2024-05-23 16:03:10 +01:00
|
|
|
if (sId) {
|
|
|
|
request["headers"] = { "Authorization": sId };
|
|
|
|
}
|
2024-04-19 22:35:49 +01:00
|
|
|
}
|
2024-05-10 04:44:09 +01:00
|
|
|
fetch(`${apiUrl}/${path}`, request)
|
|
|
|
.then(response => resolve(response))
|
|
|
|
.catch(err => reject(err));
|
2024-06-06 02:24:47 +01:00
|
|
|
}) : new Promise(() => {});
|
2023-12-30 23:41:25 +00:00
|
|
|
}
|
|
|
|
|
2024-05-23 16:03:10 +01:00
|
|
|
export function apiPost(path: string, data?: any, contentType: string = "application/json", authed: boolean = false): Promise<Response> {
|
2024-06-06 02:24:47 +01:00
|
|
|
return (isLocal && isLocalServerConnected) || !isLocal ? new Promise((resolve, reject) => {
|
2023-12-30 23:41:25 +00:00
|
|
|
const headers = {
|
2024-05-23 16:03:10 +01:00
|
|
|
"Accept": contentType,
|
|
|
|
"Content-Type": contentType,
|
2023-12-30 23:41:25 +00:00
|
|
|
};
|
2024-04-25 00:08:02 +01:00
|
|
|
if (authed) {
|
|
|
|
const sId = getCookie(sessionIdKey);
|
2024-05-23 16:03:10 +01:00
|
|
|
if (sId) {
|
|
|
|
headers["Authorization"] = sId;
|
|
|
|
}
|
2024-04-25 00:08:02 +01:00
|
|
|
}
|
2024-05-23 16:03:10 +01:00
|
|
|
fetch(`${apiUrl}/${path}`, { method: "POST", headers: headers, body: data })
|
2023-12-30 23:41:25 +00:00
|
|
|
.then(response => resolve(response))
|
2024-05-10 04:44:09 +01:00
|
|
|
.catch(err => reject(err));
|
2024-06-06 02:24:47 +01:00
|
|
|
}) : new Promise(() => {});
|
2023-12-30 23:41:25 +00:00
|
|
|
}
|
|
|
|
|
2023-04-13 00:09:15 +01:00
|
|
|
export class BooleanHolder {
|
|
|
|
public value: boolean;
|
|
|
|
|
|
|
|
constructor(value: boolean) {
|
|
|
|
this.value = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-31 04:02:35 +01:00
|
|
|
export class NumberHolder {
|
|
|
|
public value: number;
|
|
|
|
|
|
|
|
constructor(value: number) {
|
|
|
|
this.value = value;
|
|
|
|
}
|
|
|
|
}
|
2023-04-12 16:30:47 +01:00
|
|
|
|
2023-11-12 05:31:40 +00:00
|
|
|
export class IntegerHolder extends NumberHolder {
|
2023-03-28 19:54:52 +01:00
|
|
|
constructor(value: integer) {
|
2023-11-12 05:31:40 +00:00
|
|
|
super(value);
|
2023-03-28 19:54:52 +01:00
|
|
|
}
|
2023-04-12 16:30:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export class FixedInt extends IntegerHolder {
|
|
|
|
constructor(value: integer) {
|
|
|
|
super(value);
|
|
|
|
}
|
2023-10-26 04:15:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export function fixedInt(value: integer): integer {
|
|
|
|
return new FixedInt(value) as unknown as integer;
|
2023-11-24 04:52:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export function rgbToHsv(r: integer, g: integer, b: integer) {
|
2024-05-23 16:03:10 +01:00
|
|
|
const v = Math.max(r, g, b);
|
|
|
|
const c = v - Math.min(r, g, b);
|
2024-05-24 00:45:04 +01:00
|
|
|
const h = c && ((v === r) ? (g - b) / c : ((v === g) ? 2 + (b - r) / c : 4 + (r - g) / c));
|
2023-11-24 04:52:13 +00:00
|
|
|
return [ 60 * (h < 0 ? h + 6 : h), v && c / v, v];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Compare color difference in RGB
|
|
|
|
* @param {Array} rgb1 First RGB color in array
|
|
|
|
* @param {Array} rgb2 Second RGB color in array
|
|
|
|
*/
|
|
|
|
export function deltaRgb(rgb1: integer[], rgb2: integer[]): integer {
|
|
|
|
const [ r1, g1, b1 ] = rgb1;
|
|
|
|
const [ r2, g2, b2 ] = rgb2;
|
|
|
|
const drp2 = Math.pow(r1 - r2, 2);
|
|
|
|
const dgp2 = Math.pow(g1 - g2, 2);
|
|
|
|
const dbp2 = Math.pow(b1 - b2, 2);
|
|
|
|
const t = (r1 + r2) / 2;
|
|
|
|
|
|
|
|
return Math.ceil(Math.sqrt(2 * drp2 + 4 * dgp2 + 3 * dbp2 + t * (drp2 - dbp2) / 256));
|
2024-04-13 23:59:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export function rgbHexToRgba(hex: string) {
|
|
|
|
const color = hex.match(/^([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i);
|
|
|
|
return {
|
2024-05-23 16:03:10 +01:00
|
|
|
r: parseInt(color[1], 16),
|
|
|
|
g: parseInt(color[2], 16),
|
|
|
|
b: parseInt(color[3], 16),
|
|
|
|
a: 255
|
2024-04-13 23:59:58 +01:00
|
|
|
};
|
2024-04-19 03:52:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export function rgbaToInt(rgba: integer[]): integer {
|
|
|
|
return (rgba[0] << 24) + (rgba[1] << 16) + (rgba[2] << 8) + rgba[3];
|
2024-05-23 16:03:10 +01:00
|
|
|
}
|
2024-05-27 09:39:18 +01:00
|
|
|
|
|
|
|
/*This function returns true if the current lang is available for some functions
|
|
|
|
If the lang is not in the function, it usually means that lang is going to use the default english version
|
|
|
|
This function is used in:
|
|
|
|
- summary-ui-handler.ts: If the lang is not available, it'll use types.json (english)
|
|
|
|
English itself counts as not available
|
|
|
|
*/
|
|
|
|
export function verifyLang(lang?: string): boolean {
|
|
|
|
//IMPORTANT - ONLY ADD YOUR LANG HERE IF YOU'VE ALREADY ADDED ALL THE NECESSARY IMAGES
|
|
|
|
if (!lang) {
|
2024-06-04 21:11:02 +01:00
|
|
|
lang = i18next.resolvedLanguage;
|
2024-05-27 09:39:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (lang) {
|
|
|
|
case "es":
|
|
|
|
case "fr":
|
|
|
|
case "de":
|
|
|
|
case "it":
|
|
|
|
case "zh_CN":
|
|
|
|
case "zh_TW":
|
|
|
|
case "pt_BR":
|
2024-05-31 15:34:26 +01:00
|
|
|
case "ko":
|
2024-05-27 09:39:18 +01:00
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2024-05-30 16:27:17 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Prints the type and name of all game objects in a container for debuggin purposes
|
|
|
|
* @param container container with game objects inside it
|
|
|
|
*/
|
|
|
|
export function printContainerList(container: Phaser.GameObjects.Container): void {
|
|
|
|
console.log(container.list.map(go => {
|
|
|
|
return {type: go.type, name: go.name};
|
|
|
|
}));
|
|
|
|
}
|
2024-06-01 13:56:32 +01:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Truncate a string to a specified maximum length and add an ellipsis if it exceeds that length.
|
|
|
|
*
|
|
|
|
* @param str - The string to be truncated.
|
|
|
|
* @param maxLength - The maximum length of the truncated string, defaults to 10.
|
|
|
|
* @returns The truncated string with an ellipsis if it was longer than maxLength.
|
|
|
|
*/
|
|
|
|
export function truncateString(str: String, maxLength: number = 10) {
|
|
|
|
// Check if the string length exceeds the maximum length
|
|
|
|
if (str.length > maxLength) {
|
|
|
|
// Truncate the string and add an ellipsis
|
|
|
|
return str.slice(0, maxLength - 3) + "..."; // Subtract 3 to accommodate the ellipsis
|
|
|
|
}
|
|
|
|
// Return the original string if it does not exceed the maximum length
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Perform a deep copy of an object.
|
|
|
|
*
|
|
|
|
* @param values - The object to be deep copied.
|
|
|
|
* @returns A new object that is a deep copy of the input.
|
|
|
|
*/
|
|
|
|
export function deepCopy(values: object): object {
|
|
|
|
// Convert the object to a JSON string and parse it back to an object to perform a deep copy
|
|
|
|
return JSON.parse(JSON.stringify(values));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convert a space-separated string into a capitalized and underscored string.
|
|
|
|
*
|
|
|
|
* @param input - The string to be converted.
|
|
|
|
* @returns The converted string with words capitalized and separated by underscores.
|
|
|
|
*/
|
|
|
|
export function reverseValueToKeySetting(input) {
|
|
|
|
// Split the input string into an array of words
|
|
|
|
const words = input.split(" ");
|
|
|
|
// Capitalize the first letter of each word and convert the rest to lowercase
|
|
|
|
const capitalizedWords = words.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());
|
|
|
|
// Join the capitalized words with underscores and return the result
|
|
|
|
return capitalizedWords.join("_");
|
|
|
|
}
|
|
|
|
|
|
|
|
|