mirror of
https://forgejo.xatacraft.ru/Sunshine/mkxp-sunshine.git
synced 2026-08-22 23:06:18 +00:00
Better Modloading Support
This commit is contained in:
parent
48dda7da8c
commit
95ab9c4434
9 changed files with 139 additions and 50 deletions
|
|
@ -326,6 +326,7 @@ set(BINDING_SOURCE
|
|||
binding-mri/gamepad-binding.cpp
|
||||
binding-mri/profiler-binding.cpp
|
||||
binding-mri/audioplayback-binding.cpp
|
||||
binding-mri/physfs-binding.cpp
|
||||
)
|
||||
|
||||
source_group("Binding Source" FILES ${BINDING_SOURCE} ${BINDING_HEADERS})
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ void shaderBindingInit();
|
|||
void keybindingsBindingInit();
|
||||
void lightmapBindingInit();
|
||||
void ProfilerInit();
|
||||
void PhysFS_binding_init();
|
||||
|
||||
RB_METHOD(mriPrint);
|
||||
RB_METHOD(mriP);
|
||||
|
|
@ -150,6 +151,7 @@ static void mriBindingInit(){
|
|||
keybindingsBindingInit();
|
||||
lightmapBindingInit();
|
||||
ProfilerInit();
|
||||
PhysFS_binding_init();
|
||||
|
||||
_rb_define_module_function(rb_mKernel, "rgss_main", mriRgssMain);
|
||||
_rb_define_module_function(rb_mKernel, "rgss_stop", mriRgssStop);
|
||||
|
|
|
|||
|
|
@ -1,25 +1,14 @@
|
|||
//https://silverhammermba.github.io/emberb/c/
|
||||
//https://docs.ruby-lang.org/capi/en/master/d8/d68/include_2ruby_2internal_2intern_2string_8h.html
|
||||
#include "binding-util.h"
|
||||
#include "sharedstate.h"
|
||||
#include "filesystem.h"
|
||||
#include "util.h"
|
||||
#include "debugwriter.h"
|
||||
#include "ruby/encoding.h"
|
||||
#include "ruby/intern.h"
|
||||
#include "ruby/thread.h"
|
||||
#include "modloader.h"
|
||||
#include "config.h"
|
||||
#include <ruby.h>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <system_error>
|
||||
#include <vector>
|
||||
#include <physfs.h>
|
||||
#include <string>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
#include <vector>
|
||||
VALUE meow(const std::vector<std::string> vec){
|
||||
VALUE ary = rb_ary_new_capa((long)vec.size());
|
||||
for (const std::string &s : vec) {
|
||||
|
|
@ -29,7 +18,7 @@ VALUE meow(const std::vector<std::string> vec){
|
|||
return ary;
|
||||
}
|
||||
|
||||
static VALUE hooks(int argc, VALUE *argv, VALUE self) {
|
||||
static VALUE hooks(int argc, VALUE *argv, VALUE self){
|
||||
VALUE v_path = Qnil;
|
||||
rb_scan_args(argc, argv, "01", &v_path);
|
||||
std::string hook_path = "hooks";
|
||||
|
|
@ -38,23 +27,54 @@ static VALUE hooks(int argc, VALUE *argv, VALUE self) {
|
|||
hook_path = StringValueCStr(v_path);
|
||||
}
|
||||
|
||||
std::vector<std::string> files = {};
|
||||
if(!std::filesystem::exists(hook_path)){
|
||||
return meow(files);
|
||||
}
|
||||
for (const auto &entry : std::filesystem::directory_iterator(hook_path, std::filesystem::directory_options::skip_permission_denied)) {
|
||||
std::error_code ec;
|
||||
auto p = entry.path();
|
||||
if (!std::filesystem::is_regular_file(p, ec) || ec) continue;
|
||||
|
||||
auto ext = p.extension().string();
|
||||
if (ext != ".rb") continue;
|
||||
|
||||
std::string full = p.string();
|
||||
Debug() << "[MODLOADER] Executing hook: " << full;
|
||||
files.push_back(full);
|
||||
}
|
||||
return meow(files);
|
||||
std::vector<std::string> files;
|
||||
if (!PHYSFS_exists(hook_path.c_str())) {
|
||||
return meow(files);
|
||||
}
|
||||
|
||||
PHYSFS_Stat dir_stat{};
|
||||
|
||||
if (
|
||||
PHYSFS_stat(hook_path.c_str(), &dir_stat) == 0 ||
|
||||
dir_stat.filetype != PHYSFS_FILETYPE_DIRECTORY
|
||||
) {
|
||||
return meow(files);
|
||||
}
|
||||
|
||||
char **list = PHYSFS_enumerateFiles(hook_path.c_str());
|
||||
|
||||
if (list == nullptr) {
|
||||
return meow(files);
|
||||
}
|
||||
|
||||
for (char **entry = list; *entry != nullptr; ++entry) {
|
||||
std::string name = *entry;
|
||||
std::string full_path = hook_path;
|
||||
|
||||
if (!full_path.empty() && full_path.back() != '/') {
|
||||
full_path += '/';
|
||||
}
|
||||
|
||||
full_path += name;
|
||||
PHYSFS_Stat file_stat{};
|
||||
if (PHYSFS_stat(full_path.c_str(), &file_stat) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (file_stat.filetype != PHYSFS_FILETYPE_REGULAR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (name.size() < 3 ||
|
||||
name.compare(name.size() - 3, 3, ".rb") != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Debug() << "[MODLOADER] Executing hook: " << full_path;
|
||||
files.push_back(full_path);
|
||||
}
|
||||
PHYSFS_freeList(list);
|
||||
return meow(files);
|
||||
}
|
||||
|
||||
void ModLoaderBindingInit(){
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
module Kernel
|
||||
alias_method :original_puts, :puts
|
||||
|
||||
def puts(*args)
|
||||
string = ""
|
||||
args.each do |arg|
|
||||
|
|
@ -9,7 +8,6 @@ module Kernel
|
|||
MKXP.puts string
|
||||
return nil
|
||||
end
|
||||
|
||||
module_function :puts
|
||||
end
|
||||
|
||||
|
|
@ -17,15 +15,7 @@ module RPG
|
|||
module Cache
|
||||
@cache = {}
|
||||
def self.load_bitmap(folder_name, filename, hue = 0)
|
||||
if ModLoader::IS_ENABLED
|
||||
if File.exist?("/mod-storage/" + folder_name + filename)
|
||||
path = Graphics.adapted_file("/mod-storage/" + folder_name + filename)
|
||||
else
|
||||
path = Graphics.adapted_file(folder_name + filename)
|
||||
end
|
||||
else
|
||||
path = Graphics.adapted_file(folder_name + filename)
|
||||
end
|
||||
path = Graphics.adapted_file(folder_name + filename)
|
||||
if not @cache.include?(path) or @cache[path].disposed?
|
||||
if filename != ""
|
||||
@cache[path] = Bitmap.new(path)
|
||||
|
|
@ -1323,7 +1313,7 @@ module RPG
|
|||
return unless ModLoader::IS_ENABLED
|
||||
return unless path.is_a?(String)
|
||||
ModLoader.hooks(path).each do |item|
|
||||
eval(File.read(item), b)
|
||||
eval(PhysFS.read(item), b)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
70
binding-mri/physfs-binding.cpp
Normal file
70
binding-mri/physfs-binding.cpp
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#include <physfs.h>
|
||||
#include "binding-util.h"
|
||||
#include "sharedstate.h"
|
||||
#include "filesystem.h"
|
||||
#include "util.h"
|
||||
#include <ruby.h>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
VALUE module = Qnil;
|
||||
VALUE rb_ePhysFSError = Qnil;
|
||||
|
||||
std::string toStdString(VALUE v) {
|
||||
Check_Type(v, T_STRING);
|
||||
return std::string{ RSTRING_PTR(v), static_cast<std::size_t>(RSTRING_LEN(v)) };
|
||||
}
|
||||
|
||||
static VALUE rb_PhysFS_Exist(VALUE, VALUE path) {
|
||||
if(PHYSFS_exists(StringValuePtr(path)) > 0){
|
||||
return Qtrue;
|
||||
}else{
|
||||
return Qfalse;
|
||||
}
|
||||
}
|
||||
|
||||
static VALUE rb_PhysFS_Directory(VALUE, VALUE path) {
|
||||
if(PHYSFS_isDirectory(StringValuePtr(path)) > 0){
|
||||
return Qtrue;
|
||||
}else{
|
||||
return Qfalse;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<char> loadFully(const char* path) {
|
||||
PHYSFS_File* file = PHYSFS_openRead(path);
|
||||
if (!file){
|
||||
WarnMsg("Failed to load PhysFS file %s", path);
|
||||
return {};
|
||||
}
|
||||
const auto length = PHYSFS_fileLength(file);
|
||||
std::vector<char> buffer;
|
||||
if (length > 0) {
|
||||
buffer.resize(static_cast<std::size_t>(length));
|
||||
const auto got = PHYSFS_readBytes(file, buffer.data(), static_cast<PHYSFS_uint64>(length));
|
||||
if (got != length && !PHYSFS_eof(file)) {
|
||||
PHYSFS_close(file);
|
||||
WarnMsg("PhysFS readBytes failed for '%s'", path);
|
||||
}
|
||||
buffer.resize(static_cast<std::size_t>(got));
|
||||
}
|
||||
PHYSFS_close(file);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static VALUE rb_PhysFS_Read(VALUE, VALUE path) {
|
||||
try {
|
||||
const auto buf = loadFully(StringValuePtr(path));
|
||||
return rb_str_new(buf.data(), static_cast<long>(buf.size()));
|
||||
} catch (const std::exception& e) {
|
||||
rb_raise(rb_ePhysFSError, "%s", e.what());
|
||||
}
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
void PhysFS_binding_init(){
|
||||
VALUE module = rb_define_module("PhysFS");
|
||||
rb_ePhysFSError = rb_define_class_under(module, "Error", rb_eStandardError);
|
||||
rb_define_module_function(module, "exist?", rb_PhysFS_Exist, 1);
|
||||
rb_define_module_function(module, "directory?", rb_PhysFS_Directory, 1);
|
||||
rb_define_module_function(module, "read", rb_PhysFS_Read, 1);
|
||||
}
|
||||
|
|
@ -40,9 +40,13 @@ module Graphics
|
|||
|
||||
def self.adapted_file(path, extention = ".png")
|
||||
file_tag = RESOLUTIONS[Settings[:resolution] || 999]&.[](:file_tag) || ""
|
||||
if File.exist?(path + file_tag + extention)
|
||||
return path + file_tag
|
||||
if PhysFS.exist?(path + file_tag + extention)
|
||||
return path + file_tag
|
||||
else
|
||||
if File.exist?(path + file_tag + extention)
|
||||
return path + file_tag
|
||||
end
|
||||
end
|
||||
path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
0
scripts/Graphics.rb
Normal file
0
scripts/Graphics.rb
Normal file
|
|
@ -17,6 +17,7 @@ end
|
|||
|
||||
begin
|
||||
RPG::Mod.exec_hooks("hooks/Main/start", binding)
|
||||
print PhysFS.exist?("gaysex")
|
||||
$console = Graphics.fullscreen
|
||||
Graphics.frame_rate = 60
|
||||
Font.default_size = 20
|
||||
|
|
|
|||
|
|
@ -15,11 +15,12 @@
|
|||
#include <SDL3/SDL_video.h>
|
||||
#include <SDL3/SDL_timer.h>
|
||||
#include <SDL3_image/SDL_image.h>
|
||||
|
||||
#include <physfs.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "the_modded_machine.png.xxd"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
static bool stop_render = false;
|
||||
const static std::size_t N = 46;
|
||||
|
||||
|
|
@ -94,7 +95,7 @@ void ModLoader(Config conf, SDL_Window* win){
|
|||
std::string full = p.string();
|
||||
|
||||
if (ext == ".zip") {
|
||||
int ok = PHYSFS_mount(full.c_str(), "/mod-storage", 0);
|
||||
int ok = PHYSFS_mount(full.c_str(), "", 0);
|
||||
mod_list.emplace_back(full);
|
||||
modloader_add_to_log("Added mod " + full);
|
||||
mods_count++;
|
||||
|
|
|
|||
Loading…
Reference in a new issue