Giter Site home page Giter Site logo

skeldjs / skeldjs Goto Github PK

View Code? Open in Web Editor NEW
60.0 3.0 11.0 312.18 MB

A JavaScript implementation of the Among Us protocol, featuring several different projects, written in TypeScript.

Home Page: https://skeld.js.org

License: GNU General Public License v3.0

JavaScript 0.90% TypeScript 99.10% Shell 0.01%
protocol pathfinding amongus among-us bot client

skeldjs's Introduction

Skeld JS

Skeld JS

codecov license Lint and Test Build Docs

If you're looking for an Among Us server, check out my other project, Hindenburg

SkeldJS is a JavaScript implementation of the Among Us protocol and game, written in TypeScript.

Quick Start

See the Packages section for more installation information.

Features

🕵️‍♀️ Unopinionated

SkeldJS is completely unopinionated about the structure or use-case of your program, and can be used to develop clients or servers with no preference to either.

🔌 Extensible

With the power of a heavily event-based design, SkeldJS gives you the ability to extend or modify just about every aspect of its behaviour, even allowing you to create custom objects or roles.

🧩 Complete

SkeldJS is a complete implementation of everything in Among Us, and is designed to remain as close as possible to how the game actually functions, meaning you are never out of sync with the official clients, or missing out on important features.

⚡ Fast

SkeldJS uses lots of caching techniques and does no more work than absolutely necessary to remain as close as possible to the game.

Written in TypeScript

SkeldJS is written in TypeScript, not only meaning that there is a much less chance of bugs in your code, but also that you get full editor support for SkeldJS.

Packages

SkeldJS features several different packages, all focusing on different aspects of Among US development.

All of the below packages can be install with npm install --save <package name> or yarn add <package name>. For example, npm install --save @skeldjs/client.

SkeldJS does feature its own client, allowing you to connect with either the official servers, or any other Among Us server, supporting the 2 modes of authentication.

Several enums and constants in Among Us that are dumped directly from the game, and are used to ensure SkeldJS remains maintainable.

The core structures of SkeldJS, including many networked structures found in Among Us, and is the foundation for the client or any servers to build from.

Contains some useful general data to use in projects to make sense of task IDs, vent IDs, etc.

A basic DTLS socket implementation to communicate with the Among Us servers securely.

A utility package including a custom asynchronous and typed event emitter.

A tool to be used with the SkeldJS client to search for and join games on the local network.

A tool for the SkeldJS client to automatically navigate through the maps and make sense of the map colliders.

Lots of structures representing Among Us protocol byte structures, as well as providing a utility PacketDecoder class, acting similar to an event emitter.

Reactor integration for the SkeldJS client to register mods with a reactor-combatible server.

A light-weight wrapper on top of @skeldjs/core which takes in raw message buffers and translates them to be processed and to record state that trascends game data such as joining/leaving.

Contains a utility class for generating TMP in a readable code-based format, as well as a TMP parser and transpiler to HTML.

Allows you to convert game string IDs into a readable string in a language supported by Among Us, as well as supporting synthesising quick chat messages and cosmetic names.

Several utility classes and functions used in SkeldJS, separated as another module as they are unopinionated and are used all throughout.

Notes

The most comprehensive set of JavaScript protocol implementations for Among Us.

The following resources have been extremely useful in developing this project, and I suggest that you give the repositories a star if possible.

This repository is held under the GPL3 license, meaning I am not responsible for any consequences that may come from using the packages in SkeldJS.

skeldjs's People

Contributors

5gamemaker avatar edqx avatar gabriel-nsiqueira avatar ilikeplayinggames avatar jerbear2008 avatar merceyz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

skeldjs's Issues

2021.11.9 Checklist

Protocol Changes

  • Hello packet
  • Host game
  • Redirect (?)
  • Role Rpcs (?)

Auth

  • DTLS Auth method
  • Nonce exchange auth method
  • Optional use no auth

Roles

  • Gamedata changes
  • Game settings changes
  • Role classes
    • Engineer
    • Scientist
    • Guardian Angel
    • Shapeshifter

List subject to change

Fix all systems and sabotages

Systems that are done, need testing, or need implementing.

  • AutoDoors (needs testing)
  • Decon
  • Doors (needs testing)
  • Electrical Doors (needs testing)
  • MiraHq Hud (needs testing)
  • Hud
  • Oxygen
  • Med scan
  • Moving platforms (needs testing)
  • Reactor
  • Sabotage
  • Security
  • Electrical
  • Ventilation
  • Heli

parsePacket(buffer) not giving expected output.

I am trying to use cap and @skeldjs/protocol to decode player list and player position. I have a constant stream of buffers that I am sending through parsePacket() and logging the response to try to figure out how it works.

My code and the result of running it were uploaded to a new Gist here.
Looking at the auto-updating docs, which aren't very helpful, the op value should be 10, 9, 8, 12, 1, or 0, not the numbers I am getting.
I know Cap is working correctly because I only get output when connecting to the internet from Among Us and I get more when more is happening.

Am I using the wrong function to do this? Do I need to switch to TypeScript? I don't really understand how exporting interfaces to a vanilla javascript file works.

EDIT:
The problem was that I was passing the entire packet, not just the UDP payload, to the function. Also, the @skeldjs/state package is much better in this scenario. Thanks to @edqx for being insanely helpful. 😁

Pathfinding

Pathfinding broke for several reasons in recent updates, use miniduikboot's colliders to re-create the pathfinding grid.

Also look into this issue:
image
Presumably to do with building and publishing to npm.

any chances of this ever working again?

Hi! I have been searching for and API for among us and I stumbled upon this.

Any chances of this ever working again?
I mean even with basics features like hosting a game and events (in public among us servers).

Thanks <3!

Exception during game start on Skeld map

First of all, thanks for this wonderful library, I am so surprised to see such a beautifully documented, well maintained piece of software.
Everything works great and flawlessly.

I seem to be getting this exception when a Skeld map starts:

Code:


    const client = new skeldjs.SkeldjsClient('2021.11.9', {
        chatMode: skeldjs.QuickChatMode.FreeChat
    })

    console.log("Connecting..");
    await client.connect(skeldjs.OfficialServers.AS, "testname");

    console.log("Joining game..");
    await client.joinGame(code);
    console.log("Joined game.");

    await client.myPlayer.control.checkName("testname");
    await client.myPlayer.control.checkColor(2);

    const pathfinder = new SkeldjsPathfinder.SkeldjsPathfinder(client);
    let players = Array.from(client.players.entries())
    pathfinder.follow(players[Math.floor(Math.random() * players.length)][1])
    console.log("Joined!");

node:internal/errors:464
    ErrorCaptureStackTrace(err);
    ^

RangeError [ERR_OUT_OF_RANGE]: The value of "offset" is out of range. It must be >= 0 and <= 12. Received 13
    at new NodeError (node:internal/errors:371:5)
    at boundsError (node:internal/buffer:86:9)
    at Buffer.readUInt8 (node:internal/buffer:252:5)
    at HazelReader.uint8 (C:\Users\Ashesh\Desktop\Projects\among-us\node_modules\@skeldjs\util\dist\lib\HazelReader.js:33:34)
    at HazelReader.bool (C:\Users\Ashesh\Desktop\Projects\among-us\node_modules\@skeldjs\util\dist\lib\HazelReader.js:64:21)
    at AutoDoorsSystem.Deserialize (C:\Users\Ashesh\Desktop\Projects\among-us\node_modules\@skeldjs\core\dist\lib\systems\AutoDoorsSystem.js:24:37)       
    at SkeldShipStatus.Deserialize (C:\Users\Ashesh\Desktop\Projects\among-us\node_modules\@skeldjs\core\dist\lib\objects\InnerShipStatus.js:43:24)       
    at new Networkable (C:\Users\Ashesh\Desktop\Projects\among-us\node_modules\@skeldjs\core\dist\lib\Networkable.js:32:22)
    at new InnerShipStatus (C:\Users\Ashesh\Desktop\Projects\among-us\node_modules\@skeldjs\core\dist\lib\objects\InnerShipStatus.js:20:9)
    at new SkeldShipStatus (C:\Users\Ashesh\Desktop\Projects\among-us\node_modules\@skeldjs\core\dist\lib\objects\SkeldShipStatus.js:16:9) {
  code: 'ERR_OUT_OF_RANGE'
}

