Es gibt dem Spieler die Auswahlliste zurück, welche Spiele im LAN angeboten werden. Der Spieler kann sich eins aussuchen und wird am dortigen Server angemeldet.
Client-Code:
Code: Alles auswählen
; Konstanten
#MAX_PREFERRED_LENGTH = -1
#SV_TYPE_ALL = $FFFFFFFF
#NERR_SUCCESS = 0
#ERROR_MORE_DATA = 234
#MainWindow = 100
#MMTB = 200
;- Window Constants
Enumeration
#WND_Join_Game
EndEnumeration
;- Gadget Constants
Enumeration
#WND_Join_Game_LICON
#WND_Join_Game_BTN_OK
#WND_Join_Game_BTN_Abbruch
EndEnumeration
; Strukturen und Vars
Structure HOSTENT
h_name.l
h_aliases.l
h_addrtype.w
h_length.w
h_addr_list.l
EndStructure
Structure SERVER_INFO_101
dwPlatformId.l
lpszServerName.l
dwVersionMajor.l
dwVersionMinor.l
dwType.l
lpszComment.l
EndStructure
Structure LAN_RESULT
Name.s
IP_Name.s
Aktiv_Server.l ; 1, wenn dort ein aktiver Server gefunden werden konnte, dann sind auch die weiteren Daten belegt
Spiel_Name.s
Spieler_bisher.l
EndStructure
NewList LAN_Client.LAN_RESULT()
; Initialisieren
If InitSprite() And InitKeyboard() And InitNetwork() = 0
MessageRequester("Error", "Cant initialize Core")
End
EndIf
; Proceduren
Procedure.s GetIPbyName (NameIP.s)
TheIPAdress.s
pHostinfo = gethostbyname_(NameIP)
If pHostinfo = 0
TheIPAdress = "Unable to resolve domain name"
Else
CopyMemory (pHostinfo, hostinfo.HOSTENT, SizeOf(HOSTENT))
If hostinfo\h_addrtype <> #AF_INET
MessageRequester("Info","A non-IP address was returned",0)
Else
While PeekL(hostinfo\h_addr_list+AdressNumber*4)
ipAddress = PeekL(hostinfo\h_addr_list+AdressNumber*4)
TheIPAdress = StrU(PeekB(ipAddress),0)+"."+StrU(PeekB(ipAddress+1),0)+"."+StrU(PeekB(ipAddress+2),0)+"."+StrU(PeekB(ipAddress+3),0)
AdressNumber+1
Wend
EndIf
EndIf
ProcedureReturn TheIPAdress
EndProcedure
Procedure GetLANList()
IPResult.s
se101.SERVER_INFO_101
nStructSize = SizeOf(SERVER_INFO_101)
RetCode = NetServerEnum_(0, 101, @bufptr, #MAX_PREFERRED_LENGTH, @dwEntriesread, @dwTotalentries, #SV_TYPE_ALL, 0, @dwResumehandle)
If RetCode = #NERR_SUCCESS And RetCode <> #ERROR_MORE_DATA
For i = 0 To dwEntriesread - 1
CopyMemory( bufptr + (nStructSize * i),@se101, nStructSize)
Buffer.s=Space(512)
result=WideCharToMultiByte_(#CP_ACP, 0, se101\lpszServerName, 255, @Buffer.s, 512, 0, 0)
IPResult = GetIPbyName (Buffer)
AddElement(LAN_Client())
LAN_Client()\Name = Buffer
LAN_Client()\IP_Name = IPResult
Next
Else
MessageRequester("Info","Failed",0)
EndIf
NetApiBufferFree_(bufptr)
; SendMessage_(MMTextBox,$00B6,0,30)
EndProcedure
Procedure.l Open_WND_Join_Game()
; wählt ein Spiel aus und schliesst die offenen Verbindungen zu anderen Spielservern
; Gibt den Listindex des gewählten Lan-Spiels zurück, oder -1, wenn keines gewählt wurde
back.l = -1
If OpenWindow(#WND_Join_Game, 216, 0, 313, 399, #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar , "Join Game")
If CreateGadgetList(WindowID())
;-
ListIconGadget(#WND_Join_Game_LICON, 10, 30, 290, 330, "Spiel Name", 200)
AddGadgetColumn(#WND_Join_Game_LICON, 2, "Spieler bisher", 85)
AddGadgetColumn(#WND_Join_Game_LICON, 3, "", 1)
ButtonGadget(#WND_Join_Game_BTN_OK, 230, 370, 70, 20, "OK")
ButtonGadget(#WND_Join_Game_BTN_Abbruch, 10, 370, 70, 20, "Abbruch")
; die Gadgets vorbereiten
ResetList(LAN_Client())
While NextElement(LAN_Client())
If LAN_Client()\Aktiv_Server
AddGadgetItem(#WND_Join_Game_LICON, -1, LAN_Client()\Name + " - " + LAN_Client()\Spiel_Name + Chr(10) + Str(LAN_Client()\Spieler_bisher) + Chr(10) + Str(ListIndex(LAN_Client())))
EndIf
Wend
; Aktionsschleife
Repeat
Event = WaitWindowEvent()
If Event = #PB_EventGadget
GadgetID = EventGadgetID()
If GadgetID = #WND_Join_Game_LICON
back = Val(GetGadgetItemText(#WND_Join_Game_LICON, GetGadgetState(#WND_Join_Game_LICON), 2)) ; den index auslesen
ElseIf GadgetID = #WND_Join_Game_BTN_OK
Event = #PB_EventCloseWindow
ElseIf GadgetID = #WND_Join_Game_BTN_Abbruch
back = -1
Event = #PB_EventCloseWindow
EndIf
EndIf
Until Event = #PB_EventCloseWindow
Event = 0 ; nur dieses Fenster schliessen
; die anderen offenen Serververbindungen schliessen
ResetList(LAN_Client())
While NextElement(LAN_Client())
If LAN_Client()\Aktiv_Server And ListIndex(LAN_Client()) <> back ; wenn server, aber nicht der ausgewählte
CloseNetworkConnection(LAN_Client()\Aktiv_Server)
EndIf
Wend
CloseWindow(#WND_Join_Game)
EndIf
EndIf
ProcedureReturn back
EndProcedure
; Welche Clients gibts im Lan
Debug "get lan list"
GetLANList()
;{ teste die Lan-Computer auf Spiel-Server
port.l = 1000
c.l = 0
ResetList(LAN_Client())
While NextElement(LAN_Client())
Debug Str(ListIndex(LAN_Client())) + "- " + LAN_Client()\Name + " -> " + LAN_Client()\IP_Name
; auf welchen Clients läuft ein Server für das Spiel
NetzwerkID = OpenNetworkConnection(LAN_Client()\IP_Name, port)
If NetzwerkID ; wenn die Verbindung aufgebaut werden konnte
LAN_Client()\Aktiv_Server = NetzwerkID
Debug "netzwerkID gefunden: " + Str(NetzwerkID)
Msg.s = Space(20)
If ReceiveNetworkData(NetzwerkID, @Msg, 20)
Debug "received: " + Msg
LAN_Client()\Spieler_bisher = Val(Left(Msg, 1))
Msg = RTrim(Msg)
LAN_Client()\Spiel_Name = Right(Msg, Len(Msg)-1)
Debug "Spiel gefunden: " + LAN_Client()\Spiel_Name
c + 1
EndIf
EndIf
Wend
Debug "alle server getestet"
ResetList(LAN_Client())
While NextElement(LAN_Client())
; zeigt die gefunden server, wenn die letzte Zahl <> 0, läuft dort ein Server
Debug Str(ListIndex(LAN_Client())) + "- " + LAN_Client()\Name + " -> " + LAN_Client()\IP_Name + " - Erg: " + Str(LAN_Client()\Aktiv_Server)
Wend
;}
;{ Auswählen, welches Spiel mitgespielt werden soll
Anmeldung.l = 0 ; 1, wenn angelemdet
If c
t = Open_WND_Join_Game() ; wählt ein Spiel aus und schliesst die offenen Verbindungen zu anderen Spielservern
Debug "t: " + Str(t)
If t > -1 ; Spiel wurde ausgewählt
; die Verbindungsdaten übertragen
SelectElement(LAN_Client(), t)
Debug "listindex: " + Str(ListIndex(LAN_Client()))
NetzwerkID = LAN_Client()\Aktiv_Server
SpielName.s = LAN_Client()\Spiel_Name
; die Anmeldung am Spielserver machen
Debug "verbindungsdaten: ID: " + Str(NetzwerkID) + ". " + SpielName
Msg = "1" ; Bitte um Anmeldung beim Spiel
SendNetworkData(NetzwerkID, @Msg, 1) ; anmeldung für Spiel schicken
Msg = " !"
Repeat ; warte auf die Anmeldebestätigung
If NetworkClientEvent(NetzwerkID) = 2
ReceiveNetworkData(NetzwerkID, @Msg, 3)
EndIf
Debug "anmeldestring: " + Msg
Anmeldung = Val(Left(Msg, 1))
Debug "Anmeldung erhalten: " + Str(Anmeldung)
Delay(100) ; 10 Abfragen pro Sek langen
Until Anmeldung <> 0
EndIf
Else
MessageRequester("Problem", "Keine Spiele zum mitspielen vorhanden")
End
EndIf
;}
If Anmeldung = 1 ; nur starten, wenn angemeldet
MessageRequester("Angemeldet", Str(Anmeldung))
; hier beginnt nun das Spiel...
Else
MessageRequester("Fehler", "Konnte nicht an den gewünschten Spiel teilnehmen")
End
EndIf
Code: Alles auswählen
#MAX_CLIENTS = 8
Dim Client.l(#MAX_CLIENTS)
;{ Den Server erstellen
OpenConsole()
If InitNetwork() = 0
PrintN("Das Netzwerksystem konnte nicht gestartet werden")
Delay(3000)
End
EndIf
port = 1000 ; Alternativ dazu kann der Port auch eingegeben werden... (1000 wird von Clinet verwendet, muss also dort angepasst werden)
;PrintN("An welchem Port soll der Server lauschen?")
;port=Val(Input())
PrintN("")
PrintN("Geben Sie den Spielnamen an (max. 19 Zeichen)?")
SpielName.s =Input()
If Len(SpielName) > 19
SpielName = Left(SpielName, 19)
EndIf
PrintN("")
PrintN("SpielName: " + SpielName)
PrintN("")
If CreateNetworkServer(port) = 0
PrintN("Server konnte nicht erstellt werden")
Delay(3000)
End
Else
PrintN("Server wurde erstellt")
EndIf
;}
;{ Die Aktionsschleife
Repeat
Select NetworkServerEvent()
Case 1 ;{ a new client has been connected to the server
t = NetworkClientID()
c.l = 0
For x = 0 To #MAX_CLIENTS
If Client(x) <> 0
c + 1
EndIf
Next
Msg.s = Str(c) + SpielName
Msg = Msg + Space(20 - Len(Msg))
SendNetworkData(t, @Msg, 20) ; sendet die bisherige Spieleranzahl und den SPielnamen
PrintN("Serverabfrage - ID: " + Str(t))
;}
Case 2 ;{ Raw Data has been received (To be Read with ReceiveNetworkData())
t = NetworkClientID() ; sender speichern
; testen, ob Sender in Liste eingetragen
cnt.l = -1 ; nächster freier Platz
x.l = -1 ; index des Spielers mit Daten
For y = 0 To #MAX_CLIENTS
If Client(y) = t
x = y
EndIf
If Client(y) = 0 And cnt = -1
cnt = y
EndIf
Next
Debug "x: " + Str(x)
If x > -1 ; wenn schon in der Clientliste
; spezifische Datenverarbeitung
Debug "Erhalte daten von spieler (platz) " + Str(y) + " - verb: " + Str(t)
; Hier nun die Spielspezifische Datenverarbeitung
Else
Debug "neuer client sendet daten"
; Will sich der Client anmelden?
Msg.s = " " ; erwarte einen Anmeldestring
ReceiveNetworkData(t, @Msg, 1)
Debug "gesendet: " + Msg
If Msg = "1" ; Anmeldeversuch
If cnt > -1 ; wenn noch Platz in der Clientliste war
Client(cnt) = t ; in die Liste aufnehmen
PrintN("Neuer Client auf platz " + Str(cnt) + " - NR. " + Str(Client(cnt)))
Msg.s = "1-" + Str(cnt)
SendNetworkData(t, @Msg, 3) ; sende dem Client - Bestätigung Warteliste
Debug "bestätigung verschickt: " + Msg
Else
PrintN("Neuer Client versuchte sich einzuloggen - kein Platz auf Liste")
Msg.s = "9-"
SendNetworkData(t, @Msg, 2) ; sende dem Client - Absage wegen Voll
Debug "absage geschickt: " + Msg
EndIf
EndIf
EndIf
;}
Case 3 ; a file has been received (To be Read with ReceiveNetworkFile())
Case 4 ;{ a client has quit the server (deconnection)
t = NetworkClientID() ; sender speichern
; testen, ob Sender in Liste eingetragen
c.l = 0
For x = 0 To #MAX_CLIENTS
If Client(x) = t
Client(x) = 0 ; aus der Liste austragen
PrintN("Client hat sich ausgeloggt - Nr: " + Str(x))
c + 1
; evtl. Meldung an die anderen Spieler
EndIf
Next
If c = 0
PrintN("Ein Anfrager hat sich ausgeloggt - ID: " + Str(t))
EndIf
;}
EndSelect
Delay(1)
ForEver
;}
Zu guter letzt noch ne Verständnisfrage: Wenn ich das ganze übers Internet spielen will, müsste ich nur die IP-ADresse und den Port für den Server beim Client eingeben (und dafür die Suche weglassen) - Stimmt das?