Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

ENet for RMXP/VX

ENet for RPG Maker XP/VX
by Dahrkael


What is ENet?

ENet's purpose is to provide a relatively thin, simple and robust network communication layer on top of UDP (User Datagram Protocol). The primary feature it provides is optional reliable, in-order delivery of packets.

ENet omits certain higher level networking features such as authentication, lobbying, server discovery, encryption, or other similar tasks that are particularly application specific so that the library remains flexible, portable, and easily embeddable.

Isn't ENet just re-inventing TCP?! What's the point?

In a perfect world, that would be true. But as many have found, using TCP either in lieu of or in conjunction with UDP can lead to all kinds of nightmares. TCP is a good, solid protocol, however it simply isn't up to the task of real-time games. Too much of TCP's implementation dictates a policy that isn't practical for games. If you want to use TCP, then do so -- this library is for people that either don't want to use TCP or have tried and ended up being discouraged with the performance.

Can I make ultra MMORPGs with this script?

Short answer: Yes, if you know how.
Long answer: Yes, ENet is made to develop real-time games with low latency, so you can make any type of online game, but this script wont do it alone, it needs you :cry: if you dont know how to make a mmorpg, forget it. Right know this script is only an scripters tool.

Cool things about this lib

- It is made for games
- Server can be done in C/C++ using the same lib and run in different OS
- It is easy to understand
- Fuck, its cool.

Scripts and DLLs

The script uses 1 DLL in order to work: RubyENet.dll

Downlaod RubyENet.dll

This is the main script:
Ruby:
 

################################################################################

#

#   ######   #    #   ######   #####                   ENet Ruby Bindings

#   #        ##   #   #          #

#   ####     # #  #   ####       #                     Last Update: 24/8/2010

#   #        #  # #   #          #

#   ######   #   ##   ######     #                     By Dahrkael

#

################################################################################

#

# ENet's purpose is to provide a relatively thin, simple and robust network

# communication layer on top of UDP (User Datagram Protocol). 

# The primary feature it provides is optional reliable, in-order delivery 

# of packets.

#

# ENet omits certain higher level networking features such as authentication, 

# lobbying, server discovery, encryption, or other similar tasks that are

# particularly application specific so that the library remains flexible,

# portable, and easily embeddable.

#

# Copyright (c) 2002-2010 Lee Salzman

#                                                       [url=http://enet.bespin.org/]http://enet.bespin.org/[/url]

#===============================================================================

#

# TODO:

#      - Error control

#      - Add all missing internal functions

#

#===============================================================================

#

# This script is free to use and doesnt need any credits B U T enet library does

#

################################################################################

 

#==============================================================================

# * Module Enet

#

#   Methods

#    - initialize

#    - deinitialize

#    - destroy_event_packet

#    - get_packet_data

#    - get_packet_datalength

#    - get_packet_from_event

#    - get_channelid_from_event

#    - get_peer_from_event

#    - get_peer_host

#    - get_peer_port

#

#   SubModules

#    - DLLs

#    - Types

#    - Constants

#    - APIFunctions

#

#   SubClasses (and methods)

#    - ENetHost

#       - initialize

#       - create_host

#       - destroy_host

#       - connect

#       - peers_list

#       - send_packet

#       - broadcast_packet

#       - disconnect

#       - service

#       - on_packet_receive

#       - on_connection

#       - on_disconnect

#

#    - ENetAddress

#       - initialize

#       - set_host

#       - set_port

#

#    - ENetEvent

#       - initialize

#       - update

#       - peer

#       - peer_host

#       - peer_port

#       - channel_id

#       - packet

#       - destroy_packet

#

#    - ENetPacket

#       - initialize

#       - update

#       - data_length

#       - data

#

#==============================================================================

 

module Win32

 

  #--------------------------------------------------------------------------

  # * Retrieves data from a pointer.

  #--------------------------------------------------------------------------

  def copymem(len)

    buf = "\0" * len

    Win32API.new("kernel32", "RtlMoveMemory", "pll", "").call(buf, self, len)

    buf

  end

  

