1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

use bwapi_sys as sys;
use unit::Unit;
use player::Player;
use from_raw::FromRaw;
use game;

use std::ffi::CStr;
use std::os::raw::c_void as void;

#[repr(C)]
pub struct AIModule {
    vtable: Box<sys::AIModule_vtable>,
    handler: Box<game::EventHandler>,
}

impl AIModule {
    pub fn new(handler: Box<game::EventHandler>) -> AIModule {
        AIModule {
            vtable: Box::new(sys::AIModule_vtable {
                onStart: Some(AIModule::on_start),
                onEnd: Some(AIModule::on_end),
                onFrame: Some(AIModule::on_frame),
                onSendText: Some(AIModule::on_send_text),
                onReceiveText: Some(AIModule::on_receive_text),
                onPlayerLeft: Some(AIModule::on_player_left),
                onNukeDetect: Some(AIModule::on_nuke_detect),
                onUnitDiscover: Some(AIModule::on_unit_discover),
                onUnitEvade: Some(AIModule::on_unit_evade),
                onUnitShow: Some(AIModule::on_unit_show),
                onUnitHide: Some(AIModule::on_unit_hide),
                onUnitCreate: Some(AIModule::on_unit_create),
                onUnitDestroy: Some(AIModule::on_unit_destroy),
                onUnitMorph: Some(AIModule::on_unit_morph),
                onUnitRenegade: Some(AIModule::on_unit_renegade),
                onSaveGame: Some(AIModule::on_save_game),
                onUnitComplete: Some(AIModule::on_unit_complete),
            }),

            handler
        }
    }

    unsafe fn get_handler<'a>(sys_module: *mut sys::AIModule) -> &'a mut game::EventHandler {
        let module = sys_module as *mut AIModule;
        &mut * (*module).handler
    }

    unsafe extern fn on_start(sys_module: *mut sys::AIModule) {
        Self::get_handler(sys_module).on_start();
    }

    unsafe extern fn on_end(sys_module: *mut sys::AIModule, is_winner: bool) {
        Self::get_handler(sys_module).on_end(is_winner);
    }

    unsafe extern fn on_frame(sys_module: *mut sys::AIModule) {
        Self::get_handler(sys_module).on_frame();
    }

    unsafe extern fn on_send_text(sys_module: *mut sys::AIModule, text: *const ::std::os::raw::c_char) {
        let text = CStr::from_ptr(text).to_str().unwrap();
        Self::get_handler(sys_module).on_send_text(&text);
    }

    unsafe extern fn on_receive_text(sys_module: *mut sys::AIModule, player: *mut sys::Player, text: *const ::std::os::raw::c_char) {
        let mut player = Player::from_raw(player as *mut void);
        let text = CStr::from_ptr(text).to_str().unwrap();
        Self::get_handler(sys_module).on_receive_text(&mut player, &text);
    }

    unsafe extern fn on_player_left(sys_module: *mut sys::AIModule, player: *mut sys::Player) {
        let mut player = Player::from_raw(player as *mut void);
        Self::get_handler(sys_module).on_player_left(&mut player);
    }

    unsafe extern "C" fn on_nuke_detect(sys_module: *mut sys::AIModule, target: sys::Position) {
        Self::get_handler(sys_module).on_nuke_detect(target.into());
    }

    unsafe extern fn on_unit_discover(sys_module: *mut sys::AIModule, unit: *mut sys::Unit) {
        let mut unit = Unit::from_raw(unit as *mut void);
        Self::get_handler(sys_module).on_unit_discover(&mut unit);
    }

    unsafe extern fn on_unit_evade(sys_module: *mut sys::AIModule, unit: *mut sys::Unit) {
        let mut unit = Unit::from_raw(unit as *mut void);
        Self::get_handler(sys_module).on_unit_evade(&mut unit);
    }

    unsafe extern fn on_unit_show(sys_module: *mut sys::AIModule, unit: *mut sys::Unit) {
        let mut unit = Unit::from_raw(unit as *mut void);
        Self::get_handler(sys_module).on_unit_show(&mut unit);
    }

    unsafe extern fn on_unit_hide(sys_module: *mut sys::AIModule, unit: *mut sys::Unit) {
        let mut unit = Unit::from_raw(unit as *mut void);
        Self::get_handler(sys_module).on_unit_hide(&mut unit);
    }

    unsafe extern fn on_unit_create(sys_module: *mut sys::AIModule, unit: *mut sys::Unit) {
        let mut unit = Unit::from_raw(unit as *mut void);
        Self::get_handler(sys_module).on_unit_create(&mut unit);
    }

    unsafe extern fn on_unit_destroy(sys_module: *mut sys::AIModule, unit: *mut sys::Unit) {
        let mut unit = Unit::from_raw(unit as *mut void);
        Self::get_handler(sys_module).on_unit_destroy(&mut unit);
    }

    unsafe extern fn on_unit_morph(sys_module: *mut sys::AIModule, unit: *mut sys::Unit) {
        let mut unit = Unit::from_raw(unit as *mut void);
        Self::get_handler(sys_module).on_unit_morph(&mut unit);
    }

    unsafe extern fn on_unit_renegade(sys_module: *mut sys::AIModule, unit: *mut sys::Unit) {
        let mut unit = Unit::from_raw(unit as *mut void);
        Self::get_handler(sys_module).on_unit_renegade(&mut unit);
    }

    unsafe extern fn on_save_game(sys_module: *mut sys::AIModule, game_name: *const ::std::os::raw::c_char) {
        let game_name = CStr::from_ptr(game_name).to_str().unwrap();
        Self::get_handler(sys_module).on_save_game(game_name);
    }

    unsafe extern fn on_unit_complete(sys_module: *mut sys::AIModule, unit: *mut sys::Unit) {
        let mut unit = Unit::from_raw(unit as *mut void);
        Self::get_handler(sys_module).on_unit_complete(&mut unit);
    }

}

pub unsafe fn wrap_handler(handler: Box<game::EventHandler>) -> *mut ::std::os::raw::c_void {
    let module = Box::new(AIModule::new(handler));
    let module_ptr = Box::into_raw(module) as *mut sys::AIModule;

    sys::createAIModuleWrapper(module_ptr)
}