C_SCAN Funktionsweise

Posted By: CHaP

C_SCAN Funktionsweise - 09/21/10 13:52

Ich komm irgendwie noch nicht so ganz mit dem C_SCAN Befehl auf einer Multiplayer Plattform zurecht. Die Sache ist folgende:
Die Clients führen unregelmäßg C_SCAN Befehle aus und tasten somit ihre Umgebung ab. Soweit der Plan, doch es wird nichts gefunden.
Wenn ich allerdings den Clients sage: "Wenn du etwas scannen willst, informiere den Server, lasse ihn das erledigen und lasse dir das Ergebnis anschließend schicken."
Funktioniert*s.
Ich finde aber, dass das ein enormer Aufwand ist oder vielmehr ein unötiges Durcheinander.

Ist das der übliche Weg, den Server für die Clients scannen zu lassen?
Ich mein*, es klingt auch an der Stelle logisch, da ja nur er die "original" Level Geometrie erstellt hat. Ich kann es mir aber nicht vorstellen, es gibt bestimmt einen anderen Weg.
Nur komm* ich nicht drauf.
Posted By: Dark_samurai

Re: C_SCAN Funktionsweise - 09/21/10 15:53

Also eigentlich sollte das ohne Probleme funktionieren. Ein Multiplayer Spiel ist ja nichts anderes als ein Singleplayer Spiel das auf mehreren PCs gleichzeitig läuft. Über Lan oder Internet werden nun Pakete ausgetauscht, die die aktuelle Position der beweglichen Entities representieren. Jeder der PCs bewegt die Entities auf die gesendeten Positionen und so sieht es nun aus als würden alle im selben Level rumlaufen. Sprich auf allen Rechnern sind alle Entities auf der gleichen Position (zumindest theoretisch, durch den Ping ist es nicht immer so) und das Level sieht auf allen Rechnern gleich aus. Obwohl es ja in Wirklichkeit lauter einzelne voneinander unabhängige Levels sind die sich absolut nicht von Leveln im Singleplayer unterscheiden. Nur durch das austauschen der Entitypositionen bleiben die Levels synchron.

D.h. du kannst garantiert alle Funktionen wie bisher nutzen. Zusätzlich hast du die Möglichkeit etwas übers Internet/Lan zu senden um die Level synchron zu halten bzw. werden manche Dinge von der Engine automatisch synchron gehalten.

Ok so viel zur Multiplayer Theorie. Ob es intelligent ist c_scan() auf den Clients oder auf dem Server auszuführen kommt auf den Anwendungsfall an. Wenn du z.B. die Explosion eines Raketenwerfers abscannen willst ist es wichtig dies am Server zu tun. Denn dann haben 1) alle Spieler die selben Chancen (da die Spielerpositionen wegen lags nicht auf allen PCs gleich sein müssen) 2) ist es cheatsicherer da ein "böser Bub" hergehen könnte und den Clientcode seines Spiels manipulieren. D.h. der scan wird auf seinem PC durchgeführt und obwohl nichts getroffen wird schickt er ein Paket bei dem z.B. drinnen steht: "Mein Scan hat ergeben, dass ich alle Spieler getroffen habe." Schon hat er einen ultimativen Cheat und ist unaufhaltsam ^^

=> Eine große Regel beim MP programmieren ist: Spielrelevante Dinge wie Schadensberechnung, Schusserkennung (wo hat ein Schuss getroffen),... am Server durchzuführen. Die Clients bekommen dann nur die Resultate zugesendet.
Spielunrelevante Dinge die z.B. nur für "Schönheits Effekte" verwendet werden können bzw. sollten sogar auf den Clients ausgeführt werden, da sonst der Traffic zu hoch wird.

Ok jetzt bin ich zwar ein wenig abgewichen vom eigentlichen Thema aber ich wollte dir nur verdeutlichen warum es wichtig ist im vorhinein zu überlegen ob man etwas am Server oder am Client durchführt.
Posted By: Superku

Re: C_SCAN Funktionsweise - 09/21/10 15:59

Du musst deine Entity-Aktionen auch lokal ablaufen lassen, damit sie per c_scan korrekt erkannt werden können (soweit ich weiß). Stichwort: dplay_localfunction.
Posted By: CHaP

Re: C_SCAN Funktionsweise - 09/22/10 13:55

@Dark_samurai:

Ja, ich dachte auch, dass das ohne weitere Probleme funktionieren sollte. Spinnen wir das mal eben im trockenem durch:
Der Server startet und generiert das Level. Ein Client loggt sich ein und der Server erstellt einen Spieler. Dazu werden zwei Funktionen benutzt:

