mirror of
https://codeberg.org/demostf/edit.git
synced 2026-06-03 11:54:07 +02:00
fmt + CL_PreserveExistingEntity wip fix
This commit is contained in:
parent
4a970e81a2
commit
e95a9e4a2c
11 changed files with 139 additions and 49 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
use tf_demo_parser::demo::message::Message;
|
use crate::missing_preserve::RemoveInvalidPreserveEntity;
|
||||||
use tf_demo_parser::demo::message::usermessage::UserMessageType;
|
|
||||||
use crate::mutate::MutatorList;
|
use crate::mutate::MutatorList;
|
||||||
|
use tf_demo_parser::demo::message::usermessage::UserMessageType;
|
||||||
|
use tf_demo_parser::demo::message::Message;
|
||||||
|
|
||||||
/// General cleanup we always want to do
|
/// General cleanup we always want to do
|
||||||
pub fn clean_demo(mutators: &mut MutatorList) {
|
pub fn clean_demo(mutators: &mut MutatorList) {
|
||||||
|
|
@ -11,4 +12,5 @@ pub fn clean_demo(mutators: &mut MutatorList) {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
mutators.push_message_mutator(RemoveInvalidPreserveEntity::new());
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
use tf_demo_parser::demo::message::Message;
|
|
||||||
use tf_demo_parser::demo::message::packetentities::{EntityId, PacketEntity};
|
|
||||||
use tf_demo_parser::demo::sendprop::{SendPropIdentifier, SendPropValue};
|
|
||||||
use tf_demo_parser::ParserState;
|
|
||||||
use crate::mutate::MessageMutator;
|
use crate::mutate::MessageMutator;
|
||||||
use crate::MutatorList;
|
use crate::MutatorList;
|
||||||
|
use tf_demo_parser::demo::message::packetentities::{EntityId, PacketEntity};
|
||||||
|
use tf_demo_parser::demo::message::Message;
|
||||||
|
use tf_demo_parser::demo::sendprop::{SendPropIdentifier, SendPropValue};
|
||||||
|
use tf_demo_parser::ParserState;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
|
@ -70,4 +70,4 @@ pub fn strip_cond(mutators: &mut MutatorList, entity: Option<EntityId>, mask: u3
|
||||||
entity,
|
entity,
|
||||||
cond: mask as i64,
|
cond: mask as i64,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
use std::collections::{BTreeMap, BTreeSet};
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
use tf_demo_parser::demo::data::{DemoTick, ServerTick};
|
use tf_demo_parser::demo::data::{DemoTick, ServerTick};
|
||||||
use tf_demo_parser::demo::message::packetentities::{
|
use tf_demo_parser::demo::message::packetentities::{
|
||||||
EntityId, PacketEntitiesMessage, PacketEntity, UpdateType,
|
EntityId, PacketEntitiesMessage, PacketEntity, UpdateType,
|
||||||
};
|
};
|
||||||
use tf_demo_parser::demo::packet::datatable::ClassId;
|
use tf_demo_parser::demo::packet::datatable::ClassId;
|
||||||
use tf_demo_parser::demo::sendprop::{SendPropIdentifier};
|
use tf_demo_parser::demo::sendprop::SendPropIdentifier;
|
||||||
use tf_demo_parser::ParserState;
|
use tf_demo_parser::ParserState;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -20,7 +18,12 @@ pub struct ActiveEntities {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActiveEntities {
|
impl ActiveEntities {
|
||||||
pub fn handle_message(&mut self, msg: &PacketEntitiesMessage, state: &ParserState, tick: DemoTick) {
|
pub fn handle_message(
|
||||||
|
&mut self,
|
||||||
|
msg: &PacketEntitiesMessage,
|
||||||
|
state: &ParserState,
|
||||||
|
tick: DemoTick,
|
||||||
|
) {
|
||||||
self.max_entities = self.max_entities.max(msg.max_entries);
|
self.max_entities = self.max_entities.max(msg.max_entries);
|
||||||
for entity in &msg.entities {
|
for entity in &msg.entities {
|
||||||
self.removed_entities.remove(&entity.entity_index);
|
self.removed_entities.remove(&entity.entity_index);
|
||||||
|
|
@ -160,7 +163,7 @@ impl ActiveEntities {
|
||||||
},
|
},
|
||||||
serial_number: 0,
|
serial_number: 0,
|
||||||
delay: None,
|
delay: None,
|
||||||
delta: None
|
delta: None,
|
||||||
}))
|
}))
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
self.max_entities,
|
self.max_entities,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ mod entity;
|
||||||
mod string_tables;
|
mod string_tables;
|
||||||
|
|
||||||
use bitbuffer::{BitRead, BitWrite, BitWriteStream, LittleEndian};
|
use bitbuffer::{BitRead, BitWrite, BitWriteStream, LittleEndian};
|
||||||
use std::cmp::{min};
|
use std::cmp::min;
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
|
|
@ -10,19 +10,18 @@ use std::mem::take;
|
||||||
use tf_demo_parser::demo::header::Header;
|
use tf_demo_parser::demo::header::Header;
|
||||||
use tf_demo_parser::demo::message::packetentities::{EntityId, PacketEntitiesMessage, UpdateType};
|
use tf_demo_parser::demo::message::packetentities::{EntityId, PacketEntitiesMessage, UpdateType};
|
||||||
|
|
||||||
|
use tf_demo_parser::demo::data::{DemoTick, ServerTick};
|
||||||
use tf_demo_parser::demo::message::{Message, NetTickMessage};
|
use tf_demo_parser::demo::message::{Message, NetTickMessage};
|
||||||
use tf_demo_parser::demo::packet::message::{MessagePacket};
|
use tf_demo_parser::demo::packet::message::MessagePacket;
|
||||||
use tf_demo_parser::demo::packet::stop::StopPacket;
|
use tf_demo_parser::demo::packet::stop::StopPacket;
|
||||||
use tf_demo_parser::demo::packet::{Packet, PacketType};
|
use tf_demo_parser::demo::packet::{Packet, PacketType};
|
||||||
use tf_demo_parser::demo::parser::{DemoHandler, Encode, NullHandler, RawPacketStream};
|
use tf_demo_parser::demo::parser::{DemoHandler, Encode, NullHandler, RawPacketStream};
|
||||||
use tf_demo_parser::{Demo, ParserState};
|
use tf_demo_parser::{Demo, ParserState};
|
||||||
use tf_demo_parser::demo::data::{DemoTick, ServerTick};
|
|
||||||
|
|
||||||
|
|
||||||
use crate::cut::entity::ActiveEntities;
|
use crate::cut::entity::ActiveEntities;
|
||||||
use crate::cut::string_tables::StringTablesUpdates;
|
use crate::cut::string_tables::StringTablesUpdates;
|
||||||
use crate::mutate::MessageMutator;
|
use crate::mutate::MessageMutator;
|
||||||
use crate::{EditOptions, find_stv, PacketMutator};
|
use crate::{find_stv, EditOptions, PacketMutator};
|
||||||
|
|
||||||
const PRESERVE_PACKETS: &[PacketType] = &[
|
const PRESERVE_PACKETS: &[PacketType] = &[
|
||||||
PacketType::Signon,
|
PacketType::Signon,
|
||||||
|
|
@ -78,10 +77,12 @@ pub fn cut(input: &[u8], options: EditOptions) -> Vec<u8> {
|
||||||
.encode()
|
.encode()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|msg| Message::UpdateStringTable(msg));
|
.map(|msg| Message::UpdateStringTable(msg));
|
||||||
let (baseline_updates, entity_update, removed_update) =
|
let (baseline_updates, entity_update, removed_update) = start_state.entities.encode(
|
||||||
start_state
|
&start_handler.state_handler,
|
||||||
.entities
|
delta_tick - 2,
|
||||||
.encode(&start_handler.state_handler, delta_tick - 2, start_tick, &start_handler.state_handler);
|
start_tick,
|
||||||
|
&start_handler.state_handler,
|
||||||
|
);
|
||||||
let baseline_updates = baseline_updates.into_iter().map(Message::PacketEntities);
|
let baseline_updates = baseline_updates.into_iter().map(Message::PacketEntities);
|
||||||
let start_packets = string_table_updates
|
let start_packets = string_table_updates
|
||||||
.chain(baseline_updates)
|
.chain(baseline_updates)
|
||||||
|
|
@ -105,7 +106,8 @@ pub fn cut(input: &[u8], options: EditOptions) -> Vec<u8> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the net ticks needed for later deltas
|
// create the net ticks needed for later deltas
|
||||||
let fill_ticks = (delta_tick + 1).range_inclusive(start_state.server_tick)
|
let fill_ticks = (delta_tick + 1)
|
||||||
|
.range_inclusive(start_state.server_tick)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|tick| net_tick(tick));
|
.map(|tick| net_tick(tick));
|
||||||
let fill_packets = fill_ticks.map(|msg| {
|
let fill_packets = fill_ticks.map(|msg| {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use tf_demo_parser::demo::message::stringtable::{UpdateStringTableMessage};
|
use tf_demo_parser::demo::message::stringtable::UpdateStringTableMessage;
|
||||||
use tf_demo_parser::demo::message::Message;
|
use tf_demo_parser::demo::message::Message;
|
||||||
use tf_demo_parser::demo::packet::stringtable::StringTableEntry;
|
use tf_demo_parser::demo::packet::stringtable::StringTableEntry;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,10 @@ impl Args {
|
||||||
EditOptions {
|
EditOptions {
|
||||||
unlock_pov: self.unlock_pov,
|
unlock_pov: self.unlock_pov,
|
||||||
cut: if let (Some(from), Some(to)) = (self.from, self.to) {
|
cut: if let (Some(from), Some(to)) = (self.from, self.to) {
|
||||||
Some(TickRange { from: from.into(), to: to.into() })
|
Some(TickRange {
|
||||||
|
from: from.into(),
|
||||||
|
to: to.into(),
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
|
|
@ -30,6 +33,7 @@ impl Args {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
env_logger::init();
|
||||||
let args: Args = Args::parse();
|
let args: Args = Args::parse();
|
||||||
let options = args.get_options();
|
let options = args.get_options();
|
||||||
let file = fs::read(&args.path).unwrap();
|
let file = fs::read(&args.path).unwrap();
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,18 @@
|
||||||
mod mutate;
|
|
||||||
mod pov;
|
|
||||||
mod clean;
|
mod clean;
|
||||||
mod cond;
|
mod cond;
|
||||||
mod cut;
|
mod cut;
|
||||||
|
pub mod missing_preserve;
|
||||||
|
mod mutate;
|
||||||
mod options;
|
mod options;
|
||||||
|
mod pov;
|
||||||
|
|
||||||
use wasm_bindgen::prelude::*;
|
|
||||||
use tf_demo_parser::{Demo, DemoParser};
|
|
||||||
use tf_demo_parser::demo::header::Header;
|
|
||||||
use tf_demo_parser::demo::parser::{RawPacketStream, DemoHandler, Encode};
|
|
||||||
use tf_demo_parser::demo::packet::PacketType;
|
|
||||||
use bitbuffer::{BitRead, BitWriteStream, LittleEndian};
|
use bitbuffer::{BitRead, BitWriteStream, LittleEndian};
|
||||||
|
use tf_demo_parser::demo::header::Header;
|
||||||
use tf_demo_parser::demo::message::packetentities::EntityId;
|
use tf_demo_parser::demo::message::packetentities::EntityId;
|
||||||
|
use tf_demo_parser::demo::packet::PacketType;
|
||||||
|
use tf_demo_parser::demo::parser::{DemoHandler, Encode, RawPacketStream};
|
||||||
|
use tf_demo_parser::{Demo, DemoParser};
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
use bitbuffer::BitWrite;
|
use bitbuffer::BitWrite;
|
||||||
use tf_demo_parser::demo::data::DemoTick;
|
use tf_demo_parser::demo::data::DemoTick;
|
||||||
|
|
@ -20,7 +21,7 @@ use crate::clean::clean_demo;
|
||||||
use crate::cond::strip_cond;
|
use crate::cond::strip_cond;
|
||||||
use crate::cut::cut;
|
use crate::cut::cut;
|
||||||
use crate::mutate::{MutatorList, PacketMutator};
|
use crate::mutate::{MutatorList, PacketMutator};
|
||||||
pub use crate::options::{EditOptions, TickRange, CondOptions};
|
pub use crate::options::{CondOptions, EditOptions, TickRange};
|
||||||
use crate::pov::unlock_pov;
|
use crate::pov::unlock_pov;
|
||||||
|
|
||||||
extern crate web_sys;
|
extern crate web_sys;
|
||||||
|
|
@ -92,7 +93,9 @@ fn no_cut(input: &[u8], options: EditOptions) -> Vec<u8> {
|
||||||
while let Some(mut packet) = packets.next(&handler.state_handler).unwrap() {
|
while let Some(mut packet) = packets.next(&handler.state_handler).unwrap() {
|
||||||
mutators.mutate_packet(&mut packet, &handler.state_handler);
|
mutators.mutate_packet(&mut packet, &handler.state_handler);
|
||||||
|
|
||||||
if packet.packet_type() != PacketType::ConsoleCmd && packet.packet_type() != PacketType::UserCmd {
|
if packet.packet_type() != PacketType::ConsoleCmd
|
||||||
|
&& packet.packet_type() != PacketType::UserCmd
|
||||||
|
{
|
||||||
packet
|
packet
|
||||||
.encode(&mut out_stream, &handler.state_handler)
|
.encode(&mut out_stream, &handler.state_handler)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -106,6 +109,8 @@ fn no_cut(input: &[u8], options: EditOptions) -> Vec<u8> {
|
||||||
fn find_stv(demo: &Demo) -> Option<EntityId> {
|
fn find_stv(demo: &Demo) -> Option<EntityId> {
|
||||||
let parser = DemoParser::new(demo.get_stream());
|
let parser = DemoParser::new(demo.get_stream());
|
||||||
let (_, data) = parser.parse().expect("failed to parse demo");
|
let (_, data) = parser.parse().expect("failed to parse demo");
|
||||||
data.users.values().find(|user| user.steam_id == "BOT")
|
data.users
|
||||||
|
.values()
|
||||||
|
.find(|user| user.steam_id == "BOT")
|
||||||
.map(|user| user.entity_id)
|
.map(|user| user.entity_id)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
71
wasm/src/missing_preserve.rs
Normal file
71
wasm/src/missing_preserve.rs
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
use crate::mutate::MessageMutator;
|
||||||
|
use log::{info, warn};
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
|
use tf_demo_parser::demo::message::packetentities::{EntityId, PacketEntity, UpdateType};
|
||||||
|
use tf_demo_parser::demo::message::Message;
|
||||||
|
use tf_demo_parser::demo::packet::datatable::{ClassId, ServerClass};
|
||||||
|
use tf_demo_parser::ParserState;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct RemoveInvalidPreserveEntity {
|
||||||
|
known_entities: RefCell<BTreeSet<EntityId>>,
|
||||||
|
deferred_delete: RefCell<Vec<EntityId>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RemoveInvalidPreserveEntity {
|
||||||
|
pub fn new() -> RemoveInvalidPreserveEntity {
|
||||||
|
RemoveInvalidPreserveEntity::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageMutator for RemoveInvalidPreserveEntity {
|
||||||
|
fn mutate_message(&self, message: &mut Message, _state: &ParserState) {
|
||||||
|
if let Message::PacketEntities(ent_message) = message {
|
||||||
|
let deferred_deletes = self.deferred_delete.take();
|
||||||
|
for entity in ent_message.entities.iter() {
|
||||||
|
match entity.update_type {
|
||||||
|
UpdateType::Enter => {
|
||||||
|
self.known_entities.borrow_mut().insert(entity.entity_index);
|
||||||
|
}
|
||||||
|
UpdateType::Preserve => {
|
||||||
|
if !self.known_entities.borrow().contains(&entity.entity_index) {
|
||||||
|
warn!("preserving missing entity {}", entity.entity_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UpdateType::Delete => {
|
||||||
|
self.known_entities.borrow_mut().remove(&entity.entity_index);
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
ent_message.removed_entities.retain(|id| {
|
||||||
|
if self.known_entities.borrow().contains(&id) {
|
||||||
|
// just not deleting makes the demo play, but with some ERROR entities
|
||||||
|
// having a Delete or Leave makes it crash further in the demo
|
||||||
|
|
||||||
|
// warn!("inserting delete for {}", id);
|
||||||
|
// only entity_index and update_type is used
|
||||||
|
// ent_message.entities.push(PacketEntity {
|
||||||
|
// entity_index: *id,
|
||||||
|
// server_class: 0.into(),
|
||||||
|
// props: vec![],
|
||||||
|
// in_pvs: false,
|
||||||
|
// update_type: UpdateType::Leave,
|
||||||
|
// serial_number: 0,
|
||||||
|
// delay: None,
|
||||||
|
// delta: None,
|
||||||
|
// baseline_index: 0,
|
||||||
|
// });
|
||||||
|
// self.deferred_delete.borrow_mut().push(*id);
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ent_message.entities.sort_by(|a, b| a.entity_index.cmp(&b.entity_index));
|
||||||
|
ent_message.removed_entities.extend(deferred_deletes);
|
||||||
|
ent_message.removed_entities.sort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -27,7 +27,7 @@ impl<T: MessageMutator> PacketMutator for PacketMessageMutator<T> {
|
||||||
.messages
|
.messages
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.for_each(|msg| self.mutator.mutate_message(msg, state));
|
.for_each(|msg| self.mutator.mutate_message(msg, state));
|
||||||
},
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -114,4 +114,3 @@ impl PacketMutator for MutatorList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
use crate::{clean_demo, strip_cond, unlock_pov, MutatorList};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use tf_demo_parser::demo::data::DemoTick;
|
use tf_demo_parser::demo::data::DemoTick;
|
||||||
use tf_demo_parser::demo::message::packetentities::EntityId;
|
use tf_demo_parser::demo::message::packetentities::EntityId;
|
||||||
use crate::{clean_demo, MutatorList, strip_cond, unlock_pov};
|
|
||||||
use serde::{Serialize, Deserialize};
|
|
||||||
use tf_demo_parser::demo::message::Message;
|
use tf_demo_parser::demo::message::Message;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Default)]
|
#[derive(Debug, Serialize, Deserialize, Default)]
|
||||||
|
|
@ -52,4 +52,4 @@ pub struct CondOptions {
|
||||||
pub struct TickRange {
|
pub struct TickRange {
|
||||||
pub from: DemoTick,
|
pub from: DemoTick,
|
||||||
pub to: DemoTick,
|
pub to: DemoTick,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
|
use crate::mutate::{MessageMutator, MutatorList};
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use tf_demo_parser::demo::message::Message;
|
|
||||||
use tf_demo_parser::demo::message::packetentities::{EntityId, PacketEntity, UpdateType};
|
use tf_demo_parser::demo::message::packetentities::{EntityId, PacketEntity, UpdateType};
|
||||||
use tf_demo_parser::demo::message::usermessage::{UserMessage};
|
use tf_demo_parser::demo::message::usermessage::UserMessage;
|
||||||
|
use tf_demo_parser::demo::message::Message;
|
||||||
use tf_demo_parser::demo::packet::Packet;
|
use tf_demo_parser::demo::packet::Packet;
|
||||||
use tf_demo_parser::ParserState;
|
use tf_demo_parser::ParserState;
|
||||||
use crate::mutate::{MessageMutator, MutatorList};
|
|
||||||
|
|
||||||
struct AddStvEntity {
|
struct AddStvEntity {
|
||||||
added: Cell<bool>,
|
added: Cell<bool>,
|
||||||
|
|
@ -25,7 +25,11 @@ impl MessageMutator for AddStvEntity {
|
||||||
if !self.added.get() {
|
if !self.added.get() {
|
||||||
if let Message::PacketEntities(ent_message) = message {
|
if let Message::PacketEntities(ent_message) = message {
|
||||||
if ent_message.base_line == 0 {
|
if ent_message.base_line == 0 {
|
||||||
let player_entity = ent_message.entities.iter().find(|ent| ent.entity_index >= 1 && ent.entity_index < 255).expect("Failed to find a player entity");
|
let player_entity = ent_message
|
||||||
|
.entities
|
||||||
|
.iter()
|
||||||
|
.find(|ent| ent.entity_index >= 1 && ent.entity_index < 255)
|
||||||
|
.expect("Failed to find a player entity");
|
||||||
if player_entity.entity_index == self.entity_index {
|
if player_entity.entity_index == self.entity_index {
|
||||||
// already stv?
|
// already stv?
|
||||||
self.added.set(true);
|
self.added.set(true);
|
||||||
|
|
@ -42,9 +46,11 @@ impl MessageMutator for AddStvEntity {
|
||||||
serial_number: 1234567,
|
serial_number: 1234567,
|
||||||
delay: None,
|
delay: None,
|
||||||
delta: None,
|
delta: None,
|
||||||
baseline_index: 0
|
baseline_index: 0,
|
||||||
});
|
});
|
||||||
ent_message.entities.sort_by(|a, b| a.entity_index.cmp(&b.entity_index));
|
ent_message
|
||||||
|
.entities
|
||||||
|
.sort_by(|a, b| a.entity_index.cmp(&b.entity_index));
|
||||||
self.added.set(true);
|
self.added.set(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -58,9 +64,7 @@ pub fn unlock_pov(mutators: &mut MutatorList, spectator_id: EntityId) {
|
||||||
info.player_slot = u32::from(spectator_id) as u8 - 1;
|
info.player_slot = u32::from(spectator_id) as u8 - 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mutators.push_message_filter(|message: &Message| {
|
mutators.push_message_filter(|message: &Message| !matches!(message, Message::SetView(_)));
|
||||||
!matches!(message, Message::SetView(_))
|
|
||||||
});
|
|
||||||
mutators.push_message_filter(|message: &Message| {
|
mutators.push_message_filter(|message: &Message| {
|
||||||
!matches!(message, Message::UserMessage(UserMessage::VGuiMenu(_)))
|
!matches!(message, Message::UserMessage(UserMessage::VGuiMenu(_)))
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue