Skip to content

feat: add amount to /give #525

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

Merged
merged 24 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c030fa8
add amount to /give
CuzImClicks Oct 27, 2024
d2a0738
Merge branch 'andrewgazelka:main' into main
CuzImClicks Oct 27, 2024
c80b6cf
Merge branch 'main' into main
CuzImClicks Oct 28, 2024
b05d480
Merge branch 'main' of https://github.com/andrewgazelka/hyperion
CuzImClicks Oct 28, 2024
7d831ad
improve amount
CuzImClicks Oct 28, 2024
b3a34c4
Merge branch 'main' of https://github.com/CuzImClicks/hyperion
CuzImClicks Oct 28, 2024
856b3f3
fix cloning
andrewgazelka Oct 28, 2024
4634e52
Merge branch 'main' into main
CuzImClicks Oct 29, 2024
8b9b75a
fix parser for give
CuzImClicks Oct 29, 2024
c6d92b1
fix packets not being borrowed
CuzImClicks Oct 29, 2024
911a446
added ign map to CommandContext
CuzImClicks Oct 29, 2024
7639c48
rewrite using new api
CuzImClicks Oct 29, 2024
d952134
username is more descriptive
CuzImClicks Oct 29, 2024
55e8e5c
Merge branch 'main' into main
CuzImClicks Oct 30, 2024
2309658
make count optional and default to 1
CuzImClicks Oct 30, 2024
aa3cdfb
fix adding to empty slots
CuzImClicks Oct 30, 2024
1a12e61
Merge branch 'andrewgazelka:main' into fix_adding_to_empty_slot
CuzImClicks Oct 30, 2024
d393f02
Merge branch 'andrewgazelka:main' into main
CuzImClicks Oct 30, 2024
9f5c849
Merge branch 'fix_adding_to_empty_slot' of https://github.com/CuzImCl…
CuzImClicks Oct 30, 2024
a46f118
enforce minimum stack size of 1
CuzImClicks Oct 30, 2024
f5fa21c
Merge remote-tracking branch 'origin/main' into CuzImClicks-main
andrewgazelka Oct 30, 2024
b52ccdc
Merge remote-tracking branch 'origin/main' into CuzImClicks-main
andrewgazelka Oct 30, 2024
3e26f27
Merge remote-tracking branch 'origin/main' into CuzImClicks-main
andrewgazelka Oct 30, 2024
42c035e
remove unused import
andrewgazelka Oct 30, 2024
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
81 changes: 60 additions & 21 deletions events/proof-of-concept/src/module/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@ use std::borrow::Cow;

use flecs_ecs::prelude::*;
use hyperion::{
chat,
egress::player_join::{PlayerListActions, PlayerListEntry, PlayerListS2c},
net::{Compose, NetworkStreamRef},
simulation::{
blocks::Blocks,
command::{add_command, get_root_command, Command, Parser},
event, Health, InGameName, Position, Uuid,
command::{add_command, cmd_with, get_root_command, Command, Parser},
event, Health, IgnMap, InGameName, Position, Uuid,
},
storage::EventQueue,
system_registry::SystemId,
uuid,
valence_ident::ident,
valence_protocol::{
self,
game_mode::OptGameMode,
ident,
math::IVec3,
nbt,
packets::play::{
Expand Down Expand Up @@ -43,9 +44,26 @@ pub fn add_to_tree(world: &World) {
// add to tree
add_command(world, Command::literal("team"), root_command);
add_command(world, Command::literal("zombie"), root_command);
add_command(world, Command::literal("give"), root_command);
add_command(world, Command::literal("upgrade"), root_command);

cmd_with(world, "give", |scope| {
scope.argument_with(
"player",
Parser::Entity {
single: true,
only_players: true,
},
|scope| {
scope.argument_with("", Parser::ItemStack, |scope| {
scope.argument("count", Parser::Integer {
min: Some(1),
max: None,
});
});
},
);
});

let speed = add_command(world, Command::literal("speed"), root_command);
add_command(
world,
Expand Down Expand Up @@ -101,6 +119,7 @@ struct CommandContext<'a> {
inventory: &'a mut PlayerInventory,
level: &'a mut Level,
health: &'a mut Health,
ign_map: &'a IgnMap,
}

fn process_command(command: &ParsedCommand, context: &mut CommandContext<'_>) {
Expand All @@ -109,7 +128,11 @@ fn process_command(command: &ParsedCommand, context: &mut CommandContext<'_>) {
ParsedCommand::Team => handle_team_command(context),
ParsedCommand::Zombie => handle_zombie_command(context),
ParsedCommand::Dirt { x, y, z } => handle_dirt_command(*x, *y, *z, context),
ParsedCommand::Give => handle_give_command(context),
ParsedCommand::Give {
username,
item,
count,
} => handle_give_command(username, item, *count, context),
ParsedCommand::Upgrade => handle_upgrade_command(context),
ParsedCommand::Stats(stat, amount) => handle_stats(*stat, *amount, context),
ParsedCommand::Health(amount) => handle_health_command(*amount, context),
Expand Down Expand Up @@ -351,24 +374,39 @@ fn handle_stats(stat: Stat, amount: f32, context: &CommandContext<'_>) {
});
}

fn handle_give_command(context: &mut CommandContext<'_>) {
let mut blue_wool_nbt = nbt::Compound::new();
fn handle_give_command(username: &str, item_name: &str, count: i8, context: &CommandContext<'_>) {
let Some(item) = ItemKind::from_str(item_name) else {
let packet = chat!("Unknown item '{item_name:?}'");
context
.compose
.unicast(&packet, context.stream, context.system_id, context.world)
.unwrap();
return;
};

let Some(player) = context.ign_map.get(username) else {
let chat = chat!("Player {username} does not exist");
context
.compose
.unicast(&chat, context.stream, context.system_id, context.world)
.unwrap();
return;
};

let can_place_on = [
"minecraft:stone",
"minecraft:dirt",
"minecraft:grass_block",
"minecraft:blue_wool",
]
.into_iter()
.map(std::convert::Into::into)
.collect();
context
.world
.entity_from_id(*player)
.get::<&mut PlayerInventory>(|inventory| {
inventory.try_add_item(ItemStack::new(item, count, None));
});

blue_wool_nbt.insert("CanPlaceOn", nbt::List::String(can_place_on));
let name = item.to_str();

let packet = chat!("Gave {count} [{name}] to {username}");
context
.inventory
.try_add_item(ItemStack::new(ItemKind::BlueWool, 4, Some(blue_wool_nbt)));
.compose
.unicast(&packet, context.stream, context.system_id, context.world)
.unwrap();
}

fn handle_dirt_command(x: i32, y: i32, z: i32, context: &mut CommandContext<'_>) {
Expand Down Expand Up @@ -603,9 +641,9 @@ impl Module for CommandModule {

let system_id = SystemId(8);

system!("handle_poc_events_player", world, &Compose($), &mut EventQueue<event::Command<'_>>($), &mut Blocks($))
system!("handle_poc_events_player", world, &Compose($), &mut EventQueue<event::Command<'_>>($), &mut Blocks($), &IgnMap($))
.multi_threaded()
.each_iter(move |it: TableIter<'_, false>, _, (compose, event_queue, mc)| {
.each_iter(move |it: TableIter<'_, false>, _, (compose, event_queue, mc, ign_map)| {
let span = trace_span!("handle_poc_events_player");
let _enter = span.enter();

Expand Down Expand Up @@ -644,6 +682,7 @@ impl Module for CommandModule {
level,
health,
position,
ign_map,
};
process_command(&command, &mut context);
},
Expand Down
67 changes: 61 additions & 6 deletions events/proof-of-concept/src/module/command/parse.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use nom::{
branch::alt,
bytes::complete::{tag, take_until},
bytes::complete::{tag, take_until, take_while1},
character::complete::space1,
combinator::{map, map_res},
combinator::{map, map_res, opt},
number::complete::float,
sequence::preceded,
IResult, Parser,
Expand All @@ -21,13 +21,33 @@ pub enum ParsedCommand {
Speed(f32),
Team,
Zombie,
Dirt { x: i32, y: i32, z: i32 },
Give,
Dirt {
x: i32,
y: i32,
z: i32,
},
Give {
username: String,
item: String,
count: i8,
},
Upgrade,
Stats(Stat, f32),
Health(f32),
TpHere,
Tp { x: f32, y: f32, z: f32 },
Tp {
x: f32,
y: f32,
z: f32,
},
}

fn is_valid_player_char(c: char) -> bool {
c.is_alphanumeric() || c == '_'
}

fn space1_str(input: &str) -> IResult<&str, &str> {
space1::<&str, nom::error::Error<&str>>(input)
}

fn parse_speed(input: &str) -> IResult<&str, ParsedCommand> {
Expand Down Expand Up @@ -62,7 +82,23 @@ fn parse_dirt(input: &str) -> IResult<&str, ParsedCommand> {
}

fn parse_give(input: &str) -> IResult<&str, ParsedCommand> {
map(tag("give"), |_| ParsedCommand::Give).parse(input)
map(
(
tag("give "),
take_while1(is_valid_player_char),
preceded(
space1_str,
preceded(opt(tag("minecraft:")), take_while1(is_valid_player_char)),
),
opt(preceded(space1_str, nom::character::complete::i8)),
),
|(_, username, item, count)| ParsedCommand::Give {
username: username.to_string(),
item: item.to_string(),
count: count.unwrap_or(1),
},
)
.parse(input)
}

fn parse_upgrade(input: &str) -> IResult<&str, ParsedCommand> {
Expand Down Expand Up @@ -124,3 +160,22 @@ pub fn command(input: &str) -> IResult<&str, ParsedCommand> {
))
.parse(input)
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_parse_give_command() {
let input = "give Cuz_Im_Clicks minecraft:dirt 64";
let result = parse_give(input);
assert!(result.is_ok());
}

#[test]
fn test_parse_give_command_no_minecraft() {
let input = "give Cuz_Im_Clicks acacia_button 64";
let result = parse_give(input);
assert!(result.is_ok());
}
}