You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
3.5 KiB
132 lines
3.5 KiB
mod chat;
|
|
mod chests;
|
|
mod commands;
|
|
mod player;
|
|
mod special;
|
|
mod world;
|
|
|
|
use std::net::SocketAddr;
|
|
|
|
use std::sync::atomic::AtomicI32;
|
|
use std::sync::atomic::Ordering;
|
|
|
|
use valence::client::default_event_handler;
|
|
use valence::entity::player::PlayerEntityBundle;
|
|
use valence::packet::WritePacket;
|
|
use valence::prelude::*;
|
|
|
|
use valence_protocol::packet::s2c::play::ChunkRenderDistanceCenterS2c;
|
|
use valence_protocol::var_int::VarInt;
|
|
use valence_protocol::Encode;
|
|
|
|
const STATIC_SPAWN_POS: DVec3 = DVec3::new(-221.0, 64.0, 299.0);
|
|
static PLAYER_COUNT: AtomicI32 = AtomicI32::new(0);
|
|
|
|
struct MyCallbacks;
|
|
|
|
#[async_trait]
|
|
impl AsyncCallbacks for MyCallbacks {
|
|
async fn server_list_ping(
|
|
&self,
|
|
_shared: &SharedServer,
|
|
_remote_addr: SocketAddr,
|
|
_protocol_version: i32,
|
|
) -> ServerListPing {
|
|
ServerListPing::Respond {
|
|
online_players: PLAYER_COUNT.load(Ordering::Relaxed),
|
|
max_players: 69420,
|
|
player_sample: vec![],
|
|
description: "Crazy! Insane! Et cetera!".into(),
|
|
favicon_png: include_bytes!("../assets/icon.png"),
|
|
}
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
tracing_subscriber::fmt::init();
|
|
|
|
let server = ServerPlugin::new(MyCallbacks);
|
|
|
|
App::new()
|
|
.add_plugin(server)
|
|
.add_startup_system(world::setup)
|
|
.add_systems(
|
|
(
|
|
default_event_handler,
|
|
//special::tnt,
|
|
chat::chat_handler,
|
|
chests::open_chests,
|
|
commands::command_executor,
|
|
commands::command_suggestor,
|
|
player::fall_damage,
|
|
player::death,
|
|
)
|
|
.in_schedule(EventLoopSchedule),
|
|
)
|
|
.add_systems((
|
|
init_clients,
|
|
chat::player_joined,
|
|
despawn_disconnected_clients,
|
|
))
|
|
.add_systems(PlayerList::default_systems())
|
|
.run();
|
|
}
|
|
|
|
fn init_clients(
|
|
mut new_clients: Query<
|
|
(
|
|
&mut Position,
|
|
Entity,
|
|
&UniqueId,
|
|
&mut Client,
|
|
&mut GameMode,
|
|
&Username,
|
|
&mut HasRespawnScreen,
|
|
),
|
|
Added<Client>,
|
|
>,
|
|
instances: Query<Entity, With<Instance>>,
|
|
mut commands: Commands,
|
|
) {
|
|
for (_pos, entity, uuid, mut client, mut game_mode, username, mut has_respawn_screen) in
|
|
&mut new_clients
|
|
{
|
|
has_respawn_screen.0 = true;
|
|
*game_mode = GameMode::Creative;
|
|
commands.entity(entity).insert(PlayerEntityBundle {
|
|
location: Location(instances.single()),
|
|
position: Position(DVec3 {
|
|
x: -214.0,
|
|
y: 83.0,
|
|
z: 276.0,
|
|
}),
|
|
uuid: *uuid,
|
|
..Default::default()
|
|
});
|
|
|
|
client.write_packet(&ChunkRenderDistanceCenterS2c {
|
|
chunk_x: VarInt(-14),
|
|
chunk_z: VarInt(17),
|
|
});
|
|
|
|
let mut buf = Vec::new();
|
|
"Valence".encode(&mut buf).unwrap();
|
|
client.send_custom_payload(ident!("brand"), &buf);
|
|
PLAYER_COUNT.fetch_add(1, Ordering::SeqCst);
|
|
|
|
tracing::info!("{username} joined the game");
|
|
}
|
|
}
|
|
|
|
pub fn despawn_disconnected_clients(
|
|
mut commands: Commands,
|
|
mut disconnected_clients: RemovedComponents<Client>,
|
|
) {
|
|
for entity in disconnected_clients.iter() {
|
|
if let Some(mut entity) = commands.get_entity(entity) {
|
|
entity.insert(Despawned);
|
|
}
|
|
PLAYER_COUNT.fetch_sub(1, Ordering::SeqCst);
|
|
}
|
|
}
|