Official Soldat Forums
Soldat Fans => Developers Corner => Topic started by: LORD KILLA on May 15, 2010, 10:18:58 am
-
Hi everyone, just posting this becouse there are very less implementations into really needed languages like
C++, C# or VB and tons for the normal REFRESH packet
Please post your parser, and I'll add it into here. ::)
Aviable implementations:
PHP: Soldat Wiki #1 (http://devs.soldat.pl/wiki/index.php?title=Refreshx#PHP) / Soldat Wiki #2 (http://devs.soldat.pl/wiki/index.php?title=Refreshx#PHP_Class)
PHP: Pastebin (http://pastebin.com/3jZegXYC) / Attachment (http://forums.soldat.pl/index.php?action=dlattach;topic=38202.0;attach=25086) updated by ramirez (2.7.0+ support)
Ruby (http://devs.soldat.pl/wiki/index.php?title=Refreshx#Ruby_.28Possibly_not_working.29)
Haskell (http://devs.soldat.pl/wiki/index.php?title=Refreshx#Haskell)
C++ (http://pastebin.com/Hp1cMTxP) by zakath
-
http://pastebin.com/Hp1cMTxP
-
Here is an updated version of PHP (http://devs.soldat.pl/wiki/index.php?title=Refreshx#PHP)-example (by ramirez)
http://pastebin.com/3jZegXYC
added 2.7.0+ support
-
Here is my REFRESHX parser for Python. Works for 2.6.5 and should work for 2.7.0, although I dont have a 2.7.0 server to test on so Im just guessing there really. This is ripped right out of my gather bot Im working on right now.
Edited out codepad link in case it expires as well.
#===============================================================================
def parse(self,server=0,version=265):
#===============================================================================
'''Returns class Refresh() with all of the parsed information'''
self.SolSock[server].send("REFRESHX\r\n")
self.SolSock[server].recv(10)##Recieve the command first.
##Then the packet.
if version == 265:
packed = self.SolSock[server].recv(1608)
refreshx = struct.unpack('= 800B 32B 32H 32B 32H 32l 32B 32B 32B 32B 32B 32f 32f ffff HHHH 17B 2l H 3B B 17B',packed)
##offsets for parsing
offset = [25,800,832,864,896,928,960,992,1120,1152,1184,1185,1186,
1187,1188,1192,1209,1210,1211,1212,1213,1214,1215,1216]
if version == 270:
packed = self.SolSock[server].recv(1992)
##Assuming HWID is an unsigned char, will parse as such
refreshx = struct.unpack('= 800B 32B 32H 32B 32H 32l 32B 32B 32B 32B 32B 32f 32f 384B ffff HHHH 17B 2l H 3B B 17B',packed)
##Change the offsets here, and add HWID offset at the end,
##so none of the other code gets broken or needs to be changed.
offset = [25,800,832,864,896,928,960,992,1120,1152,1568,1567,1568,
1569,1570,1574,1591,1592,1593,1594,1595,1596,1597,1598,1184]
self.refresh = Refresh()
for i in range(32):
temp = ""
nicklen = refreshx[offset[0]*i]
if nicklen > 0:
for x in range(nicklen):
if x == 0:
temp += chr(refreshx[offset[0]*i+1])
else:
temp += chr(refreshx[offset[0]*i+x+1])
self.refresh.names.append(temp)
self.refresh.teams.append(refreshx[offset[1]+i])
self.refresh.kills.append(refreshx[offset[2]+i])
self.refresh.caps.append(refreshx[offset[3]+i])
self.refresh.deaths.append(refreshx[offset[4]+i])
self.refresh.pings.append(refreshx[offset[5]+i])
self.refresh.ids.append(refreshx[offset[6]+i])
t=""
for j in range(4):
t+=str(refreshx[offset[7]+i+j])+"."
t.rstrip('.')
self.refresh.ips.append(t)
self.refresh.xlocs.append(refreshx[offset[8]+i])
self.refresh.ylocs.append(refreshx[offset[9]+i])
if version == 270:
t=""
for j in range(12):
##Assuming HWID is an unsigned byte
##Parsing it as a unicode char
t+=chr(refreshx[offset[23]+i+j])
self.refresh.HWIDs.append(t)
self.refresh.redFX = refreshx[offset[10]]
self.refresh.redFY = refreshx[offset[11]]
self.refresh.blueFX = refreshx[offset[12]]
self.refresh.blueFY = refreshx[offset[13]]
for i in range(4):
self.refresh.scores.append(refreshx[offset[14]+i])
temp = ""
maplen = refreshx[offset[15]]
maplen = int(maplen)
for i in range(maplen):
temp += chr(refreshx[offset[15]+i+1])
self.refresh.map = temp
self.refresh.limit = refreshx[offset[16]]
self.refresh.timeleft = refreshx[offset[17]]
self.refresh.games = refreshx[offset[18]]
self.refresh.maxp = refreshx[offset[19]]
self.refresh.maxs = refreshx[offset[20]]
self.refresh.passw = refreshx[offset[21]]
temp = ""
maplen = refreshx[offset[22]]
maplen = int(maplen)
for i in range(maplen):
temp += chr(refreshx[offset[22]+i+1])
self.refresh.nexm = temp
return(self.refresh)
class Refresh():
def __init__(self):
self.names = []
self.teams = []
self.kills = []
self.caps = []
self.deaths = []
self.pings = []
self.ids = []
self.ips = []
self.xlocs = []
self.ylocs = []
self.HWIDs = []
self.redFX = None
self.redFY = None
self.blueFX = None
self.blueFY = None
self.scores = []
self.map = None
self.timemax = None
self.timeleft = None
self.limit = None
self.games = None
self.maxp = None
self.maxs = None
self.passw = None
self.nextm = None
-
Do pastebin posts ever expire? If so they should be copied into the posts here or attached as text/.pl/.php/.cpp/whatever files.
-
Updated version for 1.5.1
#ifndef _H_SOLDATINFOX_
#define _H_SOLDATINFOX_
// Comment out this line if you want to compile for 1.5.1
//#define OLDSOLDAT
// soldatinfo.h originally by ramirez
// modified constructor to 'default'
// defined REFRESH parsing as a method (for multiple acc)
#include <vector>
#include <string>
#include <sstream>
#include <stdexcept>
#ifndef OLDSOLDAT
#define REFRESHX_PACKET_SIZE 1992
#else
#define REFRESHX_PACKET_SIZE 1608
#endif
struct playerX
{
unsigned char namelen; // 1
char name[25]; // 24
unsigned char hwidlen; // 1
char hwid[12]; // 11
unsigned char team; // 1
unsigned short kills; // 2
unsigned char caps; // 1
unsigned short deaths; // 2
signed long ping; // 4
unsigned char id; // 1
unsigned char ip[4]; // 4
float x; // 4
float y; // 4
// 1 + 24 + 1 + 2 + 1 + 2 + 4 + 1 + 4 + 4 + 4 = 48
};
struct refreshX
{
struct playerX players[32];
float redflagx;
float redflagy;
float blueflagx;
float blueflagy;
unsigned short alphascore;
unsigned short bravoscore;
unsigned short charliescore;
unsigned short deltascore;
unsigned char currentmaplen;
char currentmap[17];
unsigned long timelimit;
unsigned long timeleft;
unsigned int limit;
unsigned char gamestyle;
unsigned char maxplayers;
unsigned char maxspectators;
unsigned char password;
unsigned char nextmaplen;
char nextmap[17];
bool check;
};
// players * 32
/*
# Player (1856 Bytes)
* Names (32*25 Bytes; first Byte (unsigned char) indicates length of the nick)
* Tagid (32*10 Bytes; char)
* Teams (32*1 Byte; 0=DM Team, 1..4=Alpha..Delta, 5=Spectator)
* Kills (32*2 Bytes; unsigned short)
* Caps (32*1 Byte; unsigned char)
* Deaths (32*2 Bytes; unsigned short)
* Pings (32*4 Bytes; signed long)
* IDs (32*1 Byte; unsigned char)
* IPs (32*4 Bytes; each byte can be decoded as unsigned char then put together in the given order to a 0.0.0.0 format; or unpack as unsigned long (big endian) and use long2ip())
* X Locations (32*4 Bytes; float)
* Y Locations (32*4 Bytes; float)
*/
#ifndef OLDSOLDAT
#define XNAMELEN_OFFSET 0
#define XNAMELEN_SIZE 1
#define XNAME_OFFSET 1
#define XNAME_SIZE 24
#define XHWIDLEN_OFFSET 25*32
#define XHWIDLEN_SIZE 1
#define XHWID_OFFSET 1
#define XHWID_SIZE 11
#define XTEAM_OFFSET 37*32
#define XTEAM_SIZE 1
#define XKILLS_OFFSET 38*32
#define XKILLS_SIZE 2
#define XCAPS_OFFSET 49*32
#define XCAPS_SIZE 1
#define XDEATHS_OFFSET 41*32
#define XDEATHS_SIZE 2
#define XPINGS_OFFSET 43*32
#define XPINGS_SIZE 4
#define XID_OFFSET 47*32
#define XID_SIZE 1
#define XIP_OFFSET 48*32
#define XIP_SIZE 4
#define XLOCX_OFFSET 52*32
#define XLOCX_SIZE 4
#define XLOCY_OFFSET 56*32
#define XLOCY_SIZE 4
// Rest
/*
# Red Flag X Location (4 Bytes; float)
# Red Flag Y Location (4 Bytes; float)
# Blue Flag X Location (4 Bytes; float)
# Blue Flag Y Location (4 Bytes; float)
# Team Scores (4*2 Bytes; unsigned short)
# Map Name (17 Bytes; first Byte (unsigned char) indicates length)
# Time Limit (4 Bytes; unsigned long; in Ticks)
# Time Left (4 Bytes; unsigned long; in Ticks)
# Cap/Kill Limit (2 Bytes; unsigned short)
# Gamestyle (1 Byte; unsigned char; 0=DM, 1=PM, 2=TM, 3=CTF, 4=RM, 5=INF, 6=HTF)
# Max Players (1 Byte; unsigned char)
# Max Spectators (1 Byte; unsigned char)
# Game Passworded? (1 Byte; boolean)
# Next Map (17 Bytes; first Byte (unsigned char) indicates length)
*/
#define XREDFLAGX_OFFSET 1920
#define XREDFLAGX_SIZE 4
#define XREDFLAGY_OFFSET 1924
#define XREDFLAGY_SIZE 4
#define XBLUEFLAGX_OFFSET 1928
#define XBLUEFLAGX_SIZE 4
#define XBLUEFLAGY_OFFSET 1932
#define XBLUEFLAGY_SIZE 4
#define XALPHATEAMSCORE_OFFSET 1936
#define XALPHATEAMSCORE_SIZE 2
#define XBRAVOTEAMSCORE_OFFSET 1938
#define XBRAVOTEAMSCORE_SIZE 2
#define XCHARLIETEAMSCORE_OFFSET 1940
#define XCHARLIETEAMSCORE_SIZE 2
#define XDELTATEAMSCORE_OFFSET 1942
#define XDELTATEAMSCORE_SIZE 2
#define XCURRENTMAPLEN_OFFSET 1944
#define XCURRENTMAPLEN_SIZE 1
#define XCURRENTMAP_OFFSET 1945
#define XCURRENTMAP_SIZE 16
#define XTIMELIMIT_OFFSET 1961
#define XTIMELIMIT_SIZE 4
#define XTIMELEFT_OFFSET 1965
#define XTIMELEFT_SIZE 4
#define XLIMIT_OFFSET 1969
#define XLIMIT_SIZE 2
#define XGAMESTYLE_OFFSET 1971
#define XGAMESTYLE_SIZE 1
#define XMAXPLAYERS_OFFSET 1972
#define XMAXPLAYERS_SIZE 1
#define XMAXSPECTATORS_OFFSET 1973
#define XMAXSPECTATORS_SIZE 1
#define XPASSWORD_OFFSET 1974
#define XPASSWORD_SIZE 1
#define XNEXTMAPLEN_OFFSET 1975
#define XNEXTMAPLEN_SIZE 1
#define XNEXTMAP_OFFSET 1976
#define XNEXTMAP_SIZE 16
#else
// players * 32
/*
# Player (1536 Bytes)
* Names (32*25 Bytes; first Byte (unsigned char) indicates length of the nick)
* hwid (32*12 Bytes; first Byte (unsigned char) indicates length of the nick)
* Teams (32*1 Byte; 0=DM Team, 1..4=Alpha..Delta, 5=Spectator)
* Kills (32*2 Bytes; unsigned short)
* Caps (32*1 Byte; unsigned char)
* Deaths (32*2 Bytes; unsigned short)
* Pings (32*4 Bytes; signed long)
* IDs (32*1 Byte; unsigned char)
* IPs (32*4 Bytes; each byte can be decoded as unsigned char then put together in the given order to a 0.0.0.0 format; or unpack as unsigned long (big endian) and use long2ip())
* X Locations (32*4 Bytes; float)
* Y Locations (32*4 Bytes; float)
*/
#define XNAMELEN_OFFSET 0
#define XNAMELEN_SIZE 1
#define XNAME_OFFSET 1
#define XNAME_SIZE 24
#define XTEAM_OFFSET 25*32
#define XTEAM_SIZE 1
#define XKILLS_OFFSET 26*32
#define XKILLS_SIZE 2
#define XCAPS_OFFSET 28*32
#define XCAPS_SIZE 1
#define XDEATHS_OFFSET 29*32
#define XDEATHS_SIZE 2
#define XPINGS_OFFSET 31*32
#define XPINGS_SIZE 4
#define XID_OFFSET 35*32
#define XID_SIZE 1
#define XIP_OFFSET 36*32
#define XIP_SIZE 4
#define XLOCX_OFFSET 40*32
#define XLOCX_SIZE 4
#define XLOCY_OFFSET 44*32
#define XLOCY_SIZE 4
// Rest
/*
# Red Flag X Location (4 Bytes; float)
# Red Flag Y Location (4 Bytes; float)
# Blue Flag X Location (4 Bytes; float)
# Blue Flag Y Location (4 Bytes; float)
# Team Scores (4*2 Bytes; unsigned short)
# Map Name (17 Bytes; first Byte (unsigned char) indicates length)
# Time Limit (4 Bytes; unsigned long; in Ticks)
# Time Left (4 Bytes; unsigned long; in Ticks)
# Cap/Kill Limit (2 Bytes; unsigned short)
# Gamestyle (1 Byte; unsigned char; 0=DM, 1=PM, 2=TM, 3=CTF, 4=RM, 5=INF, 6=HTF)
# Max Players (1 Byte; unsigned char)
# Max Spectators (1 Byte; unsigned char)
# Game Passworded? (1 Byte; boolean)
# Next Map (17 Bytes; first Byte (unsigned char) indicates length)
*/
#define XREDFLAGX_OFFSET 1536
#define XREDFLAGX_SIZE 4
#define XREDFLAGY_OFFSET 1540
#define XREDFLAGY_SIZE 4
#define XBLUEFLAGX_OFFSET 1544
#define XBLUEFLAGX_SIZE 4
#define XBLUEFLAGY_OFFSET 1548
#define XBLUEFLAGY_SIZE 4
#define XALPHATEAMSCORE_OFFSET 1552
#define XALPHATEAMSCORE_SIZE 2
#define XBRAVOTEAMSCORE_OFFSET 1554
#define XBRAVOTEAMSCORE_SIZE 2
#define XCHARLIETEAMSCORE_OFFSET 1556
#define XCHARLIETEAMSCORE_SIZE 2
#define XDELTATEAMSCORE_OFFSET 1558
#define XDELTATEAMSCORE_SIZE 2
#define XCURRENTMAPLEN_OFFSET 1560
#define XCURRENTMAPLEN_SIZE 1
#define XCURRENTMAP_OFFSET 1561
#define XCURRENTMAP_SIZE 16
#define XTIMELIMIT_OFFSET 1577
#define XTIMELIMIT_SIZE 4
#define XTIMELEFT_OFFSET 1581
#define XTIMELEFT_SIZE 4
#define XLIMIT_OFFSET 1585
#define XLIMIT_SIZE 2
#define XGAMESTYLE_OFFSET 1587
#define XGAMESTYLE_SIZE 1
#define XMAXPLAYERS_OFFSET 1588
#define XMAXPLAYERS_SIZE 1
#define XMAXSPECTATORS_OFFSET 1589
#define XMAXSPECTATORS_SIZE 1
#define XPASSWORD_OFFSET 1590
#define XPASSWORD_SIZE 1
#define XNEXTMAPLEN_OFFSET 1591
#define XNEXTMAPLEN_SIZE 1
#define XNEXTMAP_OFFSET 1592
#define XNEXTMAP_SIZE 16
#endif
class SoldatInfoX
{
public:
struct refreshX packet;
SoldatInfoX(void)
{
memset(&packet, '\0', sizeof(struct refreshX));
}
SoldatInfoX(char * buffer)
{
memset(&packet, '\0', sizeof(struct refreshX));
int loop=0;
for(loop=0;loop < 32;loop++)
{
// name length
memcpy(&packet.players[loop].namelen,buffer+(loop*(XNAME_SIZE+XNAMELEN_SIZE)+XNAMELEN_OFFSET), XNAMELEN_SIZE);
// name
memcpy(&packet.players[loop].name,buffer+(loop*(XNAME_SIZE+XNAMELEN_SIZE)+XNAME_OFFSET), XNAME_SIZE);
#ifndef OLDSOLDAT
// hwid length
memcpy(&packet.players[loop].hwidlen,buffer+(loop*(XHWID_SIZE+XHWIDLEN_SIZE)+XHWIDLEN_OFFSET), XHWIDLEN_SIZE);
// hwid
memcpy(&packet.players[loop].hwid,buffer+(loop*(XHWID_SIZE+XHWIDLEN_SIZE)+XHWID_OFFSET+XHWIDLEN_OFFSET), XHWID_SIZE);
#endif
// team
memcpy(&packet.players[loop].team,buffer+(loop*XTEAM_SIZE+XTEAM_OFFSET), XTEAM_SIZE);
// kills
memcpy(&packet.players[loop].kills,buffer+(loop*XKILLS_SIZE+XKILLS_OFFSET), XKILLS_SIZE);
// caps
memcpy(&packet.players[loop].caps,buffer+(loop*XCAPS_SIZE+XCAPS_OFFSET), XCAPS_SIZE);
// Deaths
memcpy(&packet.players[loop].deaths,buffer+(loop*XDEATHS_SIZE+XDEATHS_OFFSET), XDEATHS_SIZE);
// ping
memcpy(&packet.players[loop].ping,buffer+(loop*XPINGS_SIZE+XPINGS_OFFSET), XPINGS_SIZE);
// id
memcpy(&packet.players[loop].id,buffer+(loop*XID_SIZE+XID_OFFSET), XID_SIZE);
// ip
memcpy(&packet.players[loop].ip,buffer+(loop*XIP_SIZE+XIP_OFFSET), XIP_SIZE);
// X location
memcpy(&packet.players[loop].x,buffer+(loop*XLOCX_SIZE+XLOCX_OFFSET), XLOCX_SIZE);
// y location
memcpy(&packet.players[loop].y,buffer+(loop*XLOCY_SIZE+XLOCY_OFFSET), XLOCY_SIZE);
}
// red flag x
memcpy(&packet.redflagx,buffer+(XREDFLAGX_OFFSET), XREDFLAGX_SIZE);
// red flag y
memcpy(&packet.redflagx,buffer+(XREDFLAGY_OFFSET), XREDFLAGY_SIZE);
// blue flag x
memcpy(&packet.blueflagx,buffer+(XBLUEFLAGX_OFFSET), XBLUEFLAGX_SIZE);
// blue flag y
memcpy(&packet.blueflagx,buffer+(XBLUEFLAGY_OFFSET), XBLUEFLAGY_SIZE);
// Alpha team score
memcpy(&packet.alphascore,buffer+(XALPHATEAMSCORE_OFFSET), XALPHATEAMSCORE_SIZE);
// Bravo team score
memcpy(&packet.bravoscore,buffer+(XBRAVOTEAMSCORE_OFFSET), XBRAVOTEAMSCORE_SIZE);
// Charlie team score
memcpy(&packet.charliescore,buffer+(XCHARLIETEAMSCORE_OFFSET), XCHARLIETEAMSCORE_SIZE);
// Delta team score
memcpy(&packet.deltascore,buffer+(XDELTATEAMSCORE_OFFSET), XDELTATEAMSCORE_SIZE);
// Current map length
memcpy(&packet.currentmaplen,buffer+(XCURRENTMAPLEN_OFFSET), XCURRENTMAPLEN_SIZE);
// Current map
memcpy(&packet.currentmap,buffer+(XCURRENTMAP_OFFSET), XCURRENTMAP_SIZE);
// Time limit
memcpy(&packet.timelimit,buffer+(XTIMELIMIT_OFFSET), XTIMELIMIT_SIZE);
// Time left
memcpy(&packet.timeleft,buffer+(XTIMELEFT_OFFSET), XTIMELEFT_SIZE);
// Cap/kill limit
memcpy(&packet.limit,buffer+(XLIMIT_OFFSET), XLIMIT_SIZE);
// Game style
memcpy(&packet.gamestyle,buffer+(XGAMESTYLE_OFFSET), XGAMESTYLE_SIZE);
// Max Players
memcpy(&packet.maxplayers,buffer+(XMAXPLAYERS_OFFSET), XMAXPLAYERS_SIZE);
// Max Spectators
memcpy(&packet.maxspectators,buffer+(XMAXSPECTATORS_OFFSET), XMAXSPECTATORS_SIZE);
// Password ?
memcpy(&packet.password,buffer+(XPASSWORD_OFFSET), XPASSWORD_SIZE);
// Next map length
memcpy(&packet.nextmaplen,buffer+(XNEXTMAPLEN_OFFSET), XNEXTMAPLEN_SIZE);
// Next map
memcpy(&packet.nextmap,buffer+(XNEXTMAP_OFFSET), XNEXTMAP_SIZE);
// internal check we will set check to false if it fails otherwise true
packet.check = true;
if(packet.limit > 65535)
packet.check = false;
if(packet.gamestyle > 6)
packet.check = false;
if(packet.maxplayers > 32)
packet.check = false;
if(packet.nextmaplen > 16)
packet.check = false;
if(packet.currentmaplen > 16)
packet.check = false;
}
};
#endif
-
This PHP snippet (http://devs.soldat.pl/wiki/index.php?title=Refreshx#PHP) gives me some issues:
errors:
Warning: unpack() [function.unpack]: Type C: not enough input, need 1, have 0 in D:\...\refreshx.php on line 169
Warning: unpack() [function.unpack]: Type v: not enough input, need 2, have 0 in D:\...\refreshx.php on line 171
line 169:
$map = unpack('Clen/A16name', substr($packet, $pos, 17)); $pos += 17;
line 171:
$limit = unpack('v', substr($packet, $pos, 2)); $pos += 2;
testing it locally on both server 2.6.5 and 2.7.0. i'm just using the test code provided
-
REFRESHX parser for Ruby. Works on v.2.7.3.
module Soldat
class PlayerStat
def initialize()
@name = ''
@hwid = ''
@team = 0
@kill = 0
@flag = 0
@death = 0
@ping = 0
@id = 0
@ips = Array.new( 4, 0 )
@x = 0
@y = 0
end
attr_accessor :name, :hwid, :team, :kill, :flag, :death, :ping, :id, :ips, :x, :y
def ip
return @ips.join( '.' )
end
end
class FlagXY
def initialize()
@x = 0
@y = 0
end
attr_accessor :x, :y
end
class RefreshX
def initialize( refreshx )
raise unless refreshx.size == 1992
info = refreshx.unpack( 'CA24'*32 + 'CA11'*32 + 'C32S32C32S32L32C32' + 'C32'*4 + 'e32e32eeeeS4CA16llSCCCCCA16' )
@players = Array.new( 32, {} )
32.times do |i|
@players[i] = PlayerStat.new
@players[i].name = info[2*i+1].to_s[0, info[2*i]]
@players[i].hwid = info[2*i+65].to_s[0, info[2*i+64]]
@players[i].team = info[i+128]
@players[i].kill = info[i+160]
@players[i].flag = info[i+192]
@players[i].death = info[i+224]
@players[i].ping = info[i+256]
@players[i].id = info[i+288]
4.times do |j|
@players[i].ips[j] = info[i*4+j+320]
end
@players[i].x = info[i+448]
@players[i].y = info[i+480]
end
@redflag = FlagXY.new
@redflag.x = info[512]
@redflag.y = info[513]
@blueflag = FlagXY.new
@blueflag.x = info[514]
@blueflag.y = info[515]
@teamscore = Array.new( 4, 0 )
4.times do |i|
@teamscore[i] = info[i+516]
end
@mapname = info[521].to_s[0, info[520]]
@timelimit = info[522]
@currenttime = info[523]
@scorelimit = info[524]
@gamestyle = info[525]
@maxplayers = info[526]
@maxspectators = info[527]
@passworded = info[528]
@nextmap = info[530].to_s[0, info[529]]
end
attr_reader :players, :redflag, :blueflag, :teamscore, :mapname, :timelimit, :currenttime, :scorelimit, :gamestyle, :maxplayers, :maxspectators, :passworded, :nextmap
end
end
-
In case somebody needs a FPC (most likely in use for Lazarus) REFRESHX parser.
type
playerX = record
namelen: byte;
name: Array[1..24] of char;
tagidlen: byte;
tagid: Array[1..11] of char;
team: byte;
kills: word;
caps: byte;
deaths: word;
ping: cardinal;
id: byte;
ip: Array[1..4] of byte;
x: single;
y: single;
end;
type
refreshX = record
players: Array[0..31] of playerX;
redflagx: single;
redflagy: single;
blueflagx: single;
blueflagy: single;
alphascore: word;
bravoscore: word;
charliescore: word;
deltascore: word;
currentmaplen: byte;
currentmap: Array[1..16] of char;
timelimit: longint;
timeleft: longint;
limit: byte;
gamestyle: byte;
maxplayers: byte;
maxspectators: byte;
password: byte;
nextmaplen: byte;
nextmap: Array[1..16] of char;
end;
var
packet: ^refreshX;
procedure RefreshX(buffer: array of byte);
var
i: byte;
begin
GetMem(packet,sizeof(refreshX));
for i := 0 to 31 do begin
move(buffer[i*25],packet^.players[i].namelen, 1);
move(buffer[i*25+1],packet^.players[i].name, 24);
move(buffer[i+800],packet^.players[i].tagidlen, 1);
move(buffer[i*12+801], packet^.players[i].tagid, 11);
move(buffer[i+1184], packet^.players[i].team, 1);
move(buffer[i*2+1216], packet^.players[i].kills, 2);
move(buffer[i+1280], packet^.players[i].caps, 1);
move(buffer[i*2+1312], packet^.players[i].deaths, 2);
move(buffer[i*4+1376], packet^.players[i].ping, 4);
move(buffer[i+1504], packet^.players[i].id, 1);
move(buffer[i*4+1536], packet^.players[i].ip, 4);
move(buffer[i*4+1664], packet^.players[i].x, 4);
move(buffer[i*4+1792], packet^.players[i].y, 4);
end;
move(buffer[1920], packet^.redflagx, 4);
move(buffer[1924], packet^.redflagy, 4);
move(buffer[1928], packet^.blueflagx, 4);
move(buffer[1932], packet^.blueflagy, 4);
move(buffer[1936], packet^.alphascore, 2);
move(buffer[1938], packet^.bravoscore, 2);
move(buffer[1940], packet^.charliescore, 2);
move(buffer[1942], packet^.deltascore, 2);
move(buffer[1944], packet^.currentmaplen, 1);
move(buffer[1945], packet^.currentmap, 16);
move(buffer[1961], packet^.timelimit, 4);
move(buffer[1965], packet^.timeleft, 4);
move(buffer[1969], packet^.limit, 2);
move(buffer[1971], packet^.gamestyle, 1);
move(buffer[1972], packet^.maxplayers, 1);
move(buffer[1973], packet^.maxspectators, 1);
move(buffer[1974], packet^.password, 1);
move(buffer[1975], packet^.nextmaplen, 1);
move(buffer[1976], packet^.nextmap, 16);
end;
Edit: Edited the code a bit. So you call the procedure now with the packet.