Why I’m making a game before my next project

Quick link to the game I made


Primary Technology is a good place to work, the main reason being is that I have a lot of freedom to be creative. The ability to be creative means I get to work with a lot of different platforms and technologies. The next project I have been asked to do is a “web based really real time light-weight open source collaborative sticky note tool” AKA PrimaryWall. o_O

So let’s break that down… Web based, easy.. Really real time, not so easy when using conventions… light-weight, easy-ish.. open source, sort of easy.. collaborative, not so easy…

I could go ahead and make something with AJAX & Apache but it wouldn’t be as really real time as a lot of genuine really-real time so I’m going to be better off using NodeJS and Web Sockets. I did an example using Socket and Node a week or so ago that really got me thinking about how I can/could apply what I had learned to the projects I work on at Primary Technology.

The biggest problem I face is my lack of experience with Javascript. If I went straight into building PrimaryWall I would probably build it in a linear fashion and that would suck for an open source project because it wouldn’t feel appropriately structured.. Sure I “could” structure it all out based on what I know so far but I feel like I should do a test first and that test is to build a game using the same structure and hopefully at the same time build my knowledge of NodeJS, WebSocket + Javascript.

So I have 4 weeks to build a game then 4 weeks to build PrimaryWall (It is due at the end of March). The game will be called either “Tag” or “You’re it” and will be a simple multi-mouse game where moving the mouse is all that is required to play.

Any developers that read this think that I’m wasting my time and should just go for it?

I think this post is mostly me justifying spending the next month building a game that has been ultimately funded by the public sector.. I know this may seem a little strange but NodeJS is relatively new and so is Javascript and I really need to learn before I create as to create something that is worthwhile for other people to contribute towards….

Quick link to the game I made

Getting to know etherpad.local.properties

alwaysHttps = false // Always use HTTPs connections
ajstdlibHome = ../infrastructure/framework-src/modules // Where does ajstdlib live?
appjetHome = ./data/appjet // Where does the appjet engine live?
devMode = false // Is the server production or not? Enables/disables caching & obfustication & allows for new accounts & pro bits
etherpad.adminPass = password // Password for /ep/admin (enable/disable plugins etc.)
etherpad.fakeProduction = false // Same as below but fakeified.
etherpad.isProduction = true // Is the server production or not? Enables/disables caching & obfustication & allows for new accounts & pro bits
etherpad.proAccounts = true // Enable or Disable Pro accounts
etherpad.SQL_JDBC_DRIVER = com.mysql.jdbc.Driver // MySQL driver
etherpad.SQL_JDBC_URL = jdbc:mysql://localhost:3306/etherpad // MySQL connectivity type, host, port and database
etherpad.SQL_PASSWORD = password // MySQL password
etherpad.SQL_USERNAME = root // MySQL username
hidePorts = true // wether we should hide ports to end user, IE is the etherpad service behind a reverse proxy
listen = 9090 // tcp port to listen on
logDir = ./data/logs // where to store log files
modulePath = ./src // location of your modules
motdPage = /ep/pad/view/ro.3PfHCD0ApLc/latest? //location of motd (used when using a custom home page see http://doc.etherpad.org) fullScreen=1&slider=0&sidebar=0 // what attributes are required to be passed fullSCreen view
topdomains = www.yourdomain.com,yourdomain.com,localhost,localbox.info // What domains should etherpad listen on?
transportPrefix = /comet // How should we prefix the comet messages?
transportUseWildcardSubdomains = true // Can the comet requests use wildcard subdomains?
useHttpsUrls = false // Should we ever push out any https urls?
useVirtualFileRoot = ./src // Where is the virtual file root?
theme = primarypad // What theme should be on by default? (user can overwrite with ?_theme=whatever)
etherpad.soffice = /usr/bin/soffice // Where is the soffice executable?
customBrandingName = PrimaryPad // Top branding name on pads
customEmailAddress = contact@primarypad.com // Email address that will be used when sending out pad invites etc.
showLinkandLicense = false // Always show Etherpad license

Getting to grips with Channels in Ajax Chat

Channels in Ajax chat are really poorly documented so I wanted an easy place for you to get started.

The first thing you should know is that just adding new channels to lib/data/channels.php WILL NOT make them visible to users. To make channels visible to users you must edit lib/users.php and add the relative channelID to the user account. You can test this by logging in as admin (default password is admin). The admin by default has 0 and 1 listed as their channel IDs. Try create a new channel in channels.php and add the relevant ID to users.php.

The second thing you need to know is that Ajax Chat also calls private messages “private channels.” This is a horrible mistake by the project and I am trying to get this renamed.

That should get you started with channels. Enjoy and have fun 🙂

Real time mouse activity w/ NodeJS & Sockets

Quick link to the NodeJS/websocket game I made — includes source

Thanks to Reddit for helping me test this.

Steps:
Get NodeJS
Get npm
Get SocketIO

Create server.js
Paste in:

// Simple Node & Socket server

var http = require('http')
  , url = require('url')
  , fs = require('fs')
  , io = require('../')
  , sys = require('sys')
  , server;

