Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/game-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { setItemOnItemPlugins } from '@server/world/actor/player/action/item-on-
import { setButtonPlugins } from '@server/world/actor/player/action/button-action';
import { setCommandPlugins } from '@server/world/actor/player/action/input-command-action';
import { setWidgetPlugins } from '@server/world/actor/player/action/widget-action';
import { setItemPlugins } from '@server/world/actor/player/action/item-action';

export let serverConfig: ServerConfig;
export let gameCache377: EarlyFormatGameCache;
Expand All @@ -39,6 +40,7 @@ export async function injectPlugins(): Promise<void> {
setNpcPlugins(actionTypes[ActionType.NPC_ACTION]);
setObjectPlugins(actionTypes[ActionType.OBJECT_ACTION]);
setItemOnItemPlugins(actionTypes[ActionType.ITEM_ON_ITEM]);
setItemPlugins(actionTypes[ActionType.ITEM_ACTION]);
setCommandPlugins(actionTypes[ActionType.COMMAND]);
setWidgetPlugins(actionTypes[ActionType.WIDGET_ACTION]);
}
Expand Down
28 changes: 2 additions & 26 deletions src/net/incoming-packets/item-equip-packet.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,13 @@
import { incomingPacket } from '../incoming-packet';
import { Player } from '../../world/actor/player/player';
import { RsBuffer } from '@server/net/rs-buffer';
import { logger } from '@runejs/logger/dist/logger';
import { widgetIds } from '../../world/config/widget';
import { equipItemAction } from '../../world/actor/player/action/equip-item-action';
import { itemAction } from '@server/world/actor/player/action/item-action';

export const itemEquipPacket: incomingPacket = (player: Player, packetId: number, packetSize: number, packet: RsBuffer): void => {
const containerId = packet.readShortLE();
const widgetId = packet.readShortLE();
const slot = packet.readNegativeOffsetShortLE();
const itemId = packet.readShortBE();

if(widgetId !== widgetIds.inventory.widgetId || containerId !== widgetIds.inventory.containerId) {
logger.warn(`${player.username} attempted to equip item from incorrect widget ${widgetId}:${containerId}.`);
return;
}

if(slot < 0 || slot > 27) {
logger.warn(`${player.username} attempted to equip item ${itemId} in invalid slot ${slot}.`);
return;
}

const itemInSlot = player.inventory.items[slot];

if(!itemInSlot) {
logger.warn(`${player.username} attempted to equip item ${itemId} in slot ${slot}, but they do not have that item.`);
return;
}

if(itemInSlot.itemId !== itemId) {
logger.warn(`${player.username} attempted to equip item ${itemId} in slot ${slot}, but ${itemInSlot.itemId} was found there instead.`);
return;
}

equipItemAction(player, itemId, slot);
itemAction(player, itemId, slot, widgetId, containerId, 'equip');
};
13 changes: 6 additions & 7 deletions src/net/incoming-packets/item-option-1-packet.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import { incomingPacket } from '../incoming-packet';
import { RsBuffer } from '@server/net/rs-buffer';
import { Player } from '../../world/actor/player/player';
import { widgetIds } from '../../world/config/widget';
import { logger } from '@runejs/logger/dist/logger';
import { unequipItemAction } from '../../world/actor/player/action/unequip-item-action';
import { ItemContainer } from '@server/world/items/item-container';
import { buyItemValueAction } from '@server/world/actor/player/action/buy-item-value-action';
import { sellItemValueAction } from '@server/world/actor/player/action/sell-item-value-action';
import { itemAction } from '@server/world/actor/player/action/item-action';

export const itemOption1Packet: incomingPacket = (player: Player, packetId: number, packetSize: number, packet: RsBuffer): void => {
const itemId = packet.readNegativeOffsetShortBE();
const slot = packet.readShortLE();
const widgetId = packet.readShortLE();
const containerId = packet.readShortLE();

// @TODO parse widgets and find actual item option NAME to pass to this
itemAction(player, itemId, slot, widgetId, containerId, 'option-1');

/*
// Handles the value option in shops.
if(widgetId === widgetIds.shop.shopInventory) {
buyItemValueAction(player, itemId, slot);
Expand Down Expand Up @@ -56,5 +55,5 @@ export const itemOption1Packet: incomingPacket = (player: Player, packetId: numb

if(widgetId === widgetIds.equipment.widgetId && containerId === widgetIds.equipment.containerId) {
unequipItemAction(player, itemId, slot);
}
}*/
};
8 changes: 4 additions & 4 deletions src/net/outgoing-packets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,10 @@ export class OutgoingPackets {
this.queue(packet);
}

