250 lines
7.0 KiB
Rust
250 lines
7.0 KiB
Rust
pub mod abilities;
|
|
pub mod ai;
|
|
pub mod aim;
|
|
pub mod animation;
|
|
pub mod backpack;
|
|
pub mod camera;
|
|
pub mod cash;
|
|
pub mod cash_heal;
|
|
pub mod character;
|
|
#[cfg(feature = "client")]
|
|
pub mod client;
|
|
pub mod config;
|
|
pub mod control;
|
|
pub mod cutscene;
|
|
pub mod gates;
|
|
pub mod head;
|
|
pub mod head_drop;
|
|
pub mod heads;
|
|
pub mod heads_database;
|
|
pub mod hitpoints;
|
|
pub mod keys;
|
|
pub mod loading_assets;
|
|
pub mod loading_map;
|
|
pub mod movables;
|
|
pub mod npc;
|
|
pub mod physics_layers;
|
|
pub mod platforms;
|
|
pub mod player;
|
|
pub mod protocol;
|
|
pub mod server;
|
|
pub mod tb_entities;
|
|
pub mod tick;
|
|
pub mod utils;
|
|
pub mod water;
|
|
|
|
use crate::{
|
|
config::NetConfig,
|
|
heads_database::{HeadDatabaseAsset, HeadsDatabase},
|
|
protocol::{PlayerIdCounter, messages::AssignClientPlayer},
|
|
tb_entities::SpawnPoint,
|
|
};
|
|
use avian3d::{PhysicsPlugins, prelude::TransformInterpolation};
|
|
#[cfg(not(feature = "client"))]
|
|
use bevy::app::ScheduleRunnerPlugin;
|
|
use bevy::{core_pipeline::tonemapping::Tonemapping, prelude::*};
|
|
use bevy_common_assets::ron::RonAssetPlugin;
|
|
use bevy_replicon::{RepliconPlugins, prelude::ClientId};
|
|
use bevy_replicon_renet::RepliconRenetPlugins;
|
|
use bevy_sprite3d::Sprite3dPlugin;
|
|
use bevy_steamworks::SteamworksEvent;
|
|
use bevy_trenchbroom::{
|
|
TrenchBroomPlugins, config::TrenchBroomConfig, prelude::TrenchBroomPhysicsPlugin,
|
|
};
|
|
use bevy_trenchbroom_avian::AvianPhysicsBackend;
|
|
use utils::{billboards, squish_animation};
|
|
|
|
pub const HEDZ_GREEN: Srgba = Srgba::rgb(0.0, 1.0, 0.0);
|
|
pub const HEDZ_PURPLE: Srgba = Srgba::rgb(91. / 256., 4. / 256., 138. / 256.);
|
|
|
|
pub fn launch() {
|
|
let mut app = App::new();
|
|
|
|
app.register_type::<DebugVisuals>()
|
|
.register_type::<TransformInterpolation>();
|
|
|
|
app.insert_resource(DebugVisuals {
|
|
unlit: false,
|
|
tonemapping: Tonemapping::None,
|
|
exposure: 1.,
|
|
shadows: true,
|
|
cam_follow: true,
|
|
});
|
|
|
|
let default_plugins = DefaultPlugins;
|
|
#[cfg(feature = "client")]
|
|
let default_plugins = default_plugins.set(WindowPlugin {
|
|
primary_window: Some(Window {
|
|
title: "HEDZ Reloaded".into(),
|
|
..default()
|
|
}),
|
|
..default()
|
|
});
|
|
app.add_plugins(default_plugins);
|
|
|
|
#[cfg(not(feature = "client"))]
|
|
app.add_plugins(ScheduleRunnerPlugin::default());
|
|
|
|
#[cfg(feature = "client")]
|
|
app.add_plugins(
|
|
bevy_debug_log::LogViewerPlugin::default()
|
|
.auto_open_threshold(bevy::log::tracing::level_filters::LevelFilter::OFF),
|
|
);
|
|
|
|
app.add_plugins(PhysicsPlugins::default());
|
|
app.add_plugins((RepliconPlugins, RepliconRenetPlugins));
|
|
app.add_plugins(Sprite3dPlugin);
|
|
app.add_plugins(TrenchBroomPlugins(
|
|
TrenchBroomConfig::new("hedz").icon(None),
|
|
));
|
|
app.add_plugins(TrenchBroomPhysicsPlugin::new(AvianPhysicsBackend));
|
|
app.add_plugins(RonAssetPlugin::<HeadDatabaseAsset>::new(&["headsdb.ron"]));
|
|
|
|
app.add_plugins(plugin);
|
|
|
|
app.init_state::<GameState>();
|
|
|
|
app.run();
|
|
}
|
|
|
|
pub fn plugin(app: &mut App) {
|
|
app.add_plugins(abilities::plugin);
|
|
app.add_plugins(ai::plugin);
|
|
app.add_plugins(animation::plugin);
|
|
app.add_plugins(character::plugin);
|
|
app.add_plugins(cash::plugin);
|
|
app.add_plugins(cash_heal::plugin);
|
|
app.add_plugins(config::plugin);
|
|
app.add_plugins(player::plugin);
|
|
app.add_plugins(gates::plugin);
|
|
app.add_plugins(platforms::plugin);
|
|
app.add_plugins(movables::plugin);
|
|
app.add_plugins(utils::billboards::plugin);
|
|
app.add_plugins(aim::plugin);
|
|
app.add_plugins(npc::plugin);
|
|
app.add_plugins(keys::plugin);
|
|
app.add_plugins(utils::squish_animation::plugin);
|
|
app.add_plugins(camera::plugin);
|
|
#[cfg(feature = "client")]
|
|
app.add_plugins(client::plugin);
|
|
app.add_plugins(control::plugin);
|
|
app.add_plugins(cutscene::plugin);
|
|
app.add_plugins(backpack::plugin);
|
|
app.add_plugins(loading_assets::LoadingPlugin);
|
|
app.add_plugins(loading_map::plugin);
|
|
app.add_plugins(heads::plugin);
|
|
app.add_plugins(hitpoints::plugin);
|
|
app.add_plugins(head_drop::plugin);
|
|
app.add_plugins(protocol::plugin);
|
|
app.add_plugins(server::plugin);
|
|
app.add_plugins(tb_entities::plugin);
|
|
app.add_plugins(tick::plugin);
|
|
app.add_plugins(utils::plugin);
|
|
app.add_plugins(utils::auto_rotate::plugin);
|
|
app.add_plugins(utils::explosions::plugin);
|
|
app.add_plugins(utils::sprite_3d_animation::plugin);
|
|
app.add_plugins(utils::trail::plugin);
|
|
app.add_plugins(water::plugin);
|
|
|
|
if cfg!(feature = "client") {
|
|
app.add_systems(
|
|
OnEnter(GameState::Waiting),
|
|
start_solo_client.run_if(|config: Res<NetConfig>| config.is_singleplayer()),
|
|
);
|
|
app.add_systems(
|
|
OnEnter(GameState::Waiting),
|
|
start_listen_server.run_if(|config: Res<NetConfig>| config.is_host()),
|
|
);
|
|
app.add_systems(
|
|
OnEnter(GameState::Waiting),
|
|
start_client.run_if(|config: Res<NetConfig>| config.is_client()),
|
|
);
|
|
} else {
|
|
app.add_systems(OnEnter(GameState::Waiting), start_dedicated_server);
|
|
}
|
|
|
|
app.add_systems(Update, log_steam_events);
|
|
}
|
|
|
|
#[derive(Resource, Reflect, Debug)]
|
|
#[reflect(Resource)]
|
|
pub struct DebugVisuals {
|
|
pub unlit: bool,
|
|
pub tonemapping: Tonemapping,
|
|
pub exposure: f32,
|
|
pub shadows: bool,
|
|
pub cam_follow: bool,
|
|
}
|
|
|
|
#[derive(States, Default, Clone, Copy, Eq, PartialEq, Debug, Hash)]
|
|
pub enum GameState {
|
|
/// Loading assets from disk
|
|
#[default]
|
|
AssetLoading,
|
|
/// Loading + constructing map
|
|
MapLoading,
|
|
/// Waiting to host/connect/play
|
|
Waiting,
|
|
/// Connecting to server
|
|
Connecting,
|
|
/// Opening server
|
|
Hosting,
|
|
/// Running the game
|
|
Playing,
|
|
}
|
|
|
|
fn log_steam_events(events: Option<MessageReader<SteamworksEvent>>) {
|
|
let Some(mut events) = events else {
|
|
return;
|
|
};
|
|
|
|
for event in events.read() {
|
|
let SteamworksEvent::CallbackResult(result) = event;
|
|
info!("steam: {:?}", result);
|
|
}
|
|
}
|
|
|
|
fn start_solo_client(
|
|
commands: Commands,
|
|
mut next: ResMut<NextState<GameState>>,
|
|
query: Query<&Transform, With<SpawnPoint>>,
|
|
heads_db: Res<HeadsDatabase>,
|
|
mut assign_player_id: MessageWriter<AssignClientPlayer>,
|
|
mut ids: ResMut<PlayerIdCounter>,
|
|
) {
|
|
next.set(GameState::Playing);
|
|
|
|
ids.reset();
|
|
let id = ids.alloc();
|
|
|
|
player::spawn(commands, ClientId::Server, id, query, heads_db);
|
|
|
|
assign_player_id.write(AssignClientPlayer(id));
|
|
}
|
|
|
|
fn start_listen_server(
|
|
commands: Commands,
|
|
mut next: ResMut<NextState<GameState>>,
|
|
query: Query<&Transform, With<SpawnPoint>>,
|
|
heads_db: Res<HeadsDatabase>,
|
|
mut assign_player_id: MessageWriter<AssignClientPlayer>,
|
|
mut ids: ResMut<PlayerIdCounter>,
|
|
) {
|
|
next.set(GameState::Hosting);
|
|
|
|
ids.reset();
|
|
let id = ids.alloc();
|
|
|
|
player::spawn(commands, ClientId::Server, id, query, heads_db);
|
|
|
|
assign_player_id.write(AssignClientPlayer(id));
|
|
}
|
|
|
|
fn start_client(mut next: ResMut<NextState<GameState>>) {
|
|
next.set(GameState::Connecting);
|
|
}
|
|
|
|
fn start_dedicated_server(mut next: ResMut<NextState<GameState>>) {
|
|
next.set(GameState::Hosting);
|
|
}
|