From b5b2ee527629349b12556fc1cf763af88c5f3fd3 Mon Sep 17 00:00:00 2001 From: ConMaster2112 Date: Sun, 6 Aug 2023 14:36:02 +0200 Subject: [PATCH] Dual instance security! --- README.md | 17 +++++++++++---- database.d.ts | 14 ++++++++----- database.js | 44 +++++++++++++++++++++++++++------------ packs/BP/manifest.json | 2 +- packs/BP/scripts/index.js | 4 +++- 5 files changed, 57 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index b0ae3cf..674d020 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,13 @@ Each of these database types supports all possible [Map](https://developer.mozil - entries(): generator of all values [key, value] - forEach(callBack: (value, key, this)=>void): for each all elements and call provided function for that - get(key: string): returns value for specific key - - set(key: string, value: any): sets new value for provided key + - set(key: string: value: any): sets new value for provided key + - has(key: string): returns true when database has a value for that key - keys(): returns iterbale of keys - values(): returns iterable of values ### Additional Methods - load(): will load database from provided scoreboard - - loadAsync(): will load database asynchonously from profived scoreboard + - loadAsync(): will load database asynchonously from provided scoreboard - rebuild(): when database is deleted by user in the world you can call rebuild to save loaded data without lost - rebuildAsync(): same as rebuild() but asyncronouse ### Additional Properties @@ -32,12 +33,20 @@ Each of these database types supports all possible [Map](https://developer.mozil - NBTDatabase, is saving data in NBT form. (Fast/HardToRead) - Custom, is saving data in format of provided parser (undefined/undefined) +### Dual instance security! +```js +const myDB1 = new JsonDatabase("sameId"); +const myDB2 = new NBTDatabase("sameId"); //returns JsonDatabase because database with same id "sameId" was already created. + +console.log(myDB1 === myDB2); //true the very same instance! +``` + ### Example ```js // INITIALIZATION OF DATABASE const myDB = new JsonDatabase("MyIdentifier").load(); -const myDB = new NBTDatabase("MyIdentifier").load(); -const myDB = new CustomDatabase(JSON /* JSON is parser */,"MyIdentifier").load(); +const myDB = new NBTDatabase("MyIdentifier2").load(); +const myDB = new CustomDatabase(JSON /* JSON is parser */,"MyIdentifier3").load(); //using (get/set) to (read/write) data (from/to) database const worldOpenedCount = myDB.get("openCount")??0; diff --git a/database.d.ts b/database.d.ts index 1462d97..ca76b70 100644 --- a/database.d.ts +++ b/database.d.ts @@ -149,18 +149,18 @@ export enum ChangeAction { /**@extends {Map}*/ declare class ScoreboardDatabaseManager extends Map{ private _saveMode_: DatabaseSavingModes; + private _loadingPromise_?: Promise; private hasChanges: boolean; - readonly maxLength: number; private readonly _scoreboard_: ScoreboardObjective; protected readonly _source_: Map; protected readonly _parser_: {stringify:(data: any)=>string,parse:(data: string)=>any}; - readonly savingMode: DatabaseSavingModes; - constructor(objective, saveMode: DatabaseSavingModes); - constructor(objective, saveMode: DatabaseSavingModes.EndTickSave, interval?: number); + constructor(objective: string | ScoreboardObjective, saveMode?: DatabaseSavingModes); + constructor(objective: string | ScoreboardObjective, saveMode: DatabaseSavingModes.EndTickSave, interval?: number); /**@inheritdoc */ set(key: string, value: any): this /**@inheritdoc */ delete(key: string): boolean + /**@inheritdoc */ clear(): void load(): this loadAsync(): Promise @@ -169,10 +169,14 @@ declare class ScoreboardDatabaseManager extends Map{ readonly objective: ScoreboardObjective readonly id: string; readonly loaded: boolean; + readonly maxLength: number; + readonly savingMode: DatabaseSavingModes; + readonly type: "DefualtJsonType"| "JsonType"| "NBTType" | "CustomType"; + readonly loadingAwaiter: Promise; } export class JsonDatabase extends ScoreboardDatabaseManager{} export class NBTDatabase extends ScoreboardDatabaseManager{} export class CustomDatabase extends ScoreboardDatabaseManager{ - constructor(parser: {parse:(data:string)=>any,stringify:(data: any)=>string}, objective: string | ScoreboardObjective, saveMode: DatabaseSavingModes); + constructor(parser: {parse:(data:string)=>any,stringify:(data: any)=>string}, objective: string | ScoreboardObjective, saveMode?: DatabaseSavingModes); constructor(parser: {parse:(data:string)=>any,stringify:(data: any)=>string}, objective: string | ScoreboardObjective, saveMode: DatabaseSavingModes.EndTickSave, interval?: number); } \ No newline at end of file diff --git a/database.js b/database.js index 824c773..73f2c92 100644 --- a/database.js +++ b/database.js @@ -428,6 +428,9 @@ NBTReaderOptions.prototype.readers = defualtReaders; // DATABASE.JS /////////////////////////////////////////////////// const {scoreboard} = world, {FakePlayer} = ScoreboardIdentityType; + +const databases = new Map(); + const split = "\n_`Split`_\n"; function endTickCall(callback){ system.run(()=>system.run(()=>system.run(callback))); @@ -481,13 +484,14 @@ class ScoreboardDatabaseManager extends Map{ _saveMode_; /**@private */ hasChanges = false; + /**@private */ + _loadingPromise_; /**@readonly */ get maxLength(){return 30e3;} /**@private @type {ScoreboardObjective}*/ _scoreboard_; /**@protected @type {Map} */ _source_; - _onHandleLost_; /**@protected @readonly @type {{stringify:(data: any)=>string,parse:(data: string): any}} */ get _parser_(){return JSON;} get savingMode(){return this._saveMode_;} @@ -500,6 +504,7 @@ class ScoreboardDatabaseManager extends Map{ if(!objective) throw new RangeError("Firt parameter si not valid: " + objective); if(typeof objective !== "string" && !objective instanceof ScoreboardObjective) throw new RangeError("Firt parameter si not valid: " + objective); this._scoreboard_ = typeof objective === "string"?(scoreboard.getObjective(objective)??scoreboard.addObjective(objective,objective)):objective; + if(databases.has(this.id)) return databases.get(this.id); this._nameId_ = this.id; this._source_ = new Map(); this._changes_ = new Map(); @@ -514,6 +519,7 @@ class ScoreboardDatabaseManager extends Map{ } },this.interval); } + databases.set(this.id,this); } load(){ if(this._loaded_) return this; @@ -527,17 +533,21 @@ class ScoreboardDatabaseManager extends Map{ this._loaded_=true; return this; } - async loadAsync(){ - if(this._loaded_) return this; - for (const participant of this._scoreboard_.getParticipants()) { - const {displayName,type} = participant; - if(type !== FakePlayer) continue; - const [name,data] = displayName.split(split); - this._source_.set(name,participant); - super.set(name,this._parser_.parse(data)); - } - this._loaded_=true; - return this; + loadAsync(){ + if(this._loaded_) return this._loadingPromise_??Promise.resolve(this); + const promise = (async ()=>{ + for (const participant of this._scoreboard_.getParticipants()) { + const {displayName,type} = participant; + if(type !== FakePlayer) continue; + const [name,data] = displayName.split(split); + this._source_.set(name,participant); + super.set(name,this._parser_.parse(data)); + } + this._loaded_=true; + return this; + })(); + this._loadingPromise_ = promise; + return promise; } /**@inheritdoc */ set(key, value){ @@ -554,6 +564,7 @@ class ScoreboardDatabaseManager extends Map{ this._onChange_(key,null,ChangeAction.Remove); return super.delete(key); } + /**@inheritdoc */ clear(){ if(!this._loaded_) throw new ReferenceError("Database is not loaded"); for (const [key,value] of this.entries()) this.delete(key,value); @@ -569,6 +580,9 @@ class ScoreboardDatabaseManager extends Map{ get id(){return this._scoreboard_.id;} /**@readonly @returns {boolean} */ get loaded(){return this._loaded_;} + /**@readonly @returns {DefualtJsonType} */ + get type(){return "DefualtJsonType";} + get loadingAwaiter(){return this._loadingPromise_??this.loadAsync();} rebuild(){ if(this.objective?.isValid()) return; const newScores = scoreboard.addObjective(this._nameId_,this._nameId_); @@ -595,15 +609,19 @@ class ScoreboardDatabaseManager extends Map{ return this; } } -export class JsonDatabase extends ScoreboardDatabaseManager{} +export class JsonDatabase extends ScoreboardDatabaseManager{ + get type(){return "JsonType";} +} export class NBTDatabase extends ScoreboardDatabaseManager{ get _parser_() {return NBT;}; + get type(){return "NBTType";} } export class CustomDatabase extends ScoreboardDatabaseManager{ constructor(parser,...params){ super(params); this._parser_ = parser; } + get type(){return "CustomType";} } function generateRandomString(length) { let result = ''; diff --git a/packs/BP/manifest.json b/packs/BP/manifest.json index 30b9d1c..5585373 100644 --- a/packs/BP/manifest.json +++ b/packs/BP/manifest.json @@ -16,7 +16,7 @@ } ], "dependencies": [ - {"module_name": "@minecraft/server","version": "1.5.0-beta"}, + {"module_name": "@minecraft/server","version": "1.6.0-beta"}, {"module_name": "@minecraft/server-ui","version": "1.2.0-beta"} ], "capabilities": ["script_eval"] diff --git a/packs/BP/scripts/index.js b/packs/BP/scripts/index.js index 2b846e2..22902a5 100644 --- a/packs/BP/scripts/index.js +++ b/packs/BP/scripts/index.js @@ -1,7 +1,9 @@ -import { DatabaseSavingModes, NBTDatabase } from "db"; +import { DatabaseSavingModes, NBTDatabase, JsonDatabase } from "database"; const a = new NBTDatabase("sus2",DatabaseSavingModes.OneTimeSave,50).load(); +const b = new JsonDatabase("sus2"); +console.warn(a === b); a.set("sussy",{jerremy:(a.get("sussy")?.jerremy??0) + 1}); console.warn("Current sussy count is " + a.get("sussy").jerremy); \ No newline at end of file