Skip to main content

News

Topic: TurboSphere (Read 190943 times) previous topic - next topic

0 Members and 8 Guests are viewing this topic.
  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: TurboSphere
Reply #540
Kind of off topic, but perhaps relevant to the "talking things through" point - Have you looked at my commit history at all?  I like to tell little mini-stories with my commit descriptions (as opposed to just a commit title as most people do), making it quite interesting to go back and read through them as it basically tells the story of the project's development.  In fact that's my metric for when to commit--if it's not a substantial enough edit to warrant more than a title, I hold off on committing.

Basically I can have a dialogue with my future self through my commit messages.  It's kind of neat.
  • Last Edit: March 31, 2015, 03:05:15 am by Lord English
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: TurboSphere
Reply #541
Getting the train back on track after that digression, I highly recommend you implement GetExtensions(), as minisphere does.  It'd be useful to have this API standardized, and two engines implementing the same function goes a long way towards that.  minisphere 1.0.x returns, for example, the following array of strings: [ "sphere-legacy", "minisphere", "frameskip-api" ]

Ideally this should only return native engine functionality.  So TurboSphere could probably return [ "sphere-legacy", "pegasus" ], but if the legacy functions were instead provided externally by a script, "sphere-legacy" would be left out.
  • Last Edit: March 31, 2015, 03:28:20 am by Lord English
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

Re: TurboSphere
Reply #542
Oh, I recall the GetExtensions function :) The two main reasons I haven't had the urge to implement it is that I would need some way to share the array of strings between plugins, and also to the Turbo system scripts.

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: TurboSphere
Reply #543
I don't think the Turbo scripts should be able to affect it, honestly.  Plugins yes, but the idea is that a script calls GetExtensions to determine what the engine supports in native so it can adapt its functionality accordingly.  The Turbo runtime itself, for instance, could call it and look for the "pegasus" string and if it isn't found, fail to initialize.

The only reason I would say Turbo runtime should be able to add an extension string is if the engine is automatically eval-ing the system scripts on behalf of the game, but if so that's frankly a bit tacky and I would consider cutting that out.
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

Re: TurboSphere
Reply #544
I've been considering having TS compile some of the Turbo scripts if a game does not identify version, or identifies needing version 1. This way, when the game runs it gets as close to having a Sphere 1.5-like environment as its going to get with TS out of the box.

I went ahead and made a second kind of socket for TS. So, to accept a connection, you now do this:

Code: (javascript) [Select]

  var listener = new ListeningSocket(8192); //A constructor, otherwise a synonym for ListenOnPort
  while(true){
    var new_socket = listener.accept(); // Will return null if no incoming connections
    if(new_socket){
      // Wait until we actually have something to read.
      while(!new_socket.getPendingReadSize()) Delay(10);

      var buffer = new_socket.read(new_socket.getPendingReadSize());

      // Write out whatever we receive, just to prove it actually happened.
      var logfile = new RawFile("out.log", true);
      logfile.write(buffer);
      logfile.close();
      new_socket.close();
     
      break;
    }
    Delay(10);
  }


Then, if you were going to connect, it would be much like in Sphere 1.5:

Code: (javascript) [Select]

  var socket = new Socket("127.0.0.1", 8192);

  if(!socket.isConnected()) throw "Are you sure the server is running?";

  // The `.buffer' is because ByteArrays are actually UInt8Array's under the hood. This won't be necessary at some point in the future.
  socket.write(CreateByteArrayFromString("Hello, server!\n").buffer);
 
  while(socket.isConnected()) Delay(10); // The server function should drop us pretty quickly.

  Abort("Success!");



This makes the implementation much simpler on the back end compared to how Sphere 1.5 does it. Given the small number of networked games for Sphere, and how simple it is to change them to use this method if desired, I don't really see too much of a need to provide Sphere 1.5 compatibility here. Maybe if I get really ambitions I will add a ListenOnPort function in script to do it.

I have not pushed the Poll/Select/KQueue function out yet because it currently doesn't properly wake if one of the sockets is a listening socket that has an incoming connection on Windows or on OS X. So basically I need to make it actually work with Select and KQueue :)

I have included a simple web server in the default games to demonstrate all this with TurboSphere. I need to fix an issue with rawfile sizes before that works perfectly, but it demonstrates networking is working properly. Once Poll() works properly, then TS will really be ready for networked games!

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: TurboSphere
Reply #545
Why don't you just implement the socket API the way minisphere has it?  This way it's fully backwards compatible and you still get the accept functionality.
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

Re: TurboSphere
Reply #546
How does Minisphere do it?

I did it this way because this is the simplest way for me to implement the native functionality. It wouldn't be too hard to write a ListenOnPort in script that emulates Sphere 1.5.

The reason I want to actually have sockets and listening sockets different is that it gets complicated when someone listens again on the same port. It's kind of wasteful to close the socket and then open up a new one right away. Particularly when you want to sync a list of sockets between script and native for a Poll/Select function.

