diff --git a/packages/serenity/src/handlers/inventory-transaction.ts b/packages/serenity/src/handlers/inventory-transaction.ts index 07447b3e..0ad7eef9 100644 --- a/packages/serenity/src/handlers/inventory-transaction.ts +++ b/packages/serenity/src/handlers/inventory-transaction.ts @@ -191,8 +191,14 @@ class InventoryTransaction extends SerenityHandler { blockType.permutations[usingItem.metadata] ?? blockType.getPermutation(); + // Get the click position of the packet + const clickPosition = transaction.clickPosition; + // Set the block with the blockType permutation based off the items metadata - resultingBlock.setPermutation(blockPermutation, player); + resultingBlock.setPermutation(blockPermutation, { + player, + clickPosition + }); // Check if the player is in survival mode, if so decrement the item if (player.gamemode === Gamemode.Survival) usingItem.decrement(); diff --git a/packages/world/src/block/block.ts b/packages/world/src/block/block.ts index 2ee9074e..af25574f 100644 --- a/packages/world/src/block/block.ts +++ b/packages/world/src/block/block.ts @@ -20,10 +20,9 @@ import { CompoundTag } from "@serenityjs/nbt"; import { ItemStack } from "../item"; import { BlockComponent } from "../components"; -import type { BlockComponents } from "../types"; +import type { BlockComponents, BlockUpdateOptions } from "../types"; import type { Chunk } from "../chunk"; import type { Player } from "../player"; -import type { CardinalDirection } from "../enums"; import type { Dimension } from "../world"; class Block { @@ -164,11 +163,11 @@ class Block { /** * Sets the permutation of the block. * @param permutation The permutation to set. - * @param playerInitiated If the change was initiated by a player. + * @param options The options of the block update. */ public setPermutation( permutation: BlockPermutation, - playerInitiated?: Player + options?: BlockUpdateOptions ): Block { // Clear the previous components. if (this.permutation.type !== permutation.type) this.clearComponents(); @@ -221,11 +220,14 @@ class Block { // Check if the change was initiated by a player. // If so, we will play the block place sound. - if (playerInitiated) { + if (options && options.player) { + // Get the clicked position of the player. + const clickedPosition = options.clickPosition ?? new Vector3f(0, 0, 0); + // Call the onPlace method of the components. for (const component of this.components.values()) { // Call the onBlockPlacedByPlayer method. - component.onPlace?.(playerInitiated); + component.onPlace?.(options.player, clickedPosition); } // Create a new LevelSoundEventPacket. @@ -272,12 +274,12 @@ class Block { * @param type The type of the block. * @param playerInitiated If the change was initiated by a player. */ - public setType(type: BlockType, playerInitiated?: Player): Block { + public setType(type: BlockType, options?: BlockUpdateOptions): Block { // Get the permutation of the block. const permutation = type.getPermutation(); // Set the permutation of the block. - this.setPermutation(permutation, playerInitiated); + this.setPermutation(permutation, { player: options?.player }); // Return the block. return this; @@ -459,32 +461,6 @@ class Block { } } - /** - * Sets the direction of the block. - * @param direction The direction to set. - * @param upsideDown If the block is upside down. - */ - // TODO: Add support for minecraft:cardinal_direction states. (chest, furnace, etc.) - public setDirection( - direction: CardinalDirection, - upsideDown?: boolean - ): void { - // Get the state keys - const keys = Object.keys(this.permutation.state); - - // Check if the block has a weirdo direction state. - if (keys.includes("weirdo_direction") && keys.includes("upside_down_bit")) { - // Get the new permutation with the direction state. - const permutation = this.permutation.type.getPermutation({ - upside_down_bit: upsideDown ?? false, - weirdo_direction: direction - }); - - // set the permutation - this.setPermutation(permutation); - } - } - /** * Destroys the block. * @param playerInitiated If the block was destroyed by a player. diff --git a/packages/world/src/components/block/block-component.ts b/packages/world/src/components/block/block-component.ts index dae4fee5..d928aa6e 100644 --- a/packages/world/src/components/block/block-component.ts +++ b/packages/world/src/components/block/block-component.ts @@ -1,5 +1,6 @@ import { Component } from "../component"; +import type { Vector3f } from "@serenityjs/protocol"; import type { BlockIdentifier, BlockType } from "@serenityjs/block"; import type { Player } from "../../player"; import type { Block } from "../../block"; @@ -88,8 +89,9 @@ class BlockComponent extends Component { /** * Called when the block is placed in the dimension. * @param player The player that placed the block. + * @param clickPosition The position of the affected block which was clicked. */ - public onPlace?(player: Player): void; + public onPlace?(player: Player, clickPosition: Vector3f): void; /** * Called when the block is destruction process has started in the dimension. diff --git a/packages/world/src/components/block/state/index.ts b/packages/world/src/components/block/state/index.ts index 524379aa..42135e87 100644 --- a/packages/world/src/components/block/state/index.ts +++ b/packages/world/src/components/block/state/index.ts @@ -1,2 +1,3 @@ export * from "./cardinal-direction"; export * from "./weirdo-direction"; +export * from "./upside-down-bit"; diff --git a/packages/world/src/components/block/state/upside-down-bit.ts b/packages/world/src/components/block/state/upside-down-bit.ts new file mode 100644 index 00000000..95ff364f --- /dev/null +++ b/packages/world/src/components/block/state/upside-down-bit.ts @@ -0,0 +1,53 @@ +import { BlockComponent } from "../block-component"; + +import type { Vector3f } from "@serenityjs/protocol"; +import type { Player } from "../../../player"; +import type { Block } from "../../../block"; + +class BlockUpsideDownBitComponent extends BlockComponent { + public static readonly identifier = "minecraft:upside_down_bit"; + + public constructor(block: Block) { + super(block, BlockUpsideDownBitComponent.identifier); + } + + public onPlace(_: Player, clickPosition: Vector3f): void { + // Check if the click position is on the top face of the block + if (clickPosition.y === 1) return this.setUpsideDown(false); + + // Check if the click position is on the bottom face of + if (clickPosition.y === 0) return this.setUpsideDown(true); + + // Check if the block needs to be upside down + const upsideDown = clickPosition.y > 0.5; + + // Set the direction of the block + return this.setUpsideDown(upsideDown); + } + + /** + * Sets the direction of the block. + * @param direction The direction to set. + */ + public setUpsideDown(upsideDown: boolean): void { + // Get the block type + const type = this.block.getType(); + + // Get the state of the block + const state = this.block.permutation.state; + + // Create the state of the block + const newState = { + ...state, + upside_down_bit: upsideDown + }; + + // Set the direction of the block + const permutation = type.getPermutation(newState); + + // Set the permutation of the block + if (permutation) this.block.setPermutation(permutation); + } +} + +export { BlockUpsideDownBitComponent }; diff --git a/packages/world/src/components/block/state/weirdo-direction.ts b/packages/world/src/components/block/state/weirdo-direction.ts index 9f4707e4..7253227d 100644 --- a/packages/world/src/components/block/state/weirdo-direction.ts +++ b/packages/world/src/components/block/state/weirdo-direction.ts @@ -27,10 +27,17 @@ class BlockWeirdoDirectionComponent extends BlockComponent { // Get the block type const type = this.block.getType(); - // Get the permutation of the block - const permutation = type.getPermutation({ + // Get the state of the block + const state = this.block.permutation.state; + + // Create the state of the block + const newState = { + ...state, weirdo_direction: direction - }); + }; + + // Get the permutation of the block + const permutation = type.getPermutation(newState); // Set the permutation of the block if (permutation) this.block.setPermutation(permutation); diff --git a/packages/world/src/types/block/index.ts b/packages/world/src/types/block/index.ts index be6f7157..87f102e7 100644 --- a/packages/world/src/types/block/index.ts +++ b/packages/world/src/types/block/index.ts @@ -1 +1,2 @@ export * from "./state"; +export * from "./update"; diff --git a/packages/world/src/types/block/state.ts b/packages/world/src/types/block/state.ts index c4ea2be8..9f2691d5 100644 --- a/packages/world/src/types/block/state.ts +++ b/packages/world/src/types/block/state.ts @@ -1,4 +1,4 @@ -import { ByteTag, CompoundTag, StringTag } from "@serenityjs/nbt"; +import type { ByteTag, CompoundTag, StringTag } from "@serenityjs/nbt"; /** * A block state. diff --git a/packages/world/src/types/block/update.ts b/packages/world/src/types/block/update.ts new file mode 100644 index 00000000..45e7049b --- /dev/null +++ b/packages/world/src/types/block/update.ts @@ -0,0 +1,9 @@ +import type { Vector3f } from "@serenityjs/protocol"; +import type { Player } from "../../player"; + +interface BlockUpdateOptions { + readonly player?: Player; + readonly clickPosition?: Vector3f; +} + +export { BlockUpdateOptions }; diff --git a/packages/world/src/types/components/block.ts b/packages/world/src/types/components/block.ts index c08a05b2..7b7beb15 100644 --- a/packages/world/src/types/components/block.ts +++ b/packages/world/src/types/components/block.ts @@ -3,7 +3,8 @@ import type { BlockNametagComponent, BlockSignComponent, BlockCardinalDirectionComponent, - BlockWeirdoDirectionComponent + BlockWeirdoDirectionComponent, + BlockUpsideDownBitComponent } from "../../components"; interface BlockComponents { @@ -12,6 +13,7 @@ interface BlockComponents { "minecraft:sign": BlockSignComponent; "minecraft:cardinal_direction": BlockCardinalDirectionComponent; "minecraft:weirdo_direction": BlockWeirdoDirectionComponent; + "minecraft:upside_down_bit": BlockUpsideDownBitComponent; } export { BlockComponents };