Skip to content
This repository has been archived by the owner on Dec 24, 2024. It is now read-only.

Commit

Permalink
update command system
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewgazelka committed Jul 8, 2024
1 parent 00ecda3 commit c33edcc
Show file tree
Hide file tree
Showing 45 changed files with 446 additions and 510 deletions.
379 changes: 185 additions & 194 deletions Cargo.lock

Large diffs are not rendered by default.

24 changes: 18 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ hematite-nbt = "0.5"
swarm-bot-packets = { path = "packets", version = "0.2.0" }

# so we don't have to use v-tables
enum_dispatch = "0.3"
tokio-tungstenite = "0.20.1"

futures = "0.3"
Expand All @@ -118,6 +117,7 @@ tungstenite = "0.20.1"
generic-array = "1.0.0"
typenum = "1.17.0"
rustix = "0.38.25"
tracing = "0.1.40"

[dev-dependencies]
assert_matches = "1.5"
Expand All @@ -129,10 +129,22 @@ rustix = "0.38.25"
members = ["packets", "interfaces", "swarmbot-cli"]

[profile.dev]
split-debuginfo = "unpacked"
opt-level = 1
#split-debuginfo = "unpacked"
#opt-level = 1


[profile.release]
lto = "fat"
codegen-units = 1
#[profile.release]
#lto = "fat"
#codegen-units = 1

[lints.clippy]
complexity = { level = "deny", priority = -1 }
nursery = { level = "deny", priority = -1 }
pedantic = { level = "deny", priority = -1 }
perf = { level = "deny", priority = -1 }
style = { level = "deny", priority = -1 }
suspicious = { level = "deny", priority = -1 }

module_name_repetitions = "allow"
future_not_send = "allow"

60 changes: 37 additions & 23 deletions interfaces/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,25 @@ pub mod types;

type Id = u64;

pub trait Tag: Serialize {
const PATH: &'static str;

fn encode(&self) -> String {
let mut v = serde_json::to_value(self).unwrap();

let Some(map) = v.as_object_mut() else {
panic!("expected object")
};

map.insert(
"path".to_string(),
serde_json::Value::String(Self::PATH.to_string()),
);

serde_json::to_string(&v).unwrap()
}
}

/// The mine command.
/// Mine the given selection.
/// A global command. The process should allocate appropriately to children.
Expand All @@ -17,18 +36,30 @@ pub struct Mine {
pub sel: Selection2D,
}

impl Tag for Mine {
const PATH: &'static str = "mine";
}

/// A navigation command to go to the given block location
#[derive(Serialize, Deserialize, Debug)]
pub struct GoTo {
pub location: BlockLocation,
}

impl Tag for GoTo {
const PATH: &'static str = "goto";
}

/// Attack a given player
#[derive(Serialize, Deserialize, Debug)]
pub struct Attack {
pub name: String,
}

impl Tag for Attack {
const PATH: &'static str = "attack";
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Cancelled {
pub id: Id,
Expand All @@ -39,29 +70,11 @@ pub struct Finished {
pub id: Id,
}

macro_rules! commands {
(
$($command: ident),*
) =>
{
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "lowercase")]
#[serde(tag = "path")]
pub enum CommandData {
$($command($command)),*
}

};
}

commands! {
Mine, GoTo, Attack, Cancelled, Finished
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Command {
id: u64,
data: CommandData,
path: String,
data: serde_json::Value,
}

pub struct Comm {
Expand Down Expand Up @@ -174,14 +187,15 @@ impl Comm {

#[cfg(test)]
mod tests {
use crate::{Attack, Command, CommandData};
use crate::Command;

#[test]
fn test() {
let command = Command {
id: 123,
data: CommandData::Attack(Attack {
name: "hello".to_string(),
path: "attack".to_string(),
data: serde_json::json!({
"name": "hello"
}),
};

Expand Down
2 changes: 2 additions & 0 deletions rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[toolchain]
channel = "nightly-2024-07-04"
11 changes: 4 additions & 7 deletions src/bootstrap/dns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,8 @@ async fn dns_lookup(host: &str) -> anyhow::Result<Address> {
/// Normalizes the address. Some servers like 2b2t have a separate address for
/// minecraft since they have a special mc record
pub async fn normalize_address(host: &str, port: u16) -> Address {
match dns_lookup(host).await {
Ok(res) => res,
Err(_) => Address {
host: host.to_string(),
port,
},
}
(dns_lookup(host).await).unwrap_or_else(|_| Address {
host: host.to_string(),
port,
})
}
1 change: 1 addition & 0 deletions src/bootstrap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ async fn obtain_connection(

conn.into_inner()
} else {
println!("connecting to {target}");
TcpStream::connect(target.as_str()).await.unwrap()
};

Expand Down
5 changes: 1 addition & 4 deletions src/bootstrap/mojang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,7 @@ impl TryFrom<Option<&Proxy>> for MojangClient {
type Error = anyhow::Error;

fn try_from(value: Option<&Proxy>) -> Result<Self, Self::Error> {
match value {
None => Ok(Self::default()),
Some(proxy) => Self::try_from(proxy),
}
value.map_or_else(|| Ok(Self::default()), Self::try_from)
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/bootstrap/opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub struct CliOptions {
pub port: u16,

/// The port of the web socket that is used to communicate bot commands
/// to. This is used to interface with the SwarmBot mod, although it
/// to. This is used to interface with the `SwarmBot` mod, although it
/// can be used for anything.
#[clap(long, default_value = "8080")]
pub ws_port: u16,
Expand Down Expand Up @@ -67,7 +67,7 @@ pub struct CliOptions {

/// if we are launching in offline mode
#[clap(long)]
pub offline: bool,
pub online: bool,
}

impl CliOptions {
Expand Down
12 changes: 6 additions & 6 deletions src/client/bot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
state::{global::GlobalState, local::LocalState},
tasks::{
compound::CompoundTask, eat::EatTask, fall_bucket::FallBucketTask, mine::MineTask,
navigate::BlockTravelTask, Task, TaskTrait,
navigate::BlockTravelTask, Task,
},
},
protocol::{EventQueue, Face, InterfaceOut},
Expand All @@ -24,13 +24,13 @@ use crate::{
pub struct ActionState {
/// the task. In the future, this might change to be a priority queue of
/// tasks
task: Option<Task>,
task: Option<Box<dyn Task>>,
}

impl ActionState {
/// schedule a task
pub fn schedule<T: Into<Task>>(&mut self, task: T) {
self.task = Some(task.into());
pub fn schedule(&mut self, task: impl Task + 'static) {
self.task = Some(Box::new(task));
}
/// clear the task list
pub fn clear(&mut self) {
Expand Down Expand Up @@ -102,7 +102,7 @@ pub fn process_command(
local: &mut LocalState,
global: &mut GlobalState,
actions: &mut ActionState,
out: &mut impl InterfaceOut,
out: &mut dyn InterfaceOut,
) -> anyhow::Result<()> {
macro_rules! msg {
() => {{
Expand Down Expand Up @@ -153,7 +153,7 @@ pub fn process_command(
// }
"eat" => {
let eat_task = EatTask::default();
actions.task = Some(eat_task.into());
actions.task = Some(Box::new(eat_task));
}
"slot" => {
if let [number] = args {
Expand Down
53 changes: 29 additions & 24 deletions src/client/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,64 @@ use std::sync::mpsc::{Receiver, Sender};

use anyhow::{bail, Context};
use futures::StreamExt;
use interfaces::CommandData;
use serde_json::Value;
use tokio::net::{TcpListener, TcpStream};
use tokio_tungstenite::WebSocketStream;
use tracing::error;

/// commands received over websocket (typically forge mod)
pub struct CommandReceiver {
pub pending: Receiver<CommandData>,
pub pending: Receiver<TaggedValue>,
}

fn process(path: &str, value: Value) -> Option<CommandData> {
macro_rules! parse {
() => {{
serde_json::from_value(value).unwrap()
}};
}
struct Processor {
value: Value,
}

match path {
"mine" => Some(CommandData::Mine(parse!())),
"goto" => Some(CommandData::GoTo(parse!())),
"attack" => Some(CommandData::Attack(parse!())),
pub struct TaggedValue {
pub path: String,
pub value: Value,
}

path => {
println!("invalid {path}");
None
}
impl TaggedValue {
pub fn parse<T>(self) -> Result<T, serde_json::Error>
where
T: serde::de::DeserializeOwned,
{
serde_json::from_value(self.value)
}
}

async fn command_receiver(
tx: Sender<CommandData>,
tx: Sender<TaggedValue>,
mut ws: WebSocketStream<TcpStream>,
) -> anyhow::Result<()> {
'wloop: while let Some(msg) = ws.next().await {
while let Some(msg) = ws.next().await {
let msg = msg.context("error reading next web socket message (websocket disconnect?)")?;

let text = msg.into_text().unwrap();

let mut v: Value = match serde_json::from_str(&text) {
let v: Value = match serde_json::from_str(&text) {
Ok(v) => v,
Err(_e) => continue 'wloop,
Err(e) => {
error!("invalid json {e}");
continue;
}
};

let Value::Object(map) = &mut v else {
bail!("invalid value")
let Value::Object(mut map) = v else {
bail!("expected object")
};

let Value::String(path) = map.remove("path").expect("no path elem") else {
bail!("invalid path")
};

let command = process(&path, v).expect("invalid command");
tx.send(command).unwrap();
let value = Value::Object(map);

let elem = TaggedValue { path, value };

tx.send(elem).unwrap();
}
Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion src/client/pathfind/implementations/no_vehicle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ impl Heuristic for ChunkHeuristic {
fn heuristic(&self, input: &MoveNode) -> f64 {
let dx = f64::from(input.location.x - self.center_x);
let dz = f64::from(input.location.z - self.center_z);
let dist2 = dx * dx + dz * dz;
let dist2 = dx.mul_add(dx, dz * dz);
dist2.sqrt() * self.move_cost * 0.2
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/client/pathfind/incremental/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,14 @@ impl<T: Debug> Debug for PathResult<T> {
}

impl<T> PathResult<T> {
fn complete(value: Vec<T>) -> Self {
const fn complete(value: Vec<T>) -> Self {
Self {
complete: true,
value,
}
}

fn incomplete(value: Vec<T>) -> Self {
const fn incomplete(value: Vec<T>) -> Self {
Self {
complete: false,
value,
Expand Down
10 changes: 7 additions & 3 deletions src/client/physics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,12 @@ impl Physics {
let sideways = horizontal.cross(UNIT_Y);

let move_mults = [
horizontal.dx * forward_change + sideways.dx * strafe_change,
horizontal.dz * forward_change + sideways.dz * strafe_change,
horizontal
.dx
.mul_add(forward_change, sideways.dx * strafe_change),
horizontal
.dz
.mul_add(forward_change, sideways.dz * strafe_change),
];

let effect_mult = effects_multiplier(0.0, 0.0);
Expand Down Expand Up @@ -380,7 +384,7 @@ impl Physics {
let downwards_force = feet_flowing || head_flowing;

// TODO: remove 0.014
let res = self.prev.y_vel * WATER_SLOW_DOWN - 0.02
let res = self.prev.y_vel.mul_add(WATER_SLOW_DOWN, -0.02)
+ if self.pending.jump { 0.04 } else { 0. }
- if downwards_force { 0.014 } else { 0. };

Expand Down
Loading

0 comments on commit c33edcc

Please sign in to comment.