minerender 2.1.0-alpha.32 → 2.1.0-alpha.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bundle.js CHANGED
@@ -81078,26 +81078,40 @@ ${key}` : key;
81078
81078
  };
81079
81079
  return collect("");
81080
81080
  }
81081
- static async getEntity(modelKey, textureKey, options) {
81081
+ static async getModelFile(modelKey) {
81082
81082
  const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
81083
81083
  const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json");
81084
- const model = await Caching.entityModelCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
81084
+ return Caching.entityModelCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
81085
+ }
81086
+ static async getLayerList(modelKey) {
81087
+ return Object.keys((await this.getModelFile(modelKey))?.layers ?? {});
81088
+ }
81089
+ static async getEntity(modelKey, textureKey, options) {
81090
+ const model = await this.getModelFile(modelKey);
81085
81091
  if (!model) return void 0;
81086
- const layerName = options?.layer ?? "main";
81087
- const layer = model.layers[layerName];
81088
- if (!layer) {
81089
- throw new MineRenderError(`Entity ${model.id} has no layer "${layerName}". Available layers: ${Object.keys(model.layers).join(", ")}`);
81090
- }
81091
- let texture;
81092
- if (textureKey) {
81093
- const path2 = isAssetKey(textureKey) ? textureKey.getFullPath() : textureKey.path;
81094
- texture = isAssetKey(textureKey) && textureKey.assetType === "textures" && path2.startsWith("entity/") ? textureKey : new AssetKey(textureKey.namespace, path2, "textures", "entity", "assets", ".png", isAssetKey(textureKey) ? textureKey.root : void 0);
81095
- } else if (layer.textureLocation !== void 0) {
81096
- texture = AssetKey.parse("textures", layer.textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
81097
- } else {
81098
- texture = await this.resolveTexture(modelKey);
81099
- }
81100
- return { key: textureKey ?? modelKey, texture, layer, id: model.id };
81092
+ const names = [...new Set(options?.layers ?? [options?.layer ?? "main"])];
81093
+ if (names.length === 0) throw new MineRenderError(`Entity ${model.id} requires at least one layer`);
81094
+ const selected = names.map((name2) => {
81095
+ const layer = model.layers[name2];
81096
+ if (!layer) {
81097
+ throw new MineRenderError(`Entity ${model.id} has no layer "${name2}". Available layers: ${Object.keys(model.layers).join(", ")}`);
81098
+ }
81099
+ return { name: name2, layer };
81100
+ });
81101
+ const layers = Object.fromEntries(await Promise.all(selected.map(async ({ name: name2, layer }, index) => {
81102
+ const override = options?.textures?.[name2] ?? (index === 0 ? textureKey : void 0);
81103
+ let texture;
81104
+ if (override) {
81105
+ const path = isAssetKey(override) ? override.getFullPath() : override.path;
81106
+ texture = isAssetKey(override) && override.assetType === "textures" && path.startsWith("entity/") ? override : new AssetKey(override.namespace, path, "textures", "entity", "assets", ".png", isAssetKey(override) ? override.root : void 0);
81107
+ } else if (layer.textureLocation !== void 0) {
81108
+ texture = AssetKey.parse("textures", layer.textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
81109
+ } else {
81110
+ texture = await this.resolveTexture(modelKey);
81111
+ }
81112
+ return [name2, { key: override ?? modelKey, texture, layer }];
81113
+ })));
81114
+ return { ...layers[names[0]], id: model.id, layers };
81101
81115
  }
81102
81116
  static async resolveTexture(modelKey) {
81103
81117
  const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
@@ -81203,32 +81217,42 @@ ${key}` : key;
81203
81217
  nextInstance() {
81204
81218
  return this.instanceable.nextInstance();
81205
81219
  }
