There's no reason for that script/protocol to check that the server acknowledged an integer before sending the next piece of data; that's truly madness.
So if you were going to implement a protocol by reading and writing to a socket stream, the script would look like this:
Code:
script, check socket ok, socket, begin
if(socket is connected(socket) == false) then(
# Suppose we implement sockets to close if something goes wrong (e.g. timeout)
get socket error string(socket, 2)
show text box(6) # Network error: ${S2}
wait for text box
exit returning(false)
)
exit returning(true)
end
script, check for server acknowledgement, socket, valid reply=1, begin
if(socket receive(socket) <> valid reply) then(
show text box(7) # server refused request
wait for text box
exit returning(false)
)
exit returning(true)
end
script, send high score to server, score, name string id, begin
# Return value is the slot that the high score was saved in, 1 for first place, 2 for second place, etc...
# or -1 to indicate that saving the score failed
return(-1)
variable(socket)
socket := connect to server($0="server:foo") # Adding a lump to define server addresses seems unnecessary work
if(check socket ok(socket) == false) then(exit script)
socket send(socket, 37) # command 37 tells the server that the next data sent will be a high score
socket send(socket, score)
socket send string(socket, name string id)
# Waiting on a socket causes the data we've queued up to be flushed (sent).
wait for socket(socket)
if(check socket ok(socket) == false) then(exit script)
if(check for server acknowledgement(socket)) then(
return(socket receive(socket)) # slot
)
disconnect socket(socket)
end
if(socket is connected(socket) == false) then(
# Suppose we implement sockets to close if something goes wrong (e.g. timeout)
get socket error string(socket, 2)
show text box(6) # Network error: ${S2}
wait for text box
exit returning(false)
)
exit returning(true)
end
script, check for server acknowledgement, socket, valid reply=1, begin
if(socket receive(socket) <> valid reply) then(
show text box(7) # server refused request
wait for text box
exit returning(false)
)
exit returning(true)
end
script, send high score to server, score, name string id, begin
# Return value is the slot that the high score was saved in, 1 for first place, 2 for second place, etc...
# or -1 to indicate that saving the score failed
return(-1)
variable(socket)
socket := connect to server($0="server:foo") # Adding a lump to define server addresses seems unnecessary work
if(check socket ok(socket) == false) then(exit script)
socket send(socket, 37) # command 37 tells the server that the next data sent will be a high score
socket send(socket, score)
socket send string(socket, name string id)
# Waiting on a socket causes the data we've queued up to be flushed (sent).
wait for socket(socket)
if(check socket ok(socket) == false) then(exit script)
if(check for server acknowledgement(socket)) then(
return(socket receive(socket)) # slot
)
disconnect socket(socket)
end
There's only one wait plus the server connection, so splitting the script into two in order to continue gameplay scripts while waiting isn't so bad.
However I think that messages are more natural to deal with than streams. And apologies, I've been assuming all along that send and receive would send "packets" rather than being stream-orientated, because that's what I'm used to. But when I say "message" I don't mean a packet, but just some data bracketed by start- and end-of-message. (Bundling a stream of data into packets is actually done automatically by TCP -- in fact you can't see anything about the TCP packets.) But actually it makes the scripting interface more complex to delineate messages (just look at the mess I brainstormed on the wiki). But marking the end of a message can be done implicitly by "wait for socket".
There are advantages to having data bundled into messages, including that if the message isn't understood then the whole package can be ignored instead of getting into a confused state. (Therefore, there's no need to do error checking after every int.) And it lets you check just once that a message has arrived, rather than having to worry that every call to "socket receive" will block for data or with an error (however it could still throw an error if the next data item was a string rather than an int).
BTW James, you can write just "do (.... break ...)" instead of "while(1)do( ... break ... break)".



