================= Table of Contents ================= * How to compile the client * Understanding the Engine * How to extend the T1Game object for your program * How to listen to events with your new T1Game client * Recording demos * Tables for functions ========================= How to compile the client ========================= Visual Studio 2003 and 2005 projects are included, as well as a GNU Makefile for building on *nix systems. NOTE: If you are on a big endian system, you must define __USE_BIG_ENDIAN__ in T1.h NOTE: On Solaris, you must run "make solaris" which adds "-lsocket -lnsl". It succesfully compiles and runs a demo on all of the Source Forge compile-farm system (they don't allow outbound network access): [x86] Linux 2.6 (Debian 3.1) [x86] Linux 2.6 (Fedora FC2) [x86] FreeBSD (5.4) [x86] NetBSD (2.0.2) [AMD64] Linux 2.6 (Fedora Core 3 on AMD64 Opteron) [Alpha] Linux 2.2 (Debian 3.0) [PPC - G5] MacOS X 10.2 SERVER Edition [Power5 - OpenPower 720] SuSE Enterprise Server 9 [Sparc - R220] Sun Solaris (9) [x86] OpenBSD 3.8 [x86] Solaris 9 It succesfully compiles and runs a demo / joins actual Tribes servers under Linux 2.6 (Gentoo, x86), OpenBSD(?, x86), and Win2k (VS2003/2005, x86). ======================== Understanding the Engine ======================== To understand what's going on in the various systems, here are the functions to breakpoint or inspect: * Packet reading and decoding - T1Connection::ReadPacketHeader in T1Connection.cpp - T1NetStream::ReadPacket in T1NetStream.cpp * Demo reading - T1Demo::Poll in T1Demo.cpp * Event decoding - T1EventManager::ReadPacket in T1EventManager.cpp * Connecting to a server - T1NetLayer::Start in T1NetLayer.cpp Hierarchy of functions: Client->Demo: + T1Game::Poll |----+ T1Demo::Poll |----+ T1NetStream::ReadPacket |----+ T1EventManager::ReadPacket |----+ T1Game::OnEvent |----+ T1Game::OnEvent |----+ T1Game::OnEvent Client->Server: + T1Game::Poll |----+ T1NetLayer::Poll |----+ T1Connection::Poll |----+ T1NetStream::ReadPacket |----+ T1EventManager::ReadPacket |----+ T1Game::OnEvent |----+ T1Game::OnEvent |----+ T1Game::OnEvent ================================================ How to extend the T1Game object for your program ================================================ The simplest way to make a T1 engine is to extend the T1Game object with and empty class: /* My First Tribes client! */ #include "T1.h" #include "T1Game.h" #include "Console.h" class MyT1 : public T1Game { }; int main( int argc, char *argv[] ) { Console::Init( ); // console init T1::Net_Startup( ); // net init MyT1 *game = new MyT1; game->OpenDemo( "my_demo.rec" ); // or game->OpenServer( "IP:127.0.0.1:28001" ); to join a server if ( game->Start( ) ) { while ( game->Poll( ) ) { T1::Sleep( 20 ); } } delete game; T1::Net_Shutdown( ); Console::Close( ); return ( 0 ); } =================================================== How to listen to events with your new T1Game client =================================================== ------------------------------------------------------------------------------- NOTE: If you ever need to disconnect from the server (using T1Game::Close, T1Game::OpenLastServer, etc), ONLY do it in your ::Poll function. Doing it in your OnMissionReset or any other On???? function will destroy all buffers and connection state information while you're in the middle of the game's message loop. See "Hierarchy of functions" to see why deleting the connection anywhere but in ::Poll would be bad. Having a class flag such as "mReconnect" or something that you check in ::Poll is the best way to handle connection disconnects/reconnects. If you override any of the non-virtual methods in T1Game (Poll, Start, Close, etc), you must call T1Game::Poll, T1Game::Start, etc, at the top of your function. Of the virtual methods, OnDataFinished, OnMissionReset, or OnTeamAdd need to be chained. Call "T1Game::OnDataFinished", "T1Game::OnMissionReset", and "T1Game::OnTeamAdd" at the top of your overriddent function. This is to ensure that remoteDataFinished and remoteCGADone are called properly so demos record properly. ------------------------------------------------------------------------------- The previous example is a fully working client, but there isn't much it can do. To get some feedback on what is happening, we need to extend some of the T1Game events. The list of extendable events are in T1Game.h, and are the On??????? declarations with "virtual" in front. Let's add OnPlayerSay to our MyT1 class so we can see what players are saying. Server messages are also sent to OnPlayerSay, except they have an id_player of 0 instead of the normal 2049+. class MyT1 : public T1Game { virtual void OnPlayerSay( int id_player, int type, char *msg ) { Console::Print( "SAY: %d(%d): %s\n", id_player, type, msg ); } }; Re-run your demo and the chat and server messages will be echoed! Of course they aren't very useful since we have no idea who each player id is, so you could add an OnPlayerJoin method to keep track of which player each id is. You can also use Console::PrintColor to color the message according to what type it is (team chat, global chat, server messages, etc). Event types are stored in T1EventManager.h. The included main.cpp is an example client with handling for most events. When it is connected to a live server, it will also respond to "!test" in chat with with "Bot compiled on [DATE] for [OPERATING SYSTEM]" =============== Recording demos =============== T1Game::OpenServer and T1Game::OpenLastServer allow you to pass an argument for a demo name to record to. When the bot joins a live server, it will save a demo to that filename which can be played back by the bot or in a real Tribes client! ==================== Tables for Functions ==================== * Console.h Console Colors (Console::PrintColor) ------------------- CONSOLE_BLACK CONSOLE_BLUE CONSOLE_GREEN CONSOLE_CYAN CONSOLE_RED CONSOLE_MAGENTA CONSOLE_YELLOW CONSOLE_WHITE CONSOLE_COLOR_DEFAULT * T1EventManager.h Say types from server (T1Game::OnPlayerSay) ------------------------------------------- SAY_SYSTEM SAY_GAME SAY_GLOBAL SAY_TEAM Say types to server (T1NetStream::RemoteEval( "say", 2, msg_type, msg_text )) ----------------------------------------------------------------------------- REMOTESAY_GLOBAL REMOTESAY_TEAM Datablock Types (T1Game::OnDatablock) ------------------------------------- DB_SOUNDPROFILE DB_SOUND DB_DAMAGESKIN DB_ARMOR DB_STATICSHAPE DB_ITEM DB_ITEMIMAGE DB_MOVEABLE DB_SENSOR DB_VEHICLE DB_FLIER DB_TANK DB_HOVER DB_PROJECTILE DB_BULLET DB_GRENADE DB_ROCKET DB_LASER DB_INTERIORSHAPE DB_TURRET DB_EXPLOSION DB_MARKER DB_DEBRIS DB_MINE DB_TARGETLASER DB_SEEKINGMISSILE DB_TRIGGER DB_CAR DB_LIGHTNING DB_REPAIREFFECT DB_IRCCHANNEL * T1Connection.h Packet Types (T1Connection::SendPacket) --------------------------------------- PACKET_DATA PACKET_DISCONNECT PACKET_CONNECT PACKET_CONNECTION_ACCEPT PACKET_CONNECTION_REJECT PACKET_ACKED PACKET_PING PACKET_RESEND_FLAG PACKET_ACK_FLAG Connection States (T1Connection::mState) ---------------------------------------- STATE_NOT_CONNECTED STATE_CONNECTING_TO_CLIENT STATE_CONNECTING_TO_SERVER STATE_CONNECTED STATE_5