diff --git a/app/main.ts b/app/main.ts index f651a10..45b1f1a 100644 --- a/app/main.ts +++ b/app/main.ts @@ -6,6 +6,8 @@ import {StoredGameModel} from "./storage/StoredGameModel"; import {ScriptAccountStorage} from "./storage/storing/ScriptAccountStoring"; import {ModelComponentFileDirectory} from "./storage/ModelComponentFileDirectory"; import {GamesystemStorage} from "./storage/storing/GamesystemStorage"; +import {Character} from "../src/app/project/game-model/characters/Character"; +import {CharacterStorage} from "./storage/storing/CharacterStorage"; let win: BrowserWindow | null = null; const args = process.argv.slice(1), @@ -71,6 +73,12 @@ function createWindow(): BrowserWindow { click: () => { win!.webContents.send('context-menu', "new-scriptaccount"); } + }, + { + label: "Character", + click: () => { + win!.webContents.send('context-menu', "new-character"); + } } ] @@ -219,6 +227,9 @@ function recieveGameModelToStore(gameModel: StoredGameModel) { const gamesystemStorage = new GamesystemStorage(path.join(projectDirectory, ModelComponentFileDirectory.GAMESYSTEM_DIR_NAME)) gamesystemStorage.storeGamesystems(gameModel.storedGamesystems) + + const characterStorage = new CharacterStorage(path.join(projectDirectory, ModelComponentFileDirectory.CHARACTER_DIR_NAME)) + characterStorage.storeCharacters(gameModel.storedCharacters) } /*function deleteComponent(component: DeleteModel) { diff --git a/app/storage/FileUtils.js b/app/storage/FileUtils.js index 55d504f..28298f8 100644 --- a/app/storage/FileUtils.js +++ b/app/storage/FileUtils.js @@ -19,6 +19,11 @@ class FileUtils { (0, fs_1.mkdirSync)(parentDirectory, { recursive: true }); } } + static prepareDirectoryFroWriting(directoryFile) { + if (!fs.existsSync(directoryFile)) { + (0, fs_1.mkdirSync)(directoryFile, { recursive: true }); + } + } static removeFiles(files) { files.forEach(file => { if (fs.lstatSync(file).isDirectory()) { diff --git a/app/storage/FileUtils.ts b/app/storage/FileUtils.ts index cfab96a..3dc93ee 100644 --- a/app/storage/FileUtils.ts +++ b/app/storage/FileUtils.ts @@ -21,6 +21,12 @@ export class FileUtils { } } + public static prepareDirectoryFroWriting(directoryFile: string) { + if(!fs.existsSync(directoryFile)) { + mkdirSync(directoryFile, {recursive: true}) + } + } + public static removeFiles(files: string[]) { files.forEach(file => { if(fs.lstatSync(file).isDirectory()) { diff --git a/app/storage/ModelComponentFileDirectory.js b/app/storage/ModelComponentFileDirectory.js index 9e2de51..8d28902 100644 --- a/app/storage/ModelComponentFileDirectory.js +++ b/app/storage/ModelComponentFileDirectory.js @@ -6,6 +6,5 @@ class ModelComponentFileDirectory { exports.ModelComponentFileDirectory = ModelComponentFileDirectory; ModelComponentFileDirectory.SCRIPTACCOUNT_DIR_NAME = "script-accounts"; ModelComponentFileDirectory.GAMESYSTEM_DIR_NAME = "gamesystems"; -ModelComponentFileDirectory.GAMESYSTEM_SIMPLE_DIR_NAME = "simple"; -ModelComponentFileDirectory.GAMESYSTEM_PRODUCT_DIR_NAME = "product"; +ModelComponentFileDirectory.CHARACTER_DIR_NAME = "characters"; //# sourceMappingURL=ModelComponentFileDirectory.js.map \ No newline at end of file diff --git a/app/storage/ModelComponentFileDirectory.ts b/app/storage/ModelComponentFileDirectory.ts index 35514b9..a0b9c8c 100644 --- a/app/storage/ModelComponentFileDirectory.ts +++ b/app/storage/ModelComponentFileDirectory.ts @@ -1,6 +1,5 @@ export class ModelComponentFileDirectory { public static SCRIPTACCOUNT_DIR_NAME = "script-accounts" public static GAMESYSTEM_DIR_NAME = "gamesystems"; - public static GAMESYSTEM_SIMPLE_DIR_NAME = "simple"; - public static GAMESYSTEM_PRODUCT_DIR_NAME = "product"; + public static CHARACTER_DIR_NAME = "characters"; } diff --git a/app/storage/StoredGameModel.js b/app/storage/StoredGameModel.js index 126a61b..57bfbe7 100644 --- a/app/storage/StoredGameModel.js +++ b/app/storage/StoredGameModel.js @@ -2,10 +2,11 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.StoredGameModel = void 0; class StoredGameModel { - constructor(gameModelName, storedScriptAccounts, storedGamesystems) { + constructor(gameModelName, storedScriptAccounts, storedGamesystems, storedCharacters) { this.gameModelName = gameModelName; this.storedGamesystems = storedGamesystems; this.storedScriptAccounts = storedScriptAccounts; + this.storedCharacters = storedCharacters; } } exports.StoredGameModel = StoredGameModel; diff --git a/app/storage/StoredGameModel.ts b/app/storage/StoredGameModel.ts index 8edfee0..d9d762b 100644 --- a/app/storage/StoredGameModel.ts +++ b/app/storage/StoredGameModel.ts @@ -5,11 +5,14 @@ export class StoredGameModel { storedGamesystems: StoreComponent[] storedScriptAccounts: StoreComponent[] + storedCharacters: StoreComponent[] - constructor(gameModelName: string, storedScriptAccounts: StoreComponent[], storedGamesystems: StoreComponent[]) { + constructor(gameModelName: string, storedScriptAccounts: StoreComponent[], storedGamesystems: StoreComponent[], + storedCharacters: StoreComponent[]) { this.gameModelName = gameModelName; this.storedGamesystems = storedGamesystems; this.storedScriptAccounts = storedScriptAccounts; + this.storedCharacters = storedCharacters; } } diff --git a/app/storage/loader/CharacterLoader.js b/app/storage/loader/CharacterLoader.js new file mode 100644 index 0000000..8b5255f --- /dev/null +++ b/app/storage/loader/CharacterLoader.js @@ -0,0 +1,31 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CharacterLoader = void 0; +const StoreComponent_1 = require("../StoreComponent"); +const FileUtils_1 = require("../FileUtils"); +const ModelComponentType_1 = require("../../../src/app/project/game-model/ModelComponentType"); +const fs = require("fs"); +class CharacterLoader { + constructor(characterDir) { + this.characterDir = characterDir; + } + loadCharacters() { + const characterFiles = FileUtils_1.FileUtils.listFilesInDirectory(this.characterDir); + const loadedCharacters = []; + characterFiles.forEach(characterFile => { + const loadedCharacter = this.loadSingleCharacter(characterFile); + if (loadedCharacter != undefined) { + loadedCharacters.push(loadedCharacter); + } + }); + return loadedCharacters; + } + loadSingleCharacter(characterFile) { + if (characterFile.endsWith(".json")) { + const characterData = fs.readFileSync(characterFile, 'utf-8'); + return new StoreComponent_1.StoreComponent(characterData, characterFile, ModelComponentType_1.ModelComponentType.SCRIPTACCOUNT); + } + } +} +exports.CharacterLoader = CharacterLoader; +//# sourceMappingURL=CharacterLoader.js.map \ No newline at end of file diff --git a/app/storage/loader/CharacterLoader.ts b/app/storage/loader/CharacterLoader.ts new file mode 100644 index 0000000..ace21f5 --- /dev/null +++ b/app/storage/loader/CharacterLoader.ts @@ -0,0 +1,34 @@ +import {StoreComponent} from "../StoreComponent"; +import {FileUtils} from "../FileUtils"; +import {ModelComponentType} from "../../../src/app/project/game-model/ModelComponentType"; +import * as fs from "fs"; +import {ModelComponentFileDirectory} from "../ModelComponentFileDirectory"; +import {load} from "@angular-devkit/build-angular/src/utils/server-rendering/esm-in-memory-loader/loader-hooks"; + +export class CharacterLoader { + characterDir: string + + + constructor(characterDir: string) { + this.characterDir = characterDir; + } + + loadCharacters(): StoreComponent[] { + const characterFiles = FileUtils.listFilesInDirectory(this.characterDir); + const loadedCharacters: StoreComponent[] = [] + characterFiles.forEach(characterFile => { + const loadedCharacter = this.loadSingleCharacter(characterFile); + if(loadedCharacter != undefined) { + loadedCharacters.push(loadedCharacter) + } + }) + return loadedCharacters; + } + + private loadSingleCharacter(characterFile: string) { + if(characterFile.endsWith(".json")) { + const characterData = fs.readFileSync(characterFile, 'utf-8'); + return new StoreComponent(characterData, characterFile, ModelComponentType.SCRIPTACCOUNT); + } + } +} diff --git a/app/storage/loader/GameModelLoader.js b/app/storage/loader/GameModelLoader.js index 7139cc9..480dc36 100644 --- a/app/storage/loader/GameModelLoader.js +++ b/app/storage/loader/GameModelLoader.js @@ -6,6 +6,7 @@ const path = require("node:path"); const ModelComponentFileDirectory_1 = require("../ModelComponentFileDirectory"); const ScriptAccountLoader_1 = require("./ScriptAccountLoader"); const GamesystemLoader_1 = require("./GamesystemLoader"); +const CharacterLoader_1 = require("./CharacterLoader"); class GameModelLoader { constructor(gameModelDir) { this.gameModelDir = gameModelDir; @@ -14,7 +15,8 @@ class GameModelLoader { const gameModelName = path.basename(this.gameModelDir); const storedScriptAccounts = this.loadScriptAccountComponents(); const storedGamesystems = this.loadGamesystems(); - return new StoredGameModel_1.StoredGameModel(gameModelName, storedScriptAccounts, storedGamesystems); + const storedCharacters = this.loadCharacters(); + return new StoredGameModel_1.StoredGameModel(gameModelName, storedScriptAccounts, storedGamesystems, storedCharacters); } loadScriptAccountComponents() { const scriptAccountDir = path.join(this.gameModelDir, ModelComponentFileDirectory_1.ModelComponentFileDirectory.SCRIPTACCOUNT_DIR_NAME); @@ -26,6 +28,11 @@ class GameModelLoader { const gamesystemLoader = new GamesystemLoader_1.GamesystemLoader(gamesystemDir); return gamesystemLoader.loadGamesystems(); } + loadCharacters() { + const characterDir = path.join(this.gameModelDir, ModelComponentFileDirectory_1.ModelComponentFileDirectory.CHARACTER_DIR_NAME); + const characterLoader = new CharacterLoader_1.CharacterLoader(characterDir); + return characterLoader.loadCharacters(); + } } exports.GameModelLoader = GameModelLoader; //# sourceMappingURL=GameModelLoader.js.map \ No newline at end of file diff --git a/app/storage/loader/GameModelLoader.ts b/app/storage/loader/GameModelLoader.ts index bcbfa63..615c354 100644 --- a/app/storage/loader/GameModelLoader.ts +++ b/app/storage/loader/GameModelLoader.ts @@ -5,6 +5,7 @@ import * as fs from "fs"; import {ModelComponentFileDirectory} from "../ModelComponentFileDirectory"; import {ScriptAccountLoader} from "./ScriptAccountLoader"; import {GamesystemLoader} from "./GamesystemLoader"; +import {CharacterLoader} from "./CharacterLoader"; export class GameModelLoader { gameModelDir: string @@ -19,8 +20,9 @@ export class GameModelLoader { const storedScriptAccounts = this.loadScriptAccountComponents(); const storedGamesystems = this.loadGamesystems(); + const storedCharacters = this.loadCharacters() - return new StoredGameModel(gameModelName, storedScriptAccounts, storedGamesystems); + return new StoredGameModel(gameModelName, storedScriptAccounts, storedGamesystems, storedCharacters); } private loadScriptAccountComponents() { @@ -35,6 +37,12 @@ export class GameModelLoader { return gamesystemLoader.loadGamesystems(); } + private loadCharacters(): StoreComponent[] { + const characterDir = path.join(this.gameModelDir, ModelComponentFileDirectory.CHARACTER_DIR_NAME); + const characterLoader = new CharacterLoader(characterDir) + return characterLoader.loadCharacters(); + } + diff --git a/app/storage/storing/CharacterStorage.js b/app/storage/storing/CharacterStorage.js new file mode 100644 index 0000000..c2ac440 --- /dev/null +++ b/app/storage/storing/CharacterStorage.js @@ -0,0 +1,32 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CharacterStorage = void 0; +const FileUtils_1 = require("../FileUtils"); +const path = require("node:path"); +const fs = require("fs"); +class CharacterStorage { + constructor(characterDir) { + this.characterDir = characterDir; + FileUtils_1.FileUtils.prepareDirectoryFroWriting(characterDir); + } + storeCharacters(storedCharacters) { + this.persistDeletedCharacters(storedCharacters); + storedCharacters.forEach(storedCharacter => this.storeSingleCharacter(storedCharacter)); + } + persistDeletedCharacters(existingCharacters) { + const scriptAccountFiles = FileUtils_1.FileUtils.listFilesInDirectory(this.characterDir); + scriptAccountFiles.forEach(characterFile => { + const scriptAccountFileName = path.parse(path.basename(characterFile)).name; + if (existingCharacters.find(character => character.fileName === scriptAccountFileName) == undefined) { + //No scriptAccountFile was found with that nae of the file. So the scriptAccount was deleted. Remove file + fs.unlinkSync(characterFile); + } + }); + } + storeSingleCharacter(character) { + const completeScriptAccountFile = path.join(this.characterDir, character.fileName + ".json"); + fs.writeFileSync(completeScriptAccountFile, character.jsonString, 'utf-8'); + } +} +exports.CharacterStorage = CharacterStorage; +//# sourceMappingURL=CharacterStorage.js.map \ No newline at end of file diff --git a/app/storage/storing/CharacterStorage.ts b/app/storage/storing/CharacterStorage.ts new file mode 100644 index 0000000..8e53647 --- /dev/null +++ b/app/storage/storing/CharacterStorage.ts @@ -0,0 +1,35 @@ +import {StoreComponent} from "../StoreComponent"; +import {FileUtils} from "../FileUtils"; +import * as path from "node:path"; +import * as fs from "fs"; + +export class CharacterStorage { + private characterDir: string + + + constructor(characterDir: string) { + this.characterDir = characterDir; + FileUtils.prepareDirectoryFroWriting(characterDir) + } + + storeCharacters(storedCharacters: StoreComponent[]) { + this.persistDeletedCharacters(storedCharacters) + storedCharacters.forEach(storedCharacter => this.storeSingleCharacter(storedCharacter)) + } + + private persistDeletedCharacters(existingCharacters: StoreComponent[]) { + const scriptAccountFiles = FileUtils.listFilesInDirectory(this.characterDir); + scriptAccountFiles.forEach(characterFile => { + const scriptAccountFileName = path.parse(path.basename(characterFile)).name + if(existingCharacters.find(character => character.fileName === scriptAccountFileName) == undefined) { + //No scriptAccountFile was found with that nae of the file. So the scriptAccount was deleted. Remove file + fs.unlinkSync(characterFile) + } + }) + } + + private storeSingleCharacter(character: StoreComponent) { + const completeScriptAccountFile = path.join(this.characterDir, character.fileName + ".json") + fs.writeFileSync(completeScriptAccountFile, character.jsonString, 'utf-8') + } +} diff --git a/app/storage/storing/GamesystemStorage.js b/app/storage/storing/GamesystemStorage.js index 003890e..62730ff 100644 --- a/app/storage/storing/GamesystemStorage.js +++ b/app/storage/storing/GamesystemStorage.js @@ -7,6 +7,7 @@ const fs = require("fs"); class GamesystemStorage { constructor(gamesystemRootDir) { this.gamesystemRootDir = gamesystemRootDir; + FileUtils_1.FileUtils.prepareDirectoryFroWriting(gamesystemRootDir); } storeGamesystems(gamesystems) { const unreferencedFiles = this.detectUnusedGamesystemFiles(gamesystems); diff --git a/app/storage/storing/GamesystemStorage.ts b/app/storage/storing/GamesystemStorage.ts index c414f65..b3337c3 100644 --- a/app/storage/storing/GamesystemStorage.ts +++ b/app/storage/storing/GamesystemStorage.ts @@ -10,6 +10,7 @@ export class GamesystemStorage { constructor(gamesystemRootDir: string) { this.gamesystemRootDir = gamesystemRootDir; + FileUtils.prepareDirectoryFroWriting(gamesystemRootDir) } public storeGamesystems(gamesystems: StoreComponent[]) { diff --git a/app/storage/storing/ScriptAccountStoring.js b/app/storage/storing/ScriptAccountStoring.js index 49b0eab..331a1cb 100644 --- a/app/storage/storing/ScriptAccountStoring.js +++ b/app/storage/storing/ScriptAccountStoring.js @@ -7,6 +7,7 @@ const fs = require("fs"); class ScriptAccountStorage { constructor(scriptAccountDir) { this.scriptAccountDir = scriptAccountDir; + FileUtils_1.FileUtils.prepareDirectoryFroWriting(this.scriptAccountDir); } storeScriptAccounts(scriptAccounts) { this.persistDeletedScriptAccounts(scriptAccounts); diff --git a/app/storage/storing/ScriptAccountStoring.ts b/app/storage/storing/ScriptAccountStoring.ts index 6e73b17..eae0bdc 100644 --- a/app/storage/storing/ScriptAccountStoring.ts +++ b/app/storage/storing/ScriptAccountStoring.ts @@ -9,6 +9,7 @@ export class ScriptAccountStorage { constructor(scriptAccountDir: string) { this.scriptAccountDir = scriptAccountDir; + FileUtils.prepareDirectoryFroWriting(this.scriptAccountDir) } storeScriptAccounts(scriptAccounts: StoreComponent[]) { diff --git a/src/app/app.component.html b/src/app/app.component.html index 2801b21..0626929 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -3,7 +3,9 @@ + (click)="openGamesystemsOverview()">code + @@ -20,10 +22,12 @@ + +
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 2467861..41f2835 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -20,6 +20,10 @@ import {ElectronService} from "./core/services"; import {ScriptAccountSerializer} from "./project/serializer/ScriptAccountSerializer"; import {StoreComponent} from "../../app/storage/StoreComponent"; import {GamesystemSerializer} from "./project/serializer/GamesystemSerializer"; +import {Character} from "./project/game-model/characters/Character"; +import {CharacterOverviewComponent} from "./side-overviews/character-overview/character-overview.component"; +import {CharacterSerializer} from "./project/serializer/CharacterSerializer"; +import {CharacterParser} from "./project/parser/characterParser/CharacterParser"; @Component({ selector: 'app-root', @@ -33,6 +37,7 @@ export class AppComponent implements OnInit{ @ViewChild('editor') editor: EditorComponent|undefined @ViewChild('scriptAccountOverview') scriptAccountOverview: ScriptAccountOverviewComponent | undefined @ViewChild('gamesystemOverview') gamesystemOverview: GamescriptOverviewComponent | undefined + @ViewChild('characterOverview') characterOverview: CharacterOverviewComponent | undefined gameModel: GameModel | undefined @@ -92,6 +97,12 @@ export class AppComponent implements OnInit{ this.editor!.openGameModelComponent(gamesystem!); } } break + case ModelComponentType.CHARACTER: { + if(this.characterOverview!.selectedCharacter != undefined) { + this.editor!.openGameModelComponent(this.characterOverview!.selectedCharacter); + } + }break + } } @@ -109,6 +120,8 @@ export class AppComponent implements OnInit{ this.gameModel!.removeGamesystem(affectedModelComponent); //this.electronService.ipcRenderer.send('delete-component', new DeleteModel(affectedModelComponent.componentName, ModelComponentType.GAMESYTEM)) this.gamesystemOverview!.refresh() + } else if(affectedModelComponent instanceof Character) { + this.gameModel!.removeCharacter(affectedModelComponent) } } }) @@ -118,6 +131,7 @@ export class AppComponent implements OnInit{ switch (modelComponentType) { case ModelComponentType.SCRIPTACCOUNT: this.onCreateNewScriptAccount(); break case ModelComponentType.GAMESYTEM: this.onCreateNewGamesystem(); break + case ModelComponentType.CHARACTER: this.onCreateNewCharacter(); break } } @@ -146,6 +160,15 @@ export class AppComponent implements OnInit{ } } + private onCreateNewCharacter() { + const createdCharacter = this.gameModel!.createCharacter("New Character") + if(createdCharacter != undefined) { + this.editor?.openGameModelComponent(createdCharacter); + } else { + console.log("[DEBUG] [App-Component] ScriptAccount could not be created (Name not unique)"); + } + } + private getSelectedModelComponent(): ModelComponent | undefined { if(this.openContent == ModelComponentType.SCRIPTACCOUNT) { if(this.scriptAccountOverview != undefined) { @@ -159,6 +182,12 @@ export class AppComponent implements OnInit{ } else { console.log("[WARN] [App.component] GamesystemOverview is undefined") } + } else if(this.openContent == ModelComponentType.CHARACTER) { + if(this.characterOverview != undefined) { + return this.characterOverview.selectedCharacter; + } else { + console.log("[WARN] [App.component] ScriptAccountOverview is undefined") + } } return undefined; } @@ -175,11 +204,14 @@ export class AppComponent implements OnInit{ const gamesystemParser = new GamesystemParser(scriptAccounts); const gamesystems = gamesystemParser.parseStoredGamesystems(storedGameModel.storedGamesystems); + const characterParser = new CharacterParser(); + const characters = characterParser.parseCharacters(storedGameModel.storedCharacters); + gameModel.scriptAccounts = scriptAccounts gameModel.gamesystems = gamesystems gameModel.generateProductSystemContents() - console.log(gameModel.scriptAccounts) + gameModel.characters = characters this.gameModel = gameModel; } @@ -188,7 +220,8 @@ export class AppComponent implements OnInit{ if(this.gameModel != undefined) { const storedScriptAccounts = ScriptAccountSerializer.serializeScriptAccounts(this.gameModel.scriptAccounts) const storedGamesystems: StoreComponent[] = GamesystemSerializer.serializeGamesystems(this.gameModel.gamesystems) - const storeModel = new StoredGameModel(this.gameModel.gameModelName, storedScriptAccounts, storedGamesystems) + const storedCharacters: StoreComponent[] = CharacterSerializer.serializeCharacters(this.gameModel.characters) + const storeModel = new StoredGameModel(this.gameModel.gameModelName, storedScriptAccounts, storedGamesystems, storedCharacters) if(this.electronService.isElectron) { this.electronService.ipcRenderer.send('save-model', storeModel) @@ -206,6 +239,11 @@ export class AppComponent implements OnInit{ this.drawer!.open(); } + openCharactersOverview() { + this.openContent = ModelComponentType.CHARACTER + this.drawer!.open() + } + protected readonly ModelComponentType = ModelComponentType; closeContentOverview() { @@ -234,4 +272,6 @@ export class AppComponent implements OnInit{ this.gamesystemOverview.resetSelectedGamesystem() } } + + } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 69fde6f..7412843 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -68,6 +68,8 @@ import { import { ScriptaccountConditionEditorComponent } from "./editor/gamesystem-editor/scriptaccount-condition-editor/scriptaccount-condition-editor.component"; +import {CharacterOverviewComponent} from "./side-overviews/character-overview/character-overview.component"; +import {CharacterEditorComponent} from "./editor/character-editor/character-editor.component"; // AoT requires an exported function for factories const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json'); @@ -89,65 +91,67 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl ProductStateEditorComponent, ProductGamesystemEditorComponent, ScriptaccountActionEditorComponent, - ScriptaccountConditionEditorComponent + ScriptaccountConditionEditorComponent, + CharacterOverviewComponent, + CharacterEditorComponent + ], + imports: [ + BrowserModule, + FormsModule, + HttpClientModule, + CoreModule, + SharedModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useFactory: httpLoaderFactory, + deps: [HttpClient] + } + }), + BrowserAnimationsModule, + MatIcon, + MatToolbar, + MatButton, + MatFormField, + MatInput, + MatDrawerContainer, + MatDrawer, + MatIconButton, + MatMenuTrigger, + MatMenu, + MatMenuItem, + MatListItem, + MatActionList, + MatTabGroup, + MatTab, + MatTabLabel, + MatLabel, + MatFormField, + ReactiveFormsModule, + MatError, + MatDialogTitle, + MatDialogContent, + MatDialogActions, + MatMiniFabButton, + MatTreeModule, + MatTable, + MatColumnDef, + MatHeaderCell, + MatHeaderCellDef, + MatCellDef, + MatCell, + MatHeaderRow, + MatRow, + MatHeaderRowDef, + MatRowDef, + MatCheckbox, + MatSelect, + MatOption, + MatHint, + MatTooltip, + MatCard, + MatCardContent ], - imports: [ - BrowserModule, - FormsModule, - HttpClientModule, - CoreModule, - SharedModule, - TranslateModule.forRoot({ - loader: { - provide: TranslateLoader, - useFactory: httpLoaderFactory, - deps: [HttpClient] - } - }), - BrowserAnimationsModule, - MatIcon, - MatToolbar, - MatButton, - MatFormField, - MatInput, - MatDrawerContainer, - MatDrawer, - MatIconButton, - MatMenuTrigger, - MatMenu, - MatMenuItem, - MatListItem, - MatActionList, - MatTabGroup, - MatTab, - MatTabLabel, - MatLabel, - MatFormField, - ReactiveFormsModule, - MatError, - MatDialogTitle, - MatDialogContent, - MatDialogActions, - MatMiniFabButton, - MatTreeModule, - MatTable, - MatColumnDef, - MatHeaderCell, - MatHeaderCellDef, - MatCellDef, - MatCell, - MatHeaderRow, - MatRow, - MatHeaderRowDef, - MatRowDef, - MatCheckbox, - MatSelect, - MatOption, - MatHint, - MatTooltip, - MatCard, - MatCardContent - ], providers: [], bootstrap: [AppComponent] }) diff --git a/src/app/editor/character-editor/character-editor.component.html b/src/app/editor/character-editor/character-editor.component.html new file mode 100644 index 0000000..4750ae3 --- /dev/null +++ b/src/app/editor/character-editor/character-editor.component.html @@ -0,0 +1 @@ +

character-editor works!

diff --git a/src/app/editor/character-editor/character-editor.component.scss b/src/app/editor/character-editor/character-editor.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/editor/character-editor/character-editor.component.spec.ts b/src/app/editor/character-editor/character-editor.component.spec.ts new file mode 100644 index 0000000..8f28ce9 --- /dev/null +++ b/src/app/editor/character-editor/character-editor.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CharacterEditorComponent } from './character-editor.component'; + +describe('CharacterEditorComponent', () => { + let component: CharacterEditorComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [CharacterEditorComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(CharacterEditorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/editor/character-editor/character-editor.component.ts b/src/app/editor/character-editor/character-editor.component.ts new file mode 100644 index 0000000..23e8438 --- /dev/null +++ b/src/app/editor/character-editor/character-editor.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-character-editor', + templateUrl: './character-editor.component.html', + styleUrl: './character-editor.component.scss' +}) +export class CharacterEditorComponent { + +} diff --git a/src/app/editor/editor.component.html b/src/app/editor/editor.component.html index f51aa7a..b351774 100644 --- a/src/app/editor/editor.component.html +++ b/src/app/editor/editor.component.html @@ -14,6 +14,8 @@ [gamesystem]="convertModelComponentToGamesystem(modelComponent)" (onOpenGamesystemEditor)="openGameModelComponent($event)" [scriptAccounts]="gameModel!.scriptAccounts"> + + diff --git a/src/app/project/game-model/GameModel.ts b/src/app/project/game-model/GameModel.ts index 66dd46c..8497737 100644 --- a/src/app/project/game-model/GameModel.ts +++ b/src/app/project/game-model/GameModel.ts @@ -4,13 +4,15 @@ import {Transition} from "./gamesystems/transitions/Transition"; import {State} from "./gamesystems/states/State"; import {ProductGamesystem} from "./gamesystems/ProductGamesystem"; import {SimpleGamesystem} from "./gamesystems/SimpleGamesystem"; -import {StorageModel} from "./fs/StorageModel"; +import {Character} from "./characters/Character"; +import {ModelComponentType} from "./ModelComponentType"; export class GameModel { gameModelName: string gamesystems: Gamesystem[] = []; scriptAccounts: ScriptAccount[] = []; + characters: Character[] = [] constructor(gameModelName: string) { this.gameModelName = gameModelName; @@ -65,12 +67,28 @@ export class GameModel { } } + createCharacter(characterName: string) { + const searchedCharacter = this.characters.find(character => character.componentName === characterName); + if(searchedCharacter == undefined) { + const character = new Character(characterName, ""); + this.characters.push(character) + return character + } + return undefined + } + removeScriptAccount(scriptAccount: ScriptAccount) { if(scriptAccount != undefined) { this.scriptAccounts = this.scriptAccounts.filter(s => s != scriptAccount); } } + removeCharacter(character: Character) { + if(character != undefined) { + this.characters = this.characters.filter(c => c.componentName !== character.componentName) + } + } + findGamesystem(gamesystemName: string) { const gamesystemQueue : Gamesystem, Transition>[] = []; this.gamesystems.forEach(gamesystem => gamesystemQueue.push(gamesystem)); diff --git a/src/app/project/game-model/ModelComponentType.ts b/src/app/project/game-model/ModelComponentType.ts index 77a75a7..14eaf8b 100644 --- a/src/app/project/game-model/ModelComponentType.ts +++ b/src/app/project/game-model/ModelComponentType.ts @@ -1,5 +1,6 @@ export enum ModelComponentType { SCRIPTACCOUNT, - GAMESYTEM + GAMESYTEM, + CHARACTER } diff --git a/src/app/project/game-model/ModelComponentTypeUtillities.ts b/src/app/project/game-model/ModelComponentTypeUtillities.ts index da1f827..aa736fd 100644 --- a/src/app/project/game-model/ModelComponentTypeUtillities.ts +++ b/src/app/project/game-model/ModelComponentTypeUtillities.ts @@ -5,6 +5,7 @@ export class ModelComponentTypeUtillities { switch (modelComponentType) { case ModelComponentType.SCRIPTACCOUNT: return "ScriptAccounts"; case ModelComponentType.GAMESYTEM: return "Gamesystems"; + case ModelComponentType.CHARACTER: return "Characters" default: return "Undefined"; } } @@ -13,6 +14,7 @@ export class ModelComponentTypeUtillities { switch (modelComponentType) { case ModelComponentType.SCRIPTACCOUNT: return "ScriptAccount"; case ModelComponentType.GAMESYTEM: return "Gamesystem"; + case ModelComponentType.CHARACTER: return "Character" default: return "Undefined"; } } @@ -21,6 +23,7 @@ export class ModelComponentTypeUtillities { switch (string) { case "gamesystem": return ModelComponentType.GAMESYTEM; case "scriptaccount": return ModelComponentType.SCRIPTACCOUNT; + case "character": return ModelComponentType.CHARACTER } } } diff --git a/src/app/project/game-model/characters/Character.ts b/src/app/project/game-model/characters/Character.ts new file mode 100644 index 0000000..07acf19 --- /dev/null +++ b/src/app/project/game-model/characters/Character.ts @@ -0,0 +1,9 @@ +import {ModelComponent} from "../ModelComponent"; +import {ModelComponentType} from "../ModelComponentType"; + +export class Character extends ModelComponent{ + + constructor(componentName: string, componentDescription: string) { + super(componentName, componentDescription, ModelComponentType.CHARACTER); + } +} diff --git a/src/app/project/parser/characterParser/CharacterParser.ts b/src/app/project/parser/characterParser/CharacterParser.ts new file mode 100644 index 0000000..07d7378 --- /dev/null +++ b/src/app/project/parser/characterParser/CharacterParser.ts @@ -0,0 +1,16 @@ +import {StoreComponent} from "../../../../../app/storage/StoreComponent"; +import {Character} from "../../game-model/characters/Character"; + + +export class CharacterParser { + + public parseCharacters(characters: StoreComponent[]): Character[] { + const loadedCharacters: Character[] = [] + characters.forEach(character => loadedCharacters.push(this.parseSingleCharacter(JSON.parse(character.jsonString)))) + return loadedCharacters; + } + + private parseSingleCharacter(characterData: any): Character { + return new Character(characterData.componentName, characterData.componentDescription); + } +} diff --git a/src/app/project/serializer/CharacterSerializer.ts b/src/app/project/serializer/CharacterSerializer.ts new file mode 100644 index 0000000..4923004 --- /dev/null +++ b/src/app/project/serializer/CharacterSerializer.ts @@ -0,0 +1,26 @@ +import {Character} from "../game-model/characters/Character"; +import {StoreComponent} from "../../../../app/storage/StoreComponent"; +import {SerializeConstants} from "./SerializeConstants"; +import {ModelComponentType} from "../game-model/ModelComponentType"; + +export class CharacterSerializer { + + public static serializeCharacters(characters: Character[]): StoreComponent[] { + const storedCharacters: StoreComponent[] = [] + characters.forEach(character => storedCharacters.push(this.serializeSingleCharacter(character))) + return storedCharacters; + } + + private static serializeSingleCharacter(character: Character): StoreComponent{ + const fileName = character.componentName + const jsonString = JSON.stringify(character, (key, value) => { + if(key === 'unsaved' || key === 'type') { + return undefined + } else { + return value; + } + }, SerializeConstants.JSON_INDENT) + + return new StoreComponent(jsonString, fileName, ModelComponentType.CHARACTER); + } +} diff --git a/src/app/side-overviews/character-overview/character-overview.component.html b/src/app/side-overviews/character-overview/character-overview.component.html new file mode 100644 index 0000000..2cdb118 --- /dev/null +++ b/src/app/side-overviews/character-overview/character-overview.component.html @@ -0,0 +1,8 @@ + + + person{{character.componentName}} + + diff --git a/src/app/side-overviews/character-overview/character-overview.component.scss b/src/app/side-overviews/character-overview/character-overview.component.scss new file mode 100644 index 0000000..0dde805 --- /dev/null +++ b/src/app/side-overviews/character-overview/character-overview.component.scss @@ -0,0 +1,14 @@ +.scriptAccount-item { + min-height: 1.8em !important; + height: 1.8em !important; +} + +.scriptAccount-icon { + margin-right: 10px; + color: #ccffff; + align-content: baseline; +} + +.selected-item { + background-color: #8696b6; +} diff --git a/src/app/side-overviews/character-overview/character-overview.component.spec.ts b/src/app/side-overviews/character-overview/character-overview.component.spec.ts new file mode 100644 index 0000000..6edeb91 --- /dev/null +++ b/src/app/side-overviews/character-overview/character-overview.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CharacterOverviewComponent } from './character-overview.component'; + +describe('CharacterOverviewComponent', () => { + let component: CharacterOverviewComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [CharacterOverviewComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(CharacterOverviewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/side-overviews/character-overview/character-overview.component.ts b/src/app/side-overviews/character-overview/character-overview.component.ts new file mode 100644 index 0000000..c182485 --- /dev/null +++ b/src/app/side-overviews/character-overview/character-overview.component.ts @@ -0,0 +1,28 @@ +import {Component, EventEmitter, Input, Output} from '@angular/core'; +import {GameModel} from "../../project/game-model/GameModel"; +import {MatActionList, MatListItem} from "@angular/material/list"; +import {MatIcon} from "@angular/material/icon"; +import {NgClass, NgForOf} from "@angular/common"; +import {ScriptAccount} from "../../project/game-model/scriptAccounts/ScriptAccount"; +import {Character} from "../../project/game-model/characters/Character"; + +@Component({ + selector: 'app-character-overview', + templateUrl: './character-overview.component.html', + styleUrl: './character-overview.component.scss' +}) +export class CharacterOverviewComponent { + + @Input() gameModel: GameModel | undefined + @Output("onOpenCharacterEditor") openCharacterEmitter: EventEmitter = new EventEmitter(); + + selectedCharacter: Character | undefined + + onOpenCharacter(character: Character) { + this.openCharacterEmitter.emit(character); + } + + selectCharacter(character: Character) { + this.selectedCharacter = character; + } +} diff --git a/testModel/characters/Astrid Hofferson.json b/testModel/characters/Astrid Hofferson.json new file mode 100644 index 0000000..0678c2b --- /dev/null +++ b/testModel/characters/Astrid Hofferson.json @@ -0,0 +1,4 @@ +{ + "componentName": "Astrid Hofferson", + "componentDescription": "" +} \ No newline at end of file diff --git a/testModel/characters/Hicks Haddock.json b/testModel/characters/Hicks Haddock.json new file mode 100644 index 0000000..1e611d7 --- /dev/null +++ b/testModel/characters/Hicks Haddock.json @@ -0,0 +1,4 @@ +{ + "componentName": "Hicks Haddock", + "componentDescription": "" +} \ No newline at end of file diff --git a/testModel/gamesystems/Weathersystem/Weathersystem.json b/testModel/gamesystems/Weathersystem/Weathersystem.json index df066e7..b9abfec 100644 --- a/testModel/gamesystems/Weathersystem/Weathersystem.json +++ b/testModel/gamesystems/Weathersystem/Weathersystem.json @@ -1 +1,12 @@ -{"componentName":"Weathersystem","componentDescription":"Ein Wettersystem, dass sich aus normalem Wetter (Sonne, Regen, Wolke, Schnee, Sturm etc.) und zusätzlich den Jahreszeiten (Frühling, Sommer, Herbst, Winter, etc.) zusammensetzt.","childsystems":[{"componentName":"Season"},{"componentName":"Weather"}]} \ No newline at end of file +{ + "componentName": "Weathersystem", + "componentDescription": "Ein Wettersystem, dass sich aus normalem Wetter (Sonne, Regen, Wolke, Schnee, Sturm etc.) und zusätzlich den Jahreszeiten (Frühling, Sommer, Herbst, Winter, etc.) zusammensetzt.", + "childsystems": [ + { + "componentName": "Season" + }, + { + "componentName": "Weather" + } + ] +} \ No newline at end of file