Zeitversetzte "Aktion"

String

Erfahrenes Mitglied
Hallo zusammen,

Ich stehe vor dem Problem, dem User Zeitversetzte Aktionen ermöglichen zu müssen.
Also ein Beispiel was ich genauer meine:

Der User erstellt einen Beitrag / Schreibt einen anderen User etwas. Um zu verhindern, dass ein "unfertiger Beitrag" gepostet wird, oder der User es sich anders überlegt, soll der Beitrag automatisch nach x Minuten sichtbar sein oder beim anderen User ankommen.
(Sinn der Sache ist einfach, dass ich Zeit haben will, dein Beitrag kurz zu überarbeiten, bearbeiten bzw. eine eigene PHP Funktion drüber laufen zu lassen - nehme ich keinen Einfluss, sollte dieser einfach angezeigt werden)

Oder ein weiteres Beispiel aus vielen Browsergames: Gebäude Update dauert noch 3 Minuten. Nach den 3 Minuten ist das Häuschen dann fertig. - Kampftrupp kommt in 5 Minuten beim Gegner an usw. usw.


Rein auf PHP bezogen sehe ich da kein Problem. Ich könnte für jedes Post ein SQL Eintrag (Timestamp) machen, sobald dieser Timestamp überschritten ist, das Posting sichtbar schalten.
Oder auf das Gebäude bezogen, ist der Timestamp fällig, wird das Gebäude aufgebaut.
Anders, wo ich mir noch keinen Reim drauf machen kann: Wie Funktioniert bei Browsergames das "Gegner in 3 Minuten da, Kampf, und wieder zurück" voll automatisch..?

Nachteil dieser Methode: Bei jedem Seitenaufruf muss die "gesamte" DB bzw. die Tabellen kontrolliert werden, ob irgendwo evt. ein Timestamp fällig ist. Weiterer Nachteil: Ist der User nicht online / aktiv, passiert gar nichts und das Posting ist erstmal nicht verfügbar, das Gebäude wird nicht geupdatet, die "Gegner" kommen nicht an..
Grösster Nachteil: Sollen die anderen User auf eine Zeitversetze Aktion reagieren können (auf den Beitrag antworten, Gegner abwehren) muss die "Aktion" erst aktiv geschaltet werden / abgearbeitet werden.

Oder ich mache ein Cronjob, der jede Minute abgearbeitet wird. Das ganze ist aber ziemlich Serverlastig - Und man kann nur Minutengenau arbeiten.


Mir fehlt da so ein bisschen die Zündende Idee, welche mir das "fertig in.." ein wenig erleichtert..
Habt ihr solch ein System schonmal gemacht? Wie lösen das die Browsergames? Die nutzen die Funktion wahrscheinlich tausendfach an hundert verschiedenen stellen..

Bin für jeden Tipp dankbar :)

paD
 
Sieh die SQL-Tabelle als Timeline der zu machenden Aktionen an, die nicht vom User durchlaufen wird, sondern zB von einem Cronjob. Alle 5 Sekunden ein php-script anwerfen, das schaut, was als Nächstes passiert und entscheidet, ob es jetzt dran ist und durchgeführt wird.

Die 5 Sekunden sind jetzt dahingeschmiert, man sollte so etwas soweit wie möglich minimieren und auf den kleinsten Nenner stellen. (kleinste Zeiteinheit 30Sek, also Cronjob alle 30Sek.)

Eine Kombination könnte auch funktionieren. Wenn User online, dann in der Cookie-Session die TimelineID(s) mit ts speichern und per Javascript ständig kontrollieren, ob es Zeit wird, etwas zu unternehmen und dann das php-script mit der ID anschieben. So könnte man die zeitnahen Dinge auf die Sekunde abarbeiten.

(Einfache Gedanken zum Thema, reell nie etwas in Quasi-Echtzeit umgesetzt :))
mfg chmee
 
Hm.. hattest du da eine neue Tabelle gedacht, welche die Zeitversetzten Aufträge abarbeitet, egal welcher Art?
Also quasi:

ID, AUFTRAG, FAELLIG, USERID

Und im Auftrag steht halt was z.B. gemacht werden soll?

Dann könnte man das schön mit JS/Ajax auslesen und reagieren. Ist aber natürlich die Frage, wie gut man damit arbeiten kann und ob das System Sinnvoll ist oder sogar Probleme hat / nicht funktioniert, was mir jetzt nicht so auf anhieb einfällt..

paD
 
Ja, so in etwa dachte ich mir das.
Eine Auftragsvergabe ist ein einfaches INSERT in jene Tabelle.
Das Abarbeiten übernimmt eine andere Klasse/Funktion/Thread/wie auch immer.

Ein mögliches Problem ist, dass Du(man) nicht immer nur eine -die nächste- Aktion abfragt, sondern am Besten gleich die nächsten 20 - und nach zB 15 wieder nachschaut, ob etwas dazugekommen ist. Der Grund - zuviele SQL-Queries - und da könnte man einiges auf den Client auslagern und dann wirklich in-time abarbeiten. Nicht ganz einfach, aber viel Platz zum Optimieren :)

mfg chmee
 
Zuletzt bearbeitet:
Also ich habe das bei mir so gelöst:

Wenn ein User eine Aktion auslöst meinetwegen Kampf dann wird diese Aktion in eine Tabelle geschrieben.
Jedes Script aus der Navigation includiert zuerst die Aktionsabfrage.php. Ist bei irgendein User eine Aktion abgelaufen also Aktionende>=now() werden Berrechnung zur Aktion durchgeführt (Ressourcen gewonnen oder so) und alles in Tabelle Erreigniss eingetragen.

So werden dann alle Aktionen immer aktualisiert sobald ein User irgendwo klickt und auch nur dann ists wirklich notendig.

Ein 2.es Script Ereigniss wird ebenfalls überall includiert welches abfragt ob es Tabelle Aktion bei den gerad klickenden(Navigation) User eine Aktion gibt welche noch läuft.
Läuft sie noch dann zeige Script "Zeitausgabe bin grade unterwegs".
Das selbe Script prüft vorher ob es ein Ereigniss in der Tabelle Ereigniss gibt wenn ja zeige dem User sein Ereigniss (dann lösche es).

Kurze Erklärung was passiert: Der User klickt also irgendwo in der Navi Gibt es ein Ereigniss zeigt es dies, gibt es eine Aktion zeigt er "ich bin unterwegs". Gibt es nichts dann mach was du willst.


Das ganze funktioniert wunderbar allerdings wartet es noch auf den Praxistest zb. 20 User gleichzeitig (Ich denke da speziell an Locks wegen gleichzeitiger Zugriffe auf die DB). Es ist flexibel genug um die Probleme wie "User ist grad nicht on aber Ressourcen müssen dennoch verechnet werden" zu lösen.
 
Zuletzt bearbeitet:
Hi,

hatte bei meinem Browsergame damals zuerst auch so eine Lösung wie von Joe. Jedoch ging bei mir der Server bei etwa 75 Usern sehr in die Knie, vorallem als das Projekt dann weiter gewachsen ist.

Habe es dann so gelöst:
- Wenn sich der Benutzer einloggt, wird die Tabelle mit den Aufträgen des entsprechenden Users in der Session gespeichert.
- Bei jedem weiteren Seitenaufruf wurde dieses Feld in der Session überprüft ob Aufträge fertig waren und die entsprechenden Aktionen dann durchgeführt. Gleichzeitig wurde der Auftrag dann auch aus der MySQL-Tabelle gelöscht.
- Jeder neue Auftrag wurde zuerst in die Datenbank, und dann wieder in die Session eingetragen
- Falls der Benutzer eine Aktion ausführte, die einen anderen Spieler betraf, so wurden dessen für die Aktion relevanten Aufträge auch noch abgearbeitet.

Somit wurden die Aufträge erst dann verarbeitet, wenn es notwendig war.

// Edit: Regelmäßige "Aufträge", wie die Ressourcenproduktion wurden bei mir mit Hilfe eines Cronjobs durchgeführt, liefen somit nicht über die Auftragstabelle.

Gruß
BK
 
Zuletzt bearbeitet:
Auch eine gute Lösung @Bratkartoffel ich hoffe jetzt nur inständig das meine Scripts nicht zu serverlastig werden. An sich wird ja nur eine sich oft wiederholende Mysqlabfrage gestartet. Das sind die Dinge die man vorher sehr schlecht abschätzen kann ohne ausreichend Praxiserfahrungen. (Wäre beim Cronjob übrigens genauso)

- Falls der Benutzer eine Aktion ausführte, die einen anderen Spieler betraf, so wurden dessen für die Aktion relevanten Aufträge auch noch abgearbeitet.
Das kann dann aber ganz schön verschachtelt werden denke ich. Aber wenn sichs nicht umgehen lässt immernoch besser als nix.
 
Okay, also erstmal Danke für die Antworten.

Man scheint sich also fast einig zu sein, dass eine Art "Warteschlange" abgearbeitet werden sollte. Ob jetzt in der Session oder in MySQL ist wahrscheinlich aufgaben abhängig, wie Serverlastig diese wirklich sind.

Aber wie habt ihr das mit den benötigten Parametern gelöst?
Ich stelle mir das etwa so vor:

SQL Tabelle user_aufgaben:
id, userid, aufgabe, faelligkeit

Bei jedem Seitenaufruf wird kurz geprüft, ob meine UserID eine Aufgabe mit der Fälligkeit hat. Ist das der Fall, arbeite die Aufgabe ab.
Nur, wie sieht die "Aufgabe" aus? Schreibt ihr dort den PHP-Quelltext rein? Oder eine Datei, welche includet wird, diese dann die Aufgabe quasi abarbeitet?

Nehmen wir als Aufgabe wirklich ein Kampf zwischen Usern. Dann müsste die Aufgabe quasi so aussehen:
-> Angriffskraft gegen Verteidigungskraft aus den SQL Tabellen der User auslesen
-> Gewinner / Verluste berechnen
-> Usern die Nachricht schicken, wie es ausgegangen ist

Sind also eine Menge Faktoren (bzw. Parameter) die ich der "Kampfaufgabe" mit auf den Weg geben muss..

Wie löst ihr das? Oder wie habt ihr das gelöst? :)

Besten Dank

paD
 
Nein, die Aufgabe ist "Kampf - X gegen Y" - alles andere (welches Lvl haben sie, welche Waffen benutzen sie, sonstige Daten) sind Einzelaufgaben, für die das "Abarbeitungsmodul" Kampf XvsY zuständig ist - welches natürlich auch Zugriff auf die DB hat um diese "halbstatischen" Daten abzufragen.. Heisst also, Du baust Dir eine schicke Kurzsprache für die Befehle, welche in der Warteschlange speicherbar ist,

zB für das obige Beispiel "FIGHT-<ID1>-<ID2>"

oder für Baue Haus/Stall/Bergwerk "BUILD-<BuildingID>".

mfg chmee
 
Zuletzt bearbeitet:
Haha, auf die Idee mit der "Kurzsprache" muss man erstmal kommen.
Da lässt sich eigentlich alles mit machen, stimmt :)

Supi, danke :)

Ich setz den Thread mal auf erledigt. Wenn noch jemand gute andere Ideen hat, bitte posten :)

paD
 
Zurück