Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ECS] Inventory interactions #189

Merged
merged 38 commits into from
Jan 22, 2023
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
13941a1
add helper to convert slot ids
dyc3 Jan 16, 2023
1be7a6e
implement system to handle click container events
dyc3 Jan 16, 2023
1540bdb
update inventory_test example with block platform and some chests to …
dyc3 Jan 16, 2023
7b9acf7
add toggle_gamemode_on_sneak system to example
dyc3 Jan 16, 2023
8ac2130
fix query filter that was causing clients to get spammed with OpenScreen
dyc3 Jan 16, 2023
4067ab7
move state_id to `Client` component
dyc3 Jan 16, 2023
b033bd7
only send modified slots when observed inventories are changed
dyc3 Jan 16, 2023
0e463a8
force all click container packets to be handled before update packets…
dyc3 Jan 16, 2023
5cbc917
mark inventories as dirty instead of just sending the contents
dyc3 Jan 16, 2023
b36aaa2
add handle_set_slot_creative to handle SetCreativeModeSlot events
dyc3 Jan 16, 2023
4e858ed
exclude clients with currently open inventories from being updated by…
dyc3 Jan 16, 2023
8b17697
combine update_client_on_open_inventory into update_open_inventories
dyc3 Jan 17, 2023
d971965
track modified slots on Client and OpenInventory so we can filter pac…
dyc3 Jan 17, 2023
7562eb7
Merge branch 'ecs_rewrite' into ecs-inventory-interact
dyc3 Jan 17, 2023
a2d20bb
fix imports
dyc3 Jan 17, 2023
c6cff5e
fix formatting for warns
dyc3 Jan 18, 2023
d31a0c3
add track_caller to panicking inventory functions
dyc3 Jan 18, 2023
364663c
make slot_slice private
dyc3 Jan 18, 2023
25d9826
destructure slot_change in loops
dyc3 Jan 18, 2023
9a5cf33
change log message from warn to debug
dyc3 Jan 18, 2023
05fccf7
send resync instead of marking everything as dirty on state_id mismatch
dyc3 Jan 18, 2023
b58f207
set log level to debug for inventory_test example
dyc3 Jan 18, 2023
9995cf4
use let else and refactor to make stuff easier to read
dyc3 Jan 18, 2023
0b6e10d
refactor more into let else
dyc3 Jan 19, 2023
2dbbfe8
remove an extra branch
dyc3 Jan 19, 2023
22e4adf
Merge branch 'ecs_rewrite' into ecs-inventory-interact
dyc3 Jan 19, 2023
55d967b
refactor slot id thing for less branches
dyc3 Jan 20, 2023
ba08bf1
fix incrementing the wrong thing
dyc3 Jan 20, 2023
5e150c7
fix modified slots bit check
dyc3 Jan 20, 2023
f770427
fix player inventory slot count
dyc3 Jan 20, 2023
de10f63
add check for creative mode when handling SetCreativeModeSlot
dyc3 Jan 20, 2023
1606090
fix order of state id increment and aliasing
dyc3 Jan 20, 2023
b2efb21
send SetContainerSlotEncode every time a valid SetCreativeModeSlot is…
dyc3 Jan 20, 2023
a7b4b21
fix sending duplicate SetContainerSlot when handling SetCreativeModeSlot
dyc3 Jan 21, 2023
5a8aa17
simplify bit checks when checking modified slots for updates
dyc3 Jan 21, 2023
90c2b82
change example inventory to large chest for testing
dyc3 Jan 21, 2023
70f8b3a
clear client modified bits on open inventory when component is added
dyc3 Jan 21, 2023
8bb95dd
remove some unnecessary checks
dyc3 Jan 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 69 additions & 7 deletions crates/valence_new/examples/inventory_test.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use bevy_ecs::prelude::*;
use bevy_ecs::schedule::ShouldRun;
use tracing::info;
use valence_new::client::event::default_event_handler;
use valence_new::client::event::{default_event_handler, StartSneaking, UseItemOnBlock};
use valence_new::client::{despawn_disconnected_clients, Client};
use valence_new::config::{Config, ConnectionMode};
use valence_new::dimension::DimensionId;
use valence_new::instance::Chunk;
use valence_new::inventory::{Inventory, InventoryKind, OpenInventory};
use valence_new::protocol::types::GameMode;
use valence_new::server::Server;
use valence_protocol::{ItemKind, ItemStack};
use valence_protocol::{BlockState, ItemKind, ItemStack};

