Refine and improve

This commit is contained in:
Jeff 2024-07-05 21:48:26 -04:00
parent ea070e5bc5
commit 4618437981

View File

@ -6,7 +6,7 @@ use std::{
Arc, Mutex, Arc, Mutex,
}, },
thread, thread,
time::{Duration, Instant}, time::{self, Duration, Instant, UNIX_EPOCH},
}; };
use serde::Serialize; use serde::Serialize;
@ -48,6 +48,7 @@ pub struct Bot {
buy_prices: HashMap<String, u32>, buy_prices: HashMap<String, u32>,
sell_prices: HashMap<String, u32>, sell_prices: HashMap<String, u32>,
last_action: Instant, last_action: Instant,
last_announcement: Instant,
trade_mode: TradeMode, trade_mode: TradeMode,
} }
@ -70,7 +71,8 @@ impl Bot {
buy_prices, buy_prices,
sell_prices, sell_prices,
last_action: Instant::now(), last_action: Instant::now(),
trade_mode: TradeMode::Sell, last_announcement: Instant::now(),
trade_mode: TradeMode::Buy,
}) })
} }
@ -144,6 +146,18 @@ impl Bot {
self.last_action = Instant::now(); self.last_action = Instant::now();
} }
if self.last_announcement.elapsed() > Duration::from_secs(1800) {
self.client.send_command(
"say".to_string(),
vec![
"I'm a bot. Use /say or /tell to give commands: 'buy', 'sell' or 'prices'."
.to_string(),
],
);
self.last_announcement = Instant::now();
}
self.clock.tick(); self.clock.tick();
Ok(()) Ok(())
@ -154,14 +168,10 @@ impl Bot {
VelorenEvent::Chat(message) => { VelorenEvent::Chat(message) => {
let content = message.content().as_plain().unwrap_or_default(); let content = message.content().as_plain().unwrap_or_default();
if !content.starts_with(&self.username) {
return Ok(());
}
match message.chat_type { match message.chat_type {
ChatType::Tell(sender_uid, _) | ChatType::Say(sender_uid) => { ChatType::Tell(sender_uid, _) | ChatType::Say(sender_uid) => {
if !self.client.is_trading() { if !self.client.is_trading() {
match content.trim_start_matches(&self.username).trim() { match content.trim() {
"buy" => { "buy" => {
self.trade_mode = TradeMode::Buy; self.trade_mode = TradeMode::Buy;
self.client.send_invite(sender_uid, InviteKind::Trade); self.client.send_invite(sender_uid, InviteKind::Trade);
@ -174,31 +184,35 @@ impl Bot {
self.trade_mode = TradeMode::Take; self.trade_mode = TradeMode::Take;
self.client.send_invite(sender_uid, InviteKind::Trade); self.client.send_invite(sender_uid, InviteKind::Trade);
} }
"prices" => {
let player_name = self
.find_name(&sender_uid)
.ok_or("Failed to find player name")?
.to_string();
self.client.send_command(
"tell".to_string(),
vec![
player_name.clone(),
format!("Buy prices: {:?}", self.buy_prices),
],
);
self.client.send_command(
"tell".to_string(),
vec![
player_name,
format!("Sell prices: {:?}", self.sell_prices),
],
);
}
_ => {} _ => {}
} }
} }
match content.trim() {
"prices" => {
let player_name = self
.find_name(&sender_uid)
.ok_or("Failed to find player name")?
.to_string();
self.client.send_command(
"tell".to_string(),
vec![
player_name.clone(),
format!("Buy prices: {:?}", self.buy_prices),
],
);
self.client.send_command(
"tell".to_string(),
vec![
player_name,
format!("Sell prices: {:?}", self.sell_prices),
],
);
}
_ => {}
}
} }
_ => {} _ => {}
} }
} }
@ -223,6 +237,17 @@ impl Bot {
} }
fn handle_buy(&mut self, trade: PendingTrade) -> Result<(), String> { fn handle_buy(&mut self, trade: PendingTrade) -> Result<(), String> {
let (my_offer, their_offer) = {
let my_offer_index = trade
.which_party(self.client.uid().ok_or("Failed to get uid")?)
.ok_or("Failed to get offer index")?;
let their_offer_index = if my_offer_index == 0 { 1 } else { 0 };
(
&trade.offers[my_offer_index],
&trade.offers[their_offer_index],
)
};
let inventories = self.client.inventories(); let inventories = self.client.inventories();
let my_inventory = inventories.get(self.client.entity()).unwrap(); let my_inventory = inventories.get(self.client.entity()).unwrap();
let my_coins = my_inventory let my_coins = my_inventory
@ -238,21 +263,19 @@ impl Bot {
.get(them) .get(them)
.ok_or("Failed to find inventory".to_string())?; .ok_or("Failed to find inventory".to_string())?;
let their_offered_items_value = let their_offered_items_value =
(&trade.offers[1]) their_offer.into_iter().fold(0, |acc, (slot_id, quantity)| {
.into_iter() if let Some(item) = their_inventory.get(slot_id.clone()) {
.fold(0, |acc, (slot_id, quantity)| { let item_value = self
if let Some(item) = their_inventory.get(slot_id.clone()) { .buy_prices
let item_value = self .get(&item.persistence_item_id())
.buy_prices .unwrap_or(&1);
.get(&item.persistence_item_id())
.unwrap_or(&1);
acc + (item_value * quantity) acc + (item_value * quantity)
} else { } else {
acc acc
} }
}); });
let my_offered_coins = (&trade.offers[0]) let my_offered_coins = my_offer
.into_iter() .into_iter()
.find_map(|(slot_id, quantity)| { .find_map(|(slot_id, quantity)| {
let item = if let Some(item) = my_inventory.get(slot_id.clone()) { let item = if let Some(item) = my_inventory.get(slot_id.clone()) {
@ -272,7 +295,7 @@ impl Bot {
let mut my_items_to_remove = Vec::new(); let mut my_items_to_remove = Vec::new();
for (item_id, quantity) in &trade.offers[0] { for (item_id, quantity) in my_offer {
let item = my_inventory let item = my_inventory
.get(item_id.clone()) .get(item_id.clone())
.ok_or("Failed to find item".to_string())?; .ok_or("Failed to find item".to_string())?;
@ -284,7 +307,7 @@ impl Bot {
let mut their_items_to_remove = Vec::new(); let mut their_items_to_remove = Vec::new();
for (item_id, quantity) in &trade.offers[1] { for (item_id, quantity) in their_offer {
let item = their_inventory let item = their_inventory
.get(item_id.clone()) .get(item_id.clone())
.ok_or("Failed to find item".to_string())?; .ok_or("Failed to find item".to_string())?;
@ -333,6 +356,17 @@ impl Bot {
} }
fn handle_sell(&mut self, trade: PendingTrade) -> Result<(), String> { fn handle_sell(&mut self, trade: PendingTrade) -> Result<(), String> {
let (my_offer, their_offer) = {
let my_offer_index = trade
.which_party(self.client.uid().ok_or("Failed to get uid")?)
.ok_or("Failed to get offer index")?;
let their_offer_index = if my_offer_index == 0 { 1 } else { 0 };
(
&trade.offers[my_offer_index],
&trade.offers[their_offer_index],
)
};
let inventories = self.client.inventories(); let inventories = self.client.inventories();
let my_inventory = inventories.get(self.client.entity()).unwrap(); let my_inventory = inventories.get(self.client.entity()).unwrap();
let them = self let them = self
@ -347,22 +381,19 @@ impl Bot {
let their_coins = their_inventory let their_coins = their_inventory
.get_slot_of_item_by_def_id(&ItemDefinitionIdOwned::Simple(COINS.to_string())) .get_slot_of_item_by_def_id(&ItemDefinitionIdOwned::Simple(COINS.to_string()))
.ok_or("Failed to find coins")?; .ok_or("Failed to find coins")?;
let my_offered_items_value = let my_offered_items_value = my_offer.into_iter().fold(0, |acc, (slot_id, quantity)| {
(&trade.offers[0]) if let Some(item) = my_inventory.get(slot_id.clone()) {
.into_iter() let item_value = self
.fold(0, |acc, (slot_id, quantity)| { .sell_prices
if let Some(item) = my_inventory.get(slot_id.clone()) { .get(&item.persistence_item_id())
let item_value = self .unwrap_or(&0);
.sell_prices
.get(&item.persistence_item_id())
.unwrap_or(&0);
acc + (item_value * quantity) acc + (item_value * quantity)
} else { } else {
acc acc
} }
}); });
let their_offered_coins = (&trade.offers[1]) let their_offered_coins = their_offer
.into_iter() .into_iter()
.find_map(|(slot_id, quantity)| { .find_map(|(slot_id, quantity)| {
let item = if let Some(item) = their_inventory.get(slot_id.clone()) { let item = if let Some(item) = their_inventory.get(slot_id.clone()) {
@ -384,7 +415,7 @@ impl Bot {
let mut their_items_to_remove = Vec::new(); let mut their_items_to_remove = Vec::new();
for (item_id, quantity) in &trade.offers[1] { for (item_id, quantity) in their_offer {
let item = their_inventory let item = their_inventory
.get(item_id.clone()) .get(item_id.clone())
.ok_or("Failed to find item".to_string())?; .ok_or("Failed to find item".to_string())?;
@ -398,7 +429,7 @@ impl Bot {
let mut my_items_to_remove = Vec::new(); let mut my_items_to_remove = Vec::new();
for (item_id, quantity) in &trade.offers[0] { for (item_id, quantity) in my_offer {
let item = my_inventory let item = my_inventory
.get(item_id.clone()) .get(item_id.clone())
.ok_or("Failed to find item".to_string())?; .ok_or("Failed to find item".to_string())?;