1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2026-03-02 03:39:21 +00:00

Add constant signal emitters

This commit is contained in:
tobspr
2020-08-12 21:05:32 +02:00
parent c7b3cc1675
commit f4ac6dfe03
31 changed files with 1095 additions and 773 deletions

View File

@@ -5,11 +5,7 @@ import { BasicSerializableObject } from "../savegame/serialization";
export const enumItemType = {
shape: "shape",
color: "color",
positiveEnergy: "positiveEnergy",
negativeEnergy: "negativeEnergy",
// Can be used for filters
genericEnergy: "genericEnergy",
boolean: "boolean",
};
/**

View File

@@ -0,0 +1,51 @@
import { enumDirection, Vector } from "../../core/vector";
import { enumPinSlotType, WiredPinsComponent } from "../components/wired_pins";
import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building";
import { enumLayer, GameRoot } from "../root";
import { ConstantSignalComponent } from "../components/constant_signal";
export class MetaConstantSignalBuilding extends MetaBuilding {
constructor() {
super("constant_signal");
}
getSilhouetteColor() {
return "#2bafda";
}
/**
* @param {GameRoot} root
*/
getIsUnlocked(root) {
// @todo
return G_IS_DEV;
}
getLayer() {
return enumLayer.wires;
}
getDimensions() {
return new Vector(1, 1);
}
/**
* Creates the entity at the given location
* @param {Entity} entity
*/
setupEntityComponents(entity) {
entity.addComponent(
new WiredPinsComponent({
slots: [
{
pos: new Vector(0, 0),
direction: enumDirection.top,
type: enumPinSlotType.logicalEjector,
},
],
})
);
entity.addComponent(new ConstantSignalComponent({}));
}
}

View File

