Skip to content

Commit

Permalink
feat: client browser configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
ultraviolet-jordan committed Feb 4, 2024
1 parent 73282e6 commit 8a02d5b
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 71 deletions.
154 changes: 109 additions & 45 deletions src/js/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import ClientStream from './jagex2/io/ClientStream';
import Protocol from './jagex2/io/Protocol';
import Isaac from './jagex2/io/Isaac';
import Database from './jagex2/io/Database';
import ServerProt from './jagex2/io/ServerProt';
import ClientProt from './jagex2/io/ClientProt';

import WordFilter from './jagex2/wordenc/WordFilter';
import WordPack from './jagex2/wordenc/WordPack';
Expand Down Expand Up @@ -58,41 +60,36 @@ import ProjectileEntity from './jagex2/dash3d/entity/ProjectileEntity';
import SpotAnimEntity from './jagex2/dash3d/entity/SpotAnimEntity';

import {playMidi, playWave, setMidiVolume, setWaveVolume, stopMidi} from './jagex2/util/AudioUtil.js';
import {arraycopy, downloadUrl, sleep} from './jagex2/util/JsUtil';
import ServerProt from './jagex2/io/ServerProt';
import ClientProt from './jagex2/io/ClientProt';
import {arraycopy, downloadText, downloadUrl, sleep} from './jagex2/util/JsUtil';
import {Int32Array2d, Int32Array3d, TypedArray1d, TypedArray3d, Uint8Array3d} from './jagex2/util/Arrays';

