Compare commits
2 commits
6307780b9c
...
ee42245ebb
| Author | SHA1 | Date | |
|---|---|---|---|
| ee42245ebb | |||
| dfc702992b |
29 changed files with 21987 additions and 46 deletions
|
|
@ -5,17 +5,22 @@ import { ConfigComponent } from "./pages/config/config.component";
|
||||||
import { QuestsComponent } from "./pages/config/quests/quests.component";
|
import { QuestsComponent } from "./pages/config/quests/quests.component";
|
||||||
import { GridComponent } from "./pages/config/grid/grid.component";
|
import { GridComponent } from "./pages/config/grid/grid.component";
|
||||||
import { DbsComponent } from "./pages/config/dbs/dbs.component";
|
import { DbsComponent } from "./pages/config/dbs/dbs.component";
|
||||||
|
import { ServersComponent } from "./pages/config/servers/servers.component";
|
||||||
|
import { ServerComponent } from "./pages/config/servers/server/server.component";
|
||||||
|
import { IslandInstanceComponent } from "./pages/config/servers/island-instance/island-instance.component";
|
||||||
|
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{path: 'raw', component: RawEditorComponent},
|
{path: 'raw', component: RawEditorComponent},
|
||||||
{
|
{
|
||||||
path: 'config', component: ConfigComponent,
|
path: 'config', component: ConfigComponent, children: [
|
||||||
children: [
|
|
||||||
{path: '', redirectTo: 'grid', pathMatch: 'full'},
|
{path: '', redirectTo: 'grid', pathMatch: 'full'},
|
||||||
{path: 'grid', component: GridComponent},
|
{path: 'grid', component: GridComponent},
|
||||||
{path: 'dbs', component: DbsComponent},
|
{path: 'dbs', component: DbsComponent},
|
||||||
{path: 'quests', component: QuestsComponent},
|
{path: 'quests', component: QuestsComponent},
|
||||||
|
{path: 'servers', component: ServersComponent},
|
||||||
|
{path: 'server/:index', component: ServerComponent},
|
||||||
|
{path: 'server/:index/island/:islandIndex', component: IslandInstanceComponent}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,12 @@ import { TextComponent } from './components/form/text/text.component';
|
||||||
import { PasswordComponent } from './components/form/password/password.component';
|
import { PasswordComponent } from './components/form/password/password.component';
|
||||||
import { DbsComponent } from './pages/config/dbs/dbs.component';
|
import { DbsComponent } from './pages/config/dbs/dbs.component';
|
||||||
import { CheckboxComponent } from './components/form/checkbox/checkbox.component';
|
import { CheckboxComponent } from './components/form/checkbox/checkbox.component';
|
||||||
|
import { ServersComponent } from './pages/config/servers/servers.component';
|
||||||
|
import { ServerComponent } from './pages/config/servers/server/server.component';
|
||||||
|
import { TemplateComponent } from './pages/config/servers/template/template.component';
|
||||||
|
import { SelectListComponent } from './components/form/select-list/select-list.component';
|
||||||
|
import { SelectObjectComponent } from './components/form/select-object/select-object.component';
|
||||||
|
import { IslandInstanceComponent } from './pages/config/servers/island-instance/island-instance.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
|
@ -30,7 +36,13 @@ import { CheckboxComponent } from './components/form/checkbox/checkbox.component
|
||||||
TextComponent,
|
TextComponent,
|
||||||
PasswordComponent,
|
PasswordComponent,
|
||||||
DbsComponent,
|
DbsComponent,
|
||||||
CheckboxComponent
|
CheckboxComponent,
|
||||||
|
ServersComponent,
|
||||||
|
ServerComponent,
|
||||||
|
TemplateComponent,
|
||||||
|
SelectListComponent,
|
||||||
|
SelectObjectComponent,
|
||||||
|
IslandInstanceComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,13 @@
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label for="num-{{ id }}" class="col-2">{{ label }}</label>
|
<label for="num-{{ id }}" class="col-2">{{ label }}</label>
|
||||||
<div class="col-10">
|
<div class="col-10">
|
||||||
<input id="num-{{ id }}" type="number" class="form-control" (ngModelChange)="numberChange.emit($event)" [ngModel]="number">
|
<div class="input-group">
|
||||||
|
<input id="num-{{ id }}" type="number" class="form-control" (ngModelChange)="numberChange.emit($event)"
|
||||||
|
[ngModel]="number" min="{{ min }}" max="{{ max }}" step="{{ step }}">
|
||||||
|
<div class="input-group-append" *ngIf="postButtonText">
|
||||||
|
<button class="btn btn-outline-primary" (click)="postButton.emit($event)">{{ postButtonText }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<small class="form-text text-muted" *ngIf="help">{{ help }}</small>
|
<small class="form-text text-muted" *ngIf="help">{{ help }}</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -7,9 +7,14 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||||
export class NumberComponent implements OnInit {
|
export class NumberComponent implements OnInit {
|
||||||
@Input() number: number;
|
@Input() number: number;
|
||||||
@Output() numberChange = new EventEmitter();
|
@Output() numberChange = new EventEmitter();
|
||||||
|
@Input() postButtonText: string;
|
||||||
|
@Output() postButton = new EventEmitter();
|
||||||
@Input() label: string;
|
@Input() label: string;
|
||||||
@Input() id: string;
|
@Input() id: string;
|
||||||
@Input() help: string;
|
@Input() help: string;
|
||||||
|
@Input() min: number;
|
||||||
|
@Input() max: number;
|
||||||
|
@Input() step: number;
|
||||||
|
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="select-{{ id }}" class="col-2">{{ label }}</label>
|
||||||
|
<div class="col-10">
|
||||||
|
<select id="select-{{ id }}" class="form-control" (ngModelChange)="optionChange.emit($event)" [ngModel]="option">
|
||||||
|
<option *ngIf="withEmptyOption" value=""></option>
|
||||||
|
<option *ngFor="let option of optionList" value="{{ option }}">{{ option }}</option>
|
||||||
|
</select>
|
||||||
|
<small class="form-text text-muted" *ngIf="help">{{ help }}</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
21
src/app/components/form/select-list/select-list.component.ts
Normal file
21
src/app/components/form/select-list/select-list.component.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-select-list',
|
||||||
|
templateUrl: './select-list.component.html'
|
||||||
|
})
|
||||||
|
export class SelectListComponent implements OnInit {
|
||||||
|
@Input() withEmptyOption: boolean = false;
|
||||||
|
@Input() optionList: any[];
|
||||||
|
@Input() option: any;
|
||||||
|
@Output() optionChange = new EventEmitter();
|
||||||
|
@Input() label: string;
|
||||||
|
@Input() id: string;
|
||||||
|
@Input() help: string;
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="select-{{ id }}" class="col-2">{{ label }}</label>
|
||||||
|
<div class="col-10">
|
||||||
|
<select id="select-{{ id }}" class="form-control" (ngModelChange)="optionChange.emit($event)" [ngModel]="option">
|
||||||
|
<option *ngIf="withEmptyOption" value=""></option>
|
||||||
|
<option *ngFor="let option of optionObject | keyvalue" value="{{ option.key }}">{{ option.value }}</option>
|
||||||
|
</select>
|
||||||
|
<small class="form-text text-muted" *ngIf="help">{{ help }}</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-select-object',
|
||||||
|
templateUrl: './select-object.component.html'
|
||||||
|
})
|
||||||
|
export class SelectObjectComponent implements OnInit {
|
||||||
|
@Input() withEmptyOption: boolean = false;
|
||||||
|
@Input() optionObject: object;
|
||||||
|
@Input() option: any;
|
||||||
|
@Output() optionChange = new EventEmitter();
|
||||||
|
@Input() label: string;
|
||||||
|
@Input() id: string;
|
||||||
|
@Input() help: string;
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
20
src/app/models/atlasData/coordinate-3d-string.model.ts
Normal file
20
src/app/models/atlasData/coordinate-3d-string.model.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { Deserialize } from "../util/deserialize.model";
|
||||||
|
|
||||||
|
export class Coordinate3dStringModel implements Deserialize {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
z: number;
|
||||||
|
|
||||||
|
deserialize(input: any): this {
|
||||||
|
const array = input.split(' ');
|
||||||
|
if (array.length !== 3) throw Error(`Bad string [${input}] for Coordinate3d`);
|
||||||
|
this.x = Number.parseFloat(array[0]);
|
||||||
|
this.y = Number.parseFloat(array[1]);
|
||||||
|
this.z = Number.parseFloat(array[2]);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON(): string {
|
||||||
|
return `${this.x} ${this.y} ${this.z}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
118
src/app/models/atlasData/island-instance.model.ts
Normal file
118
src/app/models/atlasData/island-instance.model.ts
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
import { Deserialize } from "../util/deserialize.model";
|
||||||
|
import { IslandDataModel } from "../../../data/models/island-data.model";
|
||||||
|
import { Coordinate3dStringModel } from "./coordinate-3d-string.model";
|
||||||
|
|
||||||
|
export class IslandInstanceModel implements Deserialize {
|
||||||
|
name: string;
|
||||||
|
id: number;
|
||||||
|
spawnerOverrides: object; // TODO Figure out what this actually does
|
||||||
|
treasureMapSpawnPoints: Coordinate3dStringModel[];
|
||||||
|
wildPirateCampSpawnPoints: Coordinate3dStringModel[];
|
||||||
|
minTreasureQuality: number;
|
||||||
|
maxTreasureQuality: number;
|
||||||
|
useNpcVolumesForTreasures: boolean;
|
||||||
|
useLevelBoundsForTreasures: boolean;
|
||||||
|
prioritizeVolumesForTreasures: boolean;
|
||||||
|
islandPoints: number;
|
||||||
|
islandTreasureBottleSupplyCrateOverrides: string; // TODO figure out what this actually is
|
||||||
|
islandWidth: number;
|
||||||
|
islandHeight: number;
|
||||||
|
singleSpawnPointX: number;
|
||||||
|
singleSpawnPointY: number;
|
||||||
|
singleSpawnPointZ: number;
|
||||||
|
worldX: number;
|
||||||
|
worldY: number;
|
||||||
|
rotation: number;
|
||||||
|
|
||||||
|
// Specify extra player spawn points. Unique within entire grid
|
||||||
|
spawnPointRegionOverride: number = -1;
|
||||||
|
finalNPCLevelMultiplier: number = 1;
|
||||||
|
finalNPCLevelOffset: number = 0;
|
||||||
|
instanceTreasureQualityMultiplier: number = 1;
|
||||||
|
instanceTreasureQualityAddition: number = 0;
|
||||||
|
|
||||||
|
// Linked comma separated values normally. Lets just fix that...
|
||||||
|
public IslandInstanceCustomData: object = {};
|
||||||
|
public IslandInstanceClientCustomData: object = {};
|
||||||
|
|
||||||
|
deserialize(input: any): this {
|
||||||
|
// Do this before actually assigning to current object
|
||||||
|
const string1 = input.IslandInstanceCustomDatas1;
|
||||||
|
delete input.IslandInstanceCustomDatas1;
|
||||||
|
const string2 = input.IslandInstanceCustomDatas2;
|
||||||
|
delete input.IslandInstanceCustomDatas2;
|
||||||
|
const stringClient1 = input.IslandInstanceClientCustomDatas1;
|
||||||
|
delete input.IslandInstanceClientCustomDatas1;
|
||||||
|
const stringClient2 = input.IslandInstanceClientCustomDatas2;
|
||||||
|
delete input.IslandInstanceClientCustomDatas2;
|
||||||
|
Object.assign(this, input);
|
||||||
|
|
||||||
|
// Some minor assumption about how this works, but...
|
||||||
|
if (string1) {
|
||||||
|
const array1 = string1.split(',');
|
||||||
|
const array2 = string2.split(',');
|
||||||
|
if (array1.length !== array2.length)
|
||||||
|
throw Error('IslandInstanceCustomDatas unmatched array length');
|
||||||
|
array1.forEach((i, idx) => this.IslandInstanceCustomData[i] = array2[idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stringClient1) {
|
||||||
|
const array1 = stringClient1.split(',');
|
||||||
|
const array2 = stringClient2.split(',');
|
||||||
|
if (array1.length !== array2.length)
|
||||||
|
throw Error('IslandInstanceClientCustomDatas unmatched array length');
|
||||||
|
array1.forEach((i, idx) => this.IslandInstanceClientCustomData[i] = array2[idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.treasureMapSpawnPoints === undefined) this.treasureMapSpawnPoints = [];
|
||||||
|
this.treasureMapSpawnPoints = this.treasureMapSpawnPoints.map(i => new Coordinate3dStringModel().deserialize(i));
|
||||||
|
if (this.wildPirateCampSpawnPoints === undefined) this.wildPirateCampSpawnPoints = [];
|
||||||
|
this.wildPirateCampSpawnPoints = this.wildPirateCampSpawnPoints.map(i => new Coordinate3dStringModel().deserialize(i));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON(): object {
|
||||||
|
let json = Object.assign({}, this);
|
||||||
|
// Remove some stupidity from the above
|
||||||
|
delete json.IslandInstanceCustomData;
|
||||||
|
delete json.IslandInstanceClientCustomData;
|
||||||
|
// Remap to separate variables
|
||||||
|
if (Object.keys(this.IslandInstanceCustomData).length > 0) {
|
||||||
|
json['IslandInstanceCustomDatas1'] = Object.keys(this.IslandInstanceCustomData).join(',');
|
||||||
|
json['IslandInstanceCustomDatas2'] = Object.values(this.IslandInstanceCustomData).join(',');
|
||||||
|
}
|
||||||
|
if (Object.keys(this.IslandInstanceCustomData).length > 0) {
|
||||||
|
json['IslandInstanceClientCustomDatas1'] = Object.keys(this.IslandInstanceClientCustomData).join(',');
|
||||||
|
json['IslandInstanceClientCustomDatas2'] = Object.values(this.IslandInstanceClientCustomData).join(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json.spawnPointRegionOverride === -1) delete json.spawnPointRegionOverride;
|
||||||
|
if (json.finalNPCLevelMultiplier === 1) delete json.finalNPCLevelMultiplier;
|
||||||
|
if (json.finalNPCLevelOffset === 0) delete json.finalNPCLevelMultiplier;
|
||||||
|
if (json.instanceTreasureQualityMultiplier === 1) delete json.instanceTreasureQualityMultiplier;
|
||||||
|
if (json.instanceTreasureQualityAddition === 0) delete json.instanceTreasureQualityAddition;
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromIslandData(data: IslandDataModel): IslandInstanceModel {
|
||||||
|
return new IslandInstanceModel().deserialize({
|
||||||
|
name: data.name,
|
||||||
|
spawnerOverrides: data.spawnerOverrides,
|
||||||
|
treasureMapSpawnPoints: data.treasureMapSpawnPoints,
|
||||||
|
wildPirateCampSpawnPoints: data.wildPirateCampSpawnPoints,
|
||||||
|
minTreasureQuality: data.minTreasureQuality,
|
||||||
|
maxTreasureQuality: data.maxTreasureQuality,
|
||||||
|
useNpcVolumesForTreasures: data.useNpcVolumesForTreasures,
|
||||||
|
useLevelBoundsForTreasures: data.useLevelBoundsForTreasures,
|
||||||
|
prioritizeVolumesForTreasures: data.prioritizeVolumesForTreasures,
|
||||||
|
islandPoints: data.islandPoints,
|
||||||
|
islandTreasureBottleSupplyCrateOverrides: data.islandTreasureBottleSupplyCrateOverrides,
|
||||||
|
islandWidth: data.x,
|
||||||
|
islandHeight: data.y,
|
||||||
|
singleSpawnPointX: data.singleSpawnPointX,
|
||||||
|
singleSpawnPointY: data.singleSpawnPointY,
|
||||||
|
singleSpawnPointZ: data.singleSpawnPointZ
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,51 +1,77 @@
|
||||||
import { Deserialize } from "../util/deserialize.model";
|
import { Deserialize } from "../util/deserialize.model";
|
||||||
import { ServerSublevelModel } from "./serverSublevel.model";
|
import { ServerSublevelModel } from "./serverSublevel.model";
|
||||||
|
import { IslandInstanceModel } from "./island-instance.model";
|
||||||
|
|
||||||
export class ServerModel implements Deserialize {
|
export class ServerModel implements Deserialize {
|
||||||
|
// General Settings
|
||||||
|
name: string;
|
||||||
gridX: number;
|
gridX: number;
|
||||||
gridY: number;
|
gridY: number;
|
||||||
MachineIdTag: string;
|
isHomeServer: boolean;
|
||||||
|
utcOffset: number;
|
||||||
|
|
||||||
|
// Connection Settings
|
||||||
ip: string;
|
ip: string;
|
||||||
name: string;
|
|
||||||
port: number;
|
port: number;
|
||||||
gamePort: number;
|
gamePort: number;
|
||||||
seamlessDataPort: number;
|
seamlessDataPort: number;
|
||||||
isHomeServer: boolean;
|
|
||||||
AdditionalCmdLineParams: string;
|
// Gameplay Settings
|
||||||
OverrideShooterGameModeDefaultGameIni: object;
|
|
||||||
floorZDist: number;
|
floorZDist: number;
|
||||||
utcOffset: number;
|
|
||||||
transitionMinZ: number;
|
transitionMinZ: number;
|
||||||
GlobalBiomeSeamlessServerGridPreOffsetValues: string;
|
serverIslandPointsMultiplier: number;
|
||||||
GlobalBiomeSeamlessServerGridPreOffsetValuesOceanWater: string;
|
|
||||||
OceanDinoDepthEntriesOverride: string;
|
// Colour & Style Settings
|
||||||
oceanFloatsamCratesOverride: string;
|
|
||||||
treasureMapLootTablesOverride: string;
|
|
||||||
oceanEpicSpawnEntriesOverrideTemplateName: string;
|
|
||||||
NPCShipSpawnEntriesOverrideTemplateName: string;
|
|
||||||
regionOverrides: string;
|
|
||||||
waterColorR: number;
|
waterColorR: number;
|
||||||
waterColorG: number;
|
waterColorG: number;
|
||||||
waterColorB: number;
|
waterColorB: number;
|
||||||
skyStyleIndex: number;
|
skyStyleIndex: number;
|
||||||
serverIslandPointsMultiplier: number;
|
|
||||||
lastModified: string;
|
// Override Settings
|
||||||
|
OceanDinoDepthEntriesOverride: string;
|
||||||
|
oceanFloatsamCratesOverride: string;
|
||||||
|
treasureMapLootTablesOverride: string;
|
||||||
|
OverrideShooterGameModeDefaultGameIni: object;
|
||||||
|
|
||||||
|
//Dont render if default/empty
|
||||||
|
GlobalBiomeSeamlessServerGridPreOffsetValues: string;
|
||||||
|
GlobalBiomeSeamlessServerGridPreOffsetValuesOceanWater: string;
|
||||||
|
oceanEpicSpawnEntriesOverrideTemplateName: string;
|
||||||
|
NPCShipSpawnEntriesOverrideTemplateName: string;
|
||||||
|
regionOverrides: string;
|
||||||
|
|
||||||
|
|
||||||
lastImageOverride: string;
|
lastImageOverride: string;
|
||||||
islandLocked: boolean;
|
|
||||||
discoLocked: boolean;
|
|
||||||
pathsLocked: boolean;
|
|
||||||
extraSublevels: string[];
|
extraSublevels: string[];
|
||||||
totalExtraSublevels: string[];
|
totalExtraSublevels: string[];
|
||||||
islandInstances;
|
islandInstances: IslandInstanceModel[];
|
||||||
discoZones;
|
discoZones;
|
||||||
spawnRegions;
|
spawnRegions;
|
||||||
|
|
||||||
|
// Dont render if default/empty
|
||||||
serverTemplateName: string;
|
serverTemplateName: string;
|
||||||
|
|
||||||
sublevels: ServerSublevelModel[];
|
sublevels: ServerSublevelModel[];
|
||||||
|
|
||||||
|
// Irrelevant, used internally by Grapeshot
|
||||||
|
//MachineIdTag: string;
|
||||||
|
// Probably also irrelevant
|
||||||
|
//AdditionalCmdLineParams: string;
|
||||||
|
|
||||||
|
// Used by ServerGridEditor
|
||||||
|
//islandLocked: boolean;
|
||||||
|
//discoLocked: boolean;
|
||||||
|
//pathsLocked: boolean;
|
||||||
|
|
||||||
|
// Editing time for ServerGridEditor
|
||||||
|
//lastModified: string;
|
||||||
|
|
||||||
|
|
||||||
deserialize(input: any): this {
|
deserialize(input: any): this {
|
||||||
Object.assign(this, input);
|
Object.assign(this, input);
|
||||||
this.sublevels = this.sublevels.map(i => new ServerSublevelModel().deserialize(i));
|
this.sublevels = this.sublevels.map(i => new ServerSublevelModel().deserialize(i));
|
||||||
|
this.islandInstances = this.islandInstances.map(i => new IslandInstanceModel().deserialize(i));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,17 +1,40 @@
|
||||||
import { Deserialize } from "../util/deserialize.model";
|
import { Deserialize } from "../util/deserialize.model";
|
||||||
|
import { IslandInstanceModel } from "./island-instance.model";
|
||||||
|
import { ServerModel } from "./server.model";
|
||||||
|
import { ServerGridModel } from "../serverGrid.model";
|
||||||
|
import { IslandDataModel } from "../../../data/models/island-data.model";
|
||||||
|
|
||||||
export class ServerSublevelModel implements Deserialize {
|
export class ServerSublevelModel implements Deserialize {
|
||||||
public name: string;
|
public name: string;
|
||||||
public additionalTranslationX: number;
|
public additionalTranslationX: number;
|
||||||
public additionalTranslationY: number;
|
public additionalTranslationY: number;
|
||||||
public additionalTranslationZ: number;
|
public additionalTranslationZ: number = 0;
|
||||||
public additionalRotationPitch: number;
|
public additionalRotationPitch: number = 0;
|
||||||
public additionalRotationYaw: number;
|
public additionalRotationYaw: number = 0;
|
||||||
public additionalRotationRoll: number;
|
public additionalRotationRoll: number = 0;
|
||||||
public id: number;
|
public id: number;
|
||||||
public landscapeMaterialOverride: number;
|
public landscapeMaterialOverride: number;
|
||||||
|
|
||||||
deserialize(input: any): this {
|
deserialize(input: any): this {
|
||||||
return Object.assign(this, input);
|
return Object.assign(this, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setupFromIsland(island: IslandInstanceModel, islandData: IslandDataModel, cell: ServerModel, grid: ServerGridModel) {
|
||||||
|
this.id = island.id;
|
||||||
|
this.landscapeMaterialOverride = islandData.landscapeMaterialOverride;
|
||||||
|
this.additionalRotationYaw = island.rotation;
|
||||||
|
|
||||||
|
// XY are based on centre of the cell
|
||||||
|
// Use integers to reduce precision issues.
|
||||||
|
// 10 Million chosen as is larger than gridSize recommended setting
|
||||||
|
const multiplier = 10_000_000;
|
||||||
|
const worldX = island.worldX * multiplier;
|
||||||
|
const worldY = island.worldY * multiplier;
|
||||||
|
const gridSize = grid.gridSize * multiplier;
|
||||||
|
|
||||||
|
const newX = worldX - (gridSize * cell.gridX) - (gridSize / 2);
|
||||||
|
this.additionalTranslationX = newX / multiplier;
|
||||||
|
const newY = worldY - (gridSize * cell.gridY) - (gridSize / 2);
|
||||||
|
this.additionalTranslationY = newY / multiplier;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
13
src/app/models/atlasData/serverTemplate.model.ts
Normal file
13
src/app/models/atlasData/serverTemplate.model.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { Deserialize } from "../util/deserialize.model";
|
||||||
|
import { ServerModel } from "./server.model";
|
||||||
|
|
||||||
|
export class ServerTemplateModel extends ServerModel implements Deserialize {
|
||||||
|
public templateColorR: number;
|
||||||
|
public templateColorG: number;
|
||||||
|
public templateColorB: number;
|
||||||
|
|
||||||
|
deserialize(input: any): this {
|
||||||
|
Object.assign(this, input);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ import { GlobalGameplaySetupModel } from "./GlobalGameplaySetupModel";
|
||||||
import { Deserialize } from "./util/deserialize.model";
|
import { Deserialize } from "./util/deserialize.model";
|
||||||
import { DatabaseConnectionModel } from "./databaseConnection.model";
|
import { DatabaseConnectionModel } from "./databaseConnection.model";
|
||||||
import { ServerModel } from "./atlasData/server.model";
|
import { ServerModel } from "./atlasData/server.model";
|
||||||
|
import { ServerTemplateModel } from "./atlasData/serverTemplate.model";
|
||||||
|
|
||||||
export class ServerGridModel implements Deserialize {
|
export class ServerGridModel implements Deserialize {
|
||||||
// Server Argument Section
|
// Server Argument Section
|
||||||
|
|
@ -64,7 +65,7 @@ export class ServerGridModel implements Deserialize {
|
||||||
// ID Generator current values
|
// ID Generator current values
|
||||||
// Used for individual ship path
|
// Used for individual ship path
|
||||||
public shipPathsIdGenerator: number = 0;
|
public shipPathsIdGenerator: number = 0;
|
||||||
// Used for Discovery Zone IDs
|
// Used for Discovery Zone & Island IDs
|
||||||
public idGenerator: number = 0;
|
public idGenerator: number = 0;
|
||||||
// Unused as far as can see in ServerGridEditor
|
// Unused as far as can see in ServerGridEditor
|
||||||
public regionsIdGenerator: number = 0;
|
public regionsIdGenerator: number = 0;
|
||||||
|
|
@ -78,7 +79,8 @@ export class ServerGridModel implements Deserialize {
|
||||||
public globalGameplaySetup: GlobalGameplaySetupModel = new GlobalGameplaySetupModel();
|
public globalGameplaySetup: GlobalGameplaySetupModel = new GlobalGameplaySetupModel();
|
||||||
|
|
||||||
public DatabaseConnections: DatabaseConnectionModel[];
|
public DatabaseConnections: DatabaseConnectionModel[];
|
||||||
servers: ServerModel[];
|
public servers: ServerModel[];
|
||||||
|
public serverTemplates: ServerTemplateModel[];
|
||||||
|
|
||||||
public deserialize(input: any): this {
|
public deserialize(input: any): this {
|
||||||
Object.assign(this, input);
|
Object.assign(this, input);
|
||||||
|
|
@ -88,6 +90,11 @@ export class ServerGridModel implements Deserialize {
|
||||||
this.globalGameplaySetup = new GlobalGameplaySetupModel().deserialize(input.globalGameplaySetup);
|
this.globalGameplaySetup = new GlobalGameplaySetupModel().deserialize(input.globalGameplaySetup);
|
||||||
this.DatabaseConnections = this.DatabaseConnections.map(i => new DatabaseConnectionModel().deserialize(i));
|
this.DatabaseConnections = this.DatabaseConnections.map(i => new DatabaseConnectionModel().deserialize(i));
|
||||||
this.servers = this.servers.map(i => new ServerModel().deserialize(i));
|
this.servers = this.servers.map(i => new ServerModel().deserialize(i));
|
||||||
|
this.serverTemplates = this.serverTemplates.map(i => new ServerTemplateModel().deserialize(i));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getNextId() {
|
||||||
|
return ++this.idGenerator;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
<button class="btn btn-primary btn-block" [routerLink]="['grid']">Grid Settings</button>
|
<button class="btn btn-primary btn-block" [routerLink]="['grid']">Grid Settings</button>
|
||||||
<button class="btn btn-primary btn-block" [routerLink]="['dbs']">DB Settings</button>
|
<button class="btn btn-primary btn-block" [routerLink]="['dbs']">DB Settings</button>
|
||||||
<button class="btn btn-primary btn-block" [routerLink]="['quests']">Quest Settings</button>
|
<button class="btn btn-primary btn-block" [routerLink]="['quests']">Quest Settings</button>
|
||||||
|
<button class="btn btn-primary btn-block" [routerLink]="['servers']">Server Settings</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-10"><router-outlet></router-outlet></div>
|
<div class="col-10"><router-outlet></router-outlet></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -30,9 +30,9 @@
|
||||||
</ngb-panel>
|
</ngb-panel>
|
||||||
<ngb-panel id="toggle-urlSettings" title="URL Settings">
|
<ngb-panel id="toggle-urlSettings" title="URL Settings">
|
||||||
<ng-template ngbPanelContent>
|
<ng-template ngbPanelContent>
|
||||||
<app-text id="MetaWorldURL" label="Meta World URL" [(text)]="grid.MetaWorldURL"></app-text>
|
<app-text id="MetaWorldURL" label="Meta World URL" [(text)]="grid.MetaWorldURL" help="Used for an in game active map"></app-text>
|
||||||
<app-text id="AuthListURL" label="Auth List URL" [(text)]="grid.AuthListURL"></app-text>
|
<app-text id="AuthListURL" label="Auth List URL" [(text)]="grid.AuthListURL"></app-text>
|
||||||
<app-text id="MapImageURL" label="Map Image URL" [(text)]="grid.MapImageURL"></app-text>
|
<app-text id="MapImageURL" label="Map Image URL" [(text)]="grid.MapImageURL" help="Used for server listing and if Meta World URL is not defined"></app-text>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ngb-panel>
|
</ngb-panel>
|
||||||
<ngb-panel id="toggle-timeOptions" title="Time Settings">
|
<ngb-panel id="toggle-timeOptions" title="Time Settings">
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
<div class="mt-3">
|
||||||
|
<h2>{{ islandIndex }} - {{ server.islands[island.name].customDisplayName() }}
|
||||||
|
<button class="btn btn-primary btn-sm" [routerLink]="['/config', 'server', cellIndex]">Back to Cell</button>
|
||||||
|
</h2>
|
||||||
|
<p>{{ island.islandWidth }} by {{ island.islandHeight }}</p>
|
||||||
|
<ngb-accordion>
|
||||||
|
<ngb-panel title="General Settings">
|
||||||
|
<ng-template ngbPanelContent>
|
||||||
|
<app-number id="worldX" label="World X" [(number)]="island.worldX"></app-number>
|
||||||
|
<app-number id="worldY" label="World Y" [(number)]="island.worldY"></app-number>
|
||||||
|
<app-number id="rotation" label="Rotation" [(number)]="island.rotation" step="0.000001" min="{{ minRot }}" max="{{ maxRot }}"></app-number>
|
||||||
|
<app-number id="islandPoints" label="Island Points" [(number)]="island.islandPoints"></app-number>
|
||||||
|
<app-number id="spawnPointRegionOverride" label="Spawn Override"
|
||||||
|
[(number)]="island.spawnPointRegionOverride" min="-1"
|
||||||
|
help="Default -1. Set to 0 or more to allow for this island to be spawned on. Must be a unique, consecutive number across the server"></app-number>
|
||||||
|
</ng-template>
|
||||||
|
</ngb-panel>
|
||||||
|
<ngb-panel title="Treasure Settings">
|
||||||
|
<ng-template ngbPanelContent>
|
||||||
|
<app-number id="minTreasureQuality" label="Min Quality" [(number)]="island.minTreasureQuality"
|
||||||
|
help="Default -1. -1 means no limit"></app-number>
|
||||||
|
<app-number id="maxTreasureQuality" label="Max Quality" [(number)]="island.maxTreasureQuality"
|
||||||
|
help="Default -1. -1 means no limit"></app-number>
|
||||||
|
<app-checkbox id="useNpcVolumesForTreasures" label="Use NPC Volumes"
|
||||||
|
[(checkbox)]="island.useNpcVolumesForTreasures"
|
||||||
|
help="useNpcVolumesForTreasures"></app-checkbox>
|
||||||
|
<app-checkbox id="useLevelBoundsForTreasures" label="Use Level Bounds"
|
||||||
|
[(checkbox)]="island.useLevelBoundsForTreasures"
|
||||||
|
help="useLevelBoundsForTreasures"></app-checkbox>
|
||||||
|
<app-checkbox id="prioritizeVolumesForTreasures" label="Prioritise Volumes"
|
||||||
|
[(checkbox)]="island.prioritizeVolumesForTreasures"
|
||||||
|
help="prioritizeVolumesForTreasures"></app-checkbox>
|
||||||
|
<app-number id="instanceTreasureQualityMultiplier" label="Quality Multiplier"
|
||||||
|
[(number)]="island.instanceTreasureQualityMultiplier" min="0" step="0.000001"
|
||||||
|
help="Default 1"></app-number>
|
||||||
|
<app-number id="instanceTreasureQualityAddition" label="Quality Addition"
|
||||||
|
[(number)]="island.instanceTreasureQualityAddition" min="0" step="0.000001"
|
||||||
|
help="Default 0"></app-number>
|
||||||
|
</ng-template>
|
||||||
|
</ngb-panel>
|
||||||
|
<ngb-panel title="Spawn Settings">
|
||||||
|
<ng-template ngbPanelContent>
|
||||||
|
<app-number id="finalNPCLevelMultiplier" label="Level Multiplier"
|
||||||
|
[(number)]="island.finalNPCLevelMultiplier" min="0" step="0.000001"
|
||||||
|
help="Default 1"></app-number>
|
||||||
|
<app-number id="finalNPCLevelOffset" label="Level Addition"
|
||||||
|
[(number)]="island.finalNPCLevelOffset" min="0" step="0.000001"
|
||||||
|
help="Default 0"></app-number>
|
||||||
|
</ng-template>
|
||||||
|
</ngb-panel>
|
||||||
|
<ngb-panel title="Single Player Settings">
|
||||||
|
<ng-template ngbPanelContent>
|
||||||
|
<app-number id="singleSpawnPointX" label="X" [(number)]="island.singleSpawnPointX"></app-number>
|
||||||
|
<app-number id="singleSpawnPointY" label="Y" [(number)]="island.singleSpawnPointY"></app-number>
|
||||||
|
<app-number id="singleSpawnPointZ" label="Z" [(number)]="island.singleSpawnPointZ"></app-number>
|
||||||
|
</ng-template>
|
||||||
|
</ngb-panel>
|
||||||
|
<ngb-panel title="Treasure Locations">
|
||||||
|
<ng-template ngbPanelContent>
|
||||||
|
<div class="row" *ngFor="let treasurePos of island.treasureMapSpawnPoints; let i = index">
|
||||||
|
<div class="col-4">
|
||||||
|
<app-number id="{{ i }}-treasure-x" label="X" [(number)]="treasurePos.x"
|
||||||
|
step="0.000001"></app-number>
|
||||||
|
</div>
|
||||||
|
<div class="col-4">
|
||||||
|
<app-number id="{{ i }}-treasure-y" label="Y" [(number)]="treasurePos.y"
|
||||||
|
step="0.000001"></app-number>
|
||||||
|
</div>
|
||||||
|
<div class="col-4">
|
||||||
|
<app-number id="{{ i }}-treasure-z" label="Z" [(number)]="treasurePos.z" step="0.000001"
|
||||||
|
postButtonText="-" (postButton)="removeTreasureLocation(i)"></app-number>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
</ngb-panel>
|
||||||
|
<ngb-panel title="Pirate Camp Locations">
|
||||||
|
<ng-template ngbPanelContent>
|
||||||
|
<div class="row" *ngFor="let campPos of island.wildPirateCampSpawnPoints; let i = index">
|
||||||
|
<div class="col-4">
|
||||||
|
<app-number id="{{ i }}-camp-x" label="X" [(number)]="campPos.x" step="0.000001"></app-number>
|
||||||
|
</div>
|
||||||
|
<div class="col-4">
|
||||||
|
<app-number id="{{ i }}-camp-y" label="Y" [(number)]="campPos.y" step="0.000001"></app-number>
|
||||||
|
</div>
|
||||||
|
<div class="col-4">
|
||||||
|
<app-number id="{{ i }}-camp-z" label="Z" [(number)]="campPos.z" step="0.000001"
|
||||||
|
postButtonText="-" (postButton)="removeCampLocation(i)"></app-number>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
</ngb-panel>
|
||||||
|
</ngb-accordion>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { Server } from "../../../../server";
|
||||||
|
import { ServerModel } from "../../../../models/atlasData/server.model";
|
||||||
|
import { IslandInstanceModel } from "../../../../models/atlasData/island-instance.model";
|
||||||
|
import { ActivatedRoute } from "@angular/router";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-island-instance',
|
||||||
|
templateUrl: './island-instance.component.html'
|
||||||
|
})
|
||||||
|
export class IslandInstanceComponent implements OnInit {
|
||||||
|
private cell: ServerModel;
|
||||||
|
private cellIndex;
|
||||||
|
private island: IslandInstanceModel;
|
||||||
|
private islandIndex;
|
||||||
|
|
||||||
|
private minX: number;
|
||||||
|
private maxX: number;
|
||||||
|
private minY: number;
|
||||||
|
private maxY: number;
|
||||||
|
private minRot: number = 0;
|
||||||
|
private maxRot: number = 360;
|
||||||
|
|
||||||
|
constructor(private server: Server, private route: ActivatedRoute) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.cellIndex = this.route.snapshot.paramMap.get('index');
|
||||||
|
this.islandIndex = this.route.snapshot.paramMap.get('islandIndex');
|
||||||
|
this.cell = this.server.serverGrid.servers[this.cellIndex];
|
||||||
|
this.island = this.cell.islandInstances[this.islandIndex];
|
||||||
|
this.minX = this.cell.gridX * this.server.serverGrid.gridSize;
|
||||||
|
this.maxX = this.minX + this.server.serverGrid.gridSize;
|
||||||
|
this.minY = this.cell.gridY * this.server.serverGrid.gridSize;
|
||||||
|
this.maxY = this.minY + this.server.serverGrid.gridSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Issue with text arrays and editing jumps on each change.
|
||||||
|
trackByFn(index: any, item: any) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
private removeTreasureLocation(index: number) {
|
||||||
|
this.island.treasureMapSpawnPoints.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private removeCampLocation(index: number) {
|
||||||
|
this.island.wildPirateCampSpawnPoints.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
62
src/app/pages/config/servers/server/server.component.html
Normal file
62
src/app/pages/config/servers/server/server.component.html
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
<div class="mt-3">
|
||||||
|
<h2>{{ cell.name }}<em *ngIf="cell.name === '' || cell.name === undefined">No Name Set</em> - ({{ cell.gridX }}
|
||||||
|
, {{ cell.gridY }})</h2>
|
||||||
|
<ngb-accordion>
|
||||||
|
<ngb-panel title="General Settings">
|
||||||
|
<ng-template ngbPanelContent>
|
||||||
|
<app-text id="name" label="Name" [(text)]="cell.name"
|
||||||
|
help="Friendly name for this server. Can be blank"></app-text>
|
||||||
|
<app-number id="gridX" label="Grid X" [(number)]="cell.gridX"
|
||||||
|
help="X position in the Grid. 0 Indexed"></app-number>
|
||||||
|
<app-number id="gridY" label="Grid Y" [(number)]="cell.gridY"
|
||||||
|
help="Y position in the Grid. 0 Indexed"></app-number>
|
||||||
|
<app-checkbox id="isHomeServer" label="Home Server" [(checkbox)]="cell.isHomeServer"
|
||||||
|
help="Whether this cell can be used for players with no beds"></app-checkbox>
|
||||||
|
<app-number id="utcOffset" label="UTC Offset" [(number)]="cell.utcOffset"
|
||||||
|
help="Cell specific UTC offset"></app-number>
|
||||||
|
<app-select-list id="serverTemplate" label="Template" [optionList]="templateOptions"
|
||||||
|
[withEmptyOption]="true" [(option)]="cell.serverTemplateName"
|
||||||
|
help="Set base Server Template for Common Options"></app-select-list>
|
||||||
|
</ng-template>
|
||||||
|
</ngb-panel>
|
||||||
|
<ngb-panel title="Connection Settings">
|
||||||
|
<ng-template ngbPanelContent>
|
||||||
|
<app-text id="ip" label="IP" [(text)]="cell.ip" help="IP address of host this cell is on"></app-text>
|
||||||
|
<app-number id="port" label="Port" [(number)]="cell.port"
|
||||||
|
help="Port used for inter cell communication"></app-number>
|
||||||
|
<app-number id="gamePort" label="Game Port" [(number)]="cell.gamePort"
|
||||||
|
help="Port used for external UE4 traffic"></app-number>
|
||||||
|
<app-number id="seamlessDataPort" label="Seamless Port" [(number)]="cell.seamlessDataPort"
|
||||||
|
help="Used for transferring map images when no MetaWorldURL set"></app-number>
|
||||||
|
</ng-template>
|
||||||
|
</ngb-panel>
|
||||||
|
<ngb-panel title="Gameplay Settings">
|
||||||
|
<ng-template ngbPanelContent>
|
||||||
|
<app-number id="floorZDist" label="Z Floor Height" [(number)]="cell.floorZDist"></app-number>
|
||||||
|
<app-number id="transitionMinZ" label="Minimum Z Transition"
|
||||||
|
[(number)]="cell.transitionMinZ"></app-number>
|
||||||
|
<app-number id="serverIslandPointsMultiplier" label="Island Points Multiplier"
|
||||||
|
[(number)]="cell.serverIslandPointsMultiplier" help="Default 1.0"></app-number>
|
||||||
|
</ng-template>
|
||||||
|
</ngb-panel>
|
||||||
|
<ngb-panel title="Colour & Style Settings">
|
||||||
|
<ng-template ngbPanelContent>
|
||||||
|
<app-number id="waterColorR" label="Water Red" [(number)]="cell.waterColorR"></app-number>
|
||||||
|
<app-number id="waterColorG" label="Water Green" [(number)]="cell.waterColorG"></app-number>
|
||||||
|
<app-number id="waterColorB" label="Water Blue" [(number)]="cell.waterColorB"></app-number>
|
||||||
|
<app-number id="skyStyleIndex" label="Sky Style Index" [(number)]="cell.skyStyleIndex"></app-number>
|
||||||
|
</ng-template>
|
||||||
|
</ngb-panel>
|
||||||
|
<ngb-panel title="Island Settings">
|
||||||
|
<ng-template ngbPanelContent>
|
||||||
|
<p><em>Note that Sublevel settings are sorted in the background</em></p>
|
||||||
|
<div *ngFor="let island of cell.islandInstances; let i = index">
|
||||||
|
<h4>Island Instance {{ i }} - ID {{ island.id }} <button class="btn btn-sm btn-primary" [routerLink]="['island', i]">Edit</button></h4>
|
||||||
|
<app-select-object id="{{ i }}-island-name" label="Island Model" [optionObject]="islandOptions"
|
||||||
|
[option]="island.name" (optionChange)="changeIslandModel(i, $event)"></app-select-object>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
</ngb-panel>
|
||||||
|
</ngb-accordion>
|
||||||
|
<p>{{ cell | json }}</p>
|
||||||
|
</div>
|
||||||
78
src/app/pages/config/servers/server/server.component.ts
Normal file
78
src/app/pages/config/servers/server/server.component.ts
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from "@angular/router";
|
||||||
|
import { Server } from "../../../../server";
|
||||||
|
import { ServerModel } from "../../../../models/atlasData/server.model";
|
||||||
|
import { IslandDataModel } from "../../../../../data/models/island-data.model";
|
||||||
|
import { IslandInstanceModel } from "../../../../models/atlasData/island-instance.model";
|
||||||
|
import { ServerSublevelModel } from "../../../../models/atlasData/serverSublevel.model";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-server',
|
||||||
|
templateUrl: './server.component.html'
|
||||||
|
})
|
||||||
|
export class ServerComponent implements OnInit {
|
||||||
|
private cell: ServerModel;
|
||||||
|
private templateOptions: string[];
|
||||||
|
private islandOptions: object = {};
|
||||||
|
|
||||||
|
constructor(private server: Server, private route: ActivatedRoute) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
let index = this.route.snapshot.paramMap.get('index');
|
||||||
|
this.cell = this.server.serverGrid.servers[index];
|
||||||
|
this.templateOptions = this.server.serverGrid.serverTemplates.map(i => i.name);
|
||||||
|
Object.values(this.server.islands).forEach((i: IslandDataModel) => this.islandOptions[i.name] = i.customDisplayName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private changeIslandModel(index: number, name: string) {
|
||||||
|
let oldIsland = this.cell.islandInstances[index];
|
||||||
|
const newIslandData = this.server.islands[name];
|
||||||
|
const oldIslandData = this.server.islands[oldIsland.name];
|
||||||
|
|
||||||
|
let newIsland = IslandInstanceModel.fromIslandData(newIslandData);
|
||||||
|
|
||||||
|
// keep X, Y and Rotation the same
|
||||||
|
newIsland.worldX = oldIsland.worldX;
|
||||||
|
newIsland.worldY = oldIsland.worldY;
|
||||||
|
newIsland.rotation = oldIsland.rotation;
|
||||||
|
|
||||||
|
// Remove old Sublevels
|
||||||
|
oldIslandData.sublevelNames.forEach(i => {
|
||||||
|
const j = this.cell.sublevels.findIndex(sublevel => sublevel.name === i);
|
||||||
|
if (j > -1) {
|
||||||
|
this.cell.sublevels.splice(j, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get new unique ID
|
||||||
|
newIsland.id = this.server.serverGrid.getNextId();
|
||||||
|
|
||||||
|
// Add new Sublevels
|
||||||
|
newIslandData.sublevelNames.forEach(i => {
|
||||||
|
let newSublevel = new ServerSublevelModel();
|
||||||
|
newSublevel.name = i;
|
||||||
|
newSublevel.setupFromIsland(newIsland, newIslandData, this.cell, this.server.serverGrid);
|
||||||
|
this.cell.sublevels.push(newSublevel);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.cell.islandInstances[index] = newIsland;
|
||||||
|
|
||||||
|
this.updateExtraSublevels();
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateExtraSublevels() {
|
||||||
|
// Extra Sublevels can be identical across multiple islands,
|
||||||
|
// so need to merge any changes. Easiest to just merge through
|
||||||
|
// all of the available islands instead.
|
||||||
|
this.cell.totalExtraSublevels = [];
|
||||||
|
this.cell.islandInstances.forEach(i => {
|
||||||
|
const islandData = this.server.islands[i.name];
|
||||||
|
islandData.extraSublevels.forEach(j => {
|
||||||
|
if (this.cell.totalExtraSublevels.indexOf(j) === -1) {
|
||||||
|
this.cell.totalExtraSublevels.push(j);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
24
src/app/pages/config/servers/servers.component.html
Normal file
24
src/app/pages/config/servers/servers.component.html
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<div class="mt-3 mb-3">
|
||||||
|
<h2>Cell Grid</h2>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th *ngFor="let x of xArray">{{ x }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody *ngFor="let y of xArray">
|
||||||
|
<tr>
|
||||||
|
<th>{{ y }}</th>
|
||||||
|
<td *ngFor="let x of xArray"><a
|
||||||
|
[routerLink]="['/config','server', serverLookup[x][y]]">{{ serverLookup[x][y] }}</a></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<h2 *ngIf="unknownServers.length > 0">Cells Outside Grid</h2>
|
||||||
|
<button class="btn btn-warning" *ngFor="let u of unknownServers">{{ u }}</button>
|
||||||
|
<h2>Server Templates</h2>
|
||||||
|
<p>Allows for modifying or applying settings to multiple servers at the same time. Mostly useful for environmental
|
||||||
|
changes, rather than Island position</p>
|
||||||
|
<button class="btn btn-primary" *ngFor="let template of grid.serverTemplates">{{ template.name }}</button>
|
||||||
|
</div>
|
||||||
35
src/app/pages/config/servers/servers.component.ts
Normal file
35
src/app/pages/config/servers/servers.component.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { Server } from "../../../server";
|
||||||
|
import { ServerGridModel } from "../../../models/serverGrid.model";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-servers',
|
||||||
|
templateUrl: './servers.component.html'
|
||||||
|
})
|
||||||
|
export class ServersComponent implements OnInit {
|
||||||
|
private grid: ServerGridModel;
|
||||||
|
|
||||||
|
private xArray: number[];
|
||||||
|
private yArray: number[];
|
||||||
|
|
||||||
|
private serverLookup: number[][] = [];
|
||||||
|
private unknownServers: number[] = [];
|
||||||
|
|
||||||
|
constructor(private server: Server) {
|
||||||
|
this.grid = server.serverGrid;
|
||||||
|
this.xArray = Array.from(Array(this.grid.totalGridsX).keys());
|
||||||
|
this.yArray = Array.from(Array(this.grid.totalGridsY).keys());
|
||||||
|
this.grid.servers.forEach((i, index) => {
|
||||||
|
if (i.gridX < this.grid.totalGridsX && i.gridY < this.grid.totalGridsY) {
|
||||||
|
if (this.serverLookup[i.gridX] === undefined)
|
||||||
|
this.serverLookup[i.gridX] = [];
|
||||||
|
this.serverLookup[i.gridX][i.gridY] = index;
|
||||||
|
} else {
|
||||||
|
this.unknownServers.push(index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
<p>template works!</p>
|
||||||
14
src/app/pages/config/servers/template/template.component.ts
Normal file
14
src/app/pages/config/servers/template/template.component.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-template',
|
||||||
|
templateUrl: './template.component.html'
|
||||||
|
})
|
||||||
|
export class TemplateComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,11 +1,21 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { ServerGridModel } from "./models/serverGrid.model";
|
import { ServerGridModel } from "./models/serverGrid.model";
|
||||||
|
import * as islandData from '../data/islands.json';
|
||||||
|
import { IslandDataModel } from "../data/models/island-data.model";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class Server {
|
export class Server {
|
||||||
private rawData: string = "";
|
private rawData: string = "";
|
||||||
private jsonData: object = {};
|
private jsonData: object = {};
|
||||||
public serverGrid: ServerGridModel = new ServerGridModel();
|
public serverGrid: ServerGridModel = new ServerGridModel();
|
||||||
|
public islands;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.islands = (islandData as any).default;
|
||||||
|
Object.keys(this.islands).forEach(i => {
|
||||||
|
this.islands[i] = new IslandDataModel().deserialize(this.islands[i])
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public load(raw) {
|
public load(raw) {
|
||||||
this.rawData = raw;
|
this.rawData = raw;
|
||||||
|
|
|
||||||
|
|
@ -34,12 +34,6 @@ export class PegjsService {
|
||||||
if(!skip && typeof input === 'object' && typeof input.toJSON === 'function') {
|
if(!skip && typeof input === 'object' && typeof input.toJSON === 'function') {
|
||||||
input = input.toJSON();
|
input = input.toJSON();
|
||||||
}
|
}
|
||||||
// if(input !== undefined && input.hasOwnProperty('toJSON') && typeof input.toJSON === 'function') {
|
|
||||||
// console.log("calling toJSON!");
|
|
||||||
// console.log(input);
|
|
||||||
// input = input.toJSON();
|
|
||||||
// console.log(input);
|
|
||||||
// }
|
|
||||||
switch (typeof input) {
|
switch (typeof input) {
|
||||||
case "object":
|
case "object":
|
||||||
return PegjsService.deparseObject(input);
|
return PegjsService.deparseObject(input);
|
||||||
|
|
|
||||||
21199
src/data/islands.json
Normal file
21199
src/data/islands.json
Normal file
File diff suppressed because it is too large
Load diff
75
src/data/models/island-data.model.ts
Normal file
75
src/data/models/island-data.model.ts
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
import { Deserialize } from "../../app/models/util/deserialize.model";
|
||||||
|
import { IslandInstanceModel } from "../../app/models/atlasData/island-instance.model";
|
||||||
|
|
||||||
|
export class IslandDataModel implements Deserialize {
|
||||||
|
name: string;
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
imagePath: string;
|
||||||
|
landscapeMaterialOverride: number;
|
||||||
|
sublevelNames: string[];
|
||||||
|
spawnerOverrides: object;
|
||||||
|
extraSublevels: string[];
|
||||||
|
treasureMapSpawnPoints: string[];
|
||||||
|
wildPirateCampSpawnPoints: string[];
|
||||||
|
minTreasureQuality: number;
|
||||||
|
maxTreasureQuality: number;
|
||||||
|
useNpcVolumesForTreasures: boolean;
|
||||||
|
useLevelBoundsForTreasures: boolean;
|
||||||
|
prioritizeVolumesForTreasures: boolean;
|
||||||
|
islandTreasureBottleSupplyCrateOverrides: string;
|
||||||
|
islandPoints: number;
|
||||||
|
singleSpawnPointX: number;
|
||||||
|
singleSpawnPointY: number;
|
||||||
|
singleSpawnPointZ: number;
|
||||||
|
|
||||||
|
// De-parsed from the name
|
||||||
|
islandType: string;
|
||||||
|
islandShape: string;
|
||||||
|
climate: string;
|
||||||
|
variant: string;
|
||||||
|
|
||||||
|
private _climateLookup = {
|
||||||
|
CH: "High Desert",
|
||||||
|
CL: "Low Desert",
|
||||||
|
CP: "Polar",
|
||||||
|
EE: "Equatorial",
|
||||||
|
ET: "Eastern Temperate",
|
||||||
|
PO: "Polar",
|
||||||
|
TR: "Tropical",
|
||||||
|
WF: "West Temperate",
|
||||||
|
WR: "West Tropical",
|
||||||
|
WT: "West Temperate",
|
||||||
|
WU: "West Tundra",
|
||||||
|
ER: "East Tropical",
|
||||||
|
EU: "East Tundra",
|
||||||
|
BO: "Tropical",
|
||||||
|
CU: "Central Tundra"
|
||||||
|
};
|
||||||
|
|
||||||
|
private _variantLookup = {
|
||||||
|
E: 'Freeport',
|
||||||
|
PVE: 'Event'
|
||||||
|
};
|
||||||
|
|
||||||
|
deserialize(input: any): this {
|
||||||
|
Object.assign(this, input);
|
||||||
|
|
||||||
|
const parsedName = this.name.split('_');
|
||||||
|
|
||||||
|
this.islandType = parsedName[0];
|
||||||
|
this.islandShape = parsedName[1];
|
||||||
|
this.climate = this._climateLookup[parsedName[2]];
|
||||||
|
this.variant = parsedName[3] === undefined
|
||||||
|
? 'Original'
|
||||||
|
: this._variantLookup[parsedName[3]] === undefined
|
||||||
|
? parsedName[3]
|
||||||
|
: this._variantLookup[parsedName[3]];
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
customDisplayName(): string {
|
||||||
|
return `${this.islandType} (${this.islandShape}) - ${this.climate} (${this.variant})`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4286,7 +4286,8 @@
|
||||||
"-16669.841797 55933.304688 1444.562378",
|
"-16669.841797 55933.304688 1444.562378",
|
||||||
"-18995.958984 47324.730469 1258.232178",
|
"-18995.958984 47324.730469 1258.232178",
|
||||||
"-23460.324219 32488.488281 1052.984497",
|
"-23460.324219 32488.488281 1052.984497",
|
||||||
"-14030.736328 27910.121094 1495.687866-18530.439453 13729.532227 2932.062500",
|
"-14030.736328 27910.121094 1495.687866",
|
||||||
|
"-18530.439453 13729.532227 2932.062500",
|
||||||
"-880.893738 1638.657349 1831.594482",
|
"-880.893738 1638.657349 1831.594482",
|
||||||
"-16750.998047 -20462.853516 1201.228882",
|
"-16750.998047 -20462.853516 1201.228882",
|
||||||
"-24870.738281 -38881.835938 843.451538",
|
"-24870.738281 -38881.835938 843.451538",
|
||||||
|
|
@ -4335,7 +4336,8 @@
|
||||||
"-16669.841797 55933.304688 1444.562378",
|
"-16669.841797 55933.304688 1444.562378",
|
||||||
"-18995.958984 47324.730469 1258.232178",
|
"-18995.958984 47324.730469 1258.232178",
|
||||||
"-23460.324219 32488.488281 1052.984497",
|
"-23460.324219 32488.488281 1052.984497",
|
||||||
"-14030.736328 27910.121094 1495.687866-18530.439453 13729.532227 2932.062500",
|
"-14030.736328 27910.121094 1495.687866",
|
||||||
|
"-18530.439453 13729.532227 2932.062500",
|
||||||
"-880.893738 1638.657349 1831.594482",
|
"-880.893738 1638.657349 1831.594482",
|
||||||
"-16750.998047 -20462.853516 1201.228882",
|
"-16750.998047 -20462.853516 1201.228882",
|
||||||
"-24870.738281 -38881.835938 843.451538",
|
"-24870.738281 -38881.835938 843.451538",
|
||||||
|
|
@ -4384,7 +4386,8 @@
|
||||||
"-16669.841797 55933.304688 1444.562378",
|
"-16669.841797 55933.304688 1444.562378",
|
||||||
"-18995.958984 47324.730469 1258.232178",
|
"-18995.958984 47324.730469 1258.232178",
|
||||||
"-23460.324219 32488.488281 1052.984497",
|
"-23460.324219 32488.488281 1052.984497",
|
||||||
"-14030.736328 27910.121094 1495.687866-18530.439453 13729.532227 2932.062500",
|
"-14030.736328 27910.121094 1495.687866",
|
||||||
|
"-18530.439453 13729.532227 2932.062500",
|
||||||
"-880.893738 1638.657349 1831.594482",
|
"-880.893738 1638.657349 1831.594482",
|
||||||
"-16750.998047 -20462.853516 1201.228882",
|
"-16750.998047 -20462.853516 1201.228882",
|
||||||
"-24870.738281 -38881.835938 843.451538",
|
"-24870.738281 -38881.835938 843.451538",
|
||||||
|
|
@ -4433,7 +4436,8 @@
|
||||||
"-16669.841797 55933.304688 1444.562378",
|
"-16669.841797 55933.304688 1444.562378",
|
||||||
"-18995.958984 47324.730469 1258.232178",
|
"-18995.958984 47324.730469 1258.232178",
|
||||||
"-23460.324219 32488.488281 1052.984497",
|
"-23460.324219 32488.488281 1052.984497",
|
||||||
"-14030.736328 27910.121094 1495.687866-18530.439453 13729.532227 2932.062500",
|
"-14030.736328 27910.121094 1495.687866",
|
||||||
|
"-18530.439453 13729.532227 2932.062500",
|
||||||
"-880.893738 1638.657349 1831.594482",
|
"-880.893738 1638.657349 1831.594482",
|
||||||
"-16750.998047 -20462.853516 1201.228882",
|
"-16750.998047 -20462.853516 1201.228882",
|
||||||
"-24870.738281 -38881.835938 843.451538",
|
"-24870.738281 -38881.835938 843.451538",
|
||||||
|
|
@ -7157,7 +7161,8 @@
|
||||||
"-16669.841797 55933.304688 1444.562378",
|
"-16669.841797 55933.304688 1444.562378",
|
||||||
"-18995.958984 47324.730469 1258.232178",
|
"-18995.958984 47324.730469 1258.232178",
|
||||||
"-23460.324219 32488.488281 1052.984497",
|
"-23460.324219 32488.488281 1052.984497",
|
||||||
"-14030.736328 27910.121094 1495.687866-18530.439453 13729.532227 2932.062500",
|
"-14030.736328 27910.121094 1495.687866",
|
||||||
|
"-18530.439453 13729.532227 2932.062500",
|
||||||
"-880.893738 1638.657349 1831.594482",
|
"-880.893738 1638.657349 1831.594482",
|
||||||
"-16750.998047 -20462.853516 1201.228882",
|
"-16750.998047 -20462.853516 1201.228882",
|
||||||
"-24870.738281 -38881.835938 843.451538",
|
"-24870.738281 -38881.835938 843.451538",
|
||||||
|
|
@ -7206,7 +7211,8 @@
|
||||||
"-16669.841797 55933.304688 1444.562378",
|
"-16669.841797 55933.304688 1444.562378",
|
||||||
"-18995.958984 47324.730469 1258.232178",
|
"-18995.958984 47324.730469 1258.232178",
|
||||||
"-23460.324219 32488.488281 1052.984497",
|
"-23460.324219 32488.488281 1052.984497",
|
||||||
"-14030.736328 27910.121094 1495.687866-18530.439453 13729.532227 2932.062500",
|
"-14030.736328 27910.121094 1495.687866",
|
||||||
|
"-18530.439453 13729.532227 2932.062500",
|
||||||
"-880.893738 1638.657349 1831.594482",
|
"-880.893738 1638.657349 1831.594482",
|
||||||
"-16750.998047 -20462.853516 1201.228882",
|
"-16750.998047 -20462.853516 1201.228882",
|
||||||
"-24870.738281 -38881.835938 843.451538",
|
"-24870.738281 -38881.835938 843.451538",
|
||||||
|
|
@ -7255,7 +7261,8 @@
|
||||||
"-16669.841797 55933.304688 1444.562378",
|
"-16669.841797 55933.304688 1444.562378",
|
||||||
"-18995.958984 47324.730469 1258.232178",
|
"-18995.958984 47324.730469 1258.232178",
|
||||||
"-23460.324219 32488.488281 1052.984497",
|
"-23460.324219 32488.488281 1052.984497",
|
||||||
"-14030.736328 27910.121094 1495.687866-18530.439453 13729.532227 2932.062500",
|
"-14030.736328 27910.121094 1495.687866",
|
||||||
|
"-18530.439453 13729.532227 2932.062500",
|
||||||
"-880.893738 1638.657349 1831.594482",
|
"-880.893738 1638.657349 1831.594482",
|
||||||
"-16750.998047 -20462.853516 1201.228882",
|
"-16750.998047 -20462.853516 1201.228882",
|
||||||
"-24870.738281 -38881.835938 843.451538",
|
"-24870.738281 -38881.835938 843.451538",
|
||||||
|
|
@ -7304,7 +7311,8 @@
|
||||||
"-16669.841797 55933.304688 1444.562378",
|
"-16669.841797 55933.304688 1444.562378",
|
||||||
"-18995.958984 47324.730469 1258.232178",
|
"-18995.958984 47324.730469 1258.232178",
|
||||||
"-23460.324219 32488.488281 1052.984497",
|
"-23460.324219 32488.488281 1052.984497",
|
||||||
"-14030.736328 27910.121094 1495.687866-18530.439453 13729.532227 2932.062500",
|
"-14030.736328 27910.121094 1495.687866",
|
||||||
|
"-18530.439453 13729.532227 2932.062500",
|
||||||
"-880.893738 1638.657349 1831.594482",
|
"-880.893738 1638.657349 1831.594482",
|
||||||
"-16750.998047 -20462.853516 1201.228882",
|
"-16750.998047 -20462.853516 1201.228882",
|
||||||
"-24870.738281 -38881.835938 843.451538",
|
"-24870.738281 -38881.835938 843.451538",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue