Socket library for creating real-time multiplayer games. Based on TCP, with the ability to send messages over UDP (planned).

Overview

Pub Version

Game socket

The library was published in early access and is not stable, as it is being developed in parallel with other solutions. English is not a native language so there are no comments. At this stage, the library is for those who want to understand the source code and get a starting point for their solution or help me :)

Features

  • One library contains both Server and Client parts.
  • The API communication library is similar to Socket.io, but not compatible with this solution.
  • Contains a built-in binary protocol so you don't have to work at the byte level.
  • The transport layer uses TCP. To send game messages, it is planned to implement parallel work with UDP.
  • It implements such concepts as Multiplexing - interaction with several spaces through a single channel.

Support for WebSocket is not planned for the current day (but everything can change with the support of the community)

Example

Examples:

Usage

Create client:

import 'package:game_socket/client.dart';

void main() {
  var client = GameClientExample();
  client.connect('localhost', 3103);
}

class GameClientExample extends GameSocketClient {
  GameClientExample() {
    on(Event.handshake, (packet) => _onHandshake(packet));
    on(Event.roomPacket, (packet) => _onRoomPacket(packet));
  }

  void _onHandshake(Packet packet) {
    if (packet.namespace == '/') {
      sendMessage(ConnectRequest('/home'));
    } else if (packet.namespace == '/home') {
      sendMessage(JoinRoomRequest('lobby', namespace: '/home'));
    }
  }

  void _onRoomPacket(RoomPacket packet) {
    var roomName = packet.roomName;
    if (packet.joinRoom && roomName == 'lobby') {
      var msg = RoomEvent(roomName!, namespace: '/home', event: 'hello', message: 'hello all');
      sendMessage(msg);
    }
  }
}

This client connects to the main / namespace on the server, then to the /home namespace. Then it sends a request to enter the lobby room, after which it dispatches a hello event containing the message text hello all.

Create server:

import 'package:game_socket/server.dart';

void main() {
  var service = SocketServiceExample();
  service.listen();
}

class SocketServiceExample {
  late GameSocketServer server;
  late Namespace home;

  SocketServiceExample() {
    server = GameSocketServer(options: ServerOptions.byDefault()..supportRawData = true);
    home = server.of('/home');
    home.on(ServerEvent.connect, (data) => _onHomeConnect(data));
    home.on('hello', (packet) => _onHomeData(packet));
    //
    server.on(ServerEvent.connection, (socket) {
      print('/: connection $socket');
      socket.on(ServerEvent.connect, (data) => _onConnect(data[0], data[1]));
      socket.on(Event.disconnecting, (data) => _onDisconnecting(data));
      socket.on(Event.disconnect, (data) => _onDisconnect(data[0], data[1]));
      socket.on(Event.error, (data) => _onError(data));
      socket.on(Event.data, (data) => _onData(data));
      socket.on(Event.close, (data) => {_onClose(data)});
    });
    server.on(ServerEvent.error, (data) => {print('/: eventError $data')});
    server.on(ServerEvent.close, (data) => {print('/: serverClose $data')});
    server.on(ServerEvent.raw, (data) => {print('/: raw $data')});
    server.on(ServerEvent.createRoom, (data) => {print('/: createRoom $data')});
    server.on(ServerEvent.joinRoom, (data) => {print('/: joinRoom $data')});
    server.on(ServerEvent.leaveRoom, (data) => {print('/: leaveRoom $data')});
    server.on(ServerEvent.deleteRoom, (data) => {print('/: deleteRoom $data')});
  }

  void listen() {
    server.listen();
  }

  void _onHomeConnect(dynamic data) {
    print('/home: connect $data');
  }

  void _onHomeData(dynamic data) {
    print('/home: $data');
    if (data is RoomPacket && data.roomName != null) {
      home.broadcast(data, rooms: {data.roomName!});
    }
  }

  void _onConnect(String namespace, String socketId) {
    print('/: connect $socketId');
  }

  void _onDisconnecting(dynamic data) {
    print('/: disconnecting $data');
  }

  void _onDisconnect(String namespace, String reason) {
    print('$namespace: disconnect reason:$reason');
  }

  void _onError(dynamic data) {
    print('/: error $data');
  }

  void _onData(dynamic data) {
    print('/: $data');
  }

  void _onClose(dynamic data) {
    print('/: close $data');
  }
}
Server log
listen null Options{ port:3103 raw:true closeOnError:false }
/: connection GameClient{ 15466abe2006464e99b6c8b36f7f4ed8 ReadyState.open [137545126]}
/: createRoom 15466abe2006464e99b6c8b36f7f4ed8
/: joinRoom [15466abe2006464e99b6c8b36f7f4ed8, 15466abe2006464e99b6c8b36f7f4ed8]
Home: connect [/home, 15466abe2006464e99b6c8b36f7f4ed8]
Client log
open InternetAddress('127.0.0.1', IPv4) ReadyState.open
handshake Packet{[0.0 /], bit:516, bool:16, int:[0, 0, 60, 0, 0, 0], string:{3: 15466abe2006464e99b6c8b36f7f4ed8}}
>> Message{[/home] boolMask:4, int:[0, 0, 0, 0, 0, 0], string:{} null}
handshake Packet{[0.0 /home], bit:516, bool:16, int:[0, 0, 60, 0, 0, 0], string:{3: 15466abe2006464e99b6c8b36f7f4ed8}}
>> Message{[/home] boolMask:16, int:[0, 0, 0], string:{0: lobby} null}
>> Message{[/home] boolMask:512, int:[0, 0, 0], string:{0: lobby, 5: hello, 1: hello all} null}

Protocol

The protocol is schematic based. This approach allows you to save the amount of data transferred, since the data type is not transferred with the message, and the length of the numbers is not serialized.

Data types used in the schema

Type Size Range
bool 1 bit true or false
int8 1 byte 0 to 255
int16 2 bytes 0 to 65535
int32 4 bytes 0 to 4294967295
string 1 + value 0 to 255 chars
bytes 2 + value 0 to 65535 bytes

Schema creation

import 'package:game_socket/protocol.dart';
typedef PS = PlayerStateSchema;
class PlayerStateSchema extends SimpleSchema {
  @override
  int get code => 10; // unique schema code 10..255 
  @override
  int get version => 1; // version 0..255 to support game clients with different versions
  
  // bool
  static const int reserved = 0; // reserved
  @override
  int get boolCount => 1;

  // int8
  static const int speed = 0; // 0.000..1.000
  static const int health = 1; // max(100)
  @override
  int get int8Count => 2;
  // int16
  static const int uid = 2; // max(65535)
  static const int angle = 3; // radians
  static const int score = 4; // max(65535)
  @override
  int get int16Count => 3;
  // int32
  static const int elapsedTime = 5; // time for internal synchronization
  static const int x = 6; // x-coordinate
  static const int y = 7; // y-coordinate
  @override
  int get int32Count => 3;

  // strings
  static const int name = 0; // player name
  @override
  int get stringsCount => 1;
}

When you create a schema, you do two things: you take the named cell number of the array and determine the length of the array to one of the five schema data types.

Creating a message class

class PlayerStateMessage extends Message {
  PlayerStateMessage(Player player, {required double elapsedTime}) : super(PS()) {
    putUInt(PS.uid, player.uid);
    putInt(PS.x, (player.positionBody.x * 1000).toInt()); // ~ -2000000.0000..+2000000.0000
    putInt(PS.y, (player.positionBody.y * 1000).toInt());
    putInt(PS.score, player.score);
    putSingle(PS.speed, player.speed);
    putRadians(PS.angle, player.rotationBody);
    putUInt(PS.elapsedTime, (elapsedTime * 1000).toInt()); // double ms
  }
}

Data types when writing or reading messages

Operation Schema Type Dart Type Range
putBool bool bool true or false
putInt int8 int -128 to 127
putUInt int8 int 0 to 255
putInt int16 int -32768 to 32767
putUInt int16 int 0 to 65535
putInt int32 int -2147483648 to 2147483647
putUInt int32 int 0 to 4294967295
putString string String 0 to 255 chars
putSingle int8 double 0 to 1 step ~0.004
putRadians int16 double step ~0.0002
putPayload bytes Uint8List 0 to 65535 bytes

Plans

  • Initialization for sending UPD diagrams.
  • Automatic connections and reconnections.
  • Expanding the possibilities for working with rooms.
  • Conducting stress tests.

Tips for Beginners

  • If you are developing a browser game, then you need a WebSocket solution.
  • When designing a game for real-time communication, UDP should be preferred, since TCP will cause a delay in the event of packet loss.

History of creation

Sources that could have influenced the development of this work:


If you can suggest a translation better than automatic ᕙ(☉̃ₒ☉‶)ว just do it

You might also like...

Show a draggable floating chat icon button and show messages on screens

Show a draggable floating chat icon button and show messages on screens

Show a draggable floating chat icon button and show messages on screens Features A widget for displaying a chat icon (or custom widget) on top of a ba

May 5, 2022

Riverpod Messages Listener: A message notification listener for apps build with Riverpod

Riverpod Messages Listener: A message notification listener for apps build with Riverpod

Riverpod Messages Listener Hello all, this is the home page of riverpod_messages package, a message notification listener for apps build with Riverpod

Dec 8, 2022

Flutter POS Printer - A library to discover printers, and send printer commands

Flutter POS Printer - A library to discover printers, and send printer commands

Oct 5, 2022

User auth form - Signup and signin user auth form with ability to stay signed in and have an option to signout.

user_auth_form SIgnup and signin user authentification form Getting Started This project is a starting point for a Flutter application. A few resource

Jan 6, 2022

This package give you ability to integrate with Drone API easily in any platform using Dart

This package give you ability to integrate with Drone API easily in any platform using Dart

Drone Dart Dart is a multi client programming language which allow you to compile and run your code on multiple platforms. Because of that we decided

Dec 22, 2022

Multiplayer TicTacToe Game developed using Flutter, Node.js, Express, MongoDB & Mongoose.

Multiplayer TicTacToe Game developed using Flutter, Node.js, Express, MongoDB & Mongoose.

Multiplayer TicTacToe Game A completely Responsive Multiplayer TicTacToe Game- Works on Android, iOS, Web & Desktop! Features Create/Join Room Play Re

Dec 25, 2022

A dart timer that can be configured to fire once or repeatedly with ability start, stop, resume and cancel.

A timer that can be configured to fire once or repeatedly with ability start, stop, resume and cancel. Getting started Add CompleteTimer to your pubsp

Jul 20, 2022

Rolify is an app that allows you to play multiple sounds simultaneously, with the ability to manage audio individually

Rolify is an app that allows you to play multiple sounds simultaneously, with the ability to manage audio individually

Rolify is an app that allows you to play multiple sounds simultaneously, with the ability to manage audio individually. You can also add the music you have on your phone, all completely offline and free.

Sep 30, 2022

The prime objective of this app is to store the real time information of the user using firebase cloud firestore and also can delete, remove and update the customer information

crud_firestore A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started i

Mar 15, 2022
Comments
  • Example documentation

    Example documentation

    Hi,

    Thank you for the repository. Could you provide some more documentation about your example, please? Where can I find matching Event client side to ServerEvent server side? For now, it's hard to understand what type of event should I send to server to get handler that I need. By the way, as I can see, your name is Stanislav. If you are speaking Russian, we can switch to Russian. Can I find you in discord?

    opened by loothood 0
Owner
Stanislav
migrating to Dart
Stanislav
Flutter web socket - Flutter Web Socket Example

web_socket_example A new Flutter Web Socket project. Getx and web_scoket_channel

Gizem Malçok 7 Nov 2, 2022
🏆🥇 Tiaco : Online Multiplayer is one of the best puzzle games in the market. 🥇🏆

Important!!! Logo was generated by dall e 2 ?? ?? Tiaco : Online Multiplayer is one of the best puzzle games in the market. ?? ?? [Pull Request's are

Naser 2 Sep 22, 2022
Send-a-msg - Send message to WhatsApp without saving number

Send A Message Send Message to Whatsapp without saving number ToDo add logging s

Sujal 3 Apr 3, 2022
Creating terminal-based UIs and games in Dart should be accessible and fun!

griddle Griddle simplifies the concept of creating 2D games or UI applications within a 2D-matrix, or grid, which in turn makes it a suitable cross-pl

Matan Lurey 20 Dec 19, 2022
Display multiple simple messages at a same time.

Simple multipurpse flashes to announce different messages to the user and interact with them. Display multiple flashes at the same time and avoid writ

Hassan Emami 3 Oct 10, 2022
Z time ago - A simple Flutter z time ago package used to change date to time ago for english, arabic and kurdish languages

This package is used to get time duration from now and given time for kurdish, a

Zakarya Muhammad 2 May 19, 2022
Toast Library for Flutter, Easily create toast messages in single line of code

Create Toast messages on a Flutter Event. fluttertoast: ^8.0.8 Toast Library for Flutter, Easily create Personalised toast messages in single line of

Bouziani Mohammed 1 Feb 14, 2022
A powerful plugin that fully uses the native image library's ability to display images on the flutter side.

PowerImage A powerful plugin that fully uses the native image library's ability to display images on the flutter side. 中文文档 Features: Supports the abi

Alibaba 422 Dec 23, 2022
A pure Dart utility library that checks for an internet connection by opening a socket to a list of specified addresses, each with individual port and timeout. Defaults are provided for convenience.

data_connection_checker A pure Dart utility library that checks for an internet connection by opening a socket to a list of specified addresses, each

Kristiyan Mitev 103 Nov 29, 2022
App-flutter-real-estate - Real Estate App Built With Flutter

Real Estate App - Flutter Preview video: https://youtu.be/11u0KeymAAs My Twitter

Sangvaleap Vanny 136 Dec 7, 2022