You know what I forgot about InSim relay. Oh dear, I wonder what's wrong with my brain sometimes.... eh, maybe I shouldn't go there . I will add support for it before 1.6 goes final, as it will be nice to get it in.
"""Example 13: InSim Relay
This example demonstrates how to use InSim Relay. We connect to the relay,
request a list of hosts, select a random one, and then print out its
connection list.
"""
import pyinsim
import random
# List of hosts.
hosts = []
# Check if host is populated and does not require a spectator pass, then
# add to hosts list.
def hostList(isr, hos):
global hosts
for host in hos.Hosts:
if host.NumConns > 1 and not host.Flags & pyinsim.HOS_SPECPASS:
hosts.append(host.HName)
# Print out the error message.
def relayError(isr, err):
print 'InSim Relay error:', pyinsim.irerr(err.ErrNo)
# Print out the name and UCID of the connection.
def newConn(isr, ncn):
print 'New connection, UName %s (%d)' % (ncn.UName, ncn.UCID)
# Request for all connections to be sent.
def requestConns(isr):
isr.send(pyinsim.ISP_TINY, SubT=pyinsim.TINY_NCN, ReqI=1)
# Select a random host from the hosts list.
def selectHost(isr):
host = pyinsim.stripColours(random.choice(hosts))
print 'Selecting host:', host
isr.send(pyinsim.IRP_SEL, HName=host)
# Request connections after 2 seconds.
isr.timer(requestConns, 2)
# Create new InSimRelay object and bind events.
isr = pyinsim.InSimRelay()
isr.bind(pyinsim.IRP_HOS, hostList)
isr.bind(pyinsim.IRP_ERR, relayError)
isr.bind(pyinsim.ISP_NCN, newConn)
try:
# Initialise InSimRelay.
isr.init()
# Request host list.
isr.send(pyinsim.IRP_HLR)
# Select host after 5 seconds.
isr.timer(selectHost, 5)
except pyinsim.InSimError as err:
print 'Error:', err
def stripColours(lfsStr):
"""Strip colour codes (^1, ^3 etc..) from a string.
@type lfsStr: string
@param lfsStr: The string to strip.
@rtype: string
@return: The string sans colour codes.
"""
return _COLOUR_REGEX.sub('', lfsStr)
>>> class SlotsTest:
__slots__=['a','b']
>>> st = SlotsTest()
>>> st.c = 1
>>>
>>> class SlotsTest(object):
__slots__=['a','b']
>>> st = SlotsTest()
>>> st.c = 1
Traceback (most recent call last):
File "<pyshell#63>", line 1, in <module>
st.c = 1
AttributeError: 'SlotsTest' object has no attribute 'c'
>>>
"""Example 15: Cruise
A simple cruise server. As you drive you earn cash, which can be spent on buying
and selling cars. User data is stored as pickled Python objects in the
data\cruise folder, and is retrieved and stored when players join and leave the
host. There are several chat commands such as !prices, !buy, !sell, !cars and
!help, plus an onscreen display which shows the players current cash and their
total kilometers driven.
"""
# Make sure correct version of pyinsim is imported.
VERSION = '1.6.4'
try:
import pyinsim
if not pyinsim.version(VERSION):
raise ImportError
except ImportError:
print 'You must install pyinsim %s or better' % VERSION
import sys
sys.exit(1)
# Dependencies.
import cPickle
import os
# Constants.
HOST = 'localhost'
PORT = 29999
PREFIX = '!'
UDPPORT = 30000
INTERVAL = 500 # Milliseconds
PROG_NAME = '^7pyCruise'
CASH_MULTIPLIER = 2 # Dollars per second
STARTING_CARS = ['UF1',]
STARTING_CASH = 1000 # Dollars
HEARTBEAT_INTERVAL = 1 # Seconds
USER_DIR = 'data\\cruise'
HOST_ID = 0
SPEED_DEADZONE = 10
CAR_PRICES = {'XFG': 4500, 'XRG': 6000, 'FBM': 150000, 'XRT': 14000, 'RB4': 12000,
'FXO': 12000, 'LX4': 15000, 'LX6': 25000, 'MRT': 30000,'UF1': 3000,
'RAC': 30000, 'FZ5': 38000, 'XFR': 50000, 'UFR': 45000, 'FOX': 150000,
'FO8': 165000, 'BF1': 350000, 'FXR': 120000, 'XRR': 120000, 'FZR': 130000}
# Global variables.
connections = {}
players = {}
insim = pyinsim.InSim()
# Class to store user info.
class UserVars:
def __init__(self):
self.last_pos = ()
self.dist = 0
self.cash = STARTING_CASH
self.cars = STARTING_CARS
self.on_track = False
# Draw on-screen display.
def draw_osd(ncn):
insim.send(pyinsim.ISP_BTN, ReqI=1, UCID=ncn.UCID, ClickID=1,
BStyle=pyinsim.ISB_DARK, T=4, L=85, W=30, H=6,
Text='Cash: $%d | Distance: %.2f Km' % (ncn.vars.cash, ncn.vars.dist))
# Called every second to update cash and OSD.
def heartbeat(insim):
for ncn in connections.values():
if ncn.UCID != HOST_ID:
if ncn.vars.on_track:
ncn.vars.cash += CASH_MULTIPLIER
draw_osd(ncn)
insim.timer(heartbeat, HEARTBEAT_INTERVAL)
# Load user info from file.
def load_user_vars(uname):
path = os.path.join(USER_DIR, uname)
if os.path.exists(path):
try:
with open(path, 'r') as f:
return cPickle.load(f)
except IOError as err:
print 'Load Error:', err
return UserVars() # Default
# Save user info to file.
def save_user_vars(uname, vars):
path = os.path.join(USER_DIR, uname)
try:
with open(path, 'w') as f:
cPickle.dump(vars, f)
except IOError as err:
print 'Save Error:', err
# Request all connections and players to be sent.
def req_conns():
insim.send(pyinsim.ISP_TINY, ReqI=1, SubT=pyinsim.TINY_NCN)
insim.send(pyinsim.ISP_TINY, ReqI=1, SubT=pyinsim.TINY_NPL)
# New connection joined host
def new_conn(insim, ncn):
if ncn.UCID != HOST_ID:
ncn.vars = load_user_vars(ncn.UName)
connections[ncn.UCID] = ncn
# Connection left host.
def conn_left(insim, cnl):
if cnl.UCID != HOST_ID:
ncn = connections[cnl.UCID]
save_user_vars(ncn.UName, ncn.vars)
del connections[cnl.UCID]
# Player tries to join track.
def new_ply(insim, npl):
players[npl.PLID] = npl
ncn = connections[npl.UCID]
if npl.CName in ncn.vars.cars:
ncn.vars.on_track = True
else:
insim.sendm('/spec %s' % ncn.UName)
insim.sendm('^3| ^7You do not own the %s' % npl.CName, ncn.UCID)
# Player leaves track.
def ply_left(insim, pll):
npl = players[pll.PLID]
ncn = connections[npl.UCID]
ncn.vars.on_track = False
del players[pll.PLID]
# Print out car prices.
def cmd_prices(ncn, args):
insim.sendm('^3| ^7Car Prices:', ncn.UCID)
for car, price in CAR_PRICES.iteritems():
insim.sendm('^3| ^7%s: $%d' % (car, price), ncn.UCID)
# Buy a new car.
def cmd_buy(ncn, args):
if args:
for arg in args:
car = arg.upper()
if car in ncn.vars.cars:
insim.sendm('^3| ^7You already own the %s' % car, ncn.UCID)
elif car not in CAR_PRICES:
insim.sendm('^3| ^7The %s does not exist' % car, ncn.UCID)
elif CAR_PRICES[car] > ncn.vars.cash:
insim.sendm('^3| ^7You do not have enough cash for the %s' % car, ncn.UCID)
else:
ncn.vars.cash -= CAR_PRICES[car]
ncn.vars.cars.append(car)
insim.sendm('^3| %s ^7bought the %s' % (ncn.PName, car))
else:
insim.sendm('^3| ^7No car selected', ncn.UCID)
# Sell an owned car.
def cmd_sell(ncn, args):
if args:
for arg in args:
car = arg.upper()
if car not in CAR_PRICES:
insim.sendm('^3| ^7The %s does not exist' % car, ncn.UCID)
elif car not in ncn.vars.cars:
insim.sendm('^3| ^7You do not own the %s' % car, ncn.UCID)
else:
ncn.vars.cash += CAR_PRICES[car]
ncn.vars.cars.remove(car)
insim.sendm('^3| %s ^7sold the %s' % (ncn.PName, car))
else:
insim.sendm('^3| ^7No car selected', ncn.UCID)
# Print list of cars owned.
def cmd_cars(ncn, args):
insim.sendm('^3| ^7Currently Owned Cars:', ncn.UCID)
for car in ncn.vars.cars:
insim.sendm('^3| ^7%s: $%d' %(car, CAR_PRICES[car]), ncn.UCID)
# Print usage info.
def cmd_help(ncn, args):
insim.sendm('^3| ^7Usage Info:', ncn.UCID)
insim.sendm('^3| !prices ^7- View car prices', ncn.UCID)
insim.sendm('^3| !buy ^7- Buy a new car', ncn.UCID)
insim.sendm('^3| !sell ^7- Sell an owned car', ncn.UCID)
insim.sendm('^3| !cars ^7- See what cars you currently own', ncn.UCID)
CMD_LOOKUP = {'prices': cmd_prices, 'buy': cmd_buy, 'sell': cmd_sell,
'cars': cmd_cars, 'help': cmd_help,}
# Handle command message from LFS.
def message_out(insim, mso):
cmd = pyinsim.parseCmd(mso)
if cmd:
ncn = connections[mso.UCID]
cmd0 = cmd[0].lower()
if cmd0 in CMD_LOOKUP:
CMD_LOOKUP[cmd0](ncn, cmd[1])
else:
insim.sendm('^3| ^7Unknown command', ncn.UCID)
# Calculate distance travelled.
def add_distance(ncn, car):
curr_pos = (car.X, car.Y, car.Z)
if ncn.vars.last_pos:
dist = pyinsim.distance(ncn.vars.last_pos, curr_pos)
ncn.vars.dist += pyinsim.metres(dist) / 1000 # Km
ncn.vars.last_pos = curr_pos
# Player MCI updates.
def car_info(insim, mci):
for car in mci.CompCars:
if car.Speed < SPEED_DEADZONE: continue
npl = players[car.PLID]
ncn = connections[npl.UCID]
add_distance(ncn, car)
# Remind to set /cruise flag.
def race_start(insim, rst):
if not rst.Flags & pyinsim.HOSTF_CRUISE:
insim.sendm('^3| ^1WARNING: NOT IN CRUISE MODE!')
insim.sendm('^3| ^1WARNING: NOT IN CRUISE MODE!')
# Save user vars if connection is lost.
def closed(insim, reason):
for ncn in connections.values():
if ncn.UCID != HOST_ID:
save_user_vars(ncn.UName, ncn)
if __name__ == '__main__':
# Bind event-handlers.
insim.bind(pyinsim.ISP_NCN, new_conn)
insim.bind(pyinsim.ISP_CNL, conn_left)
insim.bind(pyinsim.ISP_NPL, new_ply)
insim.bind(pyinsim.ISP_PLL, ply_left)
insim.bind(pyinsim.ISP_MSO, message_out)
insim.bind(pyinsim.ISP_MCI, car_info)
insim.bind(pyinsim.ISP_RST, race_start)
insim.bind(pyinsim.EVT_CLOSED, closed)
try:
# Initialise InSim.
insim.init(HOST, PORT, IName=PROG_NAME, Prefix=PREFIX, UDPPort=UDPPORT,
Flags=pyinsim.ISF_MCI, Interval=INTERVAL)
# Request players/connections.
req_conns()
# Start heartbeat timer.
insim.timer(heartbeat, HEARTBEAT_INTERVAL)
except pyinsim.Error as err:
print 'InSim Error:', err
#Change cash level
def cmd_give(ncn, args):
if args:
for arg in args:
ncn = arg.split(':')[-0]
amt = arg.split(':')[-1]
#insim.sendm('^3| ^7You are trying to send %s $%s' % (user, amt))
ncn.vars.cash += amt
insim.sendm('cash changed')
>>> Traceback (most recent call last):
File "C:\Python264\lib\site-packages\pyinsim\pyinsim.py", line 2570, in __recvThread
[self.__recv(sock) for sock in socks]
File "C:\Python264\lib\site-packages\pyinsim\pyinsim.py", line 2591, in __recv
[self.__onPacketData(pdata) for pdata in self.__buffer]
File "C:\Python264\lib\site-packages\pyinsim\pyinsim.py", line 2608, in __onPacketData
if isp: self.event(ptype, packet)
File "C:\Python264\lib\site-packages\pyinsim\pyinsim.py", line 2475, in event
[callback(self, *args) for callback in self.__callbacks[evt]]
File "C:\Users\Jonathan\Pyinsim 164 beta\examples\cruise.py", line 267, in message_out
CMD_LOOKUP[cmd0](ncn, cmd[1])
File "C:\Users\Jonathan\Pyinsim 164 beta\examples\cruise.py", line 231, in cmd_give
ncn.vars.cash += amt
AttributeError: 'str' object has no attribute 'vars'
['DarkTimes', '500']
# Get a conn from their UName
def ncn_from_uname(uname):
ncn = filter(lambda n: n.UName == uname, connections.values())
if ncn:
return ncn[0]
return None
def cmd_give(ncn, args):
# Check args are correct length.
if len(args) != 2:
insim.sendm('^3| Invalid give command', ncn.UCID)
return
# Get the uname and ncn for the user we're giving this to.
other_uname = args[0]
other_ncn = ncn_from_uname(other_uname)
if not other_ncn:
insim.sendm('^3| The user %s ^3does not exist' % other_uname, ncn.UCID)
return
# Check the amount set is a number.
if not args[1].isdigit():
insim.sendm('^3| The amount %s is not a number' % args[1], ncn.UCID)
return
# Award the amount and confirm.
amount = int(args[1])
other_ncn.vars.cash += amount
insim.sendm('^3| You have been given $%d by %s' % (amount, ncn.PName), other_ncn.UCID)
insim.sendm('^3| You have given %s^3 the amount of $%d' % (other_ncn.PName, amount), ncn.UCID)
def cmd_location(ncn, args):
if ncn.vars.on_track:
# Get XYZ and convert to meters
last_pos = ncn.vars.last_pos
x = pyinsim.meters(last_pos[0])
y = pyinsim.meters(last_pos[1])
z = pyinsim.meters(last_pos[2])
# Send message
insim.sendm('^3| Location: %d %d %d' % (x, y, z), ncn.UCID)
else:
insim.sendm('^3| You are not on track', ncn.UCID)
>>> Traceback (most recent call last):
File "C:\Python264\lib\site-packages\pyinsim\pyinsim.py", line 2570, in __recvThread
[self.__recv(sock) for sock in socks]
File "C:\Python264\lib\site-packages\pyinsim\pyinsim.py", line 2591, in __recv
[self.__onPacketData(pdata) for pdata in self.__buffer]
File "C:\Python264\lib\site-packages\pyinsim\pyinsim.py", line 2608, in __onPacketData
if isp: self.event(ptype, packet)
File "C:\Python264\lib\site-packages\pyinsim\pyinsim.py", line 2475, in event
[callback(self, *args) for callback in self.__callbacks[evt]]
File "C:\Users\Jonathan\Pyinsim 164 beta\examples\cruise.py", line 407, in message_out
CMD_LOOKUP[cmd0](ncn, cmd[1])
File "C:\Users\Jonathan\Pyinsim 164 beta\examples\cruise.py", line 174, in cmd_location
x = pyinsim.meters(last_pos[0])
AttributeError: 'module' object has no attribute 'meters'
def cmd_location(ncn, args):
if ncn.vars.on_track:
# Get XYZ and convert to meters
last_pos = ncn.vars.last_pos
x = pyinsim.metres(last_pos[0])
y = pyinsim.metres(last_pos[1])
z = pyinsim.metres(last_pos[2])
# Send message
insim.sendm('^3| Location: %d %d %d' % (x, y, z), ncn.UCID)
else:
insim.sendm('^3| You are not on track', ncn.UCID)