Code:
/////////////////////////////////////////////////////////////////////////////////////////
void PLAYER_defaultPlayer(void)
{// SRV
	OSM_addMessage("initiated [PLAYER_movePlayer]");
	c_setminmax(my);
	set(my,FLAG2);
//	set(my,ZNEAR);
	while(1)
	{
		my.pan -= my.skill21 * time_step;
		c_move(my,vector(my.skill11,my.skill12,my.skill13),nullvector,USE_POLYGON | USE_AABB | GLIDE | IGNORE_FLAG2 | IGNORE_SPRITES);
		wait(1);
	}
}
/////////////////////////////////////////////////////////////////////////////////////////




Code:
/////////////////////////////////////////////////////////////////////////////////////////
void PLAYER_manipulatePlayer(void)
{// CL
	OSM_addMessage("initiated [PLAYER_manipulatePlayer]");
	while(1)
	{
		if(!(is(pInterfaceInfo,SHOW)))
		{// Interface aktiv? 
			my.skill11 = (5 * (key_w - key_s)) * time_step;
			my.skill12 = (5 * (key_a - key_d)) * time_step;
			my.skill13 = -(c_trace(my.x,vector(my.x,my.y,(my.z - 2000)),USE_POLYGON | USE_AABB | IGNORE_ME | IGNORE_FLAG2));
			if(!mouse_right)
			{
				my.skill21 = mickey.x * time_step;	// pan
			}
			send_skill(my.skill11,SEND_VEC);
			send_skill(my.skill21,0);
		}
		c_scan(my.x,my.pan,vector(360,0,1000),SCAN_ENTS | SCAN_LIMIT);
		wait(1);
	}
}
/////////////////////////////////////////////////////////////////////////////////////////



Die erste ist die, die den Movement des Spielers steuert/überwacht und Server seitig abläuft.
Die zweite wird auf dem Client ausgeführt und sammelt jeweils nur Werte zur Spieler-Movement Manipulation, zudem besitzt sie den C_SCAN Befehl.

Zum Schluss fehlt noch die Funktion, welche die beiden obigen auslößt, d.h.: sobald sich ein Client auf dem Server einloggt, wird diese aufgerufen:

Code:
void PLAYER_initiatePlayer(var vKindOf)
{// SRV
	switch(vKindOf)
	{
		case asCLIENT:
		{
			my = ent_create("lowPlayer.mdl",vector(g_tsCurrentPlayer.spawnX,g_tsCurrentPlayer.spawnY,g_tsCurrentPlayer.spawnZ),PLAYER_defaultPlayer);
			g_ePlayer = my;
			PLAYER_manipulatePlayer();
			break;
		}
	}
}
/////////////////////////////////////////////////////////////////////////////////////////



Weiterhin gibt es natürlich jetzt noch ein Objekt im Level, welches der Server erstellt hat und eine EVENT Funktion besitzt. Der eMASK ist auf ENABLE_SCAN sensibilisiert.
Starte ich nun eine Sitzung und nähere mich diesem scannbaren Objekt, geschieht nichts.
Sobald ich aber den Tipp von Superku berücksichtige und vor dem Laden des kompletten Levels und jeglicher Generierung von Entitys, DPLAY_LOCALFUNCTION auf 2 setze, wird das EVENT bei dem Objekt ausgelöst.

Soweit dazu. Das riecht im Grunde genommen erst einmal nach (einem schwammigen) Erfolg aber, da gibt es zwei Dinge:

1. Wenn man jetzt die Sache mit dem DPLAY_LOCALFUNCTION außer Acht lässt, gibt es da etwas, was in meiner Programmierung und der C_SCAN Sache, auffällig falsch ist?

2. Wenn ich DPLAY_LOCALFUNCTION 2 benutze, so steht es im Manual, muss ich zusätzlich allen Funktionen, welche nicht beidseitig aktiv sein sollen, anpassen, indem ich die CONNECTION Variable abfrage. Verstehe ich das richtig? Der PROC_CLIENT Befehl erschien mir da irgendwie praktischer und, nun ja, übersichtlicher.


EDIT
--------------------------
Wie es scheint, ist es der "normale" Weg mit DPLAY_LOCALFUNCTION 2. Ich habe jetzt erst einmal die Player Funktionen darauf hin angepasst und es Funktioniert. Allerdings beschleicht mich immer noch ein schwammiges Gefühl dabei.
Posted By: Dark_samurai

Re: C_SCAN Funktionsweise - 09/23/10 06:43

Wie das genau gelöst werden muss mit dem Standard Gamestudio Multiplayersystem weis ich nicht da ich es selbst schon lange nicht verwende. Ich habe nur allgemein gesprochen. Natürlich sind diverse Multiplayerimplementierungen immer etwas unterschiedlich also kann es durchaus sein, das DPLAY_LOCALFUNCTION auf 2 zu setzen der richtige Weg ist.
Posted By: CHaP

Re: C_SCAN Funktionsweise - 09/25/10 13:19

Ja, wohl wahr.
Ich halte mich derzeit noch an der experimentellen Try-And-Error Strategie fest.
Mal sehen, wie lange es noch funktioniert.

Bis dahin, Danke!
© 2024 lite-C Forums