end

 

# Extends the numeric class.

class Numeric

  include Win32

end

 

# Extends the string class.

class String

  include Win32

end

 

module Enet

  

#==============================================================================

# * M O D U L E S

#==============================================================================

  #============================================================================

  # ** DLLs

  #----------------------------------------------------------------------------

  # dlls containing needed functions

  #============================================================================

    module DLLs

        Enet            = "RubyENet.dll"      # enet itself

        RubyEnet      = "RubyENet.dll"  # auxiliar functions

    end

  

  #============================================================================

  # ** Types

  #----------------------------------------------------------------------------

  # Enet types converted to Win32API types

  #============================================================================

    module Types

        ENetAddress     = 'P'

        ENetHost        = 'L'

        ENetEvent     = 'L'

        ENetPacket    = 'L'

        ENetPeer          = 'L'

        Enet_uint32     = 'L'

        Enet_uint16     = 'L'

        Enet_uint8    = 'I'

        Size_t          = 'L'

        Int               = 'I'

        Void              = 'V'

        Const_void    = 'P'

        Const_char    = 'P'

    end

  

  #============================================================================

  # ** Constants 

  #----------------------------------------------------------------------------

  # Enet constants, better than numbers

  #============================================================================

    module Constants

        NULL                                        = 0 # yes...

    

        ENET_HOST_ANY                         = 0     

        ENET_HOST_BROADCAST                 = 0xFFFFFFFF 

        ENET_PORT_ANY                         = 0  

 

        ENET_EVENT_TYPE_NONE            = 0

        ENET_EVENT_TYPE_CONNECT         = 1

        ENET_EVENT_TYPE_DISCONNECT      = 2

        ENET_EVENT_TYPE_RECEIVE         = 3

 

        ENET_PACKET_FLAG_RELIABLE       = 1 # (1 << 0)

        ENET_PACKET_FLAG_UNSEQUENCED    = 2 # (1 << 1)

        ENET_PACKET_FLAG_NO_ALLOCATE    = 4 # (1 << 2)

    end

  

 

  #============================================================================

  # ** APIFunctions 

  #----------------------------------------------------------------------------

  # DLL Functions, some secondary and/or no-vital functions are missing

  #============================================================================

    module APIFunctions

        include Types

    

    #--------------------------------------------------------------------------

    # * Workaround Function (anyone help :3?)

    #--------------------------------------------------------------------------

        RubyEnet_CreateENetEvent              = Win32API.new(DLLs::RubyEnet, "RubyEnet_CreateENetEvent", [''], ENetEvent) 

                

    #--------------------------------------------------------------------------

    # * ENetEvent Auxiliar Functions

    #--------------------------------------------------------------------------

        RubyEnet_GetPeerFromEvent             = Win32API.new(DLLs::RubyEnet, "RubyEnet_GetPeerFromEvent", [ENetEvent], ENetPeer) 

        RubyEnet_GetEventType                 = Win32API.new(DLLs::RubyEnet, "RubyEnet_GetEventType", [ENetEvent], Int) 

        RubyEnet_GetChannelIDFromEvent  = Win32API.new(DLLs::RubyEnet, "RubyEnet_GetChannelIDFromEvent", [ENetEvent], Enet_uint8) 

         

    #--------------------------------------------------------------------------

    # * ENetPacket Auxiliar Functions

    #--------------------------------------------------------------------------

        RubyEnet_GetPacketFromEvent       = Win32API.new(DLLs::RubyEnet, "RubyEnet_GetPacketFromEvent", [ENetEvent], ENetPacket) 

        RubyEnet_GetPacket_DataLength   = Win32API.new(DLLs::RubyEnet, "RubyEnet_GetPacket_DataLength", [ENetPacket], Size_t) 

        RubyEnet_GetPacket_Data               = Win32API.new(DLLs::RubyEnet, "RubyEnet_GetPacket_Data", [ENetPacket], 'P') 

        

    #--------------------------------------------------------------------------

    # * ENetPeer Auxiliar Functions

    #--------------------------------------------------------------------------

        RubyEnet_GetPeerHost                    = Win32API.new(DLLs::RubyEnet, "RubyEnet_GetPeerHost", [ENetPeer], Enet_uint32) 

        RubyEnet_GetPeerPort                    = Win32API.new(DLLs::RubyEnet, "RubyEnet_GetPeerPort", [ENetPeer], Enet_uint32) 

    RubyEnet_GetPeerIP              = Win32API.new(DLLs::RubyEnet, "RubyEnet_GetPeerIP", [ENetPeer], "L") 

    RubyEnet_GetPeerIPlength        = Win32API.new(DLLs::RubyEnet, "RubyEnet_GetPeerIPlength", [ENetPeer], Size_t)

 

    #--------------------------------------------------------------------------

    # * ENet Basic Functions

    #--------------------------------------------------------------------------

        Enet_initialize                           = Win32API.new(DLLs::Enet, "enet_initialize", [''], Int) 

        Enet_deinitialize                       = Win32API.new(DLLs::Enet, "enet_deinitialize", [''], Void)

    

        #--------------------------------------------------------------------------

    # * ENetHost Functions

    #--------------------------------------------------------------------------

        Enet_host_create                        = Win32API.new(DLLs::Enet, "enet_host_create", [ENetAddress, Size_t, Size_t, Enet_uint32, Enet_uint32], ENetHost)

        Enet_host_destroy                     = Win32API.new(DLLs::Enet, "enet_host_destroy", [ENetHost], Void)

        Enet_host_connect                     = Win32API.new(DLLs::Enet, "enet_host_connect", [ENetHost, ENetAddress, Size_t, Enet_uint32], ENetPeer)

        Enet_host_service                     = Win32API.new(DLLs::Enet, "enet_host_service", [ENetHost, ENetEvent, Enet_uint32], Int)

        Enet_host_broadcast                     = Win32API.new(DLLs::Enet, "enet_host_broadcast", [ENetHost, Enet_uint8, ENetPacket], Void)

        Enet_host_flush                           = Win32API.new(DLLs::Enet, "enet_host_flush", [ENetHost], Void)

        Enet_address_set_host               = Win32API.new(DLLs::Enet, "enet_address_set_host", [ENetAddress, Const_char], Int)

        

    #--------------------------------------------------------------------------

    # * ENetpacket Functions

    #--------------------------------------------------------------------------

        Enet_packet_create                    = Win32API.new(DLLs::Enet, "enet_packet_create", [Const_void, Size_t, Enet_uint32], ENetPacket)

        Enet_packet_destroy                     = Win32API.new(DLLs::Enet, "enet_packet_destroy", [ENetPacket], Void)

 

    #--------------------------------------------------------------------------

    # * ENetPeer Functions

    #--------------------------------------------------------------------------

        Enet_peer_send                          = Win32API.new(DLLs::Enet, "enet_peer_send", [ENetPeer, Enet_uint8, ENetPacket], Int)

        Enet_peer_disconnect                    = Win32API.new(DLLs::Enet, "enet_peer_disconnect", [ENetPeer, Enet_uint32], Void)

        Enet_peer_reset                           = Win32API.new(DLLs::Enet, "enet_peer_reset", [ENetPeer], Void)

    end

  

