2010
05.21

I have lost touch of the quick fun games that everyone loves to play/make. I decided to get out of this little mindset by challenging myself to what i am calling a weekend game. The rules i made for myself are simple :

Start day : some day on a weekend
End day : the next weekend
Restrictions : No more than 3 days touching code, Design to succeed

The results so far, ctrlr. It is going well so far, 1 day or so of code, LOADS to polish. There is meant to be fog of war, so its not that simple even though this map might seem simple. Theres also a hidden backdoor, which lets you get the wifi quicker.

What is it :

A mix of 3 mini games, shared mechanics, simple objective based gameplay.
(so far one mini game is almost entirely playable, just posting for feedback and ideas)

Why is it :

I spent a good few hours playing commandos last weekend, and i love how difficult it is, and i love how the challenges can take long because you have to figure it out. I also love normal stealth/sneaking/security games so i figured i would want to make my own one.

The concept is the four phases, get info on the building etc, get into the internal network via hacking in, set up a nice path to infiltrate, infiltrate and complete objectives.

How is it :

Note, i am designing the game with an iPhone interface for many reasons,
so keep it mind that it will be on a touch device. This means the “weird” zooming feature in the recon phase is designed similar to the photo viewer on the device (where i prototyped interface controls). Also the world scale + finger size makes it difficult to control a tiny player, zooming in also focuses the gameplay, making it a little more intense etc.

Controls :
Double click to zoom in or out
Once zoomed in (and only when zoomed in) you click to move.
Escape goes back from any game mode or menu

Known Issues :

The controls are feeling a bit annoying in recon mode, the collision snags occasionally (my fault)…
Its possible to get “stuck” i think, not sure.
Its possible to double click and have no zoom, and move zoomed out, double click a few times to correct the view.

How does it look :

Where is it :

yes yes, there is a playable version.

Updated 25 May (adding mac build. nothing else new yet)

Windows Build – Self Extractor (1.5MB)
Popular-demand-zip (1.7MB)
Mac version ( > Intel only) (2.1MB)

2010
04.26

Why i care

I am currently using PhoenixCore for my Uplink Clone, and have watched it progress out of PhoenixGL. Jon Parrott made an incredibly cool approach to using a 2d engine with really great performance. More of his awesome work is found on the right or over here Link
PhoenixCore is EASY, its straightfoward and its high level enough to be powerful. And its easy.

What is it

Straight from the site,
PhoenixCore is an experimental 2D rendering framework based on OpenGL and written in C++.
It is a fairly abstract library for rendering 2D geometry.
PhoenixCore’s features include:
Setting up an OpenGL Context.
Processing user Input (Keyboard, Mouse).
Managing OpenGL Context (swapping buffers, etc).
Provides abstract math classes for Vectors and Matrices.
Provides interface to loading and manipulating Textures.
Provides methods to modify the View Port and Transformation Matrix.
Provides classes for representing geometric primitives.
Provides methods for drawing geometric primitives.
Provides abstract class for Color representation and manipulation.
Provides access to high-precision timers.
Provides high-level threaded resource management.
Implements and experimental automatic optimizing batch renderer.

Downloads and Docs

Docs are over here Docs

Get it over here Download

Changes in 0.2

Nightingale has several differences from 0.1. It contains major API changes and upgrading should be taken with caution.

Changed Droppable, Resource, and ResourceManager significantly. They no longer use the create() method or private constructors. They now use intrusive_ptrs instead of shared_ptrs which simplifies our interface.

Abstracted the WindowManager interface and implement GLFW as a WindowManager. This allows us to support other window managers in the future.

A new window event interface that uses boost::signals2.

Removed the core’s dependence on the EventReceiver and made it a singleton. It now has functions for getting what the user has typed ( getKeyboardString ). It also now uses the new WindowEvent system and is used exclusively in client code.

BatchGeometry’s group functions are now taken care of by GroupState objects that are attached to the BatchRenderer for each group id.
More, more.

2010
04.22

Not a lot of time at the moment but i finally fixed the key input issues i was having with my rendering. While i finish the other minor details, i can post something else.

I really love uplink. In honour of its awesomeness, you may notice some resemblance to it in certain places.

Original

My remake

Its intended as a tribute, <3 uplink.

2010
04.20

A formatting note – I have tried to clean the code a little to work with this width of page. The original code with less dumbassery is linked in the header file here for reference.

Get the example code

from here : LINK

I know i needed one.
When i had chosen v8 as my weapon of choice i found it to be incredibly easy to grasp.
What i didnt expect is for the simplicity to grab me around the ankles and dangle
me off the edge of confusion cliff.

Before i realised i was scratching my head with a few good c++ books open wondering what
on earth i had done wrong that was giving v8 exceptions from a single line of code.
What i would advise, is try to avoid shortcuts. I was using CProxyV8, i had seen v8Juice and
both of them are really neat, but every single error i ran into was related to me not understanding
what it is v8 was actually asking for and most times it was because of the use of the wrappers.

Finding my own way
I learnt a few things along the way – using v8 from the ground up is actually easier to understand.
The first thing that helps is to look at the v8 namespace comments as they usually
reveal something important, if its related to the JS side, or if its related to the c++ side.Once i saw
that i was attempting to use a JS object as a c++ class, yea things started to make more sense.

What i needed from v8.
Now while the point and line class example is so heavily leaned on, it still didnt really help me to figure out the route i needed to take to expose certain classes to the script environment. The included sample http process and the other samples also , did things in a very straightforward and limited way. Below i will present an empty class from my codebase, with the code i used to expose and gracefully use the script side easily.

I needed to wrap and unwrap a class.
In order to expose a class to JS, i wanted to use an EXISTING C++ class, and just pass a pointer/handle to the scripts. That way i can also control what part of my game/scripts they can actually overwrite and change, and what instances of class they can manipulate. For example, i dont want multiple instances of the core, or any subsystem of the core. I just want a script side global(used loosely here) that the script writer can access (and which also protects him from accidentally overwriting one of my objects).

A template based helper function
I wrote 2 functions that are free to use , and will wrap and unwrap a class accordingly. The usage of the code provided here is shown lower down, so it might not make sense here. Wrapping involves creating a JS object from a c++ class, and maintaining a handle to manipulate it, and unwrapping involves unwrapping an object to a c++ pointer again, normally from the v8arguments handle that a function passes in on being called.

example use :
ExposeClass< somenamespace::someClass >( somev8Context, someClassInstance, v8::String::New(“someclass”), v8::ReadOnly);

  1.  
  2. //http://blog.owned.co.za v8 Javascript Helper Function ,
  3. //Give this function the c++ object (an instance) to wrap,
  4. //and it returns a JS object to expose things under.
  5. //Note theres 2 functions here ,
  6. //the top one is used by the ExposeClass function
  7.  
  8. template<class T>
  9. v8::Handle<v8::Object> WrapClass(T* y)
  10. {
  11.         // Handle scope for temporary handles,
  12.         v8::HandleScope handle_scope;
  13.         v8::Persistent<v8::ObjectTemplate>  class_template_;
  14.        
  15.         v8::Handle<v8::ObjectTemplate> rt = v8::ObjectTemplate::New();
  16.        
  17.         //The raw template is the ObjectTemplate
  18.         // (that can be exposed to script too)
  19.         //but is maintained internally.
  20.         rt->SetInternalFieldCount(1);
  21.        
  22.         //Create the actual template object,
  23.         class_template_ = v8::Persistent<v8::ObjectTemplate>::New(rt);
  24.        
  25.         //Create the new handle to return, and set its template type
  26.         v8::Handle<v8::Object> result = class_template_->NewInstance();
  27.         v8::Handle<v8::External> class_ptr
  28.         class_ptr = v8::External::New(static_cast<T*>(y));
  29.        
  30.         //Point the 0 index Field to the c++ pointer for unwrapping later
  31.         result->SetInternalField(0, class_ptr);
  32.        
  33.         //Return the value, releasing the other handles on its way.
  34.         return handle_scope.Close(result);
  35. }
  36.  
  37.  
  38. template<class T>
  39. v8::Handle<v8::Object> ExposeClass(v8::Persistent<v8::Context> context,
  40.                                    T* y,
  41.                                    v8::Handle<v8::Value> exposedName,
  42.                                    v8::PropertyAttribute props)
  43. {
  44.         v8::HandleScope handle_scope;
  45.        
  46.          v8::Handle<v8::Object> obj = Core::Script::WrapClass<T>(y);
  47.         context->Global()->Set(exposedName, obj, props);
  48.        
  49.         return handle_scope.Close(obj);
  50. }                      
  51.        

And for unwrapping – (usually inside CALLED functions from script.
use : someNamespace::someClass* sc =
UnwrapClass< someNamespace::someClass >( myJSObjToUnwrap );

  1.  
  2. //http://blog.owned.co.za v8 Javascript Helper Function ,
  3. //Give this function the v8 JS object to unwrap, and the class to unwrap to.
  4.                
  5. template<class T>
  6. T* UnwrapClass(v8::Handle<v8::Object> obj)
  7. {
  8.         v8::Handle<v8::External> field;
  9.         field = v8::Handle<v8::External>::Cast(obj->GetInternalField(0));
  10.         void* ptr = field->Value();
  11.         return static_cast<T*>(ptr);
  12. }
  13.                
  14.  

How i use the above templates
Nobody is claiming magic in the code above, it might even be wrong and or, doing something badly. I just found it to work – any comments and fixes will be noted and adjusted if you comment. Now, the usage, at least MY usage of the above code was to expose c++ classes with existing c++ functions to the script context.

Step 1 – A Class to expose, with some members id like in scripts.

First, i have a c++ class declared, with some static functions that i would like to expose.

  1.  
  2. class cCore
  3. {
  4.  
  5. public:
  6.  
  7.         //This is a simple example,
  8.         //do not copy this as a real class.
  9.         cCore(){};
  10.         ~cCore() {};
  11.  
  12.         //We need a persistant handle to the core in scripts, a non persistant
  13.         //v8::Handle<v8::Object> will get lost in the handle scopes,
  14.         //and throw some weird exceptions to hunt down.
  15.         //Wrap class and unwrap class return
  16.         //NON persistant handles, so store your own
  17.         //persistant ones if you want to
  18.         //use it outside of the first handle scope.
  19.  
  20.         //core script object,  "core" in scripts.
  21.         v8::Persistent<v8::Object> cso_core;                                    
  22.  
  23.         //We expose some functions in our class to the scripts from c++,
  24.         //By wrapping an object (cso_core above) and the attaching functions
  25.         //to that object. Those functions, when called from javascript –
  26.         //end up here.
  27.  
  28.         //The functions are self explanatory.
  29.  
  30.         //Print some text to the console/ui console
  31.         static v8::Handle<v8::Value> xecho(const v8::Arguments& args);   
  32.         //execute a javascript file      
  33.         static v8::Handle<v8::Value> xexec(const v8::Arguments& args);   
  34.         //exit all systems and shutdown      
  35.         static v8::Handle<v8::Value> xexit(const v8::Arguments& args);         
  36.                                        
  37. }; //end class declaration
  38.  
  39.  

Step 2 – Creating the Javascript Object , of my class.

  1.  
  2.                
  3. //Just for clarity sake, so you can see my workflow.
  4. void cScriptSystem::startup()
  5. {
  6.         //Create a script engine for the core
  7.         v8::HandleScope handle_scope;
  8.  
  9.         //Create a context for the system to use
  10.         //(i have just one at this point)
  11.         coreContext = v8::Context::New(NULL, global);
  12.  
  13.         //Enter the main context, making it active.
  14.         v8::Context::Scope context_scope(coreContext);
  15.  
  16.         exposeCore(); //see below
  17. };
  18.                
  19. //And the code to expose the class,
  20. void cScriptSystem::exposeCore()
  21. {
  22.         v8::HandleScope handlescope;
  23.  
  24.         //This will be reused to expose multiple
  25.         //classes, short name for easy code.
  26.         v8::Handle<v8::Object> cc;
  27.                        
  28.         //get the JS version of the C++ object,
  29.         //note that core is simply Core::cCore* core;
  30.         cc = ExposeClass< Core::cCore >(coreContext, core,  
  31.                                          v8::String::New("core"),
  32.                                          v8::ReadOnly);
  33.                        
  34.         //set the persistant handle for use outside of this handlescospe
  35.         core->cso_core = v8::Persistent<v8::Object>::New(cc);
  36.  
  37.         //Give the functions to the object.
  38.         //This makes the functions come out as
  39.         //core.echo(), core.exec(), core.exit() in scripts.
  40.         Expose(core->cso_core, v8::String::New("echo") ,
  41.                v8::InvocationCallback(Core::cCore::xecho));
  42.         Expose(core->cso_core, v8::String::New("exec") ,
  43.                v8::InvocationCallback(Core::cCore::xexec));
  44.         Expose(core->cso_core, v8::String::New("exit") ,
  45.                v8::InvocationCallback(Core::cCore::xexit));
  46.  
  47. };
  48.        
  49.  

Step 3 – Actually handling the function calls on the c++ side.

This is where the unwrapClass comes in… If you noticed the v8::Arguments& args on the functions,
it hands in the class that the function is being called upon. So if i called core.exit() , the object
that it will pass me is the core object (our C++ object, in JS form). See the code for clarity,

  1.  
  2. v8::Handle<v8::Value> cCore::xexit(const v8::Arguments& args)
  3. {
  4.         //args.Holder() is the object that the function was invoked upon.
  5.         //This means it could be exposed to 2 classes,
  6.         //under different types so be sure
  7.         //that you dont just randomly unwrap into the wrong container type.
  8.                        
  9.         Core::cCore* core = UnwrapClass<Core::cCore>( args.Holder() );
  10.                                
  11.         //The code inside the normal exit function is identical,
  12.         //so i can just call the normal c++ code directly.             
  13.         core->startShutdown();
  14.                        
  15.         //This is to return void, basically.
  16.         return v8::Undefined();
  17. }
  18.  

Step 4 – The missing function.
I left out a function along the way, you may have noticed. The function is called Expose,

  1.  
  2. void Expose(v8::Handle<v8::Object> intoObject, v8::Handle<v8::Value> namev8String, v8::InvocationCallback funcID)
  3. {
  4.     v8::HandleScope handle_scope;
  5.  
  6.     v8::Handle<v8::FunctionTemplate> thisFunc;
  7.     thisFunc = v8::FunctionTemplate::New(funcID);
  8.     intoObject->Set(namev8String, thisFunc->GetFunction());
  9. }
  10.  

Conclusion

I hope this helps clarify the v8 logic, and helps users figure out how easy it actually is to automate things with templates and macros. Theres still many ways to simplify the code above but for simplicity – take it as it is.

In closing, v8 offers some super easy to use casting functions. Ill give some examples as i found these to be really nice but be wary, do exception handling, type checking and proper management of values handed to c++ from v8. It will save you some time looking through v8 exception callstacks if you manually handle possible exceptions.

  1.  
  2.         //you can now use it std::string(*somestdstring)
  3. v8::String::Utf8Value   somestdstring ( args[0] );  
  4.                
  5.         //you can now use it *somecstring (same as const char* somecstring;)
  6. v8::String::Utf8Value   somecstring ( args[1] );       
  7.  
  8.         //normal double,
  9. double somedouble = args[2]->ToNumber()->Value();
  10.         //booleans
  11. bool somebool = args[3]->ToBoolean()->BooleanValue();
  12.         //and integers.
  13. int someint = args[4]->ToInt32()->Int32Value()
  14.                
  15. //And one last thing, giving javascript meaningful return values.
  16. //This should be more than enough to let you figure out how simple
  17. //v8 makes things for you on the c++ side.
  18.                
  19.         return handle_scope.Close(v8::Number::New(somedouble));
  20.         return handle_scope.Close(v8::Int32::New(someint));
  21.         return handle_scope.Close(v8::Boolean::New(somebool));
  22.                
  23.  

Out.

2010
04.14

The future, Now.

Main menu is implemented,
new Awesomium experimental build is in and working,
new phoenixCore is being merged.
Client is on the way out, be ready.
If you want to play when its ready, let me know in the comments.

The future for everyone, right now

2010
04.06

Weekend Painting

So with the long weekend around, i decided to do some painting in between my programming to keep me sane. Top down 2d game, high school setting. Dont really wanna give much away but, heres some images –
all hand painted using little bits of photos and a pen tablet. The papers, the carpet and the wood texture is pictures, the rest is just painted in manually to fit the lighting

Click to see the real size

Cafeteria

Principals office

2010
03.24

While i really love writing stories, i know that there are people who can do a better job than i could hope to. I thought about it a while ago and figured if i can give a story writer a tool that truly exposes the features they need to create an epic tale, it will make the world of difference right?

Well, to make things easier on everyone (and offer something interesting to look at) i have made a quick sketch of what i can see a mission editor might look like. Yes, its in game too.

NOTE : CLICK ON THE IMAGE TO SEE THE ACTUAL PREVIEW

Mission Editor Mockup

Keep in mind
This is an extremely rough mockup. Dont get too excited about bad layout and missing information and blah. Its just an idea to get the creative minds thinking. Comments and feedback are more than welcome,

How can the mission editor be something really awesome? DISCUSS :>

2010
03.23

What’s new code side
After spending a bit of time rethinking things for this multi UI experience i was testing and implementing a whole bunch of core code. I rewrote a good number of things that i wasn’t happy with and i was implementing things in a more detached manner.

Once i had that all done i dug into splitting out my hacked up test code into a proper abstracted interface, i got to testing my first interface with my current interface. The test was here, could i have the console (debug window) based javascript shell running at the exact same time as the visual shell, AND, have them using the same core module? Can i tell the core i need a login, and the visual interface responds as well? All things considered i managed to achieve this and more over a few hours thanks to boost, and Jon Parrot (the anti-brain-mess filter i run sometimes).

Typing in console while the main UI runs asynchronous

Blog theme

While you may have noticed by now, i have updated the theme of my blog to something legible. Thanks for all the feedback and views on the last one, and as i continue to make this one better comments are always welcome.
Again, the awesome image in the background is from an awesome friend, Paul – Link
.Fin

2010
03.19

Ok, so apparently the last post was a bit of a mess, i will try again.

What im looking for from the response of the reader.

Simple.

Would you, perhaps a programmer or not, be inclined to extend your client with your own tools if it were like the description below.

Its not complete, its not 100% in depth, its idea based speculation based on some prototyping i did.

The concept of the game

The game is a hacking simulator, a pretend world where there are other players, and NPC’s that are hackable. If you ever played uplink from introversion then you will immediately know the premise.

In the game, a player has a/some computers at his disposable. Each of these computers in the world, can be logged into (unless protected).
The User Interface of the game is a futuristic desktop environment that is customisable via code, in game.
The gameplay consists of missions, storylines, and the usual stuff – mini games pretending to be hacking mechanics etc.

The concept of the “engine”

The idea behind the “engine” in game is to allow the player to extend the operating system. Do your best, to make yourself a better in game hacker. How do i take over the computer at server xyz? I need a tool that can list its users. Write one, steal one, copy one, buy one.

Alot of thought behind the engine i wont bother cramming in one post.

The in-game OS, your deskstop in game

This is where it all happens. You have a web browser, a few network tools (like ping below) and you have a developer priveledged account. What now?

a) Do something new. Make a new clock widget, make a cool flash based tracer. You choose.
b) Make something better. Add a user interface to the command line ping tool. Add a UI to the tracer, make it count in ms instead of seconds.
c) Give something back. Submit a new tool/modified tool for inclusion in the core OS.

The code sample

What the code below is demonstrating is an INGAME ping tool. This has nothing to do with server/game state. It is merely a tool that i would like in game. For example, if a users PC online is running on a slow connection, it will take much longer to get in, do stuff and get out.
This is important because you dont want to get caught, so i can now (based on the simple script below) tell if a user is taking a long time to respond to the server.

Keep in mind

Its a prototype code sample. It semi works and some things i just put in for brevity. I need to know if the direction im taking on exposing the core is worth taking.
WOULD YOU EVEN BOTHER to do something new in game. If its as easy as it is below, would you?

The Client side tool,

  1.  
  2. // Client side tool for pinging another player in the game
  3. // Author : FuzzYspo0N
  4. // Etc
  5.  
  6. //First, in order to create a tool on the client and server side,
  7. //we simply assign a variable as a tool type. This might fail if
  8. //there is already a tool with this name – this returns undefined.
  9.  
  10.     var corePingTool = new core.tool("corePingTool");
  11.  
  12. //Maybe something simple to register a tool with a defined
  13. //callback for users. This global tool shows up at the shell,
  14. // as a "command line" tool,and if a tool invokes
  15. //a ui then it is not run via command shell but explicitly
  16.  
  17.     core.tool.registerGlobalTool("ping", "client name, ping count ");
  18.  
  19. //onExecute gets called whenever someone tries to ping
  20. //(either called via ui or via the above command line)
  21. //Variable arguments handed in
  22. var corePingTool.onExecute = function(param)
  23. {
  24.         // 0 is reserved, so 1 is client name. 2 is ping count.
  25.     var clientName = param[1];
  26.     var pingCount = param[2];
  27.        
  28.     if(pingCount == core.invalid)
  29.     {
  30.         pingCount = 1;
  31.     }
  32.        
  33.     //if we have a user like this, we can use em
  34.     var userId = core.users.isAUser(clientName);
  35.     if(userId != core.users.invalidUser)
  36.     {
  37.         //Create a new network javascript object.
  38.         //This object handles network packing/streams internally.
  39.         //The to dev, this is simple – a javascript object.
  40.         //Push data into the stream, and be done.
  41.                
  42.         //The toolId is to header the packet type, for the server
  43.         //to know what to do with it.
  44.         var pck = new core.net.packet(this.toolId);
  45.                
  46.         //Add our data into the packet for the server to care
  47.         pck.push(userId);
  48.         pck.push(pingCount);
  49.                
  50.         //Give it a callback when its feeling talkative
  51.         pck.response = this.onResponse;
  52.                
  53.         //Send it to the server
  54.         pck.send();
  55.     }
  56. }
  57.  
  58.  
  59. //The servers response to a ping command
  60. var corePingTool.onResponse = function(param)
  61. {
  62.     //0 reserved, 1 is always the response code, 2 is the result
  63.     //(known, from server side), 3 is the client requested
  64.     if(param[1] == core.net.success)
  65.     {
  66.         //should output something like
  67.         //    ping response 128ms from " DumbassTeh"
  68.        
  69.             var end = ‘ from " ‘ + param[3] + ‘ " ‘;
  70.             echo(‘Ping response ‘ + param[2] + ‘ms’ + end);
  71.         }
  72.         else
  73.         {
  74.             //message box failure
  75.         }
  76. }
  77.  

The server side response

  1.  
  2. // Server side tool for pinging another player in the game
  3. // Author : FuzzYspo0N
  4. // Etc
  5.  
  6. //expects – a packet with
  7.     //pop 1 – sourceUserId
  8.     //pop 2 – destUserId
  9.     //pop 3 – ping count
  10.    
  11.  //context globals
  12.  
  13. //var toolId is handed in from the system
  14.  
  15. var corePingTool_Main = function( pck)
  16. {
  17.     //Pck is basically a javascript array, and pop will
  18.     //simply keep a "stackIndex" internally. So in essence
  19.     //what you can see here is
  20.     // stackIndex += 1;
  21.     // return pck[stackIndex - 1];
  22.    
  23.     var sourceId = pck.pop();
  24.     var destId = pck.pop();
  25.     var pingCount = pck.pop();
  26.    
  27.     for(i = 0; i < pingCount; ++i)
  28.     {
  29.         //query : clientId, requesterId, daemonId, handler
  30.         core.net.query(destId, sourceId, toolId, onPingBack);
  31.     }
  32.    
  33. }
  34.  
  35. var onPingBack = function(pck)
  36. {
  37.     //pop 1 – sourceUserId
  38.     //pop 2 – destUserId
  39.     //pop 3 – response – if successful, it will have the ms it took
  40.    
  41.     var sourceId = pck.pop();
  42.     var destId = pck.pop();
  43.     var response = pck.pop();
  44.    
  45.     if(response != core.net.response.timedout)
  46.     {
  47.         //the respond will hit the client callback that
  48.         //pck.onresponse registered.
  49.         core.net.respond(sourceId, toolId, response);
  50.     }
  51.     else
  52.     {
  53.         //respond : destId, toolId, responseCode
  54.         var resp = core.net.response.timedout;
  55.         core.net.respond(sourceId, toolId, resp);
  56.     }
  57. }
  58.  

Comments, views, ideas, etc – Welcome. Please, i like ideas.

Update!!

I am attaching a mockup of how the tools *could* work , for development of the OS features. This is why i need feedback, is it plausible to expect some non developers to enjoy modifiying their desktop more than just a background image? etc.
Click on the image to see the full one.

Developer tool interface? Why not.

2010
03.19

EDIT

Seeing as i had TL;DR this post. theres a new one over here

/EDIT

So i have been implementing some networking for my “design challenge” and i challenged myself to do something generic enough to allow extension without rebuilding (easy via scripting) and to challenge myself to be able to split the tasks across server/client and keep it all really simple. No network fiddling no byte packing, it will all be handled internally.

What im looking for from the response of the reader.

Simple.

Would you, perhaps a programmer or not, be inclined to extend your client with your own tools if it were like the description below.

Its not complete, its not 100% in depth, its idea based speculation based on some prototyping i did.

Disclaimer
Before i get shot at for the code below, its experimental. There is inconsistency for a reason. Theres param[] and theres pop() theres weird conventions, and looking closer you may see the third part of this “tool” is a daemon. Seems like a lot of effort? I dont know if it is and thats kind of why im posting. Keep in mind this is a “simple” networked system. Theres users, and theres scripting, and theres ideas.

The in-game OS
One note is that the “OS” in this game is designed around 3 larger parts. Tools, Daemons and the core interface. A tool is a simple utility, a daemon “listens and responds”, and the core exposes the internals.
There are programs, and apps, and widgets and blah. THe point is to not over design, but to design in a way that the code will create itself. If 4 of my friends play, and 3 of them write a simple tool – the game has gotten better for everyone. If i write a cool looking clock widget, it can be distributed as part of the core desktop. If someone writes a simple twitter viewer, etc etc etc etc. The networking interface supports much more than shown in the simple high level functions below so i guess anything is plausible.

I would like opinions or views, a discussion on my idea below. Is there a way for something as simple as ping to be even simpler for the, non core developer to ADD to the game, post release?

Observations
YES, there might be ridiculous ideas here, and I know there may also be a lot of unknowns too, in the ideas below.

The prototype code

Now theres nothing magical going on in my server, its a simple eNet server thats got a thin wrapper for data streams and managing of packets, and a simple (might have “overhead”) way to embed “variants” in a stream without worrying about it.
Implementing a simple hash table for certain network contexts that exists between client and server – instead of sending strings. If i add a string to the stream, its packed into a hash table on the server side and never sent again, only the index of that string.
The code i have below is a simple javascript code in the ideal context for the game, on the lowest level. The core has access to the networking, and to the users , and the core itself.

The Client side tool,

  1.  
  2. // Client side tool for pinging another player in the game
  3. // Author : FuzzYspo0N
  4. // Etc
  5.  
  6. //First, in order to create a tool on the client and server side,
  7. //we simply assign a variable as a tool type. This might fail if
  8. //there is already a tool with this name – this returns undefined.
  9.  
  10.     var corePingTool = new core.tool("corePingTool");
  11.  
  12. //Maybe something simple to register a tool with a defined
  13. //callback for users. This global tool shows up at the shell,
  14. // as a "command line" tool,and if a tool invokes
  15. //a ui then it is not run via command shell but explicitly
  16.  
  17.     core.tool.registerGlobalTool("ping", "client name, ping count ");
  18.  
  19. //onExecute gets called whenever someone tries to ping
  20. //(either called via ui or via the above command line)
  21. //Variable arguments handed in
  22. var corePingTool.onExecute = function(param)
  23. {
  24.         // 0 is reserved, so 1 is client name. 2 is ping count.
  25.     var clientName = param[1];
  26.     var pingCount = param[2];
  27.        
  28.     if(pingCount == core.invalid)
  29.     {
  30.         pingCount = 1;
  31.     }
  32.        
  33.     //if we have a user like this, we can use em
  34.     var userId = core.users.isAUser(clientName);
  35.     if(userId != core.users.invalidUser)
  36.     {
  37.         //Create a new network javascript object.
  38.         //This object handles network packing/streams internally.
  39.         //The to dev, this is simple – a javascript object.
  40.         //Push data into the stream, and be done.
  41.                
  42.         //The toolId is to header the packet type, for the server
  43.         //to know what to do with it.
  44.         var pck = new core.net.packet(this.toolId);
  45.                
  46.         //Add our data into the packet for the server to care
  47.         pck.push(userId);
  48.         pck.push(pingCount);
  49.                
  50.         //Give it a callback when its feeling talkative
  51.         pck.response = this.onResponse;
  52.                
  53.         //Send it to the server
  54.         pck.send();
  55.     }
  56. }
  57.  
  58.  
  59. //The servers response to a ping command
  60. var corePingTool.onResponse = function(param)
  61. {
  62.     //0 reserved, 1 is always the response code, 2 is the result
  63.     //(known, from server side), 3 is the client requested
  64.     if(param[1] == core.net.success)
  65.     {
  66.         //should output something like
  67.         //    ping response 128ms from " DumbassTeh"
  68.        
  69.             var end = ‘ from " ‘ + param[3] + ‘ " ‘;
  70.             echo(‘Ping response ‘ + param[2] + ‘ms’ + end);
  71.         }
  72.         else
  73.         {
  74.             //message box failure
  75.         }
  76. }
  77.  

