pywmdockapps/examples/pywmwet.py

263 lines
7.5 KiB
Python
Raw Normal View History

2024-09-08 16:50:24 -06:00
#!/usr/bin/env python
"""pywmwet.py
WindowMaker dockapp that tracks a Wolf:ET server and displays following info:
->Map Name
-># of Allies
-># of Axis
-># of Spectators (if server using 'P' cvar
Copyright (C) 2007 Nathan Lundquist
Licensed under the GNU General Public License.
Changes:
2007-01-16 Nate Lundquist
First attempt
"""
import sys, getopt, os
import socket
import wmdocklib
import time, datetime
DEFAULT_PORT = 27960
DEFAULT_INTERVAL = 60 #seconds
WIDTH = 64
HEIGHT = 64
XOFFSET = 4
YOFFSET = 4
MARGIN = 1
LINE_SPACING = 4
usage = '''\
pywmwet.py [options]
Available options are:
-h, --help Print this help text
-s, --server <server address> Server to track
-p, --port <port> Server port [default: 27960]
-u, --update-interval <seconds> Delay between updates [default: 60 sec]
'''
def parse_command_line(argv):
shorts = 'hs:p:u:'
longs = ['help', 'server=', 'port=', 'update-interval=']
try:
opts, nonOptArgs = getopt.getopt(argv[1:], shorts, longs)
except getopt.GetoptError, e:
print 'Error parsing commandline: ' + str(e)
print usage
sys.exit(2)
d = {}
for o, a in opts:
if o in ('-h', '--help'):
print usage
sys.exit(0)
if o in ('-s', '--server'):
d['server'] = a
if o in ('-p', '--port'):
d['port'] = int(a)
else:
d['port'] = DEFAULT_PORT
if o in ('-u', '--update-interval'):
d['update-interval'] = int(a)
else:
d['update-interval'] = DEFAULT_INTERVAL
return d
def query_server(server, port):
try:
query = '\xFF\xFF\xFF\xFF\x02getstatus\x0a\x00'
addr = (server, port)
sockobj = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sockobj.settimeout(4.0)
sockobj.connect(addr)
sockobj.send(query)
data = sockobj.recv(4096)
data = data[18:]
sockobj.shutdown(0)
sockobj.close()
#print 'query success'
#print data
return data
except socket.error:
#print 'query failure'
return False
def get_map(data):
data = data.split('\\')
i = data.index('mapname')
return ' '.join(data[i+1].split('_')).title()
def get_num_allies(data):
data = data.split('\\')
try: #servers using older cvar
i = data.index('Players_Allies')
allies = data[i+1]
return len(allies.split())
except ValueError: #possibly newer server using 'P' cvar
try:
#3 - Spectator, 2 - Allies, 1 - Axis
i = data.index('P')
slots = data[i+1]
allies = 0
for slot in slots:
if slot == '2':
allies += 1
return allies
except ValueError: #no players connected?
return 0
def get_num_axis(data):
data = data.split('\\')
try: #server using old cvar
i = data.index('Players_Axis')
axis = data[i+1]
return len(axis.split())
except ValueError: #possible new cvar
try:
#3 - Spectator, 2 - Allies, 1 - Axis
i = data.index('P')
slots = data[i+1]
axis = 0
for slot in slots:
if slot == '1':
axis += 1
return axis
except ValueError: #no players
return 0
def get_num_spectators(data):
#This will only work with servers that use the newer 'P' cvar
data = data.split('\\')
try:
#3 - Spectator, 2 - Allies, 1 - Axis
i = data.index('P')
slots = data[i+1]
spec = 0
for slot in slots:
if slot == '3':
spec += 1
return spec
except ValueError: #check if old cvars in use
if 'Players_Axis' in data or 'Players_Allies' in data:
#old cvars in use, so we don't know how many spectators there are
return '??'
else: #no players
return 0
def get_players(data):
players = []
player_data = data.strip().split('\n')[1:]
for player_line in player_data:
player = strip_name(player_line.split('"')[1])
players.append(player)
return players
def scroll_players(players):
pass
def strip_name(name):
stripped_name = ''
skip_next = False
for x in range(len(name)):
if name[x] != '^' and skip_next != True:
stripped_name += name[x]
elif name[x] == '^':
skip_next = True
continue
skip_next = False
return stripped_name
def scroll_text(s, y, speed):
#not sure if this is the best way to do this...
cen_pos = get_center(s)
end_pos = (cen_pos *2) - (MARGIN * 2) - 64
for x in range(WIDTH, end_pos, -1):
add_string(s, x, y)
wmdocklib.redraw()
time.sleep(speed)
def get_center(s):
return wmdocklib.getCenterStartPos(s, WIDTH, XOFFSET)
def add_string(s, x, y):
return wmdocklib.addString(s, x, y, XOFFSET, YOFFSET, WIDTH, HEIGHT)
def get_spacing(line_no):
if line_no == 1:
return MARGIN
else:
# 1 + (4) + 4
return MARGIN + (char_height * (line_no - 1)) + LINE_SPACING * (line_no - 1)
def check_for_events():
event = wmdocklib.getEvent()
while not event is None:
if event['type'] == 'destroynotify':
sys.exit(0)
event = wmdocklib.getEvent()
def main_loop(server, port, update_interval):
dif = datetime.timedelta(seconds=update_interval)
last_updated = datetime.datetime.now()
just_started = True
while 1:
check_for_events()
now = datetime.datetime.now()
if now > (last_updated + dif) or just_started == True:
data = query_server(server, port)
if not data:
add_string('Server', get_center('Server'), get_spacing(1))
add_string('Not', get_center('Not'), get_spacing(2))
add_string('Found', get_center('Found'), get_spacing(3))
just_started = False
else:
mapname = get_map(data)
num_allies = get_num_allies(data)
num_axis = get_num_axis(data)
num_specs = get_num_spectators(data)
last_updated = datetime.datetime.now()
just_started = False
if data:
add_string(('Allies:%s' % str(num_allies)), MARGIN, get_spacing(2) + 5)
add_string(('Axis:%s' % str(num_axis)), MARGIN, get_spacing(3) + 5)
add_string(('Spec:%s' % str(num_specs)), MARGIN, get_spacing(4) + 5)
#mapname last in case it has to scroll
if get_center(mapname) < MARGIN:
scroll_text(mapname, get_spacing(1), 0.04)
else:
add_string(mapname, get_center(mapname), get_spacing(1))
wmdocklib.redraw()
time.sleep(0.1)
def main():
clConfig = parse_command_line(sys.argv)
try:
program_name = sys.argv[0].split(os.sep)[-1]
except IndexError:
program_name = ''
if not clConfig.has_key('server'):
print '\nYou must supply a server using the -s/--server option.\n'
print 'Use -h flag to see more options.'
sys.exit(2)
global char_width, char_height
char_width, char_height = wmdocklib.initPixmap(font_name='5x7', fg=3)
wmdocklib.openXwindow(sys.argv, 64, 64)
try:
main_loop(clConfig['server'], clConfig['port'], clConfig['update-interval'])
except KeyboardInterrupt:
print 'Goodbye.'
sys.exit(0)
if __name__ == '__main__':
main()