#==============================================================================

# * M E T H O D S

#==============================================================================

 

  #----------------------------------------------------------------------------

  # * initialize

  # Starts the library

  #----------------------------------------------------------------------------

  def self.initialize

    APIFunctions::Enet_initialize.call()

  end

  

  #----------------------------------------------------------------------------

  # * deinitialize

  # Stops the library

  #----------------------------------------------------------------------------

  def self.deinitialize

    APIFunctions::Enet_deinitialize.call()

  end

  

  #----------------------------------------------------------------------------

  # * Destroy Event Packet

  # Destroys the packet contained in the event

  #----------------------------------------------------------------------------

  def self.destroy_event_packet(event)

    packet = self.get_packet_from_event(event)

    APIFunctions::Enet_packet_destroy.call(packet)

  end

  

  #----------------------------------------------------------------------------

  # * Get Packet Data

  # Returns a string with the packet data

  #----------------------------------------------------------------------------

  def self.get_packet_data(packet)

    length = APIFunctions::RubyEnet_GetPacket_DataLength.call(packet)

    data = 0.chr * length

    data = APIFunctions::RubyEnet_GetPacket_Data.call(packet)

    return data

  end

  

  #----------------------------------------------------------------------------

  # * Get Packet Datalength

  # Returns the datalength from the packet (the data size)

  #----------------------------------------------------------------------------

  def self.get_packet_datalength(packet)

    return APIFunctions::RubyEnet_GetPacket_DataLength.call(packet)

  end

  

  #----------------------------------------------------------------------------

  # * Get Packet From Event

  # Returns the packet pointer from the event

  #----------------------------------------------------------------------------

  def self.get_packet_from_event(event)

    return APIFunctions::RubyEnet_GetPacketFromEvent.call(event)

  end

  

  #----------------------------------------------------------------------------

  # * Get ChannelID From Event

  # Returns the ChannelID used

  #----------------------------------------------------------------------------

  def self.get_channelid_from_event(event)

    return APIFunctions::RubyEnet_GetChannelIDFromEvent.call(event)

  end

  

  #----------------------------------------------------------------------------

  # * Get Peer From Event

  # gets the peer pointer who generated the event

  #----------------------------------------------------------------------------

  def self.get_peer_from_event(event)

    return APIFunctions::RubyEnet_GetPeerFromEvent.call(event)

  end              

  

  #----------------------------------------------------------------------------

  # * Get Peer Host

  # Returns the hexadecimal peers address

  #----------------------------------------------------------------------------

  def self.get_peer_host(peer)

    return APIFunctions::RubyEnet_GetPeerHost.call(peer)

  end   

  

  #----------------------------------------------------------------------------

  # * Get Peer Port

  # Returns the peers port

  #----------------------------------------------------------------------------

  def self.get_peer_port(peer)

    return APIFunctions::RubyEnet_GetPeerPort.call(peer)

  end   

  

  def self.get_peer_ip(peer)

    length = APIFunctions::RubyEnet_GetPeerIPlength.call(peer)

    buf = APIFunctions::RubyEnet_GetPeerIP.call(peer)

    ip = buf.copymem(length)

    return ip

  end

  

 

#==============================================================================

# * C L A S S E S

#==============================================================================

 

  #============================================================================

  # ** ENetHost

  #----------------------------------------------------------------------------

  #    Class that represents the computer networking and the connections 

  #    associated

  #============================================================================

    class ENetHost

  #----------------------------------------------------------------------------

  # * Public Instance Variables

  #----------------------------------------------------------------------------

        attr_reader :connected # returns true if connected, all peers uses this var :/

  #----------------------------------------------------------------------------

  # * Object Initialization

  #----------------------------------------------------------------------------

        def initialize

            @enet_host = nil

            @peers = {}

            @connections = 0

            @channels = 0

            @downstream = 0

            @upstream = 0

            @event = APIFunctions::RubyEnet_CreateENetEvent.call()

      @external_event = ENetEvent.new(@event)

            @connected = false

      @on_packet_receive = nil

      @on_disconnect = nil

      @on_connection = nil

        end

    

  #----------------------------------------------------------------------------

  # * Event

  #----------------------------------------------------------------------------

    def event

      return @external_event

    end

    

  #----------------------------------------------------------------------------

  # * Create Host

  #     type:         Client or Server, NULL = Client, Pointer to ENetAddress = Server

  #     connections:  Outgoing connections allowed (number)

  #     channels:     Number of avaiable channels for connections (number)

  #     downstream:   Downstream bandwidth in bytes (number)

  #     upstream:     Upstream bandwidth in bytes (number)

  #----------------------------------------------------------------------------

        def create_host(type, connections, channels, downstream, upstream)

            @enet_host = APIFunctions::Enet_host_create.call(type, connections,  channels, downstream, upstream)

            if @enet_host != 0

                @connections = connections

                @channels = channels

                @downstream = downstream

                @upstream = upstream

                return true

            else

                return false

            end

        end

    

  #----------------------------------------------------------------------------

  # * Destroy Host

  #----------------------------------------------------------------------------

        def destroy_host

            APIFunctions::Enet_host_destroy.call(@enet_host)

            @enet_host = nil

            @connections = 0

            @channels = 0

            @downstream = 0

            @upstream = 0

        end

    

  #----------------------------------------------------------------------------

  # * Connect

  #     address: ENetAddres instance with the remote host address and port (ENetAddress)

  #     channels: Number of channels allocated for this connection (number)

  #     extradata: Optional data to send with the connection petition (string)

  #----------------------------------------------------------------------------

        def connect(address, channels, extradata=0)

            peer = APIFunctions::Enet_host_connect.call(@enet_host, address.enet_address, channels, extradata)

            if peer != 0

        address = APIFunctions::RubyEnet_GetPeerHost.call(peer)

        port = APIFunctions::RubyEnet_GetPeerPort.call(peer)

                @peers["server"] =   {

                             "peer"      => peer,

                             "address" => address,

                             "port"    => port 

                            }

        return true

            else

                return false

            end

        end

    

  #----------------------------------------------------------------------------

  # * Peers List

  #----------------------------------------------------------------------------

        def peers_list

            return @peers

        end

    

  #----------------------------------------------------------------------------

  # * Send packet

  #     peer: peer to send the packet (pointer to peer)

  #     data: data to send in the packet, text, binary, anything (~string)

  #     datalength: data length + 1 (number)

  #     channelID: Channel to send the packet (number)

  #     flags: Optional flags for the packet, default is ENET_PACKET_FLAG_RELIABLE

  #----------------------------------------------------------------------------

        def send_packet(peer, data, datalength, channelID, flags=Constants::ENET_PACKET_FLAG_RELIABLE)

            packet = APIFunctions::Enet_packet_create.call(data, datalength, flags)

            if APIFunctions::Enet_peer_send.call(peer, channelID, packet) < 0

                return false

            else

                return true

            end

        end

    

  #----------------------------------------------------------------------------

  # * Broadcast Packet

  #     data: data to send in the packet, text, binary, anything (~string)

  #     datalength: data length + 1 (number)

  #     channelID: Channel to send the packet (number)

  #     flags: Optional flags for the packet, default is ENET_PACKET_FLAG_RELIABLE

  #----------------------------------------------------------------------------

    def broadcast_packet(data, datalength, channelID, flags=Constants::ENET_PACKET_FLAG_RELIABLE)

            packet = APIFunctions::Enet_packet_create.call(data, datalength, flags)

            APIFunctions::Enet_host_broadcast.call(@enet_host, channelID, packet)

      return true

        end

    

  #----------------------------------------------------------------------------

  # * Disconnect

  #     peer: peer to disconnect (peer name string)

  #     data: extra data to send with the disconnection petition (~string)

  #     timeout: time in milliseconds to get answer, when over disconnection is forced (number)

  #----------------------------------------------------------------------------

        def disconnect(peer, data=0, timeout=3000)

            APIFunctions::Enet_peer_disconnect.call(peer, data)

            while APIFunctions::Enet_host_service.call(@enet_host, @event, timeout) > 0

                case APIFunctions::RubyEnet_GetEventType.call(@event)

                    when Constants::ENET_EVENT_TYPE_RECEIVE

                        APIFunctions::Enet_packet_destroy(RubyEnet_GetPacketFromEvent.call(@event))

                    when Constants::ENET_EVENT_TYPE_DISCONNECT

                        @peers[peer] = nil

                        #print "Disconnected"

                        return true

                end

            end

            #APIFunctions::Enet_peer_reset(@peers[peer]["peer"])

            @peers[peer] = nil

            return true

        end

    

  #----------------------------------------------------------------------------

  # * Service

  #     milliseconds: time to wait for a packet (number)

  #----------------------------------------------------------------------------

        def service(milliseconds=1000)

            while APIFunctions::Enet_host_service.call(@enet_host, @event, milliseconds) > 0

                case APIFunctions::RubyEnet_GetEventType.call(@event)

                    when Constants::ENET_EVENT_TYPE_NONE

                    

                    when Constants::ENET_EVENT_TYPE_CONNECT

                        #print "new client connected"

            @external_event.update(@event)

            on_connection

                        APIFunctions::Enet_host_flush.call(@enet_host)

                        @connected = true

                    when Constants::ENET_EVENT_TYPE_DISCONNECT

                        @connected = false

                        #print "Disconnected"

            @external_event.update(@event)

            on_disconnect

                    when Constants::ENET_EVENT_TYPE_RECEIVE

            @external_event.update(@event)

                        on_packet_receive

                end

            end

        end

    

  #----------------------------------------------------------------------------

  # * On Disconnection

  #     Method called when a disconnection event arrives

  #----------------------------------------------------------------------------

    def on_disconnect(&block)

      if block

          @on_disconnect = block

      elsif @on_disconnect

          @on_disconnect.call()

      end

    end

  #----------------------------------------------------------------------------

  # * On Connection

  #     Method called when a connection event arrives

  #----------------------------------------------------------------------------

    def on_connection(&block)

      if block

          @on_connection = block

      elsif @on_connection

          @on_connection.call()

      end

    end

  #----------------------------------------------------------------------------

  # * Packet Received

  #     Method called when an event containing a packet arrives

  #----------------------------------------------------------------------------

    def on_packet_receive(&block)

      if block

          @on_packet_receive = block

      elsif @on_packet_receive

          @on_packet_receive.call()

          #destroy_event_packet(@event)

      end

    end

    end

  

  #============================================================================

  # ** ENetAddress

  #----------------------------------------------------------------------------

  #    Class to simplify C ENetAddress structs

  #============================================================================

    class ENetAddress

  #----------------------------------------------------------------------------

  # * Public Instance Variables

  #----------------------------------------------------------------------------

        attr_reader :address

        attr_reader :port

        attr_reader :enet_address

    

  #----------------------------------------------------------------------------

  # * Object Initialization

  #----------------------------------------------------------------------------

        def initialize

            @address = ""

            @port = 0

            @enet_address = ""

        end

    

  #----------------------------------------------------------------------------

  # * Set Host

  #     host: remote host to get address (string)

  #----------------------------------------------------------------------------

        def set_host(host)

             @enet_address = [Constants::ENET_HOST_ANY, @port].pack("LS")

            if APIFunctions::Enet_address_set_host.call(@enet_address, host) < 0

                return false 

            end

            @address = host

            return true

        end

    

  #----------------------------------------------------------------------------

  # * Set Port

  #     port: port to bind

  #----------------------------------------------------------------------------

        def set_port(port)

            @port = port

            @enet_address = [Constants::ENET_HOST_ANY, @port].pack("LS")

            set_host(@address)

            return true

        end

    end

  

  #============================================================================

  # ** ENetPacket

  #----------------------------------------------------------------------------

  #    Class to simplify C ENetPacket structs

  #============================================================================

  class ENetPacket

  #----------------------------------------------------------------------------

  # * Object Initialization

  #     packet: packet to wrap

  #----------------------------------------------------------------------------

    def initialize(packet)

      @packet = packet

      @length = 0

      @data = 0

    end

  #----------------------------------------------------------------------------

  # * Update

  #     packet: packet to wrap

  #----------------------------------------------------------------------------

    def update(packet)

      @packet = packet

      @length = 0

      @data = 0

    end

  #----------------------------------------------------------------------------

  # * Data Length

  #----------------------------------------------------------------------------

    def data_length

      @length = Enet.get_packet_datalength(@packet)

      return @length

    end

  #----------------------------------------------------------------------------

  # * Data

  #----------------------------------------------------------------------------

    def data

      if RUBY_VERSION.match(/1\.8\.*/)

        @data = Enet.get_packet_data(@packet)

      elsif RUBY_VERSION.match(/1\.9\.*/)

        @length = Enet.get_packet_datalength(@packet)

        data = Enet.get_packet_data(@packet)

        @data = data.copymem(@length)

      end

       return @data

    end

  end

      

  #============================================================================

  # ** ENetEvent

  #----------------------------------------------------------------------------

  #    Class to simplify C ENetEvent structs

  #============================================================================

  class ENetEvent

  #----------------------------------------------------------------------------

  # * Object Initialization

  #     event: event to wrap

  #----------------------------------------------------------------------------

    def initialize(event)

      @event = event

      @peer = 0

      @peer_host = 0

      @peer_port = 0

      @channel_id = 0

      @packet = 0

    end

  #----------------------------------------------------------------------------

  # * Update

  #     event: event to wrap

  #----------------------------------------------------------------------------

    def update(event)

      @event = event

      @peer = 0

      @peer_host = 0

      @peer_port = 0

      @channel_id = 0

      @packet = 0

    end

  #----------------------------------------------------------------------------

  # * Peer

  #----------------------------------------------------------------------------

    def peer

      @peer = Enet.get_peer_from_event(@event)

      return @peer

    end

  #----------------------------------------------------------------------------

  # * Peer Host

  #----------------------------------------------------------------------------

    def peer_host

      if @peer == 0

        @peer = Enet.get_peer_from_event(@event)

      end

      @host = Enet.get_peer_host(@peer)

      return @host

    end

  #----------------------------------------------------------------------------

  # * Peer Port

  #----------------------------------------------------------------------------

    def peer_port

      if @peer == 0

        @peer = Enet.get_peer_from_event(@event)

      end

      @port = Enet.get_peer_port(@peer)

      return @port

    end

  #----------------------------------------------------------------------------

  # * Channel ID

  #----------------------------------------------------------------------------

    def channel_id

      @channel_id = Enet.get_channelid_from_event(@event)

    end

  #----------------------------------------------------------------------------

  # * Packet

  #----------------------------------------------------------------------------

    def packet

      if @packet == 0

        packet = Enet.get_packet_from_event(@event)

        @packet = ENetPacket.new(packet)

      end

      return @packet

    end

  #----------------------------------------------------------------------------

  # * Destroy Packet

  #----------------------------------------------------------------------------

    def destroy_packet

      Enet.destroy_event_packet(@event)

      @packet = 0

    end

  end

end # Classes end

 

Examples

Documentation from my part is not really cool, so here is an example script to make a client, so you can understand how this works:
Ruby:
 

class ENet_Example

  def run

      # First we initialize ENet

      if Enet.initialize != 0 # 0 = all ok

        print "error initializing enet"

        exit # exit if enet fails

      end

      # Now we need two things to make this work

      # an ENetAddress

      # an ENetHost

  

      # First the ENetAddress

      @address = Enet::ENetAddress.new

      

      # Set the address!

      if @address.set_host("localhost") == true

          print "host set"

        else

          print "error setting host"

      end

      # Now the port!

      if @address.set_port(8000) == true

          print "port set"

        else

          print "error setting port"

      end

      # Secondly the ENetHost

      @client = Enet::ENetHost.new

      # Now create the internal host

      if @client.create_host(Enet::Constants::NULL, 1, 2, 57600/8, 14400/8) == true

        print "host created"

      end

      

      # Optional but important step

      # tell the host what to do when a packet arrives

      @client.on_packet_receive do

        print "packet arrived"

        # get the peer

        @client.event.peer

        # show info about the peer

        print "from "

              + @client.event.peer_host.to_s

              + ":"

              + @client.event.peer_port.to_s

        print "packet arrived in channel: "

              + @client.event.channel_id.to_s

        # get the packet

        packet = @client.event.packet

        # show info about the packet

        print "packet lenght: " + packet.data_length.to_s

        print "packet data: "   + packet.data.to_s

        # finished, destroy the packet

        @client.event.destroy_packet

      end

      

      

      

      # Time to connect to the server!

      if @client.connect(@address, 2, 0) == true

        print "connection established"

      end

      

      # Now check for the server answer

      @client.service

      # if the server answers then connected will be true

      if @client.connected == true

        print "connection confirmed"

        # Retrieve the peerlist and get the server peer pointer

        # peer list is like

        # [i][0] = peer pointer

        # [i][1] = peer ip

        # [i][2] = peer port

        @server = @client.peers_list[0][0]

        

        #send and check 5 times

        for i in 0..5

          # this checks and send the packets in queue

          @client.service 

          string = "example packet"

          # this queues a new packet

          @client.send_packet(@server, string, string.size+1, 0) 

        end

      else

        print "connection unconfirmed"

      end

      # deinitialize the enet library

      Enet.deinitialize

      # finished!

    end

end

 

You can make a server script in ruby too, but if your game is gonna be cool, make it in C/C++.

Server Example:
Ruby:
 

#------------------------------------------------------------------------------#

#

#                                 Server Basis

#

#               Packet Data doesnt work on ruby 1.9.x right now

#

#------------------------------------------------------------------------------#

 

    if Enet.initialize != 0

        print "error initializing enet\r\n"

        exit

    end  

 

    address = [0, 8000].pack("LS")

 

  @server = Enet::ENetHost.new

 

  if @server.create_host(address, 32, 2, 0, 0) == true

    print "server created"

  end

      

  @server.on_connection do

    print "new user connected"

  end

  

  @server.on_disconnect do

    print "user disconnected"

  end

  

  @server.on_packet_receive do

    print "packet arrived"

    #@server.event.peer

    print "from " + Enet.get_peer_ip(@server.event.peer).to_s + ":" + @server.event.peer_port.to_s

    print "packet arrived in channel: " + @server.event.channel_id.to_s

    packet = @server.event.packet

    print "packet lenght: " + packet.data_length.to_s

    print "packet data: "   + packet.data.to_s

    @server.event.destroy_packet

  end

 

  loop do

 

    @server.service 

    #@server.send_packet(@server, string, string.size+1, 0) 

  end

 

  Enet.deinitialize

 

 

