aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock113
-rw-r--r--Cargo.toml3
-rwxr-xr-xlaunch_2p.sh4
-rw-r--r--src/main.rs174
4 files changed, 261 insertions, 33 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 146c0c6..0d8296e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -179,6 +179,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9"
[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
+[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -949,9 +960,9 @@ checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3"
[[package]]
name = "bytemuck"
-version = "1.9.1"
+version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc"
+checksum = "a5377c8865e74a160d21f29c2d40669f53286db6eab59b88540cbb12ffc8b835"
dependencies = [
"bytemuck_derive",
]
@@ -1039,6 +1050,21 @@ dependencies = [
]
[[package]]
+name = "clap"
+version = "2.34.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
+dependencies = [
+ "ansi_term",
+ "atty",
+ "bitflags",
+ "strsim 0.8.0",
+ "textwrap",
+ "unicode-width",
+ "vec_map",
+]
+
+[[package]]
name = "cocoa"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1368,7 +1394,7 @@ dependencies = [
"ident_case",
"proc-macro2",
"quote",
- "strsim",
+ "strsim 0.10.0",
"syn",
]
@@ -1822,6 +1848,15 @@ dependencies = [
]
[[package]]
+name = "heck"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1934,8 +1969,11 @@ dependencies = [
"bevy",
"bevy_ggrs",
"bevy_rapier2d",
+ "bytemuck",
+ "ggrs",
"serde",
"serde_json",
+ "structopt",
]
[[package]]
@@ -2698,6 +2736,30 @@ dependencies = [
]
[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
+[[package]]
name = "proc-macro2"
version = "1.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3044,11 +3106,41 @@ checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e"
[[package]]
name = "strsim"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+
+[[package]]
+name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
+name = "structopt"
+version = "0.3.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10"
+dependencies = [
+ "clap",
+ "lazy_static",
+ "structopt-derive",
+]
+
+[[package]]
+name = "structopt-derive"
+version = "0.4.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
+dependencies = [
+ "heck",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
name = "svg_fmt"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3100,6 +3192,15 @@ dependencies = [
]
[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
name = "thiserror"
version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3244,6 +3345,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee"
[[package]]
+name = "unicode-segmentation"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
+
+[[package]]
name = "unicode-width"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index e0ae8c6..609e9af 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,3 +12,6 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
bevy_ggrs = { git = "https://github.com/paxsethorld/bevy_ggrs", rev = "bc78d31" }
+ggrs = { git = "https://github.com/gschup/ggrs", features = ["sync-send"] }
+bytemuck = "1.11.0"
+structopt = "0.3.26"
diff --git a/launch_2p.sh b/launch_2p.sh
new file mode 100755
index 0000000..14fd8a7
--- /dev/null
+++ b/launch_2p.sh
@@ -0,0 +1,4 @@
+#! /usr/bin/bash
+
+cargo run -- --local-port=40000 --players localhost 127.0.0.1:40001 &
+cargo run -- --local-port=40001 --players localhost 127.0.0.1:40001 &
diff --git a/src/main.rs b/src/main.rs
index d37fdde..1074319 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -8,36 +8,150 @@ use bevy::{prelude::*, render::camera::ScalingMode, window::WindowResized};
use bevy_rapier2d::{pipeline::CollisionEvent::*, prelude::*};
-/// i can step the rapier simulation by adding to the rollback systems
-/// the rapier system set. bevy_rapier provides 4 system sets.
-/// bevy_ggrs can take a schedule and a type, so no RapierContext
-/// in the schedule i can
-/// deserialize RapierContext
-/// run the game logic
-/// run the rapier systems
-/// serialize RapierContext
-/// the only problem is the first RapierContext, but default should be fine
-
-fn main() {
- App::new()
- .insert_resource(WindowDescriptor {
- title: "Tanks!".to_string(),
- resizable: true,
- ..Default::default()
- })
- .add_plugins(DefaultPlugins)
- .add_startup_system(spawn_camera)
- .add_startup_system(setup)
- .add_plugin(LogDiagnosticsPlugin::default())
- .add_plugin(FrameTimeDiagnosticsPlugin::default())
- .add_plugin(RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(100.0))
- .add_plugin(RapierDebugRenderPlugin::default())
- .add_system_to_stage(CoreStage::Update, movement)
- .add_system_to_stage(CoreStage::Update, shoot)
- .add_system_to_stage(CoreStage::PostUpdate, camera_follow)
- .add_system_to_stage(CoreStage::PostUpdate, hits)
- .add_system(window_resized_event)
- .run();
+use bevy_ggrs::{GGRSPlugin, SessionType};
+use ggrs::{Config, PlayerHandle, PlayerType, SessionBuilder, UdpNonBlockingSocket};
+
+use bytemuck::{Pod, Zeroable};
+use std::net::SocketAddr;
+
+use structopt::StructOpt;
+
+#[derive(Debug)]
+pub struct GGRSConfig;
+impl Config for GGRSConfig {
+ type Input = BoxInput;
+ type State = u8;
+ type Address = SocketAddr;
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, PartialEq, Pod, Zeroable)]
+pub struct BoxInput {
+ pub inp: u8,
+}
+
+const FPS: usize = 60;
+const ROLLBACK_DEFAULT: &str = "rollback_default";
+
+const INPUT_UP: u8 = 1 << 0;
+const INPUT_DOWN: u8 = 1 << 1;
+const INPUT_LEFT: u8 = 1 << 2;
+const INPUT_RIGHT: u8 = 1 << 3;
+
+pub fn input(_handle: In<PlayerHandle>, keyboard_input: Res<Input<KeyCode>>) -> BoxInput {
+ let mut input: u8 = 0;
+
+ if keyboard_input.pressed(KeyCode::W) {
+ input |= INPUT_UP;
+ }
+ if keyboard_input.pressed(KeyCode::A) {
+ input |= INPUT_LEFT;
+ }
+ if keyboard_input.pressed(KeyCode::S) {
+ input |= INPUT_DOWN;
+ }
+ if keyboard_input.pressed(KeyCode::D) {
+ input |= INPUT_RIGHT;
+ }
+
+ BoxInput { inp: input }
+}
+
+// structopt will read command line parameters for u
+#[derive(StructOpt)]
+struct Opt {
+ #[structopt(short, long)]
+ local_port: u16,
+ #[structopt(short, long)]
+ players: Vec<String>,
+ #[structopt(short, long)]
+ spectators: Vec<SocketAddr>,
+}
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ // read cmd line arguments
+ let opt = Opt::from_args();
+ let num_players = opt.players.len();
+ assert!(num_players > 0);
+
+ // create a GGRS session
+ let mut sess_build = SessionBuilder::<GGRSConfig>::new()
+ .with_num_players(num_players)
+ .with_max_prediction_window(12) // (optional) set max prediction window
+ .with_input_delay(2); // (optional) set input delay for the local player
+
+ // add players
+ for (i, player_addr) in opt.players.iter().enumerate() {
+ // local player
+ if player_addr == "localhost" {
+ sess_build = sess_build.add_player(PlayerType::Local, i)?;
+ } else {
+ // remote players
+ let remote_addr: SocketAddr = player_addr.parse()?;
+ sess_build = sess_build.add_player(PlayerType::Remote(remote_addr), i)?;
+ }
+ }
+
+ // optionally, add spectators
+ for (i, spec_addr) in opt.spectators.iter().enumerate() {
+ sess_build = sess_build.add_player(PlayerType::Spectator(*spec_addr), num_players + i)?;
+ }
+
+ // start the GGRS session
+ let socket = UdpNonBlockingSocket::bind_to_port(opt.local_port)?;
+ let sess = sess_build.start_p2p_session(socket)?;
+
+ let mut app = App::new();
+ GGRSPlugin::<GGRSConfig>::new()
+ .with_update_frequency(FPS)
+ .with_input_system(input)
+ .register_rollback_type::<Transform>()
+ .register_rollback_type::<Velocity>()
+ .with_rollback_schedule(
+ Schedule::default().with_stage(
+ ROLLBACK_DEFAULT,
+ SystemStage::parallel()
+ .with_system_set(RapierPhysicsPlugin::<()>::get_systems(
+ PhysicsStages::SyncBackend,
+ ))
+ .with_system_set(RapierPhysicsPlugin::<()>::get_systems(
+ PhysicsStages::StepSimulation,
+ ))
+ .with_system_set(RapierPhysicsPlugin::<()>::get_systems(
+ PhysicsStages::Writeback,
+ ))
+ .with_system_set(RapierPhysicsPlugin::<()>::get_systems(
+ PhysicsStages::DetectDespawn,
+ )),
+ ),
+ )
+ .build(&mut app);
+
+ app.insert_resource(WindowDescriptor {
+ title: "Tanks!".to_string(),
+ resizable: true,
+ ..Default::default()
+ })
+ // add your GGRS session
+ .insert_resource(sess)
+ .insert_resource(SessionType::P2PSession)
+ .add_plugins(DefaultPlugins)
+ .add_startup_system(spawn_camera)
+ .add_startup_system(setup)
+ .add_plugin(LogDiagnosticsPlugin::default())
+ .add_plugin(FrameTimeDiagnosticsPlugin::default())
+ .add_plugin(
+ RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(100.0).with_default_system_setup(false),
+ )
+ .add_plugin(RapierDebugRenderPlugin::default())
+ .add_system_to_stage(CoreStage::Update, movement)
+ .add_system_to_stage(CoreStage::Update, shoot)
+ .add_system_to_stage(CoreStage::PostUpdate, camera_follow)
+ .add_system_to_stage(CoreStage::PostUpdate, hits)
+ .add_system(window_resized_event)
+ .run();
+
+ Ok(())
}
fn window_resized_event(