; HL1 RCON control snippet by NaNg
; Date: 11-06-2011
; Tested on mIRC 7.19
;
; Remote control window for HL1 engine based games (e.g. HL, CS, TF etc.),
; based on the HL1 Rcon Protocol (no source).
;
; Usage:
; * /hlrcon <ip> <port> <pass>
; Define a prefix for sockent names.
alias -l hlrcon.prefix { return HLRcon }
; Validates arguments and challenges the game server.
alias hlrcon {
; Validate arguments (simple, no need for full validation).
if ((!$longip($1)) || ($2 !isnum 1-65536) || (!$3)) {
echo -ag Invalid parameters.
return
}
; Save the server's address.
var %server.addr = $+($1, :, $2)
; Check that the user has not opened a Rcon window for the same server already.
; This makes sure that the user won't have a Rcon step over another Rcon for the same server.
if ($window(%server.addr)) {
echo -ag Rcon window for $1 is already open! close it before trying.
return
}
; Open the Rcon window whilst activating it, with an editbox, hide the @ prefix and maximize it.
window -aek0x @ $+ %server.addr
aline 12 @ $+ %server.addr HL Rcon window. Type a command\cvar to send to the server, responses will be displayed here.
aline 12 @ $+ %server.addr Warning! commands like exit or quit will close the server! avoid using them!
; Set the socket name we'll use.
var %sockname = $+($hlrcon.prefix, %server.addr)
; Save the Rcon password.
set $+(%, $hlrcon.prefix, .rconpw., %sockname) $3
; Challenge the Rcon.
hlrcon.challengercon %sockname $1 $2
}
alias -l hlrcon.challengercon {
; Construct the challenge request query.
bset &hlrcon.challenge 1 255 255 255 255
bset -t &hlrcon.challenge 5 challenge rcon
; Open the socket and challenge the game server.
sockudp -k $$1-3 &hlrcon.challenge
}
; Read data from the game server.
on *:UDPREAD:$($+($hlrcon.prefix, *)): {
; Get the window name for the current game server.
var %hlrcon.window = $+(@, $remove($sockname, $hlrcon.prefix))
; If there were errors, $sockerr will tell us so.
; Write the error message to the window and clear the connection.
if ($sockerr) {
aline 04 %hlrcon.window * Error: Reading from socket: $sock($sockname).wsmsg
sockclose $sockname
return
}
; Read the data packet type.
sockread 4 &hlrcon.pckt.type
; Since we are not using it (and we are disregarding longer packets), drop the packet type.
bunset &hlrcon.pckt.type
; Read the rest of the data.
sockread 1400 &hlrcon.pckt.data
var %hlrcon.data = $bvar(&hlrcon.pckt.data, 1, $bvar(&hlrcon.pckt.data, 0)).text
; If Rcon challenge is received, set it.
if (challenge rcon* iswm %hlrcon.data) {
; Tokenize the received data to rows.
tokenize $asc($lf) %hlrcon.data
; Tokenize the first row to get the challenge.
tokenize 32 $1
; Save the challenge.
set $+(%, $hlrcon.prefix, .challenge., $sockname) $3
}
else {
; Ignore the first byte (for non-log responses, the response contains this extra non-sense byte).
var %hlrcon.data = $bvar(&hlrcon.pckt.data, 2, $bvar(&hlrcon.pckt.data, 0)).text
}
; Tokenize the received data to rows.
tokenize $asc($lf) %hlrcon.data
; Dispose the bvar.
bunset &hlrcon.pckt.data
; Print the given data.
aline %hlrcon.window $*
; If an error occured, display a friendly message.
if (bad challenge* iswm $1) {
hlrcon.challengercon $sockname $sock($sockname).addr $sock($sockname).port
aline 04 %hlrcon.window Bad challenge, requesting a new one. Please try again.
}
elseif (bad rcon_password* iswm $1) {
aline 04 %hlrcon.window Bad Rcon password. Please try again.
}
}
; Sends user input to the server as is.
; NOTE: Commands like exit or quit will close the server!
on *:INPUT:@: {
; Get the socket name.
var %hlrcon.socket = $+($hlrcon.prefix, $remove($target, @))
; If the input is not for the HL Rcon window, ignore it.
if ($($+(%, $hlrcon.prefix, .rconpw., %hlrcon.socket), 2) == $null) { return }
; Check if the socket is still alive.
if (!$sock(%hlrcon.socket)) {
aline 04 $target * Error: Socket is dead. Close the window and try again.
return
}
; Build the command packet and send it to the server.
bset &hlrcon.cmd 1 255 255 255 255
bset -t &hlrcon.cmd 5 rcon $($+(%, $hlrcon.prefix, .challenge., %hlrcon.socket), 2) $+(", $($+(%, $hlrcon.prefix, .rconpw., %hlrcon.socket), 2), ") $1-
aline $target -> $1-
; Send the command request.
sockudp -k %hlrcon.socket $sock(%hlrcon.socket).saddr $sock(%hlrcon.socket).sport &hlrcon.cmd
}
; If the user has closed the HL Rcon window, clear the socket.
on *:CLOSE:@: {
; Construct the sock name.
var %hlrcon.socket = $+($hlrcon.prefix, $remove($target, @))
; If the input is not for the HL Rcon window, ignore it.
if ($($+(%, $hlrcon.prefix, .rconpw., %hlrcon.socket), 2) == $null) { return }
; If there's a socket named accordingly, close it.
if ($sock(%hlrcon.socket)) {
sockclose %hlrcon.socket
}
; Clear any variables set for this socket.
unset $($+(%, $hlrcon.prefix, .*., %hlrcon.socket))
}
See also