Even more work, need to refactor to deparser rather than constructor for models

This commit is contained in:
Tom Bloor 2019-12-23 13:05:31 +00:00
parent 4b222948ba
commit 8cf7cb66de
19 changed files with 2003 additions and 12 deletions

View file

@ -2,6 +2,8 @@
<dictionary name="Tom"> <dictionary name="Tom">
<words> <words>
<w>deparse</w> <w>deparse</w>
<w>gameplay</w>
<w>pegjs</w>
</words> </words>
</dictionary> </dictionary>
</component> </component>

18
package-lock.json generated
View file

@ -1916,6 +1916,11 @@
"integrity": "sha512-jRHfWsvyMtXdbhnz5CVHxaBgnV6duZnPlQuRSo/dm/GnmikNcmZhxIES4E9OZjUmQ8C+HCl4KJux+cXN/ErGDQ==", "integrity": "sha512-jRHfWsvyMtXdbhnz5CVHxaBgnV6duZnPlQuRSo/dm/GnmikNcmZhxIES4E9OZjUmQ8C+HCl4KJux+cXN/ErGDQ==",
"dev": true "dev": true
}, },
"@types/pegjs": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/@types/pegjs/-/pegjs-0.10.1.tgz",
"integrity": "sha512-ra8IchO9odGQmYKbm+94K58UyKCEKdZh9y0vxhG4pIpOJOBlC1C+ZtBVr6jLs+/oJ4pl+1p/4t3JtBA8J10Vvw=="
},
"@types/q": { "@types/q": {
"version": "0.0.32", "version": "0.0.32",
"resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz",
@ -8633,6 +8638,11 @@
"sha.js": "^2.4.8" "sha.js": "^2.4.8"
} }
}, },
"pegjs": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz",
"integrity": "sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0="
},
"performance-now": { "performance-now": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@ -10916,6 +10926,14 @@
"yn": "^2.0.0" "yn": "^2.0.0"
} }
}, },
"ts-pegjs": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/ts-pegjs/-/ts-pegjs-0.2.6.tgz",
"integrity": "sha512-mIX/dMQ6a1EHAEhvCLS6Z41+O700zlLiwB4V5ZSlKFLZKLDE93reik5IFw/HJsKgs488UiLx144yeEWWyu7YIw==",
"requires": {
"pegjs": "^0.10.0"
}
},
"tslib": { "tslib": {
"version": "1.10.0", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",

View file

@ -20,9 +20,11 @@
"@angular/platform-browser-dynamic": "~8.2.11", "@angular/platform-browser-dynamic": "~8.2.11",
"@angular/router": "~8.2.11", "@angular/router": "~8.2.11",
"@ng-bootstrap/ng-bootstrap": "^5.1.1", "@ng-bootstrap/ng-bootstrap": "^5.1.1",
"@types/pegjs": "^0.10.1",
"ace-builds": "^1.4.7", "ace-builds": "^1.4.7",
"bootstrap": "^4.3.1", "bootstrap": "^4.3.1",
"rxjs": "~6.4.0", "rxjs": "~6.4.0",
"ts-pegjs": "^0.2.6",
"tslib": "^1.10.0", "tslib": "^1.10.0",
"zone.js": "~0.9.1" "zone.js": "~0.9.1"
}, },

View file

