What is the best way to achieve a Flash/Unity app with shared Nodejs server?
Over the last week or so I have been looking into creating a shared nodejs server that has flash and unity interfaces. I'm still rather new to nodejs so this is a post to ask a question; I'm considering creating a JS file that flash and unity communicate to using external interface calls instead of putting the communication layer inside of the application.
My question is, is this an acceptable approach? One of the reasons I'm considering this is because it seems to be a pain in the ass in Unity to achieve this.
Let me know what you guys think!
Zork/MUD-like basic item structure
So at work the other day I was explaining Lantern to a buddy (@shamuspeveril) and we somehow got onto the topic of how well nodejs would work for a zork like game or a mud. Well, sure enough, with the idea stuck in my head I sat down today and tried to think through. Luckily I think this concept will apply well to what I hope to do with the Lantern server, so I don't feel like I deviated too much from my path.
In case you are not sure what a MUD is, this is a brief description grabbed from wiki :
MUDs combine elements of role-playing games, hack and slash, interactive fiction, and online chat. Players can read or view depictions of rooms, objects, other players, non-player characters, and actions performed in the virtual world. Players typically interact with each other and the world by typing commands that resemble a natural language.
And if you don't know what Zork is... Leave. Just go.
Anyways, making the basic nodejs server to handle limited verbs was pretty simple. Ex:
Server:
[code]
var http = require("http");
var url = require("url");
var fs = require("fs");
var sys = require("sys");
var qs = require("querystring");
var send404 = function(res){
res.writeHead(404);
res.write('404');
res.end();
}
var server = http.createServer(function(req,res)
{
var path = url.parse(req.url).pathname;
sys.puts(path);
switch (path)
{
case "/":
fs.readFile('mud/index.html', 'utf8', function(err, data)
{
if(err) {
res.writeHead(500, {});
res.end();
throw err;
}
res.writeHead(200, {
'Content-Length': data.length
, 'Content-Type': 'text/html'
});
res.write(data);
res.end();
});
break;
case "/command":
var commands = qs.parse(url.parse(req.url).query).commands;
handleCommands(commands);
break;
default:
if (/\.(js|html|swf)$/.test(path)){
try {
var swf = path.substr(-4) == '.swf';
res.writeHead(200, {'Content-Type': swf ? 'application/x-shockwave-flash' : ('text/' + (path.substr(-3) == '.js' ? 'javascript' : 'html'))});
res.write(fs.readFileSync(__dirname + path, swf ? 'binary' : 'utf8'), swf ? 'binary' : 'utf8');
res.end();
} catch(e){
send404(res);
}
break;
}
send404(res);
break;
}
});
server.listen(8000);
function handleCommands(commands)
{
var commandArr = commands.split(" ");
verbs(commandArr[0]);
}
function verbs(v)
{
switch(v)
{
case "n":
case "north":
sys.puts("Moving north");
break;
case "s":
case "south":
sys.puts("Moving south");
break;
}
}
[/code]
Client :
[code]
$(function(){
var commandObj = {
commands: document.getElementById('commands').value
}
$.get("http://localhost:8000/command", commandObj,
function(data)
{
}
, "json");
});
[/code]
So that just handles north/n and south/s but you can see how it would progress. Which should lead you to the problem I hit when I added the "south" command block - That is going to be one massive switch statement. So instead of continuing forward with my massive switch I decided to think about it yesterday and I think I came up with a solution that I will use also in Lantern for my crafting system.
The system relies on the item know what is can do and containing all the information that would make it able to control itself instead of a large switch/case on my part. And this whole set up is made 100 times easier because I'm going to be using mongodb. Here's some pseudo code to give you an idea of what I'm talking about:
[code]
{
type:"Room",
exits:
{
north:{desc:"You see an exit to the north",room:3242},
south:{desc:"There's a small door that seems to be locked",room:123}
},
description: "You're in a big room with two doors.",
items:"123,63,7456,34,99,4563,215789,45"
commands:
{
look:{desc:"The room you are in is stupidly large with only two tiny doors, one to the north and a seemingly locked one to the south."};
yell:{desc:"You shout at the top of your lungs and you just hear your voice echoing mockingly off the walls."}
}
}
{
type:"Item",
id:123,
description: "The rock is small and perfectly circular.",
commands:
{
take:{desc:"You take the rock and put it in your backpack.",callback:"addToInventory"};
}
}
{
type:"Item",
id:99,
description: "A small glass bottle filled with an unknown liquid."
commands:
{
combine:{desc:"Blah blah", callback:combineWith, ingredients:4345, creates:8456}
}
}
[/code]
As you can see with a system like this, each item is responsible for knowing everything about it and the other items it interacts with. While this make be more difficult to create up front, I feel that once the system is in place I could easily use this in Lantern, a MUD or really any game going forward.
Or maybe I'm brutally over thinking the problem. Is there a better way to handle item relations and verbs? Would a massive switch/case with all the different verbs I want be the way to go? Even if I got that path, I need a similar structure to above just for the content. And then added a simple onetime use command like "lick" or something would require new code instead of just text.
Let me know what you think. I will be starting on code like this soonish for Lantern and would like to have a method pinned out. Right after I figure out the mapping issues I'm having ^^
Windows + VirtualBox + Ubuntu + nodejs = hooray!
As I'm sure some of my readers (all four of you) may know because of the IRC room, I've lately been trying to get nodejs running on a virtual machine (ubuntu since nodejs doesn't like windows and I don't want to virtualize osx) that is accessible from my host (windows) so I can use it for Lantern. Well I had a few minutes tonight to sit down and do some reading and I figured it out, hence the post so I don't forget.
I'll go right from step one in case anyone else is trying to do this with no prior knowledge
I should also mention if you're on *nix you don't need to do this.
- Get virtualbox
- Get Ubuntu (or whatever distro tickles your fancy)
- Install a vm of ubuntu
- Download nodejs on vm
- Config/Make/Install - I had to install g++ and cmake to get it to build properly
- (The tricky part) On your host (windows) navigate to your virtualbox installation via command - something like this : C:\Program Files\Sun\VirtualBox\
- Run these commands :
VBoxManage.exe setextradata "ubuntu2" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/Protocol" TCP
VBoxManage.exe setextradata "ubuntu2" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/GuestPort" 8000
VBoxManage.exe setextradata "ubuntu2" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/HostPort" 8000
- Launch your vm, start node js and on your host in a browser go to localhost:8000- HOORAY!
So here's what I know about the commands what you need to edit to make it work
- Instead of "ubuntu2" use the name of your vm.
- the guestssh isn't important. Just a name use to group the settings. Call it whatever you want.
- Guest and Host ports are the port you want to access on your vm.
- If you change you're installation at all from the default you'll have to figure out the other changers yourself here : http://www.virtualbox.org/manual/ch06.html#natforward
Good luck ^^