View Full Version : Python - Pyinsim - A Python InSim Module
DarkTimes
17th April 2008, 12:48
Note: Pyinsim is written for the Python (http://www.python.org/) programming language. If you are interested in learning to program in Python, have a look at the beginners guide (http://wiki.python.org/moin/BeginnersGuide).
Pyinsim is a InSim library for the Python (http://en.wikipedia.org/wiki/Python_%28programming_language%29) programming language. It creates a socket connection with the game, in either TCP or UDP, and provides many classes, functions and enumerations for sending and receiving packets between your Python program and LFS. Python is a very compact, simple language, and Pyinsim is (hopefully) not too hard to understand or use.
Please note however that Pyinsim is not designed to hold your hand and to hide you from the inner workings of InSim. In order to use Pyinsim, you will need to refer to InSim.txt to see how packets are put together, understand what values to use where, and to understand how to use packets to communicate with the game.
It goes without saying really that you should have a semi-decent grasp of the Python programming language before you get really stuck in, but luckily Python is a relatively easy language for beginners to learn, and the fundamentals can be learned by an experienced programmer within a few hours.
There is a more detailed Pyinsim tutorial (http://www.lfsforum.net/showthread.php?t=49155) available, which is a recommended read. This page however should give someone experienced with using InSim enough to get started.
Initialising InSim
We create a new InSim object and call its Connect(host, port) method to connect to LFS. We then create a new IS_ISI InSim initialisation packet, populated with our own data, and send it to InSim.
import Pyinsim
insim = Pyinsim.InSim(Pyinsim.INSIM_TCP)
try:
insim.Connect("127.0.0.1", 29999)
except Exception, (msg):
print "Connection failed:", msg
else:
# Initialise InSim.
isi = Pyinsim.Packet(Pyinsim.ISP_ISI, Admin="Pass", IName="Pyinsim")
insim.SendP(isi)
# Keep program thread alive.
insim.Run()
finally:
insim.Close()
Hello, InSim!
We create the connection and initialise InSim, then send an MST packet to LFS, to display the words 'Hello, InSim!' on the screen.
import Pyinsim
insim = Pyinsim.InSim(Pyinsim.INSIM_TCP)
try:
insim.Connect("127.0.0.1", 29999)
except Exception, (msg):
print "Connection failed:", msg
else:
# Initialise InSim.
isi = Pyinsim.Packet(Pyinsim.ISP_ISI, Admin="Pass", IName="Pyinsim")
insim.SendP(isi)
# Hello, InSim!
mst = Pyinsim.Packet(Pyinsim.ISP_MST, Msg="Hello, InSim!")
insim.SendP(mst)
insim.Run()
finally:
insim.Close()
It's fun to note this is an entire InSim program - albeit not a very useful one. We can remove the exception handling code to shorten it further.
import Pyinsim
insim = Pyinsim.InSim()
insim.Connect("127.0.0.1", 29999)
insim.SendP(Pyinsim.Packet(Pyinsim.ISP_ISI, Admin="Pass", IName="Pyinsim"),
Packet(Pyinsim.ISP_MST, Msg="Hello, InSim!"))
insim.Run()
As you can see Pyinsim can create some extremely compact code. :)
Receiving packets:
Pyinsim uses an event driven model for incoming packets. First we create packet handling functions, then register them with the InSim object, which then calls those functions when the packets are received, passing a packet object as the parameter.
The following example establishes the connection, checks the version of InSim to make sure it's compatible, then prints out the contents of any MSO message received from LFS.
import Pyinsim
insim = Pyinsim.InSim(Pyinsim.INSIM_TCP)
# A quick version check.
def VersionCheck(ver):
if ver["InSimVer"] != Pyinsim.INSIM_VERSION:
print "Invalid version!"
insim.Close()
# Print out the MSO message.
def MessageRecieved(mso):
print "InSim Message:", mso["Msg"]
# Register the packet events.
insim.Bind({Pyinsim.ISP_VER: VersionCheck,
Pyinsim.ISP_MSO: MessageReceived})
# Connect to InSim.
try:
insim.Connect("127.0.0.1", 29999)
except Exception, (msg):
print "Connection failed:", msg
else:
insim.SendP(Pyinsim.Packet(Pyinsim.ISP_ISI, Admin="Pass", IName="Pyinsim"))
insim.Run()
finally:
insim.Close()
Receiving Packets (OOP)
It's a good point to show a more OOP way you can go about using Pyinsim, for all you multiple-paradigm haters out there ;). This is the preceding example, but recreated as a class which inherits from InSim.
from Pyinsim import *
class MyInSim(InSim):
def __init__(self, host, port, admin, iname):
InSim.__init__(self)
InSim.Bind(self, {ISP_VER: self.VersionCheck,
ISP_MSO: self.MessageReceived})
try:
InSim.Connect(self, host, port)
except Exception, (msg):
print "Connection failed:", msg
else:
InSim.SendP(self, Packet(ISP_ISI, Admin=admin, IName=iname))
InSim.Run(self)
finally:
InSim.Close(self)
def VersionCheck(self, ver):
if ver["InSimVer"] != INSIM_VERSION:
print "Invalid version!"
InSim.Close(self)
def MessageReceived(self, mso):
print "InSim Message:", mso["Msg"]
insim = MyInSim("127.0.0.1", 29999, "Pass", "Pyinsim")
View the rest of this thread and the tutorial for more examples.
Download:
You can download the latest version below. Please note that it is released under the LGPL (http://www.gnu.org/copyleft/lesser.html) license, so please read COPYING and COPYING.LESSER before you use it.
If you are a Windows user you can simply use the win32 installer included, which will install the module automatically into your Python installation. If not then you can install from the source dist included.
PyinsimTemplate.py
PyinsimTemplate is a template for Pyinsim programs, which provides a skeleton for you to add your own custom events and logic. It takes care of boring stuff, like setting up the connection and managing player and connection lists, and provides some helper functions for sending messages and the like.
Documentation
The full documentation is included as an HTML file.
the_angry_angel
17th April 2008, 13:05
Very nice work DarkTimes - lots of whitespace lovers with abnormal tab key fingers will be very happy :D The API seems straight forward, and complements that provided by LFS_External nicely.
Any objections if I move this into the libraries subforum, or are you not convinced that this is "finished"?
JamesF1
17th April 2008, 13:13
You're not going to believe this.
During the past week or so, I've been learning Python - and had started a Python InSim Module... Weird.
If you're interested in some help, I could contribute, but not so much over the next month or so.
DarkTimes
17th April 2008, 13:43
Any objections if I move this into the libraries subforum, or are you not convinced that this is "finished"?
I considered putting it in there, but really it's not finished yet, so I don't think it's ready for that.
You're not going to believe this.
During the past week or so, I've been learning Python - and had started a Python InSim Module... Weird.
If you're interested in some help, I could contribute, but not so much over the next month or so.
Hehe, awesome. :)
I would be very grateful for any input on how the actual library has been put together, how the packets are assembled etc.. I spent a lot of time going back and forwards between different designs, but I think the method I ended up with does work quite well. There's a fair amount of spaghetti code inside the packet class that needs sorting.
At the moment it sort of stands both as 'half-finished' and as a 'proof-of-concept'. It needs a lot of work to clean everything up.
I have some development tools I can post too, such as a set of functions which will parse InSim.txt to create the various packet definition lists etc..
Anyway... noob that I am I somehow managed to mess up the tab spacing in the version I posted (really smart with Python, of all languages lol), so I've uploaded a new version with the correct tab spacing.
JamesF1
17th April 2008, 13:46
I would be very grateful for any input on how the actual library has been put together, how the packets are assembled etc.. I spent a lot of time going back and forwards between different designs, but I think the method I ended up with does work quite well. There's a fair amount of spaghetti code inside the packet class that needs sorting.
Looks good from here, I had a quick scan down the source, and I can't say I'd have done it much differently. Your enumerations may benefit from being done on one line for each section, say:
ENUM_1, ENUM_2, ENUM_3 = 0, 1, 2
And you should probably document your def's like this:
def bla():
"""This is a document comment, with three double quotes"""
Just a couple of thoughts, I'll see if I get some time to look over it more fully later on :)
DarkTimes
17th April 2008, 13:48
Looks good from here, I had a quick scan down the source, and I can't say I'd have done it much differently. Your enumerations may benefit from being done on one line for each section, say:
ENUM_1, ENUM_2, ENUM_3 = 0, 1, 2And you should probably document your def's like this:
def bla():
"""This is a document comment, with three double quotes"""Just a couple of thoughts, I'll see if I get some time to look over it more fully later on :)
Yes, I need to do the docstrings. I've always been crap at documentation, and at the moment whole classes can be rewritten still (I re-wrote the InSim class earlier for instance), so it seems silly to document stuff that I'm not sure I'm going to keep. :)
The enums and the packet defs could be on one line, but I find it easier to read the way I've done it. Also I wrote a script that parses the data out of InSim.txt so I didn't have to write each enum and packet myself, and that was the easiest way to output the data.
DarkTimes
17th April 2008, 19:43
I've updated it to finish the NLP packets. I renamed _MciPacket to _CarTrackPacket, as it now handles both MCI and NLP. It's not very neat, the whole MCI/NLP packet feels like a (big) bit of a hack really, but I wanted to add NLP as it was the only major thing missing for InSim, apart from one camera packet I've not spent time working out yet. Aside from that all packets, enums and flags should be done.
Tomorrow I will spend some time refactoring and cleaning up the packet code, as it is just very messy at the moment. Do they have an obfuscated Python contest? :p
DarkTimes
17th April 2008, 19:58
InSim button example.
from Pyinsim import *
# Global variables.
BUTTON_ID = 1
insim = InSim()
# Button click event
def ButtonClick(btc):
if btc["ClickID"] == BUTTON_ID:
print "I was clicked!"
# Register the event with InSim.
insim.Bind({ISP_BTC: ButtonClick})
try:
insim.Connect("127.0.0.1", 29999)
except Exception, (msg):
print "Connection failed:", msg
else:
# Initialise InSim.
isi = Packet(ISP_ISI, Admin="Pass", IName="Pyinsim", Flags=ISF_LOCAL)
insim.SendP(isi)
# Create a button packet, fill in the values.
btn = Pyinsim.Packet(ISP_BTN)
btn["ReqI"] = 1
btn["UCID"] = 0
btn["ClickID"] = BUTTON_ID
btn["BStyle"] = ISB_DARK | ISB_CLICK
btn["T"] = 35
btn["L"] = 5
btn["W"] = 20
btn["H"] = 8
btn["Text"] = "Click me!"
insim.SendP(btn)
insim.Run()
finally:
insim.Close()
DarkTimes
18th April 2008, 15:56
Edit: Removed cause it was about an obsolete version.
DarkTimes
19th April 2008, 16:31
I've been testing a few things and I can confirm that Pyinsim runs unmodified on IronPython for the .NET Framework. I've been messing around with getting it running on the Silverlight 2 beta with IronPython, and while it fundamentally works, the socket restrictions on the beta have just made it too hard to do anything useful without a herculean effort (you need to use the web server as a proxy and bounce the packets off it. It's not very fun). From what I've read I'm confident it will work with Silverlight 2 final, albeit with some serious modifications to the socket code, so hopefully I should be able to report more progress on Pyinsim for Sliverlight in the future.
JamesF1
19th April 2008, 16:37
Good work :) When I have some spare time, I'll definitely be testing out Pyinsim :)
DarkTimes
19th April 2008, 19:07
Rolling Starts
Here is an example program which enforces rolling starts on a server. You can set the number of formation laps before the race, and if during that time a player breaks the speed-limit, or overtakes another car, they will be spectated. It also lets you configure the messages when are sent and other stuff like that.
import Pyinsim
import time
import threading
import sys
# InSim Config.
HOST = '127.0.0.1'
PORT = 29999
ADMIN = 'pass'
# Constants.
MCI_INTERVAL = 100
FORMATION_LAPS = 1
SPEED_LIMIT = 80 # Kph
START_MSG = "^1Rolling start - Keep below %d Kph and don't overtake!" % (SPEED_LIMIT)
GREEN_MSG = '^2Green flag! GO GO GO!'
SPEEDING_MSG = '%s ^3spectated for speeding!'
OVERTAKE_MSG = '%s ^3spectated for overtaking!'
MSG_TIMEOUT = 10 # How many seconds messages stay on the screen.
# Globals.
insim = Pyinsim.InSim()
players = {}
onFormationLap = False
rccTimer = None
# Player class.
class Player:
"""Small class to handle player."""
def __init__(self, npl):
self.PName = npl['PName'] # Player name.
self.PLID = npl['PLID']
self.Position = 0 # Position in race.
# Helper functions.
def SendMessage(msg):
"""Send a message to LFS."""
insim.SendP(Pyinsim.Packet(Pyinsim.ISP_MST, Msg=msg))
def SendRcmAll(msg, timeout):
"""Send RCM message to all players."""
SendMessage('/rcm %s' % (msg))
SendMessage("/rcm_all")
rccTimer = threading.Timer(timeout, ClearRcmAll)
rccTimer.start()
def ClearRcmAll():
"""Clear RCM message."""
SendMessage('/rcc_all')
def SpectatePlayer(pName):
"""Spectate a player."""
SendMessage('/spec %s' % (pName))
def ResetPositions():
"""Reset all player positions to zero."""
for player in players.itervalues():
player.Position = 0
def GetPlayer(plid):
"""Get player from players dict."""
return players[plid]
def PlayerExists(plid):
"""Get if player exists in players dict."""
return players.has_key(plid)
def RequestAllPlayers():
"""Request for all players to be sent."""
insim.SendP(Pyinsim.Packet(Pyinsim.ISP_TINY, SubT=Pyinsim.TINY_NPL, ReqI=1))
# Events.
def PlayerJoined(npl):
"""Create new player object and add to players dict."""
player = Player(npl)
players[npl['PLID']] = player
def PlayerLeft(pll):
""" Remove player object from players dict."""
del players[pll['PLID']]
# When a player leaves, any drivers behind them will be specced for
# over-taking, so we need to reset all positions.
ResetPositions()
def RaceStarted(rst):
"""Race started. Request all players to be sent and begin formation
lap."""
global onFormationLap
RequestAllPlayers()
if rst['RaceLaps'] > 0:
SendRcmAll(START_MSG, MSG_TIMEOUT)
onFormationLap = True
else:
# A qual or practice session, no formation lap.
onFormationLap = False
def CarUpdate(mci):
"""Car position update."""
global onFormationLap
for car in mci['CompCars']:
if PlayerExists(car['PLID']) and onFormationLap:
player = GetPlayer(car['PLID'])
if car['Lap'] > FORMATION_LAPS:
# Formation lap has ended.
onFormationLap = False
SendRcmAll(GREEN_MSG, MSG_TIMEOUT)
elif Pyinsim.ToKph(car['Speed']) > SPEED_LIMIT:
# Player is speeding.
SpectatePlayer(player.PName)
SendMessage(SPEEDING_MSG % (player.PName))
elif player.Position == 0:
# Player has no position, set it.
player.Position = car['Position']
elif car['Position'] < player.Position:
# Player has over-taken another car.
SpectatePlayer(player.PName)
SendMessage(OVERTAKE_MSG % (player.PName))
# Connection lost event.
def ConnectionLost():
"""Event called when connection to InSim is lost."""
print 'The connection to InSim has been lost.'
sys.exit(0)
# Register events.
insim.Bind({Pyinsim.ISP_NPL: PlayerJoined,
Pyinsim.ISP_PLL: PlayerLeft,
Pyinsim.ISP_RST: RaceStarted,
Pyinsim.ISP_MCI: CarUpdate})
insim.ConnectionLost(ConnectionLost)
try:
insim.Connect(HOST, PORT)
except Pyinsim.socket.error, (ex):
print 'Connection failed: %s' % (ex.args[1])
sys.exit(0)
else:
# Initialise InSim.
insim.SendP(Pyinsim.Packet(Pyinsim.ISP_ISI, Admin=ADMIN,
IName='RollingStarts', Flags=Pyinsim.ISF_MCI,
Interval=MCI_INTERVAL))
insim.Run()
finally:
insim.Close()
You can download the source code file below as well.
JamesF1
20th April 2008, 00:04
Pardon my ignorance - I'm not totally clued up on current InSim version details, etc. but where's the IS_REN packet in your source? I couldn't find it.
DarkTimes
20th April 2008, 00:11
There is no IS_REN packet. I believe it's now a sub-type of IS_TINY, called TINY_REN.
def TinyReceived(tiny):
if tiny["SubT"] == Pyinsim.TINY_REN:
print "Race Ending!"
insim.Bind({Pyinsim.ISP_TINY: TinyReceived})
Catch a TINY and check the SubT.
:)
JamesF1
20th April 2008, 00:13
Ahh, right-o :) Seems a bit of an odd thing to do with it... but oh well.
DarkTimes
20th April 2008, 22:38
Hello,
I have uploaded a new source-distribution to the first post, of version 0.1.3. There are a couple of quite subtle but important changes.
# The documentation has been cleaned up a lot!
# The Packet class has been completely rewritten and the code is much, much simpler. Packets now inherit directly from UserDict, meaning they now have all the same methods and properties as Python dictionaries. This means you can now iterate over packets like you can a normal dictionary.
In addition to this, the Packet class now contains a new constructor parameter called values, which allows you to specify a default dictionary for the packet. Basically that means you can create packets like this:
isi = Packet(ISP_ISI, ReqI=1, Admin="Spam", IName="Pyinsim")
# A new method named SendP() has been added to the InSim class, which allows you to send a packet without having to call its Pack() method first.
insim.SendP(isi)
# Instead of the old...
insim.Send(isi.Pack())
You can still use old Send() however, for instance if you want to send you own custom binary data to InSim.
Anyway, you can download the source-dist in the first post. These features were added to support a new Pyinsim module which I'm planning to release soon, which will make writing InSim apps easier than it currently is, but I felt these changes were useful enough on their own to warrant a separate release.
Dygear
21st April 2008, 10:01
To bad we can't give it a soul.
Sure we can, import soul;
Oh, right on python!
http://imgs.xkcd.com/comics/new_pet.png
DarkTimes
21st April 2008, 10:13
:D
I <3 xkcd. :)
mcgas001
21st April 2008, 10:20
http://imgs.xkcd.com/comics/python.png
Now that is funny! :D
Nadeo4441
21st April 2008, 14:22
Thanks for that!
*Starts learning python*
//edit: could you write a example, what will refresh speed data in a button?
DarkTimes
21st April 2008, 16:16
//edit: could you write a example, what will refresh speed data in a button?
This is a really basic example, it will only work in a single-player game and if you're the only car, but it demonstrates the principle.
from Pyinsim import *
insim = InSim()
def CarPosUpdate(mci):
for car in mci["CompCars"]:
# We convert the speed and send the button to LFS.
speed = "Speed: %3.0F Kph" % ToKph(car["Speed"])
insim.SendP(Packet(ISP_BTN, ReqI=1, ClickID=1, UCID= 0,
W=40, H=10, T=30, L=5, Text=speed))
insim.Bind({ISP_MCI: CarPosUpdate})
try:
insim.Connect("127.0.0.1", 29999)
except Exception, (msg):
print "Connection failed:", msg
else:
# Initialise InSim.
insim.SendP(Packet(ISP_ISI, Admin="Pass", IName="Pyinsim",
Flags=ISF_MCI | ISF_LOCAL, Interval=500))
insim.Run()
finally:
insim.Close()
Hope that helps. :)
Nadeo4441
21st April 2008, 16:41
I cant get it working , :shrug:
Im getting this in lfs : "InSim guest closed : "
DarkTimes
21st April 2008, 16:49
I get that error too if the program closes right away, closing the network connection, before the ISI packet has been received by LFS. You need to force the program to stay running so that Pyinsim can keep the network connection open. That's what this code is suppose to do:
insim.Run()
So first of all make sure you have that code somewhere before the end of your app. If you do, them I might need more info to solve the problem.
Nadeo4441
21st April 2008, 16:56
I have tested your unchanged code from post #21 ... i get that error too , and before the application close, it shows "Connection failed" .
DarkTimes
21st April 2008, 17:03
Please make sure you have 0.1.3 from the first post, which I uploaded last night. The example I posted is for that version. If I try it with the old 0.1.2 then I get exactly the same error you post. Please make sure you've updated.
Edit: The actual error is that SendP doesn't exist, as that wasn't added until 0.1.3. Because I'm just catching all exceptions, it's catching that one too, and printing the connection failed message. If you remove the Except exception catching block you'll see the real error message.
DarkTimes
21st April 2008, 17:13
I have uploaded the binary distributable for 0.1.3 to the first post. If you are a Windows user can just download that and run the exe, which will install it automatically.
Nadeo4441
21st April 2008, 17:46
i have installed 0.1.3, and im getting same error..
DarkTimes
21st April 2008, 17:56
There could be an issue with the Pyinsim installation, which can happen if you're upgrading from 0.1.2 (but won't happen for future upgrades as the bug has been fixed in 0.1.3).
Go to X:\Path\To\Python\Lib\site-packages and delete the following files:
Pyinsim.py
Pyinsim.pyc
Pyinsim.pyo
There should also be a folder called Pyinsim, but don't delete that, as that's where 0.1.3 has been installed. Now the script should work...
Nadeo4441
21st April 2008, 18:08
i removed Pyinsim folder, and that 3 files . After that i have installed 0.1.3 . I got this :
ImportError: No module named Pyinsim
After that i copied the files from Lib\site-packages\Pyinsim
to Lib\site-packages\ ... and it worked
Thanks for your help anyway :)
DarkTimes
21st April 2008, 18:18
I said not to remove the Pyinsim folder, but I could have been more clear, sorry.
As I said this was a bug in 0.1.2 which has been fixed now, so it won't happen again for future upgrades.
Nadeo4441
21st April 2008, 18:58
Oh, sorry, im blind :shhh:
Nadeo4441
23rd April 2008, 15:27
Sorry for doublepost, im testing this, and im stucked in that sittuation :
def Msg(mso):
msgt = mso["Msg"]
if msgt == "eTS.NadeoSvK : ^L!test":
SendMessage("/msg " + msgt)
if i type !test, it starts posting msgt ,and dont stop
// i know , its normal, but how to fix it?
filur
23rd April 2008, 16:00
how to fix it?
struct IS_MSO // MSg Out - system messages and user messages
...
byte UCID; // connection's unique id (0 = host)
if mso["UCID"] != 0 and msgt == "eTS.NadeoSvK : ^L!test":
DarkTimes
23rd April 2008, 16:03
if mso["UCID"] != 0 and msgt == "eTS.NadeoSvK : ^L!test":
There's no && in Python. :)
Nadeo4441
23rd April 2008, 16:57
thanks guys :)
//Edit: DarkTimes: What about an OutSim&OutGauge support?
DarkTimes
23rd April 2008, 22:20
I have uploaded 0.1.4 to the first post, which contains a few tweaks and additions.
Changes:
- You now define the default values for packets with traditional-style parameters, instead of passing a dictionary. Sadly this is a breaking change (the first one!), but the code looks much nicer like this. isi = Packet(ISP_ISI, ReqI=1, Admin="FishDance", IName="Pyinsim")
- The prefix char in IS_ISI is now an actual char instead of a byte, so you don't need to cast the prefix char into a byte yourself. Yes, I know, but it wasn't as simple to add as it sounds. isi["Prefix"] = "!" # This works now!
- Multiple packets obejcts can now be sent with a single SendP() call. The packets will be sent one after the other, in the order they are specified. For example: insim.SendP(isi, tiny, mst)
- An interesting little idea I had was to use XML to create packets, so I've added a new function called PacketXml which will return a packet object created from XML data. You can either parse XML from a file or from a string. Here is an example:
The XML file, called Packets.xml. You define a Packet element and give it a Name attribute, which is important as you will use that to reference the Packet later on. The rest of the info follows the typical InSim packet stuff. Anything you omit from a packet will be filled in with appropriate default data before it's sent (which is the same for everything in Pyinsim really).
<?xml version="1.0" encoding="utf-8"?>
<Pyinsim>
<Packet Name="Init">
<ReqI>1</ReqI>
<UDPPort>0</UDPPort>
<Admin>Pass</Admin>
<IName>Pyinsim</IName>
<Prefix>$</Prefix>
</Packet>
<Packet Name="HelloMsg">
<Msg>Hello, world!</Msg>
</Packet>
</Pyinsim>
You call PacketXml() and pass in the type of packet you want to create, the Name attribute for the packet in the XML file, and also the path to the XML file. PacketXml then parses the data and returns a regular Packet object populated from the XML.
xmlFile = "Packets.xml"
isi = PacketXml(ISP_ISI, "Init", xmlFile)
mst = PacketXml(ISP_MST, "HelloMsg", xmlFile)
insim.SendP(isi, mst)
Anyway...
DarkTimes
23rd April 2008, 22:59
//Edit: DarkTimes: What about an OutSim&OutGauge support?
Yes, I'm going to add that soon. I'm just trying get the InSim part right first. :)
Nadeo4441
24th April 2008, 13:29
if im a windows user , how to install it ? (0.1.4)
JamesF1
24th April 2008, 13:30
Run the installer?
Nadeo4441
24th April 2008, 13:39
doesnt work...
JamesF1
24th April 2008, 13:47
If you don't describe the problem, we can't help you. If you have Python installed, there should be no problems at all.
Nadeo4441
24th April 2008, 13:49
i have python installed , and i have Pyinsim 0.1.3. I click on the setup.py , it shows something but closes ... and it doesnt work..
DarkTimes
24th April 2008, 18:38
Edit: I have now uploaded a new fixed installer to the first post.
Nadeo4441
24th April 2008, 19:15
oh , i got it now, thanks
DarkTimes
26th April 2008, 15:49
Due to a request I have created an example of how you might go about using commands like "!help" and "!admin".
from Pyinsim import *
insim = InSim()
def MessageReceived(mso):
command = ParseCommand(mso, '!')
if command[0] == "help":
print 'Help command'
elif command[0] == "admin":
print 'Admin command'
elif command[0] == "report":
print 'Report', command[1]
insim.Bind({ISP_MSO:MessageReceived})
try:
insim.Connect("127.0.0.1", 29999)
except Exception, (msg):
print "Error:", msg
else:
insim.SendP(Packet(ISP_ISI, Admin="Pass", IName="Pyinsim"))
insim.Run()
finally:
insim.Close()
tmehlinger
6th June 2008, 21:36
I've been playing LFS for a couple months and wanted to get started in some InSim programming. Thanks very much for this Python module, it made my day. :)
DarkTimes
7th June 2008, 16:22
Thanks! Glad you find it useful. :)
Tanuva
30th September 2008, 20:07
I'm fiddling round to get the button example from the thread's first page to work, but my button still only appears in singleplayer mode.
I changed the UCID to the actual player's one - didn't really help. Hints?
InSim.SendP(self, Packet(ISP_BTN, ReqI=1, ClickID=0, UCID=ucid,
BStyle=ISB_DARK, W=40, H=10, T=30, L=5, Text=speed))
DarkTimes
30th September 2008, 23:18
It's been a while since I did any work with InSim, but I think it's because of the ISF_LOCAL flag on this line:
insim.SendP(Packet(ISP_ISI, Admin="Pass", IName="Pyinsim", Flags=ISF_LOCAL))
This flag, I believe, tells InSim to only display buttons in single-player mode, or if you are a guest on a server (not the host). Change the line to:
insim.SendP(Packet(ISP_ISI, Admin="Pass", IName="Pyinsim"))
and it should work in multiplayer.
As I say, been a while, but this should work. I reckon this is the fundamental root of the issue.
Tanuva
1st October 2008, 10:04
Yep, the ISF_LOCAL flag was the problem. Thanks! :)
Silox
1st October 2008, 12:13
B-E-A-U-tiful!
/me is desperate to learn Python as soon my Ranking System is finished...
ken830
3rd October 2008, 22:28
Just wanted to say thanks to DarkTimes for all of his hard work and for making this available to all of us. I certainly appreciate it! Thanks!
DarkTimes
7th October 2008, 15:58
Just a short note for an oddity I noticed ('pulled my hair out over') earlier. For some reason calling InSim.Close() doesn't actually seem to close the internal socket, when running in TCP mode. You need to send the packet to close InSim before you try to close the socket, or else nothing seems to happen (and nothing happening is the worst thing when you're trying to figure out a bug).
# Send tiny close to InSim.
tinyClose = Packet(ISP_TINY, SubT=TINY_CLOSE)
insim.SendP(tinyClose)
# Now you can close the socket.
insim.Close()
This may well be a Berkeley sockets issue, and not a Pyinsim or Python problem, but it's different behaviour from that in the .NET Berkeley sockets implementation that I'm used to. I'm not sure what's going on... but it's likely I've run out of brains...
I may roll a workaround into the next release, if I can get around to releasing it. :)
Edit: This is fixed in Pyinsim 0.1.5 and above.
Tanuva
10th October 2008, 16:20
Hey!
First I have to praise Darktimes for his great work on PyInsim!
My actual problem:
I have a button:
InSim.SendP(self, Packet(ISP_BTN, ReqI=1, ClickID=cid, UCID=ucid,
BStyle=ISB_DARK | ISB_RIGHT,
W=cw, H=ch, T=cy, L=cx, Text=carbtntext))
[ReqI is the same for all my buttons since I dont know what it does...]
Now I added ISP_BTC to the list of packet handlers, but the handler doesnt get triggered once I click the button (in "show connections" mode to have a cursor).
What am I doing wrong? :)
DarkTimes
10th October 2008, 16:32
I have a button:
InSim.SendP(self, Packet(ISP_BTN, ReqI=1, ClickID=cid, UCID=ucid,
BStyle=ISB_DARK | ISB_RIGHT,
W=cw, H=ch, T=cy, L=cx, Text=carbtntext))Now I added ISP_BTC to the list of packet handlers, but the handler doesnt get triggered once I click the button (in "show connections" mode to have a cursor).
What am I doing wrong? :)
It looks like you need to add the flag ISB_CLICK to the BStyles byte.
InSim.SendP(self, Packet(ISP_BTN, ReqI=1, ClickID=cid, UCID=ucid,
BStyle=ISB_DARK | ISB_RIGHT | ISB_CLICK,
W=cw, H=ch, T=cy, L=cx, Text=carbtntext))Now when the button is clicked, InSim will send back an IS_BTC packet which will be picked up by the packet handler.
Tanuva
10th October 2008, 17:03
Of course! I knew I read something about that in InSim.txt, but I couldn't refind it. Thank you! :D
DarkTimes
13th October 2008, 11:57
Uploaded version 0.1.5 to the first post. It contains a few fixes and changes, and please note that it breaks comptibility with previous versions.
Changes:
Fix: Fixed 'bad file description' error on attempted reconnects.
Fix: Fixed bug with InSim not closing when calling InSim.Close() in TCP mode.
Fix: Changed InSim.Run() documentation to make it clear it's designed to only be used when running Pyinsim from a console application.
Change: Added ISP_CPP Camera Position Packet, which means all InSim packets are now complete.
Change: Renamed InSim.RegisterPackets() and InSim.UnregisterPackets() to InSim.Bind() and InSim.Unbind() respectively. This is a breaking change.
Change: Added LFSTime class, for handling time operations.
Change: Increased internal buffer size default to 1024
Change: Added InSim.ConnectionLost() event, which is called when the InSim connection is lost.
Note: Pyinsim does not currently yet support Vectors as a data-type, so a small work-around is used. For instance, instead of the Pos attribute of the CPP packet being a vector, it is in fact split into three seperate attributes, which are named Pos1, Pos2 and Pos3, each of them containing an int.
Also note that instead of distributing four separate downloads, I have combined them all into one single package. This file contains the windows installer, the source distribution, license, readme and HTML documentation, as well as the template file.
Crady
20th October 2008, 16:15
DarkTimes!
Thank you!!!!!!
Ok... I took me some few time today and tried to understand python and your lib a bit...
Well I think I already failed at the start :(
Ok... As I told you in the PM I sent you I am also intersted in hanling a rolling start and... tataaaaaaaa... you already coded something like that!
But the Problem I have is that any speeding of 1mph causes a spec.
So I tried to change your code a bit. I wanted that a personal rcm appears to the driver who speeded (I dunno how to code buttons yet), then the timer should run, rcm should be cleared by rcc and then if the car still is faster than the limit a spec should follow...
This is my try:
elif ToKph(car["Speed"]) > SPEED_LIMIT:
# Player broke the speed-limit, spec them.
SendMessage("/rcm " + GET_SLOWER)
SendMessage("/rcm_ply " + players[car["PLID"]][0]["PName"])
BlockingTimer(MSG_TIMEOUT)
SendMessage("/rcc_ply " + players[car["PLID"]][0]["PName"])
players[car["Speed"]] = 0
if ToKph(car["Speed"]) > SPEED_LIMIT:
SendMessage("/spec " + players[car["PLID"]][0]["PName"])
SendMessage(SPEEDING_MSG)
But I realized 2 big problems with it:
1.) rcm_ply does not work with Nickname and changing "PName" to "UName" gives me an error...
2.) I become sent to spec anyway even if I slow down under the limit...
I seems to me that the 1st speed I got the message for speeding for is stored somehow and at the "if" it still is over the limit...
So I tryed to set the Speed to 0 manually which seems not to work too...
An other problem I noticed is that there seems to be an endles loop after speeding... because I am not able to join the race later - I always become to spec again as soon as I join...
Any clue?
If I (or we) manage to get this to work my next step will be to create a command like "!rollingstarton" and "!rollingstartoff" to be able to choose wether there will be a rolling start or not. The over-next step should be using a config file and then creating a exe...
DarkTimes
21st October 2008, 09:20
1.) rcm_ply does not work with Nickname and changing "PName" to "UName" gives me an error...
Using the nickname should work. Not sure why it doesn't. It works fine for me.
2.) I become sent to spec anyway even if I slow down under the limit...
The example I posted is very simple, if you go across the speed limit at all then you are just spectated immediately. If you wanted to adapt it to give a warning to slow down, you would need to setup some sort of timer that would start when the player began speeding, then after X amount of seconds had passed it would check the speed again, and if you were still over the limit you would get spectated.
Edit: The example program is badly written, I've uploaded a better version now.
DarkTimes
21st October 2008, 13:27
I've completely rewritten the original RollingStarts program and I've updated the original post. The new version is written in a much clearer way and I tested it a few times to check it works without bugs. It may still have a couple, I don't know. It still works the same way as the previous version mind you.
http://www.lfsforum.net/showthread.php?p=774956#post774956
In other news: Update version 0.1.6 in the first post.
Changes
Updated PyinsimTemplate.py to add support for taking over cars and for players being renamed. Also added connection lost event handler.
Added ToUnicode(str, default) function which converts a LFS string to unicode, and handles converting all the character encodings and escape chars. Note this is still being tested, so might be a little flaky.
Added keepAlive boolean param to InSim(connType, keepAlive) contrsuctor, which allows you to set if InSim responds to keep alive packet automatically.
Added CheckPort(ipStr) and CheckIP(portStr) functions, to make it easy to validate IP addresses and port number strings.
Added ParseCommand(mso, prefix, sansPrefix), which parses a command from an MSO packet and returns a tuple.
Added weather and wind enums.
Added flags enum to check ISP_FLG attributes.
Added car info flags
Crady
22nd October 2008, 06:14
Thank you, DarkTime, great one!
I will test your rewritten Code this afternoon and will report! But yet I got some worries in mind: What will happen if the racer at Pole spinns out although he obtained speedlimit? Do all other drivers go to spec then because they "overtake" ?? Well although it is just a "Demo Code" I would like to stay and improve on it... - I would say that spec could be changed with a drive through penalty and the formation lap Funktions itself should be switchable to on/off via a command which only can be applied by an Amdin...
Secondary I have a suggestion to python / Pyinsim itself:
What do you think about developing a good insim application together in this forum to 1st create a usefull app, 2nd to show the possibilities of Python and 3rd help ppl learning Python (espeically Pyinsim)...
DarkTimes
22nd October 2008, 13:28
Thank you, DarkTime, great one!
I will test your rewritten Code this afternoon and will report! But yet I got some worries in mind: What will happen if the racer at Pole spinns out although he obtained speedlimit? Do all other drivers go to spec then because they "overtake" ?? Well although it is just a "Demo Code" I would like to stay and improve on it... - I would say that spec could be changed with a drive through penalty and the formation lap Funktions itself should be switchable to on/off via a command which only can be applied by an Amdin...
Yes, in its current form it's very harsh on mistakes, as if you pass another driver at all it specs you. You could easily mod it to give a penalty instead.
def PenalisePlayer(pName):
SendMessage('/p_dt %s' % (pName))Which would give a drive-through instead, which an admin could clear if they decided it was unfair.
What do you think about developing a good insim application together in this forum to 1st create a usefull app, 2nd to show the possibilities of Python and 3rd help ppl learning Python (espeically Pyinsim)...Sorry, but I'm quite busy with some other projects at the moment, or I should be busy with them, if I wasn't such a slacker. I will help people using Pyinsim all I can, but I can't work on any outside projects specifically at the moment.
Crady
22nd October 2008, 14:36
Sorry, but I'm quite busy with some other projects at the moment, or I should be busy with them, if I wasn't such a slacker. I will help people using Pyinsim all I can, but I can't work on any outside projects specifically at the moment.
I really can imagine that you are very busy - as I am too...
But I now decided to change and spare my projects and believe me, I bought a Video2Brain DVD for Python beginners and a very big book "Python the complete manual"... I guess after watching the video and reading the 1st 100 pages in this book I will be able to understand it more clearly!
My big problem is the LFS insim... I never spent time in that and to be honestly I do not understand anything in the manual which can be found in the doc folder... But thats why you made this great lib... Now I only need to know what I can get from LFS and how to use it :)
My far away aim is create a webapplication which makes it via user accounts possible to manage the lapper config more easy than scripting a config file... I mean adding/removing/changing autoactions, adding/removing user rights, editing the swear filter, editing the ban list, synchronizing the ban list for several servers of a team... etc...
Well hard dreams.... but lets see, what the future brings :)
Crady
25th October 2008, 16:41
Hi...
After reading a bit in the Pyton book I bought I must say that I seem to be able to do some simple scripts...
But I want to create some insim apps... And this still is my problem:
To configure an amount of Servers I want to create an app wihich asks me "Which Admin Commad?" for Security it also should ask for the Admin Pass.
Then it should connect to to all IPs / Ports entered in a List, execute the commad, end exit insim...
But my problem is how to close the insim after the command and how to open another after this?
Or is it possible to connect to more than one Server at once?
This is my try with the use of your template:
#
# Copyright 2008 Alex McBride.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the Lesser General Public License (LGPL) as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import Pyinsim
import sys
# Init globals
insim = Pyinsim.InSim(Pyinsim.INSIM_TCP)
connections = {}
players = {}
Server = ['192.168.2.104', '127.0.0.1']
Port = [29999, 29998]
# Helper functions.
def SendMessage(msg):
"""Send message to LFS."""
if len(msg) > 64:
insim.SendP(Pyinsim.Packet(Pyinsim.ISP_MSX, Msg=msg))
else:
insim.SendP(Pyinsim.Packet(Pyinsim.ISP_MST, Msg=msg))
def SendMessageConn(msg, ucid=0, plid=0):
"""Send message to a specific connection or player."""
insim.SendP(Pyinsim.Packet(Pyinsim.ISP_MTC, Msg=msg, UCID=ucid, PLID=plid))
#def RequestPlayersConns():
# """Request all players and connections to be sent."""
# insim.SendP(Pyinsim.Packet(Pyinsim.ISP_TINY, ReqI=1, SubT=TINY_NCN))
# insim.SendP(Pyinsim.Packet(Pyinsim.ISP_TINY, ReqI=1, SubT=TINY_NPL))
def GetConnection(ucid):
"""Get connection from UCID."""
return connections[ucid]
def GetPlayer(plid):
"""Get player from PLID."""
return players[plid]
def GetPlayerFromUcid(ucid):
"""Get player from UCID."""
for player in players.itervalues():
if player['UCID'] == ucid:
return player
return None
# TODO: Add more helper functions.
# Packet received events
def VersionCheck(ver):
"""Check the version."""
if ver['InSimVer'] != Pyinsim.INSIM_VERSION:
print 'Invalid InSim version detected.'
sys.exit(0)
def ConnectionJoined(ncn):
"""Add connection to connections dictionary."""
connections[ncn['UCID']] = ncn
def ConnectionLeft(cnl):
"""Delete connection from connections dictionary."""
del connections[cnl['UCID']]
def ConnectionRenamed(cpr):
"""Rename player in connections and players lists."""
connection = GetConnection(cpr['UCID'])
connection['PName'] = cpr['PName']
player = GetPlayerFromUcid(cpr['UCID'])
player['PName'] = cpr['PName']
player['Plate'] = cpr['Plate']
def PlayerJoined(npl):
"""Add player to players dictionary."""
players[npl['PLID']] = npl
def PlayerLeft(pll):
"""Delete player from players dictionary."""
del players[pll['PLID']]
def TookOverCar(toc):
"""Change UCID for player."""
player = GetPlayer(toc['PLID'])
player['UCID'] = toc['NewUCID']
# TODO: Add more packet event handlers.
# Bind events.
insim.Bind({Pyinsim.ISP_VER: VersionCheck,
Pyinsim.ISP_NCN: ConnectionJoined,
Pyinsim.ISP_CNL: ConnectionLeft,
Pyinsim.ISP_NPL: PlayerJoined,
Pyinsim.ISP_PLL: PlayerLeft,
Pyinsim.ISP_CPR: ConnectionRenamed,
Pyinsim.ISP_TOC: TookOverCar})
# Connection lost.
def ConnectionLost():
print 'InSim connection lost.'
sys.exit(0)
insim.ConnectionLost(ConnectionLost)
# Ask for Input
Command = str(raw_input('Command?: '))
Adminpass = str(raw_input('Admin Pass?: '))
# Connect to InSim.
try:
insim.Connect(Server[0], Port[0])
except Pyinsim.socket.error, (ex):
print 'Connection to InSim failed: %s' % (ex.args[1])
sys.exit(0)
else:
# Initailise InSim and request players/connections.
insim.SendP(Pyinsim.Packet(Pyinsim.ISP_ISI, Admin=Adminpass,
IName='^3Pyinsim', ReqI=1))
# send message
SendMessage(Command)
# Keep program thread alive.
insim.Run()
finally:
insim.Close
DarkTimes
26th October 2008, 00:40
It's nice you are learning some programming. It's an addictive hobby. :)
Yes, connecting to multiple servers is possible, although it does add a few complications. The important thing to note however is that each instance of InSim() can only deal with a single server connection, so you would need to create a new InSim() object for each server you wanted to connect to. You could store them in a Python list or tuple.
This is a rough example of how might do this (it's totally untested). Note: I made the Server and Port lists a dictionary called 'hosts', and created a new list called 'sockets', just as it seemed a little neater. I loop through the list of hosts, create a new InSim connection for each server, and add each connected server to our sockets list.
# Store hosts and ports as a dictionary (dict).
hosts = {'192.168.2.104': 29999, '127.0.0.1': 29998}
# Create a list to store each InSim connection.
sockets = []
# Loop over the hosts dictionary.
for host, port in hosts.iteritems():
# Create new InSim object.
insim = Pyinsim.InSim()
# Connect to this server.
insim.Connect(host, port)
# Add connected InSim object to our sockets list.
sockets.append(insim)Then if you wanted to access a certain server, you could do something like this.
if sockets[0].Connected == True:
print 'Socket 0 connected' # First server in sockets list connected.
if sockets[1].Connected == True:
print 'Socket 1 connected' # Second server in sockets list connected.Or you could loop through each server:
for socket in sockets:
if socket.Connected == True:
print 'Socket connected!'
I hope that make some sense to you. :)
Maybe if you explain what it is you are trying to do I can provide a more detailed example, as there a quite a few ways you could go about doing this.
Crady
26th October 2008, 08:40
Hmm... wrong OS booted now... I can take a closer look on it this afternoon - after the DTM finale :)
Well exactly it should be a way in which an Admin is able to change a setting to every of his Servers once without connecting to all of them...
e.g. You have 5 server and want to change all of them to have 30 minutes quali. Then you have to connect to all 5 and have to type /qual=30 ... Or you have a guy you donīt want on your Servers, you need to visit all of your Servers and type /ban xyz xdays ... etc...
In this case I just want to create small app doing this at once... If I get this to work I would like to create a GUI... I am not sure if I should create a windows GUI or buttons in LFS...
Crady
26th October 2008, 16:27
Ok... I tryed it and got some Problems...
I in only can send the a Message if I am loggend in as Admin and if ther is the command : insim.Run() or in ,y example socket.Run()
But this command stops the program from connecting to the next server... Here is my try so far:
# Ask for Input
Command = str(raw_input('Command?: '))
Adminpass = str(raw_input('Admin Pass?: '))
# Loop over the hosts dictionary.
for host, port in hosts.iteritems():
# Create new InSim object.
insim = Pyinsim.InSim()
# Connect to this server.
insim.Connect(host, port)
# Add connected InSim object to our sockets list.
sockets.append(insim)
# Loop over the sockets
for socket in sockets:
if socket.Connected == True:
print 'connected'
socket.SendP(Pyinsim.Packet(Pyinsim.ISP_ISI, Admin=Adminpass,
IName='^3XXX', ReqI=1))
SendMessage(Command)
socket.Run()
DarkTimes
26th October 2008, 17:02
Whenever you call InSim.Run() it effectively pauses your program at that point, and no code that comes after it will be executed until the InSim connection closes. That means you need to put it right at the end of your program, something like this.
Command = str(raw_input('Command?: '))
Adminpass = str(raw_input('Admin Pass?: '))
for host, port in hosts.iteritems():
insim = Pyinsim.InSim()
insim.Connect(host, port)
sockets.append(insim)
for socket in sockets:
if socket.Connected == True:
print 'connected'
socket.SendP(Pyinsim.Packet(Pyinsim.ISP_ISI, Admin=Adminpass,
IName='^3XXX', ReqI=1))
SendMessage(Command)
# TODO: Write rest of program.
# END OF PROGRAM
for socket in sockets:
socket.Run()
Crady
26th October 2008, 18:07
Yes, thats it!
Now it works... Thank you!
Crady
26th October 2008, 21:45
ok, ok... it only seems to work on my testing place at home with 2 Servers...
Now I found another prolem:
The "real" servers are hosted at 500Servers. I am talking about 4 Server where always 2 Server have the same IP - just different ports...
If I now start the Program it only connects to 2 Server (to one for each IP) instead of all 4..
my hosts are configured like that:
hosts = {'192.168.2.104': 29999, '192.168.2.104': 2998, '127.0.0.1':2997, '127.0.0.1': 29996}
Any Idea? Perhaps I create a 2 Dictionaries? and then loop over 2 Dictionaries?
Crady
27th October 2008, 11:38
Ok... I solved this problem:
The ports are unique. So I changed the order in the dictionary to {port: host} and it works...
Thank you!
But now there encounters an other question:
By using this technique: Is it possible to use your RollingStart and FlagMessages program - or even other progrmas to work on more than one Server at time? I mean if I let the insim.connect loop over 4 or more server Do I have a rolling start option or a displayed blue/yellow flag message at all Server or do you think the program will become messed?
If I will work I would recommend that you use this option to your next programs. So teams and leagues are able to use them by only starting one app instead of one for each server..
Crady
31st October 2008, 15:54
DarkTimes,
Have been some busy these days... But now I have time to go further :)
Ok, as I told you everything works as mentioned... But now I again have one Question:
Is it possible to do the "SendMessage(Command)" to a special time or lets say every 10 Minutes?
In this way I could make this program sending some "news" every 10 Minutes as message or a "Time to sleep" warning a 00:00h every day...
like this:
for socket in sockets:
if socket.Connected == True:
print 'connected'
socket.SendP(Pyinsim.Packet(Pyinsim.ISP_ISI, Admin=Adminpass,
IName='^3XXX', ReqI=1))
SendMessage('/msg ' + News) #every 10 Minutes
SendMessage('/mag Time to sleep now') #at 00:00h every day
# TODO: Write rest of program.
# END OF PROGRAM
for socket in sockets:
socket.Run()
DarkTimes
31st October 2008, 18:37
Yes, it's possible to do this. The best way would be to use Python's built-in threading.timer class, which allows you to set up a timer which calls a function or method after a certain number of seconds have elapsed.
INTERVAL = 600 # Number of seconds in 10 minutes.
def timer_event():
# Timer event fired, send message.
SendMessage('/msg {0}' % (News))
# Start timer again.
timer = threading.Timer(INTERVAL, timer_event)
timer.start()
# Start timer.
timer = threading.Timer(INTERVAL, timer_event)
timer.start()
That's a rough example of how you might do it, you can look at the RollingStarts example I posted to see a timer in use, it uses a timer to control how long RCM messages appear on the screen.
If you wanted a message to be sent at a certain time each day, you could setup a timer that elapsed every second or so, and checked to see what the current time is. Then you could send a message
if current_time == message_send_time:
SendMessage(msg)
I'd need to look up the documentation for Python to see what classes or functions you would need for this, but you should be able to find them in Pythons time and threading.timer modules, if you look them up in the standard library yourself.
HTH :)
Crady
2nd November 2008, 12:16
Hi, DarkTims!
Again thanks:)
Well the timer in this way seems to go in an endless loop and crash the whole program when executed in IDLE... So I changed it pit and it now closes all InSim connecrions one after another after 10 Seconds...
So I am able to use Windows Scedule Service to open the program when I need it...
Because of this I only took a short view on the current_time thing... But I saw that I can get the current system time by including Year, Date, Seconds and Miliseconds as a list... So I first have to strip out only the thime etc.... Well this is done by the Windows Scedule Service too :)
tmehlinger
7th November 2008, 05:00
Wow, I kind of stopped watching this thread, glad everyone is still interested in this.
I have a question about buttons... I've had great success creating individual buttons and making them do all sorts of stuff, but I've hit a brick wall.
Is there any way to make buttons overlap? I want to do something like the menus in CTRA or Alrio where there are a bunch of buttons sitting within a "panel", but I can't seem to make it work. I figured the way to do it was make a big button with no text in it and overlay it with more buttons, but then the underlying button just doesn't display.
Any ideas?
** Edit **
Please ignore, I was using the same ClickID for the buttons meant to make this work... problem solved. Going to keep this here in case other idiots like myself stumble on the same problem. :)
Crady
13th November 2008, 15:59
Hi, Dark Times - or others!
Again I have a little problem to be solved:
I can connect to every host specified in a dictionary and then I can send a message to the host.
But what I would like to do is to send a message to every host in my dictionary every lets say 5 minutes...
I tryed doing it with a timer but it only works for the last connected server - but the message is not sent to all connected servers, it is sent e.g. twice to the last server if I have 2 Server in mx Dictionary:
def timer_message():
for socket in sockets:
sendmessage('/msg Welcome'
timer = threading.Timer(300, timer_message)
timer.start()
an other way I tried was:
a=0
for socket in sockets:
if socket.Connected == True:
socket.SendP(Pyinsim.Packet(Pyinsim.ISP_ISI, Admin=Adminpass,
IName='^3app', ReqI=1))
while a == 0:
SendMessage('/unban ' + unbans)
time.sleep(300)
a = 0
but here it only connects to the last server - which is sounding quite logical because the program has an endless loop...
Crady
13th November 2008, 21:43
OMG... there is the next idea I need your help for:
Is it possible to place a small button file which opens a list of all connected racer as buttons?
But only connected racers in a special config file should be able to see this button..
Then I can click on a Racer Name and a code will be executed with the racers licence name?
I would like to add the licence names of racers I clicked on to a text file to handle lapper options with them...
DarkTimes
14th November 2008, 14:57
a=0
for socket in sockets:
if socket.Connected == True:
socket.SendP(Pyinsim.Packet(Pyinsim.ISP_ISI, Admin=Adminpass,
IName='^3app', ReqI=1))
while a == 0:
SendMessage('/unban ' + unbans)
time.sleep(300)
a = 0
This is an infinite loop, it just keeps looping over the same code again and again, and the program never progresses past this point.
Based on the earlier code posted, I knocked up a quick example of how you could do this:
import Pyinsim
import threading
hosts = {'127.0.0.1': 29999}
sockets = []
timer = None
def SendMessage(socket, msg):
"""Send message to specific socket."""
socket.SendP(Pyinsim.Packet(Pyinsim.ISP_MST, Msg=msg))
def TimerElapsed():
"""Function called when the timer finishes."""
for socket in sockets:
SendMessage(socket, "Hello")
# Start the timer again.
StartTimer()
def StartTimer():
"""Starts the timer."""
timer = threading.Timer(300, TimerElapsed)
timer.start()
for host, port in hosts.iteritems():
# Loop through each host, connect and initailise it, then add it
# to sockets list.
insim = Pyinsim.InSim()
insim.Connect(host, port)
insim.SendP(Pyinsim.Packet(Pyinsim.ISP_ISI, Admin='pass', IName='^3XXX', ReqI=1))
sockets.append(insim)
# Start the timer.
StartTimer()
# END OF PROGRAM
for socket in sockets:
socket.Run()Hope that helps some.
Crady
14th November 2008, 16:47
Dark Times,
again and again... Thank you :)
works like charme :)
Next aim will be the button things... Do you have a usefull manual for creating buttons - I mean either I will need a mall button which opens a bigger button to type text in (which could be used later) or I will need a small button to display a clickable drivers list which gives me the licence name into a variable...
Crady
18th November 2008, 00:48
Dark Times,
Does pyinsim0.1.6 also run with python2.6 or do I have to sty at 2.5.2?
DarkTimes
18th November 2008, 01:58
It should probably work with 2.6, but I've never tried it myself.
vBulletin® v3.7.1, Copyright ©2000-2008, Jelsoft Enterprises Ltd.