Files
RustNotMC/tests/test_cushion_particles.py
T
SashegDev 874b6f20c2 Клиент: начальный импорт кодовой базы
Основа — Horizon (MIT). История апстрима не переносится: этот репозиторий ведёт свою.
2026-10-29 22:04:28 +03:00

88 lines
3.4 KiB
Python

"""Cushion particles must reach clients even when the server has no sprite atlas."""
from pathlib import Path
import shutil
import subprocess
import tempfile
import unittest
ROOT = Path(__file__).resolve().parents[1]
@unittest.skipUnless(shutil.which("rustc"), "requires Rust")
class CushionParticlesTests(unittest.TestCase):
def test_headless_server_records_break_effect_before_sprite_lookup(self):
source = (ROOT / "crates/horizon-client/src/game/cushions.rs").read_text()
start = source.index(" fn cushion_break_particles(")
end = source.index(" /// `BlockAttachedEntity.tick`", start)
fixture = r'''
#![allow(dead_code)]
#[derive(Clone, Copy)]
struct Vec3 { x: f64, y: f64, z: f64 }
struct Cushion { position: Vec3 }
impl Cushion { fn color_name(&self) -> &str { "blue" } }
struct Registry;
impl Registry {
fn default_state(&self, name: &str) -> Option<u32> {
assert_eq!(name, "minecraft:blue_wool"); Some(123)
}
}
struct Assets { registry: Registry }
struct Pack { assets: Assets }
struct Audio { capture: Option<()> }
mod horizon_client { pub mod particles {
pub enum ParticleType { Block }
pub struct ParticleOptions;
impl ParticleOptions {
pub fn block(_: ParticleType, _: String, _: u32) -> Self { Self }
}
} }
#[derive(Default)]
struct Particles { count: u32 }
impl Particles {
fn send_particles(&mut self, _: &horizon_client::particles::ParticleOptions,
at: [f64; 3], spread: [f64; 3], speed: f64, count: u32) {
assert!((at[1] - (10.0 + 1.0/6.0)).abs() < 1e-12);
assert_eq!(spread, [0.25, 0.0625, 0.25]);
assert_eq!(speed, 0.05); assert_eq!(count, 10); self.count += count;
}
}
struct Game {
pack: Pack, audio: Audio, particles: Particles, headless: bool,
lan_cushion_breaks: Vec<(u32, [f64; 3])>,
}
impl Game {
fn particle_sprite(&self, _: u32, _: [i32; 3]) -> Option<(String, u32)> {
(!self.headless).then(|| ("block/blue_wool".into(), 0xffffff))
}
METHOD
}
fn main() {
let cushion = Cushion { position: Vec3 { x: 1.5, y: 10.0, z: 2.5 } };
for headless in [true, false] {
for serving in [true, false] {
let mut game = Game {
pack: Pack { assets: Assets { registry: Registry } },
audio: Audio { capture: serving.then_some(()) },
particles: Particles::default(), headless, lan_cushion_breaks: vec![],
};
game.cushion_break_particles(&cushion);
assert_eq!(game.lan_cushion_breaks.len(), usize::from(serving));
if serving {
let (state, at) = game.lan_cushion_breaks[0];
assert_eq!(state, 123);
assert_eq!([at[0], at[2]], [1.5, 2.5]);
assert!((at[1] - (10.0 + 1.0/6.0)).abs() < 1e-12);
}
assert_eq!(game.particles.count, if headless { 0 } else { 10 });
}
}
}
'''.replace("METHOD", source[start:end])
with tempfile.TemporaryDirectory(prefix="cushion-particles-") as directory:
path = Path(directory)
(path / "main.rs").write_text(fixture)
subprocess.run(["rustc", "--edition=2024", str(path / "main.rs"), "-o", str(path / "probe")],
check=True, capture_output=True, text=True)
result = subprocess.run([str(path / "probe")], capture_output=True, text=True)
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)