some netplay sync shit I worked on but didn't push

This commit is contained in:
Alula 2022-09-12 09:44:28 +02:00
parent 6656240c8d
commit 9d39c61b8b
No known key found for this signature in database
GPG Key ID: 3E00485503A1D8BA
10 changed files with 123 additions and 54 deletions

View File

@ -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(),

View File

@ -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);
}
}

View File

@ -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,

View File

@ -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

View File

@ -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
}

View File

@ -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),
}

View File

@ -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));
}
}
}

View File

@ -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()
}

View File

@ -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 {

View File

@ -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,