mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added /rtsim_purge command
This commit is contained in:
parent
66710d5bc2
commit
64324262c7
@ -310,8 +310,9 @@ pub enum ServerChatCommand {
|
||||
Tell,
|
||||
Time,
|
||||
Tp,
|
||||
TpNpc,
|
||||
NpcInfo,
|
||||
RtsimTp,
|
||||
RtsimInfo,
|
||||
RtsimPurge,
|
||||
RtsimChunk,
|
||||
Unban,
|
||||
Version,
|
||||
@ -682,16 +683,25 @@ impl ServerChatCommand {
|
||||
"Teleport to another player",
|
||||
Some(Moderator),
|
||||
),
|
||||
ServerChatCommand::TpNpc => cmd(
|
||||
ServerChatCommand::RtsimTp => cmd(
|
||||
vec![Integer("npc index", 0, Required)],
|
||||
"Teleport to an rtsim npc",
|
||||
Some(Moderator),
|
||||
),
|
||||
ServerChatCommand::NpcInfo => cmd(
|
||||
ServerChatCommand::RtsimInfo => cmd(
|
||||
vec![Integer("npc index", 0, Required)],
|
||||
"Display information about an rtsim NPC",
|
||||
Some(Moderator),
|
||||
),
|
||||
ServerChatCommand::RtsimPurge => cmd(
|
||||
vec![Boolean(
|
||||
"whether purging of rtsim data should occur on next startup",
|
||||
true.to_string(),
|
||||
Required,
|
||||
)],
|
||||
"Purge rtsim data on next startup",
|
||||
Some(Admin),
|
||||
),
|
||||
ServerChatCommand::RtsimChunk => cmd(
|
||||
vec![],
|
||||
"Display information about the current chunk from rtsim",
|
||||
@ -824,8 +834,9 @@ impl ServerChatCommand {
|
||||
ServerChatCommand::Tell => "tell",
|
||||
ServerChatCommand::Time => "time",
|
||||
ServerChatCommand::Tp => "tp",
|
||||
ServerChatCommand::TpNpc => "tp_npc",
|
||||
ServerChatCommand::NpcInfo => "npc_info",
|
||||
ServerChatCommand::RtsimTp => "rtsim_tp",
|
||||
ServerChatCommand::RtsimInfo => "rtsim_info",
|
||||
ServerChatCommand::RtsimPurge => "rtsim_purge",
|
||||
ServerChatCommand::RtsimChunk => "rtsim_chunk",
|
||||
ServerChatCommand::Unban => "unban",
|
||||
ServerChatCommand::Version => "version",
|
||||
|
@ -3,7 +3,7 @@
|
||||
// `Agent`). When possible, this should be moved to the `rtsim`
|
||||
// module in `server`.
|
||||
|
||||
use rand::{Rng, seq::IteratorRandom};
|
||||
use rand::{seq::IteratorRandom, Rng};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specs::Component;
|
||||
use strum::{EnumIter, IntoEnumIterator};
|
||||
@ -56,7 +56,6 @@ pub enum MemoryItem {
|
||||
Mood { state: MoodState },
|
||||
}
|
||||
|
||||
|
||||
#[derive(EnumIter, Clone, Copy)]
|
||||
pub enum PersonalityTrait {
|
||||
Open,
|
||||
@ -88,7 +87,9 @@ pub struct Personality {
|
||||
|
||||
fn distributed(min: u8, max: u8, rng: &mut impl Rng) -> u8 {
|
||||
let l = max - min;
|
||||
min + rng.gen_range(0..=l / 3) + rng.gen_range(0..=l / 3 + l % 3 % 2) + rng.gen_range(0..=l / 3 + l % 3 / 2)
|
||||
min + rng.gen_range(0..=l / 3)
|
||||
+ rng.gen_range(0..=l / 3 + l % 3 % 2)
|
||||
+ rng.gen_range(0..=l / 3 + l % 3 / 2)
|
||||
}
|
||||
|
||||
impl Personality {
|
||||
@ -96,13 +97,11 @@ impl Personality {
|
||||
pub const LITTLE_HIGH: u8 = Self::MID + (Self::MAX - Self::MIN) / 20;
|
||||
pub const LITTLE_LOW: u8 = Self::MID - (Self::MAX - Self::MIN) / 20;
|
||||
pub const LOW_THRESHOLD: u8 = (Self::MAX - Self::MIN) / 5 * 2 + Self::MIN;
|
||||
const MIN: u8 = 0;
|
||||
pub const MID: u8 = (Self::MAX - Self::MIN) / 2;
|
||||
const MAX: u8 = 255;
|
||||
pub const MID: u8 = (Self::MAX - Self::MIN) / 2;
|
||||
const MIN: u8 = 0;
|
||||
|
||||
fn distributed_value(rng: &mut impl Rng) -> u8 {
|
||||
distributed(Self::MIN, Self::MAX, rng)
|
||||
}
|
||||
fn distributed_value(rng: &mut impl Rng) -> u8 { distributed(Self::MIN, Self::MAX, rng) }
|
||||
|
||||
pub fn random(rng: &mut impl Rng) -> Self {
|
||||
Self {
|
||||
@ -137,20 +136,36 @@ impl Personality {
|
||||
pub fn is(&self, trait_: PersonalityTrait) -> bool {
|
||||
match trait_ {
|
||||
PersonalityTrait::Open => self.openness > Personality::HIGH_THRESHOLD,
|
||||
PersonalityTrait::Adventurous => self.openness > Personality::HIGH_THRESHOLD && self.neuroticism < Personality::MID,
|
||||
PersonalityTrait::Adventurous => {
|
||||
self.openness > Personality::HIGH_THRESHOLD && self.neuroticism < Personality::MID
|
||||
},
|
||||
PersonalityTrait::Closed => self.openness < Personality::LOW_THRESHOLD,
|
||||
PersonalityTrait::Conscientious => self.conscientiousness > Personality::HIGH_THRESHOLD,
|
||||
PersonalityTrait::Busybody => self.agreeableness < Personality::LOW_THRESHOLD,
|
||||
PersonalityTrait::Unconscientious => self.conscientiousness < Personality::LOW_THRESHOLD,
|
||||
PersonalityTrait::Unconscientious => {
|
||||
self.conscientiousness < Personality::LOW_THRESHOLD
|
||||
},
|
||||
PersonalityTrait::Extroverted => self.extraversion > Personality::HIGH_THRESHOLD,
|
||||
PersonalityTrait::Introverted => self.extraversion < Personality::LOW_THRESHOLD,
|
||||
PersonalityTrait::Agreeable => self.agreeableness > Personality::HIGH_THRESHOLD,
|
||||
PersonalityTrait::Sociable => self.agreeableness > Personality::HIGH_THRESHOLD && self.extraversion > Personality::MID,
|
||||
PersonalityTrait::Sociable => {
|
||||
self.agreeableness > Personality::HIGH_THRESHOLD
|
||||
&& self.extraversion > Personality::MID
|
||||
},
|
||||
PersonalityTrait::Disagreeable => self.agreeableness < Personality::LOW_THRESHOLD,
|
||||
PersonalityTrait::Neurotic => self.neuroticism > Personality::HIGH_THRESHOLD,
|
||||
PersonalityTrait::Seeker => self.neuroticism > Personality::HIGH_THRESHOLD && self.openness > Personality::LITTLE_HIGH,
|
||||
PersonalityTrait::Worried => self.neuroticism > Personality::HIGH_THRESHOLD && self.agreeableness > Personality::LITTLE_HIGH,
|
||||
PersonalityTrait::SadLoner => self.neuroticism > Personality::HIGH_THRESHOLD && self.extraversion < Personality::LITTLE_LOW,
|
||||
PersonalityTrait::Seeker => {
|
||||
self.neuroticism > Personality::HIGH_THRESHOLD
|
||||
&& self.openness > Personality::LITTLE_HIGH
|
||||
},
|
||||
PersonalityTrait::Worried => {
|
||||
self.neuroticism > Personality::HIGH_THRESHOLD
|
||||
&& self.agreeableness > Personality::LITTLE_HIGH
|
||||
},
|
||||
PersonalityTrait::SadLoner => {
|
||||
self.neuroticism > Personality::HIGH_THRESHOLD
|
||||
&& self.extraversion < Personality::LITTLE_LOW
|
||||
},
|
||||
PersonalityTrait::Stable => self.neuroticism < Personality::LOW_THRESHOLD,
|
||||
}
|
||||
}
|
||||
@ -160,14 +175,19 @@ impl Personality {
|
||||
}
|
||||
|
||||
pub fn will_ambush(&self) -> bool {
|
||||
self.agreeableness < Self::LOW_THRESHOLD
|
||||
&& self.conscientiousness < Self::LOW_THRESHOLD
|
||||
self.agreeableness < Self::LOW_THRESHOLD && self.conscientiousness < Self::LOW_THRESHOLD
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Personality {
|
||||
fn default() -> Self {
|
||||
Self { openness: Personality::MID, conscientiousness: Personality::MID, extraversion: Personality::MID, agreeableness: Personality::MID, neuroticism: Personality::MID }
|
||||
Self {
|
||||
openness: Personality::MID,
|
||||
conscientiousness: Personality::MID,
|
||||
extraversion: Personality::MID,
|
||||
agreeableness: Personality::MID,
|
||||
neuroticism: Personality::MID,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,8 @@ use crate::{
|
||||
item::{tool::AbilityMap, MaterialStatManifest},
|
||||
ActiveAbilities, Beam, Body, CharacterState, Combo, ControlAction, Controller,
|
||||
ControllerInputs, Density, Energy, Health, InputAttr, InputKind, Inventory,
|
||||
InventoryAction, Mass, Melee, Ori, PhysicsState, Pos, Scale, SkillSet, Stance, StateUpdate, Stats,
|
||||
Vel,
|
||||
InventoryAction, Mass, Melee, Ori, PhysicsState, Pos, Scale, SkillSet, Stance, StateUpdate,
|
||||
Stats, Vel,
|
||||
},
|
||||
link::Is,
|
||||
mounting::Rider,
|
||||
|
@ -9,8 +9,8 @@ use common::{
|
||||
character_state::OutputEvents,
|
||||
inventory::item::{tool::AbilityMap, MaterialStatManifest},
|
||||
ActiveAbilities, Beam, Body, CharacterState, Combo, Controller, Density, Energy, Health,
|
||||
Inventory, InventoryManip, Mass, Melee, Ori, PhysicsState, Poise, Pos, Scale, SkillSet, Stance,
|
||||
StateUpdate, Stats, Vel,
|
||||
Inventory, InventoryManip, Mass, Melee, Ori, PhysicsState, Poise, Pos, Scale, SkillSet,
|
||||
Stance, StateUpdate, Stats, Vel,
|
||||
},
|
||||
event::{EventBus, LocalEvent, ServerEvent},
|
||||
link::Is,
|
||||
|
@ -43,6 +43,8 @@ pub struct Data {
|
||||
pub factions: Factions,
|
||||
|
||||
pub time_of_day: TimeOfDay,
|
||||
// If true, rtsim data will be ignored (and, hence, overwritten on next save) on load.
|
||||
pub should_purge: bool,
|
||||
}
|
||||
|
||||
pub type ReadError = rmp_serde::decode::Error;
|
||||
|
@ -44,6 +44,7 @@ impl Data {
|
||||
},
|
||||
|
||||
time_of_day: TimeOfDay(settings.start_time),
|
||||
should_purge: false,
|
||||
};
|
||||
|
||||
let initial_factions = (0..16)
|
||||
|
@ -184,8 +184,9 @@ fn do_command(
|
||||
ServerChatCommand::Tell => handle_tell,
|
||||
ServerChatCommand::Time => handle_time,
|
||||
ServerChatCommand::Tp => handle_tp,
|
||||
ServerChatCommand::TpNpc => handle_tp_npc,
|
||||
ServerChatCommand::NpcInfo => handle_npc_info,
|
||||
ServerChatCommand::RtsimTp => handle_rtsim_tp,
|
||||
ServerChatCommand::RtsimInfo => handle_rtsim_info,
|
||||
ServerChatCommand::RtsimPurge => handle_rtsim_purge,
|
||||
ServerChatCommand::RtsimChunk => handle_rtsim_chunk,
|
||||
ServerChatCommand::Unban => handle_unban,
|
||||
ServerChatCommand::Version => handle_version,
|
||||
@ -1185,7 +1186,7 @@ fn handle_tp(
|
||||
})
|
||||
}
|
||||
|
||||
fn handle_tp_npc(
|
||||
fn handle_rtsim_tp(
|
||||
server: &mut Server,
|
||||
_client: EcsEntity,
|
||||
target: EcsEntity,
|
||||
@ -1214,7 +1215,7 @@ fn handle_tp_npc(
|
||||
})
|
||||
}
|
||||
|
||||
fn handle_npc_info(
|
||||
fn handle_rtsim_info(
|
||||
server: &mut Server,
|
||||
client: EcsEntity,
|
||||
target: EcsEntity,
|
||||
@ -1263,6 +1264,36 @@ fn handle_npc_info(
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_rtsim_purge(
|
||||
server: &mut Server,
|
||||
client: EcsEntity,
|
||||
target: EcsEntity,
|
||||
args: Vec<String>,
|
||||
action: &ServerChatCommand,
|
||||
) -> CmdResult<()> {
|
||||
use crate::rtsim2::RtSim;
|
||||
if let Some(should_purge) = parse_cmd_args!(args, bool) {
|
||||
server
|
||||
.state
|
||||
.ecs()
|
||||
.write_resource::<RtSim>()
|
||||
.set_should_purge(should_purge);
|
||||
server.notify_client(
|
||||
client,
|
||||
ServerGeneral::server_msg(
|
||||
ChatType::CommandInfo,
|
||||
format!(
|
||||
"Rtsim data {} be purged on next startup",
|
||||
if should_purge { "WILL" } else { "will NOT" },
|
||||
),
|
||||
),
|
||||
);
|
||||
Ok(())
|
||||
} else {
|
||||
return Err(action.help_string());
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_rtsim_chunk(
|
||||
server: &mut Server,
|
||||
client: EcsEntity,
|
||||
|
@ -80,8 +80,8 @@ use common::{
|
||||
comp,
|
||||
event::{EventBus, ServerEvent},
|
||||
resources::{BattleMode, GameMode, Time, TimeOfDay},
|
||||
shared_server_config::ServerConstants,
|
||||
rtsim::{RtSimEntity, RtSimVehicle},
|
||||
shared_server_config::ServerConstants,
|
||||
slowjob::SlowJobPool,
|
||||
terrain::{Block, TerrainChunk, TerrainChunkSize},
|
||||
vol::RectRasterableVol,
|
||||
@ -1463,6 +1463,15 @@ impl Drop for Server {
|
||||
info!("Unloading terrain persistence...");
|
||||
terrain_persistence.unload_all()
|
||||
});
|
||||
|
||||
#[cfg(feature = "worldgen")]
|
||||
{
|
||||
info!("Saving rtsim state...");
|
||||
self.state
|
||||
.ecs()
|
||||
.write_resource::<rtsim2::RtSim>()
|
||||
.save(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,14 @@ impl RtSim {
|
||||
match Data::from_reader(io::BufReader::new(file)) {
|
||||
Ok(data) => {
|
||||
info!("Rtsim data loaded.");
|
||||
if data.should_purge {
|
||||
warn!(
|
||||
"The should_purge flag was set on the rtsim data, \
|
||||
generating afresh"
|
||||
);
|
||||
} else {
|
||||
break 'load data;
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Rtsim data failed to load: {}", e);
|
||||
@ -171,14 +178,14 @@ impl RtSim {
|
||||
self.state.data_mut().npcs.remove(entity.0);
|
||||
}
|
||||
|
||||
pub fn save(&mut self, slowjob_pool: &SlowJobPool) {
|
||||
pub fn save(&mut self, /* slowjob_pool: &SlowJobPool, */ wait_until_finished: bool) {
|
||||
info!("Saving rtsim data...");
|
||||
let file_path = self.file_path.clone();
|
||||
let data = self.state.data().clone();
|
||||
debug!("Starting rtsim data save job...");
|
||||
// TODO: Use slow job
|
||||
// slowjob_pool.spawn("RTSIM_SAVE", move || {
|
||||
std::thread::spawn(move || {
|
||||
let handle = std::thread::spawn(move || {
|
||||
let tmp_file_name = "data_tmp.dat";
|
||||
if let Err(e) = file_path
|
||||
.parent()
|
||||
@ -203,6 +210,11 @@ impl RtSim {
|
||||
error!("Saving rtsim data failed: {}", e);
|
||||
}
|
||||
});
|
||||
|
||||
if wait_until_finished {
|
||||
handle.join();
|
||||
}
|
||||
|
||||
self.last_saved = Some(Instant::now());
|
||||
}
|
||||
|
||||
@ -212,6 +224,10 @@ impl RtSim {
|
||||
}
|
||||
|
||||
pub fn state(&self) -> &RtState { &self.state }
|
||||
|
||||
pub fn set_should_purge(&mut self, should_purge: bool) {
|
||||
self.state.data_mut().should_purge = should_purge;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ChunkStates(pub Grid<Option<LoadedChunkState>>);
|
||||
|
@ -223,7 +223,9 @@ impl<'a> System<'a> for Sys {
|
||||
.last_saved
|
||||
.map_or(true, |ls| ls.elapsed() > Duration::from_secs(60))
|
||||
{
|
||||
rtsim.save(&slow_jobs);
|
||||
// TODO: Use slow jobs
|
||||
let _ = slow_jobs;
|
||||
rtsim.save(/* &slow_jobs, */ false);
|
||||
}
|
||||
|
||||
let chunk_states = rtsim.state.resource::<ChunkStates>();
|
||||
|
@ -741,12 +741,7 @@ fn do_combat(bdata: &mut BehaviorData) -> bool {
|
||||
read_data.time.0 - selected_at > RETARGETING_THRESHOLD_SECONDS;
|
||||
|
||||
if !in_aggro_range && is_time_to_retarget {
|
||||
agent_data.choose_target(
|
||||
agent,
|
||||
controller,
|
||||
read_data,
|
||||
event_emitter,
|
||||
);
|
||||
agent_data.choose_target(agent, controller, read_data, event_emitter);
|
||||
}
|
||||
|
||||
if aggro_on {
|
||||
|
@ -9,7 +9,7 @@ use common::{
|
||||
BehaviorState, ControlAction, Item, TradingBehavior, UnresolvedChatMsg, UtteranceKind,
|
||||
},
|
||||
event::ServerEvent,
|
||||
rtsim::{Memory, MemoryItem, RtSimEvent, PersonalityTrait},
|
||||
rtsim::{Memory, MemoryItem, PersonalityTrait, RtSimEvent},
|
||||
trade::{TradeAction, TradePhase, TradeResult},
|
||||
};
|
||||
use rand::{thread_rng, Rng};
|
||||
@ -106,47 +106,46 @@ pub fn handle_inbox_talk(bdata: &mut BehaviorData) -> bool {
|
||||
match subject {
|
||||
Subject::Regular => {
|
||||
if let Some(tgt_stats) = read_data.stats.get(target) {
|
||||
agent.rtsim_controller.events.push(RtSimEvent::AddMemory(
|
||||
Memory {
|
||||
agent
|
||||
.rtsim_controller
|
||||
.events
|
||||
.push(RtSimEvent::AddMemory(Memory {
|
||||
item: MemoryItem::CharacterInteraction {
|
||||
name: tgt_stats.name.clone(),
|
||||
},
|
||||
time_to_forget: read_data.time.0 + 600.0,
|
||||
},
|
||||
));
|
||||
}));
|
||||
if let Some(destination_name) = &agent.rtsim_controller.heading_to {
|
||||
let personality = &agent.rtsim_controller.personality;
|
||||
let standard_response_msg = || -> String {
|
||||
if personality.will_ambush() {
|
||||
format!(
|
||||
"I'm heading to {}! Want to come along? We'll make \
|
||||
great travel buddies, hehe.",
|
||||
"I'm heading to {}! Want to come along? We'll \
|
||||
make great travel buddies, hehe.",
|
||||
destination_name
|
||||
)
|
||||
} else if personality.is(PersonalityTrait::Extroverted)
|
||||
{
|
||||
} else if personality.is(PersonalityTrait::Extroverted) {
|
||||
format!(
|
||||
"I'm heading to {}! Want to come along?",
|
||||
destination_name
|
||||
)
|
||||
} else if personality.is(PersonalityTrait::Disagreeable)
|
||||
{
|
||||
} else if personality.is(PersonalityTrait::Disagreeable) {
|
||||
"Hrm.".to_string()
|
||||
} else {
|
||||
"Hello!".to_string()
|
||||
}
|
||||
};
|
||||
let msg = if false /* TODO: Remembers character */ {
|
||||
let msg = if false
|
||||
/* TODO: Remembers character */
|
||||
{
|
||||
if personality.will_ambush() {
|
||||
"Just follow me a bit more, hehe.".to_string()
|
||||
} else if personality.is(PersonalityTrait::Extroverted)
|
||||
{
|
||||
if personality.is(PersonalityTrait::Extroverted)
|
||||
{
|
||||
} else if personality.is(PersonalityTrait::Extroverted) {
|
||||
if personality.is(PersonalityTrait::Extroverted) {
|
||||
format!(
|
||||
"Greetings fair {}! It has been far \
|
||||
too long since last I saw you. I'm \
|
||||
going to {} right now.",
|
||||
"Greetings fair {}! It has been far too long \
|
||||
since last I saw you. I'm going to {} right \
|
||||
now.",
|
||||
&tgt_stats.name, destination_name
|
||||
)
|
||||
} else if personality.is(PersonalityTrait::Disagreeable)
|
||||
@ -154,8 +153,8 @@ pub fn handle_inbox_talk(bdata: &mut BehaviorData) -> bool {
|
||||
"Oh. It's you again.".to_string()
|
||||
} else {
|
||||
format!(
|
||||
"Hi again {}! Unfortunately I'm in a \
|
||||
hurry right now. See you!",
|
||||
"Hi again {}! Unfortunately I'm in a hurry \
|
||||
right now. See you!",
|
||||
&tgt_stats.name
|
||||
)
|
||||
}
|
||||
@ -183,14 +182,14 @@ pub fn handle_inbox_talk(bdata: &mut BehaviorData) -> bool {
|
||||
};
|
||||
agent_data.chat_npc(msg, event_emitter);
|
||||
}
|
||||
}*/ else {
|
||||
}*/
|
||||
else {
|
||||
let mut rng = thread_rng();
|
||||
if let Some(extreme_trait) = agent.rtsim_controller.personality.chat_trait(&mut rng)
|
||||
if let Some(extreme_trait) =
|
||||
agent.rtsim_controller.personality.chat_trait(&mut rng)
|
||||
{
|
||||
let msg = match extreme_trait {
|
||||
PersonalityTrait::Open => {
|
||||
"npc-speech-villager_open"
|
||||
},
|
||||
PersonalityTrait::Open => "npc-speech-villager_open",
|
||||
PersonalityTrait::Adventurous => {
|
||||
"npc-speech-villager_adventurous"
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user