diff --git a/Cargo.lock b/Cargo.lock index 69f55938..0cf01f24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,6 +125,21 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "antithesis_sdk" +version = "0.2.4" +source = "git+https://github.com/andrewgazelka/antithesis-sdk-rust?branch=andrew%2Fassert-never#4965258d7155219c1d587f7f1165787aebe3ea89" +dependencies = [ + "libc", + "libloading", + "linkme", + "once_cell", + "rand", + "rustc_version_runtime", + "serde", + "serde_json", +] + [[package]] name = "anyhow" version = "1.0.93" @@ -1048,6 +1063,15 @@ dependencies = [ "syn", ] +[[package]] +name = "envy" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f47e0157f2cb54f5ae1bd371b30a2ae4311e1c028f575cd4e81de7353215965" +dependencies = [ + "serde", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -1070,6 +1094,16 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + [[package]] name = "fast_hilbert" version = "2.0.0" @@ -1380,15 +1414,6 @@ dependencies = [ "scroll", ] -[[package]] -name = "gxhash" -version = "3.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a197c9b654827513cf53842c5c6d3da2b4b35a785f8e0eff78bdf8e445aba1bb" -dependencies = [ - "rustversion", -] - [[package]] name = "h2" version = "0.4.6" @@ -1707,6 +1732,28 @@ dependencies = [ "valence_text", ] +[[package]] +name = "hyperion-bot" +version = "0.1.0" +dependencies = [ + "antithesis_sdk", + "bytes", + "derive_more", + "dotenvy", + "envy", + "eyre", + "rand", + "regex", + "serde", + "serde_json", + "tokio", + "tracing", + "tracing-subscriber", + "uuid", + "valence_protocol", + "valence_server", +] + [[package]] name = "hyperion-clap" version = "0.1.0" @@ -1724,9 +1771,7 @@ name = "hyperion-command" version = "0.1.0" dependencies = [ "flecs_ecs", - "gxhash", "hyperion", - "indexmap", "regex", "tracing", ] @@ -2054,6 +2099,12 @@ dependencies = [ "png", ] +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + [[package]] name = "indexmap" version = "2.6.0" @@ -2226,6 +2277,26 @@ dependencies = [ "libc", ] +[[package]] +name = "linkme" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "566336154b9e58a4f055f6dd4cbab62c7dc0826ce3c0a04e63b2d2ecd784cdae" +dependencies = [ + "linkme-impl", +] + +[[package]] +name = "linkme-impl" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edbe595006d355eaf9ae11db92707d4338cd2384d16866131cc1afdbdd35d8d9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -2866,7 +2937,6 @@ dependencies = [ "dotenvy", "fastrand 2.2.0", "flecs_ecs", - "gxhash", "hyperion", "hyperion-clap", "hyperion-inventory", @@ -3238,6 +3308,25 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustc_version_runtime" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dd18cd2bae1820af0b6ad5e54f4a51d0f3fcc53b05f845675074efcc7af071d" +dependencies = [ + "rustc_version", + "semver", +] + [[package]] name = "rustix" version = "0.38.41" @@ -3385,6 +3474,12 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d659fa6f19e82a52ab8d3fff3c380bd8cc16462eaea411395618a38760eb85bc" +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + [[package]] name = "serde" version = "1.0.215" diff --git a/Cargo.toml b/Cargo.toml index 13cf1d65..521f6438 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,4 @@ +[profile] [profile.release-debug] debug = true inherits = 'release' @@ -13,24 +14,25 @@ panic = 'abort' members = [ 'crates/bvh-region', 'crates/hyperion', + 'crates/hyperion-bot', + 'crates/hyperion-clap', + 'crates/hyperion-command', 'crates/hyperion-crafting', 'crates/hyperion-event-macros', 'crates/hyperion-inventory', + 'crates/hyperion-item', 'crates/hyperion-minecraft-proto', 'crates/hyperion-nerd-font', 'crates/hyperion-palette', + 'crates/hyperion-permission', 'crates/hyperion-proto', 'crates/hyperion-proxy', + 'crates/hyperion-rank-tree', 'crates/hyperion-scheduled', 'crates/hyperion-stats', 'crates/hyperion-text', 'crates/hyperion-utils', 'events/proof-of-concept', - 'crates/hyperion-permission', - 'crates/hyperion-clap', - 'crates/hyperion-command', - 'crates/hyperion-rank-tree', - 'crates/hyperion-item', ] resolver = '2' @@ -67,17 +69,19 @@ more-asserts = '0.3.1' no_denormals = '0.1.2' num-derive = '0.4.2' num-traits = '0.2.19' -regex = { version = "1.11.1", features = ["perf-dfa-full"] } +regex = { version = "1.11.1", features = ["perf", "perf-dfa-full"] } once_cell = '1.19.0' ordered-float = '4.2.0' ouroboros = '0.18.4' papaya = '0.1.4' parking_lot = '0.12.3' +paste = '1.0.15' plotters-bitmap = '0.3.6' proc-macro2 = '1.0.89' quote = '1.0.37' rand = '0.8.5' rayon = '1.10.0' +replace_with = '0.1.7' rkyv = '0.8.8' rustc-hash = '2.0.0' serde = '1.0.214' @@ -91,8 +95,12 @@ thiserror = '2.0.1' tikv-jemallocator = '0.6.0' tokio = '1.40.0' toml = '0.8.14' -uuid = '1.8.0' -paste = "1.0.15" +trybuild = '1.0.101' + +[workspace.dependencies.antithesis] +package = 'antithesis_sdk' +git = 'https://github.com/andrewgazelka/antithesis-sdk-rust' +branch = "andrew/assert-never" [workspace.dependencies.bvh] git = 'https://github.com/andrewgazelka/bvh-data' @@ -115,6 +123,9 @@ version = '1.0.0-beta.7' [workspace.dependencies.divan] git = 'https://github.com/nvzqz/divan' +[workspace.dependencies.envy] +version = '0.4.2' + [workspace.dependencies.flate2] default-features = false version = '1.0.30' @@ -123,12 +134,12 @@ version = '1.0.30' features = ['flecs_manual_registration'] git = 'https://github.com/Indra-db/Flecs-Rust' -[workspace.dependencies.gxhash] -version = '3.4.1' - [workspace.dependencies.hyperion] path = 'crates/hyperion' +[workspace.dependencies.hyperion-bot] +path = 'crates/hyperion-bot' + [workspace.dependencies.hyperion-clap] path = 'crates/hyperion-clap' @@ -210,6 +221,10 @@ version = '0.3.18' features = ['timer-fallback'] version = '0.11.3' +[workspace.dependencies.uuid] +features = ['serde'] +version = '1.8.0' + [workspace.dependencies.valence_anvil] branch = 'feat-open' features = ['parsing'] diff --git a/Dockerfile b/Dockerfile index 65adf300..981390c8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,24 @@ # Define base arguments for versioning and optimization -ARG RUST_NIGHTLY_VERSION=nightly-2024-10-22 +ARG RUST_NIGHTLY_VERSION=nightly-2024-11-11 ARG RUST_TARGET_CPU=native -ARG RUSTFLAGS="-C target-cpu=${RUST_TARGET_CPU} -Z share-generics=y -Z threads=8 --cfg tokio_unstable" +#ARG RUSTFLAGS="-C target-cpu=${RUST_TARGET_CPU} -Z share-generics=y -Z threads=8 --cfg tokio_unstable" + + +ARG PATH_TO_LIBVOIDSTAR=/usr/lib/libvoidstar.so + + +ARG RUSTFLAGS=" \ + -Ccodegen-units=1 \ + -Cpasses=sancov-module \ + -Cllvm-args=-sanitizer-coverage-level=3 \ + -Cllvm-args=-sanitizer-coverage-trace-pc-guard \ + -Clink-args=-Wl,--build-id \ + -Clink-args=-Wl,-z,nostart-stop-gc \ + -L${PATH_TO_LIBVOIDSTAR} \ + -lvoidstar" + + + ARG CARGO_HOME=/usr/local/cargo # Use Ubuntu as base image @@ -27,13 +44,20 @@ RUN apt-get update && \ FROM packages AS builder-base ARG RUST_NIGHTLY_VERSION ARG RUSTFLAGS +ARG PATH_TO_LIBVOIDSTAR ARG CARGO_HOME ENV RUSTFLAGS=${RUSTFLAGS} ENV CARGO_HOME=${CARGO_HOME} +ENV PATH_TO_LIBVOIDSTAR=${PATH_TO_LIBVOIDSTAR} + RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain ${RUST_NIGHTLY_VERSION} && \ $CARGO_HOME/bin/rustup component add rust-src && \ $CARGO_HOME/bin/rustc --version ENV PATH="${CARGO_HOME}/bin:${PATH}" + +# copy libvoidstar.so to /usr/lib +COPY ./libvoidstar.so /usr/lib/libvoidstar.so + WORKDIR /app COPY Cargo.toml Cargo.lock ./ COPY crates/ ./crates @@ -53,7 +77,8 @@ RUN --mount=type=cache,target=${CARGO_HOME}/registry \ cargo build --frozen && \ mkdir -p /app/build && \ cp target/debug/hyperion-proxy /app/build/ && \ - cp target/debug/proof-of-concept /app/build/ + cp target/debug/proof-of-concept /app/build/ && \ + cp target/debug/hyperion-bot /app/build/ # Release builder FROM builder-base AS build-release @@ -64,7 +89,8 @@ RUN --mount=type=cache,target=${CARGO_HOME}/registry \ cargo build --profile release-full --frozen && \ mkdir -p /app/build && \ cp target/release-full/hyperion-proxy /app/build/ && \ - cp target/release-full/proof-of-concept /app/build/ + cp target/release-full/proof-of-concept /app/build/ && \ + cp target/release-full/hyperion-bot /app/build/ # Runtime base image FROM ubuntu:22.04 AS runtime-base @@ -76,6 +102,8 @@ RUN apt-get update && \ ENV RUST_BACKTRACE=1 \ RUST_LOG=info +COPY --from=builder-base /usr/lib/libvoidstar.so /usr/lib/libvoidstar.so + # Hyperion Proxy Debug FROM runtime-base AS hyperion-proxy-debug COPY --from=build-debug /app/build/hyperion-proxy / @@ -96,20 +124,36 @@ EXPOSE 8080 ENTRYPOINT ["/hyperion-proxy"] CMD ["0.0.0.0:8080"] -# NYC Debug +# Proof of Concept Debug FROM runtime-base AS proof-of-concept-debug COPY --from=build-debug /app/build/proof-of-concept / LABEL org.opencontainers.image.source="https://github.com/yourusername/proof-of-concept" \ - org.opencontainers.image.description="Debug Build - NYC Server" \ + org.opencontainers.image.description="Debug Build - Proof of Concept Server" \ org.opencontainers.image.version="1.0.0" ENTRYPOINT ["/proof-of-concept"] CMD ["--ip", "0.0.0.0", "--port", "35565"] -# NYC Release +# Proof of Concept Release FROM runtime-base AS proof-of-concept-release COPY --from=build-release /app/build/proof-of-concept / LABEL org.opencontainers.image.source="https://github.com/yourusername/proof-of-concept" \ - org.opencontainers.image.description="Release Build - NYC Server" \ + org.opencontainers.image.description="Release Build - Proof of Concept Server" \ org.opencontainers.image.version="1.0.0" ENTRYPOINT ["/proof-of-concept"] CMD ["--ip", "0.0.0.0", "--port", "35565"] + +# Hyperion Bot Debug +FROM runtime-base AS hyperion-bot-debug +COPY --from=build-debug /app/build/hyperion-bot / +LABEL org.opencontainers.image.source="https://github.com/yourusername/hyperion-bot" \ + org.opencontainers.image.description="Debug Build - Hyperion Bot" \ + org.opencontainers.image.version="1.0.0" +ENTRYPOINT ["/hyperion-bot"] +CMD ["--ip", "0.0.0.0", "--port", "35565"] + +# Hyperion Bot Release +FROM runtime-base AS hyperion-bot-release +COPY --from=build-release /app/build/hyperion-bot / +LABEL org.opencontainers.image.source="https://github.com/yourusername/hyperion-bot" \ + org.opencontainers.image.description="Release Build - Hyperion Bot" \ + org.opencontainers.image.version="1.0.0" \ No newline at end of file diff --git a/Dockerfile-config b/Dockerfile-config new file mode 100644 index 00000000..0c129d58 --- /dev/null +++ b/Dockerfile-config @@ -0,0 +1,5 @@ +FROM scratch +COPY docker-compose.yml /docker-compose.yml +#ADD config/license /license +#ADD config/volumes/database /volumes/database +#ADD config/volumes/workload-logs /volumes/workload-logs diff --git a/crates/hyperion-bot/.gitignore b/crates/hyperion-bot/.gitignore new file mode 100644 index 00000000..ea8c4bf7 --- /dev/null +++ b/crates/hyperion-bot/.gitignore @@ -0,0 +1 @@ +/target diff --git a/crates/hyperion-bot/Cargo.toml b/crates/hyperion-bot/Cargo.toml new file mode 100644 index 00000000..ac02778f --- /dev/null +++ b/crates/hyperion-bot/Cargo.toml @@ -0,0 +1,30 @@ +cargo-features = ["edition2024"] + +[dependencies] +eyre = "0.6.12" +tokio = {features = ["full"], workspace = true} +antithesis.workspace = true +derive_more.workspace = true +dotenvy.workspace = true +envy.workspace = true +rand.workspace = true +regex.workspace = true +serde.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true +uuid.workspace = true +valence_protocol.workspace = true +valence_server = { workspace = true } +bytes = { workspace = true } +serde_json = { workspace = true } + +[lints] +workspace = true + +[package] +authors = ["Andrew Gazelka "] +edition = "2024" +name = "hyperion-bot" +publish = false +readme = "README.md" +version = "0.1.0" diff --git a/crates/hyperion-bot/README.md b/crates/hyperion-bot/README.md new file mode 100644 index 00000000..44dedb88 --- /dev/null +++ b/crates/hyperion-bot/README.md @@ -0,0 +1 @@ +# hyperion-bot \ No newline at end of file diff --git a/crates/hyperion-bot/src/bot.rs b/crates/hyperion-bot/src/bot.rs new file mode 100644 index 00000000..74ea7243 --- /dev/null +++ b/crates/hyperion-bot/src/bot.rs @@ -0,0 +1,42 @@ +use bytes::BytesMut; +use tokio::net::{TcpStream, ToSocketAddrs}; +use tracing::info; +use uuid::Uuid; +use valence_protocol::{PacketDecoder, PacketEncoder}; + +mod handshake; + +pub struct Bot { + name: String, + uuid: Uuid, + connection: TcpStream, + encoder: PacketEncoder, + decoder: PacketDecoder, + decode_buf: BytesMut, +} + +impl Bot { + #[tracing::instrument(skip_all, fields(name))] + pub async fn new( + name: String, + uuid: Uuid, + addr: impl ToSocketAddrs + std::fmt::Display, + ) -> Self { + info!("connecting to {addr}"); + let addr = TcpStream::connect(addr).await.unwrap(); + + let encoder = PacketEncoder::default(); + let decoder = PacketDecoder::default(); + + let decode_buf = BytesMut::with_capacity(1024 * 1024); // 1 MiB + + Self { + name, + uuid, + connection: addr, + encoder, + decoder, + decode_buf, + } + } +} diff --git a/crates/hyperion-bot/src/bot/handshake.rs b/crates/hyperion-bot/src/bot/handshake.rs new file mode 100644 index 00000000..fb728564 --- /dev/null +++ b/crates/hyperion-bot/src/bot/handshake.rs @@ -0,0 +1,85 @@ +use antithesis::{assert_always, assert_never, random::AntithesisRng}; +use eyre::bail; +use rand::Rng; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use valence_protocol::{ + Bounded, PROTOCOL_VERSION, Packet, VarInt, packets, + packets::handshaking::handshake_c2s::HandshakeNextState, +}; + +use crate::{bot::Bot, util::random_either}; + +impl Bot { + pub async fn handshake(mut self) -> eyre::Result<()> { + let mut rng = AntithesisRng; + + let protocol_version: i32 = random_either(|| PROTOCOL_VERSION, || rng.r#gen::()); + + let addr = "placeholder"; + + let packet = packets::handshaking::HandshakeC2s { + protocol_version: VarInt(protocol_version), + server_address: Bounded(addr), + server_port: 25565, // probably does not matter + next_state: HandshakeNextState::Status, + }; + + let result = self.encoder.append_packet(&packet); + + assert_always!(result.is_ok(), "Failed to encode handshake packet"); + + let packet = packets::status::QueryRequestC2s; + + let result = self.encoder.append_packet(&packet); + + assert_always!(result.is_ok(), "Failed to encode handshake packet"); + + let bytes = self.encoder.take(); + + self.connection.write_all(&bytes).await?; + + let result_packet = self.connection.read_buf(&mut self.decode_buf).await?; + + assert_never!(result_packet == 0, "Failed to read handshake packet"); + + println!("read bytes {:?}", self.decode_buf); + self.decoder.queue_bytes(self.decode_buf.split()); + + let packet1 = self.decoder.try_next_packet(); + + let Ok(packet1) = packet1 else { + antithesis::assert_unreachable!("Failed to decode handshake packet"); + bail!("Failed to decode handshake packet"); + }; + + let Some(packet1) = packet1 else { + antithesis::assert_unreachable!("Failed to decode handshake packet"); + bail!("Failed to decode handshake packet"); + }; + + assert_always!( + packet1.id == packets::status::QueryResponseS2c::ID, + "Failed to decode handshake packet" + ); + + let packet: packets::status::QueryResponseS2c<'_> = packet1.decode().unwrap(); + + let json = packet.json; + + // todo: maybe remove unwrap and use antithesis asserts first + let json: serde_json::Value = serde_json::from_str(json).unwrap(); + + let description = json.get("description").unwrap(); + + let description = description.as_str().unwrap(); + + assert_always!( + description + == "Getting 10k Players to PvP at Once on a Minecraft Server to Break the \ + Guinness World Record", + "Failed to decode handshake packet" + ); + + Ok(()) + } +} diff --git a/crates/hyperion-bot/src/config.rs b/crates/hyperion-bot/src/config.rs new file mode 100644 index 00000000..74f7c2ca --- /dev/null +++ b/crates/hyperion-bot/src/config.rs @@ -0,0 +1,7 @@ +use serde::Deserialize; + +#[derive(Debug, Deserialize)] +pub struct Config { + pub max_number_of_bots: usize, + pub host: String, +} diff --git a/crates/hyperion-bot/src/generate.rs b/crates/hyperion-bot/src/generate.rs new file mode 100644 index 00000000..042beb24 --- /dev/null +++ b/crates/hyperion-bot/src/generate.rs @@ -0,0 +1,2 @@ +mod name; +pub use name::generate as name; diff --git a/crates/hyperion-bot/src/generate/name.rs b/crates/hyperion-bot/src/generate/name.rs new file mode 100644 index 00000000..2e0001da --- /dev/null +++ b/crates/hyperion-bot/src/generate/name.rs @@ -0,0 +1,29 @@ +use std::sync::LazyLock; + +use antithesis::random::AntithesisRng; +use rand::Rng; + +#[derive(Clone, Debug)] +pub struct Name { + pub value: String, + pub is_valid: bool, +} + +pub fn generate() -> Name { + static NAME_REGEX: LazyLock = + LazyLock::new(|| regex::Regex::new(r"^[a-zA-Z0-9_]+$").unwrap()); + + let mut rng = AntithesisRng; + + let len = rng.gen_range(0..20); + let name: String = (0..len).map(|_| rng.r#gen::()).collect(); + + // name is max 16 characters + + let is_valid = name.len() <= 16 && { NAME_REGEX.is_match(&name) }; + + Name { + value: name, + is_valid, + } +} diff --git a/crates/hyperion-bot/src/lib.rs b/crates/hyperion-bot/src/lib.rs new file mode 100644 index 00000000..892294d4 --- /dev/null +++ b/crates/hyperion-bot/src/lib.rs @@ -0,0 +1,42 @@ +use antithesis::{assert_sometimes, random::AntithesisRng}; +use rand::Rng; +use tokio::task::JoinSet; +use uuid::Uuid; + +mod config; +pub use config::Config; + +use crate::bot::Bot; + +mod generate; +mod util; + +mod bot; + +pub async fn bootstrap(config: &Config) { + // Wait for TCP port to be available + util::wait_for_tcp_port(&config.host).await; + // todo: use life cycle + + let mut rng = AntithesisRng; + + let first_name = generate::name(); + assert_sometimes!(first_name.is_valid, "First name is never invalid"); + assert_sometimes!(!first_name.is_valid, "First name is always valid"); + + let first_uuid: u128 = rng.r#gen(); + let first_uuid = Uuid::from_u128(first_uuid); + + let mut join_set = JoinSet::new(); + + for _ in 0..config.max_number_of_bots { + let name = first_name.value.clone(); + let addr = config.host.clone(); + join_set.spawn(async move { + let bot = Bot::new(name, first_uuid, addr); + bot.await.handshake().await.unwrap(); + }); + } + + join_set.join_all().await; +} diff --git a/crates/hyperion-bot/src/main.rs b/crates/hyperion-bot/src/main.rs new file mode 100644 index 00000000..18119b8f --- /dev/null +++ b/crates/hyperion-bot/src/main.rs @@ -0,0 +1,17 @@ +use eyre::Context; +use hyperion_bot::bootstrap; + +#[tokio::main] +async fn main() -> eyre::Result<()> { + tracing_subscriber::fmt::init(); + + // it is not an error if a .env file is missing + drop(dotenvy::dotenv()); + + let config = envy::from_env().wrap_err("Failed to load config from environment variables")?; + + tracing::info!("{config:?}"); + + bootstrap(&config).await; + Ok(()) +} diff --git a/crates/hyperion-bot/src/util.rs b/crates/hyperion-bot/src/util.rs new file mode 100644 index 00000000..8d8c98f5 --- /dev/null +++ b/crates/hyperion-bot/src/util.rs @@ -0,0 +1,29 @@ +use antithesis::random::AntithesisRng; +use rand::Rng; + +pub fn random_either(left: impl FnOnce() -> T, right: impl FnOnce() -> T) -> T { + let mut rng = AntithesisRng; + if rng.r#gen::() { left() } else { right() } +} + +use tokio::{ + net::TcpStream, + time::{Duration, sleep}, +}; +use tracing::{info, warn}; + +pub async fn wait_for_tcp_port(addr: &str) { + info!("Waiting for TCP port to become available at {}", addr); + loop { + match TcpStream::connect(addr).await { + Ok(_) => { + info!("Successfully connected to {}", addr); + break; + } + Err(e) => { + warn!("Failed to connect to {}: {}. Retrying in 1s...", addr, e); + sleep(Duration::from_secs(1)).await; + } + } + } +} diff --git a/crates/hyperion-command/Cargo.toml b/crates/hyperion-command/Cargo.toml index 917f4a62..c6c2e030 100644 --- a/crates/hyperion-command/Cargo.toml +++ b/crates/hyperion-command/Cargo.toml @@ -10,9 +10,7 @@ publish = false [dependencies] flecs_ecs = {workspace = true} -gxhash = {workspace = true} hyperion = {workspace = true} -indexmap = {workspace = true} regex = {workspace = true} tracing = {workspace = true} diff --git a/crates/hyperion-command/src/component.rs b/crates/hyperion-command/src/component.rs index 6dc72e29..73e2cea8 100644 --- a/crates/hyperion-command/src/component.rs +++ b/crates/hyperion-command/src/component.rs @@ -13,7 +13,7 @@ pub struct CommandHandler { #[derive(Component)] pub struct CommandRegistry { - pub(crate) commands: IndexMap, + pub(crate) commands: IndexMap, } impl CommandRegistry { diff --git a/docker-compose.yml b/docker-compose.yml index 4ceabd54..4554b710 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -30,6 +30,20 @@ services: networks: - proxy-network + hyperion-bot: + build: + context: . + dockerfile: Dockerfile + target: hyperion-bot-debug + command: [ ] # ["--ip", "0.0.0.0", "--port", "35565"] + restart: unless-stopped + environment: + - RUST_LOG=info + - HOST=hyperion-proxy:25565 + - MAX_NUMBER_OF_BOTS=1 + networks: + - proxy-network + networks: proxy-network: driver: bridge diff --git a/events/proof-of-concept/Cargo.toml b/events/proof-of-concept/Cargo.toml index 9cdecc44..86d9059f 100644 --- a/events/proof-of-concept/Cargo.toml +++ b/events/proof-of-concept/Cargo.toml @@ -21,7 +21,6 @@ tracing-subscriber = { workspace = true } tracing-tracy = { workspace = true } tracing = { workspace = true } rayon = { workspace = true } -gxhash = { workspace = true } derive_more = { workspace = true } [dev-dependencies] diff --git a/events/proof-of-concept/src/command/replace.rs b/events/proof-of-concept/src/command/replace.rs index 4e8369b8..df7c257e 100644 --- a/events/proof-of-concept/src/command/replace.rs +++ b/events/proof-of-concept/src/command/replace.rs @@ -1,7 +1,6 @@ use std::collections::{HashSet, VecDeque}; use flecs_ecs::core::{Entity, EntityViewGet, World, WorldGet}; -use gxhash::GxBuildHasher; use hyperion::{BlockState, glam::IVec3, simulation::blocks::Blocks}; use rayon::iter::ParallelIterator; @@ -63,8 +62,8 @@ const ADJACENT: [IVec3; 6] = [ /// Groups connected positions in 3D space /// Returns a vector of groups, where each group is a vector of connected positions -fn group(positions: &HashSet) -> Vec> { - let mut visited: HashSet = HashSet::default(); +fn group(positions: &HashSet) -> Vec> { + let mut visited: HashSet = HashSet::default(); let mut groups: Vec> = Vec::new(); // Iterate through all positions @@ -109,7 +108,7 @@ impl hyperion_clap::MinecraftCommand for ReplaceCommand { world.get::<&mut Blocks>(|blocks| { let started_time = std::time::Instant::now(); - let concrete_positions: HashSet<_, GxBuildHasher> = + let concrete_positions: HashSet<_> = blocks.par_scan_for(BlockState::PINK_CONCRETE).collect(); let scan_time = started_time.elapsed(); diff --git a/events/proof-of-concept/src/lib.rs b/events/proof-of-concept/src/lib.rs index 87dfc00e..541133c4 100644 --- a/events/proof-of-concept/src/lib.rs +++ b/events/proof-of-concept/src/lib.rs @@ -6,7 +6,7 @@ #![feature(iter_from_coroutine)] #![feature(exact_size_is_empty)] -use std::net::ToSocketAddrs; +use std::{collections::HashSet, net::ToSocketAddrs}; use flecs_ecs::prelude::*; use hyperion::{ @@ -37,7 +37,7 @@ mod skin; #[derive(Component, Default, Deref, DerefMut)] struct OreVeins { - ores: gxhash::HashSet, + ores: HashSet, } impl Module for ProofOfConceptModule { diff --git a/libvoidstar.so b/libvoidstar.so new file mode 100644 index 00000000..fc0dc3d2 Binary files /dev/null and b/libvoidstar.so differ