#[derive(Resource)]
struct GameState {
Expand All @@ -17,26 +18,56 @@ struct GameState {
}

fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt().init();
tracing_subscriber::fmt()
.with_max_level(tracing::Level::DEBUG)
.init();

valence_new::run_server(
Config::default().with_connection_mode(ConnectionMode::Offline),
SystemStage::parallel()
.with_system(setup.with_run_criteria(ShouldRun::once))
.with_system(init_clients)
.with_system(open_inventory_test)
.with_system(blink_items)
.with_system(default_event_handler())
.with_system(despawn_disconnected_clients),
.with_system(despawn_disconnected_clients)
// .with_system(open_inventory_test)
// .with_system(blink_items)
.with_system(open_inventory_on_interact)
.with_system(toggle_gamemode_on_sneak),
(),
)
}

fn setup(world: &mut World) {
let instance = world
let mut instance = world
.resource::<Server>()
.new_instance(DimensionId::default());

// Create spawn platform.
for z in -5..5 {
for x in -5..5 {
let mut chunk = Chunk::new(24);
for z in 0..16 {
for x in 0..16 {
chunk.set_block_state(x, 10, z, BlockState::STONE);
}
}

if x == 0 && z == 0 {
for sx in 0..3 {
for sz in 0..3 {
chunk.set_block_state(sx, 10, sz, BlockState::BRICKS);
}
chunk.set_block_state(sx, 11, 0, BlockState::CHEST);
}
chunk.set_block_state(0, 10, 0, BlockState::COPPER_BLOCK);
chunk.set_block_state(1, 10, 0, BlockState::IRON_BLOCK);
chunk.set_block_state(2, 10, 0, BlockState::GOLD_BLOCK);
}

instance.insert_chunk([x, z], chunk);
}
}

let id = world.spawn(instance).id();
world.insert_resource(GameState {
instance: id,
Expand Down Expand Up @@ -94,3 +125,34 @@ fn blink_items(mut inventories: Query<&mut Inventory>) {
}
}
}

fn open_inventory_on_interact(
mut commands: Commands,
inventories: Query<(Entity, With<Inventory>, Without<Client>)>,
mut events: EventReader<UseItemOnBlock>,
) {
for event in events.iter() {
let inventory_idx = event.position.x as usize % 3;
info!("opening inventory {}", inventory_idx);
let (target_inventory, _, _) = inventories.iter().skip(inventory_idx).next().unwrap();
commands
.entity(event.client)
.insert(OpenInventory::new(target_inventory));
}
}

fn toggle_gamemode_on_sneak(
mut clients: Query<&mut Client>,
mut events: EventReader<StartSneaking>,
) {
for event in events.iter() {
if let Ok(mut client) = clients.get_component_mut::<Client>(event.client) {
let mode = client.game_mode();
client.set_game_mode(match mode {
GameMode::Survival => GameMode::Creative,
GameMode::Creative => GameMode::Survival,
_ => GameMode::Creative,
});
}
}
}
7 changes: 7 additions & 0 deletions crates/valence_new/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::fmt;
use std::net::IpAddr;
use std::num::Wrapping;

use anyhow::{bail, Context};
use bevy_ecs::prelude::*;
Expand Down Expand Up @@ -79,6 +80,10 @@ pub struct Client {
pub(crate) cursor_item_modified: bool,
/// The current window ID. Incremented when inventories are opened.
pub(crate) window_id: u8,
pub(crate) inventory_state_id: Wrapping<i32>,
/// Tracks what slots have been modified by this client in this tick, so we
/// don't need to send updates for them.
pub(crate) inventory_slots_modified: u64,
}

impl Client {
Expand Down Expand Up @@ -124,6 +129,8 @@ impl Client {
cursor_item: None,
cursor_item_modified: false,
window_id: 0,
inventory_state_id: Wrapping(0),
inventory_slots_modified: 0,
}
}

Expand Down
Loading