mirror of
https://github.com/vladtrc/iw4L
synced 2026-10-26 02:11:39 -04:00
Remove unused runtime code and dependencies
This commit is contained in:
Generated
-48
@@ -290,7 +290,6 @@ dependencies = [
|
||||
"fastfile_iw4",
|
||||
"fastfile_iw5",
|
||||
"fastfile_t5",
|
||||
"weapon_iw4",
|
||||
"xmodel_runtime",
|
||||
]
|
||||
|
||||
@@ -367,7 +366,6 @@ dependencies = [
|
||||
name = "asset_model"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anim_iw4",
|
||||
"asset_core",
|
||||
"asset_iw4",
|
||||
"asset_material",
|
||||
@@ -415,7 +413,6 @@ dependencies = [
|
||||
"fastfile_t5",
|
||||
"fx_iw4",
|
||||
"lighting_iw4",
|
||||
"trace_iw4",
|
||||
"weapon_iw4",
|
||||
"xmodel_runtime",
|
||||
]
|
||||
@@ -424,7 +421,6 @@ dependencies = [
|
||||
name = "assets"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anim_iw4",
|
||||
"asset_anim",
|
||||
"asset_audio",
|
||||
"asset_core",
|
||||
@@ -435,22 +431,18 @@ dependencies = [
|
||||
"asset_transport",
|
||||
"asset_world",
|
||||
"async-lock",
|
||||
"bcdec_rs",
|
||||
"bevy",
|
||||
"clipmap_iw4",
|
||||
"diag",
|
||||
"dpvs_iw4",
|
||||
"fastfile_iw4",
|
||||
"fastfile_iw5",
|
||||
"fastfile_t5",
|
||||
"frame",
|
||||
"fx_iw4",
|
||||
"libc",
|
||||
"lighting_iw4",
|
||||
"png",
|
||||
"render_material",
|
||||
"serde_json",
|
||||
"trace_iw4",
|
||||
"weapon_iw4",
|
||||
"xmodel_runtime",
|
||||
]
|
||||
@@ -577,14 +569,12 @@ dependencies = [
|
||||
"frame",
|
||||
"gamemode_iw4",
|
||||
"hud_iw4",
|
||||
"killcam_iw4",
|
||||
"movement_iw4",
|
||||
"net",
|
||||
"perf",
|
||||
"playerstate_iw4",
|
||||
"sim",
|
||||
"symphonia",
|
||||
"weapon_iw4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1978,7 +1968,6 @@ dependencies = [
|
||||
"entity_iw4",
|
||||
"frame",
|
||||
"gamemode_iw4",
|
||||
"glam",
|
||||
"math_iw4",
|
||||
"movement_iw4",
|
||||
"net",
|
||||
@@ -2185,15 +2174,12 @@ dependencies = [
|
||||
"bevy",
|
||||
"bots",
|
||||
"diag",
|
||||
"dpvs_iw4",
|
||||
"entity_iw4",
|
||||
"frame",
|
||||
"hud",
|
||||
"input_iw4",
|
||||
"math_iw4",
|
||||
"net",
|
||||
"perf",
|
||||
"playerstate_iw4",
|
||||
"render",
|
||||
"render_frontend",
|
||||
"render_fx",
|
||||
@@ -3252,7 +3238,6 @@ dependencies = [
|
||||
"frame",
|
||||
"gamemode_iw4",
|
||||
"hud_iw4",
|
||||
"killcam_iw4",
|
||||
"math_iw4",
|
||||
"movement_iw4",
|
||||
"net",
|
||||
@@ -3505,7 +3490,6 @@ dependencies = [
|
||||
"rustls-pemfile",
|
||||
"rustls-platform-verifier",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3612,7 +3596,6 @@ name = "launcher"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"asset_transport",
|
||||
"assets",
|
||||
"bootstrap",
|
||||
"diag",
|
||||
]
|
||||
@@ -5003,35 +4986,16 @@ checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
|
||||
name = "render"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anim_iw4",
|
||||
"asset_iw4",
|
||||
"asset_world",
|
||||
"assets",
|
||||
"audio",
|
||||
"bevy",
|
||||
"bytemuck",
|
||||
"d3d9_sm3",
|
||||
"d3d9_state",
|
||||
"diag",
|
||||
"dpvs_iw4",
|
||||
"entity_iw4",
|
||||
"fastfile_iw4",
|
||||
"frame",
|
||||
"fx",
|
||||
"fx_iw4",
|
||||
"gamemode_iw4",
|
||||
"hud",
|
||||
"hud_iw4",
|
||||
"lighting_iw4",
|
||||
"marks_iw4",
|
||||
"math_iw4",
|
||||
"miniz_oxide",
|
||||
"naga",
|
||||
"net",
|
||||
"perf",
|
||||
"playerstate_iw4",
|
||||
"render_anim",
|
||||
"render_backend",
|
||||
"render_frame",
|
||||
"render_frontend",
|
||||
"render_fx",
|
||||
@@ -5039,8 +5003,6 @@ dependencies = [
|
||||
"render_scene",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sim",
|
||||
"weapon_iw4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5066,7 +5028,6 @@ dependencies = [
|
||||
"frame",
|
||||
"fx",
|
||||
"fx_iw4",
|
||||
"gamemode_iw4",
|
||||
"hud_iw4",
|
||||
"lighting_iw4",
|
||||
"math_iw4",
|
||||
@@ -5125,17 +5086,14 @@ dependencies = [
|
||||
"audio",
|
||||
"bevy",
|
||||
"bytemuck",
|
||||
"d3d9_decl",
|
||||
"d3d9_sm3",
|
||||
"d3d9_state",
|
||||
"diag",
|
||||
"dpvs_iw4",
|
||||
"entity_iw4",
|
||||
"fastfile_iw4",
|
||||
"frame",
|
||||
"fx",
|
||||
"fx_iw4",
|
||||
"gamemode_iw4",
|
||||
"hud_iw4",
|
||||
"lighting_iw4",
|
||||
"marks_iw4",
|
||||
@@ -5143,7 +5101,6 @@ dependencies = [
|
||||
"naga",
|
||||
"net",
|
||||
"perf",
|
||||
"playerstate_iw4",
|
||||
"render_anim",
|
||||
"render_frame",
|
||||
"render_fx",
|
||||
@@ -5194,7 +5151,6 @@ dependencies = [
|
||||
"assets",
|
||||
"bevy",
|
||||
"bytemuck",
|
||||
"d3d9_decl",
|
||||
"d3d9_sm3",
|
||||
"d3d9_state",
|
||||
"diag",
|
||||
@@ -5258,7 +5214,6 @@ dependencies = [
|
||||
"diag",
|
||||
"frame",
|
||||
"getrandom 0.3.4",
|
||||
"movement_iw4",
|
||||
"net",
|
||||
"perf",
|
||||
"playerstate_iw4",
|
||||
@@ -5577,7 +5532,6 @@ dependencies = [
|
||||
"assets",
|
||||
"audio",
|
||||
"bevy",
|
||||
"bots",
|
||||
"clipmap_iw4",
|
||||
"diag",
|
||||
"frame",
|
||||
@@ -5585,7 +5539,6 @@ dependencies = [
|
||||
"hud_iw4",
|
||||
"net",
|
||||
"perf",
|
||||
"render",
|
||||
"render_frontend",
|
||||
"render_fx",
|
||||
"sim",
|
||||
@@ -6299,7 +6252,6 @@ dependencies = [
|
||||
"diag",
|
||||
"frame",
|
||||
"net",
|
||||
"session",
|
||||
"sim",
|
||||
]
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ anim_iw4.workspace = true
|
||||
fastfile_iw4.workspace = true
|
||||
fastfile_iw5.workspace = true
|
||||
fastfile_t5.workspace = true
|
||||
weapon_iw4.workspace = true
|
||||
xmodel_runtime.workspace = true
|
||||
bevy.workspace = true
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ description = "XModel, skeleton, mesh, lighting, FPV, body, and projectile produ
|
||||
asset_core.workspace = true
|
||||
asset_material.workspace = true
|
||||
asset_iw4.workspace = true
|
||||
anim_iw4.workspace = true
|
||||
fastfile_iw4.workspace = true
|
||||
fastfile_iw5.workspace = true
|
||||
fastfile_t5.workspace = true
|
||||
|
||||
@@ -16,7 +16,6 @@ fastfile_iw5.workspace = true
|
||||
fastfile_t5.workspace = true
|
||||
dpvs_iw4.workspace = true
|
||||
clipmap_iw4.workspace = true
|
||||
trace_iw4.workspace = true
|
||||
lighting_iw4.workspace = true
|
||||
fx_iw4.workspace = true
|
||||
weapon_iw4.workspace = true
|
||||
|
||||
@@ -8,7 +8,6 @@ description = "Asset lane orchestration, linking and conversion into engine obje
|
||||
[dependencies]
|
||||
render_material.workspace = true
|
||||
diag.workspace = true
|
||||
anim_iw4.workspace = true
|
||||
xmodel_runtime.workspace = true
|
||||
asset_core.workspace = true
|
||||
asset_anim.workspace = true
|
||||
@@ -23,15 +22,11 @@ fastfile_iw4.workspace = true
|
||||
fastfile_t5.workspace = true
|
||||
fastfile_iw5.workspace = true
|
||||
asset_iw4.workspace = true
|
||||
dpvs_iw4.workspace = true
|
||||
clipmap_iw4.workspace = true
|
||||
trace_iw4.workspace = true
|
||||
# Light-grid CPU sample chain for authored smodel `$model_lighting` tiles.
|
||||
lighting_iw4.workspace = true
|
||||
fx_iw4.workspace = true
|
||||
bevy.workspace = true
|
||||
frame.workspace = true
|
||||
bcdec_rs.workspace = true
|
||||
serde_json.workspace = true
|
||||
async-lock.workspace = true
|
||||
png.workspace = true
|
||||
|
||||
@@ -14,7 +14,6 @@ asset_game.workspace = true
|
||||
asset_transport.workspace = true
|
||||
assets.workspace = true
|
||||
asset_iw4.workspace = true
|
||||
weapon_iw4.workspace = true
|
||||
movement_iw4.workspace = true
|
||||
frame.workspace = true
|
||||
entity_iw4.workspace = true
|
||||
@@ -22,7 +21,6 @@ net.workspace = true
|
||||
sim.workspace = true
|
||||
hud_iw4 = { path = "../hud_iw4" }
|
||||
playerstate_iw4.workspace = true
|
||||
killcam_iw4.workspace = true
|
||||
gamemode_iw4.workspace = true
|
||||
perf.workspace = true
|
||||
symphonia = { version = "0.5", default-features = false, features = ["mp3", "pcm", "wav", "adpcm"] }
|
||||
|
||||
@@ -19,7 +19,6 @@ movement_iw4 = { path = "../movement_iw4" }
|
||||
weapon_iw4 = { path = "../weapon_iw4" }
|
||||
math_iw4 = { path = "../math_iw4" }
|
||||
trace_iw4.workspace = true
|
||||
glam.workspace = true
|
||||
gamemode_iw4.workspace = true
|
||||
|
||||
[lints]
|
||||
|
||||
@@ -7,8 +7,6 @@ description = "Our console: input, parsing, execution, cvar storage, coverage re
|
||||
|
||||
[dependencies]
|
||||
diag.workspace = true
|
||||
math_iw4.workspace = true
|
||||
dpvs_iw4.workspace = true
|
||||
bevy.workspace = true
|
||||
frame.workspace = true
|
||||
ui.workspace = true
|
||||
@@ -19,7 +17,6 @@ asset_world.workspace = true
|
||||
assets = { path = "../assets" }
|
||||
audio = { path = "../audio" }
|
||||
input_iw4.workspace = true
|
||||
playerstate_iw4.workspace = true
|
||||
net = { path = "../net" }
|
||||
render = { path = "../render" }
|
||||
render_frontend.workspace = true
|
||||
|
||||
@@ -5,7 +5,6 @@ mod asset_type;
|
||||
mod content;
|
||||
mod envelope;
|
||||
mod load;
|
||||
pub mod shader;
|
||||
mod stream;
|
||||
mod wire;
|
||||
mod zone;
|
||||
|
||||
@@ -1,736 +0,0 @@
|
||||
use core::fmt;
|
||||
|
||||
const END: u16 = 0xffff;
|
||||
const COMMENT: u16 = 0xfffe;
|
||||
const CTAB: u32 = 0x4241_5443;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum ShaderKind {
|
||||
Pixel,
|
||||
Vertex,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct ShaderVersion {
|
||||
pub kind: ShaderKind,
|
||||
pub major: u8,
|
||||
pub minor: u8,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum ShaderError {
|
||||
Empty,
|
||||
UnalignedBytes(usize),
|
||||
UnsupportedVersion(u32),
|
||||
Truncated {
|
||||
at_word: usize,
|
||||
needed: usize,
|
||||
have: usize,
|
||||
},
|
||||
MissingEnd,
|
||||
TrailingWords(usize),
|
||||
MalformedCtab,
|
||||
}
|
||||
|
||||
impl fmt::Display for ShaderError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Empty => f.write_str("shader has no version token"),
|
||||
Self::UnalignedBytes(len) => write!(f, "shader length {len} is not DWORD-aligned"),
|
||||
Self::UnsupportedVersion(version) => {
|
||||
write!(f, "unsupported shader version {version:#010x}")
|
||||
}
|
||||
Self::Truncated {
|
||||
at_word,
|
||||
needed,
|
||||
have,
|
||||
} => write!(
|
||||
f,
|
||||
"token at word {at_word} needs {needed} words, only {have} remain"
|
||||
),
|
||||
Self::MissingEnd => f.write_str("shader has no END token"),
|
||||
Self::TrailingWords(words) => write!(f, "END is followed by {words} words"),
|
||||
Self::MalformedCtab => f.write_str("malformed CTAB comment"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Shader<'a> {
|
||||
bytes: &'a [u8],
|
||||
version: ShaderVersion,
|
||||
}
|
||||
|
||||
impl<'a> Shader<'a> {
|
||||
pub fn parse(bytes: &'a [u8]) -> Result<Self, ShaderError> {
|
||||
if bytes.is_empty() {
|
||||
return Err(ShaderError::Empty);
|
||||
}
|
||||
if !bytes.len().is_multiple_of(4) {
|
||||
return Err(ShaderError::UnalignedBytes(bytes.len()));
|
||||
}
|
||||
let version_word = word(bytes, 0).ok_or(ShaderError::Empty)?;
|
||||
let kind = match version_word >> 16 {
|
||||
0xffff => ShaderKind::Pixel,
|
||||
0xfffe => ShaderKind::Vertex,
|
||||
_ => return Err(ShaderError::UnsupportedVersion(version_word)),
|
||||
};
|
||||
let version = ShaderVersion {
|
||||
kind,
|
||||
major: ((version_word >> 8) & 0xff) as u8,
|
||||
minor: (version_word & 0xff) as u8,
|
||||
};
|
||||
if version.major != 3 || version.minor != 0 {
|
||||
return Err(ShaderError::UnsupportedVersion(version_word));
|
||||
}
|
||||
|
||||
let words = bytes.len() / 4;
|
||||
let mut at = 1;
|
||||
loop {
|
||||
let token = word(bytes, at).ok_or(ShaderError::MissingEnd)?;
|
||||
let opcode = token as u16;
|
||||
if opcode == END {
|
||||
let trailing = words - at - 1;
|
||||
return if trailing == 0 {
|
||||
Ok(Self { bytes, version })
|
||||
} else {
|
||||
Err(ShaderError::TrailingWords(trailing))
|
||||
};
|
||||
}
|
||||
let operand_words = if opcode == COMMENT {
|
||||
((token >> 16) & 0x7fff) as usize
|
||||
} else {
|
||||
((token >> 24) & 0x0f) as usize
|
||||
};
|
||||
let needed = operand_words + 1;
|
||||
let have = words - at;
|
||||
if have < needed {
|
||||
return Err(ShaderError::Truncated {
|
||||
at_word: at,
|
||||
needed,
|
||||
have,
|
||||
});
|
||||
}
|
||||
at += needed;
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn version(self) -> ShaderVersion {
|
||||
self.version
|
||||
}
|
||||
|
||||
pub const fn bytes(self) -> &'a [u8] {
|
||||
self.bytes
|
||||
}
|
||||
|
||||
pub const fn word_len(self) -> usize {
|
||||
self.bytes.len() / 4
|
||||
}
|
||||
|
||||
pub fn instructions(self) -> Instructions<'a> {
|
||||
Instructions {
|
||||
bytes: self.bytes,
|
||||
at: 1,
|
||||
done: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ctab(self) -> Result<Option<ConstantTable<'a>>, ShaderError> {
|
||||
for instruction in self.instructions() {
|
||||
let instruction = instruction?;
|
||||
let Some(comment) = instruction.comment_data() else {
|
||||
continue;
|
||||
};
|
||||
for offset in (0..comment.len()).step_by(4) {
|
||||
if word(comment, offset / 4) == Some(CTAB) {
|
||||
return ConstantTable::parse(&comment[offset + 4..]).map(Some);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub fn disassembly(self) -> Disassembly<'a> {
|
||||
Disassembly { shader: self }
|
||||
}
|
||||
}
|
||||
|
||||
fn word(bytes: &[u8], index: usize) -> Option<u32> {
|
||||
let at = index.checked_mul(4)?;
|
||||
let bytes: [u8; 4] = bytes.get(at..at + 4)?.try_into().ok()?;
|
||||
Some(u32::from_le_bytes(bytes))
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Instructions<'a> {
|
||||
bytes: &'a [u8],
|
||||
at: usize,
|
||||
done: bool,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Instructions<'a> {
|
||||
type Item = Result<Instruction<'a>, ShaderError>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.done {
|
||||
return None;
|
||||
}
|
||||
let token = word(self.bytes, self.at)?;
|
||||
let opcode = token as u16;
|
||||
if opcode == END {
|
||||
self.done = true;
|
||||
return Some(Ok(Instruction {
|
||||
token,
|
||||
operands: &[],
|
||||
at_word: self.at,
|
||||
}));
|
||||
}
|
||||
let count = if opcode == COMMENT {
|
||||
((token >> 16) & 0x7fff) as usize
|
||||
} else {
|
||||
((token >> 24) & 0x0f) as usize
|
||||
};
|
||||
let next = match self.at.checked_add(count + 1) {
|
||||
Some(next) => next,
|
||||
None => {
|
||||
return Some(Err(ShaderError::Truncated {
|
||||
at_word: self.at,
|
||||
needed: count + 1,
|
||||
have: 0,
|
||||
}));
|
||||
}
|
||||
};
|
||||
let operands = match self.bytes.get((self.at + 1) * 4..next * 4) {
|
||||
Some(operands) => operands,
|
||||
None => {
|
||||
return Some(Err(ShaderError::Truncated {
|
||||
at_word: self.at,
|
||||
needed: count + 1,
|
||||
have: self.bytes.len() / 4 - self.at,
|
||||
}));
|
||||
}
|
||||
};
|
||||
let instruction = Instruction {
|
||||
token,
|
||||
operands,
|
||||
at_word: self.at,
|
||||
};
|
||||
self.at = next;
|
||||
Some(Ok(instruction))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Instruction<'a> {
|
||||
token: u32,
|
||||
operands: &'a [u8],
|
||||
at_word: usize,
|
||||
}
|
||||
|
||||
impl<'a> Instruction<'a> {
|
||||
pub const fn at_word(self) -> usize {
|
||||
self.at_word
|
||||
}
|
||||
|
||||
pub const fn opcode(self) -> Opcode {
|
||||
Opcode(self.token as u16)
|
||||
}
|
||||
|
||||
pub const fn raw_token(self) -> u32 {
|
||||
self.token
|
||||
}
|
||||
|
||||
pub const fn predicated(self) -> bool {
|
||||
self.token & 0x1000_0000 != 0
|
||||
}
|
||||
|
||||
pub const fn coissue(self) -> bool {
|
||||
self.token & 0x4000_0000 != 0
|
||||
}
|
||||
|
||||
pub const fn operand_len(self) -> usize {
|
||||
self.operands.len() / 4
|
||||
}
|
||||
|
||||
pub fn operand(self, index: usize) -> Option<u32> {
|
||||
word(self.operands, index)
|
||||
}
|
||||
|
||||
pub fn comment_data(self) -> Option<&'a [u8]> {
|
||||
(self.opcode().0 == COMMENT).then_some(self.operands)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct Opcode(u16);
|
||||
|
||||
impl Opcode {
|
||||
pub const fn from_raw(raw: u16) -> Self {
|
||||
Self(raw)
|
||||
}
|
||||
|
||||
pub const fn raw(self) -> u16 {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub const fn name(self) -> Option<&'static str> {
|
||||
Some(match self.0 {
|
||||
0x00 => "nop",
|
||||
0x01 => "mov",
|
||||
0x02 => "add",
|
||||
0x03 => "sub",
|
||||
0x04 => "mad",
|
||||
0x05 => "mul",
|
||||
0x06 => "rcp",
|
||||
0x07 => "rsq",
|
||||
0x08 => "dp3",
|
||||
0x09 => "dp4",
|
||||
0x0a => "min",
|
||||
0x0b => "max",
|
||||
0x0c => "slt",
|
||||
0x0d => "sge",
|
||||
0x0e => "exp",
|
||||
0x0f => "log",
|
||||
0x10 => "lit",
|
||||
0x11 => "dst",
|
||||
0x12 => "lrp",
|
||||
0x13 => "frc",
|
||||
0x14 => "m4x4",
|
||||
0x15 => "m4x3",
|
||||
0x16 => "m3x4",
|
||||
0x17 => "m3x3",
|
||||
0x18 => "m3x2",
|
||||
0x19 => "call",
|
||||
0x1a => "callnz",
|
||||
0x1b => "loop",
|
||||
0x1c => "ret",
|
||||
0x1d => "endloop",
|
||||
0x1e => "label",
|
||||
0x1f => "dcl",
|
||||
0x20 => "pow",
|
||||
0x21 => "crs",
|
||||
0x22 => "sgn",
|
||||
0x23 => "abs",
|
||||
0x24 => "nrm",
|
||||
0x25 => "sincos",
|
||||
0x26 => "rep",
|
||||
0x27 => "endrep",
|
||||
0x28 => "if",
|
||||
0x29 => "ifc",
|
||||
0x2a => "else",
|
||||
0x2b => "endif",
|
||||
0x2c => "break",
|
||||
0x2d => "breakc",
|
||||
0x2e => "mova",
|
||||
0x2f => "defb",
|
||||
0x30 => "defi",
|
||||
0x40 => "texcoord",
|
||||
0x41 => "texkill",
|
||||
0x42 => "texld",
|
||||
0x4e => "expp",
|
||||
0x4f => "logp",
|
||||
0x50 => "cnd",
|
||||
0x51 => "def",
|
||||
0x58 => "cmp",
|
||||
0x59 => "bem",
|
||||
0x5a => "dp2add",
|
||||
0x5b => "dsx",
|
||||
0x5c => "dsy",
|
||||
0x5d => "texldd",
|
||||
0x5e => "setp",
|
||||
0x5f => "texldl",
|
||||
0x60 => "breakp",
|
||||
END => "end",
|
||||
COMMENT => "comment",
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
const fn source_only(self) -> bool {
|
||||
matches!(
|
||||
self.0,
|
||||
0x19 | 0x1a | 0x1b | 0x1e | 0x28 | 0x29 | 0x2d | 0x26 | 0x60
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct ConstantTable<'a> {
|
||||
bytes: &'a [u8],
|
||||
constant_count: u32,
|
||||
constant_info_offset: u32,
|
||||
}
|
||||
|
||||
impl<'a> ConstantTable<'a> {
|
||||
fn parse(bytes: &'a [u8]) -> Result<Self, ShaderError> {
|
||||
if bytes.len() < 28 || word(bytes, 0) != Some(28) {
|
||||
return Err(ShaderError::MalformedCtab);
|
||||
}
|
||||
let constant_count = word(bytes, 3).ok_or(ShaderError::MalformedCtab)?;
|
||||
let constant_info_offset = word(bytes, 4).ok_or(ShaderError::MalformedCtab)?;
|
||||
let entries_end = (constant_info_offset as usize)
|
||||
.checked_add((constant_count as usize).saturating_mul(20))
|
||||
.ok_or(ShaderError::MalformedCtab)?;
|
||||
if entries_end > bytes.len() {
|
||||
return Err(ShaderError::MalformedCtab);
|
||||
}
|
||||
Ok(Self {
|
||||
bytes,
|
||||
constant_count,
|
||||
constant_info_offset,
|
||||
})
|
||||
}
|
||||
|
||||
pub const fn len(self) -> usize {
|
||||
self.constant_count as usize
|
||||
}
|
||||
|
||||
pub const fn is_empty(self) -> bool {
|
||||
self.constant_count == 0
|
||||
}
|
||||
|
||||
pub fn constant(self, index: usize) -> Result<Constant<'a>, ShaderError> {
|
||||
if index >= self.len() {
|
||||
return Err(ShaderError::MalformedCtab);
|
||||
}
|
||||
let at = self.constant_info_offset as usize + index * 20;
|
||||
let name_offset = word_at(self.bytes, at)?;
|
||||
let register_set = u16_at(self.bytes, at + 4)?;
|
||||
let register_index = u16_at(self.bytes, at + 6)?;
|
||||
let register_count = u16_at(self.bytes, at + 8)?;
|
||||
let name = c_string_at(self.bytes, name_offset as usize)?;
|
||||
Ok(Constant {
|
||||
name,
|
||||
register_set,
|
||||
register_index,
|
||||
register_count,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn register_name(
|
||||
self,
|
||||
register_set: u16,
|
||||
register: u16,
|
||||
) -> Result<Option<&'a [u8]>, ShaderError> {
|
||||
for index in 0..self.len() {
|
||||
let constant = self.constant(index)?;
|
||||
if constant.register_set == register_set
|
||||
&& register >= constant.register_index
|
||||
&& register
|
||||
< constant
|
||||
.register_index
|
||||
.saturating_add(constant.register_count)
|
||||
{
|
||||
return Ok(Some(constant.name));
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
fn word_at(bytes: &[u8], at: usize) -> Result<u32, ShaderError> {
|
||||
let bytes: [u8; 4] = bytes
|
||||
.get(at..at + 4)
|
||||
.ok_or(ShaderError::MalformedCtab)?
|
||||
.try_into()
|
||||
.map_err(|_| ShaderError::MalformedCtab)?;
|
||||
Ok(u32::from_le_bytes(bytes))
|
||||
}
|
||||
|
||||
fn u16_at(bytes: &[u8], at: usize) -> Result<u16, ShaderError> {
|
||||
let bytes: [u8; 2] = bytes
|
||||
.get(at..at + 2)
|
||||
.ok_or(ShaderError::MalformedCtab)?
|
||||
.try_into()
|
||||
.map_err(|_| ShaderError::MalformedCtab)?;
|
||||
Ok(u16::from_le_bytes(bytes))
|
||||
}
|
||||
|
||||
fn c_string_at(bytes: &[u8], at: usize) -> Result<&[u8], ShaderError> {
|
||||
let bytes = bytes.get(at..).ok_or(ShaderError::MalformedCtab)?;
|
||||
let end = bytes
|
||||
.iter()
|
||||
.position(|&byte| byte == 0)
|
||||
.ok_or(ShaderError::MalformedCtab)?;
|
||||
Ok(&bytes[..end])
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Constant<'a> {
|
||||
pub name: &'a [u8],
|
||||
pub register_set: u16,
|
||||
pub register_index: u16,
|
||||
pub register_count: u16,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Disassembly<'a> {
|
||||
shader: Shader<'a>,
|
||||
}
|
||||
|
||||
impl fmt::Display for Disassembly<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let version = self.shader.version();
|
||||
let kind = match version.kind {
|
||||
ShaderKind::Pixel => "ps",
|
||||
ShaderKind::Vertex => "vs",
|
||||
};
|
||||
writeln!(f, "{kind}_{}_{}", version.major, version.minor)?;
|
||||
let ctab = self.shader.ctab().map_err(|_| fmt::Error)?;
|
||||
if let Some(ctab) = ctab {
|
||||
writeln!(f, "; {} named constants/samplers", ctab.len())?;
|
||||
} else {
|
||||
writeln!(f, "; 0 named constants/samplers")?;
|
||||
}
|
||||
for instruction in self.shader.instructions() {
|
||||
let instruction = instruction.map_err(|_| fmt::Error)?;
|
||||
if instruction.comment_data().is_some() {
|
||||
continue;
|
||||
}
|
||||
format_instruction(f, instruction, ctab)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn format_instruction(
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
instruction: Instruction<'_>,
|
||||
ctab: Option<ConstantTable<'_>>,
|
||||
) -> fmt::Result {
|
||||
let opcode = instruction.opcode();
|
||||
let name = opcode.name().unwrap_or("unknown");
|
||||
if opcode.0 == END {
|
||||
return writeln!(f, "end");
|
||||
}
|
||||
if opcode.0 == 0x51 && instruction.operand_len() == 5 {
|
||||
write!(f, " def ")?;
|
||||
format_register(f, instruction.operand(0).ok_or(fmt::Error)?, ctab, true)?;
|
||||
for index in 1..5 {
|
||||
let value = f32::from_bits(instruction.operand(index).ok_or(fmt::Error)?);
|
||||
f.write_str(", ")?;
|
||||
format_float_g6(f, value)?;
|
||||
}
|
||||
return writeln!(f);
|
||||
}
|
||||
if opcode.0 == 0x1f {
|
||||
write!(f, " dcl ")?;
|
||||
if instruction.operand_len() >= 2 {
|
||||
format_register(f, instruction.operand(1).ok_or(fmt::Error)?, ctab, true)?;
|
||||
return writeln!(
|
||||
f,
|
||||
" ; usage {:#x}",
|
||||
instruction.operand(0).ok_or(fmt::Error)?
|
||||
);
|
||||
}
|
||||
if instruction.operand_len() == 1 {
|
||||
format_register(f, instruction.operand(0).ok_or(fmt::Error)?, ctab, true)?;
|
||||
}
|
||||
return writeln!(f);
|
||||
}
|
||||
let comparison = match (opcode.0, (instruction.token >> 16) & 7) {
|
||||
(0x29 | 0x2d, 1) => "_gt",
|
||||
(0x29 | 0x2d, 2) => "_eq",
|
||||
(0x29 | 0x2d, 3) => "_ge",
|
||||
(0x29 | 0x2d, 4) => "_lt",
|
||||
(0x29 | 0x2d, 5) => "_ne",
|
||||
(0x29 | 0x2d, 6) => "_le",
|
||||
_ => "",
|
||||
};
|
||||
write!(f, " {name}{comparison}")?;
|
||||
let has_destination = !opcode.source_only() && instruction.operand_len() > 0;
|
||||
if has_destination {
|
||||
let dest = instruction.operand(0).ok_or(fmt::Error)?;
|
||||
format_destination_modifiers(f, dest)?;
|
||||
write!(f, " ")?;
|
||||
format_register(f, dest, ctab, true)?;
|
||||
}
|
||||
let start = usize::from(has_destination);
|
||||
if !has_destination && instruction.operand_len() > 0 {
|
||||
write!(f, " ")?;
|
||||
} else if has_destination && instruction.operand_len() > start {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
for index in start..instruction.operand_len() {
|
||||
if index > start {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
let operand = instruction.operand(index).ok_or(fmt::Error)?;
|
||||
format_source(f, operand, ctab)?;
|
||||
}
|
||||
writeln!(f)
|
||||
}
|
||||
|
||||
fn format_destination_modifiers(f: &mut fmt::Formatter<'_>, token: u32) -> fmt::Result {
|
||||
let modifiers = (token >> 20) & 0x0f;
|
||||
if modifiers & 1 != 0 {
|
||||
f.write_str("_sat")?;
|
||||
}
|
||||
if modifiers & 2 != 0 {
|
||||
f.write_str("_pp")?;
|
||||
}
|
||||
if modifiers & 4 != 0 {
|
||||
f.write_str("_centroid")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn format_register(
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
token: u32,
|
||||
ctab: Option<ConstantTable<'_>>,
|
||||
destination: bool,
|
||||
) -> fmt::Result {
|
||||
let register = (token & 0x7ff) as u16;
|
||||
let register_type = (((token & 0x7000_0000) >> 28) | ((token & 0x0000_1800) >> 8)) as u16;
|
||||
let name = match register_type {
|
||||
0 => "r",
|
||||
1 => "v",
|
||||
2 | 11 | 12 | 13 => "c",
|
||||
3 => "t",
|
||||
4 => "oPos",
|
||||
5 => "oD",
|
||||
6 => "o",
|
||||
7 => "i",
|
||||
8 => "oC",
|
||||
9 => "oDepth",
|
||||
10 => "s",
|
||||
14 => "b",
|
||||
15 => "aL",
|
||||
16 => "rf16",
|
||||
17 => "misc",
|
||||
18 => "label",
|
||||
19 => "p",
|
||||
_ => "?",
|
||||
};
|
||||
let no_number = matches!(register_type, 4 | 9 | 15);
|
||||
write!(f, "{name}")?;
|
||||
if !no_number {
|
||||
write!(f, "{register}")?;
|
||||
}
|
||||
let ctab_set = match name {
|
||||
"c" => Some(2),
|
||||
"s" => Some(3),
|
||||
"b" => Some(0),
|
||||
"i" => Some(1),
|
||||
_ => None,
|
||||
};
|
||||
if let (Some(ctab), Some(set)) = (ctab, ctab_set)
|
||||
&& let Ok(Some(constant)) = ctab.register_name(set, register)
|
||||
&& let Ok(constant) = core::str::from_utf8(constant)
|
||||
{
|
||||
write!(f, "[{constant}]")?;
|
||||
}
|
||||
if destination {
|
||||
let mask = (token >> 16) & 0x0f;
|
||||
if mask != 0x0f {
|
||||
f.write_str(".")?;
|
||||
for (bit, component) in [(1, 'x'), (2, 'y'), (4, 'z'), (8, 'w')] {
|
||||
if mask & bit != 0 {
|
||||
write!(f, "{component}")?;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let swizzle = (token >> 16) & 0xff;
|
||||
if swizzle != 0xe4 {
|
||||
let components = ['x', 'y', 'z', 'w'];
|
||||
let first = components[(swizzle & 3) as usize];
|
||||
let splat = (1..4).all(|index| ((swizzle >> (index * 2)) & 3) == (swizzle & 3));
|
||||
write!(f, ".{first}")?;
|
||||
if !splat {
|
||||
for index in 1..4 {
|
||||
write!(f, "{}", components[((swizzle >> (index * 2)) & 3) as usize])?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn format_source(
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
token: u32,
|
||||
ctab: Option<ConstantTable<'_>>,
|
||||
) -> fmt::Result {
|
||||
match (token >> 24) & 0x0f {
|
||||
0 => format_register(f, token, ctab, false),
|
||||
1 => {
|
||||
f.write_str("-")?;
|
||||
format_register(f, token, ctab, false)
|
||||
}
|
||||
3 => {
|
||||
f.write_str("|")?;
|
||||
format_register(f, token, ctab, false)?;
|
||||
f.write_str("|")
|
||||
}
|
||||
4 => {
|
||||
f.write_str("-|")?;
|
||||
format_register(f, token, ctab, false)?;
|
||||
f.write_str("|")
|
||||
}
|
||||
|
||||
_ => format_register(f, token, ctab, false),
|
||||
}
|
||||
}
|
||||
|
||||
fn format_float_g6(f: &mut fmt::Formatter<'_>, value: f32) -> fmt::Result {
|
||||
if value == 0.0 {
|
||||
return f.write_str("0");
|
||||
}
|
||||
if !value.is_finite() {
|
||||
return write!(f, "{value}");
|
||||
}
|
||||
let negative = value.is_sign_negative();
|
||||
let absolute = value.abs();
|
||||
let mut precision = 0usize;
|
||||
if absolute >= 1.0 {
|
||||
let mut whole = absolute as u64;
|
||||
let mut digits = 1usize;
|
||||
while whole >= 10 {
|
||||
whole /= 10;
|
||||
digits += 1;
|
||||
}
|
||||
precision = 6usize.saturating_sub(digits);
|
||||
} else {
|
||||
let mut scaled = absolute;
|
||||
while scaled < 1.0 {
|
||||
scaled *= 10.0;
|
||||
precision += 1;
|
||||
}
|
||||
precision += 5;
|
||||
}
|
||||
let mut scale = 1u64;
|
||||
for _ in 0..precision {
|
||||
scale = scale.saturating_mul(10);
|
||||
}
|
||||
let mut rounded = (absolute * scale as f32 + 0.5) as u64;
|
||||
while precision > 0 && rounded.is_multiple_of(10) {
|
||||
rounded /= 10;
|
||||
scale /= 10;
|
||||
precision -= 1;
|
||||
}
|
||||
if negative {
|
||||
f.write_str("-")?;
|
||||
}
|
||||
if precision == 0 {
|
||||
return write!(f, "{rounded}");
|
||||
}
|
||||
if rounded < scale {
|
||||
f.write_str("0.")?;
|
||||
let mut padding = scale / 10;
|
||||
while padding > rounded && padding > 1 {
|
||||
f.write_str("0")?;
|
||||
padding /= 10;
|
||||
}
|
||||
return write!(f, "{rounded}");
|
||||
}
|
||||
write!(f, "{}.", rounded / scale)?;
|
||||
let fraction = rounded % scale;
|
||||
let mut padding = scale / 10;
|
||||
while padding > fraction && padding > 1 {
|
||||
f.write_str("0")?;
|
||||
padding /= 10;
|
||||
}
|
||||
write!(f, "{fraction}")
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
use crate::{AssetType, Ptr, XFILE_BLOCK_VIRTUAL, XFILE_HEADER_LEN, parse_zone_header};
|
||||
use crate::{
|
||||
AssetType, MAX_XFILE_COUNT, Ptr, XFILE_BLOCK_VIRTUAL, XFILE_HEADER_LEN, parse_zone_header,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum Iw4WireFormat {
|
||||
@@ -38,7 +40,7 @@ impl WirePointer {
|
||||
} else {
|
||||
let packed = u32::try_from(raw.checked_sub(1)?).ok()?;
|
||||
let block = (packed >> 28) as u8;
|
||||
(block < 8).then_some(Self::Offset(Ptr {
|
||||
((block as usize) < MAX_XFILE_COUNT).then_some(Self::Offset(Ptr {
|
||||
block,
|
||||
offset: packed & 0x0fff_ffff,
|
||||
}))
|
||||
|
||||
@@ -23,7 +23,6 @@ net = { path = "../net" }
|
||||
sim = { path = "../sim" }
|
||||
math_iw4.workspace = true
|
||||
gamemode_iw4.workspace = true
|
||||
killcam_iw4 = { path = "../killcam_iw4" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -17,7 +17,6 @@ rustls = { version = "0.23.31", default-features = false, features = ["ring", "s
|
||||
rustls-pemfile = "2.2.0"
|
||||
rustls-platform-verifier = "0.7.0"
|
||||
tokio = { version = "1.47", features = ["macros", "rt-multi-thread", "sync", "time"] }
|
||||
tokio-util = { version = "0.7", default-features = false, features = ["rt"] }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -16,7 +16,6 @@ bevy-trace = ["bootstrap/bevy-trace"]
|
||||
[dependencies]
|
||||
diag.workspace = true
|
||||
asset_transport.workspace = true
|
||||
assets.workspace = true
|
||||
bootstrap = { path = "../bootstrap" }
|
||||
|
||||
[lints]
|
||||
|
||||
@@ -8,40 +8,19 @@ description = "Snapshot to pixels: scene, viewmodel, effects. No game logic."
|
||||
[dependencies]
|
||||
diag.workspace = true
|
||||
bevy.workspace = true
|
||||
anim_iw4.workspace = true
|
||||
asset_iw4.workspace = true
|
||||
d3d9_sm3.workspace = true
|
||||
d3d9_state.workspace = true
|
||||
dpvs_iw4.workspace = true
|
||||
entity_iw4.workspace = true
|
||||
fx.workspace = true
|
||||
fx_iw4.workspace = true
|
||||
marks_iw4.workspace = true
|
||||
gamemode_iw4.workspace = true
|
||||
fastfile_iw4.workspace = true
|
||||
lighting_iw4.workspace = true
|
||||
math_iw4.workspace = true
|
||||
playerstate_iw4.workspace = true
|
||||
weapon_iw4.workspace = true
|
||||
hud_iw4.workspace = true
|
||||
hud = { path = "../hud" }
|
||||
frame.workspace = true
|
||||
render_frame.workspace = true
|
||||
render_anim.workspace = true
|
||||
render_frontend.workspace = true
|
||||
render_backend.workspace = true
|
||||
render_fx.workspace = true
|
||||
render_gpu.workspace = true
|
||||
render_scene.workspace = true
|
||||
net = { path = "../net" }
|
||||
assets.workspace = true
|
||||
asset_world.workspace = true
|
||||
audio.workspace = true
|
||||
sim.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
miniz_oxide.workspace = true
|
||||
bytemuck = { version = "1", features = ["derive"] }
|
||||
naga = { version = "29", features = ["wgsl-in"] }
|
||||
perf.workspace = true
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ frame.workspace = true
|
||||
fx.workspace = true
|
||||
fx_iw4.workspace = true
|
||||
hud_iw4.workspace = true
|
||||
gamemode_iw4.workspace = true
|
||||
lighting_iw4.workspace = true
|
||||
math_iw4.workspace = true
|
||||
net.workspace = true
|
||||
|
||||
@@ -2,25 +2,6 @@ use asset_game::WeaponAnimSlot;
|
||||
|
||||
use crate::{EventResult, ViewmodelController, ViewmodelEvent, WeaponState};
|
||||
|
||||
pub mod auth_ws {
|
||||
pub const READY: i32 = 0x0;
|
||||
pub const RAISING: i32 = 0x1;
|
||||
pub const RAISING_ALTSWITCH: i32 = 0x2;
|
||||
pub const DROPPING: i32 = 0x3;
|
||||
pub const DROPPING_QUICK: i32 = 0x4;
|
||||
pub const DROPPING_ALTSWITCH: i32 = 0x5;
|
||||
pub const FIRING: i32 = 0x6;
|
||||
pub const RECHAMBERING: i32 = 0x7;
|
||||
pub const RELOADING: i32 = 0x8;
|
||||
pub const RELOADING_INTERRUPT: i32 = 0x9;
|
||||
pub const RELOAD_START: i32 = 0xA;
|
||||
pub const RELOAD_START_INTERRUPT: i32 = 0xB;
|
||||
pub const RELOAD_END: i32 = 0xC;
|
||||
pub const SPRINT_IN: i32 = 0x17;
|
||||
pub const SPRINT_LOOP: i32 = 0x18;
|
||||
pub const SPRINT_OUT: i32 = 0x19;
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum PresentFpvEvent {
|
||||
Fire,
|
||||
@@ -56,11 +37,7 @@ pub struct FpvPoseSample {
|
||||
pub idle_weight: f32,
|
||||
}
|
||||
|
||||
pub fn map_authority_to_fpv(
|
||||
_prev_weaponstate: Option<i32>,
|
||||
_weaponstate: i32,
|
||||
cues: AuthorityFpvCues,
|
||||
) -> Vec<PresentFpvEvent> {
|
||||
pub fn map_authority_to_fpv(cues: AuthorityFpvCues) -> Vec<PresentFpvEvent> {
|
||||
let mut out = Vec::new();
|
||||
|
||||
if cues.shot_accepted {
|
||||
@@ -248,8 +225,6 @@ pub enum WeapAnimEdge {
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct FpvPresentState {
|
||||
pub last_tick: Option<u32>,
|
||||
pub last_weaponstate: Option<i32>,
|
||||
pub last_sprinting: Option<bool>,
|
||||
|
||||
pub last_ads_frac: Option<f32>,
|
||||
|
||||
@@ -263,8 +238,6 @@ pub struct FpvPresentState {
|
||||
impl FpvPresentState {
|
||||
pub fn clear(&mut self) {
|
||||
self.last_tick = None;
|
||||
self.last_weaponstate = None;
|
||||
self.last_sprinting = None;
|
||||
self.last_ads_frac = None;
|
||||
self.last_weap_anim = None;
|
||||
self.last_weap_anim_secondary = None;
|
||||
@@ -326,10 +299,8 @@ pub fn events_for_authority_tick(
|
||||
if present.last_tick == Some(sample.tick) {
|
||||
return Vec::new();
|
||||
}
|
||||
let events = map_authority_to_fpv(present.last_weaponstate, sample.weaponstate, sample.cues);
|
||||
let events = map_authority_to_fpv(sample.cues);
|
||||
present.last_tick = Some(sample.tick);
|
||||
present.last_weaponstate = Some(sample.weaponstate);
|
||||
present.last_sprinting = Some(sample.sprinting);
|
||||
present.last_ads_frac = Some(sample.ads_frac);
|
||||
events
|
||||
}
|
||||
|
||||
@@ -19,24 +19,20 @@ xmodel_runtime.workspace = true
|
||||
anim_iw4.workspace = true
|
||||
audio.workspace = true
|
||||
bevy.workspace = true
|
||||
d3d9_decl.workspace = true
|
||||
d3d9_sm3.workspace = true
|
||||
d3d9_state.workspace = true
|
||||
diag.workspace = true
|
||||
dpvs_iw4.workspace = true
|
||||
entity_iw4.workspace = true
|
||||
fastfile_iw4.workspace = true
|
||||
frame.workspace = true
|
||||
fx.workspace = true
|
||||
fx_iw4.workspace = true
|
||||
gamemode_iw4.workspace = true
|
||||
lighting_iw4.workspace = true
|
||||
hud_iw4.workspace = true
|
||||
marks_iw4.workspace = true
|
||||
math_iw4.workspace = true
|
||||
net.workspace = true
|
||||
perf.workspace = true
|
||||
playerstate_iw4.workspace = true
|
||||
render_anim.workspace = true
|
||||
render_frame.workspace = true
|
||||
render_fx.workspace = true
|
||||
|
||||
@@ -1,336 +0,0 @@
|
||||
use super::gpu_contract::WgpuPassLayout;
|
||||
use super::material_runtime::{
|
||||
ExecutablePassView, PackedCodeConstantLane, PackedLocalBanks, PortId, RuntimeProgramPort,
|
||||
RuntimeShaderStage,
|
||||
};
|
||||
use super::sm3_abi::{ConstantBinding, ConstantSource};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct PassConstantBuffers {
|
||||
pub vertex: Vec<[u32; 4]>,
|
||||
pub pixel: Vec<[u32; 4]>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum ConstantPackRefusal {
|
||||
ExecutablePairMismatch,
|
||||
|
||||
MissingLocalBanks,
|
||||
DestinationPastConstantBlock {
|
||||
stage: RuntimeShaderStage,
|
||||
destination: u16,
|
||||
block_len: usize,
|
||||
},
|
||||
MissingConstantRegister {
|
||||
stage: RuntimeShaderStage,
|
||||
register: u16,
|
||||
source: ConstantSource,
|
||||
},
|
||||
}
|
||||
|
||||
impl RuntimeProgramPort {
|
||||
pub fn pack_hit(
|
||||
&self,
|
||||
pass: ExecutablePassView<'_>,
|
||||
) -> Result<PassConstantBuffers, ConstantPackRefusal> {
|
||||
let Some(seed) = pass.local_banks.map(Arc::as_ref) else {
|
||||
return Err(ConstantPackRefusal::MissingLocalBanks);
|
||||
};
|
||||
if seed.vertex.len() == self.module().vertex_constant_len
|
||||
&& seed.pixel.len() == self.module().pixel_constant_len
|
||||
&& seed.written_vertex.len() == seed.vertex.len()
|
||||
&& seed.written_pixel.len() == seed.pixel.len()
|
||||
{
|
||||
return pack_code_on_seed(
|
||||
self.id(),
|
||||
&self.abi().vertex_constants,
|
||||
&self.abi().pixel_constants,
|
||||
seed,
|
||||
pass,
|
||||
);
|
||||
}
|
||||
Err(ConstantPackRefusal::DestinationPastConstantBlock {
|
||||
stage: RuntimeShaderStage::Vertex,
|
||||
destination: 0,
|
||||
block_len: seed.vertex.len(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn pack_hit_into(
|
||||
&self,
|
||||
pass: ExecutablePassView<'_>,
|
||||
overlay: &[PackedCodeConstantLane],
|
||||
out: &mut Vec<u8>,
|
||||
) -> Result<(), ConstantPackRefusal> {
|
||||
let Some(seed) = pass.local_banks.map(Arc::as_ref) else {
|
||||
return Err(ConstantPackRefusal::MissingLocalBanks);
|
||||
};
|
||||
let module = self.module();
|
||||
if seed.vertex.len() != module.vertex_constant_len
|
||||
|| seed.pixel.len() != module.pixel_constant_len
|
||||
|| seed.written_vertex.len() != seed.vertex.len()
|
||||
|| seed.written_pixel.len() != seed.pixel.len()
|
||||
{
|
||||
return Err(ConstantPackRefusal::DestinationPastConstantBlock {
|
||||
stage: RuntimeShaderStage::Vertex,
|
||||
destination: 0,
|
||||
block_len: seed.vertex.len(),
|
||||
});
|
||||
}
|
||||
if !self.accepts_pass(pass) {
|
||||
return Err(ConstantPackRefusal::ExecutablePairMismatch);
|
||||
}
|
||||
require_abi_rows_with_lanes(
|
||||
RuntimeShaderStage::Vertex,
|
||||
&self.abi().vertex_constants,
|
||||
&seed.written_vertex,
|
||||
pass.code_constants,
|
||||
)?;
|
||||
require_abi_rows_with_lanes(
|
||||
RuntimeShaderStage::Pixel,
|
||||
&self.abi().pixel_constants,
|
||||
&seed.written_pixel,
|
||||
pass.code_constants,
|
||||
)?;
|
||||
let start = out.len();
|
||||
out.extend_from_slice(bytemuck::cast_slice(seed.vertex.as_slice()));
|
||||
out.extend_from_slice(bytemuck::cast_slice(seed.pixel.as_slice()));
|
||||
let result = pass
|
||||
.code_constants
|
||||
.iter()
|
||||
.chain(overlay)
|
||||
.try_for_each(|lane| {
|
||||
overlay_lane_bytes(lane, &mut out[start..], seed.vertex.len(), seed.pixel.len())
|
||||
});
|
||||
if result.is_err() {
|
||||
out.truncate(start);
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
fn overlay_lane_bytes(
|
||||
lane: &PackedCodeConstantLane,
|
||||
span: &mut [u8],
|
||||
vertex_len: usize,
|
||||
pixel_len: usize,
|
||||
) -> Result<(), ConstantPackRefusal> {
|
||||
let (bank_off, bank_len) = match lane.stage {
|
||||
RuntimeShaderStage::Vertex => (0usize, vertex_len),
|
||||
RuntimeShaderStage::Pixel => (vertex_len, pixel_len),
|
||||
};
|
||||
let first = usize::from(lane.first_row);
|
||||
let rows = &lane.rows[first..first.saturating_add(usize::from(lane.row_count))];
|
||||
for (row, words) in rows.iter().enumerate() {
|
||||
let register = usize::from(lane.destination).saturating_add(row);
|
||||
if register >= bank_len {
|
||||
return Err(ConstantPackRefusal::DestinationPastConstantBlock {
|
||||
stage: lane.stage,
|
||||
destination: u16::try_from(register).unwrap_or(u16::MAX),
|
||||
block_len: bank_len,
|
||||
});
|
||||
}
|
||||
let at = (bank_off + register) * 16;
|
||||
span[at..at + 16].copy_from_slice(bytemuck::bytes_of(words));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn require_abi_rows_with_lanes(
|
||||
stage: RuntimeShaderStage,
|
||||
bindings: &[ConstantBinding],
|
||||
seed_written: &[bool],
|
||||
lanes: &[PackedCodeConstantLane],
|
||||
) -> Result<(), ConstantPackRefusal> {
|
||||
let mut covered = [0u64; 4];
|
||||
for lane in lanes.iter().filter(|lane| lane.stage == stage) {
|
||||
let first = usize::from(lane.destination);
|
||||
for register in first..first.saturating_add(usize::from(lane.row_count)).min(256) {
|
||||
covered[register / 64] |= 1u64 << (register % 64);
|
||||
}
|
||||
}
|
||||
for binding in bindings {
|
||||
if binding.source == ConstantSource::ProgramDefined {
|
||||
continue;
|
||||
}
|
||||
let index = usize::from(binding.register);
|
||||
if index >= seed_written.len() || seed_written[index] {
|
||||
continue;
|
||||
}
|
||||
if index >= 256 || covered[index / 64] & (1u64 << (index % 64)) == 0 {
|
||||
return Err(ConstantPackRefusal::MissingConstantRegister {
|
||||
stage,
|
||||
register: binding.register,
|
||||
source: binding.source,
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn pack_code_on_seed(
|
||||
expected_port: PortId,
|
||||
vertex_constants: &[ConstantBinding],
|
||||
pixel_constants: &[ConstantBinding],
|
||||
seed: &PackedLocalBanks,
|
||||
pass: ExecutablePassView<'_>,
|
||||
) -> Result<PassConstantBuffers, ConstantPackRefusal> {
|
||||
if pass.port != expected_port || !expected_port.matches_shader_pair(pass.shader_pair) {
|
||||
return Err(ConstantPackRefusal::ExecutablePairMismatch);
|
||||
}
|
||||
let mut vertex = seed.vertex.clone();
|
||||
let mut pixel = seed.pixel.clone();
|
||||
let mut written_vertex = seed.written_vertex.clone();
|
||||
let mut written_pixel = seed.written_pixel.clone();
|
||||
for lane in pass.code_constants {
|
||||
let start = usize::from(lane.first_row);
|
||||
let end = start.saturating_add(usize::from(lane.row_count));
|
||||
write_rows(
|
||||
lane.stage,
|
||||
lane.destination,
|
||||
&lane.rows[start..end],
|
||||
&mut vertex,
|
||||
&mut pixel,
|
||||
&mut written_vertex,
|
||||
&mut written_pixel,
|
||||
)?;
|
||||
}
|
||||
require_abi_rows(
|
||||
RuntimeShaderStage::Vertex,
|
||||
vertex_constants,
|
||||
&written_vertex,
|
||||
)?;
|
||||
require_abi_rows(RuntimeShaderStage::Pixel, pixel_constants, &written_pixel)?;
|
||||
Ok(PassConstantBuffers { vertex, pixel })
|
||||
}
|
||||
|
||||
pub fn overlay_packed_code_on_banks(
|
||||
vertex: &mut [[u32; 4]],
|
||||
pixel: &mut [[u32; 4]],
|
||||
lanes: &[PackedCodeConstantLane],
|
||||
) -> Result<u32, ConstantPackRefusal> {
|
||||
let mut written = 0u32;
|
||||
for lane in lanes {
|
||||
let start = usize::from(lane.first_row);
|
||||
let end = start.saturating_add(usize::from(lane.row_count));
|
||||
overlay_write_rows(
|
||||
lane.stage,
|
||||
lane.destination,
|
||||
&lane.rows[start..end],
|
||||
vertex,
|
||||
pixel,
|
||||
)?;
|
||||
written = written.saturating_add(u32::from(lane.row_count));
|
||||
}
|
||||
Ok(written)
|
||||
}
|
||||
|
||||
fn overlay_write_rows(
|
||||
stage: RuntimeShaderStage,
|
||||
destination: u16,
|
||||
rows: &[[u32; 4]],
|
||||
vertex: &mut [[u32; 4]],
|
||||
pixel: &mut [[u32; 4]],
|
||||
) -> Result<(), ConstantPackRefusal> {
|
||||
let bank = match stage {
|
||||
RuntimeShaderStage::Vertex => &mut *vertex,
|
||||
RuntimeShaderStage::Pixel => &mut *pixel,
|
||||
};
|
||||
for (row, words) in rows.iter().enumerate() {
|
||||
let register = destination
|
||||
.checked_add(u16::try_from(row).expect("row index fits u16"))
|
||||
.ok_or(ConstantPackRefusal::DestinationPastConstantBlock {
|
||||
stage,
|
||||
destination,
|
||||
block_len: bank.len(),
|
||||
})?;
|
||||
let index = usize::from(register);
|
||||
if index >= bank.len() {
|
||||
return Err(ConstantPackRefusal::DestinationPastConstantBlock {
|
||||
stage,
|
||||
destination: register,
|
||||
block_len: bank.len(),
|
||||
});
|
||||
}
|
||||
bank[index] = *words;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_rows(
|
||||
stage: RuntimeShaderStage,
|
||||
destination: u16,
|
||||
rows: &[[u32; 4]],
|
||||
vertex: &mut [[u32; 4]],
|
||||
pixel: &mut [[u32; 4]],
|
||||
written_vertex: &mut [bool],
|
||||
written_pixel: &mut [bool],
|
||||
) -> Result<(), ConstantPackRefusal> {
|
||||
let (bank, written) = match stage {
|
||||
RuntimeShaderStage::Vertex => (&mut *vertex, &mut *written_vertex),
|
||||
RuntimeShaderStage::Pixel => (&mut *pixel, &mut *written_pixel),
|
||||
};
|
||||
for (row, words) in rows.iter().enumerate() {
|
||||
let register = destination
|
||||
.checked_add(u16::try_from(row).expect("row index fits u16"))
|
||||
.ok_or(ConstantPackRefusal::DestinationPastConstantBlock {
|
||||
stage,
|
||||
destination,
|
||||
block_len: bank.len(),
|
||||
})?;
|
||||
let index = usize::from(register);
|
||||
if index >= bank.len() {
|
||||
return Err(ConstantPackRefusal::DestinationPastConstantBlock {
|
||||
stage,
|
||||
destination: register,
|
||||
block_len: bank.len(),
|
||||
});
|
||||
}
|
||||
bank[index] = *words;
|
||||
written[index] = true;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn require_abi_rows(
|
||||
stage: RuntimeShaderStage,
|
||||
bindings: &[ConstantBinding],
|
||||
written: &[bool],
|
||||
) -> Result<(), ConstantPackRefusal> {
|
||||
for binding in bindings {
|
||||
if binding.source == ConstantSource::ProgramDefined {
|
||||
continue;
|
||||
}
|
||||
let index = usize::from(binding.register);
|
||||
if index >= written.len() {
|
||||
continue;
|
||||
}
|
||||
if !written[index] {
|
||||
return Err(ConstantPackRefusal::MissingConstantRegister {
|
||||
stage,
|
||||
register: binding.register,
|
||||
source: binding.source,
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn split_bind_layout(
|
||||
layout: &WgpuPassLayout,
|
||||
) -> (
|
||||
Vec<super::WgpuBindLayoutEntry>,
|
||||
Vec<super::WgpuBindLayoutEntry>,
|
||||
) {
|
||||
let mut constants = Vec::new();
|
||||
let mut textures = Vec::new();
|
||||
for entry in &layout.bind_entries {
|
||||
match entry.group {
|
||||
0 => constants.push(*entry),
|
||||
1 => textures.push(*entry),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
(constants, textures)
|
||||
}
|
||||
@@ -6,7 +6,6 @@ pub mod film_vision_view;
|
||||
pub mod fog;
|
||||
pub mod frame_products;
|
||||
pub mod gpu_contract;
|
||||
pub mod gpu_prepare;
|
||||
pub mod image_handles;
|
||||
pub(crate) mod list;
|
||||
pub mod lit_draw_method;
|
||||
@@ -21,7 +20,6 @@ pub mod setup;
|
||||
pub mod sm3;
|
||||
pub mod sm3_abi;
|
||||
pub mod sm3_wgsl;
|
||||
pub mod smodel_cached;
|
||||
pub mod spot_shadow_casters;
|
||||
pub mod state;
|
||||
pub mod sun_effects;
|
||||
@@ -36,7 +34,6 @@ pub use depth_range::*;
|
||||
pub use film_vision_view::*;
|
||||
pub use frame_products::*;
|
||||
pub use gpu_contract::*;
|
||||
pub use gpu_prepare::*;
|
||||
pub use image_handles::*;
|
||||
pub use list::*;
|
||||
pub use lit_draw_method::*;
|
||||
@@ -51,7 +48,6 @@ pub use setup::*;
|
||||
pub use sm3::*;
|
||||
pub use sm3_abi::*;
|
||||
pub use sm3_wgsl::*;
|
||||
pub use smodel_cached::*;
|
||||
pub use spot_shadow_casters::*;
|
||||
pub use state::*;
|
||||
pub use sun_effects::SunEffectsFrameInput;
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
use asset_iw4::vertex_decl as vd;
|
||||
use bevy::mesh::VertexBufferLayout;
|
||||
use bevy::render::render_resource::{VertexAttribute, VertexFormat, VertexStepMode};
|
||||
|
||||
use super::sm3_abi::PassProgramAbi;
|
||||
|
||||
pub const SMODEL_PRETESS_VERTEX: usize = asset_iw4::size::GFX_PACKED_VERTEX + 16;
|
||||
|
||||
pub fn cached_lighting_location(abi: &PassProgramAbi) -> Option<u32> {
|
||||
let max = abi
|
||||
.vertex_inputs
|
||||
.iter()
|
||||
.map(|input| input.attribute.map(|attribute| attribute.location))
|
||||
.max()??;
|
||||
max.checked_add(1)
|
||||
}
|
||||
|
||||
pub fn lighting_texcoord_register(abi: &PassProgramAbi) -> Option<String> {
|
||||
abi.varyings.iter().find_map(|varying| {
|
||||
if varying.semantic.usage == vd::D3DDECLUSAGE_TEXCOORD && varying.semantic.usage_index == 6
|
||||
{
|
||||
Some(format!("o{}", varying.vertex_register.index))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn cached_lighting_vertex_buffers(
|
||||
packed: &[VertexBufferLayout],
|
||||
location: u32,
|
||||
) -> Vec<VertexBufferLayout> {
|
||||
packed
|
||||
.iter()
|
||||
.map(|buffer| {
|
||||
let mut attributes = buffer.attributes.to_vec();
|
||||
attributes.push(VertexAttribute {
|
||||
format: VertexFormat::Float32x4,
|
||||
offset: asset_iw4::size::GFX_PACKED_VERTEX as u64,
|
||||
shader_location: location,
|
||||
});
|
||||
VertexBufferLayout {
|
||||
array_stride: SMODEL_PRETESS_VERTEX as u64,
|
||||
step_mode: VertexStepMode::Vertex,
|
||||
attributes: attributes.into(),
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn inject_cached_lighting_attribute(
|
||||
source: &str,
|
||||
location: u32,
|
||||
lighting_register: Option<&str>,
|
||||
) -> Option<String> {
|
||||
const SIG_END: &str = ") -> Sm3Varyings {";
|
||||
let start = source.find("@vertex")?;
|
||||
let sig = source[start..].find(SIG_END)? + start;
|
||||
let mut out = String::with_capacity(source.len() + 160);
|
||||
out.push_str(&source[..sig]);
|
||||
out.push_str(&format!(
|
||||
" @location({location}) attribute_{location}: vec4<f32>,\n"
|
||||
));
|
||||
out.push_str(SIG_END);
|
||||
let after_sig = sig + SIG_END.len();
|
||||
out.push_str(&format!(
|
||||
"\n let lighting_coords = attribute_{location};\n"
|
||||
));
|
||||
if let Some(register) = lighting_register {
|
||||
const RET: &str = " return Sm3Varyings(";
|
||||
let rel = source[after_sig..].find(RET)?;
|
||||
let at = after_sig + rel;
|
||||
out.push_str(&source[after_sig..at]);
|
||||
out.push_str(&format!(" {register} = lighting_coords;\n"));
|
||||
out.push_str(&source[at..]);
|
||||
} else {
|
||||
out.push_str(&source[after_sig..]);
|
||||
}
|
||||
Some(out)
|
||||
}
|
||||
@@ -12,7 +12,6 @@ asset_material.workspace = true
|
||||
asset_world.workspace = true
|
||||
assets.workspace = true
|
||||
bytemuck = { version = "1", features = ["derive"] }
|
||||
d3d9_decl.workspace = true
|
||||
d3d9_sm3.workspace = true
|
||||
d3d9_state.workspace = true
|
||||
diag.workspace = true
|
||||
|
||||
@@ -12,7 +12,6 @@ frame.workspace = true
|
||||
net.workspace = true
|
||||
sim.workspace = true
|
||||
playerstate_iw4.workspace = true
|
||||
movement_iw4.workspace = true
|
||||
perf.workspace = true
|
||||
getrandom = "0.3"
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ asset_world.workspace = true
|
||||
assets.workspace = true
|
||||
audio.workspace = true
|
||||
net.workspace = true
|
||||
render.workspace = true
|
||||
render_frontend.workspace = true
|
||||
render_fx.workspace = true
|
||||
sim.workspace = true
|
||||
@@ -28,7 +27,6 @@ clipmap_iw4.workspace = true
|
||||
weapon_iw4.workspace = true
|
||||
xmodel_runtime.workspace = true
|
||||
hud_iw4.workspace = true
|
||||
bots.workspace = true
|
||||
perf.workspace = true
|
||||
|
||||
[lints]
|
||||
|
||||
@@ -241,20 +241,6 @@ fn hash_equipment(h: &mut Digest, rows: &[crate::EquipmentRuntimeFacts]) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn content_digest_v1(
|
||||
combat: &[WeaponCombatFacts],
|
||||
bootstrap: &MatchBootstrap,
|
||||
clip_brushes: &[SimBrush],
|
||||
) -> u64 {
|
||||
let mut h = Digest::new();
|
||||
h.u64(CONTENT_DIGEST_SCHEME);
|
||||
hash_combat(&mut h, combat);
|
||||
hash_class_catalog(&mut h);
|
||||
hash_spawns(&mut h, &bootstrap.spawns);
|
||||
hash_collision(&mut h, clip_brushes);
|
||||
h.finish()
|
||||
}
|
||||
|
||||
fn hash_script_models(h: &mut Digest, script_models: &[crate::EntityCollisionCapabilities]) {
|
||||
h.u32(script_models.len() as u32);
|
||||
for capabilities in script_models {
|
||||
@@ -300,7 +286,7 @@ fn hash_script_models(h: &mut Digest, script_models: &[crate::EntityCollisionCap
|
||||
}
|
||||
}
|
||||
|
||||
pub fn content_digest_v2(
|
||||
pub fn content_digest(
|
||||
combat: &[WeaponCombatFacts],
|
||||
runnable: &[bool],
|
||||
transition_groups: &[u32],
|
||||
@@ -332,7 +318,7 @@ pub struct ContentComponents {
|
||||
pub classes: u64,
|
||||
}
|
||||
|
||||
pub fn content_components_v2(
|
||||
pub fn content_components(
|
||||
combat: &[WeaponCombatFacts],
|
||||
runnable: &[bool],
|
||||
transition_groups: &[u32],
|
||||
@@ -370,11 +356,3 @@ pub fn content_components_v2(
|
||||
classes: classes.finish(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn content_digest_v0(combat: &[WeaponCombatFacts], classes: &[ClassDef]) -> u64 {
|
||||
let bootstrap = MatchBootstrap {
|
||||
classes: classes.to_vec(),
|
||||
..MatchBootstrap::default()
|
||||
};
|
||||
content_digest_v1(combat, &bootstrap, &[])
|
||||
}
|
||||
|
||||
@@ -60,10 +60,7 @@ pub use combat::{
|
||||
AcceptedShot, Emission, EntityClipKind, PlayerCollisionRepresentation, ShotCollisionGeometry,
|
||||
ShotCollisionVerdict, TracePhaseOutput, spread_direction_on_plane, spread_pellet_direction,
|
||||
};
|
||||
pub use content::{
|
||||
CONTENT_DIGEST_SCHEME, ContentComponents, content_components_v2, content_digest_v0,
|
||||
content_digest_v1, content_digest_v2,
|
||||
};
|
||||
pub use content::{CONTENT_DIGEST_SCHEME, ContentComponents, content_components, content_digest};
|
||||
pub use corpse::{PlayerCorpsePool, PlayerCorpseSlot, level_time_ms};
|
||||
pub use damage::{DamageAttempt, DamageOutcome, DamageRefusal, DeathCommit};
|
||||
pub use equipment::{
|
||||
|
||||
@@ -1247,7 +1247,7 @@ impl SimState {
|
||||
}
|
||||
|
||||
fn recompute_content_digest(&mut self) {
|
||||
self.content_digest = crate::content::content_digest_v2(
|
||||
self.content_digest = crate::content::content_digest(
|
||||
&self.content.data.weapon_combat,
|
||||
&self.content.data.weapon_runnable,
|
||||
&self.content.data.weapon_transition_groups,
|
||||
@@ -1256,7 +1256,7 @@ impl SimState {
|
||||
&self.content.data.clip_brushes,
|
||||
&self.entity_collision_capabilities,
|
||||
);
|
||||
self.content_components = crate::content::content_components_v2(
|
||||
self.content_components = crate::content::content_components(
|
||||
&self.content.data.weapon_combat,
|
||||
&self.content.data.weapon_runnable,
|
||||
&self.content.data.weapon_transition_groups,
|
||||
|
||||
@@ -15,7 +15,6 @@ asset_transport.workspace = true
|
||||
assets.workspace = true
|
||||
frame.workspace = true
|
||||
net = { path = "../net" }
|
||||
session.workspace = true
|
||||
sim.workspace = true
|
||||
|
||||
[lints]
|
||||
|
||||
Reference in New Issue
Block a user