Rust version upgrade

This commit is contained in:
Condorra 2024-03-11 20:42:52 +11:00
parent be0204f5d9
commit e144771018
31 changed files with 561 additions and 162 deletions

132
Cargo.lock generated
View File

@ -73,7 +73,7 @@ dependencies = [
"ansi_markup",
"nom",
"quote",
"syn 2.0.48",
"syn 2.0.52",
]
[[package]]
@ -103,7 +103,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.52",
]
[[package]]
@ -125,7 +125,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.52",
]
[[package]]
@ -136,7 +136,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.52",
]
[[package]]
@ -162,9 +162,9 @@ dependencies = [
[[package]]
name = "base64"
version = "0.21.5"
version = "0.21.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[package]]
name = "bcrypt"
@ -219,7 +219,7 @@ dependencies = [
"deadpool-postgres",
"futures",
"humantime",
"itertools 0.12.0",
"itertools 0.12.1",
"log",
"mockall",
"mockall_double",
@ -314,7 +314,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.52",
"syn_derive",
]
@ -381,9 +381,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
[[package]]
name = "chrono"
version = "0.4.31"
version = "0.4.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a"
dependencies = [
"android-tzdata",
"iana-time-zone",
@ -391,7 +391,7 @@ dependencies = [
"num-traits",
"serde",
"wasm-bindgen",
"windows-targets 0.48.5",
"windows-targets 0.52.0",
]
[[package]]
@ -411,7 +411,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8"
dependencies = [
"lazy_static",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -543,7 +543,7 @@ dependencies = [
"num-traits",
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.52",
]
[[package]]
@ -647,7 +647,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.52",
]
[[package]]
@ -901,9 +901,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.1.0"
version = "2.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4"
dependencies = [
"equivalent",
"hashbrown 0.14.3",
@ -929,9 +929,9 @@ dependencies = [
[[package]]
name = "itertools"
version = "0.12.0"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
dependencies = [
"either",
]
@ -981,9 +981,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.20"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "md-5"
@ -1040,7 +1040,7 @@ checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
dependencies = [
"libc",
"wasi",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -1067,7 +1067,7 @@ dependencies = [
"cfg-if",
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.52",
]
[[package]]
@ -1079,7 +1079,7 @@ dependencies = [
"cfg-if",
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.52",
]
[[package]]
@ -1188,9 +1188,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "ouroboros"
version = "0.18.2"
version = "0.18.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a50b637ffd883b2733a8483599fb6136b9dcedaa1850f7ac08b9b6f9f2061208"
checksum = "97b7be5a8a3462b752f4be3ff2b2bf2f7f1d00834902e46be2a4d68b87b0573c"
dependencies = [
"aliasable",
"ouroboros_macro",
@ -1199,16 +1199,16 @@ dependencies = [
[[package]]
name = "ouroboros_macro"
version = "0.18.2"
version = "0.18.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3633d65683f13b9bcfaa3150880b018899fb0e5d0542f4adaea4f503fdb5eabf"
checksum = "b645dcde5f119c2c454a92d0dfa271a2a3b205da92e4292a68ead4bdbfde1f33"
dependencies = [
"heck",
"itertools 0.12.0",
"itertools 0.12.1",
"proc-macro2",
"proc-macro2-diagnostics",
"quote",
"syn 2.0.48",
"syn 2.0.52",
]
[[package]]
@ -1270,7 +1270,7 @@ dependencies = [
"phf_shared",
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.52",
]
[[package]]
@ -1299,7 +1299,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.52",
]
[[package]]
@ -1435,7 +1435,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.52",
"version_check",
"yansi",
]
@ -1564,16 +1564,17 @@ dependencies = [
[[package]]
name = "ring"
version = "0.17.7"
version = "0.17.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74"
checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
dependencies = [
"cc",
"cfg-if",
"getrandom",
"libc",
"spin",
"untrusted",
"windows-sys",
"windows-sys 0.52.0",
]
[[package]]
@ -1607,9 +1608,9 @@ dependencies = [
[[package]]
name = "rust_decimal"
version = "1.33.1"
version = "1.34.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06676aec5ccb8fc1da723cc8c0f9a46549f21ebb8753d3915c6c41db1e7f1dc4"
checksum = "b39449a79f45e8da28c57c341891b69a183044b29518bb8f86dbac9df60bb7df"
dependencies = [
"arrayvec",
"borsh",
@ -1662,9 +1663,9 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]]
name = "serde"
version = "1.0.195"
version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
dependencies = [
"serde_derive",
]
@ -1681,20 +1682,20 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.195"
version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.52",
]
[[package]]
name = "serde_json"
version = "1.0.111"
version = "1.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4"
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
dependencies = [
"itoa",
"ryu",
@ -1715,9 +1716,9 @@ dependencies = [
[[package]]
name = "serde_yaml"
version = "0.9.30"
version = "0.9.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1bf28c79a99f70ee1f1d83d10c875d2e70618417fda01ad1785e027579d9d38"
checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f"
dependencies = [
"indexmap",
"itoa",
@ -1772,7 +1773,7 @@ dependencies = [
"colored",
"log",
"time",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -1803,7 +1804,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
dependencies = [
"libc",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -1848,9 +1849,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.48"
version = "2.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
dependencies = [
"proc-macro2",
"quote",
@ -1866,7 +1867,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.52",
]
[[package]]
@ -1898,7 +1899,7 @@ checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.52",
]
[[package]]
@ -1949,9 +1950,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.35.1"
version = "1.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104"
checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
dependencies = [
"backtrace",
"bytes",
@ -1962,7 +1963,7 @@ dependencies = [
"signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
@ -1973,7 +1974,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.52",
]
[[package]]
@ -2110,7 +2111,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.52",
]
[[package]]
@ -2214,9 +2215,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]]
name = "uuid"
version = "1.6.1"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560"
checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a"
dependencies = [
"getrandom",
"serde",
@ -2310,7 +2311,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.52",
"wasm-bindgen-shared",
]
@ -2332,7 +2333,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.52",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@ -2381,6 +2382,15 @@ dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.0",
]
[[package]]
name = "windows-targets"
version = "0.48.5"

View File

@ -9,5 +9,5 @@ proc-macro = true
[dependencies]
nom = "7.1.3"
quote = "1.0.35"
syn = "2.0.48"
syn = "2.0.52"
ansi_markup = { path = "../ansi_markup" }

View File

@ -6,40 +6,40 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
base64 = "0.21.5"
base64 = "0.21.7"
blastmud_interfaces = { path = "../blastmud_interfaces" }
ansi = { path = "../ansi" }
ansi_markup = { path = "../ansi_markup" }
deadpool = "0.10.0"
deadpool-postgres = { version = "0.12.1", features = ["serde"] }
futures = "0.3.30"
log = "0.4.20"
log = "0.4.21"
nix = { version = "0.27.1", features = ["process", "signal"] }
ring = "0.17.7"
serde = { version = "1.0.195", features = ["derive", "serde_derive"] }
serde_yaml = "0.9.30"
ring = "0.17.8"
serde = { version = "1.0.197", features = ["derive", "serde_derive"] }
serde_yaml = "0.9.32"
simple_logger = "4.3.3"
tokio = { version = "1.35.1", features = ["signal", "net", "macros", "rt-multi-thread", "rt", "tokio-macros", "time", "sync", "io-util"] }
tokio = { version = "1.36.0", features = ["signal", "net", "macros", "rt-multi-thread", "rt", "tokio-macros", "time", "sync", "io-util"] }
tokio-postgres = { version = "0.7.10", features = ["with-uuid-1", "with-serde_json-1"] }
tokio-serde = { version = "0.8.0", features = ["serde", "serde_cbor", "cbor"] }
tokio-stream = "0.1.14"
tokio-util = { version = "0.7.10", features = ["codec"] }
uuid = { version = "1.6.1", features = ["v4", "serde", "rng"] }
serde_json = "1.0.111"
uuid = { version = "1.7.0", features = ["v4", "serde", "rng"] }
serde_json = "1.0.114"
phf = { version = "0.11.2", features = ["macros"] }
async-trait = "0.1.77"
nom = "7.1.3"
ouroboros = "0.18.2"
chrono = { version = "0.4.31", features = ["serde"] }
ouroboros = "0.18.3"
chrono = { version = "0.4.35", features = ["serde"] }
bcrypt = "0.15.0"
validator = "0.16.1"
itertools = "0.12.0"
itertools = "0.12.1"
once_cell = "1.19.0"
rand = "0.8.5"
async-recursion = "1.0.5"
rand_distr = "0.4.3"
humantime = "2.1.0"
rust_decimal = "1.33.1"
rust_decimal = "1.34.3"
mockall_double = "0.3.1"
[dev-dependencies]

View File

@ -1091,6 +1091,25 @@ impl DBTrans {
Ok(())
}
pub async fn fetch_specific_task<'a>(
&'a self,
task_type: &'a str,
task_code: &'a str,
) -> DResult<Option<TaskParse>> {
match self
.pg_trans()?
.query_opt(
"SELECT details FROM tasks WHERE details->>'task_type' = $1 AND \
details->>'task_code' = $2",
&[&task_type, &task_code],
)
.await?
{
None => Ok(None),
Some(row) => Ok(serde_json::from_value(row.get("details"))?),
}
}
pub async fn upsert_task<'a>(&'a self, task: &'a Task) -> DResult<()> {
self.pg_trans()?
.execute(
@ -1583,7 +1602,7 @@ impl DBTrans {
self.pg_trans()?
.execute(
"DELETE FROM corp_membership WHERE details->>'invited_at' <= $1",
&[&(Utc::now() - chrono::Duration::hours(4))
&[&(Utc::now() - chrono::TimeDelta::try_hours(4).unwrap())
.to_rfc3339_opts(chrono::SecondsFormat::Nanos, true)],
)
.await?;

View File

@ -233,8 +233,10 @@ fn compute_new_consent_state(
Some(n) => Some(n.min(60 * 24 * 7)),
}
};
new_consent.expires = expires_minutes
.map(|n| chrono::Utc::now() + chrono::Duration::minutes(n.min(60 * 24 * 365 * 25) as i64));
new_consent.expires = expires_minutes.map(|n| {
chrono::Utc::now()
+ chrono::TimeDelta::try_minutes(n.min(60 * 24 * 365 * 25) as i64).unwrap()
});
match their_target_consent
.as_ref()
.and_then(|c| c.expires)
@ -575,7 +577,8 @@ mod tests {
&ConsentDetails::default_for(&ConsentType::Fight),
&None,
&Some(Consent {
expires: Some(chrono::Utc::now() + chrono::Duration::minutes(60 * 24 * 7)),
expires: Some(chrono::Utc::now() + chrono::TimeDelta::try_minutes(60 * 24 * 7))
.unwrap(),
fight_consent: Some(FightConsent::default()),
..Consent::default()
}),
@ -605,7 +608,8 @@ mod tests {
..ConsentDetails::default_for(&ConsentType::Fight)
},
&Some(Consent {
expires: Some(chrono::Utc::now() + chrono::Duration::minutes(60 * 24 * 7)),
expires: Some(chrono::Utc::now() + chrono::TimeDelta::try_minutes(60 * 24 * 7))
.unwrap(),
fight_consent: Some(FightConsent {
status: ConsentStatus::Active,
..FightConsent::default()
@ -613,7 +617,8 @@ mod tests {
..Consent::default()
}),
&Some(Consent {
expires: Some(chrono::Utc::now() + chrono::Duration::minutes(60 * 24 * 7)),
expires: Some(chrono::Utc::now() + chrono::TimeDelta::try_minutes(60 * 24 * 7))
.unwrap(),
fight_consent: Some(FightConsent {
status: ConsentStatus::Active,
..FightConsent::default()
@ -662,7 +667,8 @@ mod tests {
..ConsentDetails::default_for(&ConsentType::Fight)
},
&Some(Consent {
expires: Some(chrono::Utc::now() + chrono::Duration::minutes(60 * 24 * 7)),
expires: Some(chrono::Utc::now() + chrono::TimeDelta::try_minutes(60 * 24 * 7))
.unwrap(),
fight_consent: Some(FightConsent {
status: ConsentStatus::Active,
..FightConsent::default()
@ -670,11 +676,15 @@ mod tests {
..Consent::default()
}),
&Some(Consent {
expires: Some(chrono::Utc::now() + chrono::Duration::minutes(60 * 24 * 7)),
expires: Some(chrono::Utc::now() + chrono::TimeDelta::try_minutes(60 * 24 * 7))
.unwrap(),
fight_consent: Some(FightConsent {
status: ConsentStatus::Active,
pending_change: Some(Box::new(Consent {
expires: Some(chrono::Utc::now() + chrono::Duration::minutes(60 * 24 * 7)),
expires: Some(
chrono::Utc::now() + chrono::TimeDelta::try_minutes(60 * 24 * 7),
)
.unwrap(),
fight_consent: Some(FightConsent {
freely_revoke: true,
..FightConsent::default()

View File

@ -164,7 +164,7 @@ impl UserVerb for Verb {
.upsert_task(&Task {
meta: TaskMeta {
task_code: username.clone(),
next_scheduled: Utc::now() + chrono::Duration::days(7),
next_scheduled: Utc::now() + chrono::TimeDelta::try_days(7).unwrap(),
..Default::default()
},
details: TaskDetails::DestroyUser { username },

View File

@ -92,7 +92,7 @@ pub async fn consider_expire_job_for_item(trans: &DBTrans, item: &Item) -> DResu
.upsert_task(&Task {
meta: TaskMeta {
task_code: format!("{}/{}", item.item_type, item.item_code),
next_scheduled: Utc::now() + chrono::Duration::hours(1),
next_scheduled: Utc::now() + chrono::TimeDelta::try_hours(1).unwrap(),
..Default::default()
},
details: TaskDetails::ExpireItem {

View File

@ -230,7 +230,8 @@ impl UserVerb for Verb {
task_code: npc.item_code.clone(),
is_static: false,
recurrence: None, // Managed by the handler.
next_scheduled: Utc::now() + Duration::seconds(hire_dat.frequency_secs as i64),
next_scheduled: Utc::now()
+ Duration::try_seconds(hire_dat.frequency_secs as i64).unwrap(),
..Default::default()
},
details: TaskDetails::ChargeWages {

View File

@ -26,6 +26,7 @@ use crate::{
check_consent, check_one_consent,
combat::{change_health, handle_resurrect, stop_attacking_mut},
comms::broadcast_to_room,
environment::ensure_appropriate_environment_handler_after_movement,
sharing::stop_conversation_mut,
skills::skill_check_and_grind,
urges::{recalculate_urge_growth, thirst_changed},
@ -376,7 +377,7 @@ pub async fn reverse_climb(
// Returns true if the move is either complete or still in progress.
// Returns false if the move failed.
async fn attempt_move_immediate(
pub async fn attempt_move_immediate(
direction: &Direction,
ctx: &mut QueuedCommandContext<'_>,
source: &MovementSource,
@ -482,6 +483,15 @@ async fn attempt_move_immediate(
broadcast_to_room(ctx.trans, &from_room, None, &msg).await?;
broadcast_to_room(ctx.trans, &to_room, None, &msg).await?;
ctx.item.queue.truncate(0);
if got_there {
if let Some((old_loc_type, old_loc_code)) = use_location.split_once("/") {
check_for_exit_action(ctx, old_loc_type, old_loc_code).await?;
}
check_for_instant_aggro(&ctx.trans, &mut ctx.item).await?;
check_for_enter_action(ctx).await?;
ensure_appropriate_environment_handler_after_movement(ctx).await?;
}
return Ok(got_there);
} else if skills <= 0.0 {
if climb.height >= 0 {
@ -735,6 +745,7 @@ async fn attempt_move_immediate(
check_for_instant_aggro(&ctx.trans, &mut ctx.item).await?;
check_for_enter_action(ctx).await?;
ensure_appropriate_environment_handler_after_movement(ctx).await?;
Ok(true)
}

View File

@ -188,7 +188,7 @@ pub async fn attempt_open_immediate(
.upsert_task(&Task {
meta: TaskMeta {
task_code: format!("{}/{}", &room_1.refstr(), &direction.describe()),
next_scheduled: Utc::now() + chrono::Duration::seconds(120),
next_scheduled: Utc::now() + chrono::TimeDelta::try_seconds(120).unwrap(),
..Default::default()
},
details: TaskDetails::SwingShut {

View File

@ -119,7 +119,7 @@ impl UserVerb for Verb {
.upsert_task(&Task {
meta: TaskMeta {
task_code: refstr.clone(),
next_scheduled: Utc::now() + Duration::minutes(1),
next_scheduled: Utc::now() + Duration::try_minutes(1).unwrap(),
..Default::default()
},
details: TaskDetails::ChargeItem { item: refstr },

View File

@ -8,6 +8,7 @@ use crate::{
queue_command_and_save, QueueCommand, QueueCommandHandler, QueuedCommandContext,
},
services::{comms::broadcast_to_room, urges::recalculate_urge_growth},
static_content::room::{room_map_by_code, MaterialType},
};
use async_trait::async_trait;
use std::time;
@ -47,6 +48,20 @@ impl QueueCommandHandler for QueueHandler {
}
_ => {}
}
let (loc_type, loc_code) = match ctx.item.location.split_once("/") {
None => user_error("You've ended up in a bad place.".to_owned())?,
Some(v) => v,
};
if loc_type == "room" {
if let Some(room) = room_map_by_code().get(loc_code) {
match room.material_type {
MaterialType::Underwater | MaterialType::WaterSurface => {
user_error("You're already floating around".to_owned())?
}
_ => {}
}
}
}
match item_ref {
None => {}
Some(item_ref) => {
@ -107,6 +122,20 @@ impl QueueCommandHandler for QueueHandler {
}
_ => {}
}
let (loc_type, loc_code) = match ctx.item.location.split_once("/") {
None => user_error("You've ended up in a bad place.".to_owned())?,
Some(v) => v,
};
if loc_type == "room" {
if let Some(room) = room_map_by_code().get(loc_code) {
match room.material_type {
MaterialType::Underwater | MaterialType::WaterSurface => {
user_error("You're already floating around".to_owned())?
}
_ => {}
}
}
}
let (item, desc) = match item_ref {
None => (None, "the floor".to_owned()),
Some(item_ref) => {

View File

@ -21,7 +21,7 @@ use crate::{
use ansi::ansi;
use async_recursion::async_recursion;
use async_trait::async_trait;
use chrono::{DateTime, Duration, Utc};
use chrono::{DateTime, TimeDelta, Utc};
use itertools::Itertools;
use log::info;
use mockall_double::double;
@ -96,7 +96,7 @@ async fn bill_residential_room(
}
let mut zone_item_mut = (*zone_item).clone();
zone_item_mut.special_data = Some(ItemSpecialData::DynzoneData {
vacate_after: Some(Utc::now() + Duration::days(1)),
vacate_after: Some(Utc::now() + TimeDelta::try_days(1).unwrap()),
zone_exit: match zone_item.special_data.as_ref() {
Some(ItemSpecialData::DynzoneData { zone_exit, .. }) => zone_exit.clone(),
_ => None,
@ -168,7 +168,7 @@ async fn bill_commercial_room(
}
let mut zone_item_mut = (*zone_item).clone();
zone_item_mut.special_data = Some(ItemSpecialData::DynzoneData {
vacate_after: Some(Utc::now() + Duration::days(1)),
vacate_after: Some(Utc::now() + TimeDelta::try_days(1).unwrap()),
zone_exit: match zone_item.special_data.as_ref() {
Some(ItemSpecialData::DynzoneData { zone_exit, .. }) => zone_exit.clone(),
_ => None,
@ -493,7 +493,7 @@ impl UserVerb for Verb {
task_code: format!("charge_rent/{}", &zonecode),
is_static: false,
recurrence: None, // Managed by the handler.
next_scheduled: Utc::now() + Duration::days(1),
next_scheduled: Utc::now() + TimeDelta::try_days(1).unwrap(),
..Default::default()
},
details: TaskDetails::ChargeRoom {

View File

@ -11,7 +11,7 @@ use crate::{
};
use ansi::ansi;
use async_trait::async_trait;
use chrono::{Duration, Utc};
use chrono::{TimeDelta, Utc};
use itertools::Itertools;
pub struct Verb;
@ -108,7 +108,9 @@ impl UserVerb for Verb {
.save_item_model(&Item {
special_data: Some(ItemSpecialData::DynzoneData {
zone_exit: ex.clone(),
vacate_after: Some(Utc::now() + Duration::days(1)),
vacate_after: Some(
Utc::now() + TimeDelta::try_days(1).unwrap(),
),
}),
..(*ex_zone).clone()
})

View File

@ -80,6 +80,10 @@ pub enum TaskDetails {
ChargeItem {
item: String,
},
ApplyEnvironmentalEffects {
on_player_type: String,
on_player_code: String,
},
}
impl TaskDetails {
pub fn name(self: &Self) -> &'static str {
@ -109,6 +113,7 @@ impl TaskDetails {
ExpireBuff { .. } => "ExpireBuff",
DischargeLight { .. } => "DischargeLight",
ChargeItem { .. } => "ChargeItem",
ApplyEnvironmentalEffects { .. } => "ApplyEnvironmentalEffects",
// Don't forget to add to TASK_HANDLER_REGISTRY in regular_tasks.rs too.
}
}
@ -130,7 +135,7 @@ impl Default for TaskMeta {
is_static: false,
recurrence: None,
consecutive_failure_count: 0,
next_scheduled: Utc::now() + chrono::Duration::seconds(3600),
next_scheduled: Utc::now() + chrono::TimeDelta::try_seconds(3600).unwrap(),
}
}
}

View File

@ -9,7 +9,7 @@ use crate::{
listener::{ListenerMap, ListenerSend},
message_handler::user_commands::{delete, drop, hire, open, rent},
models::task::Task,
services::{charging, combat, effect, idlepark, sharing, spawn, tempbuff, urges},
services::{charging, combat, effect, environment, idlepark, sharing, spawn, tempbuff, urges},
static_content::{
npc::{self, computer_museum_npcs},
possession_type::lights,
@ -72,6 +72,7 @@ fn task_handler_registry(
("ExpireBuff", tempbuff::EXPIRE_BUFF_TASK),
("DischargeLight", lights::DISCHARGE_TASK),
("ChargeItem", charging::TASK_HANDLER),
("ApplyEnvironmentalEffects", environment::TASK_HANDLER),
]
.into_iter()
.collect()
@ -199,8 +200,8 @@ async fn process_tasks_once(pool: db::DBPool) -> DResult<()> {
)
.await?;
} else {
task.meta.next_scheduled =
Utc::now() + chrono::Duration::seconds(60);
task.meta.next_scheduled = Utc::now()
+ chrono::TimeDelta::try_seconds(60).unwrap();
tx.update_task(
&task.details.name(),
&task.meta.task_code,
@ -226,7 +227,10 @@ async fn process_tasks_once(pool: db::DBPool) -> DResult<()> {
}
Some(TaskRecurrence::FixedDuration { seconds }) => {
task.meta.next_scheduled = Utc::now()
+ chrono::Duration::seconds(seconds as i64);
+ chrono::TimeDelta::try_seconds(
seconds as i64,
)
.unwrap();
tx.update_task(
&task.details.name(),
&task.meta.task_code,
@ -256,9 +260,9 @@ async fn process_tasks_once(pool: db::DBPool) -> DResult<()> {
tx.commit().await?;
}
Some(TaskRecurrence::FixedDuration { seconds }) => {
task.meta
.next_scheduled
.add_assign(chrono::Duration::seconds(seconds as i64));
task.meta.next_scheduled.add_assign(
chrono::TimeDelta::try_seconds(seconds as i64).unwrap(),
);
tx.update_task(
&task.task_type,
&task.meta.task_code,

View File

@ -340,7 +340,7 @@ pub async fn queue_command(
.upsert_task(&Task {
meta: TaskMeta {
task_code: item.refstr(),
next_scheduled: Utc::now() + chrono::Duration::from_std(dur)?,
next_scheduled: Utc::now() + chrono::TimeDelta::from_std(dur)?,
..Default::default()
},
details: TaskDetails::RunQueuedCommand,
@ -387,7 +387,7 @@ pub async fn queue_command_for_npc(
.upsert_task(&Task {
meta: TaskMeta {
task_code: item.refstr(),
next_scheduled: Utc::now() + chrono::Duration::from_std(dur)?,
next_scheduled: Utc::now() + chrono::TimeDelta::from_std(dur)?,
..Default::default()
},
details: TaskDetails::RunQueuedCommand,

View File

@ -22,6 +22,7 @@ pub mod combat;
pub mod comms;
pub mod display;
pub mod effect;
pub mod environment;
pub mod idlepark;
pub mod room_effects;
pub mod sharing;

View File

@ -35,7 +35,7 @@ use crate::{
use ansi::ansi;
use async_recursion::async_recursion;
use async_trait::async_trait;
use chrono::{Duration, Utc};
use chrono::{TimeDelta, Utc};
use mockall_double::double;
use rand::{prelude::IteratorRandom, thread_rng, Rng};
use rand_distr::{Distribution, Normal};
@ -707,7 +707,7 @@ pub async fn handle_death(trans: &DBTrans, whom: &mut Item) -> DResult<()> {
.upsert_task(&Task {
meta: TaskMeta {
task_code: whom.item_code.clone(),
next_scheduled: Utc::now() + chrono::Duration::seconds(600),
next_scheduled: Utc::now() + chrono::TimeDelta::try_seconds(600).unwrap(),
..Default::default()
},
details: TaskDetails::RecloneNPC {
@ -979,7 +979,8 @@ pub async fn start_attack_mut(
meta: TaskMeta {
task_code: format!("{}/{}", by_whom.item_type, by_whom.item_code),
next_scheduled: Utc::now()
+ chrono::Duration::milliseconds(attack_speed(by_whom).as_millis() as i64),
+ chrono::TimeDelta::try_milliseconds(attack_speed(by_whom).as_millis() as i64)
.unwrap(),
..Default::default()
},
details: TaskDetails::AttackTick,
@ -1008,7 +1009,7 @@ pub async fn corpsify_item(trans: &DBTrans, base_item: &Item) -> DResult<Item> {
.upsert_task(&Task {
meta: TaskMeta {
task_code: new_item.item_code.clone(),
next_scheduled: Utc::now() + chrono::Duration::minutes(5),
next_scheduled: Utc::now() + chrono::TimeDelta::try_minutes(5).unwrap(),
..Default::default()
},
details: TaskDetails::RotCorpse {
@ -1045,10 +1046,12 @@ pub async fn switch_to_power_attack(ctx: &VerbContext<'_>, who: &Arc<Item>) -> U
match who
.tactic_use
.last_pow
.map(|lp| (lp + Duration::seconds(pow_delay)) - Utc::now())
.map(|lp| (lp + TimeDelta::try_seconds(pow_delay).unwrap()) - Utc::now())
{
None => {}
Some(d) if d < Duration::seconds(0) || who.flags.contains(&ItemFlag::Invincible) => {}
Some(d)
if d < TimeDelta::try_seconds(0).unwrap()
|| who.flags.contains(&ItemFlag::Invincible) => {}
Some(d) => user_error(format!(
"You can't powerattack again for another {} seconds.",
d.num_seconds()
@ -1076,8 +1079,12 @@ pub async fn switch_to_power_attack(ctx: &VerbContext<'_>, who: &Arc<Item>) -> U
.upsert_task(&Task {
meta: TaskMeta {
task_code: format!("{}/{}", &who.item_type, &who.item_code),
next_scheduled: Utc::now()
+ chrono::Duration::milliseconds(attack_speed(&who_mut).as_millis() as i64),
next_scheduled:
Utc::now()
+ chrono::TimeDelta::try_milliseconds(
attack_speed(&who_mut).as_millis() as i64
)
.unwrap(),
..Default::default()
},
details: TaskDetails::AttackTick,
@ -1102,10 +1109,10 @@ pub async fn switch_to_feint(ctx: &VerbContext<'_>, who: &Arc<Item>) -> UResult<
match who
.tactic_use
.last_feint
.map(|lp| (lp + Duration::seconds(feint_delay)) - Utc::now())
.map(|lp| (lp + TimeDelta::try_seconds(feint_delay).unwrap()) - Utc::now())
{
None => {}
Some(d) if d < Duration::seconds(0) => {}
Some(d) if d < TimeDelta::try_seconds(0).unwrap() => {}
Some(d) => user_error(format!(
"You can't feint again for another {} seconds.",
d.num_seconds()
@ -1173,8 +1180,12 @@ pub async fn switch_to_feint(ctx: &VerbContext<'_>, who: &Arc<Item>) -> UResult<
.upsert_task(&Task {
meta: TaskMeta {
task_code: format!("{}/{}", &who.item_type, &who.item_code),
next_scheduled: Utc::now()
+ chrono::Duration::milliseconds(attack_speed(&who_mut).as_millis() as i64),
next_scheduled:
Utc::now()
+ chrono::TimeDelta::try_milliseconds(
attack_speed(&who_mut).as_millis() as i64
)
.unwrap(),
..Default::default()
},
details: TaskDetails::AttackTick,

View File

@ -313,7 +313,7 @@ pub async fn run_effects(
.upsert_task(&Task {
meta: TaskMeta {
task_code: format!("{}/{}", &actual_target.refstr(), task_ref),
next_scheduled: Utc::now() + chrono::Duration::seconds(dispel_time_secs as i64),
next_scheduled: Utc::now() + chrono::TimeDelta::try_seconds(dispel_time_secs as i64).unwrap(),
..Default::default()
},
details: TaskDetails::DispelEffect {
@ -329,7 +329,7 @@ pub async fn run_effects(
.upsert_task(&Task {
meta: TaskMeta {
task_code: format!("{}/{}", eff_item, trans.alloc_task_code().await?),
next_scheduled: Utc::now() + chrono::Duration::seconds(l[0].delay as i64),
next_scheduled: Utc::now() + chrono::TimeDelta::try_seconds(l[0].delay as i64).unwrap(),
..Default::default()
},
details: TaskDetails::DelayedHealth {
@ -344,7 +344,7 @@ pub async fn run_effects(
.upsert_task(&Task {
meta: TaskMeta {
task_code: format!("{}/{}", eff_item, task_ref),
next_scheduled: Utc::now() + chrono::Duration::seconds(l[0].delay as i64),
next_scheduled: Utc::now() + chrono::TimeDelta::try_seconds(l[0].delay as i64).unwrap(),
..Default::default()
},
details: TaskDetails::DelayedMessage {

View File

@ -0,0 +1,197 @@
use std::time;
use async_trait::async_trait;
use chrono::Utc;
use log::warn;
use uuid::Uuid;
use crate::{
message_handler::user_commands::{
movement::attempt_move_immediate, CommandHandlingError, UResult,
},
models::{
item::{Item, SkillType},
task::{Task, TaskDetails, TaskMeta},
},
regular_tasks::{
queued_command::{MovementSource, QueueCommand, QueuedCommandContext},
TaskHandler, TaskRunContext,
},
static_content::room::{room_map_by_code, Direction, MaterialType, Room},
DResult,
};
use super::{combat::change_health, comms::broadcast_to_room, skills::skill_check_and_grind};
pub struct EnvironmentHandler;
pub async fn ensure_appropriate_environment_handler_after_movement(
ctx: &mut QueuedCommandContext<'_>,
) -> UResult<()> {
if ctx.item.item_type != "player" {
return Ok(());
}
let (loc_type, loc_code) = match ctx.item.location.split_once("/") {
None => return Ok(()),
Some(v) => v,
};
let need_handler = if loc_type != "room" {
false
} else {
let room = match room_map_by_code().get(loc_code) {
None => return Ok(()),
Some(r) => r,
};
match room.material_type {
MaterialType::WaterSurface | MaterialType::Underwater => true,
_ => false,
}
};
let existing_task = ctx
.trans
.fetch_specific_task("ApplyEnvironmentalEffects", &ctx.item.refstr())
.await?;
if need_handler {
if existing_task.is_none() {
ctx.trans
.upsert_task(&Task {
meta: TaskMeta {
task_code: ctx.item.refstr(),
next_scheduled: Utc::now() + chrono::TimeDelta::try_seconds(10).unwrap(),
..Default::default()
},
details: TaskDetails::ApplyEnvironmentalEffects {
on_player_type: ctx.item.item_type.clone(),
on_player_code: ctx.item.item_code.clone(),
},
})
.await?;
}
} else {
if existing_task.is_some() {
ctx.trans
.delete_task("ApplyEnvironmentalEffects", &ctx.item.refstr())
.await?;
}
}
Ok(())
}
#[async_trait]
impl TaskHandler for EnvironmentHandler {
async fn do_task(&self, ctx: &mut TaskRunContext) -> DResult<Option<time::Duration>> {
let (player_type, player_code) = match &ctx.task.details {
TaskDetails::ApplyEnvironmentalEffects {
on_player_type,
on_player_code,
} => (on_player_type, on_player_code),
x => {
warn!(
"EnvironmentHandler called with bad TaskDetail type: {:#?}",
x
);
return Ok(None);
}
};
let player = match ctx
.trans
.find_item_by_type_code(&player_type, &player_code)
.await?
{
None => return Ok(None),
Some(p) => p,
};
let mut player = (*player).clone();
let (loc_type, loc_code) = match player.location.split_once("/") {
None => return Ok(None),
Some(v) => v,
};
if loc_type != "room" {
return Ok(None);
};
let room = match room_map_by_code().get(loc_code) {
None => return Ok(None),
Some(r) => r,
};
let need_save = water_environment_effects(ctx, &room, &mut player).await?;
if need_save {
ctx.trans.save_item_model(&player).await?;
}
Ok(Some(time::Duration::from_secs(10)))
}
}
pub async fn water_environment_effects(
ctx: &mut TaskRunContext<'_>,
room: &Room,
player_item: &mut Item,
) -> DResult<bool> {
match room.material_type {
MaterialType::WaterSurface => {}
MaterialType::Underwater => {
if change_health(
&ctx.trans,
-5,
player_item,
&format!(
"{} can't breathe underwater",
player_item.display_for_sentence(1, true)
),
)
.await?
{
return Ok(true);
}
}
_ => return Ok(false),
}
match room.exits.iter().find(|v| v.direction == Direction::DOWN) {
None => return Ok(false),
Some(_) => {
if player_item.active_climb.is_some() {
return Ok(false);
}
if skill_check_and_grind(&ctx.trans, player_item, &SkillType::Swim, 9.0).await? > 0.0 {
return Ok(true);
} else {
broadcast_to_room(
&ctx.trans,
&player_item.location,
None,
&format!(
"{} seems to be sinking.\n",
player_item.display_for_sentence(1, true)
),
)
.await?;
player_item.queue.truncate(0);
let source = MovementSource::Internal {
event_id: Uuid::new_v4(),
};
let mut qctx = QueuedCommandContext {
trans: ctx.trans,
command: &QueueCommand::Movement {
direction: Direction::DOWN,
source: source.clone(),
},
item: player_item,
};
match attempt_move_immediate(&Direction::DOWN, &mut qctx, &source).await {
Ok(_) => {}
Err(CommandHandlingError::UserError(_)) => {}
Err(CommandHandlingError::SystemError(e)) => return Err(e),
}
}
}
}
Ok(true)
}
pub static TASK_HANDLER: &'static (dyn TaskHandler + Sync + Send) = &EnvironmentHandler;

View File

@ -55,7 +55,7 @@ pub fn idlepark_tasks() -> Box<dyn Iterator<Item = StaticTask>> {
task_code: "IdlePark".to_owned(),
is_static: true,
recurrence: Some(TaskRecurrence::FixedDuration { seconds: 120 }),
next_scheduled: Utc::now() + chrono::Duration::seconds(120),
next_scheduled: Utc::now() + chrono::TimeDelta::try_seconds(120).unwrap(),
..Default::default()
},
details: TaskDetails::IdlePark,

View File

@ -667,7 +667,7 @@ pub async fn start_conversation(
.upsert_task(&Task {
meta: TaskMeta {
task_code: share_event_name(&initiator, &acceptor),
next_scheduled: Utc::now() + chrono::Duration::milliseconds(5000),
next_scheduled: Utc::now() + chrono::TimeDelta::try_milliseconds(5000).unwrap(),
..Default::default()
},
details: TaskDetails::ShareTick,
@ -774,7 +774,7 @@ async fn apply_conversation_buff(trans: &DBTrans, to_player: &mut Item) -> DResu
.upsert_task(&Task {
meta: TaskMeta {
task_code: exp_task_code.clone(),
next_scheduled: Utc::now() + chrono::Duration::seconds(600),
next_scheduled: Utc::now() + chrono::TimeDelta::try_seconds(600).unwrap(),
..Default::default()
},
details: TaskDetails::ExpireBuff {

View File

@ -264,7 +264,7 @@ pub fn urge_tasks() -> Box<dyn Iterator<Item = StaticTask>> {
task_code: "tick_urges".to_owned(),
is_static: true,
recurrence: Some(TaskRecurrence::FixedDuration { seconds: 60 }),
next_scheduled: Utc::now() + chrono::Duration::seconds(60),
next_scheduled: Utc::now() + chrono::TimeDelta::try_seconds(60).unwrap(),
..TaskMeta::default()
},
details: TaskDetails::TickUrges,

View File

@ -264,8 +264,9 @@ pub fn npc_static_items() -> Box<dyn Iterator<Item = StaticItem>> {
let mut pos_it: Item = spawn_item.what.clone().into();
pos_it.location = npc_ref.clone();
pos_it.action_type = spawn_item.action_type.clone();
pos_it.action_type_started =
Some(Utc::now() - chrono::Duration::seconds(spawn_item.wear_layer));
pos_it.action_type_started = Some(
Utc::now() - chrono::TimeDelta::try_seconds(spawn_item.wear_layer).unwrap(),
);
pos_it
}))
}),
@ -276,29 +277,30 @@ pub fn npc_static_items() -> Box<dyn Iterator<Item = StaticItem>> {
pub fn npc_say_tasks() -> Box<dyn Iterator<Item = StaticTask>> {
Box::new(npc_list().iter().flat_map(|c| {
c.says.iter().map(|say| StaticTask {
task_code: c.code.to_owned() + "_" + say.say_code,
initial_task: Box::new(|| {
let mut rng = thread_rng();
Task {
meta: TaskMeta {
task_code: c.code.to_owned() + "_" + say.say_code,
is_static: true,
recurrence: Some(TaskRecurrence::FixedDuration {
seconds: say.frequency_secs as u32,
}),
next_scheduled: Utc::now()
+ chrono::Duration::seconds(
rng.gen_range(0..say.frequency_secs) as i64
),
..TaskMeta::default()
},
details: TaskDetails::NPCSay {
npc_code: c.code.to_owned(),
say_code: say.say_code.to_owned(),
},
}
}),
})
task_code: c.code.to_owned() + "_" + say.say_code,
initial_task: Box::new(|| {
let mut rng = thread_rng();
Task {
meta: TaskMeta {
task_code: c.code.to_owned() + "_" + say.say_code,
is_static: true,
recurrence: Some(TaskRecurrence::FixedDuration {
seconds: say.frequency_secs as u32,
}),
next_scheduled: Utc::now()
+ chrono::TimeDelta::try_seconds(
rng.gen_range(0..say.frequency_secs) as i64
)
.unwrap(),
..TaskMeta::default()
},
details: TaskDetails::NPCSay {
npc_code: c.code.to_owned(),
say_code: say.say_code.to_owned(),
},
}
}),
})
}))
}
@ -319,7 +321,8 @@ pub fn npc_wander_tasks() -> Box<dyn Iterator<Item = StaticTask>> {
seconds: rng.gen_range(250..350) as u32,
}),
next_scheduled: Utc::now()
+ chrono::Duration::seconds(rng.gen_range(0..300) as i64),
+ chrono::TimeDelta::try_seconds(rng.gen_range(0..300) as i64)
.unwrap(),
..TaskMeta::default()
},
details: TaskDetails::NPCWander {
@ -352,7 +355,10 @@ pub fn npc_aggro_tasks() -> Box<dyn Iterator<Item = StaticTask>> {
seconds: aggro_time as u32,
}),
next_scheduled: Utc::now()
+ chrono::Duration::seconds(rng.gen_range(0..aggro_time) as i64),
+ chrono::TimeDelta::try_seconds(
rng.gen_range(0..aggro_time) as i64
)
.unwrap(),
..TaskMeta::default()
},
details: TaskDetails::NPCAggro {

View File

@ -265,7 +265,7 @@ impl NPCMessageHandler for DoorbotMsgHandler {
.upsert_task(&Task {
meta: TaskMeta {
task_code: "room/computer_museum_hackers_club/south".to_owned(),
next_scheduled: Utc::now() + chrono::Duration::seconds(120),
next_scheduled: Utc::now() + chrono::TimeDelta::try_seconds(120).unwrap(),
..Default::default()
},
details: TaskDetails::SwingShut {
@ -294,7 +294,7 @@ impl NPCMessageHandler for DoorbotMsgHandler {
.upsert_task(&Task {
meta: TaskMeta {
task_code: "reset_hanoi_computer_club".to_owned(),
next_scheduled: Utc::now() + chrono::Duration::seconds(600),
next_scheduled: Utc::now() + chrono::TimeDelta::try_seconds(600).unwrap(),
..Default::default()
},
details: TaskDetails::ResetHanoi,

View File

@ -61,7 +61,7 @@ impl TurnToggleHandler for LanternHandler {
.upsert_task(&Task {
meta: TaskMeta {
task_code: item_mut.refstr(),
next_scheduled: Utc::now() + chrono::Duration::minutes(5),
next_scheduled: Utc::now() + chrono::TimeDelta::try_minutes(5).unwrap(),
..Default::default()
},
details: TaskDetails::DischargeLight {

View File

@ -28,7 +28,7 @@ impl RoomEnterTrigger for EnterERTrigger {
.upsert_task(&Task {
meta: TaskMeta {
task_code: ctx.item.refstr(),
next_scheduled: Utc::now() + chrono::Duration::seconds(60),
next_scheduled: Utc::now() + chrono::TimeDelta::try_seconds(60).unwrap(),
..Default::default()
},
details: TaskDetails::HospitalERSeePatient {

View File

@ -16,5 +16,98 @@
z: 0
description: "The start of a deteriorating asphalt road that leads north through a barren dusty environment. The road is blocked by a barrier arm. The arm is attached to a box with a window in it, occupied by a guard in a fluorescent yellow high-visibility vest. The side of the box is painted with a symbol featuring three black wedges arranged circularly around a central black circle, on a yellow background. Beneath it is the text: <red>DANGER - FALLOUT - Ionising Radiation Hazard. Access to the radfields by permit only<reset>"
exits:
- direction: north
- direction: south
target: !Custom room/melbs_latrobest_140
- zone: northern_radfields
code: northrad_s6
name: Northern Radfields - Melbs outskirts
short: <yellow>||<reset>
grid_coords:
x: 6
y: 19
z: 0
description: "A stretch of deteriorating asphalt road, its once smooth surface now cracked and uneven. Scattered debris litters the sides of the road, remnants of vehicles long abandoned. Ahead, a solitary gum tree stands tall against the elements, its leaves a brilliant green amidst the parched land. It smells like eucalyptus here. To the south you a gatehouse and signs of civilisation in the distance"
exits:
- direction: north
- direction: south
- zone: northern_radfields
code: northrad_r6
name: Northern Radfields - Outside the abandoned windfarm
short: <yellow>||<reset>
grid_coords:
x: 6
y: 18
z: 0
description: "A crumbling stretch of asphalt road that weaves through a field of giant wind turbines overgrown with noxious weeds, some of which are spilling out and narrowing the road. Some of the turbines seem to be on a lean and, and some have dropped rusted blades, but a few still turn lazily in the wind, emitting a hum as they spin. It smells faintly of ozone"
exits:
- direction: north
- direction: south
- zone: northern_radfields
code: northrad_q6
name: Northern Radfields - Crystal clear pond
short: <yellow>||<reset>
grid_coords:
x: 6
y: 17
z: 0
description: "A potholed stretch of asphalt road that runs past an abandoned farm, rusting machinery sitting in a barren reddish brown field, all plant life dead. An irrigation pond looks crystal clear, as if something has killed all the algae. A white powdery substance seems to line the sides of the pond, giving off a barely perceptible blue glow. It smells earthy here. The road bends off to the northwest"
exits:
- direction: northwest
- direction: south
- zone: northern_radfields
code: northrad_p5
name: Northern Radfields - The Bend Community Hall
short: <yellow>||<reset>
grid_coords:
x: 5
y: 16
z: 0
description: "A gravel-covered stretch of road that runs past an collapsing and overgrown community centre, identified by a faded and bent but still standing sign as \"The Bend Community Centre\". It features tennis courts covered in fallout dust, and a hall with a collapsed roof"
exits:
- direction: north
- direction: southeast
- zone: northern_radfields
code: northrad_o5
name: Northern Radfields - Gorge Southbank
short: <yellow>||<reset>
grid_coords:
x: 5
y: 15
z: 0
description: "A partly washed-out stretch of gravel road that leads up to a gorge with steep rocky sides, with a sheer drop and slowly flowing water at the bottom. Posts and bent metal suggest a bridge was once here, but it is now gone - perhaps under the water! If you want to get across, evidently you'll have to climb down and swim"
exits:
- direction: north
exit_climb:
height: -10
difficulty: 10
- direction: south
- zone: northern_radfields
code: northrad_n5
name: Northern Radfields - Gorge River
short: <bgwhite><blue>~~<reset>
grid_coords:
x: 5
y: 14
z: 0
description: "A river of slowly moving water at the bottom of a gorge. The water is icy cold, and seems quite deep, and the cliffs on either side are high"
material_type: !WaterSurface
exits:
- direction: down
- direction: south
exit_climb:
height: 10
difficulty: 8
- zone: northern_radfields
code: northrad_n5_deep
name: Northern Radfields - Beneath the gorge River
short: <bgwhite><blue>~~<reset>
grid_coords:
x: 5
y: 14
z: -1
description: "Beneath the cold deep water you can see the rocky bottom of the gorge. You notice parts of a broken bridge lying on the river bed. An occasional silvery fish swims past"
material_type: !Underwater
exits:
- direction: up

View File

@ -6,5 +6,5 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = { version = "1.0.195", features = ["derive", "serde_derive"] }
uuid = { version = "1.6.1", features = ["serde"] }
serde = { version = "1.0.197", features = ["derive", "serde_derive"] }
uuid = { version = "1.7.0", features = ["serde"] }

View File

@ -8,16 +8,16 @@ edition = "2021"
[dependencies]
blastmud_interfaces = { path = "../blastmud_interfaces" }
futures = "0.3.30"
log = "0.4.20"
log = "0.4.21"
nix = "0.27.1"
once_cell = "1.19.0"
rand = "0.8.5"
serde = { version = "1.0.195", features = ["derive", "serde_derive"] }
serde_yaml = "0.9.30"
serde = { version = "1.0.197", features = ["derive", "serde_derive"] }
serde_yaml = "0.9.32"
simple_logger = "4.3.3"
tokio = { version = "1.35.1", features = ["signal", "net", "macros", "rt-multi-thread", "rt", "tokio-macros", "time", "sync", "io-util"] }
tokio = { version = "1.36.0", features = ["signal", "net", "macros", "rt-multi-thread", "rt", "tokio-macros", "time", "sync", "io-util"] }
tokio-serde = { version = "0.8.0", features = ["cbor", "serde", "serde_cbor"] }
tokio-stream = "0.1.14"
tokio-util = { version = "0.7.10", features = ["codec"] }
uuid = { version = "1.6.1", features = ["rng", "serde", "v4"] }
uuid = { version = "1.7.0", features = ["rng", "serde", "v4"] }
warp = "0.3.6"