You've already forked Nitro_Render_V3
mirror of
https://github.com/duckietm/Nitro_Render_V3.git
synced 2026-06-19 15:06:20 +00:00
Move to Renderer V2
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": [ "@nitrots/eslint-config" ]
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# compiled output
|
||||
/dist
|
||||
/tmp
|
||||
/out-tsc
|
||||
# Only exists if Bazel was run
|
||||
/bazel-out
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# profiling files
|
||||
chrome-profiler-events*.json
|
||||
speed-measure-plugin*.json
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# IDE - VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.history/*
|
||||
|
||||
# misc
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
testem.log
|
||||
/typings
|
||||
.git
|
||||
|
||||
# System Files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
*.zip
|
||||
*.as
|
||||
*.bin
|
||||
@@ -0,0 +1 @@
|
||||
export * from './src';
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "@nitrots/localization",
|
||||
"description": "Nitro localization module",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"license": "GPL-3.0",
|
||||
"scripts": {
|
||||
"compile": "tsc --project ./tsconfig.json --noEmit false",
|
||||
"eslint": "eslint ./src --fix"
|
||||
},
|
||||
"main": "./index",
|
||||
"dependencies": {
|
||||
"@nitrots/api": "1.0.0",
|
||||
"@nitrots/communication": "1.0.0",
|
||||
"@nitrots/configuration": "1.0.0",
|
||||
"@nitrots/eslint-config": "1.0.0",
|
||||
"@nitrots/events": "1.0.0",
|
||||
"pixi.js": "^8.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "~5.4.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
export class BadgeBaseAndLevel
|
||||
{
|
||||
private _badgeId: string = '';
|
||||
private _level: number = 1;
|
||||
private _base: string = '';
|
||||
|
||||
constructor(badgeId: string)
|
||||
{
|
||||
this._badgeId = badgeId;
|
||||
|
||||
this.parseText();
|
||||
}
|
||||
|
||||
private parseText():void
|
||||
{
|
||||
let length = (this._badgeId.length - 1);
|
||||
|
||||
while(length > 0 && this.isNumber(this._badgeId.charAt(length))) length--;
|
||||
|
||||
this._base = this._badgeId.substr(0, (length + 1));
|
||||
|
||||
const level = this._badgeId.substr((length + 1), this._badgeId.length);
|
||||
|
||||
if(level && (level !== '')) this._level = Number.parseInt(level);
|
||||
}
|
||||
|
||||
private isNumber(text: string): boolean
|
||||
{
|
||||
const char = text.charCodeAt(0);
|
||||
|
||||
return (char >= 48 && char <= 57);
|
||||
}
|
||||
|
||||
public get level(): number
|
||||
{
|
||||
return this._level;
|
||||
}
|
||||
|
||||
public set level(k : number)
|
||||
{
|
||||
this._level = Math.max(1, k);
|
||||
}
|
||||
|
||||
public get getBadgeId(): string
|
||||
{
|
||||
return this._base + this._level;
|
||||
}
|
||||
|
||||
public get base(): string
|
||||
{
|
||||
return this._base;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { LocalizationManager } from './LocalizationManager';
|
||||
|
||||
const localization = new LocalizationManager();
|
||||
|
||||
export const GetLocalizationManager = () => localization;
|
||||
@@ -0,0 +1,304 @@
|
||||
import { ILocalizationManager } from '@nitrots/api';
|
||||
import { BadgePointLimitsEvent, GetCommunication } from '@nitrots/communication';
|
||||
import { GetConfiguration } from '@nitrots/configuration';
|
||||
import { BadgeBaseAndLevel } from './BadgeBaseAndLevel';
|
||||
|
||||
export class LocalizationManager implements ILocalizationManager
|
||||
{
|
||||
private _definitions: Map<string, string> = new Map();
|
||||
private _parameters: Map<string, Map<string, string>> = new Map();
|
||||
private _badgePointLimits: Map<string, number> = new Map();
|
||||
private _romanNumerals: string[] = [ 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X', 'XI', 'XII', 'XIII', 'XIV', 'XV', 'XVI', 'XVII', 'XVIII', 'XIX', 'XX', 'XXI', 'XXII', 'XXIII', 'XXIV', 'XXV', 'XXVI', 'XXVII', 'XXVIII', 'XXIX', 'XXX' ];
|
||||
|
||||
public async init(): Promise<void>
|
||||
{
|
||||
try
|
||||
{
|
||||
const urls = GetConfiguration().getValue<string[]>('external.texts.url').slice();
|
||||
|
||||
if(!urls || !urls.length) throw new Error('Invalid localization urls');
|
||||
|
||||
for(let url of urls)
|
||||
{
|
||||
if(!url || !url.length) return;
|
||||
|
||||
url = GetConfiguration().interpolate(url);
|
||||
|
||||
const response = await fetch(url);
|
||||
|
||||
if(response.status !== 200) throw new Error('Invalid localization file');
|
||||
|
||||
this.parseLocalization(await response.json());
|
||||
}
|
||||
|
||||
GetCommunication().registerMessageEvent(new BadgePointLimitsEvent(this.onBadgePointLimitsEvent.bind(this)));
|
||||
}
|
||||
|
||||
catch (err)
|
||||
{
|
||||
throw new Error(err);
|
||||
}
|
||||
}
|
||||
|
||||
private parseLocalization(data: { [index: string]: any }): boolean
|
||||
{
|
||||
if(!data) return false;
|
||||
|
||||
for(const key in data) this._definitions.set(key, data[key]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private onBadgePointLimitsEvent(event: BadgePointLimitsEvent): void
|
||||
{
|
||||
const parser = event.getParser();
|
||||
|
||||
for(const data of parser.data) this.setBadgePointLimit(data.badgeId, data.limit);
|
||||
}
|
||||
|
||||
public getBadgePointLimit(badge: string): number
|
||||
{
|
||||
return (this._badgePointLimits.get(badge) || -1);
|
||||
}
|
||||
|
||||
public setBadgePointLimit(badge: string, point: number): void
|
||||
{
|
||||
this._badgePointLimits.set(badge, point);
|
||||
}
|
||||
|
||||
public getRomanNumeral(number: number): string
|
||||
{
|
||||
return this._romanNumerals[Math.max(0, (number - 1))];
|
||||
}
|
||||
|
||||
public getPreviousLevelBadgeId(badgeName: string): string
|
||||
{
|
||||
const badge = new BadgeBaseAndLevel(badgeName);
|
||||
|
||||
badge.level--;
|
||||
|
||||
return badge.getBadgeId;
|
||||
}
|
||||
|
||||
public hasValue(key: string): boolean
|
||||
{
|
||||
return this._definitions.has(key);
|
||||
}
|
||||
|
||||
public getValue(key: string, doParams: boolean = true): string
|
||||
{
|
||||
if(!key || !key.length) return null;
|
||||
|
||||
const keys = key.match(/\$\{.[^}]*\}/g);
|
||||
|
||||
if(keys && keys.length)
|
||||
{
|
||||
for(const splitKey of keys) key = key.replace(splitKey, this.getValue(splitKey.slice(2, -1), doParams));
|
||||
}
|
||||
|
||||
let value = (this._definitions.get(key) || null);
|
||||
|
||||
if(!value)
|
||||
{
|
||||
value = (GetConfiguration().definitions.get(key) as any);
|
||||
|
||||
if(value) return value;
|
||||
}
|
||||
|
||||
if(value && doParams)
|
||||
{
|
||||
const parameters = this._parameters.get(key);
|
||||
|
||||
if(parameters)
|
||||
{
|
||||
for(const [parameter, replacement] of parameters)
|
||||
{
|
||||
value = value.replace('%' + parameter + '%', replacement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (value || key);
|
||||
}
|
||||
|
||||
public getValueWithParameter(key: string, parameter: string, replacement: string): string
|
||||
{
|
||||
const value = this.getValue(key, false);
|
||||
|
||||
const replacedValue = value.replace('%' + parameter + '%', replacement);
|
||||
|
||||
if(value.startsWith('%{'))
|
||||
{
|
||||
// This adds support for multi-optioned texts like
|
||||
// catalog.vip.item.header.months=%{NUM_MONTHS|0 months|1 month|%% months}
|
||||
// It only checks for this multi-optioned thext if the value of the key starts with %{
|
||||
|
||||
// If it does, it will create a RegEx with the provided parameter, eg. NUM_DAYS or NUM_MONTS
|
||||
// Then, based on the provided replacement it searches for the resultgroup based on the replacement.
|
||||
// If the replacement is not either 0, 1 - it will be assumed it will be plural. (eg. Months)
|
||||
const regex = new RegExp('%{' + parameter.toUpperCase() + '\\|([^|]*)\\|([^|]*)\\|([^|]*)}');
|
||||
const result = value.match(regex);
|
||||
|
||||
if(!result) return replacedValue;
|
||||
|
||||
let indexKey = -1;
|
||||
const replacementAsNumber = Number.parseInt(replacement);
|
||||
let replace = false;
|
||||
|
||||
switch(replacementAsNumber)
|
||||
{
|
||||
case 0:
|
||||
indexKey = 1;
|
||||
break;
|
||||
case 1:
|
||||
indexKey = 2;
|
||||
break;
|
||||
default:
|
||||
case 2:
|
||||
indexKey = 3;
|
||||
replace = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if(indexKey == -1 || typeof result[indexKey] == 'undefined')
|
||||
{
|
||||
return replacedValue;
|
||||
}
|
||||
|
||||
const valueFromResults = result[indexKey];
|
||||
|
||||
if(valueFromResults)
|
||||
{
|
||||
return valueFromResults.replace('%%', replacement);
|
||||
}
|
||||
}
|
||||
|
||||
return replacedValue;
|
||||
}
|
||||
|
||||
public getValueWithParameters(key: string, parameters: string[], replacements: string[]): string
|
||||
{
|
||||
let value = this.getValue(key, false);
|
||||
|
||||
if(parameters)
|
||||
{
|
||||
for(let i = 0; i < parameters.length; i++)
|
||||
{
|
||||
const parameter = parameters[i];
|
||||
const replacement = replacements[i];
|
||||
|
||||
if(replacement === undefined) continue;
|
||||
|
||||
value = value.replace('%' + parameter + '%', replacement);
|
||||
|
||||
if(value.startsWith('%{'))
|
||||
{
|
||||
const regex = new RegExp('%{' + parameter.toUpperCase() + '\\|([^|]*)\\|([^|]*)\\|([^|]*)}');
|
||||
const result = value.match(regex);
|
||||
|
||||
if(!result) continue;
|
||||
|
||||
const replacementAsNumber = parseInt(replacement);
|
||||
|
||||
let indexKey = -1;
|
||||
let replace = false;
|
||||
|
||||
switch(replacementAsNumber)
|
||||
{
|
||||
case 0:
|
||||
indexKey = 1;
|
||||
break;
|
||||
case 1:
|
||||
indexKey = 2;
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
indexKey = 3;
|
||||
replace = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if((indexKey === -1) || (typeof result[indexKey] === 'undefined')) continue;
|
||||
|
||||
const valueFromResults = result[indexKey];
|
||||
|
||||
if(valueFromResults)
|
||||
{
|
||||
value = valueFromResults.replace('%%', replacement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public setValue(key: string, value: string): void
|
||||
{
|
||||
this._definitions.set(key, value);
|
||||
}
|
||||
|
||||
public registerParameter(key: string, parameter: string, value: string): void
|
||||
{
|
||||
if(!key || (key.length === 0) || !parameter || (parameter.length === 0)) return;
|
||||
|
||||
let existing = this._parameters.get(key);
|
||||
|
||||
if(!existing)
|
||||
{
|
||||
existing = new Map();
|
||||
|
||||
this._parameters.set(key, existing);
|
||||
}
|
||||
|
||||
existing.set(parameter, value);
|
||||
}
|
||||
|
||||
public getBadgeName(key: string): string
|
||||
{
|
||||
const badge = new BadgeBaseAndLevel(key);
|
||||
const keys = ['badge_name_' + key, 'badge_name_' + badge.base];
|
||||
|
||||
let name = this.fixBadLocalization(this.getExistingKey(keys));
|
||||
|
||||
name = name.replace('%roman%', this.getRomanNumeral(badge.level));
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public getBadgeDesc(key: string): string
|
||||
{
|
||||
const badge = new BadgeBaseAndLevel(key);
|
||||
const keys = ['badge_desc_' + key, 'badge_desc_' + badge.base];
|
||||
|
||||
let desc = this.fixBadLocalization(this.getExistingKey(keys));
|
||||
|
||||
const limit = this.getBadgePointLimit(key);
|
||||
|
||||
if(limit > -1) desc = desc.replace('%limit%', limit.toString());
|
||||
|
||||
desc = desc.replace('%roman%', this.getRomanNumeral(badge.level));
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
private getExistingKey(keys: string[]): string
|
||||
{
|
||||
for(const entry of keys)
|
||||
{
|
||||
const item = this.getValue(entry);
|
||||
if(item != entry) return item;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
private fixBadLocalization(k: string): string
|
||||
{
|
||||
return k.replace('${', '$')
|
||||
.replace('{', '$')
|
||||
.replace('}', '$');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export * from './BadgeBaseAndLevel';
|
||||
export * from './GetLocalization';
|
||||
export * from './LocalizationManager';
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./src",
|
||||
"outDir": "./dist",
|
||||
"sourceMap": false,
|
||||
"declaration": true,
|
||||
"experimentalDecorators": true,
|
||||
"moduleResolution": "Node",
|
||||
"esModuleInterop": true,
|
||||
"importHelpers": true,
|
||||
"isolatedModules": true,
|
||||
"resolveJsonModule": true,
|
||||
"downlevelIteration": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"noEmit": true,
|
||||
"strict": false,
|
||||
"strictNullChecks": false,
|
||||
"target": "ES6",
|
||||
"lib": [
|
||||
"DOM",
|
||||
"DOM.Iterable",
|
||||
"ESNext"
|
||||
],
|
||||
"module": "ES6"
|
||||
},
|
||||
"include": [
|
||||
"src" ]
|
||||
}
|
||||
Reference in New Issue
Block a user