mirror of
https://github.com/italicsjenga/valence.git
synced 2024-12-23 22:41:30 +11:00
Allow pausing and clearing the conway example
This commit is contained in:
parent
79399c153e
commit
6e0a7e0a88
|
@ -29,6 +29,7 @@ pub fn main() -> ShutdownResult {
|
||||||
},
|
},
|
||||||
ServerState {
|
ServerState {
|
||||||
player_list: None,
|
player_list: None,
|
||||||
|
paused: false,
|
||||||
board: vec![false; SIZE_X * SIZE_Z].into_boxed_slice(),
|
board: vec![false; SIZE_X * SIZE_Z].into_boxed_slice(),
|
||||||
board_buf: vec![false; SIZE_X * SIZE_Z].into_boxed_slice(),
|
board_buf: vec![false; SIZE_X * SIZE_Z].into_boxed_slice(),
|
||||||
},
|
},
|
||||||
|
@ -41,10 +42,17 @@ struct Game {
|
||||||
|
|
||||||
struct ServerState {
|
struct ServerState {
|
||||||
player_list: Option<PlayerListId>,
|
player_list: Option<PlayerListId>,
|
||||||
|
paused: bool,
|
||||||
board: Box<[bool]>,
|
board: Box<[bool]>,
|
||||||
board_buf: Box<[bool]>,
|
board_buf: Box<[bool]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct ClientState {
|
||||||
|
entity_id: EntityId,
|
||||||
|
sneaking: bool,
|
||||||
|
}
|
||||||
|
|
||||||
const MAX_PLAYERS: usize = 10;
|
const MAX_PLAYERS: usize = 10;
|
||||||
|
|
||||||
const SIZE_X: usize = 100;
|
const SIZE_X: usize = 100;
|
||||||
|
@ -54,7 +62,7 @@ const BOARD_Y: i32 = 50;
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Config for Game {
|
impl Config for Game {
|
||||||
type ServerState = ServerState;
|
type ServerState = ServerState;
|
||||||
type ClientState = EntityId;
|
type ClientState = ClientState;
|
||||||
type EntityState = ();
|
type EntityState = ();
|
||||||
type WorldState = ();
|
type WorldState = ();
|
||||||
type ChunkState = ();
|
type ChunkState = ();
|
||||||
|
@ -114,6 +122,8 @@ impl Config for Game {
|
||||||
SIZE_Z as f64 / 2.0,
|
SIZE_Z as f64 / 2.0,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
server.state.paused = false;
|
||||||
|
|
||||||
server.clients.retain(|_, client| {
|
server.clients.retain(|_, client| {
|
||||||
if client.created_this_tick() {
|
if client.created_this_tick() {
|
||||||
if self
|
if self
|
||||||
|
@ -131,7 +141,7 @@ impl Config for Game {
|
||||||
.entities
|
.entities
|
||||||
.insert_with_uuid(EntityKind::Player, client.uuid(), ())
|
.insert_with_uuid(EntityKind::Player, client.uuid(), ())
|
||||||
{
|
{
|
||||||
Some((id, _)) => client.state = id,
|
Some((id, _)) => client.state.entity_id = id,
|
||||||
None => {
|
None => {
|
||||||
client.disconnect("Conflicting UUID");
|
client.disconnect("Conflicting UUID");
|
||||||
return false;
|
return false;
|
||||||
|
@ -155,73 +165,87 @@ impl Config for Game {
|
||||||
}
|
}
|
||||||
|
|
||||||
client.send_message("Welcome to Conway's game of life in Minecraft!".italic());
|
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());
|
client.send_message(
|
||||||
|
"Sneak and hold the left mouse button to bring blocks to life.".italic(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if client.is_disconnected() {
|
if client.is_disconnected() {
|
||||||
self.player_count.fetch_sub(1, Ordering::SeqCst);
|
self.player_count.fetch_sub(1, Ordering::SeqCst);
|
||||||
server.entities.remove(client.state);
|
server.entities.remove(client.state.entity_id);
|
||||||
if let Some(id) = &server.state.player_list {
|
if let Some(id) = &server.state.player_list {
|
||||||
server.player_lists.get_mut(id).remove(client.uuid());
|
server.player_lists.get_mut(id).remove(client.uuid());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let player = server.entities.get_mut(client.state).unwrap();
|
let player = server.entities.get_mut(client.state.entity_id).unwrap();
|
||||||
|
|
||||||
if client.position().y <= 0.0 {
|
if client.position().y <= 0.0 {
|
||||||
client.teleport(spawn_pos, client.yaw(), client.pitch());
|
client.teleport(spawn_pos, client.yaw(), client.pitch());
|
||||||
|
server.state.board.fill(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
while let Some(event) = client_event_boilerplate(client, player) {
|
while let Some(event) = client_event_boilerplate(client, player) {
|
||||||
if let ClientEvent::Digging { position, .. } = event {
|
match event {
|
||||||
if (0..SIZE_X as i32).contains(&position.x)
|
ClientEvent::Digging { position, .. } => {
|
||||||
&& (0..SIZE_Z as i32).contains(&position.z)
|
if (0..SIZE_X as i32).contains(&position.x)
|
||||||
&& position.y == BOARD_Y
|
&& (0..SIZE_Z as i32).contains(&position.z)
|
||||||
{
|
&& position.y == BOARD_Y
|
||||||
server.state.board[position.x as usize + position.z as usize * SIZE_X] =
|
{
|
||||||
true;
|
server.state.board
|
||||||
|
[position.x as usize + position.z as usize * SIZE_X] = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
ClientEvent::StartSneaking => {
|
||||||
|
client.state.sneaking = true;
|
||||||
|
}
|
||||||
|
ClientEvent::StopSneaking => {
|
||||||
|
client.state.sneaking = false;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if client.state.sneaking {
|
||||||
|
server.state.paused = true;
|
||||||
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
});
|
});
|
||||||
|
|
||||||
if server.shared.current_tick() % 4 != 0 {
|
if !server.state.paused {
|
||||||
return;
|
server
|
||||||
}
|
.state
|
||||||
|
.board_buf
|
||||||
|
.par_iter_mut()
|
||||||
|
.enumerate()
|
||||||
|
.for_each(|(i, cell)| {
|
||||||
|
let cx = (i % SIZE_X) as i32;
|
||||||
|
let cz = (i / SIZE_Z) as i32;
|
||||||
|
|
||||||
server
|
let mut live_count = 0;
|
||||||
.state
|
for z in cz - 1..=cz + 1 {
|
||||||
.board_buf
|
for x in cx - 1..=cx + 1 {
|
||||||
.par_iter_mut()
|
if !(x == cx && z == cz) {
|
||||||
.enumerate()
|
let i = x.rem_euclid(SIZE_X as i32) as usize
|
||||||
.for_each(|(i, cell)| {
|
+ z.rem_euclid(SIZE_Z as i32) as usize * SIZE_X;
|
||||||
let cx = (i % SIZE_X) as i32;
|
if server.state.board[i] {
|
||||||
let cz = (i / SIZE_Z) as i32;
|
live_count += 1;
|
||||||
|
}
|
||||||
let mut live_count = 0;
|
|
||||||
for z in cz - 1..=cz + 1 {
|
|
||||||
for x in cx - 1..=cx + 1 {
|
|
||||||
if !(x == cx && z == cz) {
|
|
||||||
let i = x.rem_euclid(SIZE_X as i32) as usize
|
|
||||||
+ z.rem_euclid(SIZE_Z as i32) as usize * SIZE_X;
|
|
||||||
if server.state.board[i] {
|
|
||||||
live_count += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if server.state.board[cx as usize + cz as usize * SIZE_X] {
|
if server.state.board[cx as usize + cz as usize * SIZE_X] {
|
||||||
*cell = (2..=3).contains(&live_count);
|
*cell = (2..=3).contains(&live_count);
|
||||||
} else {
|
} else {
|
||||||
*cell = live_count == 3;
|
*cell = live_count == 3;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mem::swap(&mut server.state.board, &mut server.state.board_buf);
|
mem::swap(&mut server.state.board, &mut server.state.board_buf);
|
||||||
|
}
|
||||||
|
|
||||||
let min_y = server.shared.dimensions().next().unwrap().1.min_y;
|
let min_y = server.shared.dimensions().next().unwrap().1.min_y;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue