Skip to content

Latest commit

 

History

History
157 lines (124 loc) · 6.02 KB

README.md

File metadata and controls

157 lines (124 loc) · 6.02 KB

This is an implementation of the Anarchy Online Chat Protocol, written in Java.

To install locally (to resolve dependencies)

  1. Download TyrLib source
git clone https://github.com/Budabot/TyrLib.git
cd TyrLib/
  1. (Optional) If you need a particular version, switch to that version
git checkout 1.11
  1. Build and Install (run this from the TyrLib directory)
docker run -it --rm --name tyrlib-build -v ~/.m2:/root/.m2 -v "$(pwd)":/usr/src/mymaven -w /usr/src/mymaven maven:3.6.3-jdk-11-slim mvn -e install

Sample Bot

package com.example;

import aoChatLib.Crypto;
import com.jkbff.ao.tyrlib.chat.socket.AOClientSocket;
import com.jkbff.ao.tyrlib.chat.socket.Closeable;
import com.jkbff.ao.tyrlib.packets.serialization.ClientPacketSerializer;
import com.jkbff.ao.tyrlib.packets.client.LoginRequest;
import com.jkbff.ao.tyrlib.packets.client.LoginSelect;
import com.jkbff.ao.tyrlib.packets.serialization.ServerPacketDeserializer;
import com.jkbff.ao.tyrlib.packets.server.*;

import java.net.Socket;

public class LoginExample {

    private boolean isRunning = true;

    private String username = "username";
    private String password = "password";
    private String characterName = "character";

    public static void main(String[] args) throws Exception {
        new LoginExample().start();
    }

    public void start() throws Exception {
        // set server address and port
        String serverAddress = "chat.d1.funcom.com";
        int serverPort = 7105;

        // the library needs to know how to create incoming packets from bytes (deserializer), and how to convert
        // outgoing packets to bytes (serializer).  the library includes an implementation to do this, but you can
        // provide your own serializer/deserializer (and packet implementations) if desired
        ClientPacketSerializer serializer = new ClientPacketSerializer();
        ServerPacketDeserializer deserializer = new ServerPacketDeserializer();


        // we need a class with a close() method that will be called when there is a socket/connection error
        // so we can cleanup resources.  in this example, it just sets isRunning flag to false so the connection
        // will shut down gracefully
        Closeable onError = new SocketError(this);

        // create a client socket (a bot will act as a client to the ao chat server)
        AOClientSocket aoClientSocket = new AOClientSocket("main", new Socket(serverAddress, serverPort), deserializer, serializer, onError);

        // connect socket to ao chat server
        aoClientSocket.start();

        while (isRunning) {
            // read packet from socket, packet will wait up to 1s for a packet, and then will return null
            // this is then done in a loop, to allow graceful shutdown when isRunning is flipped to false
            BaseServerPacket packet = aoClientSocket.readPacket();
            if (packet != null) {
                // print out packet for debug purposes
                System.out.println(packet);

                // get type of packet based on the packet type
                switch (packet.getPacketType()) {
                    case LoginSeed.TYPE:
                        // cast to correct packet type
                        LoginSeed loginSeed = (LoginSeed) packet;

                        // generate login key from username, password, and seed using AO Crypto class
                        String loginKey = Crypto.generateKey(username, password, loginSeed.getSeed());

                        // create LoginRequest packet
                        LoginRequest loginRequest = new LoginRequest(0, username, loginKey);

                        // send packet (this should take a generic type, and allow an outgoing packet factory for
                        // converting a packet to bytes but this has not been done yet)
                        aoClientSocket.sendPacket(loginRequest);
                        break;
                    case LoginError.TYPE:
                        // cast to correct packet type
                        LoginError loginError = (LoginError) packet;

                        System.out.println("error logging in: " + loginError.getMessage());
                        this.stop();
                        break;
                    case CharacterList.TYPE:
                        // cast to correct packet type
                        CharacterList characterList = (CharacterList) packet;

                        // find character id for the character we want to login as
                        long charId = -1;
                        for (int i = 0; i < characterList.getName().length; i++) {
                            if (characterList.getName()[i].getData().equals(characterName)) {
                                charId = characterList.getUserId()[i].getData();
                            }
                        }

                        if (charId == -1) {
                            System.out.println("Could not find character '" + characterName + "' on account");
                            this.stop();
                        } else {
                            LoginSelect loginSelect = new LoginSelect(charId);
                            aoClientSocket.sendPacket(loginSelect);
                        }
                        break;
                    case LoginOk.TYPE:
                        System.out.println("Login successful!");
                        break;
                    // TODO handle other packets
                    default:
                        // do nothing
                }
            }
        }

        System.out.println("bot is shutdown");
    }

    public void stop() {
        this.isRunning = false;
    }
}


class SocketError implements Closeable {
    private LoginExample loginExample;

    public SocketError(LoginExample loginExample) {
        this.loginExample = loginExample;
    }

    @Override
    public void close() {
        // cleanup any resources (eg. threadpools, file pointers, database connections, etc)

        // shutdown bot gracefull
        this.loginExample.stop();
    }
}