public showScreenAndTabWidgets(widgetId: number, sidebarId: number) : void {
const packet = new Packet(128);
packet.writeNegativeOffsetShortBE(widgetId);
packet.writeNegativeOffsetShortLE(sidebarId);
public showScreenAndTabWidgets(widgetId: number, tabWidgetId: number) : void {
const packet = new Packet(84);
packet.writeUnsignedShortBE(tabWidgetId);
packet.writeUnsignedOffsetShortLE(widgetId);
this.queue(packet);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,57 @@
import { Player } from '../player';
import { world } from '@server/game-server';
import { logger } from '@runejs/logger/dist/logger';
import { ActionType, RunePlugin } from '@server/plugins/plugin';
import { widgetIds } from '@server/world/config/widget';
import { getItemFromContainer, itemAction } from '@server/world/actor/player/action/item-action';
import { updateBonusStrings } from '@server/plugins/equipment/equipment-stats-plugin';
import { EquipmentSlot, equipmentSlotIndex, ItemDetails, WeaponType } from '@server/world/config/item-data';
import { Item } from '@server/world/items/item';
import { widgetIds } from '../../../config/widget';
import { world } from '@server/game-server';
import { Player } from '@server/world/actor/player/player';
import { ItemContainer } from '@server/world/items/item-container';

export const equipItemAction = (player: Player, itemId: number, inventorySlot: number) => {
const itemToEquipData = world.itemData.get(itemId);
function unequipItem(player: Player, inventory: ItemContainer, equipment: ItemContainer, slot: EquipmentSlot): boolean {
const inventorySlot = inventory.getFirstOpenSlot();

if(!itemToEquipData || !itemToEquipData.equipment || !itemToEquipData.equipment.slot) {
logger.warn(`Can not equip item ${itemId}/${itemToEquipData.name}`);
return;
if(inventorySlot === -1) {
player.outgoingPackets.chatboxMessage(`You don't have enough free space to do that.`);
return false;
}

const itemInSlot = equipment.items[slot];

if(!itemInSlot) {
return true;
}

equipment.remove(slot);
inventory.set(inventorySlot, itemInSlot);
return true;
}

export const action: itemAction = (details) => {
const { player, itemId, itemSlot, itemDetails, widgetId } = details;

const inventory = player.inventory;
const equipment = player.equipment;
const equipmentSlot = equipmentSlotIndex(itemToEquipData.equipment.slot);
const itemToEquip = getItemFromContainer(itemId, itemSlot, inventory);

if(!itemToEquip) {
// The specified item was not found in the specified slot.
return;
}

if(!itemDetails || !itemDetails.equipment || !itemDetails.equipment.slot) {
player.outgoingPackets.chatboxMessage(`Unable to equip item ${itemId}/${itemDetails.name}: Missing equipment data.`);
return;
}

const equipmentSlot = equipmentSlotIndex(itemDetails.equipment.slot);

const itemToEquip: Item = inventory.items[inventorySlot];
const itemToUnequip: Item = equipment.items[equipmentSlot];
let shouldUnequipOffHand: boolean = false;
let shouldUnequipMainHand: boolean = false;

if(itemToEquipData && itemToEquipData.equipment) {
if(itemToEquipData.equipment.weaponType === WeaponType.TWO_HANDED) {
if(itemDetails && itemDetails.equipment) {
if(itemDetails.equipment.weaponType === WeaponType.TWO_HANDED) {
shouldUnequipOffHand = true;
}

Expand All @@ -47,13 +74,13 @@ export const equipItemAction = (player: Player, itemId: number, inventorySlot: n
}

equipment.remove(equipmentSlot, false);
inventory.remove(inventorySlot, false);
inventory.remove(itemSlot, false);

equipment.set(equipmentSlot, itemToEquip);
inventory.set(inventorySlot, itemToUnequip);
inventory.set(itemSlot, itemToUnequip);
} else {
equipment.set(equipmentSlot, itemToEquip);
inventory.remove(inventorySlot);
inventory.remove(itemSlot);

if(shouldUnequipOffHand) {
unequipItem(player, inventory, equipment, EquipmentSlot.OFF_HAND);
Expand All @@ -64,28 +91,24 @@ export const equipItemAction = (player: Player, itemId: number, inventorySlot: n
}
}

player.updateBonuses();

// @TODO change packets to only update modified container slots
player.outgoingPackets.sendUpdateAllWidgetItems(widgetIds.inventory, inventory);
player.outgoingPackets.sendUpdateAllWidgetItems(widgetIds.equipment, equipment);
// player.updateBonuses(); @TODO move this to when the equipment widget gets opened
player.updateFlags.appearanceUpdateRequired = true;
};

function unequipItem(player: Player, inventory: ItemContainer, equipment: ItemContainer, slot: EquipmentSlot): boolean {
const inventorySlot = inventory.getFirstOpenSlot();

if(inventorySlot === -1) {
player.outgoingPackets.chatboxMessage(`You don't have enough free space to do that.`);
return false;
if(player.hasWidgetOpen(widgetIds.equipmentStats.widgetId)) {
player.outgoingPackets.sendUpdateAllWidgetItems(widgetIds.equipmentStats, equipment);
updateBonusStrings(player);
}

const itemInSlot = equipment.items[slot];

if(!itemInSlot) {
return true;
}
player.updateFlags.appearanceUpdateRequired = true;
};

equipment.remove(slot);
inventory.set(inventorySlot, itemInSlot);
return true;
}
export default new RunePlugin({
type: ActionType.ITEM_ACTION,
widgets: widgetIds.inventory,
options: 'equip',
action,
cancelOtherActions: false
});
42 changes: 42 additions & 0 deletions src/plugins/equipment/equipment-stats-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { buttonAction } from '@server/world/actor/player/action/button-action';
import { ActionType, RunePlugin } from '@server/plugins/plugin';
import { widgetIds } from '@server/world/config/widget';
import { Player } from '@server/world/actor/player/player';

export function updateBonusStrings(player: Player) {
[
{ id: 108, text: 'Stab', value: player.bonuses.offencive.stab },
{ id: 109, text: 'Slash', value: player.bonuses.offencive.slash },
{ id: 110, text: 'Crush', value: player.bonuses.offencive.crush },
{ id: 111, text: 'Magic', value: player.bonuses.offencive.magic },
{ id: 112, text: 'Range', value: player.bonuses.offencive.ranged },
{ id: 113, text: 'Stab', value: player.bonuses.defencive.stab },
{ id: 114, text: 'Slash', value: player.bonuses.defencive.slash },
{ id: 115, text: 'Crush', value: player.bonuses.defencive.crush },
{ id: 116, text: 'Magic', value: player.bonuses.defencive.magic },
{ id: 117, text: 'Range', value: player.bonuses.defencive.ranged },
{ id: 119, text: 'Strength', value: player.bonuses.skill.strength },
{ id: 120, text: 'Prayer', value: player.bonuses.skill.prayer },
].forEach(bonus => player.outgoingPackets.updateWidgetString(widgetIds.equipmentStats.widgetId, bonus.id,
`${bonus.text}: ${bonus.value > 0 ? `+${bonus.value}` : bonus.value}`));
}

export const action: buttonAction = (details) => {
const { player } = details;

player.updateBonuses();

updateBonusStrings(player);

player.outgoingPackets.sendUpdateAllWidgetItems(widgetIds.equipmentStats, player.equipment);
player.outgoingPackets.sendUpdateAllWidgetItems(widgetIds.inventory, player.inventory);

player.activeWidget = {
widgetId: widgetIds.equipmentStats.widgetId,
secondaryWidgetId: widgetIds.inventory.widgetId,
type: 'SCREEN_AND_TAB',
closeOnWalk: true
};
};

export default new RunePlugin({ type: ActionType.BUTTON, widgetId: widgetIds.equipment.widgetId, buttonIds: 24, action });
50 changes: 50 additions & 0 deletions src/plugins/equipment/unequip-item-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { ActionType, RunePlugin } from '@server/plugins/plugin';
import { widgetIds } from '@server/world/config/widget';
import { getItemFromContainer, itemAction } from '@server/world/actor/player/action/item-action';
import { updateBonusStrings } from '@server/plugins/equipment/equipment-stats-plugin';

export const action: itemAction = (details) => {
const { player, itemId, itemSlot, widgetId } = details;

const equipment = player.equipment;
const item = getItemFromContainer(itemId, itemSlot, equipment);

if(!item) {
// The specified item was not found in the specified slot.
return;
}

const inventory = player.inventory;
const inventorySlot = inventory.getFirstOpenSlot();

if(inventorySlot === -1) {
player.outgoingPackets.chatboxMessage(`You don't have enough free space to do that.`);
return;
}

equipment.remove(itemSlot);
inventory.set(inventorySlot, item);

player.updateBonuses();

player.outgoingPackets.sendUpdateSingleWidgetItem(widgetIds.inventory, inventorySlot, item);
player.outgoingPackets.sendUpdateSingleWidgetItem(widgetIds.equipment, itemSlot, null);

if(widgetId === widgetIds.equipmentStats.widgetId) {
player.outgoingPackets.sendUpdateSingleWidgetItem(widgetIds.equipmentStats, itemSlot, null);
updateBonusStrings(player);
}

player.updateFlags.appearanceUpdateRequired = true;
};

export default new RunePlugin({
type: ActionType.ITEM_ACTION,
widgets: [
widgetIds.equipment,
widgetIds.equipmentStats
],
options: 'option-1',
action,
cancelOtherActions: false
});
28 changes: 28 additions & 0 deletions src/plugins/plugin-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,34 @@ import * as fs from 'fs';
import * as util from 'util';
import { RunePlugin } from '@server/plugins/plugin';

export const basicStringFilter = (pluginValues: string | string[], searchValue: string): boolean => {
if(Array.isArray(pluginValues)) {
if(pluginValues.indexOf(searchValue) === -1) {
return false;
}
} else {
if(pluginValues !== searchValue) {
return false;
}
}

return true;
};

export const basicNumberFilter = (pluginValues: number | number[], searchValue: number): boolean => {
if(Array.isArray(pluginValues)) {
if(pluginValues.indexOf(searchValue) === -1) {
return false;
}
} else {
if(pluginValues !== searchValue) {
return false;
}
}

return true;
};

export const pluginFilter = (pluginIds: number | number[], searchId: number, pluginOptions?: string | string[], searchOption?: string): boolean => {
if(Array.isArray(pluginIds)) {
if(pluginIds.indexOf(searchId) === -1) {
Expand Down
8 changes: 5 additions & 3 deletions src/plugins/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import { ButtonActionPlugin } from '@server/world/actor/player/action/button-act
import { ItemOnItemActionPlugin } from '@server/world/actor/player/action/item-on-item-action';
import { CommandActionPlugin } from '@server/world/actor/player/action/input-command-action';
import { WidgetActionPlugin } from '@server/world/actor/player/action/widget-action';
import { ItemActionPlugin } from '@server/world/actor/player/action/item-action';

export enum ActionType {
BUTTON = 'button',
WIDGET_ACTION = 'widget_action',
ITEM_ON_ITEM = 'item_on_item',
ITEM_ACTION = 'item_action',
NPC_ACTION = 'npc_action',
OBJECT_ACTION = 'object_action',
COMMAND = 'command'
Expand All @@ -21,12 +23,12 @@ export interface ActionPlugin {
export class RunePlugin {

public actions: (NpcActionPlugin | ObjectActionPlugin | ButtonActionPlugin | ItemOnItemActionPlugin |
CommandActionPlugin | WidgetActionPlugin)[];
CommandActionPlugin | WidgetActionPlugin | ItemActionPlugin)[];

public constructor(actions: NpcActionPlugin | ObjectActionPlugin | ButtonActionPlugin | ItemOnItemActionPlugin |
CommandActionPlugin | WidgetActionPlugin |
CommandActionPlugin | WidgetActionPlugin | ItemActionPlugin |
(NpcActionPlugin | ObjectActionPlugin | ButtonActionPlugin | ItemOnItemActionPlugin |
CommandActionPlugin | WidgetActionPlugin)[]) {
CommandActionPlugin | WidgetActionPlugin | ItemActionPlugin)[]) {
if(!Array.isArray(actions)) {
this.actions = [actions];
} else {
Expand Down
Loading