@ -9,6 +9,7 @@ import { CodeEditorComponent } from './components/code-editor/code-editor.compon
import { ConfigComponent } from './pages/config/config.component'; import { ConfigComponent } from './pages/config/config.component';
import { FormsModule } from "@angular/forms"; import { FormsModule } from "@angular/forms";
import { Server } from "./server"; import { Server } from "./server";
import { PegjsService } from "./services/pegjs.service";
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -23,7 +24,7 @@ import { Server } from "./server";
NgbModule, NgbModule,
FormsModule FormsModule
], ],
providers: [Server], providers: [Server, PegjsService],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })
export class AppModule { export class AppModule {

View file

@ -0,0 +1,14 @@
import { ToJSON } from "../util/toJson";
export class BlueprintGeneratedClass implements ToJSON {
public texture: string;
constructor(raw: object) {
if( raw[0] !== 'BlueprintGeneratedClass') Error('wrong type, expecting BlueprintGeneratedClass, got [' + raw[0] + ']!');
this.texture = raw[1];
};
public toJSON(): object {
return [ 'BlueprintGeneratedClass', this.texture ];
}
}

View file

@ -0,0 +1,46 @@
import { Texture2D } from "./texture2D";
export class QuestEntry {
public QuestID: number;
public CompletedIcon: Texture2D;
public UncompletedIcon: Texture2D;
public QuestName: string;
public QuestDescription: string;
public UnlockFeatNames: Array<string>;
public CompleteGiveEngramClasses: object;
public QuestPointsOfInterest: Array<object>;
constructor(raw?: Partial<QuestEntry>) {
Object.assign(this, raw);
this.CompletedIcon = new Texture2D(raw.CompletedIcon);
this.UncompletedIcon = new Texture2D(raw.UncompletedIcon);
}
public toJSON() {
let output = {};
const JsonSubModels = [
'CompletedIcon',
'UncompletedIcon'
];
JsonSubModels.forEach(item => {
output[item] = this[item].toJSON();
});
const RawSubData = [
'QuestID',
'QuestName',
'QuestDescription',
'UnlockFeatNames',
'CompleteGiveEngramClasses',
'QuestPointsOfInterest'
];
RawSubData.forEach(item => {
output[item] = this[item];
});
return output;
}
}

View file

@ -0,0 +1,14 @@
import { ToJSON } from "../util/toJson";
export class Texture2D implements ToJSON {
public texture: string;
constructor(raw: object) {
if( raw[0] !== 'Texture2D') Error('wrong type, expecting Texture2D, got [' + raw[0] + ']!');
this.texture = raw[1];
};
public toJSON(): object {
return [ 'Texture2D', this.texture ];
}
}

View file

@ -0,0 +1,25 @@
import { PegjsService } from "../services/pegjs.service";
import { ToAtlas } from "./util/toAtlas";
import { QuestEntry } from "./atlasData/questEntry";
export class GlobalGameplaySetupModel implements ToAtlas {
public QuestEntries: Array<QuestEntry> = [];
constructor(raw: any = "()") {
const rawData = <object>PegjsService.parse(raw);
Object.assign(this, rawData);
let tempQuestEntries = [];
this.QuestEntries.forEach(item => {
tempQuestEntries.push(new QuestEntry(item));
});
this.QuestEntries = tempQuestEntries;
}
public toAtlas(): string {
const output = [];
this.QuestEntries.forEach(item => {
output.push(item.toJSON());
});
return PegjsService.format({QuestEntries: output});
}
}

View file

@ -1,8 +1,10 @@
import { TribeLogConfigModel } from "./tribeLogConfig.model"; import { TribeLogConfigModel } from "./tribeLogConfig.model";
import { SharedLogConfigModel } from "./sharedLogConfig.model"; import { SharedLogConfigModel } from "./sharedLogConfig.model";
import { TravelDataConfigModel } from "./travelDataConfig.model"; import { TravelDataConfigModel } from "./travelDataConfig.model";
import { ToJSON } from "./util/toJson";
import { GlobalGameplaySetupModel } from "./GlobalGameplaySetupModel";
export class ServerGridModel { export class ServerGridModel implements ToJSON {
// Server Argument Section // Server Argument Section
public BaseServerArgs: string = ""; public BaseServerArgs: string = "";
public AdditionalCmdLineParams: string = ""; public AdditionalCmdLineParams: string = "";
@ -51,21 +53,106 @@ export class ServerGridModel {
public LocalS3Region: string = ""; public LocalS3Region: string = "";
// Unsorted... // Unsorted...
public globalGameplaySetup: string = "";
public shipPathsIdGenerator: number = 1; public shipPathsIdGenerator: number = 1;
public idGenerator: number = 127; public idGenerator: number = 127;
public regionsIdGenerator: number = 0; public regionsIdGenerator: number = 0;
// Log Configs // Log Configs
public TribeLogConfig: TribeLogConfigModel; public TribeLogConfig: TribeLogConfigModel = new TribeLogConfigModel();
public SharedLogConfig: SharedLogConfigModel; public SharedLogConfig: SharedLogConfigModel = new SharedLogConfigModel();
public TravelDataConfig: TravelDataConfigModel; public TravelDataConfig: TravelDataConfigModel = new TravelDataConfigModel();
constructor(raw?:Partial<ServerGridModel>) { // Large Objects of Doom
public globalGameplaySetup: GlobalGameplaySetupModel = new GlobalGameplaySetupModel();
constructor(raw?: Partial<ServerGridModel>) {
Object.assign(this, raw); Object.assign(this, raw);
this.SharedLogConfig = new SharedLogConfigModel(raw.SharedLogConfig); this.SharedLogConfig = new SharedLogConfigModel(raw.SharedLogConfig);
this.TribeLogConfig = new TribeLogConfigModel(raw.TribeLogConfig); this.TribeLogConfig = new TribeLogConfigModel(raw.TribeLogConfig);
this.TravelDataConfig = new TravelDataConfigModel(raw.TravelDataConfig); this.TravelDataConfig = new TravelDataConfigModel(raw.TravelDataConfig);
this.globalGameplaySetup = new GlobalGameplaySetupModel(raw.globalGameplaySetup);
console.log(this); console.log(this);
} }
public toJSON() {
let output = {};
// All full models of this object for deflation
const JsonSubModels = [
'SharedLogConfig',
'TribeLogConfig',
'TravelDataConfig',
];
JsonSubModels.forEach(item => {
output[item] = this[item].toJSON();
});
const AtlasSubModels = [
'globalGameplaySetup'
];
AtlasSubModels.forEach(item => {
output[item] = this[item].toAtlas();
});
const RawSubData = [
'BaseServerArgs',
'AdditionalCmdLineParams',
// World Options
'WorldFriendlyName',
'WorldAtlasId',
'WorldAtlasPassword',
'ModIDs',
// Grid Options
'gridSize',
'totalGridsX',
'totalGridsY',
'coordsScaling',
'globalTransitionMinZ',
// Image Paths
'backgroundImgPath',
'discoZonesImagePath',
// URL Options
'MetaWorldURL',
'AuthListURL',
'MapImageURL',
// Time Options
'Day0',
'bUseUTCTime',
'columnUTCOffset',
'lastImageOverride',
// Info Options
'showServerInfo',
'showDiscoZoneInfo',
'showShipPathsInfo',
'showIslandNames',
'showLines',
'showBackground',
// S3 Options
'LocalS3URL',
'LocalS3AccessKeyId',
'LocalS3SecretKey',
'LocalS3BucketName',
'LocalS3Region',
// Unsorted...
'shipPathsIdGenerator',
'idGenerator',
'regionsIdGenerator',
];
RawSubData.forEach(item => {
output[item] = this[item];
});
return output;
}
} }

View file

@ -1,6 +1,7 @@
import {BaseConfig} from "./abstract/baseConfig.model"; import {BaseConfig} from "./abstract/baseConfig.model";
import { ToJSON } from "./util/toJson";
export class SharedLogConfigModel extends BaseConfig { export class SharedLogConfigModel extends BaseConfig implements ToJSON {
public FetchRateSec: number = 60; public FetchRateSec: number = 60;
public SnapshotCleanupSec: number = 900; public SnapshotCleanupSec: number = 900;
public SnapshotRateSec: number = 1800; public SnapshotRateSec: number = 1800;
@ -10,4 +11,8 @@ export class SharedLogConfigModel extends BaseConfig {
super(); super();
Object.assign(this, raw); Object.assign(this, raw);
} }
public toJSON() {
return this;
}
} }

View file

@ -1,9 +1,14 @@
import {BaseConfig} from "./abstract/baseConfig.model"; import {BaseConfig} from "./abstract/baseConfig.model";
import { ToJSON } from "./util/toJson";
export class TravelDataConfigModel extends BaseConfig { export class TravelDataConfigModel extends BaseConfig implements ToJSON {
constructor(raw?:Partial<TravelDataConfigModel>) { constructor(raw?:Partial<TravelDataConfigModel>) {
super(); super();
Object.assign(this, raw); Object.assign(this, raw);
} }
public toJSON() {
return this;
}
} }

View file

@ -1,10 +1,15 @@
import {BaseConfig} from "./abstract/baseConfig.model"; import {BaseConfig} from "./abstract/baseConfig.model";
import { ToJSON } from "./util/toJson";
export class TribeLogConfigModel extends BaseConfig { export class TribeLogConfigModel extends BaseConfig implements ToJSON {
public MaxRedisEntries: number = 1000; public MaxRedisEntries: number = 1000;
constructor(raw?:Partial<TribeLogConfigModel>) { constructor(raw?:Partial<TribeLogConfigModel>) {
super(); super();
Object.assign(this, raw); Object.assign(this, raw);
} }
public toJSON() {
return this;
}
} }

View file

@ -0,0 +1,3 @@
export interface ToAtlas {
toString(): string;
}

View file

@ -0,0 +1,3 @@
export interface ToJSON {
toJSON(): object;
}

View file

@ -1 +1,2 @@
<p>config works!</p> <p>config works!</p>
<input [(ngModel)]="server.serverGrid.WorldFriendlyName">

View file

@ -1,4 +1,5 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Server } from "../../server";
@Component({ @Component({
selector: 'app-config', selector: 'app-config',
@ -7,7 +8,8 @@ import { Component, OnInit } from '@angular/core';
}) })
export class ConfigComponent implements OnInit { export class ConfigComponent implements OnInit {
constructor() { } constructor(private server: Server) {
}
ngOnInit() { ngOnInit() {
} }

View file

@ -5,7 +5,7 @@ import { ServerGridModel } from "./models/serverGrid.model";
export class Server { export class Server {
private rawData: string = ""; private rawData: string = "";
private jsonData: object = {}; private jsonData: object = {};
serverGrid: ServerGridModel; public serverGrid: ServerGridModel = new ServerGridModel({});
public load(raw) { public load(raw) {
this.rawData = raw; this.rawData = raw;
@ -18,6 +18,7 @@ export class Server {
} }
public save() { public save() {
this.jsonData = this.serverGrid.toJSON();
this.rawData = JSON.stringify(this.jsonData); this.rawData = JSON.stringify(this.jsonData);
return this.rawData; return this.rawData;
} }

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,133 @@
import { Injectable } from '@angular/core';
import { parse } from './atlas.pegjs';
const beginObject = '(';
const endObject = ')';
const nameSeparator = '=';
const valueSeparator = ',';
@Injectable({
providedIn: 'root'
})
export class PegjsService {
constructor() {}
public static parse(input: string): object {
let output = {};
try {
output = parse(input);
} catch (e) {
// TODO put a popover somewhere with a location of the error
console.log(e);
console.log(e.location);
}
return output;
}
public static format(input: object): string {
return PegjsService.deparseJson(input)
}
private static deparseJson(input, key?) {
switch (typeof input) {
case "object":
return PegjsService.deparseObject(input);
case "number":
return PegjsService.deparseNumber(input, key);
case "string":
return PegjsService.deparseString(input);
case "undefined":
return "";
case "boolean":
return PegjsService.deparseBoolean(input);
default:
console.log("Unknown type for input", input);
return "";
}
}
private static deparseObject(input) {
if (Array.isArray(input)) {
return this.deparseArray(input);
}
if (input === null) {
return "None";
}
let output = '';
output += beginObject;
Object.keys(input).forEach(function (key, idx, array) {
output += key;
output += nameSeparator;
output += PegjsService.deparseJson(input[key], key);
if (idx !== array.length - 1) {
// Not the last item
output += valueSeparator
}
});
output += endObject;
return output;
}
private static deparseArray(input) {
// We have one funky array option, where its 2 values and one of them is a recognised class.
// These are here for easier maintenance, as adding any new ones should just work. These all
// Work off string equality, see found below.
const specialCases = [
'BlueprintGeneratedClass',
'Blueprint',
'SoundWave',
'Texture2D'
];
const found = specialCases.indexOf(input[0]);
if (found > -1) {
// We found one of our special cases!
const val = specialCases[found];
return val + "'" + input[1] + "'";
}
let output = '';
output += beginObject;
input.forEach(function (data, idx, array) {
output += PegjsService.deparseJson(data);
if (idx !== array.length - 1) {
output += valueSeparator;
}
});
output += endObject;
return output;
}
private static deparseNumber(input, key) {
// Any number which has a decimal is stored to 6 decimal places
// Except for IDs. Unless they actually have such a number... erm...
if (key.substr(key.length - 2, 2) === "ID") {
if (input % 1 === 0) {
return Number(input).toString();
}
// Else drop out and return as normal
}
return Number(input).toFixed(6);
}
private static deparseString(input) {
// We need to re-encode the strings properly
return JSON.stringify(input);
}
private static deparseBoolean(input) {
if ( input ) {
return 'True';
} else {
return 'False';
}
}
}