koishipro-core.js 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@ export * from './src/structs';
6
6
  export * from './src/adapters';
7
7
  export * from './src/constants';
8
8
  export * from './src/vendor';
9
- export * from './src/sqljs-card-reader';
9
+ export * from './src/script-reader';
10
+ export * from './src/card-reader';
10
11
  export * from './src/play-yrp';
11
12
  export * from './src/test-card';
package/dist/index.mjs CHANGED
@@ -1097,150 +1097,6 @@ async function createOcgcoreWrapper(options = {}) {
1097
1097
  return new OcgcoreWrapper(moduleInstance);
1098
1098
  }
1099
1099
 
1100
- // src/adapters/script-readers.ts
1101
- import JSZip from "jszip";
1102
-
1103
- // src/utility/load-node-module.ts
1104
- function loadNodeModule(id, altId) {
1105
- const req = typeof module.require !== "undefined" ? module.require : void 0;
1106
- if (!req) {
1107
- return null;
1108
- }
1109
- try {
1110
- return req(id);
1111
- } catch {
1112
- if (!altId) return null;
1113
- try {
1114
- return req(altId);
1115
- } catch {
1116
- return null;
1117
- }
1118
- }
1119
- }
1120
-
1121
- // src/utility/node-fs.ts
1122
- function getNodeFs(noThrow = false) {
1123
- const mod = loadNodeModule("node:fs", "fs");
1124
- if (mod) return mod;
1125
- if (noThrow) return null;
1126
- throw new Error("Node.js fs module is not available.");
1127
- }
1128
-
1129
- // src/utility/node-path.ts
1130
- function getNodePath(noThrow = false) {
1131
- const mod = loadNodeModule("node:path", "path");
1132
- if (mod) return mod;
1133
- if (noThrow) return null;
1134
- throw new Error("Node.js path module is not available.");
1135
- }
1136
-
1137
- // src/adapters/script-readers.ts
1138
- var SCRIPT_PREFIX = "./script/";
1139
- function normalizePath(input) {
1140
- let path = input.replace(/\\/g, "/");
1141
- if (path.startsWith(SCRIPT_PREFIX)) {
1142
- path = path.slice(SCRIPT_PREFIX.length);
1143
- }
1144
- return path;
1145
- }
1146
- function buildCandidates(filename) {
1147
- const entries = [
1148
- filename,
1149
- `specials/${filename}`,
1150
- `expansions/script/${filename}`,
1151
- `script/${filename}`
1152
- ];
1153
- const candidates = [];
1154
- for (const entry of entries) {
1155
- candidates.push(entry);
1156
- if (!entry.startsWith("./")) {
1157
- const dotEntry = entry.startsWith("/") ? `./${entry.slice(1)}` : `./${entry}`;
1158
- candidates.push(dotEntry);
1159
- }
1160
- }
1161
- return candidates;
1162
- }
1163
- function joinPath(baseDir, relativePath) {
1164
- const pathMod = getNodePath();
1165
- if (pathMod) {
1166
- return pathMod.join(baseDir, relativePath);
1167
- }
1168
- const trimmedBase = baseDir.replace(/[/\\]+$/, "");
1169
- const trimmedRel = relativePath.replace(/^[/\\]+/, "");
1170
- return `${trimmedBase}/${trimmedRel}`;
1171
- }
1172
- function MapReader(...maps) {
1173
- return (path) => {
1174
- const filename = normalizePath(path);
1175
- if (!filename.toLowerCase().endsWith(".lua")) {
1176
- return null;
1177
- }
1178
- const candidates = buildCandidates(filename);
1179
- for (const candidate of candidates) {
1180
- for (const map of maps) {
1181
- if (map.has(candidate)) {
1182
- return map.get(candidate) ?? null;
1183
- }
1184
- }
1185
- }
1186
- return null;
1187
- };
1188
- }
1189
- function DirReader(...baseDirs) {
1190
- const fs = getNodeFs();
1191
- return (path) => {
1192
- const filename = normalizePath(path);
1193
- if (!filename.toLowerCase().endsWith(".lua")) {
1194
- return null;
1195
- }
1196
- const candidates = buildCandidates(filename);
1197
- for (const baseDir of baseDirs) {
1198
- for (const candidate of candidates) {
1199
- const normalized = candidate.startsWith("/") ? candidate.slice(1) : candidate;
1200
- const fullPath = joinPath(baseDir, normalized);
1201
- if (fs.existsSync(fullPath)) {
1202
- return fs.readFileSync(fullPath);
1203
- }
1204
- }
1205
- }
1206
- return null;
1207
- };
1208
- }
1209
- function normalizeZipEntryName(name) {
1210
- const normalized = name.replace(/\\/g, "/").replace(/^\.?\//, "");
1211
- const names = /* @__PURE__ */ new Set();
1212
- names.add(normalized);
1213
- if (normalized.startsWith("script/")) {
1214
- names.add(normalized.slice("script/".length));
1215
- }
1216
- return Array.from(names);
1217
- }
1218
- async function ZipReader(...inputs) {
1219
- const maps = await Promise.all(
1220
- inputs.map(async (data) => {
1221
- const zip = await JSZip.loadAsync(data);
1222
- const map = /* @__PURE__ */ new Map();
1223
- const entries = Object.values(zip.files);
1224
- await Promise.all(
1225
- entries.map(async (entry) => {
1226
- if (entry.dir) {
1227
- return;
1228
- }
1229
- if (!entry.name.toLowerCase().endsWith(".lua")) {
1230
- return;
1231
- }
1232
- const content = await entry.async("uint8array");
1233
- for (const name of normalizeZipEntryName(entry.name)) {
1234
- map.set(name, content);
1235
- }
1236
- })
1237
- );
1238
- return map;
1239
- })
1240
- );
1241
- return MapReader(...maps);
1242
- }
1243
-
1244
1100
  // src/vendor/script-constants.ts
1245
1101
  var OcgcoreScriptConstants = {
1246
1102
  ACTIVITY_ATTACK: 5,
@@ -2079,7 +1935,243 @@ var OcgcoreScriptConstants = {
2079
1935
  TYPE_XYZ: 8388608
2080
1936
  };
2081
1937
 
2082
- // src/sqljs-card-reader.ts
1938
+ // src/script-reader/script-readers.ts
1939
+ import JSZip from "jszip";
1940
+
1941
+ // src/utility/load-node-module.ts
1942
+ function loadNodeModule(id, altId) {
1943
+ const req = typeof module.require !== "undefined" ? module.require : void 0;
1944
+ if (!req) {
1945
+ return null;
1946
+ }
1947
+ try {
1948
+ return req(id);
1949
+ } catch {
1950
+ if (!altId) return null;
1951
+ try {
1952
+ return req(altId);
1953
+ } catch {
1954
+ return null;
1955
+ }
1956
+ }
1957
+ }
1958
+
1959
+ // src/utility/node-fs.ts
1960
+ function getNodeFs(noThrow = false) {
1961
+ const mod = loadNodeModule("node:fs", "fs");
1962
+ if (mod) return mod;
1963
+ if (noThrow) return null;
1964
+ throw new Error("Node.js fs module is not available.");
1965
+ }
1966
+
1967
+ // src/utility/node-path.ts
1968
+ function getNodePath(noThrow = false) {
1969
+ const mod = loadNodeModule("node:path", "path");
1970
+ if (mod) return mod;
1971
+ if (noThrow) return null;
1972
+ throw new Error("Node.js path module is not available.");
1973
+ }
1974
+
1975
+ // src/script-reader/script-readers.ts
1976
+ var SCRIPT_PREFIX = "./script/";
1977
+ function normalizePath(input) {
1978
+ let path = input.replace(/\\/g, "/");
1979
+ if (path.startsWith(SCRIPT_PREFIX)) {
1980
+ path = path.slice(SCRIPT_PREFIX.length);
1981
+ }
1982
+ return path;
1983
+ }
1984
+ function buildCandidates(filename) {
1985
+ const entries = [
1986
+ filename,
1987
+ `specials/${filename}`,
1988
+ `expansions/script/${filename}`,
1989
+ `script/${filename}`
1990
+ ];
1991
+ const candidates = [];
1992
+ for (const entry of entries) {
1993
+ candidates.push(entry);
1994
+ if (!entry.startsWith("./")) {
1995
+ const dotEntry = entry.startsWith("/") ? `./${entry.slice(1)}` : `./${entry}`;
1996
+ candidates.push(dotEntry);
1997
+ }
1998
+ }
1999
+ return candidates;
2000
+ }
2001
+ function joinPath(baseDir, relativePath) {
2002
+ const pathMod = getNodePath();
2003
+ if (pathMod) {
2004
+ return pathMod.join(baseDir, relativePath);
2005
+ }
2006
+ const trimmedBase = baseDir.replace(/[/\\]+$/, "");
2007
+ const trimmedRel = relativePath.replace(/^[/\\]+/, "");
2008
+ return `${trimmedBase}/${trimmedRel}`;
2009
+ }
2010
+ function MapScriptReader(...maps) {
2011
+ return (path) => {
2012
+ const filename = normalizePath(path);
2013
+ if (!filename.toLowerCase().endsWith(".lua")) {
2014
+ return null;
2015
+ }
2016
+ const candidates = buildCandidates(filename);
2017
+ for (const candidate of candidates) {
2018
+ for (const map of maps) {
2019
+ if (map.has(candidate)) {
2020
+ return map.get(candidate) ?? null;
2021
+ }
2022
+ }
2023
+ }
2024
+ return null;
2025
+ };
2026
+ }
2027
+ function DirScriptReader(...baseDirs) {
2028
+ const fs = getNodeFs();
2029
+ return (path) => {
2030
+ const filename = normalizePath(path);
2031
+ if (!filename.toLowerCase().endsWith(".lua")) {
2032
+ return null;
2033
+ }
2034
+ const candidates = buildCandidates(filename);
2035
+ for (const baseDir of baseDirs) {
2036
+ for (const candidate of candidates) {
2037
+ const normalized = candidate.startsWith("/") ? candidate.slice(1) : candidate;
2038
+ const fullPath = joinPath(baseDir, normalized);
2039
+ if (fs.existsSync(fullPath)) {
2040
+ return fs.readFileSync(fullPath);
2041
+ }
2042
+ }
2043
+ }
2044
+ return null;
2045
+ };
2046
+ }
2047
+ function normalizeZipEntryName(name) {
2048
+ const normalized = name.replace(/\\/g, "/").replace(/^\.?\//, "");
2049
+ const names = /* @__PURE__ */ new Set();
2050
+ names.add(normalized);
2051
+ if (normalized.startsWith("script/")) {
2052
+ names.add(normalized.slice("script/".length));
2053
+ }
2054
+ return Array.from(names);
2055
+ }
2056
+ async function ZipScriptReader(...inputs) {
2057
+ const maps = await Promise.all(
2058
+ inputs.map(async (data) => {
2059
+ const zip = await JSZip.loadAsync(data);
2060
+ const map = /* @__PURE__ */ new Map();
2061
+ const entries = Object.values(zip.files);
2062
+ await Promise.all(
2063
+ entries.map(async (entry) => {
2064
+ if (entry.dir) {
2065
+ return;
2066
+ }
2067
+ if (!entry.name.toLowerCase().endsWith(".lua")) {
2068
+ return;
2069
+ }
2070
+ const content = await entry.async("uint8array");
2071
+ for (const name of normalizeZipEntryName(entry.name)) {
2072
+ map.set(name, content);
2073
+ }
2074
+ })
2075
+ );
2076
+ return map;
2077
+ })
2078
+ );
2079
+ return MapScriptReader(...maps);
2080
+ }
2081
+ function MapReader(...maps) {
2082
+ return MapScriptReader(...maps);
2083
+ }
2084
+ function DirReader(...baseDirs) {
2085
+ return DirScriptReader(...baseDirs);
2086
+ }
2087
+ async function ZipReader(...inputs) {
2088
+ return ZipScriptReader(...inputs);
2089
+ }
2090
+
2091
+ // src/utility/search-zips.ts
2092
+ function joinPath2(pathMod, baseDir, rel) {
2093
+ if (pathMod) {
2094
+ return pathMod.join(baseDir, rel);
2095
+ }
2096
+ const trimmedBase = baseDir.replace(/[/\\]+$/, "");
2097
+ const trimmedRel = rel.replace(/^[/\\]+/, "");
2098
+ return `${trimmedBase}/${trimmedRel}`;
2099
+ }
2100
+ async function safeReadDir(fs, dirPath) {
2101
+ try {
2102
+ return await fs.promises.readdir(dirPath);
2103
+ } catch {
2104
+ return [];
2105
+ }
2106
+ }
2107
+ async function searchZips(fs, pathMod, baseDir) {
2108
+ const results = [];
2109
+ const rootEntries = await safeReadDir(fs, baseDir);
2110
+ for (const entry of rootEntries) {
2111
+ const lower = entry.toLowerCase();
2112
+ if (!lower.endsWith(".zip") && !lower.endsWith(".ypk")) {
2113
+ continue;
2114
+ }
2115
+ const fullPath = joinPath2(pathMod, baseDir, entry);
2116
+ try {
2117
+ const stats = await fs.promises.stat(fullPath);
2118
+ if (stats.isFile()) {
2119
+ results.push(fullPath);
2120
+ }
2121
+ } catch {
2122
+ continue;
2123
+ }
2124
+ }
2125
+ const expansionsDir = joinPath2(pathMod, baseDir, "expansions");
2126
+ const expansionEntries = await safeReadDir(fs, expansionsDir);
2127
+ for (const entry of expansionEntries) {
2128
+ const lower = entry.toLowerCase();
2129
+ if (!lower.endsWith(".zip") && !lower.endsWith(".ypk")) {
2130
+ continue;
2131
+ }
2132
+ const fullPath = joinPath2(pathMod, expansionsDir, entry);
2133
+ try {
2134
+ const stats = await fs.promises.stat(fullPath);
2135
+ if (stats.isFile()) {
2136
+ results.push(fullPath);
2137
+ }
2138
+ } catch {
2139
+ continue;
2140
+ }
2141
+ }
2142
+ return results;
2143
+ }
2144
+
2145
+ // src/script-reader/dir-script-reader-ex.ts
2146
+ function getNodeModuleOrThrow(value, label) {
2147
+ if (!value) {
2148
+ throw new Error(`${label} is not supported in this runtime.`);
2149
+ }
2150
+ return value;
2151
+ }
2152
+ async function DirScriptReaderEx(...baseDirs) {
2153
+ const fs = getNodeModuleOrThrow(getNodeFs(), "DirScriptReaderEx");
2154
+ const pathMod = getNodeModuleOrThrow(getNodePath(), "DirScriptReaderEx");
2155
+ const fsReader = DirScriptReader(...baseDirs);
2156
+ const zipInputs = [];
2157
+ for (const baseDir of baseDirs) {
2158
+ const zipPaths = await searchZips(fs, pathMod, baseDir);
2159
+ for (const zipPath of zipPaths) {
2160
+ try {
2161
+ zipInputs.push(await fs.promises.readFile(zipPath));
2162
+ } catch {
2163
+ continue;
2164
+ }
2165
+ }
2166
+ }
2167
+ if (zipInputs.length === 0) {
2168
+ return fsReader;
2169
+ }
2170
+ const zipReader = await ZipScriptReader(...zipInputs);
2171
+ return (path) => fsReader(path) ?? zipReader(path);
2172
+ }
2173
+
2174
+ // src/card-reader/sqljs-card-reader.ts
2083
2175
  function toUint16ArrayFromSetcode(value) {
2084
2176
  let raw = typeof value === "bigint" ? value : BigInt(value >>> 0);
2085
2177
  const list = new Uint16Array(16);
@@ -2160,7 +2252,7 @@ function queryOne(db, cardId) {
2160
2252
  attribute: row[8]
2161
2253
  });
2162
2254
  }
2163
- function createSqljsCardReader(...dbs) {
2255
+ function SqljsCardReader(...dbs) {
2164
2256
  return (cardId) => {
2165
2257
  for (const db of dbs) {
2166
2258
  const data = queryOne(db, cardId);
@@ -2171,6 +2263,105 @@ function createSqljsCardReader(...dbs) {
2171
2263
  return null;
2172
2264
  };
2173
2265
  }
2266
+ function createSqljsCardReader(...dbs) {
2267
+ return SqljsCardReader(...dbs);
2268
+ }
2269
+
2270
+ // src/card-reader/dir-card-reader.ts
2271
+ import JSZip2 from "jszip";
2272
+ function joinPath3(pathMod, baseDir, rel) {
2273
+ if (pathMod) {
2274
+ return pathMod.join(baseDir, rel);
2275
+ }
2276
+ const trimmedBase = baseDir.replace(/[/\\]+$/, "");
2277
+ const trimmedRel = rel.replace(/^[/\\]+/, "");
2278
+ return `${trimmedBase}/${trimmedRel}`;
2279
+ }
2280
+ function getNodeModuleOrThrow2(value, label) {
2281
+ if (!value) {
2282
+ throw new Error(`${label} is not supported in this runtime.`);
2283
+ }
2284
+ return value;
2285
+ }
2286
+ async function safeReadDir2(fs, dirPath) {
2287
+ try {
2288
+ return await fs.promises.readdir(dirPath);
2289
+ } catch {
2290
+ return [];
2291
+ }
2292
+ }
2293
+ async function collectFsDbPaths(fs, pathMod, baseDir) {
2294
+ const results = [];
2295
+ const baseDb = joinPath3(pathMod, baseDir, "cards.cdb");
2296
+ try {
2297
+ const stats = await fs.promises.stat(baseDb);
2298
+ if (stats.isFile()) {
2299
+ results.push(baseDb);
2300
+ }
2301
+ } catch {
2302
+ }
2303
+ const expansionsDir = joinPath3(pathMod, baseDir, "expansions");
2304
+ const entries = await safeReadDir2(fs, expansionsDir);
2305
+ for (const entry of entries) {
2306
+ if (!entry.toLowerCase().endsWith(".cdb")) {
2307
+ continue;
2308
+ }
2309
+ const fullPath = joinPath3(pathMod, expansionsDir, entry);
2310
+ try {
2311
+ const stats = await fs.promises.stat(fullPath);
2312
+ if (stats.isFile()) {
2313
+ results.push(fullPath);
2314
+ }
2315
+ } catch {
2316
+ continue;
2317
+ }
2318
+ }
2319
+ return results;
2320
+ }
2321
+ function isRootCdbEntry(entryName) {
2322
+ const normalized = entryName.replace(/\\/g, "/").replace(/^\.?\//, "");
2323
+ return !normalized.includes("/") && normalized.toLowerCase().endsWith(".cdb");
2324
+ }
2325
+ async function DirCardReader(sqljs, ...baseDirs) {
2326
+ const fs = getNodeModuleOrThrow2(getNodeFs(), "DirCardReader");
2327
+ const pathMod = getNodeModuleOrThrow2(getNodePath(), "DirCardReader");
2328
+ const dbs = [];
2329
+ for (const baseDir of baseDirs) {
2330
+ const dbPaths = await collectFsDbPaths(fs, pathMod, baseDir);
2331
+ for (const dbPath of dbPaths) {
2332
+ try {
2333
+ const bytes = await fs.promises.readFile(dbPath);
2334
+ dbs.push(new sqljs.Database(bytes));
2335
+ } catch {
2336
+ continue;
2337
+ }
2338
+ }
2339
+ }
2340
+ for (const baseDir of baseDirs) {
2341
+ const zipPaths = await searchZips(fs, pathMod, baseDir);
2342
+ for (const zipPath of zipPaths) {
2343
+ try {
2344
+ const bytes = await fs.promises.readFile(zipPath);
2345
+ const zip = await JSZip2.loadAsync(bytes);
2346
+ const entries = Object.values(zip.files);
2347
+ for (const entry of entries) {
2348
+ if (entry.dir || !isRootCdbEntry(entry.name)) {
2349
+ continue;
2350
+ }
2351
+ try {
2352
+ const content = await entry.async("uint8array");
2353
+ dbs.push(new sqljs.Database(content));
2354
+ } catch {
2355
+ continue;
2356
+ }
2357
+ }
2358
+ } catch {
2359
+ continue;
2360
+ }
2361
+ }
2362
+ }
2363
+ return SqljsCardReader(...dbs);
2364
+ }
2174
2365
 
2175
2366
  // src/play-yrp.ts
2176
2367
  import { YGOProYrp } from "ygopro-yrp-encode";
@@ -2289,7 +2480,8 @@ function* playYrpStep(ocgcoreWrapper, yrpInput) {
2289
2480
  const result = duel.process();
2290
2481
  yield {
2291
2482
  duel,
2292
- result
2483
+ result,
2484
+ responses
2293
2485
  };
2294
2486
  if (result.raw.length > 0 && result.raw[0] === OcgcoreCommonConstants.MSG_RETRY) {
2295
2487
  throw new Error("Got MSG_RETRY");
@@ -2371,12 +2563,16 @@ if (typeof globalThis !== "undefined" && !globalThis.Buffer) {
2371
2563
  }
2372
2564
  export {
2373
2565
  CardDataStruct,
2566
+ DirCardReader,
2374
2567
  DirReader,
2568
+ DirScriptReader,
2569
+ DirScriptReaderEx,
2375
2570
  LEN_EMPTY,
2376
2571
  LEN_FAIL,
2377
2572
  LEN_HEADER,
2378
2573
  MESSAGE_BUFFER_SIZE,
2379
2574
  MapReader,
2575
+ MapScriptReader,
2380
2576
  OcgcoreCommonConstants,
2381
2577
  OcgcoreDuel,
2382
2578
  OcgcoreDuelOptionFlag,
@@ -2386,7 +2582,9 @@ export {
2386
2582
  OcgcoreWrapper,
2387
2583
  QUERY_BUFFER_SIZE,
2388
2584
  REGISTRY_BUFFER_SIZE,
2585
+ SqljsCardReader,
2389
2586
  ZipReader,
2587
+ ZipScriptReader,
2390
2588
  createOcgcoreWrapper,
2391
2589
  createSqljsCardReader,
2392
2590
  normalizeStartDuelOptions,