Cornix
25.04.2011, 17:16
Guten Tag,
ich weis dies wird sehr oft gefragt und die Antworten sind meistens vorhersehbar doch ich wage es einmal dennoch zu fragen.
Ich habe mich in den letzten zwei Tagen sehr viel mit der Fragestellung beschäftigt wie ich ein Multiplayer Projekt mit dem RPG-Maker XP / VX erarbeiten kann.
Ich stieß auf lediglich ein einziges vielversprechendes Ergebniss im Internet: http://nrpgxpfiles.webs.com/
Zusammenfassend gesagt sei, dass hier ein kompletter Client für ein Massive-Multiplayer-Online-RPG mit dem RPG-Maker XP erstellt wird; der Server hingegen wird extern betrieben. Verständlicherweise.
Allerdings will ich kein MMORPG erstellen, gott bewahre, so utopisch sind meine Fantasien nicht.
Aber ich würde gerne ein kleines einfaches RTS-Spiel von mir für zwei Spieler umkonzipieren. Es handelt sich dabei um nichts allzu aufwändiges, Performance und Datenübertragungsmengen sollten keine nennenswerte Rolle spielen.
Was ich nun brauche ist keine genaue Anleitung wie soetwas aufgebaut wird, das schaffe ich wahrscheinlich. Ich brauche nur die nötigen Klassen, sprich die Schnittstellen zu den WindowsAPI's um eine Verbindung zwischen zwei Computern herzustellen.
Unter den oben verlinkten Scripten für den Client ließen sich folgende Zeilen extrahieren:
module Win32
#----------------------------------------------------------------------------
# ● Retrieves data from a pointer.
#----------------------------------------------------------------------------
def copymem(len)
buf = "\0" * len
Win32API.new('kernel32', 'RtlMoveMemory', 'ppl', '').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 Winsock - Maps out the functions held in the Winsock DLL.
#------------------------------------------------------------------------------
# Author Ruby
# Version 1.8.1
#==============================================================================
module Winsock
DLL = 'ws2_32'
#----------------------------------------------------------------------------
# * Accept Connection
#----------------------------------------------------------------------------
def self.accept(*args)
Win32API.new(DLL, 'accept', 'ppl', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Bind
#----------------------------------------------------------------------------
def self.bind(*args)
Win32API.new(DLL, 'bind', 'ppl', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Close Socket
#----------------------------------------------------------------------------
def self.closesocket(*args)
Win32API.new(DLL, 'closesocket', 'p', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Connect
#----------------------------------------------------------------------------
def self.connect(*args)
Win32API.new(DLL, 'connect', 'ppl', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Get host (Using Adress)
#----------------------------------------------------------------------------
def self.gethostbyaddr(*args)
Win32API.new(DLL, 'gethostbyaddr', 'pll', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Get host (Using Name)
#----------------------------------------------------------------------------
def self.gethostbyname(*args)
Win32API.new(DLL, 'gethostbyname', 'p', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Get host's Name
#----------------------------------------------------------------------------
def self.gethostname(*args)
Win32API.new(DLL, 'gethostname', 'pl', '').call(*args)
end
#----------------------------------------------------------------------------
# * Get Server (Using Name)
#----------------------------------------------------------------------------
def self.getservbyname(*args)
Win32API.new(DLL, 'getservbyname', 'pp', 'p').call(*args)
end
#----------------------------------------------------------------------------
# * HT OnL
#----------------------------------------------------------------------------
def self.htonl(*args)
Win32API.new(DLL, 'htonl', 'l', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * HT OnS
#----------------------------------------------------------------------------
def self.htons(*args)
Win32API.new(DLL, 'htons', 'l', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Inet Adress
#----------------------------------------------------------------------------
def self.inet_addr(*args)
Win32API.new(DLL, 'inet_addr', 'p', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Inet NtOA
#----------------------------------------------------------------------------
def self.inet_ntoa(*args)
Win32API.new(DLL, 'inet_ntoa', 'l', 'p').call(*args)
end
#----------------------------------------------------------------------------
# * Listen
#----------------------------------------------------------------------------
def self.listen(*args)
Win32API.new(DLL, 'listen', 'pl', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Recieve
#----------------------------------------------------------------------------
def self.recv(*args)
Win32API.new(DLL, 'recv', 'ppll', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Select
#----------------------------------------------------------------------------
def self.select(*args)
Win32API.new(DLL, 'select', 'lpppp', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Send
#----------------------------------------------------------------------------
def self.send(*args)
Win32API.new(DLL, 'send', 'ppll', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Set Socket Options
#----------------------------------------------------------------------------
def self.setsockopt(*args)
Win32API.new(DLL, 'setsockopt', 'pllpl', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Shutdown
#----------------------------------------------------------------------------
def self.shutdown(*args)
Win32API.new(DLL, 'shutdown', 'pl', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Socket
#----------------------------------------------------------------------------
def self.socket(*args)
Win32API.new(DLL, 'socket', 'lll', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Get Last Error
#----------------------------------------------------------------------------
def self.WSAGetLastError(*args)
Win32API.new(DLL, 'WSAGetLastError', '', 'l').call(*args)
end
end
#==============================================================================
# ** Socket - Creates and manages sockets.
#------------------------------------------------------------------------------
# Author Ruby
# Version 1.8.1
#==============================================================================
class Socket
#----------------------------------------------------------------------------
# ● Constants
#----------------------------------------------------------------------------
AF_UNSPEC = 0
AF_UNIX = 1
AF_INET = 2
AF_IPX = 6
AF_APPLETALK = 16
PF_UNSPEC = 0
PF_UNIX = 1
PF_INET = 2
PF_IPX = 6
PF_APPLETALK = 16
SOCK_STREAM = 1
SOCK_DGRAM = 2
SOCK_RAW = 3
SOCK_RDM = 4
SOCK_SEQPACKET = 5
IPPROTO_IP = 0
IPPROTO_ICMP = 1
IPPROTO_IGMP = 2
IPPROTO_GGP = 3
IPPROTO_TCP = 6
IPPROTO_PUP = 12
IPPROTO_UDP = 17
IPPROTO_IDP = 22
IPPROTO_ND = 77
IPPROTO_RAW = 255
IPPROTO_MAX = 256
SOL_SOCKET = 65535
SO_DEBUG = 1
SO_REUSEADDR = 4
SO_KEEPALIVE = 8
SO_DONTROUTE = 16
SO_BROADCAST = 32
SO_LINGER = 128
SO_OOBINLINE = 256
SO_RCVLOWAT = 4100
SO_SNDTIMEO = 4101
SO_RCVTIMEO = 4102
SO_ERROR = 4103
SO_TYPE = 4104
SO_SNDBUF = 4097
SO_RCVBUF = 4098
SO_SNDLOWAT = 4099
TCP_NODELAY = 1
MSG_OOB = 1
MSG_PEEK = 2
MSG_DONTROUTE = 4
IP_OPTIONS = 1
IP_DEFAULT_MULTICAST_LOOP = 1
IP_DEFAULT_MULTICAST_TTL = 1
IP_MULTICAST_IF = 2
IP_MULTICAST_TTL = 3
IP_MULTICAST_LOOP = 4
IP_ADD_MEMBERSHIP = 5
IP_DROP_MEMBERSHIP = 6
IP_TTL = 7
IP_TOS = 8
IP_MAX_MEMBERSHIPS = 20
EAI_ADDRFAMILY = 1
EAI_AGAIN = 2
EAI_BADFLAGS = 3
EAI_FAIL = 4
EAI_FAMILY = 5
EAI_MEMORY = 6
EAI_NODATA = 7
EAI_NONAME = 8
EAI_SERVICE = 9
EAI_SOCKTYPE = 10
EAI_SYSTEM = 11
EAI_BADHINTS = 12
EAI_PROTOCOL = 13
EAI_MAX = 14
AI_PASSIVE = 1
AI_CANONNAME = 2
AI_NUMERICHOST = 4
AI_MASK = 7
AI_ALL = 256
AI_V4MAPPED_CFG = 512
AI_ADDRCONFIG = 1024
AI_DEFAULT = 1536
AI_V4MAPPED = 2048
#----------------------------------------------------------------------------
# ● Returns the associated IP address for the given hostname.
#----------------------------------------------------------------------------
def self.getaddress(host)
gethostbyname(host)[3].unpack('C4').join('.')
end
#----------------------------------------------------------------------------
# ● Returns the associated IP address for the given hostname.
#----------------------------------------------------------------------------
def self.getservice(serv)
case serv
when Numeric
return serv
when String
return getservbyname(serv)
else
raise 'Please use an interger or string for services.'
end
end
#----------------------------------------------------------------------------
# ● Returns information about the given hostname.
#----------------------------------------------------------------------------
def self.gethostbyname(name)
raise SocketError::ENOASSOCHOST if (ptr = Winsock.gethostbyname(name)) == 0
host = ptr.copymem(16).unpack('iissi')
[host[0].copymem(64).split("\0")[0], [], host[2], host[4].copymem(4).unpack('l')[0].copymem(4)]
end
#----------------------------------------------------------------------------
# ● Returns the user's hostname.
#----------------------------------------------------------------------------
def self.gethostname
buf = "\0" * 256
Winsock.gethostname(buf, 256)
buf.strip
end
#----------------------------------------------------------------------------
# ● Returns information about the given service.
#----------------------------------------------------------------------------
def self.getservbyname(name)
case name
when /echo/i
return 7
when /daytime/i
return 13
when /ftp/i
return 21
when /telnet/i
return 23
when /smtp/i
return 25
when /time/i
return 37
when /http/i
return 80
when /pop/i
return 110
else
raise 'Service not recognized.'
end
end
#----------------------------------------------------------------------------
# ● Creates an INET-sockaddr struct.
#----------------------------------------------------------------------------
def self.sockaddr_in(port, host)
begin
[AF_INET, getservice(port)].pack('sn') + gethostbyname(host)[3] + [].pack('x8')
rescue
end
end
#----------------------------------------------------------------------------
# ● Creates a new socket and connects it to the given host and port.
#----------------------------------------------------------------------------
def self.open(*args)
socket = new(*args)
if block_given?
begin
yield socket
ensure
socket.close
end
end
nil
end
#----------------------------------------------------------------------------
# ● Creates a new socket.
#----------------------------------------------------------------------------
def initialize(domain, type, protocol)
SocketError.check if (@fd = Winsock.socket(domain, type, protocol)) == -1
@fd
end
#----------------------------------------------------------------------------
# ● Accepts incoming connections.
#----------------------------------------------------------------------------
def accept(flags = 0)
buf = "\0" * 16
SocketError.check if Winsock.accept(@fd, buf, flags) == -1
buf
end
#----------------------------------------------------------------------------
# ● Binds a socket to the given sockaddr.
#----------------------------------------------------------------------------
def bind(sockaddr)
SocketError.check if (ret = Winsock.bind(@fd, sockaddr, sockaddr.size)) == -1
ret
end
#----------------------------------------------------------------------------
# ● Closes a socket.
#----------------------------------------------------------------------------
def close
SocketError.check if (ret = Winsock.closesocket(@fd)) == -1
ret
end
#----------------------------------------------------------------------------
# ● Connects a socket to the given sockaddr.
#----------------------------------------------------------------------------
def connect(sockaddr)
SocketError.check if (ret = Winsock.connect(@fd, sockaddr, sockaddr.size)) == -1
ret
end
#----------------------------------------------------------------------------
# ● Listens for incoming connections.
#----------------------------------------------------------------------------
def listen(backlog)
SocketError.check if (ret = Winsock.listen(@fd, backlog)) == -1
ret
end
#----------------------------------------------------------------------------
# ● Checks waiting data's status.
#----------------------------------------------------------------------------
def select(timeout)
SocketError.check if (ret = Winsock.select(1, [1, @fd].pack('ll'), 0, 0, [timeout, timeout * 1000000].pack('ll'))) == -1
ret
end
#----------------------------------------------------------------------------
# ● Checks if data is waiting.
#----------------------------------------------------------------------------
def ready?
not select(0) == 0
end
#----------------------------------------------------------------------------
# ● Reads data from socket.
#----------------------------------------------------------------------------
def read(len)
buf = "\0" * len
Win32API.new('msvcrt', '_read', 'lpl', 'l').call(@fd, buf, len)
buf
end
#----------------------------------------------------------------------------
# ● Returns recieved data.
#----------------------------------------------------------------------------
def recv(len, flags = 0)
buf = "\0" * len
SocketError.check if Winsock.recv(@fd, buf, buf.size, flags) == -1
buf
end
#----------------------------------------------------------------------------
# ● Sends data to a host.
#----------------------------------------------------------------------------
def send(data, flags = 0)
SocketError.check if (ret = Winsock.send(@fd, data, data.size, flags)) == -1
ret
end
#----------------------------------------------------------------------------
# ● Writes data to socket.
#----------------------------------------------------------------------------
def write(data)
Win32API.new('msvcrt', '_write', 'lpl', 'l').call(@fd, data, 1)
end
end
#==============================================================================
# ** TCPSocket - Creates and manages TCP sockets.
#------------------------------------------------------------------------------
# Author Ruby
# Version 1.8.1
#==============================================================================
class TCPSocket < Socket
#----------------------------------------------------------------------------
# ● Creates a new socket and connects it to the given host and port.
#----------------------------------------------------------------------------
def self.open(*args)
socket = new(*args)
if block_given?
begin
yield socket
ensure
socket.close
end
end
nil
end
#----------------------------------------------------------------------------
# ● Creates a new socket and connects it to the given host and port.
#----------------------------------------------------------------------------
def initialize(host, port)
super(AF_INET, SOCK_STREAM, IPPROTO_TCP)
connect(Socket.sockaddr_in(port, host))
end
end
#==============================================================================
# ** SocketError
#------------------------------------------------------------------------------
# Default exception class for sockets.
#==============================================================================
class SocketError < StandardError
ENOASSOCHOST = 'getaddrinfo: no address associated with hostname.'
def self.check
errno = Winsock.WSAGetLastError
raise Errno.const_get(Errno.constants.detect { |c| Errno.const_get(c).new.errno == errno })
end
end
Unschwer zu erkennen sind dies die benötigten Klassen um einen TCP-Client zu starten und diesen mit einem Server zu verbinden. Eine Hälfte wäre also gefunden.
Allerdings finde ich keine vergleichbaren Scripte für einen Server. Ich habe tatsächlich Stunden damit verbracht und verschiedene Ansätze verfolgt wie ich zwei Computer nur über den RPG-Maker verbinden kann ohne einen externen Server zu verwenden. Ohne Erfolg versteht sich, sonst würde ich nun nicht hier um Hilfe bitten.
Ich weis nicht in welcher Schwierigkeitsstufe sich diese Bitte bewegt, ich sehe, die Klassen für die Clientverbindung lassen sich in überschaubarem geringen Aufwand erstellen, ich weis auch, dass soetwas mit dem RPG-Maker 2000 (DestinyPatch) möglich ist.
Falls mir also irgendjemand bei diesem Problem helfen kann, sprich eine Schnittstelle zwischen den nötigen WindowsAPI's und dem Ruby Interpreter des Makers bereitstellen so wäre ich sehr sehr dankbar.
Selbstverständlich würde ein Creditseintrag bei jedem Spiel welches die Scripte verwendet gesichert sein und ich würde die Scripte auch bereitwillig jedem Interessenten zur Verfügung stellen so wie sie mir gegeben worden sind.
Danke nocheinmal im Vorraus,
Cornix.
ich weis dies wird sehr oft gefragt und die Antworten sind meistens vorhersehbar doch ich wage es einmal dennoch zu fragen.
Ich habe mich in den letzten zwei Tagen sehr viel mit der Fragestellung beschäftigt wie ich ein Multiplayer Projekt mit dem RPG-Maker XP / VX erarbeiten kann.
Ich stieß auf lediglich ein einziges vielversprechendes Ergebniss im Internet: http://nrpgxpfiles.webs.com/
Zusammenfassend gesagt sei, dass hier ein kompletter Client für ein Massive-Multiplayer-Online-RPG mit dem RPG-Maker XP erstellt wird; der Server hingegen wird extern betrieben. Verständlicherweise.
Allerdings will ich kein MMORPG erstellen, gott bewahre, so utopisch sind meine Fantasien nicht.
Aber ich würde gerne ein kleines einfaches RTS-Spiel von mir für zwei Spieler umkonzipieren. Es handelt sich dabei um nichts allzu aufwändiges, Performance und Datenübertragungsmengen sollten keine nennenswerte Rolle spielen.
Was ich nun brauche ist keine genaue Anleitung wie soetwas aufgebaut wird, das schaffe ich wahrscheinlich. Ich brauche nur die nötigen Klassen, sprich die Schnittstellen zu den WindowsAPI's um eine Verbindung zwischen zwei Computern herzustellen.
Unter den oben verlinkten Scripten für den Client ließen sich folgende Zeilen extrahieren:
module Win32
#----------------------------------------------------------------------------
# ● Retrieves data from a pointer.
#----------------------------------------------------------------------------
def copymem(len)
buf = "\0" * len
Win32API.new('kernel32', 'RtlMoveMemory', 'ppl', '').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 Winsock - Maps out the functions held in the Winsock DLL.
#------------------------------------------------------------------------------
# Author Ruby
# Version 1.8.1
#==============================================================================
module Winsock
DLL = 'ws2_32'
#----------------------------------------------------------------------------
# * Accept Connection
#----------------------------------------------------------------------------
def self.accept(*args)
Win32API.new(DLL, 'accept', 'ppl', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Bind
#----------------------------------------------------------------------------
def self.bind(*args)
Win32API.new(DLL, 'bind', 'ppl', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Close Socket
#----------------------------------------------------------------------------
def self.closesocket(*args)
Win32API.new(DLL, 'closesocket', 'p', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Connect
#----------------------------------------------------------------------------
def self.connect(*args)
Win32API.new(DLL, 'connect', 'ppl', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Get host (Using Adress)
#----------------------------------------------------------------------------
def self.gethostbyaddr(*args)
Win32API.new(DLL, 'gethostbyaddr', 'pll', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Get host (Using Name)
#----------------------------------------------------------------------------
def self.gethostbyname(*args)
Win32API.new(DLL, 'gethostbyname', 'p', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Get host's Name
#----------------------------------------------------------------------------
def self.gethostname(*args)
Win32API.new(DLL, 'gethostname', 'pl', '').call(*args)
end
#----------------------------------------------------------------------------
# * Get Server (Using Name)
#----------------------------------------------------------------------------
def self.getservbyname(*args)
Win32API.new(DLL, 'getservbyname', 'pp', 'p').call(*args)
end
#----------------------------------------------------------------------------
# * HT OnL
#----------------------------------------------------------------------------
def self.htonl(*args)
Win32API.new(DLL, 'htonl', 'l', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * HT OnS
#----------------------------------------------------------------------------
def self.htons(*args)
Win32API.new(DLL, 'htons', 'l', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Inet Adress
#----------------------------------------------------------------------------
def self.inet_addr(*args)
Win32API.new(DLL, 'inet_addr', 'p', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Inet NtOA
#----------------------------------------------------------------------------
def self.inet_ntoa(*args)
Win32API.new(DLL, 'inet_ntoa', 'l', 'p').call(*args)
end
#----------------------------------------------------------------------------
# * Listen
#----------------------------------------------------------------------------
def self.listen(*args)
Win32API.new(DLL, 'listen', 'pl', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Recieve
#----------------------------------------------------------------------------
def self.recv(*args)
Win32API.new(DLL, 'recv', 'ppll', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Select
#----------------------------------------------------------------------------
def self.select(*args)
Win32API.new(DLL, 'select', 'lpppp', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Send
#----------------------------------------------------------------------------
def self.send(*args)
Win32API.new(DLL, 'send', 'ppll', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Set Socket Options
#----------------------------------------------------------------------------
def self.setsockopt(*args)
Win32API.new(DLL, 'setsockopt', 'pllpl', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Shutdown
#----------------------------------------------------------------------------
def self.shutdown(*args)
Win32API.new(DLL, 'shutdown', 'pl', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Socket
#----------------------------------------------------------------------------
def self.socket(*args)
Win32API.new(DLL, 'socket', 'lll', 'l').call(*args)
end
#----------------------------------------------------------------------------
# * Get Last Error
#----------------------------------------------------------------------------
def self.WSAGetLastError(*args)
Win32API.new(DLL, 'WSAGetLastError', '', 'l').call(*args)
end
end
#==============================================================================
# ** Socket - Creates and manages sockets.
#------------------------------------------------------------------------------
# Author Ruby
# Version 1.8.1
#==============================================================================
class Socket
#----------------------------------------------------------------------------
# ● Constants
#----------------------------------------------------------------------------
AF_UNSPEC = 0
AF_UNIX = 1
AF_INET = 2
AF_IPX = 6
AF_APPLETALK = 16
PF_UNSPEC = 0
PF_UNIX = 1
PF_INET = 2
PF_IPX = 6
PF_APPLETALK = 16
SOCK_STREAM = 1
SOCK_DGRAM = 2
SOCK_RAW = 3
SOCK_RDM = 4
SOCK_SEQPACKET = 5
IPPROTO_IP = 0
IPPROTO_ICMP = 1
IPPROTO_IGMP = 2
IPPROTO_GGP = 3
IPPROTO_TCP = 6
IPPROTO_PUP = 12
IPPROTO_UDP = 17
IPPROTO_IDP = 22
IPPROTO_ND = 77
IPPROTO_RAW = 255
IPPROTO_MAX = 256
SOL_SOCKET = 65535
SO_DEBUG = 1
SO_REUSEADDR = 4
SO_KEEPALIVE = 8
SO_DONTROUTE = 16
SO_BROADCAST = 32
SO_LINGER = 128
SO_OOBINLINE = 256
SO_RCVLOWAT = 4100
SO_SNDTIMEO = 4101
SO_RCVTIMEO = 4102
SO_ERROR = 4103
SO_TYPE = 4104
SO_SNDBUF = 4097
SO_RCVBUF = 4098
SO_SNDLOWAT = 4099
TCP_NODELAY = 1
MSG_OOB = 1
MSG_PEEK = 2
MSG_DONTROUTE = 4
IP_OPTIONS = 1
IP_DEFAULT_MULTICAST_LOOP = 1
IP_DEFAULT_MULTICAST_TTL = 1
IP_MULTICAST_IF = 2
IP_MULTICAST_TTL = 3
IP_MULTICAST_LOOP = 4
IP_ADD_MEMBERSHIP = 5
IP_DROP_MEMBERSHIP = 6
IP_TTL = 7
IP_TOS = 8
IP_MAX_MEMBERSHIPS = 20
EAI_ADDRFAMILY = 1
EAI_AGAIN = 2
EAI_BADFLAGS = 3
EAI_FAIL = 4
EAI_FAMILY = 5
EAI_MEMORY = 6
EAI_NODATA = 7
EAI_NONAME = 8
EAI_SERVICE = 9
EAI_SOCKTYPE = 10
EAI_SYSTEM = 11
EAI_BADHINTS = 12
EAI_PROTOCOL = 13
EAI_MAX = 14
AI_PASSIVE = 1
AI_CANONNAME = 2
AI_NUMERICHOST = 4
AI_MASK = 7
AI_ALL = 256
AI_V4MAPPED_CFG = 512
AI_ADDRCONFIG = 1024
AI_DEFAULT = 1536
AI_V4MAPPED = 2048
#----------------------------------------------------------------------------
# ● Returns the associated IP address for the given hostname.
#----------------------------------------------------------------------------
def self.getaddress(host)
gethostbyname(host)[3].unpack('C4').join('.')
end
#----------------------------------------------------------------------------
# ● Returns the associated IP address for the given hostname.
#----------------------------------------------------------------------------
def self.getservice(serv)
case serv
when Numeric
return serv
when String
return getservbyname(serv)
else
raise 'Please use an interger or string for services.'
end
end
#----------------------------------------------------------------------------
# ● Returns information about the given hostname.
#----------------------------------------------------------------------------
def self.gethostbyname(name)
raise SocketError::ENOASSOCHOST if (ptr = Winsock.gethostbyname(name)) == 0
host = ptr.copymem(16).unpack('iissi')
[host[0].copymem(64).split("\0")[0], [], host[2], host[4].copymem(4).unpack('l')[0].copymem(4)]
end
#----------------------------------------------------------------------------
# ● Returns the user's hostname.
#----------------------------------------------------------------------------
def self.gethostname
buf = "\0" * 256
Winsock.gethostname(buf, 256)
buf.strip
end
#----------------------------------------------------------------------------
# ● Returns information about the given service.
#----------------------------------------------------------------------------
def self.getservbyname(name)
case name
when /echo/i
return 7
when /daytime/i
return 13
when /ftp/i
return 21
when /telnet/i
return 23
when /smtp/i
return 25
when /time/i
return 37
when /http/i
return 80
when /pop/i
return 110
else
raise 'Service not recognized.'
end
end
#----------------------------------------------------------------------------
# ● Creates an INET-sockaddr struct.
#----------------------------------------------------------------------------
def self.sockaddr_in(port, host)
begin
[AF_INET, getservice(port)].pack('sn') + gethostbyname(host)[3] + [].pack('x8')
rescue
end
end
#----------------------------------------------------------------------------
# ● Creates a new socket and connects it to the given host and port.
#----------------------------------------------------------------------------
def self.open(*args)
socket = new(*args)
if block_given?
begin
yield socket
ensure
socket.close
end
end
nil
end
#----------------------------------------------------------------------------
# ● Creates a new socket.
#----------------------------------------------------------------------------
def initialize(domain, type, protocol)
SocketError.check if (@fd = Winsock.socket(domain, type, protocol)) == -1
@fd
end
#----------------------------------------------------------------------------
# ● Accepts incoming connections.
#----------------------------------------------------------------------------
def accept(flags = 0)
buf = "\0" * 16
SocketError.check if Winsock.accept(@fd, buf, flags) == -1
buf
end
#----------------------------------------------------------------------------
# ● Binds a socket to the given sockaddr.
#----------------------------------------------------------------------------
def bind(sockaddr)
SocketError.check if (ret = Winsock.bind(@fd, sockaddr, sockaddr.size)) == -1
ret
end
#----------------------------------------------------------------------------
# ● Closes a socket.
#----------------------------------------------------------------------------
def close
SocketError.check if (ret = Winsock.closesocket(@fd)) == -1
ret
end
#----------------------------------------------------------------------------
# ● Connects a socket to the given sockaddr.
#----------------------------------------------------------------------------
def connect(sockaddr)
SocketError.check if (ret = Winsock.connect(@fd, sockaddr, sockaddr.size)) == -1
ret
end
#----------------------------------------------------------------------------
# ● Listens for incoming connections.
#----------------------------------------------------------------------------
def listen(backlog)
SocketError.check if (ret = Winsock.listen(@fd, backlog)) == -1
ret
end
#----------------------------------------------------------------------------
# ● Checks waiting data's status.
#----------------------------------------------------------------------------
def select(timeout)
SocketError.check if (ret = Winsock.select(1, [1, @fd].pack('ll'), 0, 0, [timeout, timeout * 1000000].pack('ll'))) == -1
ret
end
#----------------------------------------------------------------------------
# ● Checks if data is waiting.
#----------------------------------------------------------------------------
def ready?
not select(0) == 0
end
#----------------------------------------------------------------------------
# ● Reads data from socket.
#----------------------------------------------------------------------------
def read(len)
buf = "\0" * len
Win32API.new('msvcrt', '_read', 'lpl', 'l').call(@fd, buf, len)
buf
end
#----------------------------------------------------------------------------
# ● Returns recieved data.
#----------------------------------------------------------------------------
def recv(len, flags = 0)
buf = "\0" * len
SocketError.check if Winsock.recv(@fd, buf, buf.size, flags) == -1
buf
end
#----------------------------------------------------------------------------
# ● Sends data to a host.
#----------------------------------------------------------------------------
def send(data, flags = 0)
SocketError.check if (ret = Winsock.send(@fd, data, data.size, flags)) == -1
ret
end
#----------------------------------------------------------------------------
# ● Writes data to socket.
#----------------------------------------------------------------------------
def write(data)
Win32API.new('msvcrt', '_write', 'lpl', 'l').call(@fd, data, 1)
end
end
#==============================================================================
# ** TCPSocket - Creates and manages TCP sockets.
#------------------------------------------------------------------------------
# Author Ruby
# Version 1.8.1
#==============================================================================
class TCPSocket < Socket
#----------------------------------------------------------------------------
# ● Creates a new socket and connects it to the given host and port.
#----------------------------------------------------------------------------
def self.open(*args)
socket = new(*args)
if block_given?
begin
yield socket
ensure
socket.close
end
end
nil
end
#----------------------------------------------------------------------------
# ● Creates a new socket and connects it to the given host and port.
#----------------------------------------------------------------------------
def initialize(host, port)
super(AF_INET, SOCK_STREAM, IPPROTO_TCP)
connect(Socket.sockaddr_in(port, host))
end
end
#==============================================================================
# ** SocketError
#------------------------------------------------------------------------------
# Default exception class for sockets.
#==============================================================================
class SocketError < StandardError
ENOASSOCHOST = 'getaddrinfo: no address associated with hostname.'
def self.check
errno = Winsock.WSAGetLastError
raise Errno.const_get(Errno.constants.detect { |c| Errno.const_get(c).new.errno == errno })
end
end
Unschwer zu erkennen sind dies die benötigten Klassen um einen TCP-Client zu starten und diesen mit einem Server zu verbinden. Eine Hälfte wäre also gefunden.
Allerdings finde ich keine vergleichbaren Scripte für einen Server. Ich habe tatsächlich Stunden damit verbracht und verschiedene Ansätze verfolgt wie ich zwei Computer nur über den RPG-Maker verbinden kann ohne einen externen Server zu verwenden. Ohne Erfolg versteht sich, sonst würde ich nun nicht hier um Hilfe bitten.
Ich weis nicht in welcher Schwierigkeitsstufe sich diese Bitte bewegt, ich sehe, die Klassen für die Clientverbindung lassen sich in überschaubarem geringen Aufwand erstellen, ich weis auch, dass soetwas mit dem RPG-Maker 2000 (DestinyPatch) möglich ist.
Falls mir also irgendjemand bei diesem Problem helfen kann, sprich eine Schnittstelle zwischen den nötigen WindowsAPI's und dem Ruby Interpreter des Makers bereitstellen so wäre ich sehr sehr dankbar.
Selbstverständlich würde ein Creditseintrag bei jedem Spiel welches die Scripte verwendet gesichert sein und ich würde die Scripte auch bereitwillig jedem Interessenten zur Verfügung stellen so wie sie mir gegeben worden sind.
Danke nocheinmal im Vorraus,
Cornix.