diff --git a/server/MPClient.ts b/server/MPClient.ts index 1a97370..bf361a1 100644 --- a/server/MPClient.ts +++ b/server/MPClient.ts @@ -272,7 +272,7 @@ export class MPClient { return; } - if (itemStack.isBlock) { + if (itemStack.isBlock && Block.blocks[itemStack.itemID].behaviour.canPlaceBlockAt(this.entity.world, this.diggingAt.x, this.diggingAt.y, this.diggingAt.z)) { if (this.entity.world.getBlockId(this.diggingAt.x, this.diggingAt.y, this.diggingAt.z) === 0) { itemStack.size--; this.entity.world.setBlockAndMetadataWithNotify(this.diggingAt.x, this.diggingAt.y, this.diggingAt.z, itemStack.itemID, itemStack.damage); diff --git a/server/blocks/Block.ts b/server/blocks/Block.ts index 9e30397..bbd73f5 100644 --- a/server/blocks/Block.ts +++ b/server/blocks/Block.ts @@ -98,6 +98,7 @@ export class Block { } public setBehaviour(value:IBlockBehaviour) { + value.block = this; this.behaviour = value; return this; } diff --git a/server/blocks/BlockBehaviorSugarcane.ts b/server/blocks/BlockBehaviorSugarcane.ts index 36b0b81..2f768c7 100644 --- a/server/blocks/BlockBehaviorSugarcane.ts +++ b/server/blocks/BlockBehaviorSugarcane.ts @@ -11,6 +11,35 @@ export class BlockBehaviourSugarcane extends BlockBehaviour { } } + public canPlaceBlockAt(world: World, x: number, y: number, z: number) { + const blockBelow = world.getBlockId(x, y - 1, z); + + if (blockBelow === this.block.blockId) { + return true; + } + + // Check if right ground block + if (blockBelow !== Block.grass.blockId && blockBelow !== Block.dirt.blockId) { + return false; + } + + // Check if water is around + if (world.getBlockId(x - 1, y - 1, z) === Block.waterStill.blockId) { + return true; + } + if (world.getBlockId(x + 1, y - 1, z) === Block.waterStill.blockId) { + return true; + } + if (world.getBlockId(x, y - 1, z - 1) === Block.waterStill.blockId) { + return true; + } + if (world.getBlockId(x, y - 1, z + 1) === Block.waterStill.blockId) { + return true; + } + + return false; + } + public getBoundingBox() { return AABB.getAABB(0, 0, 0, 0, 0, 0); } diff --git a/server/blocks/BlockBehaviour.ts b/server/blocks/BlockBehaviour.ts index af76cf7..70a8606 100644 --- a/server/blocks/BlockBehaviour.ts +++ b/server/blocks/BlockBehaviour.ts @@ -1,12 +1,16 @@ import AABB from "../AABB"; import Random from "../Random"; import { World } from "../World"; +import { Block } from "./Block"; import { IBlockBehaviour } from "./IBlockBehaviour"; export class BlockBehaviour implements IBlockBehaviour { + public block!:Block; + public neighborBlockChange(world:World, x:number, y:number, z:number, blockId:number) {} public droppedItem(blockId:number) { return blockId; } public droppedCount(blockId:number) { return 1; } public getBoundingBox(x:number, y:number, z:number) { return AABB.getAABB(0 + x, 0 + y, 0 + z, 1 + x, 1 + y, 1 + z); } public randomTick(world:World, x:number, y:number, z:number, random:Random) {} + public canPlaceBlockAt(world:World, x:number, y:number, z:number) { return true; } } \ No newline at end of file diff --git a/server/blocks/IBlockBehaviour.ts b/server/blocks/IBlockBehaviour.ts index 9f15b23..63ed61f 100644 --- a/server/blocks/IBlockBehaviour.ts +++ b/server/blocks/IBlockBehaviour.ts @@ -1,9 +1,15 @@ import AABB from "../AABB"; +import Random from "../Random"; import { World } from "../World"; +import { Block } from "./Block"; export interface IBlockBehaviour { + block:Block, + neighborBlockChange(world:World, x:number, y:number, z:number, blockId:number): void, droppedItem: (blockId:number) => number, droppedCount: (blockId:number) => number, getBoundingBox: (x:number, y:number, z:number) => AABB, + randomTick: (world:World, x:number, y:number, z:number, random:Random) => void, + canPlaceBlockAt: (world:World, x:number, y:number, z:number) => boolean } \ No newline at end of file diff --git a/server/packets/WindowClick.ts b/server/packets/WindowClick.ts new file mode 100644 index 0000000..58b4abf --- /dev/null +++ b/server/packets/WindowClick.ts @@ -0,0 +1,54 @@ +import { createWriter, IReader, Endian } from "bufferstuff"; +import { IPacket } from "./IPacket"; +import { Packet } from "../enums/Packet"; + +export class PacketWindowClick implements IPacket { + public packetId = Packet.WindowClick; + public windowId:number; + public slot:number; + public rightClick:boolean; + public actionNumber:number; + public shift:boolean; + public itemId:number; + public itemCount:number; + public itemUses:number; + + public constructor(windowId?:number, slot?:number, rightClick?:boolean, actionNumber?:number, shift?:boolean, itemId?:number, itemCount?:number, itemUses?:number) { + if (typeof(windowId) === "number" && typeof(slot) === "number" && typeof(rightClick) === "boolean" && typeof(actionNumber) === "number" && typeof(shift) === "boolean" && typeof(itemId) === "number" && typeof(itemCount) === "number" && typeof(itemUses) === "number") { + this.windowId = windowId; + this.slot = slot; + this.rightClick = rightClick; + this.actionNumber = actionNumber; + this.shift = shift; + this.itemId = itemId; + this.itemCount = itemCount; + this.itemUses = itemUses; + } else { + this.windowId = Number.MIN_VALUE; + this.slot = Number.MIN_VALUE; + this.rightClick = false; + this.actionNumber = Number.MIN_VALUE; + this.shift = false; + this.itemId = Number.MIN_VALUE; + this.itemCount = Number.MIN_VALUE; + this.itemUses = Number.MIN_VALUE; + } + } + + public readData(reader:IReader) { + this.windowId = reader.readByte(); + this.slot = reader.readShort(); + this.rightClick = reader.readBool(); + this.actionNumber = reader.readShort(); + this.shift = reader.readBool(); + this.itemId = reader.readShort(); + this.itemCount = reader.readByte(); + this.itemUses = reader.readShort(); + + return this; + } + + public writeData() { + return createWriter(Endian.BE, 4).writeUByte(this.packetId).writeByte(this.windowId).writeShort(this.slot).writeBool(this.rightClick).writeShort(this.actionNumber).writeShort(this.itemId).writeByte(this.itemCount).writeShort(this.itemUses).toBuffer(); + } +} \ No newline at end of file