WIP: Item Collection
This commit is contained in:
parent
3ea5e47c57
commit
dc05cd4a2d
9 changed files with 92 additions and 4 deletions
|
@ -14,6 +14,7 @@ import { PacketDestroyEntity } from "./packets/DestroyEntity";
|
||||||
import { PacketPickupSpawn } from "./packets/PickupSpawn";
|
import { PacketPickupSpawn } from "./packets/PickupSpawn";
|
||||||
import { QueuedBlockUpdate } from "./queuedUpdateTypes/BlockUpdate";
|
import { QueuedBlockUpdate } from "./queuedUpdateTypes/BlockUpdate";
|
||||||
import { IQueuedUpdate } from "./queuedUpdateTypes/IQueuedUpdate";
|
import { IQueuedUpdate } from "./queuedUpdateTypes/IQueuedUpdate";
|
||||||
|
import AABB from "./AABB";
|
||||||
|
|
||||||
export class World {
|
export class World {
|
||||||
public static ENTITY_MAX_SEND_DISTANCE = 50;
|
public static ENTITY_MAX_SEND_DISTANCE = 50;
|
||||||
|
@ -25,6 +26,7 @@ export class World {
|
||||||
public chunks:FunkyArray<number, Chunk>;
|
public chunks:FunkyArray<number, Chunk>;
|
||||||
public entites:FunkyArray<number, IEntity>;
|
public entites:FunkyArray<number, IEntity>;
|
||||||
public players:FunkyArray<number, Player>;
|
public players:FunkyArray<number, Player>;
|
||||||
|
public playerHitboxes:FunkyArray<number, AABB>;
|
||||||
|
|
||||||
public queuedChunkBlocks:Array<IQueuedUpdate>;
|
public queuedChunkBlocks:Array<IQueuedUpdate>;
|
||||||
public queuedUpdates:Array<IQueuedUpdate>;
|
public queuedUpdates:Array<IQueuedUpdate>;
|
||||||
|
@ -40,6 +42,7 @@ export class World {
|
||||||
this.chunks = new FunkyArray<number, Chunk>();
|
this.chunks = new FunkyArray<number, Chunk>();
|
||||||
this.entites = new FunkyArray<number, IEntity>();
|
this.entites = new FunkyArray<number, IEntity>();
|
||||||
this.players = new FunkyArray<number, Player>();
|
this.players = new FunkyArray<number, Player>();
|
||||||
|
this.playerHitboxes = new FunkyArray<number, AABB>();
|
||||||
this.queuedChunkBlocks = new Array<IQueuedUpdate>();
|
this.queuedChunkBlocks = new Array<IQueuedUpdate>();
|
||||||
this.queuedUpdates = new Array<IQueuedUpdate>();
|
this.queuedUpdates = new Array<IQueuedUpdate>();
|
||||||
this.generator = generator;
|
this.generator = generator;
|
||||||
|
@ -47,6 +50,7 @@ export class World {
|
||||||
|
|
||||||
public addEntity(entity:IEntity) {
|
public addEntity(entity:IEntity) {
|
||||||
this.entites.set(entity.entityId, entity);
|
this.entites.set(entity.entityId, entity);
|
||||||
|
this.playerHitboxes.set(entity.entityId, entity.entityAABB);
|
||||||
if (entity instanceof Player) {
|
if (entity instanceof Player) {
|
||||||
this.players.set(entity.entityId, entity);
|
this.players.set(entity.entityId, entity);
|
||||||
} else if (entity instanceof EntityItem) {
|
} else if (entity instanceof EntityItem) {
|
||||||
|
@ -72,6 +76,7 @@ export class World {
|
||||||
entity.loadedChunks = new Array<number>();
|
entity.loadedChunks = new Array<number>();
|
||||||
entity.justUnloaded = new Array<number>();
|
entity.justUnloaded = new Array<number>();
|
||||||
|
|
||||||
|
this.playerHitboxes.remove(entity.entityId);
|
||||||
this.players.remove(entity.entityId);
|
this.players.remove(entity.entityId);
|
||||||
|
|
||||||
if (!entity.isDead) {
|
if (!entity.isDead) {
|
||||||
|
@ -274,8 +279,7 @@ export class World {
|
||||||
if (entity instanceof Player) {
|
if (entity instanceof Player) {
|
||||||
if (entity.justUnloaded.length > 0) {
|
if (entity.justUnloaded.length > 0) {
|
||||||
for (const coordPair of entity.justUnloaded) {
|
for (const coordPair of entity.justUnloaded) {
|
||||||
if (this.chunks.get(coordPair) != undefined)
|
if (this.chunks.get(coordPair) != undefined) {
|
||||||
{
|
|
||||||
const chunkToUnload = this.getChunkByCoordPair(coordPair);
|
const chunkToUnload = this.getChunkByCoordPair(coordPair);
|
||||||
chunkToUnload.playersInChunk.remove(entity.entityId);
|
chunkToUnload.playersInChunk.remove(entity.entityId);
|
||||||
if (!chunkToUnload.forceLoaded && chunkToUnload.playersInChunk.length === 0) {
|
if (!chunkToUnload.forceLoaded && chunkToUnload.playersInChunk.length === 0) {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import { PacketEntityRelativeMove } from "../packets/EntityRelativeMove";
|
||||||
import { PacketEntityTeleport } from "../packets/EntityTeleport";
|
import { PacketEntityTeleport } from "../packets/EntityTeleport";
|
||||||
import { PacketEntityVelocity } from "../packets/EntityVelocity";
|
import { PacketEntityVelocity } from "../packets/EntityVelocity";
|
||||||
import { IEntity } from "./IEntity";
|
import { IEntity } from "./IEntity";
|
||||||
|
import { Player } from "./Player";
|
||||||
|
|
||||||
export class Entity implements IEntity {
|
export class Entity implements IEntity {
|
||||||
public static nextEntityId:number = 0;
|
public static nextEntityId:number = 0;
|
||||||
|
@ -113,6 +114,17 @@ export class Entity implements IEntity {
|
||||||
.writeByte(this.health);
|
.writeByte(this.health);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
collidesWithPlayer(aabb:AABB) {
|
||||||
|
let collidedWith:Player | undefined;
|
||||||
|
this.world.players.forEach(player => {
|
||||||
|
if (this.entityAABB.intersects(player.entityAABB)) {
|
||||||
|
collidedWith = player;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return collidedWith;
|
||||||
|
}
|
||||||
|
|
||||||
sendToNearby(buffer:Buffer) {
|
sendToNearby(buffer:Buffer) {
|
||||||
this.world.sendToNearbyClients(this, buffer);
|
this.world.sendToNearbyClients(this, buffer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { World } from "../World";
|
import { World } from "../World";
|
||||||
import { ItemStack } from "../inventories/ItemStack";
|
import { ItemStack } from "../inventories/ItemStack";
|
||||||
import { Entity } from "./Entity";
|
import { Entity } from "./Entity";
|
||||||
|
import { Player } from "./Player";
|
||||||
|
|
||||||
export class EntityItem extends Entity {
|
export class EntityItem extends Entity {
|
||||||
public age:number;
|
public age:number;
|
||||||
|
@ -27,6 +28,15 @@ export class EntityItem extends Entity {
|
||||||
super.onTick();
|
super.onTick();
|
||||||
if (this.pickupDelay > 0) {
|
if (this.pickupDelay > 0) {
|
||||||
this.pickupDelay--;
|
this.pickupDelay--;
|
||||||
|
} else {
|
||||||
|
let playerCollided;
|
||||||
|
if (playerCollided = this.collidesWithPlayer(this.entityAABB)) {
|
||||||
|
playerCollided.inventory.addItemStack(this.itemStack);
|
||||||
|
playerCollided.itemPickup(this, this.itemStack.size);
|
||||||
|
if (this.itemStack.size <= 0) {
|
||||||
|
this.kill();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.motion.add(0, -0.04, 0);
|
this.motion.add(0, -0.04, 0);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import AABB from "../AABB"
|
||||||
import Vec3 from "../Vec3"
|
import Vec3 from "../Vec3"
|
||||||
|
|
||||||
export interface IEntity {
|
export interface IEntity {
|
||||||
|
@ -8,6 +9,7 @@ export interface IEntity {
|
||||||
crouching:boolean,
|
crouching:boolean,
|
||||||
isDead:boolean,
|
isDead:boolean,
|
||||||
markedForDisposal:boolean,
|
markedForDisposal:boolean,
|
||||||
|
entityAABB:AABB,
|
||||||
updateMetadata:() => void,
|
updateMetadata:() => void,
|
||||||
distanceTo:(entity:IEntity) => number,
|
distanceTo:(entity:IEntity) => number,
|
||||||
onTick:() => void
|
onTick:() => void
|
||||||
|
|
|
@ -13,6 +13,9 @@ import PlayerInventory from "../inventories/PlayerInventory";
|
||||||
import { Item } from "../items/Item";
|
import { Item } from "../items/Item";
|
||||||
import { PacketEntityEquipment } from "../packets/EntityEquipment";
|
import { PacketEntityEquipment } from "../packets/EntityEquipment";
|
||||||
import { IReader, IWriter } from "bufferstuff";
|
import { IReader, IWriter } from "bufferstuff";
|
||||||
|
import { EntityItem } from "./EntityItem";
|
||||||
|
import { Entity } from "./Entity";
|
||||||
|
import { PacketCollectItem } from "../packets/CollectItem";
|
||||||
|
|
||||||
const CHUNK_LOAD_RANGE = 15;
|
const CHUNK_LOAD_RANGE = 15;
|
||||||
|
|
||||||
|
@ -34,7 +37,7 @@ export class Player extends EntityLiving {
|
||||||
this.loadedChunks = new Array<number>();
|
this.loadedChunks = new Array<number>();
|
||||||
this.justUnloaded = new Array<number>();
|
this.justUnloaded = new Array<number>();
|
||||||
|
|
||||||
this.inventory = new PlayerInventory();
|
this.inventory = new PlayerInventory(this);
|
||||||
|
|
||||||
this.inventory.setSlotItemStack(36, new ItemStack(Item.ironSword, 1));
|
this.inventory.setSlotItemStack(36, new ItemStack(Item.ironSword, 1));
|
||||||
this.inventory.setSlotItemStack(37, new ItemStack(Item.ironPickaxe, 1));
|
this.inventory.setSlotItemStack(37, new ItemStack(Item.ironPickaxe, 1));
|
||||||
|
@ -68,6 +71,14 @@ export class Player extends EntityLiving {
|
||||||
this.firstUpdate = true;
|
this.firstUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public itemPickup(entity:Entity, stackSize:number) {
|
||||||
|
if (!this.isDead) {
|
||||||
|
if (entity instanceof EntityItem) {
|
||||||
|
this.sendToAllNearby(new PacketCollectItem(entity.entityId, this.entityId).writeData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async updatePlayerChunks() {
|
private async updatePlayerChunks() {
|
||||||
const bitX = this.position.x >> 4;
|
const bitX = this.position.x >> 4;
|
||||||
const bitZ = this.position.z >> 4;
|
const bitZ = this.position.z >> 4;
|
||||||
|
|
|
@ -22,6 +22,7 @@ export enum Packet {
|
||||||
EntityAction = 0x13,
|
EntityAction = 0x13,
|
||||||
NamedEntitySpawn = 0x14,
|
NamedEntitySpawn = 0x14,
|
||||||
PickupSpawn = 0x15,
|
PickupSpawn = 0x15,
|
||||||
|
CollectItem = 0x16,
|
||||||
|
|
||||||
EntityVelocity = 0x1C,
|
EntityVelocity = 0x1C,
|
||||||
DestroyEntity = 0x1D,
|
DestroyEntity = 0x1D,
|
||||||
|
|
|
@ -38,6 +38,7 @@ export class Inventory implements IInventory {
|
||||||
}
|
}
|
||||||
|
|
||||||
addItemStack(itemStack:ItemStack) {
|
addItemStack(itemStack:ItemStack) {
|
||||||
|
throw new Error("Adding items to non player inventories is unimplemented.");
|
||||||
// Check bottom inventory row (hotbar) first.
|
// Check bottom inventory row (hotbar) first.
|
||||||
/*let workingItemStack:ItemStack | null;
|
/*let workingItemStack:ItemStack | null;
|
||||||
for (let slotId = 9; slotId <= 35; slotId++) {
|
for (let slotId = 9; slotId <= 35; slotId++) {
|
||||||
|
@ -106,4 +107,16 @@ export class Inventory implements IInventory {
|
||||||
|
|
||||||
return writer.toBuffer();
|
return writer.toBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constructInventorySinglePayload(slotId:number) {
|
||||||
|
const stack = this.itemStacks[slotId];
|
||||||
|
const writer = createWriter(Endian.BE, stack == null ? 2 : 5);
|
||||||
|
writer.writeShort(stack == null ? -1 : stack.itemID);
|
||||||
|
if (stack != null) {
|
||||||
|
writer.writeByte(stack.size);
|
||||||
|
writer.writeShort(stack.damage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return writer.toBuffer();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,14 @@
|
||||||
|
import { Player } from "../entities/Player";
|
||||||
import { Inventory } from "./Inventory";
|
import { Inventory } from "./Inventory";
|
||||||
import { ItemStack } from "./ItemStack";
|
import { ItemStack } from "./ItemStack";
|
||||||
|
|
||||||
export default class PlayerInventory extends Inventory {
|
export default class PlayerInventory extends Inventory {
|
||||||
public constructor() {
|
private player:Player;
|
||||||
|
|
||||||
|
public constructor(player:Player) {
|
||||||
super(44, "Player Inventory");
|
super(44, "Player Inventory");
|
||||||
|
|
||||||
|
this.player = player;
|
||||||
}
|
}
|
||||||
|
|
||||||
addItemStack(itemStack:ItemStack) {
|
addItemStack(itemStack:ItemStack) {
|
||||||
|
|
30
server/packets/CollectItem.ts
Normal file
30
server/packets/CollectItem.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { createWriter, IReader, Endian } from "bufferstuff";
|
||||||
|
import { IPacket } from "./IPacket";
|
||||||
|
import { Packet } from "../enums/Packet";
|
||||||
|
|
||||||
|
export class PacketCollectItem implements IPacket {
|
||||||
|
public packetId = Packet.CollectItem;
|
||||||
|
public collectedEID:number;
|
||||||
|
public collectorEID:number;
|
||||||
|
|
||||||
|
public constructor(collectedEID?:number, collectorEID?:number) {
|
||||||
|
if (typeof(collectedEID) === "number" && typeof(collectorEID) === "number") {
|
||||||
|
this.collectedEID = collectedEID;
|
||||||
|
this.collectorEID = collectorEID;
|
||||||
|
} else {
|
||||||
|
this.collectedEID = Number.MIN_VALUE;
|
||||||
|
this.collectorEID = Number.MIN_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readData(reader:IReader) {
|
||||||
|
this.collectedEID = reader.readInt();
|
||||||
|
this.collectorEID = reader.readInt();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public writeData() {
|
||||||
|
return createWriter(Endian.BE, 9).writeUByte(this.packetId).writeInt(this.collectedEID).writeInt(this.collectorEID).toBuffer();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue