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

Initial support for adding new buildings

This commit is contained in:
tobspr 2022-01-14 07:05:46 +01:00
parent 8777e4c6ea
commit 01b9bf561c
7 changed files with 165 additions and 20 deletions

View File

@ -1,6 +1,7 @@
import { globalConfig } from "../../core/config";
import { DrawParameters } from "../../core/draw_parameters";
import { Signal } from "../../core/signal";
import { MODS } from "../../mods/modloader";
import { KEYMAPPINGS } from "../key_action_mapper";
import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root";
@ -91,6 +92,7 @@ export class GameHUD {
const frag = document.createDocumentFragment();
for (const key in this.parts) {
MODS.signals.hudElementInitialized.dispatch(this.parts[key]);
this.parts[key].createElements(frag);
}
@ -98,6 +100,7 @@ export class GameHUD {
for (const key in this.parts) {
this.parts[key].initialize();
MODS.signals.hudElementFinalized.dispatch(this.parts[key]);
}
this.root.keyMapper.getBinding(KEYMAPPINGS.ingame.toggleHud).add(this.toggleUi, this);

View File

@ -1,4 +1,5 @@
import { gMetaBuildingRegistry } from "../../../core/global_registries";
import { globalWarn } from "../../../core/logging";
import { STOP_PROPAGATION } from "../../../core/signal";
import { makeDiv, safeModulo } from "../../../core/utils";
import { MetaBlockBuilding } from "../../buildings/block";
@ -101,7 +102,12 @@ export class HUDBaseToolbar extends BaseHUDPart {
rawBinding = KEYMAPPINGS.buildings[metaBuilding.getId()];
}
const binding = actionMapper.getBinding(rawBinding);
if (rawBinding) {
const binding = actionMapper.getBinding(rawBinding);
binding.add(() => this.selectBuildingForPlacement(metaBuilding));
} else {
globalWarn("Building has no keybinding:", metaBuilding.getId());
}
const itemContainer = makeDiv(
this.primaryBuildings.includes(allBuildings[i]) ? rowPrimary : rowSecondary,
@ -110,7 +116,6 @@ export class HUDBaseToolbar extends BaseHUDPart {
);
itemContainer.setAttribute("data-icon", "building_icons/" + metaBuilding.getId() + ".png");
itemContainer.setAttribute("data-id", metaBuilding.getId());
binding.add(() => this.selectBuildingForPlacement(metaBuilding));
const icon = makeDiv(itemContainer, null, ["icon"]);

View File

@ -126,12 +126,15 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic {
rawBinding = KEYMAPPINGS.buildings[metaBuilding.getId()];
}
const binding = this.root.keyMapper.getBinding(rawBinding);
this.buildingInfoElements.hotkey.innerHTML = T.ingame.buildingPlacement.hotkeyLabel.replace(
"<key>",
"<code class='keybinding'>" + binding.getKeyCodeString() + "</code>"
);
if (rawBinding) {
const binding = this.root.keyMapper.getBinding(rawBinding);
this.buildingInfoElements.hotkey.innerHTML = T.ingame.buildingPlacement.hotkeyLabel.replace(
"<key>",
"<code class='keybinding'>" + binding.getKeyCodeString() + "</code>"
);
} else {
this.buildingInfoElements.hotkey.innerHTML = "";
}
this.buildingInfoElements.tutorialImage.setAttribute(
"data-icon",

View File

@ -205,18 +205,15 @@ export function initMetaBuildingRegistry() {
const id = metaBuilding.getId();
if (!["hub"].includes(id)) {
if (!KEYMAPPINGS.buildings[id]) {
assertAlways(
false,
console.error(
"Building " + id + " has no keybinding assigned! Add it to key_action_mapper.js"
);
}
if (!T.buildings[id]) {
assertAlways(false, "Translation for building " + id + " missing!");
}
if (!T.buildings[id].default) {
assertAlways(false, "Translation for building " + id + " missing (default variant)!");
console.error("Translation for building " + id + " missing!");
} else if (!T.buildings[id].default) {
console.error("Translation for building " + id + " missing (default variant)!");
}
}
});

File diff suppressed because one or more lines are too long

View File

@ -1,14 +1,17 @@
/* typehints:start */
import { Application } from "../application";
import { ModLoader } from "./modloader";
import { MetaBuilding } from "../game/meta_building";
/* typehints:end */
import { defaultBuildingVariant } from "../game/meta_building";
import { createLogger } from "../core/logging";
import { AtlasSprite, SpriteAtlasLink } from "../core/sprites";
import { enumShortcodeToSubShape, enumSubShape, enumSubShapeToShortcode } from "../game/shape_definition";
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";
const LOG = createLogger("mod-interface");
@ -113,4 +116,77 @@ export class ModInterface {
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;
}
`);
}
}

View File

@ -3,6 +3,7 @@ import { Signal } from "../core/signal";
import { DemoMod } from "./demo_mod";
import { Mod } from "./mod";
import { ModInterface } from "./mod_interface";
import { BaseHUDPart } from "../game/hud/base_hud_part";
const LOG = createLogger("mods");
@ -25,6 +26,9 @@ export class ModLoader {
injectSprites: new Signal(),
preprocessTheme: /** @type {TypedSignal<[Object]>} */ (new Signal()),
modifyLevelDefinitions: /** @type {TypedSignal<[Array[Object]]>} */ (new Signal()),
hudElementInitialized: /** @type {TypedSignal<[BaseHUDPart]>} */ (new Signal()),
hudElementFinalized: /** @type {TypedSignal<[BaseHUDPart]>} */ (new Signal()),
};
this.registerMod(DemoMod);