mirror of
https://github.com/tobspr/shapez.io.git
synced 2024-10-27 20:34:29 +00:00
Refactor belt underlay feature into seperate component
This commit is contained in:
parent
f91e677f2e
commit
b3b8da04a1
@ -1,14 +1,14 @@
|
||||
import { globalConfig } from "../../core/config";
|
||||
import { enumDirection, Vector } from "../../core/vector";
|
||||
import { ItemAcceptorComponent } from "../components/item_acceptor";
|
||||
import { ItemEjectorComponent } from "../components/item_ejector";
|
||||
import { enumItemProcessorTypes, ItemProcessorComponent } from "../components/item_processor";
|
||||
import { Entity } from "../entity";
|
||||
import { MetaBuilding, defaultBuildingVariant } from "../meta_building";
|
||||
import { GameRoot, enumLayer } from "../root";
|
||||
import { GameRoot } from "../root";
|
||||
import { enumHubGoalRewards } from "../tutorial_goals";
|
||||
import { T } from "../../translations";
|
||||
import { formatItemsPerSecond } from "../../core/utils";
|
||||
import { BeltUnderlaysComponent } from "../components/belt_underlays";
|
||||
|
||||
/** @enum {string} */
|
||||
export const enumSplitterVariants = { compact: "compact", compactInverse: "compact-inverse" };
|
||||
@ -88,6 +88,8 @@ export class MetaSplitterBuilding extends MetaBuilding {
|
||||
slots: [], // set later
|
||||
})
|
||||
);
|
||||
|
||||
entity.addComponent(new BeltUnderlaysComponent({ underlays: [] }));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,9 +117,9 @@ export class MetaSplitterBuilding extends MetaBuilding {
|
||||
{ pos: new Vector(1, 0), direction: enumDirection.top },
|
||||
]);
|
||||
|
||||
entity.components.ItemAcceptor.beltUnderlays = [
|
||||
{ pos: new Vector(0, 0), direction: enumDirection.top, layer: enumLayer.regular },
|
||||
{ pos: new Vector(1, 0), direction: enumDirection.top, layer: enumLayer.regular },
|
||||
entity.components.BeltUnderlays.underlays = [
|
||||
{ pos: new Vector(0, 0), direction: enumDirection.top },
|
||||
{ pos: new Vector(1, 0), direction: enumDirection.top },
|
||||
];
|
||||
|
||||
break;
|
||||
@ -143,8 +145,8 @@ export class MetaSplitterBuilding extends MetaBuilding {
|
||||
{ pos: new Vector(0, 0), direction: enumDirection.top },
|
||||
]);
|
||||
|
||||
entity.components.ItemAcceptor.beltUnderlays = [
|
||||
{ pos: new Vector(0, 0), direction: enumDirection.top, layer: enumLayer.regular },
|
||||
entity.components.BeltUnderlays.underlays = [
|
||||
{ pos: new Vector(0, 0), direction: enumDirection.top },
|
||||
];
|
||||
|
||||
break;
|
||||
|
@ -13,6 +13,7 @@ import { StorageComponent } from "./components/storage";
|
||||
import { EnergyGeneratorComponent } from "./components/energy_generator";
|
||||
import { WiredPinsComponent } from "./components/wired_pins";
|
||||
import { EnergyConsumerComponent } from "./components/energy_consumer";
|
||||
import { BeltUnderlaysComponent } from "./components/belt_underlays";
|
||||
|
||||
export function initComponentRegistry() {
|
||||
gComponentRegistry.register(StaticMapEntityComponent);
|
||||
@ -29,6 +30,7 @@ export function initComponentRegistry() {
|
||||
gComponentRegistry.register(EnergyGeneratorComponent);
|
||||
gComponentRegistry.register(WiredPinsComponent);
|
||||
gComponentRegistry.register(EnergyConsumerComponent);
|
||||
gComponentRegistry.register(BeltUnderlaysComponent);
|
||||
|
||||
// IMPORTANT ^^^^^ UPDATE ENTITY COMPONENT STORAGE AFTERWARDS
|
||||
|
||||
|
44
src/js/game/components/belt_underlays.js
Normal file
44
src/js/game/components/belt_underlays.js
Normal file
@ -0,0 +1,44 @@
|
||||
import { Component } from "../component";
|
||||
import { types } from "../../savegame/serialization";
|
||||
import { enumDirection, Vector } from "../../core/vector";
|
||||
|
||||
export class BeltUnderlaysComponent extends Component {
|
||||
static getId() {
|
||||
return "BeltUnderlays";
|
||||
}
|
||||
|
||||
static getSchema() {
|
||||
return {
|
||||
underlays: types.array(
|
||||
types.structured({
|
||||
pos: types.vector,
|
||||
direction: types.enum(enumDirection),
|
||||
})
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
duplicateWithoutContents() {
|
||||
const beltUnderlaysCopy = [];
|
||||
for (let i = 0; i < this.underlays.length; ++i) {
|
||||
const underlay = this.underlays[i];
|
||||
beltUnderlaysCopy.push({
|
||||
pos: underlay.pos.copy(),
|
||||
direction: underlay.direction,
|
||||
});
|
||||
}
|
||||
|
||||
return new BeltUnderlaysComponent({
|
||||
underlays: beltUnderlaysCopy,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} param0
|
||||
* @param {Array<{pos: Vector, direction: enumDirection}>=} param0.underlays Where to render belt underlays
|
||||
*/
|
||||
constructor({ underlays }) {
|
||||
super();
|
||||
this.underlays = underlays;
|
||||
}
|
||||
}
|
@ -39,16 +39,6 @@ export class ItemAcceptorComponent extends Component {
|
||||
directions: types.array(types.enum(enumDirection)),
|
||||
filter: types.nullable(types.enum(enumItemType)),
|
||||
|
||||
// TODO: MIGRATE
|
||||
layer: types.enum(enumLayer),
|
||||
})
|
||||
),
|
||||
animated: types.bool,
|
||||
beltUnderlays: types.array(
|
||||
types.structured({
|
||||
pos: types.vector,
|
||||
direction: types.enum(enumDirection),
|
||||
|
||||
// TODO: MIGRATE
|
||||
layer: types.enum(enumLayer),
|
||||
})
|
||||
@ -68,20 +58,8 @@ export class ItemAcceptorComponent extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
const beltUnderlaysCopy = [];
|
||||
for (let i = 0; i < this.beltUnderlays.length; ++i) {
|
||||
const underlay = this.beltUnderlays[i];
|
||||
beltUnderlaysCopy.push({
|
||||
pos: underlay.pos.copy(),
|
||||
direction: underlay.direction,
|
||||
layer: underlay.layer,
|
||||
});
|
||||
}
|
||||
|
||||
return new ItemAcceptorComponent({
|
||||
slots: slotsCopy,
|
||||
beltUnderlays: beltUnderlaysCopy,
|
||||
animated: this.animated,
|
||||
});
|
||||
}
|
||||
|
||||
@ -89,23 +67,16 @@ export class ItemAcceptorComponent extends Component {
|
||||
*
|
||||
* @param {object} param0
|
||||
* @param {Array<ItemAcceptorSlotConfig>} param0.slots The slots from which we accept items
|
||||
* @param {boolean=} param0.animated Whether to animate item consumption
|
||||
* @param {Array<{pos: Vector, direction: enumDirection, layer: enumLayer}>=} param0.beltUnderlays Where to render belt underlays
|
||||
*/
|
||||
constructor({ slots = [], beltUnderlays = [], animated = true }) {
|
||||
constructor({ slots = [] }) {
|
||||
super();
|
||||
|
||||
this.animated = animated;
|
||||
|
||||
/**
|
||||
* Fixes belt animations
|
||||
* @type {Array<{ item: BaseItem, slotIndex: number, animProgress: number, direction: enumDirection }>}
|
||||
*/
|
||||
this.itemConsumptionAnimations = [];
|
||||
|
||||
/* Which belt underlays to render */
|
||||
this.beltUnderlays = beltUnderlays;
|
||||
|
||||
this.setSlots(slots);
|
||||
}
|
||||
|
||||
@ -164,14 +135,12 @@ export class ItemAcceptorComponent extends Component {
|
||||
* @param {BaseItem} item
|
||||
*/
|
||||
onItemAccepted(slotIndex, direction, item) {
|
||||
if (this.animated) {
|
||||
this.itemConsumptionAnimations.push({
|
||||
item,
|
||||
slotIndex,
|
||||
direction,
|
||||
animProgress: 0.0,
|
||||
});
|
||||
}
|
||||
this.itemConsumptionAnimations.push({
|
||||
item,
|
||||
slotIndex,
|
||||
direction,
|
||||
animProgress: 0.0,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -398,7 +398,7 @@ export class GameCore {
|
||||
|
||||
if (!this.root.camera.getIsMapOverlayActive()) {
|
||||
// Underlays for splitters / balancers
|
||||
systems.itemAcceptor.drawUnderlays(params, enumLayer.regular);
|
||||
systems.beltUnderlays.drawUnderlays(params, enumLayer.regular);
|
||||
|
||||
// Belt items
|
||||
systems.belt.drawLayerBeltItems(params, enumLayer.regular);
|
||||
|
@ -13,6 +13,7 @@ import { StorageComponent } from "./components/storage";
|
||||
import { EnergyGeneratorComponent } from "./components/energy_generator";
|
||||
import { WiredPinsComponent } from "./components/wired_pins";
|
||||
import { EnergyConsumerComponent } from "./components/energy_consumer";
|
||||
import { BeltUnderlaysComponent } from "./components/belt_underlays";
|
||||
/* typehints:end */
|
||||
|
||||
/**
|
||||
@ -65,6 +66,9 @@ export class EntityComponentStorage {
|
||||
/** @type {EnergyConsumerComponent} */
|
||||
this.EnergyConsumer;
|
||||
|
||||
/** @type {BeltUnderlaysComponent} */
|
||||
this.BeltUnderlays;
|
||||
|
||||
/* typehints:end */
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import { StorageSystem } from "./systems/storage";
|
||||
import { EnergyGeneratorSystem } from "./systems/energy_generator";
|
||||
import { WiredPinsSystem } from "./systems/wired_pins";
|
||||
import { EnergyConsumerSystem } from "./systems/energy_consumer";
|
||||
import { BeltUnderlaysSystem } from "./systems/belt_underlays";
|
||||
|
||||
const logger = createLogger("game_system_manager");
|
||||
|
||||
@ -68,6 +69,9 @@ export class GameSystemManager {
|
||||
/** @type {EnergyConsumerSystem} */
|
||||
energyConsumer: null,
|
||||
|
||||
/** @type {BeltUnderlaysSystem} */
|
||||
beltUnderlays: null,
|
||||
|
||||
/* typehints:end */
|
||||
};
|
||||
this.systemUpdateOrder = [];
|
||||
@ -110,6 +114,8 @@ export class GameSystemManager {
|
||||
|
||||
add("energyConsumer", EnergyConsumerSystem);
|
||||
|
||||
add("beltUnderlays", BeltUnderlaysSystem);
|
||||
|
||||
// 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
|
||||
|
75
src/js/game/systems/belt_underlays.js
Normal file
75
src/js/game/systems/belt_underlays.js
Normal file
@ -0,0 +1,75 @@
|
||||
import { GameSystemWithFilter } from "../game_system_with_filter";
|
||||
import { BeltUnderlaysComponent } from "../components/belt_underlays";
|
||||
import { BELT_ANIM_COUNT } from "./belt";
|
||||
import { Loader } from "../../core/loader";
|
||||
import { enumLayer } from "../root";
|
||||
import { Entity } from "../entity";
|
||||
import { enumDirectionToAngle } from "../../core/vector";
|
||||
import { globalConfig } from "../../core/config";
|
||||
import { drawRotatedSprite } from "../../core/draw_utils";
|
||||
|
||||
export class BeltUnderlaysSystem extends GameSystemWithFilter {
|
||||
constructor(root) {
|
||||
super(root, [BeltUnderlaysComponent]);
|
||||
|
||||
this.underlayBeltSprites = [];
|
||||
|
||||
for (let i = 0; i < BELT_ANIM_COUNT; ++i) {
|
||||
this.underlayBeltSprites.push(Loader.getSprite("sprites/belt/forward_" + i + ".png"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the acceptor underlays
|
||||
* @param {import("../../core/draw_utils").DrawParameters} parameters
|
||||
* @param {enumLayer} layer
|
||||
*/
|
||||
drawUnderlays(parameters, layer) {
|
||||
this.forEachMatchingEntityOnScreen(parameters, this.drawEntityUnderlays.bind(this, layer));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {enumLayer} layer
|
||||
* @param {import("../../core/draw_utils").DrawParameters} parameters
|
||||
* @param {Entity} entity
|
||||
*/
|
||||
drawEntityUnderlays(layer, parameters, entity) {
|
||||
const staticComp = entity.components.StaticMapEntity;
|
||||
const underlayComp = entity.components.BeltUnderlays;
|
||||
|
||||
if (entity.layer !== layer) {
|
||||
// Not our layer
|
||||
return;
|
||||
}
|
||||
|
||||
if (!staticComp.shouldBeDrawn(parameters)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Limit speed to avoid belts going backwards
|
||||
const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(layer), 10);
|
||||
|
||||
const underlays = underlayComp.underlays;
|
||||
for (let i = 0; i < underlays.length; ++i) {
|
||||
const { pos, direction } = underlays[i];
|
||||
|
||||
const transformedPos = staticComp.localTileToWorld(pos);
|
||||
const angle = enumDirectionToAngle[staticComp.localDirectionToWorld(direction)];
|
||||
|
||||
// SYNC with systems/belt.js:drawSingleEntity!
|
||||
const animationIndex = Math.floor(
|
||||
((this.root.time.realtimeNow() * speedMultiplier * BELT_ANIM_COUNT * 126) / 42) *
|
||||
globalConfig.beltItemSpacingByLayer[layer]
|
||||
);
|
||||
|
||||
drawRotatedSprite({
|
||||
parameters,
|
||||
sprite: this.underlayBeltSprites[animationIndex % this.underlayBeltSprites.length],
|
||||
x: (transformedPos.x + 0.5) * globalConfig.tileSize,
|
||||
y: (transformedPos.y + 0.5) * globalConfig.tileSize,
|
||||
angle: Math.radians(angle),
|
||||
size: globalConfig.tileSize,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -13,12 +13,6 @@ import { enumLayer } from "../root";
|
||||
export class ItemAcceptorSystem extends GameSystemWithFilter {
|
||||
constructor(root) {
|
||||
super(root, [ItemAcceptorComponent]);
|
||||
|
||||
this.underlayBeltSprites = [];
|
||||
|
||||
for (let i = 0; i < BELT_ANIM_COUNT; ++i) {
|
||||
this.underlayBeltSprites.push(Loader.getSprite("sprites/belt/forward_" + i + ".png"));
|
||||
}
|
||||
}
|
||||
|
||||
update() {
|
||||
@ -59,15 +53,6 @@ export class ItemAcceptorSystem extends GameSystemWithFilter {
|
||||
this.forEachMatchingEntityOnScreen(parameters, this.drawEntityRegularLayer.bind(this, layer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the acceptor underlays
|
||||
* @param {DrawParameters} parameters
|
||||
* @param {enumLayer} layer
|
||||
*/
|
||||
drawUnderlays(parameters, layer) {
|
||||
this.forEachMatchingEntityOnScreen(parameters, this.drawEntityUnderlays.bind(this, layer));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {enumLayer} layer
|
||||
* @param {DrawParameters} parameters
|
||||
@ -105,48 +90,4 @@ export class ItemAcceptorSystem extends GameSystemWithFilter {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {enumLayer} layer
|
||||
* @param {DrawParameters} parameters
|
||||
* @param {Entity} entity
|
||||
*/
|
||||
drawEntityUnderlays(layer, parameters, entity) {
|
||||
const staticComp = entity.components.StaticMapEntity;
|
||||
const acceptorComp = entity.components.ItemAcceptor;
|
||||
|
||||
if (!staticComp.shouldBeDrawn(parameters)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Limit speed to avoid belts going backwards
|
||||
const speedMultiplier = Math.min(this.root.hubGoals.getBeltBaseSpeed(layer), 10);
|
||||
|
||||
const underlays = acceptorComp.beltUnderlays;
|
||||
for (let i = 0; i < underlays.length; ++i) {
|
||||
const { pos, direction, layer: underlayLayer } = underlays[i];
|
||||
if (underlayLayer !== layer) {
|
||||
// Not our layer
|
||||
continue;
|
||||
}
|
||||
|
||||
const transformedPos = staticComp.localTileToWorld(pos);
|
||||
const angle = enumDirectionToAngle[staticComp.localDirectionToWorld(direction)];
|
||||
|
||||
// SYNC with systems/belt.js:drawSingleEntity!
|
||||
const animationIndex = Math.floor(
|
||||
((this.root.time.realtimeNow() * speedMultiplier * BELT_ANIM_COUNT * 126) / 42) *
|
||||
globalConfig.beltItemSpacingByLayer[layer]
|
||||
);
|
||||
|
||||
drawRotatedSprite({
|
||||
parameters,
|
||||
sprite: this.underlayBeltSprites[animationIndex % this.underlayBeltSprites.length],
|
||||
x: (transformedPos.x + 0.5) * globalConfig.tileSize,
|
||||
y: (transformedPos.y + 0.5) * globalConfig.tileSize,
|
||||
angle: Math.radians(angle),
|
||||
size: globalConfig.tileSize,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user