Weirdly, this does not happen in Polus map (couldn't test on Mira because of the server issues).

Any idea why this might be?

Can't connect to server, causes error

I can't do await client.connect('NA', 'meeee'); because that gives me an error:

throw new TypeError("Expected an integer, instead got a fraction.");
                  ^

TypeError: Expected an integer, instead got a fraction.
    at Function.checkInteger (/Users/hacker/Documents/GitHub/ConsoleAmogus/node_modules/@skeldjs/util/dist/lib/HazelBuffer.js:14:19)
    at HazelWriter.int32 (/Users/hacker/Documents/GitHub/ConsoleAmogus/node_modules/@skeldjs/util/dist/lib/HazelWriter.js:317:35)
    at VersionInfo.Serialize (/Users/hacker/Documents/GitHub/ConsoleAmogus/node_modules/@skeldjs/util/dist/lib/Version.js:35:16)
    at HazelWriter.write (/Users/hacker/Documents/GitHub/ConsoleAmogus/node_modules/@skeldjs/util/dist/lib/HazelWriter.js:211:22)
    at HelloPacket.Serialize (/Users/hacker/Documents/GitHub/ConsoleAmogus/node_modules/@skeldjs/protocol/dist/lib/packets/option/Hello.js:31:16)
    at HazelWriter.write (/Users/hacker/Documents/GitHub/ConsoleAmogus/node_modules/@skeldjs/util/dist/lib/HazelWriter.js:211:22)
    at SkeldjsClient.send (/Users/hacker/Documents/GitHub/ConsoleAmogus/node_modules/@skeldjs/client/dist/lib/client.js:183:20)
    at SkeldjsClient.identify (/Users/hacker/Documents/GitHub/ConsoleAmogus/node_modules/@skeldjs/client/dist/lib/client.js:153:20)
    at async SkeldjsClient.connect (/Users/hacker/Documents/GitHub/ConsoleAmogus/node_modules/@skeldjs/client/dist/lib/client.js:107:17)
    at async SkeldjsClient.connect (/Users/hacker/Documents/GitHub/ConsoleAmogus/node_modules/@skeldjs/client/dist/lib/client.js:93:20)

Here is my code:

const skeldjs = require('@skeldjs/client');

(async () => {
	const client = new skeldjs.SkeldjsClient(‎'2021.6.15');

	await client.connect('NA', 'meeee');
	console.info('Connected to server');
})();

Refactor for "Client modding" capabilities.

Currently a fork is required to create client mods for SkeldJS, a refactor on several parts of SkeldJS will make this easier and allow multiple mods to be ran at the same time without manual merging of forks.

These can also be seen as plugins for the client, as the refactor will also make server plugins more powerful.

  • Packet handling refactor
    • Allow registering and listening to custom packets.
  • Component/Object refactor
    • Allow registering/replacing custom components (can replace serialization and deserialization).
    • Allow registering/replacing custom prefabs for spawning components.
  • Event refactor
    • Refactor for class-based events.
    • Refactor for proper event cancelling/hooking.
    • Refactor for events to be fired when using commands locally (e.g. PlayerControl.SetName should fire a player.setname event). This can be done by allowing the developer to change the name on the event rather than the player to avoid recursion.

List is probably subject to change.

Unable to connect

Hi,
When I try to run the following code, it just keeps on « connecting » indefinitely.
Any solutions?

const skeldjs = require('@skeldjs/client');
const util = require('@skeldjs/util');
(async()=>{
  
    const client = new skeldjs.SkeldjsClient('2022.3.29', {
        chatMode: skeldjs.QuickChatMode.QuickChat
    });
    console.log("client created")

    console.log("Connecting..");
    client.connect(skeldjs.OfficialServers.EU, "testhello").then(async connected => {
      console.log("Connected")
          console.log("Connected, finding games");

    const games = await client.findGames();
    console.log("Received games list");
const game = games[games.length-1];
console.log("Attempting to join game",game)
const formatted = util.Int2Code(game.code);
console.log("Formatted code:",formatted);
const code = await client.joinGame(formatted);

console.log("Joined game", game);

    await client.myPlayer.control.checkName("testhello");
    await client.myPlayer.control.checkColor(2);

    let players = Array.from(client.players.entries())
    //console.log(players)    
    console.log("Joined!");
  client.on("room.assignRoles", (evt) => {
    console.log("Roles assigned...",evt);
  })

  client.on("player.spawn", (evt) => {
    console.log("A player spawned",evt.player.username);
  })
    }).catch(err => {
      console.log("An error occured.",err);
    })

})()

(all the packages used are updated in the latest version, both 2.15.19)

Get auth token from Among Us servers before connecting

The airship update added an account system, and SkeldJS currently doesn't support the new authentication protocol.

The protocol uses DTLS, and every game server has an authentication server running at the same IP but with +2 added to the port, so eu.mm.among.us:22323 would have an authentication server hosted at eu.mm.among.us:22325.

It has the following format:

Type Name Description
int32 Client Verison The version of the game that the client is connecting from
byte Platform ID The platform ID of the client, see below.
string Client ID? The platform-specific access token to auth with.

Platforms

ID Name
0 Unknown
1 StandaloneEpicPC
2 StandaloneSteamPC
3 StandaloneMac
4 StandaloneWin10
5 StandaloneItch
6 IPhone
7 Android
8 Switch

EOS currently doesn't support Itch, so it doesn't have a proper way of authentication, as such, it can be implemented without using a special clientid the following way in C#:

MessageWriter messageWriter = MessageWriter.Get();
messageWriter.Write(0x03030fcc); // Client Version
messageWriter.Write((byte)5); // Platform ID
messageWriter.Write(""); // Client ID
return messageWriter.ToByteArray(includeHeader: false);

The hard part is DTLS in nodejs. There are a few libraries, the main one being https://github.com/nodertc/dtls.

EOS authentication broken for the latest update (2022.12.8)

i am using the following code:

import skeldjs from "@skeldjs/client";
import util from "@skeldjs/util";
const { AuthMethod, EosHttpApi } = skeldjs;
const { GameCode } = util;

const clientId = "xyza7891qtrmoYLr86we6DlfCA1RRsp8";
const clientSecret = "nGThQanzvthA2HPaARXe/xutzsKyx5WJveNkBx44ti4";
const deploymentId = "3ce14d8292084c80a8364a8b5f0dfbf4";

const randomDeviceModel = EosHttpApi.generateRandomDeviceModel();

const { access_token } = await EosHttpApi.authRequestGetDeviceIdAccessToken(clientId, clientSecret, randomDeviceModel);

const account = await EosHttpApi.authRequestEosAccessToken({
    grantType: "external_auth",
    externalAuthType: "deviceid_access_token",
    clientId: clientId,
    clientSecret: clientSecret,
    deploymentId: deploymentId,
    nonce: "aaaaaaaaab",
    displayName: "lxwusr",
    externalAuthToken: access_token,
});

const client = new skeldjs.SkeldjsClient("2022.9.2.0s", "lxwusr", {
    authMethod: AuthMethod.SecureTransport,
    idToken: account.id_token,
    eosProductUserId: account.product_user_id
});

await client.connect("https://matchmaker-eu.among.us", 443);
const code = await client.createGame();

client.myPlayer?.control?.checkName("weakeyes");
client.myPlayer?.control?.checkColor(skeldjs.Color.Red);

console.log(code);
console.log("Created game @ %s", GameCode.convertIntToString(code));

however this results in the following error:

C:\Users\leaf\Desktop\skeldjs>node index.js
C:\Users\leaf\Desktop\skeldjs\node_modules\@skeldjs\client\dist\lib\client.js:257
                rej(new errors_1.ConnectError(ev.reason, ev.message || data_1.DisconnectMessages[ev.reason] || ""));
                    ^

ConnectError: The Among Us servers could not authenticate you.

You must have an Among Us account to play online. (Guest account is okay!)
    at Array.onDisconnect (C:\Users\leaf\Desktop\skeldjs\node_modules\@skeldjs\client\dist\lib\client.js:257:21)
    at SkeldjsClient.emitSync (C:\Users\leaf\Desktop\skeldjs\node_modules\@skeldjs\events\dist\lib\EventEmitter.js:27:25)
    at C:\Users\leaf\Desktop\skeldjs\node_modules\@skeldjs\client\dist\lib\client.js:72:18
    at PacketDecoder.emit (C:\Users\leaf\Desktop\skeldjs\node_modules\@skeldjs\protocol\dist\lib\PacketDecoder.js:83:31)
    at PacketDecoder.emitDecoded (C:\Users\leaf\Desktop\skeldjs\node_modules\@skeldjs\protocol\dist\lib\PacketDecoder.js:60:20)
    at SkeldjsClient.handleInboundMessage (C:\Users\leaf\Desktop\skeldjs\node_modules\@skeldjs\client\dist\lib\client.js:365:28)
    at DtlsSocket.emit (node:events:390:28)
    at DtlsSocket.handlePayload (C:\Users\leaf\Desktop\skeldjs\node_modules\@skeldjs\dtls\dist\lib\DtlsSocket.js:247:22)
    at DtlsSocket.handleRecv (C:\Users\leaf\Desktop\skeldjs\node_modules\@skeldjs\dtls\dist\lib\DtlsSocket.js:215:18)
    at Socket.<anonymous> (C:\Users\leaf\Desktop\skeldjs\node_modules\@skeldjs\dtls\dist\lib\DtlsSocket.js:67:22) {
  reason: 11
}

Node.js v17.3.0

i'm not sure why this happens as the code I am using is very similar to the code here

UInt48 reader acts as a SInt32 reader.

JS handles shifts on 32 bit registers, causing this code:

        if (be) {
            return (bytes[0] << 40) | (bytes[1] << 32) | (bytes[2] << 24) | (bytes[3] << 16) | (bytes[4] << 8) | bytes[5];
        } else {
            return (bytes[5] << 40) | (bytes[4] << 32) | (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0];
        }

from /packages/dtls/lib/types/uint48.ts to act as a SInt32 reader, that skips the first or last two bytes (depending on endianness).

here's code from an unreleased project that should demonstrate as an example working implementation of a proper reader:

  /**
   * WARNING: SLOW. No native call for reading UInt48s.
   */
  readUInt48BE(): number {
    return (this.readUInt24BE() * 0x1000000) + this.readUInt24BE();
  }

  /**
   * WARNING: SLOW. No native call for reading SInt48s.
   */
  readSInt48BE(): number {
    const val = this.readUInt48BE();
    const neg = val >= 0x800000_000000;

    if (!neg)
      return val;

    return (0xFFFFFF_FFFFFF - val + 1) * -1;
  }

  /**
   * WARNING: SLOW. No native call for reading UInt48s.
   */
  readUInt48LE(): number {
    let binary = this.readUInt8();
    binary |= this.readUInt8() << 8;
    binary |= this.readUInt8() << 16;
    binary |= this.readUInt8() << 24;
    binary >>>= 0;
    binary += this.readUInt8() * 0x100000000;
    binary += this.readUInt8() * 0x10000000000;
    return binary;
  }

  /**
   * WARNING: SLOW. No native call for reading SInt48s.
   */
  readSInt48LE(): number {
    const val = this.readUInt48LE();
    const neg = val >= 0x800000_000000;

    if (!neg)
      return val;

    return (0xFFFFFF_FFFFFF - val + 1) * -1;
  }

Get the game code

Hey, i don't understand how can i get the game code as a RoomID ?
client.myPlayer.room.code gives me a negative number like : -1940292113
But the setCode() require a RoomID, but can't find a RoomID type in the doc of the room...

There is a method to convert the number into a String ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.