diff --git a/data/config/widgets.json5 b/data/config/widgets.json5 new file mode 100644 index 000000000..c0e807265 --- /dev/null +++ b/data/config/widgets.json5 @@ -0,0 +1,85 @@ +{ + characterDesign: 269, + furnace: { + widgetId: 311, + slots: { + slot0: { modelId: 4, titleId: 16 }, + slot1: { modelId: 5, titleId: 20 }, + slot2: { modelId: 6, titleId: 24 }, + slot3: { modelId: 7, titleId: 28 }, + slot4: { modelId: 8, titleId: 32 }, + slot5: { modelId: 9, titleId: 36 }, + slot6: { modelId: 10, titleId: 40 }, + slot7: { modelId: 11, titleId: 44 }, + slot8: { modelId: 12, titleId: 48 } + } + }, + inventory: { + widgetId: 149, + containerId: 0 + }, + equipment: { + widgetId: 387, + containerId: 25 + }, + equipmentStats: { + widgetId: 465, + containerId: 103 + }, + equipmentStatsInventory: { + widgetId: 336, + containerId: 0 + }, + bank: { + depositBoxWidget: { + widgetId: 11 + }, + pinSettingsWidget: { + widgetId: 14 + }, + screenWidget: { + widgetId: 12, + containerId: 89 + }, + tabWidget: { + widgetId: 266, + containerId: 0 + } + }, + defaultCombatStyle: 92, + skillGuide: 308, + skillsTab: 320, + friendsList: 131, + ignoreList: 148, + logoutTab: 182, + settingsTab: 261, + emotesTab: 464, + musicPlayerTab: 239, + prayerTab: 271, + standardSpellbookTab: 192, + questTab: 274, + shop: { + widgetId: 300, + containerId: 75, + title: 76 + }, + shopPlayerInventory: { + widgetId: 301, + containerId: 0 + }, + questJournal: 275, + questReward: 277, + welcomeScreen: 378, + welcomeScreenChildren: { + cogs: 16, + question: 17, + drama: 18, + bankPin: 19, + bankPinQuestion: 20, + scamming: 21, + bankPinKey: 22, + christmas: 23, + killcount: 24 + }, + whatWouldYouLikeToSpin: 459 +} diff --git a/package-lock.json b/package-lock.json index 02edbb17d..bdc6718a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1746,9 +1746,9 @@ "dev": true }, "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.30.tgz", + "integrity": "sha512-sqm9g7mHlPY/43fcSNrCYfOeX9zkTTK+euO5E6+CVijSMm5tTjkVdwdqRkY3ljjIAf8679vps5jKUoJBCLsMDA==", "dev": true }, "@types/lodash": { @@ -2899,6 +2899,15 @@ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, + "rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -4784,12 +4793,11 @@ "dev": true }, "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", "requires": { - "minimist": "^1.2.0" + "minimist": "^1.2.5" } }, "keyv": { @@ -6126,9 +6134,9 @@ "dev": true }, "rxjs": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", - "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", + "version": "7.0.0-beta.8", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.0.0-beta.8.tgz", + "integrity": "sha512-rnLwH1WJR67m7p5m+KQNqXd1A+PO/WLZZMd1JuzIRm2AOmhJttBGyDiyanky65rHaYzhEztU1QPak68hm+R4qA==", "requires": { "tslib": "^1.9.0" } @@ -6823,6 +6831,23 @@ "json5": "^1.0.1", "minimist": "^1.2.0", "strip-bom": "^3.0.0" + }, + "dependencies": { + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + } } }, "tslib": { diff --git a/package.json b/package.json index 7261f795d..fefeb76df 100644 --- a/package.json +++ b/package.json @@ -37,9 +37,10 @@ "crc-32": "^1.2.0", "express": "^4.17.1", "js-yaml": "^3.13.1", + "json5": "^2.1.3", "lodash": "^4.17.15", "quadtree-lib": "^1.0.9", - "rxjs": "^6.5.4", + "rxjs": "^7.0.0-beta.8", "source-map-support": "^0.5.16", "ts-node": "^8.4.1", "tslib": "^1.10.0", @@ -59,6 +60,7 @@ "@types/express": "^4.17.2", "@types/hapi__joi": "^16.0.6", "@types/js-yaml": "^3.12.1", + "@types/json5": "0.0.30", "@types/lodash": "^4.14.149", "@types/node": "^12.12.6", "@types/uuid": "^3.4.6", diff --git a/src/config/index.ts b/src/config/index.ts index 1bd8f9732..a715909d1 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -17,7 +17,8 @@ import { } from '@server/config/npc-config'; import { loadNpcSpawnConfigurations, NpcSpawn } from '@server/config/npc-spawn-config'; import { loadShopConfigurations, Shop } from '@server/config/shop-config'; - +import json5 from 'json5'; +require('json5/lib/register'); export async function loadConfigurationFiles(configurationDir: string): Promise { const files = []; @@ -47,6 +48,7 @@ export let npcIdMap: { [key: number]: string }; export let npcPresetMap: NpcPresetConfiguration; export let npcSpawns: NpcSpawn[] = []; export let shopMap: { [key: string]: Shop }; +export const widgets: { [key: string]: any } = require('../../data/config/widgets.json5'); export async function loadConfigurations(): Promise { diff --git a/src/config/shop-config.ts b/src/config/shop-config.ts index e01b5643b..b346fc0e7 100644 --- a/src/config/shop-config.ts +++ b/src/config/shop-config.ts @@ -1,7 +1,6 @@ import { ItemContainer } from '@server/world/items/item-container'; -import { findItem, loadConfigurationFiles } from '@server/config/index'; +import { findItem, loadConfigurationFiles, widgets } from '@server/config/index'; import { Player } from '@server/world/actor/player/player'; -import { widgets } from '@server/world/config/widget'; import { ItemDetails } from '@server/config/item-config'; @@ -96,12 +95,14 @@ export class Shop { player.outgoingPackets.sendUpdateAllWidgetItems(widgets.shop, this.container); player.outgoingPackets.sendUpdateAllWidgetItems(widgets.shopPlayerInventory, player.inventory); - player.activeWidget = { - widgetId: widgets.shop.widgetId, - secondaryWidgetId: widgets.shopPlayerInventory.widgetId, - type: 'SCREEN_AND_TAB', - closeOnWalk: true - }; + player.interfaceState.openWidget(widgets.shop.widgetId, { + slot: 'screen', + multi: true + }); + player.interfaceState.openWidget(widgets.shopPlayerInventory.widgetId, { + slot: 'tabarea', + multi: true + }); } } diff --git a/src/net/inbound-packets/button-click-packet.js b/src/net/inbound-packets/button-click-packet.js index 133b611d5..408aec03f 100644 --- a/src/net/inbound-packets/button-click-packet.js +++ b/src/net/inbound-packets/button-click-packet.js @@ -1,17 +1,11 @@ import { actionHandler } from '../../world/action'; -const ignoreButtons = [ - '269:99' // character design accept button -]; - const buttonClickPacket = (player, packet) => { const { buffer } = packet; const widgetId = buffer.get('SHORT'); const buttonId = buffer.get('SHORT'); - if(ignoreButtons.indexOf(`${widgetId}:${buttonId}`) === -1) { - actionHandler.call('button', player, widgetId, buttonId); - } + actionHandler.call('button', player, widgetId, buttonId); }; export default { diff --git a/src/net/inbound-packets/character-design-packet.js b/src/net/inbound-packets/character-design-packet.js index eb7b6123f..bce0e57b2 100644 --- a/src/net/inbound-packets/character-design-packet.js +++ b/src/net/inbound-packets/character-design-packet.js @@ -1,4 +1,4 @@ -import { widgets } from '../../world/config/widget'; +import { widgets } from '../../config'; const characterDesignPacket = (player, packet) => { if(!player.activeWidget || player.activeWidget.widgetId !== widgets.characterDesign) { @@ -38,7 +38,7 @@ const characterDesignPacket = (player, packet) => { }; player.updateFlags.appearanceUpdateRequired = true; - player.closeActiveWidgets(); + player.player.interfaceState.closeAllSlots(); }; export default { diff --git a/src/net/inbound-packets/item-on-item-packet.js b/src/net/inbound-packets/item-on-item-packet.js index dcd4af64b..4e413ba08 100644 --- a/src/net/inbound-packets/item-on-item-packet.js +++ b/src/net/inbound-packets/item-on-item-packet.js @@ -1,6 +1,6 @@ -import { widgets } from '../../world/config/widget'; import { logger } from '@runejs/core'; import { actionHandler } from '../../world/action'; +import { widgets } from '../../config'; const itemOnItemPacket = (player, packet) => { const { buffer } = packet; diff --git a/src/net/inbound-packets/item-on-npc-packet.js b/src/net/inbound-packets/item-on-npc-packet.js index 0050e10ac..c1f3753f7 100644 --- a/src/net/inbound-packets/item-on-npc-packet.js +++ b/src/net/inbound-packets/item-on-npc-packet.js @@ -1,8 +1,8 @@ -import { widgets } from '../../world/config/widget'; import { logger } from '@runejs/core'; import { world } from '../../game-server'; import { World } from '../../world'; import { actionHandler } from '../../world/action'; +import { widgets } from '../../config'; const itemOnNpcPacket = (player, packet) => { const { buffer } = packet; diff --git a/src/net/inbound-packets/item-on-object-packet.js b/src/net/inbound-packets/item-on-object-packet.js index 4ad76289f..06ca26c3e 100644 --- a/src/net/inbound-packets/item-on-object-packet.js +++ b/src/net/inbound-packets/item-on-object-packet.js @@ -1,8 +1,8 @@ -import { widgets } from '../../world/config/widget'; import { logger } from '@runejs/core'; import { Position } from '../../world/position'; import { cache, world } from '../../game-server'; import { actionHandler } from '../../world/action'; +import { widgets } from '../../config'; const itemOnObjectPacket = (player, packet) => { const { buffer } = packet; diff --git a/src/net/inbound-packets/widgets-closed-packet.js b/src/net/inbound-packets/widgets-closed-packet.js index 271fabc44..61ceb792b 100644 --- a/src/net/inbound-packets/widgets-closed-packet.js +++ b/src/net/inbound-packets/widgets-closed-packet.js @@ -1,5 +1,5 @@ export default { opcode: 176, size: 0, - handler: player => player.closeActiveWidgets(false) + handler: player => player.interfaceState.closeAllSlots() }; diff --git a/src/net/outbound-packets.ts b/src/net/outbound-packets.ts index 8c7db184a..370370cf4 100644 --- a/src/net/outbound-packets.ts +++ b/src/net/outbound-packets.ts @@ -312,10 +312,15 @@ export class OutboundPackets { this.queue(new Packet(180)); } - public showScreenWidget(widgetId: number): void { - const packet = new Packet(118); + public showScreenOverlayWidget(widgetId: number): void { + const packet = new Packet(56); packet.put(widgetId, 'SHORT'); + this.queue(packet); + } + public showStandaloneScreenWidget(widgetId: number): void { + const packet = new Packet(118); + packet.put(widgetId, 'SHORT'); this.queue(packet); } @@ -407,6 +412,12 @@ export class OutboundPackets { this.queue(packet); } + public showTabWidget(widgetId: number): void { + const packet = new Packet(237); + packet.put(widgetId, 'SHORT'); + this.queue(packet); + } + public sendTabWidget(tabIndex: number, widgetId: number | null): void { if(widgetId < 0) { return; @@ -443,6 +454,12 @@ export class OutboundPackets { this.queue(packet); } + public showChatDialogue(widgetId: number): void { + const packet = new Packet(185); + packet.put(widgetId, 'SHORT'); + this.queue(packet); + } + public updateCarryWeight(weight: number): void { const packet = new Packet(171); packet.put(weight, 'SHORT'); diff --git a/src/plugins/buttons/logout-button-plugin.ts b/src/plugins/buttons/logout-button-plugin.ts index 4c49a22da..91b3e769c 100644 --- a/src/plugins/buttons/logout-button-plugin.ts +++ b/src/plugins/buttons/logout-button-plugin.ts @@ -1,6 +1,6 @@ import { buttonAction } from '@server/world/action/button-action'; -import { widgets } from '@server/world/config/widget'; import { world } from '@server/game-server'; +import { widgets } from '@server/config'; export const action: buttonAction = (details) => { const { player } = details; diff --git a/src/plugins/buttons/player-emotes-plugin.ts b/src/plugins/buttons/player-emotes-plugin.ts index 2697df070..d0cfd80e6 100644 --- a/src/plugins/buttons/player-emotes-plugin.ts +++ b/src/plugins/buttons/player-emotes-plugin.ts @@ -1,7 +1,7 @@ import { buttonAction } from '@server/world/action/button-action'; -import { widgets } from '@server/world/config/widget'; import { Player } from '@server/world/actor/player/player'; import { itemIds } from '@server/world/config/item-ids'; +import { widgets } from '@server/config'; interface Emote { animationId: number; diff --git a/src/plugins/buttons/player-setting-button-plugin.ts b/src/plugins/buttons/player-setting-button-plugin.ts index 96cc97fc6..27275bff2 100644 --- a/src/plugins/buttons/player-setting-button-plugin.ts +++ b/src/plugins/buttons/player-setting-button-plugin.ts @@ -1,5 +1,5 @@ import { buttonAction } from '@server/world/action/button-action'; -import { widgets } from '@server/world/config/widget'; +import { widgets } from '@server/config'; const buttonIds: number[] = [ 0, // walk/run diff --git a/src/plugins/combat/combat-styles.ts b/src/plugins/combat/combat-styles.ts index b15ba81ab..2e14f1b74 100644 --- a/src/plugins/combat/combat-styles.ts +++ b/src/plugins/combat/combat-styles.ts @@ -1,8 +1,8 @@ import { equipAction, EquipActionData } from '@server/world/action/equip-action'; import { ItemDetails, WeaponStyle, weaponWidgetIds } from '@server/config/item-config'; -import { widgets, widgetScripts } from '@server/world/config/widget'; +import { widgetScripts } from '@server/world/config/widget'; import { Player, playerInitAction } from '@server/world/actor/player/player'; -import { findItem } from '@server/config'; +import { findItem, widgets } from '@server/config'; import { buttonAction } from '@server/world/action/button-action'; import { combatStyles } from '@server/world/actor/combat'; import { serverConfig } from '@server/game-server'; diff --git a/src/plugins/commands/widget-commands.ts b/src/plugins/commands/widget-commands.ts index d8d23c0b8..3e8c5a07f 100644 --- a/src/plugins/commands/widget-commands.ts +++ b/src/plugins/commands/widget-commands.ts @@ -7,18 +7,18 @@ const action: commandAction = (details) => { const secondaryWidgetId: number = args.secondaryWidgetId as number; if(secondaryWidgetId === 1) { - player.activeWidget = { - type: 'SCREEN', - widgetId, - closeOnWalk: true - }; + player.interfaceState.openWidget(widgetId, { + slot: 'screen' + }); } else { - player.activeWidget = { - type: 'SCREEN_AND_TAB', - widgetId, - secondaryWidgetId, - closeOnWalk: true - }; + player.interfaceState.openWidget(widgetId, { + slot: 'screen', + multi: true + }); + player.interfaceState.openWidget(secondaryWidgetId, { + slot: 'tabarea', + multi: true + }); } }; diff --git a/src/plugins/dialogue/dialogue-option-plugin.ts b/src/plugins/dialogue/dialogue-option-plugin.ts index a93afdf82..b5bdee75b 100644 --- a/src/plugins/dialogue/dialogue-option-plugin.ts +++ b/src/plugins/dialogue/dialogue-option-plugin.ts @@ -11,8 +11,8 @@ const dialogueIds = [ * Handles a basic NPC/Player/Option/Text dialogue choice/action. */ export const action: widgetAction = (details) => { - const { player, childId } = details; - player.dialogueInteractionEvent.next(childId); + const { player, widgetId, childId } = details; + player.interfaceState.closeWidget(widgetId, childId); }; export default { type: 'widget_action', widgetIds: dialogueIds, action, cancelActions: true }; diff --git a/src/plugins/dialogue/item-selection-plugin.ts b/src/plugins/dialogue/item-selection-plugin.ts index 61a66103a..7d1c00237 100644 --- a/src/plugins/dialogue/item-selection-plugin.ts +++ b/src/plugins/dialogue/item-selection-plugin.ts @@ -4,8 +4,8 @@ import { widgetAction } from '@server/world/action/widget-action'; * Handles an item selection dialogue choice. */ export const action: widgetAction = (details) => { - const { player, childId } = details; - player.dialogueInteractionEvent.next(childId); + const { player, widgetId, childId } = details; + player.interfaceState.closeWidget(widgetId, childId); }; export default { type: 'widget_action', widgetIds: [ 303, 304, 305, 306, 307, 309 ], action, cancelActions: false }; diff --git a/src/plugins/items/buckets/empty-container-plugin.ts b/src/plugins/items/buckets/empty-container-plugin.ts index a21e14730..ffe390f8b 100644 --- a/src/plugins/items/buckets/empty-container-plugin.ts +++ b/src/plugins/items/buckets/empty-container-plugin.ts @@ -1,8 +1,8 @@ import { itemAction } from '@server/world/action/item-action'; -import { widgets } from '@server/world/config/widget'; import { soundIds } from '@server/world/config/sound-ids'; import { itemIds } from '@server/world/config/item-ids'; import { getItemFromContainer } from '@server/world/items/item-container'; +import { widgets } from '@server/config'; export const action: itemAction = (details) => { const { player, itemId, itemSlot } = details; diff --git a/src/plugins/items/drop-item-plugin.ts b/src/plugins/items/drop-item-plugin.ts index c0a0fd3aa..ee5d9dff8 100644 --- a/src/plugins/items/drop-item-plugin.ts +++ b/src/plugins/items/drop-item-plugin.ts @@ -1,9 +1,9 @@ -import { widgets } from '@server/world/config/widget'; import { itemAction } from '@server/world/action/item-action'; import { soundIds } from '@server/world/config/sound-ids'; import { getItemFromContainer } from '@server/world/items/item-container'; import { serverConfig } from '@server/game-server'; import { Rights } from '@server/world/actor/player/player'; +import { widgets } from '@server/config'; export const action: itemAction = ({ player, itemId, itemSlot }) => { const inventory = player.inventory; diff --git a/src/plugins/items/equipment/equip-item-plugin.ts b/src/plugins/items/equipment/equip-item-plugin.ts index 65c44710b..f483e66ff 100644 --- a/src/plugins/items/equipment/equip-item-plugin.ts +++ b/src/plugins/items/equipment/equip-item-plugin.ts @@ -1,5 +1,5 @@ -import { widgets } from '@server/world/config/widget'; import { itemAction } from '@server/world/action/item-action'; +import { widgets } from '@server/config'; export const action: itemAction = (details) => { const { player, itemId, itemSlot, itemDetails } = details; diff --git a/src/plugins/items/equipment/equipment-stats-plugin.ts b/src/plugins/items/equipment/equipment-stats-plugin.ts index 914430e87..5257f8315 100644 --- a/src/plugins/items/equipment/equipment-stats-plugin.ts +++ b/src/plugins/items/equipment/equipment-stats-plugin.ts @@ -1,6 +1,6 @@ import { buttonAction } from '@server/world/action/button-action'; -import { widgets } from '@server/world/config/widget'; import { Player } from '@server/world/actor/player/player'; +import { widgets } from '@server/config'; export function updateBonusStrings(player: Player): void { [ @@ -30,12 +30,14 @@ export const action: buttonAction = (details) => { player.outgoingPackets.sendUpdateAllWidgetItems(widgets.equipmentStats, player.equipment); player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, player.inventory); - player.activeWidget = { - widgetId: widgets.equipmentStats.widgetId, - secondaryWidgetId: widgets.inventory.widgetId, - type: 'SCREEN_AND_TAB', - closeOnWalk: true - }; + player.interfaceState.openWidget(widgets.equipmentStats.widgetId, { + multi: true, + slot: 'screen' + }); + player.interfaceState.openWidget(widgets.inventory.widgetId, { + multi: true, + slot: 'tabarea' + }); }; export default { type: 'button', widgetId: widgets.equipment.widgetId, buttonIds: 24, action }; diff --git a/src/plugins/items/equipment/unequip-item-plugin.ts b/src/plugins/items/equipment/unequip-item-plugin.ts index 073af7ba6..4cc0b492f 100644 --- a/src/plugins/items/equipment/unequip-item-plugin.ts +++ b/src/plugins/items/equipment/unequip-item-plugin.ts @@ -1,6 +1,6 @@ -import { widgets } from '@server/world/config/widget'; import { itemAction } from '@server/world/action/item-action'; import { getItemFromContainer } from '@server/world/items/item-container'; +import { widgets } from '@server/config'; export const action: itemAction = (details) => { const { player, itemId, itemSlot, itemDetails } = details; diff --git a/src/plugins/items/move-item-plugin.ts b/src/plugins/items/move-item-plugin.ts index 92d6c7896..98b561e7e 100644 --- a/src/plugins/items/move-item-plugin.ts +++ b/src/plugins/items/move-item-plugin.ts @@ -1,7 +1,7 @@ import { swapItemsAction } from '@server/world/action/swap-items-action'; -import { widgets } from '@server/world/config/widget'; import { ItemContainer } from '@server/world/items/item-container'; import { Player } from '@server/world/actor/player/player'; +import { widgets } from '@server/config'; type WidgetDetail = [ number, number, (player: Player) => ItemContainer ]; diff --git a/src/plugins/items/pickup-item-plugin.ts b/src/plugins/items/pickup-item-plugin.ts index 7fde8f28a..7c21e36ed 100644 --- a/src/plugins/items/pickup-item-plugin.ts +++ b/src/plugins/items/pickup-item-plugin.ts @@ -1,7 +1,7 @@ import { worldItemAction } from '@server/world/action/world-item-action'; import { Item } from '../../world/items/item'; -import { widgets } from '../../world/config/widget'; import { soundIds } from '@server/world/config/sound-ids'; +import { widgets } from '@server/config'; export const action: worldItemAction = ({ player, worldItem, itemDetails }) => { const inventory = player.inventory; diff --git a/src/plugins/items/pots/empty-pot-plugin.ts b/src/plugins/items/pots/empty-pot-plugin.ts index 9a5b97145..d0c7e67e5 100644 --- a/src/plugins/items/pots/empty-pot-plugin.ts +++ b/src/plugins/items/pots/empty-pot-plugin.ts @@ -1,10 +1,10 @@ import { itemAction } from '@server/world/action/item-action'; -import { widgets } from '@server/world/config/widget'; import { soundIds } from '@server/world/config/sound-ids'; import { RunePlugin } from '@server/plugins/plugin'; import { itemIds } from '@server/world/config/item-ids'; import { getItemFromContainer } from '@server/world/items/item-container'; import { ActionType } from '@server/world/action'; +import { widgets } from '@server/config'; export const action: itemAction = (details) => { const { player, itemId, itemSlot } = details; diff --git a/src/plugins/items/shopping/buy-from-shop-plugin.ts b/src/plugins/items/shopping/buy-from-shop-plugin.ts index 030d6a471..67fc65977 100644 --- a/src/plugins/items/shopping/buy-from-shop-plugin.ts +++ b/src/plugins/items/shopping/buy-from-shop-plugin.ts @@ -1,9 +1,8 @@ import { itemAction } from '@server/world/action/item-action'; -import { widgets } from '@server/world/config/widget'; import { Item } from '@server/world/items/item'; import { getItemFromContainer, ItemContainer } from '@server/world/items/item-container'; import { itemIds } from '@server/world/config/item-ids'; -import { findItem } from '@server/config'; +import { findItem, widgets } from '@server/config'; import { Shop } from '@server/config/shop-config'; @@ -16,7 +15,7 @@ function removeCoins(inventory: ItemContainer, coinsIndex: number, cost: number) export const action: itemAction = (details) => { const { player, itemId, itemSlot, widgetId, option } = details; - if(!player.activeWidget || player.activeWidget.widgetId !== widgetId) { + if(!player.interfaceState.findWidget(widgetId)) { return; } diff --git a/src/plugins/items/shopping/item-value-plugin.ts b/src/plugins/items/shopping/item-value-plugin.ts index 01639ce68..6b7235a4a 100644 --- a/src/plugins/items/shopping/item-value-plugin.ts +++ b/src/plugins/items/shopping/item-value-plugin.ts @@ -1,6 +1,6 @@ import { itemAction } from '@server/world/action/item-action'; -import { widgets } from '@server/world/config/widget'; import { Shop } from '@server/config/shop-config'; +import { widgets } from '@server/config'; export const shopSellValueAction: itemAction = ({ player, itemDetails }) => { const itemValue = itemDetails.value || 1; diff --git a/src/plugins/items/shopping/sell-to-shop.ts b/src/plugins/items/shopping/sell-to-shop.ts index e16d4797b..6ab56ed2d 100644 --- a/src/plugins/items/shopping/sell-to-shop.ts +++ b/src/plugins/items/shopping/sell-to-shop.ts @@ -1,14 +1,14 @@ import { itemAction } from '@server/world/action/item-action'; -import { widgets } from '@server/world/config/widget'; import { itemIds } from '@server/world/config/item-ids'; import { getItemFromContainer } from '@server/world/items/item-container'; import { Shop } from '@server/config/shop-config'; +import { widgets } from '@server/config'; export const action: itemAction = (details) => { const { player, itemId, itemSlot, option, itemDetails } = details; - if(!player.activeWidget || player.activeWidget.widgetId !== widgets.shop.widgetId) { + if(!player.interfaceState.findWidget(widgets.shop.widgetId)) { return; } diff --git a/src/plugins/items/swap-items-plugin.ts b/src/plugins/items/swap-items-plugin.ts index 7128ffaff..1c78a4f6b 100644 --- a/src/plugins/items/swap-items-plugin.ts +++ b/src/plugins/items/swap-items-plugin.ts @@ -1,7 +1,7 @@ import { swapItemsAction } from '@server/world/action/swap-items-action'; -import { widgets } from '@server/world/config/widget'; import { ItemContainer } from '@server/world/items/item-container'; import { Player } from '@server/world/actor/player/player'; +import { widgets } from '@server/config'; type WidgetDetail = [ number, number, (player: Player) => ItemContainer ]; diff --git a/src/plugins/npcs/al-kharid/karim-plugin.ts b/src/plugins/npcs/al-kharid/karim-plugin.ts index 651d8af64..eec5c6406 100644 --- a/src/plugins/npcs/al-kharid/karim-plugin.ts +++ b/src/plugins/npcs/al-kharid/karim-plugin.ts @@ -1,7 +1,7 @@ import { npcAction } from '@server/world/action/npc-action'; import { itemIds } from '@server/world/config/item-ids'; -import { widgets } from '@server/world/config/widget'; import { dialogue, Emote, execute } from '@server/world/actor/dialogue'; +import { widgets } from '@server/config'; const talkToAction : npcAction = (details) => { const { player, npc } = details; diff --git a/src/plugins/npcs/varrock/blue-moon-inn-plugin.ts b/src/plugins/npcs/varrock/blue-moon-inn-plugin.ts index 4fdc8fddf..e2e08bf60 100644 --- a/src/plugins/npcs/varrock/blue-moon-inn-plugin.ts +++ b/src/plugins/npcs/varrock/blue-moon-inn-plugin.ts @@ -1,7 +1,7 @@ import { npcAction } from '@server/world/action/npc-action'; import { dialogue, Emote, execute } from '@server/world/actor/dialogue'; import { itemIds } from '@server/world/config/item-ids'; -import { widgets } from '@server/world/config/widget'; +import { widgets } from '@server/config'; const talkToBartender : npcAction = (details) => { diff --git a/src/plugins/npcs/varrock/master-smithing-tutor-plugin.ts b/src/plugins/npcs/varrock/master-smithing-tutor-plugin.ts index d7c681847..8220dde32 100644 --- a/src/plugins/npcs/varrock/master-smithing-tutor-plugin.ts +++ b/src/plugins/npcs/varrock/master-smithing-tutor-plugin.ts @@ -1,7 +1,7 @@ import { npcAction } from '@server/world/action/npc-action'; import { dialogue, Emote, execute, goto } from '@server/world/actor/dialogue'; import { itemIds } from '@server/world/config/item-ids'; -import { widgets } from '@server/world/config/widget'; +import { widgets } from '@server/config'; const talkTo : npcAction = (details) => { diff --git a/src/plugins/objects/bank/bank-plugin.ts b/src/plugins/objects/bank/bank-plugin.ts index ac6ec8672..203b90025 100644 --- a/src/plugins/objects/bank/bank-plugin.ts +++ b/src/plugins/objects/bank/bank-plugin.ts @@ -1,11 +1,12 @@ import { objectIds } from '@server/world/config/object-ids'; -import { widgets, widgetScripts } from '@server/world/config/widget'; +import { widgetScripts } from '@server/world/config/widget'; import { objectAction } from '@server/world/action/object-action'; import { ItemContainer } from '@server/world/items/item-container'; import { itemAction } from '@server/world/action/item-action'; import { fromNote, Item, toNote } from '@server/world/items/item'; import { buttonAction } from '@server/world/action/button-action'; import { dialogue, Emote, execute } from '@server/world/actor/dialogue'; +import { widgets } from '@server/config'; const buttonIds: number[] = [ @@ -16,12 +17,14 @@ const buttonIds: number[] = [ ]; export const openBankInterface: objectAction = ({ player }) => { - player.activeWidget = { - widgetId: widgets.bank.screenWidget.widgetId, - secondaryWidgetId: widgets.bank.tabWidget.widgetId, - type: 'SCREEN_AND_TAB', - closeOnWalk: true - }; + player.interfaceState.openWidget(widgets.bank.screenWidget.widgetId, { + slot: 'screen', + multi: true + }); + player.interfaceState.openWidget(widgets.bank.tabWidget.widgetId, { + slot: 'tabarea', + multi: true + }); player.outgoingPackets.sendUpdateAllWidgetItems(widgets.bank.tabWidget, player.inventory); player.outgoingPackets.sendUpdateAllWidgetItems(widgets.bank.screenWidget, player.bank); @@ -30,18 +33,14 @@ export const openBankInterface: objectAction = ({ player }) => { }; export const openPinSettings: objectAction = ({ player }) => { - player.activeWidget = { - widgetId: widgets.bank.pinSettingsWidget.widgetId, - type: 'SCREEN', - closeOnWalk: true - }; + player.interfaceState.openWidget(widgets.bank.pinSettingsWidget.widgetId, { + slot: 'screen' + }); }; export const depositItem: itemAction = (details) => { // Check if player might be spawning widget clientside - if (!details.player.activeWidget || - !(details.player.activeWidget.widgetId === widgets.bank.screenWidget.widgetId) || - !(details.player.activeWidget.secondaryWidgetId === widgets.bank.tabWidget.widgetId)) { + if (!details.player.interfaceState.findWidget(widgets.bank.screenWidget.widgetId)) { return; } @@ -107,9 +106,7 @@ export const depositItem: itemAction = (details) => { export const withdrawItem: itemAction = (details) => { // Check if player might be spawning widget clientside - if (!details.player.activeWidget || - !(details.player.activeWidget.widgetId === widgets.bank.screenWidget.widgetId) || - !(details.player.activeWidget.secondaryWidgetId === widgets.bank.tabWidget.widgetId)) { + if (!details.player.interfaceState.findWidget(widgets.bank.screenWidget.widgetId)) { return; } // Check if the player has the item diff --git a/src/plugins/quests/goblin-diplomacy-tutorial/index.ts b/src/plugins/quests/goblin-diplomacy-tutorial/index.ts index 109b42eda..6a048af3f 100644 --- a/src/plugins/quests/goblin-diplomacy-tutorial/index.ts +++ b/src/plugins/quests/goblin-diplomacy-tutorial/index.ts @@ -1,5 +1,4 @@ import { defaultPlayerTabWidgets, Player, playerInitAction, Tabs } from '@server/world/actor/player/player'; -import { widgets } from '@server/world/config/widget'; import { serverConfig, world } from '@server/game-server'; import { npcAction } from '@server/world/action/npc-action'; import uuidv4 from 'uuid/v4'; @@ -7,7 +6,7 @@ import { Npc } from '@server/world/actor/npc/npc'; import { logger } from '@runejs/core'; import { Position } from '@server/world/position'; import { WorldInstance } from '@server/world/instances'; -import { findNpc } from '@server/config'; +import { findNpc, widgets } from '@server/config'; import { updateCombatStyleWidget } from '@server/plugins/combat/combat-styles'; import { runescapeGuideDialogueHandler } from '@server/plugins/quests/goblin-diplomacy-tutorial/runescape-guide-dialogue'; import { harlanDialogueHandler } from '@server/plugins/quests/goblin-diplomacy-tutorial/melee-tutor-dialogue'; @@ -16,6 +15,7 @@ import { Subject } from 'rxjs'; import { dialogue } from '@server/world/actor/dialogue'; import { take } from 'rxjs/operators'; import { equipAction } from '@server/world/action/equip-action'; +import { buttonAction } from '@server/world/action/button-action'; export const tutorialTabWidgetOrder = [ @@ -107,11 +107,17 @@ export const startTutorial = async (player: Player): Promise => { player.inventory.add('rs:coins'); player.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, player.inventory); - await player.openInteractiveWidget({ - widgetId: widgets.characterDesign, - type: 'SCREEN', - disablePlayerMovement: true - }).toPromise(); + await dialogue([ player ], [ + titled => [ `Getting Started`, `\nCreate your character!` ] + ], { + permanent: true + }); + + player.interfaceState.openWidget(widgets.characterDesign, { + slot: 'screen' + }); + + await player.interfaceState.widgetClosed('screen'); }; export async function spawnGoblinBoi(player: Player, spawnPoint: 'beginning' | 'end'): Promise { @@ -209,6 +215,10 @@ const trainingSwordEquipAction: equipAction = async ({ player, itemDetails }) => } }; +const createCharacterAction: buttonAction = ({ player }): void => { + player.interfaceState.closeAllSlots(); +}; + export default [ { type: 'player_init', @@ -233,5 +243,10 @@ export default [ equipType: 'EQUIP', action: trainingSwordEquipAction, itemIds: [ 9703, 9704 ] + }, + { + type: 'button', + widgetId: widgets.characterDesign, + action: createCharacterAction } ]; diff --git a/src/plugins/quests/goblin-diplomacy-tutorial/stage-handler.ts b/src/plugins/quests/goblin-diplomacy-tutorial/stage-handler.ts index f22544d35..8c54ad54c 100644 --- a/src/plugins/quests/goblin-diplomacy-tutorial/stage-handler.ts +++ b/src/plugins/quests/goblin-diplomacy-tutorial/stage-handler.ts @@ -1,14 +1,11 @@ import { Player, Tabs } from '@server/world/actor/player/player'; import { dialogue } from '@server/world/actor/dialogue'; -import { Subject } from 'rxjs'; -import { take } from 'rxjs/operators'; import { handleTutorial, npcHint, showTabWidgetHint, spawnGoblinBoi, startTutorial, unlockAvailableTabs } from '@server/plugins/quests/goblin-diplomacy-tutorial/index'; -import { Position } from '@server/world/position'; import { schedule } from '@server/task/task'; import { world } from '@server/game-server'; import { findNpc } from '@server/config'; @@ -42,13 +39,11 @@ export const goblinDiplomacyStageHandler: { [key: number]: (player: Player) => v unlockAvailableTabs(player, 1); - if(!player.activeWidget) { - dialogue([ player ], [ - titled => [ `Getting Started`, `\nSpeak with the Guide to continue.` ] - ], { - permanent: true - }); - } + dialogue([ player ], [ + titled => [ `Getting Started`, `\nSpeak with the Guide to continue.` ] + ], { + permanent: true + }); }, 20: player => { showTabWidgetHint(player, Tabs.friends, 2, 25, @@ -71,13 +66,11 @@ export const goblinDiplomacyStageHandler: { [key: number]: (player: Player) => v unlockAvailableTabs(player, 4); - if(!player.activeWidget) { - dialogue([ player ], [ - titled => [ `Continue`, `\nSpeak with the Guide to continue.` ] - ], { - permanent: true - }); - } + dialogue([ player ], [ + titled => [ `Continue`, `\nSpeak with the Guide to continue.` ] + ], { + permanent: true + }); }, 40: player => { showTabWidgetHint(player, Tabs.music, 5, 45, @@ -89,26 +82,22 @@ export const goblinDiplomacyStageHandler: { [key: number]: (player: Player) => v npcHint(player, 'rs:runescape_guide'); unlockAvailableTabs(player, 5); - if(!player.activeWidget) { - dialogue([ player ], [ - titled => [ `Continue`, `\nSpeak with the Guide to continue.` ] - ], { - permanent: true - }); - } + dialogue([ player ], [ + titled => [ `Continue`, `\nSpeak with the Guide to continue.` ] + ], { + permanent: true + }); }, 50: player => { player.metadata.blockObjectInteractions = false; npcHint(player, 'rs:melee_combat_tutor'); unlockAvailableTabs(player, 5); - if(!player.activeWidget) { - dialogue([ player ], [ - titled => [ `Continue`, `\nSpeak with the Melee Combat Tutor to continue.` ] - ], { - permanent: true - }); - } + dialogue([ player ], [ + titled => [ `Continue`, `\nSpeak with the Melee Combat Tutor to continue.` ] + ], { + permanent: true + }); }, 55: player => { showTabWidgetHint(player, Tabs.inventory, 6, 60, diff --git a/src/plugins/quests/quest-journal-plugin.ts b/src/plugins/quests/quest-journal-plugin.ts index 2c025f364..3c399d5b1 100644 --- a/src/plugins/quests/quest-journal-plugin.ts +++ b/src/plugins/quests/quest-journal-plugin.ts @@ -1,7 +1,7 @@ import { buttonAction } from '@server/world/action/button-action'; -import { widgets } from '@server/world/config/widget'; import { wrapText } from '@server/util/strings'; import { pluginActions } from '@server/game-server'; +import { widgets } from '@server/config'; export const action: buttonAction = (details) => { const { player, buttonId } = details; @@ -15,7 +15,7 @@ export const action: buttonAction = (details) => { (playerQuest) => playerQuest.questId === quest.questTabId ); - let playerStage = "NOT_STARTED"; + let playerStage = 'NOT_STARTED'; if (playerQuest && playerQuest.stage) { playerStage = playerQuest.stage; } @@ -52,11 +52,10 @@ export const action: buttonAction = (details) => { } } - player.activeWidget = { - widgetId: widgets.questJournal, - type: 'SCREEN', - closeOnWalk: true - }; + player.interfaceState.openWidget(widgets.questJournal, { + slot: 'screen', + multi: false + }); }; export default { type: 'button', widgetId: widgets.questTab, action }; diff --git a/src/plugins/rune.js b/src/plugins/rune.js index feaae3781..83fb692b3 100644 --- a/src/plugins/rune.js +++ b/src/plugins/rune.js @@ -13,3 +13,4 @@ export * from '../world/actor/update-flags'; export * from '../world/actor/skills'; export * from '../world/actor/player/achievements'; export * from '../task/task'; +export { widgets } from '../config'; diff --git a/src/plugins/skills/crafting/spinning-wheel-plugin.ts b/src/plugins/skills/crafting/spinning-wheel-plugin.ts index 0ab6f6d69..646e0837d 100644 --- a/src/plugins/skills/crafting/spinning-wheel-plugin.ts +++ b/src/plugins/skills/crafting/spinning-wheel-plugin.ts @@ -6,9 +6,9 @@ import { itemIds } from '@server/world/config/item-ids'; import { loopingAction } from '@server/world/action'; import { Skill } from '@server/world/actor/skills'; import { cache } from '@server/game-server'; -import { widgets } from '@server/world/config/widget'; import { animationIds } from '@server/world/config/animation-ids'; import { objectIds } from '@server/world/config/object-ids'; +import { widgets } from '@server/config'; interface Spinnable { input: number | number[]; @@ -72,11 +72,9 @@ const widgetButtonIds: Map = new Map { - details.player.activeWidget = { - widgetId: widgets.whatWouldYouLikeToSpin, - type: 'SCREEN', - closeOnWalk: true - }; + details.player.interfaceState.openWidget(widgets.whatWouldYouLikeToSpin, { + slot: 'screen' + }); }; const spinProduct: any = (details: ButtonActionData, spinnable: Spinnable, count: number) => { @@ -139,13 +137,13 @@ const spinProduct: any = (details: ButtonActionData, spinnable: Spinnable, count export const buttonClicked: buttonAction = (details) => { // Check if player might be spawning widget clientside - if (!details.player.activeWidget || !(details.player.activeWidget.widgetId === 459)) { + if (!details.player.interfaceState.findWidget(459)) { return; } const product = widgetButtonIds.get(details.buttonId); // Close the widget as it is no longer needed - details.player.closeActiveWidgets(); + details.player.interfaceState.closeAllSlots(); if (!details.player.skills.hasLevel(Skill.CRAFTING, product.spinnable.requiredLevel)) { details.player.sendMessage(`You need a crafting level of ${product.spinnable.requiredLevel} to craft ${cache.itemDefinitions.get(product.spinnable.output).name.toLowerCase()}.`, true); diff --git a/src/plugins/skills/level-up-dialogue-plugin.ts b/src/plugins/skills/level-up-dialogue-plugin.ts index aa499fdcc..4ddae86e6 100644 --- a/src/plugins/skills/level-up-dialogue-plugin.ts +++ b/src/plugins/skills/level-up-dialogue-plugin.ts @@ -17,7 +17,7 @@ const widgetIds = [ */ export const action: widgetAction = (details) => { const { player } = details; - player.closeActiveWidgets(); + player.interfaceState.closeChatOverlayWidget(); }; export default { type: 'widget_action', widgetIds, action, cancelActions: false }; diff --git a/src/plugins/skills/prayer.js b/src/plugins/skills/prayer.js index 91b94cd21..9655029b2 100644 --- a/src/plugins/skills/prayer.js +++ b/src/plugins/skills/prayer.js @@ -3,7 +3,7 @@ import { soundIds } from '../../world/config/sound-ids'; import { animationIds } from '../../world/config/animation-ids'; import { Achievements, giveAchievement } from '../../world/actor/player/achievements'; import { Skill } from '../../world/actor/skills'; -import { widgets } from '../../world/config/widget'; +import { widgets } from '../../config'; const action = async details => { const { player, itemSlot } = details; diff --git a/src/plugins/skills/runecrafting/runecrafting-crafting.ts b/src/plugins/skills/runecrafting/runecrafting-crafting.ts index d241c4f8c..f68429c1b 100644 --- a/src/plugins/skills/runecrafting/runecrafting-crafting.ts +++ b/src/plugins/skills/runecrafting/runecrafting-crafting.ts @@ -4,7 +4,6 @@ import { objectAction, ObjectActionData } from '@server/world/action/object-action'; import { Skill } from '@server/world/actor/skills'; -import { widgets } from '@server/world/config/widget'; import { altars, combinationRunes, getEntityByAttr, @@ -16,6 +15,7 @@ import { RunecraftingCombinationRune } from '@server/plugins/skills/runecrafting import { randomBetween } from '@server/util/num'; import { itemIds } from '@server/world/config/item-ids'; import { cache } from '@server/game-server'; +import { widgets } from '@server/config'; const craftRune: objectAction = (details: ObjectActionData) => { diff --git a/src/plugins/skills/skill-guide-plugin.ts b/src/plugins/skills/skill-guide-plugin.ts index 3dafac567..0d22ddfd7 100644 --- a/src/plugins/skills/skill-guide-plugin.ts +++ b/src/plugins/skills/skill-guide-plugin.ts @@ -4,7 +4,7 @@ import { JSON_SCHEMA, safeLoad } from 'js-yaml'; import { readFileSync } from 'fs'; import { Player } from '@server/world/actor/player/player'; import { widgetAction } from '@server/world/action/widget-action'; -import { widgets } from '@server/world/config/widget'; +import { widgets } from '@server/config'; // @TODO fix me! @@ -93,11 +93,10 @@ function loadGuide(player: Player, guideId: number, subGuideId: number = 0, refr } } - player.activeWidget = { - widgetId: widgets.skillGuide, - type: 'SCREEN', - closeOnWalk: true - }; + player.interfaceState.openWidget(widgets.skillGuide, { + slot: 'screen', + multi: false + }); player.metadata['activeSkillGuide'] = guideId; } diff --git a/src/plugins/skills/smithing/smelting-plugin.ts b/src/plugins/skills/smithing/smelting-plugin.ts index 51fc24edd..e238d399e 100644 --- a/src/plugins/skills/smithing/smelting-plugin.ts +++ b/src/plugins/skills/smithing/smelting-plugin.ts @@ -2,7 +2,6 @@ import { Item } from '@server/world/items/item'; import { ItemContainer } from '@server/world/items/item-container'; import { objectIds } from '@server/world/config/object-ids'; import { objectAction, ObjectActionData } from '@server/world/action/object-action'; -import { widgets } from '@server/world/config/widget'; import { buttonAction, ButtonActionData } from '@server/world/action/button-action'; import { itemIds } from '@server/world/config/item-ids'; import { Subscription } from 'rxjs'; @@ -12,6 +11,7 @@ import { loopingAction } from '@server/world/action'; import { animationIds } from '@server/world/config/animation-ids'; import { soundIds } from '@server/world/config/sound-ids'; import { colors } from '@server/util/colors'; +import { widgets } from '@server/config'; export interface Bar { barId: number; @@ -109,11 +109,9 @@ const RUNEITE : Bar = { }; export const openSmeltingInterface: objectAction = (details) => { - details.player.activeWidget = { - widgetId: widgets.furnace.widgetId, - type: 'CHAT', - closeOnWalk: true - }; + details.player.interfaceState.openWidget(widgets.furnace.widgetId, { + slot: 'chatbox' + }) loadSmeltingInterface(details); }; @@ -259,13 +257,13 @@ const smeltProduct = (details: ButtonActionData, bar: Bar, count: number) => { export const buttonClicked : buttonAction = (details) => { // Check if player might be spawning widget clientside - if (!details.player.activeWidget || !(details.player.activeWidget.widgetId === widgets.furnace.widgetId)) { + if (!details.player.interfaceState.findWidget(widgets.furnace.widgetId)) { return; } const product = widgetButtonIds.get(details.buttonId); - details.player.closeActiveWidgets(); + details.player.interfaceState.closeAllSlots(); if (!product.takesInput) { smeltProduct(details, product.bar, product.count); @@ -288,7 +286,7 @@ export const buttonClicked : buttonAction = (details) => { export default [ { type: 'object_action', - objectIds: [objectIds.furnace], + objectIds: [objectIds.furnace, 11666], options: ['smelt'], walkTo: true, action: openSmeltingInterface diff --git a/src/world/actor/dialogue.ts b/src/world/actor/dialogue.ts index 898a6e67d..e812f7b03 100644 --- a/src/world/actor/dialogue.ts +++ b/src/world/actor/dialogue.ts @@ -6,6 +6,7 @@ import _ from 'lodash'; import { wrapText } from '@server/util/strings'; import { take } from 'rxjs/operators'; import { findNpc } from '@server/config'; +import { lastValueFrom } from 'rxjs'; export enum Emote { POMPOUS = 'POMPOUS', @@ -518,34 +519,30 @@ async function runDialogueAction(player: Player, dialogueAction: string | Dialog } if(tag === undefined && widgetId) { - let closeOnWalk = true; - if(additionalOptions && additionalOptions.closeOnWalk !== undefined) { - closeOnWalk = additionalOptions.closeOnWalk; - } - const permanent = additionalOptions?.permanent || false; - player.activeWidget = { - widgetId: widgetId, - type: 'CHAT', - closeOnWalk, - permanent - }; + if(permanent) { + player.interfaceState.openChatOverlayWidget(widgetId); + } else { + player.interfaceState.openWidget(widgetId, { + slot: 'chatbox', + multi: false + }); - const dialogueChoice = await Promise.race([ player.dialogueInteractionEvent.pipe(take(1)).toPromise(), - player.activeWidget.closed.pipe(take(1)).toPromise() ]); + const widgetClosedEvent = await player.interfaceState.widgetClosed('chatbox'); - if(dialogueChoice === undefined) { - throw new Error('Dialogue Cancelled'); - } + if(widgetClosedEvent.data === undefined) { + throw new Error('Dialogue Cancelled.'); + } - if(isOptions && typeof dialogueChoice === 'number') { - const optionsAction = dialogueAction as OptionsDialogueAction; - const options = Object.keys(optionsAction.options); - const trees = options.map(option => optionsAction.options[option]); - const tree: ParsedDialogueTree = trees[dialogueChoice - 1]; - if(tree && tree.length !== 0) { - await runParsedDialogue(player, tree, tag, additionalOptions); + if(isOptions && typeof widgetClosedEvent.data === 'number') { + const optionsAction = dialogueAction as OptionsDialogueAction; + const options = Object.keys(optionsAction.options); + const trees = options.map(option => optionsAction.options[option]); + const tree: ParsedDialogueTree = trees[widgetClosedEvent.data - 1]; + if(tree && tree.length !== 0) { + await runParsedDialogue(player, tree, tag, additionalOptions); + } } } } @@ -556,7 +553,6 @@ async function runDialogueAction(player: Player, dialogueAction: string | Dialog async function runParsedDialogue(player: Player, dialogueTree: ParsedDialogueTree, tag?: string, additionalOptions?: AdditionalOptions): Promise { for(let i = 0; i < dialogueTree.length; i++) { tag = await runDialogueAction(player, dialogueTree[i], tag, additionalOptions); - player.activeWidget = null; } return tag === undefined; @@ -584,7 +580,6 @@ export async function dialogue(participants: (Player | NpcParticipant)[], dialog runParsedDialogue(player, parsedDialogueTree, undefined, additionalOptions).then(() => { resolve(); }).catch(error => { - player.activeWidget = null; reject(error); }); }); @@ -592,8 +587,10 @@ export async function dialogue(participants: (Player | NpcParticipant)[], dialog try { await run(); + player.interfaceState.closeAllSlots(); return true; } catch(error) { + player.interfaceState.closeAllSlots(); logger.warn(`Dialogue cancelled.`); return false; } @@ -681,11 +678,10 @@ export async function itemSelectionDialogue(player: Player, type: 'COOKING' | 'M }); return new Promise((resolve, reject) => { - player.activeWidget = { - widgetId, - type: 'CHAT', - closeOnWalk: true - }; + player.interfaceState.openWidget(widgetId, { + slot: 'chatbox', + multi: true + }); let actionsSub = player.actionsCancelled.subscribe(() => { actionsSub.unsubscribe(); @@ -693,7 +689,7 @@ export async function itemSelectionDialogue(player: Player, type: 'COOKING' | 'M }); const interactionSub = player.dialogueInteractionEvent.subscribe(childId => { - if(!player.activeWidget || player.activeWidget.widgetId !== widgetId) { + if(!player.interfaceState.widgetOpen('chatbox', widgetId)) { interactionSub.unsubscribe(); actionsSub.unsubscribe(); reject('Active Widget Mismatch'); @@ -739,10 +735,10 @@ export async function itemSelectionDialogue(player: Player, type: 'COOKING' | 'M interactionSub.unsubscribe(); if(input < 1 || input > 2147483647) { - player.closeActiveWidgets(); + player.interfaceState.closeWidget('chatbox'); reject('Invalid User Amount Input'); } else { - player.closeActiveWidgets(); + player.interfaceState.closeWidget('chatbox'); resolve({ itemId, amount: input } as ItemSelection); } }); @@ -753,7 +749,7 @@ export async function itemSelectionDialogue(player: Player, type: 'COOKING' | 'M actionsSub.unsubscribe(); interactionSub.unsubscribe(); - player.closeActiveWidgets(); + player.interfaceState.closeWidget('chatbox'); resolve({ itemId, amount } as ItemSelection); } }); diff --git a/src/world/actor/player/dialogue-action.ts b/src/world/actor/player/dialogue-action.ts index 564fd4058..c4833c78b 100644 --- a/src/world/actor/player/dialogue-action.ts +++ b/src/world/actor/player/dialogue-action.ts @@ -137,12 +137,9 @@ export class DialogueAction { } return new Promise((resolve, reject) => { - this.p.activeWidget = { - widgetId: widgetId, - type: 'CHAT', - closeOnWalk: true, - forceClosed: () => reject(new WidgetsClosedWarning()) - }; + this.p.interfaceState.openWidget(widgetId, { + slot: 'chatbox' + }) const sub = this.p.dialogueInteractionEvent.subscribe(action => { sub.unsubscribe(); diff --git a/src/world/actor/player/interface-state.ts b/src/world/actor/player/interface-state.ts new file mode 100644 index 000000000..869fdca76 --- /dev/null +++ b/src/world/actor/player/interface-state.ts @@ -0,0 +1,291 @@ +import { Player } from '@server/world/actor/player/player'; +import { ItemContainer } from '@server/world/items/item-container'; +import { Subject, lastValueFrom } from 'rxjs'; +import { filter, take } from 'rxjs/operators'; + + +export type TabType = 'combat' | 'skills' | 'quests' | 'inventory' | 'equipment' | 'prayers' | + 'spells' | 'friends' | 'ignores' | 'logout' | 'emotes' | 'settings' | 'music'; + +export type GameInterfaceSlot = 'full' | 'screen' | 'chatbox' | 'tabarea'; + + +export const tabIndex: { [key: string]: number } = { + 'combat': 0, + 'skills': 1, + 'quests': 2, + 'inventory': 3, + 'equipment': 4, + 'prayers': 5, + 'spells': 6, + 'friends': 8, + 'ignores': 9, + 'logout': 10, + 'emotes': 11, + 'settings': 12, + 'music': 13 +}; + + +export interface WidgetOptions { + slot: GameInterfaceSlot; + multi?: boolean; + queued?: boolean; + containerId?: number; + container?: ItemContainer; +} + + +export class Widget { + + public widgetId: number; + public slot: GameInterfaceSlot; + public multi: boolean = false; + public queued: boolean = false; + public containerId: number; + public container: ItemContainer = null; + + public constructor(interfaceId: number, options: WidgetOptions) { + const { slot, multi, queued, containerId, container } = options; + + this.widgetId = interfaceId; + this.slot = slot; + this.multi = multi || false; + this.queued = queued || false; + this.containerId = containerId || -1; + this.container = container || null; + } + +} + +interface WidgetClosedEvent { + widget: Widget; + data?: number; +} + +/** + * Control's a Player's Game Interface state. + */ +export class InterfaceState { + + public readonly tabs: { [key: string]: Widget | null }; + public readonly widgetSlots: { [key: string]: Widget | null }; + public readonly closed: Subject = new Subject(); + private readonly player: Player; + private _screenOverlayWidget: number | null; + private _chatOverlayWidget: number | null; + + public constructor(player: Player) { + this.tabs = { + 'combat': null, + 'skills': null, + 'quests': null, + 'inventory': null, + 'equipment': null, + 'prayers': null, + 'spells': null, + 'friends': null, + 'ignores': null, + 'logout': null, + 'emotes': null, + 'settings': null, + 'music': null + }; + + this.widgetSlots = {}; + this._screenOverlayWidget = null; + this._chatOverlayWidget = null; + this.clearSlots(); + + this.player = player; + } + + public openChatOverlayWidget(widgetId: number): void { + this._chatOverlayWidget = widgetId; + this.player.outgoingPackets.showChatDialogue(widgetId); + } + + public closeChatOverlayWidget(): void { + this._chatOverlayWidget = null; + this.player.outgoingPackets.showChatDialogue(-1); + } + + public openScreenOverlayWidget(widgetId: number): void { + this._screenOverlayWidget = widgetId; + this.player.outgoingPackets.showScreenOverlayWidget(widgetId); + } + + public closeScreenOverlayWidget(): void { + this._screenOverlayWidget = null; + this.player.outgoingPackets.showScreenOverlayWidget(-1); + } + + public async widgetClosed(slot: GameInterfaceSlot): Promise { + return await lastValueFrom(this.closed.pipe( + filter(event => event.widget.slot === slot)).pipe(take(1))); + } + + public closeWidget(widgetId: number, data?: number): void; + public closeWidget(slot: GameInterfaceSlot, data?: number): void; + public closeWidget(i: GameInterfaceSlot | number, data?: number): void { + let widget: Widget | null; + + if(typeof i === 'number') { + widget = this.findWidget(i); + } else { + widget = this.widgetSlots[i] || null; + } + + if(!widget) { + return; + } + + this.closed.next({ widget, data }); + this.widgetSlots[widget.slot] = null; + } + + public openWidget(widgetId: number, options: WidgetOptions): void { + if(this.widgetOpen(options.slot, widgetId)) { + console.log('already open'); + return; + } + + const widget = new Widget(widgetId, options); + + if(widget.queued) { + // @TODO queued widgets + } + + if(widget.slot === 'full' || !widget.multi) { + this.clearSlots(); + } + + this.widgetSlots[widget.slot] = widget; + this.showWidget(widget); + } + + public setTab(type: TabType, widget: Widget | number | null): void { + if(widget && typeof widget === 'number') { + // Create a new tab interface instance + + let container: ItemContainer | undefined; + if(type === 'inventory') { + container = this.player.inventory; + } else if(type === 'equipment') { + container = this.player.equipment; + } + + widget = new Widget(widget, { + slot: 'tabarea', + multi: true, + container + }); + } + + widget = widget as Widget || null; + + this.tabs[type] = widget; + this.player.outgoingPackets.sendTabWidget(tabIndex[type], widget === null ? -1 : widget.widgetId); + } + + public getTab(type: TabType): Widget | null { + return this.tabs[type] || null; + } + + public findWidget(widgetId: number): Widget | null { + const slots: GameInterfaceSlot[] = Object.keys(this.widgetSlots) as GameInterfaceSlot[]; + let widget: Widget; + slots.forEach(slot => { + if(this.widgetSlots[slot]?.widgetId === widgetId) { + widget = this.widgetSlots[slot]; + } + }); + return widget || null; + } + + public widgetOpen(slot: GameInterfaceSlot, widgetId?: number): boolean { + if(widgetId === undefined) { + return this.getWidget(slot) !== null; + } else { + return this.getWidget(slot)?.widgetId === widgetId; + } + } + + public getWidget(slot: GameInterfaceSlot): Widget | null { + return this.widgetSlots[slot] || null; + } + + public closeAllSlots(): void { + const slots: GameInterfaceSlot[] = Object.keys(this.widgetSlots) as GameInterfaceSlot[]; + slots.forEach(slot => this.closeWidget(slot)); + this.player.outgoingPackets.closeActiveWidgets(); + } + + private showWidget(widget: Widget): void { + const { outgoingPackets: packets } = this.player; + const { widgetId, containerId, slot, multi } = widget; + + if(slot === 'full' || !multi) { + this.closeOthers(slot); + } + + if(slot === 'full' && containerId !== undefined) { + packets.showFullscreenWidget(widgetId, containerId); + } else if(slot === 'screen') { + const tabWidget = this.getWidget('tabarea'); + if(multi && tabWidget) { + packets.showScreenAndTabWidgets(widgetId, tabWidget.widgetId); + } else { + packets.showStandaloneScreenWidget(widgetId); + } + } else if(slot === 'chatbox') { + if(multi) { + // Dialogue Widget + packets.showChatDialogue(widgetId); + } else { + // Chatbox Widget + packets.showChatboxWidget(widgetId); + } + } else if(slot === 'tabarea') { + const screenWidget = this.getWidget('screen'); + if(multi) { + packets.showScreenAndTabWidgets(screenWidget.widgetId, widgetId); + } else { + packets.showTabWidget(widgetId); + } + } + } + + private closeOthers(openSlot: GameInterfaceSlot): void { + const slots: GameInterfaceSlot[] = Object.keys(this.widgetSlots) + .filter(slot => slot !== openSlot) as GameInterfaceSlot[]; + slots.forEach(slot => this.closeWidget(slot)); + } + + private clearSlots(): void { + this.widgetSlots.full = null; + this.widgetSlots.screen = null; + this.widgetSlots.chatbox = null; + this.widgetSlots.tabarea = null; + } + + public get fullScreenWidget(): Widget | null { + return this.widgetSlots.full || null; + } + + public get screenWidget(): Widget | null { + return this.widgetSlots.screen || null; + } + + public get chatboxWidget(): Widget | null { + return this.widgetSlots.chatbox || null; + } + + public get tabareaWidget(): Widget | null { + return this.widgetSlots.tabarea || null; + } + + public get screenOverlayWidget(): number | null { + return this._screenOverlayWidget; + } +} diff --git a/src/world/actor/player/player.ts b/src/world/actor/player/player.ts index 4a23e84d1..68b965a40 100644 --- a/src/world/actor/player/player.ts +++ b/src/world/actor/player/player.ts @@ -14,22 +14,20 @@ import { PlayerSave, PlayerSettings, QuestProgress, savePlayerData } from './player-data'; -import { PlayerWidget, widgets, widgetScripts } from '../../config/widget'; +import { PlayerWidget, widgetScripts } from '../../config/widget'; import { ContainerUpdateEvent, getItemFromContainer, ItemContainer } from '../../items/item-container'; import { Item } from '../../items/item'; import { Npc } from '../npc/npc'; import { NpcSyncTask } from './sync/npc-sync-task'; -import { Observable, Subject } from 'rxjs'; +import { Subject } from 'rxjs'; import { Chunk, ChunkUpdateItem } from '@server/world/map/chunk'; import { QuadtreeKey } from '@server/world'; import { daysSinceLastLogin } from '@server/util/time'; import { itemIds } from '@server/world/config/item-ids'; -import { dialogueAction } from '@server/world/actor/player/dialogue-action'; import { songs } from '@server/world/config/songs'; import { colors, hexToRgb, rgbTo16Bit } from '@server/util/colors'; import { ItemDefinition } from '@runejs/cache-parser'; import { PlayerCommandAction } from '@server/world/action/player-command-action'; -import { take } from 'rxjs/operators'; import { updateBonusStrings } from '@server/plugins/items/equipment/equipment-stats-plugin'; import { Action, actionHandler } from '@server/world/action'; import { @@ -39,12 +37,14 @@ import { ItemDetails, OffensiveBonuses, SkillBonuses } from '@server/config/item-config'; -import { findItem, npcIdMap } from '@server/config'; +import { findItem, npcIdMap, widgets } from '@server/config'; import { NpcDetails } from '@server/config/npc-config'; import { animationIds } from '@server/world/config/animation-ids'; import { combatStyles } from '@server/world/actor/combat'; import { WorldInstance, TileModifications } from '@server/world/instances'; import { Cutscene } from '@server/world/actor/player/cutscenes'; +import { InterfaceState } from '@server/world/actor/player/interface-state'; +import { dialogue } from '@server/world/actor/dialogue'; export const playerOptions: { option: string, index: number, placement: 'TOP' | 'BOTTOM' }[] = [ { @@ -108,6 +108,7 @@ export class Player extends Actor { public readonly numericInputEvent: Subject; public readonly dialogueInteractionEvent: Subject; public readonly personalInstance = new WorldInstance(uuidv4()); + public readonly interfaceState = new InterfaceState(this); public isLowDetail: boolean; public trackedPlayers: Player[]; public trackedNpcs: Npc[]; @@ -130,7 +131,6 @@ export class Player extends Actor { private _lastAddress: string; private firstTimePlayer: boolean; private _appearance: Appearance; - private _activeWidget: PlayerWidget; private queuedWidgets: PlayerWidget[]; private _bonuses: { offensive: OffensiveBonuses, defensive: DefensiveBonuses, skill: SkillBonuses }; private _carryWeight: number; @@ -156,7 +156,6 @@ export class Player extends Actor { this.npcUpdateTask = new NpcSyncTask(this); this.trackedPlayers = []; this.trackedNpcs = []; - this._activeWidget = null; this.queuedWidgets = []; this._carryWeight = 0; this._equipment = new ItemContainer(14); @@ -193,11 +192,10 @@ export class Player extends Actor { if(this.firstTimePlayer) { if(!serverConfig.tutorialEnabled) { - this.openInteractiveWidget({ - widgetId: widgets.characterDesign, - type: 'SCREEN', - disablePlayerMovement: true - }).toPromise(); + this.interfaceState.openWidget(widgets.characterDesign, { + slot: 'screen', + multi: false + }); } } else if(serverConfig.showWelcome && this.savedMetadata.tutorialComplete) { const daysSinceLogin = daysSinceLastLogin(this.loginDate); @@ -219,11 +217,10 @@ export class Player extends Actor { this.outgoingPackets.updateWidgetString(widgets.welcomeScreen, 21, `To start a subscripton:\\n1) Logout and return to the frontpage of this website.\\n2) Choose 'Start a new subscription'`); this.outgoingPackets.updateWidgetString(widgets.welcomeScreen, 19, `You are not a member.\\n\\nChoose to subscribe and\\nyou'll get loads of extra\\nbenefits and features.`); - this.activeWidget = { - widgetId: widgets.welcomeScreen, - secondaryWidgetId: widgets.welcomeScreenChildren.question, - type: 'FULLSCREEN' - }; + this.interfaceState.openWidget(widgets.welcomeScreen, { + slot: 'full', + containerId: widgets.welcomeScreenChildren.question + }); } for(const playerOption of playerOptions) { @@ -239,32 +236,18 @@ export class Player extends Actor { this.inventory.containerUpdated.subscribe(event => this.inventoryUpdated(event)); this.actionsCancelled.subscribe(type => { - let closeWidget = false; + let closeWidget: boolean; - const widget = this.activeWidget; - - if(widget && !widget.permanent) { - if(type === 'manual-movement' || type === 'pathing-movement') { - if(widget.closeOnWalk) { - closeWidget = true; - } - } else if(type === 'keep-widgets-open' || type === 'button' || type === 'widget') { - closeWidget = false; - } else { - closeWidget = true; - } + if(type === 'manual-movement' || type === 'pathing-movement') { + closeWidget = true; + } else if(type === 'keep-widgets-open' || type === 'button' || type === 'widget') { + closeWidget = false; + } else { + closeWidget = true; } if(closeWidget) { - widget.closed.next(); - widget.closed.complete(); - - if(widget.forceClosed !== undefined) { - widget.forceClosed(); - } - - this.outgoingPackets.closeActiveWidgets(); - this._activeWidget = null; + this.interfaceState.closeAllSlots(); } }); @@ -378,29 +361,6 @@ export class Player extends Actor { return true; } - public openInteractiveWidget(widget: PlayerWidget): Observable { - const subject = new Subject(); - this.activeWidget = widget; - - this.actionsCancelled.pipe(take(1)).subscribe(() => { - subject.next(-1); - subject.complete(); - }); - - this.metadata.buttonListener = { - widgetId: widget.widgetId, - event: new Subject() - }; - - this.metadata.buttonListener.event.pipe(take(1)).subscribe(buttonId => { - delete this.metadata.buttonListener; - subject.next(buttonId); - subject.complete(); - }); - - return subject.asObservable(); - } - /** * Should be fired whenever the player's chunk changes. This will fire off chunk updates for all chunks not * already tracked by the player - all the new chunks that are coming into view. @@ -537,11 +497,10 @@ export class Player extends Actor { questData.completion.modelRotationX || 0, questData.completion.modelRotationY || 0, questData.completion.modelZoom || 0); - this.activeWidget = { - widgetId: widgets.questReward, - type: 'SCREEN', - closeOnWalk: true - }; + this.interfaceState.openWidget(widgets.questReward, { + slot: 'screen', + multi: false + }); this.modifyWidget(widgets.questTab, { childId: questData.questTabId, textColor: colors.green }); @@ -607,23 +566,21 @@ export class Player extends Actor { * @returns A Promise that resolves when the player has clicked the "click to continue" button or * after their chat messages have been sent. */ - public async sendMessage(messages: string | string[], showDialogue: boolean = false): Promise { + public async sendMessage(messages: string | string[], showDialogue: boolean = false): Promise { if(!Array.isArray(messages)) { messages = [ messages ]; } if(!showDialogue) { messages.forEach(message => this.outgoingPackets.chatboxMessage(message)); - return Promise.resolve(); } else { - if(messages.length > 5) { - throw new Error(`Dialogues have a maximum of 5 lines!`); + for(let i = 0; i < messages.length; i++) { + messages[i] = messages[i]?.trim() || ''; } - return dialogueAction(this, { type: 'TEXT', lines: messages }).then(async d => { - d.close(); - return Promise.resolve(); - }); + return await dialogue([ this ], [ + text => (messages as string[]).join(' ') + ]); } } @@ -759,19 +716,6 @@ export class Player extends Actor { } } - /** - * Queues up a widget to be displayed when the active widget is closed. - * If there is no active widget, the provided widget will be automatically displayed. - * @param widget The widget to queue. - */ - public queueWidget(widget: PlayerWidget): void { - if(this.activeWidget === null) { - this.activeWidget = widget; - } else { - this.queuedWidgets.push(widget); - } - } - public sendLogMessage(message: string, isConsole: boolean): void { if(isConsole) { this.outgoingPackets.consoleMessage(message); @@ -802,36 +746,6 @@ export class Player extends Actor { } } - /** - * Closes the currently active widget or widget pair. - * @param notifyClient [optional] Whether or not to notify the game client that widgets should be cleared. Defaults to true. - */ - public closeActiveWidgets(notifyClient: boolean = true): void { - if(notifyClient) { - if(this.queuedWidgets.length !== 0) { - this.activeWidget = this.queuedWidgets.shift(); - } else { - this.activeWidget = null; - } - } else { - this._activeWidget = null; - - if(this.queuedWidgets.length !== 0) { - this.activeWidget = this.queuedWidgets.shift(); - } else { - this.actionsCancelled.next('keep-widgets-open'); - } - } - } - - /** - * Checks to see if the player has the specified widget ID open on their screen or not. - * @param widgetId The ID of the widget to look for. - */ - public hasWidgetOpen(widgetId: number): boolean { - return this.activeWidget && this.activeWidget.widgetId === widgetId; - } - public isItemEquipped(item: number | Item | string): boolean { if(typeof item === 'string') { item = findItem(item)?.gameId || 0; @@ -928,7 +842,7 @@ export class Player extends Actor { this.outgoingPackets.sendUpdateAllWidgetItems(widgets.inventory, this.inventory); this.outgoingPackets.sendUpdateAllWidgetItems(widgets.equipment, this.equipment); - if(this.hasWidgetOpen(widgets.equipmentStats.widgetId)) { + if(this.interfaceState.widgetOpen('screen', widgets.equipmentStats.widgetId)) { this.outgoingPackets.sendUpdateAllWidgetItems(widgets.equipmentStats, this.equipment); updateBonusStrings(this); } @@ -1236,39 +1150,6 @@ export class Player extends Actor { this._appearance = value; } - public get activeWidget(): PlayerWidget { - return this._activeWidget; - } - - public set activeWidget(value: PlayerWidget) { - if(value !== null) { - value.closed = new Subject(); - - if(value.beforeOpened !== undefined) { - value.beforeOpened(); - } - - if(value.type === 'SCREEN') { - this.outgoingPackets.showScreenWidget(value.widgetId); - } else if(value.type === 'CHAT') { - this.outgoingPackets.showChatboxWidget(value.widgetId); - } else if(value.type === 'FULLSCREEN') { - this.outgoingPackets.showFullscreenWidget(value.widgetId, value.secondaryWidgetId); - } else if(value.type === 'SCREEN_AND_TAB') { - this.outgoingPackets.showScreenAndTabWidgets(value.widgetId, value.secondaryWidgetId); - } - - if(value.afterOpened !== undefined) { - value.afterOpened(); - } - } else { - this.outgoingPackets.closeActiveWidgets(); - } - - this.actionsCancelled.next('keep-widgets-open'); - this._activeWidget = value; - } - public get equipment(): ItemContainer { return this._equipment; } diff --git a/src/world/actor/walking-queue.ts b/src/world/actor/walking-queue.ts index 27d2d308c..77106c59d 100644 --- a/src/world/actor/walking-queue.ts +++ b/src/world/actor/walking-queue.ts @@ -136,14 +136,11 @@ export class WalkingQueue { if(this.actor instanceof Player) { this.actor.actionsCancelled.next('pathing-movement'); - - const activeWidget = this.actor.activeWidget; - if(activeWidget && (!walkPosition.metadata || !walkPosition.metadata.ignoreWidgets)) { - if(activeWidget.disablePlayerMovement) { - this.resetDirections(); - return; - } - } + // if(activeWidget.disablePlayerMovement) { + // this.resetDirections(); + // return; + // } + //this.actor.interfaceState.closeAllSlots(); } if(this.actor.metadata['faceActorClearedByWalking'] === undefined || this.actor.metadata['faceActorClearedByWalking']) { diff --git a/src/world/config/widget.ts b/src/world/config/widget.ts index 618424c03..ed4ea09d0 100644 --- a/src/world/config/widget.ts +++ b/src/world/config/widget.ts @@ -1,91 +1,5 @@ import { Subject } from 'rxjs'; -export const widgets: any = { - characterDesign: 269, - furnace: { - widgetId: 311, - slots: { - slot0: { modelId: 4, titleId: 16 }, - slot1: { modelId: 5, titleId: 20 }, - slot2: { modelId: 6, titleId: 24 }, - slot3: { modelId: 7, titleId: 28 }, - slot4: { modelId: 8, titleId: 32 }, - slot5: { modelId: 9, titleId: 36 }, - slot6: { modelId: 10, titleId: 40 }, - slot7: { modelId: 11, titleId: 44 }, - slot8: { modelId: 12, titleId: 48 }, - } - }, - inventory: { - widgetId: 149, - containerId: 0 - }, - equipment: { - widgetId: 387, - containerId: 25 - }, - equipmentStats: { - widgetId: 465, - containerId: 103 - }, - equipmentStatsInventory: { - widgetId: 336, - containerId: 0 - }, - bank: { - depositBoxWidget: { - widgetId: 11 - }, - pinSettingsWidget: { - widgetId: 14 - }, - screenWidget: { - widgetId: 12, - containerId: 89, - }, - tabWidget: { - widgetId: 266, - containerId: 0 - } - }, - defaultCombatStyle: 92, - skillGuide: 308, - skillsTab: 320, - friendsList: 131, - ignoreList: 148, - logoutTab: 182, - settingsTab: 261, - emotesTab: 464, - musicPlayerTab: 239, - prayerTab: 271, - standardSpellbookTab: 192, - questTab: 274, - shop: { - widgetId: 300, - containerId: 75, - title: 76 - }, - shopPlayerInventory: { - widgetId: 301, - containerId: 0 - }, - questJournal: 275, - questReward: 277, - welcomeScreen: 378, - welcomeScreenChildren: { - cogs: 16, - question: 17, - drama: 18, - bankPin: 19, - bankPinQuestion: 20, - scamming: 21, - bankPinKey: 22, - christmas: 23, - killcount: 24 - }, - whatWouldYouLikeToSpin: 459 -}; - export const widgetScripts = { musicPlayer: 18, attackStyle: 43, diff --git a/src/world/index.ts b/src/world/index.ts index e8ffa8176..b8fb03095 100644 --- a/src/world/index.ts +++ b/src/world/index.ts @@ -288,7 +288,7 @@ export class World { for(let i = 0; i < 1000; i++) { const player = new Player(null, null, null, i, `test${i}`, 'abs', true); this.registerPlayer(player); - player.activeWidget = null; + player.interfaceState.closeAllSlots(); xOffset++;