Demo

All packed in one rpg maker xp demo:
Download RPG Maker XP Demo

Bugs

- No known bugs

Final Notes


Ask anything, request anything, comment anything. Cheers.
 
Are you planning to include that necessary feature named "user authentication"? AFAIK, you didn't included such thing due to replacing TCP protocol with this... eh, solution...
 
kyonides":3iii5xjc said:
Are you planning to include that necessary feature named "user authentication"?
Thats your works when writing the server for your game, send a packet with the user and pass base64 encoded from the client and check it in the server, thats not a protocol thing.

kyonides":3iii5xjc said:
AFAIK, you didn't included such thing due to replacing TCP protocol with this... eh, solution...
err.. what?

if you want a full Netplay++++ 7.0 + bonus pack, you can start writing ;D
 
the channel feature from UDP is pretty cool :) that can simplify the identification of data for the server or the client. :)
( like channel 1 handles user-auth, channel 2 for the chat, etc... )


EDIT Can't it be used with default network libraries if the server is in another language or even ruby as an external program, UDP is a standard after all ?
 
EDIT Can't it be used with default network libraries if the server is in another language or even ruby as an external program, UDP is a standard after all ?

of course you can, but this lib is like a layer between the UDP and your app, so the main problem would be recreating the basic stuff of that layer in order to know whats going on :thumb:
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top