Bicameral Engine
GPU-resident engine for a magic-research open-world game
Loading...
Searching...
No Matches
luau_package.h
Go to the documentation of this file.
1// luau_package.h — Luau のパッケージ(1 フォルダ = 1 パッケージ)を読み、表を合わせる(T-0138、13 §2・D-320・ADR-0031)。
2//
3// パッケージ: フォルダの中の *.luau。ゲーム本体もパッケージの 1 つ(options.basePackage)。
4// package.luau(マニフェスト)が表を返す: { format = 1, depends = { "core" }, entry = "init" }(depends・entry は省ける)。
5// entry のファイルが「分類 → 鍵 → 値」の表を返す(例 { reactions = { burn = {...} }, elements = {...} })。
6// require("sub/util") はそのパッケージの中の sub/util.luau だけを読む(ほかのパッケージ・ファイルの外には届かない)。
7// 読む順番: 依存の後。依存の関係で決まらないものはパッケージの名前(バイト順)。フォルダを並べた順・入れた順には依らない(決定性)。
8// 表の合わせ方(MergeMode。QUESTIONS Q8 が未回答なので切り替えられる形。仮で C: 既定は AddOnly、上書きを許す設定は OverrideMarked):
9// 新しい鍵は足す。既にある鍵を書こうとしたら AddOnly ではそのパッケージ(と依存するもの)を読まない、
10// OverrideMarked では上書きして「改造された世界」の印を付ける、Override では印なしで上書きする。値は丸ごと置き換える。
11// データの流れ: フォルダ → ReadPackageRoot → PackageSource → LoadPackages(殻で走らせる)→ PackageSetResult → ベイク(T-0021)。
12// ここは CPU だけ(原則 1・2)。同じパッケージ群・同じ設定なら、同じ PackageSetResult(CanonicalBytes が同じ)になる。
13#pragma once
14
15#include <cstdint>
16#include <expected>
17#include <map>
18#include <span>
19#include <string>
20#include <string_view>
21#include <vector>
22
23#include "core/aliases.h"
25#include "script/script_value.h"
26
27namespace bicameral::script {
28
29 class LuauSandbox;
30
31 constexpr int64_t PACKAGE_FORMAT_VERSION = 1; // マニフェストの format(D-320: データ形式に版を付ける)
32
33 // 1 つのパッケージの中身(ディスクから読んでも、テストで手で作ってもよい)
34 // NOLINTNEXTLINE(bugprone-exception-escape) MSVC の std::map は作るときに番兵を確保する(投げたら落ちてよい)
36 std::string name; // フォルダの名前 = パッケージの名前
37 std::map<std::string, std::string> files; // パッケージの中の相対パス("/" 区切り。例 "sub/util.luau")→ ソース
38 };
39
40 enum class MergeMode : uint8_t {
41 AddOnly, // 案 B・案 C の既定: 足すだけ。既にある鍵を書こうとしたパッケージは読まない
42 OverrideMarked, // 案 C の「上書きを許す」設定: 上書きを通し、「改造された世界」の印を付ける
43 Override, // 案 A: 上書きを印なしで通す
44 };
45
48 std::string basePackage; // ゲーム本体。空でなければ、ほかの全部がこれに依存する(最初に読む)
49
50 // あれば、走らせる前に型検査する(T-0140・ADR-0046): マニフェストの前に package.luau、entry の前に全部のファイル。
51 // 誤りがあるパッケージ(と依存するもの)は読まない。理由に「ファイル:行:列: 何が違うか」が入る
53 };
54
55 // 読まなかったパッケージと理由
57 std::string package;
58 std::string reason;
59 };
60
61 // 上書きの記録(「改造された世界」の中身。誰の何を誰が書き換えたか)
63 std::string category;
64 std::string key;
65 std::string previousPackage;
66 std::string package;
67 };
68
69 struct TableEntry {
71 std::string package; // 最後に書いたパッケージ
72 };
73
74 // NOLINTNEXTLINE(bugprone-exception-escape) MSVC の std::map は作るときに番兵を確保する(投げたら落ちてよい)
76 std::vector<std::string> loadOrder; // 読めたパッケージ(読んだ順)
77 std::vector<PackageRejection> rejected; // 読まなかったパッケージ(見つけた順)
78 std::map<std::string, std::map<std::string, TableEntry>> tables; // 分類 → 鍵 → 値(バイト順)
79 std::vector<TableOverride> overrides; // 上書き(起きた順)
80 bool modifiedWorld = false; // 「改造された世界」の印(OverrideMarked で上書きがあった)
81 std::vector<TypeDiagnostic>
82 typeDiagnostics; // 型検査の誤り(見つけた順。1 つのパッケージの中はファイル → 行の順)
83 };
84
85 // --- ディスクから読む(エディタ・ツール用)---
86
87 // folder の中の *.luau を全部(下のフォルダも)読む。名前はフォルダの名前
88 [[nodiscard]] std::expected<PackageSource, std::string> ReadPackageFolder(const fs::path& folder);
89
90 // root の直下のフォルダを 1 つずつパッケージとして読む(名前の順)
91 [[nodiscard]] std::expected<std::vector<PackageSource>, std::string> ReadPackageRoot(const fs::path& root);
92
93 // --- 読み込みと合わせ ---
94
95 // sandbox は Seal 済みのもの(ホストの関数は呼び手が登録しておく)。名前の重複・Seal 前は error、パッケージごとの誤りは rejected へ
96 [[nodiscard]] std::expected<PackageSetResult, std::string> LoadPackages(LuauSandbox& sandbox,
97 std::span<const PackageSource> packages,
98 const PackageLoadOptions& options);
99
100 // 合わせた表の中身(分類・鍵・値)のバイト列。どのパッケージが書いたかは入れない(同じ中身なら同じ版)
101 [[nodiscard]] std::string TableBytes(const PackageSetResult& result);
102
103 // 表の版(TableBytes のハッシュ)。再生ファイルや発見の共有(D-110・15 §3)で、同じ法則の世界かを見分けるのに使う
104 [[nodiscard]] uint64_t TableVersion(const PackageSetResult& result);
105
106 // 名前の規則(パッケージ・分類・require のパスの区切りごと): 英小文字・数字・'_'・'-' だけで 1〜64 文字
107 [[nodiscard]] bool IsValidPackageName(std::string_view name);
108
109 // require の名前 → パッケージの中のファイル("sub/util" → "sub/util.luau")。名前の規則に合わなければ理由。型検査(T-0140)も使う
110 [[nodiscard]] std::expected<std::string, std::string> PackageModulePath(std::string_view name);
111
112} // namespace bicameral::script
std::expected< PackageSource, std::string > ReadPackageFolder(const fs::path &folder)
std::expected< std::vector< PackageSource >, std::string > ReadPackageRoot(const fs::path &root)
std::expected< std::string, std::string > PackageModulePath(std::string_view name)
constexpr int64_t PACKAGE_FORMAT_VERSION
std::expected< PackageSetResult, std::string > LoadPackages(LuauSandbox &sandbox, std::span< const PackageSource > packages, const PackageLoadOptions &options)
uint64_t TableVersion(const PackageSetResult &result)
std::string TableBytes(const PackageSetResult &result)
bool IsValidPackageName(std::string_view name)
std::vector< TypeDiagnostic > typeDiagnostics
std::vector< TableOverride > overrides
std::vector< std::string > loadOrder
std::vector< PackageRejection > rejected
std::map< std::string, std::map< std::string, TableEntry > > tables
std::map< std::string, std::string > files