Skip to content

Commit

Permalink
iquare: Add bank commands
Browse files Browse the repository at this point in the history
  • Loading branch information
neivv committed Oct 25, 2018
1 parent 9cd8589 commit 505702e
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 7 deletions.
24 changes: 19 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "aise"
version = "2.14.0"
version = "2.15.0"
authors = ["Markus Heikkinen <ittevien@gmail.com>"]

[lib]
Expand All @@ -23,6 +23,7 @@ bincode = "1.0"
bitflags = "1.0"
byteorder = "1.1"
chrono = "0.4"
directories = "1.0.2"
fern = "0.5"
lazy_static = "1.0"
libc = "0.2"
Expand Down
125 changes: 124 additions & 1 deletion src/aiscript.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
use std::fmt;
use std::fs::{self, File};
use std::mem;
use std::path::{Component, Path, PathBuf};
use std::ptr::null_mut;
use std::slice;

use bincode;
use byteorder::{WriteBytesExt, LE};
use directories::UserDirs;
use serde::{self, Deserialize, Deserializer, Serialize, Serializer};
use smallvec::SmallVec;

Expand All @@ -14,7 +18,9 @@ use block_alloc::BlockAllocSet;
use bw;
use datreq::{DatReq, ReadDatReqs};
use game::Game;
use globals::{self, BaseLayout, BunkerCondition, BunkerState, Globals, RevealState, RevealType};
use globals::{
self, BankKey, BaseLayout, BunkerCondition, BunkerState, Globals, RevealState, RevealType,
};
use list::ListIter;
use order::{self, OrderId};
use rng::Rng;
Expand Down Expand Up @@ -979,6 +985,123 @@ pub unsafe extern fn reveal_area(script: *mut bw::AiScript) {
reveal(game, src.area, players, true);
}

fn get_bank_path(name: &str) -> Option<PathBuf> {
let name = Path::new(name);
let bad_path = name.components().any(|x| match x {
Component::Prefix(..) | Component::RootDir | Component::ParentDir => true,
Component::CurDir | Component::Normal(..) => false,
});
if bad_path {
return None;
}
let root = if bw::is_scr() {
UserDirs::new()
.and_then(|user_dirs| user_dirs.document_dir().map(|s| s.join("Starcraft")))
.unwrap_or_else(|| ".".into())
} else {
".".into()
};
Some(root.join("save").join(name))
}

pub unsafe extern fn save_bank(script: *mut bw::AiScript) {
let mut read = ScriptData::new(script);
let name = read.read_string();
let globals = Globals::get();
let name = String::from_utf8_lossy(name).to_string();
let path = match get_bank_path(&name) {
Some(s) => s,
None => return,
};
let folder = Path::parent(&path);
if let Some(s) = folder {
let _ = fs::create_dir(s);
}
let mut file = match File::create(&path) {
Ok(o) => o,
Err(e) => {
bw::print_text(format!("Bank load error: {}", e));
return;
}
};
if let Err(e) = bincode::serialize_into(&mut file, &globals.bank) {
bw::print_text(format!("Bank save error: {}", e));
}
}

pub unsafe extern fn load_bank(script: *mut bw::AiScript) {
let mut read = ScriptData::new(script);
let name = read.read_string();
let mut globals = Globals::get();
globals.bank.reset();
let name = String::from_utf8_lossy(name);
let path = match get_bank_path(&name) {
Some(s) => s,
None => return,
};
if path.exists() {
let mut file = match File::open(path) {
Ok(o) => o,
Err(e) => {
bw::print_text(format!("Bank load error: {}", e));
return;
}
};
globals.bank = match bincode::deserialize_from(&mut file) {
Ok(o) => o,
Err(e) => {
bw::print_text(format!("Bank load error: {}", e));
return;
}
};
}
}

