;- standard headers ;used in most games #TestMode=1 Global TraceMode.l Global GameName.s If InitSprite() = 0 Or InitPalette() = 0 Or InitKeyboard() = 0 MessageRequester("Header Error", "Can't open DirectX 7 or later", 0) End EndIf If InitSprite3D()=0 MessageRequester("Header Error","Can't open 3D sprite",0) End EndIf If InitSound() = 0 MessageRequester("Header Error", "Can't open DirectX 7 Or Sound Card is not present", 0) End EndIf TransparentSpriteColor(-1,0,0,0) ;- Path stuff Global Bitmaps.s Bitmaps="Bitmap files|*.bmp;*.gif;*.ico;*.jpg|All Files|*.*" Global Senario.s Senario="Senario|*.map|Text files|*.txt|All files|*.*" Global XFile.s XFile="Directx|*.x|MilkShape text|*.txt|All Files|*.*" Global MainPath.s Global EXEName.s Global RunMode.l EXEName=ProgramFilename() If Left(UCase(GetFilePart(ProgramFilename() )),9)="PUREBASIC" MainPath="C:\Program Files\PB42\Projects\FPS\" EXEName="FPS Debug" RunMode=1 Else MainPath=GetPathPart(EXEName) EXEName=GetFilePart(EXEName) EndIf ;this is replaced by PB internal functions ;hMod.l = GetModuleHandle_(0) ;MainPath = Space(255) ;GetModuleFileName_(hMod,@MainPath,255) ;MainPath=GetPathPart(MainPath) ;- NetworkINI ;also common internet headers ;note on data header .... ;first word is PlayerNum ; ThisUser or Assigned User ; LastPlayer ;Global maxbuffer.l ;Global datasize.l #DataSize=100 Global NetworkOK NetWorkOK=InitNetwork() #maxbuffer=1000 Global *Buffer ;reserved memory markers, 2 bytes per data #M_LastPlayer=0 #M_ThisUser=2 #M_PlayerNum=4 #M_UserStart=6 Global ModBuffer.l *Buffer=AllocateMemory(#maxbuffer) ;note, first 10 bytes are reserved for system use ;*Buffer = "***0" ;*Buffer +8 = current player turn ... PlayerNum ;*Buffer +6 = ID assigned by Host to Connecting client ... LastPlayer ;*Buffer +4 = Last player number assigned by host Global Port Port=1666 Global GameMode Global NetID Global LastPlayer ; Gamemodes.............. ; 0 - offline ; 1 - host ; 2 - join Global ThisUser ; If joining a game, ThisUser is assigned by the host ; if hosting, this value indicated host options... ; 0 - offline ; 1 - play all unassigned players.... ; 2 - all unassigned players are skipped except player 1 Global UID Global PlayerNum.l ;- PlayerStruct ;ID indicates who controls player ; -1 is computer player controlled by host ; 0, player is not playing Structure PlayerStruct Score.l ID.l Name.s CID.l PingTime.l EndStructure Dim Player.PlayerStruct(4) Player(1)\name="Red" Player(2)\name="Green" Player(3)\name="Blue" Player(4)\name="Purple" ;and of course ;common internet functions Procedure CloseNetwork() If GameMode If GameMode=2 If NetID CloseNetworkConnection(NETID) EndIf Else If NetID CloseNetworkServer() EndIf EndIf EndIf GameMode=0 NETID=0 PlayerNum=0 ThisUser=0 LastPlayer=0 For p=1 To 4 Player(p)\ID=0 Next p ;CallDebugger EndProcedure Procedure ClearBuffer() ;simply fills buffer with null memory to clear any old data For x.l=0 To (#DataSize -1) Step 2 PokeW(*Buffer +x,0) Next x EndProcedure Procedure ClearQue() reply.l=0 event.l=0 Repeat LID.l=0 If GameMode=1 event=NetworkServerEvent() LID=NetworkClientID() ElseIf GameMode=2 event=NetworkClientEvent(NetID) LID=NetID EndIf result.l=0 Select event Case 1 ;new client If LastPlayer=4 ;too many players CloseNetworkConnection(NetworkClientID()) Else LastPlayer +1 Player(LastPlayer)\CID=NetworkClientID() Player(LastPlayer)\ID=LastPlayer EndIf Case 2 ;data result=ReceiveNetworkData(LID, *Buffer, #MaxBuffer) Case 3 ;file ;not supported Case 4 ;disconnection ;scan for player For pn=1 To 4 If Player(pn)\CID=LID CloseNetworkConnection(LID) Player(pn)\CID=0 Player(pn)\ID=0 MessageRequester(GameName,Player(pn)\name+" has disconnected",0) EndIf Next EndSelect Until event=0 EndProcedure Procedure DumpData(msg.s,a.l,b.l) ;msg is the caption for the msg box function ;a is the first word to list ;b is the last word to list thedump.s="" For BufCount.l=a To b thedump=thedump+Str(BufCount)+" > "+Str(PeekW(*Buffer + BufCount*2))+Chr(10) Next BufCount thedump=thedump+"Begin trace?"+Chr(10) thedump=thedump+"Yes to trace, No to abort, Cancel to continue" Select MessageRequester(msg,thedump,#PB_MessageRequester_YesNoCancel) Case #MBID_YES CallDebugger TraceMode=1 Case #MBID_NO End Default TraceMode=0 EndSelect EndProcedure Procedure SendData(APlayer.l) result.l=0 PokeW(*Buffer+#M_PlayerNum,PlayerNum) DumpData("User "+Str(ThisUser)+ " sending to "+Str(APlayer),0,20) If APlayer If Player(APlayer)\CID If GameMode=1 PokeW(*Buffer+#M_ThisUser,APlayer) PokeW(*Buffer+#M_LastPlayer,LastPlayer) EndIf result=SendNetworkData(Player(APlayer)\CID, *Buffer, #datasize) DebugWait("Sending data to player "+Str(APlayer)+" Total data="+Str(result)) Else MessageRequester("Feudal Message Error","Wrong Player CID for Player "+Str(APlayer),0) EndIf Else If GameMode=1 Aplayer=PeekW(*Buffer+#M_ThisUser) PokeW(*Buffer+#M_LastPlayer,LastPlayer) For pn.l=1 To 4 If Player(pn)\CID PokeW(*Buffer+#M_ThisUser,pn) Result = SendNetworkData(Player(pn)\CID, *Buffer, #datasize) DebugWait("Sending data to player "+Str(pn)+" Total data="+Str(result)) EndIf Next PokeW(*Buffer+#M_ThisUser,APlayer) Else If GameMode If NetID PokeW(*Buffer+#M_ThisUser,ThisUser) Result = SendNetworkData(NetID, *Buffer, #datasize) DebugWait("Sending data to Host player Total data="+Str(result)) Else MessageRequester("Feudal Message Error","Wrong NetID for client",0) EndIf EndIf EndIf EndIf Delay(1) EndProcedure Procedure.l CheckData() ;this checks for incoming data reply.l=0 event.l=0 LID.l=0 If GameMode=1 event=NetworkServerEvent() LID=NetworkClientID() ElseIf GameMode=2 event=NetworkClientEvent(NetID) LID=NetID EndIf result.l=0 Select event Case 1 ;new client If LastPlayer=4 ;too many players CloseNetworkConnection(NetworkClientID()) Else LastPlayer +1 Player(LastPlayer)\CID=NetworkClientID() Player(LastPlayer)\ID=LastPlayer ;SaveGameState() ;add a flag here to inform new client of position ;PokeW(*Buffer+2,LastPlayer) ;Result = SendNetworkData(NetworkClientID(), *Buffer, #datasize) ;flag main program of new player entering game reply=-1 EndIf Case 2 ;data result=ReceiveNetworkData(LID, *Buffer+ModBuffer, #MaxBuffer - ModBuffer) DumpData("received by "+Player(ThisUser)\name,0,20) Debug "data in="+Str(result) Debug "mod buffer="+Str(ModBuffer) Debug "Terminate text="+PeekS(*Buffer+#DataSize-5,4) ;DebugWait("Checking data, result="+Str(result)+" ModBuffer="+Str(ModBuffer)) If result>0 If ModBuffer+result=#DataSize ModBuffer=0 reply=#DataSize If GameMode=1 SendData(0) EndIf Else ;check for multiple data in same send If ModBuffer+result>#DataSize reply=#DataSize CopyMemory(*Buffer+#DataSize+1,*Buffer,ModBuffer+result-#DataSize) ModBuffer=ModBuffer+result-#DataSize If GameMode=1 SendData(0) EndIf Else ModBuffer=ModBuffer+result ;check if this is all data If ModBuffer>=#DataSize reply=#DataSize CopyMemory(*Buffer+#DataSize+1,*Buffer,ModBuffer-#DataSize) ModBuffer=ModBuffer-#DataSize If GameMode=1 SendData(0) EndIf EndIf EndIf EndIf Else Debug "no data available" !CheckTestMode ModBuffer=0 reply=DataSize EndIf Case 3 ;file ;not supported Case 4 ;disconnection ;scan for player For pn=1 To 4 If Player(pn)\CID=LID CloseNetworkConnection(LID) Player(pn)\CID=0 Player(pn)\ID=0 MessageRequester(GameName,Player(pn)\name+" has disconnected",0) EndIf Next pn EndSelect ProcedureReturn reply EndProcedure Procedure HostGame() If GameMode If MessageRequester(GameName,"Terminate existing network game?",#PB_MessageRequester_YesNo)=6 ;close the connection CloseNetwork() ;open a new one NetID=CreateNetworkServer(port) If NetID LastPlayer=1 GameMode=1 ThisUser=1 Player(1)\ID=NetID Debug "HostGame MyID="+Str(Player(1)\ID) ;CallDebugger Else MessageRequester(GameName,"Unable to create server",0) EndIf EndIf Else If NetworkOK ;open a connection NetID=CreateNetworkServer(port) If NetID LastPlayer=1 GameMode=1 ThisUser=1 Player(1)\ID=NetID Debug "HostGame MyID="+Str(Player(1)\ID) ;CallDebugger Else MessageRequester(GameName,"Unable to create server",0) EndIf Else MessageRequester(GameName,"Unable use network functions",0) EndIf EndIf EndProcedure Procedure JoinGame() If GameMode If MessageRequester(GameName,"Terminate existing network game?",#PB_MessageRequester_YesNo)=6 ;close the connection CloseNetwork() ;open a new one ExamineIPAddresses() r=NextIPAddress() isp.s=InputRequester(GameName,"What is the target IP address?",IPString(r)) NetID = OpenNetworkConnection(isp, Port) If NetID LastPlayer=0 GameMode=2 ThisUser=0 ;assigned 0 untill assigned a real number by the host Else MessageRequester(GameName,"Unable To join game",0) EndIf EndIf Else If NetworkOK ;open a connection ExamineIPAddresses() r=NextIPAddress() isp.s=InputRequester(GameName,"What is the target IP address?",IPString(r)) NetID = OpenNetworkConnection(isp, Port) If NetID LastPlayer=0 GameMode=2 ThisUser=0 Else MessageRequester(GameName,"Unable To join game",0) EndIf Else MessageRequester(GameName,"Unable use network functions",0) EndIf EndIf EndProcedure Procedure LaunchChat() RunProgram("http://developer.thegamecreators.com/?f=irc") EndProcedure Procedure About(t.s,m.s,v.s) ;norms goofy help about box msg.s="This is norm's"+m+Chr(10) msg=msg+"Version "+v+Chr(10) msg=msg+"Build = "+Str(#PB_Compiler_Date ) MessageRequester(t,msg,0) EndProcedure Procedure PauseKey() ;this pauses until all keys are released ExamineKeyboard() While KeyboardPushed(#PB_Key_All) Delay(1) ExamineKeyboard() Wend EndProcedure Procedure DebugWait(m.s) ;this just pauses a minute ;and adds extra options for tracing CompilerIf #TestMode m=m+Chr(10) prompt.l=#PB_MessageRequester_YesNo CompilerIf #TestMode=2 prompt=#PB_MessageRequester_YesNoCancel m=m+"Press Yes to Trace or Cancel to Continue" CompilerElse m=m+"Press Yes to continue" CompilerEndIf Select MessageRequester("DebugWait",m,prompt) Case #MBID_YES CompilerIf #TestMode=2 CallDebugger TraceMode=1 CompilerEndIf Case #MBID_NO End Default TraceMode=0 EndSelect CompilerEndIf EndProcedure Procedure pCheckTestMode() If TraceMode CallDebugger Else If #TestMode=2 If MessageRequester("Macro Wait","Begin Trace?",#PB_MessageRequester_YesNo)=#MBID_YES TraceMode=1 CallDebugger EndIf EndIf EndIf EndProcedure Procedure.l GetSign(D.l) ;this determines a direction .... ;use this for setting a change direction flag ;0 indicates D is not changing reply.l=0 If d If d>0 reply=1 Else reply=-1 EndIf EndIf ProcedureReturn reply EndProcedure