mirror of
https://forgejo.xatacraft.ru/Sunshine/mkxp-sunshine.git
synced 2026-08-19 13:29:54 +00:00
Mrowg
This commit is contained in:
parent
0cc72b0b4e
commit
501ff1b02b
13 changed files with 97 additions and 152 deletions
1
MODDING.md
Normal file
1
MODDING.md
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
# How Sunshine ModLoader work
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
#include "boost-hash.h"
|
#include "boost-hash.h"
|
||||||
#include "meow.h"
|
#include "meow.h"
|
||||||
#include "sunshine.h"
|
#include "sunshine.h"
|
||||||
|
#include "modloader.h"
|
||||||
|
|
||||||
#include <ruby.h>
|
#include <ruby.h>
|
||||||
#include <ruby/debug.h>
|
#include <ruby/debug.h>
|
||||||
|
|
@ -178,6 +179,7 @@ static void mriBindingInit(){
|
||||||
SunshineBindingInit();
|
SunshineBindingInit();
|
||||||
steamBindingInit();
|
steamBindingInit();
|
||||||
shaderBindingInit();
|
shaderBindingInit();
|
||||||
|
ModLoader();
|
||||||
ModLoaderBindingInit();
|
ModLoaderBindingInit();
|
||||||
keybindingsBindingInit();
|
keybindingsBindingInit();
|
||||||
lightmapBindingInit();
|
lightmapBindingInit();
|
||||||
|
|
@ -198,6 +200,7 @@ static void mriBindingInit(){
|
||||||
_rb_define_module_function(mod, "puts", mkxpPuts);
|
_rb_define_module_function(mod, "puts", mkxpPuts);
|
||||||
_rb_define_module_function(mod, "raw_key_states", mkxpRawKeyStates);
|
_rb_define_module_function(mod, "raw_key_states", mkxpRawKeyStates);
|
||||||
_rb_define_module_function(mod, "mouse_in_window", mkxpMouseInWindow);
|
_rb_define_module_function(mod, "mouse_in_window", mkxpMouseInWindow);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void printP(int argc, VALUE *argv, const char *convMethod, const char *sep){
|
static void printP(int argc, VALUE *argv, const char *convMethod, const char *sep){
|
||||||
|
|
|
||||||
|
|
@ -186,8 +186,7 @@ RB_METHOD(_marshalLoad){
|
||||||
VALUE marsh = rb_const_get(rb_cObject, rb_intern("Marshal"));
|
VALUE marsh = rb_const_get(rb_cObject, rb_intern("Marshal"));
|
||||||
|
|
||||||
VALUE v[] = { port, utf8Proc };
|
VALUE v[] = { port, utf8Proc };
|
||||||
return rb_marshal_load(port); // uh.. well.. it works now at least.
|
return rb_marshal_load(port);
|
||||||
//return rb_funcall_with_block(marsh, rb_intern("_mkxp_load_alias"), 1, &port, utf8Proc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void fileIntBindingInit(){
|
void fileIntBindingInit(){
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include <SDL3/SDL_version.h>
|
#include <SDL3/SDL_version.h>
|
||||||
#include <SDL3/SDL_gamepad.h>
|
#include <SDL3/SDL_gamepad.h>
|
||||||
#include <SDL3/SDL_joystick.h>
|
#include <SDL3/SDL_joystick.h>
|
||||||
|
#include <SDL3/SDL_hints.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include "ruby/backward/cxxanyargs.hpp"
|
#include "ruby/backward/cxxanyargs.hpp"
|
||||||
#include "ruby/internal/arithmetic/double.h"
|
#include "ruby/internal/arithmetic/double.h"
|
||||||
|
|
@ -21,6 +22,10 @@ static VALUE sunshine_set_crash_privacy(VALUE, VALUE v) {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE sunshine_set_hint(VALUE, VALUE h, VALUE v) {
|
||||||
|
return SDL_SetHint(StringValueCStr(h), StringValueCStr(v));
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE obj_clone(VALUE self){
|
static VALUE obj_clone(VALUE self){
|
||||||
return rb_obj_clone(self);
|
return rb_obj_clone(self);
|
||||||
}
|
}
|
||||||
|
|
@ -57,6 +62,7 @@ void SunshineBindingInit(){
|
||||||
rb_const_set(module, rb_intern("SECURITYSTATE"), rb_str_new_cstr(securitystate));
|
rb_const_set(module, rb_intern("SECURITYSTATE"), rb_str_new_cstr(securitystate));
|
||||||
rb_define_singleton_method(module, "crashprivacy", RUBY_METHOD_FUNC(sunshine_get_crash_privacy), 0);
|
rb_define_singleton_method(module, "crashprivacy", RUBY_METHOD_FUNC(sunshine_get_crash_privacy), 0);
|
||||||
rb_define_singleton_method(module, "crashprivacy=", RUBY_METHOD_FUNC(sunshine_set_crash_privacy), 1);
|
rb_define_singleton_method(module, "crashprivacy=", RUBY_METHOD_FUNC(sunshine_set_crash_privacy), 1);
|
||||||
|
rb_define_singleton_method(module, "setSDLHint", RUBY_METHOD_FUNC(sunshine_set_hint), 2);
|
||||||
//если методы доступны то просто не перезаписываем их
|
//если методы доступны то просто не перезаписываем их
|
||||||
if (!rb_respond_to(rb_cObject, rb_intern("class"))) {
|
if (!rb_respond_to(rb_cObject, rb_intern("class"))) {
|
||||||
rb_define_method(rb_cObject, "class", rb_obj_class, 0);
|
rb_define_method(rb_cObject, "class", rb_obj_class, 0);
|
||||||
|
|
|
||||||
|
|
@ -10,3 +10,4 @@ Added help screen in Settings
|
||||||
"Skip Text (R)" fixed
|
"Skip Text (R)" fixed
|
||||||
Fixed language selection
|
Fixed language selection
|
||||||
Replaced Japanese font with pixel one
|
Replaced Japanese font with pixel one
|
||||||
|
Added SDL_HINT_INVALID_PARAM_CHECKS controller in Settings>Advanced
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,8 @@ set(scripts
|
||||||
Input.rb
|
Input.rb
|
||||||
Dynamic_Light.rb
|
Dynamic_Light.rb
|
||||||
Gamepad_Colors.rb
|
Gamepad_Colors.rb
|
||||||
Dynamic_Resolution.rb)
|
Dynamic_Resolution.rb
|
||||||
|
ModAPI.rb)
|
||||||
|
|
||||||
find_program(RUBY_EXE ruby
|
find_program(RUBY_EXE ruby
|
||||||
DOC "Location of the Ruby executable")
|
DOC "Location of the Ruby executable")
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,9 @@ module Settings
|
||||||
|
|
||||||
# Advanced
|
# Advanced
|
||||||
:crashlog_privacy => false,
|
:crashlog_privacy => false,
|
||||||
|
:streamer_privacy => false,
|
||||||
|
:SDL_HINT_INVALID_PARAM_CHECKS => false,
|
||||||
|
|
||||||
#controls
|
#controls
|
||||||
:gamepad_led => true,
|
:gamepad_led => true,
|
||||||
:gamepad_deadzone => 5,
|
:gamepad_deadzone => 5,
|
||||||
|
|
@ -44,7 +46,7 @@ module Settings
|
||||||
:debug_text_scene_title => true,
|
:debug_text_scene_title => true,
|
||||||
:debug_picture_names => false,
|
:debug_picture_names => false,
|
||||||
:debug_lightmap => false,
|
:debug_lightmap => false,
|
||||||
|
:SDL_HINT_SHUTDOWN_DBUS_ON_QUIT => false,
|
||||||
|
|
||||||
#Hidden
|
#Hidden
|
||||||
:is_dejavu => false,
|
:is_dejavu => false,
|
||||||
|
|
@ -125,6 +127,12 @@ end
|
||||||
class Window_Settings
|
class Window_Settings
|
||||||
# if parameter is linked to data in class Settings, then default value in this structure is ignored
|
# if parameter is linked to data in class Settings, then default value in this structure is ignored
|
||||||
DATA = {
|
DATA = {
|
||||||
|
"Help" => [
|
||||||
|
{ :type => :base, :name => "(!) - It's Dangerous!" },
|
||||||
|
{ :type => :base, :name => "(WIP) - Work In Progress" },
|
||||||
|
{ :type => :base, :name => "(GRR) - Game Restart Required" },
|
||||||
|
{ :type => :base, :name => "(LRR) - Location Reload Required" },
|
||||||
|
],
|
||||||
"Audio" => [
|
"Audio" => [
|
||||||
{
|
{
|
||||||
:type => :slider,
|
:type => :slider,
|
||||||
|
|
@ -140,6 +148,7 @@ class Window_Settings
|
||||||
:min => 0,
|
:min => 0,
|
||||||
:max => 100
|
:max => 100
|
||||||
},
|
},
|
||||||
|
{ :type => :sep, :name => "Game tracks"},
|
||||||
{
|
{
|
||||||
:type => :bool,
|
:type => :bool,
|
||||||
:name => "ITS TIME FOR FIGHT CRIME",
|
:name => "ITS TIME FOR FIGHT CRIME",
|
||||||
|
|
@ -165,13 +174,13 @@ class Window_Settings
|
||||||
:name => "Frameskip",
|
:name => "Frameskip",
|
||||||
:parameter => :frameskip
|
:parameter => :frameskip
|
||||||
},
|
},
|
||||||
{ :type => :sep, :name => "Other"},
|
|
||||||
{
|
{
|
||||||
:type => :enum,
|
:type => :enum,
|
||||||
:name => "Scaling mode",
|
:name => "Scaling mode",
|
||||||
:parameter => :scaling_mode,
|
:parameter => :scaling_mode,
|
||||||
:values => ["Nearest Neighbor", "Smooth(old)"]
|
:values => ["Nearest Neighbor", "Smooth(old)"]
|
||||||
},
|
},
|
||||||
|
{ :type => :sep, :name => "Effects"},
|
||||||
{
|
{
|
||||||
:type => :bool,
|
:type => :bool,
|
||||||
:name => "Dynamic Light",
|
:name => "Dynamic Light",
|
||||||
|
|
@ -182,11 +191,6 @@ class Window_Settings
|
||||||
:name => "World machine shader",
|
:name => "World machine shader",
|
||||||
:parameter => :twm_shader
|
:parameter => :twm_shader
|
||||||
},
|
},
|
||||||
{
|
|
||||||
:type => :bool,
|
|
||||||
:name => "Colorblind mode",
|
|
||||||
:parameter => :colorblind
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
"UI" => [
|
"UI" => [
|
||||||
{
|
{
|
||||||
|
|
@ -208,6 +212,12 @@ class Window_Settings
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"Gameplay" => [
|
"Gameplay" => [
|
||||||
|
{ :type => :sep, :name => "Vanila" },
|
||||||
|
{
|
||||||
|
:type => :bool,
|
||||||
|
:name => "Colorblind mode",
|
||||||
|
:parameter => :colorblind
|
||||||
|
},
|
||||||
{
|
{
|
||||||
:type => :enum,
|
:type => :enum,
|
||||||
:name => "Default movement",
|
:name => "Default movement",
|
||||||
|
|
@ -219,8 +229,9 @@ class Window_Settings
|
||||||
:name => "Skip Text (R)",
|
:name => "Skip Text (R)",
|
||||||
:parameter => :skip_text
|
:parameter => :skip_text
|
||||||
},
|
},
|
||||||
|
{ :type => :sep, :name => "Sunshine" },
|
||||||
{
|
{
|
||||||
:type => :bool,
|
:type => :bool,
|
||||||
:name => "Purple message box for Entity",
|
:name => "Purple message box for Entity",
|
||||||
:parameter => :en_purple_messagebox
|
:parameter => :en_purple_messagebox
|
||||||
},
|
},
|
||||||
|
|
@ -241,7 +252,7 @@ class Window_Settings
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
:type => :bool,
|
:type => :bool,
|
||||||
:name => "World machine shader on Entity footprints",
|
:name => "World machine shader on Entity footprints(WIP)",
|
||||||
:parameter => :twm_shader_footprint
|
:parameter => :twm_shader_footprint
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -325,7 +336,6 @@ class Window_Settings
|
||||||
:parameter => :controls_nav_right,
|
:parameter => :controls_nav_right,
|
||||||
:bind => Input::R
|
:bind => Input::R
|
||||||
},
|
},
|
||||||
#{ :type => :sep, :name => "Other" },
|
|
||||||
{
|
{
|
||||||
:type => :action,
|
:type => :action,
|
||||||
:name => "Reset Controls",
|
:name => "Reset Controls",
|
||||||
|
|
@ -333,11 +343,22 @@ class Window_Settings
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"Advanced" => [
|
"Advanced" => [
|
||||||
|
{ :type => :sep, :name => "Privacy" },
|
||||||
{
|
{
|
||||||
:type => :bool,
|
:type => :bool,
|
||||||
:name => "Crashlog privacy",
|
:name => "Crashlog privacy",
|
||||||
:parameter => :crashlog_privacy
|
:parameter => :crashlog_privacy
|
||||||
|
},
|
||||||
|
{
|
||||||
|
:type => :bool,
|
||||||
|
:name => "Streamer privacy",
|
||||||
|
:parameter => :streamer_privacy
|
||||||
|
},
|
||||||
|
{ :type => :sep, :name => "Other" },
|
||||||
|
{
|
||||||
|
:type => :bool,
|
||||||
|
:name => "SDL_HINT_INVALID_PARAM_CHECKS (!)",
|
||||||
|
:parameter => :SDL_HINT_INVALID_PARAM_CHECKS
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"Debug" => [
|
"Debug" => [
|
||||||
|
|
@ -371,6 +392,11 @@ class Window_Settings
|
||||||
:name => "Debug lightmap",
|
:name => "Debug lightmap",
|
||||||
:parameter => :debug_lightmap
|
:parameter => :debug_lightmap
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
:type => :bool,
|
||||||
|
:name => "SDL_HINT_SHUTDOWN_DBUS_ON_QUIT",
|
||||||
|
:parameter => :SDL_HINT_SHUTDOWN_DBUS_ON_QUIT
|
||||||
|
},
|
||||||
{ :type => :sep },
|
{ :type => :sep },
|
||||||
{
|
{
|
||||||
:type => :key,
|
:type => :key,
|
||||||
|
|
@ -378,12 +404,20 @@ class Window_Settings
|
||||||
:parameter => :controls_debug,
|
:parameter => :controls_debug,
|
||||||
:bind => Input::DEBUGACTION
|
:bind => Input::DEBUGACTION
|
||||||
},
|
},
|
||||||
{ :type => :sep },
|
{ :type => :seps},
|
||||||
{
|
{
|
||||||
:type => :action,
|
:type => :action,
|
||||||
:name => "Clear image cache",
|
:name => "Clear image cache",
|
||||||
:action => Proc.new { RPG::Cache.clear }
|
:action => Proc.new { RPG::Cache.clear }
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"Mods" => [
|
||||||
|
{ :type => :base, :name => "Modloader enabled? #{ModLoader::IS_ENABLED}" },
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Part of ModAPI
|
||||||
|
def self.add_setting(setting)
|
||||||
|
DATA["Mods"] << setting
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -62,13 +62,28 @@ module Settings
|
||||||
$game_switches[251] = value != 0
|
$game_switches[251] = value != 0
|
||||||
end
|
end
|
||||||
def skip_text(value)
|
def skip_text(value)
|
||||||
# idk how to set skip_text parameter
|
$game_switches[253] = value != 0
|
||||||
# TODO: fix skip_text settings setter
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def frameskip(value)
|
def frameskip(value)
|
||||||
Graphics.frameskip = value
|
Graphics.frameskip = value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def SDL_HINT_INVALID_PARAM_CHECKS(value)
|
||||||
|
if value
|
||||||
|
Sunshine.setSDLHint("SDL_HINT_INVALID_PARAM_CHECKS", "1")
|
||||||
|
else
|
||||||
|
Sunshine.setSDLHint("SDL_HINT_INVALID_PARAM_CHECKS", "2")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def SDL_HINT_SHUTDOWN_DBUS_ON_QUIT(value)
|
||||||
|
if value
|
||||||
|
Sunshine.setSDLHint("SDL_HINT_SHUTDOWN_DBUS_ON_QUIT", "1")
|
||||||
|
else
|
||||||
|
Sunshine.setSDLHint("SDL_HINT_SHUTDOWN_DBUS_ON_QUIT", "0")
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
3
scripts/ModAPI.rb
Normal file
3
scripts/ModAPI.rb
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
module ModAPI
|
||||||
|
APIVER = 1
|
||||||
|
end
|
||||||
|
|
@ -108,3 +108,6 @@ Particles
|
||||||
|
|
||||||
EdText
|
EdText
|
||||||
Main
|
Main
|
||||||
|
|
||||||
|
ModAPI
|
||||||
|
|
||||||
|
|
|
||||||
16
src/main.cpp
16
src/main.cpp
|
|
@ -51,10 +51,6 @@
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
#include "security.h"
|
#include "security.h"
|
||||||
|
|
||||||
#ifndef ps2
|
|
||||||
#include "modloader.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "sunshine.h"
|
#include "sunshine.h"
|
||||||
|
|
||||||
#include "define.h"
|
#include "define.h"
|
||||||
|
|
@ -302,16 +298,6 @@ int main(int argc, char *argv[]){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ps2
|
|
||||||
std::string new_path = ModLoader(conf);
|
|
||||||
if(new_path != ""){
|
|
||||||
if (chdir(new_path.c_str()) != 0){
|
|
||||||
crash(Exception::MEOW, "Unable to switch into new gameFolder %s", new_path);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern int screenMain(Config &conf);
|
extern int screenMain(Config &conf);
|
||||||
if (conf.screenMode)
|
if (conf.screenMode)
|
||||||
|
|
@ -379,7 +365,7 @@ int main(int argc, char *argv[]){
|
||||||
|
|
||||||
/* Load and post key bindings */
|
/* Load and post key bindings */
|
||||||
rtData.bindingUpdateMsg.post(loadBindings(conf));
|
rtData.bindingUpdateMsg.post(loadBindings(conf));
|
||||||
|
|
||||||
/* Start RGSS thread */
|
/* Start RGSS thread */
|
||||||
SDL_Thread *rgssThread = SDL_CreateThread(rgssThreadFun, "rgss", &rtData);
|
SDL_Thread *rgssThread = SDL_CreateThread(rgssThreadFun, "rgss", &rtData);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,36 +25,9 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
#include <SDL3/SDL_system.h>
|
#include <SDL3/SDL_system.h>
|
||||||
|
#include <physfs.h>
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
// Get directory for storing cached builds
|
|
||||||
//TODO: support for other OS and platforms
|
|
||||||
std::string getCacheDir(){
|
|
||||||
#ifdef _WIN32
|
|
||||||
return SDL_getenv("Temp");
|
|
||||||
#elif __linux__
|
|
||||||
return std::string(SDL_getenv("HOME")) + "/.cache";
|
|
||||||
#elif BSD
|
|
||||||
return std::string(SDL_getenv("HOME")) + "/.cache";
|
|
||||||
#elif __APPLE__
|
|
||||||
return "~/Library/Caches";
|
|
||||||
#elif __ANDROID__
|
|
||||||
return std::string str(SDL_GetAndroidCachePath());
|
|
||||||
#else
|
|
||||||
return "idk";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
//helper
|
|
||||||
bool ensure_parent_dir(const std::filesystem::path& p){
|
|
||||||
if (p.has_parent_path()){
|
|
||||||
std::error_code ec;
|
|
||||||
std::filesystem::create_directories(p.parent_path(), ec);
|
|
||||||
return !ec;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string sha512(const std::string str){
|
std::string sha512(const std::string str){
|
||||||
unsigned char hash[SHA512_DIGEST_LENGTH];
|
unsigned char hash[SHA512_DIGEST_LENGTH];
|
||||||
|
|
||||||
|
|
@ -98,19 +71,14 @@ std::string sha256_file(const std::string &fn) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
void ModLoader(){
|
||||||
std::string ModLoader(Config conf){ return ""; }
|
std::string path = "mods";
|
||||||
#else
|
|
||||||
std::string ModLoader(Config conf){
|
|
||||||
std::string path = conf.Modloader.ModsDirPath;
|
|
||||||
if (!fs::exists(path) || !std::filesystem::is_directory(path)) {
|
if (!fs::exists(path) || !std::filesystem::is_directory(path)) {
|
||||||
Debug() << "[MODLOADER] Mods directory not found, skip.";
|
Debug() << "[MODLOADER] Mods directory not found, skip.";
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fs::is_empty(path)){
|
if (fs::is_empty(path)){
|
||||||
Debug() << "[MODLOADER] Mods directory empty, skip.";
|
Debug() << "[MODLOADER] Mods directory empty, skip.";
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//buildID - unique ID of a certain combination of mods
|
//buildID - unique ID of a certain combination of mods
|
||||||
|
|
@ -118,16 +86,18 @@ std::string ModLoader(Config conf){
|
||||||
std::string buildID_tmp = "";
|
std::string buildID_tmp = "";
|
||||||
std::vector<std::string> mod_list = {};
|
std::vector<std::string> mod_list = {};
|
||||||
try{
|
try{
|
||||||
//1.check if any zip(mod) file, 2. calculate sha256 hash of zip(mod) files
|
//1.check if any zip(mod) file, 2. calculate sha256 hash of zip(mod) files 3.mount mod via PhysFS
|
||||||
for (const auto &entry : std::filesystem::directory_iterator(path, std::filesystem::directory_options::skip_permission_denied)) {
|
for (const auto &entry : std::filesystem::directory_iterator(path, std::filesystem::directory_options::skip_permission_denied)) {
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
auto p = entry.path();
|
auto p = entry.path();
|
||||||
if (!std::filesystem::is_regular_file(p, ec) || ec) continue;
|
if (!std::filesystem::is_regular_file(p, ec) || ec) continue;
|
||||||
|
|
||||||
auto ext = p.extension().string();
|
auto ext = p.extension().string();
|
||||||
if (ext != ".zip") continue;
|
if (ext != ".zip") continue;
|
||||||
|
|
||||||
std::string full = p.string();
|
std::string full = p.string();
|
||||||
|
int ok = PHYSFS_mount(full.c_str(), "/", 0);
|
||||||
|
if (!ok) {
|
||||||
|
crash(Exception::ModLoaderError, "PhysFS_mount failed: %s", PHYSFS_getLastError());
|
||||||
|
}
|
||||||
Debug() << "[MODLOADER] " << full;
|
Debug() << "[MODLOADER] " << full;
|
||||||
mod_list.push_back(full);
|
mod_list.push_back(full);
|
||||||
mods_count++;
|
mods_count++;
|
||||||
|
|
@ -138,84 +108,9 @@ std::string ModLoader(Config conf){
|
||||||
|
|
||||||
buildID = sha512(buildID_tmp);
|
buildID = sha512(buildID_tmp);
|
||||||
Debug() << "[MODLOADER] BuildID: " << buildID;
|
Debug() << "[MODLOADER] BuildID: " << buildID;
|
||||||
std::string path3 = getCacheDir() + "/sunshine-" + buildID;
|
|
||||||
int err = 0;
|
modloader_is_enabled = true;
|
||||||
modloader_is_enabled = true;
|
|
||||||
if(!std::filesystem::exists(path3)){
|
|
||||||
std::error_code ec;
|
|
||||||
fs::create_directory(path3, ec);
|
|
||||||
if (ec) {
|
|
||||||
crash(Exception::ModLoaderError, "Failed to create destination: %s", ec.message().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
fs::copy(conf.gameFolder, path3, fs::copy_options::recursive | fs::copy_options::overwrite_existing, ec);
|
|
||||||
if (ec) {
|
|
||||||
crash(Exception::ModLoaderError, "Copy error: %s", ec.message().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
//Extracting zipsodpsofspo idk
|
|
||||||
for (size_t i = 0; i < mod_list.size(); ++i){
|
|
||||||
zip_t* za = zip_open(mod_list[i].c_str(), ZIP_RDONLY, &err);
|
|
||||||
if (!za){
|
|
||||||
crash(Exception::ModLoaderError, "Failed to open zip");
|
|
||||||
}
|
|
||||||
|
|
||||||
zip_int64_t n = zip_get_num_entries(za, 0);
|
|
||||||
for (zip_uint64_t i2 = 0; i2 < static_cast<zip_uint64_t>(n); ++i2) {
|
|
||||||
zip_stat_t st;
|
|
||||||
if (zip_stat_index(za, i2, 0, &st) != 0) {
|
|
||||||
crash(Exception::ModLoaderError, "zip_stat_index failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string name = st.name;
|
|
||||||
std::filesystem::path target = path3 / std::filesystem::path(name);
|
|
||||||
|
|
||||||
// If entry name ends with '/', treat as directory
|
|
||||||
if (!name.empty() && name.back() == '/') {
|
|
||||||
std::error_code ec;
|
|
||||||
std::filesystem::create_directories(target, ec);
|
|
||||||
if (ec) crash(Exception::MEOW, "Failed to create dir");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ensure_parent_dir(target)){
|
|
||||||
crash(Exception::ModLoaderError, "Failed to create parent dirs");
|
|
||||||
}
|
|
||||||
|
|
||||||
zip_file_t* zf = zip_fopen_index(za, i2, 0);
|
|
||||||
if (!zf) {
|
|
||||||
crash(Exception::ModLoaderError, "zip_fopen_index failed");
|
|
||||||
}
|
|
||||||
std::ofstream out(target, std::ios::binary);
|
|
||||||
if (!out) {
|
|
||||||
crash(Exception::ModLoaderError, "Failed to open output file %s", target.c_str());
|
|
||||||
zip_fclose(zf);
|
|
||||||
}
|
|
||||||
|
|
||||||
const zip_uint64_t bufsize = 4096;
|
|
||||||
std::vector<char> buf(bufsize);
|
|
||||||
zip_int64_t bytes_read;
|
|
||||||
zip_uint64_t remaining = st.size;
|
|
||||||
while (remaining > 0) {
|
|
||||||
zip_uint64_t to_read = std::min<zip_uint64_t>(bufsize, remaining);
|
|
||||||
bytes_read = zip_fread(zf, buf.data(), to_read);
|
|
||||||
if (bytes_read < 0) {
|
|
||||||
crash(Exception::ModLoaderError, "zip_fread error for %s", name.c_str());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
out.write(buf.data(), bytes_read);
|
|
||||||
remaining -= bytes_read;
|
|
||||||
}
|
|
||||||
zip_fclose(zf);
|
|
||||||
}
|
|
||||||
zip_close(za);
|
|
||||||
}
|
|
||||||
return path3;
|
|
||||||
}else{
|
|
||||||
return path3;
|
|
||||||
}
|
|
||||||
}catch(const std::exception& e){
|
}catch(const std::exception& e){
|
||||||
crash(Exception::ModLoaderError, "Something is wrong, Exception: %s ", e.what());
|
crash(Exception::ModLoaderError, "Something is wrong, Exception: %s ", e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
//modloader bruh
|
//modloader bruh
|
||||||
#include <string>
|
void ModLoader();
|
||||||
#include "config.h"
|
|
||||||
std::string ModLoader(Config conf);
|
|
||||||
|
|
||||||
inline bool modloader_is_enabled = false;
|
inline bool modloader_is_enabled = false;
|
||||||
inline unsigned int mods_count = 0;
|
inline unsigned int mods_count = 0;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue