Spawn player entities in the conway example

This commit is contained in:
Ryan 2022-07-03 20:31:20 -07:00
parent a6bb67ecfe
commit fb09ab7f8c
5 changed files with 54 additions and 34 deletions

View file

@ -1,3 +1,4 @@
use std::collections::HashMap;
use std::mem;
use std::net::SocketAddr;
use std::sync::atomic::{AtomicUsize, Ordering};
@ -6,12 +7,12 @@ use std::sync::Mutex;
use log::LevelFilter;
use num::Integer;
use rayon::iter::{IndexedParallelIterator, IntoParallelRefMutIterator, ParallelIterator};
use valence::client::{Event, GameMode};
use valence::client::{ClientId, Event, GameMode};
use valence::config::{Config, ServerListPing};
use valence::text::Color;
use valence::{
async_trait, ident, Biome, BlockState, Dimension, DimensionId, Server, SharedServer,
ShutdownResult, TextFormat,
async_trait, ident, Biome, BlockState, Dimension, DimensionId, EntityId, EntityType, Server,
SharedServer, ShutdownResult, TextFormat,
};
pub fn main() -> ShutdownResult {
@ -23,6 +24,7 @@ pub fn main() -> ShutdownResult {
valence::start_server(Game {
player_count: AtomicUsize::new(0),
state: Mutex::new(State {
player_entities: HashMap::new(),
board: vec![false; SIZE_X * SIZE_Z].into_boxed_slice(),
board_buf: vec![false; SIZE_X * SIZE_Z].into_boxed_slice(),
}),
@ -35,6 +37,7 @@ struct Game {
}
struct State {
player_entities: HashMap<ClientId, EntityId>,
board: Box<[bool]>,
board_buf: Box<[bool]>,
}
@ -105,8 +108,20 @@ impl Config for Game {
SIZE_Z as f64 / 2.0,
];
server.clients.retain(|_, client| {
let State {
player_entities,
board,
board_buf,
} = &mut *self.state.lock().unwrap();
server.clients.retain(|client_id, client| {
if client.created_tick() == server.shared.current_tick() {
if client.is_disconnected() {
self.player_count.fetch_sub(1, Ordering::SeqCst);
player_entities.remove(&client_id);
return false;
}
if self
.player_count
.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |count| {
@ -131,21 +146,27 @@ impl Config for Game {
None,
);
player_entities.insert(
client_id,
server
.entities
.create_with_uuid(client.uuid(), EntityType::Player)
.unwrap()
.0,
);
client.send_message("Welcome to Conway's game of life in Minecraft!".italic());
client.send_message("Hold the left mouse button to bring blocks to life.".italic());
}
if client.is_disconnected() {
self.player_count.fetch_sub(1, Ordering::SeqCst);
false
} else {
true
}
true
});
let State { board, board_buf } = &mut *self.state.lock().unwrap();
for (_, client) in server.clients.iter_mut() {
for (client_id, client) in server.clients.iter_mut() {
let player = server
.entities
.get_mut(player_entities[&client_id])
.unwrap();
while let Some(event) = client.pop_event() {
match event {
Event::Digging(e) => {
@ -158,10 +179,17 @@ impl Config for Game {
board[pos.x as usize + pos.z as usize * SIZE_X] = true;
}
}
Event::Movement { position, .. } => {
if position.y <= 0.0 {
Event::Movement { .. } => {
if client.position().y <= 0.0 {
client.teleport(spawn_pos, client.yaw(), client.pitch());
}
player.set_world(client.world());
player.set_position(client.position());
player.set_yaw(client.yaw());
player.set_head_yaw(client.yaw());
player.set_pitch(client.pitch());
player.set_on_ground(client.on_ground());
}
_ => {}
}

View file

@ -70,9 +70,8 @@ impl Config for Game {
}
self.cows.lock().unwrap().extend((0..200).map(|_| {
let (id, e) = server.entities.create();
let (id, e) = server.entities.create(EntityType::Cow);
e.set_world(world_id);
e.set_type(EntityType::Cow);
id
}));
}

View file

@ -565,7 +565,7 @@ impl Client {
C2sPlayPacket::SetJigsawBlock(_) => {}
C2sPlayPacket::SetStructureBlock(_) => {}
C2sPlayPacket::SignUpdate(_) => {}
C2sPlayPacket::Swing(_) => {}
C2sPlayPacket::Swing(p) => self.events.push_back(Event::ArmSwing(p.hand)),
C2sPlayPacket::TeleportToEntity(_) => {}
C2sPlayPacket::UseItemOn(_) => {}
C2sPlayPacket::UseItem(_) => {}

View file

@ -24,6 +24,7 @@ pub enum Event {
pitch: f32,
on_ground: bool,
},
ArmSwing(Hand),
InteractWithEntity {
/// The ID of the entity being interacted with.
id: EntityId,

View file

@ -37,11 +37,8 @@ impl Entities {
/// Spawns a new entity with the default data. The new entity's [`EntityId`]
/// is returned.
///
/// To actually see the new entity, set its position to somewhere nearby and
/// [set its type](EntityData::set_type) to something visible.
pub fn create(&mut self) -> (EntityId, &mut Entity) {
self.create_with_uuid(Uuid::from_bytes(rand::random()))
pub fn create(&mut self, typ: EntityType) -> (EntityId, &mut Entity) {
self.create_with_uuid(Uuid::from_bytes(rand::random()), typ)
.expect("UUID collision")
}
@ -50,13 +47,17 @@ impl Entities {
///
/// The provided UUID must not conflict with an existing entity UUID in this
/// world. If it does, `None` is returned and the entity is not spawned.
pub fn create_with_uuid(&mut self, uuid: Uuid) -> Option<(EntityId, &mut Entity)> {
pub fn create_with_uuid(
&mut self,
uuid: Uuid,
typ: EntityType,
) -> Option<(EntityId, &mut Entity)> {
match self.uuid_to_entity.entry(uuid) {
Entry::Occupied(_) => None,
Entry::Vacant(ve) => {
let (k, e) = self.sm.insert(Entity {
flags: EntityFlags(0),
meta: EntityMeta::new(EntityType::Marker),
meta: EntityMeta::new(typ),
world: None,
new_position: Vec3::default(),
old_position: Vec3::default(),
@ -222,15 +223,6 @@ impl Entity {
self.meta.typ()
}
/// Changes the [`EntityType`] of this entity to the provided type.
///
/// All metadata of this entity is reset to the default values.
pub fn set_type(&mut self, typ: EntityType) {
self.meta = EntityMeta::new(typ);
// All metadata is lost so we must mark it as modified unconditionally.
self.flags.set_type_modified(true);
}
pub fn world(&self) -> Option<WorldId> {
self.world
}