Something i needed while working on something recently was the ability to look at a javascript object backwards.
I know there are plenty of ways to do this, so here is mine (it uses mootools btw).
View the live demo with code here : jsFiddle demo
p.s jsFiddle is so awesome.
CouchDB is a nosql, document-based database system. When i first started using couchDB it was a little perplexing for my years of SQL and relational database use. This means that i have come away with something that i will share in the hopes to simplify your learning curve, and to offer a simplistic and short explanation that might help in deciding whether or not couchDB fits your needs.
You might also find my V8 javascript crash course helpful ( Link )
Non-relational
Relational databases simply have a schema, a "best practices" if you like. The term means that certain structures and conventions are enforced, and help you design data in a relational manner.
Relational data just means data that shares common fields, are stored together. They are grouped into a table. Books all share common data right? A title, an author. This makes the data inside the "books" table relational data.
For couch, data is stored in a "document" instead. Documents don't enforce any schema so you can store data however you like. The design choices affect things, obviously, but it stores data as simple, easy to edit JSON items.
If you aren't familiar with JSON, its JavaScript Object Notation, it uses key/value type pairs (that can contain children, like a folder tree) and it is a hugely supported and readily available transport language.
JSON
See that? Thats a simple javascript object. It holds a single key, called 'name', and its value is 'sven'. JSON can get pretty complex when doing larger data structures, so it is always good to have a good JSON editor or "prettyfier" handy. CouchDB comes with a relatively useful editor for editing the data, but it can get pretty convoluted pretty quick. Let's look back at our book example.
{ title:'Pro JavaScript with MooTools' , author:'Mark Obcena' }
So, let's complicate the example by adding some release dates. The situation calls for more than one of the same thing, so lets group the release dates into their own object, making them easier to work with. Here are two release dates.
{ 'releaseDate':'1/1/11' } , { 'releaseDate':'5/1/11' }
So, two release dates but they feel non-descriptive.
[{
country: 'UK',
releaseDate: '1/1/11'
},
{
country: 'ZA',
releaseDate: '6/1/12'
}]
There, that makes a bit more sense. In order to "insert" these two into the JSON object, we enclose them as an array, using the familiar [ ] construct. This leaves our final object looking like this :
{
title: 'Pro JavaScript with MooTools',
author: 'Mark Obcena',
releaseDates: [
{
country: 'UK',
date: '1/1/11'
},
{
country: 'ZA',
date: '6/1/12'
}
]
}
Documents
Well, as you can see, a document just contains a JSON object. A tree of them? A single object? See, Couch doesn't mind.
Usually, you store one code side object per document. Take a user for example. Login details, private messages, personal info. They can all be a single document. This actually immediately strikes a chord in the "a huge list is bad" crowd, which is what got me at first. I tried embedding as much as possible so i would have less documents to "speed up" the data flow. Well, this is how it thrives.
The way it works is simple, it caches things. When you ask for all the documents of type "user", and you sort them by "user name", the user name part is cached and makes all consequent accesses on that "query" super fast. It also caches a bunch of other info about the users for being able to access it quickly, and thats what makes the documents great.
Views
A view is quite simply explained by a function that runs on each document of a database. This small function has a map and reduce flow, and rereduce. These are well explained in the docs so i needn't get into much detail here, but lets say we wanted to view the data in our book document. We know what it has has, so we can construct a view to do something specific. For example, list only the author and title. The emit function "returns" the JSON of the request.
function(doc) {
emit(doc.title, doc.author);
}
Or, lets return all books that have an unknown author,
function(doc) {
if( ( doc.title && !doc.author ) ||
( doc.title && doc.author == 'unknown') )
emit(doc.title, 'missing author');
}
Features
Couch doesn't just store bunches of JSON objects. It can do a heck of a lot more for you, and includes templating systems already built in ( think rails, sinatra, cakePHP ). It also supports internal versioning, and conflict handling. It also is a peer driven model, meaning data can be merged smartly. If you add a second author to the book above, it only modifies that entry, and makes things simple when having distributed changes synced back into the db.
Conclusion
There are plenty NoSql database systems. Couch is particularly interesting to me because it covers the most common format in my current engines, JSON.
It also ties my entire engine to being javascript overall, with C++ in the background. Node.js has decent couch support, and it ties together extremely well in my current toolchain. There are many alternatives, that are just as good and widespread. For example, MongoDB is a great alternative to couch depending on your needs.
Thanks for reading.
Its real
Click here : The book i mentioned. Its gonna be awesome.
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.
The original :
My game :
Its intended as a tribute cos i really loved the original.
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);
//http://blog.owned.co.za v8 Javascript Helper Function ,
//Give this function the c++ object (an instance) to wrap,
//and it returns a JS object to expose things under.
//Note theres 2 functions here ,
//the top one is used by the ExposeClass function
template
v8::Handle WrapClass(T* y)
{
// Handle scope for temporary handles,
v8::HandleScope handle_scope;
v8::Persistent class_template_;
v8::Handle rt = v8::ObjectTemplate::New();
//The raw template is the ObjectTemplate
// (that can be exposed to script too)
//but is maintained internally.
rt->SetInternalFieldCount(1);
//Create the actual template object,
class_template_ = v8::Persistent::New(rt);
//Create the new handle to return, and set its template type
v8::Handle result = class_template_->NewInstance();
v8::Handle class_ptr
class_ptr = v8::External::New(static_cast(y));
//Point the 0 index Field to the c++ pointer for unwrapping later
result->SetInternalField(0, class_ptr);
//Return the value, releasing the other handles on its way.
return handle_scope.Close(result);
}
template
v8::Handle ExposeClass(v8::Persistent context,
T* y,
v8::Handle exposedName,
v8::PropertyAttribute props)
{
v8::HandleScope handle_scope;
v8::Handle obj = Core::Script::WrapClass(y);
context->Global()->Set(exposedName, obj, props);
return handle_scope.Close(obj);
}
And for unwrapping - (usually inside CALLED functions from script. use : someNamespace::someClass* sc = UnwrapClass< someNamespace::someClass >( myJSObjToUnwrap );
//http://blog.owned.co.za v8 Javascript Helper Function ,
//Give this function the v8 JS object to unwrap, and the class to unwrap to.
template
T* UnwrapClass(v8::Handle obj)
{
v8::Handle field;
field = v8::Handle::Cast(obj->GetInternalField(0));
void* ptr = field->Value();
return static_cast(ptr);
}
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.
class cCore
{
public:
//This is a simple example,
//do not copy this as a real class.
cCore(){};
~cCore() {};
//We need a persistant handle to the core in scripts, a non persistant
//v8::Handle will get lost in the handle scopes,
//and throw some weird exceptions to hunt down.
//Wrap class and unwrap class return
//NON persistant handles, so store your own
//persistant ones if you want to
//use it outside of the first handle scope.
//core script object, "core" in scripts.
v8::Persistent cso_core;
//We expose some functions in our class to the scripts from c++,
//By wrapping an object (cso_core above) and the attaching functions
//to that object. Those functions, when called from javascript -
//end up here.
//The functions are self explanatory.
//Print some text to the console/ui console
static v8::Handle xecho(const v8::Arguments& args);
//execute a javascript file
static v8::Handle xexec(const v8::Arguments& args);
//exit all systems and shutdown
static v8::Handle xexit(const v8::Arguments& args);
}; //end class declaration
Step 2 - Creating the Javascript Object , of my class.
//Just for clarity sake, so you can see my workflow.
void cScriptSystem::startup()
{
//Create a script engine for the core
v8::HandleScope handle_scope;
//Create a context for the system to use
//(i have just one at this point)
coreContext = v8::Context::New(NULL, global);
//Enter the main context, making it active.
v8::Context::Scope context_scope(coreContext);
exposeCore(); //see below
};
//And the code to expose the class,
void cScriptSystem::exposeCore()
{
v8::HandleScope handlescope;
//This will be reused to expose multiple
//classes, short name for easy code.
v8::Handle cc;
//get the JS version of the C++ object,
//note that core is simply Core::cCore* core;
cc = ExposeClass< Core::cCore >(coreContext, core,
v8::String::New("core"),
v8::ReadOnly);
//set the persistant handle for use outside of this handlescospe
core->cso_core = v8::Persistent::New(cc);
//Give the functions to the object.
//This makes the functions come out as
//core.echo(), core.exec(), core.exit() in scripts.
Expose(core->cso_core, v8::String::New("echo") ,
v8::InvocationCallback(Core::cCore::xecho));
Expose(core->cso_core, v8::String::New("exec") ,
v8::InvocationCallback(Core::cCore::xexec));
Expose(core->cso_core, v8::String::New("exit") ,
v8::InvocationCallback(Core::cCore::xexit));
};
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,
v8::Handle cCore::xexit(const v8::Arguments& args)
{
//args.Holder() is the object that the function was invoked upon.
//This means it could be exposed to 2 classes,
//under different types so be sure
//that you dont just randomly unwrap into the wrong container type.
Core::cCore* core = UnwrapClass( args.Holder() );
//The code inside the normal exit function is identical,
//so i can just call the normal c++ code directly.
core->startShutdown();
//This is to return void, basically.
return v8::Undefined();
}
Step 4 - The missing function. I left out a function along the way, you may have noticed. The function is called Expose,
void Expose(v8::Handle intoObject, v8::Handle namev8String, v8::InvocationCallback funcID)
{
v8::HandleScope handle_scope;
v8::Handle thisFunc;
thisFunc = v8::FunctionTemplate::New(funcID);
intoObject->Set(namev8String, thisFunc->GetFunction());
}
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.
//you can now use it std::string(*somestdstring)
v8::String::Utf8Value somestdstring ( args[0] );
//you can now use it *somecstring (same as const char* somecstring;)
v8::String::Utf8Value somecstring ( args[1] );
//normal double,
double somedouble = args[2]->ToNumber()->Value();
//booleans
bool somebool = args[3]->ToBoolean()->BooleanValue();
//and integers.
int someint = args[4]->ToInt32()->Int32Value();
//And one last thing, giving javascript meaningful return values.
//This should be more than enough to let you figure out how simple
//v8 makes things for you on the c++ side.
return handle_scope.Close(v8::Number::New(somedouble));
return handle_scope.Close(v8::Int32::New(someint));
return handle_scope.Close(v8::Boolean::New(somebool));
Out.
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
[caption id="attachment_110" align="aligncenter" width="640" caption="Mission Editor Mockup"]
[/caption]
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 :>
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).
[caption id="attachment_110" align="aligncenter" width="450" caption="Typing in console while the main UI runs asynchronous"]
[/caption]
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
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,
// Client side tool for pinging another player in the game
// Author : FuzzYspo0N
// Etc
//First, in order to create a tool on the client and server side,
//we simply assign a variable as a tool type. This might fail if
//there is already a tool with this name - this returns undefined.
var corePingTool = new core.tool("corePingTool");
//Maybe something simple to register a tool with a defined
//callback for users. This global tool shows up at the shell,
// as a "command line" tool,and if a tool invokes
//a ui then it is not run via command shell but explicitly
core.tool.registerGlobalTool("ping", "client name, ping count ");
//onExecute gets called whenever someone tries to ping
//(either called via ui or via the above command line)
//Variable arguments handed in
var corePingTool.onExecute = function(param)
{
// 0 is reserved, so 1 is client name. 2 is ping count.
var clientName = param[1];
var pingCount = param[2];
if(pingCount == core.invalid)
{
pingCount = 1;
}
//if we have a user like this, we can use em
var userId = core.users.isAUser(clientName);
if(userId != core.users.invalidUser)
{
//Create a new network javascript object.
//This object handles network packing/streams internally.
//The to dev, this is simple - a javascript object.
//Push data into the stream, and be done.
//The toolId is to header the packet type, for the server
//to know what to do with it.
var pck = new core.net.packet(this.toolId);
//Add our data into the packet for the server to care
pck.push(userId);
pck.push(pingCount);
//Give it a callback when its feeling talkative
pck.response = this.onResponse;
//Send it to the server
pck.send();
}
}
//The servers response to a ping command
var corePingTool.onResponse = function(param)
{
//0 reserved, 1 is always the response code, 2 is the result
//(known, from server side), 3 is the client requested
if(param[1] == core.net.success)
{
//should output something like
// ping response 128ms from " DumbassTeh"
var end = ' from " ' + param[3] + ' " ';
echo('Ping response ' + param[2] + 'ms' + end);
}
else
{
//message box failure
}
}
The server side response
// Server side tool for pinging another player in the game
// Author : FuzzYspo0N
// Etc
//expects - a packet with
//pop 1 - sourceUserId
//pop 2 - destUserId
//pop 3 - ping count
//context globals
//var toolId is handed in from the system
var corePingTool_Main = function( pck)
{
//Pck is basically a javascript array, and pop will
//simply keep a "stackIndex" internally. So in essence
//what you can see here is
// stackIndex += 1;
// return pck[stackIndex - 1];
var sourceId = pck.pop();
var destId = pck.pop();
var pingCount = pck.pop();
for(i = 0; i
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.
[caption id="attachment_110" align="aligncenter" width="450" caption="Developer tool interface? Why not."][/caption]
To celebrate the months wasted trying to find a way to make gameswf work for me, i am going to post the test build of the game here. There is not a lot to the UI yet, just a login screen and a "login complete" screen. After that, there is the escape key to exit.
For this test, the username is devcore , and so is the password. Iv attached some images below for post sake.
The tech so far
Currently im using v8 javascript engine for scripting,
PhoenixCore for rendering Link
And awesomium for the UI stuff Link
The rest of the story
Is still to come. I will post later today sometime maybe, the ideas behind the networking code on the client tool development side,
and i hope that there will be some discussion behind that. So if you can/want to please check back in a while for the networking part.
Candy
[caption id="attachment_110" align="aligncenter" width="431" caption="FLCore"]
[/caption]
[caption id="attachment_110" align="aligncenter" width="450" caption="FLCore"]
[/caption]
Notes :
Requires VC (vs2008) runtime libraries. Google these, if you dont have them. If you cant run the exe, open the html instead for now.
The Download
Self Extractor (3.8 MB)
Link
Taking on a challenge (while waiting for certain things to be finalised on shadowracer, and other things taking my time), I decided to challenge myself to some code architecture design. Like designing systems that are clean, simple and efficient while being powerful enough to maintain their stability and usability on a much larger scale. Things like networking, user interface design, game core runtime designs etc.
V8
One of those steps was getting the v8 javascript engine running nice and smoothly behind the scenes of the core code base, which was incredibly easy thanks to their simple approach. Using a modified base of CProxyV8, i have managed to expose entire classes to script on a whim via some really minimal preprocessing of class files and macros, which will be polished and released here as soon as its a viable tool.
Multi User Interface design
Allowing the switching of user interface engines at any time (even runtime) was another challenge i took on, which has also proven quite fruitful so far. While using the PhoenixCore engine for rendering at the moment and hooking up some gameswf flash UI code to that is quite powerful , i still have the flexibility to change those at any time with minimal wrapping of gameplay code.
Interesting Gameplay
While the engine may be all cool and dynamic it doesn't serve any good without a nice fun game to play. I wont be speaking on what exactly i have gotten into making with some friends but i can post some mockups that have come up so far.
[caption id="attachment_110" align="aligncenter" width="598" caption="Coming sometime"]
[/caption]
[caption id="attachment_110" align="aligncenter" width="800" caption="Coming sometime"]
[/caption]
One thing i forgot to post (doh!) while working on the reflection setups in my engine for shadowracer was the reflectance tests i had done. I had typed an incorrect value and ended up with a super low res reflection - This and something Blindside had mentioned to me before about trying that as a trick got me into messing around with ambient color and reflectance under the diffuse layer, based on the realtime environment around the car itself.
i attempted to layer the lighting setup in such a way to have a diffuse map + ambient surrounding reflectance + the realtime reflection and it looked really nice - but within certain parameters was not giving what i expected due to the nature of the reflection im using. After a lot of messing around and tweaking i reimplemented the layer for ambient reflectance but pre diffuse texture in the pipeline. This means i ran the low pass reflection on the white/blank slate car instead of the diffuse texture. This gave me even better underlying results for the reflectance and i already had an ambient texture attached to the map (a baked AO map) in the 4th slot. Multiplying adding and trying different combinations gave some cool results, so i tried using the abient map as a falloff of reflectance and fresnel and who knows what else i added for the testing phase, but a lot of really interesting results came about. Below is only one of the stages i had reached and i realised i hadnt shown any of this progress so i figured what the hell. The amount of time its taken to finish this small post in between the rest of the fun things that im working on (work side) and the fact that i had an image set already screencapped means you get one bunch of pictures. Enjoy!
[caption id="" align="alignleft" width="840" caption="Reflectance of ambient scene lighting and surrounding objects"]
[/caption]
Some notes : the reflection and base shaders are based on my own work, but the original point i started at was BLindsides great DP realtime reflectance in irrliche engine.
All shots realtime, +- 300 fps, 16x16 RTT per pass (2 passes per object) on a ATI thats not immense
All images are overly exaggerated to demonstrate the effects here, a low level ambient reflectance works really well with any material, wood, metal, concrete etc etc. More sometime, i think!
One thing i love is when reality is smacked on top of a buzzword, and a current OMG moment.
I really appreciate such a nice breakdown, especially for indies/beginners. Thanks Brett!
http://www.torquepowered.com/community/blogs/view/18741
Go ahead, indulge yourself. Im making this post about the UDK license and the REALITY behind their move to make the engine free.
Torque3D kicks ass, btw.
Check out the demo on the www.torquepowered.com website - and read the development blogs.
0.2.1 is here, 9 days later the simple irrlicht framework team re-emerges with a feature and bug release.
Some bugs have been fixed and some new features introduced, the changes include :
* Script-side GameStates:
It is now truely possible to derive from the GameState class (through CGameState) in scripts. A bug in previous versions prevented this, but this bug has now been fixed.
* Script-side Components:
EntityComponent can be derived from script-side (through CEntityComponent), classes in script can now create components and register them with entities from script or engine side.
* Script-side Events:
The event system is now integrated into the script engine. Script-side classes can derive from IHasSlots and can register, connect and disconnect from slot events.
* Important Bug Fixes :
- Construction of entity components with parent is now relatively safe. If you are not sure whether your component has a parent, check it after construction. If the component has no parent, destroy it as quickly as possible
- AssetProcessors on windows were never loading assets unless the files were all lowercase, restrictions were irrlicht related but solved.
- Minor bug fixes with script side things, Scolor fixes, asset groups on entities and much much more.
Helpful Links :
Sourceforge Page
Downloads
Documentation
Tutorials
|