Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
4eefa1c
one of these days i'll remember to do incremental commits. not today tho
ReCore-sys Jun 21, 2026
63e2d50
Set up some ECS stuff
ReCore-sys Jun 21, 2026
1c36d92
Wiring in the new command shit
ReCore-sys Jun 21, 2026
d749c78
More replacement stuff
ReCore-sys Jun 21, 2026
bffac67
Implemented the tp command and tweaked the api a little
ReCore-sys Jun 22, 2026
64bca86
single/no args commands implemented
ReCore-sys Jun 22, 2026
c4c6502
Fix for invalid graph being sent
ReCore-sys Jun 22, 2026
e448398
Suggestions + some fixes
ReCore-sys Jun 26, 2026
db62dcb
fixed entity tp not being synced
ReCore-sys Jun 26, 2026
277c0de
Subcommands + some other shit
ReCore-sys Jun 26, 2026
451f874
permissions and aliases on args/subcommands
ReCore-sys Jun 26, 2026
2c6ebee
Time command
ReCore-sys Jun 27, 2026
72d1a21
single/multi entity args
ReCore-sys Jun 27, 2026
c758961
about 4.2 fucktillion bug fixes with suggestions
ReCore-sys Jun 28, 2026
7f809af
bossbar plus some bug fixes
ReCore-sys Jun 28, 2026
ab1c6f5
gamemode
ReCore-sys Jun 28, 2026
2c470cc
credits and kill command
ReCore-sys Jun 28, 2026
81ec3e8
docs + bump deps
ReCore-sys Jun 28, 2026
5fd6689
TUI commands
ReCore-sys Jun 28, 2026
ca23eb9
Added /stop alias
ReCore-sys Jun 28, 2026
5bd8c3c
op command
ReCore-sys Jun 28, 2026
d5acfd8
Removing the old system
ReCore-sys Jun 28, 2026
315c67e
Docs and cleanup
ReCore-sys Jun 28, 2026
79715bc
fmt
ReCore-sys Jun 28, 2026
a717cd8
fmt
ReCore-sys Jun 28, 2026
17df2df
Handler now returns a result
ReCore-sys Jul 2, 2026
1d84fd8
Removed unneeded permissions checks
ReCore-sys Jul 2, 2026
a44ce57
fmt
ReCore-sys Jul 2, 2026
b0f3e48
fix for tests + bevy being weird
ReCore-sys Jul 2, 2026
ab7476c
Merge branch 'dev' into feature/vanilla-commands
ReCore-sys Jul 2, 2026
1aeb4ae
forgot to pull from dev branch
ReCore-sys Jul 2, 2026
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
30 changes: 15 additions & 15 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ members = [
"src/blocks/crates/build",
"src/blocks/crates/data",
"src/bin",
"src/commands",
"src/command-infra",
"src/components",
"src/core",
"src/dashboard",
Expand Down Expand Up @@ -129,14 +129,14 @@ temper-block-data = { path = "src/blocks/crates/data" }
temper-config = { path = "src/config" }
temper-core = { path = "src/core" }
temper-default-commands = { path = "src/default_commands" }
temper-commands = { path = "src/commands" }
temper-general-purpose = { path = "src/base/general_purpose" }
temper-logging = { path = "src/base/logging" }
temper-macros = { path = "src/base/macros" }
temper-nbt = { path = "src/adapters/nbt" }
temper-net-runtime = { path = "src/net/runtime" }
temper-performance = { path = "src/performance" }
temper-codec = { path = "src/net/codec" }
temper-command-infra = { path = "src/command-infra" }
temper-protocol = { path = "src/net/protocol" }
temper-encryption = { path = "src/net/encryption" }
temper-profiling = { path = "src/base/profiling" }
Expand Down Expand Up @@ -180,7 +180,7 @@ tracing = "0.1.44"
tracing-subscriber = { version = "0.3.23", features = ["env-filter"] }
tracing-appender = "0.2.5"
tracing-tracy = { version = "0.11.4", features = ["timer-fallback", "ondemand", "fibers", "context-switch-tracing", "delayed-init"] }
log = "0.4.32"
log = "0.4.33"
tracy-client = "0.18.4"

# Concurrency/Parallelism
Expand All @@ -195,7 +195,7 @@ reqwest = { version = "0.13.4", features = ["json", "native-tls", "blocking", "h

# Error handling
thiserror = "2.0.18"
anyhow = "1.0.102"
anyhow = "1.0.103"

# Cryptography
rand = "0.10.1"
Expand Down Expand Up @@ -228,16 +228,16 @@ byteorder = "1.5.0"

# Data types
dashmap = { version = "7.0.0-rc2", features = ["serde"] }
uuid = { version = "1.23.3", features = ["v4", "v3", "serde"] }
uuid = { version = "1.23.4", features = ["v4", "v3", "serde"] }
indexmap = { version = "2.14.0", features = ["serde"] }
bimap = "0.6.3"
arrayvec = "0.7.6"
arrayvec = "0.7.7"
fastcache = "0.1.7"

# Macros
lazy_static = "1.5.0"
quote = "1.0.45"
syn = { version = "2.0.117", features = ["extra-traits"] }
quote = "1.0.46"
syn = { version = "2.0.118", features = ["extra-traits", "full"] }
proc-macro2 = "1.0.106"
paste = "1.0.15"
maplit = "1.0.2"
Expand All @@ -260,7 +260,7 @@ heed = "0.22.1"
# Misc
deepsize = "0.2.0"
page_size = "0.6.0"
enum-ordinalize = "4.3.2"
enum-ordinalize = "4.4.1"
regex = "1.12.4"
noise = "0.9.0"
ctrlc = "3.5.2"
Expand All @@ -274,9 +274,9 @@ mime_guess = "2.0.5"

## TUI/CLI
crossterm = "0.29.0"
ratatui-core = "0.1.1"
ratatui-core = "0.1.2"
tui-input = "0.15.3"
ratatui = "0.30.1"
ratatui = "0.30.2"
tui-logger = { version = "0.18.2", features = ["tracing-support", "crossterm"] }
clap = { version = "4.6.1", features = ["derive", "env"] }
indicatif = "0.18.4"
Expand All @@ -285,22 +285,22 @@ unicode-width = "0.2.2"
heck = "0.5.0"

# I/O
memmap2 = "0.9.10"
memmap2 = "0.9.11"
tempfile = "3.27.0"
walkdir = "2.5.0"
include_dir = "0.7.4"

# Benchmarking
criterion = { version = "0.8.2", features = ["html_reports"] }

phf = { version = "0.13.1", features = ["macros"] }
phf_codegen = { version = "0.13.1" }
phf = { version = "0.14.0", features = ["macros"] }
phf_codegen = { version = "0.14.0" }

# Web server
axum = { version = "0.8.9", features = ["tokio", "ws"] }

# Stats
sysinfo = { version = "0.39.3", default-features = false, features = ["system"] }
sysinfo = { version = "0.39.5", default-features = false, features = ["system"] }
dir-size = "0.1.1"

# Compression is a real bottleneck that we can do little about, so compiling it with optimizations is needed in dev mode.
Expand Down
201 changes: 201 additions & 0 deletions src/base/macros/src/command_derive/attrs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
use syn::parse::{Parse, ParseStream};
use syn::{
Attribute, Expr, ExprArray, ExprLit, Ident, Lit, LitStr, Path, Result as SynResult, Token,
};

pub enum CommandKind {
Root(CommandAttrs),
Subcommand(SubcommandAttrs),
}

pub struct CommandAttrs {
pub name: LitStr,
pub aliases: Vec<LitStr>,
pub permission: Option<Path>,
}

pub struct SubcommandAttrs {
pub permission: Option<Path>,
}

pub enum VariantPrefix {
Literal(PrefixAttrs),
Subcommand(PrefixAttrs),
}

pub struct PrefixAttrs {
pub name: LitStr,
pub aliases: Vec<LitStr>,
}

pub struct VariantAttrs {
pub prefix: Option<VariantPrefix>,
pub permission: Option<Path>,
}

pub fn command_kind(attrs: &[Attribute]) -> SynResult<CommandKind> {
for attr in attrs {
if !attr.path().is_ident("command") {
continue;
}

if let Ok(name) = attr.parse_args::<LitStr>() {
return Ok(CommandKind::Root(CommandAttrs {
name,
aliases: Vec::new(),
permission: None,
}));
}

let mut name = None;
let mut aliases = Vec::new();
let mut permission = None;
let mut subcommand = false;

attr.parse_nested_meta(|meta| {
if meta.path.is_ident("name") {
name = Some(meta.value()?.parse::<LitStr>()?);
Ok(())
} else if meta.path.is_ident("aliases") {
aliases = parse_aliases(meta.value()?.parse::<ExprArray>()?)?;
Ok(())
} else if meta.path.is_ident("permission") {
permission = Some(meta.value()?.parse::<Path>()?);
Ok(())
} else if meta.path.is_ident("subcommand") {
subcommand = true;
Ok(())
} else {
Err(meta.error("unsupported command option"))
}
})?;

return match (name, subcommand) {
(Some(name), false) => Ok(CommandKind::Root(CommandAttrs {
name,
aliases,
permission,
})),
(None, true) => Ok(CommandKind::Subcommand(SubcommandAttrs { permission })),
(Some(_), true) => Err(syn::Error::new_spanned(
attr,
"command cannot be both named and a subcommand",
)),
(None, false) => Err(syn::Error::new_spanned(
attr,
"expected #[command(\"name\")], #[command(name = \"name\")], or #[command(subcommand)]",
)),
};
}

Err(syn::Error::new(
proc_macro2::Span::call_site(),
"missing #[command(...)] attribute",
))
}

pub fn variant_attrs(attrs: &[Attribute]) -> SynResult<VariantAttrs> {
let mut prefix = None;
let mut permission = None;

for attr in attrs {
let next = if attr.path().is_ident("literal") {
Some(VariantPrefix::Literal(attr.parse_args::<PrefixAttrs>()?))
} else if attr.path().is_ident("subcommand") {
Some(VariantPrefix::Subcommand(attr.parse_args::<PrefixAttrs>()?))
} else {
None
};

if let Some(next) = next {
if prefix.is_some() {
return Err(syn::Error::new_spanned(
attr,
"command variants can only have one #[literal(...)] or #[subcommand(...)] attribute",
));
}

prefix = Some(next);
continue;
}

if attr.path().is_ident("permission") {
if permission.is_some() {
return Err(syn::Error::new_spanned(
attr,
"command variants can only have one #[permission(...)] attribute",
));
}

permission = Some(attr.parse_args::<Path>()?);
}
}

Ok(VariantAttrs { prefix, permission })
}

pub fn permission_attr(attrs: &[Attribute]) -> SynResult<Option<Path>> {
let mut permission = None;

for attr in attrs {
if !attr.path().is_ident("permission") {
continue;
}

if permission.is_some() {
return Err(syn::Error::new_spanned(
attr,
"fields can only have one #[permission(...)] attribute",
));
}

permission = Some(attr.parse_args::<Path>()?);
}

Ok(permission)
}

fn parse_aliases(aliases: ExprArray) -> SynResult<Vec<LitStr>> {
aliases
.elems
.into_iter()
.map(|expr| match expr {
Expr::Lit(ExprLit {
lit: Lit::Str(alias),
..
}) => Ok(alias),
_ => Err(syn::Error::new_spanned(
expr,
"aliases must be string literals",
)),
})
.collect()
}

impl Parse for PrefixAttrs {
fn parse(input: ParseStream<'_>) -> SynResult<Self> {
let name = input.parse::<LitStr>()?;
let mut aliases = Vec::new();

while input.peek(Token![,]) {
input.parse::<Token![,]>()?;

if input.is_empty() {
break;
}

let option = input.parse::<Ident>()?;
if option != "aliases" {
return Err(syn::Error::new_spanned(
option,
"unsupported literal/subcommand option",
));
}

input.parse::<Token![=]>()?;
aliases = parse_aliases(input.parse::<ExprArray>()?)?;
}

Ok(Self { name, aliases })
}
}
Loading