81220
+ get activeInstanceable() {
81221
+ if (!this.instanceable.isInstanceActive(this.index, this)) throw new MineRenderError("Instance has been removed");
81222
+ return this.instanceable;
81223
+ }
81224
+ removeFromScene() {
81225
+ if (this.instanceable.isInstanceActive(this.index, this)) this.instanceable.removeInstanceAt(this.index);
81226
+ }
81227
+ dispose() {
81228
+ this.removeFromScene();
81229
+ }
81206
81230
  getMatrix(matrix) {
81207
- return this.instanceable.getMatrixAt(this.index, matrix);
81231
+ return this.activeInstanceable.getMatrixAt(this.index, matrix);
81208
81232
  }
81209
81233
  setMatrix(matrix) {
81210
- this.instanceable.setMatrixAt(this.index, matrix);
81234
+ this.activeInstanceable.setMatrixAt(this.index, matrix);
81211
81235
  }
81212
81236
  setPositionRotationScale(position, rotation, scale) {
81213
- this.instanceable.setPositionRotationScaleAt(this.index, position, rotation, scale);
81237
+ this.activeInstanceable.setPositionRotationScaleAt(this.index, position, rotation, scale);
81214
81238
  }
81215
81239
  setPosition(position) {
81216
- this.instanceable.setPositionAt(this.index, position);
81240
+ this.activeInstanceable.setPositionAt(this.index, position);
81217
81241
  }
81218
81242
  getPosition() {
81219
- return this.instanceable.getPositionAt(this.index);
81243
+ return this.activeInstanceable.getPositionAt(this.index);
81220
81244
  }
81221
81245
  setRotation(rotation) {
81222
- this.instanceable.setRotationAt(this.index, rotation);
81246
+ this.activeInstanceable.setRotationAt(this.index, rotation);
81223
81247
  }
81224
81248
  getRotation() {
81225
- return this.instanceable.getRotationAt(this.index);
81249
+ return this.activeInstanceable.getRotationAt(this.index);
81226
81250
  }
81227
81251
  setScale(scale) {
81228
- this.instanceable.setScaleAt(this.index, scale);
81252
+ this.activeInstanceable.setScaleAt(this.index, scale);
81229
81253
  }
81230
81254
  getScale() {
81231
- return this.instanceable.getScaleAt(this.index);
81255
+ return this.activeInstanceable.getScaleAt(this.index);
81232
81256
  }
81233
81257
  //TODO: support for custom methods e.g. setting block variants
81234
81258
  };
@@ -81246,6 +81270,8 @@ ${key}` : key;
81246
81270
  this.materialCallbacks = {};
81247
81271
  this._isInstanced = false;
81248
81272
  this._instanceCounter = 0;
81273
+ this.instanceReferences = /* @__PURE__ */ new Map();
81274
+ this.freeInstanceIndices = [];
81249
81275
  this.options = (0, import_ts_deepmerge3.default)({}, _SceneObject.DEFAULT_OPTIONS, options ?? {});
81250
81276
  console.log("SceneObject options", this.options);
81251
81277
  }
@@ -81341,6 +81367,8 @@ ${key}` : key;
81341
81367
  createInstancedMesh(name2, geometry, material, count) {
81342
81368
  const mesh = new InstancedMesh(geometry, material, count);
81343
81369
  mesh.count = 0;
81370
+ this.instanceMesh = mesh;
81371
+ this._isInstanced = true;
81344
81372
  if (name2) {
81345
81373
  mesh.name = `mesh:${name2}`;
81346
81374
  }
@@ -81408,40 +81436,70 @@ ${key}` : key;
81408
81436
  return new InstanceReference(this, i4);
81409
81437
  }
81410
81438
  nextInstance() {
81411
- if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
81412
- const i4 = this._instanceCounter++;
81413
- this.setMatrixAt(i4, new Matrix4());
81414
- const mesh = this.children[0];
81415
- if (mesh && isInstancedMesh(mesh)) {
81416
- mesh.count = Math.min(this._instanceCounter, mesh.instanceMatrix.count);
81417
- }
81418
- console.debug(p9, "nextInstance " + i4);
81419
- if (i4 === this.options.maxInstanceCount) {
81420
- console.warn(p9, "Max instance count reached for " + this);
81421
- }
81422
- if (this.scene) {
81423
- this.scene.stats.instanceCount++;
81439
+ const mesh = this.instanceMesh;
81440
+ if (!mesh) throw new MineRenderError("Object is not instanced");
81441
+ const index = this.freeInstanceIndices.pop() ?? mesh.count;
81442
+ if (index >= mesh.instanceMatrix.count) this.growInstances(index + 1);
81443
+ const reference = this.constructInstanceReference(index);
81444
+ this.instanceReferences.set(index, reference);
81445
+ this._instanceCounter = this.instanceReferences.size;
81446
+ mesh.count = Math.max(mesh.count, index + 1);
81447
+ if (mesh.instanceColor) {
81448
+ mesh.setColorAt(index, new Color(16777215));
81449
+ mesh.instanceColor.needsUpdate = true;
81450
+ }
81451
+ if (this._scene) this._scene.stats.instanceCount++;
81452
+ this.setMatrixAt(index, new Matrix4());
81453
+ return reference;
81454
+ }
81455
+ isInstanceActive(index, reference) {
81456
+ return this.instanceReferences.get(index) === reference;
81457
+ }
81458
+ removeInstanceAt(index) {
81459
+ if (!this.instanceReferences.has(index)) return;
81460
+ const mesh = this.instanceMesh;
81461
+ this.setMatrixAt(index, new Matrix4().makeScale(0, 0, 0));
81462
+ this.instanceReferences.delete(index);
81463
+ this.freeInstanceIndices.push(index);
81464
+ this._instanceCounter = this.instanceReferences.size;
81465
+ while (mesh.count > 0 && !this.instanceReferences.has(mesh.count - 1)) mesh.count--;
81466
+ if (this._scene) this._scene.stats.instanceCount--;
81467
+ }
81468
+ growInstances(required) {
81469
+ const mesh = this.instanceMesh;
81470
+ const capacity = Math.max(required, mesh.instanceMatrix.count * 2);
81471
+ const grow = (attribute, fill) => {
81472
+ const array = new Float32Array(capacity * attribute.itemSize).fill(fill);
81473
+ array.set(attribute.array);
81474
+ return new InstancedBufferAttribute(array, attribute.itemSize, attribute.normalized, attribute.meshPerAttribute).setUsage(attribute.usage);
81475
+ };
81476
+ const matrix = grow(mesh.instanceMatrix, 0);
81477
+ const color2 = mesh.instanceColor ? grow(mesh.instanceColor, 1) : null;
81478
+ mesh.dispose();
81479
+ mesh.instanceMatrix = matrix;
81480
+ mesh.instanceColor = color2;
81481
+ }
81482
+ *activeInstanceIndices() {
81483
+ if (this.instanceMesh) {
81484
+ yield* this.instanceReferences.keys();
81485
+ } else {
81486
+ for (let i4 = 0; i4 < this.instanceCounter; i4++) yield i4;
81424
81487
  }
81425
- this.notifyDirty();
81426
- return this.constructInstanceReference(i4);
81427
81488
  }
81428
81489
  //</editor-fold>
81429
81490
  //<editor-fold desc="TRANSFORMATION">
81430
81491
  getMatrixAt(index, matrix = new Matrix4()) {
81431
- if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
81432
- const child = this.children[0];
81433
- if (child && isInstancedMesh(child)) {
81434
- child.getMatrixAt(index, matrix);
81435
- }
81492
+ if (!this.instanceReferences.has(index)) throw new MineRenderError("Instance is not active");
81493
+ this.instanceMesh.getMatrixAt(index, matrix);
81436
81494
  return matrix;
81437
81495
  }
81438
81496
  setMatrixAt(index, matrix) {
81439
- if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
81440
- const child = this.children[0];
81441
- if (child && isInstancedMesh(child)) {
81442
- child.setMatrixAt(index, matrix);
81443
- child.instanceMatrix.needsUpdate = true;
81444
- }
81497
+ if (!this.instanceReferences.has(index)) throw new MineRenderError("Instance is not active");
81498
+ const mesh = this.instanceMesh;
81499
+ mesh.setMatrixAt(index, matrix);
81500
+ mesh.instanceMatrix.needsUpdate = true;
81501
+ mesh.boundingBox = null;
81502
+ mesh.boundingSphere = null;
81445
81503
  this.notifyDirty();
81446
81504
  }
81447
81505
  setPositionRotationScaleAt(index, position, rotation, scale) {
@@ -81492,7 +81550,7 @@ ${key}` : key;
81492
81550
  }
