Skip to content

Commit

Permalink
feat: prevent moving items in inventory
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewgazelka committed Nov 13, 2024
1 parent d01763c commit bcb4936
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 18 deletions.
2 changes: 1 addition & 1 deletion crates/hyperion-inventory/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ impl PlayerInventory {
pub const OFFHAND_SLOT: u16 = OFFHAND_SLOT;

#[must_use]
pub fn crafting_item(&self, registry: &CraftingRegistry) -> ItemStack {
pub fn crafting_result(&self, registry: &CraftingRegistry) -> ItemStack {
let indices = core::array::from_fn::<u16, 4, _>(|i| (u16::try_from(i).unwrap() + 1));

let mut min_count = i8::MAX;
Expand Down
51 changes: 41 additions & 10 deletions crates/hyperion/src/simulation/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use hyperion_utils::EntityExt;
use tracing::{info, instrument, trace, warn};
use valence_generated::block::{BlockKind, BlockState, PropName};
use valence_protocol::{
Decode, Hand, Packet, VarInt, nbt,
Decode, Hand, ItemStack, Packet, VarInt, nbt,
packets::play::{
self, click_slot_c2s::SlotChange, client_command_c2s::ClientCommand,
player_action_c2s::PlayerAction, player_interact_entity_c2s::EntityInteraction,
Expand Down Expand Up @@ -292,7 +292,7 @@ fn player_action(mut data: &[u8], query: &PacketSwitchQuery<'_>) -> anyhow::Resu

query.events.push(event, query.world);
}
_ => bail!("unimplemented"),
action => bail!("unimplemented {action:?}"),
}

// todo: implement
Expand Down Expand Up @@ -510,17 +510,48 @@ pub fn custom_payload(
Ok(())
}

fn click_slot(mut data: &[u8], query: &mut PacketSwitchQuery<'_>) -> anyhow::Result<()> {
fn click_slot(mut data: &'static [u8], query: &mut PacketSwitchQuery<'_>) -> anyhow::Result<()> {
let pkt = play::ClickSlotC2s::decode(&mut data)?;

// todo(security): validate the player can do this. This is a MAJOR security issue.
// as players will be able to spawn items in their inventory wit current logic.
for SlotChange { idx, stack } in pkt.slot_changes.iter() {
let idx = u16::try_from(*idx).context("slot index is negative")?;
query.inventory.set(idx, stack.clone())?;
}
let to_send_pkt = play::ScreenHandlerSlotUpdateS2c {
window_id: -1,
state_id: VarInt::default(),
slot_idx: 0, // crafting result
slot_data: Cow::Borrowed(&ItemStack::EMPTY),
};

// negate click
query
.compose
.unicast(&to_send_pkt, query.io_ref, query.system_id, query.world)?;

let item_in_slot = query
.inventory
.get(pkt.slot_idx as u16)
.context("slot index is negative")?;

let to_send_pkt = play::ScreenHandlerSlotUpdateS2c {
window_id: 0,
state_id: VarInt::default(),
slot_idx: pkt.slot_idx,
slot_data: Cow::Borrowed(&item_in_slot),
};

query
.compose
.unicast(&to_send_pkt, query.io_ref, query.system_id, query.world)?;

// info!("click slot\n{pkt:#?}");

// // todo(security): validate the player can do this. This is a MAJOR security issue.
// // as players will be able to spawn items in their inventory wit current logic.
// for SlotChange { idx, stack } in pkt.slot_changes.iter() {
// let idx = u16::try_from(*idx).context("slot index is negative")?;
// query.inventory.set(idx, stack.clone())?;
// }

let item = query.inventory.crafting_result(query.crafting_registry);

let item = query.inventory.crafting_item(query.crafting_registry);
let set_item_pkt = play::ScreenHandlerSlotUpdateS2c {
window_id: 0,
state_id: VarInt(0),
Expand Down
8 changes: 1 addition & 7 deletions events/proof-of-concept/src/module/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,14 +233,8 @@ impl Module for BlockModule {
let block = event.block;
mc.set_block(position, event.block).unwrap();

let chat = chat!("§c§l{block} was placed at {position}");

event.from.entity_view(world).get::<&NetworkStreamRef>(|stream| {
compose.broadcast(&chat, SystemId(100)).send(&world).unwrap();
});

pending_air.destroy_at.schedule(Instant::now() + TOTAL_DESTRUCTION_TIME, position);

{
let sequence = fastrand::i32(..);
// Schedule destruction stages 0 through 9
Expand Down

0 comments on commit bcb4936

Please sign in to comment.