Game Development Community

Sending a GUI from Server to Client

by Rarw Muffinz · in Torque 3D Beginner · 03/16/2014 (11:36 am) · 10 replies

Hello everyone,
I just wanted to know how to send a gui in a zipped folder from the server to the client.
This would be helpful for sending custom GUIs created by users without leaving the game.
I did a bit of looking around and I couldn't seem to find anything.
Does anyone know how to do this?
Thanks,
Rarw

#1
03/16/2014 (2:30 pm)
In theory you could use a TCPObject or HTTPObject to send the zipped file but you might have to write some custom engine-side code to pack and unpack the zip file and execute the GUI scripts on download if they needed to run in the current game session....

You have the source - "Everything is possible, nothing is forbidden."
#2
03/16/2014 (2:39 pm)
I actually don't have the source in this case. I'm making an extension to a game that I am not the owner of.
#3
03/16/2014 (3:42 pm)
Without the source code, the easiest way to do a server -> client transmission is to code up a custom clientCmd event that transfers the gui in 'x' bytes at a time.

Don't use a .zip, transfer the gui directly using the gui's file. Essentially on the server end, use a FileObject to read the lines from the .gui / .cs file and then do a simple loop IE:

while(!%fileObj.isEOF()) {
   %stuff = %fileObj.read(); //Edit this to get data in groupings of 128 - 256, or w/e
   commandToClient(%client, 'transmitGui', %stuff);
}
commandToClient(%client, 'transmitDone');

The last command tells the client it should have all the data, then you'll just append all the data together, and use eval or some equivalent on it, and there you go.
#4
03/16/2014 (5:28 pm)
Expanded on Robert Fritzen's idea, this should be a bit more complete and working (although untested)

Put this on your server side:
$TMP_FILE + "art/tmpfile.cs";

function SimObject::serialize(%this) {
	//Save to a file so we can read it-- this is the easiest way to serialize
	// without any engine modification
	%this.save($TMP_FILE);
	
	//Read from the saved file
	%file = new FileObject();
	if (!%file.openForRead($TMP_FILE)) {
		//Could not read it
		error("Could not read saved file.");
		%file.close();
		%file.delete();
		return "";
	}
	
	//Ok, we've opened the file. Read it into %buffer
	%buffer = "";
	while (!%file.isEOF()) {
		//Read the next line of the file to %line
		%line = %file.readLine();
		
		//Append %line to %buffer
		%buffer = %buffer NL %line;
	}
	
	%file.close();
	%file.delete();
	return %buffer;
}

function SimObject::send(%this, %client) {
	//Send %this to %client

	//Grab the serialized (stringified) form of %this
	%serialized = %this.serialize();
	
	if (%serialized $= "") {
		//Serialization failed
		error("Could not serialize.");
		return;
	}
	
	//CommandToClient can only send 255 characters at a time
	%maxChars = 255;

	//Split %serialized into parts of %maxChars length
	%parts = mCeil(strLen(%serialized) / %maxChars);
	
	//Send each part to the client
	for (%i = 0; %i < %parts; %i ++) {
		//Get the substring part of the string to send
		%part = getSubStr(%serialized, %maxChars * %i, %maxChars);
   	
		//Send to the client, use id for a unique key
		commandToClient(%client, 'SimSend', %this.getId(), %part);
	}
	//Let them know we finished
	commandToClient(%client, 'SimSendFinish', %this.getId());
}

And on your client side put this:
function clientCmdSimSend(%id, %blob) {
	//Received %blob data, add it to the buffer
	$SimSend::Buffer[%id] = $SimSend::Buffer[%id] @ %blob;
}

function clientCmdSimSendFinish(%id) {
	//We finished receiving the file, evaluate it
	eval($SimSend::Buffer[%id]);
	
	//Clear the buffer
	$SimSend::Buffer[%id] = "";
}
#5
03/16/2014 (6:10 pm)
[redacted, he changed the code]
#6
03/17/2014 (6:33 pm)
Thanks Glenn and Robert. What about picture files that are included with the gui. For example mygui.gui contains a bitmap control "mypic.png". Because a picture cannot be "Read" would seen as a text file?
Im not very good at wording this but I hope someone understands
#7
03/17/2014 (7:50 pm)
You could probably use the same concept. Although at that point it would be easier to just try to get access to the source to use binary transfers.
#8
03/17/2014 (7:56 pm)
can't transfer binary in that engine afaik (if its Blockland your refering too, as we couldn't in marble blast)

wait, now that i think about it....the engine will automatically send textures, so hmm if you could hook it as a texture file and then once its received, call setModPaths() on the root folder, it *might* work. Now, file transfer in MB was slow as heck (MBP 1.50 Multiplayer) so idk how up to date blockland was.
#9
03/17/2014 (8:02 pm)
As far as I know, image sending doesn't work at all. The only real example of binary transfer from server to client is through textures. You could try mapping the image textures to a shape file (as Jeff mentioned), but it would be incredibly hacky and slow. Best to include all the textures beforehand.
#10
03/17/2014 (8:05 pm)
To expand on this as well, the version of torque that blockland used was TGE, not even T3d (I don't know much about it now). If its still the same old engine, then chances are what Glenn and myself mentioned are correct (personal experience I have with MB, as we couldn't and didn't have source access for MBP).