// noinspection JSSuspiciousNameCombination
class Client extends GameShell {
// static readonly HOST: string = 'http://localhost';
// static readonly PORT: number = 43595;
static readonly HOST: string = 'https://w2.225.2004scape.org';
static readonly PORT: number = 43599;
static readonly CHARSET: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!"£$%^&*()-_=+[{]};:\'@#~,<.>/?\\| ';

static EXPONENT: bigint = 58778699976184461502525193738213253649000149147835990136706041084440742975821n;
static MODULUS: bigint = 7162900525229798032761816791230527296329313291232324290237849263501208207972894053929065636522363163621000728841182238772712427862772219676577293600221789n;
static MEMBERS: boolean = true;
static readonly clientversion: number = 225;
static nodeId: number = 10;
static portOffset: number = 0;
static members: boolean = true;
static lowMemory: boolean = false;

static updateCounter: number = 0;
static update2Counter: number = 0;
static sidebarInputCounter: number = 0;
static opHeld1Counter: number = 0;
static opLoc4Counter: number = 0;
static opNpc5Counter: number = 0;
static drawCounter: number = 0;
static opHeld4Counter: number = 0;
static opLoc5Counter: number = 0;
static opNpc3Counter: number = 0;
static opHeld9Counter: number = 0;
static opPlayer2Counter: number = 0;
static updatePlayersCounter: number = 0;
static ifButton5Counter: number = 0;
static updateLocCounter: number = 0;

static nodeId: number = 0; // TODO
static serverAddress: string = '';

private static readonly exponent: bigint = 58778699976184461502525193738213253649000149147835990136706041084440742975821n;
private static readonly modulus: bigint = 7162900525229798032761816791230527296329313291232324290237849263501208207972894053929065636522363163621000728841182238772712427862772219676577293600221789n;

private static updateCounter: number = 0;
private static update2Counter: number = 0;
private static sidebarInputCounter: number = 0;
private static opHeld1Counter: number = 0;
private static opLoc4Counter: number = 0;
private static opNpc5Counter: number = 0;
private static drawCounter: number = 0;
private static opHeld4Counter: number = 0;
private static opLoc5Counter: number = 0;
private static opNpc3Counter: number = 0;
private static opHeld9Counter: number = 0;
private static opPlayer2Counter: number = 0;
private static updatePlayersCounter: number = 0;
private static ifButton5Counter: number = 0;
private static updateLocCounter: number = 0;

static setHighMemory = (): void => {
World3D.lowMemory = false;
Expand Down Expand Up @@ -515,7 +512,7 @@ class Client extends GameShell {
await Bzip.load(await (await fetch('bz2.wasm')).arrayBuffer());
this.db = new Database(await Database.openDatabase());

const checksums: Packet = new Packet(new Uint8Array(await downloadUrl(`${Client.HOST}/crc`)));
const checksums: Packet = new Packet(new Uint8Array(await downloadUrl(`${Client.serverAddress}/crc`)));
for (let i: number = 0; i < 9; i++) {
this.archiveChecksums[i] = checksums.g4;
}
Expand Down Expand Up @@ -682,7 +679,7 @@ class Client extends GameShell {
SeqType.unpack(config);
LocType.unpack(config);
FloType.unpack(config);
ObjType.unpack(config, Client.MEMBERS);
ObjType.unpack(config, Client.members);
NpcType.unpack(config);
IdkType.unpack(config);
SpotAnimType.unpack(config);
Expand Down Expand Up @@ -1298,8 +1295,8 @@ class Client extends GameShell {
}

let valid: boolean = false;
for (let i: number = 0; i < Client.CHARSET.length; i++) {
if (String.fromCharCode(key) === Client.CHARSET.charAt(i)) {
for (let i: number = 0; i < PixFont.CHARSET.length; i++) {
if (String.fromCharCode(key) === PixFont.CHARSET.charAt(i)) {
valid = true;
break;
}
Expand Down Expand Up @@ -1438,7 +1435,7 @@ class Client extends GameShell {
this.loginMessage1 = 'Connecting to server...';
await this.drawTitleScreen();
}
this.stream = new ClientStream(await ClientStream.openSocket({host: Client.HOST, port: Client.PORT}));
this.stream = new ClientStream(await ClientStream.openSocket({host: Client.serverAddress, port: 43594 + Client.portOffset}));
await this.stream?.readBytes(this.in.data, 0, 8);
this.in.pos = 0;
this.serverSeed = this.in.g8;
Expand All @@ -1452,7 +1449,7 @@ class Client extends GameShell {
this.out.p4(0); // TODO signlink UUID
this.out.pjstr(username);
this.out.pjstr(password);
this.out.rsaenc(Client.MODULUS, Client.EXPONENT);
this.out.rsaenc(Client.modulus, Client.exponent);
this.loginout.pos = 0;
if (reconnect) {
this.loginout.p1(18);
Expand All @@ -1473,7 +1470,6 @@ class Client extends GameShell {
this.randomIn = new Isaac(seed);
this.stream?.write(this.loginout.data, this.loginout.pos, 0);
const reply: number = await this.stream.read();
console.log(`Login reply was: ${reply}`);

if (reply === 1) {
await sleep(2000);
Expand Down Expand Up @@ -7049,7 +7045,6 @@ class Client extends GameShell {
};

private addMessage = (type: number, text: string, sender: string): void => {
console.log(`${type}, ${text}, ${sender}, ${this.stickyChatInterfaceId}`);
if (type === 0 && this.stickyChatInterfaceId !== -1) {
this.modalMessage = text;
this.mouseClickButton = 0;
Expand Down Expand Up @@ -8626,7 +8621,6 @@ class Client extends GameShell {
player.chatColor = colorEffect >> 8;
player.chatStyle = colorEffect & 0xff;
player.chatTimer = 150;
console.log(filtered);
if (type > 1) {
this.addMessage(1, filtered, player.name);
} else {
Expand Down Expand Up @@ -10162,7 +10156,7 @@ class Client extends GameShell {
await this.showProgress(progress, `Requesting ${displayName}`);

try {
data = await downloadUrl(`${Client.HOST}/${filename}${crc}`);
data = await downloadUrl(`${Client.serverAddress}/${filename}${crc}`);
} catch (e) {
data = undefined;
for (let i: number = retry; i > 0; i--) {
Expand All @@ -10187,7 +10181,7 @@ class Client extends GameShell {

if (!data) {
try {
data = await downloadUrl(`${Client.HOST}/${name}_${crc}.mid`);
data = await downloadUrl(`${Client.serverAddress}/${name}_${crc}.mid`);
if (length !== data.length) {
data = data.slice(0, length);
}
Expand Down Expand Up @@ -10492,7 +10486,77 @@ class Client extends GameShell {
};
}

const client: Client = new Client();
Client.setHighMemory();
console.log('RS2 user client - release #225');
client.run().then((): void => {});
// ----

// main to launch the client
type WorldList = {
id: number;
region: string;
address: string;
portOffset: number;
players: number;
members?: boolean;
};

const hostname: string = window.location.hostname;
const secured: boolean = hostname.startsWith('https');

//// check and set default browser params before starting
if (GameShell.getParameter('world').length === 0) {
GameShell.setParameter('world', '1');
}

if (GameShell.getParameter('detail').length === 0) {
GameShell.setParameter('detail', 'high');
}

if (GameShell.getParameter('method').length === 0) {
GameShell.setParameter('method', '0');
}

if (hostname === 'localhost' && GameShell.getParameter('world') === '0') {
localConfiguration();
} else {
await liveConfiguration();
}

if (GameShell.getParameter('detail') === 'low') {
Client.setLowMemory();
} else {
Client.setHighMemory();
}

console.log(`RS2 user client - release #${Client.clientversion}`);
new Client().run().then((): void => {});

function localConfiguration(): void {
Client.serverAddress = 'http://localhost';
Client.portOffset = 0;
}

async function liveConfiguration(): Promise<void> {
// noinspection HttpUrlsUsage
const world: WorldList = await getWorldInfo(parseInt(GameShell.getParameter('world'), 10));

Client.nodeId = 10 + world.id - 1;
// noinspection HttpUrlsUsage
Client.serverAddress = world.address;
if (!secured) {
Client.serverAddress = Client.serverAddress.replace('https', 'http');
}
Client.portOffset = world.portOffset;
Client.members = world?.members === true;
}

async function getWorldInfo(id: number, retries: number = 0): Promise<WorldList> {
if (retries >= 10) {
throw new Error('could not find world to connect!');
}
const worldlist: WorldList[] = JSON.parse(await downloadText('http://2004scape.org/api/v1/worldlist'));
const world: WorldList | undefined = worldlist.find((x): boolean => x.id === id);
if (!world) {
await sleep(1000);
return getWorldInfo(id, ++retries);
}
return world;
}
36 changes: 18 additions & 18 deletions src/js/jagex2/graphics/PixFont.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,31 @@ import JavaRandom from '../util/JavaRandom';
import Colors from './Colors';

export default class PixFont extends Hashable {
static CHARSET: number[] = [];
static readonly CHARSET: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!"£$%^&*()-_=+[{]};:\'@#~,<.>/?\\| ';
static readonly CHARCODESET: number[] = [];

static {
const s: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!"£$%^&*()-_=+[{]};:\'@#~,<.>/?\\| ';

for (let i: number = 0; i < 256; i++) {
let c: number = s.indexOf(String.fromCharCode(i));
let c: number = PixFont.CHARSET.indexOf(String.fromCharCode(i));

if (c === -1) {
c = 74; // space
}

PixFont.CHARSET[i] = c;
PixFont.CHARCODESET[i] = c;
}
}

charMask: Int8Array[] = [];
charMaskWidth: Int32Array = new Int32Array(94);
charMaskHeight: Int32Array = new Int32Array(94);
charOffsetX: Int32Array = new Int32Array(94);
charOffsetY: Int32Array = new Int32Array(94);
charAdvance: Int32Array = new Int32Array(95);
drawWidth: Int32Array = new Int32Array(256);
private readonly charMask: Int8Array[] = [];
private readonly charMaskWidth: Int32Array = new Int32Array(94);
private readonly charMaskHeight: Int32Array = new Int32Array(94);
private readonly charOffsetX: Int32Array = new Int32Array(94);
private readonly charOffsetY: Int32Array = new Int32Array(94);
private readonly charAdvance: Int32Array = new Int32Array(95);
private readonly drawWidth: Int32Array = new Int32Array(256);
private readonly random: JavaRandom = new JavaRandom(BigInt(Date.now()));

height: number = 0;
random: JavaRandom = new JavaRandom(BigInt(Date.now()));

static fromArchive = (archive: Jagfile, name: string): PixFont => {
const dat: Packet = new Packet(archive.read(name + '.dat'));
Expand Down Expand Up @@ -104,7 +104,7 @@ export default class PixFont extends Hashable {

font.charAdvance[94] = font.charAdvance[8];
for (let i: number = 0; i < 256; i++) {
font.drawWidth[i] = font.charAdvance[PixFont.CHARSET[i]];
font.drawWidth[i] = font.charAdvance[PixFont.CHARCODESET[i]];
}

return font;
Expand All @@ -121,7 +121,7 @@ export default class PixFont extends Hashable {
const length: number = str.length;
y -= this.height;
for (let i: number = 0; i < length; i++) {
const c: number = PixFont.CHARSET[str.charCodeAt(i)];
const c: number = PixFont.CHARCODESET[str.charCodeAt(i)];

if (c !== 94) {
this.drawChar(this.charMask[c], x + this.charOffsetX[c], y + this.charOffsetY[c], this.charMaskWidth[c], this.charMaskHeight[c], color);
Expand All @@ -142,7 +142,7 @@ export default class PixFont extends Hashable {
color = this.evaluateTag(str.substring(i + 1, i + 4));
i += 4;
} else {
const c: number = PixFont.CHARSET[str.charCodeAt(i)];
const c: number = PixFont.CHARCODESET[str.charCodeAt(i)];

if (c !== 94) {
if (shadowed) {
Expand Down Expand Up @@ -205,7 +205,7 @@ export default class PixFont extends Hashable {
color = this.evaluateTag(str.substring(i + 1, i + 4));
i += 4;
} else {
const c: number = PixFont.CHARSET[str.charCodeAt(i)];
const c: number = PixFont.CHARCODESET[str.charCodeAt(i)];
if (c !== 94) {
if (shadowed) {
this.drawCharAlpha(x + this.charOffsetX[c] + 1, offY + this.charOffsetY[c] + 1, this.charMaskWidth[c], this.charMaskHeight[c], Colors.BLACK, 192, this.charMask[c]);
Expand Down Expand Up @@ -244,7 +244,7 @@ export default class PixFont extends Hashable {
const offY: number = y - this.height;

for (let i: number = 0; i < str.length; i++) {
const c: number = PixFont.CHARSET[str.charCodeAt(i)];
const c: number = PixFont.CHARCODESET[str.charCodeAt(i)];

if (c != 94) {
this.drawChar(this.charMask[c], x + this.charOffsetX[c], offY + this.charOffsetY[c] + ((Math.sin(i / 2.0 + phase / 5.0) * 5.0) | 0), this.charMaskWidth[c], this.charMaskHeight[c], color);
Expand Down
9 changes: 4 additions & 5 deletions src/js/jagex2/graphics/PixMap.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import Draw2D from './Draw2D';
import {canvas2d} from './Canvas';
import Colors from './Colors';

export default class PixMap {
// constructor
readonly image: ImageData;
private readonly image: ImageData;
private readonly width: number;
private readonly height: number;
private readonly ctx: CanvasRenderingContext2D;
readonly pixels: Int32Array;
readonly width: number;
readonly height: number;
readonly ctx: CanvasRenderingContext2D;

constructor(width: number, height: number, ctx: CanvasRenderingContext2D = canvas2d) {
this.ctx = ctx;
Expand Down
8 changes: 5 additions & 3 deletions src/js/jagex2/io/ClientStream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ export default class ClientStream {

static openSocket = async (socket: Socket): Promise<WebSocket> => {
return await new Promise<WebSocket>((resolve, reject): void => {
const protocol: string = socket.host.startsWith('https') ? 'wss' : 'ws';
const secured: boolean = socket.host.startsWith('https');
const protocol: string = secured ? 'wss' : 'ws';
const host: string = socket.host.substring(socket.host.indexOf('//') + 2);
const ws: WebSocket = new WebSocket(`${protocol}://${host}:${socket.port}`, 'binary');
const port: number = secured ? socket.port + 2 : socket.port + 1;
const ws: WebSocket = new WebSocket(`${protocol}://${host}:${port}`, 'binary');
ws.binaryType = 'arraybuffer';

ws.addEventListener('open', (): void => {
Expand Down Expand Up @@ -68,7 +70,7 @@ export default class ClientStream {
}

if (this.remaining < 1) {
await sleep(1); // TODO maybe not do this?
await sleep(1);
return this.read();
}

Expand Down

0 comments on commit 8a02d5b

Please sign in to comment.