Skip to content

Commit

Permalink
Merge pull request #244 from rune-js/feature/world-item-spawns
Browse files Browse the repository at this point in the history
Implementing a world item spawning system
  • Loading branch information
Tynarus authored Dec 19, 2020
2 parents 52261d1 + 92d6f78 commit 28c426c
Show file tree
Hide file tree
Showing 23 changed files with 248 additions and 60 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ module.exports = {
"object-curly-spacing": [ "error", "always" ],
"no-var": "error",
"prefer-const": "error",
"indent": [ "error", 4, {
"indent": [ "warn", 4, {
"SwitchCase": 1
} ],
"@typescript-eslint/no-inferrable-types": 0,
Expand Down
34 changes: 34 additions & 0 deletions data/config/item-spawns/lumbridge/lumbridge.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[
{
"item": "rs:coins",
"amount": 25,
"spawn_x": 3211,
"spawn_y": 3240,
"instance": "global",
"respawn": 25,
"metadata": {
"hello": "world"
}
},
{
"item": "rs:egg",
"spawn_x": 3191,
"spawn_y": 3276
},
{
"item": "rs:egg",
"spawn_x": 3226,
"spawn_y": 3300
},
{
"item": "rs:egg",
"spawn_x": 3228,
"spawn_y": 3299
},
{
"item": "rs:egg",
"spawn_x": 3231,
"spawn_y": 3301,
"instance": "player"
}
]
6 changes: 6 additions & 0 deletions data/config/items/skills/baking.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,11 @@
"examine": "Useful for baking cakes.",
"tradable": true,
"weight": 0.1
},
"rs:egg": {
"game_id": 1944,
"examine": "A nice fresh egg.",
"tradable": true,
"weight": 0.02
}
}
9 changes: 9 additions & 0 deletions src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
import { loadNpcSpawnConfigurations, NpcSpawn } from '@server/config/npc-spawn-config';
import { loadShopConfigurations, Shop } from '@server/config/shop-config';
import { Quest } from '@server/world/actor/player/quest';
import { ItemSpawn, loadItemSpawnConfigurations } from '@server/config/item-spawn-config';
require('json5/lib/register');

export async function loadConfigurationFiles(configurationDir: string): Promise<any[]> {
Expand Down Expand Up @@ -47,11 +48,15 @@ export let npcMap: { [key: string]: NpcDetails };
export let npcIdMap: { [key: number]: string };
export let npcPresetMap: NpcPresetConfiguration;
export let npcSpawns: NpcSpawn[] = [];
export let itemSpawns: ItemSpawn[] = [];
export let shopMap: { [key: string]: Shop };

export const widgets: { [key: string]: any } = require('../../data/config/widgets.json5');


export async function loadConfigurations(): Promise<void> {
logger.info(`Loading server configurations...`);

const { items, itemIds, itemPresets } = await loadItemConfigurations('data/config/items');
itemMap = items;
itemIdMap = itemIds;
Expand All @@ -63,8 +68,12 @@ export async function loadConfigurations(): Promise<void> {
npcPresetMap = npcPresets;

npcSpawns = await loadNpcSpawnConfigurations('data/config/npc-spawns');
itemSpawns = await loadItemSpawnConfigurations('data/config/item-spawns');

shopMap = await loadShopConfigurations('data/config/shops');

logger.info(`Loaded ${Object.keys(itemMap).length} items, ${itemSpawns.length} item spawns, ` +
`${Object.keys(npcMap).length} npcs, ${npcSpawns.length} npc spawns, and ${Object.keys(shopMap).length} shops.`);
}


Expand Down
57 changes: 57 additions & 0 deletions src/config/item-spawn-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Position } from '@server/world/position';
import { loadConfigurationFiles } from '@server/config/index';


export interface ItemSpawnConfiguration {
item: string;
amount?: number;
spawn_x: number;
spawn_y: number;
spawn_level?: number;
instance?: 'global' | 'player';
respawn?: number;
metadata?: { [key: string]: unknown };
}

export class ItemSpawn {

public itemKey: string;
public amount: number = 1;
public spawnPosition: Position;
public instance: 'global' | 'player' = 'global';
public respawn: number = 30;
public metadata: { [key: string]: unknown } = {};

public constructor(itemKey: string, position: Position) {
this.itemKey = itemKey;
this.spawnPosition = position;
}

}

export function translateItemSpawnConfig(config: ItemSpawnConfiguration): ItemSpawn {
const spawn = new ItemSpawn(config.item, new Position(config.spawn_x, config.spawn_y, config.spawn_level || 0));
if(config.amount !== undefined) {
spawn.amount = config.amount;
}
if(config.instance !== undefined) {
spawn.instance = config.instance;
}
if(config.respawn !== undefined) {
spawn.respawn = config.respawn;
}
if(config.metadata !== undefined) {
spawn.metadata = config.metadata;
}

return spawn;
}

export async function loadItemSpawnConfigurations(path: string): Promise<ItemSpawn[]> {
const itemSpawns = [];

const files = await loadConfigurationFiles(path);
files.forEach(spawns => spawns.forEach(itemSpawn => itemSpawns.push(translateItemSpawnConfig(itemSpawn))));

return itemSpawns;
}
8 changes: 4 additions & 4 deletions src/config/npc-spawn-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ export interface NpcSpawnConfiguration {

export class NpcSpawn {

readonly npcKey: string;
readonly spawnPosition: Position;
readonly movementRadius: number;
readonly faceDirection: Direction;
public npcKey: string;
public spawnPosition: Position;
public movementRadius: number;
public faceDirection: Direction;

public constructor(npcKey: string, spawnPosition: Position, movementRadius: number = 0,
faceDirection: Direction = 'WEST') {
Expand Down
9 changes: 8 additions & 1 deletion src/net/inbound-packets/pickup-item-packet.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,14 @@ const pickupItemPacket = (player, packet) => {

const worldMods = player.instance.getInstancedChunk(worldItemPosition);
const worldItems = worldMods?.mods?.get(worldItemPosition.key)?.worldItems || [];
const worldItem = worldItems.find(i => i.itemId === itemId) || null;

let worldItem = worldItems.find(i => i.itemId === itemId) || null;

if(!worldItem) {
const personalMods = player.personalInstance.getInstancedChunk(worldItemPosition);
const personalItems = personalMods?.mods?.get(worldItemPosition.key)?.worldItems || [];
worldItem = personalItems.find(i => i.itemId === itemId) || null;
}

if(worldItem && !worldItem.removed) {
if(worldItem.owner && !worldItem.owner.equals(player)) {
Expand Down
6 changes: 4 additions & 2 deletions src/plugins/combat/combat-styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ export function updateCombatStyle(player: Player, weaponStyle: WeaponStyle, styl
player.savedMetadata.combatStyle = [ weaponStyle, styleIndex ];
player.settings.attackStyle = styleIndex;

const buttonId = combatStyles[weaponStyle][styleIndex].button_id;
player.outgoingPackets.updateClientConfig(widgetScripts.attackStyle, buttonId);
const buttonId = combatStyles[weaponStyle][styleIndex]?.button_id;
if(buttonId !== undefined) {
player.outgoingPackets.updateClientConfig(widgetScripts.attackStyle, buttonId);
}
}

export function showUnarmed(player: Player): void {
Expand Down
11 changes: 6 additions & 5 deletions src/plugins/combat/combat.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { npcAction } from '@server/world/action/npc-action';
import { Actor } from '@server/world/actor/actor';
import { Player } from '@server/world/actor/player/player';
import { timer } from 'rxjs';
import { lastValueFrom, timer } from 'rxjs';
import { World } from '@server/world';
import { filter, take } from 'rxjs/operators';
import { animationIds } from '@server/world/config/animation-ids';
Expand All @@ -28,8 +28,8 @@ class Combat {
public cancelCombat(): void {
this.contactInitiated = false;
this.combatActive = false;
this.assailant.actionsCancelled.next();
this.victim.actionsCancelled.next();
this.assailant.actionsCancelled.next(null);
this.victim.actionsCancelled.next(null);
}

public async initiateCombat(): Promise<void> {
Expand Down Expand Up @@ -59,7 +59,7 @@ class Combat {
await this.assailant.tail(this.victim);

if(!firstAttack) {
await timer(4 * World.TICK_LENGTH).toPromise();
await lastValueFrom(timer(4 * World.TICK_LENGTH).pipe(take(1)));
}

if(!this.combatActive) {
Expand Down Expand Up @@ -155,7 +155,8 @@ class Combat {
instance = victim.instance;
}

instance.spawnWorldItem(itemIds.bones, deathPosition, this.assailant instanceof Player ? this.assailant : undefined, 300);
instance.spawnWorldItem(itemIds.bones, deathPosition,
{ owner: this.assailant instanceof Player ? this.assailant : undefined, expires: 300 });
}

// https://forum.tip.it/topic/199687-runescape-formulas-revealed
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/items/drop-item-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ export const action: itemAction = ({ player, itemId, itemSlot }) => {
inventory.remove(itemSlot);
player.outgoingPackets.sendUpdateSingleWidgetItem(widgets.inventory, itemSlot, null);
player.playSound(soundIds.dropItem, 5);
player.instance.spawnWorldItem(item, player.position, player, 300);
player.actionsCancelled.next();
player.instance.spawnWorldItem(item, player.position, { owner: player, expires: 300 });
player.actionsCancelled.next(null);
};

export default {
Expand Down
20 changes: 11 additions & 9 deletions src/plugins/items/pickup-item-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@ import { Item } from '../../world/items/item';
import { soundIds } from '@server/world/config/sound-ids';
import { widgets } from '@server/config';


export const action: worldItemAction = ({ player, worldItem, itemDetails }) => {
const inventory = player.inventory;
let slot = -1;
let amount = worldItem.amount;
const amount = worldItem.amount;
let slot = -1

if(itemDetails.stackable) {
const existingItemIndex = inventory.findIndex(worldItem.itemId);
if(existingItemIndex !== -1) {
const existingItem = inventory.items[existingItemIndex];
if(existingItem.amount + worldItem.amount < 2147483647) {
existingItem.amount += worldItem.amount;
amount += existingItem.amount;
if(existingItem.amount + worldItem.amount >= 2147483647) {
// @TODO create new item stack
return;
} else {
slot = existingItemIndex;
}
}
Expand All @@ -29,17 +31,17 @@ export const action: worldItemAction = ({ player, worldItem, itemDetails }) => {
return;
}

player.instance.despawnWorldItem(worldItem);
worldItem.instance.despawnWorldItem(worldItem);

const item: Item = {
itemId: worldItem.itemId,
amount
};

inventory.add(item);
player.outgoingPackets.sendUpdateSingleWidgetItem(widgets.inventory, slot, item);
const addedItem = inventory.add(item);
player.outgoingPackets.sendUpdateSingleWidgetItem(widgets.inventory, addedItem.slot, addedItem.item);
player.playSound(soundIds.pickupItem, 3);
player.actionsCancelled.next();
player.actionsCancelled.next(null);
};

export default {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
startTutorial,
unlockAvailableTabs
} from '@server/plugins/quests/goblin-diplomacy-tutorial/goblin-diplomacy';
import { schedule } from '@server/task/task';
import { schedule } from '@server/world/task';
import { world } from '@server/game-server';
import { findNpc } from '@server/config';
import { Cutscene } from '@server/world/actor/player/cutscenes';
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/rune.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ export * from '../world/action';
export * from '../world/actor/update-flags';
export * from '../world/actor/skills';
export * from '../world/actor/player/achievements';
export * from '../task/task';
export * from '../world/task';
export { widgets } from '../config';
4 changes: 2 additions & 2 deletions src/plugins/skills/firemaking-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const lightFire = (player: Player, position: Position, worldItemLog: WorldItem,
}

player.instance.spawnTemporaryGameObject(fireObject, position, fireDuration()).then(() => {
player.instance.spawnWorldItem({ itemId: itemIds.ashes, amount: 1 }, position, null, 300);
player.instance.spawnWorldItem({ itemId: itemIds.ashes, amount: 1 }, position, { expires: 300 });
});

player.face(position, false);
Expand Down Expand Up @@ -89,7 +89,7 @@ const action: itemOnItemAction = (details) => {
// @TODO check firemaking level

player.removeItem(removeFromSlot);
const worldItemLog = player.instance.spawnWorldItem(log, player.position, player, 300);
const worldItemLog = player.instance.spawnWorldItem(log, player.position, { owner: player, expires: 300 });

if(player.metadata['lastFire'] && Date.now() - player.metadata['lastFire'] < 1200 &&
canChain(skillInfo.requiredLevel, player.skills.firemaking.level)) {
Expand Down
17 changes: 0 additions & 17 deletions src/task/task.ts

This file was deleted.

1 change: 1 addition & 0 deletions src/world/actor/player/player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ export class Player extends Actor {
resolve();
});

world.spawnWorldItems(this);
this.chunkChanged(playerChunk);

this.outgoingPackets.flushQueue();
Expand Down
2 changes: 1 addition & 1 deletion src/world/actor/player/sync/npc-sync-task.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Task } from '@server/task/task';
import { Task } from '@server/world/task';
import { Player } from '../player';
import { Packet, PacketType } from '@server/net/packet';
import { Npc } from '@server/world/actor/npc/npc';
Expand Down
2 changes: 1 addition & 1 deletion src/world/actor/player/sync/player-sync-task.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Player } from '../player';
import { Task } from '@server/task/task';
import { Task } from '@server/world/task';
import { UpdateFlags } from '@server/world/actor/update-flags';
import { Packet, PacketType } from '@server/net/packet';
import { world } from '@server/game-server';
Expand Down
Loading

0 comments on commit 28c426c

Please sign in to comment.