sandstone-cli 0.6.0 → 0.6.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/README.md +31 -30
- package/lib/build/buildProject.d.ts +3 -2
- package/lib/build/buildProject.js +334 -145
- package/lib/commands/build.d.ts +2 -2
- package/lib/commands/build.js +1 -1
- package/lib/commands/create.d.ts +3 -2
- package/lib/commands/create.js +38 -29
- package/lib/commands/watch.d.ts +2 -2
- package/lib/commands/watch.js +7 -5
- package/lib/template/README.md +2 -2
- package/oclif.manifest.json +1 -1
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ $ npm install -g sandstone-cli
|
|
|
19
19
|
$ sand COMMAND
|
|
20
20
|
running command...
|
|
21
21
|
$ sand (-v|--version|version)
|
|
22
|
-
sandstone-cli/0.6.
|
|
22
|
+
sandstone-cli/0.6.2 linux-x64 node-v16.19.1
|
|
23
23
|
$ sand --help [COMMAND]
|
|
24
24
|
USAGE
|
|
25
25
|
$ sand COMMAND
|
|
@@ -36,7 +36,7 @@ USAGE
|
|
|
36
36
|
|
|
37
37
|
## `sand build PATH CONFIG-PATH`
|
|
38
38
|
|
|
39
|
-
Build the
|
|
39
|
+
Build the packs. ⛏
|
|
40
40
|
|
|
41
41
|
```
|
|
42
42
|
USAGE
|
|
@@ -47,7 +47,7 @@ ARGUMENTS
|
|
|
47
47
|
CONFIG-PATH [default: .] Path of the sandstone.config.ts folder.
|
|
48
48
|
|
|
49
49
|
OPTIONS
|
|
50
|
-
-d, --dry Do not save the
|
|
50
|
+
-d, --dry Do not save the pack. Mostly useful with `verbose`.
|
|
51
51
|
-h, --help show CLI help
|
|
52
52
|
-p, --production Runs Sandstone in production mode. This sets process.env.SANDSTONE_ENV to "production".
|
|
53
53
|
-v, --verbose Log all resulting resources: functions, advancements...
|
|
@@ -55,23 +55,23 @@ OPTIONS
|
|
|
55
55
|
--autoReload=port Automatically reload your data pack in-game. Requires to open the world to LAN with
|
|
56
56
|
cheats enabled, and to specify the port.
|
|
57
57
|
|
|
58
|
+
--clientPath=clientPath Path of the client folder. Override the value specified in the configuration file.
|
|
59
|
+
|
|
58
60
|
--description=description Description of the data pack. Override the value specified in the configuration file.
|
|
59
61
|
|
|
60
62
|
--formatVersion=formatVersion Pack format version. Override the value specified in the configuration file.
|
|
61
63
|
|
|
62
64
|
--fullTrace Show the full stack trace on errors.
|
|
63
65
|
|
|
64
|
-
--minecraftPath=minecraftPath Path of the .minecraft folder. Override the value specified in the configuration file.
|
|
65
|
-
|
|
66
66
|
--name=name Name of the data pack. Override the value specified in the configuration file.
|
|
67
67
|
|
|
68
68
|
--namespace=namespace The default namespace. Override the value specified in the configuration file.
|
|
69
69
|
|
|
70
|
-
--
|
|
70
|
+
--root Save the data pack & resource pack in the .minecraft/datapacks &
|
|
71
|
+
.minecraft/resource_packs folders. Override the value specified in the configuration
|
|
71
72
|
file.
|
|
72
73
|
|
|
73
|
-
--
|
|
74
|
-
in the configuration file.
|
|
74
|
+
--serverPath=serverPath Path of the server folder. Override the value specified in the configuration file.
|
|
75
75
|
|
|
76
76
|
--strictErrors Stop data pack compilation on type errors.
|
|
77
77
|
|
|
@@ -84,7 +84,7 @@ EXAMPLES
|
|
|
84
84
|
$ sand build --verbose --dry
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
-
_See code: [src/commands/build.ts](https://github.com/TheMrZZ/sandstone-cli/blob/v0.6.
|
|
87
|
+
_See code: [src/commands/build.ts](https://github.com/TheMrZZ/sandstone-cli/blob/v0.6.2/src/commands/build.ts)_
|
|
88
88
|
|
|
89
89
|
## `sand create PROJECT-NAME`
|
|
90
90
|
|
|
@@ -98,26 +98,27 @@ ARGUMENTS
|
|
|
98
98
|
PROJECT-NAME Name of the project folder. This is not the name of the data pack.
|
|
99
99
|
|
|
100
100
|
OPTIONS
|
|
101
|
-
-
|
|
102
|
-
-
|
|
103
|
-
-
|
|
104
|
-
-
|
|
101
|
+
-c, --client-path=client-path The client path to write packs at.
|
|
102
|
+
-d, --pack-name=pack-name The name of the data pack.
|
|
103
|
+
-h, --help show CLI help
|
|
104
|
+
-n, --namespace=namespace The default namespace that will be used.
|
|
105
105
|
|
|
106
|
-
-r, --save-root
|
|
107
|
-
|
|
106
|
+
-r, --save-root Save the data pack & resource pack in the .minecraft/datapacks &
|
|
107
|
+
.minecraft/resource_packs folders. Not compatible with --world.
|
|
108
108
|
|
|
109
|
-
-
|
|
110
|
-
--custom-path.
|
|
109
|
+
-s, --server-path=server-path The server path to write the server-side packs at. Not compatible with --world.
|
|
111
110
|
|
|
112
|
-
--
|
|
111
|
+
-w, --world=world The world to save the packs in. Not compatible with --save-root or --server
|
|
113
112
|
|
|
114
|
-
--
|
|
113
|
+
--npm Use npm.
|
|
114
|
+
|
|
115
|
+
--yarn Use yarn instead of npm.
|
|
115
116
|
|
|
116
117
|
EXAMPLE
|
|
117
|
-
$ sand create my-
|
|
118
|
+
$ sand create my-pack
|
|
118
119
|
```
|
|
119
120
|
|
|
120
|
-
_See code: [src/commands/create.ts](https://github.com/TheMrZZ/sandstone-cli/blob/v0.6.
|
|
121
|
+
_See code: [src/commands/create.ts](https://github.com/TheMrZZ/sandstone-cli/blob/v0.6.2/src/commands/create.ts)_
|
|
121
122
|
|
|
122
123
|
## `sand help [COMMAND]`
|
|
123
124
|
|
|
@@ -159,11 +160,11 @@ EXAMPLES
|
|
|
159
160
|
$ sand update --cli --sandstone --skip
|
|
160
161
|
```
|
|
161
162
|
|
|
162
|
-
_See code: [src/commands/update.ts](https://github.com/TheMrZZ/sandstone-cli/blob/v0.6.
|
|
163
|
+
_See code: [src/commands/update.ts](https://github.com/TheMrZZ/sandstone-cli/blob/v0.6.2/src/commands/update.ts)_
|
|
163
164
|
|
|
164
165
|
## `sand watch PATH CONFIG-PATH`
|
|
165
166
|
|
|
166
|
-
Build the
|
|
167
|
+
Build the packs, and rebuild them on file change. ⛏
|
|
167
168
|
|
|
168
169
|
```
|
|
169
170
|
USAGE
|
|
@@ -174,7 +175,7 @@ ARGUMENTS
|
|
|
174
175
|
CONFIG-PATH [default: .] Path of the sandstone.config.ts folder.
|
|
175
176
|
|
|
176
177
|
OPTIONS
|
|
177
|
-
-d, --dry Do not save the
|
|
178
|
+
-d, --dry Do not save the pack. Mostly useful with `verbose`.
|
|
178
179
|
-h, --help show CLI help
|
|
179
180
|
-p, --production Runs Sandstone in production mode. This sets process.env.SANDSTONE_ENV to "production".
|
|
180
181
|
-v, --verbose Log all resulting resources: functions, advancements...
|
|
@@ -182,23 +183,23 @@ OPTIONS
|
|
|
182
183
|
--autoReload=port Automatically reload your data pack in-game. Requires to open the world to LAN with
|
|
183
184
|
cheats enabled, and to specify the port.
|
|
184
185
|
|
|
186
|
+
--clientPath=clientPath Path of the client folder. Override the value specified in the configuration file.
|
|
187
|
+
|
|
185
188
|
--description=description Description of the data pack. Override the value specified in the configuration file.
|
|
186
189
|
|
|
187
190
|
--formatVersion=formatVersion Pack format version. Override the value specified in the configuration file.
|
|
188
191
|
|
|
189
192
|
--fullTrace Show the full stack trace on errors.
|
|
190
193
|
|
|
191
|
-
--minecraftPath=minecraftPath Path of the .minecraft folder. Override the value specified in the configuration file.
|
|
192
|
-
|
|
193
194
|
--name=name Name of the data pack. Override the value specified in the configuration file.
|
|
194
195
|
|
|
195
196
|
--namespace=namespace The default namespace. Override the value specified in the configuration file.
|
|
196
197
|
|
|
197
|
-
--
|
|
198
|
+
--root Save the data pack & resource pack in the .minecraft/datapacks &
|
|
199
|
+
.minecraft/resource_packs folders. Override the value specified in the configuration
|
|
198
200
|
file.
|
|
199
201
|
|
|
200
|
-
--
|
|
201
|
-
in the configuration file.
|
|
202
|
+
--serverPath=serverPath Path of the server folder. Override the value specified in the configuration file.
|
|
202
203
|
|
|
203
204
|
--strictErrors Stop data pack compilation on type errors.
|
|
204
205
|
|
|
@@ -211,5 +212,5 @@ EXAMPLES
|
|
|
211
212
|
$ sand watch --verbose --dry
|
|
212
213
|
```
|
|
213
214
|
|
|
214
|
-
_See code: [src/commands/watch.ts](https://github.com/TheMrZZ/sandstone-cli/blob/v0.6.
|
|
215
|
+
_See code: [src/commands/watch.ts](https://github.com/TheMrZZ/sandstone-cli/blob/v0.6.2/src/commands/watch.ts)_
|
|
215
216
|
<!-- commandsstop -->
|
|
@@ -2,8 +2,9 @@ import { ProjectFolders } from '../utils';
|
|
|
2
2
|
export declare type BuildOptions = {
|
|
3
3
|
world?: string;
|
|
4
4
|
root?: boolean;
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
clientPath?: string;
|
|
6
|
+
serverPath?: string;
|
|
7
|
+
ssh?: string;
|
|
7
8
|
namespace?: string;
|
|
8
9
|
name?: string;
|
|
9
10
|
description?: string;
|
|
@@ -1,10 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
2
21
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
22
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
23
|
};
|
|
5
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
25
|
exports.buildProject = void 0;
|
|
7
26
|
const path_1 = __importDefault(require("path"));
|
|
27
|
+
const os = __importStar(require("os"));
|
|
8
28
|
const crypto_1 = __importDefault(require("crypto"));
|
|
9
29
|
const util_1 = require("util");
|
|
10
30
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
@@ -13,6 +33,8 @@ const klaw_1 = __importDefault(require("klaw"));
|
|
|
13
33
|
const madge_1 = __importDefault(require("madge"));
|
|
14
34
|
const graph_1 = require("./graph");
|
|
15
35
|
const chalk_1 = __importDefault(require("chalk"));
|
|
36
|
+
const adm_zip_1 = __importDefault(require("adm-zip"));
|
|
37
|
+
const delete_empty_1 = __importDefault(require("delete-empty"));
|
|
16
38
|
const pe = new pretty_error_1.default();
|
|
17
39
|
// Return the hash of a string
|
|
18
40
|
function hash(stringToHash) {
|
|
@@ -33,36 +55,9 @@ async function mkDir(dirPath) {
|
|
|
33
55
|
// Directory already exists
|
|
34
56
|
}
|
|
35
57
|
}
|
|
36
|
-
|
|
58
|
+
let cache;
|
|
37
59
|
const dependenciesCache = new graph_1.DependencyGraph({});
|
|
38
60
|
const fileResources = new Map();
|
|
39
|
-
/**
|
|
40
|
-
* Recursively removes empty directories from the given directory.
|
|
41
|
-
*
|
|
42
|
-
* If the directory itself is empty, it is also removed.
|
|
43
|
-
*
|
|
44
|
-
* Code taken from: https://gist.github.com/jakub-g/5903dc7e4028133704a4
|
|
45
|
-
*
|
|
46
|
-
* @param {string} directory Path to the directory to clean up
|
|
47
|
-
*/
|
|
48
|
-
async function removeEmptyDirectories(directory) {
|
|
49
|
-
// lstat does not follow symlinks (in contrast to stat)
|
|
50
|
-
const fileStats = await fs_extra_1.default.lstat(directory);
|
|
51
|
-
if (!fileStats.isDirectory()) {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
let fileNames = await fs_extra_1.default.readdir(directory);
|
|
55
|
-
if (fileNames.length > 0) {
|
|
56
|
-
const recursiveRemovalPromises = fileNames.map((fileName) => removeEmptyDirectories(path_1.default.join(directory, fileName)));
|
|
57
|
-
await Promise.all(recursiveRemovalPromises);
|
|
58
|
-
// re-evaluate fileNames; after deleting subdirectory
|
|
59
|
-
// we may have parent directory empty now
|
|
60
|
-
fileNames = await fs_extra_1.default.readdir(directory);
|
|
61
|
-
}
|
|
62
|
-
if (fileNames.length === 0) {
|
|
63
|
-
await fs_extra_1.default.rmdir(directory);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
61
|
function getNewModules(dependenciesGraph, rawFiles, projectFolder) {
|
|
67
62
|
const rawFilesPath = rawFiles.map(({ path }) => path);
|
|
68
63
|
// Get only the new modules
|
|
@@ -85,76 +80,137 @@ function diffMap(map1, map2) {
|
|
|
85
80
|
return new Map([...map1.entries()].filter(([key, value]) => !map2.has(key)));
|
|
86
81
|
}
|
|
87
82
|
function diffResources(tree1, tree2) {
|
|
88
|
-
return tree1
|
|
83
|
+
return diffSet(tree1, tree2);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
*
|
|
87
|
+
* @param worldName The name of the world
|
|
88
|
+
* @param minecraftPath The optional location of the .minecraft folder.
|
|
89
|
+
* If left unspecified, the .minecraft will be found automatically.
|
|
90
|
+
*/
|
|
91
|
+
async function getClientWorldPath(worldName, minecraftPath = undefined) {
|
|
92
|
+
let mcPath;
|
|
93
|
+
if (minecraftPath) {
|
|
94
|
+
mcPath = minecraftPath;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
mcPath = await getClientPath();
|
|
98
|
+
}
|
|
99
|
+
const savesPath = path_1.default.join(mcPath, 'saves');
|
|
100
|
+
const worldPath = path_1.default.join(savesPath, worldName);
|
|
101
|
+
if (!fs_extra_1.default.existsSync(worldPath)) {
|
|
102
|
+
const existingWorlds = (await fs_extra_1.default.readdir(savesPath, { withFileTypes: true })).filter((f) => f.isDirectory).map((f) => f.name);
|
|
103
|
+
throw new Error(`Unable to locate the "${worldPath}" folder. Word ${worldName} does not exists. List of existing worlds: ${JSON.stringify(existingWorlds, null, 2)}`);
|
|
104
|
+
}
|
|
105
|
+
return worldPath;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get the .minecraft path
|
|
109
|
+
*/
|
|
110
|
+
async function getClientPath() {
|
|
111
|
+
function getMCPath() {
|
|
112
|
+
switch (os.platform()) {
|
|
113
|
+
case 'win32':
|
|
114
|
+
return path_1.default.join(os.homedir(), 'AppData/Roaming/.minecraft');
|
|
115
|
+
case 'darwin':
|
|
116
|
+
return path_1.default.join(os.homedir(), 'Library/Application Support/minecraft');
|
|
117
|
+
case 'linux':
|
|
118
|
+
default:
|
|
119
|
+
return path_1.default.join(os.homedir(), '.minecraft');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const mcPath = getMCPath();
|
|
123
|
+
if (!await fs_extra_1.default.stat(mcPath)) {
|
|
124
|
+
throw new Error('Unable to locate the .minecraft folder. Please specify it manually.');
|
|
125
|
+
}
|
|
126
|
+
return mcPath;
|
|
89
127
|
}
|
|
90
128
|
/**
|
|
91
129
|
* Build the project, but might throw errors.
|
|
92
130
|
*
|
|
93
|
-
* @param
|
|
131
|
+
* @param cliOptions The options to build the project with.
|
|
94
132
|
*
|
|
95
133
|
* @param projectFolder The folder of the project. It needs a sandstone.config.ts, and it or one of its parent needs a package.json.
|
|
96
134
|
*/
|
|
97
|
-
async function _buildProject(
|
|
98
|
-
var _a, _b, _c, _d, _e, _f, _g
|
|
135
|
+
async function _buildProject(cliOptions, { absProjectFolder, rootFolder, sandstoneConfigFolder }, changedFiles) {
|
|
136
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
99
137
|
const sandstoneLocation = path_1.default.join(rootFolder, 'node_modules/sandstone/');
|
|
100
138
|
// First, read sandstone.config.ts to get all properties
|
|
101
139
|
const sandstoneConfig = require(path_1.default.join(sandstoneConfigFolder, 'sandstone.config.ts')).default;
|
|
102
140
|
const { saveOptions, scripts } = sandstoneConfig;
|
|
141
|
+
const outputFolder = path_1.default.join(rootFolder, '.sandstone', 'output');
|
|
103
142
|
/// OPTIONS ///
|
|
104
|
-
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
143
|
+
const clientPath = !cliOptions.production ? (cliOptions.clientPath || saveOptions.clientPath || await getClientPath()) : undefined;
|
|
144
|
+
const server = !cliOptions.production && (cliOptions.serverPath || saveOptions.serverPath || cliOptions.ssh || saveOptions.ssh) ? await (async () => {
|
|
145
|
+
if (cliOptions.ssh || saveOptions.ssh) {
|
|
146
|
+
const sshOptions = JSON.stringify(await fs_extra_1.default.readFile(cliOptions.ssh || saveOptions.ssh, 'utf8'));
|
|
147
|
+
// TODO: implement SFTP
|
|
148
|
+
return {
|
|
149
|
+
readFile: async (relativePath, encoding = 'utf8') => { },
|
|
150
|
+
writeFile: async (relativePath, contents) => { },
|
|
151
|
+
remove: async (relativePath) => { },
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
const serverPath = cliOptions.serverPath || saveOptions.serverPath;
|
|
155
|
+
return {
|
|
156
|
+
readFile: async (relativePath, encoding = 'utf8') => await fs_extra_1.default.readFile(path_1.default.join(serverPath, relativePath), encoding),
|
|
157
|
+
writeFile: async (relativePath, contents) => {
|
|
158
|
+
if (contents === undefined) {
|
|
159
|
+
await fs_extra_1.default.unlink(path_1.default.join(serverPath, relativePath));
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
await fs_extra_1.default.writeFile(path_1.default.join(serverPath, relativePath), contents);
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
remove: async (relativePath) => await fs_extra_1.default.remove(path_1.default.join(serverPath, relativePath))
|
|
166
|
+
};
|
|
167
|
+
})() : undefined;
|
|
168
|
+
let worldName = cliOptions.world || saveOptions.world;
|
|
169
|
+
// Make sure the world exists
|
|
170
|
+
if (worldName && !cliOptions.production) {
|
|
171
|
+
await getClientWorldPath(worldName, clientPath);
|
|
172
|
+
}
|
|
173
|
+
const root = cliOptions.root !== undefined ? cliOptions.root : saveOptions.root;
|
|
174
|
+
const packName = (_a = cliOptions.name) !== null && _a !== void 0 ? _a : sandstoneConfig.name;
|
|
175
|
+
if (worldName && root) {
|
|
176
|
+
throw new Error(`Expected only 'world' or 'root'. Got both.`);
|
|
113
177
|
}
|
|
114
178
|
// Important /!\: The below if statements, which set environment variables, must run before importing any Sandstone file.
|
|
115
179
|
// Set the pack ID environment variable
|
|
116
180
|
// Set production/development mode
|
|
117
|
-
if (
|
|
181
|
+
if (cliOptions.production) {
|
|
118
182
|
process.env.SANDSTONE_ENV = 'production';
|
|
119
183
|
}
|
|
120
184
|
else {
|
|
121
185
|
process.env.SANDSTONE_ENV = 'development';
|
|
122
186
|
}
|
|
187
|
+
process.env.WORKING_DIR = absProjectFolder;
|
|
123
188
|
if (sandstoneConfig.packUid) {
|
|
124
189
|
process.env.PACK_UID = sandstoneConfig.packUid;
|
|
125
190
|
}
|
|
126
191
|
// Set the namespace
|
|
127
|
-
const namespace =
|
|
192
|
+
const namespace = cliOptions.namespace || sandstoneConfig.namespace;
|
|
128
193
|
if (namespace) {
|
|
129
194
|
process.env.NAMESPACE = namespace;
|
|
130
195
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
process.env[`${
|
|
196
|
+
const { onConflict } = sandstoneConfig;
|
|
197
|
+
if (onConflict) {
|
|
198
|
+
for (const resource of Object.entries(onConflict)) {
|
|
199
|
+
process.env[`${resource[0].toUpperCase()}_CONFLICT_STRATEGY`] = resource[1];
|
|
135
200
|
}
|
|
136
201
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
setStrategy('mcfunction', onConflict === null || onConflict === void 0 ? void 0 : onConflict.mcFunction);
|
|
142
|
-
setStrategy('predicate', onConflict === null || onConflict === void 0 ? void 0 : onConflict.predicate);
|
|
143
|
-
setStrategy('recipe', onConflict === null || onConflict === void 0 ? void 0 : onConflict.recipe);
|
|
144
|
-
setStrategy('tag', onConflict === null || onConflict === void 0 ? void 0 : onConflict.tag);
|
|
202
|
+
// JSON indentation
|
|
203
|
+
process.env.INDENTATION = saveOptions.indentation;
|
|
204
|
+
// Pack mcmeta
|
|
205
|
+
process.env.PACK_OPTIONS = JSON.stringify(sandstoneConfig.packs);
|
|
145
206
|
// Configure error display
|
|
146
|
-
if (!
|
|
207
|
+
if (!cliOptions.fullTrace) {
|
|
147
208
|
pe.skipNodeFiles();
|
|
148
209
|
}
|
|
149
210
|
/// IMPORTING USER CODE ///
|
|
150
211
|
// The configuration is ready.
|
|
151
212
|
// Now, let's run the beforeAll script
|
|
152
|
-
|
|
153
|
-
const destinationPath = getDestinationPath(dataPackName, { world, asRootDatapack: root, customPath, minecraftPath });
|
|
154
|
-
await ((_c = scripts === null || scripts === void 0 ? void 0 : scripts.beforeAll) === null || _c === void 0 ? void 0 : _c.call(scripts, {
|
|
155
|
-
dataPackName,
|
|
156
|
-
destination: destinationPath,
|
|
157
|
-
}));
|
|
213
|
+
await ((_b = scripts === null || scripts === void 0 ? void 0 : scripts.beforeAll) === null || _b === void 0 ? void 0 : _b.call(scripts));
|
|
158
214
|
// Finally, let's import all .ts & .js files under ./src.
|
|
159
215
|
let error = false;
|
|
160
216
|
// Get the list of all files
|
|
@@ -188,28 +244,17 @@ async function _buildProject(options, { absProjectFolder, rootFolder, sandstoneC
|
|
|
188
244
|
dependenciesCache.merge(dependenciesGraph);
|
|
189
245
|
// Transform resolved dependents into a flat list of files, and sort them by their number of dependencies
|
|
190
246
|
const newModules = getNewModules(dependenciesCache, changedFilesPaths !== null && changedFilesPaths !== void 0 ? changedFilesPaths : rawFiles, absProjectFolder);
|
|
191
|
-
const {
|
|
192
|
-
const { dataPack } = require(sandstoneLocation + '/init');
|
|
247
|
+
const { sandstonePack } = require(sandstoneLocation);
|
|
193
248
|
// If files changed, we need to clean the cache & delete the related resources
|
|
194
249
|
if (changedFiles) {
|
|
195
250
|
for (const node of newModules) {
|
|
196
|
-
// For
|
|
251
|
+
// For each changed file, we need to reset the require cache
|
|
197
252
|
delete require.cache[path_1.default.join(absProjectFolder, node.name)];
|
|
198
253
|
// Then we need to delete all resources the file created
|
|
199
254
|
const oldResources = fileResources.get(node.name);
|
|
200
255
|
if (oldResources) {
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
dataPack.resources.deleteResource(resource.path, resource.resourceType);
|
|
204
|
-
}
|
|
205
|
-
for (const resource of customResources) {
|
|
206
|
-
dataPack.customResources.delete(resource);
|
|
207
|
-
}
|
|
208
|
-
for (const objective of objectives.keys()) {
|
|
209
|
-
dataPack.objectives.delete(objective);
|
|
210
|
-
}
|
|
211
|
-
for (const rootFunction of rootFunctions) {
|
|
212
|
-
dataPack.rootFunctions.delete(rootFunction);
|
|
256
|
+
for (const resource of oldResources.resources) {
|
|
257
|
+
sandstonePack.core.deleteResource(resource.path, resource.resourceType);
|
|
213
258
|
}
|
|
214
259
|
}
|
|
215
260
|
}
|
|
@@ -218,10 +263,8 @@ async function _buildProject(options, { absProjectFolder, rootFolder, sandstoneC
|
|
|
218
263
|
for (const node of newModules) {
|
|
219
264
|
const modulePath = path_1.default.join(absProjectFolder, node.name);
|
|
220
265
|
const currentResources = {
|
|
221
|
-
resources:
|
|
222
|
-
objectives: new
|
|
223
|
-
rootFunctions: new Set([...dataPack.rootFunctions]),
|
|
224
|
-
customResources: new Set([...dataPack.customResources]),
|
|
266
|
+
resources: new Set([...sandstonePack.core.resourceNodes]),
|
|
267
|
+
objectives: new Set([...sandstonePack.objectives.entries()])
|
|
225
268
|
};
|
|
226
269
|
// We have a module, let's require it!
|
|
227
270
|
const filePath = path_1.default.resolve(modulePath);
|
|
@@ -230,10 +273,6 @@ async function _buildProject(options, { absProjectFolder, rootFolder, sandstoneC
|
|
|
230
273
|
if (await fs_extra_1.default.pathExists(filePath)) {
|
|
231
274
|
require(filePath);
|
|
232
275
|
}
|
|
233
|
-
// Generate the mcfunctions
|
|
234
|
-
for (const mcfunction of dataPack.rootFunctions) {
|
|
235
|
-
await mcfunction.generate();
|
|
236
|
-
}
|
|
237
276
|
}
|
|
238
277
|
catch (e) {
|
|
239
278
|
logError(e, node.name);
|
|
@@ -242,10 +281,8 @@ async function _buildProject(options, { absProjectFolder, rootFolder, sandstoneC
|
|
|
242
281
|
// Now, find the resources that were added by this file & store them.
|
|
243
282
|
// This will be used if those files are changed later.
|
|
244
283
|
const newResources = {
|
|
245
|
-
resources: diffResources(
|
|
246
|
-
|
|
247
|
-
rootFunctions: diffSet(dataPack.rootFunctions, currentResources.rootFunctions),
|
|
248
|
-
objectives: diffMap(dataPack.objectives, currentResources.objectives),
|
|
284
|
+
resources: diffResources(sandstonePack.core.resourceNodes, currentResources.resources),
|
|
285
|
+
objectives: diffSet(sandstonePack.objectives, currentResources.objectives),
|
|
249
286
|
};
|
|
250
287
|
fileResources.set(node.name, newResources);
|
|
251
288
|
}
|
|
@@ -255,72 +292,223 @@ async function _buildProject(options, { absProjectFolder, rootFolder, sandstoneC
|
|
|
255
292
|
/// SAVING RESULTS ///
|
|
256
293
|
// Setup the cache if it doesn't exist.
|
|
257
294
|
// This cache is here to avoid writing files on disk when they did not change.
|
|
258
|
-
const newCache = {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
295
|
+
const newCache = {};
|
|
296
|
+
const cacheFile = path_1.default.join(rootFolder, '.sandstone', 'cache.json');
|
|
297
|
+
if (cache === undefined) {
|
|
298
|
+
let oldCache;
|
|
299
|
+
try {
|
|
300
|
+
const fileRead = await fs_extra_1.default.readFile(cacheFile, 'utf8');
|
|
301
|
+
if (fileRead) {
|
|
302
|
+
oldCache = JSON.parse(fileRead);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
catch { }
|
|
306
|
+
if (oldCache) {
|
|
307
|
+
cache = oldCache;
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
cache = {};
|
|
311
|
+
}
|
|
265
312
|
}
|
|
266
313
|
// Save the pack
|
|
267
|
-
// Run the beforeSave script
|
|
268
|
-
await ((
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
customPath: customPath,
|
|
277
|
-
minecraftPath: minecraftPath,
|
|
278
|
-
indentation: saveOptions.indentation,
|
|
279
|
-
// Data pack mcmeta
|
|
280
|
-
description: (_e = options.description) !== null && _e !== void 0 ? _e : sandstoneConfig.description,
|
|
281
|
-
formatVersion: (_f = options.formatVersion) !== null && _f !== void 0 ? _f : sandstoneConfig.formatVersion,
|
|
314
|
+
// Run the beforeSave script (TODO: This is where sandstone-server will remove restart env vars)
|
|
315
|
+
await ((_c = scripts === null || scripts === void 0 ? void 0 : scripts.beforeSave) === null || _c === void 0 ? void 0 : _c.call(scripts));
|
|
316
|
+
const excludeOption = (_d = saveOptions.resources) === null || _d === void 0 ? void 0 : _d.exclude;
|
|
317
|
+
const fileExclusions = excludeOption ? {
|
|
318
|
+
generated: (excludeOption.generated || excludeOption),
|
|
319
|
+
existing: (excludeOption.existing || excludeOption)
|
|
320
|
+
} : false;
|
|
321
|
+
const fileHandlers = ((_e = saveOptions.resources) === null || _e === void 0 ? void 0 : _e.handle) || false;
|
|
322
|
+
const packTypes = await sandstonePack.save({
|
|
282
323
|
// Additional parameters
|
|
283
|
-
|
|
284
|
-
verbose:
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
if (
|
|
295
|
-
|
|
296
|
-
|
|
324
|
+
dry: cliOptions.dry,
|
|
325
|
+
verbose: cliOptions.verbose,
|
|
326
|
+
fileHandler: (_f = saveOptions.customFileHandler) !== null && _f !== void 0 ? _f : (async (relativePath, content) => {
|
|
327
|
+
let pathPass = true;
|
|
328
|
+
if (fileExclusions && fileExclusions.generated) {
|
|
329
|
+
for (const exclude of fileExclusions.generated) {
|
|
330
|
+
if (!Array.isArray(exclude)) {
|
|
331
|
+
pathPass = !exclude.test(relativePath);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
if (fileHandlers) {
|
|
336
|
+
for (const handler of fileHandlers) {
|
|
337
|
+
if (handler.path.test(relativePath)) {
|
|
338
|
+
content = await handler.callback(content);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
if (pathPass) {
|
|
343
|
+
// We hash the relative path alongside the content to ensure unique hash.
|
|
344
|
+
const hashValue = hash(content + relativePath);
|
|
345
|
+
// Add to new cache.
|
|
346
|
+
newCache[relativePath] = hashValue;
|
|
347
|
+
if (cache[relativePath] === hashValue) {
|
|
348
|
+
// Already in cache - skip
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
// Not in cache: write to disk
|
|
352
|
+
const realPath = path_1.default.join(outputFolder, relativePath);
|
|
353
|
+
await mkDir(path_1.default.dirname(realPath));
|
|
354
|
+
return await fs_extra_1.default.writeFile(realPath, content);
|
|
297
355
|
}
|
|
298
|
-
// Not in cache: write to disk
|
|
299
|
-
await mkDir(path_1.default.dirname(realPath));
|
|
300
|
-
return await fs_extra_1.default.writeFile(realPath, content);
|
|
301
356
|
})
|
|
302
357
|
});
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
358
|
+
async function handleResources(packType) {
|
|
359
|
+
const working = path_1.default.join(rootFolder, 'resources', packType);
|
|
360
|
+
for await (const file of (0, klaw_1.default)(path_1.default.join(rootFolder, 'resources', packType), { filter: (_path) => {
|
|
361
|
+
const relativePath = path_1.default.join(packType, _path.split(working)[1]);
|
|
362
|
+
let pathPass = true;
|
|
363
|
+
if (fileExclusions && fileExclusions.existing) {
|
|
364
|
+
for (const exclude of fileExclusions.existing) {
|
|
365
|
+
pathPass = Array.isArray(exclude) ? !exclude[0].test(relativePath) : !exclude.test(relativePath);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
return pathPass;
|
|
369
|
+
} })) {
|
|
370
|
+
const relativePath = path_1.default.join(packType, file.path.split(working)[1]);
|
|
371
|
+
try {
|
|
372
|
+
let content = await fs_extra_1.default.readFile(file.path);
|
|
373
|
+
if (fileHandlers) {
|
|
374
|
+
for (const handler of fileHandlers) {
|
|
375
|
+
if (handler.path.test(relativePath)) {
|
|
376
|
+
content = await handler.callback(content);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
// We hash the relative path alongside the content to ensure unique hash.
|
|
381
|
+
const hashValue = hash(content + relativePath);
|
|
382
|
+
// Add to new cache.
|
|
383
|
+
newCache[relativePath] = hashValue;
|
|
384
|
+
if (cache[relativePath] !== hashValue) {
|
|
385
|
+
// Not in cache: write to disk
|
|
386
|
+
const realPath = path_1.default.join(outputFolder, relativePath);
|
|
387
|
+
await mkDir(path_1.default.dirname(realPath));
|
|
388
|
+
await fs_extra_1.default.writeFile(realPath, content);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
catch (e) { }
|
|
312
392
|
}
|
|
313
|
-
|
|
314
|
-
|
|
393
|
+
}
|
|
394
|
+
async function archiveOutput(packType) {
|
|
395
|
+
const outputPath = path_1.default.join(rootFolder, '.sandstone/output/archives', `${packName}_${packType.type}`);
|
|
396
|
+
const archive = new adm_zip_1.default();
|
|
397
|
+
await archive.addLocalFolderPromise(outputPath, {});
|
|
398
|
+
await archive.writeZipPromise(`${outputPath}.zip`, { overwrite: true });
|
|
399
|
+
}
|
|
400
|
+
// TODO: implement linking to make the cache more useful when not archiving.
|
|
401
|
+
if (!cliOptions.production) {
|
|
402
|
+
for await (const _packType of packTypes) {
|
|
403
|
+
const packType = _packType[1];
|
|
404
|
+
const outputPath = path_1.default.join(rootFolder, '.sandstone/output', packType.type);
|
|
405
|
+
if (packType.handleOutput) {
|
|
406
|
+
await packType.handleOutput('output', async (relativePath, encoding = 'utf8') => await fs_extra_1.default.readFile(path_1.default.join(outputPath, relativePath), encoding), async (relativePath, contents) => {
|
|
407
|
+
if (contents === undefined) {
|
|
408
|
+
await fs_extra_1.default.unlink(path_1.default.join(outputPath, relativePath));
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
await fs_extra_1.default.writeFile(path_1.default.join(outputPath, relativePath), contents);
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
handleResources(packType.type);
|
|
416
|
+
if (packType.archiveOutput) {
|
|
417
|
+
archiveOutput(packType);
|
|
418
|
+
}
|
|
419
|
+
// Handle client
|
|
420
|
+
if (!(server && packType.networkSides === 'server')) {
|
|
421
|
+
let fullClientPath;
|
|
422
|
+
if (worldName) {
|
|
423
|
+
fullClientPath = path_1.default.join(clientPath, packType.clientPath);
|
|
424
|
+
try {
|
|
425
|
+
fullClientPath = fullClientPath.replace('$packName$', packName);
|
|
426
|
+
}
|
|
427
|
+
catch { }
|
|
428
|
+
try {
|
|
429
|
+
fullClientPath = fullClientPath.replace('$worldName$', worldName);
|
|
430
|
+
}
|
|
431
|
+
catch { }
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
fullClientPath = path_1.default.join(clientPath, packType.rootPath);
|
|
435
|
+
try {
|
|
436
|
+
fullClientPath = fullClientPath.replace('$packName$', packName);
|
|
437
|
+
}
|
|
438
|
+
catch { }
|
|
439
|
+
}
|
|
440
|
+
if (packType.archiveOutput) {
|
|
441
|
+
await fs_extra_1.default.copyFile(`${outputPath}.zip`, `${fullClientPath}.zip`);
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
await fs_extra_1.default.remove(fullClientPath);
|
|
445
|
+
await fs_extra_1.default.copy(outputPath, fullClientPath);
|
|
446
|
+
}
|
|
447
|
+
if (packType.handleOutput) {
|
|
448
|
+
await packType.handleOutput('client', async (relativePath, encoding = 'utf8') => await fs_extra_1.default.readFile(path_1.default.join(clientPath, relativePath), encoding), async (relativePath, contents) => {
|
|
449
|
+
if (contents === undefined) {
|
|
450
|
+
fs_extra_1.default.unlink(path_1.default.join(clientPath, relativePath));
|
|
451
|
+
}
|
|
452
|
+
else {
|
|
453
|
+
await fs_extra_1.default.writeFile(path_1.default.join(clientPath, relativePath), contents);
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
// Handle server
|
|
459
|
+
if (server && (packType.networkSides === 'server' || packType.networkSides === 'both')) {
|
|
460
|
+
let serverPath = packType.serverPath;
|
|
461
|
+
try {
|
|
462
|
+
serverPath = serverPath.replace('$packName$', packName);
|
|
463
|
+
}
|
|
464
|
+
catch { }
|
|
465
|
+
if (packType.archiveOutput) {
|
|
466
|
+
await server.writeFile(await fs_extra_1.default.readFile(`${outputPath}.zip`, 'utf8'), `${serverPath}.zip`);
|
|
467
|
+
}
|
|
468
|
+
else {
|
|
469
|
+
server.remove(serverPath);
|
|
470
|
+
for await (const file of (0, klaw_1.default)(outputPath)) {
|
|
471
|
+
await server.writeFile(path_1.default.join(serverPath, file.path.split(outputPath)[1]), await fs_extra_1.default.readFile(file.path));
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
if (packType.handleOutput) {
|
|
475
|
+
await packType.handleOutput('server', server.readFile, server.writeFile);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
else {
|
|
481
|
+
for await (const packType of packTypes) {
|
|
482
|
+
const outputPath = path_1.default.join(rootFolder, '.sandstone/output/archives', `${packName}_${packType.type}`);
|
|
483
|
+
if (packType.handleOutput) {
|
|
484
|
+
await packType.handleOutput('output', async (relativePath, encoding = 'utf8') => await fs_extra_1.default.readFile(path_1.default.join(outputPath, relativePath), encoding), async (relativePath, contents) => {
|
|
485
|
+
if (contents === undefined) {
|
|
486
|
+
await fs_extra_1.default.unlink(path_1.default.join(outputPath, relativePath));
|
|
487
|
+
}
|
|
488
|
+
else {
|
|
489
|
+
await fs_extra_1.default.writeFile(path_1.default.join(outputPath, relativePath), contents);
|
|
490
|
+
}
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
handleResources(packType.type);
|
|
494
|
+
if (packType.archiveOutput) {
|
|
495
|
+
archiveOutput(packType);
|
|
496
|
+
}
|
|
315
497
|
}
|
|
316
498
|
}
|
|
499
|
+
// Delete old files that aren't cached anymore
|
|
500
|
+
const oldFilesNames = new Set(Object.keys(cache));
|
|
501
|
+
Object.keys(newCache).forEach(name => oldFilesNames.delete(name));
|
|
502
|
+
await Promise.allSettled([...oldFilesNames.values()].map(name => {
|
|
503
|
+
return (0, util_1.promisify)(fs_extra_1.default.rm)(path_1.default.join(outputFolder, name));
|
|
504
|
+
}));
|
|
505
|
+
await (0, delete_empty_1.default)(outputFolder);
|
|
317
506
|
// Override old cache
|
|
318
|
-
cache
|
|
507
|
+
cache = newCache;
|
|
508
|
+
// Write the cache to disk
|
|
509
|
+
await fs_extra_1.default.writeFile(cacheFile, JSON.stringify(cache));
|
|
319
510
|
// Run the afterAll script
|
|
320
|
-
await ((
|
|
321
|
-
dataPackName,
|
|
322
|
-
destination: destinationPath,
|
|
323
|
-
}));
|
|
511
|
+
await ((_g = scripts === null || scripts === void 0 ? void 0 : scripts.afterAll) === null || _g === void 0 ? void 0 : _g.call(scripts));
|
|
324
512
|
}
|
|
325
513
|
/**
|
|
326
514
|
* Build the project. Will log errors and never throw any.
|
|
@@ -336,7 +524,7 @@ async function buildProject(options, folders, changedFiles) {
|
|
|
336
524
|
await _buildProject(options, folders, changedFiles);
|
|
337
525
|
}
|
|
338
526
|
catch (err) {
|
|
339
|
-
|
|
527
|
+
console.log(err);
|
|
340
528
|
}
|
|
341
529
|
}
|
|
342
530
|
exports.buildProject = buildProject;
|
|
@@ -345,6 +533,7 @@ function logError(err, file) {
|
|
|
345
533
|
if (file) {
|
|
346
534
|
console.error(' ' + chalk_1.default.bgRed.white('BuildError') + chalk_1.default.gray(':'), `While loading "${file}", the following error happened:\n`);
|
|
347
535
|
}
|
|
536
|
+
debugger;
|
|
348
537
|
console.error(pe.render(err));
|
|
349
538
|
}
|
|
350
539
|
}
|
package/lib/commands/build.d.ts
CHANGED
|
@@ -9,8 +9,8 @@ export default class Build extends Command {
|
|
|
9
9
|
namespace: import("@oclif/command/lib/flags").IOptionFlag<string | undefined>;
|
|
10
10
|
world: import("@oclif/command/lib/flags").IOptionFlag<string | undefined>;
|
|
11
11
|
root: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
clientPath: import("@oclif/command/lib/flags").IOptionFlag<string | undefined>;
|
|
13
|
+
serverPath: import("@oclif/command/lib/flags").IOptionFlag<string | undefined>;
|
|
14
14
|
name: import("@oclif/command/lib/flags").IOptionFlag<string | undefined>;
|
|
15
15
|
description: import("@oclif/command/lib/flags").IOptionFlag<string | undefined>;
|
|
16
16
|
formatVersion: import("@oclif/parser/lib/flags").IOptionFlag<number | undefined>;
|
package/lib/commands/build.js
CHANGED
package/lib/commands/create.d.ts
CHANGED
|
@@ -6,11 +6,12 @@ export default class Create extends Command {
|
|
|
6
6
|
help: import("@oclif/parser/lib/flags").IBooleanFlag<void>;
|
|
7
7
|
yarn: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
|
|
8
8
|
npm: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
|
|
9
|
-
'
|
|
9
|
+
'pack-name': flags.IOptionFlag<string | undefined>;
|
|
10
10
|
namespace: flags.IOptionFlag<string | undefined>;
|
|
11
11
|
'save-root': import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
|
|
12
12
|
world: flags.IOptionFlag<string | undefined>;
|
|
13
|
-
'
|
|
13
|
+
'server-path': flags.IOptionFlag<string | undefined>;
|
|
14
|
+
'client-path': flags.IOptionFlag<string | undefined>;
|
|
14
15
|
};
|
|
15
16
|
static args: {
|
|
16
17
|
name: string;
|
package/lib/commands/create.js
CHANGED
|
@@ -28,7 +28,7 @@ class Create extends command_1.Command {
|
|
|
28
28
|
const { args, flags } = this.parse(Create);
|
|
29
29
|
const projectPath = path_1.default.resolve(args['project-name']);
|
|
30
30
|
const projectName = path_1.default.basename(projectPath);
|
|
31
|
-
const
|
|
31
|
+
const packName = await (0, utils_1.getFlagOrPrompt)(flags, 'pack-name', {
|
|
32
32
|
message: 'Name of your data pack (can be changed later) >',
|
|
33
33
|
type: 'input',
|
|
34
34
|
default: projectName,
|
|
@@ -41,27 +41,27 @@ class Create extends command_1.Command {
|
|
|
41
41
|
else if (flags.world) {
|
|
42
42
|
saveOptions.world = flags.world;
|
|
43
43
|
}
|
|
44
|
-
else if (flags['
|
|
45
|
-
saveOptions.
|
|
44
|
+
else if (flags['server-path']) {
|
|
45
|
+
saveOptions.serverPath = flags['server-path'];
|
|
46
46
|
}
|
|
47
|
-
else {
|
|
48
|
-
// User didn't specify a way to save the file. Ask
|
|
47
|
+
else { // TODO: Add support for ssh
|
|
48
|
+
// User didn't specify a way to save the file. Ask them.
|
|
49
49
|
const { saveChoice } = await inquirer_1.default.prompt({
|
|
50
50
|
name: 'saveChoice',
|
|
51
51
|
type: 'list',
|
|
52
|
-
message: 'Where do you want your
|
|
52
|
+
message: 'Where do you want your packs to be saved (can be changed later)?',
|
|
53
53
|
choices: [{
|
|
54
|
-
name: 'In the root .minecraft
|
|
54
|
+
name: 'In the root client (.minecraft) folder',
|
|
55
55
|
value: 'root',
|
|
56
|
-
short: '
|
|
56
|
+
short: 'Client folder',
|
|
57
57
|
}, {
|
|
58
|
-
name: 'In
|
|
58
|
+
name: 'In a world',
|
|
59
59
|
value: 'world',
|
|
60
|
-
short: 'World
|
|
60
|
+
short: 'World',
|
|
61
61
|
}, {
|
|
62
|
-
name: '
|
|
63
|
-
value: 'path',
|
|
64
|
-
short: '
|
|
62
|
+
name: 'In a server',
|
|
63
|
+
value: 'server-path',
|
|
64
|
+
short: 'Server path',
|
|
65
65
|
}],
|
|
66
66
|
});
|
|
67
67
|
if (saveChoice === 'root') {
|
|
@@ -69,22 +69,25 @@ class Create extends command_1.Command {
|
|
|
69
69
|
}
|
|
70
70
|
else if (saveChoice === 'world') {
|
|
71
71
|
const { world } = await inquirer_1.default.prompt({
|
|
72
|
-
name: '
|
|
73
|
-
message: 'What world do you want to save the
|
|
72
|
+
name: 'World',
|
|
73
|
+
message: 'What world do you want to save the packs in? >',
|
|
74
74
|
type: 'list',
|
|
75
75
|
choices: utils_1.getWorldsList,
|
|
76
76
|
});
|
|
77
77
|
saveOptions.world = world;
|
|
78
78
|
}
|
|
79
|
-
else {
|
|
80
|
-
const {
|
|
81
|
-
name: 'path',
|
|
82
|
-
message: 'Where
|
|
79
|
+
else { // TODO: Add native folder selector
|
|
80
|
+
const { serverPath } = await inquirer_1.default.prompt({
|
|
81
|
+
name: 'Server path',
|
|
82
|
+
message: 'Where is the server to save the packs in? Relative paths are accepted. >',
|
|
83
83
|
type: 'input',
|
|
84
84
|
});
|
|
85
|
-
saveOptions.
|
|
85
|
+
saveOptions.serverPath = serverPath;
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
|
+
if (flags['client-path']) {
|
|
89
|
+
saveOptions.clientPath = flags['client-path'];
|
|
90
|
+
}
|
|
88
91
|
const namespace = await (0, utils_1.getFlagOrPrompt)(flags, 'namespace', {
|
|
89
92
|
message: 'Default namespace (can be changed later) >',
|
|
90
93
|
default: 'default',
|
|
@@ -115,6 +118,7 @@ class Create extends command_1.Command {
|
|
|
115
118
|
(0, child_process_1.execSync)('npm install sandstone', { cwd: projectPath });
|
|
116
119
|
(0, child_process_1.execSync)('npm install --save-dev typescript @types/node sandstone-cli', { cwd: projectPath });
|
|
117
120
|
}
|
|
121
|
+
// TODO: Make profiles for either packs or libraries
|
|
118
122
|
// Merge with the package.json template
|
|
119
123
|
const generatedPackage = JSON.parse(fs_1.default.readFileSync(path_1.default.join(projectPath, 'package.json')).toString());
|
|
120
124
|
/** Remove the `main` property */
|
|
@@ -125,12 +129,16 @@ class Create extends command_1.Command {
|
|
|
125
129
|
const templateFolder = path_1.default.join(__dirname, '../template/');
|
|
126
130
|
await fs_extra_1.default.copy(templateFolder, projectPath);
|
|
127
131
|
// Write the sandstone.json file
|
|
128
|
-
fs_1.default.writeFileSync(path_1.default.join(projectPath, 'sandstone.config.ts'), `import type { SandstoneConfig } from 'sandstone'
|
|
132
|
+
fs_1.default.writeFileSync(path_1.default.join(projectPath, 'sandstone.config.ts'), `import type { DatapackConfig, SandstoneConfig } from 'sandstone'
|
|
129
133
|
|
|
130
134
|
export default {
|
|
131
|
-
name: ${toJson(
|
|
132
|
-
|
|
133
|
-
|
|
135
|
+
name: ${toJson(packName)},
|
|
136
|
+
packs: {
|
|
137
|
+
datapack: {
|
|
138
|
+
description: ${toJson(['A ', { text: 'Sandstone', color: 'gold' }, ' data pack.'])},
|
|
139
|
+
packFormat: ${11},
|
|
140
|
+
} as DatapackConfig
|
|
141
|
+
},
|
|
134
142
|
namespace: ${toJson(namespace)},
|
|
135
143
|
packUid: ${toJson((0, nanoid_1.nanoid)(8))},
|
|
136
144
|
saveOptions: ${toJson(Object.fromEntries(Object.entries(saveOptions).filter(([_, value]) => value !== undefined)))},
|
|
@@ -151,17 +159,18 @@ export default {
|
|
|
151
159
|
exports.default = Create;
|
|
152
160
|
Create.description = 'Create a new Sandstone project.';
|
|
153
161
|
Create.examples = [
|
|
154
|
-
'$ sand create my-
|
|
162
|
+
'$ sand create my-pack',
|
|
155
163
|
];
|
|
156
164
|
Create.flags = {
|
|
157
165
|
help: command_1.flags.help({ char: 'h' }),
|
|
158
166
|
yarn: command_1.flags.boolean({ description: 'Use yarn instead of npm.', env: 'USE_YARN', exclusive: ['npm'] }),
|
|
159
167
|
npm: command_1.flags.boolean({ description: 'Use npm.', env: 'USE_NPM', exclusive: ['yarn'] }),
|
|
160
|
-
'
|
|
168
|
+
'pack-name': command_1.flags.string({ char: 'd', env: 'PACK_NAME', description: 'The name of the data pack.' }),
|
|
161
169
|
namespace: command_1.flags.string({ char: 'n', env: 'NAMESPACE', description: 'The default namespace that will be used.' }),
|
|
162
|
-
'save-root': command_1.flags.boolean({ char: 'r', env: 'SAVE_ROOT', description: 'Save the data pack in the .minecraft/datapacks
|
|
163
|
-
world: command_1.flags.string({ char: 'w', env: 'WORLD', description: 'The world to save the
|
|
164
|
-
'
|
|
170
|
+
'save-root': command_1.flags.boolean({ char: 'r', env: 'SAVE_ROOT', description: 'Save the data pack & resource pack in the .minecraft/datapacks & .minecraft/resource_packs folders. Not compatible with --world.', exclusive: ['world'] }),
|
|
171
|
+
world: command_1.flags.string({ char: 'w', env: 'WORLD', description: 'The world to save the packs in. Not compatible with --save-root or --server', exclusive: ['save-root', 'server'] }),
|
|
172
|
+
'server-path': command_1.flags.string({ char: 's', env: 'SERVER_PATH', description: 'The server path to write the server-side packs at. Not compatible with --world.', exclusive: ['world'] }),
|
|
173
|
+
'client-path': command_1.flags.string({ char: 'c', env: 'CLIENT_PATH', description: 'The client path to write packs at.' }),
|
|
165
174
|
};
|
|
166
175
|
Create.args = [{
|
|
167
176
|
name: 'project-name',
|
package/lib/commands/watch.d.ts
CHANGED
|
@@ -9,8 +9,8 @@ export default class Watch extends Command {
|
|
|
9
9
|
namespace: flags.IOptionFlag<string | undefined>;
|
|
10
10
|
world: flags.IOptionFlag<string | undefined>;
|
|
11
11
|
root: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
clientPath: flags.IOptionFlag<string | undefined>;
|
|
13
|
+
serverPath: flags.IOptionFlag<string | undefined>;
|
|
14
14
|
name: flags.IOptionFlag<string | undefined>;
|
|
15
15
|
description: flags.IOptionFlag<string | undefined>;
|
|
16
16
|
formatVersion: import("@oclif/parser/lib/flags").IOptionFlag<number | undefined>;
|
package/lib/commands/watch.js
CHANGED
|
@@ -15,6 +15,7 @@ class Watch extends command_1.Command {
|
|
|
15
15
|
let alreadyBuilding = false;
|
|
16
16
|
let needRebuild = false;
|
|
17
17
|
let client = null;
|
|
18
|
+
// TODO: add support for clients & resources that require restarts & world resets, sandstone-server should override the involved environment variables if mods are present that fix it
|
|
18
19
|
if (flags.autoReload !== undefined) {
|
|
19
20
|
try {
|
|
20
21
|
client = (await require('minecraft-protocol')).createClient({
|
|
@@ -72,7 +73,7 @@ class Watch extends command_1.Command {
|
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
exports.default = Watch;
|
|
75
|
-
Watch.description = 'Build the
|
|
76
|
+
Watch.description = 'Build the packs, and rebuild them on file change. ⛏';
|
|
76
77
|
Watch.examples = [
|
|
77
78
|
'$ sand watch',
|
|
78
79
|
'$ sand watch --verbose',
|
|
@@ -80,13 +81,14 @@ Watch.examples = [
|
|
|
80
81
|
];
|
|
81
82
|
Watch.flags = {
|
|
82
83
|
help: command_1.flags.help({ char: 'h' }),
|
|
83
|
-
dry: command_1.flags.boolean({ char: 'd', description: 'Do not save the
|
|
84
|
+
dry: command_1.flags.boolean({ char: 'd', description: 'Do not save the pack. Mostly useful with `verbose`.' }),
|
|
84
85
|
verbose: command_1.flags.boolean({ char: 'v', description: 'Log all resulting resources: functions, advancements...' }),
|
|
85
86
|
namespace: command_1.flags.string({ description: 'The default namespace. Override the value specified in the configuration file.' }),
|
|
86
87
|
world: command_1.flags.string({ description: 'The world to save the data pack in. Override the value specified in the configuration file.' }),
|
|
87
|
-
root: command_1.flags.boolean({ description: 'Save the data pack in the
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
root: command_1.flags.boolean({ description: 'Save the data pack & resource pack in the .minecraft/datapacks & .minecraft/resource_packs folders. Override the value specified in the configuration file.' }),
|
|
89
|
+
clientPath: command_1.flags.string({ name: 'client-path', description: 'Path of the client folder. Override the value specified in the configuration file.' }),
|
|
90
|
+
serverPath: command_1.flags.string({ name: 'server-path', description: 'Path of the server folder. Override the value specified in the configuration file.' }),
|
|
91
|
+
// TODO: ssh
|
|
90
92
|
name: command_1.flags.string({ description: 'Name of the data pack. Override the value specified in the configuration file.' }),
|
|
91
93
|
description: command_1.flags.string({ description: 'Description of the data pack. Override the value specified in the configuration file.' }),
|
|
92
94
|
formatVersion: command_1.flags.integer({ name: 'format', description: 'Pack format version. Override the value specified in the configuration file.' }),
|
package/lib/template/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Sandstone project
|
|
2
2
|
|
|
3
|
-
To build the
|
|
3
|
+
To build the packs, run:
|
|
4
4
|
```ts
|
|
5
5
|
npm run build
|
|
6
6
|
// or
|
|
@@ -9,7 +9,7 @@ yarn build
|
|
|
9
9
|
sand build
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
To automatically rebuild the
|
|
12
|
+
To automatically rebuild the packs on each change, run:
|
|
13
13
|
```ts
|
|
14
14
|
npm run watch
|
|
15
15
|
// or
|
package/oclif.manifest.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"0.6.
|
|
1
|
+
{"version":"0.6.2","commands":{"build":{"id":"build","description":"Build the packs. ⛏","pluginName":"sandstone-cli","pluginType":"core","aliases":[],"examples":["$ sand build","$ sand build --verbose","$ sand build --verbose --dry"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"dry":{"name":"dry","type":"boolean","char":"d","description":"Do not save the pack. Mostly useful with `verbose`.","allowNo":false},"verbose":{"name":"verbose","type":"boolean","char":"v","description":"Log all resulting resources: functions, advancements...","allowNo":false},"namespace":{"name":"namespace","type":"option","description":"The default namespace. Override the value specified in the configuration file."},"world":{"name":"world","type":"option","description":"The world to save the data pack in. Override the value specified in the configuration file."},"root":{"name":"root","type":"boolean","description":"Save the data pack & resource pack in the .minecraft/datapacks & .minecraft/resource_packs folders. Override the value specified in the configuration file.","allowNo":false},"clientPath":{"name":"clientPath","type":"option","description":"Path of the client folder. Override the value specified in the configuration file."},"serverPath":{"name":"serverPath","type":"option","description":"Path of the server folder. Override the value specified in the configuration file."},"name":{"name":"name","type":"option","description":"Name of the data pack. Override the value specified in the configuration file."},"description":{"name":"description","type":"option","description":"Description of the data pack. Override the value specified in the configuration file."},"formatVersion":{"name":"formatVersion","type":"option","description":"Pack format version. Override the value specified in the configuration file."},"fullTrace":{"name":"fullTrace","type":"boolean","description":"Show the full stack trace on errors.","allowNo":false},"strictErrors":{"name":"strictErrors","type":"boolean","description":"Stop data pack compilation on type errors.","allowNo":false},"production":{"name":"production","type":"boolean","char":"p","description":"Runs Sandstone in production mode. This sets process.env.SANDSTONE_ENV to \"production\".","allowNo":false},"autoReload":{"name":"autoReload","type":"option","description":"Automatically reload your data pack in-game. Requires to open the world to LAN with cheats enabled, and to specify the port.","helpValue":"port"}},"args":[{"name":"path","description":"Path of the folder containing source files.","required":true,"default":"./src"},{"name":"config-path","description":"Path of the sandstone.config.ts folder.","required":true,"default":"."}]},"create":{"id":"create","description":"Create a new Sandstone project.","pluginName":"sandstone-cli","pluginType":"core","aliases":[],"examples":["$ sand create my-pack"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"yarn":{"name":"yarn","type":"boolean","description":"Use yarn instead of npm.","allowNo":false},"npm":{"name":"npm","type":"boolean","description":"Use npm.","allowNo":false},"pack-name":{"name":"pack-name","type":"option","char":"d","description":"The name of the data pack."},"namespace":{"name":"namespace","type":"option","char":"n","description":"The default namespace that will be used."},"save-root":{"name":"save-root","type":"boolean","char":"r","description":"Save the data pack & resource pack in the .minecraft/datapacks & .minecraft/resource_packs folders. Not compatible with --world.","allowNo":false},"world":{"name":"world","type":"option","char":"w","description":"The world to save the packs in. Not compatible with --save-root or --server"},"server-path":{"name":"server-path","type":"option","char":"s","description":"The server path to write the server-side packs at. Not compatible with --world."},"client-path":{"name":"client-path","type":"option","char":"c","description":"The client path to write packs at."}},"args":[{"name":"project-name","description":"Name of the project folder. This is not the name of the data pack.","required":true}]},"update":{"id":"update","description":"Update Sandstone & Sandstone-CLI.","pluginName":"sandstone-cli","pluginType":"core","aliases":[],"examples":["$ sand update","$ sand update --cli","$ sand update --sandstone","$ sand update --cli --sandstone --skip"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"cli":{"name":"cli","type":"boolean","description":"Update the Sandstone CLI without asking.","allowNo":false},"sandstone":{"name":"sandstone","type":"boolean","description":"Update the current Sandstone version without asking.","allowNo":false},"skip":{"name":"skip","type":"boolean","description":"Skip all interactive prompts and refuse them.","allowNo":false},"yarn":{"name":"yarn","type":"boolean","description":"Use yarn to install the updates.","allowNo":false},"npm":{"name":"npm","type":"boolean","description":"Use npm to install the updates.","allowNo":false}},"args":[]},"watch":{"id":"watch","description":"Build the packs, and rebuild them on file change. ⛏","pluginName":"sandstone-cli","pluginType":"core","aliases":[],"examples":["$ sand watch","$ sand watch --verbose","$ sand watch --verbose --dry"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"dry":{"name":"dry","type":"boolean","char":"d","description":"Do not save the pack. Mostly useful with `verbose`.","allowNo":false},"verbose":{"name":"verbose","type":"boolean","char":"v","description":"Log all resulting resources: functions, advancements...","allowNo":false},"namespace":{"name":"namespace","type":"option","description":"The default namespace. Override the value specified in the configuration file."},"world":{"name":"world","type":"option","description":"The world to save the data pack in. Override the value specified in the configuration file."},"root":{"name":"root","type":"boolean","description":"Save the data pack & resource pack in the .minecraft/datapacks & .minecraft/resource_packs folders. Override the value specified in the configuration file.","allowNo":false},"clientPath":{"name":"clientPath","type":"option","description":"Path of the client folder. Override the value specified in the configuration file."},"serverPath":{"name":"serverPath","type":"option","description":"Path of the server folder. Override the value specified in the configuration file."},"name":{"name":"name","type":"option","description":"Name of the data pack. Override the value specified in the configuration file."},"description":{"name":"description","type":"option","description":"Description of the data pack. Override the value specified in the configuration file."},"formatVersion":{"name":"formatVersion","type":"option","description":"Pack format version. Override the value specified in the configuration file."},"fullTrace":{"name":"fullTrace","type":"boolean","description":"Show the full stack trace on errors.","allowNo":false},"strictErrors":{"name":"strictErrors","type":"boolean","description":"Stop data pack compilation on type errors.","allowNo":false},"production":{"name":"production","type":"boolean","char":"p","description":"Runs Sandstone in production mode. This sets process.env.SANDSTONE_ENV to \"production\".","allowNo":false},"autoReload":{"name":"autoReload","type":"option","description":"Automatically reload your data pack in-game. Requires to open the world to LAN with cheats enabled, and to specify the port.","helpValue":"port"}},"args":[{"name":"path","description":"Path of the folder containing source files.","required":true,"default":"./src"},{"name":"config-path","description":"Path of the sandstone.config.ts folder.","required":true,"default":"."}]}}}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sandstone-cli",
|
|
3
3
|
"description": "The CLI for Sandstone - the data pack creation library.",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.2",
|
|
5
5
|
"contributors": [
|
|
6
6
|
{
|
|
7
7
|
"name": "TheMrZZ - Florian ERNST",
|
|
@@ -22,10 +22,14 @@
|
|
|
22
22
|
"@oclif/config": "^1",
|
|
23
23
|
"@oclif/plugin-help": "^3",
|
|
24
24
|
"@oclif/plugin-warn-if-update-available": "^1.7.0",
|
|
25
|
-
"@types/
|
|
25
|
+
"@types/adm-zip": "^0.5.0",
|
|
26
|
+
"@types/delete-empty": "^3.0.2",
|
|
27
|
+
"@types/node": "^18.14.0",
|
|
26
28
|
"@types/semver": "^7.3.4",
|
|
29
|
+
"adm-zip": "^0.5.10",
|
|
27
30
|
"chalk": "^4.1.0",
|
|
28
31
|
"chokidar": "^3.4.3",
|
|
32
|
+
"delete-empty": "^3.0.0",
|
|
29
33
|
"fs-extra": "^9.0.1",
|
|
30
34
|
"inquirer": "^7.3.3",
|
|
31
35
|
"klaw": "^3.0.0",
|
|
@@ -42,7 +46,7 @@
|
|
|
42
46
|
"@oclif/dev-cli": "^1",
|
|
43
47
|
"@types/fs-extra": "^9.0.4",
|
|
44
48
|
"@types/inquirer": "^7.3.1",
|
|
45
|
-
"@types/klaw": "^3.0.
|
|
49
|
+
"@types/klaw": "^3.0.3",
|
|
46
50
|
"@types/lodash.debounce": "^4.0.6",
|
|
47
51
|
"@types/madge": "^5.0.0",
|
|
48
52
|
"@types/nodemon": "^1.19.0",
|