mirror of
https://github.com/italicsjenga/valence.git
synced 2024-12-23 14:31:30 +11:00
Spawn player entities in the conway example
This commit is contained in:
parent
a6bb67ecfe
commit
fb09ab7f8c
|
@ -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());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -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(_) => {}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue