diff --git a/src/Action/CheckBuildingRemainingTimeAction.ts b/src/Action/CheckBuildingRemainingTimeAction.ts index 8c1e920..b31c83a 100644 --- a/src/Action/CheckBuildingRemainingTimeAction.ts +++ b/src/Action/CheckBuildingRemainingTimeAction.ts @@ -2,6 +2,7 @@ import { ActionController, registerAction } from './ActionController'; import { Args } from '../Common'; import { Task } from '../Storage/TaskQueue'; import { BuildingQueueFullError } from '../Errors'; +import { grabActiveVillageId } from '../Page/EveryPage'; @registerAction export class CheckBuildingRemainingTimeAction extends ActionController { @@ -10,7 +11,12 @@ export class CheckBuildingRemainingTimeAction extends ActionController { if (timer.length === 1) { const remainingSeconds = Number(timer.attr('value')); if (remainingSeconds > 0) { - throw new BuildingQueueFullError(task.id, remainingSeconds + 1, 'Building queue is full'); + throw new BuildingQueueFullError( + task.id, + grabActiveVillageId(), + remainingSeconds + 1, + 'Building queue is full' + ); } } } diff --git a/src/Dashboard/Dashboard.ts b/src/Dashboard/Dashboard.ts index 833cf75..338e257 100644 --- a/src/Dashboard/Dashboard.ts +++ b/src/Dashboard/Dashboard.ts @@ -3,7 +3,12 @@ import { markPage, waitForLoad } from '../utils'; import { Scheduler } from '../Scheduler'; import { TaskQueueRenderer } from '../TaskQueueRenderer'; import { BuildPage } from '../Page/BuildPage'; -import { grabActiveVillageId, showBuildingSlotIds, showFieldsSlotIds } from '../Page/EveryPage'; +import { + grabActiveVillageId, + onResourceSlotCtrlClick, + showBuildingSlotIds, + showFieldsSlotIds, +} from '../Page/EveryPage'; import { UpgradeBuildingTask } from '../Task/UpgradeBuildingTask'; export class Dashboard { @@ -34,6 +39,11 @@ export class Dashboard { if (p.pathname === '/dorf1.php') { showFieldsSlotIds(buildingsInQueue); + onResourceSlotCtrlClick(buildId => { + this.scheduler.scheduleTask(UpgradeBuildingTask.name, { villageId, buildId }); + const n = new Notification(`Building ${buildId} scheduled`); + setTimeout(() => n && n.close(), 4000); + }); } if (p.pathname === '/dorf2.php') { diff --git a/src/Errors.ts b/src/Errors.ts index 1a26b36..71ff81b 100644 --- a/src/Errors.ts +++ b/src/Errors.ts @@ -32,10 +32,12 @@ export class TryLaterError extends Error { export class BuildingQueueFullError extends Error { readonly seconds: number; + readonly villageId: number; readonly taskId: TaskId; - constructor(taskId: TaskId, seconds: number, msg: string = '') { + constructor(taskId: TaskId, villageId: number, seconds: number, msg: string = '') { super(msg); + this.villageId = villageId; this.taskId = taskId; this.seconds = seconds; Object.setPrototypeOf(this, BuildingQueueFullError.prototype); diff --git a/src/Page/EveryPage.ts b/src/Page/EveryPage.ts index 0f435f5..2a4370e 100644 --- a/src/Page/EveryPage.ts +++ b/src/Page/EveryPage.ts @@ -8,28 +8,60 @@ export function grabActiveVillageId(): number { return getNumber(p.query.newdid); } -function showSlotIds(prefix: string, buildingIds: number[]): void { +interface Slot { + el: HTMLElement; + buildId: number; +} + +function slotElements(prefix: string): Array { + const result: Array = []; jQuery('.level.colorLayer').each((idx, el) => { const buildId = getNumber(elClassId(jQuery(el).attr('class') || '', prefix)); - const oldLabel = jQuery(el) + result.push({ + el, + buildId, + }); + }); + return result; +} + +function showSlotIds(prefix: string, buildingIds: number[]): void { + const slots = slotElements(prefix); + slots.forEach(slot => { + const oldLabel = jQuery(slot.el) .find('.labelLayer') .text(); - jQuery(el) + jQuery(slot.el) .find('.labelLayer') - .text(buildId + ':' + oldLabel); - const inQueue = buildingIds.includes(buildId); + .text(slot.buildId + ':' + oldLabel); + const inQueue = buildingIds.includes(slot.buildId); if (inQueue) { - jQuery(el).css({ + jQuery(slot.el).css({ 'background-image': 'linear-gradient(to top, #f00, #f00 100%)', }); } }); } -export function showFieldsSlotIds(buildingIds: number[]) { +export function showFieldsSlotIds(buildingIds: number[]): void { showSlotIds('buildingSlot', buildingIds); } -export function showBuildingSlotIds(buildingIds: number[]) { +export function showBuildingSlotIds(buildingIds: number[]): void { showSlotIds('aid', buildingIds); } + +export function onResourceSlotCtrlClick(cb: (buildId: number) => void): void { + const slots = slotElements('buildingSlot'); + slots.forEach(slot => { + jQuery(slot.el) + .find('.labelLayer') + .on('click', evt => { + if (evt.ctrlKey) { + evt.preventDefault(); + evt.stopPropagation(); + cb(slot.buildId); + } + }); + }); +} diff --git a/src/Scheduler.ts b/src/Scheduler.ts index 3fc1388..90979a2 100644 --- a/src/Scheduler.ts +++ b/src/Scheduler.ts @@ -123,7 +123,7 @@ export class Scheduler { if (err instanceof BuildingQueueFullError) { this.logWarn('BUILDING QUEUE FULL, TRY ALL AFTER', err.seconds); this.taskQueue.modify( - t => t.name === UpgradeBuildingTask.name, + t => t.name === UpgradeBuildingTask.name && t.args.villageId === err.villageId, t => t.withTime(timestamp() + err.seconds) ); return;