Placing underground belts now removes belts and other (unneeded) tunnels inbetween

This commit is contained in:
tobspr 2020-06-16 13:19:53 +02:00
parent 90cb56292b
commit b8c3668d88
4 changed files with 150 additions and 7 deletions

View File

@ -6,6 +6,8 @@ export const CHANGELOG = [
"There is now an indicator (compass) to the HUB for the HUB Marker!",
"You can now include shape short keys in markers to render shape icons instead of text!",
"Added mirrored variant of the painter",
"When placing tunnels, unnecessary belts inbetween are now removed!",
"You can now drag tunnels and they will automatically expand! (Just try it out, its intuitive)",
],
},
{

View File

@ -483,6 +483,10 @@ export class HUDBuildingPlacer extends BaseHUDPart {
) {
// Succesfully placed
const entity = this.root.map.getTileContent(tile);
assert(entity, "Entity was not actually placed");
this.root.signals.entityManuallyPlaced.dispatch(entity);
if (
metaBuilding.getFlipOrientationAfterPlacement() &&
!this.root.keyMapper

View File

@ -130,6 +130,7 @@ export class GameRoot {
this.signals = {
// Entities
entityManuallyPlaced: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
entityAdded: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
entityGotNewComponent: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
entityComponentRemoved: /** @type {TypedSignal<[Entity]>} */ (new Signal()),

View File

@ -1,12 +1,17 @@
import { GameSystemWithFilter } from "../game_system_with_filter";
import { UndergroundBeltComponent, enumUndergroundBeltMode } from "../components/underground_belt";
import { Entity } from "../entity";
import { Loader } from "../../core/loader";
import { Math_max } from "../../core/builtins";
import { globalConfig } from "../../core/config";
import { enumDirection, enumDirectionToVector, enumDirectionToAngle } from "../../core/vector";
import { MapChunkView } from "../map_chunk_view";
import { DrawParameters } from "../../core/draw_parameters";
import { Loader } from "../../core/loader";
import {
enumDirection,
enumDirectionToAngle,
enumDirectionToVector,
Vector,
enumAngleToDirection,
enumInvertedDirections,
} from "../../core/vector";
import { enumUndergroundBeltMode, UndergroundBeltComponent } from "../components/underground_belt";
import { Entity } from "../entity";
import { GameSystemWithFilter } from "../game_system_with_filter";
export class UndergroundBeltSystem extends GameSystemWithFilter {
constructor(root) {
@ -20,6 +25,8 @@ export class UndergroundBeltSystem extends GameSystemWithFilter {
"sprites/buildings/underground_belt_exit.png"
),
};
this.root.signals.entityManuallyPlaced.add(this.onEntityPlaced, this);
}
update() {
@ -46,6 +53,135 @@ export class UndergroundBeltSystem extends GameSystemWithFilter {
}
}
/**
* Callback when an entity got placed, used to remove belts between underground belts
* @param {Entity} entity
*/
onEntityPlaced(entity) {
const undergroundComp = entity.components.UndergroundBelt;
if (undergroundComp && undergroundComp.mode === enumUndergroundBeltMode.receiver) {
const staticComp = entity.components.StaticMapEntity;
const tile = staticComp.origin;
const direction = enumAngleToDirection[staticComp.rotation];
const inverseDirection = enumInvertedDirections[direction];
const offset = enumDirectionToVector[inverseDirection];
let currentPos = tile.copy();
const tier = undergroundComp.tier;
const range = globalConfig.undergroundBeltMaxTilesByTier[tier];
// Search for the entrance which is furthes apart (this is why we can't reuse logic here)
let matchingEntrance = null;
for (let i = 0; i < range; ++i) {
currentPos.addInplace(offset);
const contents = this.root.map.getTileContent(currentPos);
if (!contents) {
continue;
}
const contentsUndergroundComp = contents.components.UndergroundBelt;
if (
contentsUndergroundComp &&
contentsUndergroundComp.tier === undergroundComp.tier &&
contentsUndergroundComp.mode === enumUndergroundBeltMode.sender
) {
matchingEntrance = {
entity: contents,
range: i,
};
}
}
if (!matchingEntrance) {
// Nothing found
return;
}
// Remove any belts between entrance and exit which have the same direction
currentPos = tile.copy();
for (let i = 0; i < matchingEntrance.range; ++i) {
currentPos.addInplace(offset);
const contents = this.root.map.getTileContent(currentPos);
if (!contents) {
continue;
}
const contentsStaticComp = contents.components.StaticMapEntity;
const contentsBeltComp = contents.components.Belt;
if (contentsBeltComp) {
// It's a belt
if (
contentsBeltComp.direction === enumDirection.top &&
enumAngleToDirection[contentsStaticComp.rotation] === direction
) {
// It's same rotation, drop it
this.root.logic.tryDeleteBuilding(contents);
}
}
}
// Remove any double tunnels, by checking the tile plus the tile above
currentPos = tile.copy().add(offset);
for (let i = 0; i < matchingEntrance.range - 1; ++i) {
const posBefore = currentPos.copy();
currentPos.addInplace(offset);
const entityBefore = this.root.map.getTileContent(posBefore);
const entityAfter = this.root.map.getTileContent(currentPos);
if (!entityBefore || !entityAfter) {
continue;
}
const undergroundBefore = entityBefore.components.UndergroundBelt;
const undergroundAfter = entityAfter.components.UndergroundBelt;
if (!undergroundBefore || !undergroundAfter) {
// Not an underground belt
continue;
}
if (
// Both same tier
undergroundBefore.tier !== undergroundAfter.tier ||
// And same tier as our original entity
undergroundBefore.tier !== undergroundComp.tier
) {
// Mismatching tier
continue;
}
if (
undergroundBefore.mode !== enumUndergroundBeltMode.sender ||
undergroundAfter.mode !== enumUndergroundBeltMode.receiver
) {
// Not the right mode
continue;
}
// Check rotations
const staticBefore = entityBefore.components.StaticMapEntity;
const staticAfter = entityAfter.components.StaticMapEntity;
if (
enumAngleToDirection[staticBefore.rotation] !== direction ||
enumAngleToDirection[staticAfter.rotation] !== direction
) {
// Wrong rotation
continue;
}
// All good, can remove
this.root.logic.tryDeleteBuilding(entityBefore);
this.root.logic.tryDeleteBuilding(entityAfter);
}
}
}
/**
*
* @param {Entity} entity