Dedicated servers, listen servers

Discuss programming topics for the various GPL'd game engine sources.
Post Reply
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Dedicated servers, listen servers

Post by toneddu2000 »

Hi guys, I'd like to know how to give players the possibility to create a multiplayer game inside FTEQW(but maybe it's for every other quake 1 engine). I created in qc a multiplayer menu that it's like that
  1. Start a listen server
  2. Find a server
  3. Connect to IP
Then I'd like that
  1. Create a listen server. Is it possible in Quake engine or do I need to launch a dedicated server via command line?
  2. Launch in qc menu_slist and it shows all the servers connected at that moment
  3. Connect to an IP that another friend started with his/her listen server(probably storing the IP 192.bla.bla via say command or some such)
Do you guys think it's possible?
Another thing: starting FTEQW dedicated server, it searches

Code: Select all

couldn't exec ftesrv.cfg
Exe: May 12 2015 23:25:33
FTE build May 12 2015
======== fteskel Initialized ========
Loaded progs qwprogs.dat
Server spawned.
Sending heartbeat to 69.59.212.88:27950 (ghdigital.com:27950 69.59.212.88:27950)

Sending heartbeat to 107.161.23.68:27950 (dpmaster.deathmask.net:27950 107.161.2
3.68:27950 [2604:180::4ac:98c1]:27950)
Sending heartbeat to 92.62.40.73:27950 (dpmaster.tchr.no:27950 92.62.40.73:27950
)
]
If I understood correctly, only servers that has the protocol name included in manifest file AND present in that list above, will be present in menu_slist. Am I right?
If yes, how is it possible to add my fteskel protocol and to search for only servers that use that protocol? Has it to be done hardcoded in C?

Thanks a lot guyyyyyyyys!!! :D
Meadow Fun!! - my first commercial game, made with FTEQW game engine
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Dedicated servers, listen servers

Post by Spike »

localcmd("sv_clientslots 255; deathmatch 1; coop 0; setrenderer sv; map dm4\n");

connecting to a friend's server requires that their firewall/nat forwards the packets to the server. the master server stuff requires that the server's NAT/router is reconfigured to have a static public/private port mapping, and that it does not act as a firewall on that port.



It is generally still possible to get a game going even if you're firewalled (so long as you NAT doesn't randomize ports), and without reconfiguring your NAT, by using fte's xmpp plugin. This requires that both users log into an xmpp account (which will automatically log in next time you start up the game, so beware of that). Once you're both logged in, there should be an option to join/invite your friends to your game (as well as enable voip without necessarily connecting to any server). Note that this isn't suitable for unattended dedicated servers.

By using an xmpp server as a relay, the two clients can share information and punch holes in both user's NATs. Typically at least one of you will have a NAT that opens up and lets the other through - its not guarenteed though, as I didn't get around to providing any support for proxies using this.

