Multiplayer-Monopoly nach MVC

Die Frage brennt mir jetzt schon länger unter den Fingernägeln, und ich habe wirklich versucht mich intensiv mit zu befassen, aber am Ende kommt doch wieder nur Spaghetti-Code raus.
Der Titel sagt es eigentlich schon : ich möchte gerne ein Online-Multiplayer-Monopoly “korrekt” nach MVC gestalten. Leider werde ich weder aus Wikipedia, noch aus dem Beispiel hier noch aus anderen Foren-Posts so wirklich richtig schlau.

Soweit wieich MVC bisher verstanden habe : es gibt drei Komponenten : Model (Daten), View (Darstellung) und Controller (der Name ist Programm).
Weiterhin habe ich verstanden das wenn man es “richtig” macht jede Komponente für sich austauschbar ist (sein sollte) ohne das Änderungen an den anderen Beiden vorgenommen werden müssen. Hier ganz klar : Interfaces !
Nur was mir noch nicht wirklich in den Kopf will ist das Thema : “Wer kennt Wen und Wie ?”.
Laut dem was ich so gelesen und hoffentlich verstanden habe kennt Controller sowohl Model als auch View und registriert sich bei diesen über Listener um auf Änderungen zu reagieren (wobei das schon erweitertes MVC mit Observer ist) und View bzw Model kennen sich weder gegenseitig noch Controller.

Erstmal die Zwischenfrage : bis hier hin richtig oder schon irgendwo falsch ?

Weiter : da das ganze ja Online-Multiplayer-fähig werden soll muss ich auf beiden Seiten mit Proxies arbeiten, zumindest aber zwischen View (Client) und Controller (Server). Wo aber bei dieser Vorgehensweise das Model unterbringen ? Doppelt sowohl Client als auch Server oder nur auf dem Server zentral für alle ? Dann wäre aber der Client selbst wieder nicht “rein” nach MVC sondern auch wieder stark spaghetti-mäßig. Oder würdet ihr hier ganz anders verfahren ?

Die Implementierung der Spiel-Logik an sich und des Net-Stacks ist für mich kein Problem, das graphische werd ich auch noch irgendwie hinbekommen auch wenn es mangels Fähigkeiten im Grafik-Design eher funktional als ansehnlich wird … ich hab halt Probleme erstmal eine vernünftige Struktur reinzubekommen.

Das soll mein erstes “größeres” Projekt werden. Bisher hab ich halt nur so für mich gecoded oder mal was kleines für Freunde gemacht. Auch ein 2-Mann-Schiffe-versenken war schon mal da, aber so wirklich schön war das alles nicht.
Wäre daher froh wenn mir jemand bei diesem Projekt etwas unter die Arme greifen könnte damit ich das ganze mal ordentlich auf die Reihe bekomme.

ps : ich möchte hier keine Grundsatz-Diskusionen lostreten wie man was am umständlichsten machen soll, und es soll auch nicht so nach dem Motto : MVC die x-te werden, aber alleine kommt nur Murks raus.

in der Theorie schon mal alles richtig

ABER

ich habe das Gefühl Du versuchst das gesamte System in MVC zu quetschen - das wird nicht funktionieren. Betrachte doch einfach mal den Client via MVC. Der View ist klar JFrame & Co. Der Controler sitzt irgend wie zwischen View und Model. Das Model ist erstmal nur lokal für View und Controler. Das die Daten eigentlich von einem Server kommen ist dann dem View und Controler schon mal völlig egal.

[QUOTE=Sen-Mithrarin]
Soweit wieich MVC bisher verstanden habe : es gibt drei Komponenten : Model (Daten), View (Darstellung) und Controller (der Name ist Programm).
Weiterhin habe ich verstanden das wenn man es “richtig” macht jede Komponente für sich austauschbar ist (sein sollte) ohne das Änderungen an den anderen Beiden vorgenommen werden müssen. Hier ganz klar : Interfaces !
Nur was mir noch nicht wirklich in den Kopf will ist das Thema : “Wer kennt Wen und Wie ?”.[/QUOTE]
Es gibt nicht die korrekte Implementierung für MVC.
Austauschbar sind die Komponenten oft nur bedingt. Oft ist der Controller recht viewspezifisch. Die View kennt aber auf abstrakter Ebene definitiv das Model, denn diese reagiert auf Änderungen und besorgt sich über die Schnittstelle direkt vom Model die Daten.
Außerdem gibt es je nach Komplexität des Systems mehrere Controller, Models und Views.
Im konkreten Fall sollte m.M. nach das ganze zunächst einmal so implementiert werden, dass das Spiel lauffähig ist unabhängig davon wer und wo der Gegner ist. Soll heißen der Clientanteil ist ein relativ eigenständiges MVC dem es egal ist, ob es überhaupt Gegner gibt, ob diese echt oder KI sind und, ob diese über Netzwerk teilnehmen oder auf dem selben PC spielen. Das miteinander spielen wird dann über einen weiteren “zentralen” Controller gesteuert, der ggf ein eigenes Model nutzt - kenne Monopoly nicht sonderlich gut und bis ins letzte Detail, um dazu konkretere Vorschläge zu machen.

Welches meinst du? Das TicTacToe-Beispiel von Marco13?

*** Edit ***

Stimmt, ich habe mal gelesen, man sollte sogar für jede View einen Controller haben.

@Lex
Ja, genau das meine ich.

@all
Ich glaube, und das wurde ja soweit schon angesprochen, das ich in meiner Vorstellung schon den falschen Ansatz habe. Soweit wie ich mir das ganze bisher zurecht gelegt habe wollte ich halt das reine View vom Controller-Model trennen und eben durch die Netzwerk-Verbindung ersetzen, so das also der Client als solches in sich komplett nur das View selbst darstellt, aber selbst halt weder Controller noch Model hat.

Nach der Erklärung von mogel ergibt das ganze schon mehr Sinn : erstmal den Client als solches nach MVC aufbauen wobei hier alle 3 Komponenten lokal vorhanden sind, und dann lediglich den Controller “nach außen hin” verbinden.

Jedoch auch wenn ich das ganze “umbaue” und dann lokal auch einen Controller habe braucht der Client selbst nicht wirklich ein eigenes Model da die Daten des View nur über den Controller manipuliert werden. Die allgemein bekannte Beziehung das View auch Model kennt bzw sich selbst bei diesem registriert um selbst direkt auf Änderungen reagieren zu können würde ich gerne aufheben / ersatzlos wegfallen lassen so das der Client selbst nur aus View und (Proxy-)Controller besteht und der Server dann logicherweise aus Controller und Model.

Hat auch noch den Hintergrund : auch bei sowas simplen wie Monopoly sollte es nur eine übergeordnete Kontroll-Instanz geben welche die korrekten Daten kennt, und das ist bei nem Multiplayer-Spiel eh immer der Server (zumindest sollte es so sein, es gibt ja diverse sog. AAA-Titel bei denen dieser einfache Grundsatz nicht befolgt wird).

Demnach würde ich es dann so umsetzen das wie gesagt der Client ein View bekommt (halt das Frame und alles was darauf angezeigt wird) welches nur direkt durch den client-seitigen Proxy-Controller manipuliert wird welcher selbst wiederum seine Updates vom Server erhält. Außerdem registriert sich der lokale Controller über Listener am View um halt auf Events (Maus-Klicks oder andere Aktionen) zu reagieren und diese dann an den eigentlichen Haupt-Controller auf dem Server weiter zu leiten.

Auf dem Server dann die Gegenseite : hier verwaltet der Haupt-Controller alle aktuellen Spieler (glaube im “original”-Monopoly waren es bis zu 6) und hält die Daten wie z.B. akutelle Position, Besitztümer, Finanzen im Model.

Der “Zug-Ablauf” wäre dann das erstmal der Server selbst wissen muss welcher Spieler dran ist und nur diesem überhaupt eine Steuer-Eingabe erlaubt und alle anderen deaktiviert. Das ganze dann im Game-Loop per Broadcast an alle Teilnehmer.

Führt der aktive Spieler nun eine Aktion aus prüft der Controller erstmal ob diese Aktion überhaupt zulässig ist, führt entsprechende Aktion aus und informiert alle Spieler über den dann neuen IST-Zustand.
Hier könnte man auch “sparsam” nur die geänderten Daten übermitteln statt jedes mal quasi das komplette Model auf den Client zu spiegeln, aber das bisschen Bandbreite für die paar Kilobytes sollte jeder heutzutage haben.
Auch brauch ich mir zum Glück keine Gedanken über Dinge machen wie “jeder Spieler sieht nur seine Informationen” da beim normalen Brettspiel eh jeder zu jeder Zeit den Status aller anderen sehen kann.

Würde das dann soweit immer noch halbwegs MVC sein oder laufe ich hier schon wieder gefahr Spaghetti-Code zu erzeugen ?

Danke trotzdem erstmal soweit für den Input.

Spaghetti-Code geht nur wenn Du GOTO verwendest

Solch eine Trennung bekommst du nur mit einem hochkomplexen, generischen Client hin: einem Webbrowser. Und auch nur deshalb, weil du dich um den Client an sich nicht kümmern musst. Ansonsen hast du auf der Clientseite immer Code, der sich um die Verbindung mit dem Server kümmern muss, der Benutzereingaben annimmt etc…

[quote=Sen-Mithrarin;93974]und dann lediglich den Controller „nach außen hin“ verbinden.

Jedoch auch wenn ich das ganze „umbaue“ und dann lokal auch einen Controller habe braucht der Client selbst nicht wirklich ein eigenes Model da die Daten des View nur über den Controller manipuliert werden.[/quote]
Nein, nicht der Controller, sondern das Model muss „nach außen hin“, also zum Server, verbunden werden. Der Controller (im MVC-Sinne) sucht nur die passenden Modellobjekte zusammen und ruft dann die richtigen Methoden darauf auf.

Auf der Serverseite brauchst du in dem Sinne nicht unbedingt MVC. Du kannst dir eine Remote Facade* bauen, auf die du z. B. per RMI zugreifst. Wichtig ist, dass du die Schnittstelle klar definierst.

Zum Rest deines Beitrages: je generischer du den Client hältst, desto flexibler kannst du natürlich die Spieldaten modellieren. Der Client wird dann weitestgehend von den Spielregeln und -steinen unabhängig. Das hat aber auch den Nachteil, dass du keine effiziente Schnittstelle zwischen Client und Server haben kannst, weil der Server dem Client alles detailliert erklären muss. Es wäre dann z. B. nicht so einfach möglich, einen JavaScript Client für das selbe Spiel zu programmieren.

MVC ist nicht das einzige Pattern! MMn spielt MVC hier nur im Client eine Rolle. Die Architektur des Modells solltest du dir viel gründlicher überlegen als diesen kleinen Teilaspekt.

  • eine Remote-Facade, um die Anzahl der Webaufrufe zu minimieren, was die Latenz verringert.

[QUOTE=Sen-Mithrarin]Die allgemein bekannte Beziehung das View auch Model kennt bzw sich selbst bei diesem registriert um selbst direkt auf Änderungen reagieren zu können würde ich gerne aufheben / ersatzlos wegfallen lassen so das der Client selbst nur aus View und (Proxy-)Controller besteht und der Server dann logicherweise aus Controller und Model.

Hat auch noch den Hintergrund : auch bei sowas simplen wie Monopoly sollte es nur eine übergeordnete Kontroll-Instanz geben welche die korrekten Daten kennt, und das ist bei nem Multiplayer-Spiel eh immer der Server (zumindest sollte es so sein, es gibt ja diverse sog. AAA-Titel bei denen dieser einfache Grundsatz nicht befolgt wird).[/QUOTE]
Wie kommst Du darauf, dass es diesen Grundsatz gibt - und falls ja, dass dieser sinnvoll ist bzw. Du in korrekt interpretierst?
Sicher das „es (sollte) nur eine übergeordnete Kontroll-Instanz geben welche die korrekten Daten kennt“ bedeutet, ein Client darf kein Model besitzen?

