Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
211 changes: 136 additions & 75 deletions server/src/assets.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CompletionItemKind, CompletionItem } from "vscode-languageserver/node";
import { CompletionItemKind, CompletionItem, InsertTextMode } from "vscode-languageserver/node";
import * as fs from "fs";
import * as log from "./log";
import { CompletionVisitor } from "./completions";
Expand All @@ -16,7 +16,14 @@ export async function resetAssetIndex(): Promise<void> {
ASSET_INDEX = await AssetIndex.new();
}

class Asset {
abstract class AssetInterface {
abstract id: string;
abstract location: string;
}

type AssetInterfaceConstructor<T extends AssetInterface> = new (id: string, location: string) => T;

class Asset implements AssetInterface {
id: string;
location: string;

Expand All @@ -27,35 +34,50 @@ class Asset {
async visit(_provider: CompletionVisitor): Promise<void> {
throw new Error("Method 'visit' must be implemented.");
}
static getCompletions(): CompletionItem[] {
throw new Error("Method 'getCompletions' must be implemented.");
static all(): Asset[] {
throw new Error("Static method 'all' must be implemented.");
}
static getCompletions(_condition: (asset: Asset) => boolean = () => true): CompletionItem[] {
throw new Error("Static method 'getCompletions' must be implemented.");
}
}
export class Block extends Asset {
async visit(provider: CompletionVisitor): Promise<void> {
await provider.onBlock(this);
}
static getCompletions(): CompletionItem[] {
static all(): Block[] {
return ASSET_INDEX?.blocks ?? [];
}
static getCompletions(condition: (asset: Block) => boolean = () => true): CompletionItem[] {
const completions: CompletionItem[] = [];
ASSET_INDEX?.blocks.forEach((element) => {
completions.push({
label: element.id,
kind: CompletionItemKind.Field,
data: completions.length,
});
if (condition(element))
completions.push({
label: element.id,
kind: CompletionItemKind.Class,
data: completions.length,
detail: "block",
});
});
return completions;
}
}
export class BlockTexture extends Asset {
static getCompletions(): CompletionItem[] {
static all(): BlockTexture[] {
return ASSET_INDEX?.blockTextures ?? [];
}
static getCompletions(
condition: (asset: BlockTexture) => boolean = () => true,
): CompletionItem[] {
const completions: CompletionItem[] = [];
ASSET_INDEX?.blockTextures.forEach((element) => {
completions.push({
label: element.id,
kind: CompletionItemKind.File,
data: completions.length,
});
if (condition(element))
completions.push({
label: element.id,
kind: CompletionItemKind.Struct,
data: completions.length,
detail: "block texture",
});
});
return completions;
}
Expand All @@ -64,27 +86,41 @@ export class Item extends Asset {
async visit(provider: CompletionVisitor): Promise<void> {
await provider.onItem(this);
}
static getCompletions(): CompletionItem[] {
static all(): Item[] {
return ASSET_INDEX?.items ?? [];
}
static getCompletions(condition: (asset: Item) => boolean = () => true): CompletionItem[] {
const completions: CompletionItem[] = [];
ASSET_INDEX?.items.forEach((element) => {
completions.push({
label: element.id,
kind: CompletionItemKind.Function,
data: completions.length,
});
if (condition(element))
completions.push({
label: element.id,
kind: CompletionItemKind.Class,
data: completions.length,
detail: "item",
});
});
return completions;
}
}
export class ItemTexture extends Asset {
static getCompletions(): CompletionItem[] {
static all(): ItemTexture[] {
return ASSET_INDEX?.itemTextures ?? [];
}
static getCompletions(
condition: (asset: ItemTexture) => boolean = () => true,
): CompletionItem[] {
const completions: CompletionItem[] = [];
ASSET_INDEX?.itemTextures.forEach((element) => {
completions.push({
label: element.id,
kind: CompletionItemKind.File,
data: completions.length,
});
if (condition(element))
completions.push({
label: element.id,
insertText: '"' + element.id + '"',
insertTextMode: InsertTextMode.asIs,
kind: CompletionItemKind.Struct,
data: completions.length,
detail: "item texture",
});
});
return completions;
}
Expand All @@ -93,14 +129,19 @@ export class Tool extends Asset {
async visit(provider: CompletionVisitor): Promise<void> {
await provider.onTool(this);
}
static getCompletions(): CompletionItem[] {
static all(): Tool[] {
return ASSET_INDEX?.tools ?? [];
}
static getCompletions(condition: (asset: Tool) => boolean = () => true): CompletionItem[] {
const completions: CompletionItem[] = [];
ASSET_INDEX?.tools.forEach((element) => {
completions.push({
label: element.id,
kind: CompletionItemKind.Method,
data: completions.length,
});
if (condition(element))
completions.push({
label: element.id,
kind: CompletionItemKind.Class,
data: completions.length,
detail: "tool",
});
});
return completions;
}
Expand All @@ -109,27 +150,37 @@ export class Biome extends Asset {
async visit(provider: CompletionVisitor): Promise<void> {
await provider.onBiome(this);
}
static getCompletions(): CompletionItem[] {
static all(): Biome[] {
return ASSET_INDEX?.biomes ?? [];
}
static getCompletions(condition: (asset: Biome) => boolean = () => true): CompletionItem[] {
const completions: CompletionItem[] = [];
ASSET_INDEX?.biomes.forEach((element) => {
completions.push({
label: element.id,
kind: CompletionItemKind.Interface,
data: completions.length,
});
if (condition(element))
completions.push({
label: element.id,
kind: CompletionItemKind.Class,
data: completions.length,
detail: "biome",
});
});
return completions;
}
}
export class Model extends Asset {
static getCompletions(): CompletionItem[] {
static all(): Model[] {
return ASSET_INDEX?.models ?? [];
}
static getCompletions(condition: (asset: Model) => boolean = () => true): CompletionItem[] {
const completions: CompletionItem[] = [];
ASSET_INDEX?.models.forEach((element) => {
completions.push({
label: element.id,
kind: CompletionItemKind.Module,
data: completions.length,
});
if (condition(element))
completions.push({
label: element.id,
kind: CompletionItemKind.Module,
data: completions.length,
detail: "model",
});
});
return completions;
}
Expand All @@ -138,27 +189,37 @@ export class SBB extends Asset {
async visit(provider: CompletionVisitor): Promise<void> {
await provider.onSBB(this);
}
static getCompletions(): CompletionItem[] {
static all(): SBB[] {
return ASSET_INDEX?.structureBuildingBlocks ?? [];
}
static getCompletions(condition: (asset: SBB) => boolean = () => true): CompletionItem[] {
const completions: CompletionItem[] = [];
ASSET_INDEX?.structureBuildingBlocks.forEach((element) => {
completions.push({
label: element.id,
kind: CompletionItemKind.Class,
data: completions.length,
});
if (condition(element))
completions.push({
label: element.id,
kind: CompletionItemKind.Class,
data: completions.length,
detail: "SBB",
});
});
return completions;
}
}
export class Blueprint extends Asset {
static getCompletions(): CompletionItem[] {
static all(): Blueprint[] {
return ASSET_INDEX?.blueprints ?? [];
}
static getCompletions(condition: (asset: Blueprint) => boolean = () => true): CompletionItem[] {
const completions: CompletionItem[] = [];
ASSET_INDEX?.blueprints.forEach((element) => {
completions.push({
label: element.id,
kind: CompletionItemKind.File,
data: completions.length,
});
if (condition(element))
completions.push({
label: element.id,
kind: CompletionItemKind.Module,
data: completions.length,
detail: "blueprint",
});
});
return completions;
}
Expand Down Expand Up @@ -190,73 +251,73 @@ export class AssetIndex {
index.blocks,
"blocks",
addon.name,
".zig.zon"
".zig.zon",
);
await AssetIndex.registerAsset<BlockTexture>(
BlockTexture,
index.blockTextures,
"blocks/textures",
addon.name,
".png"
".png",
);
await AssetIndex.registerAsset<Item>(
Item,
index.items,
"items",
addon.name,
".zig.zon"
".zig.zon",
);
await AssetIndex.registerTextures<ItemTexture>(
ItemTexture,
index.itemTextures,
"items/textures",
addon.name
addon.name,
);
await AssetIndex.registerAsset<Tool>(
Tool,
index.tools,
"tools",
addon.name,
".zig.zon"
".zig.zon",
);
await AssetIndex.registerAsset<Biome>(
Biome,
index.biomes,
"biomes",
addon.name,
".zig.zon"
".zig.zon",
);
await AssetIndex.registerAsset<Model>(
Model,
index.models,
"models",
addon.name,
".obj"
".obj",
);
await AssetIndex.registerAsset<SBB>(
SBB,
index.structureBuildingBlocks,
"sbb",
addon.name,
".zig.zon"
".zig.zon",
);
await AssetIndex.registerAsset<Blueprint>(
Blueprint,
index.blueprints,
"sbb",
addon.name,
".blp"
".blp",
);
}
return index;
}

static async registerAsset<AssetT>(
cls: new (id: string, location: string) => AssetT,
storage: AssetT[],
static async registerAsset<T extends Asset>(
cls: AssetInterfaceConstructor<T>,
storage: T[],
scope: string,
addon: string,
extension: string
extension: string,
) {
const basePath = `assets/${addon}/${scope}/`;
if (!fs.existsSync(basePath) || !fs.statSync(basePath).isDirectory()) return;
Expand Down Expand Up @@ -284,11 +345,11 @@ export class AssetIndex {
log.log(`Registered ${scope} asset: '${id}' at ${location}`);
}
}
static async registerTextures<AssetT>(
cls: new (id: string, location: string) => AssetT,
storage: AssetT[],
static async registerTextures<T extends Asset>(
cls: AssetInterfaceConstructor<T>,
storage: T[],
scope: string,
addon: string
addon: string,
) {
const basePath = `assets/${addon}/${scope}/`;
if (!fs.existsSync(basePath) || !fs.statSync(basePath).isDirectory()) return;
Expand Down
Loading