(I really ought to integrate this stuff into the irc plugin too so that this stuff doesn't need passwords)
if you both a gmail accounts, then you can use that. however, you will generally both need to disable 2-factor authentication. Strictly speaking its possible to connect using google's oauth2, but frankly its a nightmare to do - the only way to make this vaugely user friendly is to send your login details to a server under my control (instead of your client), which is utterly absurd, yay for snooping on everyone's accounts! Naturally this is something I refuse to do.



the dpmaster protocol (of which those three masters that you listed use), permits support for custom protocol names (master servers are sort of like a telephone directory service - they don't provide any actual games, they just tell you about other servers).
they will return ONLY the servers with a matching 'com_protocolname' cvar. There should be no spaces in it or anything (use hypens or underscores if needed).
If its set to the default value, FTE will also utilise quakeworld master server as well as a few NQ ones (which will not only list said servers but also expose your server to people looking for games via said qw master servers).

you can set sv_public 0 to disable the heartbeats, but it can take a while for the master and any clients to realise that your server is meant to be private.



you can implement your own server browser via some menuqc builtins to query the client's database.



so the answers to your two actual questions are:

'setrenderer sv' switches the renderer to the dedicated server. this will also disconnect the local client if you're currently running a map. 'setrenderer gl' can be used to switch back to gl. you might want to create an alias for that or something, so it has a more memorable name.

setting com_protocolname to the same value in both your client and server will make the client's server browser list display ONLY that server (assuming its unique, might need to restart the engine in order to ensure caches are fully purged).
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: Dedicated servers, listen servers

Post by toneddu2000 »

Thanks a lot Spike! But still everything it's a bit to evanescent to me.

Forgetting for a moment the firewall problem (on my Windows7, every time I started a new client/server FTE installation, O.S. asks me if I want to allow fte to use my system ports, so I guess this is just fine. Probably it's a little more complicated for Linux users, but usually a Linux user knows how to solve problems), regarding your reply:
  1. sv_clientslots seems impossible to find in whole fte 4870 release (maybe newer ones?)
  2. You said "the dpmaster protocol (of which those three masters that you listed use), permits support for custom protocol names (master servers are sort of like a telephone directory service - they don't provide any actual games, they just tell you about other servers).
    they will return ONLY the servers with a matching 'com_protocolname' cvar. There should be no spaces in it or anything (use hypens or underscores if needed).
    If its set to the default value, FTE will also utilise quakeworld master server as well as a few NQ ones (which will not only list said servers but also expose your server to people looking for games via said qw master servers).
    "

    Ok, both my FTE server and client have fteskel protocol name, checked by com_protocolname cvar. So, now? How can I start a dedicated server (let's start with this for now) on my little room in Italy (having a public IP, of course, I'm not so ignorant! :D ) and make my map visible in EVERY client's serverlist in the world who has FTE with fteskel protocol set? I mean, how can serverlist retrieve every server with that protocol name in the world? Should'nt be some sort of server list? A remote file, with every server per column with it own IP, which clients download every time in a remote location, to know which servers are up?
[*]setrenderer sv simply transform my client in a server, which it's not what I was looking for. I don't know if terminology I used is correct but, for listen server I meant a temporary server I (as client) run at the moment of game (and it's present as a normal dedicated server in server list) and that turns off when I disconnect my client. Is that possible?


Thanks again Spike!
Meadow Fun!! - my first commercial game, made with FTEQW game engine
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Dedicated servers, listen servers

Post by Spike »

if sv_public is set, and the master servers are configured properly, and its multiplayer, the server will periodically send heartbeats to the master servers.
the master servers will see these heartbeats and add the sender's ip:port to a list (per protocol name). if a server stops sending heartbeats, the server is removed from the list again.

when the user goes into the server browser, the client sends a message to those master servers, asking for a copy of those lists.
when the client receives the addresses, it sends a ping to each game server in turn (to the same public port that the master server saw). this not only discovers the ping to said game server, but also reveals the server's player counts, hostname, and other rules to the client.

local servers can be found by the server browser by using broadcast pings. this means everything still works fine on a closed lan - you can still get a game going.

Its quite disturbing that we don't have any real standard for NQ master servers, but that's a different topic.


its sv_playerslots. which specifies the absolute maximum number of players or spectators on the server (including zombies). it defaults to 32 if deathmatch or coop is enabled, thus ensuring compat with more QW clients. you can set it to 16 if you want to play host to nq clients without bugging them out. any changes will wait until the next map change, however.
maxclients limits the number of players who may join at any one time. it can be changed dynamically, and does not limit spectators.
maxspectators limits spectators but not players. again, dynamic limit.
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: Dedicated servers, listen servers

Post by toneddu2000 »

Re: Dedicated servers, listen servers
if sv_public is set, and the master servers are configured properly, and its multiplayer, the server will periodically send heartbeats to the master servers.
the master servers will see these heartbeats and add the sender's ip:port to a list (per protocol name). if a server stops sending heartbeats, the server is removed from the list again.

when the user goes into the server browser, the client sends a message to those master servers, asking for a copy of those lists.
when the client receives the addresses, it sends a ping to each game server in turn (to the same public port that the master server saw). this not only discovers the ping to said game server, but also reveals the server's player counts, hostname, and other rules to the client.
Ok, thanks. Now it's more clear. But, where are those master servers? Do I need to create my own master server with my fteskel protocol name? And, if yes, do I need to alter C-code in FTEQW engine to do that?
local servers can be found by the server browser by using broadcast pings. this means everything still works fine on a closed lan - you can still get a game going.
Well, on my same PC, I can connect 2+ clients with my server, but it's still not present in my server list. For "broadcast pings", do you mean connect command? Beacause that's what I'm using.
its sv_playerslots. which specifies the absolute maximum number of players or spectators on the server (including zombies). it defaults to 32 if deathmatch or coop is enabled, thus ensuring compat with more QW clients. you can set it to 16 if you want to play host to nq clients without bugging them out. any changes will wait until the next map change, however.
maxclients limits the number of players who may join at any one time. it can be changed dynamically, and does not limit spectators.
maxspectators limits spectators but not players. again, dynamic limit.
Thanks, understood

You said earlier:
you can implement your own server browser via some menuqc builtins to query the client's database.
Please, please, tell me which are those builtins! I read something on FTE_CSQC_SERVERBROWSER, but methods names are difficult to interpret! :D

I tried everything but my server list is always empty. Probably I should update master servers with my fteskel protocol name, but I'm not sure. I'm completely noob to net programming.. :(

Thanks again Spike
Meadow Fun!! - my first commercial game, made with FTEQW game engine
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: Dedicated servers, listen servers

Post by toneddu2000 »

ok it works!! I started a server session with a remote debian server and now, when I refresh the server list, my server it's over there! Yay! :D

Just few more questions Spike:
  1. Server list doesn't upload players present on map, even after lots of refreshing
  2. Server list double click it's not aligned correctly. You have to click a lot more down than where the server bar actually is. That helps me to ask you the 3rd question
  3. Can you please explain how to simulate a server list in csqc? I only need the names of the functions, that's it. I'll do the code
Thanks a loooott! :D
Meadow Fun!! - my first commercial game, made with FTEQW game engine
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Dedicated servers, listen servers

Post by Spike »

search the builtins for *hostcache* (both with different prefixes and postfixes, to make life easy...)

you can find a lame example menuqc/csqc server menu here: http://triptohell.info/moodles/junk/aft ... enusrc.zip (menu/servers.qc)
I ought to put those files onto fte's svn some time.
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: Dedicated servers, listen servers

Post by toneddu2000 »

Spike wrote:you can find a lame example menuqc/csqc server menu here: http://triptohell.info/moodles/junk/aft ... enusrc.zip (menu/servers.qc)
:shock: Cannot believe what I saw! :D OOP in quakec, classes, instantiantions,wow! I always learn something new seeing what you do, Spike! :D
Thanks a lot, I'll post here every progress I make in creating a csqc server list graphic interface
Meadow Fun!! - my first commercial game, made with FTEQW game engine
toneddu2000
Posts: 1395
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: Dedicated servers, listen servers

Post by toneddu2000 »

ok, done. The code I wrote it will be considered a real trash for a REAL programmer like Spike, LH, mh and others, but, for me, it's quite a success! :lol:
Instead of creating a GUI with a slider which it's quite complex to me to do it in quakec (and Spike's example in object oriented quakec it's too difficult to comprehend to me), I created a pre-determined number of rows (60 to be precise) which are populate by ip, name, players present / max players allowed and ping.
Masks are still not implemented. Next time, if I've time! :D

In your csdefs

Code: Select all

.float 		uiMenuServerListRefreshTime;
float 		UI_MENU_MULTI_SERVERLIST_MAX_ROWS=60;
float   	uiMenuServerListSelectedLocY;
float		uiMenuServerListSelectedAddress;
float		UI_MENU_MULTI_SERVERLIST_CHARSIZE = 6;

Code: Select all

void UI_MenuMultiplayerServerlist(float screeenwidth,float screeenheight)
{
	local float field_address = gethostcacheindexforkey("address");
	local float field_name = gethostcacheindexforkey("name");
	local float field_ping = gethostcacheindexforkey("ping");
	local float field_numplayers = gethostcacheindexforkey("numplayers");
	local float field_maxplayers = gethostcacheindexforkey("maxplayers");
        local float maxsv = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT);//VITAL!! without this set, refresh won't work!!!
	local int i,f=0;
	local .float baroddeven=0;
	local float thisping,baropacity;
	
	//draw row headers
	drawstring([50, 0, 0], "Address", [4, 4, 0], [0, 0.45, 0.7], 0.8, 0);
	drawstring([15, 0, 0], "Ping", [4, 4, 0], [0, 0.45, 0.7], 0.8, 0);
	drawstring([400, 0, 0], "Players / Max players", [4, 4, 0], [0, 0.45, 0.7], 0.8, 0);
	drawstring([250, 0, 0], "Server name", [4, 4, 0], [0, 0.45, 0.7], 0.8, 0);
	//populate rows
	if(self.menuPage == UI_MENU_PAGE_MULTI_SERVERLIST){
		for(i=0; i<UI_MENU_MULTI_SERVERLIST_MAX_ROWS; i++){
			f+=UI_MENU_MULTI_SERVERLIST_CHARSIZE;
			thisping = gethostcachenumber(field_ping, i);
			//don't draw empty rows
			if(thisping > 0){
				//odd - even row background
				self.baroddeven = !self.baroddeven;
				if(self.baroddeven){
					baropacity = 0.1;
				}
				else{
					baropacity = 0.25;
				}
				//draw row elements
				drawstring([50, f, 0], sprintf("%-16s", gethostcachestring(field_address, i)), [UI_MENU_MULTI_SERVERLIST_CHARSIZE, UI_MENU_MULTI_SERVERLIST_CHARSIZE, 0], [1, 1, 1], 1, 0);
				drawstring([15, f, 0], sprintf("%d", gethostcachenumber(field_ping, i)), [UI_MENU_MULTI_SERVERLIST_CHARSIZE, UI_MENU_MULTI_SERVERLIST_CHARSIZE, 0], [1, 1, 1], 1, 0);
				drawstring([400, f, 0], strcat(sprintf("%d", gethostcachenumber(field_numplayers, i))," / ",sprintf("%d", gethostcachenumber(field_maxplayers, i))), [UI_MENU_MULTI_SERVERLIST_CHARSIZE, UI_MENU_MULTI_SERVERLIST_CHARSIZE, 0], [1, 1, 1], 1, 0);
				drawstring([250, f, 0], sprintf("%s", gethostcachestring(field_name, i)), [UI_MENU_MULTI_SERVERLIST_CHARSIZE, UI_MENU_MULTI_SERVERLIST_CHARSIZE, 0], [1, 1, 1], 1, 0);
				drawfill([0,f,0] ,[screeenwidth, UI_MENU_MULTI_SERVERLIST_CHARSIZE, 0],[1 , 1, 1], baropacity,0);
			}
		}
		local string addressselected = gethostcachestring(field_address, uiMenuServerListSelectedAddress);
		//draw server selected text
		if(strlen(addressselected)<4){
			drawstring([screeenwidth-360,screeenheight-80, 0], "No server selected", [8, 8, 0], [0.7, 0.2, 0.2], 0.6, 0);
		}
		else{
			drawstring([screeenwidth-360,screeenheight-80, 0], strcat("Server selected: ",gethostcachestring(field_address, uiMenuServerListSelectedAddress)), [8, 8, 0], [1, 1, 1], 0.9, 0);
		}
		//selected highlighted bar
		if(uiMenuServerListSelectedLocY<370){
			drawfill([0,(uiMenuServerListSelectedLocY+UI_MENU_MULTI_SERVERLIST_CHARSIZE),0] ,[screeenwidth, UI_MENU_MULTI_SERVERLIST_CHARSIZE, 0],[0.4 , 0.4, 0], 0.35,0);
		}
	}
}
Then, where you decide your click function

Code: Select all

local string serveraddress = gethostcachestring(gethostcacheindexforkey("address"), uiMenuServerListSelectedAddress);

	if(self.menuPage == UI_MENU_PAGE_MULTI_SERVERLIST){
		//address = gethostcachestring(gethostcacheindexforkey("address"), serverId[z]);
		uiMenuServerListSelectedLocY = floor(menuCursorPos_y)-UI_MENU_MULTI_SERVERLIST_CHARSIZE;
		if(uiMenuServerListSelectedLocY % UI_MENU_MULTI_SERVERLIST_CHARSIZE == 0){
			uiMenuServerListSelectedAddress = uiMenuServerListSelectedLocY;
		}
	}
	//server list refresh button
	if(menuCursorPos_y > 374 && menuCursorPos_y < 389){
		if(self.menuPage == UI_MENU_PAGE_MULTI_SERVERLIST){
			refreshhostcache();
		}
	}
	//server list connect button
	if(menuCursorPos_y > UI_MENU_BUTTON_VERTICAL_PREBOTTOM_MIN && menuCursorPos_y < UI_MENU_BUTTON_VERTICAL_PREBOTTOM_MAX){
		if(self.menuPage == UI_MENU_PAGE_MULTI_SERVERLIST){
			if(serveraddress == ""){
				return;
			}
			if (serveraddress){
				menuActive = FALSE;
				localcmd(sprintf("m_pop;connect %s\n", serveraddress));
			}
		}
	}
Server list not refreshed - connect button inactive
Image
Server list refreshed (by clocking refresh button) - connect button activated
Image

This code will be present in 0.4 fteskel update, when it will be ready
Meadow Fun!! - my first commercial game, made with FTEQW game engine
Post Reply