In native, it's true that technically when you are listening on a socket it's a fully fledged socket. But it's nonsensical to actually use it like a socket--writing to it or reading from it doesn't make sense to do. They are less similar than a FD and socket. I think it's not a bad thing for that dissimilarity to be present, in some form, in script.

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: TurboSphere
Reply #547
Signature for ListenOnPort in minisphere:

Code: [Select]
ListenOnPort(port[, backlog])


If backlog is not specified, the socket behaves as in Sphere 1.5.  Otherwise, it persists as a listener and you call .acceptNext() on it to accept connections.  If you try to read or write to it directly, the engine will throw an exception.
  • Last Edit: April 02, 2015, 09:36:36 pm by Lord English
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

Re: TurboSphere
Reply #548

If backlog is not specified, the socket behaves as in Sphere 1.5.


This is the complex part, and the part I am not going to put into the engine proper. It will be fine to have this kind of thing be only available from ListenOnPort. Any TurboSphere-aware program will call the constructor instead of ListenOnPort, and any Sphere 1.5 game won't use actual constructors.

I certainly could add backlog support, but I don't especially think it's a useful value to adjust from script. Setting it to 16 should really be enough for any game.
  • Last Edit: April 02, 2015, 09:39:53 pm by Flying Jester

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: TurboSphere
Reply #549
Oh, of course. :). I didn't expect you to build that into the engine proper, I was just giving you a tip for how to implement ListenOnPort() when you get around to that, to maintain backwards compatibility.
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

Re: TurboSphere
Reply #550
Yeah, I was mostly just working out the native TS API right now.

Oh yeah, and I forgot April Fools! Insert some skit about TurboSphere being Solaris UltraSparc only, or switching to be written PHP...I was busy and couldn't flesh out my ideas for it in time!

I solemnly swear to have a joke ready in time for next year ;D

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: TurboSphere
Reply #551
Honestly I almost forgot about it myself.  The only reason I remembered was because I ended up posting 1.0.3 that day anyway and when I went to update the release date I said "oh yeah, it's April fools!" :D
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: TurboSphere
Reply #552

I certainly could add backlog support, but I don't especially think it's a useful value to adjust from script. Setting it to 16 should really be enough for any game.


Yeah, I don't expect most games to really care about the backlog size much, but keep in mind my other options:
1) Create a whole new set of APIs to create "new" BSD-style sockets, e.g. CreateSocket(), Socket:bind(), etc.
2) Make the optional second parameter to ListenOnPort a boolean, true for BSD style, false for Sphere 1.5 style

My KISS philosophy and goal of keeping minisphere small, both in executable size and codebase precludes the first option, but since I'm adding a new parameter to a function's signature anyway, it makes sense to try to get as much value out of the API change as possible.  The second option would be rather limiting in that regard.  So I arrived at my third option: The optional parameter specifies the size of the backlog.  Even if most games never need to set it to anything other than 16, the option is there.  I'm more forward-thinking than I look. :)
  • Last Edit: April 03, 2015, 01:05:04 am by Lord English
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

Re: TurboSphere
Reply #553
So, I've update the Galileo specification in Pegasus to correlate to how it works in TurboSphere. Based on actual performance characteristics, many of the qualities of Shapes now exist in Groups, and a stubbed up Shader system exists. Despite the word 'Shader', the spec is shading-language agnostic, and doesn't even require a programmable pipeline. In fact, TurboSphere doesn't have one yet, since I haven't needed it yet.

None of this is new in TurboSphere, but the Pegasus docs didn't reflect this until now.
Feedback is welcome! I haven't really had a need for too much more than what's in it now, even when writing the map engine.

On a side note about Pegasus, I'm not too savvy on its whole dependency system. It's a nice idea, but I believe it is a complex solution to a simple problem.

I've also rewritten the FileSystem plugin to be less horrible. It worked well enough, it just looked awful. It's now the same format as Cinnamon and the other simpler plugins are, with a [Plugin].cpp/hpp holding the plugin API code and script.cpp/hpp holding the bindings. I forget why I made the old scriptfs plugin a different way. I must have been under some form of possession or something when I thought up how its source was laid out.

I also got a new laptop. Well, new to me. I began seeing about making a new Windows release. And I remember now why developing in Windows is not my favorite thing to do :P
  • Last Edit: April 06, 2015, 01:44:18 am by Flying Jester

Re: TurboSphere
Reply #554
I may not have mentioned this when I first implemented it, but I did recently fix it again and I thought it might be worth mentioning.

You can pass in actual functions to `SetUpdateScript' and `SetRenderScript', and just about any script-setting function. I think it's pretty ugly to pass in strings to evaluate to those functions in the first place, and I would assume the reason strings were used was that it was easier/the only way in the ancient SpiderMonkey of pre-2000 that the API was originally developed for (especially given how ridiculous the code to call `game()' is in Sphere).

This is also important to note because the scoping in TurboSphere's SetUpdateScript/SetRenderScript is slightly different than it is in Sphere 1.5. It's now the same as if passing in `new Function(str)' was used, rather than the scoping rules of eval. To get the old scoping rules you can just as easily use an anonymous function.