-
Notifications
You must be signed in to change notification settings - Fork 143
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
Commands #487
base: main
Are you sure you want to change the base?
Commands #487
Conversation
Added command support for plugins, quill_sys::modify_command_executor, new bungeecord example, improved plugin messaging
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are not going to solve borrow checking issues with an unsafe magic pointer.
I would recommend cherry picking all your commits and reapplying over the current main, as this pr includes code that was unmerged.
feather/commands/src/impls.rs
Outdated
// // Some(uuid) => uuid, | ||
// // None => return Err(PardonError::NotPlayer.into()), | ||
// //}; | ||
// | ||
// //{ | ||
// // let bi_lock = ctx.game.resources.get::<WrappedBanInfo>(); | ||
// // let mut ban_info = bi_lock.write().unwrap(); | ||
// // ban_info | ||
// // .uuid_bans | ||
// // .remove(&uuid.to_hyphenated_ref().to_string()); | ||
// //} | ||
// | ||
// if let Ok(mut chat) = ctx.ecs.get_mut::<ChatBox>(ctx.sender) { | ||
// let kick_confirm = | ||
// Text::translate_with("commands.pardon.success", vec![Text::from(name.0)]); | ||
// chat.send_system(kick_confirm); | ||
// } | ||
// | ||
// Ok(None) | ||
// } | ||
// | ||
// #[derive(Debug, Error)] | ||
// pub enum PardonIpError { | ||
// #[error("Invalid IP Address")] | ||
// NotIp, | ||
// } | ||
// | ||
// #[command(usage = "pardon-ip <ip>")] | ||
// pub fn pardonip(ctx: &mut CommandCtx, ip: String) -> anyhow::Result<Option<String>> { | ||
// // Try to parse ip | ||
// let _addr = IpAddr::from_str(&ip).map_err(|_| PardonIpError::NotIp)?; | ||
// | ||
// //{ | ||
// // let mut bi_lock = ctx.game.resources.get_mut::<WrappedBanInfo>(); | ||
// // let mut ban_info = bi_lock.write().unwrap(); | ||
// // ban_info.ip_bans.remove(&addr); | ||
// //} | ||
// | ||
// if let Ok(mut chat) = ctx.ecs.get_mut::<ChatBox>(ctx.sender) { | ||
// let kick_confirm = Text::translate_with("commands.pardon.success", vec![Text::from(ip)]); | ||
// chat.send_system(kick_confirm); | ||
// } | ||
// | ||
// Ok(None) | ||
// } | ||
// | ||
// #[command(usage = "time query <info>")] | ||
// pub fn time_query( | ||
// ctx: &mut CommandCtx, | ||
// info: TimeQueryInformation, | ||
// ) -> anyhow::Result<Option<String>> { | ||
// let time = match info { | ||
// TimeQueryInformation::DayTime => ctx.world.time.time(), | ||
// TimeQueryInformation::GameTime => ctx.world.time.world_age(), | ||
// TimeQueryInformation::Day => ctx.world.time.days(), | ||
// }; | ||
// | ||
// if let Ok(mut chat) = ctx.ecs.get_mut::<ChatBox>(ctx.sender) { | ||
// let message = | ||
// Text::translate_with("commands.time.query", vec![Text::from(time.to_string())]); | ||
// chat.send_system(message); | ||
// } | ||
// | ||
// Ok(None) | ||
// } | ||
// | ||
// #[command(usage = "time add <time>")] | ||
// pub fn time_add(ctx: &mut CommandCtx, time: TimeArgument) -> anyhow::Result<Option<String>> { | ||
// let time = ctx.world.time.time() + time.0; | ||
// set_time(ctx, time); | ||
// Ok(None) | ||
// } | ||
// | ||
// #[command(usage = "time set <time>")] | ||
// pub fn time_set_0(ctx: &mut CommandCtx, time: TimeArgument) -> anyhow::Result<Option<String>> { | ||
// set_time(ctx, time.0); | ||
// Ok(None) | ||
// } | ||
// | ||
// #[command(usage = "time set <time_spec>")] | ||
// pub fn time_set_1(ctx: &mut CommandCtx, time_spec: TimeSpec) -> anyhow::Result<Option<String>> { | ||
// set_time( | ||
// ctx, | ||
// match time_spec { | ||
// TimeSpec::Day => 1_000, | ||
// TimeSpec::Noon => 6_000, | ||
// TimeSpec::Night => 13_000, | ||
// TimeSpec::Midnight => 18_000, | ||
// }, | ||
// ); | ||
// Ok(None) | ||
// } | ||
// | ||
// fn set_time(ctx: &mut CommandCtx, time: u64) { | ||
// ctx.ecs.insert_event(TimeUpdateEvent { | ||
// old: ctx.world.time.time(), | ||
// new: time, | ||
// }); | ||
// ctx.world.time.set_time(time); | ||
// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might want to look into a different way to organize commands instead of a monolithic implementation file.
feather/commands/src/lib.rs
Outdated
/// Dumb workaround for a certain lifetime issue. | ||
/// | ||
/// `CommandCtx` stores references to `Game`, and it | ||
/// is used as the `C` parameter for `CommandDispatcher`, | ||
/// This combination of lifetimes and storage in structs | ||
/// prevents a lifetime-based `CommandCtx` from being stored | ||
/// in `CommandState` without adding a lifetime parameter to `CommandState`. | ||
/// | ||
/// Since `CommandCtx` is never actually _stored_ in `CommandState` (it's | ||
/// only passed into a function), we can (hopefully) soundly erase | ||
/// the lifetime parameters. FIXME: if someone has a better solution, | ||
/// a PR is welcome :) | ||
pub struct LifetimelessMut<T>(*mut T); | ||
|
||
impl<T> Deref for LifetimelessMut<T> { | ||
type Target = T; | ||
|
||
fn deref(&self) -> &Self::Target { | ||
unsafe { &mut *self.0 } | ||
} | ||
} | ||
|
||
impl<T> DerefMut for LifetimelessMut<T> { | ||
fn deref_mut(&mut self) -> &mut Self::Target { | ||
unsafe { &mut *self.0 } | ||
} | ||
} | ||
|
||
unsafe impl<T> Send for LifetimelessMut<T> where T: Send {} | ||
unsafe impl<T> Sync for LifetimelessMut<T> where T: Sync {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Q_Q Can we talk about this please
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's basically 0 chance this will ever be merged as-is
Commands
Status
Description
This PR adds commands. I've started working on this with lieutenant, but I did't like regex because it's hard to write regexps for something like
@e[advancements={"adv":{criteria:"true"}}]
, it required some refactoring to make compatible structure for Declare Commands packet,CommandCtx: Send + Sync
wouldn't allowLifetimelessMut<Game>
and has no concept of tab completion, so I decided to make my own dispatcher instead of rewriting 95% of the existing code.Things to do:
Things to discuss
Related issues
Checklist
cargo fmt
,cargo clippy --all-targets
,cargo build --release
andcargo test
and fixed any generated errors!Note: if you locally don't get any errors, but GitHub Actions fails (especially at
clippy
) you might want to check your rust toolchain version. You can then feel free to fix these warnings/errors in your PR.