Skip to content

Commit

Permalink
物编修改器
Browse files Browse the repository at this point in the history
  • Loading branch information
sumneko committed Jul 11, 2024
1 parent a5a1b4b commit b5f4db4
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 33 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"out",
"dist",
"3rd",
"**/*.d.ts"
"**/*.d.ts",
"template"
]
}
36 changes: 21 additions & 15 deletions src/editorTable/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@ function makeSandbox() {
};
}

export async function runEditor(uri: vscode.Uri) {
export async function runEditor(uri: vscode.Uri, funcName: string = 'main') {
y3.log.show();
try {
const file = await y3.fs.readFile(uri);
let content = file!.string;
content = content + '\n\nmodule.exports = main';
content = content + `\n\nmodule.exports = ${funcName}`;
let script = new vm.Script(content, {
filename: uri.path,
});
let main = script.runInNewContext(vm.createContext(makeSandbox()));
if (typeof main !== 'function') {
throw new Error('没有导出 main 函数');
let func = script.runInNewContext(vm.createContext(makeSandbox()));
if (typeof func !== 'function') {
throw new Error('没有找到要执行的函数');
}
await main();
await func();
y3.log.info(`执行 "${uri.path.split('/').pop()}" 成功!`);
} catch (error) {
vscode.window.showErrorMessage(`运行物编脚本出错:${error}`);
Expand All @@ -43,13 +43,19 @@ export async function runEditor(uri: vscode.Uri) {

class RunButtonProvider implements vscode.CodeLensProvider {
public provideCodeLenses(document: vscode.TextDocument): vscode.CodeLens[] | undefined {
return [
new vscode.CodeLens(new vscode.Range(0, 0, 0, 0), {
title: '$(debug-start)运行',
command: 'y3-helper.runObjectEditor',
arguments: [document.uri],
}),
];
let codeLens: vscode.CodeLens[] = [];
for (let i = 0; i < document.lineCount; i++) {
const line = document.lineAt(i);
const name = line.text.match(/^async\s+function\s+([\w_]+)/)?.[1];
if (name) {
codeLens.push(new vscode.CodeLens(new vscode.Range(i, 0, i, 0), {
title: `$(debug-start)运行 ${name} 函数`,
command: 'y3-helper.runObjectEditor',
arguments: [document.uri, name],
}));
}
}
return codeLens;
}
}

Expand Down Expand Up @@ -79,14 +85,14 @@ export function init() {
}
});

vscode.commands.registerCommand('y3-helper.runObjectEditor', async (uri?: vscode.Uri) => {
vscode.commands.registerCommand('y3-helper.runObjectEditor', async (uri?: vscode.Uri, funcName?: string) => {
if (!uri) {
uri = vscode.window.activeTextEditor?.document.uri;
if (!uri) {
return;
}
}
await runEditor(uri);
await runEditor(uri, funcName);
});

vscode.languages.registerCodeLensProvider({
Expand Down
35 changes: 28 additions & 7 deletions src/editorTable/editorTable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,15 @@ export class EditorObject<N extends Table.NameCN> {
private _name?: string;
public text?: string;
public uri?: vscode.Uri;
constructor(public tableName: Table.NameCN, public key: number) {}
constructor(public tableName: N, public key: number) {}

toString() {
return `{物编对象|${this.name}|${this.tableName}-${this.key}}`;
}

/**
* 获取对象的json数据语法树
*/
public get json(): y3.json.Json | undefined {
if (this._json === undefined) {
if (!this.text) {
Expand All @@ -100,6 +103,9 @@ export class EditorObject<N extends Table.NameCN> {
return this._json;
}

/**
* 获取对象的物编数据
*/
private _data?: EditorData<N>;
public get data(): EditorData<N> {
if (this._data === undefined) {
Expand Down Expand Up @@ -227,6 +233,9 @@ export class EditorObject<N extends Table.NameCN> {
return res;
}

/**
* 获取对象的名称
*/
public get name(): string {
if (!this._name) {
let name = this.text?.match(/"name"\s*:\s*(\-?\d*)/);
Expand Down Expand Up @@ -313,7 +322,7 @@ export class EditorObject<N extends Table.NameCN> {
}
}

async function loadObject(tableName: Table.NameCN, key: number) {
async function loadObject<N extends Table.NameCN>(tableName: N, key: number) {
let table = openTable(tableName);
let uri = table.getUri(key);
let file = await y3.fs.readFile(uri);
Expand Down Expand Up @@ -377,7 +386,7 @@ export class EditorTable<N extends Table.NameCN> extends vscode.Disposable {
*/
public async get(key: number): Promise<EditorObject<N> | undefined> {
if (this._objectCache[key] === undefined) {
this._objectCache[key] = await loadObject(this.name, key);
this._objectCache[key] = await loadObject<N>(this.name, key);
}
return this._objectCache[key] ?? undefined;
}
Expand Down Expand Up @@ -454,10 +463,18 @@ export class EditorTable<N extends Table.NameCN> extends vscode.Disposable {
* 生成一个可用的新key
* @returns
*/
public async makeNewKey() {
public async makeNewKey(copyKey?: number) {
let list = await this.getList();
let max = list[list.length - 1];
return max ? max + 1 : 100001;
if (copyKey) {
let i = copyKey + 1;
while (list.includes(i)) {
i++;
}
return i;
} else {
let max = list[list.length - 1];
return max ? max + 1 : 100001;
}
}

/**
Expand All @@ -467,14 +484,18 @@ export class EditorTable<N extends Table.NameCN> extends vscode.Disposable {
*/
public async create(options?: CreateOptions<N>): Promise<EditorObject<N> | undefined>{
let name = options?.name ?? `新建${this.name}`;

let key: number;
if (options?.key) {
key = options.key;
if (!await this.canUseKey(key, options?.overwrite)) {
return undefined;
}
} else {
key = await this.makeNewKey();
let copyKey = options?.copyFrom instanceof EditorObject
? options.copyFrom.key
: options?.copyFrom;
key = await this.makeNewKey(copyKey);
}

let templateJson: string;
Expand Down
26 changes: 25 additions & 1 deletion src/y3-helper.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as vscode from 'vscode';
import { fs } from './tools';
import { fs, log } from './tools';

export * as excel from './editorTable/EXCEL';
export * as table from './editorTable/editorTable';
Expand All @@ -9,6 +9,10 @@ export * as const from './constants';
export { env } from './env';
export let helper: vscode.ExtensionContext;

/**
* 拼接路径为 Uri
* @returns
*/
export function uri(base: vscode.Uri | string, ...paths: string[]): vscode.Uri {
if (typeof base === 'string') {
if (fs.isAbsolutePath(base)) {
Expand All @@ -20,6 +24,10 @@ export function uri(base: vscode.Uri | string, ...paths: string[]): vscode.Uri {
return vscode.Uri.joinPath(base, ...paths);
}

/**
* 获取《Y3开发助手》插件的相对路径
* @returns
*/
export function extensionPath(...paths: string[]): vscode.Uri {
return vscode.Uri.joinPath(helper.extensionUri, ...paths);
}
Expand All @@ -28,6 +36,22 @@ export function setContext(ctx: vscode.ExtensionContext) {
helper = ctx;
}

/**
* 打印内容,也会打印到日志窗口中
* @param args 要打印的内容
*/
export function print(...args: any[]) {
vscode.window.showInformationMessage(args.join(' '));
log.info(args.join(' '));
}

/**
* 在VSCode中打开文件
* @param uri 文件路径
*/
export function open(uri: vscode.Uri | string) {
if (typeof uri === 'string') {
uri = vscode.Uri.parse(uri);
}
vscode.commands.executeCommand('vscode.open', uri);
}
31 changes: 31 additions & 0 deletions template/object/1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
let y3 = require('y3-helper')

// 定义一个函数,然后点击运行函数按钮即可执行
async function example() {
//1. 先来创建一个新的单位
let unitTable = y3.table.openTable('单位') // 打开单位表

// 创建单位需要一些时间(往硬盘写入文件),因此需要加上 await
let unit1 = await unitTable.create({
name: '演示单位1', // 起个名字
key: 11037, // 这个单位的key,如果不填,会自动生成一个可用的key
overwrite: true, // 如果指定了key,是否允许覆盖已有的单位;否则可能会创建失败
})

y3.print('演示单位1创建完成', unit1)

//2. 复制一个已有的单位
let unit2 = await unitTable.create({
copyFrom: unit1, // 要复制的单位,也可以用数字key
name: '演示单位2',
key: 11038,
overwrite: true,
})

y3.print('演示单位2创建完成', unit2)

//3. 修改单位的数据
unit2.data.ori_speed = 5 // 修改移动速度

y3.print('移动速度修改完成')
}
78 changes: 69 additions & 9 deletions template/object/y3-helper.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,25 @@ declare module 'y3-helper/editorTable/editorTable' {
}
type EditorData<N extends Table.NameCN> = N extends '单位' ? UnitData : N extends '声音' ? SoundData : N extends '技能' ? AbilityData : N extends '装饰物' ? DecorationData : N extends '可破坏物' ? DestructibleData : N extends '物品' ? ItemData : N extends '魔法效果' ? ModifierData : N extends '投射物' ? ProjectileData : N extends '科技' ? TechData : never;
export class EditorObject<N extends Table.NameCN> {
tableName: Table.NameCN;
tableName: N;
key: number;
text?: string;
uri?: vscode.Uri;
constructor(tableName: Table.NameCN, key: number);
constructor(tableName: N, key: number);
toString(): string;
/**
* 获取对象的json数据语法树
*/
get json(): y3.json.Json | undefined;
get data(): EditorData<N>;
/**
* 获取对象的名称
*/
get name(): string;
getFieldInfo(field: string): y3.table.FieldInfo | undefined;
listFields(): string[];
}
interface CreateOptions {
interface CreateOptions<N extends Table.NameCN> {
/**
* 新对象的名称,如果不填则使用默认名称
*/
Expand All @@ -73,14 +80,14 @@ declare module 'y3-helper/editorTable/editorTable' {
/**
* 从哪个对象复制,如果不填则从模板复制为空对象
*/
copyFrom?: number;
copyFrom?: number | EditorObject<N>;
/**
* 如果目标key已存在,是否覆盖
*/
overwrite?: boolean;
}
export class EditorTable<N extends Table.NameCN> extends vscode.Disposable {
nameCN: N;
name: N;
uri: vscode.Uri;
nameEN: {
readonly 单位: "unit";
Expand All @@ -93,23 +100,76 @@ declare module 'y3-helper/editorTable/editorTable' {
readonly 可破坏物: "destructible";
readonly 声音: "sound";
}[N];
constructor(nameCN: N);
constructor(name: N);
toString(): string;
/**
* 获取具体的对象
* @param key 对象的key(一串数字)
* @returns 对象
*/
get(key: number): Promise<EditorObject<N> | undefined>;
fetch(key: number): EditorObject<N> | undefined;
/**
* 获取这个类型下的所有对象的key
* @returns 这个类型下的所有对象的key
*/
getList(): Promise<number[]>;
fetchList(): number[] | undefined;
/**
* 删除一个对象
* @param key 对象的key
*/
delete(key: number): Promise<void>;
/**
* 检查一个key是否可以使用
* @param key 要检查的key
* @param overwirte 是否允许覆盖已有的key,默认不允许
* @returns
*/
canUseKey(key: number, overwirte?: boolean): Promise<boolean>;
makeNewKey(): Promise<number>;
create(options?: CreateOptions): Promise<EditorObject<N> | undefined>;
/**
* 生成一个可用的新key
* @returns
*/
makeNewKey(copyKey?: number): Promise<number>;
/**
* 创建一个对象
* @param options 创建的参数
* @returns
*/
create(options?: CreateOptions<N>): Promise<EditorObject<N> | undefined>;
/**
* 获取对象在硬盘中的文件路径
* @param key 对象的key
* @returns 对象的路径
*/
getUri(key: number): vscode.Uri;
getFieldInfo(field: string): FieldInfo | undefined;
listFields(): string[];
onDidChange(callback: () => void): vscode.Disposable;
}
/**
* 打开物编表
* @param tableName 哪种表
* @returns 表对象
*/
export function openTable<N extends Table.NameCN>(tableName: N): EditorTable<N>;
/**
* 根据文件名获取文件对应的key
* @param fileName 文件名
* @returns 文件名对应的key
*/
export function getFileKey(fileName: string): number | undefined;
export function getObject(uri: vscode.Uri): Promise<EditorObject<Table.NameCN> | undefined>;
/**
* 根据文件路径获取对象
* @param uri 文件路径
* @returns 对象
*/
export function getObject(uri: vscode.Uri | string): Promise<EditorObject<Table.NameCN> | undefined>;
/**
* 获取所有的对象(速度比较慢)
* @returns 所有对象
*/
export function getAllObjects(): Promise<y3.table.EditorObject<"单位" | "装饰物" | "物品" | "技能" | "魔法效果" | "投射物" | "科技" | "可破坏物" | "声音">[]>;
export function init(): void;
export {};
Expand Down

0 comments on commit b5f4db4

Please sign in to comment.