Skip to content

Commit

Permalink
Merge pull request #111 from Promises/master
Browse files Browse the repository at this point in the history
item on npc, and abusing sheep
  • Loading branch information
TheBlackParade authored Mar 2, 2020
2 parents ea8b929 + 8da020a commit c281e35
Show file tree
Hide file tree
Showing 15 changed files with 351 additions and 55 deletions.
24 changes: 24 additions & 0 deletions data/config/npc-spawns.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,27 @@
x: 3253
y: 3274
radius: 1
- npcId: 3579
x: 3197
y: 3262
radius: 10
- npcId: 43
x: 3199
y: 3267
radius: 10
- npcId: 43
x: 3203
y: 3271
radius: 10
- npcId: 43
x: 3199
y: 3273
radius: 10
- npcId: 43
x: 3208
y: 3273
radius: 10
- npcId: 43
x: 3209
y: 3260
radius: 10
2 changes: 2 additions & 0 deletions src/game-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { setWidgetPlugins } from '@server/world/actor/player/action/widget-actio
import { setItemPlugins } from '@server/world/actor/player/action/item-action';
import { setWorldItemPlugins } from '@server/world/actor/player/action/world-item-action';
import { setItemOnObjectPlugins } from '@server/world/actor/player/action/item-on-object-action';
import { setItemOnNpcPlugins } from '@server/world/actor/player/action/item-on-npc-action';
import { setPlayerInitPlugins } from '@server/world/actor/player/player';
import { setNpcInitPlugins } from '@server/world/actor/npc/npc';

Expand All @@ -44,6 +45,7 @@ export async function injectPlugins(): Promise<void> {
setNpcPlugins(actionTypes[ActionType.NPC_ACTION]);
setObjectPlugins(actionTypes[ActionType.OBJECT_ACTION]);
setItemOnObjectPlugins(actionTypes[ActionType.ITEM_ON_OBJECT_ACTION]);
setItemOnNpcPlugins(actionTypes[ActionType.ITEM_ON_NPC_ACTION]);
setItemOnItemPlugins(actionTypes[ActionType.ITEM_ON_ITEM]);
setItemPlugins(actionTypes[ActionType.ITEM_ACTION]);
setWorldItemPlugins(actionTypes[ActionType.WORLD_ITEM_ACTION]);
Expand Down
2 changes: 2 additions & 0 deletions src/net/incoming-packet-directory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { pickupItemPacket } from '@server/net/incoming-packets/pickup-item-packe
import { itemInteractionPacket } from '@server/net/incoming-packets/item-interaction-packet';
import { itemOnObjectPacket } from '@server/net/incoming-packets/item-on-object-packet';
import { numberInputPacket } from '@server/net/incoming-packets/number-input-packet';
import { itemOnNpcPacket } from '@server/net/incoming-packets/item-on-npc-packet';

const ignore = [ 234, 160, 58 /* camera move */ ];

Expand Down Expand Up @@ -52,6 +53,7 @@ const packets: { [key: number]: incomingPacket } = {
63: npcInteractionPacket,
116: npcInteractionPacket,
24: itemOnObjectPacket,
208: itemOnNpcPacket,

30: objectInteractionPacket,
164: objectInteractionPacket,
Expand Down
2 changes: 1 addition & 1 deletion src/net/incoming-packet-sizes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const incomingPacketSizes: number[] = [
-3, -3, -3, -3, -3, -3, 0, -3, 0, -3, //170
-3, -3, -3, 6, -3, -3, -3, -3, -3, -3, //180
-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, //190
-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, //200
-3, -3, -3, -3, -3, -3, -3, -3, 10, -3, //200
-3, -3, -3, -3, -3, -3, 0, -3, -3, -3, //210
-3, -3, -3, -3, -3, -3, -3, -3, 8, -3, //220
-3, 13, -3, -3, 4, -3, -1, -3, 4, -3, //230
Expand Down
60 changes: 60 additions & 0 deletions src/net/incoming-packets/item-on-npc-packet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { incomingPacket } from '../incoming-packet';
import { Player } from '../../world/actor/player/player';
import { RsBuffer } from '@server/net/rs-buffer';
import { widgets } from '@server/world/config/widget';
import { logger } from '@runejs/logger/dist/logger';
import { itemOnItemAction } from '@server/world/actor/player/action/item-on-item-action';
import { Position } from '@server/world/position';
import { gameCache, world } from '@server/game-server';
import { objectAction } from '@server/world/actor/player/action/object-action';
import { itemOnObjectAction } from '@server/world/actor/player/action/item-on-object-action';
import { World } from '@server/world/world';
import { npcAction } from '@server/world/actor/player/action/npc-action';
import { itemOnNpcAction } from '@server/world/actor/player/action/item-on-npc-action';

export const itemOnNpcPacket: incomingPacket = (player: Player, packetId: number, packetSize: number, packet: RsBuffer): void => {
const npcIndex = packet.readNegativeOffsetShortBE();
const itemId = packet.readNegativeOffsetShortBE();
const itemSlot = packet.readNegativeOffsetShortLE();
const itemWidgetId = packet.readShortBE();
const itemContainerId = packet.readShortBE();

let usedItem;
if (itemWidgetId === widgets.inventory.widgetId && itemContainerId === widgets.inventory.containerId) {
if (itemSlot < 0 || itemSlot > 27) {
return;
}

usedItem = player.inventory.items[itemSlot];
if (!usedItem) {
return;
}

if (usedItem.itemId !== itemId) {
return;
}
} else {
logger.warn(`Unhandled item on object case using widget ${itemWidgetId}:${itemContainerId}`);
}


if (npcIndex < 0 || npcIndex > World.MAX_NPCS - 1) {
return;
}

const npc = world.npcList[npcIndex];
if (!npc) {
return;
}

const position = npc.position;
const distance = Math.floor(position.distanceBetween(player.position));

// Too far away
if (distance > 16) {
return;
}

itemOnNpcAction(player, npc, position, usedItem, itemWidgetId, itemContainerId);

};
53 changes: 32 additions & 21 deletions src/net/outgoing-packets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ export class OutgoingPackets {
this.queue(packet);
}

public playSoundAtPosition(chunk: Chunk, soundId: number, soundX: number, soundY: number, volume: number, radius: number = 5, delay: number = 0): void {
const packet = new Packet(9);
const offset = 0;
packet.writeUnsignedByte(offset);
packet.writeUnsignedShortBE(soundId);
packet.writeUnsignedByte((volume & 7) + (radius << 4));
packet.writeUnsignedByte(delay);

this.queue(packet);
}

private getChunkPositionOffset(x: number, y: number, chunk: Chunk): number {
const offsetX = x - ((chunk.position.x + 6) * 8);
const offsetY = y - ((chunk.position.y + 6) * 8);
Expand All @@ -63,32 +74,32 @@ export class OutgoingPackets {
offsetX -= (this.player.lastMapRegionUpdatePosition.chunkX * 8);
offsetY -= (this.player.lastMapRegionUpdatePosition.chunkY * 8);

return { offsetX, offsetY };
return {offsetX, offsetY};
}

public updateChunk(chunk: Chunk, chunkUpdates: ChunkUpdateItem[]): void {
const { offsetX, offsetY } = this.getChunkOffset(chunk);
const {offsetX, offsetY} = this.getChunkOffset(chunk);

const packet = new Packet(63, PacketType.DYNAMIC_LARGE);
packet.writeByteInverted(offsetX);
packet.writeNegativeOffsetByte(offsetY);

chunkUpdates.forEach(update => {
if(update.type === 'ADD') {
if(update.object) {
if (update.type === 'ADD') {
if (update.object) {
const offset = this.getChunkPositionOffset(update.object.x, update.object.y, chunk);
packet.writeUnsignedByte(241);
packet.writeByteInverted((update.object.type << 2) + (update.object.rotation & 3));
packet.writeUnsignedShortBE(update.object.objectId);
packet.writeUnsignedOffsetByte(offset);
} else if(update.worldItem) {
} else if (update.worldItem) {
const offset = this.getChunkPositionOffset(update.worldItem.position.x, update.worldItem.position.y, chunk);
packet.writeUnsignedByte(175);
packet.writeUnsignedShortLE(update.worldItem.itemId);
packet.writeUnsignedShortBE(update.worldItem.amount);
packet.writeUnsignedByte(offset);
}
} else if(update.type === 'REMOVE') {
} else if (update.type === 'REMOVE') {
const offset = this.getChunkPositionOffset(update.object.x, update.object.y, chunk);
packet.writeUnsignedByte(143);
packet.writeUnsignedOffsetByte(offset);
Expand All @@ -100,7 +111,7 @@ export class OutgoingPackets {
}

public clearChunk(chunk: Chunk): void {
const { offsetX, offsetY } = this.getChunkOffset(chunk);
const {offsetX, offsetY} = this.getChunkOffset(chunk);

const packet = new Packet(64);
packet.writeUnsignedByte(offsetY);
Expand Down Expand Up @@ -195,7 +206,7 @@ export class OutgoingPackets {
this.queue(packet);
}

public showScreenAndTabWidgets(widgetId: number, tabWidgetId: number) : void {
public showScreenAndTabWidgets(widgetId: number, tabWidgetId: number): void {
const packet = new Packet(84);
packet.writeUnsignedShortBE(tabWidgetId);
packet.writeUnsignedOffsetShortLE(widgetId);
Expand All @@ -205,7 +216,7 @@ export class OutgoingPackets {
public updateClientConfig(configId: number, value: number): void {
let packet: Packet;

if(value > 128) {
if (value > 128) {
packet = new Packet(2);
packet.writeIntME2(value);
packet.writeUnsignedShortBE(configId);
Expand Down Expand Up @@ -252,12 +263,12 @@ export class OutgoingPackets {
packet.writeIntBE(widget.widgetId << 16 | widget.containerId);
packet.writeSmart(slot);

if(!item) {
if (!item) {
packet.writeUnsignedShortBE(0);
} else {
packet.writeUnsignedShortBE(item.itemId + 1); // +1 because 0 means an empty slot

if(item.amount >= 255) {
if (item.amount >= 255) {
packet.writeUnsignedByte(255);
packet.writeIntBE(item.amount);
} else {
Expand All @@ -275,12 +286,12 @@ export class OutgoingPackets {

const items = container.items;
items.forEach(item => {
if(!item) {
if (!item) {
// Empty slot
packet.writeUnsignedOffsetByte(0);
packet.writeOffsetShortBE(0);
} else {
if(item.amount >= 255) {
if (item.amount >= 255) {
packet.writeUnsignedByteOffset(255);
packet.writeIntBE(item.amount);
} else {
Expand All @@ -300,7 +311,7 @@ export class OutgoingPackets {
packet.writeShortBE(itemIds.length);

itemIds.forEach(itemId => {
if(!itemId) {
if (!itemId) {
// Empty slot
packet.writeUnsignedOffsetByte(0);
packet.writeOffsetShortBE(0);
Expand Down Expand Up @@ -426,9 +437,9 @@ export class OutgoingPackets {
packet.writeOffsetShortLE(this.player.position.chunkY + 6);
packet.writeByteInverted(this.player.position.level);

for(let xCalc = Math.floor(this.player.position.chunkX / 8); xCalc <= Math.floor((this.player.position.chunkX + 12) / 8); xCalc++) {
for(let yCalc = Math.floor(this.player.position.chunkY / 8); yCalc <= Math.floor((this.player.position.chunkY + 12) / 8); yCalc++) {
for(let seeds = 0; seeds < 4; seeds++){
for (let xCalc = Math.floor(this.player.position.chunkX / 8); xCalc <= Math.floor((this.player.position.chunkX + 12) / 8); xCalc++) {
for (let yCalc = Math.floor(this.player.position.chunkY / 8); yCalc <= Math.floor((this.player.position.chunkY + 12) / 8); yCalc++) {
for (let seeds = 0; seeds < 4; seeds++) {
packet.writeIntME1(0);
}
}
Expand All @@ -438,12 +449,12 @@ export class OutgoingPackets {
}

public flushQueue(): void {
if(!this.socket || this.socket.destroyed) {
if (!this.socket || this.socket.destroyed) {
return;
}

const buffer = Buffer.concat([ ...this.packetQueue, ...this.updatingQueue ]);
if(buffer.length !== 0) {
const buffer = Buffer.concat([...this.packetQueue, ...this.updatingQueue]);
if (buffer.length !== 0) {
this.socket.write(buffer);
}

Expand All @@ -452,7 +463,7 @@ export class OutgoingPackets {
}

public queue(packet: Packet, updateTask: boolean = false): void {
if(!this.socket || this.socket.destroyed) {
if (!this.socket || this.socket.destroyed) {
return;
}

Expand Down
54 changes: 54 additions & 0 deletions src/plugins/npcs/lumbridge/sheep-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { ActionType, RunePlugin } from '@server/plugins/plugin';
import { npcIds } from '@server/world/config/npc-ids';
import { npcInitAction } from '@server/world/actor/npc/npc';
import { World } from '@server/world/world';
import { itemOnNpcAction } from '@server/world/actor/player/action/item-on-npc-action';
import { itemIds } from '@server/world/config/item-ids';
import { soundIds } from '@server/world/config/sound-ids';
import { animationIds } from '@server/world/config/animation-ids';

const initAction: npcInitAction = (details) => {
setInterval(() => {
if (Math.random() >= 0.66) {
details.npc.updateFlags.addChatMessage({message: `Baa!`});
details.npc.sendSound(soundIds.sheepBaa, 4);
}
}, (Math.floor(Math.random() * 20) + 10) * World.TICK_LENGTH);
};

export const shearAction: itemOnNpcAction = (details) => {
details.player.busy = true;
details.player.playAnimation(animationIds.shearSheep);
details.player.outgoingPackets.playSound(soundIds.shearSheep, 5);

setTimeout(() => {
if (Math.random() >= 0.66) {
details.player.outgoingPackets.chatboxMessage('The sheep manages to get away from you!');
// TODO: move sheep backwards about 5 tiles, moonwalk, not turn around
} else {
details.player.outgoingPackets.chatboxMessage('You get some wool.');
details.player.giveItem(itemIds.wool);
details.npc.updateFlags.addChatMessage({message: 'Baa!'});
details.npc.sendSound(soundIds.sheepBaa, 4);
//TODO: Replace with naked sheep

}
details.player.busy = false;
}, World.TICK_LENGTH);

};
export default new RunePlugin([
{
type: ActionType.NPC_INIT,
npcIds: npcIds.sheep,
action: initAction
},
{
type: ActionType.ITEM_ON_NPC_ACTION,
npcsIds: [npcIds.sheep],
itemIds: [itemIds.shears, itemIds.recruitmentDrive.shears],
walkTo: true,
action: shearAction
}
]
);
Loading

0 comments on commit c281e35

Please sign in to comment.