some netplay sync shit I worked on but didn't push
This commit is contained in:
parent
6656240c8d
commit
9d39c61b8b
|
@ -8,7 +8,7 @@ use crate::shared_game_state::SharedGameState;
|
|||
|
||||
struct MessageData {
|
||||
content: String,
|
||||
fade: u8,
|
||||
fade: u16,
|
||||
}
|
||||
|
||||
pub struct Chat {
|
||||
|
@ -22,7 +22,7 @@ impl Chat {
|
|||
}
|
||||
|
||||
pub fn push_message(&mut self, content: String) {
|
||||
self.messages.push_front(MessageData { content, fade: 150 });
|
||||
self.messages.push_front(MessageData { content, fade: 300 });
|
||||
|
||||
while self.messages.len() > self.max_messages {
|
||||
self.messages.pop_back();
|
||||
|
@ -47,7 +47,7 @@ impl GameEntity<()> for Chat {
|
|||
|
||||
for message in self.messages.iter() {
|
||||
if message.fade > 0 {
|
||||
let fade = message.fade.min(50);
|
||||
let fade = message.fade.min(50) as u8;
|
||||
|
||||
state.font.draw_colored_text_with_shadow_scaled(
|
||||
message.content.chars(),
|
||||
|
|
|
@ -184,7 +184,7 @@ impl PlayerController for DummyPlayerController {
|
|||
|
||||
fn set_state(&mut self, state: (u16, u16, u16)) {
|
||||
self.state = KeyState(state.0);
|
||||
self.old_state = KeyState(state.1);
|
||||
self.trigger = KeyState(state.2);
|
||||
//self.old_state = KeyState(state.1);
|
||||
//self.trigger = KeyState(state.2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,11 @@ use crate::weapon::{Weapon, WeaponLevel, WeaponType};
|
|||
use crate::player::{Player, TargetPlayer};
|
||||
use crate::weapon::bullet::BulletManager;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, bincode::Encode, bincode::Decode)]
|
||||
/// (id, amount)
|
||||
pub struct Item(pub u16, pub u16);
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, bincode::Encode, bincode::Decode)]
|
||||
pub struct Inventory {
|
||||
pub current_item: u16,
|
||||
pub current_weapon: u16,
|
||||
|
|
|
@ -347,10 +347,23 @@ impl Client {
|
|||
if let Some(npc_ref) = game_scene.npc_list.get_npc(npc.id as usize) {
|
||||
*npc_ref = npc;
|
||||
}
|
||||
game_scene.npc_list.recheck();
|
||||
}
|
||||
DRSPacket::SyncControlFlags(flags) => {
|
||||
state.control_flags = flags;
|
||||
}
|
||||
DRSPacket::SyncFlags(flags) => {
|
||||
for (idx, &flags) in flags.iter().enumerate() {
|
||||
state.set_flag(idx * 8, flags & 0b00000001 != 0);
|
||||
state.set_flag(idx * 8 + 1, flags & 0b00000010 != 0);
|
||||
state.set_flag(idx * 8 + 2, flags & 0b00000100 != 0);
|
||||
state.set_flag(idx * 8 + 3, flags & 0b00001000 != 0);
|
||||
state.set_flag(idx * 8 + 4, flags & 0b00010000 != 0);
|
||||
state.set_flag(idx * 8 + 5, flags & 0b00100000 != 0);
|
||||
state.set_flag(idx * 8 + 6, flags & 0b01000000 != 0);
|
||||
state.set_flag(idx * 8 + 7, flags & 0b10000000 != 0);
|
||||
}
|
||||
}
|
||||
DRSPacket::SyncPlayer(data) => {
|
||||
let player = if data.target == TargetPlayer::Player1 {
|
||||
&mut game_scene.player1
|
||||
|
@ -371,6 +384,13 @@ impl Client {
|
|||
player.air_counter = data.air_counter;
|
||||
player.air = data.air;
|
||||
}
|
||||
DRSPacket::SyncInventory(target, inventory) => {
|
||||
if target == TargetPlayer::Player1 {
|
||||
game_scene.inventory_player1 = inventory;
|
||||
} else {
|
||||
game_scene.inventory_player2 = inventory;
|
||||
}
|
||||
}
|
||||
DRSPacket::Move(data) => {
|
||||
let player = if data.target == TargetPlayer::Player1 {
|
||||
&mut game_scene.player1
|
||||
|
|
|
@ -9,6 +9,8 @@ use crate::netplay::protocol::DRSPacket;
|
|||
pub fn make_socket_config() -> Config {
|
||||
let mut config = Config::default();
|
||||
config.idle_connection_timeout = Duration::new(30, 0);
|
||||
config.max_fragments = 128;
|
||||
config.max_packet_size = 128 * 1024;
|
||||
config
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::scripting::tsc::text_script::{
|
|||
use crate::stage::Stage;
|
||||
use crate::{GameResult, ScriptMode};
|
||||
use crate::components::number_popup::NumberPopup;
|
||||
use crate::inventory::Inventory;
|
||||
use crate::npc::NPC;
|
||||
|
||||
#[derive(Clone, bincode::Decode, bincode::Encode)]
|
||||
|
@ -103,10 +104,12 @@ pub enum DRSPacket {
|
|||
ConnectResponse(TargetPlayer),
|
||||
Move(PlayerMove),
|
||||
SyncControlFlags(ControlFlags),
|
||||
SyncFlags([u8; 1000]),
|
||||
SyncStageData(StageData),
|
||||
SyncTSCScripts(Scripts),
|
||||
SyncTSC(TextScriptData),
|
||||
SyncPlayer(PlayerData),
|
||||
SyncInventory(TargetPlayer, Inventory),
|
||||
SyncNPC(NPC),
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ use crate::netplay::common::{make_socket_config, SenderExt};
|
|||
use crate::netplay::protocol::{DRSPacket, HelloData, PlayerData, PlayerMove, ServerInfo, StageData, TextScriptData};
|
||||
use crate::netplay::server_config::ServerConfiguration;
|
||||
use crate::player::TargetPlayer;
|
||||
use crate::profile::GameProfile;
|
||||
use crate::scene::game_scene::GameScene;
|
||||
use crate::SharedGameState;
|
||||
|
||||
|
@ -131,10 +132,10 @@ impl Server {
|
|||
continue;
|
||||
}
|
||||
|
||||
let mut target = TargetPlayer::Player2;
|
||||
let mut target = TargetPlayer::Player1;
|
||||
for (_, state) in players.iter() {
|
||||
if state.target == TargetPlayer::Player2 {
|
||||
target = TargetPlayer::Player1;
|
||||
if state.target == TargetPlayer::Player1 {
|
||||
target = TargetPlayer::Player2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,6 +246,7 @@ impl Server {
|
|||
match msg {
|
||||
SyncMessage::SyncStageToPlayer(target) => {
|
||||
self.sync_transfer_stage(state, game_scene, Some(target));
|
||||
self.sync_flags(state, game_scene, Some(target));
|
||||
self.sync_players(state, game_scene);
|
||||
}
|
||||
SyncMessage::SyncNewPlayer(target) => {
|
||||
|
@ -281,7 +283,7 @@ impl Server {
|
|||
|
||||
if self.tick % 300 == 50 {
|
||||
for npc in game_scene.npc_list.iter_alive() {
|
||||
let _ = self.broadcast_packet_queue.send((DRSPacket::SyncNPC(npc.clone()), DeliveryType::Reliable));
|
||||
let _ = self.broadcast_packet_queue.send((DRSPacket::SyncNPC(npc.clone()), DeliveryType::Unreliable));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,6 +297,8 @@ impl Server {
|
|||
for target in players {
|
||||
let player =
|
||||
if target == TargetPlayer::Player1 { &mut game_scene.player1 } else { &mut game_scene.player2 };
|
||||
let inventory =
|
||||
if target == TargetPlayer::Player1 { &mut game_scene.inventory_player1 } else { &mut game_scene.inventory_player2 };
|
||||
|
||||
let (state, old_state, trigger) = player.controller.dump_state();
|
||||
|
||||
|
@ -327,8 +331,11 @@ impl Server {
|
|||
cond: player.cond,
|
||||
});
|
||||
|
||||
let inventory_packet = DRSPacket::SyncInventory(target, inventory.clone());
|
||||
|
||||
let _ = self.broadcast_packet_queue.send((sync_packet, DeliveryType::Reliable));
|
||||
let _ = self.broadcast_packet_queue.send((move_packet, DeliveryType::Reliable));
|
||||
let _ = self.broadcast_packet_queue.send((inventory_packet, DeliveryType::Reliable));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -400,4 +407,19 @@ impl Server {
|
|||
|
||||
self.sync_tsc(state, game_scene, target);
|
||||
}
|
||||
|
||||
pub fn sync_flags(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
game_scene: &mut GameScene,
|
||||
target: Option<TargetPlayer>,
|
||||
) {
|
||||
let flags = GameProfile::dump(state, game_scene).flags;
|
||||
|
||||
if let Some(target) = target {
|
||||
let _ = self.send_packet_queue.send((target, DRSPacket::SyncFlags(flags), DeliveryType::Reliable));
|
||||
} else {
|
||||
let _ = self.broadcast_packet_queue.send((DRSPacket::SyncFlags(flags), DeliveryType::Reliable));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -145,6 +145,22 @@ impl NPCList {
|
|||
NPC_LIST_MAX_CAP as u16
|
||||
}
|
||||
|
||||
pub fn recheck(&self) {
|
||||
let mut max_alive = 0;
|
||||
|
||||
unsafe {
|
||||
for (id, npc) in (&mut *self.npcs.get()).iter_mut().enumerate() {
|
||||
npc.id = id as u16;
|
||||
|
||||
if npc.cond.alive() {
|
||||
max_alive = npc.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.max_npc.replace(max_alive);
|
||||
}
|
||||
|
||||
unsafe fn npcs<'a: 'b, 'b>(&'a self) -> &'b [NPC; NPC_LIST_MAX_CAP] {
|
||||
&*self.npcs.get()
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use crossbeam_channel::tick;
|
|||
use log::info;
|
||||
|
||||
use crate::caret::CaretType;
|
||||
use crate::common::{Color, Direction, interpolate_fix9_scale, Rect};
|
||||
use crate::common::{interpolate_fix9_scale, Color, Direction, Rect};
|
||||
use crate::components::background::Background;
|
||||
use crate::components::boss_life_bar::BossLifeBar;
|
||||
use crate::components::credits::Credits;
|
||||
|
@ -27,32 +27,32 @@ use crate::components::water_renderer::{WaterLayer, WaterRenderer};
|
|||
use crate::components::whimsical_star::WhimsicalStar;
|
||||
use crate::entity::GameEntity;
|
||||
use crate::frame::{Frame, UpdateTarget};
|
||||
use crate::framework::{filesystem, graphics};
|
||||
use crate::framework::backend::SpriteBatchCommand;
|
||||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::framework::graphics::{BlendMode, draw_rect, FilterMode};
|
||||
use crate::framework::graphics::{draw_rect, BlendMode, FilterMode};
|
||||
use crate::framework::ui::Components;
|
||||
use crate::framework::{filesystem, graphics};
|
||||
use crate::input::touch_controls::TouchControlType;
|
||||
use crate::inventory::{Inventory, TakeExperienceResult};
|
||||
use crate::map::WaterParams;
|
||||
use crate::menu::pause_menu::PauseMenu;
|
||||
use crate::npc::{NPC, NPCLayer};
|
||||
use crate::npc::boss::BossNPC;
|
||||
use crate::npc::list::NPCList;
|
||||
use crate::physics::{OFFSETS, PhysicalEntity};
|
||||
use crate::npc::{NPCLayer, NPC};
|
||||
use crate::physics::{PhysicalEntity, OFFSETS};
|
||||
use crate::player::{ControlMode, Player, TargetPlayer};
|
||||
use crate::rng::RNG;
|
||||
use crate::scene::Scene;
|
||||
use crate::scene::title_scene::TitleScene;
|
||||
use crate::scene::Scene;
|
||||
use crate::scripting::tsc::credit_script::CreditScriptVM;
|
||||
use crate::scripting::tsc::text_script::{ScriptMode, TextScriptExecutionState, TextScriptVM};
|
||||
use crate::settings::ControllerType;
|
||||
use crate::shared_game_state::{Language, PlayerCount, ReplayState, SharedGameState, TileSize};
|
||||
use crate::stage::{BackgroundType, Stage, StageTexturePaths};
|
||||
use crate::texture_set::SpriteBatch;
|
||||
use crate::weapon::{Weapon, WeaponType};
|
||||
use crate::weapon::bullet::BulletManager;
|
||||
use crate::weapon::{Weapon, WeaponType};
|
||||
|
||||
pub struct GameScene {
|
||||
pub tick: u32,
|
||||
|
@ -1427,11 +1427,11 @@ impl GameScene {
|
|||
|
||||
match self.frame.update_target {
|
||||
UpdateTarget::Player => {
|
||||
if self.player2.cond.alive()
|
||||
if !state.is_netplay() && (self.player2.cond.alive()
|
||||
&& !self.player2.cond.hidden()
|
||||
&& (self.player1.x - self.player2.x).abs() < 240 * 0x200
|
||||
&& (self.player1.y - self.player2.y).abs() < 200 * 0x200
|
||||
&& self.player1.control_mode != ControlMode::IronHead
|
||||
&& self.player1.control_mode != ControlMode::IronHead)
|
||||
{
|
||||
self.frame.target_x = (self.player1.target_x * 2 + self.player2.target_x) / 3;
|
||||
self.frame.target_y = (self.player1.target_y * 2 + self.player2.target_y) / 3;
|
||||
|
@ -1439,11 +1439,11 @@ impl GameScene {
|
|||
self.frame.target_x = self.frame.target_x.clamp(self.player1.x - 0x8000, self.player1.x + 0x8000);
|
||||
self.frame.target_y = self.frame.target_y.clamp(self.player1.y, self.player1.y);
|
||||
} else {
|
||||
self.frame.target_x = self.player1.target_x;
|
||||
self.frame.target_y = self.player1.target_y;
|
||||
self.frame.target_x = self.local_player().target_x;
|
||||
self.frame.target_y = self.local_player().target_y;
|
||||
}
|
||||
|
||||
if self.player2.cond.alive() && !self.player2.cond.hidden() {
|
||||
if !state.is_netplay() && self.player2.cond.alive() && !self.player2.cond.hidden() {
|
||||
if self.player2.x + 0x1000 < self.frame.x
|
||||
|| self.player2.x - 0x1000 > self.frame.x + state.canvas_size.0 as i32 * 0x200
|
||||
|| self.player2.y + 0x1000 < self.frame.y
|
||||
|
@ -1633,9 +1633,11 @@ impl GameScene {
|
|||
impl Scene for GameScene {
|
||||
fn init(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||
let mut is_server = false;
|
||||
let mut is_client = false;
|
||||
#[cfg(feature = "netplay")]
|
||||
{
|
||||
is_server = state.server.is_some();
|
||||
is_client = state.client.is_some();
|
||||
}
|
||||
|
||||
if state.mod_path.is_some() && state.replay_state == ReplayState::Recording {
|
||||
|
@ -1656,11 +1658,13 @@ impl Scene for GameScene {
|
|||
|
||||
self.npc_list.set_rng_seed(state.game_rng.next());
|
||||
self.boss.init_rng(state.game_rng.next());
|
||||
state.textscript_vm.set_scene_script(self.stage.load_text_script(
|
||||
&state.constants.base_paths,
|
||||
&state.constants,
|
||||
ctx,
|
||||
)?);
|
||||
if !is_client {
|
||||
state.textscript_vm.set_scene_script(self.stage.load_text_script(
|
||||
&state.constants.base_paths,
|
||||
&state.constants,
|
||||
ctx,
|
||||
)?);
|
||||
}
|
||||
state.textscript_vm.suspend = false;
|
||||
state.tile_size = self.stage.map.tile_size;
|
||||
#[cfg(feature = "scripting-lua")]
|
||||
|
@ -1671,24 +1675,26 @@ impl Scene for GameScene {
|
|||
self.player2.controller = state.settings.create_player2_controller();
|
||||
}
|
||||
|
||||
let npcs = self.stage.load_npcs(&state.constants.base_paths, ctx)?;
|
||||
for npc_data in npcs.iter() {
|
||||
log::info!("creating npc: {:?}", npc_data);
|
||||
if !is_client {
|
||||
let npcs = self.stage.load_npcs(&state.constants.base_paths, ctx)?;
|
||||
for npc_data in npcs.iter() {
|
||||
log::info!("creating npc: {:?}", npc_data);
|
||||
|
||||
let mut npc = NPC::create_from_data(npc_data, &state.npc_table, state.tile_size);
|
||||
if npc.npc_flags.appear_when_flag_set() {
|
||||
if state.get_flag(npc_data.flag_num as _) {
|
||||
let mut npc = NPC::create_from_data(npc_data, &state.npc_table, state.tile_size);
|
||||
if npc.npc_flags.appear_when_flag_set() {
|
||||
if state.get_flag(npc_data.flag_num as _) {
|
||||
npc.cond.set_alive(true);
|
||||
}
|
||||
} else if npc.npc_flags.hide_unless_flag_set() {
|
||||
if !state.get_flag(npc_data.flag_num as _) {
|
||||
npc.cond.set_alive(true);
|
||||
}
|
||||
} else {
|
||||
npc.cond.set_alive(true);
|
||||
}
|
||||
} else if npc.npc_flags.hide_unless_flag_set() {
|
||||
if !state.get_flag(npc_data.flag_num as _) {
|
||||
npc.cond.set_alive(true);
|
||||
}
|
||||
} else {
|
||||
npc.cond.set_alive(true);
|
||||
|
||||
self.npc_list.spawn_at_slot(npc_data.id, npc)?;
|
||||
}
|
||||
|
||||
self.npc_list.spawn_at_slot(npc_data.id, npc)?;
|
||||
}
|
||||
|
||||
state.npc_table.stage_textures = self.stage_textures.clone();
|
||||
|
@ -1754,6 +1760,15 @@ impl Scene for GameScene {
|
|||
let chat = state.chat.clone();
|
||||
chat.borrow_mut().tick(state, ())?;
|
||||
|
||||
if !self.pause_menu.is_paused() && state.replay_state == ReplayState::Playback {
|
||||
self.replay.tick(state, (ctx, &mut self.player1))?;
|
||||
}
|
||||
|
||||
self.player1.controller.update(state, ctx)?;
|
||||
self.player1.controller.update_trigger();
|
||||
self.player2.controller.update(state, ctx)?;
|
||||
self.player2.controller.update_trigger();
|
||||
|
||||
#[cfg(feature = "netplay")]
|
||||
{
|
||||
let state_ref = unsafe { &mut *(state as *mut SharedGameState) };
|
||||
|
@ -1764,15 +1779,6 @@ impl Scene for GameScene {
|
|||
}
|
||||
}
|
||||
|
||||
if !self.pause_menu.is_paused() && state.replay_state == ReplayState::Playback {
|
||||
self.replay.tick(state, (ctx, &mut self.player1))?;
|
||||
}
|
||||
|
||||
self.player1.controller.update(state, ctx)?;
|
||||
self.player1.controller.update_trigger();
|
||||
self.player2.controller.update(state, ctx)?;
|
||||
self.player2.controller.update_trigger();
|
||||
|
||||
state.touch_controls.control_type = if state.control_flags.control_enabled() && !self.pause_menu.is_paused() {
|
||||
TouchControlType::Controls
|
||||
} else {
|
||||
|
|
|
@ -19,7 +19,7 @@ mod snake;
|
|||
mod spur;
|
||||
mod super_missile_launcher;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone, FromPrimitive)]
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone, FromPrimitive, bincode::Encode, bincode::Decode)]
|
||||
#[repr(u8)]
|
||||
pub enum WeaponType {
|
||||
None = 0,
|
||||
|
@ -35,7 +35,7 @@ pub enum WeaponType {
|
|||
Spur = 13,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone, bincode::Encode, bincode::Decode)]
|
||||
#[repr(u8)]
|
||||
pub enum WeaponLevel {
|
||||
None = 0,
|
||||
|
@ -64,7 +64,7 @@ impl WeaponLevel {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, bincode::Encode, bincode::Decode)]
|
||||
pub struct Weapon {
|
||||
pub wtype: WeaponType,
|
||||
pub level: WeaponLevel,
|
||||
|
|
Loading…
Reference in New Issue