rust/hedgewars-engine/src/main.rs
changeset 15805 61da40b657fa
parent 15802 d5c37e78ab83
child 15806 36816af30583
equal deleted inserted replaced
15804:747278149393 15805:61da40b657fa
     1 extern crate libloading;
     1 extern crate libloading;
     2 
     2 
     3 use libloading::{Library, Symbol};
     3 use libloading::{Library, Symbol};
     4 use std::ops::Deref;
     4 use std::ops::Deref;
       
     5 use std::env;
       
     6 use getopts::Options;
       
     7 use std::io::prelude::*;
       
     8 use std::io::{self, Read};
       
     9 use std::net::{Shutdown, TcpStream};
       
    10 use image::{GrayImage, imageops};
     5 
    11 
     6 struct EngineInstance {}
    12 struct EngineInstance {}
     7 
    13 
     8 struct Engine<'a> {
    14 struct Engine<'a> {
     9     protocol_version: Symbol<'a, unsafe fn() -> u32>,
    15     protocol_version: Symbol<'a, unsafe fn() -> u32>,
    10     start_engine: Symbol<'a, unsafe fn() -> *mut EngineInstance>,
    16     start_engine: Symbol<'a, unsafe fn() -> *mut EngineInstance>,
       
    17     generate_preview: Symbol<'a, unsafe fn(engine_state: &mut EngineInstance, preview: &mut PreviewInfo)>,
       
    18     dispose_preview: Symbol<'a, unsafe fn(engine_state: &mut EngineInstance, preview: &mut PreviewInfo)>,
    11     cleanup: Symbol<'a, unsafe fn(engine_state: *mut EngineInstance)>,
    19     cleanup: Symbol<'a, unsafe fn(engine_state: *mut EngineInstance)>,
       
    20     send_ipc: Symbol<'a, unsafe fn(engine_state: &mut EngineInstance, buf: *const u8, size: usize)>,
       
    21     read_ipc: Symbol<'a, unsafe fn(engine_state: &mut EngineInstance, buf: *mut u8, size: usize) -> usize>,
       
    22 }
       
    23 
       
    24 #[repr(C)]
       
    25 #[derive(Copy, Clone)]
       
    26 struct PreviewInfo {
       
    27   width: u32,
       
    28   height: u32,
       
    29   hedgehogs_number: u8,
       
    30   land: *const u8,
    12 }
    31 }
    13 
    32 
    14 fn main() {
    33 fn main() {
    15     let hwlib = Library::new("libhedgewars_engine.so").unwrap();
    34     let hwlib = Library::new("libhedgewars_engine.so").unwrap();
    16 
    35 
    17     unsafe {
    36     unsafe {
    18         let engine = Engine {
    37         let engine = Engine {
    19             protocol_version: hwlib.get(b"hedgewars_engine_protocol_version").unwrap(),
    38             protocol_version: hwlib.get(b"hedgewars_engine_protocol_version").unwrap(),
    20             start_engine: hwlib.get(b"start_engine").unwrap(),
    39             start_engine: hwlib.get(b"start_engine").unwrap(),
       
    40             generate_preview: hwlib.get(b"generate_preview").unwrap(),
       
    41             dispose_preview: hwlib.get(b"dispose_preview").unwrap(),
    21             cleanup: hwlib.get(b"cleanup").unwrap(),
    42             cleanup: hwlib.get(b"cleanup").unwrap(),
       
    43             send_ipc: hwlib.get(b"send_ipc").unwrap(),
       
    44             read_ipc: hwlib.get(b"read_ipc").unwrap(),
    22         };
    45         };
    23 
    46 
    24         println!("Hedgewars engine, protocol version {}", engine.protocol_version.deref()());
    47         println!("Hedgewars engine, protocol version {}", engine.protocol_version.deref()());
       
    48 
       
    49         let args: Vec<String> = env::args().collect();
       
    50 
       
    51         let mut opts = getopts::Options::new();
       
    52         opts.optflag("", "internal", "[internal]");
       
    53         opts.optflag("", "landpreview", "[internal]");
       
    54         opts.optflag("", "recorder", "[internal]");
       
    55         opts.optopt("", "port", "[internal]", "PORT");
       
    56         opts.optopt("", "user-prefix", "Set the path to the custom data folder to find game content", "PATH_TO_FOLDER");
       
    57         opts.optopt("", "prefix", "Set the path to the system game data folder", "PATH_TO_FOLDER");
       
    58 
       
    59         let matches = match opts.parse(&args[1..]) {
       
    60             Ok(m) => { m }
       
    61             Err(f) => { panic!(f.to_string()) }
       
    62         };
       
    63 
       
    64         let engine_state = &mut *engine.start_engine.deref()();
       
    65 
       
    66         let port: String = matches.opt_str("port").unwrap();
       
    67 
       
    68         println!("PORT: {}", port);
       
    69 
       
    70         if matches.opt_present("landpreview") {
       
    71 
       
    72             let mut stream = TcpStream::connect(format!("127.0.0.1:{}", port)).expect("Failed to connect to IPC port. Feelsbadman.");
       
    73 
       
    74             //stream.write(b"\x01C").unwrap(); // config
       
    75             //stream.write(b"\x01?").unwrap(); // ping
       
    76 
       
    77             let mut buf = [0;1];
       
    78             loop {
       
    79                 let bytes_read = stream.read(&mut buf).unwrap();
       
    80                 if bytes_read == 0 {
       
    81                     break;
       
    82                 }
       
    83                 engine.send_ipc.deref()(engine_state, &buf[0], buf.len());
       
    84                 // this looks like length 1 is being announced
       
    85                 if buf[0] == 1 {
       
    86                     let bytes_read = stream.read(&mut buf).unwrap();
       
    87                     if bytes_read == 0 {
       
    88                         break;
       
    89                     }
       
    90                     if buf[0] == 33 {
       
    91                         println!("Ping? Pong!");
       
    92                         break;
       
    93                     }
       
    94                 }
       
    95             };
       
    96 
       
    97             let preview_info = &mut PreviewInfo {
       
    98                 width: 0,
       
    99                 height: 0,
       
   100                 hedgehogs_number: 0,
       
   101                 land: std::ptr::null(),
       
   102             };
       
   103 
       
   104             engine.generate_preview.deref()(engine_state, preview_info);
       
   105 
       
   106             println!("Sending preview...");
       
   107 
       
   108             //println!("Preview: w = {}, h = {}, n = {}", preview_info.width, preview_info.height, preview_info.hedgehogs_number);
       
   109 
       
   110             let land_size: usize = (preview_info.width * preview_info.height) as usize;
       
   111 
       
   112             let land_array: &[u8] = std::slice::from_raw_parts(preview_info.land, land_size);
       
   113 
       
   114             let raw_image = GrayImage::from_raw(preview_info.width, preview_info.height, land_array.to_vec()).unwrap();
       
   115 
       
   116             const PREVIEW_WIDTH: u32 = 256;
       
   117             const PREVIEW_HEIGHT: u32 = 128;
       
   118 
       
   119             let preview_image = imageops::resize(&raw_image, PREVIEW_WIDTH, PREVIEW_HEIGHT, imageops::FilterType::Triangle);
       
   120 
       
   121             stream.write(preview_image.as_raw()).unwrap();
       
   122             stream.flush().unwrap();
       
   123             stream.write(&[preview_info.hedgehogs_number]).unwrap();
       
   124             stream.flush().unwrap();
       
   125 
       
   126             println!("Preview sent, disconnect");
       
   127 
       
   128             stream.shutdown(Shutdown::Both).expect("IPC shutdown call failed");
       
   129 
       
   130             engine.dispose_preview.deref()(engine_state, preview_info);
       
   131         }
       
   132 
       
   133         engine.cleanup.deref()(engine_state);
    25     }
   134     }
    26 }
   135 }