TenIO is an open-source project to create multiplayer online games that includes a java NIO (Non-blocking I/O) based server specifically designed for multiplayer games, which supports UDP, TCP, Websocket, HTTP transports, and available simple client projects for quick development.
- Scalable, distributed design
- Easy-to-use, OOP design
- Based on standard Java development, ensuring cross-platform support
- Simple event handlers implementation
- Simple physic simulator and debugger
- Have simple existing game clients for rapid development
|  Game Box Online |  Gold Miner Online |  Brick Game Online | 
|---|
- Establishes a simple server with only a single Java class
/**
 * This class shows how a simple server handle messages that came from a client.
 */
@Bootstrap
public final class TestSimpleServer {
  public static void main(String[] params) {
    ApplicationLauncher.run(TestSimpleServer.class, params);
  }
  /**
   * Create your own configurations.
   */
  @Setting
  public static class TestConfiguration extends CoreConfiguration implements Configuration {
    @Override
    protected void extend(Map<String, String> extProperties) {
      for (Map.Entry<String, String> entry : extProperties.entrySet()) {
        var paramName = entry.getKey();
        push(ExampleConfigurationType.getByValue(paramName), String.valueOf(entry.getValue()));
      }
    }
  }
  /**
   * Define your handlers.
   */
  @EventHandler
  public static class ConnectionEstablishedHandler extends AbstractHandler
      implements EventConnectionEstablishedResult<ZeroMap> {
    @Override
    public void handle(Session session, ZeroMap message, ConnectionEstablishedResult result) {
      if (result == ConnectionEstablishedResult.SUCCESS) {
        api().login(message.getString(SharedEventKey.KEY_PLAYER_LOGIN), session);
      }
    }
  }
  @EventHandler
  public static class PlayerLoggedInHandler extends AbstractHandler
      implements EventPlayerLogin<Player> {
    @Override
    public void handle(Player player) {
      var parcel = map().putString(SharedEventKey.KEY_PLAYER_LOGIN,
            String.format("Welcome to server: %s", player.getName()));
      response().setContent(parcel.toBinary()).setRecipientPlayer(player).write();
    }
  }
  @EventHandler
  public static class ReceivedMessageFromPlayerHandler extends AbstractHandler
      implements EventReceivedMessageFromPlayer<Player, ZeroMap> {
    @Override
    public void handle(Player player, ZeroMap message) {
      var parcel =
          map().putString(SharedEventKey.KEY_CLIENT_SERVER_ECHO, String.format("Echo(%s): %s",
              player.getName(),
              message.getString(SharedEventKey.KEY_CLIENT_SERVER_ECHO)));
      response().setContent(parcel.toBinary()).setRecipientPlayer(player).write();
    }
  }
}- Supports self-defined commands to interact with the server conveniently
- Usage
2022-11-20 05:20:38,256 [main] INFO  com.tenio.core.server.ServerImpl - [SERVER][Example] Started
$ help
help - Shows all supporting commands
  [<command>,<command>,<command>]
info - Provides brief information about players and rooms on the server
  player
  room
player - Logout the first player from the server
  logout first
server - Allows stopping or restarting the server
  stop
  restart
unban - Allows removing banned Ip addresses from the ban list
  [<address>,<command>,<command>]
$ info player
> There are 1 players > The first 10 entities > [Player{name='IkjvI', properties={}, session=Session{id=0, name='IkjvI', transportType=TCP, createdTime=1668918078524, lastReadTime=1668918078524, lastWriteTime=1668918078524, lastActivityTime=1668918078524, readBytes=75, writtenBytes=120, droppedPackets=0, inactivatedTime=0, datagramRemoteSocketAddress=null, clientAddress='127.0.0.1', clientPort=60659, serverPort=8032, serverAddress='127.0.0.1', maxIdleTimeInSecond=0, activated=true, connected=true, hasUdp=false, enabledKcp=false, hasKcp=false}, currentRoom=null, state=null, roleInRoom=SPECTATOR, lastLoginTime=1668918078589, lastJoinedRoomTime=1668918078588, playerSlotInCurrentRoom=-1, loggedIn=true, activated=true, hasSession=true}]
$ 
- Make sure to set the command usage flag in setting.json file to be enabled
{
  "command": {
    "enabled": true
  },
  "plugin": {
    "enabled": false,
    "path": "/plugin"
  }
}- Simple implementation
@Command(label = "player", usage = {
    "logout first"
}, description = "Logout the first player from the server")
public class PlayerCommand extends AbstractCommandHandler {
  @Override
  public void execute(List<String> args) {
    var action = args.get(0);
    var param = args.get(1);
    if (action.equals("logout") && param.equals("first")) {
      var players = api().getReadonlyPlayersList();
      if (players.isEmpty()) {
        CommandUtility.INSTANCE.showConsoleMessage("Empty list of players.");
        return;
      }
      var firstPlayer = players.get(0);
      CommandUtility.INSTANCE.showConsoleMessage("Player {" + firstPlayer.getName() + "} is " +
          "going to logout.");
      api().logout(firstPlayer);
    } else {
      CommandUtility.INSTANCE.showConsoleMessage("Invalid action.");
    }
  }
}The wiki provides implementation level details and answers to general questions that a developer starting to use TenIO might have about it.
|  TenIO Cocos2dx |  TenIO Libgdx |  TenIO Unity |  TenIO Phaserjs | 
|---|
The project is strongly based on the same name framework as you can be referenced by the following repositories.
- Java 17The TenIO project is currently available under the MIT License.
Please check out the contributing guideline for more details.
Please check out the documentations directory for more details.
$ git clone https://github.com/congcoi123/tenio.gitPlease check out this repository for references.
Then you should check out this showcase for more details.
Happy coding !
 
    