pub unsafe extern fn bank_data(script: *mut bw::AiScript) {
let old_pos = (*script).pos - 1;
let mut read = ScriptData::new(script);
let modifier = read.read_modifier();
let category = read.read_string();
let label = read.read_string();
let amount = read.read_u32();
let dest = read.read_jump_pos();
let mut globals = Globals::get();
let globals = &mut *globals;
let key = BankKey {
label: String::from_utf8_lossy(label).to_string(),
category: String::from_utf8_lossy(category).to_string(),
};

match modifier.ty {
ModifierType::Read(read) => {
let value = globals.bank.get(&key);
let read_req = modifier.get_read_req();
if read.compare(value, amount) == read_req {
match modifier.action {
ModifierAction::Jump => {
(*script).pos = dest as u32;
}
ModifierAction::Call => {
let ret = (*script).pos;
(*script).pos = dest as u32;
(*Script::ptr_from_bw(script)).call_stack.push(ret);
}
ModifierAction::Wait => {
(*script).pos = old_pos;
(*script).wait = 30;
}
}
}
}
ModifierType::Write(write) => {
let rng = &mut globals.rng;
globals
.bank
.update(key, |val| write.apply(val, amount, rng));
}
}
}

pub unsafe extern fn remove_creep(script: *mut bw::AiScript) {
if bw::is_scr() {
bw::print_text("remove_creep is not supported in SCR");
Expand Down
60 changes: 60 additions & 0 deletions src/globals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,64 @@ pub struct SingleBunkerState {
pub bunker: Unit,
}

#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
pub struct BankKey {
pub label: String,
pub category: String,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct BankValue {
pub key: BankKey,
pub value: u32,
}

impl BankValue {
pub fn new(key: BankKey, value: u32) -> BankValue {
BankValue {
key,
value,
}
}
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Bank {
pub bank_data: Vec<BankValue>,
}

impl Bank {
pub fn reset(&mut self) {
self.bank_data.clear();
}

pub fn get(&self, key: &BankKey) -> u32 {
match self.bank_data.iter().position(|i| i.key == *key) {
Some(pos) => self.bank_data[pos].value as u32,
None => 0,
}
}

pub fn update<F: FnOnce(u32) -> u32>(&mut self, key: BankKey, update_fn: F) {
match self.bank_data.iter_mut().position(|i| i.key == key) {
Some(pos) => {
let new = update_fn(self.bank_data[pos].value);
if new == 0 {
self.bank_data.swap_remove(pos);
} else {
self.bank_data[pos].value = new;
}
}
None => {
let new = update_fn(0);
if new != 0 {
self.bank_data.push(BankValue::new(key, new));
}
}
}
}
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct BunkerCondition {
pub bunker_states: Vec<BunkerState>,
Expand Down Expand Up @@ -248,6 +306,7 @@ pub struct Globals {
pub town_ids: Vec<TownId>,
pub bunker_states: BunkerCondition,
pub guards: GuardState,
pub bank: Bank,
pub reveal_states: Vec<RevealState>,
pub under_attack_mode: [Option<bool>; 8],
pub ai_mode: [AiMode; 8],
Expand All @@ -274,6 +333,7 @@ impl Globals {
reveal_states: Vec::new(),
bunker_states: Default::default(),
guards: GuardState::new(),
bank: Default::default(),
under_attack_mode: [None; 8],
ai_mode: [Default::default(); 8],
towns: Vec::new(),
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ extern crate bincode;
extern crate bitflags;
extern crate byteorder;
extern crate chrono;
extern crate directories;
extern crate fern;
#[macro_use]
extern crate lazy_static;
Expand Down
3 changes: 3 additions & 0 deletions src/samase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,9 @@ pub unsafe extern fn samase_plugin_init(api: *const PluginApi) {
aiscript_opcode(api, 0x91, ::aiscript::reveal_area);
aiscript_opcode(api, 0x92, ::aiscript::tech_avail);
aiscript_opcode(api, 0x93, ::aiscript::remove_creep);
aiscript_opcode(api, 0x94, ::aiscript::save_bank);
aiscript_opcode(api, 0x95, ::aiscript::load_bank);
aiscript_opcode(api, 0x96, ::aiscript::bank_data);

GAME.init(((*api).game)().map(|x| mem::transmute(x)), "Game object");
AI_REGIONS.init(
Expand Down

0 comments on commit 505702e

Please sign in to comment.