1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-12-13 18:21:51 +00:00
tobspr_shapez.io/src/js/mods/mod_interface.js

193 lines
6.1 KiB
JavaScript
Raw Normal View History

2022-01-13 20:20:42 +00:00
/* typehints:start */
import { ModLoader } from "./modloader";
import { MetaBuilding } from "../game/meta_building";
2022-01-13 20:20:42 +00:00
/* typehints:end */
import { defaultBuildingVariant } from "../game/meta_building";
2022-01-13 20:20:42 +00:00
import { createLogger } from "../core/logging";
import { AtlasSprite, SpriteAtlasLink } from "../core/sprites";
2022-01-13 20:45:09 +00:00
import { enumShortcodeToSubShape, enumSubShape, enumSubShapeToShortcode } from "../game/shape_definition";
2022-01-13 21:14:49 +00:00
import { Loader } from "../core/loader";
import { LANGUAGES } from "../languages";
import { matchDataRecursive, T } from "../translations";
import { registerBuildingVariant } from "../game/building_codes";
import { gMetaBuildingRegistry } from "../core/global_registries";
2022-01-13 20:20:42 +00:00
const LOG = createLogger("mod-interface");
2022-01-13 20:45:09 +00:00
/**
* @type {Object<string, (distanceToOriginInChunks: number) => number>}
*/
export const MODS_ADDITIONAL_SHAPE_MAP_WEIGHTS = {};
/**
* @typedef {{
* context: CanvasRenderingContext2D,
* quadrantSize: number,
* layerScale: number,
* }} SubShapeDrawOptions
*/
/**
* @type {Object<string, (options: SubShapeDrawOptions) => void>}
*/
export const MODS_ADDITIONAL_SUB_SHAPE_DRAWERS = {};
2022-01-13 20:20:42 +00:00
export class ModInterface {
/**
*
* @param {ModLoader} modLoader
*/
2022-01-13 21:14:49 +00:00
constructor(modLoader) {
2022-01-13 20:20:42 +00:00
this.modLoader = modLoader;
2022-01-13 21:14:49 +00:00
/** @type {Map<string, AtlasSprite>} */
this.lazySprites = new Map();
2022-01-13 20:20:42 +00:00
}
registerCss(cssString) {
const element = document.createElement("style");
element.textContent = cssString;
document.head.appendChild(element);
}
registerSprite(spriteId, base64string) {
assert(base64string.startsWith("data:image"));
const img = new Image();
img.src = base64string;
const sprite = new AtlasSprite(spriteId);
const link = new SpriteAtlasLink({
w: img.width,
h: img.height,
atlas: img,
packOffsetX: 0,
packOffsetY: 0,
packedW: img.width,
packedH: img.height,
packedX: 0,
packedY: 0,
});
sprite.linksByResolution["0.25"] = link;
sprite.linksByResolution["0.5"] = link;
sprite.linksByResolution["0.75"] = link;
2022-01-13 21:14:49 +00:00
this.lazySprites.set(spriteId, sprite);
}
injectSprites() {
LOG.log("inject sprites");
this.lazySprites.forEach((sprite, key) => {
Loader.sprites.set(key, sprite);
console.log("override", key);
});
2022-01-13 20:20:42 +00:00
}
2022-01-13 20:45:09 +00:00
/**
*
* @param {object} param0
* @param {string} param0.id
* @param {string} param0.shortCode
* @param {(distanceToOriginInChunks: number) => number} param0.weightComputation
2022-01-13 22:16:24 +00:00
* @param {(options: SubShapeDrawOptions) => void} param0.draw
2022-01-13 20:45:09 +00:00
*/
2022-01-13 22:16:24 +00:00
registerSubShapeType({ id, shortCode, weightComputation, draw }) {
2022-01-13 20:45:09 +00:00
if (shortCode.length !== 1) {
throw new Error("Bad short code: " + shortCode);
}
enumSubShape[id] = id;
enumSubShapeToShortcode[id] = shortCode;
enumShortcodeToSubShape[shortCode] = id;
MODS_ADDITIONAL_SHAPE_MAP_WEIGHTS[id] = weightComputation;
2022-01-13 22:16:24 +00:00
MODS_ADDITIONAL_SUB_SHAPE_DRAWERS[id] = draw;
2022-01-13 20:45:09 +00:00
}
registerTranslations(language, translations) {
const data = LANGUAGES[language];
if (!data) {
throw new Error("Unknown language: " + language);
}
matchDataRecursive(data.data, translations, true);
if (language === "en") {
matchDataRecursive(T, translations, true);
}
}
/**
*
* @param {object} param0
* @param {typeof MetaBuilding} param0.metaClass
* @param {string=} param0.buildingIconBase64
* @param {({
* variant?: string;
* rotationVariant?: number;
* name: string;
* description: string;
* blueprintImageBase64?: string;
* regularImageBase64?: string;
* tutorialImageBase64?: string;
* }[])} param0.variantsAndRotations
*/
registerNewBuilding({ metaClass, variantsAndRotations, buildingIconBase64 }) {
const id = new /** @type {new () => MetaBuilding} */ (metaClass)().getId();
if (gMetaBuildingRegistry.hasId(id)) {
throw new Error("Tried to register building twice: " + id);
}
gMetaBuildingRegistry.register(metaClass);
T.buildings[id] = {};
variantsAndRotations.forEach(payload => {
const actualVariant = payload.variant || defaultBuildingVariant;
registerBuildingVariant(id, metaClass, actualVariant, payload.rotationVariant || 0);
T.buildings[id][actualVariant] = {
name: payload.name,
description: payload.description,
};
const buildingIdentifier =
id + (actualVariant === defaultBuildingVariant ? "" : "-" + actualVariant);
if (payload.regularImageBase64) {
this.registerSprite(
"sprites/buildings/" + buildingIdentifier + ".png",
payload.regularImageBase64
);
}
if (payload.blueprintImageBase64) {
this.registerSprite(
"sprites/blueprints/" + buildingIdentifier + ".png",
payload.blueprintImageBase64
);
}
if (payload.tutorialImageBase64) {
this.setBuildingTutorialImage(id, actualVariant, payload.tutorialImageBase64);
}
});
if (buildingIconBase64) {
this.setBuildingToolbarIcon(id, buildingIconBase64);
}
}
setBuildingToolbarIcon(buildingId, iconBase64) {
this.registerCss(`
[data-icon="building_icons/${buildingId}.png"] .icon {
background-image: url('${iconBase64}') !important;
}
`);
}
setBuildingTutorialImage(buildingId, variant, imageBase64) {
const buildingIdentifier = buildingId + (variant === defaultBuildingVariant ? "" : "-" + variant);
this.registerCss(`
[data-icon="building_tutorials/${buildingIdentifier}.png"] {
background-image: url('${imageBase64}') !important;
}
`);
}
2022-01-13 20:20:42 +00:00
}