Item entities
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import { ItemStack } from "$/common/inventory.ts";
|
||||
import type { EntityInfo } from "$/common/protocol.ts";
|
||||
import type { ClientLevel } from "../level/client_level.ts";
|
||||
import { Entity } from "./entity.ts";
|
||||
|
||||
// how many ticks a server position takes to reach, like minecraft's lerpTo
|
||||
const LERP_TICKS = 3;
|
||||
// how many ticks it takes to fly into whoever picked it up
|
||||
const PICKUP_TICKS = 3;
|
||||
|
||||
// an item lying on the ground. the server simulates it, this only moves where it's told and spins
|
||||
export class ItemEntity extends Entity {
|
||||
item: ItemStack;
|
||||
// ticks since it showed up, for spinning and bobbing
|
||||
age = 0;
|
||||
// so items dropped together don't spin in step
|
||||
readonly bob_offset = Math.random() * Math.PI * 2;
|
||||
|
||||
#target_x: number;
|
||||
#target_y: number;
|
||||
#target_z: number;
|
||||
#lerp_ticks = 0;
|
||||
|
||||
// who's picking it up, and for how many ticks it has been flying to them
|
||||
#picked_up_by: Entity | undefined;
|
||||
#pickup_age = 0;
|
||||
|
||||
constructor(level: ClientLevel, info: EntityInfo) {
|
||||
super(level, info.id, 0.25, 0.25, 0.125);
|
||||
this.item = ItemStack.from_data(info.item);
|
||||
this.set_position(info.x, info.y, info.z);
|
||||
this.#target_x = info.x;
|
||||
this.#target_y = info.y;
|
||||
this.#target_z = info.z;
|
||||
}
|
||||
|
||||
lerp_to(x: number, y: number, z: number) {
|
||||
this.#target_x = x;
|
||||
this.#target_y = y;
|
||||
this.#target_z = z;
|
||||
this.#lerp_ticks = LERP_TICKS;
|
||||
}
|
||||
|
||||
// it already went into their inventory on the server, this is only the animation
|
||||
pick_up(by: Entity) {
|
||||
this.#picked_up_by = by;
|
||||
}
|
||||
|
||||
tick() {
|
||||
this.age += 1;
|
||||
|
||||
if (this.#picked_up_by) {
|
||||
this.#pickup_age += 1;
|
||||
if (this.#pickup_age >= PICKUP_TICKS) {
|
||||
this.level.remove_entity(this.id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.#lerp_ticks > 0) {
|
||||
this.x += (this.#target_x - this.x) / this.#lerp_ticks;
|
||||
this.y += (this.#target_y - this.y) / this.#lerp_ticks;
|
||||
this.z += (this.#target_z - this.z) / this.#lerp_ticks;
|
||||
this.#lerp_ticks -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// while being picked up it speeds towards the middle of whoever took it, like minecraft's ItemPickupParticle
|
||||
override render_position(partial_tick: number) {
|
||||
const position = super.render_position(partial_tick);
|
||||
const by = this.#picked_up_by;
|
||||
if (!by) {
|
||||
return position;
|
||||
}
|
||||
const target = by.render_position(partial_tick);
|
||||
const t = Math.min(1, (this.#pickup_age + partial_tick) / PICKUP_TICKS) ** 2;
|
||||
return {
|
||||
x: position.x + (target.x - position.x) * t,
|
||||
y: position.y + (target.y + 0.5 - position.y) * t,
|
||||
z: position.z + (target.z - position.z) * t,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user