Async Mmocore

The Goal of the async-mmocore is to provide a way to handle MMO connections abstracting the networking layer complexity.

License

License

GroupId

GroupId

io.github.joealisson
ArtifactId

ArtifactId

async-mmocore
Last Version

Last Version

3.3.0
Release Date

Release Date

Type

Type

jar
Description

Description

Async Mmocore
The Goal of the async-mmocore is to provide a way to handle MMO connections abstracting the networking layer complexity.
Project URL

Project URL

https://github.com/JoeAlisson/async-mmocore
Source Code Management

Source Code Management

https://github.com/JoeAlisson/async-mmocore/tree/master

Download async-mmocore

How to add to project

<!-- https://jarcasting.com/artifacts/io.github.joealisson/async-mmocore/ -->
<dependency>
    <groupId>io.github.joealisson</groupId>
    <artifactId>async-mmocore</artifactId>
    <version>3.3.0</version>
</dependency>
// https://jarcasting.com/artifacts/io.github.joealisson/async-mmocore/
implementation 'io.github.joealisson:async-mmocore:3.3.0'
// https://jarcasting.com/artifacts/io.github.joealisson/async-mmocore/
implementation ("io.github.joealisson:async-mmocore:3.3.0")
'io.github.joealisson:async-mmocore:jar:3.3.0'
<dependency org="io.github.joealisson" name="async-mmocore" rev="3.3.0">
  <artifact name="async-mmocore" type="jar" />
</dependency>
@Grapes(
@Grab(group='io.github.joealisson', module='async-mmocore', version='3.3.0')
)
libraryDependencies += "io.github.joealisson" % "async-mmocore" % "3.3.0"
[io.github.joealisson/async-mmocore "3.3.0"]

Dependencies

compile (1)

Group / Artifact Type Version
org.slf4j : slf4j-api jar 2.0.0-alpha1

Project Modules

There are no modules declared in this project.

async-mmocore

Code Badge Code Badge Code Badge License badge Maven Central

Quality Metrics

Build Quality Gate Status Maintainability Rating Security Rating Reliability Rating Coverage Bugs Code Smells

The Goal

The Async-mmocore is primarily designed to Massive Multiplayer Online (MMO) Game Servers. The Goal of the Async-mmocore is to provide an easy way to handle MMO connections to a server abstracting the networking layer complexity.

The Requirements

The Async-mmocore is built on top of Java NIO.2 API using Asynchronous Socket Channels. It is recommended Java 11+ to build and run.

The ReadablePacket and WritablePacket Classes

These classes, herein referenced as packets, are the abstraction of data send through the network. All packets must have a Header and an optional payload.

The header is a Short number the carries out the size the packet. The payload is the essential information to the server or client. The packet must be composed by at maximum 32767 bytes. Packets greater than this can be lead to unexpected behaviour.

The Basics to Use

  • Define a Client Implementation

The client Class is a representation of an external connection. Thus, it's the unique source of incoming packets and the target of the outcome packets.

The Client Class must implement the abstract class Client

public class ClientImpl extends Client<Connection<ClientImpl>> {
    
    public ClientImpl(Connection<ClientImpl> connection) {
        super(connection);
    }
        
    @Override
    public boolean decrypt(Buffer data, int offset, int size) {
        return myCrypter.decrypt(data, offset, size);
    }
    
    @Override
    public boolean encrypt(Buffer data, int offset, int size) {
        return myCrypter.encrypt(data, offset, size);
    }
    
    @Override
    protected void onDisconnection() {
        saveDataAndReleaseResources();
    }
    
    @Override
    public void onConnected() {
        doTheInitialJob();    
    }
    
    public void sendPacket(WritablePacket<ClientImpl> packet) {
        writePacket(packet);
    }
}
  • Define a Client Factory Implementation

The Client Factory instantiate the new incoming connections.

The Client Factory must implement the interface ClientFactory

public class ClientFactoryImpl implements ClientFactory<ClientImpl> {
    
    @Override
    public ClientImpl create(Connection<ClientImpl> connection) {
        return new ClientImpl(connection);
    }    
}
  • Define a Packet Handler Implementation

The Packet Handler converts the incoming data into a ReadablePacket.

The Packet Handler must implement the interface PacketHandler

public class PacketHandlerImpl implements PacketHandler<ClientImpl> {
    
     @Override
    public ReadablePacket<ClientImpl> handlePacket(ReadableBuffer buffer, ClientImpl client) {
        ReadablePacket<ClientImpl> packet = convertToPacket(buffer, client);
        return packet;
    }
}
  • Define a Packet Executor Implementation

The Packet Executor executes the incoming Packets.

Although the packet can be executed in the same Thread, it's HIGHLY recommended that the Executors executes the packet on an apart Thread. That's because the Thread that calls the execute method is the same which process the network I/O operations. Thus, these threads must be short-living and execute only non-blocking operations.

The Packet Executor must implement the interface PacketExecutor

public class PacketExecutorImpl implements PacketExecutor<ClientImpl> {
    
    @Override
    public void execute(ReadablePacket<AsyncClient> packet) { 
        threadPoolExecutor.execute(packet);
    }
}
  • Listen Connections

To listen Connections it's necessary to build a ConnectionHandler

public class ServerHandler {
    public void startListen(String host, int port) { 
        ConnectionHandler<ClientImpl> connectionHandler = ConnectionBuilder.create(new InetSocketAddress(host, port), new ClientFactoryImpl(), new PacketHandlerImpl(), new PacketExecutorImpl()).build();
        connectionHandler.start();
    }    
} 
  • Sending a Packet

To send a Packet it's necessary to implement the abstract class WritablePacket

public class ServerInfo implements WritablePacket<ClientImpl> {
    @Override
    protected boolean write(ClientImpl client, WritableBuffer buffer) {
        buffer.writeByte(this.getServerId());
        buffer.writeString(this.getServerName());
        buffer.writeLong(this.getServerCurrentTime());
        buffer.writeInt(this.getServerCurrentUsers());
        return true;      
    }
}

After it just send it through the client

public class ServerHandler {
    public void sendServerInfoToClient(ClientImpl client) {
        client.sendPacket(new ServerInfo());
    }
}
  • Receiving a Packet

The receiving packet is almost all done by the Async-mmocore. The only part to be implemented to fully read is the steps described in Define a Packet Handler Implementation and Define a Packet Executor Implementation sections.

public class ReceivedServerInfo implements ReadablePacket<ClientImpl> {
    
    @Override
    protected boolean read() {
        this.serverId = readByte();
        this.serverName = readString();
        this.serverCurrentTime = readLong();
        this.serverCurrentUsers = readInt();
        return true;
    }
    
    @Override
    public void run() {
        showServerInfoToClient();
    }
}

Client Side

The class Connector provides client side asynchronous connection support. It works just like ConnectionBuilder, so you must define the ClientFactory, the PacketHandler and the PacketExecutor implementations.

public class ConnectionFactory {

    public static ClientImpl create(String host, int port) {
        ClientImpl client = Connector.create(clientFactory, packetHandler, packetExecutor).connect(new InetSocketAddress(host, port));
        return client;
    }

}

Versions

Version
3.3.0
3.0.1
3.0.0
2.2.0
2.1.1
2.1.0