start working on physics, all over the place right now
This commit is contained in:
parent
f1509a3a64
commit
9c980bc725
|
@ -29,6 +29,8 @@
|
||||||
"@freeblox/engine": "workspace:^",
|
"@freeblox/engine": "workspace:^",
|
||||||
"three": "^0.153.0",
|
"three": "^0.153.0",
|
||||||
"vite-plugin-dts": "^2.3.0",
|
"vite-plugin-dts": "^2.3.0",
|
||||||
|
"vite-plugin-top-level-await": "^1.3.1",
|
||||||
|
"vite-plugin-wasm": "^3.2.2",
|
||||||
"vue": "^3.2.47"
|
"vue": "^3.2.47"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
LevelComponent,
|
LevelComponent,
|
||||||
Engine,
|
Engine,
|
||||||
assetManager,
|
assetManager,
|
||||||
|
PhysicsWorldComponent,
|
||||||
} from '@freeblox/engine';
|
} from '@freeblox/engine';
|
||||||
import { GameEvents } from '../types/events';
|
import { GameEvents } from '../types/events';
|
||||||
import { GameplayComponent } from './gameplay';
|
import { GameplayComponent } from './gameplay';
|
||||||
|
@ -21,6 +22,7 @@ export class Game extends Engine {
|
||||||
this.use(LevelComponent);
|
this.use(LevelComponent);
|
||||||
this.use(GameplayComponent);
|
this.use(GameplayComponent);
|
||||||
this.use(MouseComponent);
|
this.use(MouseComponent);
|
||||||
|
this.use(PhysicsWorldComponent);
|
||||||
|
|
||||||
this.getComponent(ViewportComponent).setSizeFromViewport();
|
this.getComponent(ViewportComponent).setSizeFromViewport();
|
||||||
this.start();
|
this.start();
|
||||||
|
|
|
@ -28,6 +28,7 @@ export class GameplayComponent extends EngineComponent {
|
||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
};
|
};
|
||||||
|
public jump = false;
|
||||||
|
|
||||||
private move = new Vector3();
|
private move = new Vector3();
|
||||||
private look = new Vector3();
|
private look = new Vector3();
|
||||||
|
@ -60,6 +61,10 @@ export class GameplayComponent extends EngineComponent {
|
||||||
if (this.move.length()) {
|
if (this.move.length()) {
|
||||||
this.character?.setLook(this.move.clone().normalize());
|
this.character?.setLook(this.move.clone().normalize());
|
||||||
}
|
}
|
||||||
|
if (this.jump) {
|
||||||
|
this.jump = false;
|
||||||
|
this.character?.jump();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override dispose(): void {
|
override dispose(): void {
|
||||||
|
@ -98,6 +103,9 @@ export class GameplayComponent extends EngineComponent {
|
||||||
case 'KeyD':
|
case 'KeyD':
|
||||||
this.movement.right = this.movementSpeed;
|
this.movement.right = this.movementSpeed;
|
||||||
break;
|
break;
|
||||||
|
case 'Space':
|
||||||
|
this.jump = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const keyUpEvent = (event: KeyboardEvent) => {
|
const keyUpEvent = (event: KeyboardEvent) => {
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
import vue from '@vitejs/plugin-vue';
|
import vue from '@vitejs/plugin-vue';
|
||||||
import dts from 'vite-plugin-dts'
|
import dts from 'vite-plugin-dts';
|
||||||
|
import wasm from 'vite-plugin-wasm';
|
||||||
|
import topLevelAwait from 'vite-plugin-top-level-await';
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [vue(), dts()],
|
plugins: [vue(), dts(), wasm(), topLevelAwait()],
|
||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
entry: 'src/index.ts',
|
entry: 'src/index.ts',
|
||||||
name: 'Client',
|
name: 'Client',
|
||||||
fileName: 'client',
|
fileName: 'client',
|
||||||
formats: ['es', 'cjs', 'umd']
|
formats: ['es', 'cjs', 'umd'],
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
external: ['vue'],
|
external: ['vue'],
|
||||||
|
@ -20,5 +22,5 @@ export default defineConfig({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
"typescript": "^5.0.4"
|
"typescript": "^5.0.4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@dimforge/rapier3d": "^0.11.2",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"three": "^0.153.0"
|
"three": "^0.153.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,3 +2,4 @@ export * from './environment';
|
||||||
export * from './viewport';
|
export * from './viewport';
|
||||||
export * from './mouse';
|
export * from './mouse';
|
||||||
export * from './level';
|
export * from './level';
|
||||||
|
export * from './physicsworld';
|
||||||
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
import { SkinnedMesh, Vector3 } from 'three';
|
||||||
|
import { EngineComponent } from '../types/engine-component';
|
||||||
|
import { World } from '../gameobjects/world.object';
|
||||||
|
import {
|
||||||
|
PhysicsObjectAssociation,
|
||||||
|
getRapier,
|
||||||
|
ColliderFactory,
|
||||||
|
HumanoidPhysicsProxy,
|
||||||
|
} from '../physics';
|
||||||
|
import { Brick } from '../gameobjects/brick.object';
|
||||||
|
import type Rapier from '@dimforge/rapier3d';
|
||||||
|
import { Humanoid } from '../gameobjects/humanoid.object';
|
||||||
|
|
||||||
|
export class PhysicsWorldComponent extends EngineComponent {
|
||||||
|
public name = PhysicsWorldComponent.name;
|
||||||
|
private world!: World;
|
||||||
|
private physicsWorld!: Rapier.World;
|
||||||
|
private physicsEngine!: typeof Rapier;
|
||||||
|
private characterPhysics!: Rapier.KinematicCharacterController;
|
||||||
|
private characterRay!: Rapier.Ray;
|
||||||
|
private initEventFiredBeforeEngineLoad = false;
|
||||||
|
private cleanUpEvents?: Function;
|
||||||
|
private sceneInitialized = false;
|
||||||
|
private trackedObjects: PhysicsObjectAssociation[] = [];
|
||||||
|
|
||||||
|
initialize(): void {
|
||||||
|
this.world = this.renderer.scene.getObjectByName('World') as World;
|
||||||
|
this.cleanUpEvents = this.bindEvents();
|
||||||
|
this.createRapier();
|
||||||
|
}
|
||||||
|
|
||||||
|
update(delta: number): void {
|
||||||
|
// FIXME: physics is tied to the FPS
|
||||||
|
this.physicsWorld?.step();
|
||||||
|
for (const object of this.trackedObjects) object.tick(delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose(): void {
|
||||||
|
this.cleanUpEvents?.call(this);
|
||||||
|
this.physicsWorld.removeCharacterController(this.characterPhysics);
|
||||||
|
}
|
||||||
|
|
||||||
|
private createRapier() {
|
||||||
|
getRapier().then((R) => {
|
||||||
|
const gravity = new Vector3(0, this.world.gravity, 0);
|
||||||
|
const world = new R.World(gravity);
|
||||||
|
this.physicsWorld = world;
|
||||||
|
this.physicsEngine = R;
|
||||||
|
|
||||||
|
if (this.initEventFiredBeforeEngineLoad) {
|
||||||
|
this.initEventFiredBeforeEngineLoad = false;
|
||||||
|
setTimeout(() => this.initializePhysicsScene(), 500); // FIXME
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private bindEvents() {
|
||||||
|
const initializeEvent = () => {
|
||||||
|
if (!this.physicsWorld) {
|
||||||
|
this.initEventFiredBeforeEngineLoad = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setTimeout(() => this.initializePhysicsScene(), 500); // FIXME
|
||||||
|
};
|
||||||
|
|
||||||
|
this.events.addListener('initialized', initializeEvent);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
this.events.removeEventListener('initialized', initializeEvent);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private applyPhysics(object: Brick) {
|
||||||
|
// This object has effecively no physics:
|
||||||
|
// doesn't move, doesn't collide
|
||||||
|
if (object.anchored && !object.canCollide) return;
|
||||||
|
|
||||||
|
let bodyDesc: Rapier.RigidBodyDesc;
|
||||||
|
if (object.anchored) bodyDesc = this.physicsEngine.RigidBodyDesc.fixed();
|
||||||
|
else bodyDesc = this.physicsEngine.RigidBodyDesc.dynamic();
|
||||||
|
|
||||||
|
bodyDesc
|
||||||
|
.setTranslation(...object.position.toArray())
|
||||||
|
.setRotation(object.quaternion);
|
||||||
|
|
||||||
|
const body = this.physicsWorld.createRigidBody(bodyDesc);
|
||||||
|
|
||||||
|
let collider: Rapier.Collider | undefined;
|
||||||
|
if (object.canCollide) {
|
||||||
|
collider = ColliderFactory.createCollider(
|
||||||
|
object,
|
||||||
|
this.physicsEngine,
|
||||||
|
this.physicsWorld,
|
||||||
|
body
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const tracker = new PhysicsObjectAssociation(object, collider, body);
|
||||||
|
console.log(tracker);
|
||||||
|
this.trackedObjects.push(tracker);
|
||||||
|
return tracker;
|
||||||
|
}
|
||||||
|
|
||||||
|
private applyHumanoidPhysics(humanoid: Humanoid) {
|
||||||
|
const halfVec = new Vector3(0, humanoid.characterHalfHeight, 0);
|
||||||
|
const colliderDesc = this.physicsEngine.ColliderDesc.cuboid(
|
||||||
|
1,
|
||||||
|
humanoid.characterHalfHeight,
|
||||||
|
0.5
|
||||||
|
);
|
||||||
|
const rigidBodyDesc =
|
||||||
|
this.physicsEngine.RigidBodyDesc.kinematicPositionBased();
|
||||||
|
const rigidBody = this.physicsWorld.createRigidBody(rigidBodyDesc);
|
||||||
|
const collider = this.physicsWorld.createCollider(colliderDesc, rigidBody);
|
||||||
|
rigidBody.setTranslation(humanoid.parent!.position.clone(), true);
|
||||||
|
rigidBody.setRotation(humanoid.parent!.quaternion, true);
|
||||||
|
collider.setTranslationWrtParent(halfVec);
|
||||||
|
const proxy = new HumanoidPhysicsProxy(
|
||||||
|
humanoid,
|
||||||
|
this.characterPhysics,
|
||||||
|
this.characterRay,
|
||||||
|
this.physicsWorld,
|
||||||
|
collider,
|
||||||
|
rigidBody
|
||||||
|
);
|
||||||
|
this.trackedObjects.push(proxy);
|
||||||
|
humanoid.setPhysics(proxy);
|
||||||
|
console.log('set physics', proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async initializePhysicsScene() {
|
||||||
|
if (this.sceneInitialized) return;
|
||||||
|
console.log('init scene');
|
||||||
|
|
||||||
|
this.characterRay = new this.physicsEngine.Ray(
|
||||||
|
{ x: 0, y: 0, z: 0 },
|
||||||
|
{ x: 0, y: -0.5, z: 0 }
|
||||||
|
);
|
||||||
|
this.characterPhysics = this.physicsWorld.createCharacterController(0.01);
|
||||||
|
this.characterPhysics.setApplyImpulsesToDynamicBodies(true);
|
||||||
|
this.characterPhysics.setMaxSlopeClimbAngle((75 * Math.PI) / 180);
|
||||||
|
// Automatically slide down on slopes smaller than 30 degrees.
|
||||||
|
// this.characterPhysics.setMinSlopeSlideAngle((30 * Math.PI) / 180);
|
||||||
|
|
||||||
|
this.world.traverse((object) => {
|
||||||
|
if (object instanceof Humanoid) return this.applyHumanoidPhysics(object);
|
||||||
|
if (!(object instanceof Brick)) return;
|
||||||
|
// Do not apply physics to animated objects
|
||||||
|
if ((object.getMesh() as SkinnedMesh).skeleton) return;
|
||||||
|
this.applyPhysics(object);
|
||||||
|
});
|
||||||
|
this.sceneInitialized = true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -74,4 +74,12 @@ export class Brick extends GameObject3D {
|
||||||
this.name = this.objectType;
|
this.name = this.objectType;
|
||||||
this.add(this.mesh);
|
this.add(this.mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getGeometry() {
|
||||||
|
return this.geometry;
|
||||||
|
}
|
||||||
|
|
||||||
|
getMesh() {
|
||||||
|
return this.mesh;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,11 @@ import { GameObject } from '../types/game-object';
|
||||||
import { Ticking } from '../types/ticking';
|
import { Ticking } from '../types/ticking';
|
||||||
import { EditorProperty } from '../decorators/property';
|
import { EditorProperty } from '../decorators/property';
|
||||||
import { MeshPart } from './mesh.object';
|
import { MeshPart } from './mesh.object';
|
||||||
import { clamp } from 'three/src/math/MathUtils.js';
|
import { clamp, lerp } from 'three/src/math/MathUtils.js';
|
||||||
import { NameTag } from './nametag.object';
|
import { NameTag } from './nametag.object';
|
||||||
import { CanvasUtils } from '../canvas/utils';
|
import { CanvasUtils } from '../canvas/utils';
|
||||||
|
import { Disposable } from '../types/disposable';
|
||||||
|
import { HumanoidPhysicsProxy } from '../physics';
|
||||||
|
|
||||||
export type HumanoidBodyPart =
|
export type HumanoidBodyPart =
|
||||||
| 'Head'
|
| 'Head'
|
||||||
|
@ -23,7 +25,7 @@ export type HumanoidBodyPart =
|
||||||
| 'LegRight'
|
| 'LegRight'
|
||||||
| 'LegLeft';
|
| 'LegLeft';
|
||||||
|
|
||||||
export class Humanoid extends GameObject implements Ticking {
|
export class Humanoid extends GameObject implements Ticking, Disposable {
|
||||||
public isTickingObject = true;
|
public isTickingObject = true;
|
||||||
public objectType = 'Humanoid';
|
public objectType = 'Humanoid';
|
||||||
public name = 'Humanoid';
|
public name = 'Humanoid';
|
||||||
|
@ -32,9 +34,12 @@ export class Humanoid extends GameObject implements Ticking {
|
||||||
private _health = 100;
|
private _health = 100;
|
||||||
private _maxHealth = 100;
|
private _maxHealth = 100;
|
||||||
private _velocity = new Vector3(0, 0, 0);
|
private _velocity = new Vector3(0, 0, 0);
|
||||||
|
private _appliedGravity = new Vector3(0, 0, 0);
|
||||||
|
private _grounded = true;
|
||||||
private _lookAt = new Vector3(0, 0, 1);
|
private _lookAt = new Vector3(0, 0, 1);
|
||||||
private _currentLookAt = new Vector3(0, 0, 1);
|
private _currentLookAt = new Vector3(0, 0, 1);
|
||||||
private _animState = 0;
|
private _animState = 0;
|
||||||
|
private _jumpEnergy = 0;
|
||||||
public static bodyPartNames = [
|
public static bodyPartNames = [
|
||||||
'Head',
|
'Head',
|
||||||
'Torso',
|
'Torso',
|
||||||
|
@ -63,11 +68,18 @@ export class Humanoid extends GameObject implements Ticking {
|
||||||
textBorderSize: 1,
|
textBorderSize: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
public characterHeight = 5.5;
|
||||||
|
public characterHalfHeight = this.characterHeight / 2;
|
||||||
|
|
||||||
|
public jumpPower = 18;
|
||||||
|
|
||||||
private mixer!: AnimationMixer;
|
private mixer!: AnimationMixer;
|
||||||
private idleAction!: AnimationAction;
|
private idleAction!: AnimationAction;
|
||||||
private walkAction!: AnimationAction;
|
private walkAction!: AnimationAction;
|
||||||
|
private jumpAction!: AnimationAction;
|
||||||
|
|
||||||
private nameTag?: NameTag;
|
private nameTag?: NameTag;
|
||||||
|
private physics?: HumanoidPhysicsProxy;
|
||||||
|
|
||||||
@EditorProperty({ type: Number })
|
@EditorProperty({ type: Number })
|
||||||
get health() {
|
get health() {
|
||||||
|
@ -95,6 +107,16 @@ export class Humanoid extends GameObject implements Ticking {
|
||||||
return this.health > 0;
|
return this.health > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get grounded() {
|
||||||
|
return this._grounded;
|
||||||
|
}
|
||||||
|
set grounded(value: boolean) {
|
||||||
|
if (value && this._jumpEnergy < this.jumpPower / 2) {
|
||||||
|
this._jumpEnergy = 0;
|
||||||
|
}
|
||||||
|
this._grounded = value;
|
||||||
|
}
|
||||||
|
|
||||||
private get bodyParts() {
|
private get bodyParts() {
|
||||||
return Humanoid.bodyPartNames.map((key) => this.getBodyPartByName(key));
|
return Humanoid.bodyPartNames.map((key) => this.getBodyPartByName(key));
|
||||||
}
|
}
|
||||||
|
@ -123,8 +145,10 @@ export class Humanoid extends GameObject implements Ticking {
|
||||||
|
|
||||||
const idleClip = AnimationClip.findByName(this.parent.animations, 'Idle');
|
const idleClip = AnimationClip.findByName(this.parent.animations, 'Idle');
|
||||||
const walkClip = AnimationClip.findByName(this.parent.animations, 'Walk');
|
const walkClip = AnimationClip.findByName(this.parent.animations, 'Walk');
|
||||||
|
const jumpClip = AnimationClip.findByName(this.parent.animations, 'Jump');
|
||||||
this.idleAction = this.mixer.clipAction(idleClip);
|
this.idleAction = this.mixer.clipAction(idleClip);
|
||||||
this.walkAction = this.mixer.clipAction(walkClip);
|
this.walkAction = this.mixer.clipAction(walkClip);
|
||||||
|
this.jumpAction = this.mixer.clipAction(jumpClip);
|
||||||
this.idleAction.play();
|
this.idleAction.play();
|
||||||
|
|
||||||
this.createNameTag();
|
this.createNameTag();
|
||||||
|
@ -140,14 +164,40 @@ export class Humanoid extends GameObject implements Ticking {
|
||||||
this._lookAt.lerp(vector, 0.15);
|
this._lookAt.lerp(vector, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jump() {
|
||||||
|
if (!this.grounded) return;
|
||||||
|
this.grounded = false;
|
||||||
|
this._jumpEnergy = this.jumpPower;
|
||||||
|
}
|
||||||
|
|
||||||
tick(dt: number): void {
|
tick(dt: number): void {
|
||||||
if (!this.ready) return;
|
if (!this.ready) return;
|
||||||
this.mixer.update(dt);
|
this.mixer.update(dt);
|
||||||
this.parent?.position.add(this._velocity.clone().multiplyScalar(dt));
|
|
||||||
|
if (!this.grounded) {
|
||||||
|
this._appliedGravity.y = -9.81;
|
||||||
|
} else {
|
||||||
|
this._appliedGravity.y = 0;
|
||||||
|
}
|
||||||
|
if (this._jumpEnergy > 0) {
|
||||||
|
this._appliedGravity.y += this._jumpEnergy;
|
||||||
|
this._jumpEnergy -= 10 * dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.physics)
|
||||||
|
this.physics.applyMovement(
|
||||||
|
this.parent!.position,
|
||||||
|
this._velocity.clone().add(this._appliedGravity).multiplyScalar(dt)
|
||||||
|
);
|
||||||
|
else this.parent?.position.add(this._velocity.clone().multiplyScalar(dt));
|
||||||
|
|
||||||
this._currentLookAt.copy(this.parent!.position);
|
this._currentLookAt.copy(this.parent!.position);
|
||||||
this._currentLookAt.add(this._lookAt);
|
this._currentLookAt.add(this._lookAt);
|
||||||
this.parent?.lookAt(this._currentLookAt);
|
this.parent?.lookAt(this._currentLookAt);
|
||||||
|
|
||||||
|
if (this.physics) {
|
||||||
|
this.physics.applyRotation(this.parent!.quaternion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setWalkAnimationState(index: number) {
|
setWalkAnimationState(index: number) {
|
||||||
|
@ -197,4 +247,12 @@ export class Humanoid extends GameObject implements Ticking {
|
||||||
this.nameTag.position.set(0, 1.5, 0);
|
this.nameTag.position.set(0, 1.5, 0);
|
||||||
this.add(this.nameTag);
|
this.add(this.nameTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setPhysics(physics?: HumanoidPhysicsProxy) {
|
||||||
|
this.physics = physics;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose(): void {
|
||||||
|
this.nameTag?.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,6 @@ export class MeshPart extends Brick {
|
||||||
super(geometry, material, mesh);
|
super(geometry, material, mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
getMesh() {
|
|
||||||
return this.mesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Do some surgery to convert a loaded SkinnedMesh into a game object */
|
/** Do some surgery to convert a loaded SkinnedMesh into a game object */
|
||||||
static fromLoaded(loaded: SkinnedMesh) {
|
static fromLoaded(loaded: SkinnedMesh) {
|
||||||
const newObject = new MeshPart(loaded.geometry, undefined, loaded);
|
const newObject = new MeshPart(loaded.geometry, undefined, loaded);
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import { Sprite, CanvasTexture, SpriteMaterial } from 'three';
|
import { Sprite, CanvasTexture, SpriteMaterial } from 'three';
|
||||||
import { CanvasUtils } from '../canvas';
|
import { CanvasUtils } from '../canvas';
|
||||||
import { GameObject } from '..';
|
import { Disposable } from '../types/disposable';
|
||||||
|
import { GameObject } from '../types/game-object';
|
||||||
|
|
||||||
export class NameTag extends GameObject {
|
export class NameTag extends GameObject implements Disposable {
|
||||||
public objectType = NameTag.name;
|
public objectType = NameTag.name;
|
||||||
public virtual = true;
|
public virtual = true;
|
||||||
public archivable = false;
|
public archivable = false;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { EditorProperty } from '..';
|
||||||
import { GameObject } from '../types/game-object';
|
import { GameObject } from '../types/game-object';
|
||||||
|
|
||||||
export class World extends GameObject {
|
export class World extends GameObject {
|
||||||
|
@ -5,8 +6,12 @@ export class World extends GameObject {
|
||||||
public name = 'World';
|
public name = 'World';
|
||||||
public virtual = true;
|
public virtual = true;
|
||||||
|
|
||||||
|
@EditorProperty({ type: Number })
|
||||||
|
public gravity = -9.81;
|
||||||
|
|
||||||
override get properties() {
|
override get properties() {
|
||||||
return [];
|
const properties = super.properties;
|
||||||
|
return properties.filter((prop) => ['gravity'].includes(prop.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
import {
|
||||||
|
Brick,
|
||||||
|
Cylinder,
|
||||||
|
Sphere,
|
||||||
|
Torus,
|
||||||
|
Capsule,
|
||||||
|
Wedge,
|
||||||
|
WedgeCorner,
|
||||||
|
WedgeInnerCorner,
|
||||||
|
} from '../gameobjects';
|
||||||
|
import type RAPIER from '@dimforge/rapier3d';
|
||||||
|
import { Instancable } from '../types/instancable';
|
||||||
|
import { Matrix4 } from 'three';
|
||||||
|
|
||||||
|
export class ColliderFactory {
|
||||||
|
static gameObjectColliders = [
|
||||||
|
{
|
||||||
|
instance: Cylinder,
|
||||||
|
createCollisionShape: (
|
||||||
|
obj: Brick,
|
||||||
|
factory: typeof RAPIER,
|
||||||
|
world: RAPIER.World,
|
||||||
|
body?: RAPIER.RigidBody
|
||||||
|
) => {
|
||||||
|
const height = obj.scale.y / 2;
|
||||||
|
const radius = (obj.scale.x / 2 + obj.scale.z / 2) / 2;
|
||||||
|
const collider = factory.ColliderDesc.cylinder(height, radius);
|
||||||
|
return world.createCollider(collider, body);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instance: Sphere,
|
||||||
|
createCollisionShape: (
|
||||||
|
obj: Brick,
|
||||||
|
factory: typeof RAPIER,
|
||||||
|
world: RAPIER.World,
|
||||||
|
body?: RAPIER.RigidBody
|
||||||
|
) => {
|
||||||
|
const radius = Math.max(obj.scale.x, obj.scale.y, obj.scale.z) / 2;
|
||||||
|
const collider = factory.ColliderDesc.ball(radius);
|
||||||
|
return world.createCollider(collider, body);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instance: Torus,
|
||||||
|
createCollisionShape: (
|
||||||
|
obj: Brick,
|
||||||
|
factory: typeof RAPIER,
|
||||||
|
world: RAPIER.World,
|
||||||
|
body?: RAPIER.RigidBody
|
||||||
|
) => {
|
||||||
|
const height = obj.scale.y / 2;
|
||||||
|
const radius = (obj.scale.x / 2 + obj.scale.z / 2) / 2;
|
||||||
|
const collider = factory.ColliderDesc.roundCylinder(
|
||||||
|
height,
|
||||||
|
radius,
|
||||||
|
height
|
||||||
|
);
|
||||||
|
return world.createCollider(collider, body);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instance: Capsule,
|
||||||
|
createCollisionShape: (
|
||||||
|
obj: Brick,
|
||||||
|
factory: typeof RAPIER,
|
||||||
|
world: RAPIER.World,
|
||||||
|
body?: RAPIER.RigidBody
|
||||||
|
) => {
|
||||||
|
const height = obj.scale.y / 2;
|
||||||
|
const radius = (obj.scale.x / 2 + obj.scale.z / 2) / 2;
|
||||||
|
const collider = factory.ColliderDesc.capsule(height, radius);
|
||||||
|
return world.createCollider(collider, body);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instance: Wedge,
|
||||||
|
createCollisionShape: (
|
||||||
|
obj: Brick,
|
||||||
|
factory: typeof RAPIER,
|
||||||
|
world: RAPIER.World,
|
||||||
|
body?: RAPIER.RigidBody
|
||||||
|
) => {
|
||||||
|
const mat = new Matrix4();
|
||||||
|
mat.makeScale(...obj.scale.toArray());
|
||||||
|
const points = obj
|
||||||
|
.getGeometry()
|
||||||
|
.getAttribute('position')
|
||||||
|
.clone()
|
||||||
|
.applyMatrix4(mat)?.array as Float32Array;
|
||||||
|
const collider = factory.ColliderDesc.convexMesh(points)!;
|
||||||
|
return world.createCollider(collider, body);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instance: WedgeCorner,
|
||||||
|
createCollisionShape: (
|
||||||
|
obj: Brick,
|
||||||
|
factory: typeof RAPIER,
|
||||||
|
world: RAPIER.World,
|
||||||
|
body?: RAPIER.RigidBody
|
||||||
|
) => {
|
||||||
|
const mat = new Matrix4();
|
||||||
|
mat.makeScale(...obj.scale.toArray());
|
||||||
|
const points = obj
|
||||||
|
.getGeometry()
|
||||||
|
.getAttribute('position')
|
||||||
|
.clone()
|
||||||
|
.applyMatrix4(mat)?.array as Float32Array;
|
||||||
|
const collider = factory.ColliderDesc.convexMesh(points)!;
|
||||||
|
return world.createCollider(collider, body);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instance: WedgeInnerCorner,
|
||||||
|
createCollisionShape: (
|
||||||
|
obj: Brick,
|
||||||
|
factory: typeof RAPIER,
|
||||||
|
world: RAPIER.World,
|
||||||
|
body?: RAPIER.RigidBody
|
||||||
|
) => {
|
||||||
|
const mat = new Matrix4();
|
||||||
|
mat.makeScale(...obj.scale.toArray());
|
||||||
|
const points = obj
|
||||||
|
.getGeometry()
|
||||||
|
.getAttribute('position')
|
||||||
|
.clone()
|
||||||
|
.applyMatrix4(mat)?.array as Float32Array;
|
||||||
|
const collider = factory.ColliderDesc.convexMesh(points)!;
|
||||||
|
return world.createCollider(collider, body);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instance: Brick,
|
||||||
|
createCollisionShape: (
|
||||||
|
obj: Brick,
|
||||||
|
factory: typeof RAPIER,
|
||||||
|
world: RAPIER.World,
|
||||||
|
body?: RAPIER.RigidBody
|
||||||
|
) => {
|
||||||
|
const scale = obj.scale.clone().divideScalar(2);
|
||||||
|
const collider = factory.ColliderDesc.cuboid(scale.x, scale.y, scale.z);
|
||||||
|
return world.createCollider(collider, body);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
static createCollider<T extends Brick>(
|
||||||
|
obj: T,
|
||||||
|
factory: typeof RAPIER,
|
||||||
|
world: RAPIER.World,
|
||||||
|
body?: RAPIER.RigidBody
|
||||||
|
) {
|
||||||
|
const collider = ColliderFactory.gameObjectColliders.find(
|
||||||
|
(entry) => obj instanceof entry.instance
|
||||||
|
);
|
||||||
|
if (!collider) return undefined;
|
||||||
|
return collider.createCollisionShape(obj, factory, world, body);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
export * from './rapier';
|
||||||
|
export * from './physics-object';
|
||||||
|
export * from './colliders';
|
|
@ -0,0 +1,73 @@
|
||||||
|
import { Quaternion, Vector3 } from 'three';
|
||||||
|
import { GameObject3D } from '../types/game-object';
|
||||||
|
import { Ticking } from '../types/ticking';
|
||||||
|
import type { Humanoid } from '../gameobjects/humanoid.object';
|
||||||
|
import type Rapier from '@dimforge/rapier3d';
|
||||||
|
|
||||||
|
export class PhysicsObjectAssociation implements Ticking {
|
||||||
|
uuid: string;
|
||||||
|
isTickingObject = true;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public object: GameObject3D,
|
||||||
|
public collider?: Rapier.Collider,
|
||||||
|
public body?: Rapier.RigidBody
|
||||||
|
) {
|
||||||
|
this.uuid = object.uuid;
|
||||||
|
}
|
||||||
|
initialize(): void {}
|
||||||
|
|
||||||
|
tick(dt: number): void {
|
||||||
|
if (!this.body) return;
|
||||||
|
this.object.position.copy(this.body.translation() as any);
|
||||||
|
this.object.quaternion.copy(this.body.rotation() as any);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HumanoidPhysicsProxy extends PhysicsObjectAssociation {
|
||||||
|
constructor(
|
||||||
|
private humanoid: Humanoid,
|
||||||
|
private controller: Rapier.KinematicCharacterController,
|
||||||
|
private ray: Rapier.Ray,
|
||||||
|
private world: Rapier.World,
|
||||||
|
collider: Rapier.Collider,
|
||||||
|
body: Rapier.RigidBody
|
||||||
|
) {
|
||||||
|
super(humanoid.parent! as GameObject3D, collider, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
applyMovement(position: Vector3, velocity: Vector3) {
|
||||||
|
const vec3 = position.clone();
|
||||||
|
this.controller.computeColliderMovement(this.collider!, velocity);
|
||||||
|
const computed = this.controller.computedMovement();
|
||||||
|
vec3.copy(computed as Vector3);
|
||||||
|
// console.log(computed, position);
|
||||||
|
this.body?.setNextKinematicTranslation(vec3.add(position));
|
||||||
|
// After the collider movement calculation is done, we can read the
|
||||||
|
// collision events.
|
||||||
|
// for (let i = 0; i < this.controller.numComputedCollisions(); i++) {
|
||||||
|
// let collision = this.controller.computedCollision(i);
|
||||||
|
// // Do something with that collision information.
|
||||||
|
// console.log(collision);
|
||||||
|
// }
|
||||||
|
// this.collider?.setTranslation(colliderHalf);
|
||||||
|
// this.humanoid.parent!.position.copy(computed as Vector3).sub(halfVec);
|
||||||
|
|
||||||
|
vec3.copy(this.humanoid.parent!.position);
|
||||||
|
this.ray.origin = vec3;
|
||||||
|
this.ray.origin.y -= 0.01;
|
||||||
|
const hit = this.world.castRay(this.ray, 0.5, false);
|
||||||
|
this.humanoid.grounded = false;
|
||||||
|
if (hit) {
|
||||||
|
const point = this.ray.pointAt(hit.toi);
|
||||||
|
const diff = vec3.y - (point.y + 0.15);
|
||||||
|
if (diff < 0) {
|
||||||
|
this.humanoid.grounded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
applyRotation(quat: Quaternion) {
|
||||||
|
this.body?.setNextKinematicRotation(quat);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
export type Rapier = typeof import('@dimforge/rapier3d');
|
||||||
|
|
||||||
|
export function getRapier() {
|
||||||
|
return import('@dimforge/rapier3d');
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
export interface Disposable {
|
||||||
|
dispose(): void;
|
||||||
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
|
import { Disposable } from './disposable';
|
||||||
import { Renderer } from '../core/renderer';
|
import { Renderer } from '../core/renderer';
|
||||||
import { EventEmitter } from '../utils/events';
|
import { EventEmitter } from '../utils/events';
|
||||||
import { EngineEvents } from './events';
|
import { EngineEvents } from './events';
|
||||||
|
|
||||||
export abstract class EngineComponent {
|
export abstract class EngineComponent implements Disposable {
|
||||||
public abstract name: string;
|
public abstract name: string;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|
|
@ -80,6 +80,7 @@ export type EngineEvents = {
|
||||||
instance: (event: InstanceEvent) => void;
|
instance: (event: InstanceEvent) => void;
|
||||||
sceneJoin: (event: Object3D) => void;
|
sceneJoin: (event: Object3D) => void;
|
||||||
sceneLeave: (event: Object3D) => void;
|
sceneLeave: (event: Object3D) => void;
|
||||||
|
queueFree: (event: Object3D) => void;
|
||||||
loadComplete: () => void;
|
loadComplete: () => void;
|
||||||
initialized: () => void;
|
initialized: () => void;
|
||||||
reset: () => void;
|
reset: () => void;
|
||||||
|
|
|
@ -5,3 +5,4 @@ export * from './game-object';
|
||||||
export * from './instancable';
|
export * from './instancable';
|
||||||
export * from './world-file';
|
export * from './world-file';
|
||||||
export * from './asset';
|
export * from './asset';
|
||||||
|
export * from './disposable';
|
||||||
|
|
|
@ -80,6 +80,7 @@ export const instanceCharacterObject = async (name: string) => {
|
||||||
controller.position.set(0, 4.75, 0);
|
controller.position.set(0, 4.75, 0);
|
||||||
controller.archivable = false;
|
controller.archivable = false;
|
||||||
baseObject.add(controller);
|
baseObject.add(controller);
|
||||||
|
baseObject.position.set(0, 0.1, 0);
|
||||||
|
|
||||||
return baseObject;
|
return baseObject;
|
||||||
};
|
};
|
||||||
|
|
162
pnpm-lock.yaml
162
pnpm-lock.yaml
|
@ -98,6 +98,12 @@ importers:
|
||||||
vite-plugin-dts:
|
vite-plugin-dts:
|
||||||
specifier: ^2.3.0
|
specifier: ^2.3.0
|
||||||
version: 2.3.0(vite@4.3.9)
|
version: 2.3.0(vite@4.3.9)
|
||||||
|
vite-plugin-top-level-await:
|
||||||
|
specifier: ^1.3.1
|
||||||
|
version: 1.3.1(vite@4.3.9)
|
||||||
|
vite-plugin-wasm:
|
||||||
|
specifier: ^3.2.2
|
||||||
|
version: 3.2.2(vite@4.3.9)
|
||||||
vue:
|
vue:
|
||||||
specifier: ^3.2.47
|
specifier: ^3.2.47
|
||||||
version: 3.2.47
|
version: 3.2.47
|
||||||
|
@ -160,6 +166,9 @@ importers:
|
||||||
|
|
||||||
packages/engine:
|
packages/engine:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@dimforge/rapier3d':
|
||||||
|
specifier: ^0.11.2
|
||||||
|
version: 0.11.2
|
||||||
reflect-metadata:
|
reflect-metadata:
|
||||||
specifier: ^0.1.13
|
specifier: ^0.1.13
|
||||||
version: 0.1.13
|
version: 0.1.13
|
||||||
|
@ -529,6 +538,10 @@ packages:
|
||||||
mime: 3.0.0
|
mime: 3.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@dimforge/rapier3d@0.11.2:
|
||||||
|
resolution: {integrity: sha512-B+AKkPmtJxED3goMTGU8v0ju8hUAUQGLgghzCos4G4OeN9X+mJ5lfN2xtNA0n8tJRJk2YfsMk9BOj/6AN89Acg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@esbuild-kit/cjs-loader@2.4.2:
|
/@esbuild-kit/cjs-loader@2.4.2:
|
||||||
resolution: {integrity: sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==}
|
resolution: {integrity: sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -1322,6 +1335,16 @@ packages:
|
||||||
terser: 5.18.1
|
terser: 5.18.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@rollup/plugin-virtual@3.0.1:
|
||||||
|
resolution: {integrity: sha512-fK8O0IL5+q+GrsMLuACVNk2x21g3yaw+sG2qn16SnUd3IlBsQyvWxLMGHmCmXRMecPjGRSZ/1LmZB4rjQm68og==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
rollup: ^1.20.0||^2.0.0||^3.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
rollup:
|
||||||
|
optional: true
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@rollup/plugin-wasm@6.1.3(rollup@3.23.0):
|
/@rollup/plugin-wasm@6.1.3(rollup@3.23.0):
|
||||||
resolution: {integrity: sha512-7ItTTeyauE6lwdDtQWceEHZ9+txbi4RRy0mYPFn9BW7rD7YdgBDu7HTHsLtHrRzJc313RM/1m6GKgV3np/aEaw==}
|
resolution: {integrity: sha512-7ItTTeyauE6lwdDtQWceEHZ9+txbi4RRy0mYPFn9BW7rD7YdgBDu7HTHsLtHrRzJc313RM/1m6GKgV3np/aEaw==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
|
@ -1419,6 +1442,118 @@ packages:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@swc/core-darwin-arm64@1.3.65:
|
||||||
|
resolution: {integrity: sha512-fQIXZgr7CD/+1ADqrVbz/gHvSoIMmggHvPzguQjV8FggBuS9Efm1D1ZrdUSqptggKvuLLHMZf+49tENq8NWWcg==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@swc/core-darwin-x64@1.3.65:
|
||||||
|
resolution: {integrity: sha512-kGuWP7OP9mwOiIcJpEVa+ydC3Wxf0fPQ1MK0hUIPFcR6tAUEdOvdAuCzP6U20RX/JbbgwfI/Qq6ugT7VL6omgg==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@swc/core-linux-arm-gnueabihf@1.3.65:
|
||||||
|
resolution: {integrity: sha512-Bjbzldp8n4mWSdAvBt4VuLiHlfFM5pyftjJvJnmSY4H1IzbxkByyT60OHOedcIPRiZveD8NJzUJqutqrgTmtLg==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@swc/core-linux-arm64-gnu@1.3.65:
|
||||||
|
resolution: {integrity: sha512-GmxtcCymeQqEqT9n5mo857koRsUbEwmuijrBA4OeD5KOPW9gqAmUxr+ZgwgYHwyJ3CiN+UbK8uEqPsL6UVQmLg==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@swc/core-linux-arm64-musl@1.3.65:
|
||||||
|
resolution: {integrity: sha512-yv9jP3gbfMsYrqswT2MwK5Q1+avSwRXAKo+LYUknTeoLQNNlukDfqSLHajNq23XrVDRP4B3Pjn7kaqjxRcihbg==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@swc/core-linux-x64-gnu@1.3.65:
|
||||||
|
resolution: {integrity: sha512-GQkwysEPTlAOQ3jiTiedObzh6pBaf9RLaQqpGdCp+iKze9+BR+STBP0IIKhZDMPG/nWWNhrYFD/VMQxRoYPjfw==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@swc/core-linux-x64-musl@1.3.65:
|
||||||
|
resolution: {integrity: sha512-ETzhOhtDluYFK4x73OTM9gVTMyzGd2WeWGlCu3WoT1EPPUwCqQpcAqI3TfEcP1ljFDG0pPkpYzVpwNf8yjQElg==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@swc/core-win32-arm64-msvc@1.3.65:
|
||||||
|
resolution: {integrity: sha512-3weD0I6F8bggN0KOnbZkvYC1PBrT5wrvohpvtgijRsODxjoWwztozjawJxF3rqgVqlSI/+nA+JkrN48e2cxJjQ==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [win32]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@swc/core-win32-ia32-msvc@1.3.65:
|
||||||
|
resolution: {integrity: sha512-i6c3D7E9Ca41HteW3+hn1OKQfjIabc2P0p1mJRXBkn+igwb+Ba6gXJc7NqhrlF8uZsDhhcGZTsAqBBtfcfTuHQ==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [ia32]
|
||||||
|
os: [win32]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@swc/core-win32-x64-msvc@1.3.65:
|
||||||
|
resolution: {integrity: sha512-tQ9hEDtwPZxQ2sYb2n8ypfmdMjobKAf6VSnChteLMktofU7o562op5pLS6D6QCP2AtL3lcwe1piTCgIhk4vmjA==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@swc/core@1.3.65:
|
||||||
|
resolution: {integrity: sha512-d5iDiKWf12FBo6h9Fro2pcnLK6HSPbyZ7A1U5iFNpRRx8XEd4uGdKtf5NoXJ3GDLQDLXnNSLA82Cl6SfrJ1lyw==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
requiresBuild: true
|
||||||
|
peerDependencies:
|
||||||
|
'@swc/helpers': ^0.5.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@swc/helpers':
|
||||||
|
optional: true
|
||||||
|
optionalDependencies:
|
||||||
|
'@swc/core-darwin-arm64': 1.3.65
|
||||||
|
'@swc/core-darwin-x64': 1.3.65
|
||||||
|
'@swc/core-linux-arm-gnueabihf': 1.3.65
|
||||||
|
'@swc/core-linux-arm64-gnu': 1.3.65
|
||||||
|
'@swc/core-linux-arm64-musl': 1.3.65
|
||||||
|
'@swc/core-linux-x64-gnu': 1.3.65
|
||||||
|
'@swc/core-linux-x64-musl': 1.3.65
|
||||||
|
'@swc/core-win32-arm64-msvc': 1.3.65
|
||||||
|
'@swc/core-win32-ia32-msvc': 1.3.65
|
||||||
|
'@swc/core-win32-x64-msvc': 1.3.65
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@tootallnate/once@2.0.0:
|
/@tootallnate/once@2.0.0:
|
||||||
resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
|
resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
|
@ -6655,6 +6790,11 @@ packages:
|
||||||
which-typed-array: 1.1.9
|
which-typed-array: 1.1.9
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/uuid@9.0.0:
|
||||||
|
resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==}
|
||||||
|
hasBin: true
|
||||||
|
dev: false
|
||||||
|
|
||||||
/validate-npm-package-license@3.0.4:
|
/validate-npm-package-license@3.0.4:
|
||||||
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
|
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -6790,6 +6930,20 @@ packages:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/vite-plugin-top-level-await@1.3.1(vite@4.3.9):
|
||||||
|
resolution: {integrity: sha512-55M1h4NAwkrpxPNOJIBzKZFihqLUzIgnElLSmPNPMR2Fn9+JHKaNg3sVX1Fq+VgvuBksQYxiD3OnwQAUu7kaPQ==}
|
||||||
|
peerDependencies:
|
||||||
|
vite: '>=2.8'
|
||||||
|
dependencies:
|
||||||
|
'@rollup/plugin-virtual': 3.0.1
|
||||||
|
'@swc/core': 1.3.65
|
||||||
|
uuid: 9.0.0
|
||||||
|
vite: 4.3.9(@types/node@18.0.0)(sass@1.62.1)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@swc/helpers'
|
||||||
|
- rollup
|
||||||
|
dev: false
|
||||||
|
|
||||||
/vite-plugin-vue-inspector@3.4.2(vite@4.3.9):
|
/vite-plugin-vue-inspector@3.4.2(vite@4.3.9):
|
||||||
resolution: {integrity: sha512-q5OTkcZJqL78bwGJl1Zk8CNqtxZ9wP2udJYqyFIZzL1lTax0/oq7DhNkLrnPTxkJuf0QPZKdunb1vDyCByn4dQ==}
|
resolution: {integrity: sha512-q5OTkcZJqL78bwGJl1Zk8CNqtxZ9wP2udJYqyFIZzL1lTax0/oq7DhNkLrnPTxkJuf0QPZKdunb1vDyCByn4dQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -6809,6 +6963,14 @@ packages:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/vite-plugin-wasm@3.2.2(vite@4.3.9):
|
||||||
|
resolution: {integrity: sha512-cdbBUNR850AEoMd5nvLmnyeq63CSfoP1ctD/L2vLk/5+wsgAPlAVAzUK5nGKWO/jtehNlrSSHLteN+gFQw7VOA==}
|
||||||
|
peerDependencies:
|
||||||
|
vite: ^2 || ^3 || ^4
|
||||||
|
dependencies:
|
||||||
|
vite: 4.3.9(@types/node@18.0.0)(sass@1.62.1)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/vite@4.3.9(@types/node@18.0.0)(sass@1.62.1):
|
/vite@4.3.9(@types/node@18.0.0)(sass@1.62.1):
|
||||||
resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==}
|
resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==}
|
||||||
engines: {node: ^14.18.0 || >=16.0.0}
|
engines: {node: ^14.18.0 || >=16.0.0}
|
||||||
|
|
Loading…
Reference in New Issue