This commit is contained in:
Joshua Barretto 2023-01-01 16:59:12 +00:00
parent 558b5f7c3a
commit acecc62d40
7 changed files with 68 additions and 45 deletions

View File

@ -1,3 +1,4 @@
use crate::rule::npc_ai;
pub use common::rtsim::{NpcId, Profession};
use common::{
comp,
@ -12,14 +13,16 @@ use slotmap::HopSlotMap;
use std::{
any::{Any, TypeId},
collections::VecDeque,
ops::{ControlFlow, Deref, DerefMut, Generator, GeneratorState},
sync::{Arc, atomic::{AtomicPtr, Ordering}},
pin::Pin,
marker::PhantomData,
ops::{ControlFlow, Deref, DerefMut, Generator, GeneratorState},
pin::Pin,
sync::{
atomic::{AtomicPtr, Ordering},
Arc,
},
};
use vek::*;
use world::{civ::Track, site::Site as WorldSite, util::RandomPerm};
use crate::rule::npc_ai;
#[derive(Copy, Clone, Default)]
pub enum NpcMode {
@ -160,7 +163,7 @@ impl TaskState {
pub unsafe trait Context {
// TODO: Somehow we need to enforce this bound, I think?
// Hence, this trait is unsafe for now.
type Ty<'a>;// where for<'a> Self::Ty<'a>: 'a;
type Ty<'a>; // where for<'a> Self::Ty<'a>: 'a;
}
pub struct Data<C: Context>(Arc<AtomicPtr<()>>, PhantomData<C>);
@ -196,12 +199,7 @@ pub struct TaskBox<C: Context, A = ()> {
}
impl<C: Context, A> TaskBox<C, A> {
pub fn new(data: Data<C>) -> Self {
Self {
task: None,
data,
}
}
pub fn new(data: Data<C>) -> Self { Self { task: None, data } }
#[must_use]
pub fn finish(&mut self, prio: Priority) -> ControlFlow<A> {
@ -225,7 +223,12 @@ impl<C: Context, A> TaskBox<C, A> {
task: T,
) -> ControlFlow<A> {
let ty = TypeId::of::<T>();
if self.task.as_mut().filter(|(ty1, _, _)| *ty1 == ty).is_none() {
if self
.task
.as_mut()
.filter(|(ty1, _, _)| *ty1 == ty)
.is_none()
{
self.task = Some((ty, Box::new(task), prio));
};
@ -239,18 +242,19 @@ pub struct Brain<C: Context, A = ()> {
}
impl<C: Context, A> Brain<C, A> {
pub fn new<T: Generator<Data<C>, Yield = A, Return = !> + Unpin + Any + Send + Sync>(task: T) -> Self {
pub fn new<T: Generator<Data<C>, Yield = A, Return = !> + Unpin + Any + Send + Sync>(
task: T,
) -> Self {
Self {
task: Box::new(task),
data: Data(Arc::new(AtomicPtr::new(std::ptr::null_mut())), PhantomData),
}
}
pub fn tick(
&mut self,
ctx_ref: &mut C::Ty<'_>,
) -> A {
self.data.0.store(ctx_ref as *mut C::Ty<'_> as *mut (), Ordering::SeqCst);
pub fn tick(&mut self, ctx_ref: &mut C::Ty<'_>) -> A {
self.data
.0
.store(ctx_ref as *mut C::Ty<'_> as *mut (), Ordering::SeqCst);
match Pin::new(&mut self.task).resume(self.data.clone()) {
GeneratorState::Yielded(action) => {
self.data.0.store(std::ptr::null_mut(), Ordering::Release);

View File

@ -2,7 +2,10 @@ use std::{collections::VecDeque, hash::BuildHasherDefault};
use crate::{
data::{
npc::{Controller, Npc, NpcId, PathData, PathingMemory, Task, TaskState, CONTINUE, FINISH, TaskBox, Brain, Data, Context},
npc::{
Brain, Context, Controller, Data, Npc, NpcId, PathData, PathingMemory, Task, TaskBox,
TaskState, CONTINUE, FINISH,
},
Sites,
},
event::OnTick,
@ -59,7 +62,7 @@ fn path_in_site(start: Vec2<i32>, end: Vec2<i32>, site: &site2::Site) -> PathRes
TileKind::Empty => 3.0,
TileKind::Hazard(_) => 50.0,
TileKind::Field => 8.0,
TileKind::Plaza | TileKind::Road { .. } => 1.0,
TileKind::Plaza | TileKind::Road { .. } | TileKind::Path => 1.0,
TileKind::Building
| TileKind::Castle
@ -640,7 +643,8 @@ TravelTo {
}
*/
trait IsTask = core::ops::Generator<Data<NpcData<'static>>, Yield = (), Return = ()> + Any + Send + Sync;
trait IsTask =
core::ops::Generator<Data<NpcData<'static>>, Yield = (), Return = ()> + Any + Send + Sync;
pub struct NpcData<'a> {
ctx: &'a EventCtx<'a, NpcAi, OnTick>,
@ -689,7 +693,13 @@ pub fn brain() -> Brain<NpcData<'static>> {
PathResult::Path(path) => path,
_ => return None,
};
println!("CHOSE PATH, len = {}, start = {:?}, end = {:?}\nnpc = {:?}", path.len(), start, end, d.npc_id);
println!(
"CHOSE PATH, len = {}, start = {:?}, end = {:?}\nnpc = {:?}",
path.len(),
start,
end,
d.npc_id
);
Some((current_site.world_site?, path))
});
@ -711,7 +721,8 @@ fn walk_path(site: Id<WorldSite>, path: Path<Vec2<i32>>) -> impl IsTask {
move |mut data: Data<NpcData>| {
for tile in path {
println!("TILE");
let wpos = data.with(|d| match &d.ctx.index.sites.get(site).kind {
let wpos = data.with(|d| {
match &d.ctx.index.sites.get(site).kind {
SiteKind::Refactor(site2)
| SiteKind::CliffTown(site2)
| SiteKind::DesertCity(site2) => Some(site2),
@ -720,17 +731,27 @@ fn walk_path(site: Id<WorldSite>, path: Path<Vec2<i32>>) -> impl IsTask {
.expect("intrasite path should only be started on a site2 site")
.tile_center_wpos(tile)
.as_()
+ 0.5);
+ 0.5
});
println!("Walking to next tile... tile wpos = {:?} npc wpos = {:?}", wpos, data.with(|d| d.npc.wpos));
println!(
"Walking to next tile... tile wpos = {:?} npc wpos = {:?}",
wpos,
data.with(|d| d.npc.wpos)
);
while data.with(|d| d.npc.wpos.xy().distance_squared(wpos) > 2.0) {
data.with(|d| d.controller.goto = Some((
wpos.with_z(d.ctx.world
data.with(|d| {
d.controller.goto = Some((
wpos.with_z(
d.ctx
.world
.sim()
.get_alt_approx(wpos.map(|e| e as i32))
.unwrap_or(0.0)),
.unwrap_or(0.0),
),
1.0,
)));
))
});
yield ();
}
}

View File

@ -1,4 +1,3 @@
use common::rtsim::RtSimEntity;
use common::{
comp::{
agent::{
@ -10,6 +9,7 @@ use common::{
},
event::{Emitter, ServerEvent},
path::TraversalConfig,
rtsim::RtSimEntity,
};
use rand::{prelude::ThreadRng, thread_rng, Rng};
use specs::{

View File

@ -15,9 +15,7 @@ use common::{
use rand::{thread_rng, Rng};
use specs::saveload::Marker;
use crate::{
sys::agent::util::get_entity_by_id,
};
use crate::sys::agent::util::get_entity_by_id;
use super::{BehaviorData, BehaviorTree};

View File

@ -636,7 +636,7 @@ impl Scene {
Vec3::unit_z() * (up * viewpoint_scale - tilt.min(0.0).sin() * dist * 0.6)
} else {
self.figure_mgr
.viewpoint_offset(scene_data, scene_data.viewpoint_entity) * viewpoint_scale
.viewpoint_offset(scene_data, scene_data.viewpoint_entity)
};
match self.camera.get_mode() {