mod bumper;
mod collection;
mod decal;
mod dragpoint;
mod flasher;
mod flipper;
mod font;
mod gate;
mod generic;
mod hittarget;
mod kicker;
mod light;
mod lightcenter;
mod lightsequencer;
mod plunger;
mod primitive;
mod ramp;
mod reel;
mod rubber;
mod spinner;
mod table;
mod textbox;
mod timer;
mod trigger;
mod vertex2d;
mod vertex3d;
mod wall;
use crate::vpx::biff::BiffRead;
use super::biff::{BiffReader, BiffWrite, BiffWriter};
trait GameItem: BiffRead {
fn name(&self) -> &str;
}
#[derive(PartialEq, Debug)]
pub enum GameItemEnum {
Wall(wall::Wall),
Flipper(flipper::Flipper),
Timer(timer::Timer),
Plunger(plunger::Plunger),
TextBox(textbox::TextBox),
Bumper(bumper::Bumper),
Trigger(trigger::Trigger),
Light(light::Light),
Kicker(kicker::Kicker),
Decal(decal::Decal),
Gate(gate::Gate),
Spinner(spinner::Spinner),
Ramp(ramp::Ramp),
Table(table::Table),
LightCenter(lightcenter::LightCenter),
DragPoint(dragpoint::DragPoint),
Collection(collection::Collection),
Reel(reel::Reel),
LightSequencer(lightsequencer::LightSequencer),
Primitive(primitive::Primitive),
Flasher(flasher::Flasher),
Rubber(rubber::Rubber),
HitTarget(hittarget::HitTarget),
Generic(u32, generic::Generic),
}
impl GameItemEnum {
fn name(&self) -> &str {
match self {
GameItemEnum::Wall(wall) => &wall.name,
GameItemEnum::Flipper(flipper) => flipper.name(),
GameItemEnum::Timer(timer) => &timer.name,
GameItemEnum::Plunger(plunger) => &plunger.name,
GameItemEnum::TextBox(textbox) => &textbox.name,
GameItemEnum::Bumper(bumper) => bumper.name(),
GameItemEnum::Trigger(trigger) => &trigger.name,
GameItemEnum::Light(light) => &light.name,
GameItemEnum::Kicker(kicker) => &kicker.name,
GameItemEnum::Decal(decal) => &decal.name,
GameItemEnum::Gate(gate) => &gate.name,
GameItemEnum::Spinner(spinner) => &spinner.name,
GameItemEnum::Ramp(ramp) => &ramp.name,
GameItemEnum::Table(table) => &table.name,
GameItemEnum::LightCenter(lightcenter) => &lightcenter.name,
GameItemEnum::DragPoint(dragpoint) => dragpoint.name(),
GameItemEnum::Collection(collection) => &collection.name,
GameItemEnum::Reel(reel) => &reel.name,
GameItemEnum::LightSequencer(lightsequencer) => &lightsequencer.name,
GameItemEnum::Primitive(primitive) => &primitive.name,
GameItemEnum::Flasher(flasher) => &flasher.name,
GameItemEnum::Rubber(rubber) => &rubber.name,
GameItemEnum::HitTarget(hittarget) => &hittarget.name,
GameItemEnum::Generic(_item_type, generic) => generic.name(),
}
}
}
const ITEM_TYPE_WALL: u32 = 0;
const ITEM_TYPE_FLIPPER: u32 = 1;
const ITEM_TYPE_TIMER: u32 = 2;
const ITEM_TYPE_PLUNGER: u32 = 3;
const ITEM_TYPE_TEXT_BOX: u32 = 4;
const ITEM_TYPE_BUMPER: u32 = 5;
const ITEM_TYPE_TRIGGER: u32 = 6;
const ITEM_TYPE_LIGHT: u32 = 7;
const ITEM_TYPE_KICKER: u32 = 8;
const ITEM_TYPE_DECAL: u32 = 9;
const ITEM_TYPE_GATE: u32 = 10;
const ITEM_TYPE_SPINNER: u32 = 11;
const ITEM_TYPE_RAMP: u32 = 12;
const ITEM_TYPE_TABLE: u32 = 13;
const ITEM_TYPE_LIGHT_CENTER: u32 = 14;
const ITEM_TYPE_DRAG_POINT: u32 = 15;
const ITEM_TYPE_COLLECTION: u32 = 16;
const ITEM_TYPE_REEL: u32 = 17;
const ITEM_TYPE_LIGHT_SEQUENCER: u32 = 18;
const ITEM_TYPE_PRIMITIVE: u32 = 19;
const ITEM_TYPE_FLASHER: u32 = 20;
const ITEM_TYPE_RUBBER: u32 = 21;
const ITEM_TYPE_HIT_TARGET: u32 = 22;
pub const FILTER_NONE: u32 = 0;
pub const FILTER_ADDITIVE: u32 = 1;
pub const FILTER_OVERLAY: u32 = 2;
pub const FILTER_MULTIPLY: u32 = 3;
pub const FILTER_SCREEN: u32 = 4;
pub const IMAGE_ALIGN_WORLD: u32 = 0;
pub const IMAGE_ALIGN_TOP_LEFT: u32 = 1;
pub const IMAGE_ALIGN_CENTER: u32 = 2;
pub const TRIGGER_SHAPE_NONE: u32 = 0;
pub const TRIGGER_SHAPE_WIRE_A: u32 = 1;
pub const TRIGGER_SHAPE_STAR: u32 = 2;
pub const TRIGGER_SHAPE_WIRE_B: u32 = 3;
pub const TRIGGER_SHAPE_BUTTON: u32 = 4;
pub const TRIGGER_SHAPE_WIRE_C: u32 = 5;
pub const TRIGGER_SHAPE_WIRE_D: u32 = 6;
pub fn read(input: &[u8]) -> GameItemEnum {
let mut reader = BiffReader::new(input);
let item_type = reader.get_u32_no_remaining_update();
match item_type {
ITEM_TYPE_WALL => GameItemEnum::Wall(wall::Wall::biff_read(&mut reader)),
ITEM_TYPE_FLIPPER => GameItemEnum::Flipper(flipper::Flipper::biff_read(&mut reader)),
ITEM_TYPE_TIMER => GameItemEnum::Timer(timer::Timer::biff_read(&mut reader)),
ITEM_TYPE_PLUNGER => GameItemEnum::Plunger(plunger::Plunger::biff_read(&mut reader)),
ITEM_TYPE_TEXT_BOX => GameItemEnum::TextBox(textbox::TextBox::biff_read(&mut reader)),
ITEM_TYPE_BUMPER => GameItemEnum::Bumper(bumper::Bumper::biff_read(&mut reader)),
ITEM_TYPE_TRIGGER => GameItemEnum::Trigger(trigger::Trigger::biff_read(&mut reader)),
ITEM_TYPE_LIGHT => GameItemEnum::Light(light::Light::biff_read(&mut reader)),
ITEM_TYPE_KICKER => GameItemEnum::Kicker(kicker::Kicker::biff_read(&mut reader)),
ITEM_TYPE_DECAL => GameItemEnum::Decal(decal::Decal::biff_read(&mut reader)),
ITEM_TYPE_GATE => GameItemEnum::Gate(gate::Gate::biff_read(&mut reader)),
ITEM_TYPE_SPINNER => GameItemEnum::Spinner(spinner::Spinner::biff_read(&mut reader)),
ITEM_TYPE_RAMP => GameItemEnum::Ramp(ramp::Ramp::biff_read(&mut reader)),
ITEM_TYPE_TABLE => GameItemEnum::Table(table::Table::biff_read(&mut reader)),
ITEM_TYPE_LIGHT_CENTER => {
GameItemEnum::LightCenter(lightcenter::LightCenter::biff_read(&mut reader))
}
ITEM_TYPE_DRAG_POINT => {
GameItemEnum::DragPoint(dragpoint::DragPoint::biff_read(&mut reader))
}
ITEM_TYPE_COLLECTION => {
GameItemEnum::Collection(collection::Collection::biff_read(&mut reader))
}
ITEM_TYPE_REEL => GameItemEnum::Reel(reel::Reel::biff_read(&mut reader)),
ITEM_TYPE_LIGHT_SEQUENCER => {
GameItemEnum::LightSequencer(lightsequencer::LightSequencer::biff_read(&mut reader))
}
ITEM_TYPE_PRIMITIVE => {
GameItemEnum::Primitive(primitive::Primitive::biff_read(&mut reader))
}
ITEM_TYPE_FLASHER => GameItemEnum::Flasher(flasher::Flasher::biff_read(&mut reader)),
ITEM_TYPE_RUBBER => GameItemEnum::Rubber(rubber::Rubber::biff_read(&mut reader)),
ITEM_TYPE_HIT_TARGET => {
GameItemEnum::HitTarget(hittarget::HitTarget::biff_read(&mut reader))
}
other_item_type => {
GameItemEnum::Generic(other_item_type, generic::Generic::biff_read(&mut reader))
}
}
}
pub(crate) fn write(gameitem: &GameItemEnum) -> Vec<u8> {
match gameitem {
GameItemEnum::Wall(wall) => write_with_type(ITEM_TYPE_WALL, wall),
GameItemEnum::Flipper(flipper) => write_with_type(ITEM_TYPE_FLIPPER, flipper),
GameItemEnum::Timer(timer) => write_with_type(ITEM_TYPE_TIMER, timer),
GameItemEnum::Plunger(plunger) => write_with_type(ITEM_TYPE_PLUNGER, plunger),
GameItemEnum::TextBox(textbox) => write_with_type(ITEM_TYPE_TEXT_BOX, textbox),
GameItemEnum::Bumper(bumper) => write_with_type(ITEM_TYPE_BUMPER, bumper),
GameItemEnum::Trigger(trigger) => write_with_type(ITEM_TYPE_TRIGGER, trigger),
GameItemEnum::Light(light) => write_with_type(ITEM_TYPE_LIGHT, light),
GameItemEnum::Kicker(kicker) => write_with_type(ITEM_TYPE_KICKER, kicker),
GameItemEnum::Decal(decal) => write_with_type(ITEM_TYPE_DECAL, decal),
GameItemEnum::Gate(gate) => write_with_type(ITEM_TYPE_GATE, gate),
GameItemEnum::Spinner(spinner) => write_with_type(ITEM_TYPE_SPINNER, spinner),
GameItemEnum::Ramp(ramp) => write_with_type(ITEM_TYPE_RAMP, ramp),
GameItemEnum::Reel(reel) => write_with_type(ITEM_TYPE_REEL, reel),
GameItemEnum::LightSequencer(lightsequencer) => {
write_with_type(ITEM_TYPE_LIGHT_SEQUENCER, lightsequencer)
}
GameItemEnum::Primitive(primitive) => write_with_type(ITEM_TYPE_PRIMITIVE, primitive),
GameItemEnum::Flasher(flasher) => write_with_type(ITEM_TYPE_FLASHER, flasher),
GameItemEnum::Rubber(rubber) => write_with_type(ITEM_TYPE_RUBBER, rubber),
GameItemEnum::HitTarget(hittarget) => write_with_type(ITEM_TYPE_HIT_TARGET, hittarget),
_ => {
unimplemented!("write gameitem {:?}", gameitem);
}
}
}
fn write_with_type<T: BiffWrite>(item_type: u32, item: &T) -> Vec<u8> {
let mut writer = BiffWriter::new();
writer.write_u32(item_type);
item.biff_write(&mut writer);
writer.get_data().to_vec()
}