3#include <simplesquirrel/simplesquirrel.hpp>
10#include "physfs/physfs.h"
17bool readViaPhysFS(
const char* path, std::string& out) {
18 if (!PHYSFS_isInit() || !PHYSFS_exists(path))
return false;
19 PHYSFS_file*
f = PHYSFS_openRead(path);
21 const PHYSFS_uint64 len = PHYSFS_fileLength(
f);
22 out.resize(
static_cast<size_t>(len));
23 if (len > 0 && PHYSFS_readBytes(
f, out.data(), len) != len) {
32bool readViaOS(
const char* path, std::string& out) {
33 std::ifstream ifs(path, std::ios::binary);
34 if (!ifs)
return false;
35 out.assign(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>());
39bool readFileContent(
const char* path, std::string& out) {
40 if (readViaPhysFS(path, out) && !out.empty())
return true;
42 return readViaOS(path, out);
47 const SQChar* path =
nullptr;
48 if (SQ_FAILED(sq_getstring(
vm, 2, &path)) || !path)
49 return sq_throwerror(
vm,
"expected a script filename");
52 if (!readFileContent(path, content))
53 return sq_throwerror(
vm,
"cannot open script");
56 if (content.size() >= 3 && (
unsigned char)content[0] == 0xEF &&
57 (
unsigned char)content[1] == 0xBB && (
unsigned char)content[2] == 0xBF)
60 if (SQ_FAILED(sq_compilebuffer(
vm, content.c_str(),
static_cast<SQInteger
>(content.size()),
67 if (SQ_FAILED(sq_call(
vm, 1, SQFalse, SQTrue)))
return SQ_ERROR;
72SQInteger sq_dofile(
HSQUIRRELVM vm) {
return compileAndMaybeRun(
vm,
true); }
73SQInteger sq_loadfile(
HSQUIRRELVM vm) {
return compileAndMaybeRun(
vm,
false); }
77bool getThisStr(
HSQUIRRELVM vm,
const SQChar* field, std::string& out) {
78 sq_pushstring(
vm, field, -1);
79 if (SQ_SUCCEEDED(sq_get(
vm, 1))) {
80 const SQChar*
s =
nullptr;
81 if (SQ_SUCCEEDED(sq_getstring(
vm, -1, &
s)) &&
s) out =
s;
95 if (!getThisStr(
vm, _SC(
"_data"), data))
return sq_throwerror(
vm,
"file not readable");
96 sq_pushstring(
vm,
data.c_str(),
static_cast<SQInteger
>(
data.size()));
102 if (!getThisStr(
vm, _SC(
"_data"), data))
return sq_throwerror(
vm,
"file not readable");
103 sq_pushinteger(
vm,
static_cast<SQInteger
>(
data.size()));
108 sq_pushbool(
vm, SQTrue);
113 sq_pushinteger(
vm, 0);
118 sq_pushbool(
vm, SQTrue);
124 getThisStr(
vm, _SC(
"_path"), path);
125 sq_pushstring(
vm, path.c_str(),
static_cast<SQInteger
>(path.size()));
130 const SQChar* path =
nullptr;
131 const SQChar* mode =
nullptr;
132 if (SQ_FAILED(sq_getstring(
vm, 2, &path)) || SQ_FAILED(sq_getstring(
vm, 3, &mode)))
133 return sq_throwerror(
vm,
"file: expected (path, mode)");
135 std::string
m(mode ? mode :
"");
136 const bool writing =
m.find(
'w') != std::string::npos ||
m.find(
'a') != std::string::npos;
142 if (!readFileContent(path, content))
143 return sq_throwerror(
vm,
"cannot open file");
147 sq_pushstring(
vm, path, -1);
148 sq_newslot(
vm, -3, SQFalse);
149 sq_pushstring(
vm, content.c_str(),
static_cast<SQInteger
>(content.size()));
150 sq_newslot(
vm, -3, SQFalse);
152 struct {
const SQChar*
name; SQFUNCTION
fn; } methods[] = {
153 {_SC(
"close"), sq_f_close},
154 {_SC(
"read"), sq_f_read},
155 {_SC(
"readString"), sq_f_read},
156 {_SC(
"getSize"), sq_f_getSize},
157 {_SC(
"isEOF"), sq_f_isEOF},
158 {_SC(
"tell"), sq_f_tell},
159 {_SC(
"seek"), sq_f_seek},
160 {_SC(
"getFilename"), sq_f_getFilename},
162 for (
const auto& mth : methods) {
163 sq_pushstring(
vm, mth.name, -1);
164 sq_newclosure(
vm, mth.fn, 0);
165 sq_newslot(
vm, -3, SQFalse);
174 const SQInteger top = sq_gettop(
h);
176 struct {
const SQChar*
name; SQFUNCTION
fn; } globals[] = {
177 {_SC(
"dofile"), sq_dofile},
178 {_SC(
"loadfile"), sq_loadfile},
179 {_SC(
"file"), sq_file},
181 for (
const auto& g : globals) {
183 sq_pushstring(
h, g.name, -1);
184 sq_newclosure(
h, g.fn, 0);
185 sq_newslot(
h, -3, SQTrue);
struct SQVM * HSQUIRRELVM
SettlementPipeline::Stage fn
void installScriptFileApi(ssq::VM &vm)
用 PhysFS 版本覆盖 Squirrel 的 file / dofile / loadfile 全局, 使脚本与资源从已挂载的游戏源(真实目录或内存挂载的 .eve 归档)解析; PhysFS 中不...