mirror of
https://forgejo.xatacraft.ru/Sunshine/mkxp-sunshine.git
synced 2026-08-19 21:39:57 +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 "meow.h"
|
||||
#include "sunshine.h"
|
||||
#include "modloader.h"
|
||||
|
||||
#include <ruby.h>
|
||||
#include <ruby/debug.h>
|
||||
|
|
@ -178,6 +179,7 @@ static void mriBindingInit(){
|
|||
SunshineBindingInit();
|
||||
steamBindingInit();
|
||||
shaderBindingInit();
|
||||
ModLoader();
|
||||
ModLoaderBindingInit();
|
||||
keybindingsBindingInit();
|
||||
lightmapBindingInit();
|
||||
|
|
@ -198,6 +200,7 @@ static void mriBindingInit(){
|
|||
_rb_define_module_function(mod, "puts", mkxpPuts);
|
||||
_rb_define_module_function(mod, "raw_key_states", mkxpRawKeyStates);
|
||||
_rb_define_module_function(mod, "mouse_in_window", mkxpMouseInWindow);
|
||||
|
||||
}
|
||||
|
||||
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 v[] = { port, utf8Proc };
|
||||
return rb_marshal_load(port); // uh.. well.. it works now at least.
|
||||
//return rb_funcall_with_block(marsh, rb_intern("_mkxp_load_alias"), 1, &port, utf8Proc);
|
||||
return rb_marshal_load(port);
|
||||
}
|
||||
|
||||
void fileIntBindingInit(){
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include <SDL3/SDL_version.h>
|
||||
#include <SDL3/SDL_gamepad.h>
|
||||
#include <SDL3/SDL_joystick.h>
|
||||
#include <SDL3/SDL_hints.h>
|
||||
#include <limits.h>
|
||||
#include "ruby/backward/cxxanyargs.hpp"
|
||||
#include "ruby/internal/arithmetic/double.h"
|
||||
|
|
@ -21,6 +22,10 @@ static VALUE sunshine_set_crash_privacy(VALUE, VALUE 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){
|
||||
return rb_obj_clone(self);
|
||||
}
|
||||
|
|
@ -57,6 +62,7 @@ void SunshineBindingInit(){
|
|||
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_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"))) {
|
||||
rb_define_method(rb_cObject, "class", rb_obj_class, 0);
|
||||
|
|
|
|||
|
|
@ -10,3 +10,4 @@ Added help screen in Settings
|
|||
"Skip Text (R)" fixed
|
||||
Fixed language selection
|
||||
Replaced Japanese font with pixel one
|
||||
Added SDL_HINT_INVALID_PARAM_CHECKS controller in Settings>Advanced
|
||||
|
|
|
|||
|
|
@ -86,7 +86,8 @@ set(scripts
|
|||
Input.rb
|
||||
Dynamic_Light.rb
|
||||
Gamepad_Colors.rb
|
||||
Dynamic_Resolution.rb)
|
||||
Dynamic_Resolution.rb
|
||||
ModAPI.rb)
|
||||
|
||||
find_program(RUBY_EXE ruby
|
||||
DOC "Location of the Ruby executable")
|
||||
|
|
|
|||
|
|
@ -32,7 +32,9 @@ module Settings
|
|||
|
||||
# Advanced
|
||||
:crashlog_privacy => false,
|
||||
|
||||
:streamer_privacy => false,
|
||||
:SDL_HINT_INVALID_PARAM_CHECKS => false,
|
||||
|
||||
#controls
|
||||
:gamepad_led => true,
|
||||
:gamepad_deadzone => 5,
|
||||
|
|
@ -44,7 +46,7 @@ module Settings
|
|||
:debug_text_scene_title => true,
|
||||
:debug_picture_names => false,
|
||||
:debug_lightmap => false,
|
||||
|
||||
:SDL_HINT_SHUTDOWN_DBUS_ON_QUIT => false,
|
||||
|
||||
#Hidden
|
||||
:is_dejavu => false,
|
||||
|
|
@ -125,6 +127,12 @@ end
|
|||
class Window_Settings
|
||||
# if parameter is linked to data in class Settings, then default value in this structure is ignored
|
||||
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" => [
|
||||
{
|
||||
:type => :slider,
|
||||
|
|
@ -140,6 +148,7 @@ class Window_Settings
|
|||
:min => 0,
|
||||
:max => 100
|
||||
},
|
||||
{ :type => :sep, :name => "Game tracks"},
|
||||
{
|
||||
:type => :bool,
|
||||
:name => "ITS TIME FOR FIGHT CRIME",
|
||||
|
|
@ -165,13 +174,13 @@ class Window_Settings
|
|||
:name => "Frameskip",
|
||||
:parameter => :frameskip
|
||||
},
|
||||
{ :type => :sep, :name => "Other"},
|
||||
{
|
||||
:type => :enum,
|
||||
:name => "Scaling mode",
|
||||
:parameter => :scaling_mode,
|
||||
:values => ["Nearest Neighbor", "Smooth(old)"]
|
||||
},
|
||||
{ :type => :sep, :name => "Effects"},
|
||||
{
|
||||
:type => :bool,
|
||||
:name => "Dynamic Light",
|
||||
|
|
@ -182,11 +191,6 @@ class Window_Settings
|
|||
:name => "World machine shader",
|
||||
:parameter => :twm_shader
|
||||
},
|
||||
{
|
||||
:type => :bool,
|
||||
:name => "Colorblind mode",
|
||||
:parameter => :colorblind
|
||||
},
|
||||
],
|
||||
"UI" => [
|
||||
{
|
||||
|
|
@ -208,6 +212,12 @@ class Window_Settings
|
|||
},
|
||||
],
|
||||
"Gameplay" => [
|
||||
{ :type => :sep, :name => "Vanila" },
|
||||
{
|
||||
:type => :bool,
|
||||
:name => "Colorblind mode",
|
||||
:parameter => :colorblind
|
||||
},
|
||||
{
|
||||
:type => :enum,
|
||||
:name => "Default movement",
|
||||
|
|
@ -219,8 +229,9 @@ class Window_Settings
|
|||
:name => "Skip Text (R)",
|
||||
:parameter => :skip_text
|
||||
},
|
||||
{ :type => :sep, :name => "Sunshine" },
|
||||
{
|
||||
:type => :bool,
|
||||
:type => :bool,
|
||||
:name => "Purple message box for Entity",
|
||||
:parameter => :en_purple_messagebox
|
||||
},
|
||||
|
|
@ -241,7 +252,7 @@ class Window_Settings
|
|||
},
|
||||
{
|
||||
:type => :bool,
|
||||
:name => "World machine shader on Entity footprints",
|
||||
:name => "World machine shader on Entity footprints(WIP)",
|
||||
:parameter => :twm_shader_footprint
|
||||
},
|
||||
],
|
||||
|
|
@ -325,7 +336,6 @@ class Window_Settings
|
|||
:parameter => :controls_nav_right,
|
||||
:bind => Input::R
|
||||
},
|
||||
#{ :type => :sep, :name => "Other" },
|
||||
{
|
||||
:type => :action,
|
||||
:name => "Reset Controls",
|
||||
|
|
@ -333,11 +343,22 @@ class Window_Settings
|
|||
},
|
||||
],
|
||||
"Advanced" => [
|
||||
{ :type => :sep, :name => "Privacy" },
|
||||
{
|
||||
:type => :bool,
|
||||
:name => "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" => [
|
||||
|
|
@ -371,6 +392,11 @@ class Window_Settings
|
|||
:name => "Debug lightmap",
|
||||
:parameter => :debug_lightmap
|
||||
},
|
||||
{
|
||||
:type => :bool,
|
||||
:name => "SDL_HINT_SHUTDOWN_DBUS_ON_QUIT",
|
||||
:parameter => :SDL_HINT_SHUTDOWN_DBUS_ON_QUIT
|
||||
},
|
||||
{ :type => :sep },
|
||||
{
|
||||
:type => :key,
|
||||
|
|
@ -378,12 +404,20 @@ class Window_Settings
|
|||
:parameter => :controls_debug,
|
||||
:bind => Input::DEBUGACTION
|
||||
},
|
||||
{ :type => :sep },
|
||||
{ :type => :seps},
|
||||
{
|
||||
:type => :action,
|
||||
:name => "Clear image cache",
|
||||
: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
|
||||
|
|
|
|||
|
|
@ -62,13 +62,28 @@ module Settings
|
|||
$game_switches[251] = value != 0
|
||||
end
|
||||
def skip_text(value)
|
||||
# idk how to set skip_text parameter
|
||||
# TODO: fix skip_text settings setter
|
||||
$game_switches[253] = value != 0
|
||||
end
|
||||
|
||||
def frameskip(value)
|
||||
Graphics.frameskip = value
|
||||
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
|
||||
|
|
|
|||
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
|
||||
Main
|
||||
|
||||
ModAPI
|
||||
|
||||
|
|
|
|||
16
src/main.cpp
16
src/main.cpp
|
|
@ -51,10 +51,6 @@
|
|||
#include "i18n.h"
|
||||
#include "security.h"
|
||||
|
||||
#ifndef ps2
|
||||
#include "modloader.h"
|
||||
#endif
|
||||
|
||||
#include "sunshine.h"
|
||||
|
||||
#include "define.h"
|
||||
|
|
@ -302,16 +298,6 @@ int main(int argc, char *argv[]){
|
|||
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);
|
||||
if (conf.screenMode)
|
||||
|
|
@ -379,7 +365,7 @@ int main(int argc, char *argv[]){
|
|||
|
||||
/* Load and post key bindings */
|
||||
rtData.bindingUpdateMsg.post(loadBindings(conf));
|
||||
|
||||
|
||||
/* Start RGSS thread */
|
||||
SDL_Thread *rgssThread = SDL_CreateThread(rgssThreadFun, "rgss", &rtData);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,36 +25,9 @@
|
|||
#include <algorithm>
|
||||
#include <system_error>
|
||||
#include <SDL3/SDL_system.h>
|
||||
#include <physfs.h>
|
||||
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){
|
||||
unsigned char hash[SHA512_DIGEST_LENGTH];
|
||||
|
||||
|
|
@ -98,19 +71,14 @@ std::string sha256_file(const std::string &fn) {
|
|||
return out;
|
||||
}
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
std::string ModLoader(Config conf){ return ""; }
|
||||
#else
|
||||
std::string ModLoader(Config conf){
|
||||
std::string path = conf.Modloader.ModsDirPath;
|
||||
void ModLoader(){
|
||||
std::string path = "mods";
|
||||
if (!fs::exists(path) || !std::filesystem::is_directory(path)) {
|
||||
Debug() << "[MODLOADER] Mods directory not found, skip.";
|
||||
return "";
|
||||
}
|
||||
|
||||
if (fs::is_empty(path)){
|
||||
Debug() << "[MODLOADER] Mods directory empty, skip.";
|
||||
return "";
|
||||
}
|
||||
|
||||
//buildID - unique ID of a certain combination of mods
|
||||
|
|
@ -118,16 +86,18 @@ std::string ModLoader(Config conf){
|
|||
std::string buildID_tmp = "";
|
||||
std::vector<std::string> mod_list = {};
|
||||
try{
|
||||
//1.check if any zip(mod) file, 2. calculate sha256 hash of zip(mod) files
|
||||
for (const auto &entry : std::filesystem::directory_iterator(path, std::filesystem::directory_options::skip_permission_denied)) {
|
||||
//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)) {
|
||||
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 != ".zip") continue;
|
||||
|
||||
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;
|
||||
mod_list.push_back(full);
|
||||
mods_count++;
|
||||
|
|
@ -138,84 +108,9 @@ std::string ModLoader(Config conf){
|
|||
|
||||
buildID = sha512(buildID_tmp);
|
||||
Debug() << "[MODLOADER] BuildID: " << buildID;
|
||||
std::string path3 = getCacheDir() + "/sunshine-" + buildID;
|
||||
int err = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
modloader_is_enabled = true;
|
||||
}catch(const std::exception& e){
|
||||
crash(Exception::ModLoaderError, "Something is wrong, Exception: %s ", e.what());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
//modloader bruh
|
||||
#include <string>
|
||||
#include "config.h"
|
||||
std::string ModLoader(Config conf);
|
||||
void ModLoader();
|
||||
|
||||
inline bool modloader_is_enabled = false;
|
||||
inline unsigned int mods_count = 0;
|
||||
|
|
|
|||
Loading…
Reference in a new issue