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

Command API #351

Closed
wants to merge 34 commits into from
Closed

Command API #351

wants to merge 34 commits into from

Conversation

Jenya705
Copy link
Contributor

@Jenya705 Jenya705 commented Jun 2, 2023

Description

Will solve issue: #332
This is draft, because I want to get feedback on early stage.

  • Nodes are entities, that are connected with each other using NodeFlow
  • Executable nodes have NodeSystem component, which contains a bevy's system, which will be executed when the command is executed
  • Argument nodes have NodeParser component, which contains a boxed trait, which parses reader and puts the parsed object into special struct called ParseResultsWrite
  • Literal nodes have just NodeName on them (no NodeParser)
  • Root nodes can have NodeExclude component on them to exclude nodes that this specific root node doesn't want to use
  • Multiple nodes which can be chosen using EntityNode component (if there is not such component on an entity then PrimaryRootNode will be chosen)
  • Now commands have a few methods to manipulate with node's entities ( spawn_node, node, spawn_root_node)

Check out example command.rs

@rj00a rj00a self-requested a review June 3, 2023 05:22
Copy link
Collaborator

@dyc3 dyc3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very excited to see progress on this! I haven't looked too hard at this yet, just a couple notes.

crates/valence_core/src/game_mode.rs Outdated Show resolved Hide resolved
crates/valence_command/src/reader.rs Outdated Show resolved Hide resolved
crates/valence_command/src/argument.rs Outdated Show resolved Hide resolved
Cargo.toml Outdated Show resolved Hide resolved
Cargo.toml Outdated Show resolved Hide resolved
crates/valence_core/src/game_mode.rs Outdated Show resolved Hide resolved
crates/valence_nbt/src/compound.rs Outdated Show resolved Hide resolved
crates/valence_command/src/reader.rs Outdated Show resolved Hide resolved
crates/valence_command/src/reader.rs Outdated Show resolved Hide resolved
crates/valence_command/src/parser.rs Outdated Show resolved Hide resolved
@rj00a
Copy link
Member

rj00a commented Jun 5, 2023

Not a full review from me yet, but that's what I've noticed so far.

@rj00a rj00a self-requested a review June 17, 2023 13:41
@Jenya705
Copy link
Contributor Author

Jenya705 commented Jul 24, 2023

I changed the whole system again. Now:

  • Nodes are entities, that are connected with each other using NodeFlow
  • Executable nodes have NodeSystem component, which contains a bevy's system, which will be executed when the command is executed
  • Argument nodes have NodeParser component, which contains a boxed trait, which parses reader and puts the parsed object into special struct called ParseResultsWrite
  • Literal nodes have just NodeName on them (no NodeParser)
  • Root nodes can have NodeExclude component on them to exclude nodes that this specific root node doesn't want to use
  • Multiple nodes which can be chosen using EntityNode component (if there is not such component on an entity then PrimaryRootNode will be chosen)
  • Now commands have a few methods to manipulate with node's entities ( spawn_node, node, spawn_root_node)

Check out example command.rs

@Jenya705
Copy link
Contributor Author

Jenya705 commented Jul 24, 2023

What I think should also be done:

  • Suggestions - the same as execution systems but they will only accept ReadOnlySystemParam
  • Better error handles - many of error cases are not handled correctly, they just panic
  • Better safety comments - I didn't write a lot of comments for unsafe blocks
  • Command macro - a command macro, which will automatically insert all required nodes into Root
  • Super root node - a root node, which doesn't need to have a specific Entity. The same as NodeRoot but has all not root nodes in it
  • Node name -> Node entity - helper to get a node by it's name
  • Parallel execution - we can do the same what bevy does with their systems

Comment on lines 47 to 57
.with_child(|child| {
child.name(Cow::Borrowed("creative")).executor(
|In(arguments): In<CommandArguments>, mut query: Query<&mut GameMode>| {
if let RealCommandExecutor::Player(client) = arguments.1 {
if let Ok(mut game_mode) = query.get_mut(client) {
*game_mode = GameMode::Creative;
}
}
},
);
})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting... I'd like to see another example command that implements /tp x y z or /give. It's not really clear to me how one would go about that.

examples/command.rs Outdated Show resolved Hide resolved
@JackCrumpLeys
Copy link
Contributor

I know that this is likely completely of the rails compared to the current implementation but cant we just use bevy plugins and events? this way we are tightly coupled with bevy and would make it much nicer to code. I have a few ideas on how this could look here is one (I just typed these up on the textbox so could have errors):

struct TeleportCommand;

impl Command for TeleportCommand {
    fn command(&self) -> impl Into<String> {
        "tp"
    }
    fn params(&self) -> impl Into<Vec<CommandParameter>> { // with CommandParameter being some kind of enum
        vec![CommandParameter::Position]
        // This might also be vec![CommandParameter::Position(None)] or even vec![CommandParameterMarker::Position]
    }
    // ...
}

// ...
app.add_plugins(CommandHandler::from_command(TeleportCommand)) 
// this should send out events that look something like CommandExecutionEvent<TeleportCommand> 
// this event should contain the params. 

I have good ideas on how to make this happen and if you think it is a good idea I could work on the code? again I am really just throughing something out into the blue here but I would like to see an as ergonomic as possible API for this.

@hwittenborn
Copy link

I haven't looked too much into this PR yet, but would it be possible to make command parsing work via the clap crate? I feel like that'd make things a lot simpler and reliable long-term.

Sorry if this PRs already doing that or anything, it was just a thought in my head and I thought I'd go ahead and mention it.

@dyc3
Copy link
Collaborator

dyc3 commented Aug 1, 2023

No, the way that minecraft commands work is not compatible with clap. IIRC, this was explicitly discussed on the thread in discord. Minecraft commands can have cyclic references for suggestions, and parsers for stuff like relative coordinates and target selectors (eg, @p) would be very hard under clap's model.

Copy link
Contributor

@JackCrumpLeys JackCrumpLeys left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a little skim of the code and reviewed a little.

answer: &mut crate::suggestions::SuggestionAnswerer,
suggestions: Self::Suggestions,
command: String,
world: &bevy_ecs::world::World,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accessing the whole world is not a very good idea especially for something as simple as a suggestion.

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum RealCommandExecutor {
Player(Entity),
Console,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would console exist? It should be up to the user of valance to make logic to execute commands though the console. Is this used anywhere in the protocol?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not covered by protocol because it has nothing to do with it, console's command executions handled by server anyway (the same as block's command executions). And I think that console can be a command executor, the same as a block.

pub(crate) type PCRelationVec = SmallVec<[Entity; 2]>;

#[derive(Component, Debug)]
pub struct NodeName(pub(crate) Cow<'static, str>);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just store a String?

use crate::pkt::{self, RawCommandTreeS2c};
use crate::suggestions::RawParseSuggestions;

pub(crate) type PCRelationVec = SmallVec<[Entity; 2]>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this ever exceed 2 things? If not why not just use a tuple or array?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a vec for parents and children relation, so yeah it can exceed 2 elements

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In directed graphs generally you have a source and a target for edges, how is this data able to excede 2 elements?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how this graph called but each node can have many parents and many children

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally when you have a graph like this you want to use edges between the nodes. How do you Tel if an item in this list is parent or child?

Copy link
Contributor

@JackCrumpLeys JackCrumpLeys left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some more comments.

}
}

pub const CONSOLE_EVENT_ID: u32 = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep consts at top of file


#[derive(Clone, Debug)]
pub struct Suggestion<'a> {
pub message: Cow<'a, str>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you using Cow<'a, str> everywhere?

SuggestionsTransaction::Event { id } => {
self.event.send(SuggestionAnswerEvent {
suggestions: suggestions
.map(|v| v.into_iter().map(|v| v.clone_static()).collect()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name v better: suggestion same goes for everywhere you use v.

use crate::pkt::{self, RawCommandTreeS2c};
use crate::suggestions::RawParseSuggestions;

pub(crate) type PCRelationVec = SmallVec<[Entity; 2]>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In directed graphs generally you have a source and a target for edges, how is this data able to excede 2 elements?

@Jenya705
Copy link
Contributor Author

Jenya705 commented Aug 5, 2023

Suggestions are done. @rj00a, can you review current code? If you have any questions feel free to ask

@Jenya705 Jenya705 marked this pull request as ready for review August 5, 2023 10:03
@Jenya705 Jenya705 marked this pull request as draft August 5, 2023 10:04
@rj00a
Copy link
Member

rj00a commented Aug 5, 2023

Sorry, I might be a bit slow to get to a review.

@JackCrumpLeys
Copy link
Contributor

This should be closed or renamed as #446 has been merged.

@JackCrumpLeys
Copy link
Contributor

@rj00a this should be closed.

@rj00a rj00a closed this Jun 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants