/* Crystal Space Entity Layer Copyright (C) 2005 by Christian Van Brussel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "cssysdef.h" #include "nettest.h" #include "netmanagers.h" #include "networktypes.h" #include "csutil/sysfunc.h" #include "iutil/vfs.h" #include "iutil/object.h" #include "iutil/cmdline.h" #include "csutil/cscolor.h" #include "cstool/csview.h" #include "cstool/initapp.h" #include "csutil/event.h" #include "iutil/eventq.h" #include "iutil/event.h" #include "iutil/objreg.h" #include "iutil/csinput.h" #include "iutil/virtclk.h" #include "iutil/plugin.h" #include "iengine/sector.h" #include "iengine/engine.h" #include "iengine/camera.h" #include "iengine/campos.h" #include "iengine/collectn.h" #include "iengine/light.h" #include "iengine/texture.h" #include "iengine/mesh.h" #include "iengine/movable.h" #include "iengine/material.h" #include "iengine/region.h" #include "imesh/thing.h" #include "imesh/sprite3d.h" #include "imesh/object.h" #include "ivideo/graph3d.h" #include "ivideo/graph2d.h" #include "ivideo/txtmgr.h" #include "ivideo/texture.h" #include "ivideo/material.h" #include "ivideo/fontserv.h" #include "igraphic/imageio.h" #include "imap/loader.h" #include "ivaria/reporter.h" #include "ivaria/stdrep.h" #include "ivaria/collider.h" #include "csutil/cmdhelp.h" #include "csutil/debug.h" #include "csutil/csshlib.h" #include "celtool/initapp.h" #include "celtool/persisthelper.h" #include "physicallayer/pl.h" #include "physicallayer/propfact.h" #include "physicallayer/propclas.h" #include "physicallayer/entity.h" #include "physicallayer/persist.h" #include "behaviourlayer/bl.h" #include "propclass/test.h" #include "propclass/mesh.h" #include "propclass/meshsel.h" #include "propclass/inv.h" #include "propclass/chars.h" #include "propclass/move.h" #include "propclass/tooltip.h" #include "propclass/defcam.h" #include "propclass/gravity.h" #include "propclass/timer.h" #include "propclass/region.h" #include "propclass/input.h" #include "propclass/navgraph.h" #include "propclass/linmove.h" #include "propclass/actormove.h" #include "propclass/quest.h" #include "propclass/trigger.h" #include "propclass/zone.h" NetTest::NetTest () { SetApplicationName ("Network test"); gfm = 0; } NetTest::~NetTest () { delete gfm; } void NetTest::OnExit () { if (pl) pl->CleanCache (); } void NetTest::ProcessFrame () { // We let the entity system do this so there is nothing here. } void NetTest::PostProcessFrame () { // We let the entity system do this so there is nothing here. if (gfm && g3d->BeginDraw (CSDRAW_2DGRAPHICS)) { // write player data if (gfm->IsClientAvailable ()) { celPlayer* player = gfm->game->GetGameClient()->GetPlayer(); gfm->game->GetGameClient()->GetNetworkStats (stats); celGameInfo* game_info = gfm->game->GetGameInfo (); csString player_data; player_data.Format("(%d) %s (%s:%d) - Server %d (%s:%d) - Latency: %d ms", player->player_id, player->player_name.GetData(), player->hostname.GetData (), player->port_nb, game_info->game_id, game_info->hostname.GetData (), game_info->port_nb, stats.latency); WriteShadow( 0, 10, 10, g2d->FindRGB(219, 230, 222), "%s", player_data.GetData()); } // write network state WriteShadow( 0, 10, 22, g2d->FindRGB(219, 230, 222), "%s", gfm->GetConnectionState().GetData()); // write comments if (gfm->client_manager) { int pos_y = 34; size_t i = 0; for ( ; i < gfm->client_manager->comments.Length(); i++) { WriteShadow( 0, 10, pos_y, g2d->FindRGB(119, 130, 122), "%s", gfm->client_manager->comments[i].GetData()); pos_y += 12; } } } } void NetTest::FinishFrame () { if (gfm && gfm->IsClientAvailable ()) { g3d->FinishDraw (); g3d->Print (0); } } bool NetTest::OnKeyboard (iEvent &ev) { // We got a keyboard event. if (csKeyEventHelper::GetEventType (&ev) == csKeyEventTypeDown) { // The user pressed a key (as opposed to releasing it). utf32_char code = csKeyEventHelper::GetCookedCode (&ev); if (code == CSKEY_ESC) { // The user pressed escape. For now we will simply exit the // application. The proper way to quit a Crystal Space application // is by broadcasting a csevQuit event. That will cause the // main runloop to stop. To do that we get the event queue from // the object registry and then post the event. csRef q = CS_QUERY_REGISTRY (object_reg, iEventQueue); q->GetEventOutlet ()->Broadcast (csevQuit (object_reg)); } if (gfm && gfm->IsClientAvailable ()) { if (code == CSKEY_F1) { printf ("Key F1 pressed: sending two empty events\n"); fflush (stdout); // launch simple client event celClientEventData event_data; event_data.event_type = CLIENT_EVENT_SIMPLE_TEST; gfm->GetClient ()->LaunchClientEvent (event_data); gfm->GetClient ()->LaunchClientEvent (event_data); } if (code == CSKEY_F2) { printf ("Key F2 pressed: sending two complex data buffers\n"); fflush (stdout); // launch complex client event celClientEventData event; event.event_type = CLIENT_EVENT_COMPLEX_TEST; event.event_time = 100; event.event_data = pl->CreateDataBuffer (0); event.event_data->Add ((bool) 1); event.event_data->Add ((int8) -5); event.event_data->Add ((uint8) 5); event.event_data->Add ((int16) -50); event.event_data->Add ((uint16) 50); event.event_data->Add ((int32) -500); event.event_data->Add ((uint32) 500); event.event_data->Add ((float) 3.5); csString txt = "nice text nice text nice text nice text nice text nice text nice text nice text"; event.event_data->Add (txt.GetData ()); csVector2 v2; v2.x = 10; v2.y = 20; event.event_data->Add (v2); csVector3 v3; v3.x = 10; v3.y = 20; v3.z = 30; event.event_data->Add (v3); event.event_data->Add (csColor (119, 130, 122)); gfm->GetClient ()->LaunchClientEvent (event); gfm->GetClient ()->LaunchClientEvent (event); } if (code == CSKEY_F3) { printf ("Key F3 pressed: sending an event to be forwarded to all players\n"); fflush (stdout); // launch client event celClientEventData event; event.event_type = CLIENT_EVENT_FORWARD_TEST; event.event_time = 1000; event.event_data = pl->CreateDataBuffer (0); csString txt; txt.Format("Message forwarded from %s", gfm->GetClient () ->GetPlayer ()->player_name.GetData ()); event.event_data->Add (txt.GetData ()); event.event_data->Add (gfm->GetClient ()->GetPlayer () ->hostname.GetData ()); event.event_data->Add (gfm->GetClient ()->GetPlayer ()->port_nb); gfm->GetClient ()->LaunchClientEvent (event); } if (code == CSKEY_F4) { printf ("Key F4 pressed: asking to be kicked\n"); fflush (stdout); // launch client event celClientEventData event_data; event_data.event_type = CLIENT_EVENT_KICKING_TEST; gfm->GetClient ()->LaunchClientEvent (event_data); } if (code == CSKEY_F5) { printf ("Key F5 pressed: asking to kick all players\n"); fflush (stdout); // launch client event celClientEventData event_data; event_data.event_type = CLIENT_EVENT_KICKING_ALL_TEST; gfm->GetClient ()->LaunchClientEvent (event_data); } } if (code == CSKEY_F6) gfm->factory->CloseGame (); } return false; } csPtr NetTest::CreateActor (const char* name, const char* /*factname*/, const csVector3& /*pos*/) { // The Real Camera csRef entity_cam = pl->CreateEntity (name, bltest, "actor", "pccommandinput", "pcdefaultcamera", "pcactormove", "pcmesh", "pcmeshselect", "pclinearmovement", "pctooltip", "pcinventory", CEL_PROPCLASS_END); if (!entity_cam) return 0; csRef pcinp = CEL_QUERY_PROPCLASS_ENT (entity_cam, iPcCommandInput); pcinp->Bind ("up", "forward"); pcinp->Bind ("down", "backward"); pcinp->Bind ("shift", "run"); pcinp->Bind ("m", "cammode"); pcinp->Bind ("left", "rotateleft"); pcinp->Bind ("right", "rotateright"); pcinp->Bind ("a", "strafeleft"); pcinp->Bind ("d", "straferight"); pcinp->Bind ("space", "jump"); pcinp->Bind ("x", "center"); pcinp->Bind ("pgup", "lookup"); pcinp->Bind ("pgdn", "lookdown"); csRef pccamera = CEL_QUERY_PROPCLASS_ENT ( entity_cam, iPcDefaultCamera); pccamera->SetMode (iPcDefaultCamera::firstperson); pccamera->SetSpringParameters (10.0f, 0.1f, 0.01f); pccamera->SetMode (iPcDefaultCamera::thirdperson); pccamera->SetSpringParameters (3.5f, 0.25f, 0.01f); pccamera->SetMode (iPcDefaultCamera::m64_thirdperson); pccamera->SetSpringParameters (3.5f, 0.25f, 0.01f); pccamera->SetMinMaxCameraDistance (2.0f, 6.0f); pccamera->SetTurnSpeed (1.0f); pccamera->SetMode (iPcDefaultCamera::lara_thirdperson); pccamera->SetSpringParameters (3.5f, 0.25f, 0.01f); pccamera->SetMinMaxCameraDistance (2.0f, 6.0f); pccamera->SetTurnSpeed (1.0f); pccamera->SetSwingCoef (0.7f); pccamera->SetMode (iPcDefaultCamera::freelook); pccamera->SetSpringParameters (3.5f, 0.25f, 0.01f); pccamera->SetMinMaxCameraDistance (2.0f, 16.0f); pccamera->SetFirstPersonOffset (csVector3 (0, 1, 0)); pccamera->SetThirdPersonOffset (csVector3 (0, 1, 3)); pccamera->SetModeName ("thirdperson"); // Get the iPcActorMove interface so that we can set movement speed. csRef pcactormove = CEL_QUERY_PROPCLASS_ENT (entity_cam, iPcActorMove); pcactormove->SetMovementSpeed (2.0f); pcactormove->SetRunningSpeed (5.0f); pcactormove->SetRotationSpeed (1.75f); pcactormove->SetJumpingVelocity (6.31f); csRef pcmesh = CEL_QUERY_PROPCLASS_ENT (entity_cam, iPcMesh); bool hascal3d = true; pcmesh->SetPath ("/cel/data"); hascal3d = pcmesh->SetMesh ("test", "cally.cal3d"); csRef pclinmove = CEL_QUERY_PROPCLASS_ENT (entity_cam, iPcLinearMovement); if (hascal3d) { pclinmove->InitCD ( csVector3 (0.5f, 0.8f, 0.5f), csVector3 (0.5f, 0.4f, 0.5f), csVector3 (0.0f, 0.01f, 0.0f)); } else { pclinmove->InitCD ( csVector3 (0.5f, 0.8f, 0.5f), csVector3 (0.5f, 0.4f, 0.5f), csVector3 (0.0f, -0.4f, 0.0f)); } scfString regionname, startname; pczonemgr->GetLastStartLocation (®ionname, &startname); pccamera->SetZoneManager (pczonemgr, true, regionname, startname); if (pczonemgr->PointMesh (name, regionname, startname) != CEL_ZONEERROR_OK) { ReportError ("Error finding actor start position!"); return 0; } /* csRef pcinv_room = CEL_QUERY_PROPCLASS_ENT (entity_room, iPcInventory); if (!pcinv_room->AddEntity (entity_cam)) return 0; */ return csPtr (entity_cam); } csPtr NetTest::CreateActorNPC (const char* name, const char* /*factname*/, const csVector3& /*pos*/) { csRef entity_cam = pl->CreateEntity (name, bltest, "actor", "pcactormove", "pcmesh", "pclinearmovement", CEL_PROPCLASS_END); if (!entity_cam) return 0; // Get the iPcActorMove interface so that we can set movement speed. csRef pcactormove = CEL_QUERY_PROPCLASS_ENT (entity_cam, iPcActorMove); pcactormove->SetMovementSpeed (2.0f); pcactormove->SetRunningSpeed (5.0f); pcactormove->SetRotationSpeed (1.75f); pcactormove->SetJumpingVelocity (6.31f); csRef pcmesh = CEL_QUERY_PROPCLASS_ENT (entity_cam, iPcMesh); bool hascal3d = true; pcmesh->SetPath ("/cel/data"); hascal3d = pcmesh->SetMesh ("test", "cally.cal3d"); csRef pclinmove = CEL_QUERY_PROPCLASS_ENT (entity_cam, iPcLinearMovement); if (hascal3d) { pclinmove->InitCD ( csVector3 (0.5f, 0.8f, 0.5f), csVector3 (0.5f, 0.4f, 0.5f), csVector3 (0.0f, 0.01f, 0.0f)); } else { pclinmove->InitCD ( csVector3 (0.5f, 0.8f, 0.5f), csVector3 (0.5f, 0.4f, 0.5f), csVector3 (0.0f, -0.4f, 0.0f)); } scfString regionname, startname; pczonemgr->GetLastStartLocation (®ionname, &startname); if (pczonemgr->PointMesh (name, regionname, startname) != CEL_ZONEERROR_OK) { ReportError ("Error finding npc start position!"); return 0; } return csPtr (entity_cam); } csPtr NetTest::CreateDefaultCamera (const char *name) { csRef default_camera = pl->CreateEntity (name, bltest, "actor", "pcdefaultcamera", CEL_PROPCLASS_END); if (!default_camera) return 0; scfString regionname, startname; pczonemgr->GetLastStartLocation (®ionname, &startname); csRef pccamera = CEL_QUERY_PROPCLASS_ENT ( default_camera, iPcDefaultCamera); pccamera->SetZoneManager (pczonemgr, true, regionname, startname); if (pczonemgr->PointMesh (name, regionname, startname) != CEL_ZONEERROR_OK) { ReportError ("Error finding npc start position!"); return 0; } return csPtr (default_camera); } bool NetTest::CreateRoom (const csString path, const csString file) { printf ("Loading level path: %s file: %s\n", path.GetData (), file.GetData ()); fflush (stdout); // Create the room entity. entity_room = pl->CreateEntity ("room", bltest, "room", "pczonemanager", "pcinventory", CEL_PROPCLASS_END); // Engine init. engine->Prepare (); // Load the level csRef vfs = CS_QUERY_REGISTRY (object_reg, iVFS); csStringArray paths; paths.Push ("/cellib/lev/"); if (!vfs->ChDirAuto (path, &paths, 0, file)) return ReportError ("Bad file path '%s' at '%s'!", file.GetData (), path.GetData ()); pczonemgr = CEL_QUERY_PROPCLASS_ENT (entity_room, iPcZoneManager); if (!pczonemgr->Load (0, file)) return ReportError ("Error loading level '%s' at '%s'!", file.GetData (), path.GetData ()); printf ("Level loaded\n"); fflush (stdout); return true; } bool NetTest::OnInitialize (int argc, char* argv[]) { csDebuggingGraph::SetupGraph (object_reg); // analyse command line arguments csRef cmdline = CS_QUERY_REGISTRY (object_reg, iCommandLineParser); // help if (cmdline->GetOption ("nethelp") != 0 || cmdline->GetOption ("help") != 0) { csPrintf ("\nYou can use the following options to this program:\n"); csPrintf (" -path=[value] The path of the level to be loaded (to be used on server side)\n"); csPrintf (" -file=[value] The file of the level to be loaded (to be used on server side)\n"); csPrintf (" -server If a server must be created\n"); csPrintf (" -client If a client must be created\n"); csPrintf (" -serverhost The hostname of the server (when there is only a client)\n"); csPrintf (" -singleplayer If the game is in single player mode\n"); csPrintf (" -player=[value] To specify the name of the player\n"); csPrintf (" -nethelp This help message\n"); csPrintf ("\n"); csPrintf (" When used without any options, the default behavior is to create\n"); csPrintf (" a client and a server.\n"); csPrintf ("\n"); csPrintf ("Examples:\n"); csPrintf (" nettest -server -path=cellib/lev -file=basic_world\n"); csPrintf (" nettest -server -path=lev/terrainf -file=world\n"); csPrintf (" nettest -client -player=Marc -serverhost=192.168.1.15\n"); csPrintf (" nettest -client -serverhost=localhost\n"); csPrintf ("\n"); csPrintf ("WARNING:\n"); csPrintf (" Under MS Windows and if you are using MSYS, when you specify \n"); csPrintf (" the level path with the --path option, you must be aware that \n"); csPrintf (" MSYS adds the full path to MSYS when an option begins with a ""/"".\n"); csPrintf (" You can avoid this problem by removing the first ""/"" of the path.\n"); exit(0); } bool do_server = cmdline->GetOption ("server") != 0; bool do_client = cmdline->GetOption ("client") != 0; if (!celInitializer::RequestPlugins (object_reg, CS_REQUEST_VFS, CS_REQUEST_PLUGIN ( (do_server && !do_client) ? "crystalspace.graphics3d.null" : "crystalspace.graphics3d.opengl", iGraphics3D), CS_REQUEST_ENGINE, CS_REQUEST_FONTSERVER, CS_REQUEST_IMAGELOADER, CS_REQUEST_LEVELLOADER, CS_REQUEST_REPORTER, CS_REQUEST_REPORTERLISTENER, CS_REQUEST_PLUGIN ("cel.physicallayer", iCelPlLayer), CS_REQUEST_PLUGIN ("cel.behaviourlayer.test:iCelBlLayer.Test", iCelBlLayer), CS_REQUEST_PLUGIN ("cel.persistence.xml", iCelPersistence), CS_REQUEST_PLUGIN ("cel.network.tcp", iCelGameFactory), CS_REQUEST_PLUGIN ("crystalspace.collisiondetection.opcode", iCollideSystem), CS_REQUEST_END)) { return ReportError ("Can't initialize plugins!"); } csBaseEventHandler::Initialize (object_reg); // Now we need to setup an event handler for our application. // Crystal Space is fully event-driven. Everything (except for this // initialization) happens in an event. if (!RegisterQueue (object_reg, csevAllEvents (object_reg))) return ReportError ("Can't setup event handler!"); return true; } bool NetTest::Application () { // Open the main system. This will open all the previously loaded plug-ins. // i.e. all windows will be opened. if (!OpenApplication (object_reg)) return ReportError ("Error opening system!"); // The virtual clock. vc = CS_QUERY_REGISTRY (object_reg, iVirtualClock); if (!vc) return ReportError ("Can't find the virtual clock!"); // Find the pointer to engine plugin engine = CS_QUERY_REGISTRY (object_reg, iEngine); if (!engine) return ReportError ("No iEngine plugin!"); loader = CS_QUERY_REGISTRY (object_reg, iLoader); if (!loader) return ReportError ("No iLoader plugin!"); g3d = CS_QUERY_REGISTRY (object_reg, iGraphics3D); if (!g3d) return ReportError ("No iGraphics3D plugin!"); g2d = g3d->GetDriver2D (); csRef fs = g3d->GetDriver2D()->GetFontServer (); if (!fs) return ReportError("Failed to locate font server!"); font = fs->LoadFont (CSFONT_LARGE); if (!font) return ReportError("Failed to locate font!"); kbd = CS_QUERY_REGISTRY (object_reg, iKeyboardDriver); if (!kbd) return ReportError ("No iKeyboardDriver plugin!"); pl = CS_QUERY_REGISTRY (object_reg, iCelPlLayer); if (!pl) return ReportError ("CEL physical layer missing!"); bltest = CS_QUERY_REGISTRY_TAG_INTERFACE (object_reg, "iCelBlLayer.Test", iCelBlLayer); if (!bltest) return ReportError ("CEL test behaviour layer missing!"); pl->RegisterBehaviourLayer (bltest); // initialize game factory game_factory = CS_QUERY_REGISTRY (object_reg, iCelGameFactory); if (!game_factory) return ReportError ("CEL network layer missing!"); game_factory->SetGameName ("CEL network test"); game_factory->SetProtocolVersion ("v0.1"); csRef vfs = CS_QUERY_REGISTRY (object_reg, iVFS); #if defined(VFS_PKGDATADIR) && defined(VFS_TOPSRCDIR) vfs->Mount ("cel", VFS_PKGDATADIR"$/, "VFS_TOPSRCDIR"$/"); #else // VFS_PKGDATADIR vfs->Mount ("cel", "$.$/"); #endif // VFS_PKGDATADIR // XXX: This should be in a config file... if (!pl->LoadPropertyClassFactory ("cel.pcfactory.test")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.linmove")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.actormove")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.solid")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.colldet")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.region")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.zonemanager")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.defaultcamera")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.tooltip")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.timer")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.inventory")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.characteristics")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.mesh")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.light")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.meshselect")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.pccommandinput")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.quest")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.properties")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.trigger")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.billboard")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.graph")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.link")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.node")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.navgraphrules")) return false; if (!pl->LoadPropertyClassFactory ("cel.pcfactory.navgraphrulesfps")) return false; // analyse command line arguments csRef cmdline = CS_QUERY_REGISTRY (object_reg, iCommandLineParser); // read level path and file csString level_path; csString level_file; level_path = cmdline->GetOption ("path"); if (!level_path.IsEmpty ()) { level_file = cmdline->GetOption ("file"); if (level_file.IsEmpty ()) level_file = "level.xml"; } else { level_path = "/cellib/lev"; level_file = "basic_world"; //level_file = "basic_level.xml"; } // read client-server type of this application // 0 means singleplayer, 1 means server, 2 means client, 3 means client + server + open to other players # define APP_SINGLEPLAYER 0 # define APP_SERVER 1 # define APP_CLIENT 2 # define APP_CLIENTSERVER 3 int app_type = APP_CLIENT; if (cmdline->GetOption ("server") != 0) { if (cmdline->GetOption ("client") != 0) app_type = APP_CLIENTSERVER; else app_type = APP_SERVER; } else if (cmdline->GetOption ("client") != 0) app_type = APP_CLIENT; else if (cmdline->GetOption ("singleplayer") != 0) app_type = APP_SINGLEPLAYER; // read player name csString player_name = cmdline->GetOption ("player"); // read server hostname csString server_hostname = cmdline->GetOption ("serverhost"); // register game factory manager gfm = new GameFactoryManager (this, game_factory, level_path, level_file); game_factory->RegisterGameFactoryManager (gfm); // create game info celGameInfo game_info; game_info.game_name = "Test game"; game_info.hostname = "127.0.0.1"; game_info.port_nb = 25000; game_info.password = "nice password"; game_info.max_players = 3; game_info.custom_data = pl->CreateDataBuffer (0); game_info.custom_data->Add (level_path); game_info.custom_data->Add (level_file); // create player celPlayer player; if (!player_name.IsEmpty()) player.player_name = player_name; else player.player_name = "Test player"; // launch networked game switch (app_type) { case APP_SINGLEPLAYER: csPrintf ("Creating singleplayer game with player %s\n", player.player_name.GetData ()); if (!game_factory->CreateNewGame (CEL_NET_SINGLEPLAYER, &game_info, &player)) return false; break; case APP_SERVER: csPrintf ("Creating server\n"); if (!game_factory->CreateNewGame (CEL_NET_LOCAL, &game_info)) return false; break; case APP_CLIENT: csPrintf ("Starting client with player %s\n", player.player_name.GetData ()); if (server_hostname && !server_hostname.IsEmpty ()) game_info.hostname = server_hostname; if (!game_factory->ConnectGame (&game_info, &player)) return false; break; case APP_CLIENTSERVER: csPrintf ("Starting client and server with player %s\n", player.player_name.GetData ()); if (!game_factory->CreateNewGame (CEL_NET_LOCAL, &game_info, &player)) return false; break; } // This calls the default runloop. This will basically just keep // broadcasting process events to keep the game going. Run (); return true; } void NetTest::WriteShadow (int align,int x,int y,int fg,char *str,...) { char buf[256]; va_list arg; va_start (arg, str); vsprintf (buf, str, arg); va_end (arg); Write (align, x+1, y-1, 0, -1, buf); Write (align, x, y, fg, -1, buf); } void NetTest::Write(int align,int x,int y,int fg,int bg,char *str,...) { va_list arg; char b[256], *buf = b; va_start (arg,str); int l = vsprintf (buf, str, arg); va_end (arg); if (align != 0) { int rb = 0; if (align == 1) { int where; sscanf (buf, "%d%n", &rb,&where); buf += where + 1; l -= where + 1; } int w, h; font->GetDimensions (buf, w, h); switch(align) { case 2: x -= w; break; case 1: x = (x + rb - w) / 2; break; } } g2d->Write (font, x, y, fg, bg, buf); }