Filterable attributes, Int64 entity

This commit is contained in:
barsdeveloper
2023-01-03 22:53:17 +01:00
parent f4ebfa488a
commit a16481194c
21 changed files with 401 additions and 214 deletions

View File

@@ -3,25 +3,18 @@ import IntegerEntity from "./IntegerEntity"
export default class ByteEntity extends IntegerEntity {
static attributes = {
value: 0,
...super.attributes,
value: {
...super.attributes.value,
predicate: v => v % 1 == 0 && v >= 0 && v < 1 << 8,
},
}
static {
this.cleanupAttributes(this.attributes)
}
/** @param {Object | Number | String} values */
constructor(values = 0) {
super(values)
const value = Math.round(this.value)
this.value = value >= 0 && value < 1 << 8 ? value : 0
}
valueOf() {
return this.value
}
toString() {
return this.value.toString()
}
}

View File

@@ -6,7 +6,7 @@ import Utility from "../Utility"
/**
* @typedef {(entity: IEntity) => AnyValue} ValueSupplier
* @typedef {(entity: IEntity) => AnyValueConstructor<AnyValue>} TypeSupplier
* @typedef {IEntity | String | Number | Boolean} AnySimpleValue
* @typedef {IEntity | String | Number | BigInt | Boolean} AnySimpleValue
* @typedef {AnySimpleValue | AnySimpleValue[]} AnyValue
* @typedef {{
* [key: String]: AttributeInformation | AnyValue | SubAttributesDeclaration
@@ -19,12 +19,13 @@ import Utility from "../Utility"
* nullable?: Boolean,
* ignored?: Boolean,
* serialized?: Boolean,
* predicate?: (value: AnyValue) => Boolean,
* }} AttributeInformation
*/
/**
* @template {AnyValue} T
* @typedef {(new () => T) | EntityConstructor | StringConstructor | NumberConstructor | BooleanConstructor | ArrayConstructor} AnyValueConstructor
* @typedef {(new () => T) | EntityConstructor | StringConstructor | NumberConstructor | BigIntConstructor | BooleanConstructor | ArrayConstructor} AnyValueConstructor
*/
export default class IEntity {
@@ -46,8 +47,9 @@ export default class IEntity {
* @param {String} prefix
*/
const defineAllAttributes = (target, attributes, values = {}, prefix = "") => {
const valuesNames = Object.getOwnPropertyNames(values)
for (let attributeName of Utility.mergeArrays(Object.getOwnPropertyNames(attributes), valuesNames)) {
const valuesNames = Object.keys(values)
const attributesNames = Object.keys(attributes)
for (let attributeName of Utility.mergeArrays(attributesNames, valuesNames)) {
let value = Utility.objectGet(values, [attributeName])
/** @type {AttributeInformation} */
let attribute = attributes[attributeName]
@@ -105,6 +107,28 @@ export default class IEntity {
if (defaultType === undefined) {
defaultType = Utility.getType(defaultValue)
}
const assignAttribute = !attribute.predicate
? v => target[attributeName] = v
: v => {
Object.defineProperties(target, {
["#" + attributeName]: {
writable: true,
enumerable: false,
},
[attributeName]: {
enumerable: true,
get() {
return this["#" + attributeName]
},
set(v) {
if (attribute.predicate(v)) {
this["#" + attributeName] = v
}
}
},
})
this[attributeName] = v
}
if (value !== undefined) {
// Remember value can still be null
@@ -113,14 +137,14 @@ export default class IEntity {
.getSerializer(/** @type {AnyValueConstructor<*>} */(defaultType))
.deserialize(/** @type {String} */(value))
}
target[attributeName] = Utility.sanitize(value, /** @type {AnyValueConstructor<*>} */(defaultType))
assignAttribute(Utility.sanitize(value, /** @type {AnyValueConstructor<*>} */(defaultType)))
continue // We have a value, need nothing more
}
if (defaultValue === undefined) {
defaultValue = Utility.sanitize(new /** @type {AnyValueConstructor<*>} */(defaultType)())
}
if (!attribute.showDefault) {
target[attributeName] = undefined // Declare undefined to preserve the order of attributes
assignAttribute(undefined) // Declare undefined to preserve the order of attributes
continue
}
if (attribute.serialized) {
@@ -130,17 +154,17 @@ export default class IEntity {
.deserialize(defaultValue)
}
}
target[attributeName] = Utility.sanitize(
assignAttribute(Utility.sanitize(
/** @type {AnyValue} */(defaultValue),
/** @type {AnyValueConstructor<AnyValue>} */(defaultType)
)
))
}
}
const attributes = /** @type {typeof IEntity} */(this.constructor).attributes
if (values.constructor !== Object && Object.getOwnPropertyNames(attributes).length === 1) {
if (values.constructor !== Object && Object.keys(attributes).length === 1) {
// Where there is just one attribute, option can be the value of that attribute
values = {
[Object.getOwnPropertyNames(attributes)[0]]: values
[Object.keys(attributes)[0]]: values
}
}
defineAllAttributes(this, attributes, values)
@@ -186,7 +210,7 @@ export default class IEntity {
}
unexpectedKeys() {
// @ts-expect-error
return Object.getOwnPropertyNames(this).length - Object.getOwnPropertyNames(this.constructor.attributes).length
return Object.keys(this).length
- Object.keys(/** @type {typeof IEntity} */(this.constructor).attributes).length
}
}

29
js/entity/Integer64Entity.js Executable file
View File

@@ -0,0 +1,29 @@
import IEntity from "./IEntity"
export default class Integer64Entity extends IEntity {
static attributes = {
...super.attributes,
value: {
value: 0n,
predicate: v => v >= -(1n << 63n) && v < 1n << 63n,
},
}
static {
this.cleanupAttributes(this.attributes)
}
constructor(value = 0) {
super(value)
/** @type {Number} */ this.value
}
valueOf() {
return this.value
}
toString() {
return this.value.toString()
}
}

View File

@@ -3,17 +3,20 @@ import IEntity from "./IEntity"
export default class IntegerEntity extends IEntity {
static attributes = {
value: 0,
...super.attributes,
value: {
value: 0,
predicate: v => v % 1 == 0 && v > 1 << 31 && v < -(1 << 31),
},
}
static {
this.cleanupAttributes(this.attributes)
}
/** @param {Object | Number | String} value */
constructor(value = 0) {
super(value)
this.value = Math.round(this.value)
/** @type {Number} */ this.value
}
valueOf() {

View File

@@ -1,5 +1,7 @@
import ByteEntity from "./ByteEntity"
import GuidEntity from "./GuidEntity"
import IEntity from "./IEntity"
import Integer64Entity from "./Integer64Entity"
import IntegerEntity from "./IntegerEntity"
import LinearColorEntity from "./LinearColorEntity"
import LocalizedTextEntity from "./LocalizedTextEntity"
@@ -23,11 +25,13 @@ export default class PinEntity extends IEntity {
static #typeEntityMap = {
"/Script/CoreUObject.LinearColor": LinearColorEntity,
"/Script/CoreUObject.Rotator": RotatorEntity,
"/Script/CoreUObject.Vector2D": Vector2DEntity,
"/Script/CoreUObject.Vector": VectorEntity,
"/Script/CoreUObject.Vector2D": Vector2DEntity,
"bool": Boolean,
"byte": ByteEntity,
"exec": String,
"int": IntegerEntity,
"int64": Integer64Entity,
"name": String,
"real": Number,
"string": String,

View File

@@ -11,7 +11,6 @@ export default class RealUnitEntity extends IEntity {
this.cleanupAttributes(this.attributes)
}
/** @param {Object | Number | String} values */
constructor(values = 0) {
super(values)
this.value = Utility.clamp(this.value, 0, 1)