Spätestens hier („nur geänderte Daten übermitteln“ ) sollte, dann die Frage auftauchen: Geändert gegenüber welchem Zustand und wohin sollen diese übermittelt werden, wenn es auf der Empfängerseite nur Controller und View gibt?
Bei einem simplen Spiel wie Monopoly, könnte man vielleicht das Model (wobei es bereits hier nicht „das“ Model gibt, sondern die Verwaltung der Daten sicherlich in mehreren Models sinnvoll wäre) ausschließlich auf dem Server halten. Das bedeutet u.a. aber für die View, dass Sie ständig (alle benötigten) Daten auf dem Server anfragen muss, wenn die View sich neuzeichnet. Der Traffic ist hier sicherlich noch überschaubar. Problematisch könnte es sein, das ausgerechnet zum Zeitpunkt eines „Repaints“ (kurzfristig) die Netzwerkverbindung streikt und die View im besten Fall ein leeres Spielfeld und im schlechtesten nur ein graues Fenster zeigt. Unschön aber für den weiteren Spielverlauf nicht weiter tragisch. Spätestens bei aufwändigeren Echtzeitspielen, bei denen die View mit 30fps oder mehr rendert stellt sich die Frage: Ist es sinnvoll so oft alle notwendigen Daten zu übertragen und was passiert bei Lags in der Verbindung…

Geht doch in Java gar nicht, oder doch ?

Sie es mal im größeren Kontext : das Gesamt-Projekt ist nach MVC geplant. Wie ich sagte : Server > Controller-Model , Client > View

Wie bitte soll ich DAS denn umsetzen ? Auch wenn man den Client selbst nach MVC aufbaut, also einen Proxy-Controller und ein eigenes Model hat, ist die Verbindung NICHT Aufgabe des Models sondern des Controllers. Deiner Aussage nach müsste ich die Netzwerk-Verbindung im Model implementieren und dann quasi über RMI-Listener ne Art Auto-Sync basteln. Ähm, NOPE. Das ist Aufgabe der Controller untereinander zu kommunizieren.
Wenn also im Game-Loop vom Client der Befehl kommt „würfeln“ dann „würfelt“ der Server und sendet den Wurf sowie die neue bereits im eigenen Model gespeicherten Position an alle Clients via Broadcast. Die Clients können dann entweder über den lokalen Controller die neue Position dierekt setzen oder wenn vorhanden in ein lokales Model speichern (was meiner Meinung nach nicht notwendig ist).

RMI ? Über NAT-Router ? Danke, funktioniert nicht. Hier wäre dann sehr Umständlich eine eigene-Implementierung nötig oder ein entsprechendes Framework. Warum soll ich direkt mit Objekten rumspacken wenn ichs auch einfach mit ein paar Commands machen kann ? Selbst wenn ich es als String übertrage kommt dabei so gut wie nichts an Traffic zusammen.

Eine Implementierung eines AJAX-Client wird schon daran scheitern das die Daten nicht über einen HTTP-Server zur Verfügung gestellt werden sondern über einen eigenen Game-Server, ergo : ich gebe selbst die entsprechende Struktur vor wie das Protokoll aufgebaut wird. Und wenn ich ein „komplettes“ Protokoll habe ist dies an sich bereits die Schnittstelle. Ein Client muss dieses Protkoll dann lediglich korrekt implementieren.

Ist richtig, und MVC selbst wird so ja meist in Verbindung mit Observer implementiert, und wie gesagt : es geht nicht darum den Client selbst als MVC umzusetzen, sondern das Gesamtprojekt, also Client und Server zusammen.

[QUOTE=Unregistered;93991]Wie kommst Du darauf, dass es diesen Grundsatz gibt - und falls ja, dass dieser sinnvoll ist bzw. Du in korrekt interpretierst?
Sicher das „es (sollte) nur eine übergeordnete Kontroll-Instanz geben welche die korrekten Daten kennt“ bedeutet, ein Client darf kein Model besitzen?[/QUOTE]

Gut, nenn mir mal im Bereich „Multiplayer-Gaming“ ein anderes Prinzip ? Es ist nun mal so das sowas (so gut wie) immer als Client-Server Struktur aufgebaut ist. Und dabei MUSS es einfach eine zentral Kontrolle geben > den Server.

Anders ausgedrückt : dürfte Client C1 autonom mit Client C2 irgendwas aushandeln (Positionsbestimmung oder änliches) ohne das es durch den Server, der bei sowas die einzige Instanz ist die was zu sagen hat, kontrolliert wird, würden die Clients 1) a-sync zum Server laufen und 2) durch fehlende Kontrolle Manipulation ermöglichen.

Wenn du das anders siehst, gib mir ein Beispiel

Und NEIN : ich wollte damit NICHT sagen das dies bedeutet das der Client kein eigenes Model haben darf, sondern lediglich das eine eigenmächtige Änderung nich zulässig ist und nur auf Anforderung durch den Server erfolgen darf.

[QUOTE=Unregistered;93991]Spätestens hier („nur geänderte Daten übermitteln“ ) sollte, dann die Frage auftauchen: Geändert gegenüber welchem Zustand und wohin sollen diese übermittelt werden, wenn es auf der Empfängerseite nur Controller und View gibt?
Bei einem simplen Spiel wie Monopoly, könnte man vielleicht das Model (wobei es bereits hier nicht „das“ Model gibt, sondern die Verwaltung der Daten sicherlich in mehreren Models sinnvoll wäre) ausschließlich auf dem Server halten. Das bedeutet u.a. aber für die View, dass Sie ständig (alle benötigten) Daten auf dem Server anfragen muss, wenn die View sich neuzeichnet. Der Traffic ist hier sicherlich noch überschaubar. Problematisch könnte es sein, das ausgerechnet zum Zeitpunkt eines „Repaints“ (kurzfristig) die Netzwerkverbindung streikt und die View im besten Fall ein leeres Spielfeld und im schlechtesten nur ein graues Fenster zeigt. Unschön aber für den weiteren Spielverlauf nicht weiter tragisch. Spätestens bei aufwändigeren Echtzeitspielen, bei denen die View mit 30fps oder mehr rendert stellt sich die Frage: Ist es sinnvoll so oft alle notwendigen Daten zu übertragen und was passiert bei Lags in der Verbindung…[/QUOTE]

Gut, man KÖNNTE (z.B. wenn man alles im JPanel aufbaut) die entsprechende paint() Methode so aufrufen das diese sich irgendwo die Info holt was halt gezeichnet werden soll. Dazu wäre es nötig das das entsprechende JPanel eine ID hat, das System weis wo diese ID im Spielfeld liegt und dann auch im Model für jede ID alle Möglichkeiten speichern müsste was wo wie gezeichnet werden kann. Alleine bei Monopoly wird das, selbst wenn man es als Bit-Maske umsetzt, relativ viel.
→ Vorraussetzung : View müsste Controller oder Model selbst direkt kennen, und genau DAS will ich ja vermeiden.

Eine andere Möglichkeit : das JPanel selbst enthält Flags was in diesem beim nächsten repaint gezeichnet werden soll und diese werden von außen über Setter direkt vom Controller manipuliert. Damit schlägt man gleich zwei Fliegen mit einer Klappe : die benötigten Daten sind grundsätzlich vorhanden (ja, wenn man es ganz eng sieht ist es in dem Sinne ein „das Model ins View stecken“) und View selbst muss Controller nicht kennen da es ausreicht wenn Controller View kennt und sich höchstens über Listener bei diesem Registriert um auf Input-Events zu reagieren.

Trotzdem erstmal danke für den Input.

wie Dir alle versuchen zu erklären: dies wird nicht funktionieren

Hab keine Lust zu jedem Punkt, zu dem mir etwas aufgefallen ist auch etwas zu sagen…

[QUOTE=Sen-Mithrarin]Gut, nenn mir mal im Bereich “Multiplayer-Gaming” ein anderes Prinzip ? Es ist nun mal so das sowas (so gut wie) immer als Client-Server Struktur aufgebaut ist. Und dabei MUSS es einfach eine zentral Kontrolle geben > den Server.

Anders ausgedrückt : dürfte Client C1 autonom mit Client C2 irgendwas aushandeln (Positionsbestimmung oder änliches) ohne das es durch den Server, der bei sowas die einzige Instanz ist die was zu sagen hat, kontrolliert wird, würden die Clients 1) a-sync zum Server laufen und 2) durch fehlende Kontrolle Manipulation ermöglichen.[/QUOTE]
… daher reduziert auf das Wesentliche:

Es hat doch niemand etwas gegen eine “Client-Server Struktur” (i.d.R. sind solche System noch weitaus komplexer) oder etwas dagegen gesagt, dass der Server die Kontrolle über die Daten hat und dieser als einziger die “Wahrheit” kennt und kommuniziert. Auch hat niemand vorgeschlagen, dass Clients direkt miteinander kommunizieren.
Was wir (ich hoffe ich nehme mir damit nicht zuviel heraus) hier versuchen Dir zu erklären ist, das kein (sinnvoller) Weg daran vorbei führt den Client nach MVC oder einem ähnlichen Prinzip aufzubauen. Der Client (wir reden hier ja nicht von einer Web Applikation?) kommt um ein eigenes Model nicht herum. Es geht hierbei nicht um das Model, denn das Model ist die “Wahrheit” auf dem Server, der diese Wahrheit an seine Clients verbreitet. Da deine Clients eine View besitzen, welche Daten/Informationen darstellen sollen, müssen diese Daten an einer Stelle bereitgestellt werden. Das kann ein zentrales, auf einem Server bereitgestelltes Model sein. Bedeutet dann aber, das sobald die View sich aktualisiert alle zur Darstellung relevanten Daten am Server erfragt werden müssen. Bei einem simplen Monopoly ist das ja nicht unbedingt ein Problem. Da der Spieler ja nicht in Echtzeit auf Aktionen seiner Mitspieler reagieren muss, kann er es sicherlich verschmerzen, wenn in einem ungünstigen Fall die Aktualisierung der View ein paar Sekunden oder bei Netzwerkproblem sogar ein paar Minuten dauert. Ob das dann dem Spaß am Spiel förderlich ist, hängt dann sicherlich von der Toleranz des Spielers ab.
Hat der Client Zugriff auf ein “lokales” Model, das immer mit der “Wahrheit” synchronisiert wird und in dem alle für die View relevanten Daten hinterlegt sind, beschränkt sich der Austausch von Client und Server auf ein notwendiges Minimum. Im Falle von Störungen des Netzwerks, kann der Client bzw. dessen View zumindest den letzten für ihn gültigen Stand darstellen und ggf. den Spieler darüber informieren, dass Netzwerk oder sonstige Probleme vorliegen, die eine Aktualisierung der Daten verzögert.
(Wäre mir persönlich lieber, als vor einer Anwendung zu sitzen die nicht reagiert, im schlechtesten Fall die View komplett zerschossen ist und ich keine Ahnung habe warum diese nicht reagiert)

Der Aussage das ein einfacher Swing-Client ohne eigenes Model jedes mal beim Server nachfragen müsste muss ich so leider widersprechen.
Brechen wir es doch wirklich mal auf das einfachste Beispiel runter : JLabel

Server > Game-Loop > Aktion X > Broadcast an alle Spieler > Client-Controller > JLabel.setText()

Jetzt muss man sich erstmal im klaren werden : WO genau werden denn hier die Daten gespeichert ? Genau : im JLabel selbst.
ERGO : alleine dadurch das man vom Server ein Commando an den Client schickt und dieser entsprechendes Verarbeitet kopiert man schon das Model so das bei einem repaint() keine Daten erneut angefordert werden müssen.

Erweitert man das ganze jetzt auf ein aus mehreren JPanel zusammengesetztes Spielbrett so muss der Controller lediglich auf Befehl vom Server bei bestimmten Panels Flags löschen und bei anderen setzen (hier mal davon ausgegangen das in der von JPanel abgeleiteten Klasse entsprechende Flags vorhanden sind). Die Logik was welches Flag letztlich bedeutet und wie damit interagiert werden kann hat den Client nicht zu interessieren.

Und DAS ist für mich schon die Ent-Kopplung zwischen View(-Client) und Controller-Model(-Server).

Sicher, das mag so für ein einfaches Monopoly in Java-Swing hinhauen, und wie es jetzt bei nem 3D-Shooter laufen würde … ganz erlich : keine Ahnung. Aber mit sowas muss ich mich auch nicht weiter beschäftigen, ich bin kein Spieleentwickler.

Und wenn ihr halt meint das wäre so kein MVC und mein vorhaben wäre so nicht durchführbar, naja, dann ist es halt so. An sich das ganze lauffähig umzusetzen ist kein Thema, das wird mit etwas ugly-Code auch so laufen. Ich wollte es halt nur etwas “strukturierter” aufziehen.

~ soweit erstmal solved ~

Ich denke hier ist eher sowas wie „alles kennt und kann alles und alles unübersichtlich und dreckig und und… nicht strukturiert!“ gemeint ^^