@ -35,11 +35,12 @@ local module_states = {} -- persistent state per module for render()
local command_handlers = { }
local command_handlers = { }
local framework = { }
local framework = { }
local _current_module = nil
local _current_module = nil
admin_visible = false
local admin_visible = false
local recent_logs = { }
local recent_logs = { }
local MAX_LOGS = 100
local MAX_LOGS = 100
local notifications = { } -- {text, level, time, start}
local notifications = { } -- {text, level, time, start}
local module_errors = { } -- ["module_name"] = "last error"
local module_errors = { } -- ["module_name"] = "last error"
local module_windows = { } -- {name = {visible, title, width, height}}
local function log ( level , tag , ... )
local function log ( level , tag , ... )
if not rust then return print ( " [ " .. level .. " ][ " .. tag .. " ] " , ... ) end
if not rust then return print ( " [ " .. level .. " ][ " .. tag .. " ] " , ... ) end
@ -503,6 +504,33 @@ function setup_framework()
rust.rgl_register_command ( name , owner )
rust.rgl_register_command ( name , owner )
log ( " INFO " , " CMD " , " Registered / " .. name .. " ( " .. owner .. " ) " )
log ( " INFO " , " CMD " , " Registered / " .. name .. " ( " .. owner .. " ) " )
end
end
-- Module imgui window registry
framework.register_window = function ( opts )
opts = opts or { }
local mod_name = _current_module or " __unknown "
module_windows [ mod_name ] = {
visible = false ,
title = opts.title or mod_name ,
width = opts.width or 450 ,
height = opts.height or 400 ,
}
end
framework.toggle_window = function ( name )
local w = module_windows [ name or _current_module ]
if w then w.visible = not w.visible end
end
framework.show_window = function ( name )
local w = module_windows [ name or _current_module ]
if w then w.visible = true end
end
framework.hide_window = function ( name )
local w = module_windows [ name or _current_module ]
if w then w.visible = false end
end
end
end
----------------------------------------------------------------
----------------------------------------------------------------
@ -514,8 +542,15 @@ function load_single_module(name)
local f = io.open ( path ) ; if not f then return false , " not found " end ; f : close ( )
local f = io.open ( path ) ; if not f then return false , " not found " end ; f : close ( )
_current_module = name
_current_module = name
local ok , mod = pcall ( dofile , path )
local chunk , cerr = loadfile ( path )
if not ok then _current_module = nil ; return false , " load: " .. tostring ( mod ) end
if not chunk then _current_module = nil ; return false , " load: " .. tostring ( cerr ) end
-- Sandbox: module gets its own environment, reads fall through to _G
local sandbox = setmetatable ( { } , { __index = _G } )
setfenv ( chunk , sandbox )
local ok , mod = pcall ( chunk )
if not ok then _current_module = nil ; return false , " exec: " .. tostring ( mod ) end
if not mod or not mod.init then _current_module = nil ; return false , " no init() " end
if not mod or not mod.init then _current_module = nil ; return false , " no init() " end
-- Create per-module framework wrapper with bound db prefix
-- Create per-module framework wrapper with bound db prefix
@ -565,7 +600,7 @@ function load_single_module(name)
_current_module = nil
_current_module = nil
if not iok then return false , " init: " .. tostring ( ierr ) end
if not iok then return false , " init: " .. tostring ( ierr ) end
loaded_modules [ name ] = { mod = mod , status = " loaded " }
loaded_modules [ name ] = { mod = mod , status = " loaded " , sandbox = sandbox }
module_states [ name ] = module_states [ name ] or { }
module_states [ name ] = module_states [ name ] or { }
register_module_render ( name )
register_module_render ( name )
log ( " INFO " , " MODS " , " Loaded: " .. name )
log ( " INFO " , " MODS " , " Loaded: " .. name )
@ -585,6 +620,7 @@ function unload_single_module(name)
event_interceptors [ ev ] = new
event_interceptors [ ev ] = new
end
end
rust.rgl_register_module ( name , " " )
rust.rgl_register_module ( name , " " )
module_windows [ name ] = nil
loaded_modules [ name ] = nil
loaded_modules [ name ] = nil
log ( " INFO " , " MODS " , " Unloaded: " .. name )
log ( " INFO " , " MODS " , " Unloaded: " .. name )
return true
return true
@ -964,20 +1000,30 @@ if imgui_loaded and imgui then
end
end
)
)
-- BTC module window (and any other module with render() )
-- Dynamic module windows (registered via fw.register_window )
local btc_window = imgui.new . bool ( )
local mod_window_bool = imgui.new . bool ( )
imgui.OnFrame (
imgui.OnFrame (
function ( ) return btc_visible end ,
function ( )
function ( )
btc_window [ 0 ] = true
for _ , w in pairs ( module_windows ) do
imgui.SetNextWindowSize ( imgui.ImVec2 ( 450 * dpi , 400 * dpi ) , imgui.Cond . FirstUseEver )
if w.visible then return true end
imgui.Begin ( " BTC Miner " , btc_window , imgui.WindowFlags . NoCollapse )
end
return false
end ,
function ( )
for name , w in pairs ( module_windows ) do
if w.visible then
mod_window_bool [ 0 ] = true
imgui.SetNextWindowSize (
imgui.ImVec2 ( w.width * dpi , w.height * dpi ) ,
imgui.Cond . FirstUseEver
)
imgui.Begin ( w.title , mod_window_bool , imgui.WindowFlags . NoCollapse )
local mod = loaded_modules and loaded_modules [ " btc " ]
local entry = loaded_modules and loaded_modules [ name ]
if mod and mod.mod and mod.mod . render then
if entry and entry.mod and entry .mod. render then
local ui = create_ui_imgui ( )
local ui = create_ui_imgui ( )
if ui then
if ui then
local rok , rerr = pcall ( mod.mod . render , ui , module_states [ " btc " ] or { } )
local rok , rerr = pcall ( entry.mod. render , ui , module_states [ name ] or { } )
if not rok then
if not rok then
imgui.TextColored ( imgui.ImVec4 ( 1 , 0.3 , 0.3 , 1 ) , " Render error: " )
imgui.TextColored ( imgui.ImVec4 ( 1 , 0.3 , 0.3 , 1 ) , " Render error: " )
imgui.TextWrapped ( tostring ( rerr ) )
imgui.TextWrapped ( tostring ( rerr ) )
@ -985,11 +1031,13 @@ if imgui_loaded and imgui then
imgui.EndTabBar ( )
imgui.EndTabBar ( )
end
end
else
else
imgui.Text ( " BTC module not loaded" )
imgui.Text ( name .. " module not loaded" )
end
end
imgui.End ( )
imgui.End ( )
if not btc_window [ 0 ] then btc_visible = false end
if not mod_window_bool [ 0 ] then w.visible = false end
end
end
end
end
)
)