@2003scape/rsc-client
Version:
runescape classic web client
1,823 lines (1,499 loc) • 85.5 kB
JavaScript
const Utility = require('./utility');
const SLEEP_WIDTH = 255;
const SLEEP_HEIGHT = 40;
const BLACK = 0;
const DARK_GREY = 0xa0a0a0;
const LIGHT_GREY = 0xdcdcdc;
const C_0 = '0'.charCodeAt(0);
const C_9 = '9'.charCodeAt(0);
class Surface {
constructor(width, height, limit, mudclient) {
this.mudclient = mudclient;
this.image = null;
this.anIntArray340 = null;
this.anIntArray341 = null;
this.anIntArray342 = null;
this.anIntArray343 = null;
this.anIntArray344 = null;
this.anIntArray345 = null;
this.boundsTopY = 0;
this.boundsTopX = 0;
this.interlace = false;
this.loggedIn = false;
this.boundsBottomY = height;
this.boundsBottomX = width;
this.width1 = this.width2 = width;
this.height1 = this.height2 = height;
this.area = width * height;
this.pixels = new Int32Array(width * height);
this.surfacePixels = [];
this.surfacePixels.length = limit;
this.surfacePixels.fill(null);
this.spriteColoursUsed = [];
this.spriteColoursUsed.length = limit;
this.spriteColoursUsed.fill(null);
this.spriteColourList = [];
this.spriteColourList.length = limit;
this.spriteColourList.fill(null);
this.spriteTranslate = new Int8Array(limit);
this.spriteWidth = new Int32Array(limit);
this.spriteHeight = new Int32Array(limit);
this.spriteWidthFull = new Int32Array(limit);
this.spriteHeightFull = new Int32Array(limit);
this.spriteTranslateX = new Int32Array(limit);
this.spriteTranslateY = new Int32Array(limit);
this.rgbPixels = new Uint8Array(
this.pixels.buffer,
this.pixels.byteOffset
);
this.imageData = mudclient._graphics.ctx.createImageData(width, height);
this.setComplete();
}
static rgbToInt(red, green, blue) {
return (red << 16) + (green << 8) + blue;
}
static createFont(bytes, id) {
Surface.gameFonts[id] = bytes;
}
setComplete() {
for (let i = 0; i < this.area * 4; i += 4) {
const blue = this.rgbPixels[i];
this.rgbPixels[i] = this.rgbPixels[i + 2];
this.rgbPixels[i + 2] = blue;
this.rgbPixels[i + 3] = 255;
}
this.imageData.data.set(this.rgbPixels);
}
setBounds(x1, y1, x2, y2) {
if (x1 < 0) {
x1 = 0;
}
if (y1 < 0) {
y1 = 0;
}
if (x2 > this.width2) {
x2 = this.width2;
}
if (y2 > this.height2) {
y2 = this.height2;
}
this.boundsTopX = x1;
this.boundsTopY = y1;
this.boundsBottomX = x2;
this.boundsBottomY = y2;
}
resetBounds() {
this.boundsTopX = 0;
this.boundsTopY = 0;
this.boundsBottomX = this.width2;
this.boundsBottomY = this.height2;
}
draw(graphics, x, y) {
this.setComplete();
graphics.drawImage(this.imageData, x, y);
}
blackScreen() {
const area = this.width2 * this.height2;
if (!this.interlace) {
for (let i = 0; i < area; i++) {
this.pixels[i] = 0;
}
return;
}
let pixelIdx = 0;
for (let y = -this.height2; y < 0; y += 2) {
for (let x = -this.width2; x < 0; x++) {
this.pixels[pixelIdx++] = 0;
}
pixelIdx += this.width2;
}
}
drawCircle(x, y, radius, colour, alpha) {
const bgAlpha = 256 - alpha;
const red = ((colour >> 16) & 0xff) * alpha;
const green = ((colour >> 8) & 0xff) * alpha;
const blue = (colour & 0xff) * alpha;
let top = y - radius;
if (top < 0) {
top = 0;
}
let bottom = y + radius;
if (bottom >= this.height2) {
bottom = this.height2 - 1;
}
let vertInc = 1;
if (this.interlace) {
vertInc = 2;
if ((top & 1) !== 0) {
top++;
}
}
for (let yy = top; yy <= bottom; yy += vertInc) {
const l3 = yy - y;
const i4 = Math.sqrt(radius * radius - l3 * l3) | 0;
let j4 = x - i4;
if (j4 < 0) {
j4 = 0;
}
let k4 = x + i4;
if (k4 >= this.width2) {
k4 = this.width2 - 1;
}
let index = j4 + yy * this.width2;
for (let i = j4; i <= k4; i++) {
const bgRed = ((this.pixels[index] >> 16) & 0xff) * bgAlpha;
const bgGreen = ((this.pixels[index] >> 8) & 0xff) * bgAlpha;
const bgBlue = (this.pixels[index] & 0xff) * bgAlpha;
const newColour =
(((red + bgRed) >> 8) << 16) +
(((green + bgGreen) >> 8) << 8) +
((blue + bgBlue) >> 8);
this.pixels[index++] = newColour;
}
}
}
drawBoxAlpha(x, y, width, height, colour, alpha) {
if (x < this.boundsTopX) {
width -= this.boundsTopX - x;
x = this.boundsTopX;
}
if (y < this.boundsTopY) {
height -= this.boundsTopY - y;
y = this.boundsTopY;
}
if (x + width > this.boundsBottomX) {
width = this.boundsBottomX - x;
}
if (y + height > this.boundsBottomY) {
height = this.boundsBottomY - y;
}
const backgroundAlpha = 256 - alpha;
const red = ((colour >> 16) & 0xff) * alpha;
const green = ((colour >> 8) & 0xff) * alpha;
const blue = (colour & 0xff) * alpha;
let j3 = this.width2 - width; // wat
let vertInc = 1;
if (this.interlace) {
vertInc = 2;
j3 += this.width2;
if ((y & 1) !== 0) {
y++;
height--;
}
}
let pixelIdx = x + y * this.width2;
for (let i = 0; i < height; i += vertInc) {
for (let j = -width; j < 0; j++) {
const backgroundRed =
((this.pixels[pixelIdx] >> 16) & 0xff) * backgroundAlpha;
const backgroundGreen =
((this.pixels[pixelIdx] >> 8) & 0xff) * backgroundAlpha;
const backgroundBlue =
(this.pixels[pixelIdx] & 0xff) * backgroundAlpha;
const newColour =
(((red + backgroundRed) >> 8) << 16) +
(((green + backgroundGreen) >> 8) << 8) +
((blue + backgroundBlue) >> 8);
this.pixels[pixelIdx++] = newColour;
}
pixelIdx += j3;
}
}
drawGradient(x, y, width, height, colourTop, colourBottom) {
if (x < this.boundsTopX) {
width -= this.boundsTopX - x;
x = this.boundsTopX;
}
if (x + width > this.boundsBottomX) {
width = this.boundsBottomX - x;
}
const bottomRed = (colourBottom >> 16) & 0xff;
const bottomGreen = (colourBottom >> 8) & 0xff;
const bottomBlue = colourBottom & 0xff;
const topRed = (colourTop >> 16) & 0xff;
const topGreen = (colourTop >> 8) & 0xff;
const topBlue = colourTop & 0xff;
let i3 = this.width2 - width; // wat
let vertInc = 1;
if (this.interlace) {
vertInc = 2;
i3 += this.width2;
if ((y & 1) !== 0) {
y++;
height--;
}
}
let pixelIdx = x + y * this.width2;
for (let i = 0; i < height; i += vertInc) {
if (i + y >= this.boundsTopY && i + y < this.boundsBottomY) {
const newColour =
(((bottomRed * i + topRed * (height - i)) / height) << 16) +
(((bottomGreen * i + topGreen * (height - i)) / height) <<
8) +
(((bottomBlue * i + topBlue * (height - i)) / height) | 0);
for (let j = -width; j < 0; j++) {
this.pixels[pixelIdx++] = newColour;
}
pixelIdx += i3;
} else {
pixelIdx += this.width2;
}
}
}
drawBox(x, y, w, h, colour) {
if (x < this.boundsTopX) {
w -= this.boundsTopX - x;
x = this.boundsTopX;
}
if (y < this.boundsTopY) {
h -= this.boundsTopY - y;
y = this.boundsTopY;
}
if (x + w > this.boundsBottomX) {
w = this.boundsBottomX - x;
}
if (y + h > this.boundsBottomY) {
h = this.boundsBottomY - y;
}
let j1 = this.width2 - w; // wat
let vertInc = 1;
if (this.interlace) {
vertInc = 2;
j1 += this.width2;
if ((y & 1) !== 0) {
y++;
h--;
}
}
let pixelIdx = x + y * this.width2;
for (let l1 = -h; l1 < 0; l1 += vertInc) {
for (let i2 = -w; i2 < 0; i2++) {
this.pixels[pixelIdx++] = colour;
}
pixelIdx += j1;
}
}
drawBoxEdge(x, y, width, height, colour) {
this.drawLineHoriz(x, y, width, colour);
this.drawLineHoriz(x, y + height - 1, width, colour);
this.drawLineVert(x, y, height, colour);
this.drawLineVert(x + width - 1, y, height, colour);
}
drawLineHoriz(x, y, width, colour) {
if (y < this.boundsTopY || y >= this.boundsBottomY) {
return;
}
if (x < this.boundsTopX) {
width -= this.boundsTopX - x;
x = this.boundsTopX;
}
if (x + width > this.boundsBottomX) {
width = this.boundsBottomX - x;
}
let i1 = x + y * this.width2;
for (let j1 = 0; j1 < width; j1++) {
this.pixels[i1 + j1] = colour;
}
}
drawLineVert(x, y, height, colour) {
if (x < this.boundsTopX || x >= this.boundsBottomX) {
return;
}
if (y < this.boundsTopY) {
height -= this.boundsTopY - y;
y = this.boundsTopY;
}
if (y + height > this.boundsBottomX) {
height = this.boundsBottomY - y;
}
let i1 = x + y * this.width2;
for (let j1 = 0; j1 < height; j1++) {
this.pixels[i1 + j1 * this.width2] = colour;
}
}
setPixel(x, y, colour) {
if (
x < this.boundsTopX ||
y < this.boundsTopY ||
x >= this.boundsBottomX ||
y >= this.boundsBottomY
) {
return;
}
this.pixels[x + y * this.width2] = colour;
}
fadeToBlack() {
const area = this.width2 * this.height2;
for (let j = 0; j < area; j++) {
let i = this.pixels[j] & 0xffffff;
this.pixels[j] =
((i >>> 1) & 0x7f7f7f) +
((i >>> 2) & 0x3f3f3f) +
((i >>> 3) & 0x1f1f1f) +
((i >>> 4) & 0xf0f0f);
}
}
drawLineAlpha(i, j, x, y, width, height) {
for (let xx = x; xx < x + width; xx++) {
for (let yy = y; yy < y + height; yy++) {
let i2 = 0;
let j2 = 0;
let k2 = 0;
let l2 = 0;
for (let i3 = xx - i; i3 <= xx + i; i3++)
if (i3 >= 0 && i3 < this.width2) {
for (let j3 = yy - j; j3 <= yy + j; j3++) {
if (j3 >= 0 && j3 < this.height2) {
let k3 = this.pixels[i3 + this.width2 * j3];
i2 += (k3 >> 16) & 0xff;
j2 += (k3 >> 8) & 0xff;
k2 += k3 & 0xff;
l2++;
}
}
}
this.pixels[xx + this.width2 * yy] =
((i2 / l2) << 16) + ((j2 / l2) << 8) + ((k2 / l2) | 0);
}
}
}
clear() {
for (let i = 0; i < this.surfacePixels.length; i++) {
this.surfacePixels[i] = null;
this.spriteWidth[i] = 0;
this.spriteHeight[i] = 0;
this.spriteColoursUsed[i] = null;
this.spriteColourList[i] = null;
}
}
parseSprite(spriteID, spriteData, indexData, frameCount) {
let indexOffset = Utility.getUnsignedShort(spriteData, 0);
const fullWidth = Utility.getUnsignedShort(indexData, indexOffset);
indexOffset += 2;
const fullHeight = Utility.getUnsignedShort(indexData, indexOffset);
indexOffset += 2;
const colourCount = indexData[indexOffset++] & 0xff;
const colours = new Int32Array(colourCount);
colours[0] = 0xff00ff;
for (let i = 0; i < colourCount - 1; i++) {
colours[i + 1] =
((indexData[indexOffset] & 0xff) << 16) +
((indexData[indexOffset + 1] & 0xff) << 8) +
(indexData[indexOffset + 2] & 0xff);
indexOffset += 3;
}
let spriteOffset = 2;
for (let id = spriteID; id < spriteID + frameCount; id++) {
this.spriteTranslateX[id] = indexData[indexOffset++] & 0xff;
this.spriteTranslateY[id] = indexData[indexOffset++] & 0xff;
this.spriteWidth[id] = Utility.getUnsignedShort(
indexData,
indexOffset
);
indexOffset += 2;
this.spriteHeight[id] = Utility.getUnsignedShort(
indexData,
indexOffset
);
indexOffset += 2;
const unknown = indexData[indexOffset++] & 0xff;
const size = this.spriteWidth[id] * this.spriteHeight[id];
this.spriteColoursUsed[id] = new Int8Array(size);
this.spriteColourList[id] = colours;
this.spriteWidthFull[id] = fullWidth;
this.spriteHeightFull[id] = fullHeight;
this.surfacePixels[id] = null;
this.spriteTranslate[id] = false;
if (
this.spriteTranslateX[id] !== 0 ||
this.spriteTranslateY[id] !== 0
) {
this.spriteTranslate[id] = true;
}
if (unknown === 0) {
for (let pixel = 0; pixel < size; pixel++) {
this.spriteColoursUsed[id][pixel] =
spriteData[spriteOffset++];
if (this.spriteColoursUsed[id][pixel] === 0) {
this.spriteTranslate[id] = true;
}
}
} else if (unknown === 1) {
for (let x = 0; x < this.spriteWidth[id]; x++) {
for (let y = 0; y < this.spriteHeight[id]; y++) {
this.spriteColoursUsed[id][
x + y * this.spriteWidth[id]
] = spriteData[spriteOffset++];
if (
this.spriteColoursUsed[id][
x + y * this.spriteWidth[id]
] === 0
) {
this.spriteTranslate[id] = true;
}
}
}
}
}
}
readSleepWord(spriteID, spriteData) {
const pixels = (this.surfacePixels[spriteID] = new Int32Array(
SLEEP_WIDTH * SLEEP_HEIGHT
));
this.spriteWidth[spriteID] = SLEEP_WIDTH;
this.spriteHeight[spriteID] = SLEEP_HEIGHT;
this.spriteTranslateX[spriteID] = 0;
this.spriteTranslateY[spriteID] = 0;
this.spriteWidthFull[spriteID] = SLEEP_WIDTH;
this.spriteHeightFull[spriteID] = SLEEP_HEIGHT;
this.spriteTranslate[spriteID] = false;
let colour = 0;
let packetOffset = 1;
let pixelOffset = 0;
for (pixelOffset = 0; pixelOffset < 255; ) {
const length = spriteData[packetOffset++] & 0xff;
for (let i = 0; i < length; i++) {
pixels[pixelOffset++] = colour;
}
// alternate between black and white
colour = 0xffffff - colour;
}
for (let y = 1; y < 40; y++) {
for (let x = 0; x < 255; ) {
const length = spriteData[packetOffset++] & 0xff;
for (let i = 0; i < length; i++) {
pixels[pixelOffset] = pixels[pixelOffset - 255];
pixelOffset++;
x++;
}
if (x < 255) {
pixels[pixelOffset] = 0xffffff - pixels[pixelOffset - 255];
pixelOffset++;
x++;
}
}
}
}
drawWorld(spriteId) {
let spriteSize =
this.spriteWidth[spriteId] * this.spriteHeight[spriteId];
let spritePixels = this.surfacePixels[spriteId];
let ai1 = new Int32Array(32768);
for (let k = 0; k < spriteSize; k++) {
let l = spritePixels[k];
ai1[
((l & 0xf80000) >> 9) + ((l & 0xf800) >> 6) + ((l & 0xf8) >> 3)
]++;
}
let ai2 = new Int32Array(256);
ai2[0] = 0xff00ff;
let ai3 = new Int32Array(256);
for (let i1 = 0; i1 < 32768; i1++) {
let j1 = ai1[i1];
if (j1 > ai3[255]) {
for (let k1 = 1; k1 < 256; k1++) {
if (j1 <= ai3[k1]) {
continue;
}
for (let i2 = 255; i2 > k1; i2--) {
ai2[i2] = ai2[i2 - 1];
ai3[i2] = ai3[i2 - 1];
}
ai2[k1] =
((i1 & 0x7c00) << 9) +
((i1 & 0x3e0) << 6) +
((i1 & 0x1f) << 3) +
0x40404;
ai3[k1] = j1;
break;
}
}
ai1[i1] = -1;
}
let abyte0 = new Int8Array(spriteSize);
for (let l1 = 0; l1 < spriteSize; l1++) {
let j2 = spritePixels[l1];
let k2 =
((j2 & 0xf80000) >> 9) +
((j2 & 0xf800) >> 6) +
((j2 & 0xf8) >> 3);
let l2 = ai1[k2];
if (l2 === -1) {
let i3 = 999999999;
let j3 = (j2 >> 16) & 0xff;
let k3 = (j2 >> 8) & 0xff;
let l3 = j2 & 0xff;
for (let i4 = 0; i4 < 256; i4++) {
let j4 = ai2[i4];
let k4 = (j4 >> 16) & 0xff;
let l4 = (j4 >> 8) & 0xff;
let i5 = j4 & 0xff;
let j5 =
(j3 - k4) * (j3 - k4) +
(k3 - l4) * (k3 - l4) +
(l3 - i5) * (l3 - i5);
if (j5 < i3) {
i3 = j5;
l2 = i4;
}
}
ai1[k2] = l2;
}
abyte0[l1] = l2 & 0xff; // << 24 >> 24
}
this.spriteColoursUsed[spriteId] = abyte0;
this.spriteColourList[spriteId] = ai2;
this.surfacePixels[spriteId] = null;
}
loadSprite(spriteID) {
if (this.spriteColoursUsed[spriteID] === null) {
return;
}
const size = this.spriteWidth[spriteID] * this.spriteHeight[spriteID];
const idx = this.spriteColoursUsed[spriteID];
const cols = this.spriteColourList[spriteID];
const pixels = new Int32Array(size);
for (let pixel = 0; pixel < size; pixel++) {
let colour = cols[idx[pixel] & 0xff];
if (colour === 0) {
colour = 1;
} else if (colour === 0xff00ff) {
colour = 0;
}
pixels[pixel] = colour;
}
this.surfacePixels[spriteID] = pixels;
this.spriteColoursUsed[spriteID] = null;
this.spriteColourList[spriteID] = null;
}
// used from World
drawSpriteMinimap(sprite, x, y, width, height) {
this.spriteWidth[sprite] = width;
this.spriteHeight[sprite] = height;
this.spriteTranslate[sprite] = false;
this.spriteTranslateX[sprite] = 0;
this.spriteTranslateY[sprite] = 0;
this.spriteWidthFull[sprite] = width;
this.spriteHeightFull[sprite] = height;
this.surfacePixels[sprite] = new Int32Array(width * height);
let pixel = 0;
for (let xx = x; xx < x + width; xx++) {
for (let yy = y; yy < y + height; yy++) {
this.surfacePixels[sprite][pixel++] = this.pixels[
xx + yy * this.width2
];
}
}
}
// used from mudclient
_drawSprite_from5(sprite, x, y, width, height) {
this.spriteWidth[sprite] = width;
this.spriteHeight[sprite] = height;
this.spriteTranslate[sprite] = false;
this.spriteTranslateX[sprite] = 0;
this.spriteTranslateY[sprite] = 0;
this.spriteWidthFull[sprite] = width;
this.spriteHeightFull[sprite] = height;
this.surfacePixels[sprite] = new Int32Array(width * height);
let pixel = 0;
for (let yy = y; yy < y + height; yy++) {
for (let xx = x; xx < x + width; xx++) {
this.surfacePixels[sprite][pixel++] = this.pixels[
xx + yy * this.width2
];
}
}
}
_drawSprite_from3(x, y, id) {
if (this.spriteTranslate[id]) {
x += this.spriteTranslateX[id];
y += this.spriteTranslateY[id];
}
let rY = x + y * this.width2;
let rX = 0;
let height = this.spriteHeight[id];
let width = this.spriteWidth[id];
let w2 = this.width2 - width;
let h2 = 0;
if (y < this.boundsTopY) {
let j2 = this.boundsTopY - y;
height -= j2;
y = this.boundsTopY;
rX += j2 * width;
rY += j2 * this.width2;
}
if (y + height >= this.boundsBottomY) {
height -= y + height - this.boundsBottomY + 1;
}
if (x < this.boundsTopX) {
let k2 = this.boundsTopX - x;
width -= k2;
x = this.boundsTopX;
rX += k2;
rY += k2;
h2 += k2;
w2 += k2;
}
if (x + width >= this.boundsBottomX) {
let l2 = x + width - this.boundsBottomX + 1;
width -= l2;
h2 += l2;
w2 += l2;
}
if (width <= 0 || height <= 0) {
return;
}
let inc = 1;
if (this.interlace) {
inc = 2;
w2 += this.width2;
h2 += this.spriteWidth[id];
if ((y & 1) !== 0) {
rY += this.width2;
height--;
}
}
if (this.surfacePixels[id] === null) {
this._drawSprite_from10A(
this.pixels,
this.spriteColoursUsed[id],
this.spriteColourList[id],
rX,
rY,
width,
height,
w2,
h2,
inc
);
} else {
this._drawSprite_from10(
this.pixels,
this.surfacePixels[id],
0,
rX,
rY,
width,
height,
w2,
h2,
inc
);
}
}
_spriteClipping_from5(x, y, width, height, spriteId) {
try {
const spriteWidth = this.spriteWidth[spriteId];
const spriteHeight = this.spriteHeight[spriteId];
let l1 = 0;
let i2 = 0;
let j2 = ((spriteWidth << 16) / width) | 0;
let k2 = ((spriteHeight << 16) / height) | 0;
if (this.spriteTranslate[spriteId]) {
let l2 = this.spriteWidthFull[spriteId];
let j3 = this.spriteHeightFull[spriteId];
j2 = ((l2 << 16) / width) | 0;
k2 = ((j3 << 16) / height) | 0;
x +=
((this.spriteTranslateX[spriteId] * width + l2 - 1) / l2) |
0;
y +=
((this.spriteTranslateY[spriteId] * height + j3 - 1) / j3) |
0;
if ((this.spriteTranslateX[spriteId] * width) % l2 !== 0) {
l1 =
(((l2 -
((this.spriteTranslateX[spriteId] * width) % l2)) <<
16) /
width) |
0;
}
if ((this.spriteTranslateY[spriteId] * height) % j3 !== 0) {
i2 =
(((j3 -
((this.spriteTranslateY[spriteId] * height) %
j3)) <<
16) /
height) |
0;
}
width =
((width * (this.spriteWidth[spriteId] - (l1 >> 16))) / l2) |
0;
height =
((height * (this.spriteHeight[spriteId] - (i2 >> 16))) /
j3) |
0;
}
let i3 = x + y * this.width2;
let k3 = this.width2 - width;
if (y < this.boundsTopY) {
let l3 = this.boundsTopY - y;
height -= l3;
y = 0;
i3 += l3 * this.width2;
i2 += k2 * l3;
}
if (y + height >= this.boundsBottomY) {
height -= y + height - this.boundsBottomY + 1;
}
if (x < this.boundsTopX) {
let i4 = this.boundsTopX - x;
width -= i4;
x = 0;
i3 += i4;
l1 += j2 * i4;
k3 += i4;
}
if (x + width >= this.boundsBottomX) {
let j4 = x + width - this.boundsBottomX + 1;
width -= j4;
k3 += j4;
}
let yInc = 1;
if (this.interlace) {
yInc = 2;
k3 += this.width2;
k2 += k2;
if ((y & 1) !== 0) {
i3 += this.width2;
height--;
}
}
this._plotScale_from13(
this.pixels,
this.surfacePixels[spriteId],
0,
l1,
i2,
i3,
k3,
width,
height,
j2,
k2,
spriteWidth,
yInc
);
} catch (e) {
console.error(e);
}
}
_spriteClipping_from7(x, y, w, h, id, tx, ty) {
if (id >= 50000) {
this.mudclientref.drawTeleportBubble(
x,
y,
w,
h,
id - 50000,
tx,
ty
);
return;
}
if (id >= 40000) {
this.mudclientref.drawItem(x, y, w, h, id - 40000, tx, ty);
return;
}
if (id >= 20000) {
this.mudclientref.drawNpc(x, y, w, h, id - 20000, tx, ty);
return;
}
if (id >= 5000) {
this.mudclientref.drawPlayer(x, y, w, h, id - 5000, tx, ty);
return;
}
this._spriteClipping_from5(x, y, w, h, id);
}
_drawSpriteAlpha_from4(x, y, spriteId, alpha) {
if (this.spriteTranslate[spriteId]) {
x += this.spriteTranslateX[spriteId];
y += this.spriteTranslateY[spriteId];
}
let size = x + y * this.width2;
let j1 = 0;
let height = this.spriteHeight[spriteId];
let width = this.spriteWidth[spriteId];
let extraXSpace = this.width2 - width;
let j2 = 0;
if (y < this.boundsTopY) {
let k2 = this.boundsTopY - y;
height -= k2;
y = this.boundsTopY;
j1 += k2 * width;
size += k2 * this.width2;
}
if (y + height >= this.boundsBottomY) {
height -= y + height - this.boundsBottomY + 1;
}
if (x < this.boundsTopX) {
let l2 = this.boundsTopX - x;
width -= l2;
x = this.boundsTopX;
j1 += l2;
size += l2;
j2 += l2;
extraXSpace += l2;
}
if (x + width >= this.boundsBottomX) {
let i3 = x + width - this.boundsBottomX + 1;
width -= i3;
j2 += i3;
extraXSpace += i3;
}
if (width <= 0 || height <= 0) {
return;
}
let yInc = 1;
if (this.interlace) {
yInc = 2;
extraXSpace += this.width2;
j2 += this.spriteWidth[spriteId];
if ((y & 1) !== 0) {
size += this.width2;
height--;
}
}
if (this.surfacePixels[spriteId] === null) {
this._drawSpriteAlpha_from11A(
this.pixels,
this.spriteColoursUsed[spriteId],
this.spriteColourList[spriteId],
j1,
size,
width,
height,
extraXSpace,
j2,
yInc,
alpha
);
} else {
this._drawSpriteAlpha_from11(
this.pixels,
this.surfacePixels[spriteId],
0,
j1,
size,
width,
height,
extraXSpace,
j2,
yInc,
alpha
);
}
}
drawActionBubble(x, y, scaleX, scaleY, sprite, alpha) {
try {
const spriteWidth = this.spriteWidth[sprite];
const spriteHeight = this.spriteHeight[sprite];
let i2 = 0;
let j2 = 0;
let k2 = ((spriteWidth << 16) / scaleX) | 0;
let l2 = ((spriteHeight << 16) / scaleY) | 0;
if (this.spriteTranslate[sprite]) {
const i3 = this.spriteWidthFull[sprite];
const k3 = this.spriteHeightFull[sprite];
k2 = ((i3 << 16) / scaleX) | 0;
l2 = ((k3 << 16) / scaleY) | 0;
x +=
((this.spriteTranslateX[sprite] * scaleX + i3 - 1) / i3) |
0;
y +=
((this.spriteTranslateY[sprite] * scaleY + k3 - 1) / k3) |
0;
if ((this.spriteTranslateX[sprite] * scaleX) % i3 !== 0) {
i2 =
(((i3 -
((this.spriteTranslateX[sprite] * scaleX) % i3)) <<
16) /
scaleX) |
0;
}
if ((this.spriteTranslateY[sprite] * scaleY) % k3 !== 0) {
j2 =
(((k3 -
((this.spriteTranslateY[sprite] * scaleY) % k3)) <<
16) /
scaleY) |
0;
}
scaleX =
((scaleX * (this.spriteWidth[sprite] - (i2 >> 16))) / i3) |
0;
scaleY =
((scaleY * (this.spriteHeight[sprite] - (j2 >> 16))) / k3) |
0;
}
let j3 = x + y * this.width2;
let l3 = this.width2 - scaleX;
if (y < this.boundsTopY) {
let i4 = this.boundsTopY - y;
scaleY -= i4;
y = 0;
j3 += i4 * this.width2;
j2 += l2 * i4;
}
if (y + scaleY >= this.boundsBottomY)
scaleY -= y + scaleY - this.boundsBottomY + 1;
if (x < this.boundsTopX) {
let j4 = this.boundsTopX - x;
scaleX -= j4;
x = 0;
j3 += j4;
i2 += k2 * j4;
l3 += j4;
}
if (x + scaleX >= this.boundsBottomX) {
let k4 = x + scaleX - this.boundsBottomX + 1;
scaleX -= k4;
l3 += k4;
}
let yInc = 1;
if (this.interlace) {
yInc = 2;
l3 += this.width2;
l2 += l2;
if ((y & 1) !== 0) {
j3 += this.width2;
scaleY--;
}
}
this.transparentScale(
this.pixels,
this.surfacePixels[sprite],
0,
i2,
j2,
j3,
l3,
scaleX,
scaleY,
k2,
l2,
spriteWidth,
yInc,
alpha
);
} catch (e) {
console.error(e);
}
}
_spriteClipping_from6(x, y, width, height, spriteId, colour) {
try {
let k1 = this.spriteWidth[spriteId];
let l1 = this.spriteHeight[spriteId];
let i2 = 0;
let j2 = 0;
let k2 = ((k1 << 16) / width) | 0;
let l2 = ((l1 << 16) / height) | 0;
if (this.spriteTranslate[spriteId]) {
let i3 = this.spriteWidthFull[spriteId];
let k3 = this.spriteHeightFull[spriteId];
k2 = ((i3 << 16) / width) | 0;
l2 = ((k3 << 16) / height) | 0;
x +=
((this.spriteTranslateX[spriteId] * width + i3 - 1) / i3) |
0;
y +=
((this.spriteTranslateY[spriteId] * height + k3 - 1) / k3) |
0;
if ((this.spriteTranslateX[spriteId] * width) % i3 !== 0) {
i2 =
(((i3 -
((this.spriteTranslateX[spriteId] * width) % i3)) <<
16) /
width) |
0;
}
if ((this.spriteTranslateY[spriteId] * height) % k3 !== 0) {
j2 =
(((k3 -
((this.spriteTranslateY[spriteId] * height) %
k3)) <<
16) /
height) |
0;
}
width =
((width * (this.spriteWidth[spriteId] - (i2 >> 16))) / i3) |
0;
height =
((height * (this.spriteHeight[spriteId] - (j2 >> 16))) /
k3) |
0;
}
let j3 = x + y * this.width2;
let l3 = this.width2 - width;
if (y < this.boundsTopY) {
let i4 = this.boundsTopY - y;
height -= i4;
y = 0;
j3 += i4 * this.width2;
j2 += l2 * i4;
}
if (y + height >= this.boundsBottomY) {
height -= y + height - this.boundsBottomY + 1;
}
if (x < this.boundsTopX) {
let j4 = this.boundsTopX - x;
width -= j4;
x = 0;
j3 += j4;
i2 += k2 * j4;
l3 += j4;
}
if (x + width >= this.boundsBottomX) {
let k4 = x + width - this.boundsBottomX + 1;
width -= k4;
l3 += k4;
}
let yInc = 1;
if (this.interlace) {
yInc = 2;
l3 += this.width2;
l2 += l2;
if ((y & 1) !== 0) {
j3 += this.width2;
height--;
}
}
this._plotScale_from14(
this.pixels,
this.surfacePixels[spriteId],
0,
i2,
j2,
j3,
l3,
width,
height,
k2,
l2,
k1,
yInc,
colour
);
} catch (e) {
console.error(e);
}
}
_drawSprite_from10(
dest,
src,
i,
srcPos,
destPos,
width,
height,
j1,
k1,
yInc
) {
let i2 = -(width >> 2);
width = -(width & 3);
for (let j2 = -height; j2 < 0; j2 += yInc) {
for (let k2 = i2; k2 < 0; k2++) {
i = src[srcPos++];
if (i !== 0) {
dest[destPos++] = i;
} else {
destPos++;
}
i = src[srcPos++];
if (i !== 0) {
dest[destPos++] = i;
} else {
destPos++;
}
i = src[srcPos++];
if (i !== 0) {
dest[destPos++] = i;
} else {
destPos++;
}
i = src[srcPos++];
if (i !== 0) {
dest[destPos++] = i;
} else {
destPos++;
}
}
for (let l2 = width; l2 < 0; l2++) {
i = src[srcPos++];
if (i !== 0) {
dest[destPos++] = i;
} else {
destPos++;
}
}
destPos += j1;
srcPos += k1;
}
}
_drawSprite_from10A(
target,
colourIdx,
colours,
srcPos,
destPos,
width,
height,
w2,
h2,
rowInc
) {
let l1 = -(width >> 2);
width = -(width & 3);
for (let i2 = -height; i2 < 0; i2 += rowInc) {
for (let j2 = l1; j2 < 0; j2++) {
let byte0 = colourIdx[srcPos++];
if (byte0 !== 0) {
target[destPos++] = colours[byte0 & 0xff];
} else {
destPos++;
}
byte0 = colourIdx[srcPos++];
if (byte0 !== 0) {
target[destPos++] = colours[byte0 & 0xff];
} else {
destPos++;
}
byte0 = colourIdx[srcPos++];
if (byte0 !== 0) {
target[destPos++] = colours[byte0 & 0xff];
} else {
destPos++;
}
byte0 = colourIdx[srcPos++];
if (byte0 !== 0) {
target[destPos++] = colours[byte0 & 0xff];
} else {
destPos++;
}
}
for (let k2 = width; k2 < 0; k2++) {
let byte1 = colourIdx[srcPos++];
if (byte1 !== 0) {
target[destPos++] = colours[byte1 & 0xff];
} else {
destPos++;
}
}
destPos += w2;
srcPos += h2;
}
}
_plotScale_from13(dest, src, i, j, k, destPos, i1, j1, k1, l1, i2, j2, k2) {
try {
let l2 = j;
for (let i3 = -k1; i3 < 0; i3 += k2) {
let j3 = (k >> 16) * j2;
for (let k3 = -j1; k3 < 0; k3++) {
i = src[(j >> 16) + j3];
if (i !== 0) {
dest[destPos++] = i;
} else {
destPos++;
}
j += l1;
}
k += i2;
j = l2;
destPos += i1;
}
} catch (e) {
console.error(e);
}
}
_drawSpriteAlpha_from11(
dest,
src,
i,
srcPos,
size,
width,
height,
extraXSpace,
k1,
yInc,
alpha
) {
let j2 = 256 - alpha;
for (let k2 = -height; k2 < 0; k2 += yInc) {
for (let l2 = -width; l2 < 0; l2++) {
i = src[srcPos++];
if (i !== 0) {
let i3 = dest[size];
dest[size++] =
((((i & 0xff00ff) * alpha + (i3 & 0xff00ff) * j2) &
-16711936) +
(((i & 0xff00) * alpha + (i3 & 0xff00) * j2) &
0xff0000)) >>
8;
} else {
size++;
}
}
size += extraXSpace;
srcPos += k1;
}
}
_drawSpriteAlpha_from11A(
dest,
coloursUsed,
colourList,
listPos,
size,
width,
height,
extraXSpace,
j1,
yInc,
alpha
) {
let i2 = 256 - alpha;
for (let j2 = -height; j2 < 0; j2 += yInc) {
for (let k2 = -width; k2 < 0; k2++) {
let l2 = coloursUsed[listPos++];
if (l2 !== 0) {
l2 = colourList[l2 & 0xff];
let i3 = dest[size];
dest[size++] =
((((l2 & 0xff00ff) * alpha + (i3 & 0xff00ff) * i2) &
-16711936) +
(((l2 & 0xff00) * alpha + (i3 & 0xff00) * i2) &
0xff0000)) >>
8;
} else {
size++;
}
}
size += extraXSpace;
listPos += j1;
}
}
transparentScale(
dest,
src,
i,
j,
k,
destPos,
i1,
j1,
k1,
l1,
i2,
j2,
yInc,
alpha
) {
let i3 = 256 - alpha;
try {
let j3 = j;
for (let k3 = -k1; k3 < 0; k3 += yInc) {
let l3 = (k >> 16) * j2;
for (let i4 = -j1; i4 < 0; i4++) {
i = src[(j >> 16) + l3];
if (i !== 0) {
let j4 = dest[destPos];
dest[destPos++] =
((((i & 0xff00ff) * alpha + (j4 & 0xff00ff) * i3) &
-0xff0100) +
(((i & 0xff00) * alpha + (j4 & 0xff00) * i3) &
0xff0000)) >>
8;
} else {
destPos++;
}
j += l1;
}
k += i2;
j = j3;
destPos += i1;
}
} catch (e) {
console.error(e);
}
}
_plotScale_from14(
target,
pixels,
i,
j,
k,
l,
i1,
width,
height,
l1,
i2,
j2,
yInc,
colour
) {
let i3 = (colour >> 16) & 0xff;
let j3 = (colour >> 8) & 0xff;
let k3 = colour & 0xff;
try {
let l3 = j;
for (let i4 = -height; i4 < 0; i4 += yInc) {
let j4 = (k >> 16) * j2;
for (let k4 = -width; k4 < 0; k4++) {
i = pixels[(j >> 16) + j4];
if (i !== 0) {
let l4 = (i >> 16) & 0xff;
let i5 = (i >> 8) & 0xff;
let j5 = i & 0xff;
if (l4 === i5 && i5 === j5) {
target[l++] =
(((l4 * i3) >> 8) << 16) +
(((i5 * j3) >> 8) << 8) +
((j5 * k3) >> 8);
} else {
target[l++] = i;
}
} else {
l++;
}
j += l1;
}
k += i2;
j = l3;
l += i1;
}
} catch (e) {
console.error(e);
}
}
// "scale" is not actually scaling when it comes to the landscape
drawMinimapSprite(x, y, sprite, rotation, scale) {
let j1 = this.width2;
let k1 = this.height2;
if (!this.sinCosCache) {
this.sinCosCache = new Int32Array(512);
for (let i = 0; i < 256; i++) {
this.sinCosCache[i] = (Math.sin(i * 0.02454369) * 32768) | 0;
this.sinCosCache[i + 256] =
(Math.cos(i * 0.02454369) * 32768) | 0;
}
}
let i2 = -((this.spriteWidthFull[sprite] / 2) | 0);
let j2 = -((this.spriteHeightFull[sprite] / 2) | 0);
if (this.spriteTranslate[sprite]) {
i2 += this.spriteTranslateX[sprite];
j2 += this.spriteTranslateY[sprite];
}
let k2 = i2 + this.spriteWidth[sprite];
let l2 = j2 + this.spriteHeight[sprite];
let i3 = k2;
let j3 = j2;
let k3 = i2;
let l3 = l2;
rotation &= 0xff;
let i4 = this.sinCosCache[rotation] * scale;
let j4 = this.sinCosCache[rotation + 256] * scale;
let k4 = x + ((j2 * i4 + i2 * j4) >> 22);
let l4 = y + ((j2 * j4 - i2 * i4) >> 22);
let i5 = x + ((j3 * i4 + i3 * j4) >> 22);
let j5 = y + ((j3 * j4 - i3 * i4) >> 22);
let k5 = x + ((l2 * i4 + k2 * j4) >> 22);
let l5 = y + ((l2 * j4 - k2 * i4) >> 22);
let i6 = x + ((l3 * i4 + k3 * j4) >> 22);
let j6 = y + ((l3 * j4 - k3 * i4) >> 22);
if (scale === 192 && (rotation & 0x3f) === (Surface.anInt348 & 0x3f)) {
Surface.anInt346++;
} else if (scale === 128) {
Surface.anInt348 = rotation;
} else {
Surface.anInt347++;
}
let k6 = l4;
let l6 = l4;
if (j5 < k6) {
k6 = j5;
} else if (j5 > l6) {
l6 = j5;
}
if (l5 < k6) {
k6 = l5;
} else if (l5 > l6) {
l6 = l5;
}
if (j6 < k6) {
k6 = j6;
} else if (j6 > l6) {
l6 = j6;
}
if (k6 < this.boundsTopY) {
k6 = this.boundsTopY;
}
if (l6 > this.boundsBottomY) {
l6 = this.boundsBottomY;
}
if (
this.anIntArray340 === null ||
this.anIntArray340.length !== k1 + 1
) {
this.anIntArray340 = new Int32Array(k1 + 1);
this.anIntArray341 = new Int32Array(k1 + 1);
this.anIntArray342 = new Int32Array(k1 + 1);
this.anIntArray343 = new Int32Array(k1 + 1);
this.anIntArray344 = new Int32Array(k1 + 1);
this.anIntArray345 = new Int32Array(k1 + 1);
}
for (let i7 = k6; i7 <= l6; i7++) {
this.anIntArray340[i7] = 99999999;
this.anIntArray341[i7] = -99999999;
}
let i8 = 0;
let k8 = 0;
let i9 = 0;
let j9 = this.spriteWidth[sprite];
let k9 = this.spriteHeight[sprite];
i2 = 0;
j2 = 0;
i3 = j9 - 1;
j3 = 0;
k2 = j9 - 1;
l2 = k9 - 1;
k3 = 0;
l3 = k9 - 1;
if (j6 !== l4) {
i8 = (((i6 - k4) << 8) / (j6 - l4)) | 0;
i9 = (((l3 - j2) << 8) / (j6 - l4)) | 0;
}
let j7 = 0;
let k7 = 0;
let l7 = 0;
let l8 = 0;
if (l4 > j6) {
l7 = i6 << 8;
l8 = l3 << 8;
j7 = j6;
k7 = l4;
} else {
l7 = k4 << 8;
l8 = j2 << 8;
j7 = l4;
k7 = j6;
}
if (j7 < 0) {
l7 -= i8 * j7;
l8 -= i9 * j7;
j7 = 0;
}
if (k7 > k1 - 1) {
k7 = k1 - 1;
}
for (let i = j7; i <= k7; i++) {
this.anIntArray340[i] = this.anIntArray341[i] = l7;
l7 += i8;
this.anIntArray342[i] = this.anIntArray343[i] = 0;
this.anIntArray344[i] = this.anIntArray345[i] = l8;
l8 += i9;
}
if (j5 !==