Fix bug that prevented trades
This commit is contained in:
parent
2a2a295cc2
commit
546346f707
37
src/bot.rs
37
src/bot.rs
@ -57,7 +57,7 @@ pub struct Bot {
|
|||||||
sell_prices: PriceList,
|
sell_prices: PriceList,
|
||||||
trade_mode: TradeMode,
|
trade_mode: TradeMode,
|
||||||
|
|
||||||
previous_offer: Option<(HashMap<InvSlotId, u32>, HashMap<InvSlotId, u32>)>,
|
previous_trade: Option<PendingTrade>,
|
||||||
last_trade_action: Instant,
|
last_trade_action: Instant,
|
||||||
last_announcement: Instant,
|
last_announcement: Instant,
|
||||||
last_ouch: Instant,
|
last_ouch: Instant,
|
||||||
@ -153,7 +153,7 @@ impl Bot {
|
|||||||
buy_prices,
|
buy_prices,
|
||||||
sell_prices,
|
sell_prices,
|
||||||
trade_mode: TradeMode::Trade,
|
trade_mode: TradeMode::Trade,
|
||||||
previous_offer: None,
|
previous_trade: None,
|
||||||
last_trade_action: now,
|
last_trade_action: now,
|
||||||
last_announcement: now,
|
last_announcement: now,
|
||||||
last_ouch: now,
|
last_ouch: now,
|
||||||
@ -256,7 +256,7 @@ impl Bot {
|
|||||||
if self.is_user_admin(&sender)? && !self.client.is_trading() {
|
if self.is_user_admin(&sender)? && !self.client.is_trading() {
|
||||||
log::info!("Providing admin access");
|
log::info!("Providing admin access");
|
||||||
|
|
||||||
self.previous_offer = None;
|
self.previous_trade = None;
|
||||||
self.trade_mode = TradeMode::AdminAccess;
|
self.trade_mode = TradeMode::AdminAccess;
|
||||||
|
|
||||||
self.client.send_invite(sender, InviteKind::Trade);
|
self.client.send_invite(sender, InviteKind::Trade);
|
||||||
@ -402,8 +402,8 @@ impl Bot {
|
|||||||
|
|
||||||
match result {
|
match result {
|
||||||
TradeResult::Completed => {
|
TradeResult::Completed => {
|
||||||
if let Some(offer) = &self.previous_offer {
|
if let Some(trade) = &self.previous_trade {
|
||||||
log::info!("Trade with {their_name}: {offer:?}",);
|
log::info!("Trade with {their_name}: {:?}", trade.offers);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.client.send_command(
|
self.client.send_command(
|
||||||
@ -531,8 +531,8 @@ impl Bot {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// If the trade hasn't changed, do nothing to avoid spamming the server.
|
// If the trade hasn't changed, do nothing to avoid spamming the server.
|
||||||
if let Some(previous) = &self.previous_offer {
|
if let Some(previous) = &self.previous_trade {
|
||||||
if (&previous.0, &previous.1) == (my_offer, their_offer) {
|
if previous == &trade {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -627,7 +627,7 @@ impl Bot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !self.sell_prices.0.contains_key(&item_id) {
|
if !self.sell_prices.0.contains_key(&item_id) {
|
||||||
my_item_to_remove = Some((slot_id, amount));
|
my_item_to_remove = Some((*slot_id, *amount));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -642,23 +642,25 @@ impl Bot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !self.buy_prices.0.contains_key(&item_id) {
|
if !self.buy_prices.0.contains_key(&item_id) {
|
||||||
their_item_to_remove = Some((slot_id, amount));
|
their_item_to_remove = Some((*slot_id, *amount));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(inventories);
|
drop(inventories);
|
||||||
|
|
||||||
|
let phase = trade.phase;
|
||||||
|
|
||||||
// Up until now there may have been an error, so we only update the previous offer now.
|
// Up until now there may have been an error, so we only update the previous offer now.
|
||||||
// The trade action is infallible from here.
|
// The trade action is infallible from here.
|
||||||
self.previous_offer = Some((my_offer.clone(), their_offer.clone()));
|
self.previous_trade = Some(trade);
|
||||||
|
|
||||||
// Before running any actual trade logic, remove items that are not for sale or not being
|
// Before running any actual trade logic, remove items that are not for sale or not being
|
||||||
// purchased. End this trade action if an item was removed.
|
// purchased. End this trade action if an item was removed.
|
||||||
|
|
||||||
if let Some((slot_id, quantity)) = my_item_to_remove {
|
if let Some((slot_id, quantity)) = my_item_to_remove {
|
||||||
self.client.perform_trade_action(TradeAction::RemoveItem {
|
self.client.perform_trade_action(TradeAction::RemoveItem {
|
||||||
item: *slot_id,
|
item: slot_id,
|
||||||
quantity: *quantity,
|
quantity,
|
||||||
ours: true,
|
ours: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -667,8 +669,8 @@ impl Bot {
|
|||||||
|
|
||||||
if let Some((slot_id, quantity)) = their_item_to_remove {
|
if let Some((slot_id, quantity)) = their_item_to_remove {
|
||||||
self.client.perform_trade_action(TradeAction::RemoveItem {
|
self.client.perform_trade_action(TradeAction::RemoveItem {
|
||||||
item: *slot_id,
|
item: slot_id,
|
||||||
quantity: *quantity,
|
quantity,
|
||||||
ours: false,
|
ours: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -685,8 +687,7 @@ impl Bot {
|
|||||||
// If the trade is balanced
|
// If the trade is balanced
|
||||||
if difference == 0 {
|
if difference == 0 {
|
||||||
// Accept
|
// Accept
|
||||||
self.client
|
self.client.perform_trade_action(TradeAction::Accept(phase));
|
||||||
.perform_trade_action(TradeAction::Accept(trade.phase));
|
|
||||||
// If they are offering more
|
// If they are offering more
|
||||||
} else if difference > 0 {
|
} else if difference > 0 {
|
||||||
// If they are offering coins
|
// If they are offering coins
|
||||||
@ -748,7 +749,7 @@ impl Bot {
|
|||||||
.to_string();
|
.to_string();
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
|
|
||||||
for (item_id, price) in &self.buy_prices {
|
for (item_id, price) in &self.buy_prices.0 {
|
||||||
let item_name = self.get_item_name(item_id.as_ref());
|
let item_name = self.get_item_name(item_id.as_ref());
|
||||||
|
|
||||||
if item_name.to_lowercase().contains(&search_term) {
|
if item_name.to_lowercase().contains(&search_term) {
|
||||||
@ -784,7 +785,7 @@ impl Bot {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (item_id, price) in &self.sell_prices {
|
for (item_id, price) in &self.sell_prices.0 {
|
||||||
let item_name = self.get_item_name(item_id.as_ref());
|
let item_name = self.get_item_name(item_id.as_ref());
|
||||||
|
|
||||||
if item_name.to_lowercase().contains(&search_term) {
|
if item_name.to_lowercase().contains(&search_term) {
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
/**
|
/// Configuration used to initiate the bot.
|
||||||
Configuration used to initiate the bot.
|
///
|
||||||
|
/// The Config struct is used to store configuration values that are not sensitive. This includes
|
||||||
The Config struct is used to store configuration values that are not sensitive. This includes the
|
/// the price data for items, the game server to connect to, and the position and orientation of
|
||||||
price data for items, the game server to connect to, and the position and orientation of the bot.
|
/// the bot. The price lists have manual implementations for deserialization to allow turning
|
||||||
The price lists have manual implementations for deserialization to allow turning shortened item
|
/// shortened item IDs into the full IDs used by the Veloren client.
|
||||||
IDs into the full IDs used by the Veloren client.
|
///
|
||||||
|
/// The Secrets struct is used to store sensitive information that should not be shared. This
|
||||||
The Secrets struct is used to store sensitive information that should not be shared. This should
|
/// should be read from a separate file that is not checked into version control. In production,
|
||||||
be read from a separate file that is not checked into version control. In production, use a secure
|
/// use a secure means of storing this information, such as the secret manager for Podman.
|
||||||
means of storing this information, such as the secret manager for Podman.
|
use hashbrown::HashMap;
|
||||||
*/
|
|
||||||
use hashbrown::{hash_map, HashMap};
|
|
||||||
use serde::{
|
use serde::{
|
||||||
de::{self, Visitor},
|
de::{self, Visitor},
|
||||||
Deserialize,
|
Deserialize,
|
||||||
@ -54,31 +52,13 @@ impl<'de> Deserialize<'de> for PriceList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoIterator for PriceList {
|
|
||||||
type Item = (ItemDefinitionIdOwned, u32);
|
|
||||||
type IntoIter = hash_map::IntoIter<ItemDefinitionIdOwned, u32>;
|
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
self.0.into_iter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> IntoIterator for &'a PriceList {
|
|
||||||
type Item = (&'a ItemDefinitionIdOwned, &'a u32);
|
|
||||||
type IntoIter = hash_map::Iter<'a, ItemDefinitionIdOwned, u32>;
|
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
self.0.iter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PriceListVisitor;
|
pub struct PriceListVisitor;
|
||||||
|
|
||||||
impl<'de> Visitor<'de> for PriceListVisitor {
|
impl<'de> Visitor<'de> for PriceListVisitor {
|
||||||
type Value = PriceList;
|
type Value = PriceList;
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
formatter.write_str("a map with simple and/or modular keys: Material|primary|secondary")
|
formatter.write_str("a map with simple and/or modular keys: material|primary|secondary")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
||||||
@ -95,7 +75,7 @@ impl<'de> Visitor<'de> for PriceListVisitor {
|
|||||||
let mut secondary = secondary.to_string();
|
let mut secondary = secondary.to_string();
|
||||||
|
|
||||||
primary.insert_str(0, "common.items.modular.weapon.primary.");
|
primary.insert_str(0, "common.items.modular.weapon.primary.");
|
||||||
secondary.insert_str(0, "common.items.modular.weapon.secondar.");
|
secondary.insert_str(0, "common.items.modular.weapon.secondary.");
|
||||||
|
|
||||||
let material = ItemDefinitionIdOwned::Simple(
|
let material = ItemDefinitionIdOwned::Simple(
|
||||||
material
|
material
|
||||||
@ -108,15 +88,13 @@ impl<'de> Visitor<'de> for PriceListVisitor {
|
|||||||
})?
|
})?
|
||||||
.to_string(),
|
.to_string(),
|
||||||
);
|
);
|
||||||
let secondary = ItemDefinitionIdOwned::Compound {
|
|
||||||
// This unwrap is safe because the ItemDefinitionId is always Simple.
|
|
||||||
simple_base: primary,
|
|
||||||
components: vec![material],
|
|
||||||
};
|
|
||||||
|
|
||||||
ItemDefinitionIdOwned::Modular {
|
ItemDefinitionIdOwned::Modular {
|
||||||
pseudo_base: "veloren.core.pseudo_items.modular.tool".to_string(),
|
pseudo_base: "veloren.core.pseudo_items.modular.tool".to_string(),
|
||||||
components: vec![secondary],
|
components: vec![ItemDefinitionIdOwned::Compound {
|
||||||
|
simple_base: primary,
|
||||||
|
components: vec![ItemDefinitionIdOwned::Simple(secondary), material],
|
||||||
|
}],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[simple] => {
|
[simple] => {
|
||||||
|
Loading…
Reference in New Issue
Block a user