1use proc_macro::TokenStream;
2use quote::{format_ident, quote, ToTokens};
3use syn::{parse_macro_input, ItemStruct};
4
5#[proc_macro_attribute]
6pub fn plugin(_args: TokenStream, stream: TokenStream) -> TokenStream {
7 let input = parse_macro_input!(stream as ItemStruct);
8 let mut output = proc_macro2::TokenStream::new();
9
10 let plugin_t = format_ident!("{}", input.ident);
11 let plugin = format_ident!("__{}", input.ident.to_string().to_uppercase());
12
13 let eq_version_str = include_str!(concat!(env!("OUT_DIR"), "/eq_version.txt")).as_bytes();
14
15 let implementation = quote! {
16 #[no_mangle]
17 pub static IsBuiltForNext: bool = true;
18
19 #[no_mangle]
20 pub static EverQuestVersion: [u8; 21] = [#(#eq_version_str),*,0];
21
22
23 static #plugin: ::macroquest::PluginHandler<#plugin_t> = ::macroquest::PluginHandler::new();
24
25 #[no_mangle]
26 extern "system" fn DllMain(
27 _: ::macroquest::windows::HINSTANCE,
28 call_reason: u32,
29 _: *mut (),
30 ) -> bool {
31 use ::macroquest::windows::{DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH};
32
33 match call_reason {
34 DLL_PROCESS_ATTACH => #plugin.replace(Some(#plugin_t::new())),
35 DLL_PROCESS_DETACH => #plugin.replace(None),
36 _ => {}
37 }
38
39 true
40 }
41
42 #[no_mangle]
43 pub fn InitializePlugin() {
44 #plugin.initialize()
45 }
46
47 #[no_mangle]
48 pub fn ShutdownPlugin() {
49 #plugin.shutdown()
50 }
51
52 #[no_mangle]
53 pub fn OnCleanUI() {
54 #plugin.on_clean_ui()
55 }
56
57 #[no_mangle]
58 pub fn OnReloadUI() {
59 #plugin.on_reload_ui()
60 }
61
62 #[no_mangle]
63 pub fn OnDrawHUD() {
64 #plugin.on_draw_hud()
65 }
66
67 #[no_mangle]
68 pub fn SetGameState(state: i32) {
69 #plugin.on_set_game_state(state)
70 }
71
72 #[no_mangle]
73 pub fn OnPulse() {
74 #plugin.on_pulse()
75 }
76
77 #[no_mangle]
78 pub unsafe fn OnWriteChatColor(
79 line_ptr: *const ::std::os::raw::c_char,
80 color: i32,
81 _filter: i32, ) {
83 #plugin.on_write_chat_color(line_ptr, color)
84 }
85
86 #[no_mangle]
87 pub unsafe fn OnIncomingChat(
88 line_ptr: *const ::std::os::raw::c_char,
89 color: u32,
90 ) -> bool {
91 #plugin.on_incoming_chat(line_ptr, color as i32)
92 }
93
94 #[no_mangle]
95 pub unsafe fn OnAddSpawn(spawn: *const ::macroquest::ffi::eqlib::PlayerClient) {
96 #plugin.on_add_spawn(spawn)
97 }
98
99 #[no_mangle]
100 pub unsafe fn OnRemoveSpawn(spawn: *const ::macroquest::ffi::eqlib::PlayerClient) {
101 #plugin.on_remove_spawn(spawn)
102 }
103
104 #[no_mangle]
105 pub unsafe fn OnAddGroundItem(item: *const ::macroquest::ffi::eqlib::EQGroundItem) {
106 #plugin.on_add_ground_item(item)
107 }
108
109 #[no_mangle]
110 pub unsafe fn OnRemoveGroundItem(item: *const ::macroquest::ffi::eqlib::EQGroundItem) {
111 #plugin.on_remove_ground_item(item)
112 }
113
114 #[no_mangle]
115 pub fn OnBeginZone() {
116 #plugin.on_begin_zone()
117 }
118
119 #[no_mangle]
120 pub fn OnEndZone() {
121 #plugin.on_end_zone()
122 }
123
124 #[no_mangle]
125 pub fn OnZoned() {
126 #plugin.on_zoned()
127 }
128
129 #[no_mangle]
130 pub fn OnUpdateImGui() {
131 #plugin.on_update_imgui()
132 }
133
134 #[no_mangle]
135 pub unsafe fn OnMacroStart(name_ptr: *const ::std::os::raw::c_char) {
136 #plugin.on_macro_start(name_ptr)
137 }
138
139 #[no_mangle]
140 pub unsafe fn OnMacroStop(name_ptr: *const ::std::os::raw::c_char) {
141 #plugin.on_macro_stop(name_ptr)
142 }
143
144 #[no_mangle]
145 pub unsafe fn OnLoadPlugin(name_ptr: *const ::std::os::raw::c_char) {
146 #plugin.on_plugin_load(name_ptr)
147 }
148
149 #[no_mangle]
150 pub unsafe fn OnUnloadPlugin(name_ptr: *const ::std::os::raw::c_char) {
151 #plugin.on_plugin_unload(name_ptr)
152 }
153 };
154
155 input.to_tokens(&mut output);
156 implementation.to_tokens(&mut output);
157
158 TokenStream::from(output)
159}
160
161