The server side response

On the server side, once i, an in game developer have registered my new tool (via the developer tools/console), i can begin to expand the server script locally (theres a sandbox of sorts that allows this).

The way it will work is based on the toolId that is handed in the packet to the server. What the server does, to keep things generic, is look for a script on the server based on tool ids. For example, it might look like core/tools/34ea3.js when the server is done with it. It then looks for the tool name (handed in the constructor of the tool) to use as a function :

execute(toolName + “_Main”, packet);

The simplicity allows as many tools as needed be registered automatically without explicity adding them, the developer of the tool simply registers his tool via the constructor and console.
The code sample below can demonstrate the idea behind the above client code, on the server side.

  1.  
  2. // Server side tool for pinging another player in the game
  3. // Author : FuzzYspo0N
  4. // Etc
  5.  
  6. //expects – a packet with
  7.     //pop 1 – sourceUserId
  8.     //pop 2 – destUserId
  9.     //pop 3 – ping count
  10.    
  11.  //context globals
  12.  
  13. //var toolId is handed in from the system
  14.  
  15. var corePingTool_Main = function( pck)
  16. {
  17.     //Pck is basically a javascript array, and pop will
  18.     //simply keep a "stackIndex" internally. So in essence
  19.     //what you can see here is
  20.     // stackIndex += 1;
  21.     // return pck[stackIndex - 1];
  22.    
  23.     var sourceId = pck.pop();
  24.     var destId = pck.pop();
  25.     var pingCount = pck.pop();
  26.    
  27.     for(i = 0; i < pingCount; ++i)
  28.     {
  29.         //query : clientId, requesterId, daemonId, handler
  30.         core.net.query(destId, sourceId, toolId, onPingBack);
  31.     }
  32.    
  33. }
  34.  
  35. var onPingBack = function(pck)
  36. {
  37.     //pop 1 – sourceUserId
  38.     //pop 2 – destUserId
  39.     //pop 3 – response – if successful, it will have the ms it took
  40.    
  41.     var sourceId = pck.pop();
  42.     var destId = pck.pop();
  43.     var response = pck.pop();
  44.    
  45.     if(response != core.net.response.timedout)
  46.     {
  47.         //the respond will hit the client callback that
  48.         //pck.onresponse registered.
  49.         core.net.respond(sourceId, toolId, response);
  50.     }
  51.     else
  52.     {
  53.         //respond : destId, toolId, responseCode
  54.         core.net.respond(sourceId, toolId, core.net.response.timedout);
  55.     }
  56. }
  57.  

Comments, views, ideas, etc – Welcome. Please, i like ideas.