Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding player_region_changed action hook and removed old scenery spawns #259

Merged
merged 4 commits into from
Mar 6, 2021
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
600 changes: 0 additions & 600 deletions data/config/scenery-spawns.yaml

Large diffs are not rendered by default.

36 changes: 25 additions & 11 deletions src/plugins/music/music-regions-plugin.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,36 @@
import { logger } from '@runejs/core';
import { Player } from '@server/world/actor/player/player';
import { musicRegionMap, musicRegions } from '@server/config';
import { songs } from '@server/world/config/songs';
import { playerRegionChangedHook } from '@server/world/action/player-region-changed';
import { playerInitAction } from '@server/world/actor/player/player';

musicRegions.forEach(song => song.regionIds.forEach(region => musicRegionMap.set(region, song.songId)));

export function playSongForRegion(player: Player): void {
const regionId = ((player.position.x >> 6) * 256) + (player.position.y >> 6);
const songId: number = musicRegionMap.get(regionId);
logger.info('Playing: ' + getByValue(songs, songId) + ' (Song ID: ' + songId + ' Region ID: ' + regionId + ')');

player.playSong(songId);
player.metadata['updateMusic'] = false;
}
musicRegions.forEach(song => song.regionIds.forEach(region => musicRegionMap.set(region, song.songId)));

function getByValue(map, searchValue) {
for (const [key, value] of map.entries()) {
if (value === searchValue)
return key;
}
}

const regionChangedHandler = ({ player, currentMapRegionId }): void => {
const songId: number = musicRegionMap.get(currentMapRegionId);
player.sendMessage(`Playing ${songId}:${getByValue(songs, songId)} at region ${currentMapRegionId}`);
player.playSong(songId);
player.metadata['updateMusic'] = false;
};

const playerInitHandler: playerInitAction = ({ player }): void => {
// Plays the appropriate location's song on player init
regionChangedHandler({ player,
currentMapRegionId: ((player.position.x >> 6) << 8) + (player.position.y >> 6) });
};

export default [{
type: 'player_region_changed',
regionType: 'map',
handler: regionChangedHandler
}, {
type: 'player_init',
action: playerInitHandler
}];
23 changes: 15 additions & 8 deletions src/plugins/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import { Player } from '@server/world/actor/player/player';
import { Action } from '@server/world/action';
import { basicNumberFilter } from '@server/plugins/plugin-loader';
import { Quest } from '@server/world/actor/player/quest';
import { QuestKey } from '@server/config/quest-config';


export interface QuestRequirement {
questId: string;
stage?: number;
stage?: QuestKey;
stages?: number[];
}

Expand All @@ -26,13 +27,19 @@ export function questFilter(player: Player, plugin: Action): boolean {
return plugin.questRequirement.stage === 0;
}

if(plugin.questRequirement.stage !== undefined) {
if(!basicNumberFilter(plugin.questRequirement.stage, playerQuest.progress)) {
return false;
}
} else if(plugin.questRequirement.stages !== undefined) {
if(!basicNumberFilter(plugin.questRequirement.stages, playerQuest.progress)) {
return false;
if(plugin.questRequirement.stage === 'complete') {
return playerQuest.progress === 'complete';
}

if(typeof playerQuest.progress === 'number') {
if(plugin.questRequirement.stage !== undefined) {
if(!basicNumberFilter(plugin.questRequirement.stage, playerQuest.progress)) {
return false;
}
} else if(plugin.questRequirement.stages !== undefined) {
if(!basicNumberFilter(plugin.questRequirement.stages, playerQuest.progress)) {
return false;
}
}
}

Expand Down
24 changes: 15 additions & 9 deletions src/world/action/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,18 +184,24 @@ export interface Action {
export type ActionType =
'button'
| 'widget_action'
| 'item_on_item'
| 'item_action'
| 'equip_action'
| 'world_item_action'

| 'npc_init'
| 'npc_action'

| 'object_action'

| 'item_on_object'
| 'item_on_npc'
| 'player_command'
| 'player_init'
| 'npc_init'
| 'swap_items'
| 'move_item'
| 'world_item_action'
| 'item_on_item'
| 'item_action'
| 'equip_action'

| 'quest'

| 'player_init'
| 'player_command'
| 'player_action'
| 'swap_items'
| 'move_item';
| 'player_region_changed';
7 changes: 4 additions & 3 deletions src/world/action/player-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface PlayerActionData {
}

/**
* Defines a player interaction plugin.
* Defines a player interaction action.
* The option selected, the action to be performed, and whether or not the player must first walk to the other player.
*/
export interface PlayerAction extends Action {
Expand All @@ -42,7 +42,8 @@ const playerActionHandler = (player: Player, otherPlayer: Player, position: Posi
}

// Find all player action plugins that reference this option
let interactionActions = getActionList('player_action').filter(plugin => questFilter(player, plugin) && basicStringFilter(plugin.options, option));
let interactionActions = getActionList('player_action')
.filter(plugin => questFilter(player, plugin) && basicStringFilter(plugin.options, option));
const questActions = interactionActions.filter(plugin => plugin.questRequirement !== undefined);

if(questActions.length !== 0) {
Expand All @@ -54,7 +55,7 @@ const playerActionHandler = (player: Player, otherPlayer: Player, position: Posi
return;
}

player.actionsCancelled.next();
player.actionsCancelled.next(null);

// Separate out walk-to actions from immediate actions
const walkToPlugins = interactionActions.filter(plugin => plugin.walkTo);
Expand Down
162 changes: 162 additions & 0 deletions src/world/action/player-region-changed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import { Player } from '@server/world/actor/player/player';
import { Coords, Position } from '@server/world/position';
import { Action, getActionList } from '@server/world/action/index';
import { RegionType } from '@server/world/map/region';


/**
* The definition for a player action function.
*/
export type playerRegionChangedHook = (playerActionData: PlayerRegionChangedData) => void;

/**
* Details about a player being interacted with.
*/
export interface PlayerRegionChangedData {
// The player performing the action.
player: Player;
// Whether or not the player is teleporting to their new location
teleporting: boolean;
// The original position that the player was at before moving to the new region.
originalPosition: Position;
// The position that the player ended up at in the new region.
currentPosition: Position;
// The player's original chunk coordinates
originalChunkCoords: Coords;
// The player's current chunk coordinates
currentChunkCoords: Coords;
// The player's original map region coordinates
originalMapRegionCoords: Coords;
// The player's current map region coordinates
currentMapRegionCoords: Coords;
// The player's original map region id
originalMapRegionId: number;
// The player's current map region id
currentMapRegionId: number;
// The region types that changed for the player.
regionTypes: RegionType[];
}

/**
* Defines a player region changed action.
*/
export interface PlayerRegionChangedAction extends Action {
// The action function to be performed.
handler: playerRegionChangedHook;
// Optional single region type for the action hook to apply to.
regionType?: RegionType;
// Optional multiple region types for the action hook to apply to.
regionTypes?: RegionType[];
// Optional teleporting requirement
teleporting?: boolean;
}

/**
* Creates a PlayerRegionChangedData object from the given inputs.
* @param player The player.
* @param originalPosition The player's original position.
* @param currentPosition The player's current position.
* @param teleporting Whether or not the player is teleporting; defaults to false.
*/
export const regionChangedDataFactory = (player: Player,
originalPosition: Position, currentPosition: Position,
teleporting: boolean = false): PlayerRegionChangedData => {
const regionTypes: RegionType[] = [];
const originalMapRegionId: number = ((originalPosition.x >> 6) << 8) + (originalPosition.y >> 6);
const currentMapRegionId: number = ((currentPosition.x >> 6) << 8) + (currentPosition.y >> 6);
const originalChunkCoords: Coords = {
x: originalPosition.chunkX,
y: originalPosition.chunkY,
level: originalPosition.level
};
const currentChunkCoords: Coords = {
x: currentPosition.chunkX,
y: currentPosition.chunkY,
level: currentPosition.level
};

if(originalMapRegionId !== currentMapRegionId) {
regionTypes.push('map');
}

if(!Coords.equals(originalChunkCoords, currentChunkCoords)) {
regionTypes.push('chunk');
}

if(regionTypes.length === 0) {
return null;
}

return {
player, regionTypes, teleporting,

originalPosition,
originalChunkCoords,
originalMapRegionCoords: {
x: originalPosition.x >> 6,
y: originalPosition.y >> 6,
level: originalPosition.level
},
originalMapRegionId,

currentPosition: player.position,
currentChunkCoords,
currentMapRegionCoords: {
x: currentPosition.x >> 6,
y: currentPosition.y >> 6,
level: currentPosition.level
},
currentMapRegionId
};
};

const playerRegionChangedHandler = (actionData: PlayerRegionChangedData): void => {
if(!actionData) {
return;
}

const { regionTypes } = actionData;

if(!regionTypes || regionTypes.length === 0) {
return;
}

// Find all action hooks that match the provided input
const actionList = getActionList('player_region_changed')?.filter((actionHook: PlayerRegionChangedAction) => {
if(actionHook.teleporting && !actionData.teleporting) {
return false;
}

if(actionHook.regionType) {
return regionTypes.indexOf(actionHook.regionType) !== -1;
} else if(actionHook.regionTypes && actionHook.regionTypes.length !== 0) {
let valid = false;
for(const type of actionHook.regionTypes) {
if(regionTypes.indexOf(type) !== -1) {
valid = true;
break;
}
}

return valid;
}

return false;
}) || null;

if(!actionList || actionList.length === 0) {
// No matching actions found
return;
}

actionList.forEach(async actionHook =>
new Promise<void>(resolve => {
actionHook.handler(actionData);
resolve();
}));
};

export default {
action: 'player_region_changed',
handler: playerRegionChangedHandler
};
8 changes: 6 additions & 2 deletions src/world/actor/player/player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { InterfaceState } from '@server/world/actor/player/interface-state';
import { dialogue } from '@server/world/actor/dialogue';
import { PlayerQuest, QuestKey } from '@server/config/quest-config';
import { Quest } from '@server/world/actor/player/quest';
import { regionChangedDataFactory } from '@server/world/action/player-region-changed';


export const playerOptions: { option: string, index: number, placement: 'TOP' | 'BOTTOM' }[] = [
Expand Down Expand Up @@ -233,7 +234,6 @@ export class Player extends Actor {
this.updateBonuses();
this.updateCarryWeight(true);
this.modifyWidget(widgets.musicPlayerTab, { childId: 82, textColor: colors.green }); // Set "Harmony" to green/unlocked on the music tab
this.playSong(songs.harmony);
this.updateQuestTab();

this.inventory.containerUpdated.subscribe(event => this.inventoryUpdated(event));
Expand Down Expand Up @@ -592,7 +592,8 @@ export class Player extends Actor {
* @param newPosition The player's new position.
*/
public teleport(newPosition: Position): void {
const oldChunk = world.chunkManager.getChunkForWorldPosition(this.position);
const originalPosition = this.position;
const oldChunk = world.chunkManager.getChunkForWorldPosition(originalPosition);
const newChunk = world.chunkManager.getChunkForWorldPosition(newPosition);

this.walkingQueue.clear();
Expand All @@ -604,6 +605,9 @@ export class Player extends Actor {

if(!oldChunk.equals(newChunk)) {
this.metadata['updateChunk'] = { newChunk, oldChunk };

actionHandler.call('player_region_changed', regionChangedDataFactory(
this, originalPosition, newPosition, true));
}
}

Expand Down
Loading