mirror of
https://github.com/doukutsu-rs/doukutsu-rs.git
synced 2026-08-24 13:02:49 -07:00
general cleanup, hooks and android build fix
This commit is contained in:
+2
-14
@@ -15,14 +15,6 @@ test = false
|
||||
bench = false
|
||||
required-features = ["exe"]
|
||||
|
||||
[[example]]
|
||||
name = "drsandroid"
|
||||
path = "src/main_android.rs"
|
||||
crate-type = ["cdylib"]
|
||||
test = false
|
||||
bench = false
|
||||
required-features = ["android"]
|
||||
|
||||
[profile.release]
|
||||
lto = 'thin'
|
||||
panic = 'abort'
|
||||
@@ -30,12 +22,6 @@ panic = 'abort'
|
||||
[profile.dev.package."*"]
|
||||
opt-level = 3
|
||||
|
||||
[profile.dev.build-override]
|
||||
opt-level = 1
|
||||
|
||||
[profile.release.build-override]
|
||||
opt-level = 1
|
||||
|
||||
[features]
|
||||
default = ["scripting", "backend-sdl", "ogg-playback", "netplay", "exe"]
|
||||
ogg-playback = ["lewton"]
|
||||
@@ -45,6 +31,7 @@ backend-glutin = ["winit", "glutin"]
|
||||
scripting = ["lua-ffi"]
|
||||
netplay = []
|
||||
editor = []
|
||||
hooks = ["libc"]
|
||||
exe = []
|
||||
android = []
|
||||
|
||||
@@ -64,6 +51,7 @@ image = { version = "0.23", default-features = false, features = ["png", "bmp"]
|
||||
itertools = "0.10"
|
||||
lazy_static = "1.4.0"
|
||||
lewton = { version = "0.10.2", optional = true }
|
||||
libc = { version = "0.2", optional = true }
|
||||
log = "0.4"
|
||||
lua-ffi = { git = "https://github.com/doukutsu-rs/lua-ffi.git", rev = "1ef3caf772d72068297ddf75df06fd2ef8c1daab", optional = true }
|
||||
lru = "0.6.0"
|
||||
|
||||
@@ -18,7 +18,7 @@ android {
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
ndk {
|
||||
abiFilters 'x86', 'arm64-v8a'
|
||||
abiFilters 'x86', 'arm64-v8a', 'armeabi-v7a'
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
@@ -69,13 +69,14 @@ println("cargo target: ${project.buildDir.getAbsolutePath()}/rust-target")
|
||||
cargoNdk {
|
||||
targets = [
|
||||
"x86",
|
||||
"arm",
|
||||
"arm64"
|
||||
]
|
||||
librariesNames = ["libdrsembedded.so"]
|
||||
librariesNames = ["libdrsandroid.so"]
|
||||
//targetDirectory = "${project.buildDir.getAbsolutePath()}/rust-target"
|
||||
module = "../"
|
||||
module = "../drsandroid/"
|
||||
extraCargoEnv = ["ANDROID_NDK_HOME": android.ndkDirectory]
|
||||
extraCargoBuildArguments = ["--no-default-features", "--features", "backend-glutin ogg-playback scripting"]
|
||||
extraCargoBuildArguments = []
|
||||
verbose = true
|
||||
|
||||
buildTypes {
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
android:screenOrientation="sensorLandscape"
|
||||
android:launchMode="standard"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize">
|
||||
<meta-data android:name="android.app.lib_name" android:value="doukutsu_rs" />
|
||||
<meta-data android:name="android.app.lib_name" android:value="drsandroid" />
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::path::PathBuf;
|
||||
|
||||
// #[cfg(feature = "generate-gl")]
|
||||
// use gl_generator::{Api, Fallbacks, Profile, Registry};
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "drsandroid"
|
||||
version = "0.1.0"
|
||||
authors = ["Alula"]
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
ndk = "0.2"
|
||||
ndk-glue = "0.2"
|
||||
ndk-sys = "0.2"
|
||||
doukutsu-rs = { path = "../", default-features = false, features = ["android", "backend-glutin", "ogg-playback", "scripting"] }
|
||||
@@ -2,4 +2,4 @@
|
||||
#[cfg_attr(target_os = "android", ndk_glue::main())]
|
||||
pub fn android_main() {
|
||||
doukutsu_rs::init().unwrap();
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,32 @@ pub enum CaretType {
|
||||
PushJumpKey,
|
||||
}
|
||||
|
||||
impl CaretType {
|
||||
pub fn from_int(id: usize) -> Option<CaretType> {
|
||||
match id {
|
||||
0 => Some(CaretType::None),
|
||||
1 => Some(CaretType::Bubble),
|
||||
2 => Some(CaretType::ProjectileDissipation),
|
||||
3 => Some(CaretType::Shoot),
|
||||
4 => Some(CaretType::SnakeAfterimage),
|
||||
5 => Some(CaretType::Zzz),
|
||||
6 => Some(CaretType::SnakeAfterimage2),
|
||||
7 => Some(CaretType::Exhaust),
|
||||
8 => Some(CaretType::DrownedQuote),
|
||||
9 => Some(CaretType::QuestionMark),
|
||||
10 => Some(CaretType::LevelUp),
|
||||
11 => Some(CaretType::HurtParticles),
|
||||
12 => Some(CaretType::Explosion),
|
||||
13 => Some(CaretType::LittleParticles),
|
||||
14 => Some(CaretType::Unknown),
|
||||
15 => Some(CaretType::SmallProjectileDissipation),
|
||||
16 => Some(CaretType::Empty),
|
||||
17 => Some(CaretType::PushJumpKey),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Caret {
|
||||
pub ctype: CaretType,
|
||||
pub x: i32,
|
||||
|
||||
+7
-1
@@ -2,7 +2,7 @@ use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use num_traits::{abs, AsPrimitive, Num};
|
||||
use num_traits::{abs, Num};
|
||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use serde::de::{SeqAccess, Visitor};
|
||||
use serde::ser::SerializeTupleStruct;
|
||||
@@ -21,6 +21,7 @@ lazy_static! {
|
||||
|
||||
bitfield! {
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct Flag(u32);
|
||||
impl Debug;
|
||||
|
||||
@@ -63,6 +64,7 @@ impl Flag {
|
||||
|
||||
bitfield! {
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct Equipment(u16);
|
||||
impl Debug;
|
||||
|
||||
@@ -88,6 +90,7 @@ bitfield! {
|
||||
|
||||
bitfield! {
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct Condition(u16);
|
||||
impl Debug;
|
||||
|
||||
@@ -106,6 +109,7 @@ bitfield! {
|
||||
|
||||
bitfield! {
|
||||
#[derive(Clone, Copy, Serialize, Deserialize)]
|
||||
#[repr(C)]
|
||||
pub struct ControlFlags(u16);
|
||||
impl Debug;
|
||||
|
||||
@@ -121,6 +125,7 @@ bitfield! {
|
||||
|
||||
bitfield! {
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct BulletFlag(u16);
|
||||
impl Debug;
|
||||
pub flag_x01, set_flag_x01: 0; // 0x01
|
||||
@@ -257,6 +262,7 @@ impl<T: Num + PartialOrd + Copy> Point<T> {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct Rect<T: Num + PartialOrd + Copy = isize> {
|
||||
pub left: T,
|
||||
pub top: T,
|
||||
|
||||
@@ -37,7 +37,7 @@ impl Flash {
|
||||
}
|
||||
|
||||
impl GameEntity<()> for Flash {
|
||||
fn tick(&mut self, state: &mut SharedGameState, _custom: ()) -> GameResult<()> {
|
||||
fn tick(&mut self, _state: &mut SharedGameState, _custom: ()) -> GameResult<()> {
|
||||
match self.state {
|
||||
FlashState::None => {}
|
||||
FlashState::Cross(x, y, tick) => {
|
||||
|
||||
+60
-11
@@ -1,30 +1,79 @@
|
||||
use crate::entity::GameEntity;
|
||||
use crate::inventory::Inventory;
|
||||
use crate::framework::context::Context;
|
||||
use crate::frame::Frame;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::inventory::Inventory;
|
||||
use crate::player::Player;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
use crate::text_script::ScriptMode;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
enum InventoryFocus {
|
||||
None,
|
||||
Weapons,
|
||||
Items,
|
||||
}
|
||||
|
||||
pub struct InventoryUI {
|
||||
text_y_pos: usize,
|
||||
tick: usize,
|
||||
current_script: usize,
|
||||
focus: InventoryFocus,
|
||||
}
|
||||
|
||||
impl InventoryUI {
|
||||
pub fn new() -> InventoryUI {
|
||||
InventoryUI {
|
||||
text_y_pos: 24,
|
||||
tick: 0,
|
||||
InventoryUI { text_y_pos: 24, tick: 0, current_script: 0, focus: InventoryFocus::None }
|
||||
}
|
||||
}
|
||||
|
||||
impl GameEntity<(&mut Player, &mut Inventory)> for InventoryUI {
|
||||
fn tick(
|
||||
&mut self,
|
||||
state: &mut SharedGameState,
|
||||
(player, inventory): (&mut Player, &mut Inventory),
|
||||
) -> GameResult<()> {
|
||||
if state.control_flags.control_enabled()
|
||||
&& (player.controller.trigger_inventory() || player.controller.trigger_menu_back())
|
||||
{
|
||||
self.focus = InventoryFocus::None;
|
||||
state.textscript_vm.reset();
|
||||
state.textscript_vm.set_mode(ScriptMode::Map);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GameEntity<&mut Inventory> for InventoryUI {
|
||||
fn tick(&mut self, state: &mut SharedGameState, custom: &mut Inventory) -> GameResult<()> {
|
||||
match self.focus {
|
||||
InventoryFocus::None => {
|
||||
self.focus = InventoryFocus::Weapons;
|
||||
state.textscript_vm.start_script(1004);
|
||||
}
|
||||
InventoryFocus::Weapons => {}
|
||||
InventoryFocus::Items => {}
|
||||
}
|
||||
|
||||
self.tick = self.tick.wrapping_add(1);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw(&self, state: &mut SharedGameState, ctx: &mut Context, frame: &Frame) -> GameResult<()> {
|
||||
fn draw(&self, state: &mut SharedGameState, ctx: &mut Context, _frame: &Frame) -> GameResult<()> {
|
||||
let mut y = 8.0;
|
||||
|
||||
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "TextBox")?;
|
||||
for i in 0..=18 {
|
||||
let rect = match i {
|
||||
0 => &state.constants.textscript.inventory_rect_top,
|
||||
18 => &state.constants.textscript.inventory_rect_bottom,
|
||||
_ => &state.constants.textscript.inventory_rect_middle,
|
||||
};
|
||||
|
||||
batch.add_rect(((state.canvas_size.0 - 244.0) / 2.0).floor(), y, rect);
|
||||
y += 8.0;
|
||||
}
|
||||
|
||||
batch.draw(ctx)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ pub struct BoosterConsts {
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct MyCharConsts {
|
||||
pub display_bounds: Rect<usize>,
|
||||
pub hit_bounds: Rect<usize>,
|
||||
pub display_bounds: Rect<u32>,
|
||||
pub hit_bounds: Rect<u32>,
|
||||
pub life: u16,
|
||||
pub max_life: u16,
|
||||
pub control_mode: ControlMode,
|
||||
|
||||
@@ -3,8 +3,6 @@ use serde::{Deserialize, Serialize};
|
||||
use crate::common::Rect;
|
||||
|
||||
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
|
||||
|
||||
// 360/369 (97.56%) NPCs defined
|
||||
pub struct NPCConsts {
|
||||
// pub n000_null: () // Defined in code
|
||||
|
||||
@@ -1062,9 +1060,6 @@ pub struct NPCConsts {
|
||||
#[serde(default = "default_n360_credits_thank_you")]
|
||||
pub n360_credits_thank_you: Rect<u16>,
|
||||
|
||||
#[serde(default = "default_n361_gaudi_dashing")]
|
||||
pub n361_gaudi_dashing: [Rect<u16>; 4],
|
||||
|
||||
#[serde(default = "default_b01_omega")]
|
||||
pub b01_omega: [Rect<u16>; 10],
|
||||
|
||||
@@ -4744,15 +4739,6 @@ fn default_n360_credits_thank_you() -> Rect<u16> {
|
||||
Rect { left: 0, top: 176, right: 48, bottom: 184 }
|
||||
}
|
||||
|
||||
fn default_n361_gaudi_dashing() -> [Rect<u16>; 4] {
|
||||
[
|
||||
Rect { left: 48, top: 48, right: 72, bottom: 72 },
|
||||
Rect { left: 72, top: 48, right: 96, bottom: 72 },
|
||||
Rect { left: 48, top: 72, right: 72, bottom: 96 },
|
||||
Rect { left: 72, top: 72, right: 96, bottom: 96 },
|
||||
]
|
||||
}
|
||||
|
||||
fn default_b01_omega() -> [Rect<u16>; 10] {
|
||||
[
|
||||
Rect { left: 0, top: 0, right: 80, bottom: 56 },
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use imgui::DrawData;
|
||||
|
||||
use crate::common::{Color, Point, Rect};
|
||||
use crate::common::{Color, Rect};
|
||||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::framework::graphics::BlendMode;
|
||||
@@ -21,7 +21,7 @@ pub trait BackendRenderer {
|
||||
|
||||
fn present(&mut self) -> GameResult;
|
||||
|
||||
fn prepare_draw(&mut self, width: f32, height: f32) -> GameResult {
|
||||
fn prepare_draw(&mut self, _width: f32, _height: f32) -> GameResult {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ impl BackendTexture for NullTexture {
|
||||
(self.0, self.1)
|
||||
}
|
||||
|
||||
fn add(&mut self, command: SpriteBatchCommand) {
|
||||
fn add(&mut self, _command: SpriteBatchCommand) {
|
||||
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ impl BackendTexture for NullTexture {
|
||||
pub struct NullRenderer(RefCell<imgui::Context>);
|
||||
|
||||
impl BackendRenderer for NullRenderer {
|
||||
fn clear(&mut self, color: Color) {
|
||||
fn clear(&mut self, _color: Color) {
|
||||
|
||||
}
|
||||
|
||||
@@ -94,23 +94,23 @@ impl BackendRenderer for NullRenderer {
|
||||
Ok(Box::new(NullTexture(width, height)))
|
||||
}
|
||||
|
||||
fn create_texture(&mut self, width: u16, height: u16, data: &[u8]) -> GameResult<Box<dyn BackendTexture>> {
|
||||
fn create_texture(&mut self, width: u16, height: u16, _data: &[u8]) -> GameResult<Box<dyn BackendTexture>> {
|
||||
Ok(Box::new(NullTexture(width, height)))
|
||||
}
|
||||
|
||||
fn set_blend_mode(&mut self, blend: BlendMode) -> GameResult {
|
||||
fn set_blend_mode(&mut self, _blend: BlendMode) -> GameResult {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_render_target(&mut self, texture: Option<&Box<dyn BackendTexture>>) -> GameResult {
|
||||
fn set_render_target(&mut self, _texture: Option<&Box<dyn BackendTexture>>) -> GameResult {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw_rect(&mut self, rect: Rect<isize>, color: Color) -> GameResult {
|
||||
fn draw_rect(&mut self, _rect: Rect<isize>, _color: Color) -> GameResult {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw_outline_rect(&mut self, rect: Rect<isize>, line_width: usize, color: Color) -> GameResult {
|
||||
fn draw_outline_rect(&mut self, _rect: Rect<isize>, _line_width: usize, _color: Color) -> GameResult {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ impl BackendRenderer for NullRenderer {
|
||||
unsafe { Ok(&mut *self.0.as_ptr()) }
|
||||
}
|
||||
|
||||
fn render_imgui(&mut self, draw_data: &DrawData) -> GameResult {
|
||||
fn render_imgui(&mut self, _draw_data: &DrawData) -> GameResult {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
use imgui::internal::RawWrapper;
|
||||
use imgui::{ConfigFlags, DrawCmd, DrawData, ImString, Key, MouseCursor, TextureId, Ui};
|
||||
use imgui::{ConfigFlags, DrawCmd, DrawData, ImString, Key, MouseCursor, TextureId};
|
||||
use sdl2::event::{Event, WindowEvent};
|
||||
use sdl2::keyboard::Scancode;
|
||||
use sdl2::mouse::{Cursor, SystemCursor};
|
||||
@@ -17,7 +17,7 @@ use crate::common::{Color, Rect};
|
||||
use crate::framework::backend::{Backend, BackendEventLoop, BackendRenderer, BackendTexture, SpriteBatchCommand};
|
||||
use crate::framework::context::Context;
|
||||
use crate::framework::error::{GameError, GameResult};
|
||||
use crate::framework::graphics::{imgui_context, BlendMode};
|
||||
use crate::framework::graphics::{BlendMode};
|
||||
use crate::framework::keyboard::ScanCode;
|
||||
use crate::framework::ui::init_imgui;
|
||||
use crate::Game;
|
||||
@@ -121,7 +121,7 @@ impl BackendEventLoop for SDL2EventLoop {
|
||||
imgui.io_mut().display_size = [ctx.screen_size.0, ctx.screen_size.1];
|
||||
}
|
||||
}
|
||||
state.handle_resize(ctx);
|
||||
state.handle_resize(ctx).unwrap();
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
@@ -858,7 +858,6 @@ impl ImguiSdl2 {
|
||||
}
|
||||
|
||||
pub fn handle_event(&mut self, imgui: &mut imgui::Context, event: &Event) {
|
||||
use sdl2::keyboard;
|
||||
use sdl2::mouse::MouseButton;
|
||||
|
||||
fn set_mod(imgui: &mut imgui::Context, keymod: keyboard::Mod) {
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
use std::env;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::io::SeekFrom;
|
||||
use std::path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use directories::ProjectDirs;
|
||||
|
||||
use crate::framework::context::Context;
|
||||
use crate::framework::error::{GameError, GameResult};
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt::{self, Debug};
|
||||
use std::fs;
|
||||
use std::io::{BufRead, Read, Seek, Write};
|
||||
use std::io::{Read, Seek, Write};
|
||||
use std::path::{self, Path, PathBuf};
|
||||
|
||||
use crate::framework::error::{GameError, GameResult};
|
||||
|
||||
+276
@@ -0,0 +1,276 @@
|
||||
use crate::caret::CaretType;
|
||||
use crate::common::Direction;
|
||||
use crate::npc::list::NPCList;
|
||||
use crate::npc::NPC;
|
||||
use crate::player::Player;
|
||||
use crate::rng::RNG;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
use crate::stage::Stage;
|
||||
use crate::weapon::bullet::BulletManager;
|
||||
|
||||
pub struct CHooks {
|
||||
handle_npc: unsafe extern "C" fn(callbacks: *const Callbacks, ctx: *const CtxData),
|
||||
}
|
||||
|
||||
pub struct Callbacks {
|
||||
random: unsafe extern "C" fn(ctx: *mut CtxData, min: i32, max: i32) -> i32,
|
||||
play_sfx: unsafe extern "C" fn(ctx: *mut CtxData, id: u8),
|
||||
set_quake: unsafe extern "C" fn(ctx: *mut CtxData, ticks: u16),
|
||||
set_caret: unsafe extern "C" fn(ctx: *mut CtxData, x: i32, y: i32, id: u16, direction: u8),
|
||||
get_flag: unsafe extern "C" fn(ctx: *mut CtxData, id: u16) -> bool,
|
||||
get_map_data: unsafe extern "C" fn(ctx: *mut CtxData) -> MapData,
|
||||
get_player_info: unsafe extern "C" fn(ctx: *mut CtxData) -> PlayerInfo,
|
||||
update_player_info: unsafe extern "C" fn(ctx: *mut CtxData, player_info: *const PlayerInfo),
|
||||
destroy_npc: unsafe extern "C" fn(ctx: *mut CtxData, npc: *mut NPC),
|
||||
vanish_npc: unsafe extern "C" fn(ctx: *mut CtxData, npc: *mut NPC),
|
||||
create_npc: unsafe extern "C" fn(
|
||||
ctx: *mut CtxData,
|
||||
npc_id: u16,
|
||||
x: i32,
|
||||
y: i32,
|
||||
vel_x: i32,
|
||||
vel_y: i32,
|
||||
direction: u16,
|
||||
parent: u16,
|
||||
min_id: u16,
|
||||
),
|
||||
get_npc: unsafe extern "C" fn(ctx: *mut CtxData, npc_id: u16) -> *mut NPC,
|
||||
current_npc: unsafe extern "C" fn(ctx: *mut CtxData) -> *mut NPC,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PlayerInfo {
|
||||
x: i32,
|
||||
y: i32,
|
||||
vel_x: i32,
|
||||
vel_y: i32,
|
||||
flags: u32,
|
||||
anim_num: u16,
|
||||
cond: u16,
|
||||
shock: u8,
|
||||
direct: u8,
|
||||
up: bool,
|
||||
down: bool,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct MapData {
|
||||
tiles: *const u8,
|
||||
attrib: *const u8,
|
||||
width: u16,
|
||||
height: u16,
|
||||
}
|
||||
|
||||
static mut HOOKS: *mut CHooks = std::ptr::null_mut();
|
||||
struct CtxData<'a, 'b, 'c, 'd, 'e, 'f>(
|
||||
&'a mut NPC,
|
||||
&'b mut SharedGameState,
|
||||
&'c mut Player,
|
||||
&'d NPCList,
|
||||
&'e mut Stage,
|
||||
&'f BulletManager,
|
||||
);
|
||||
|
||||
pub fn init_hooks() {
|
||||
#[cfg(target_os = "linux")]
|
||||
unsafe {
|
||||
let module: *mut libc::c_void = libc::dlopen(b"./libdrshooks.so\0".as_ptr() as *const _, libc::RTLD_NOW);
|
||||
if module.is_null() {
|
||||
let error = libc::dlerror();
|
||||
let message = std::ffi::CString::from_raw(error).to_string_lossy().to_string();
|
||||
|
||||
log::warn!("Cannot initialize hooks?: {}", message);
|
||||
return;
|
||||
}
|
||||
|
||||
log::info!("Loaded libhooks...");
|
||||
|
||||
let symbol: *mut libc::c_void = libc::dlsym(module, b"drs_hooks_init\0".as_ptr() as *const _);
|
||||
|
||||
if symbol.is_null() {
|
||||
log::warn!("initialization function hasn't been found in libhooks.");
|
||||
return;
|
||||
}
|
||||
|
||||
let init: unsafe extern "C" fn() -> *mut CHooks = std::mem::transmute(symbol);
|
||||
HOOKS = (init)();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
unsafe {
|
||||
use winapi::um::libloaderapi::LoadLibraryA;
|
||||
use winapi::um::libloaderapi::GetProcAddress;
|
||||
use winapi::um::errhandlingapi::GetLastError;
|
||||
|
||||
let module = LoadLibraryA(b"drshooks.dll\0".as_ptr() as *const _);
|
||||
|
||||
if module.is_null() {
|
||||
let error = GetLastError();
|
||||
|
||||
log::warn!("Cannot initialize hooks?: {:#x}", error);
|
||||
return;
|
||||
}
|
||||
|
||||
log::info!("Loaded libhooks...");
|
||||
|
||||
let symbol = GetProcAddress(module, b"drs_hooks_init\0".as_ptr() as *const _);
|
||||
|
||||
if symbol.is_null() {
|
||||
log::warn!("initialization function hasn't been found in libhooks.");
|
||||
return;
|
||||
}
|
||||
|
||||
let init: unsafe extern "C" fn() -> *mut CHooks = std::mem::transmute(symbol);
|
||||
HOOKS = (init)();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reload_hooks() {}
|
||||
|
||||
pub fn run_npc_hook(
|
||||
npc: &mut NPC,
|
||||
state: &mut SharedGameState,
|
||||
players: [&mut Player; 2],
|
||||
npc_list: &NPCList,
|
||||
stage: &mut Stage,
|
||||
bullet_manager: &BulletManager,
|
||||
) {
|
||||
unsafe {
|
||||
let mut ctx_data = CtxData(npc, state, players[0], npc_list, stage, bullet_manager);
|
||||
|
||||
unsafe extern "C" fn random(ctx: *mut CtxData, min: i32, max: i32) -> i32 {
|
||||
let ctx = &*ctx;
|
||||
|
||||
ctx.0.rng.range(min..max)
|
||||
};
|
||||
|
||||
unsafe extern "C" fn play_sfx(ctx: *mut CtxData, id: u8) {
|
||||
(*ctx).1.sound_manager.play_sfx(id);
|
||||
}
|
||||
|
||||
unsafe extern "C" fn set_quake(ctx: *mut CtxData, ticks: u16) {
|
||||
(*ctx).1.quake_counter = ticks;
|
||||
}
|
||||
|
||||
unsafe extern "C" fn set_caret(ctx: *mut CtxData, x: i32, y: i32, id: u16, direction: u8) {
|
||||
(*ctx).1.create_caret(
|
||||
x,
|
||||
y,
|
||||
CaretType::from_int(id as usize).unwrap_or(CaretType::None),
|
||||
Direction::from_int_facing(direction as usize).unwrap_or(Direction::Left),
|
||||
);
|
||||
}
|
||||
|
||||
unsafe extern "C" fn get_flag(ctx: *mut CtxData, id: u16) -> bool {
|
||||
(*ctx).1.get_flag(id as usize)
|
||||
}
|
||||
|
||||
unsafe extern "C" fn get_map_data(ctx: *mut CtxData) -> MapData {
|
||||
let stage = &(*ctx).4;
|
||||
|
||||
MapData {
|
||||
tiles: stage.map.tiles.as_ptr(),
|
||||
attrib: stage.map.attrib.as_ptr(),
|
||||
width: stage.map.width,
|
||||
height: stage.map.height,
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn get_player_info(ctx: *mut CtxData) -> PlayerInfo {
|
||||
let player = &(*ctx).2;
|
||||
|
||||
PlayerInfo {
|
||||
x: player.x,
|
||||
y: player.y,
|
||||
vel_x: player.vel_x,
|
||||
vel_y: player.vel_y,
|
||||
flags: player.flags.0,
|
||||
anim_num: player.anim_num,
|
||||
cond: player.cond.0,
|
||||
shock: player.shock_counter,
|
||||
direct: player.direction as u8,
|
||||
up: player.up,
|
||||
down: player.down
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn update_player_info(ctx: *mut CtxData, player_info: *const PlayerInfo) {
|
||||
let mut player = &mut (*ctx).2;
|
||||
let player_info = &(*player_info);
|
||||
|
||||
player.x = player_info.x;
|
||||
player.y = player_info.y;
|
||||
player.vel_x = player_info.vel_x;
|
||||
player.vel_y = player_info.vel_y;
|
||||
player.flags.0 = player_info.flags;
|
||||
player.cond.0 = player_info.cond;
|
||||
player.direction = Direction::from_int(player_info.direct as usize).unwrap_or(Direction::Left);
|
||||
}
|
||||
|
||||
unsafe extern "C" fn create_npc(
|
||||
ctx: *mut CtxData,
|
||||
npc_id: u16,
|
||||
x: i32,
|
||||
y: i32,
|
||||
vel_x: i32,
|
||||
vel_y: i32,
|
||||
direction: u16,
|
||||
parent: u16,
|
||||
min_id: u16,
|
||||
) {
|
||||
let ctx = &*ctx;
|
||||
|
||||
let mut npc = NPC::create(npc_id, &ctx.1.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = x;
|
||||
npc.y = y;
|
||||
npc.vel_x = vel_x;
|
||||
npc.vel_y = vel_y;
|
||||
npc.direction = Direction::from_int(direction as usize).unwrap_or(Direction::Left);
|
||||
npc.tsc_direction = direction;
|
||||
npc.parent_id = parent;
|
||||
|
||||
let _ = ctx.3.spawn(min_id, npc);
|
||||
};
|
||||
|
||||
unsafe extern "C" fn get_npc(ctx: *mut CtxData, npc_id: u16) -> *mut NPC {
|
||||
(*ctx).3.get_npc(npc_id as usize).unwrap() as *mut NPC
|
||||
}
|
||||
|
||||
unsafe extern "C" fn destroy_npc(ctx: *mut CtxData, npc: *mut NPC) {
|
||||
let npc = &mut (*npc);
|
||||
|
||||
npc.cond.set_explode_die(true);
|
||||
}
|
||||
|
||||
unsafe extern "C" fn vanish_npc(ctx: *mut CtxData, npc: *mut NPC) {
|
||||
let npc = &mut (*npc);
|
||||
|
||||
npc.vanish((*ctx).1);
|
||||
}
|
||||
|
||||
unsafe extern "C" fn current_npc(ctx: *mut CtxData) -> *mut NPC {
|
||||
(*ctx).0 as *mut NPC
|
||||
}
|
||||
|
||||
let callbacks = Callbacks {
|
||||
random,
|
||||
play_sfx,
|
||||
set_quake,
|
||||
set_caret,
|
||||
get_flag,
|
||||
get_map_data,
|
||||
get_player_info,
|
||||
update_player_info,
|
||||
destroy_npc,
|
||||
vanish_npc,
|
||||
create_npc,
|
||||
get_npc,
|
||||
current_npc,
|
||||
};
|
||||
|
||||
if let Some(hook) = HOOKS.as_ref() {
|
||||
(hook.handle_npc)(&callbacks as *const Callbacks, &mut ctx_data as *mut CtxData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,6 @@ use crate::engine_constants::EngineConstants;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
use crate::weapon::{Weapon, WeaponLevel, WeaponType};
|
||||
use crate::player::{Player, TargetPlayer};
|
||||
use crate::caret::CaretType;
|
||||
use crate::common::Direction;
|
||||
use crate::weapon::bullet::BulletManager;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
||||
@@ -43,6 +43,8 @@ mod frame;
|
||||
mod framework;
|
||||
mod input;
|
||||
mod inventory;
|
||||
#[cfg(feature = "hooks")]
|
||||
mod hooks;
|
||||
mod live_debugger;
|
||||
mod macros;
|
||||
mod map;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user