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/gamepad-binding.cpp
|
||||||
binding-mri/profiler-binding.cpp
|
binding-mri/profiler-binding.cpp
|
||||||
binding-mri/audioplayback-binding.cpp
|
binding-mri/audioplayback-binding.cpp
|
||||||
|
binding-mri/physfs-binding.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
source_group("Binding Source" FILES ${BINDING_SOURCE} ${BINDING_HEADERS})
|
source_group("Binding Source" FILES ${BINDING_SOURCE} ${BINDING_HEADERS})
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ void shaderBindingInit();
|
||||||
void keybindingsBindingInit();
|
void keybindingsBindingInit();
|
||||||
void lightmapBindingInit();
|
void lightmapBindingInit();
|
||||||
void ProfilerInit();
|
void ProfilerInit();
|
||||||
|
void PhysFS_binding_init();
|
||||||
|
|
||||||
RB_METHOD(mriPrint);
|
RB_METHOD(mriPrint);
|
||||||
RB_METHOD(mriP);
|
RB_METHOD(mriP);
|
||||||
|
|
@ -150,6 +151,7 @@ static void mriBindingInit(){
|
||||||
keybindingsBindingInit();
|
keybindingsBindingInit();
|
||||||
lightmapBindingInit();
|
lightmapBindingInit();
|
||||||
ProfilerInit();
|
ProfilerInit();
|
||||||
|
PhysFS_binding_init();
|
||||||
|
|
||||||
_rb_define_module_function(rb_mKernel, "rgss_main", mriRgssMain);
|
_rb_define_module_function(rb_mKernel, "rgss_main", mriRgssMain);
|
||||||
_rb_define_module_function(rb_mKernel, "rgss_stop", mriRgssStop);
|
_rb_define_module_function(rb_mKernel, "rgss_stop", mriRgssStop);
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,14 @@
|
||||||
//https://silverhammermba.github.io/emberb/c/
|
//https://silverhammermba.github.io/emberb/c/
|
||||||
//https://docs.ruby-lang.org/capi/en/master/d8/d68/include_2ruby_2internal_2intern_2string_8h.html
|
//https://docs.ruby-lang.org/capi/en/master/d8/d68/include_2ruby_2internal_2intern_2string_8h.html
|
||||||
#include "binding-util.h"
|
#include "binding-util.h"
|
||||||
#include "sharedstate.h"
|
|
||||||
#include "filesystem.h"
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "debugwriter.h"
|
#include "debugwriter.h"
|
||||||
#include "ruby/encoding.h"
|
|
||||||
#include "ruby/intern.h"
|
|
||||||
#include "ruby/thread.h"
|
|
||||||
#include "modloader.h"
|
#include "modloader.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <ruby.h>
|
#include <ruby.h>
|
||||||
#include <filesystem>
|
#include <physfs.h>
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <system_error>
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
VALUE meow(const std::vector<std::string> vec){
|
VALUE meow(const std::vector<std::string> vec){
|
||||||
VALUE ary = rb_ary_new_capa((long)vec.size());
|
VALUE ary = rb_ary_new_capa((long)vec.size());
|
||||||
for (const std::string &s : vec) {
|
for (const std::string &s : vec) {
|
||||||
|
|
@ -29,7 +18,7 @@ VALUE meow(const std::vector<std::string> vec){
|
||||||
return ary;
|
return ary;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE hooks(int argc, VALUE *argv, VALUE self) {
|
static VALUE hooks(int argc, VALUE *argv, VALUE self){
|
||||||
VALUE v_path = Qnil;
|
VALUE v_path = Qnil;
|
||||||
rb_scan_args(argc, argv, "01", &v_path);
|
rb_scan_args(argc, argv, "01", &v_path);
|
||||||
std::string hook_path = "hooks";
|
std::string hook_path = "hooks";
|
||||||
|
|
@ -38,23 +27,54 @@ static VALUE hooks(int argc, VALUE *argv, VALUE self) {
|
||||||
hook_path = StringValueCStr(v_path);
|
hook_path = StringValueCStr(v_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> files = {};
|
std::vector<std::string> files;
|
||||||
if(!std::filesystem::exists(hook_path)){
|
if (!PHYSFS_exists(hook_path.c_str())) {
|
||||||
return meow(files);
|
return meow(files);
|
||||||
}
|
}
|
||||||
for (const auto &entry : std::filesystem::directory_iterator(hook_path, std::filesystem::directory_options::skip_permission_denied)) {
|
|
||||||
std::error_code ec;
|
PHYSFS_Stat dir_stat{};
|
||||||
auto p = entry.path();
|
|
||||||
if (!std::filesystem::is_regular_file(p, ec) || ec) continue;
|
if (
|
||||||
|
PHYSFS_stat(hook_path.c_str(), &dir_stat) == 0 ||
|
||||||
auto ext = p.extension().string();
|
dir_stat.filetype != PHYSFS_FILETYPE_DIRECTORY
|
||||||
if (ext != ".rb") continue;
|
) {
|
||||||
|
return meow(files);
|
||||||
std::string full = p.string();
|
}
|
||||||
Debug() << "[MODLOADER] Executing hook: " << full;
|
|
||||||
files.push_back(full);
|
char **list = PHYSFS_enumerateFiles(hook_path.c_str());
|
||||||
}
|
|
||||||
return meow(files);
|
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(){
|
void ModLoaderBindingInit(){
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
module Kernel
|
module Kernel
|
||||||
alias_method :original_puts, :puts
|
alias_method :original_puts, :puts
|
||||||
|
|
||||||
def puts(*args)
|
def puts(*args)
|
||||||
string = ""
|
string = ""
|
||||||
args.each do |arg|
|
args.each do |arg|
|
||||||
|
|
@ -9,7 +8,6 @@ module Kernel
|
||||||
MKXP.puts string
|
MKXP.puts string
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
module_function :puts
|
module_function :puts
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -17,15 +15,7 @@ module RPG
|
||||||
module Cache
|
module Cache
|
||||||
@cache = {}
|
@cache = {}
|
||||||
def self.load_bitmap(folder_name, filename, hue = 0)
|
def self.load_bitmap(folder_name, filename, hue = 0)
|
||||||
if ModLoader::IS_ENABLED
|
path = Graphics.adapted_file(folder_name + filename)
|
||||||
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
|
|
||||||
if not @cache.include?(path) or @cache[path].disposed?
|
if not @cache.include?(path) or @cache[path].disposed?
|
||||||
if filename != ""
|
if filename != ""
|
||||||
@cache[path] = Bitmap.new(path)
|
@cache[path] = Bitmap.new(path)
|
||||||
|
|
@ -1323,7 +1313,7 @@ module RPG
|
||||||
return unless ModLoader::IS_ENABLED
|
return unless ModLoader::IS_ENABLED
|
||||||
return unless path.is_a?(String)
|
return unless path.is_a?(String)
|
||||||
ModLoader.hooks(path).each do |item|
|
ModLoader.hooks(path).each do |item|
|
||||||
eval(File.read(item), b)
|
eval(PhysFS.read(item), b)
|
||||||
end
|
end
|
||||||
end
|
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")
|
def self.adapted_file(path, extention = ".png")
|
||||||
file_tag = RESOLUTIONS[Settings[:resolution] || 999]&.[](:file_tag) || ""
|
file_tag = RESOLUTIONS[Settings[:resolution] || 999]&.[](:file_tag) || ""
|
||||||
if File.exist?(path + file_tag + extention)
|
if PhysFS.exist?(path + file_tag + extention)
|
||||||
return path + file_tag
|
return path + file_tag
|
||||||
|
else
|
||||||
|
if File.exist?(path + file_tag + extention)
|
||||||
|
return path + file_tag
|
||||||
|
end
|
||||||
end
|
end
|
||||||
path
|
path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
0
scripts/Graphics.rb
Normal file
0
scripts/Graphics.rb
Normal file
|
|
@ -17,6 +17,7 @@ end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
RPG::Mod.exec_hooks("hooks/Main/start", binding)
|
RPG::Mod.exec_hooks("hooks/Main/start", binding)
|
||||||
|
print PhysFS.exist?("gaysex")
|
||||||
$console = Graphics.fullscreen
|
$console = Graphics.fullscreen
|
||||||
Graphics.frame_rate = 60
|
Graphics.frame_rate = 60
|
||||||
Font.default_size = 20
|
Font.default_size = 20
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,12 @@
|
||||||
#include <SDL3/SDL_video.h>
|
#include <SDL3/SDL_video.h>
|
||||||
#include <SDL3/SDL_timer.h>
|
#include <SDL3/SDL_timer.h>
|
||||||
#include <SDL3_image/SDL_image.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"
|
#include "the_modded_machine.png.xxd"
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
static bool stop_render = false;
|
static bool stop_render = false;
|
||||||
const static std::size_t N = 46;
|
const static std::size_t N = 46;
|
||||||
|
|
||||||
|
|
@ -94,7 +95,7 @@ void ModLoader(Config conf, SDL_Window* win){
|
||||||
std::string full = p.string();
|
std::string full = p.string();
|
||||||
|
|
||||||
if (ext == ".zip") {
|
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);
|
mod_list.emplace_back(full);
|
||||||
modloader_add_to_log("Added mod " + full);
|
modloader_add_to_log("Added mod " + full);
|
||||||
mods_count++;
|
mods_count++;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue