feather
feather copied to clipboard
Block placement / interaction
The PlayerBlockPlacement
packet is also responsible for any block interaction ie. opening chests or filling bottles from a cauldron. The current block placement system have to be reworked into the following three steps.
-
Try to interact with the block
-
Try to place the held item at the location
-
Try to place the held item at the location + face
-
Interacting with blocks simple match over held item and block.
match (held_item, from_block) {
(_, Block::Chest(_)) => open_chest(),
(Item::Bottle, Block::Cauldron(_)) => fill_bottle(),
...
}
- Simple match on the from block, ie. can the block be replaced
match from_block {
Block::Air | Block::CaveAir | Block::Grass ... => place_block
}
// Handle waterlog
match (held_item, from_block) {
(Item::WaterBucket, Block::Fence) => Block::Fence(data.waterlogged = true),
...
}
- This step is identical to step 2. but the from block = state.block_at(location + face).
It might be wise to use a different approach than the match
for interactions—as the number of blocks supporting interactions increases, this function is going to get pretty unwieldy. Would something like the inventory crate be of interest here?
It seems like inventory would be a nice fit, however I had thought about using the event system. Such that an interaction event is first fired and it has a mutable canceled
field which any event handler must set to true if the interaction was successful. Second a block place event is fired at the location if the previous event was unsuccessful and last a block place event at location + face
.
I dont know how to add a mutable field to an event, if it is even possible without a mutex guard. If so it would be a synchronization overhead which would negatively effect performance.
Seems like tonks already uses inventory for event handler registration?
It appears block placement does not have any checks to make sure it is not blocked by an entity (ex: players) - I don't believe this is a known issue at the moment