1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434 |
- //
- // Copyright 2020 Electronic Arts Inc.
- //
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
- // software: you can redistribute it and/or modify it under the terms of
- // the GNU General Public License as published by the Free Software Foundation,
- // either version 3 of the License, or (at your option) any later version.
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
- // in the hope that it will be useful, but with permitted additional restrictions
- // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
- // distributed with this program. You should have received a copy of the
- // GNU General Public License along with permitted additional restrictions
- // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
- /* $Header: F:\projects\c&c\vcs\code\netdlg.cpv 2.17 16 Oct 1995 16:52:26 JOE_BOSTIC $ */
- /***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : Command & Conquer *
- * *
- * File Name : NETDLG.CPP *
- * *
- * Programmer : Bill Randolph *
- * *
- * Start Date : January 23, 1995 *
- * *
- * Last Update : July 8, 1995 [BRR] *
- * *
- *---------------------------------------------------------------------------------------------*
- * *
- * These routines establish & maintain peer-to-peer connections between this system *
- * and all others in the game. Each system finds out the IPX address of the others, *
- * and forms a direct connection (IPXConnectionClass) to that system. Systems are *
- * found out via broadcast queries. Every system broadcasts its queries, and every *
- * system replies to queries it receives. At the point when the game owner signals *
- * 'OK', every system must know about all the other systems in the game. *
- * *
- * How Bridges are handled: *
- * Currently, bridges are handled by specifying the destination IPX address of the *
- * "server" (game owner's system) on the command-line. This address is used to *
- * derive a broadcast address to that destination network, and this system's queries *
- * are broadcast over its network & the server's network; replies to the queries come *
- * with each system's IPX address attached, so once we have the address, we can form *
- * a connection with any system on the bridged net. *
- * *
- * The flaw in this plan is that we can only cross one bridge. If there are 3 nets *
- * bridged (A, B, & C), and the server is on net B, and we're on net A, our broadcasts *
- * will reach nets A & B, but not C. The way to circumvent this (if it becomes a problem) *
- * would be to have the server tell us what other systems are in its game, not each *
- * individual player's system. Thus, each system would find out about all the other systems *
- * by interacting with the game's owner system (this would be more involved than what *
- * I'm doing here). *
- * *
- * Here's a list of all the different packets sent over the Global Channel: *
- * *
- * NET_QUERY_GAME *
- * (no other data) *
- * NET_ANSWER_GAME *
- * Name: game owner's name *
- * GameInfo: game's version & open state *
- * NET_QUERY_PLAYER *
- * Name: name of game we want players to respond for *
- * NET_ANSWER_PLAYER *
- * Name: player's name *
- * PlayerInfo: info about player *
- * NET_QUERY_JOIN *
- * Name: name of player wanting to join *
- * PlayerInfo: player's requested house & color *
- * NET_CONFIRM_JOIN *
- * PlayerInfo: approves player's house & color *
- * NET_REJECT_JOIN *
- * (no other data) *
- * NET_GAME_OPTIONS *
- * ScenarioInfo: info about scenario *
- * NET_SIGN_OFF *
- * Name: name of player signing off *
- * NET_PING *
- * (no other data) *
- * NET_GO *
- * Delay: value of one-way response time, in frames *
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * Clear_Game_List -- Clears the game-name listbox & 'Games' Vector *
- * Clear_Player_List -- Clears the player-name listbox & Vector *
- * Destroy_Connection -- destroys the given connection *
- * Get_Join_Responses -- sends queries for the Join Dialog *
- * Get_NewGame_Responses -- processes packets for New Game dialog *
- * Init_Network -- initializes network stuff *
- * Net_Join_Dialog -- lets user join an existing game, or start a new one *
- * Net_New_Dialog -- lets user start a new game *
- * Process_Global_Packet -- responds to remote queries *
- * Remote_Connect -- handles connecting this user to others *
- * Request_To_Join -- Sends a JOIN request packet to game owner *
- * Send_Join_Queries -- sends queries for the Join Dialog *
- * Shutdown_Network -- shuts down network stuff *
- * Compute_Name_CRC -- computes CRC from char string *
- * Net_Reconnect_Dialog -- Draws/updates the network reconnect dialog *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "function.h"
- #include <time.h>
- #include "tcpip.h"
- #include "ccdde.h"
- #define SHOW_MONO 0
- // ST = 12/17/2018 5:44PM
- #ifndef TickCount
- extern TimerClass TickCount;
- #endif
- #ifndef DEMO
- /*---------------------------------------------------------------------------
- The possible states of the join-game dialog
- ---------------------------------------------------------------------------*/
- typedef enum {
- JOIN_REJECTED = -1, // we've been rejected
- JOIN_NOTHING, // we're not trying to join a game
- JOIN_WAIT_CONFIRM, // we're asking to join, & waiting for confirmation
- JOIN_CONFIRMED, // we've been confirmed
- JOIN_GAME_START, // the game we've joined is starting
- } JoinStateType;
- /*---------------------------------------------------------------------------
- The possible return codes from Get_Join_Responses()
- ---------------------------------------------------------------------------*/
- typedef enum {
- EV_NONE, // nothing happened
- EV_STATE_CHANGE, // Join dialog is in a new state
- EV_NEW_GAME, // a new game was detected
- EV_NEW_PLAYER, // a new player was detected
- EV_PLAYER_SIGNOFF, // a player has signed off
- EV_GAME_SIGNOFF, // a gamed owner has signed off
- EV_GAME_OPTIONS, // a game options packet was received
- EV_MESSAGE, // a message was received
- } JoinEventType;
- /*
- ******************************** Prototypes *********************************
- */
- static int Net_Join_Dialog(void);
- static void Clear_Game_List (ListClass *gamelist);
- static void Clear_Player_List (ListClass *playerlist);
- static int Request_To_Join (char *playername, int join_index, ListClass *playerlist,
- HousesType house, int color);
- static void Send_Join_Queries(int curgame, int gamenow, int playernow);
- static JoinEventType Get_Join_Responses(JoinStateType *joinstate, ListClass *gamelist,
- ColorListClass *playerlist, int join_index);
- static int Net_New_Dialog(void);
- static JoinEventType Get_NewGame_Responses(ColorListClass *playerlist);
- static int Net_Fake_New_Dialog(void);
- static int Net_Fake_Join_Dialog(void);
- /***********************************************************************************************
- * Init_Network -- initializes network stuff *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * true = Initialization OK, false = error *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 02/14/1995 BR : Created. *
- *=============================================================================================*/
- bool Init_Network (void)
- {
- NetNumType net;
- NetNodeType node;
- /*------------------------------------------------------------------------
- This call allocates all necessary queue buffers, allocates Real-mode
- memory, and commands IPX to start listening on the Global Channel.
- ------------------------------------------------------------------------*/
- if (!Ipx.Init())
- return(false);
- /*------------------------------------------------------------------------
- Allocate our "meta-packet" buffer
- ------------------------------------------------------------------------*/
- if (!MetaPacket) {
- MetaPacket = new char [sizeof (EventClass) * MAX_EVENTS];
- }
- /*------------------------------------------------------------------------
- Set up the IPX manager to cross a bridge
- ------------------------------------------------------------------------*/
- if (!(GameToPlay == GAME_INTERNET)){
- if (IsBridge) {
- BridgeNet.Get_Address(net,node);
- Ipx.Set_Bridge(net);
- }
- }
- return(true);
- } /* end of Init_Network */
- /***********************************************************************************************
- * Shutdown_Network -- shuts down network stuff *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 02/14/1995 BR : Created. *
- *=============================================================================================*/
- void Shutdown_Network (void)
- {
- //
- // Note: The thought behind this section of code was that if the program
- // terminates early, without an EventClass::EXIT event, it still needs to
- // tell the other systems that it's gone, so it would send a SIGN_OFF packet.
- // BUT, this causes a sync bug if the systems are running slow and this system
- // is running ahead of the others; it will send the NET_SIGN_OFF >>before<<
- // the other system execute their EventClass::EXIT event, and the other systems
- // will kill the connection at some random Frame # & turn my stuff over to
- // the computer possibly at different times.
- // BRR, 10/29/96
- //
- #if (0)
- /*------------------------------------------------------------------------
- Broadcast a sign-off packet, by sending the packet over the Global Channel,
- telling the IPX Manager that no ACK is required, and specifying a NULL
- destination address.
- ------------------------------------------------------------------------*/
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_SIGN_OFF;
- strcpy (GPacket.Name, MPlayerName);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType), 0, NULL);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType), 0, NULL);
- if (IsBridge && !Winsock.Get_Connected()) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0, &BridgeNet);
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0, &BridgeNet);
- }
- /*------------------------------------------------------------------------
- Wait for the packets to finish going out (or the Global Channel times out)
- ------------------------------------------------------------------------*/
- for (;;) {
- if (Ipx.Global_Num_Send()==0) {
- break;
- }
- Ipx.Service();
- }
- #endif //(0)
- /*------------------------------------------------------------------------
- Delete our "meta-packet"
- ------------------------------------------------------------------------*/
- delete [] MetaPacket;
- MetaPacket = 0;
- /*------------------------------------------------------------------------
- If I was in a game, I'm not now, so clear the game name
- ------------------------------------------------------------------------*/
- MPlayerGameName[0] = 0;
- }
- /***********************************************************************************************
- * Process_Global_Packet -- responds to remote queries *
- * *
- * The only commands from other systems this routine responds to are NET_QUERY_GAME *
- * and NET_QUERY_PLAYER. The other commands are too context-specific to be able *
- * to handle here, such as joining the game or signing off; but this routine handles *
- * the majority of the program's needs. *
- * *
- * INPUT: *
- * packet ptr to packet to process *
- * address source address of sender *
- * *
- * OUTPUT: *
- * true = packet was processed, false = wasn't *
- * *
- * WARNINGS: *
- * MPlayerName & MPlayerGameName must have been filled in before this function *
- * can be called. *
- * *
- * HISTORY: *
- * 02/15/1995 BR : Created. *
- *=============================================================================================*/
- bool Process_Global_Packet(GlobalPacketType *packet, IPXAddressClass *address)
- {
- GlobalPacketType mypacket;
- /*
- ---------------- Another system asking what game this is -----------------
- */
- if (packet->Command==NET_QUERY_GAME && NetStealth==0) {
- /*.....................................................................
- If the game is closed, let every player respond, and let the sender of
- the query sort it all out. This way, if the game's host exits the game,
- the game still shows up on other players' dialogs.
- If the game is open, only the game owner may respond.
- .....................................................................*/
- if (strlen(MPlayerName) > 0 && strlen(MPlayerGameName) > 0 &&
- ((!NetOpen) || (NetOpen && !strcmp(MPlayerName,MPlayerGameName)))) {
- memset (packet, 0, sizeof(GlobalPacketType));
- mypacket.Command = NET_ANSWER_GAME;
- strcpy(mypacket.Name, MPlayerGameName);
- #ifdef PATCH
- if (IsV107) {
- mypacket.GameInfo.Version = 1;
- } else {
- mypacket.GameInfo.Version = 2;
- }
- #else
- mypacket.GameInfo.Version = Version_Number();
- #endif
- mypacket.GameInfo.IsOpen = NetOpen;
- Ipx.Send_Global_Message (&mypacket, sizeof(GlobalPacketType), 1,
- address);
- }
- return(true);
- } else {
- /*
- ----------------- Another system asking what player I am -----------------
- */
- if (packet->Command==NET_QUERY_PLAYER &&
- !strcmp (packet->Name, MPlayerGameName) &&
- (strlen(MPlayerGameName) > 0) && NetStealth==0) {
- memset (packet, 0, sizeof(GlobalPacketType));
- mypacket.Command = NET_ANSWER_PLAYER;
- strcpy(mypacket.Name, MPlayerName);
- mypacket.PlayerInfo.House = MPlayerHouse;
- mypacket.PlayerInfo.Color = MPlayerColorIdx;
- mypacket.PlayerInfo.NameCRC = Compute_Name_CRC(MPlayerGameName);
- Ipx.Send_Global_Message (&mypacket, sizeof(GlobalPacketType), 1, address);
- return(true);
- }
- }
- return(false);
- }
- /***********************************************************************************************
- * Destroy_Connection -- destroys the given connection *
- * *
- * Call this routine when a connection goes bad, or another player signs off. *
- * *
- * INPUT: *
- * id connection ID to destroy *
- * error 0 = user signed off; 1 = connection error; otherwise, no error is shown. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 04/22/1995 BR : Created. *
- *=============================================================================================*/
- void Destroy_Connection(int id, int error)
- {
- int i,j;
- HousesType house;
- HouseClass *housep;
- char txt[80];
- /*------------------------------------------------------------------------
- Create a message to display to the user
- ------------------------------------------------------------------------*/
- txt[0] = '\0';
- if (error==1) {
- sprintf(txt,Text_String(TXT_CONNECTION_LOST),Ipx.Connection_Name(id));
- } else if (error==0) {
- sprintf(txt,Text_String(TXT_LEFT_GAME),Ipx.Connection_Name(id));
- }
- if (strlen(txt)) {
- Messages.Add_Message (txt,
- MPlayerTColors[MPlayerID_To_ColorIndex((unsigned char)id)],
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 600, 0, 0);
- Map.Flag_To_Redraw(false);
- }
- /*------------------------------------------------------------------------
- Delete the IPX connection, shift the MPlayerID's & MPlayerHouses' back one.
- ------------------------------------------------------------------------*/
- Ipx.Delete_Connection(id);
- for (i = 0; i < MPlayerCount; i++) {
- if (MPlayerID[i] == (unsigned char)id) {
- /*..................................................................
- Turn the player's house over to the computer's AI
- ..................................................................*/
- house = MPlayerHouses[i];
- housep = HouseClass::As_Pointer (house);
- housep->IsHuman = false;
- housep->IsStarted = true;
- /*..................................................................
- Move arrays back by one
- ..................................................................*/
- for (j = i; j < MPlayerCount - 1; j++) {
- MPlayerID[j] = MPlayerID[j + 1];
- MPlayerHouses[j] = MPlayerHouses[j + 1];
- strcpy (MPlayerNames[j], MPlayerNames[j+1]);
- TheirProcessTime[j] = TheirProcessTime[j+1];
- }
- }
- }
- MPlayerCount--;
- /*------------------------------------------------------------------------
- If we're the last player left, tell the user.
- ------------------------------------------------------------------------*/
- if (MPlayerCount == 1) {
- sprintf(txt,"%s",Text_String(TXT_JUST_YOU_AND_ME));
- Messages.Add_Message (txt,
- MPlayerTColors[MPlayerID_To_ColorIndex((unsigned char)id)],
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 600, 0, 0);
- Map.Flag_To_Redraw(false);
- }
- } /* end of Destroy_Connection */
- /***********************************************************************************************
- * Remote_Connect -- handles connecting this user to others *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * true = connections established; false = not *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 02/14/1995 BR : Created. *
- *=============================================================================================*/
- bool Remote_Connect(void)
- {
- int rc;
- int stealth; // original state of NetStealth flag
- /*------------------------------------------------------------------------
- Init network timing parameters; these values should work for both a "real"
- network, and a simulated modem network (ie Kali)
- ------------------------------------------------------------------------*/
- Ipx.Set_Timing ( 30, // retry 2 times per second
- -1, // ignore max retries
- 600); // give up after 10 seconds
- /*------------------------------------------------------------------------
- Save the original value of the NetStealth flag, so we can turn stealth
- off for now (during this portion of the dialogs, we must show ourselves)
- ------------------------------------------------------------------------*/
- stealth = NetStealth;
- NetStealth = 0;
- /*------------------------------------------------------------------------
- Init my game name to 0-length, since I haven't joined any game yet.
- ------------------------------------------------------------------------*/
- MPlayerGameName[0] = 0;
- /*------------------------------------------------------------------------
- The game is now "open" for joining. Close it as soon as we exit this
- routine.
- ------------------------------------------------------------------------*/
- NetOpen = 1;
- /*------------------------------------------------------------------------
- Read the default values from the INI file
- ------------------------------------------------------------------------*/
- Read_MultiPlayer_Settings ();
- /*------------------------------------------------------------------------
- Keep looping until something useful happens.
- ------------------------------------------------------------------------*/
- while (1) {
- /*---------------------------------------------------------------------
- Pop up the network Join/New dialog
- ---------------------------------------------------------------------*/
- rc = Net_Join_Dialog();
- /*---------------------------------------------------------------------
- -1 = user selected Cancel
- ---------------------------------------------------------------------*/
- if (rc==-1) {
- NetStealth = stealth;
- NetOpen = 0;
- return(false);
- } else {
- /*---------------------------------------------------------------------
- 0 = user has joined an existing game; save values & return
- ---------------------------------------------------------------------*/
- if (rc==0) {
- Write_MultiPlayer_Settings ();
- NetStealth = stealth;
- NetOpen = 0;
- return(true);
- } else {
- /*---------------------------------------------------------------------
- 1 = user requests New Network Game
- ---------------------------------------------------------------------*/
- if (rc==1) {
- /*..................................................................
- Pop up the New Network Game dialog; if user selects OK, return
- 'true'; otherwise, return to the Join Dialog.
- ..................................................................*/
- if (Net_New_Dialog()) {
- Write_MultiPlayer_Settings ();
- NetOpen = 0;
- NetStealth = stealth;
- NetOpen = 0;
- return(true);
- } else {
- continue;
- }
- }
- }
- }
- }
- }
- /***********************************************************************************************
- * Remote_Connect -- handles connecting this host to the server in an internet game *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * true = connections established; false = not *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 02/14/1995 BR : Created. *
- *=============================================================================================*/
- bool Server_Remote_Connect(void)
- {
- int stealth; // original state of NetStealth flag
- /*------------------------------------------------------------------------
- Init network timing parameters; these values should work for both a "real"
- network, and a simulated modem network (ie Kali)
- ------------------------------------------------------------------------*/
- Ipx.Set_Timing ( 30, // retry 2 times per second
- -1, // ignore max retries
- 600); // give up after 10 seconds
- /*------------------------------------------------------------------------
- Save the original value of the NetStealth flag, so we can turn stealth
- off for now (during this portion of the dialogs, we must show ourselves)
- ------------------------------------------------------------------------*/
- stealth = NetStealth;
- NetStealth = 0;
- /*------------------------------------------------------------------------
- The game is now "open" for joining. Close it as soon as we exit this
- routine.
- ------------------------------------------------------------------------*/
- NetOpen = 1;
- /*------------------------------------------------------------------------
- Read the default values from the INI file
- ------------------------------------------------------------------------*/
- Read_MultiPlayer_Settings ();
- if (!Net_Fake_New_Dialog()){
- Write_MultiPlayer_Settings ();
- return (false);
- }
- NetOpen = 0;
- NetStealth = stealth;
- Write_MultiPlayer_Settings ();
- return (true);
- }
- /***********************************************************************************************
- * Client_Remote_Connect -- handles connecting this client to the server in an internet game *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * true = connections established; false = not *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 02/14/1995 ST : Created. *
- *=============================================================================================*/
- bool Client_Remote_Connect(void)
- {
- int rc;
- int stealth; // original state of NetStealth flag
- /*------------------------------------------------------------------------
- Init network timing parameters; these values should work for both a "real"
- network, and a simulated modem network (ie Kali)
- ------------------------------------------------------------------------*/
- Ipx.Set_Timing ( 30, // retry 2 times per second
- -1, // ignore max retries
- 600); // give up after 10 seconds
- /*------------------------------------------------------------------------
- Save the original value of the NetStealth flag, so we can turn stealth
- off for now (during this portion of the dialogs, we must show ourselves)
- ------------------------------------------------------------------------*/
- stealth = NetStealth;
- NetStealth = 0;
- /*------------------------------------------------------------------------
- The game is now "open" for joining. Close it as soon as we exit this
- routine.
- ------------------------------------------------------------------------*/
- NetOpen = 1;
- /*------------------------------------------------------------------------
- Read the default values from the INI file
- ------------------------------------------------------------------------*/
- Read_MultiPlayer_Settings ();
- /*---------------------------------------------------------------------
- Pop up the network Join/New dialog
- ---------------------------------------------------------------------*/
- rc = Net_Fake_Join_Dialog();
- Write_MultiPlayer_Settings ();
- NetStealth = stealth;
- NetOpen = 0;
- if (rc == -1) {
- return(false);
- } else {
- return(true);
- }
- }
- /***********************************************************************************************
- * Net_Join_Dialog -- lets user join an existing game or start a new one *
- * *
- * This dialog displays an edit field for the player's name, and a list of all non-stealth- *
- * mode games. Clicking once on a game name displays a list of who's in that game. Clicking *
- * "New" takes the user to the Net_New dialog, where he waits for other users to join his *
- * game. All other input is done through this dialog. *
- * *
- * The dialog has several "states": *
- * *
- * 1) Initially, it waits for the user to fill in his/her name and then to select Join or New; *
- * if New is selected, this dialog is exited. *
- * *
- * 2) If Join is selected, the Join & New buttons are removed, but the Cancel button remains. *
- * The join request is transmitted to the game's owner, and the message "Waiting for *
- * Confirmation" is displayed, until a confirmation or denial is received from the game's *
- * owner. The user may click Cancel at this point to cancel the join request. *
- * (Once Join is selected, the name editing field is disabled, and becomes a display-only *
- * field. If cancel is selected, it reappears as an edit field.) The user can still click *
- * around & see who's in which games. *
- * *
- * 3) If the join request is denied, the dialog re-initializes to its pre-join state; the *
- * Join & New buttons reappear, & the Name field is available again. *
- * *
- * 4) If join confirmation is obtained, the message just changes to "Confirmed. Waiting for *
- * Entry Signal." or some such nonsense. The user can still click around & see who's *
- * in which games. *
- * *
- * Any game running in Stealth mode won't show up on this dialog. *
- * *
- * ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ *
- * ³ Network Games ³ *
- * ³ ³ *
- * ³ Your Name: ____________ ³ *
- * ³ House: [GDI] [NOD] ³ *
- * ³ Desired Color: [ ][ ][ ][ ] ³ *
- * ³ ³ *
- * ³ Games Players ³ *
- * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ³ *
- * ³ ³(Bill's Game )³³ ³ Peter Parker GDI ³³ ³ *
- * ³ ³ Peter Parker's Game ÃÄ´ ³ Mary Jane GDI ÃÄ´ ³ *
- * ³ ³(Magnum PI's Game )³ ³ ³ JJ Jameson NOD ³ ³ ³ *
- * ³ ³ ÃÄ´ ³ ÃÄ´ ³ *
- * ³ ³ ³³ ³ ³³ ³ *
- * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ³ *
- * ³ Scenario: Big Long Description ³ *
- * ³ Starting Credits: xxxx ³ *
- * ³ Count: --- Level: --- ³ *
- * ³ Bases: ON Crates: ON ³ *
- * ³ Tiberium: ON AI Players: ON ³ *
- * ³ ³ *
- * ³ [Join] [Cancel] [New] ³ *
- * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ *
- * ³ ³ ³ ³ *
- * ³ ³ ³ ³ *
- * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ *
- * ³ [Send Message] ³ *
- * ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * -1 = cancel, 0 = OK, 1 = New net game requested *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 02/14/1995 BR : Created. *
- *=============================================================================================*/
- static int Net_Join_Dialog(void)
- {
- int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
- /*........................................................................
- Dialog & button dimensions
- ........................................................................*/
- /* ###Change collision detected! C:\PROJECTS\CODE\NETDLG.CPP... */
- int d_dialog_w = 287 *factor; // dialog width
- int d_dialog_h = 198*factor; // dialog height
- int d_dialog_x = ((320*factor - d_dialog_w) / 2); // dialog x-coord
- int d_dialog_y = ((200*factor - d_dialog_h) / 2); // centered y-coord
- int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
- int d_txt6_h = 6*factor+1; // ht of 6-pt text
- int d_margin1 = 5*factor; // large margin
- int d_margin2 = 2*factor; // small margin
- int d_name_w = 70*factor;
- int d_name_h = 9*factor;
- int d_name_x = d_dialog_cx - 10*factor;
- int d_name_y = d_dialog_y + d_margin1 + d_txt6_h + d_txt6_h;
- int d_gdi_w = 30*factor;
- int d_gdi_h = 9*factor;
- int d_gdi_x = d_dialog_cx - 10*factor;
- int d_gdi_y = d_name_y + d_name_h + d_margin2;
- int d_nod_w = 30*factor;
- int d_nod_h = 9*factor;
- int d_nod_x = d_gdi_x + d_gdi_w;
- int d_nod_y = d_name_y + d_name_h + d_margin2;
- int d_color_w = 10*factor;
- int d_color_h = 9*factor;
- int d_color_y = d_nod_y + d_nod_h + d_margin2;
- int d_gamelist_w = 160*factor;
- int d_gamelist_h = 27*factor;
- int d_gamelist_x = d_dialog_x + d_margin1;
- int d_gamelist_y = d_color_y + d_color_h + d_margin1 + d_txt6_h;
- int d_playerlist_w = 106*factor;
- int d_playerlist_h = 27*factor;
- int d_playerlist_x = d_dialog_x + d_dialog_w - d_margin1 - d_playerlist_w;
- int d_playerlist_y = d_color_y + d_color_h + d_margin1 + d_txt6_h;
- int d_msg1_y = d_gamelist_y + d_gamelist_h + d_margin1;
- int d_msg2_y = d_msg1_y + d_txt6_h;
- int d_msg3_y = d_msg2_y + d_txt6_h;
- int d_msg4_y = d_msg3_y + d_txt6_h;
- int d_msg5_y = d_msg4_y + d_txt6_h;
- int d_join_w = 40*factor;
- int d_join_h = 9*factor;
- int d_join_x = d_dialog_x + (d_dialog_w / 6) - (d_join_w / 2);
- int d_join_y = d_msg5_y + d_txt6_h + d_margin1;
- #if (GERMAN | FRENCH)
- int d_cancel_w = 50*factor;
- #else
- int d_cancel_w = 40*factor;
- #endif
- int d_cancel_h = 9*factor;
- int d_cancel_x = d_dialog_cx - d_cancel_w / 2;
- int d_cancel_y = d_msg5_y + d_txt6_h + d_margin1;
- int d_new_w = 40*factor;
- int d_new_h = 9*factor;
- int d_new_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_new_w / 2);
- int d_new_y = d_msg5_y + d_txt6_h + d_margin1;
- int d_message_w = d_dialog_w - (d_margin1 * 2);
- int d_message_h = 34*factor;
- int d_message_x = d_dialog_x + d_margin1;
- int d_message_y = d_cancel_y + d_cancel_h + d_margin1;
- int d_send_w = 80*factor;
- int d_send_h = 9*factor;
- int d_send_x = d_dialog_cx - (d_send_w / 2);
- int d_send_y = d_message_y + d_message_h + d_margin2;
- /*........................................................................
- Button Enumerations
- ........................................................................*/
- enum {
- BUTTON_NAME = 100,
- BUTTON_GDI,
- BUTTON_NOD,
- BUTTON_GAMELIST,
- BUTTON_PLAYERLIST,
- BUTTON_JOIN,
- BUTTON_CANCEL,
- BUTTON_NEW,
- BUTTON_SEND,
- };
- /*........................................................................
- Redraw values: in order from "top" to "bottom" layer of the dialog
- ........................................................................*/
- typedef enum {
- REDRAW_NONE = 0,
- REDRAW_MESSAGE,
- REDRAW_COLORS,
- REDRAW_BUTTONS,
- REDRAW_BACKGROUND,
- REDRAW_ALL = REDRAW_BACKGROUND
- } RedrawType;
- /*........................................................................
- Dialog variables
- ........................................................................*/
- RedrawType display = REDRAW_ALL; // redraw level
- bool process = true; // process while true
- KeyNumType input;
- int cbox_x[] = { d_gdi_x,
- d_gdi_x + d_color_w,
- d_gdi_x + (d_color_w * 2),
- d_gdi_x + (d_color_w * 3),
- d_gdi_x + (d_color_w * 4),
- d_gdi_x + (d_color_w * 5)};
- JoinStateType joinstate = JOIN_NOTHING; // current "state" of this dialog
- char namebuf[MPLAYER_NAME_MAX] = {0}; // buffer for player's name
- int tabs[] = {77*factor}; // tabs for player list box
- int game_index = -1; // index of currently-selected game
- int join_index = -1; // index of game we're joining
- int rc = 0; // -1 = user cancelled, 1 = New
- JoinEventType event; // event from incoming packet
- int i,j; // loop counter
- char txt[80];
- char const *p;
- int parms_received; // 1 = game options received
- int found;
- unsigned char tmp_id[MAX_PLAYERS]; // temp storage for sorting player ID's
- int min_index; // for sorting player ID's
- unsigned char min_id; // for sorting player ID's
- unsigned char id; // connection ID
- char * item;
- unsigned long starttime;
- NodeNameType *who;
- int message_length;
- int sent_so_far;
- unsigned short magic_number;
- unsigned short crc;
- void const *up_button;
- void const *down_button;
- if (InMainLoop){
- up_button = Hires_Retrieve("BTN-UP.SHP");
- down_button = Hires_Retrieve("BTN-DN.SHP");
- }else{
- up_button = Hires_Retrieve("BTN-UP2.SHP");
- down_button = Hires_Retrieve("BTN-DN2.SHP");
- }
- /*........................................................................
- Buttons
- ........................................................................*/
- GadgetClass *commands; // button list
- EditClass name_edt (BUTTON_NAME,
- namebuf, MPLAYER_NAME_MAX, TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_name_x, d_name_y, d_name_w, d_name_h, EditClass::ALPHANUMERIC);
- TextButtonClass gdibtn(BUTTON_GDI, TXT_G_D_I,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_gdi_x, d_gdi_y, d_gdi_w, d_gdi_h);
- TextButtonClass nodbtn(BUTTON_NOD, TXT_N_O_D,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_nod_x, d_nod_y, d_nod_w, d_nod_h);
- ListClass gamelist(BUTTON_GAMELIST,
- d_gamelist_x, d_gamelist_y, d_gamelist_w, d_gamelist_h,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- up_button,
- down_button);
- ColorListClass playerlist(BUTTON_PLAYERLIST,
- d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- up_button,
- down_button);
- TextButtonClass joinbtn(BUTTON_JOIN, TXT_JOIN,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- #ifdef FRENCH
- d_join_x, d_join_y);
- #else
- d_join_x, d_join_y, d_join_w, d_join_h);
- #endif
- TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- //#if (GERMAN | FRENCH)
- // d_cancel_x, d_cancel_y);
- //#else
- d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
- //#endif
- TextButtonClass newbtn(BUTTON_NEW, TXT_NEW,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_new_x, d_new_y, d_new_w, d_new_h);
- TextButtonClass sendbtn(BUTTON_SEND, TXT_SEND_MESSAGE,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- //#if (GERMAN | FRENCH)
- // d_send_x, d_send_y);
- //#else
- d_send_x, d_send_y, d_send_w, d_send_h);
- //#endif
- playerlist.Set_Tabs(tabs);
- /*
- ----------------------------- Various Inits ------------------------------
- */
- MPlayerColorIdx = MPlayerPrefColor; // init my preferred color
- strcpy (namebuf, MPlayerName); // set my name
- name_edt.Set_Text(namebuf,MPLAYER_NAME_MAX);
- name_edt.Set_Color (MPlayerTColors[MPlayerColorIdx]);
- playerlist.Set_Selected_Style(ColorListClass::SELECT_NONE);
- if (MPlayerHouse==HOUSE_GOOD) {
- gdibtn.Turn_On();
- } else {
- nodbtn.Turn_On();
- }
- Fancy_Text_Print("", 0, 0, CC_GREEN, TBLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- Messages.Init (d_message_x + 2, d_message_y + 2, 4,
- MAX_MESSAGE_LENGTH, d_txt6_h);
- /*
- --------------------------- Send network query ---------------------------
- */
- Send_Join_Queries (game_index, 1, 0);
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- Blit_Hid_Page_To_Seen_Buff();
- Set_Palette(Palette);
- /*
- ---------------------------- Init Mono Output ----------------------------
- */
- #if(SHOW_MONO)
- Ipx.Configure_Debug(-1, sizeof (GlobalHeaderType),
- sizeof(NetCommandType), GlobalPacketNames, 11);
- Ipx.Mono_Debug_Print(-1,1);
- #endif
- while (Get_Mouse_State() > 0) Show_Mouse();
- /*
- ---------------------------- Processing loop -----------------------------
- */
- while (process) {
- /*
- ** If we have just received input focus again after running in the background then
- ** we need to redraw.
- */
- if (AllSurfaces.SurfacesRestored){
- AllSurfaces.SurfacesRestored=FALSE;
- display=REDRAW_ALL;
- }
- #if(SHOW_MONO)
- Ipx.Mono_Debug_Print(-1,0);
- #endif
- /*
- ...................... Refresh display if needed ......................
- */
- if (display) {
- Hide_Mouse();
- /*
- .................. Redraw backgound & dialog box ...................
- */
- if (display >= REDRAW_BACKGROUND) {
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- Blit_Hid_Page_To_Seen_Buff();
- Set_Palette(Palette);
- Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
- /*...............................................................
- Dialog & Field labels
- ...............................................................*/
- Draw_Caption (TXT_JOIN_NETWORK_GAME, d_dialog_x, d_dialog_y, d_dialog_w);
- Fancy_Text_Print(TXT_YOUR_NAME,
- d_name_x - 5, d_name_y + 1, CC_GREEN, TBLACK,
- TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- Fancy_Text_Print(TXT_SIDE_COLON,
- d_gdi_x - 5, d_gdi_y + 1, CC_GREEN, TBLACK,
- TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- Fancy_Text_Print(TXT_COLOR_COLON,
- cbox_x[0] - 5, d_color_y + 1, CC_GREEN, TBLACK,
- TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- Fancy_Text_Print(TXT_GAMES,
- d_gamelist_x + (d_gamelist_w / 2), d_gamelist_y - d_txt6_h,
- CC_GREEN, TBLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- Fancy_Text_Print(TXT_PLAYERS,
- d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h,
- CC_GREEN, TBLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- /*...............................................................
- Join-state-specific labels:
- ...............................................................*/
- if (joinstate > JOIN_NOTHING) {
- Fancy_Text_Print(namebuf, d_name_x, d_name_y + 1, CC_GREEN,
- TBLACK, TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- if (MPlayerHouse==HOUSE_GOOD) {
- Fancy_Text_Print(TXT_G_D_I, d_gdi_x, d_gdi_y + 1, CC_GREEN,
- TBLACK, TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- } else {
- Fancy_Text_Print(TXT_N_O_D, d_gdi_x, d_gdi_y + 1, CC_GREEN,
- TBLACK, TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- }
- }
- /*
- .................... Rebuild the button list ....................
- */
- cancelbtn.Zap();
- gamelist.Zap();
- playerlist.Zap();
- gdibtn.Zap();
- nodbtn.Zap();
- name_edt.Zap();
- joinbtn.Zap();
- newbtn.Zap();
- sendbtn.Zap();
- commands = &cancelbtn;
- gamelist.Add_Tail(*commands);
- playerlist.Add_Tail(*commands);
- /*...............................................................
- Only add the name edit field, the House, Join & New buttons if
- we're doing nothing, or we've just been rejected.
- ...............................................................*/
- if (joinstate <= JOIN_NOTHING) {
- gdibtn.Add_Tail(*commands);
- nodbtn.Add_Tail(*commands);
- name_edt.Add_Tail(*commands);
- joinbtn.Add_Tail(*commands);
- newbtn.Add_Tail(*commands);
- }
- if (joinstate == JOIN_CONFIRMED)
- sendbtn.Add_Tail(*commands);
- }
- /*
- .......................... Redraw buttons ..........................
- */
- if (display >= REDRAW_BUTTONS) {
- commands->Draw_All();
- }
- /*..................................................................
- Draw the color boxes
- ..................................................................*/
- if (display >= REDRAW_COLORS) {
- for (i = 0; i < MAX_MPLAYER_COLORS; i++) {
- LogicPage->Fill_Rect (cbox_x[i] + 1, d_color_y + 1,
- cbox_x[i] + 1 + d_color_w - 2, d_color_y + 1 + d_color_h - 2,
- MPlayerGColors[i]);
- if (i == MPlayerColorIdx) {
- Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h,
- BOXSTYLE_GREEN_DOWN, false);
- } else {
- Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h,
- BOXSTYLE_GREEN_RAISED, false);
- }
- }
- }
- /*..................................................................
- Draw the message:
- - Erase an old message first
- - If we're in a game, print the game options (if they've been
- received)
- - If we've been rejected from a game, print that message
- ..................................................................*/
- if (display >= REDRAW_MESSAGE) {
- Draw_Box(d_message_x, d_message_y, d_message_w, d_message_h,
- BOXSTYLE_GREEN_BORDER, true);
- Messages.Draw();
- LogicPage->Fill_Rect( d_dialog_x + 2,
- d_msg1_y,
- d_dialog_x + d_dialog_w - 4,
- d_msg5_y + d_txt6_h,
- BLACK);
- if (joinstate==JOIN_CONFIRMED && parms_received) {
- /*............................................................
- Scenario title
- ............................................................*/
- p = Text_String(TXT_SCENARIO_COLON);
- if (ScenarioIdx != -1) {
- sprintf(txt,"%s %s",p, MPlayerScenarios[ScenarioIdx]);
- Fancy_Text_Print (txt, d_dialog_cx,
- d_msg1_y, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW | TPF_CENTER);
- } else {
- sprintf(txt,"%s %s",p,Text_String(TXT_NOT_FOUND));
- Fancy_Text_Print (txt, d_dialog_cx,
- d_msg1_y, CC_NOD_COLOR, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW | TPF_CENTER);
- }
- /*............................................................
- # of credits
- ............................................................*/
- p = Text_String(TXT_START_CREDITS_COLON);
- sprintf(txt, "%s %d", p, MPlayerCredits);
- Fancy_Text_Print (txt, d_dialog_cx,
- d_msg2_y, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW | TPF_CENTER);
- /*............................................................
- Count & Level values
- ............................................................*/
- p = Text_String(TXT_COUNT);
- sprintf(txt,"%s %d",p,MPlayerUnitCount);
- Fancy_Text_Print (txt,
- d_dialog_x + (d_dialog_w / 4) - String_Pixel_Width(p),
- d_msg3_y, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- p = Text_String(TXT_LEVEL);
- if (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {
- sprintf(txt, "%s %d", p, BuildLevel);
- } else {
- sprintf(txt, "%s **", p);
- }
- Fancy_Text_Print (txt,
- d_dialog_x + d_dialog_w - (d_dialog_w / 4) - String_Pixel_Width(p),
- d_msg3_y, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- /*............................................................
- Bases
- ............................................................*/
- p = Text_String(TXT_BASES_COLON);
- if (MPlayerBases) {
- sprintf(txt,"%s %s",p,Text_String(TXT_ON));
- } else {
- sprintf(txt,"%s %s",p,Text_String(TXT_OFF));
- }
- Fancy_Text_Print (txt,
- d_dialog_x + (d_dialog_w / 4) - String_Pixel_Width(p),
- d_msg4_y, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- /*............................................................
- Tiberium
- ............................................................*/
- p = Text_String(TXT_TIBERIUM_COLON);
- if (MPlayerTiberium) {
- sprintf(txt,"%s %s",p,Text_String(TXT_ON));
- } else {
- sprintf(txt,"%s %s",p,Text_String(TXT_OFF));
- }
- Fancy_Text_Print (txt,
- d_dialog_x + (d_dialog_w / 4) - String_Pixel_Width(p),
- d_msg5_y, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- /*............................................................
- Goody boxes
- ............................................................*/
- p = Text_String(TXT_CRATES_COLON);
- if (MPlayerGoodies) {
- sprintf(txt,"%s %s",p,Text_String(TXT_ON));
- } else {
- sprintf(txt,"%s %s",p,Text_String(TXT_OFF));
- }
- Fancy_Text_Print (txt,
- d_dialog_x + d_dialog_w - (d_dialog_w / 4) - String_Pixel_Width(p),
- d_msg4_y, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- /*............................................................
- Computer AI players
- ............................................................*/
- if (Special.IsCaptureTheFlag) {
- p = Text_String(TXT_CAPTURE_THE_FLAG_COLON);
- sprintf(txt,"%s %s",p,Text_String(TXT_ON));
- } else {
- p = Text_String(TXT_AI_PLAYERS_COLON);
- if (MPlayerGhosts) {
- sprintf(txt,"%s %s",p,Text_String(TXT_ON));
- } else {
- sprintf(txt,"%s %s",p,Text_String(TXT_OFF));
- }
- }
- Fancy_Text_Print (txt,
- d_dialog_x + d_dialog_w - (d_dialog_w / 4) - String_Pixel_Width(p),
- d_msg5_y, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- } else {
- /*...............................................................
- Rejection notice
- ...............................................................*/
- if (joinstate==JOIN_REJECTED) {
- Fancy_Text_Print(TXT_REQUEST_DENIED,
- d_dialog_cx, d_msg3_y, CC_GREEN, TBLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- }
- }
- }
- Show_Mouse();
- display = REDRAW_NONE;
- }
- /*
- ........................... Get user input ............................
- */
- input = commands->Input();
- /*
- ---------------------------- Process input ----------------------------
- */
- switch (input) {
- /*------------------------------------------------------------------
- User clicks on a color button:
- - If we've joined a game, don't allow a new color selection
- - otherwise, select that color
- ------------------------------------------------------------------*/
- case KN_LMOUSE:
- if (joinstate > JOIN_NOTHING)
- break;
- if (_Kbd->MouseQX > cbox_x[0] &&
- _Kbd->MouseQX < (cbox_x[MAX_MPLAYER_COLORS - 1] + d_color_w) &&
- _Kbd->MouseQY > d_color_y &&
- _Kbd->MouseQY < (d_color_y + d_color_h)) {
- MPlayerPrefColor = (_Kbd->MouseQX - cbox_x[0]) / d_color_w;
- MPlayerColorIdx = MPlayerPrefColor;
- name_edt.Set_Color (MPlayerTColors[MPlayerColorIdx]);
- name_edt.Flag_To_Redraw();
- display = REDRAW_COLORS;
- }
- break;
- /*------------------------------------------------------------------
- User clicks on the game list:
- - If we've joined a game, don't allow the selected item to change;
- otherwise:
- - Clear the player list
- - Send an immediate player query
- ------------------------------------------------------------------*/
- case (BUTTON_GAMELIST | KN_BUTTON):
- if (joinstate==JOIN_CONFIRMED) {
- gamelist.Set_Selected_Index(game_index);
- } else {
- if (gamelist.Current_Index() != game_index) {
- Clear_Player_List (&playerlist);
- game_index = gamelist.Current_Index();
- Send_Join_Queries (game_index, 0, 1);
- }
- }
- break;
- /*------------------------------------------------------------------
- House Buttons: set the player's desired House
- ------------------------------------------------------------------*/
- case (BUTTON_GDI | KN_BUTTON):
- MPlayerHouse = HOUSE_GOOD;
- gdibtn.Turn_On();
- nodbtn.Turn_Off();
- break;
- case (BUTTON_NOD | KN_BUTTON):
- MPlayerHouse = HOUSE_BAD;
- gdibtn.Turn_Off();
- nodbtn.Turn_On();
- break;
- /*------------------------------------------------------------------
- JOIN: send a join request packet & switch to waiting-for-confirmation
- mode. (Request_To_Join fills in MPlayerName with my namebuf.)
- ------------------------------------------------------------------*/
- case (BUTTON_JOIN | KN_BUTTON):
- name_edt.Clear_Focus();
- name_edt.Flag_To_Redraw();
- join_index = gamelist.Current_Index();
- parms_received = 0;
- if (Request_To_Join (namebuf, join_index, &playerlist, MPlayerHouse,
- MPlayerColorIdx)) {
- joinstate = JOIN_WAIT_CONFIRM;
- } else {
- display = REDRAW_ALL;
- }
- break;
- /*------------------------------------------------------------------
- CANCEL: send a SIGN_OFF
- - If we're part of a game, stay in this dialog; otherwise, exit
- ------------------------------------------------------------------*/
- case (KN_ESC):
- if (Messages.Get_Edit_Buf() != NULL) {
- Messages.Input(input);
- display = REDRAW_MESSAGE;
- break;
- }
- case (BUTTON_CANCEL | KN_BUTTON):
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_SIGN_OFF;
- strcpy(GPacket.Name,MPlayerName);
- /*...............................................................
- If we're joined to a game, make extra sure the other players in
- that game know I'm exiting; send my SIGN_OFF as an ack-required
- packet. Do not send this packet to myself (index 0).
- ...............................................................*/
- if (joinstate == JOIN_CONFIRMED) {
- //
- // Remove myself from the player list box
- //
- if (playerlist.Count()) { // added: BRR 6/14/96
- item = (char *)(playerlist.Get_Item(0));
- playerlist.Remove_Item(item);
- delete [] item;
- playerlist.Flag_To_Redraw();
- }
- //
- // Remove myself from the Players list
- //
- if (Players.Count()) { // added: BRR 6/14/96
- who = Players[0];
- Players.Delete(0);
- delete who;
- }
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
- &(Players[i]->Address));
- Ipx.Service();
- }
- }
- /*...............................................................
- Now broadcast my SIGN_OFF so other players looking at this game
- know I'm leaving.
- ...............................................................*/
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- if (IsBridge) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- }
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- if (joinstate != JOIN_CONFIRMED) {
- process = false;
- rc = -1;
- } else {
- MPlayerGameName[0] = 0;
- joinstate = JOIN_NOTHING;
- display = REDRAW_ALL;
- }
- break;
- /*------------------------------------------------------------------
- NEW: bail out with return code 1
- ------------------------------------------------------------------*/
- case (BUTTON_NEW | KN_BUTTON):
- /*
- .................. Force user to enter a name ...................
- */
- if (strlen(namebuf)==0) {
- CCMessageBox().Process(TXT_NAME_ERROR);
- display = REDRAW_ALL;
- break;
- }
- /*
- ..................... Ensure name is unique .....................
- */
- found = 0;
- for (i = 0; i < Games.Count(); i++) {
- if (!stricmp(Games[i]->Name, namebuf)) {
- found = 1;
- CCMessageBox().Process (TXT_GAMENAME_MUSTBE_UNIQUE);
- display = REDRAW_ALL;
- break;
- }
- }
- if (found)
- break;
- /*
- .................... Save player & game name ....................
- */
- strcpy(MPlayerName,namebuf);
- strcpy(MPlayerGameName,namebuf);
- name_edt.Clear_Focus();
- name_edt.Flag_To_Redraw();
- rc = 1;
- process = false;
- break;
- /*------------------------------------------------------------------
- Default: manage the inter-player messages
- ------------------------------------------------------------------*/
- default:
- /*...............................................................
- F4/SEND/'M' = edit a message
- ...............................................................*/
- if (Messages.Get_Edit_Buf()==NULL) {
- if ( (input == KN_M && joinstate==JOIN_CONFIRMED) ||
- input==(BUTTON_SEND | KN_BUTTON) || input == KN_F4) {
- memset (txt, 0, 80);
- strcpy(txt,Text_String(TXT_TO_ALL)); // "To All:"
- Messages.Add_Edit (MPlayerTColors[MPlayerColorIdx],
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, d_message_w-70*factor);
- if (joinstate <= JOIN_NOTHING) {
- name_edt.Clear_Focus();
- name_edt.Flag_To_Redraw();
- }
- display = REDRAW_MESSAGE;
- break;
- }
- } else
- /*...............................................................
- If we're already editing a message and the user clicks on
- 'Send', translate our input to a Return so Messages.Input() will
- work properly.
- ...............................................................*/
- if (input==(BUTTON_SEND | KN_BUTTON)) {
- input = KN_RETURN;
- }
- /*...............................................................
- Manage the message system (get rid of old messages)
- ...............................................................*/
- if (Messages.Manage()) {
- display = REDRAW_MESSAGE;
- }
- /*...............................................................
- Service keyboard input for any message being edited.
- ...............................................................*/
- i = Messages.Input(input);
- /*...............................................................
- If 'Input' returned 1, it means refresh the message display.
- ...............................................................*/
- if (i==1) {
- Messages.Draw();
- } else {
- /*...............................................................
- If 'Input' returned 2, it means redraw the message display.
- ...............................................................*/
- if (i==2) {
- display = REDRAW_MESSAGE;
- } else {
- /*...............................................................
- If 'input' returned 3, it means send the current message.
- ...............................................................*/
- if (i==3) {
- long actual_message_size;
- char *the_string;
- sent_so_far = 0;
- magic_number = MESSAGE_HEAD_MAGIC_NUMBER;
- message_length = strlen(Messages.Get_Edit_Buf());
- crc = (unsigned short)
- (Calculate_CRC(Messages.Get_Edit_Buf(),message_length) &0xffff);
- while ( sent_so_far < message_length ){
- GPacket.Command = NET_MESSAGE;
- strcpy (GPacket.Name, namebuf);
- memcpy (GPacket.Message.Buf, Messages.Get_Edit_Buf()+sent_so_far, COMPAT_MESSAGE_LENGTH-5);
- /*
- ** Steve I's stuff for splitting message on word boundries
- */
- actual_message_size = COMPAT_MESSAGE_LENGTH - 5;
- /* Start at the end of the message and find a space with 10 chars. */
- the_string = GPacket.Message.Buf;
- while ( (COMPAT_MESSAGE_LENGTH -5) -actual_message_size < 10 &&
- the_string[actual_message_size] != ' '){
- --actual_message_size;
- }
- if ( the_string[actual_message_size] == ' ' ){
- /* Now delete the extra characters after the space (they musnt print) */
- for ( int i=0 ; i< (COMPAT_MESSAGE_LENGTH-5) - actual_message_size; i++ ){
- the_string[i + actual_message_size] = 0; //0xff; ST - 12/18/2018 11:36AM
- }
- }else{
- actual_message_size = COMPAT_MESSAGE_LENGTH - 5;
- }
- *(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-5) = 0;
- *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-4)) = magic_number;
- *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-2)) = crc;
- GPacket.Message.ID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
- GPacket.Message.NameCRC = Compute_Name_CRC(MPlayerGameName);
- /*..................................................................
- Send the message to every player in our player list. The local
- system will also receive this message, since it's in the Player list.
- ..................................................................*/
- if (joinstate == JOIN_CONFIRMED) {
- for (i = 1; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket,
- sizeof(GlobalPacketType), 1, &(Players[i]->Address));
- Ipx.Service();
- }
- sprintf(txt,Text_String (TXT_FROM), MPlayerName, GPacket.Message.Buf);
- Messages.Add_Message (txt,
- MPlayerTColors[MPlayerColorIdx],
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 600, magic_number, crc);
- }
- else {
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket,
- sizeof(GlobalPacketType), 1, &(Players[i]->Address));
- Ipx.Service();
- }
- }
- magic_number++;
- sent_so_far += actual_message_size; //COMPAT_MESSAGE_LENGTH-5;
- }
- }
- }
- }
- break;
- }
- /*---------------------------------------------------------------------
- Resend our query packets
- ---------------------------------------------------------------------*/
- Send_Join_Queries(game_index, 0, 0);
- /*---------------------------------------------------------------------
- Process incoming packets
- ---------------------------------------------------------------------*/
- event = Get_Join_Responses(&joinstate, &gamelist, &playerlist,
- join_index);
- /*.....................................................................
- If we've changed state, redraw everything; if we're starting the game,
- break out of the loop. If we've just joined, send out a player query
- so I'll get added to the list instantly.
- .....................................................................*/
- if (event == EV_STATE_CHANGE) {
- display = REDRAW_ALL;
- if (joinstate==JOIN_GAME_START) {
- rc = 0;
- process = false;
- } else {
- /*..................................................................
- If we're newly-confirmed, immediately send out a player query
- ..................................................................*/
- if (joinstate==JOIN_CONFIRMED) {
- Clear_Player_List(&playerlist);
- item = new char [MPLAYER_NAME_MAX + 4];
- if (MPlayerHouse==HOUSE_GOOD) {
- sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_G_D_I));
- } else {
- sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_N_O_D));
- }
- playerlist.Add_Item (item, MPlayerTColors[MPlayerColorIdx]);
- who = new NodeNameType;
- strcpy(who->Name, MPlayerName);
- who->Address = IPXAddressClass();
- who->Player.House = MPlayerHouse;
- who->Player.Color = MPlayerColorIdx;
- Players.Add (who);
- Send_Join_Queries (game_index, 0, 1);
- } else {
- /*..................................................................
- If we've been rejected, clear any messages we may have been typing.
- ..................................................................*/
- if (joinstate==JOIN_REJECTED) {
- //
- // Remove myself from the player list box
- //
- if (playerlist.Count()) { // added: BRR 6/14/96
- item = (char *)(playerlist.Get_Item(0));
- if (item){
- playerlist.Remove_Item(item);
- delete [] item;
- playerlist.Flag_To_Redraw();
- }
- }
- //
- // Remove myself from the Players list
- //
- if (Players.Count()){
- who = Players[0];
- Players.Delete(0);
- delete who;
- }
- Messages.Init (d_message_x + 2, d_message_y + 2, 4,
- MAX_MESSAGE_LENGTH, d_txt6_h);
- }
- }
- }
- } else
- /*.....................................................................
- If a new game is detected, and it's the first game on our list,
- automatically send out a player query for that game.
- .....................................................................*/
- if (event == EV_NEW_GAME && gamelist.Count()==1) {
- gamelist.Set_Selected_Index(0);
- game_index = gamelist.Current_Index();
- Send_Join_Queries (game_index, 0, 1);
- } else
- /*.....................................................................
- If the game options have changed, print them.
- .....................................................................*/
- if (event == EV_GAME_OPTIONS) {
- parms_received = 1;
- display = REDRAW_MESSAGE;
- } else
- /*.....................................................................
- Draw an incoming message
- .....................................................................*/
- if (event == EV_MESSAGE) {
- display = REDRAW_MESSAGE;
- } else
- /*.....................................................................
- A game before the one I've selected is gone, so we have a new index now.
- 'game_index' must be kept set to the currently-selected list item, so
- we send out queries for the currently-selected game. It's therefore
- imperative that we detect any changes to the game list.
- If we're joined in a game, we must decrement our game_index to keep
- it aligned with the game we're joined to.
- .....................................................................*/
- if (event == EV_GAME_SIGNOFF) {
- if (joinstate==JOIN_CONFIRMED) {
- game_index--;
- join_index--;
- gamelist.Set_Selected_Index(join_index);
- } else {
- gamelist.Flag_To_Redraw();
- Clear_Player_List(&playerlist);
- game_index = gamelist.Current_Index();
- Send_Join_Queries (game_index, 0, 1);
- }
- }
- /*---------------------------------------------------------------------
- Service the Ipx connections
- ---------------------------------------------------------------------*/
- Ipx.Service();
- /*---------------------------------------------------------------------
- Clean out the Game List; if an old entry is found:
- - Remove it
- - Clear the player list
- - Send queries for the new selected game, if there is one
- ---------------------------------------------------------------------*/
- for (i = 0; i < Games.Count(); i++) {
- if (TickCount.Time() - Games[i]->Game.LastTime > 400) {
- Games.Delete(Games[i]);
- item = (char *)(gamelist.Get_Item (i));
- gamelist.Remove_Item (item);
- delete [] item;
- if (i <= game_index) {
- gamelist.Flag_To_Redraw();
- Clear_Player_List(&playerlist);
- game_index = gamelist.Current_Index();
- Send_Join_Queries (game_index, 0, 1);
- }
- }
- }
- /*---------------------------------------------------------------------
- Service the sounds & score; GameActive must be false at this point,
- so Call_Back() doesn't intercept global messages from me!
- ---------------------------------------------------------------------*/
- Call_Back();
- }
- /*------------------------------------------------------------------------
- Establish connections with all other players.
- ------------------------------------------------------------------------*/
- if (rc == 0) {
- /*.....................................................................
- If the other guys are playing a scenario I don't have (sniff), I can't
- play. Try to bail gracefully.
- .....................................................................*/
- if (ScenarioIdx==-1) {
- CCMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH);
- //
- // Remove myself from the player list box
- //
- if (playerlist.Count()) { // added: BRR 6/14/96
- item = (char *)(playerlist.Get_Item(0));
- playerlist.Remove_Item(item);
- delete [] item;
- playerlist.Flag_To_Redraw();
- }
- //
- // Remove myself from the Players list
- //
- if (Players.Count()) { // added: BRR 6/14/96
- who = Players[0];
- Players.Delete(0);
- delete who;
- }
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_SIGN_OFF;
- strcpy (GPacket.Name, MPlayerName);
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
- &(Players[i]->Address));
- Ipx.Service();
- }
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- if (IsBridge) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- }
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- rc = -1;
- } else {
- /*..................................................................
- Set the number of players in this game, and my ID
- ..................................................................*/
- MPlayerCount = Players.Count();
- MPlayerLocalID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
- /*..................................................................
- Get the scenario number
- ..................................................................*/
- Scenario = MPlayerFilenum[ScenarioIdx];
- /*..................................................................
- Form connections with all other players. Form the IPX Connection ID
- from the player's Color and House. This will let us extract any
- player's color & house at any time. Fill in 'tmp_id' while we're
- doing this.
- ..................................................................*/
- for (i = 0; i < Players.Count(); i++) {
- /*...............................................................
- Only create the connection if it's not myself!
- ...............................................................*/
- if (strcmp (MPlayerName, Players[i]->Name)) {
- id = Build_MPlayerID(Players[i]->Player.Color,
- Players[i]->Player.House);
- tmp_id[i] = id;
- Ipx.Create_Connection((int)id, Players[i]->Name, &(Players[i]->Address) );
- } else {
- tmp_id[i] = MPlayerLocalID;
- }
- }
- /*..................................................................
- Store every player's ID in the MPlayerID[] array. This array will
- determine the order of event execution, so the ID's must be stored
- in the same order on all systems.
- ..................................................................*/
- for (i = 0; i < MPlayerCount; i++) {
- min_index = 0;
- min_id = 0xff;
- for (j = 0; j < MPlayerCount; j++) {
- if (tmp_id[j] < min_id) {
- min_id = tmp_id[j];
- min_index = j;
- }
- }
- MPlayerID[i] = tmp_id[min_index];
- tmp_id[min_index] = 0xff;
- }
- /*..................................................................
- Fill in the array of player names, including my own.
- ..................................................................*/
- for (i = 0; i < MPlayerCount; i++) {
- if (MPlayerID[i] == MPlayerLocalID) {
- strcpy (MPlayerNames[i], MPlayerName);
- } else {
- strcpy (MPlayerNames[i], Ipx.Connection_Name(MPlayerID[i]));
- }
- }
- }
- /*---------------------------------------------------------------------
- Wait a while, polling the IPX service routines, to give our ACK
- a chance to get to the other system. If he doesn't get our ACK, he'll
- be waiting the whole time we load MIX files.
- ---------------------------------------------------------------------*/
- i = MAX(Ipx.Global_Response_Time() * 2, (unsigned long)60);
- starttime = TickCount.Time();
- while (TickCount.Time() - starttime < (unsigned)i) {
- Ipx.Service();
- }
- }
- /*------------------------------------------------------------------------
- Init network timing values, using previous response times as a measure
- of what our retry delta & timeout should be.
- ------------------------------------------------------------------------*/
- Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,
- Ipx.Global_Response_Time() * 4);
- /*------------------------------------------------------------------------
- Clear all lists
- ------------------------------------------------------------------------*/
- Clear_Game_List(&gamelist);
- Clear_Player_List(&playerlist);
- /*------------------------------------------------------------------------
- Restore screen
- ------------------------------------------------------------------------*/
- Hide_Mouse();
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- Blit_Hid_Page_To_Seen_Buff();
- Show_Mouse();
- return(rc);
- }
- /***************************************************************************
- * Clear_Game_List -- Clears the game-name listbox & 'Games' Vector *
- * *
- * Assumes each entry in 'Games' & the list box have been allocated *
- * separately. *
- * *
- * INPUT: *
- * gamelist ptr to list box *
- * *
- * OUTPUT: *
- * none *
- * *
- * WARNINGS: *
- * none *
- * *
- * HISTORY: *
- *=========================================================================*/
- static void Clear_Game_List (ListClass *gamelist)
- {
- char * item;
- int i;
- /*------------------------------------------------------------------------
- Clear the list box
- ------------------------------------------------------------------------*/
- while (gamelist->Count()) {
- item = (char *)(gamelist->Get_Item (0));
- gamelist->Remove_Item(item);
- delete [] item;
- }
- gamelist->Flag_To_Redraw();
- /*------------------------------------------------------------------------
- Clear the 'Games' Vector
- ------------------------------------------------------------------------*/
- for (i = 0; i < Games.Count(); i++)
- delete Games[i];
- Games.Clear();
- } /* end of Clear_Game_List */
- /***************************************************************************
- * Clear_Player_List -- Clears the player-name listbox & Vector *
- * *
- * Assumes each entry in 'Players' & the list box have been allocated *
- * separately. *
- * *
- * INPUT: *
- * playerlist ptr to list box *
- * *
- * OUTPUT: *
- * none *
- * *
- * WARNINGS: *
- * none *
- * *
- * HISTORY: *
- *=========================================================================*/
- static void Clear_Player_List (ListClass *playerlist)
- {
- char * item;
- int i;
- /*------------------------------------------------------------------------
- Clear the list box
- ------------------------------------------------------------------------*/
- while (playerlist->Count()) {
- item = (char *)(playerlist->Get_Item(0));
- playerlist->Remove_Item(item);
- delete [] item;
- }
- playerlist->Flag_To_Redraw();
- /*------------------------------------------------------------------------
- Clear the 'Players' Vector
- ------------------------------------------------------------------------*/
- for (i = 0; i < Players.Count(); i++)
- delete Players[i];
- Players.Clear();
- } /* end of Clear_Player_List */
- /***************************************************************************
- * Request_To_Join -- Sends a JOIN request packet to game owner *
- * *
- * Regardless of the return code, the Join Dialog will need to be redrawn *
- * after calling this routine. *
- * *
- * INPUT: *
- * playername player's name *
- * join_index index of game we're joining *
- * playerlist listbox containing other players' names *
- * house requested house *
- * color requested color *
- * *
- * OUTPUT: *
- * 1 = Packet sent, 0 = wasn't *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- *=========================================================================*/
- static int Request_To_Join (char *playername, int join_index, ListClass *playerlist,
- HousesType house, int color)
- {
- int i;
- playerlist = playerlist; // shaddup, Mr stupid compiler!
- /*
- --------------------------- Validate join_index --------------------------
- */
- if ( (Games.Count()==0) || join_index > Games.Count() || join_index < 0) {
- CCMessageBox().Process (TXT_NOTHING_TO_JOIN);
- return(false);
- }
- /*
- ----------------------- Force user to enter a name -----------------------
- */
- if (strlen(playername)==0) {
- CCMessageBox().Process (TXT_NAME_ERROR);
- return(false);
- }
- /*
- ------------------------- The game must be open --------------------------
- */
- if (!Games[join_index]->Game.IsOpen) {
- CCMessageBox().Process(TXT_GAME_IS_CLOSED);
- return (false);
- }
- /*
- ------------------------ Make sure name is unique ------------------------
- */
- for (i = 0; i < Players.Count(); i++) {
- if (!stricmp(playername, Players[i]->Name)) {
- CCMessageBox().Process (TXT_NAME_MUSTBE_UNIQUE);
- return(false);
- }
- }
- /*
- ----------------------------- Check version #'s --------------------------
- */
- int v;
- #ifdef PATCH
- if (IsV107) {
- v = 1;
- } else {
- v = 2;
- }
- #else
- v = Version_Number();
- #endif
- if (Games[join_index]->Game.Version > v) {
- CCMessageBox().Process (TXT_YOURGAME_OUTDATED);
- return(false);
- } else {
- if (Games[join_index]->Game.Version < v) {
- CCMessageBox().Process (TXT_DESTGAME_OUTDATED);
- return(false);
- }
- }
- /*
- ----------------------------- Save game name -----------------------------
- */
- strcpy (MPlayerName,playername);
- /*
- ----------------------- Send packet to game's owner ----------------------
- */
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_QUERY_JOIN;
- strcpy (GPacket.Name, MPlayerName);
- GPacket.PlayerInfo.House = house;
- GPacket.PlayerInfo.Color = color;
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
- &(Games[join_index]->Address));
- return(true);
- }
- /***********************************************************************************************
- * Send_Join_Queries -- sends queries for the Join Dialog *
- * *
- * This routine [re]sends the queries related to the Join Dialog: *
- * - NET_QUERY_GAME *
- * - NET_QUERY_PLAYER for the game currently selected (if there is one) *
- * *
- * The queries are "staggered" in time so they aren't all sent at once; otherwise, we'd *
- * be inundated with reply packets & we'd miss some (even though the replies will require *
- * ACK's). *
- * *
- * INPUT: *
- * curgame index of currently-selected game; -1 = none *
- * gamenow if 1, will immediately send the game query *
- * playernow if 1, will immediately send the player query for currently-selected game *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 02/14/1995 BR : Created. *
- * 04/15/1995 BRR : Created. *
- *=============================================================================================*/
- static void Send_Join_Queries(int curgame, int gamenow, int playernow)
- {
- static int lasttime1 = 0; // time since last Game query sent out
- static int lasttime2 = 0; // time since last Player query sent out
- /*------------------------------------------------------------------------
- Send the game-name query if the time has expired, or we're told to do
- it right now
- ------------------------------------------------------------------------*/
- if ( (TickCount.Time() - lasttime1 > 120) || gamenow) {
- lasttime1 = TickCount.Time();
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_QUERY_GAME;
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0, NULL);
- /*.....................................................................
- If the user specified a remote server address, broadcast over that
- network, too.
- .....................................................................*/
- if (IsBridge)
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- }
- /*------------------------------------------------------------------------
- Send the player query for the game currently clicked on, if the time has
- expired and there is a currently-selected game, or we're told to do it
- right now
- ------------------------------------------------------------------------*/
- if ( (curgame != -1) && curgame < Games.Count() &&
- ((TickCount.Time() - lasttime2 > 35) || playernow) ) {
- lasttime2 = TickCount.Time();
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_QUERY_PLAYER;
- strcpy (GPacket.Name, Games[curgame]->Name);
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0, NULL);
- /*.....................................................................
- If the user specified a remote server address, broadcast over that
- network, too.
- .....................................................................*/
- if (IsBridge)
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- }
- } /* end of Send_Join_Queries */
- /***********************************************************************************************
- * Get_Join_Responses -- sends queries for the Join Dialog *
- * *
- * This routine polls the Global Channel to see if there are any incoming packets; *
- * if so, it processes them. This routine can change the state of the Join Dialog, or *
- * the contents of the list boxes, based on what the packet is. *
- * *
- * The list boxes are passed in as pointers; they can't be made globals, because they *
- * can't be constructed, because they require shape pointers to the arrow buttons, and *
- * the mix files won't have been initialized when the global variables' constructors are *
- * called. *
- * *
- * This routine sets the globals *
- * MPlayerHouse (from NET_CONFIRM_JOIN) *
- * MPlayerColorIdx (from NET_CONFIRM_JOIN) *
- * MPlayerBases (from NET_GAME_OPTIONS) *
- * MPlayerTiberium (from NET_GAME_OPTIONS) *
- * MPlayerGoodies (from NET_GAME_OPTIONS) *
- * MPlayerGhosts (from NET_GAME_OPTIONS) *
- * ScenarioIdx (from NET_GAME_OPTIONS; -1 = scenario not found) *
- * *
- * INPUT: *
- * joinstate current state of Join Dialog *
- * gamelist list box containing game names *
- * playerlist list box containing player names for the currently-selected game *
- * join_index index of the game we've joined or are asking to join *
- * *
- * OUTPUT: *
- * Event that occurred *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 02/14/1995 BR : Created. *
- * 04/15/1995 BRR : Created. *
- *=============================================================================================*/
- static JoinEventType Get_Join_Responses(JoinStateType *joinstate, ListClass *gamelist,
- ColorListClass *playerlist, int join_index)
- {
- int rc;
- char * item; // general-purpose string
- NodeNameType *who; // node to add to Games or Players
- int i;
- int found;
- JoinEventType retcode = EV_NONE;
- char txt[80];
- int color;
- unsigned short magic_number;
- unsigned short crc;
- /*------------------------------------------------------------------------
- If there is no incoming packet, just return
- ------------------------------------------------------------------------*/
- rc = Ipx.Get_Global_Message (&GPacket, &GPacketlen, &GAddress, &GProductID);
- if (!rc || GProductID != IPXGlobalConnClass::COMMAND_AND_CONQUER)
- return(EV_NONE);
- /*------------------------------------------------------------------------
- If we're joined in a game, handle the packet in a standard way; otherwise,
- don't answer standard queries.
- ------------------------------------------------------------------------*/
- if ( (*joinstate)==JOIN_CONFIRMED &&
- Process_Global_Packet(&GPacket,&GAddress)!=0)
- return(EV_NONE);
- /*------------------------------------------------------------------------
- NET_ANSWER_GAME: Another system is answering our GAME query, so add that
- system to our list box if it's new.
- ------------------------------------------------------------------------*/
- if (GPacket.Command==NET_ANSWER_GAME) {
- /*.....................................................................
- See if this name is unique
- .....................................................................*/
- retcode = EV_NONE;
- found = 0;
- for (i = 0; i < Games.Count(); i++) {
- if (!strcmp(Games[i]->Name, GPacket.Name)) {
- found = 1;
- /*...............................................................
- If name was found, update the node's time stamp & IsOpen flag.
- ...............................................................*/
- Games[i]->Game.LastTime = TickCount.Time();
- if (Games[i]->Game.IsOpen != GPacket.GameInfo.IsOpen) {
- item = (char *)gamelist->Get_Item(i);
- if (GPacket.GameInfo.IsOpen) {
- sprintf(item,Text_String(TXT_THATGUYS_GAME),GPacket.Name);
- } else {
- sprintf(item,Text_String(TXT_THATGUYS_GAME_BRACKET),GPacket.Name);
- }
- Games[i]->Game.IsOpen = GPacket.GameInfo.IsOpen;
- gamelist->Flag_To_Redraw();
- /*............................................................
- If this game has gone from closed to open, copy the responder's
- address into our Game slot, since the guy responding to this
- must be game owner.
- ............................................................*/
- if (Games[i]->Game.IsOpen)
- Games[i]->Address = GAddress;
- }
- break;
- }
- }
- /*.....................................................................
- name not found (or addresses are different); add it to 'Games'
- .....................................................................*/
- if (found==0) {
- /*..................................................................
- Create a new node structure, fill it in, add it to 'Games'
- ..................................................................*/
- who = new NodeNameType;
- strcpy(who->Name, GPacket.Name);
- who->Address = GAddress;
- who->Game.Version = GPacket.GameInfo.Version;
- who->Game.IsOpen = GPacket.GameInfo.IsOpen;
- who->Game.LastTime = TickCount.Time();
- Games.Add (who);
- /*..................................................................
- Create a string for "xxx's Game", leaving room for brackets around
- the string if it's a closed game
- ..................................................................*/
- item = new char [MPLAYER_NAME_MAX + 9];
- if (GPacket.GameInfo.IsOpen) {
- sprintf(item,Text_String(TXT_THATGUYS_GAME),GPacket.Name);
- } else {
- sprintf(item,Text_String(TXT_THATGUYS_GAME_BRACKET),GPacket.Name);
- }
- gamelist->Add_Item(item);
- retcode = EV_NEW_GAME;
- }
- }
- /*------------------------------------------------------------------------
- NET_ANSWER_PLAYER: Another system is answering our PLAYER query, so add it
- to our player list box & the Player Vector if it's new
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_ANSWER_PLAYER) {
- /*.....................................................................
- See if this name is unique
- .....................................................................*/
- retcode = EV_NONE;
- found = 0;
- for (i = 0; i < Players.Count(); i++) {
- /*..................................................................
- If the address is already present, re-copy their name, color &
- house into the existing entry, in case they've changed it without
- our knowledge; set the 'found' flag so we won't create a new entry.
- ..................................................................*/
- if (Players[i]->Address==GAddress) {
- strcpy(Players[i]->Name, GPacket.Name);
- Players[i]->Player.House = GPacket.PlayerInfo.House;
- Players[i]->Player.Color = GPacket.PlayerInfo.Color;
- playerlist->Colors[i] = MPlayerTColors[GPacket.PlayerInfo.Color];
- found = 1;
- break;
- }
- }
- /*.....................................................................
- Don't add this player if he's not part of the game that's selected.
- .....................................................................*/
- i = gamelist->Current_Index();
- if (Games.Count() && GPacket.PlayerInfo.NameCRC != Compute_Name_CRC(Games[i]->Name))
- found = 1;
- /*
- ** Dont add this player if its really me! (hack, hack)
- */
- if (!strcmp(GPacket.Name, MPlayerName)){
- found = 1;
- }
- /*.....................................................................
- name not found (or address didn't match); add to player list box & Vector
- .....................................................................*/
- if (found==0) {
- /*..................................................................
- Create & add a node to the Vector
- ..................................................................*/
- who = new NodeNameType;
- strcpy(who->Name, GPacket.Name);
- who->Address = GAddress;
- who->Player.House = GPacket.PlayerInfo.House;
- who->Player.Color = GPacket.PlayerInfo.Color;
- Players.Add (who);
- /*..................................................................
- Create & add a string to the list box
- ..................................................................*/
- item = new char [MPLAYER_NAME_MAX + 4];
- if (GPacket.PlayerInfo.House==HOUSE_GOOD) {
- sprintf(item,"%s\t%s",GPacket.Name,Text_String(TXT_G_D_I));
- } else {
- sprintf(item,"%s\t%s",GPacket.Name,Text_String(TXT_N_O_D));
- }
- playerlist->Add_Item(item, MPlayerTColors[who->Player.Color]);
- retcode = EV_NEW_PLAYER;
- }
- }
- /*------------------------------------------------------------------------
- NET_CONFIRM_JOIN: The game owner has confirmed our JOIN query; mark us as
- being confirmed, and start answering queries from other systems
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_CONFIRM_JOIN) {
- if ( (*joinstate) != JOIN_CONFIRMED) {
- strcpy (MPlayerGameName, GPacket.Name);
- MPlayerHouse = GPacket.PlayerInfo.House;
- MPlayerColorIdx = GPacket.PlayerInfo.Color;
- (*joinstate) = JOIN_CONFIRMED;
- retcode = EV_STATE_CHANGE;
- }
- }
- /*------------------------------------------------------------------------
- NET_REJECT_JOIN: The game owner has turned down our JOIN query; restore
- the dialog state to its first pop-up state. Broadcast a sign-off to
- tell all other systems that I'm no longer a part of any game; this way,
- I'll be properly removed from their dialogs.
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_REJECT_JOIN) {
- if ( (*joinstate) != JOIN_REJECTED) {
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_SIGN_OFF;
- strcpy (GPacket.Name,MPlayerName);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType), 0, NULL);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType), 0, NULL);
- if (IsBridge) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- }
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- MPlayerGameName[0] = 0;
- (*joinstate) = JOIN_REJECTED;
- retcode = EV_STATE_CHANGE;
- }
- }
- /*------------------------------------------------------------------------
- NET_GAME_OPTIONS: The game owner has changed the game options & is sending
- us the new values.
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_GAME_OPTIONS) {
- if ( (*joinstate)==JOIN_CONFIRMED) {
- MPlayerCredits = GPacket.ScenarioInfo.Credits;
- MPlayerBases = GPacket.ScenarioInfo.IsBases;
- MPlayerTiberium = GPacket.ScenarioInfo.IsTiberium;
- MPlayerGoodies = GPacket.ScenarioInfo.IsGoodies;
- MPlayerGhosts = GPacket.ScenarioInfo.IsGhosties;
- BuildLevel = GPacket.ScenarioInfo.BuildLevel;
- MPlayerUnitCount = GPacket.ScenarioInfo.UnitCount;
- Seed = GPacket.ScenarioInfo.Seed;
- Special = GPacket.ScenarioInfo.Special;
- Options.GameSpeed = GPacket.ScenarioInfo.GameSpeed;
- if (MPlayerTiberium) {
- Special.IsTGrowth = 1;
- Special.IsTSpread = 1;
- } else {
- Special.IsTGrowth = 0;
- Special.IsTSpread = 0;
- }
- if (Winsock.Get_Connected()){
- ScenarioIdx = GPacket.ScenarioInfo.Scenario;
- }else{
- ScenarioIdx = -1;
- for (i = 0; i < MPlayerFilenum.Count(); i++) {
- if (GPacket.ScenarioInfo.Scenario == MPlayerFilenum[i])
- ScenarioIdx = i;
- }
- }
- retcode = EV_GAME_OPTIONS;
- }
- }
- /*------------------------------------------------------------------------
- NET_SIGN_OFF: Another system is signing off: search for that system in
- both the game list & player list, & remove it if found
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_SIGN_OFF) {
- /*.....................................................................
- Remove this name from the list of games
- .....................................................................*/
- for (i = 0; i < Games.Count(); i++) {
- if (!strcmp(Games[i]->Name, GPacket.Name) &&
- Games[i]->Address==GAddress) {
- /*...............................................................
- If the system signing off is the currently-selected list
- item, clear the player list since that game is no longer
- forming.
- ...............................................................*/
- if (i==gamelist->Current_Index()) {
- Clear_Player_List (playerlist);
- }
- /*...............................................................
- If the system signing off was the owner of our game, mark
- ourselves as rejected
- ...............................................................*/
- if ( (*joinstate) > JOIN_NOTHING && i==join_index) {
- (*joinstate) = JOIN_REJECTED;
- retcode = EV_STATE_CHANGE;
- }
- /*
- ....................... Set my return code ......................
- */
- if (retcode == EV_NONE) {
- if (i <= gamelist->Current_Index()) {
- retcode = EV_GAME_SIGNOFF;
- } else {
- retcode = EV_PLAYER_SIGNOFF;
- }
- }
- /*
- ................. Remove game name from game list ...............
- */
- Games.Delete(Games[i]);
- item = (char *)(gamelist->Get_Item (i));
- gamelist->Remove_Item (item);
- delete [] item;
- gamelist->Flag_To_Redraw();
- }
- }
- /*.....................................................................
- Remove this name from the list of players
- .....................................................................*/
- for (i = 0; i < Players.Count(); i++) {
- /*
- ..................... Name found; remove it .....................
- */
- if (Players[i]->Address==GAddress) {
- item = (char *)(playerlist->Get_Item(i));
- playerlist->Remove_Item(item);
- delete [] item;
- Players.Delete(Players[i]);
- playerlist->Flag_To_Redraw();
- if (retcode == EV_NONE)
- retcode = EV_PLAYER_SIGNOFF;
- }
- }
- }
- /*------------------------------------------------------------------------
- NET_GO: The game's owner is signalling us to start playing.
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_GO) {
- if ( (*joinstate)==JOIN_CONFIRMED) {
- MPlayerMaxAhead = GPacket.ResponseTime.OneWay;
- (*joinstate) = JOIN_GAME_START;
- retcode = EV_STATE_CHANGE;
- CCDebugString ("C&C95 - Received the 'GO' packet\n");
- }
- }
- /*------------------------------------------------------------------------
- NET_MESSAGE: Someone is sending us a message
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_MESSAGE) {
- sprintf(txt,Text_String (TXT_FROM), GPacket.Name, GPacket.Message.Buf);
- magic_number = *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-4));
- crc = *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-2));
- color = MPlayerID_To_ColorIndex(GPacket.Message.ID);
- Messages.Add_Message (txt, MPlayerTColors[color],
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 1200, magic_number, crc);
- retcode = EV_MESSAGE;
- }
- /*------------------------------------------------------------------------
- NET_PING: Someone is pinging me to get a response time measure (will only
- happen after I've joined a game). Do nothing; the IPX Manager will handle
- sending an ACK, and updating the response time measurements.
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_PING) {
- retcode = EV_NONE;
- }
- /*------------------------------------------------------------------------
- Default case: nothing happened. (This case will be hit every time I
- receive my own NET_QUERY_GAME or NET_QUERY_PLAYER packets.)
- ------------------------------------------------------------------------*/
- else {
- retcode = EV_NONE;
- }
- return(retcode);
- }
- /***********************************************************************************************
- * Net_New_Dialog -- lets user start a new game *
- * *
- * This dialog shows a list of who's requesting to join this game, and lets *
- * the game initiator selectively approve each user. *
- * *
- * ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ *
- * ³ New Network Game ³ *
- * ³ ³ *
- * ³ Players Scenario ³ *
- * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ³ *
- * ³ ³ Boffo ³³ ³ Hell's Kitchen ³³ ³ *
- * ³ ³ Bozo ÃÄ´ ³ Heaven's Gate ÃÄ´ ³ *
- * ³ ³ Bonzo ³ ³ ³ ... ³ ³ ³ *
- * ³ ³ ÃÄ´ ³ ÃÄ´ ³ *
- * ³ ³ ³³ ³ ³³ ³ *
- * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ³ *
- * ³ [Reject] Count:--- ## ³ *
- * ³ Level:--- ## ³ *
- * ³ ³ *
- * ³ Credits: _____ ³ *
- * ³ [ Bases ] [ Crates ] ³ *
- * ³ [ Tiberium ] [ AI Players ] ³ *
- * ³ ³ *
- * ³ [OK] [Cancel] ³ *
- * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ *
- * ³ ³ ³ ³ *
- * ³ ³ ³ ³ *
- * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ *
- * ³ [Send Message] ³ *
- * ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * true = success, false = cancel *
- * *
- * WARNINGS: *
- * MPlayerName & MPlayerGameName must contain this player's name. *
- * *
- * HISTORY: *
- * 02/14/1995 BR : Created. *
- *=============================================================================================*/
- static int Net_New_Dialog(void)
- {
- /* ###Change collision detected! C:\PROJECTS\CODE\NETDLG.CPP... */
- int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
- /*........................................................................
- Dialog & button dimensions
- ........................................................................*/
- //D_DIALOG_W = 281; // dialog width
- int d_dialog_w = 287*factor; // dialog width
- int d_dialog_h = 177*factor; // dialog height
- int d_dialog_x = ((320*factor - d_dialog_w) / 2); // dialog x-coord
- int d_dialog_y = ((200*factor - d_dialog_h) / 2); // centered y-coord
- int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
- int d_txt6_h = 6*factor+1; // ht of 6-pt text
- int d_margin1 = 5*factor; // margin width/height
- int d_margin2 = 2*factor; // margin width/height
- //d_playerlist_w = 100;
- int d_playerlist_w = 106*factor;
- int d_playerlist_h = 27*factor;
- int d_playerlist_x = d_dialog_x + d_margin1;
- int d_playerlist_y = d_dialog_y + d_margin1 + (d_txt6_h * 3);
- int d_scenariolist_w = 162*factor;
- int d_scenariolist_h = 27*factor;
- int d_scenariolist_x = d_dialog_x + d_dialog_w - d_margin1 - d_scenariolist_w;
- int d_scenariolist_y = d_dialog_y + d_margin1 + (d_txt6_h * 3);
- #if (GERMAN | FRENCH)
- int d_reject_w = 55*factor;
- #else
- int d_reject_w = 45*factor;
- #endif
- int d_reject_h = 9*factor;
- int d_reject_x = d_playerlist_x + (d_playerlist_w / 2) - (d_reject_w / 2);
- int d_reject_y = d_playerlist_y + d_playerlist_h + d_margin2;
- int d_count_w = 25*factor;
- int d_count_h = d_txt6_h;
- int d_count_x = d_scenariolist_x + (d_scenariolist_w / 2);
- int d_count_y = d_scenariolist_y + d_scenariolist_h + d_margin2;
- int d_level_w = 25*factor;
- int d_level_h = d_txt6_h;
- int d_level_x = d_scenariolist_x + (d_scenariolist_w / 2);
- int d_level_y = d_count_y + d_count_h;
- int d_credits_w = ((CREDITSBUF_MAX - 1) * 7*factor) + 4*factor;
- //int d_credits_w = ((CREDITSBUF_MAX - 1) * 6*factor) + 3*factor;
- int d_credits_h = 9*factor;
- int d_credits_x = d_dialog_cx + 2*factor;
- int d_credits_y = d_level_y + d_level_h + d_margin1;
- #if (GERMAN | FRENCH)
- int d_bases_w = 120*factor;//bga:100;
- #else
- int d_bases_w = 100*factor;
- #endif
- int d_bases_h = 9*factor;
- int d_bases_x = d_dialog_cx - d_bases_w - d_margin2;
- int d_bases_y = d_credits_y + d_credits_h + d_margin2;
- #if (GERMAN | FRENCH)
- int d_tiberium_w = 120*factor;
- #else
- int d_tiberium_w = 100*factor;
- #endif
- int d_tiberium_h = 9*factor;
- int d_tiberium_x = d_dialog_cx - d_bases_w - d_margin2;
- int d_tiberium_y = d_bases_y + d_bases_h + d_margin2;
- #if (GERMAN | FRENCH)
- int d_goodies_w = 120*factor;
- #else
- int d_goodies_w = 100*factor;
- #endif
- int d_goodies_h = 9*factor;
- int d_goodies_x = d_dialog_cx + d_margin2;
- int d_goodies_y = d_credits_y + d_credits_h + d_margin2;
- #if (GERMAN | FRENCH)
- int d_ghosts_w = 120*factor;
- #else
- int d_ghosts_w = 100*factor;
- #endif
- int d_ghosts_h = 9*factor;
- int d_ghosts_x = d_dialog_cx + d_margin2;
- int d_ghosts_y = d_goodies_y + d_goodies_h + d_margin2;
- int d_ok_w = 45*factor;
- int d_ok_h = 9*factor;
- int d_ok_x = d_dialog_cx - d_margin2 - (d_bases_w / 2) - (d_ok_w / 2);
- int d_ok_y = d_ghosts_y + d_ghosts_h + d_margin1;
- #if (GERMAN | FRENCH)
- int d_cancel_w = 50*factor;
- #else
- int d_cancel_w = 45*factor;
- #endif
- int d_cancel_h = 9*factor;
- int d_cancel_x = d_dialog_cx + d_margin2 + (d_goodies_w / 2) - (d_cancel_w / 2);
- int d_cancel_y = d_ghosts_y + d_ghosts_h + d_margin1;
- int d_message_w = d_dialog_w - (d_margin1 * 2);
- int d_message_h = 34*factor;
- int d_message_x = d_dialog_x + d_margin1;
- int d_message_y = d_cancel_y + d_cancel_h + d_margin1;
- int d_send_w = 80*factor;
- int d_send_h = 9*factor;
- int d_send_x = d_dialog_cx - (d_send_w / 2);
- int d_send_y = d_message_y + d_message_h + d_margin2;
- /*........................................................................
- Button Enumerations
- ........................................................................*/
- enum {
- BUTTON_PLAYERLIST = 100,
- BUTTON_SCENARIOLIST,
- BUTTON_REJECT,
- BUTTON_COUNT,
- BUTTON_LEVEL,
- BUTTON_CREDITS,
- BUTTON_BASES,
- BUTTON_TIBERIUM,
- BUTTON_GOODIES,
- BUTTON_GHOSTS,
- BUTTON_OK,
- BUTTON_CANCEL,
- BUTTON_SEND,
- };
- /*........................................................................
- Redraw values: in order from "top" to "bottom" layer of the dialog
- ........................................................................*/
- typedef enum {
- REDRAW_NONE = 0,
- REDRAW_UNIT_COUNT,
- REDRAW_MESSAGE,
- REDRAW_BUTTONS,
- REDRAW_BACKGROUND,
- REDRAW_ALL = REDRAW_BACKGROUND
- } RedrawType;
- /*........................................................................
- Dialog variables
- ........................................................................*/
- RedrawType display = REDRAW_ALL; // redraw level
- bool process = true; // process while true
- KeyNumType input;
- char credbuf[CREDITSBUF_MAX]; // for credit edit box
- int old_cred; // old value in credits buffer
- int transmit; // 1 = re-transmit new game options
- long ok_timer = 0; // for timing OK button
- int index; // index for rejecting a player
- int rc;
- int i,j;
- char *item;
- int tabs[] = {77*factor}; // tabs for player list box
- long ping_timer = 0; // for sending Ping packets
- unsigned char tmp_id[MAX_PLAYERS]; // temp storage for sorting player ID's
- int min_index; // for sorting player ID's
- unsigned char min_id; // for sorting player ID's
- unsigned char id; // connection ID
- char txt[80];
- JoinEventType whahoppa; // event generated by received packets
- static int first_time = 1; // 1 = 1st time this dialog is run
- int message_length;
- int sent_so_far;
- unsigned short magic_number;
- unsigned short crc;
- /*........................................................................
- Buttons
- ........................................................................*/
- GadgetClass *commands; // button list
- void const *up_button;
- void const *down_button;
- if (InMainLoop){
- up_button = Hires_Retrieve("BTN-UP.SHP");
- down_button = Hires_Retrieve("BTN-DN.SHP");
- }else{
- up_button = Hires_Retrieve("BTN-UP2.SHP");
- down_button = Hires_Retrieve("BTN-DN2.SHP");
- }
- ColorListClass playerlist(BUTTON_PLAYERLIST,
- d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- up_button,
- down_button);
- ListClass scenariolist(BUTTON_SCENARIOLIST,
- d_scenariolist_x, d_scenariolist_y, d_scenariolist_w, d_scenariolist_h,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- up_button,
- down_button);
- EditClass credit_edt (BUTTON_CREDITS,
- credbuf, CREDITSBUF_MAX,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_credits_x, d_credits_y, d_credits_w, d_credits_h, EditClass::ALPHANUMERIC);
- TextButtonClass rejectbtn(BUTTON_REJECT, TXT_REJECT,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- //#if (GERMAN | FRENCH)
- // d_reject_x, d_reject_y);
- //#else
- d_reject_x, d_reject_y, d_reject_w, d_reject_h);
- //#endif
- GaugeClass countgauge (BUTTON_COUNT,
- d_count_x, d_count_y, d_count_w, d_count_h);
- GaugeClass levelgauge (BUTTON_LEVEL,
- d_level_x, d_level_y, d_level_w, d_level_h);
- TextButtonClass basesbtn(BUTTON_BASES, TXT_BASES_OFF,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_bases_x, d_bases_y, d_bases_w, d_bases_h);
- TextButtonClass tiberiumbtn(BUTTON_TIBERIUM, TXT_TIBERIUM_OFF,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_tiberium_x, d_tiberium_y, d_tiberium_w, d_tiberium_h);
- TextButtonClass goodiesbtn(BUTTON_GOODIES, TXT_CRATES_OFF,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_goodies_x, d_goodies_y, d_goodies_w, d_goodies_h);
- TextButtonClass ghostsbtn(BUTTON_GHOSTS, TXT_AI_PLAYERS_OFF,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_ghosts_x, d_ghosts_y, d_ghosts_w, d_ghosts_h);
- TextButtonClass okbtn(BUTTON_OK, TXT_OK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_ok_x, d_ok_y, d_ok_w, d_ok_h);
- TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- //#if (GERMAN | FRENCH)
- // d_cancel_x, d_cancel_y);
- //#else
- d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
- //#endif
- TextButtonClass sendbtn(BUTTON_SEND, TXT_SEND_MESSAGE,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- //#if (GERMAN | FRENCH)
- // d_send_x, d_send_y);
- //#else
- d_send_x, d_send_y, d_send_w, d_send_h);
- //#endif
- /*
- ------------------------- Build the button list --------------------------
- */
- commands = &playerlist;
- scenariolist.Add_Tail(*commands);
- credit_edt.Add_Tail(*commands);
- rejectbtn.Add_Tail(*commands);
- countgauge.Add_Tail(*commands);
- levelgauge.Add_Tail(*commands);
- basesbtn.Add_Tail(*commands);
- tiberiumbtn.Add_Tail(*commands);
- goodiesbtn.Add_Tail(*commands);
- ghostsbtn.Add_Tail(*commands);
- okbtn.Add_Tail(*commands);
- cancelbtn.Add_Tail(*commands);
- sendbtn.Add_Tail(*commands);
- playerlist.Set_Tabs(tabs);
- /*
- ----------------------------- Various Inits ------------------------------
- */
- /*........................................................................
- Init dialog values, only the first time through
- ........................................................................*/
- if (first_time) {
- MPlayerCredits = 3000; // init credits & credit buffer
- MPlayerBases = 1; // init scenario parameters
- MPlayerTiberium = 0;
- MPlayerGoodies = 0;
- MPlayerGhosts = 0;
- Special.IsCaptureTheFlag = 0;
- MPlayerUnitCount = (MPlayerCountMax[MPlayerBases] + MPlayerCountMin[MPlayerBases]) / 2;
- first_time = 0;
- }
- /*........................................................................
- Init button states
- ........................................................................*/
- if (MPlayerBases) {
- basesbtn.Turn_On();
- basesbtn.Set_Text(TXT_BASES_ON);
- }
- if (MPlayerTiberium) {
- tiberiumbtn.Turn_On();
- tiberiumbtn.Set_Text(TXT_TIBERIUM_ON);
- }
- if (MPlayerGoodies) {
- goodiesbtn.Turn_On();
- goodiesbtn.Set_Text(TXT_CRATES_ON);
- }
- if (MPlayerGhosts) {
- ghostsbtn.Turn_On();
- ghostsbtn.Set_Text(TXT_AI_PLAYERS_ON);
- }
- if (Special.IsCaptureTheFlag) {
- MPlayerGhosts = 0;
- ghostsbtn.Turn_On();
- ghostsbtn.Set_Text(TXT_CAPTURE_THE_FLAG);
- }
- sprintf(credbuf, "%d", MPlayerCredits);
- credit_edt.Set_Text(credbuf, CREDITSBUF_MAX);
- old_cred = MPlayerCredits;
- levelgauge.Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1);
- levelgauge.Set_Value(BuildLevel - 1);
- countgauge.Set_Maximum(MPlayerCountMax[MPlayerBases] - MPlayerCountMin[MPlayerBases]);
- countgauge.Set_Value(MPlayerUnitCount - MPlayerCountMin[MPlayerBases]);
- /*........................................................................
- Init other scenario parameters
- ........................................................................*/
- Special.IsTGrowth = MPlayerTiberium;
- Special.IsTSpread = MPlayerTiberium;
- transmit = 0;
- /*........................................................................
- Init scenario description list box
- ........................................................................*/
- for (i = 0; i < MPlayerScenarios.Count(); i++) {
- scenariolist.Add_Item (strupr(MPlayerScenarios[i]));
- }
- ScenarioIdx = 0; // 1st scenario is selected
- /*........................................................................
- Init player color-used flags
- ........................................................................*/
- for (i = 0; i < MAX_MPLAYER_COLORS; i++) {
- ColorUsed[i] = 0; // init all colors to available
- }
- ColorUsed[MPlayerColorIdx] = 1; // set my color to used
- playerlist.Set_Selected_Style(ColorListClass::SELECT_BAR, CC_GREEN_SHADOW);
- /*........................................................................
- Init random-number generator, & create a seed to be used for all random
- numbers from here on out
- ........................................................................*/
- //ST - 12/18/2018 11:37AM
- //randomize();
- //Seed = rand();
- /*........................................................................
- Init the message display system
- ........................................................................*/
- Messages.Init (d_message_x + 2*factor, d_message_y + 2*factor, 4, MAX_MESSAGE_LENGTH,
- d_txt6_h);
- /*------------------------------------------------------------------------
- Add myself to the list. Note that since I'm not in the Players Vector,
- the Vector & listbox are now 1 out of sync.
- ------------------------------------------------------------------------*/
- item = new char [MPLAYER_NAME_MAX + 4];
- if (MPlayerHouse==HOUSE_GOOD) {
- sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_G_D_I));
- } else {
- sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_N_O_D));
- }
- playerlist.Add_Item(item, MPlayerTColors[MPlayerColorIdx]);
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- Blit_Hid_Page_To_Seen_Buff();
- Set_Palette(Palette);
- while (Get_Mouse_State() > 0) Show_Mouse();
- /*
- ---------------------------- Processing loop -----------------------------
- */
- while (process) {
- /*
- ** If we have just received input focus again after running in the background then
- ** we need to redraw.
- */
- if (AllSurfaces.SurfacesRestored){
- AllSurfaces.SurfacesRestored=FALSE;
- display=REDRAW_ALL;
- }
- #if(SHOW_MONO)
- Ipx.Mono_Debug_Print(-1,0);
- #endif
- /*
- ...................... Refresh display if needed ......................
- */
- if (display == REDRAW_UNIT_COUNT){
- /*
- ** Wipe the background behind the unit count then reprint it
- */
- LogicPage->Fill_Rect(d_count_x + d_count_w + 2*factor,
- d_count_y,
- d_count_x + d_count_w + 2*factor + 20,
- d_count_y + 12,
- 0 );
- sprintf(txt,"%d",MPlayerUnitCount);
- Fancy_Text_Print (txt, d_count_x + d_count_w + 2*factor, d_count_y,
- CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL);
- display = REDRAW_NONE;
- }
- if (display) {
- Hide_Mouse();
- /*
- .................. Redraw backgound & dialog box ...................
- */
- if (display >= REDRAW_BACKGROUND) {
- /*
- ** Reload and draw the title page
- */
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- Blit_Hid_Page_To_Seen_Buff();
- Set_Palette(Palette);
- Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
- /*...............................................................
- Dialog & Field labels
- ...............................................................*/
- Draw_Caption (TXT_NETGAME_SETUP, d_dialog_x, d_dialog_y, d_dialog_w);
- Fancy_Text_Print(TXT_PLAYERS,
- d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h,
- CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_CENTER);
- Fancy_Text_Print(TXT_SCENARIOS,
- d_scenariolist_x + (d_scenariolist_w / 2),
- d_scenariolist_y - d_txt6_h,
- CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_CENTER);
- Fancy_Text_Print (TXT_COUNT, d_count_x - 2*factor, d_count_y,
- CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_RIGHT);
- sprintf(txt,"%d",MPlayerUnitCount);
- Fancy_Text_Print (txt, d_count_x + d_count_w + 2*factor, d_count_y,
- CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL);
- Fancy_Text_Print (TXT_LEVEL, d_level_x - 2*factor, d_level_y,
- CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_RIGHT);
- if (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {
- sprintf(txt,"%d",BuildLevel);
- } else {
- sprintf(txt, "**");
- }
- Fancy_Text_Print (txt, d_level_x + d_level_w + 2*factor, d_level_y,
- CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL);
- Fancy_Text_Print (TXT_START_CREDITS_COLON, d_credits_x - 5*factor,
- d_credits_y + 1*factor, CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_RIGHT);
- }
- /*
- .......................... Redraw buttons ..........................
- */
- if (display >= REDRAW_BUTTONS) {
- commands->Draw_All();
- }
- /*..................................................................
- Draw the messages:
- - Erase an old message first
- - If we're in a game, print the game options (if they've been
- received)
- - If we've been rejected from a game, print that message
- ..................................................................*/
- if (display >= REDRAW_MESSAGE) {
- Draw_Box(d_message_x, d_message_y, d_message_w, d_message_h,
- BOXSTYLE_GREEN_BORDER, true);
- Messages.Draw();
- }
- Show_Mouse();
- display = REDRAW_NONE;
- }
- /*
- ........................... Get user input ............................
- */
- input = commands->Input();
- /*
- ---------------------------- Process input ----------------------------
- */
- switch (input) {
- /*------------------------------------------------------------------
- New Scenario selected.
- ------------------------------------------------------------------*/
- case (BUTTON_SCENARIOLIST | KN_BUTTON):
- if (scenariolist.Current_Index() != ScenarioIdx) {
- ScenarioIdx = scenariolist.Current_Index();
- MPlayerCredits = atoi(credbuf);
- transmit = 1;
- }
- break;
- /*------------------------------------------------------------------
- Reject the currently-selected player (don't allow rejecting myself,
- who will be the first entry in the list)
- ------------------------------------------------------------------*/
- case (BUTTON_REJECT | KN_BUTTON):
- index = playerlist.Current_Index();
- if (index == 0) {
- CCMessageBox().Process (TXT_CANT_REJECT_SELF, TXT_OOPS);
- display = REDRAW_ALL;
- break;
- } else {
- if (index < 0 || index >= playerlist.Count()) {
- CCMessageBox().Process (TXT_SELECT_PLAYER_REJECT,TXT_OOPS);
- display = REDRAW_ALL;
- break;
- }
- }
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_REJECT_JOIN;
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType), 1,
- &(Players[index - 1]->Address));
- break;
- /*------------------------------------------------------------------
- User adjusts max # units
- ------------------------------------------------------------------*/
- case (BUTTON_COUNT | KN_BUTTON):
- MPlayerUnitCount = countgauge.Get_Value() + MPlayerCountMin[MPlayerBases];
- Hide_Mouse();
- LogicPage->Fill_Rect (d_count_x + d_count_w + 2*factor, d_count_y,
- d_count_x + d_count_w + 14*factor, d_count_y + 6*factor, BLACK);
- sprintf(txt,"%d",MPlayerUnitCount);
- Fancy_Text_Print (txt, d_count_x + d_count_w + 2*factor, d_count_y,
- CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL);
- Show_Mouse();
- transmit = 1;
- break;
- /*------------------------------------------------------------------
- User adjusts build level
- ------------------------------------------------------------------*/
- case (BUTTON_LEVEL | KN_BUTTON):
- BuildLevel = levelgauge.Get_Value() + 1;
- if (BuildLevel > MPLAYER_BUILD_LEVEL_MAX) // if it's pegged, max it out
- BuildLevel = MPLAYER_BUILD_LEVEL_MAX;
- Hide_Mouse();
- LogicPage->Fill_Rect (d_level_x + d_level_w + 2*factor, d_level_y,
- d_level_x + d_level_w + 14*factor, d_level_y + 6*factor, BLACK);
- if (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {
- sprintf(txt,"%d",BuildLevel);
- } else {
- sprintf(txt, "**");
- }
- Fancy_Text_Print (txt, d_level_x + d_level_w + 2*factor, d_level_y,
- CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL);
- Show_Mouse();
- transmit = 1;
- break;
- /*------------------------------------------------------------------
- User edits the credits value; retransmit new game options
- ------------------------------------------------------------------*/
- case (BUTTON_CREDITS | KN_BUTTON):
- MPlayerCredits = atoi(credbuf);
- transmit = 1;
- break;
- /*------------------------------------------------------------------
- Toggle bases:
- - Clear scenario list & rebuild it with new names
- - toggle bases button, change its text
- - adjust the MPlayerUnitCount to reflect the new allowed range,
- using the current gauge setting
- - Change the unit count gauge limit & value
- ------------------------------------------------------------------*/
- case (BUTTON_BASES | KN_BUTTON):
- if (MPlayerBases) {
- MPlayerBases = 0;
- basesbtn.Turn_Off();
- basesbtn.Set_Text(TXT_BASES_OFF);
- MPlayerUnitCount = Fixed_To_Cardinal (MPlayerCountMax[0]-MPlayerCountMin[0],
- Cardinal_To_Fixed(MPlayerCountMax[1]-MPlayerCountMin[1],
- MPlayerUnitCount-MPlayerCountMin[1])) + MPlayerCountMin[0];
- } else {
- MPlayerBases = 1;
- basesbtn.Turn_On();
- basesbtn.Set_Text(TXT_BASES_ON);
- MPlayerUnitCount = Fixed_To_Cardinal (MPlayerCountMax[1]-MPlayerCountMin[1],
- Cardinal_To_Fixed(MPlayerCountMax[0]-MPlayerCountMin[0],
- MPlayerUnitCount-MPlayerCountMin[0])) + MPlayerCountMin[1];
- }
- MPlayerCredits = atoi(credbuf);
- countgauge.Set_Maximum(MPlayerCountMax[MPlayerBases] - MPlayerCountMin[MPlayerBases]);
- countgauge.Set_Value(MPlayerUnitCount - MPlayerCountMin[MPlayerBases]);
- transmit = 1;
- countgauge.Flag_To_Redraw();
- display = REDRAW_UNIT_COUNT;
- break;
- /*------------------------------------------------------------------
- Toggle tiberium
- ------------------------------------------------------------------*/
- case (BUTTON_TIBERIUM | KN_BUTTON):
- if (MPlayerTiberium) {
- MPlayerTiberium = 0;
- Special.IsTGrowth = 0;
- Special.IsTSpread = 0;
- tiberiumbtn.Turn_Off();
- tiberiumbtn.Set_Text(TXT_TIBERIUM_OFF);
- } else {
- MPlayerTiberium = 1;
- Special.IsTGrowth = 1;
- Special.IsTSpread = 1;
- tiberiumbtn.Turn_On();
- tiberiumbtn.Set_Text(TXT_TIBERIUM_ON);
- }
- MPlayerCredits = atoi(credbuf);
- transmit = 1;
- break;
- /*------------------------------------------------------------------
- Toggle goodies
- ------------------------------------------------------------------*/
- case (BUTTON_GOODIES | KN_BUTTON):
- if (MPlayerGoodies) {
- MPlayerGoodies = 0;
- goodiesbtn.Turn_Off();
- goodiesbtn.Set_Text(TXT_CRATES_OFF);
- } else {
- MPlayerGoodies = 1;
- goodiesbtn.Turn_On();
- goodiesbtn.Set_Text(TXT_CRATES_ON);
- }
- MPlayerCredits = atoi(credbuf);
- transmit = 1;
- break;
- /*------------------------------------------------------------------
- Toggle ghosts/capture-the-flag
- ------------------------------------------------------------------*/
- case (BUTTON_GHOSTS | KN_BUTTON):
- if (!MPlayerGhosts && !Special.IsCaptureTheFlag) { // ghosts OFF => ghosts ON
- MPlayerGhosts = 1;
- Special.IsCaptureTheFlag = 0;
- ghostsbtn.Turn_On();
- ghostsbtn.Set_Text(TXT_AI_PLAYERS_ON);
- } else {
- if (MPlayerGhosts) { // ghosts ON => capture-flag
- MPlayerGhosts = 0;
- Special.IsCaptureTheFlag = 1;
- ghostsbtn.Turn_On();
- ghostsbtn.Set_Text(TXT_CAPTURE_THE_FLAG);
- } else {
- if (Special.IsCaptureTheFlag) { // capture-flag => AI OFF
- MPlayerGhosts = 0;
- Special.IsCaptureTheFlag = 0;
- ghostsbtn.Turn_Off();
- ghostsbtn.Set_Text(TXT_AI_PLAYERS_OFF);
- }
- }
- }
- MPlayerCredits = atoi(credbuf);
- transmit = 1;
- break;
- /*------------------------------------------------------------------
- OK: exit loop with TRUE status
- ------------------------------------------------------------------*/
- case (BUTTON_OK | KN_BUTTON):
- /*...............................................................
- If a new player has joined in the last second, don't allow
- an OK; force a wait longer than 1 second (to give all players
- a chance to know about this new guy)
- ...............................................................*/
- i = MAX(Ipx.Global_Response_Time() * 2, (unsigned long)60);
- while (TickCount.Time() - ok_timer < i)
- Ipx.Service();
- /*...............................................................
- If there are at least 2 players, go ahead & play; error otherwise
- ...............................................................*/
- if (MPlayerSolo || Players.Count() > 0) {
- rc = TRUE;
- process = FALSE;
- } else {
- CCMessageBox().Process (TXT_ONLY_ONE,TXT_OOPS,NULL);
- display = REDRAW_ALL;
- }
- break;
- /*------------------------------------------------------------------
- CANCEL: send a SIGN_OFF, bail out with error code
- ------------------------------------------------------------------*/
- case (KN_ESC):
- if (Messages.Get_Edit_Buf() != NULL) {
- Messages.Input(input);
- if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;
- break;
- }
- case (BUTTON_CANCEL | KN_BUTTON):
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_SIGN_OFF;
- strcpy (GPacket.Name, MPlayerName);
- /*...............................................................
- Broadcast my sign-off over my network
- ...............................................................*/
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- /*...............................................................
- Broadcast my sign-off over a bridged network if there is one
- ...............................................................*/
- if (IsBridge) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- }
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- /*...............................................................
- And now, just be absolutely sure, send my sign-off to each
- player in my game. (If there's a bridge between us, the other
- player will have specified my address, so he can cross the
- bridge; but I may not have specified a bridge address, so the
- only way I have of crossing the bridge is to send a packet
- directly to him.)
- ...............................................................*/
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
- &(Players[i]->Address));
- Ipx.Service();
- }
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- MPlayerGameName[0] = 0;
- process = false;
- rc = false;
- break;
- /*------------------------------------------------------------------
- Default: manage the inter-player messages
- ------------------------------------------------------------------*/
- default:
- /*...............................................................
- F4/SEND/'M' = send a message
- ...............................................................*/
- if (Messages.Get_Edit_Buf()==NULL) {
- if (input == KN_M || input==(BUTTON_SEND | KN_BUTTON) ||
- input == KN_F4) {
- memset (txt, 0, 80);
- strcpy(txt,Text_String(TXT_TO_ALL)); // "To All:"
- Messages.Add_Edit (MPlayerTColors[MPlayerColorIdx],
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, d_message_w-70*factor);
- credit_edt.Clear_Focus();
- credit_edt.Flag_To_Redraw();
- if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;
- break;
- }
- } else {
- /*...............................................................
- If we're already editing a message and the user clicks on
- 'Send', translate our input to a Return so Messages.Input() will
- work properly.
- ...............................................................*/
- if (input==(BUTTON_SEND | KN_BUTTON)) {
- input = KN_RETURN;
- }
- }
- /*...............................................................
- Manage the message system (get rid of old messages)
- ...............................................................*/
- if (Messages.Manage()) {
- if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;
- }
- /*...............................................................
- Re-draw the messages & service keyboard input for any message
- being edited.
- ...............................................................*/
- i = Messages.Input(input);
- /*...............................................................
- If 'Input' returned 1, it means refresh the message display.
- ...............................................................*/
- if (i==1) {
- Messages.Draw();
- }
- /*...............................................................
- If 'Input' returned 2, it means redraw the message display.
- ...............................................................*/
- else if (i==2) {
- if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;
- }
- /*...............................................................
- If 'input' returned 3, it means send the current message.
- ...............................................................*/
- else if (i==3) {
- long actual_message_size;
- char *the_string;
- sent_so_far = 0;
- magic_number = MESSAGE_HEAD_MAGIC_NUMBER;
- message_length = strlen(Messages.Get_Edit_Buf());
- crc = (unsigned short)
- (Calculate_CRC(Messages.Get_Edit_Buf(), message_length) &0xffff);
- while ( sent_so_far < message_length ){
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_MESSAGE;
- strcpy (GPacket.Name, MPlayerName);
- memcpy (GPacket.Message.Buf, Messages.Get_Edit_Buf()+sent_so_far, COMPAT_MESSAGE_LENGTH-5);
- /*
- ** Steve I's stuff for splitting message on word boundries
- */
- actual_message_size = COMPAT_MESSAGE_LENGTH - 5;
- /* Start at the end of the message and find a space with 10 chars. */
- the_string = GPacket.Message.Buf;
- while ( (COMPAT_MESSAGE_LENGTH -5) -actual_message_size < 10 &&
- the_string[actual_message_size] != ' '){
- --actual_message_size;
- }
- if ( the_string[actual_message_size] == ' ' ){
- /* Now delete the extra characters after the space (they musnt print) */
- for ( int i=0 ; i< (COMPAT_MESSAGE_LENGTH-5) - actual_message_size; i++ ){
- the_string[i + actual_message_size] = 0; //0xff; ST - 12/18/2018 11:37AM
- }
- }else{
- actual_message_size = COMPAT_MESSAGE_LENGTH - 5;
- }
- *(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-5) = 0;
- *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-4)) = magic_number;
- *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-2)) = crc;
- GPacket.Message.ID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
- GPacket.Message.NameCRC = Compute_Name_CRC(MPlayerGameName);
- /*..................................................................
- Send the message to every player in our player list.
- ..................................................................*/
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
- &(Players[i]->Address));
- Ipx.Service();
- }
- /*..................................................................
- Add the message to our own list, since we're not in the player list
- on this dialog.
- ..................................................................*/
- sprintf(txt,Text_String (TXT_FROM), MPlayerName, GPacket.Message.Buf);
- Messages.Add_Message (txt, MPlayerTColors[MPlayerColorIdx],
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 1200, magic_number, crc);
- magic_number++;
- sent_so_far += actual_message_size; //COMPAT_MESSAGE_LENGTH-5;
- }
- if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;
- }
- }
- /*---------------------------------------------------------------------
- Detect editing of the credits buffer, transmit new values to players
- ---------------------------------------------------------------------*/
- if (atoi(credbuf) != old_cred) {
- old_cred = Bound(atoi(credbuf), 0, 9999);
- MPlayerCredits = old_cred;
- transmit = 1;
- sprintf(credbuf, "%d", MPlayerCredits);
- credit_edt.Set_Text(credbuf, CREDITSBUF_MAX);
- }
- /*---------------------------------------------------------------------
- Process incoming packets
- ---------------------------------------------------------------------*/
- whahoppa = Get_NewGame_Responses(&playerlist);
- if (whahoppa == EV_NEW_PLAYER) {
- ok_timer = TickCount.Time();
- transmit = 1;
- } else {
- if (whahoppa == EV_MESSAGE) {
- if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;
- }
- }
- /*---------------------------------------------------------------------
- If our Transmit flag is set, we need to send out a game option packet
- ---------------------------------------------------------------------*/
- if (transmit) {
- for (i = 0; i < Players.Count(); i++) {
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_GAME_OPTIONS;
- GPacket.ScenarioInfo.Scenario = MPlayerFilenum[ScenarioIdx];
- GPacket.ScenarioInfo.Credits = MPlayerCredits;
- GPacket.ScenarioInfo.IsBases = MPlayerBases;
- GPacket.ScenarioInfo.IsTiberium = MPlayerTiberium;
- GPacket.ScenarioInfo.IsGoodies = MPlayerGoodies;
- GPacket.ScenarioInfo.IsGhosties = MPlayerGhosts;
- GPacket.ScenarioInfo.BuildLevel = BuildLevel;
- GPacket.ScenarioInfo.UnitCount = MPlayerUnitCount;
- GPacket.ScenarioInfo.Seed = Seed;
- GPacket.ScenarioInfo.Special = Special;
- GPacket.ScenarioInfo.GameSpeed = Options.GameSpeed;
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 1, &(Players[i]->Address) );
- }
- transmit = 0;
- }
- /*---------------------------------------------------------------------
- Ping every player in my game, to force the Global Channel to measure
- the connection response time.
- ---------------------------------------------------------------------*/
- if (TickCount.Time() - ping_timer > 15) {
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_PING;
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 1, &(Players[i]->Address) );
- }
- ping_timer = TickCount.Time();
- }
- /*---------------------------------------------------------------------
- Service the Ipx connections
- ---------------------------------------------------------------------*/
- Ipx.Service();
- /*---------------------------------------------------------------------
- Service the sounds & score; GameActive must be false at this point,
- so Call_Back() doesn't intercept global messages from me!
- ---------------------------------------------------------------------*/
- Call_Back();
- } /* end of while */
- /*------------------------------------------------------------------------
- Establish connections with all other players.
- ------------------------------------------------------------------------*/
- if (rc) {
- /*.....................................................................
- Set the number of players in this game, and my ID
- .....................................................................*/
- MPlayerCount = Players.Count() + 1;
- MPlayerLocalID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
- /*.....................................................................
- Get the scenario filename
- .....................................................................*/
- Scenario = MPlayerFilenum[ScenarioIdx];
- /*.....................................................................
- Compute frame delay value for packet transmissions:
- - Divide global channel's response time by 8 (2 to convert to 1-way
- value, 4 more to convert from ticks to frames)
- .....................................................................*/
- MPlayerMaxAhead = MAX( (Ipx.Global_Response_Time() / 8), (unsigned long)2);
- /*.....................................................................
- Send all players the NET_GO packet. Wait until all ACK's have been
- received.
- .....................................................................*/
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_GO;
- GPacket.ResponseTime.OneWay = MPlayerMaxAhead;
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 1, &(Players[i]->Address) );
- /*..................................................................
- Wait for all the ACK's to come in.
- ..................................................................*/
- while (Ipx.Global_Num_Send() > 0)
- Ipx.Service();
- }
- /*.....................................................................
- Form connections with all other players. Form the IPX Connection ID
- from the player's Color (high byte) and House (low byte). This
- will let us extract any player's color & house at any time.
- Fill in 'tmp_id' while we're doing this.
- .....................................................................*/
- for (i = 0; i < Players.Count(); i++) {
- id = Build_MPlayerID (Players[i]->Player.Color,
- Players[i]->Player.House);
- tmp_id[i] = id;
- Ipx.Create_Connection(id, Players[i]->Name, &(Players[i]->Address) );
- }
- tmp_id[i] = MPlayerLocalID;
- /*.....................................................................
- Store every player's ID in the MPlayerID[] array. This array will
- determine the order of event execution, so the ID's must be stored
- in the same order on all systems.
- .....................................................................*/
- for (i = 0; i < MPlayerCount; i++) {
- min_index = 0;
- min_id = 0xff;
- for (j = 0; j < MPlayerCount; j++) {
- if (tmp_id[j] < min_id) {
- min_id = tmp_id[j];
- min_index = j;
- }
- }
- MPlayerID[i] = tmp_id[min_index];
- tmp_id[min_index] = 0xff;
- }
- /*.....................................................................
- Fill in the array of player names, including my own.
- .....................................................................*/
- for (i = 0; i < MPlayerCount; i++) {
- if (MPlayerID[i] == MPlayerLocalID) {
- strcpy (MPlayerNames[i], MPlayerName);
- } else {
- strcpy (MPlayerNames[i], Ipx.Connection_Name(MPlayerID[i]));
- }
- }
- }
- /*------------------------------------------------------------------------
- Init network timing values, using previous response times as a measure
- of what our retry delta & timeout should be.
- ------------------------------------------------------------------------*/
- Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,
- Ipx.Global_Response_Time() * 4);
- /*------------------------------------------------------------------------
- Clear all lists
- ------------------------------------------------------------------------*/
- while (scenariolist.Count()) {
- scenariolist.Remove_Item(scenariolist.Get_Item(0));
- }
- Clear_Player_List(&playerlist);
- /*------------------------------------------------------------------------
- Restore screen
- ------------------------------------------------------------------------*/
- Hide_Mouse();
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- Blit_Hid_Page_To_Seen_Buff();
- Show_Mouse();
- return(rc);
- }
- /***************************************************************************
- * Get_NewGame_Responses -- processes packets for New Game dialog *
- * *
- * This routine can modify the contents of the given list box, as well *
- * as the contents of the Players Vector global. *
- * *
- * INPUT: *
- * playerlist list of players in this game *
- * *
- * OUTPUT: *
- * EV_NONE = nothing happened *
- * EV_NEW_PLAYER = a new player has joined; false otherwise *
- * EV_MESSAGE = a message was received *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 04/18/1995 BRR : Created. *
- *=========================================================================*/
- static JoinEventType Get_NewGame_Responses(ColorListClass *playerlist)
- {
- int rc;
- char * item; // general-purpose string
- NodeNameType *who; // node to add to Players Vector
- int i;
- int found;
- JoinEventType retval = EV_NONE;
- int resend;
- char txt[80];
- int color;
- unsigned short magic_number;
- unsigned short crc;
- /*------------------------------------------------------------------------
- If there is no incoming packet, just return
- ------------------------------------------------------------------------*/
- rc = Ipx.Get_Global_Message (&GPacket, &GPacketlen, &GAddress, &GProductID);
- if (!rc || GProductID != IPXGlobalConnClass::COMMAND_AND_CONQUER) {
- return(EV_NONE);
- }
- /*------------------------------------------------------------------------
- Try to handle the packet in a standard way
- ------------------------------------------------------------------------*/
- if (Process_Global_Packet(&GPacket,&GAddress) != 0) {
- return(EV_NONE);
- } else
- /*------------------------------------------------------------------------
- NET_QUERY_JOIN:
- ------------------------------------------------------------------------*/
- if (GPacket.Command==NET_QUERY_JOIN) {
- /*.....................................................................
- See if this name is unique:
- - If the name matches, but the address is different, reject this player
- - If the name & address match, this packet must be a re-send of a
- prevous request; in this case, do nothing. The other player must have
- received my CONFIRM_JOIN packet (since it was sent with an ACK
- required), so we can ignore this resend.
- .....................................................................*/
- found = 0;
- resend = 0;
- for (i = 0; i < Players.Count(); i++) {
- if (!strcmp(Players[i]->Name,GPacket.Name)) {
- if (Players[i]->Address != GAddress) {
- found = 1;
- }
- else {
- resend = 1;
- }
- break;
- }
- }
- if (!strcmp (MPlayerName, GPacket.Name)) {
- found = 1;
- }
- /*.....................................................................
- Reject if name is a duplicate, or if there are too many players:
- .....................................................................*/
- if (found || (Players.Count() >= (MPlayerMax - 1) && !resend) ) {
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_REJECT_JOIN;
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 1, &GAddress);
- }
- /*.....................................................................
- If this packet is NOT a resend, accept the player. Grant him the
- requested color if possible.
- .....................................................................*/
- else if (!resend) {
- /*..................................................................
- Add node to the Vector list
- ..................................................................*/
- who = new NodeNameType;
- strcpy(who->Name, GPacket.Name);
- who->Address = GAddress;
- who->Player.House = GPacket.PlayerInfo.House;
- Players.Add (who);
- /*..................................................................
- Set player's color; if requested color isn't used, give it to him;
- otherwise, give him the 1st available color. Mark the color we
- give him as used.
- ..................................................................*/
- if (ColorUsed[GPacket.PlayerInfo.Color] == 0) {
- who->Player.Color = GPacket.PlayerInfo.Color;
- } else {
- for (i = 0; i < MAX_MPLAYER_COLORS; i++) {
- if (ColorUsed[i]==0) {
- who->Player.Color = i;
- break;
- }
- }
- }
- ColorUsed[who->Player.Color] = 1;
- /*..................................................................
- Add player name to the list box
- ..................................................................*/
- item = new char [MPLAYER_NAME_MAX + 4];
- if (GPacket.PlayerInfo.House==HOUSE_GOOD) {
- sprintf(item,"%s\t%s",GPacket.Name,Text_String(TXT_G_D_I));
- } else {
- sprintf(item,"%s\t%s",GPacket.Name,Text_String(TXT_N_O_D));
- }
- playerlist->Add_Item (item, MPlayerTColors[who->Player.Color]);
- /*..................................................................
- Send a confirmation packet
- ..................................................................*/
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_CONFIRM_JOIN;
- strcpy(GPacket.Name,MPlayerName);
- GPacket.PlayerInfo.House = who->Player.House;
- GPacket.PlayerInfo.Color = who->Player.Color;
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 1, &GAddress);
- retval = EV_NEW_PLAYER;
- }
- }
- /*------------------------------------------------------------------------
- NET_SIGN_OFF: Another system is signing off: search for that system in
- the player list, & remove it if found
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_SIGN_OFF) {
- for (i = 0; i < Players.Count(); i++) {
- /*
- ....................... Name found; remove it ......................
- */
- if (!strcmp (Players[i]->Name, GPacket.Name) &&
- Players[i]->Address==GAddress) {
- /*...............................................................
- Remove from the list box
- ...............................................................*/
- item = (char *)(playerlist->Get_Item(i + 1));
- playerlist->Remove_Item(item);
- playerlist->Flag_To_Redraw();
- delete [] item;
- /*...............................................................
- Mark his color as available
- ...............................................................*/
- ColorUsed[Players[i]->Player.Color] = 0;
- /*...............................................................
- Delete from the Vector list
- ...............................................................*/
- Players.Delete(Players[i]);
- break;
- }
- }
- }
- /*------------------------------------------------------------------------
- NET_MESSAGE: Someone is sending us a message
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_MESSAGE) {
- sprintf(txt,Text_String (TXT_FROM), GPacket.Name, GPacket.Message.Buf);
- magic_number = *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-4));
- crc = *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-2));
- color = MPlayerID_To_ColorIndex(GPacket.Message.ID);
- Messages.Add_Message (txt, MPlayerTColors[color],
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 1200, magic_number, crc);
- retval = EV_MESSAGE;
- }
- return(retval);
- }
- /***************************************************************************
- * Compute_Name_CRC -- computes CRC from char string *
- * *
- * INPUT: *
- * name string to create CRC for *
- * *
- * OUTPUT: *
- * CRC *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 06/29/1995 BRR : Created. *
- *=========================================================================*/
- unsigned long Compute_Name_CRC(char *name)
- {
- char buf[80];
- unsigned long crc = 0L;
- int i;
- strcpy (buf, name);
- strupr (buf);
- for (i = 0; i < (int)strlen(buf); i++) {
- Add_CRC (&crc, (unsigned long)buf[i]);
- }
- return (crc);
- }
- /***************************************************************************
- * Net_Reconnect_Dialog -- Draws/updates the network reconnect dialog *
- * *
- * INPUT: *
- * reconn 1 = reconnect, 0 = waiting for first-time connection *
- * fresh 1 = draw from scratch, 0 = only update time counter *
- * oldest_index IPX connection index of oldest connection *
- * (only used for reconnection) *
- * timeval value to print in the countdown field *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 07/08/1995 BRR : Created. *
- *=========================================================================*/
- void Net_Reconnect_Dialog(int reconn, int fresh, int oldest_index,
- unsigned long timeval)
- {
- static int x,y,w,h;
- int id;
- char buf1[40] = {0};
- char buf2[40] = {0};
- char const *buf3 = "";
- int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
- int d_txt6_h = 6*factor+1;
- int d_margin = 5*factor;
- /*------------------------------------------------------------------------
- Draw the dialog from scratch
- ------------------------------------------------------------------------*/
- if (fresh) {
- Fancy_Text_Print ("", 0, 0, CC_GREEN, TBLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- if (reconn) {
- id = Ipx.Connection_ID(oldest_index);
- sprintf(buf1,Text_String(TXT_RECONNECTING_TO),
- Ipx.Connection_Name(id));
- } else {
- sprintf(buf1,Text_String(TXT_WAITING_FOR_CONNECTIONS));
- }
- sprintf(buf2,Text_String(TXT_TIME_ALLOWED), timeval + 1);
- buf3 = Text_String(TXT_PRESS_ESC);
- w = MAX(String_Pixel_Width(buf1),String_Pixel_Width(buf2));
- w = MAX(String_Pixel_Width(buf3), (unsigned)w);
- w += (d_margin * 4);
- h = (d_txt6_h * 3) + (d_margin * 6);
- x = 160*factor - (w / 2);
- y = 100*factor - (h / 2);
- Hide_Mouse();
- Set_Logic_Page(SeenBuff);
- Dialog_Box(x, y, w, h);
- Fancy_Text_Print (buf1, 160*factor, y + (d_margin * 2), CC_GREEN, BLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- Fancy_Text_Print (buf2, 160*factor, y + (d_margin * 2) + d_txt6_h + d_margin,
- CC_GREEN, BLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- Fancy_Text_Print (buf3, 160*factor, y + (d_margin * 2) + (d_txt6_h + d_margin) * 2,
- CC_GREEN, BLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- Show_Mouse();
- } else {
- /*------------------------------------------------------------------------
- Just update the timeout value on the dialog
- ------------------------------------------------------------------------*/
- Hide_Mouse();
- Set_Logic_Page(SeenBuff);
- sprintf(buf2,Text_String(TXT_TIME_ALLOWED), timeval + 1);
- int pixwidth = String_Pixel_Width (buf2);
- LogicPage->Fill_Rect (160*factor - (pixwidth/2) - 12, y+(d_margin*2) + d_txt6_h + d_margin,
- 160*factor + (pixwidth/2) + 12, y+(d_margin*2) + d_txt6_h*2 + d_margin,
- TBLACK);
- Fancy_Text_Print (buf2, 160*factor, y + (d_margin * 2) + d_txt6_h + d_margin,
- CC_GREEN, BLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- Show_Mouse();
- }
- }
- /***********************************************************************************************
- * Wait_For_Focus -- Wait for game to be in focus before proceeding *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 1/6/97 3:23PM ST : Created *
- *=============================================================================================*/
- void Wait_For_Focus (void)
- {
- CountDownTimerClass focus_timer;
- focus_timer.Set(5*60);
- ShowWindow ( MainWindow, SW_SHOWMAXIMIZED );
- /*
- ** Process the message loop until we are in focus.
- */
- if (!GameInFocus){
- CCDebugString ("C&C95 - Waiting for game to come into focus.");
- do {
- CCDebugString (".");
- Keyboard::Check();
- if (!focus_timer.Time()){
- CCDebugString ("C&C95 - Calling SetForgroundWindow.\n");
- SetForegroundWindow ( MainWindow );
- CCDebugString ("C&C95 - Calling ShowWindow.\n");
- ShowWindow ( MainWindow, SW_SHOWMAXIMIZED );
- focus_timer.Set(5*60);
- }
- }while (!GameInFocus);
- CCDebugString ("\n");
- AllSurfaces.SurfacesRestored=FALSE;
- }
- }
- extern bool Spawn_WChat(bool can_launch);
- /***********************************************************************************************
- * Net_Fake_New_Dialog -- Just like Net_New_Dialog but without the Dialog. For internet play *
- * *
- * This 'dialog' does all the non-dialog game set up stuff that is done in the normal *
- * network game set up dialog. The only visible button is 'cancel' *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: true if successfully connected *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 5/24/96 10:34AM ST : Created *
- *=============================================================================================*/
- static int Net_Fake_New_Dialog(void)
- {
- int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
- int d_dialog_w = 120*factor; // dialog width
- int d_dialog_h = 80*factor; // dialog height
- int d_dialog_x = ((320*factor - d_dialog_w) / 2); // dialog x-coord
- int d_dialog_y = ((200*factor - d_dialog_h) / 2); // centered y-coord
- int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
- //d_playerlist_w = 100;
- int d_playerlist_w = 106*factor;
- int d_playerlist_h = 27*factor;
- //int d_playerlist_x = 10 * factor; //off screen
- int d_playerlist_x = 500*factor; //10 * factor; //off screen
- int d_playerlist_y = d_dialog_y + 20;
- #if (GERMAN | FRENCH)
- int d_cancel_w = 50*factor;
- #else
- int d_cancel_w = 45*factor;
- #endif
- int d_cancel_h = 9*factor;
- int d_cancel_x = d_dialog_cx - (d_cancel_w / 2);
- int d_cancel_y = d_dialog_y + d_dialog_h - 20*factor;
- #if (GERMAN | FRENCH)
- int width=160*factor;
- int height=80*factor;
- #else
- int width=120*factor;
- int height=80*factor;
- #endif //GERMAN | FRENCH
- bool player_joined = false;
- CountDownTimerClass join_timer;
- Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);
- Format_Window_String((char*)Text_String(TXT_CONNECTING), SeenBuff.Get_Height(), width, height);
- #if (GERMAN | FRENCH)
- d_dialog_w = width + 25*factor;
- d_dialog_x = ((320*factor - d_dialog_w) / 2); // dialog x-coord
- d_cancel_x = d_dialog_cx - (d_cancel_w / 2);
- #endif
- /*........................................................................
- Button Enumerations
- ........................................................................*/
- enum {
- BUTTON_CANCEL = 100,
- BUTTON_PLAYERLIST,
- };
- /*........................................................................
- Redraw values: in order from "top" to "bottom" layer of the dialog
- ........................................................................*/
- typedef enum {
- REDRAW_NONE = 0,
- REDRAW_MESSAGE,
- REDRAW_BUTTONS,
- REDRAW_BACKGROUND,
- REDRAW_ALL = REDRAW_BACKGROUND
- } RedrawType;
- /*........................................................................
- Dialog variables
- ........................................................................*/
- RedrawType display = REDRAW_ALL; // redraw level
- bool process = true; // process while true
- KeyNumType input;
- char credbuf[CREDITSBUF_MAX]; // for credit edit box
- int old_cred; // old value in credits buffer
- int transmit; // 1 = re-transmit new game options
- long ok_timer = 0; // for timing OK button
- int rc;
- int i,j;
- char *item;
- int tabs[] = {77*factor}; // tabs for player list box
- long ping_timer = 0; // for sending Ping packets
- unsigned char tmp_id[MAX_PLAYERS]; // temp storage for sorting player ID's
- int min_index; // for sorting player ID's
- unsigned char min_id; // for sorting player ID's
- unsigned char id; // connection ID
- JoinEventType whahoppa; // event generated by received packets
- void const *up_button;
- void const *down_button;
- if (InMainLoop){
- up_button = Hires_Retrieve("BTN-UP.SHP");
- down_button = Hires_Retrieve("BTN-DN.SHP");
- }else{
- up_button = Hires_Retrieve("BTN-UP2.SHP");
- down_button = Hires_Retrieve("BTN-DN2.SHP");
- }
- /*........................................................................
- Buttons
- ........................................................................*/
- GadgetClass *commands; // button list
- ColorListClass playerlist(BUTTON_PLAYERLIST,
- d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- up_button,
- down_button);
- TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- //#if (GERMAN | FRENCH)
- // d_cancel_x, d_cancel_y);
- //#else
- d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
- //#endif
- CCDebugString ("C&C95 - In new game dialog - initialising lists.\n");
- /*
- ------------------------- Build the button list --------------------------
- */
- commands = &playerlist;
- cancelbtn.Add_Tail(*commands);
- playerlist.Set_Tabs(tabs);
- /*
- ----------------------------- Various Inits ------------------------------
- */
- sprintf(credbuf, "%d", MPlayerCredits);
- old_cred = MPlayerCredits;
- /*........................................................................
- Init other scenario parameters
- ........................................................................*/
- Special.IsTGrowth = MPlayerTiberium;
- Special.IsTSpread = MPlayerTiberium;
- transmit = 0;
- /*........................................................................
- Init player color-used flags
- ........................................................................*/
- for (i = 0; i < MAX_MPLAYER_COLORS; i++) {
- ColorUsed[i] = 0; // init all colors to available
- }
- ColorUsed[MPlayerColorIdx] = 1; // set my color to used
- playerlist.Set_Selected_Style(ColorListClass::SELECT_BAR, CC_GREEN_SHADOW);
- /*........................................................................
- Init random-number generator, & create a seed to be used for all random
- numbers from here on out
- ........................................................................*/
- //ST - 12/18/2018 11:37AM
- //randomize();
- //Seed = rand();
- /*------------------------------------------------------------------------
- Add myself to the list. Note that since I'm not in the Players Vector,
- the Vector & listbox are now 1 out of sync.
- ------------------------------------------------------------------------*/
- item = new char [MPLAYER_NAME_MAX + 4];
- if (MPlayerHouse==HOUSE_GOOD) {
- sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_G_D_I));
- } else {
- sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_N_O_D));
- }
- playerlist.Add_Item(item, MPlayerTColors[MPlayerColorIdx]);
- Wait_For_Focus();
- CCDebugString ("C&C95 - About to uncompress title page.\n");
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- Blit_Hid_Page_To_Seen_Buff();
- CCDebugString ("C&C95 - About to set the palette.\n");
- Set_Palette(Palette);
- CCDebugString ("C&C95 - Palette was set OK.\n");
- if (LogicPage != &SeenBuff && LogicPage!= &HidPage){
- CCDebugString ("C&C95 - Logic page invalid");
- Set_Logic_Page (SeenBuff);
- }
- char a_buffer [128];
- sprintf (a_buffer, "Number of players:%d", Players.Count());
- CCDebugString (a_buffer);
- #ifdef VIRTUAL_SUBNET_SERVER
- /*
- ** Send a bogus packet to wake up the VSS
- */
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = (NetCommandType)50; //Invalid command
- strcpy (GPacket.Name, MPlayerName);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType), 0, NULL);
- #endif //VIRTUAL_SUBNET_SERVER
- CCDebugString ("C&C95 - About to reveal mouse\n");
- while (Get_Mouse_State() > 0) Show_Mouse();
- /*
- ---------------------------- Processing loop -----------------------------
- */
- CCDebugString ("C&C95 - Entering join dialogue loop\n");
- while (process) {
- /*
- ** If we have just received input focus again after running in the background then
- ** we need to redraw.
- */
- if (AllSurfaces.SurfacesRestored){
- AllSurfaces.SurfacesRestored=FALSE;
- display=REDRAW_ALL;
- }
- /*
- ...................... Refresh display if needed ......................
- */
- if (display) {
- Hide_Mouse();
- /*
- .................. Redraw backgound & dialog box ...................
- */
- if (display >= REDRAW_BACKGROUND) {
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- Blit_Hid_Page_To_Seen_Buff();
- Set_Palette(Palette);
- Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
- /*...............................................................
- Dialog & Field labels
- ...............................................................*/
- Draw_Caption (TXT_NONE, d_dialog_x, d_dialog_y, d_dialog_w);
- Fancy_Text_Print(TXT_CONNECTING, d_dialog_cx-width/2, d_dialog_y + 25*factor, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- }
- /*
- .......................... Redraw buttons ..........................
- */
- if (display >= REDRAW_BUTTONS) {
- commands->Draw_All();
- }
- Show_Mouse();
- display = REDRAW_NONE;
- }
- /*
- ........................... Get user input ............................
- */
- input = commands->Input();
- /*
- ---------------------------- Process input ----------------------------
- */
- switch (input) {
- /*------------------------------------------------------------------
- CANCEL: send a SIGN_OFF, bail out with error code
- ------------------------------------------------------------------*/
- case (KN_ESC):
- case (BUTTON_CANCEL | KN_BUTTON):
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_SIGN_OFF;
- strcpy (GPacket.Name, MPlayerName);
- /*...............................................................
- Broadcast my sign-off over my network
- ...............................................................*/
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- /*...............................................................
- Broadcast my sign-off over a bridged network if there is one
- ...............................................................*/
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- /*...............................................................
- And now, just be absolutely sure, send my sign-off to each
- player in my game. (If there's a bridge between us, the other
- player will have specified my address, so he can cross the
- bridge; but I may not have specified a bridge address, so the
- only way I have of crossing the bridge is to send a packet
- directly to him.)
- ...............................................................*/
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
- &(Players[i]->Address));
- Ipx.Service();
- }
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- MPlayerGameName[0] = 0;
- process = false;
- rc = false;
- Send_Data_To_DDE_Server ("Hello", strlen("Hello"), DDEServerClass::DDE_CONNECTION_FAILED);
- GameStatisticsPacketSent = false;
- Spawn_WChat(false);
- break;
- /*------------------------------------------------------------------
- default: exit loop with TRUE status
- ------------------------------------------------------------------*/
- default:
- #ifdef VIRTUAL_SUBNET_SERVER
- if (Players.Count() == InternetMaxPlayers-1){
- #else //VIRTUAL_SUBNET_SERVER
- if (Players.Count() > 0){
- #endif // VIRTUAL_SUBNET_SERVER
- //char ddkks[128];
- //sprintf (ddkks, "C&C95 - Players.Count() = %d\n", Players.Count());
- //CCDebugString (ddkks);
- /*
- ** Wait for several secs after receiving request to join before sending
- ** start game packet
- */
- if (!player_joined){
- player_joined = true;
- join_timer.Set (3*60, true);
- break;
- }else{
- if (join_timer.Time()) break;
- }
- CCDebugString ("C&C95 - Join timer expired\n");
- /*...............................................................
- If a new player has joined in the last second, don't allow
- an OK; force a wait longer than 2 seconds (to give all players
- a chance to know about this new guy)
- ...............................................................*/
- i = MAX(Ipx.Global_Response_Time() * 2, (unsigned long)120);
- while (TickCount.Time() - ok_timer < i)
- Ipx.Service();
- /*...............................................................
- If there are at least 2 players, go ahead & play; error otherwise
- ...............................................................*/
- if (MPlayerSolo || Players.Count() > 0) {
- rc = TRUE;
- process = FALSE;
- } else {
- CCMessageBox().Process (TXT_ONLY_ONE,TXT_OOPS,NULL);
- display = REDRAW_ALL;
- }
- }
- break;
- }
- /*---------------------------------------------------------------------
- Process incoming packets
- ---------------------------------------------------------------------*/
- whahoppa = Get_NewGame_Responses(&playerlist);
- if (whahoppa == EV_NEW_PLAYER) {
- ok_timer = TickCount.Time();
- transmit = 1;
- } else {
- if (whahoppa == EV_MESSAGE) {
- display = REDRAW_MESSAGE;
- }
- }
- /*---------------------------------------------------------------------
- If our Transmit flag is set, we need to send out a game option packet
- ---------------------------------------------------------------------*/
- if (transmit) {
- for (i = 0; i < Players.Count(); i++) {
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_GAME_OPTIONS;
- GPacket.ScenarioInfo.Scenario = ScenarioIdx; //MPlayerFilenum[ScenarioIdx];
- GPacket.ScenarioInfo.Credits = MPlayerCredits;
- GPacket.ScenarioInfo.IsBases = MPlayerBases;
- GPacket.ScenarioInfo.IsTiberium = MPlayerTiberium;
- GPacket.ScenarioInfo.IsGoodies = MPlayerGoodies;
- GPacket.ScenarioInfo.IsGhosties = MPlayerGhosts;
- GPacket.ScenarioInfo.BuildLevel = BuildLevel;
- GPacket.ScenarioInfo.UnitCount = MPlayerUnitCount;
- GPacket.ScenarioInfo.Seed = Seed;
- GPacket.ScenarioInfo.Special = Special;
- GPacket.ScenarioInfo.GameSpeed = Options.GameSpeed;
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 1, &(Players[i]->Address) );
- }
- transmit = 0;
- }
- /*---------------------------------------------------------------------
- Ping every player in my game, to force the Global Channel to measure
- the connection response time.
- ---------------------------------------------------------------------*/
- if (TickCount.Time() - ping_timer > 15) {
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_PING;
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 1, &(Players[i]->Address) );
- }
- ping_timer = TickCount.Time();
- }
- /*---------------------------------------------------------------------
- Service the Ipx connections
- ---------------------------------------------------------------------*/
- Ipx.Service();
- /*---------------------------------------------------------------------
- Service the sounds & score; GameActive must be false at this point,
- so Call_Back() doesn't intercept global messages from me!
- ---------------------------------------------------------------------*/
- Call_Back();
- } /* end of while */
- CCDebugString ("C&C95 - Exited process loop\n");
- /*------------------------------------------------------------------------
- Establish connections with all other players.
- ------------------------------------------------------------------------*/
- if (rc) {
- /*.....................................................................
- Set the number of players in this game, and my ID
- .....................................................................*/
- MPlayerCount = Players.Count() + 1;
- MPlayerLocalID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
- /*.....................................................................
- Get the scenario filename
- .....................................................................*/
- Scenario = ScenarioIdx; //PlayerFilenum[ScenarioIdx]; We are passed actual number now from wchat not index from
- //Scenario = MPlayerFilenum[ScenarioIdx];
- /*.....................................................................
- Compute frame delay value for packet transmissions:
- - Divide global channel's response time by 8 (2 to convert to 1-way
- value, 4 more to convert from ticks to frames)
- .....................................................................*/
- MPlayerMaxAhead = MAX( (Ipx.Global_Response_Time() / 8), (unsigned long)2);
- /*.....................................................................
- Send all players the NET_GO packet. Wait until all ACK's have been
- received.
- .....................................................................*/
- CCDebugString ("C&C95 - Sending the 'GO' packet\n");
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_GO;
- GPacket.ResponseTime.OneWay = MPlayerMaxAhead;
- for (i = 0; i < Players.Count(); i++) {
- char flopbuf [128];
- sprintf (flopbuf, "Sending 'GO' packet to address %d\n", *((unsigned short*)&(Players[i]->Address)));
- CCDebugString (flopbuf);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 1, &(Players[i]->Address) );
- /*..................................................................
- Wait for all the ACK's to come in.
- ..................................................................*/
- while (Ipx.Global_Num_Send() > 0)
- Ipx.Service();
- }
- /*.....................................................................
- Form connections with all other players. Form the IPX Connection ID
- from the player's Color (high byte) and House (low byte). This
- will let us extract any player's color & house at any time.
- Fill in 'tmp_id' while we're doing this.
- .....................................................................*/
- for (i = 0; i < Players.Count(); i++) {
- id = Build_MPlayerID (Players[i]->Player.Color,
- Players[i]->Player.House);
- tmp_id[i] = id;
- Ipx.Create_Connection(id, Players[i]->Name, &(Players[i]->Address) );
- }
- #ifdef VIRTUAL_SUBNET_SERVER
- CCDebugString ("C&C95 - Creating connection to the VSS\n");
- /*
- ** Create an additional connection to the VSS
- */
- if (UseVirtualSubnetServer){
- IPXAddressClass vss_global_address;
- NetNodeType vss_node;
- NetNumType vss_net;
- memset (vss_net, 1, sizeof (vss_net));
- memset (vss_node, 0, sizeof (vss_node));
- vss_global_address.Set_Address(vss_net, vss_node);
- Ipx.Create_Connection( VSS_ID, "VSS", &vss_global_address);
- }
- #endif //VIRTUAL_SUBNET_SERVER
- tmp_id[i] = MPlayerLocalID;
- /*.....................................................................
- Store every player's ID in the MPlayerID[] array. This array will
- determine the order of event execution, so the ID's must be stored
- in the same order on all systems.
- .....................................................................*/
- for (i = 0; i < MPlayerCount; i++) {
- min_index = 0;
- min_id = 0xff;
- for (j = 0; j < MPlayerCount; j++) {
- if (tmp_id[j] < min_id) {
- min_id = tmp_id[j];
- min_index = j;
- }
- }
- MPlayerID[i] = tmp_id[min_index];
- tmp_id[min_index] = 0xff;
- }
- /*.....................................................................
- Fill in the array of player names, including my own.
- .....................................................................*/
- for (i = 0; i < MPlayerCount; i++) {
- if (MPlayerID[i] == MPlayerLocalID) {
- strcpy (MPlayerNames[i], MPlayerName);
- } else {
- strcpy (MPlayerNames[i], Ipx.Connection_Name(MPlayerID[i]));
- }
- }
- }
- /*------------------------------------------------------------------------
- Init network timing values, using previous response times as a measure
- of what our retry delta & timeout should be.
- ------------------------------------------------------------------------*/
- Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,
- Ipx.Global_Response_Time() * 4);
- /*------------------------------------------------------------------------
- Clear all lists
- ------------------------------------------------------------------------*/
- Clear_Player_List(&playerlist);
- /*------------------------------------------------------------------------
- Restore screen
- ------------------------------------------------------------------------*/
- Hide_Mouse();
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- Blit_Hid_Page_To_Seen_Buff();
- Show_Mouse();
- if (rc){
- Wait_For_Focus();
- }
- return(rc);
- }
- /***********************************************************************************************
- * Net_Fake_Join_Dialog -- Like Net_Join_Dialog but with no dialogs. For Internet Play. *
- * *
- * This 'dialog' does all the non-dialog game set up stuff that is done in the normal *
- * network game set up dialog. The only visible button is 'cancel' *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: 0 = good, -1 = bad *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 5/24/96 11:07AM ST : Created *
- *=============================================================================================*/
- static int Net_Fake_Join_Dialog(void)
- {
- int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
- /*........................................................................
- Dialog & button dimensions
- ........................................................................*/
- /* ###Change collision detected! C:\PROJECTS\CODE\NETDLG.CPP... */
- int d_dialog_w = 120 *factor; // dialog width
- int d_dialog_h = 80*factor; // dialog height
- int d_dialog_x = ((320*factor - d_dialog_w) / 2); // dialog x-coord
- int d_dialog_y = ((200*factor - d_dialog_h) / 2); // centered y-coord
- int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
- int d_margin1=10;
- int d_txt6_h=15;
- int d_gamelist_w = 160*factor;
- int d_gamelist_h = 27*factor;
- int d_gamelist_x = 500*factor; //230*factor; //Off screen
- //int d_gamelist_x = 230*factor; //Off screen
- int d_gamelist_y = d_dialog_y + 20;
- int d_playerlist_w = 106*factor;
- int d_playerlist_h = 27*factor;
- //int d_playerlist_x = 10 * factor; //Off screen
- int d_playerlist_x = 500*factor; //10 * factor; //Off screen
- int d_playerlist_y = d_gamelist_y + 20;
- #if (GERMAN | FRENCH)
- int d_cancel_w = 50*factor;
- #else
- int d_cancel_w = 45*factor;
- #endif
- int d_cancel_h = 9*factor;
- int d_cancel_x = d_dialog_cx - d_cancel_w / 2;
- int d_cancel_y = d_dialog_y + d_dialog_h - 20*factor;
- bool ready_to_go = false;
- #if (GERMAN | FRENCH)
- int width=160*factor;
- int height=80*factor;
- #else
- int width=120*factor;
- int height=80*factor;
- #endif //GERMAN | FRENCH
- Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);
- Format_Window_String((char*)Text_String(TXT_CONNECTING), SeenBuff.Get_Height(), width, height);
- #if (GERMAN | FRENCH)
- d_dialog_w = width + 25*factor;
- d_dialog_x = ((320*factor - d_dialog_w) / 2); // dialog x-coord
- d_cancel_x = d_dialog_cx - (d_cancel_w / 2);
- #endif
- /*........................................................................
- Button Enumerations
- ........................................................................*/
- enum {
- BUTTON_CANCEL = 100,
- BUTTON_GAMELIST,
- BUTTON_PLAYERLIST,
- };
- /*........................................................................
- Redraw values: in order from "top" to "bottom" layer of the dialog
- ........................................................................*/
- typedef enum {
- REDRAW_NONE = 0,
- REDRAW_MESSAGE,
- REDRAW_COLORS,
- REDRAW_BUTTONS,
- REDRAW_BACKGROUND,
- REDRAW_ALL = REDRAW_BACKGROUND
- } RedrawType;
- /*........................................................................
- Dialog variables
- ........................................................................*/
- RedrawType display = REDRAW_ALL; // redraw level
- bool process = true; // process while true
- KeyNumType input;
- JoinStateType joinstate = JOIN_NOTHING; // current "state" of this dialog
- char namebuf[MPLAYER_NAME_MAX] = {0}; // buffer for player's name
- int game_index = -1; // index of currently-selected game
- int join_index = -1; // index of game we're joining
- int rc = 0; // -1 = user cancelled, 1 = New
- JoinEventType event; // event from incoming packet
- int i,j; // loop counter
- int parms_received; // 1 = game options received
- unsigned char tmp_id[MAX_PLAYERS]; // temp storage for sorting player ID's
- int min_index; // for sorting player ID's
- unsigned char min_id; // for sorting player ID's
- unsigned char id; // connection ID
- char * item;
- unsigned long starttime;
- NodeNameType *who;
- void const *up_button;
- void const *down_button;
- if (InMainLoop){
- up_button = Hires_Retrieve("BTN-UP.SHP");
- down_button = Hires_Retrieve("BTN-DN.SHP");
- }else{
- up_button = Hires_Retrieve("BTN-UP2.SHP");
- down_button = Hires_Retrieve("BTN-DN2.SHP");
- }
- /*........................................................................
- Buttons
- ........................................................................*/
- GadgetClass *commands; // button list
- ColorListClass playerlist(BUTTON_PLAYERLIST,
- d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- up_button,
- down_button);
- ListClass gamelist(BUTTON_GAMELIST,
- d_gamelist_x, d_gamelist_y, d_gamelist_w, d_gamelist_h,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- up_button,
- down_button);
- TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- //#if (GERMAN | FRENCH)
- // d_cancel_x, d_cancel_y);
- //#else
- d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
- //#endif
- /*
- ----------------------------- Various Inits ------------------------------
- */
- //MPlayerColorIdx = MPlayerPrefColor; // init my preferred color
- playerlist.Set_Selected_Style(ColorListClass::SELECT_NONE);
- Fancy_Text_Print("", 0, 0, CC_GREEN, TBLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- /*
- --------------------------- Send network query ---------------------------
- */
- CCDebugString ("C&C95 - About to call Send_Join_Queries.\n");
- Send_Join_Queries (game_index, 1, 0);
- Wait_For_Focus();
- CCDebugString ("C&C95 - About to uncompress title page.\n");
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- Blit_Hid_Page_To_Seen_Buff();
- CCDebugString ("C&C95 - About to set the palette.\n");
- Set_Palette(Palette);
- CCDebugString ("C&C95 - Palette was set OK.\n");
- if (LogicPage != &SeenBuff && LogicPage!= &HidPage){
- CCDebugString ("C&C95 - Logic page invalid\n");
- Set_Logic_Page (SeenBuff);
- }
- char a_buffer [128];
- sprintf (a_buffer, "C&C95 - Number of players:%d\n", Players.Count());
- CCDebugString (a_buffer);
- /*
- ---------------------------- Init Mono Output ----------------------------
- */
- CCDebugString ("C&C95 - About to reveal mouse\n");
- while (Get_Mouse_State() > 0) Show_Mouse();
- /*
- ---------------------------- Processing loop -----------------------------
- */
- CCDebugString ("C&C95 - Entering join dialogue loop\n");
- while (process) {
- /*
- ** If we have just received input focus again after running in the background then
- ** we need to redraw.
- */
- if (AllSurfaces.SurfacesRestored){
- AllSurfaces.SurfacesRestored=FALSE;
- display=REDRAW_ALL;
- }
- /*
- ...................... Refresh display if needed ......................
- */
- if (display) {
- Hide_Mouse();
- /*
- .................. Redraw backgound & dialog box ...................
- */
- if (display >= REDRAW_BACKGROUND) {
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- Blit_Hid_Page_To_Seen_Buff();
- Set_Palette(Palette);
- Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
- /*...............................................................
- Dialog & Field labels
- ...............................................................*/
- Draw_Caption (TXT_NONE, d_dialog_x, d_dialog_y, d_dialog_w);
- Fancy_Text_Print(TXT_CONNECTING, d_dialog_cx-width/2, d_dialog_y + 25*factor, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- /*
- .................... Rebuild the button list ....................
- */
- cancelbtn.Zap();
- gamelist.Zap();
- playerlist.Zap();
- commands = &cancelbtn;
- gamelist.Add_Tail(*commands);
- playerlist.Add_Tail(*commands);
- }
- /*
- .......................... Redraw buttons ..........................
- */
- if (display >= REDRAW_BUTTONS) {
- commands->Draw_All();
- }
- Show_Mouse();
- display = REDRAW_NONE;
- }
- /*
- ........................... Get user input ............................
- */
- input = commands->Input();
- /*
- ---------------------------- Process input ----------------------------
- */
- switch (input) {
- /*------------------------------------------------------------------
- CANCEL: send a SIGN_OFF
- - If we're part of a game, stay in this dialog; otherwise, exit
- ------------------------------------------------------------------*/
- case (KN_ESC):
- case (BUTTON_CANCEL | KN_BUTTON):
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_SIGN_OFF;
- strcpy(GPacket.Name,MPlayerName);
- /*...............................................................
- If we're joined to a game, make extra sure the other players in
- that game know I'm exiting; send my SIGN_OFF as an ack-required
- packet. Do not send this packet to myself (index 0).
- ...............................................................*/
- if (joinstate == JOIN_CONFIRMED) {
- //
- // Remove myself from the player list box
- //
- item = (char *)(playerlist.Get_Item(0));
- playerlist.Remove_Item(item);
- delete [] item;
- playerlist.Flag_To_Redraw();
- //
- // Remove myself from the Players list
- //
- who = Players[0];
- Players.Delete(0);
- delete who;
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
- &(Players[i]->Address));
- Ipx.Service();
- }
- }
- /*...............................................................
- Now broadcast my SIGN_OFF so other players looking at this game
- know I'm leaving.
- ...............................................................*/
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- if (IsBridge) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- }
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- Send_Data_To_DDE_Server ("Hello", strlen("Hello"), DDEServerClass::DDE_CONNECTION_FAILED);
- GameStatisticsPacketSent = false;
- Spawn_WChat(false);
- process = false;
- rc = -1;
- #if (0)
- if (joinstate != JOIN_CONFIRMED) {
- process = false;
- rc = -1;
- } else {
- MPlayerGameName[0] = 0;
- joinstate = JOIN_NOTHING;
- display = REDRAW_ALL;
- }
- #endif //(0)
- break;
- /*------------------------------------------------------------------
- JOIN: send a join request packet & switch to waiting-for-confirmation
- mode. (Request_To_Join fills in MPlayerName with my namebuf.)
- ------------------------------------------------------------------*/
- default:
- if (joinstate == JOIN_NOTHING && Games.Count()!=0){
- gamelist.Set_Selected_Index(0);
- join_index = gamelist.Current_Index();
- parms_received = 0;
- if (Request_To_Join (MPlayerName, join_index, &playerlist, MPlayerHouse,
- MPlayerColorIdx)) {
- joinstate = JOIN_WAIT_CONFIRM;
- } else {
- display = REDRAW_ALL;
- }
- }
- break;
- }
- /*---------------------------------------------------------------------
- Resend our query packets
- ---------------------------------------------------------------------*/
- Send_Join_Queries(game_index, 0, 0);
- /*---------------------------------------------------------------------
- Process incoming packets
- ---------------------------------------------------------------------*/
- event = Get_Join_Responses(&joinstate, &gamelist, &playerlist,
- join_index);
- /*.....................................................................
- If we've changed state, redraw everything; if we're starting the game,
- break out of the loop. If we've just joined, send out a player query
- so I'll get added to the list instantly.
- .....................................................................*/
- if (event == EV_STATE_CHANGE) {
- display = REDRAW_ALL;
- if (joinstate==JOIN_GAME_START) {
- CCDebugString ("C&C95 - Received 'GO' packet\n");
- ready_to_go = true;
- } else {
- /*..................................................................
- If we're newly-confirmed, immediately send out a player query
- ..................................................................*/
- if (joinstate==JOIN_CONFIRMED) {
- Clear_Player_List(&playerlist);
- item = new char [MPLAYER_NAME_MAX + 4];
- if (MPlayerHouse==HOUSE_GOOD) {
- sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_G_D_I));
- } else {
- sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_N_O_D));
- }
- playerlist.Add_Item (item, MPlayerTColors[MPlayerColorIdx]);
- who = new NodeNameType;
- strcpy(who->Name, MPlayerName);
- who->Address = IPXAddressClass();
- who->Player.House = MPlayerHouse;
- who->Player.Color = MPlayerColorIdx;
- Players.Add (who);
- Send_Join_Queries (game_index, 0, 1);
- } else {
- /*..................................................................
- If we've been rejected, clear any messages we may have been typing.
- ..................................................................*/
- if (joinstate==JOIN_REJECTED) {
- //
- // Remove myself from the player list box
- //
- item = (char *)(playerlist.Get_Item(0));
- if (item){
- playerlist.Remove_Item(item);
- delete [] item;
- playerlist.Flag_To_Redraw();
- }
- //
- // Remove myself from the Players list
- //
- if (Players.Count()){
- who = Players[0];
- Players.Delete(0);
- delete who;
- }
- }
- }
- }
- } else
- /*.....................................................................
- If a new game is detected, and it's the first game on our list,
- automatically send out a player query for that game.
- .....................................................................*/
- if (event == EV_NEW_GAME && gamelist.Count()==1) {
- gamelist.Set_Selected_Index(0);
- game_index = gamelist.Current_Index();
- Send_Join_Queries (game_index, 0, 1);
- } else
- /*.....................................................................
- If the game options have changed, print them.
- .....................................................................*/
- if (event == EV_GAME_OPTIONS) {
- parms_received = 1;
- display = REDRAW_MESSAGE;
- } else
- /*.....................................................................
- Draw an incoming message
- .....................................................................*/
- if (event == EV_MESSAGE) {
- display = REDRAW_MESSAGE;
- } else
- /*.....................................................................
- A game before the one I've selected is gone, so we have a new index now.
- 'game_index' must be kept set to the currently-selected list item, so
- we send out queries for the currently-selected game. It's therefore
- imperative that we detect any changes to the game list.
- If we're joined in a game, we must decrement our game_index to keep
- it aligned with the game we're joined to.
- .....................................................................*/
- if (event == EV_GAME_SIGNOFF) {
- if (joinstate==JOIN_CONFIRMED) {
- game_index--;
- join_index--;
- gamelist.Set_Selected_Index(join_index);
- } else {
- gamelist.Flag_To_Redraw();
- Clear_Player_List(&playerlist);
- game_index = gamelist.Current_Index();
- Send_Join_Queries (game_index, 0, 1);
- }
- }
- /*---------------------------------------------------------------------
- Service the Ipx connections
- ---------------------------------------------------------------------*/
- Ipx.Service();
- /*---------------------------------------------------------------------
- Clean out the Game List; if an old entry is found:
- - Remove it
- - Clear the player list
- - Send queries for the new selected game, if there is one
- ---------------------------------------------------------------------*/
- for (i = 0; i < Games.Count(); i++) {
- if (TickCount.Time() - Games[i]->Game.LastTime > 400) {
- Games.Delete(Games[i]);
- item = (char *)(gamelist.Get_Item (i));
- gamelist.Remove_Item (item);
- delete [] item;
- if (i <= game_index) {
- gamelist.Flag_To_Redraw();
- Clear_Player_List(&playerlist);
- game_index = gamelist.Current_Index();
- Send_Join_Queries (game_index, 0, 1);
- }
- }
- }
- /*
- ** If we were flagged to start the game and we recognise both players then quit the loop
- */
- //char ddkks[128];
- //sprintf (ddkks, "C&C95 - Players.Count() = %d\n", Players.Count());
- //CCDebugString (ddkks);
- if (ready_to_go){ // && Players.Count() == InternetMaxPlayers){
- rc = 0;
- process = false;
- }
- /*---------------------------------------------------------------------
- Service the sounds & score; GameActive must be false at this point,
- so Call_Back() doesn't intercept global messages from me!
- ---------------------------------------------------------------------*/
- Call_Back();
- }
- /*------------------------------------------------------------------------
- Establish connections with all other players.
- ------------------------------------------------------------------------*/
- if (rc == 0) {
- /*.....................................................................
- If the other guys are playing a scenario I don't have (sniff), I can't
- play. Try to bail gracefully.
- .....................................................................*/
- if (ScenarioIdx==-1) {
- CCMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH);
- //
- // Remove myself from the player list box
- //
- item = (char *)(playerlist.Get_Item(0));
- playerlist.Remove_Item(item);
- delete [] item;
- playerlist.Flag_To_Redraw();
- //
- // Remove myself from the Players list
- //
- who = Players[0];
- Players.Delete(0);
- delete who;
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_SIGN_OFF;
- strcpy (GPacket.Name, MPlayerName);
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
- &(Players[i]->Address));
- Ipx.Service();
- }
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- if (IsBridge) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- }
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- rc = -1;
- } else {
- /*..................................................................
- Set the number of players in this game, and my ID
- ..................................................................*/
- MPlayerCount = Players.Count();
- MPlayerLocalID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
- /*..................................................................
- Get the scenario number
- ..................................................................*/
- Scenario = ScenarioIdx; //PlayerFilenum[ScenarioIdx]; We are passed actual number now from wchat not index from
- /*..................................................................
- Form connections with all other players. Form the IPX Connection ID
- from the player's Color and House. This will let us extract any
- player's color & house at any time. Fill in 'tmp_id' while we're
- doing this.
- ..................................................................*/
- for (i = 0; i < Players.Count(); i++) {
- /*...............................................................
- Only create the connection if it's not myself!
- ...............................................................*/
- if (strcmp (MPlayerName, Players[i]->Name)) {
- id = Build_MPlayerID(Players[i]->Player.Color,
- Players[i]->Player.House);
- tmp_id[i] = id;
- Ipx.Create_Connection((int)id, Players[i]->Name, &(Players[i]->Address) );
- } else {
- tmp_id[i] = MPlayerLocalID;
- }
- }
- #ifdef VIRTUAL_SUBNET_SERVER
- /*
- ** Create an additional connection to the VSS
- */
- if (UseVirtualSubnetServer){
- IPXAddressClass vss_global_address;
- NetNodeType vss_node;
- NetNumType vss_net;
- memset (vss_net, 1, sizeof (vss_net));
- memset (vss_node, 0, sizeof (vss_node));
- vss_global_address.Set_Address(vss_net, vss_node);
- Ipx.Create_Connection( VSS_ID, "VSS", &vss_global_address);
- }
- #endif //VIRTUAL_SUBNET_SERVER
- /*..................................................................
- Store every player's ID in the MPlayerID[] array. This array will
- determine the order of event execution, so the ID's must be stored
- in the same order on all systems.
- ..................................................................*/
- for (i = 0; i < MPlayerCount; i++) {
- min_index = 0;
- min_id = 0xff;
- for (j = 0; j < MPlayerCount; j++) {
- if (tmp_id[j] < min_id) {
- min_id = tmp_id[j];
- min_index = j;
- }
- }
- MPlayerID[i] = tmp_id[min_index];
- tmp_id[min_index] = 0xff;
- }
- /*..................................................................
- Fill in the array of player names, including my own.
- ..................................................................*/
- for (i = 0; i < MPlayerCount; i++) {
- if (MPlayerID[i] == MPlayerLocalID) {
- strcpy (MPlayerNames[i], MPlayerName);
- } else {
- strcpy (MPlayerNames[i], Ipx.Connection_Name(MPlayerID[i]));
- }
- }
- }
- /*---------------------------------------------------------------------
- Wait a while, polling the IPX service routines, to give our ACK
- a chance to get to the other system. If he doesn't get our ACK, he'll
- be waiting the whole time we load MIX files.
- ---------------------------------------------------------------------*/
- i = MAX(Ipx.Global_Response_Time() * 2, (unsigned long)120);
- starttime = TickCount.Time();
- while (TickCount.Time() - starttime < (unsigned)i) {
- Ipx.Service();
- }
- }
- /*------------------------------------------------------------------------
- Init network timing values, using previous response times as a measure
- of what our retry delta & timeout should be.
- ------------------------------------------------------------------------*/
- Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,
- Ipx.Global_Response_Time() * 4);
- /*------------------------------------------------------------------------
- Clear all lists
- ------------------------------------------------------------------------*/
- Clear_Game_List(&gamelist);
- Clear_Player_List(&playerlist);
- /*------------------------------------------------------------------------
- Restore screen
- ------------------------------------------------------------------------*/
- Hide_Mouse();
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- Blit_Hid_Page_To_Seen_Buff();
- Show_Mouse();
- if (rc != -1){
- Wait_For_Focus();
- }
- return(rc);
- }
- #endif
|