@@ -11,6 +11,7 @@ import { StorageComponent } from "./components/storage";
import { WiredPinsComponent } from "./components/wired_pins";
import { BeltUnderlaysComponent } from "./components/belt_underlays";
import { WireComponent } from "./components/wire";
import { ConstantSignalComponent } from "./components/constant_signal";
export function initComponentRegistry() {
gComponentRegistry.register(StaticMapEntityComponent);
@@ -25,6 +26,7 @@ export function initComponentRegistry() {
gComponentRegistry.register(WiredPinsComponent);
gComponentRegistry.register(BeltUnderlaysComponent);
gComponentRegistry.register(WireComponent);
gComponentRegistry.register(ConstantSignalComponent);
// IMPORTANT ^^^^^ UPDATE ENTITY COMPONENT STORAGE AFTERWARDS

View File

@@ -0,0 +1,30 @@
import { gItemRegistry } from "../../core/global_registries";
import { types } from "../../savegame/serialization";
import { Component } from "../component";
import { BaseItem } from "../base_item";
export class ConstantSignalComponent extends Component {
static getId() {
return "ConstantSignal";
}
static getSchema() {
return {
signal: types.nullable(types.obj(gItemRegistry)),
};
}
duplicateWithoutContents() {
return new ConstantSignalComponent({ signal: this.signal });
}
/**
*
* @param {object} param0
* @param {BaseItem=} param0.signal The signal to store
*/
constructor({ signal = null }) {
super();
this.signal = signal;
}
}

View File

@@ -87,25 +87,7 @@ export class ItemAcceptorComponent extends Component {
*/
canAcceptItem(slotIndex, item) {
const slot = this.slots[slotIndex];
return this.filterMatches(slot.filter, item);
}
/**
* Returns if the given filter matches
* @param {enumItemType|null} filter
* @param {BaseItem} item
*/
filterMatches(filter, item) {
if (!filter) {
return true;
}
const itemType = item.getItemType();
if (filter === enumItemType.genericEnergy) {
return itemType === enumItemType.positiveEnergy || itemType === enumItemType.negativeEnergy;
}
return itemType === filter;
return !slot.filter || slot.filter === item.getItemType();
}
/**

View File

@@ -11,6 +11,7 @@ import { StorageComponent } from "./components/storage";
import { UndergroundBeltComponent } from "./components/underground_belt";
import { WiredPinsComponent } from "./components/wired_pins";
import { WireComponent } from "./components/wire";
import { ConstantSignalComponent } from "./components/constant_signal";
/* typehints:end */
/**
@@ -57,6 +58,9 @@ export class EntityComponentStorage {
/** @type {WireComponent} */
this.Wire;
/** @type {ConstantSignalComponent} */
this.ConstantSignal;
/* typehints:end */
}
}

View File

@@ -16,6 +16,7 @@ import { StorageSystem } from "./systems/storage";
import { WiredPinsSystem } from "./systems/wired_pins";
import { BeltUnderlaysSystem } from "./systems/belt_underlays";
import { WireSystem } from "./systems/wire";
import { ConstantSignalSystem } from "./systems/constant_signal";
const logger = createLogger("game_system_manager");
@@ -68,6 +69,9 @@ export class GameSystemManager {
/** @type {WireSystem} */
wire: null,
/** @type {ConstantSignalSystem} */
constantSignal: null,
/* typehints:end */
};
this.systemUpdateOrder = [];
@@ -108,6 +112,8 @@ export class GameSystemManager {
add("beltUnderlays", BeltUnderlaysSystem);
add("constantSignal", ConstantSignalSystem);
// IMPORTANT: Must be after belt system since belt system can change the
// orientation of an entity after it is placed -> the item acceptor cache
// then would be invalid

View File

@@ -1,8 +1,9 @@
import { enumLayer } from "../../root";
import { HUDBaseToolbar } from "./base_toolbar";
import { MetaWireBuilding } from "../../buildings/wire";
import { MetaConstantSignalBuilding } from "../../buildings/constant_signal";
const supportedBuildings = [MetaWireBuilding];
const supportedBuildings = [MetaWireBuilding, MetaConstantSignalBuilding];
export class HUDWiresToolbar extends HUDBaseToolbar {
constructor(root) {

View File

@@ -1,12 +1,10 @@
import { gItemRegistry } from "../core/global_registries";
import { ShapeItem } from "./items/shape_item";
import { ColorItem } from "./items/color_item";
import { PositiveEnergyItem } from "./items/positive_energy_item";
import { NegativeEnergyItem } from "./items/negative_energy_item";
import { BooleanItem } from "./items/boolean_item";
export function initItemRegistry() {
gItemRegistry.register(ShapeItem);
gItemRegistry.register(ColorItem);
gItemRegistry.register(PositiveEnergyItem);
gItemRegistry.register(NegativeEnergyItem);
gItemRegistry.register(BooleanItem);
}

View File

@@ -0,0 +1,53 @@
import { DrawParameters } from "../../core/draw_parameters";
import { Loader } from "../../core/loader";
import { types } from "../../savegame/serialization";
import { BaseItem, enumItemType } from "../base_item";
export class BooleanItem extends BaseItem {
static getId() {
return "boolean_item";
}
static getSchema() {
return types.uint;
}
serialize() {
return this.value;
}
deserialize(data) {
this.value = data;
}
getItemType() {
return enumItemType.boolean;
}
/**
* @param {number} value
*/
constructor(value) {
super();
this.value = value ? 1 : 0;
}
/**
* @param {number} x
* @param {number} y
* @param {number} size
* @param {DrawParameters} parameters
*/
draw(x, y, parameters, size = 12) {
let sprite;
if (this.value) {
sprite = Loader.getSprite("sprites/wires/boolean_true.png");
} else {
sprite = Loader.getSprite("sprites/wires/boolean_false.png");
}
sprite.drawCachedCentered(parameters, x, y, size * 1.5);
}
}
export const BOOL_FALSE_SINGLETON = new BooleanItem(0);
export const BOOL_TRUE_SINGLETON = new BooleanItem(1);

View File

@@ -1,37 +0,0 @@
import { DrawParameters } from "../../core/draw_parameters";
import { Loader } from "../../core/loader";
import { types } from "../../savegame/serialization";
import { BaseItem, enumItemType } from "../base_item";
export class NegativeEnergyItem extends BaseItem {
static getId() {
return "negative_energy";
}
static getSchema() {
return types.uint;
}
serialize() {
return 0;
}
deserialize(data) {}
getItemType() {
return enumItemType.negativeEnergy;
}
/**
* @param {number} x
* @param {number} y
* @param {number} size
* @param {DrawParameters} parameters
*/
draw(x, y, parameters, size = 12) {
const sprite = Loader.getSprite("sprites/wires/negative_energy.png");
sprite.drawCachedCentered(parameters, x, y, size * 1.5);
}
}
export const NEGATIVE_ENERGY_ITEM_SINGLETON = new NegativeEnergyItem();

View File

@@ -1,37 +0,0 @@
import { DrawParameters } from "../../core/draw_parameters";
import { Loader } from "../../core/loader";
import { types } from "../../savegame/serialization";
import { BaseItem, enumItemType } from "../base_item";
export class PositiveEnergyItem extends BaseItem {
static getId() {
return "positive_energy";
}
static getSchema() {
return types.uint;
}
serialize() {
return 0;
}
deserialize(data) {}
getItemType() {
return enumItemType.positiveEnergy;
}
/**
* @param {number} x
* @param {number} y
* @param {number} size
* @param {DrawParameters} parameters
*/
draw(x, y, parameters, size = 12) {
const sprite = Loader.getSprite("sprites/wires/positive_energy.png");
sprite.drawCachedCentered(parameters, x, y, size * 1.5);
}
}
export const POSITIVE_ENERGY_ITEM_SINGLETON = new PositiveEnergyItem();

View File

@@ -56,6 +56,7 @@ export const KEYMAPPINGS = {
trash: { keyCode: key("0") },
wire: { keyCode: key("1") },
constant_signal: { keyCode: key("2") },
},
placement: {

View File

@@ -15,6 +15,7 @@ import { enumUndergroundBeltVariants, MetaUndergroundBeltBuilding } from "./buil
import { MetaWireBuilding } from "./buildings/wire";
import { gBuildingVariants, registerBuildingVariant } from "./building_codes";
import { defaultBuildingVariant } from "./meta_building";
import { MetaConstantSignalBuilding } from "./buildings/constant_signal";
const logger = createLogger("building_registry");
@@ -31,6 +32,7 @@ export function initMetaBuildingRegistry() {
gMetaBuildingRegistry.register(MetaUndergroundBeltBuilding);
gMetaBuildingRegistry.register(MetaHubBuilding);
gMetaBuildingRegistry.register(MetaWireBuilding);
gMetaBuildingRegistry.register(MetaConstantSignalBuilding);
// Belt
registerBuildingVariant(1, MetaBeltBaseBuilding, defaultBuildingVariant, 0);
@@ -86,6 +88,9 @@ export function initMetaBuildingRegistry() {
registerBuildingVariant(29, MetaWireBuilding, defaultBuildingVariant, 2);
registerBuildingVariant(30, MetaWireBuilding, defaultBuildingVariant, 3);
// Constant signal
registerBuildingVariant(31, MetaConstantSignalBuilding);
// Propagate instances
for (const key in gBuildingVariants) {
gBuildingVariants[key].metaInstance = gMetaBuildingRegistry.findByClass(

View File

@@ -0,0 +1,98 @@
import { ConstantSignalComponent } from "../components/constant_signal";
import { GameSystemWithFilter } from "../game_system_with_filter";
import { Entity } from "../entity";
import { DialogWithForm } from "../../core/modal_dialog_elements";
import { FormElementInput } from "../../core/modal_dialog_forms";
import { enumColors } from "../colors";
import { ColorItem } from "../items/color_item";
import trim from "trim";
import { BOOL_TRUE_SINGLETON, BOOL_FALSE_SINGLETON } from "../items/boolean_item";
import { ShapeDefinition } from "../shape_definition";
import { ShapeItem } from "../items/shape_item";
export class ConstantSignalSystem extends GameSystemWithFilter {
constructor(root) {
super(root, [ConstantSignalComponent]);
this.root.signals.entityManuallyPlaced.add(this.querySigalValue, this);
}
update() {
// Set signals
for (let i = 0; i < this.allEntities.length; ++i) {
const entity = this.allEntities[i];
const pinsComp = entity.components.WiredPins;
const signalComp = entity.components.ConstantSignal;
pinsComp.slots[0].value = signalComp.signal;
}
}
/**
* Asks the entity to enter a valid signal code
* @param {Entity} entity
*/
querySigalValue(entity) {
if (!entity.components.ConstantSignal) {
return;
}
// Ok, query, but also save the uid because it could get stale
const uid = entity.uid;
const signalValueInput = new FormElementInput({
id: "markerName",
label: null,
placeholder: "",
defaultValue: "",
validator: val => this.parseSignalCode(val),
});
const dialog = new DialogWithForm({
app: this.root.app,
title: "Set Signal",
desc: "Enter a shape code, color or '0' or '1'",
formElements: [signalValueInput],
buttons: ["cancel", "ok:good"],
});
this.root.hud.parts.dialogs.internalShowDialog(dialog);
dialog.buttonSignals.ok.add(() => {
if (!this.root || !this.root.entityMgr) {
// Game got stopped
return;
}
const entityRef = this.root.entityMgr.findByUid(uid, false);
if (!entityRef) {
// outdated
return;
}
const constantComp = entityRef.components.ConstantSignal;
if (!constantComp) {
// no longer interesting
return;
}
constantComp.signal = this.parseSignalCode(signalValueInput.getValue());
});
}
parseSignalCode(code) {
code = trim(code);
if (enumColors[code]) {
return new ColorItem(code);
}
if (code === "1" || code === "true") {
return BOOL_TRUE_SINGLETON;
}
if (code === "0" || code === "false") {
return BOOL_FALSE_SINGLETON;
}
if (ShapeDefinition.isValidShortKey(code)) {
return new ShapeItem(this.root.shapeDefinitionMgr.getShapeFromShortKey(code));
}
return null;
}
}

View File

@@ -183,7 +183,7 @@ export class WiredPinsSystem extends GameSystemWithFilter {
// Draw contained item to visualize whats emitted
const value = slot.value;
if (value) {
value.draw(worldPos.x, worldPos.y, parameters, 12);
value.draw(worldPos.x, worldPos.y, parameters, 10);
}
}
}