server = http.createServer(function(req, res){
  var path = url.parse(req.url).pathname;
  switch (path){
    case '/':
      res.writeHead(200, {'Content-Type': 'text/html'});
      res.write('<h1>Welcome. Try the <a href="/chat.html">chat</a> example.</h1>');
      res.end();
      break;
      
    case '/json.js':
    case '/test.html':
      fs.readFile(__dirname + path, function(err, data){
        if (err) return send404(res);
        res.writeHead(200, {'Content-Type': path == 'json.js' ? 'text/javascript' : 'text/html'})
        res.write(data, 'utf8');
        res.end();
      });
      break;
    default: send404(res);
  }
}),

send404 = function(res){
  res.writeHead(404);
  res.write('404');
  res.end();
};
server.listen(8080);

// socket.io, I choose you
var io = io.listen(server)
  , buffer = [];
  
io.on('connection', function(client){
  client.send({ buffer: buffer });
  client.broadcast({ announcement: client.sessionId + ' connected' });
  
  client.on('message', function(message){
    var msg = { message: [client.sessionId, message] };
    buffer.push(msg);
    if (buffer.length > 15) buffer.shift();
    client.broadcast(msg);
//    console.log(msg);
});
  client.on('disconnect', function(){
    client.broadcast({ announcement: client.sessionId + ' disconnected' });
  });
});

Create test.html
Paste in:

<!doctype html>
<html>
  <head>
    <title>Multi Mouse - How many mice can I mouse eater eat?</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script> <!-- jquery -->        
    <script src="/json.js"></script> <!-- for ie -->
    <script src="socket.io/socket.io.js"></script> <!-- sockets -->
  </head>
  <body>
<h1> You can see my mouse!! ZOMG - <a href="http://www.youtube.com/watch?v=aFLcbBvTGns">Video explaining why I'm doign this</a></h1>    

    <script>

// some random color 
function randc(){
colors = new Array('#FF0000','#00FF00','#0000FF','#00FFFF','#FF00FF','#C0C0C0');
var color = colors[Math.floor(Math.random()*colors.length)]
return color;
}

// When a new message arrives..
      function message(obj){
	var data = obj.message[1].split(':');
	var x = data[0];
	var y = data[1];
        var userid = obj.message[0];

  if($('#mouse_'+userid).length == 0 && userid != 'you') {
	var randcolor = randc();
	$('body').append('<div class="dot" style="background-color:'+randcolor+'" id="mouse_'+userid+'"/>'
    );
  }

// stops a dot being drawn for local user
if (userid != 'you'){
   $('#mouse_'+userid).css({
    'left' : x + 'px',
    'top' : y + 'px'
  })
}
        var el = document.createElement('p');
        if ('announcement' in obj) el.innerHTML = '<em>' + esc(obj.announcement) + '</em>';
        else if ('message' in obj) el.innerHTML = '<b>' + esc(obj.message[0]) + ':</b> ' + esc(obj.message[1]);
        document.getElementById('chat').appendChild(el);
        document.getElementById('chat').scrollTop = 1000000;
      }
      
// A function to define how we send data
      function send(){
        var val = document.getElementById('text').value;
        socket.send(val);
        message({ message: ['you', val] });
        document.getElementById('text').value = '';
      }
      
// When a mouse is moved
      window.onmousemove = function(event){
	 message({ message: ['you', event.clientX+':'+event.clientY] });
         socket.send(event.clientX+':'+event.clientY);
      };

// replace <&> w/ &lt&&gt
      function esc(msg){
        return msg.replace(/</g, '&lt;').replace(/>/g, '&gt;');
      };

// establish the socket connection      
      var socket = new io.Socket(null, {port: 8080, rememberTransport: false});
      socket.connect();
      socket.on('message', function(obj){
        if ('buffer' in obj){
          document.getElementById('form').style.display='none';
          document.getElementById('chat').innerHTML = '';
          
          for (var i in obj.buffer) message(obj.buffer[i]);
        } else message(obj);
      });
    </script>
    
    <div id="chat"><p>Connecting...</p></div>
    <form id="form" onsubmit="send(); return false">
      <input type="text" autocomplete="off" id="text"><input type="submit" value="Send">
    </form>
    
    <style>
      .dot { height: 10px; width: 10px; background-color:#000000;position:absolute;left:0;top:0;}
    </style>
    
  </body>
</html>

Run it with

node server.js

Test it by visiting http://whatever:8080

Quick link to the NodeJS/websocket game I made — includes source

Profanity filtering in AjaxChat

AjaxChat provide a Client side profanity filter but this is not cool because:

a) Big arrays of profanities on your client is going to kill javascript
b) You are going to be passing your users an array of profanities.

Fix? Do it server side. giggidy. Jump into /ajaxchat/lib/class/AJAXChat.php

Just above the insertCustomMessage function add

 function filterMessageText($text){
    $prof = array("badword1","badword2"); // extend this with your bad words..
    $replace = array();
    foreach ($prof as $word){
       $replace[] = str_repeat('*', strlen($word));
    }
    return str_ireplace($prof, $replace, $text);
  }

Go to line 1498 and add:

// Copies the original text to a value we can store in a separate table if we want to.
   $original_text = $text;
// Pass the text through the filter.
          $text = $this->filterMessageText($text);