Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@2003scape/rsc-landscape

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@2003scape/rsc-landscape

(de)serialize runescape classic landscape files

  • 1.0.0
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
3
decreased by-50%
Maintainers
1
Weekly downloads
 
Created
Source

rsc-landscape

(de)serialize runescape classic landscape files. parse the original land and maps archives into a tile objects, dump PNGs, make changes and encode + compress them back to an original archive.

a world map generated with rsc-landscape

comparison with jagex's world map

the official world map generated by jagex contains less detail due to GIF palette compression, as well as clipped object symbols between sectors. it's also missing some areas compared to the latest revision (gertrude's house, digsite, shilo village, etc.).

install

$ npm install @2003scape/rsc-landscape

cli usage

rsc-landscape <command>

Commands:
  rsc-landscape generate-map <archives>  generate a world map image
  rsc-landscape dump-json <archives>     dump JSON files of each sector
  rsc-landscape pack-json <directory>    generate land and maps archives from a
                                         directory of JSON files

Options:
  --help     Show help                                                 [boolean]
  --version  Show version number                                       [boolean]

example

const fs = require('fs');
const { Landscape } = require('./src');

const landscape = new Landscape();

landscape.loadJag(fs.readFileSync('./land63.jag'),
    fs.readFileSync('./maps63.jag'));
landscape.loadMem(fs.readFileSync('./land63.mem'),
    fs.readFileSync('./maps63.mem'));

landscape.parseArchives();

const lumbridge = landscape.sectors[50][50][0];
process.stdout.write(lumbridge.toString(true));
fs.writeFileSync(`./sector-lumbridge.png`, lumbridge.toCanvas().toBuffer());

(async () => {
    fs.writeFileSync(`./worldmap.png`, (await landscape.toCanvas({
        points: require('./map-points.json'),
        objects: require('./object-locs.json'),
        labels: require('./map-labels.json')
    })).toBuffer());
})();

file formats

the runescape classic world is separated into sectors, each containing 48x48 (2304) tiles. each sector has at least 1 file associated with it:

  • a .hei file in the land archive which stores the elevation and colour of each tile
  • a .dat file in the maps archive which stores the wall and object direction of each tile
  • an optional .loc file in the maps archive which stores object IDs (used for the login screen previews)

api

.terrainColours.integer

array of the original, undarkened 256 colours the client uses for each tile.

.terrainColours.rgb

array of 256 map colours used for each tile, darkened by 50% and converted to rgb(r, g, b) format.

.overlays

map of overlay names to overlay IDs.

.overlayColours

map of overlay names corresponding to the colour that should be used to represent it on a map.

tile = new Tile({ sector, x, y, ... })

create a new sector tile. accepts all of the properties below in object.

tile.colour

number from 0-255 corresponding to colour in .terrainColours.

tile.elevation

number from 0-255 describing the height of the tile.

tile.direction

number from 0-6 describing the direction objects should face on this tile.

tile.overlay

overlay type index. the corresponding names are stored in .overlays.

tile.wall

object with the following potential properties:

{
    diagonal: {
        direction: '/' || '\\',
        overlay: overlay
    } || null,
    vertical: overlay || 0,
    horizontal: overlay || 0,
    roof: roofOverlay || 0
}

tile.objectId

store an object here for the login screen previews.

tile.populate()

read buffers from tile's sector and populate its properties.

sector = new Sector({ x, y, plane, members?, tiles? })

create a new sector instance.

sector.members

should this be stored in the .jag or .mem?

sector.width

amount of tiles on the x axis (48).

sector.height

amount of tiles on the y axis (48).

sector.terrainHeight

sector.terrainColour

sector.wallsVertical

sector.wallsHorizontal

sector.wallsRoof

sector.tileDecoration

sector.tileDirection

Int8Array buffers populated from archive files with sector.parse* or from sector's tile objects with sector.populateBuffers(). these buffers are encoded + compressed into final file buffers.

sector.wallsDiagonal

Int32Array buffer, similar to above but 32-bit to store values > 255 ( potentially larger than 48000 if objects are stored).

sector.tiles[width][height]

2d array of tile objects. populate this field from the archive buffers with sector.populateTiles(), or populate the future archive buffers with sector.populateBuffers().

sector.parseHei(buffer)

populate sector.terrainHeight and sector.terrainColour from a .hei file.

sector.parseDat(buffer)

populate sector.walls*, sector.tileDecoration and sector.tileDirection from a .dat file.

sector.parseLoc(buffer)

populate sector.wallsDiagonal with object IDs from a .loc file.

sector.populateTiles()

populate sector.tiles with a 2d array (48x48) of tile objects based on buffers we parsed from archived files.

sector.populateBuffers()

populate future archive buffers (sector.terrain*, sector.wall*, etc.) with sector.tiles.

sector.getEntryName()

get the main portion of a landscape archive filename.

sector.toHei()

get a .hei file buffer for this sector.

sector.toDat()

get a .dat file buffer for this sector.

sector.toLoc()

get a .loc file buffer for this sector (or null if no objects ID are stored).

sector.toCanvas(options, [ north, east, south, west ])

render an individual sector to a canvas. the second argument is optional if you want to antialias the edges properly using the neighbouring sectors (world map generation does this automatically).

in node, you can turn this into a PNG with .toBuffer().

sector.toString(terminal = false)

if terminal is true, return a nethack-esque terminal rendering of the sector:

...otherwise just return the name and size of the sector.

landscape = new Landscape()

generate a new landscape (de)serializer instance.

landscape.loadJag(landBuffer, mapBuffer)

landscape.loadMem(landBuffer, mapBuffer)

prepare .jag and .mem buffers to be parsed. any sectors loaded with landscape.loadMem will have sector.members = true.

landscape.parseArchives()

populate landscape.sectors with loaded buffers.

*landscape.getPopulatedSectors()

return an iterator of all the non-empty sectors.

landscape.getSectorNeighbours(x, y, plane)

return neighbours to a sector position as [north, east, south, west].

async landscape.toCanvas({ objects, points, labels })

create a world map image from all of the non-empty sectors.

  • objects is an optional array of the following:
{
    id: 1,
    position: [x, y]
}

its x and y are multipled by the tile size.

  • points is an optional array of the following:
{
    type: 'altar', // 'general-shop', 'dungeon' etc. see ./res/key/
    x, y
}

each point image is 15x15.

  • labels is an optional array of the following:
{
    text: 'label\nfor\nsomething',
    x, y,
    size: 10, // 8 is the smallest in use, while 14 is the largest
    align: 'center',
    bold: true || undefined,
    colour: 'rgb(254, 165, 0)' || undefined
}

license

Copyright 2019 2003Scape Team

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Keywords

FAQs

Package last updated on 03 Dec 2019

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc