

Usage:
  PIE script.php [config.cfg]       - config settings override script settings

  
Called (user-defined) functions:
  PIE_settings()                   - called at startup, should return array of required settings (overrides defaults, is overridden by cfg file). Should return settings only, PIE object is not yet ready here.
  PIE_start()                      - called once, after connection is confirmed. PIE object is now ready.
  PIE_clock($t)                    - called once per second, with integer utime as $t
  PIE_tick($u)                     - called each cycle, with fractional utime as $u
  PIE_shutdown()                   - called after the main program loop is stopped
  PIE_commands($cmd, $args, $UCID) - called on use of chat $cmd by $UCID, $args as array

  PIE_XXX($data)        - where XXX = packet name: called on receipt of packet, $data indexes match InSim.txt
  PIE_OutGauge($data)   - called on receipt of OutGauge packet, $data indexes match InSim.txt
  PIE_OutSim($data)     - called on receipt of OutSim packet, $data indexes match InSim.txt
  
  
Utility functions (packet sending):
  PIE_sendpacket($data)                       - sends packet (match required indices to InSim.txt, e.g. $data['Type'] etc. Size and ReqI are handled by PIE)
  PIE_sendTINY($subtype)                      - send TINY packet of $subtype
  PIE_sendSMALL($subtype, $value)             - send SMALL packet of $subtype with $value
  PIE_sendTTC($subtype, $UCID, $b1, $b2, $b3) - send TTC packet to $UCID with $b1, $b2, $b3

  
Utility functions (misc):  
  PIE_say($msg)                           - send $msg to chat (as your player in local insims; as host in host insims)
  PIE_saylocal($msg)                      - send $msg to local chat (local insims, ignored as host)
  PIE_sayto($UCID, $msg, [$sound])        - send $msg to single connection (use UCID 255 to send to all)
  PIE_PLIDfromUCID($UCID)                 - returns PLID corresponding to $UCID (in the case of multiple PLIDS, will return only one, prioritising non-AI player)
  PIE_PLIDsfromUCID($UCID)                - returns array of PLIDs corresponding to $UCID
  PIE_UCIDfromPLID($PLID)                 - returns UCID corresponding to $PLID
  PIE_isLFSadmin($UCID)                   - server admin
  PIE_isPIEadmin($UCID)                   - local admin (requires localadmin setting when client is in multiplayer)
  PIE_isadmin($UCID)                      - PIEadmin in localmode, else LFSadmin
  PIE_isAI($PLID)                         - is AI player
  PIE_isontrack($PLID)                    - (not including pit screen)
  PIE_isme($PLID)                         - is local car, not ai
  PIE_setcallback($time, $func, [$args])  - sets callback of $func($args) at $time (unix timestamp, fractional allowed)
  PIE_kill()                              - closes PIE at the end of the current cycle
  PIE_timerstart($name)                   - start or restart timer $name
  PIE_timerget($name)                     - get time since start of timer $name (in seconds, fractional)
  PIE_timerkill($name)                    - unsets timer $name
  PIE_tickfraction($time)                 - returns $time as fraction of current tick length

  
Access PIE data; Store user data:
  $PIE = PIE::connect();                - returns reference to PIE object
  $PIE->set($name)                      - returns true if $name is set
  $PIE->set($name, $value)              - sets $name to $value
  $PIE->seta($name, $index)             - returns true if $name[$index] is set
  $PIE->seta($name, $index, $value)     - sets $name[$index] to $value
  $PIE->get($name)                      - returns value stored in $name
  $PIE->get($name, $index)              - returns value stored in $name[$index]
  $PIE->clear($name)                    - clears $name
  $PIE->clear($name, $index)            - clears $name[$index]
  $PIE->push($name, $value)             - adds $value to end of $name array (creates array if not set)
  $PIE->pop($name)                      - returns value from end of $name array (removes from array)
  $PIE->shift($name)                    - returns value from start of $name array (removes from array)
  $PIE->contains($target, $name)        - returns true if $name array contains $target 
  $PIE->contains($target, $name, true)  - returns index if $name array contains $target 
  
  
PIE Internal data (automatically updated, use for reading only):
  PIE_connections       - array of connection NCN data, indexed by UCID
  PIE_players           - array of player NPL data, indexed by PLID
  PIE_playersontrack    - array of true (on track) or false (garage screen etc), indexed by PLID
  PIE_lastplayer        - NPL data of the last player to spectate
  PIE_admins            - array of UCIDs of admin connections
  PIE_STA               - current STA data (server state)
  PIE_MCI               - current MCI CompCar data (or NLP NodeLap + blanks), indexed by PLID (position, speed, etc)
  PIE_AXI               - current AXI data (layout)
  PIE_VER               - current VER data (version)
  PIE_ISM               - current ISM data (host)
  PIE_MAL               - current MAL data (allowed mods in SkinID format)
  PIE_SLC               - current SLC data, indexed by UCID (selected car)
  PIE_NCI               - current NCI data, indexed by UCID (connections (extended))
  PIE_CIM               - current CIM data, indexed by UCID (interface)
  
  
PIE Internal chat commands (available to all server admins in host mode, specified user in local mode):
  pie                  - reports PIE version and scriptname
  piedebug             - reports current debuglevel
  piedebug level       - sets debuglevel to level
  pietiny type         - send TINY request of type (type is NOT case sensitive)
  piesmall type value  - send SMALL packet of type and value (type is NOT case sensitive)
  piepeek name         - reports values from PIE_name (case sensitive)
  piepeek name index   - reports values from PIE_name[index] (case sensitive)
  piepeeku name        - reports values from name (case sensitive)
  piepeeku name index  - reports values from name[index] (case sensitive)
  piepokeu name value  - sets name to value (case sensitive) (beware multiple instances following a single command!)
  pieut                - reports time since start of PIE
  piela                - reports recent tick lengths (min/avg/max) over 1/3/5 seconds
  piemem               - reports current memory usage
  piekill              - generates new kill token
  piekill token        - shuts down PIE if tokens match (token is NOT case sensitive)

 
PIE Debug settings:
  PIE_DEBUGNONE                 0 - Off
  PIE_DEBUGBASEPIE              1 - PIE functions
  PIE_DEBUGPACKETSOUT           2 - Outward packets
  PIE_DEBUGBASEPACKETSIN        4 - Inward packets (base set)
  PIE_DEBUGMCI                  8 - MCI/NLP packets (PIE_DEBUGNLP is an alias)
  PIE_DEBUGAXM                 16 - AXM packets
  PIE_DEBUGBTN                 32 - BTN packets
  PIE_DEBUGOUTSIM              64 - OutSim packets, post processing
  PIE_DEBUGOUTGAUGE           128 - OutGauge packets, post processing
  PIE_DEBUGPACKETDATA         256 - Verbose packet data, post processing
  PIE_DEBUGUSER1              512 - User defined 1
  PIE_DEBUGUSER2             1024 - User defined 2
  PIE_DEBUGUSER3             2048 - User defined 3
  PIE_DEBUGUSER4             4096 - User defined 4
  
  PIE_DEBUGALL                    - All above
  PIE_DEBUGJ                      - All above, minus verbose/OutSim/OutGauge data
  PIE_DEBUGBASEUSER               - PIE function and user defined only
  
 
PIE Constants: 
  PIE_LOCALMODE         - boolean for connection mode
  PIE_EXEDIR            - directory of PIE executable 
  PIE_SCRIPTDIR         - directory of PIE script 
  

PIE Extras:  
  PIE_MSO: Added index 'MsgOnly' - the 'Msg' field stripped of sender name
  PIE_MCI: Added index 'Odometer' for distances travelled since: array(serverjoin, trackjoin, racestart);
  CarContact: Added 'Throttle', 'Brake', 'Clutch', 'Handbrake' and 'Gear' (separated from their combined values)
  PIE_STA,
  PIE_RST: Added 'Laps' and 'Hours' (separated from RaceLaps)
   
   
Notes: 
  - Capitalisation is matched to InSim.txt, and avoided elsewhere except for universal conventions. (It's the least painful compromise I can find to a clash of styles. This sort of thing is not new to a PHPer, though, is it?)
  - All defines, enums and consts from InSim.txt are available as constants 
  - You don't need to send an ISI packet to initialise the connection, PIE does that.
  - You don't need to send or respond to TINY_PING packets, PIE does that.
  - Functions called for packets received will be passed a single array as a parameter. The array will contain the packet data as listed in InSim.txt (with some ease-of-use additions and modifications, listed)
  - All trailing null characters have been removed from packet text fields.
  - When you send a packet, ignore the size. PIE will calculate it when building the packet.
  - When you send a packet, you can ignore the ReqI. PIE will use the default unless you override it.
  - When connecting in local mode, you will need to provide an admin password if set (check LFS's cfg.txt, 'Game Admin' setting)
  - Outgoing MSX packets are buffered when in local mode (LFS rate-limits chat by ignoring packets, PIE_say() uses MSX packets for non-command text)
  - OutGauge host/port must be enabled in LFS's cfg file 
  - OutSim host/port/options must be enabled in LFS's cfg file. Mismatched options will cause corrupt data. NOTE: PIE requires decimal value, LFS cfg requires hex value.
  - The OutSim/OutGauge Delay setting in LFS's cfg file will override any rate set in InSim. Set them to 0 in the .cfg to control the rates from InSim.
  - OCO packets have no effect on unoptimsed (newly-placed) lights. A race restart will reoptimise all objects.
  - There is a small, random length delay when adding or removing objects with AXM, changing lights with OCO, or moving cars with JRR. PIE will continue running during the delay.
  - PIE will stop running if you scroll and hold the console display, for as long as the mouse button is held (a limitation of the compiler used). Holding for too long will cause the connection to timeout. (If you go full debug, do it through a tail'd file)
  - PIE can't save you from PHP errors, including parse errors. It must be valid PHP.
  
  
Exceptions:
  - Car names are provided by PIE in SkinID format, not raw data (raw data may contain harmful characters)
  - Car names must be provided to PIE in SkinID format, not raw bytes (e.g, FOX, 6FB5F5). Not case sensitive.
  - The PIE_start, PIE_tick and PIE_clock functions are not called until a successful connection is established
  
  
PIE Default settings:
  host              - '127.0.0.1'       - default is local computer
  port              - 29999             - set locally with "/insim 29999" or in configuration file
  adminpass         - ''                - required if set
  insimname         - 'PIEscript'       - script name (15 character max)
  reqi              - 104               - ReqI is automatically set to this value
  controlchar       - ';'
  flags             -   ISF_LOCAL
                      | ISF_MSO_COLS
                      | ISF_MCI
                      | ISF_CON 
                      | ISF_OBH
                      | ISF_HLV
                      | ISF_AXM_LOAD  
                      | ISF_AXM_EDIT
  buffersize        - 10240             - Main insim buffer size, in bytes
  loopsleep         - 50000             - PIE target sleep between ticks, 50,000 = 20 Hz
  positioninterval  - 200               - MCI/OutGauge packet rate, 1,000 =  1 second
  pingtime          - 10                - connection maintaining ping, in seconds
  debug             - PIE_DEBUGNONE     - debug level, default off
  outsimhost        - ''                - IP address for OutSim
  outsimport        - 0                 - port for OutSim
  outsimoptions     - 0                 - options for OutSim (decimal value required, LFS's cfg.txt uses hexadecimal value)
  outgaugehost      - ''                - IP address for OutGauge
  outgaugeport      - 0                 - port for OutGauge
  
  
Enabled PHP extensions:
  cURL, PDO MySQL, PDO PostgreSQL, sockets, Multibyte String
  