81493
81551
  setPositionRotationScale(position, rotation, scale) {
81494
81552
  if (this.isInstanced) {
81495
- for (let i4 = 0; i4 < this.instanceCounter; i4++) {
81553
+ for (const i4 of this.activeInstanceIndices()) {
81496
81554
  this.setPositionRotationScaleAt(i4, position, rotation, scale);
81497
81555
  }
81498
81556
  } else {
@@ -81510,7 +81568,7 @@ ${key}` : key;
81510
81568
  }
81511
81569
  setPosition(position) {
81512
81570
  if (this.isInstanced) {
81513
- for (let i4 = 0; i4 < this.instanceCounter; i4++) {
81571
+ for (const i4 of this.activeInstanceIndices()) {
81514
81572
  this.setPositionRotationScaleAt(i4, position);
81515
81573
  }
81516
81574
  } else {
@@ -81520,14 +81578,14 @@ ${key}` : key;
81520
81578
  }
81521
81579
  getPosition() {
81522
81580
  if (this.isInstanced) {
81523
- return this.getPositionAt(0);
81581
+ return this.getPositionAt(this.instanceReferences.keys().next().value ?? 0);
81524
81582
  } else {
81525
81583
  return this.position;
81526
81584
  }
81527
81585
  }
81528
81586
  setRotation(rotation) {
81529
81587
  if (this.isInstanced) {
81530
- for (let i4 = 0; i4 < this.instanceCounter; i4++) {
81588
+ for (const i4 of this.activeInstanceIndices()) {
81531
81589
  this.setPositionRotationScaleAt(i4, void 0, rotation);
81532
81590
  }
81533
81591
  } else {
@@ -81537,14 +81595,14 @@ ${key}` : key;
81537
81595
  }
81538
81596
  getRotation() {
81539
81597
  if (this.isInstanced) {
81540
- return this.getRotationAt(0);
81598
+ return this.getRotationAt(this.instanceReferences.keys().next().value ?? 0);
81541
81599
  } else {
81542
81600
  return this.rotation;
81543
81601
  }
81544
81602
  }
81545
81603
  setScale(scale) {
81546
81604
  if (this.isInstanced) {
81547
- for (let i4 = 0; i4 < this.instanceCounter; i4++) {
81605
+ for (const i4 of this.activeInstanceIndices()) {
81548
81606
  this.setPositionRotationScaleAt(i4, void 0, void 0, scale);
81549
81607
  }
81550
81608
  } else {
@@ -81554,7 +81612,7 @@ ${key}` : key;
81554
81612
  }
81555
81613
  getScale() {
81556
81614
  if (this.isInstanced) {
81557
- return this.getScaleAt(0);
81615
+ return this.getScaleAt(this.instanceReferences.keys().next().value ?? 0);
81558
81616
  } else {
81559
81617
  return this.scale;
81560
81618
  }
@@ -81578,6 +81636,17 @@ ${key}` : key;
81578
81636
  this.notifyDirty();
81579
81637
  }
81580
81638
  disposeAndRemoveAllChildren() {
81639
+ if (this.instanceMesh) {
81640
+ if (this._scene) this._scene.stats.instanceCount -= this.instanceReferences.size;
81641
+ this.instanceReferences.clear();
81642
+ this.freeInstanceIndices.length = 0;
81643
+ this._instanceCounter = 0;
81644
+ this.instanceMesh.count = 0;
81645
+ this.instanceMesh.dispose();
81646
+ this.instanceMesh.removeFromParent();
81647
+ this.instanceMesh = void 0;
81648
+ this._isInstanced = false;
81649
+ }
81581
81650
  while (this.children.length > 0) {
81582
81651
  let c4 = this.children[0];
81583
81652
  if (isDisposable(c4)) {
@@ -81621,9 +81690,21 @@ ${key}` : key;
81621
81690
  dispose() {
81622
81691
  super.dispose();
81623
81692
  }
81624
- get textureKey() {
81625
- if (this.entity.texture) return this.entity.texture;
81626
- const key = this.entity.key;
81693
+ getLayerGroup(name2) {
81694
+ return super.getGroupByName(`layer:${name2}`);
81695
+ }
81696
+ getGroupByName(name2, layerName) {
81697
+ return layerName === void 0 ? super.getGroupByName(name2) : this.getLayerGroup(layerName)?.getObjectByName(`group:${name2}`);
81698
+ }
81699
+ getMeshByName(name2, layerName) {
81700
+ return layerName === void 0 ? super.getMeshByName(name2) : this.getLayerGroup(layerName)?.getObjectByName(`mesh:${name2}`);
81701
+ }
81702
+ get entityLayers() {
81703
+ return this.entity.layers ?? { main: this.entity };
81704
+ }
81705
+ getTextureKey(layer) {
81706
+ if (layer.texture) return layer.texture;
81707
+ const key = layer.key;
81627
81708
  return new AssetKey(
81628
81709
  key.namespace,
81629
81710
  isAssetKey(key) ? key.getFullPath() : key.path,
@@ -81633,18 +81714,22 @@ ${key}` : key;
81633
81714
  ".png"
81634
81715
  );
81635
81716
  }
81636
- async loadTextures() {
81637
- this.imageData = await ModelTextures.get(this.textureKey);
81717
+ async loadTextures(layer = this.entity) {
81718
+ return ModelTextures.get(this.getTextureKey(layer));
81638
81719
  }
81639
81720
  createMeshes(force = false) {
81640
81721
  if (this.meshesCreated && !force) return;
81641
81722
  const modelRoot = new Object3D();
81642
81723
  if (this.options.flip) modelRoot.scale.set(-1, -1, 1);
81643
81724
  this.add(modelRoot);
81644
- this.createPart("root", this.entity.layer.root, modelRoot, this.entity.layer.texture, Materials.MISSING_TEXTURE);
81725
+ Object.entries(this.entityLayers).forEach(([name2, layer], index) => {
81726
+ const group = this.createGroup(`layer:${name2}`);
81727
+ modelRoot.add(group);
81728
+ this.createPart("root", layer.layer.root, group, layer.layer.texture, Materials.MISSING_TEXTURE, index);
81729
+ });
81645
81730
  this.meshesCreated = true;
81646
81731
  }
81647
- createPart(name2, part, parent, textureSize, material) {
81732
+ createPart(name2, part, parent, textureSize, material, renderOrder) {
81648
81733
  const anchor = this.createGroup(name2);
81649
81734
  anchor.position.fromArray(part.pose.offset);
81650
81735
  anchor.rotation.set(...part.pose.rotation, "ZYX");
@@ -81664,30 +81749,31 @@ ${key}` : key;
81664
81749
  ).clone();
81665
81750
  geometry.translate(cube.origin[0] + width / 2, cube.origin[1] + height / 2, cube.origin[2] + depth / 2);
81666
81751
  const mesh = this.createMesh(name2, geometry, material);
81752
+ mesh.renderOrder = renderOrder;
81667
81753
  anchor.add(mesh);
81668
81754
  if (this.options.wireframe) addWireframeToMesh(geometry, mesh);
81669
81755
  }
81670
81756
  for (const [childName, child] of Object.entries(part.children)) {
81671
- this.createPart(childName, child, anchor, size, material);
81757
+ this.createPart(childName, child, anchor, size, material, renderOrder);
81672
81758
  }
81673
81759
  }
81674
81760
  async applyTextures() {
81675
- const assetKeyStr = this.textureKey.serialize();
81676
- const keyStr = `entity:${assetKeyStr}`;
81677
- let mat = Caching.materialCache.getIfPresent(keyStr);
81678
- if (!mat) {
81679
- const pending = this.loadTextures();
81680
- const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
81681
- await pending;
81682
- if (!this.imageData) return;
81683
- const canvas = this.imageData.data.canvas;
81684
- const createMaterial = () => Materials.createBasicCanvasMaterial(canvas);
81685
- mat = cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
81686
- this.imageData = void 0;
81687
- }
81688
- this.iterateAllMeshes((mesh) => {
81689
- mesh.material = mat;
81690
- });
81761
+ await Promise.all(Object.entries(this.entityLayers).map(async ([name2, layer]) => {
81762
+ const assetKeyStr = this.getTextureKey(layer).serialize();
81763
+ const keyStr = `entity:${assetKeyStr}`;
81764
+ let mat = Caching.materialCache.getIfPresent(keyStr);
81765
+ if (!mat) {
81766
+ const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
81767
+ const imageData = await this.loadTextures(layer);
81768
+ if (!imageData) return;
81769
+ const canvas = imageData.data.canvas;
81770
+ const createMaterial = () => Materials.createBasicCanvasMaterial(canvas);
81771
+ mat = cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
81772
+ }
81773
+ this.getLayerGroup(name2)?.traverse((object) => {
81774
+ if (isMesh(object)) object.material = mat;
81775
+ });
81776
+ }));
81691
81777
  this.notifyDirty();
81692
81778
  }
81693
81779
  };
@@ -82874,10 +82960,6 @@ ${key}` : key;
82874
82960
  this.createMeshes();
82875
82961
  this.applyTextures();
82876
82962
  }
82877
- dispose() {
82878
- super.dispose();
82879
- this.atlas?.dispose();
82880
- }
82881
82963
  get textureAtlas() {
82882
82964
  return this.atlas;
82883
82965
  }
@@ -83042,18 +83124,21 @@ ${key}` : key;
83042
83124
  }
83043
83125
  }
83044
83126
  dispose() {
83127
+ this.clearModels();
83045
83128
  super.dispose();
83046
83129
  }
83047
83130
  removeFromScene() {
83048
- for (let model of this._models) {
83049
- if (isModelObject(model)) {
83050
- model.removeFromScene();
83051
- } else if (isInstanceReference(model)) {
83052
- model.setScale(new Vector3(0, 0, 0));
83053
- }
83054
- }
83131
+ this.clearModels();
83055
83132
  super.removeFromScene();
83056
83133
  }
83134
+ clearModels() {
83135
+ for (const model of this._models.splice(0)) {
83136
+ model.removeFromScene();
83137
+ if (!isInstanceReference(model)) model.dispose();
83138
+ }
83139
+ this._isInstanced = false;
83140
+ this._instanceCounter = 0;
83141
+ }
83057
83142
  get state() {
83058
83143
  return this._state;
83059
83144
  }
@@ -83102,22 +83187,7 @@ ${key}` : key;
83102
83187
  return out;
83103
83188
  }
83104
83189
  async recreateModels() {
83105
- const instanceInfo = [];
83106
- if (this.isInstanced) {
83107
- for (let i4 = 0; i4 < this.instanceCounter; i4++) {
83108
- instanceInfo[i4] = this.getMatrixAt(i4);
83109
- }
83110
- }
83111
- for (let model of this._models) {
83112
- if (isInstanceReference(model)) {
83113
- model.setScale(new Vector3(0, 0, 0));
83114
- } else {
83115
- model.dispose();
83116
- }
83117
- }
83118
- while (this._models.length > 0) {
83119
- this._models.shift();
83120
- }
83190
+ this.clearModels();
83121
83191
  const variantsToCreate = await this.mapStateToVariant(this.state);
83122
83192
  this._variants = variantsToCreate;
83123
83193
  for (let blockStateVariant of variantsToCreate) {
@@ -83168,6 +83238,7 @@ ${key}` : key;
83168
83238
  this._instanceCounter = 1;
83169
83239
  }
83170
83240
  obj.setRotation(rotation);
83241
+ obj.setPosition(this.position);
83171
83242
  return obj;
83172
83243
  }
83173
83244
  async resetState() {