diff --git a/.gitignore b/.gitignore index 47e2d23..de30e87 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules .idea build +test \ No newline at end of file diff --git a/package.json b/package.json index b319e8b..f00b072 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "", "main": "gulpfile.js", "dependencies": { - "socket.io": "^1.3.5", + "socket.io": "^1.3.5" }, "devDependencies": { "babelify": "^6.1.2", @@ -17,6 +17,12 @@ "promise": "^7.0.1", "pubsub-js": "^1.5.2", "shortid": "^2.2.2", + "connect": "3.0.1", + "express": "4.12.3", + "minimist": "1.1.0", + "serve-static": "1.8.0", + "socketcluster": "2.2.x", + "socketcluster-client": "2.2.x", "vinyl-source-stream": "^1.1.0" }, "scripts": { diff --git a/public/js/client.js b/public/js/client.js index 59e21d9..1bf1ea9 100644 --- a/public/js/client.js +++ b/public/js/client.js @@ -1,4 +1,5 @@ -var io = require("socket.io-client")/*("http://localhost:16918")*/; +/*("http://localhost:16918")*/ +var socketCluster = require("socketcluster-client"); var Backbone = require("backbone"); var Handlebars = require("handlebars"); var $ = require("jquery"); @@ -22,8 +23,9 @@ Handlebars.registerHelper("health", function(lives, options){ var Config = {}; Config.Server = { - "URL": "http://localhost", - "PORT": 16918 + "hostname": "localhost", + "port": 16918, + secure: false } var App = Backbone.Router.extend({ @@ -40,14 +42,14 @@ var App = Backbone.Router.extend({ Backbone.history.start(); }, connect: function(){ - this.socket = io(Config.Server.URL + ":" + Config.Server.PORT); + this.socket = socketCluster.connect(Config.Server); }, receive: function(event, cb){ this.socket.on(event, cb); - }, + }, /* receiveOnce: function(event, cb){ this.socket.once(event, cb); - }, + },*/ send: function(event, data){ data = data || null; var socket = this.socket; @@ -141,7 +143,7 @@ var SideView = Backbone.View.extend({ this.$info.addClass("removeBackground"); } - this.$info.find(".passing").html(d.passing?"Passed":""); + this.$info.find(".passing").html(d.passing ? "Passed" : ""); }, renderCloseField: function(){ @@ -219,6 +221,8 @@ var BattleView = Backbone.View.extend({ this.$hand = this.$el.find(".field-hand"); this.$preview = this.$el.find(".card-preview"); + /*//this.battleChannel = app.socket.subscribe() + app.receive("update:hand", function(data){ if(user.get("roomSide") == data._roomSide){ self.handCards = JSON.parse(data.cards); @@ -257,13 +261,14 @@ var BattleView = Backbone.View.extend({ side.field.weather = data.weather; side.render(); - }) + })*/ var interval = setInterval(function(){ if(!user.get("room")) return; + this.setUpBattleEvents(user.get("room")); this.app.send("request:gameLoaded", {_roomID: user.get("room")}); clearInterval(interval); - }.bind(this), 100); + }.bind(this), 10); this.render(); @@ -346,6 +351,48 @@ var BattleView = Backbone.View.extend({ this.yourSide.render(); this.otherSide.render();*/ return this; + }, + setUpBattleEvents: function(channelName){ + this.battleChannel = this.app.socket.subscribe(channelName); + var self = this; + var user = this.user; + + this.battleChannel.watch(function(d){ + var event = d.event, data = d.data; + + if(event === "update:hand"){ + if(user.get("roomSide") == data._roomSide){ + self.handCards = JSON.parse(data.cards); + self.render(); + } + } + else if(event === "update:info"){ + var _side = data._roomSide; + var infoData = data.info; + var leader = data.leader; + + var side = self.yourSide; + if(user.get("roomSide") != _side){ + side = self.otherSide; + } + side.infoData = infoData; + side.leader = leader; + side.render(); + } + else if(event === "update:fields"){ + var _side = data._roomSide; + + var side = self.yourSide; + if(user.get("roomSide") != _side){ + side = self.otherSide; + } + side.field.close = data.close; + side.field.ranged = data.ranged; + side.field.siege = data.siege; + side.field.weather = data.weather; + side.render(); + } + }) } }); @@ -357,6 +404,8 @@ var User = Backbone.Model.extend({ var self = this; var app = this.get("app"); + this.listenTo(this.attributes, "change:room", this.subscribeRoom); + app.receive("response:name", function(data){ self.set("name", data.name); }); @@ -364,6 +413,8 @@ var User = Backbone.Model.extend({ app.receive("init:battle", function(data){ console.log("opponent found!"); self.set("roomSide", data.side); + /* + self.set("channel:battle", app.socket.subscribe(self.get("room")));*/ app.navigate("battle", {trigger: true}); }) @@ -396,6 +447,11 @@ var User = Backbone.Model.extend({ joinRoom: function(){ this.get("app").send("request:joinRoom"); }, + subscribeRoom: function(){ + var room = this.get("room"); + var app = this.get("app"); + app.socket.subscribe(room); + }, setName: function(name){ this.get("app").send("request:name", {name: name}); } diff --git a/server/Battle.js b/server/Battle.js index 65ba397..12ebea7 100644 --- a/server/Battle.js +++ b/server/Battle.js @@ -2,12 +2,12 @@ var Battleside = require("./Battleside"); var PubSub = require("pubsub-js"); var Card = require("./Card"); -var io = global.io; +/*var io = global.io;*/ var Battle = (function(){ - var Battle = function(id, p1, p2){ + var Battle = function(id, p1, p2, socket){ if(!(this instanceof Battle)){ - return (new Battle(id, p1, p2)); + return (new Battle(id, p1, p2, socket)); } /** * constructor here @@ -15,6 +15,8 @@ var Battle = (function(){ this._id = id; this._user1 = p1; this._user2 = p2; + this.socket = socket; + this.channel = {}; }; var r = Battle.prototype; /** @@ -29,21 +31,28 @@ var Battle = (function(){ r._user2 = null; r.turn = 0; + r.socket = null; + r.channel = null; r._id = null; r.init = function(){ PubSub.subscribe("update", this.update.bind(this)); + + + this.channel = this.socket.subscribe(this._id); this.p1 = Battleside(this._user1.getName(), 0, this, this._user1); this.p2 = Battleside(this._user2.getName(), 1, this, this._user2); this.p1.foe = this.p2; this.p2.foe = this.p1; this.p1.setUpWeatherFieldWith(this.p2); + this.start(); } + r.start = function(){ this.p1.setLeadercard(); this.p2.setLeadercard(); @@ -81,7 +90,7 @@ var Battle = (function(){ var side = this.turn++ % 2 ? this.p1 : this.p2; if(side.isPassing()){ - if(__flag) { + if(__flag){ return this.startNextRound(); } return this.switchTurn(1); @@ -93,7 +102,7 @@ var Battle = (function(){ } - r.startNextRound = function() { + r.startNextRound = function(){ } @@ -119,9 +128,23 @@ var Battle = (function(){ } r.send = function(event, data){ - io.to(this._id).emit(event, data); + this.channel.publish({ + event: event, + data: data + }); } + /*r._setUpChannel = function() { + var self = this; + this._abilityChannel.watch(function(d) { + var event = d.event, data = d.data; + + if(event === "update") { + data(); + } + }) + }*/ + return Battle; })(); diff --git a/server/Battleside.js b/server/Battleside.js index b0717ea..895a87f 100644 --- a/server/Battleside.js +++ b/server/Battleside.js @@ -174,19 +174,6 @@ Battleside = (function(){ } r.update = function(){ - /* - this.send("update:info", { - info: this.getInfo(), - leader: this.field[Card.TYPE.LEADER].get()[0] - }) - this.send("update:hand", { - cards: JSON.stringify(this.hand.getCards()) - }); - this.send("update:fields", { - close: this.field[Card.TYPE.CLOSE_COMBAT], - ranged: this.field[Card.TYPE.RANGED], - siege: this.field[Card.TYPE.SIEGE] - })*/ PubSub.publish("update"); } diff --git a/server/Card.js b/server/Card.js index b4d9655..0941a00 100644 --- a/server/Card.js +++ b/server/Card.js @@ -9,6 +9,7 @@ var Card = (function(){ /** * constructor here */ + this.channel = {}; this._key = key; this._data = CardData[key]; this._boost = 0; @@ -38,6 +39,8 @@ var Card = (function(){ WEATHER: 5 }; + r.channel = null + r._init = function(){ this._id = ++Card.__id; diff --git a/server/Npc.js b/server/Npc.js deleted file mode 100644 index bd723c3..0000000 --- a/server/Npc.js +++ /dev/null @@ -1,28 +0,0 @@ -var Entity = require("./Entity"); - - -var Npc = (function(){ - var Npc = function(){ - if(!(this instanceof Npc)){ - return (new Npc()); - } - Entity.call(this); - /** - * constructor here - */ - - - }; - Npc.prototype = Object.create(Entity.prototype); - var r = Npc.prototype; - /** - * methods && properties here - * r.property = null; - * r.getProperty = function() {...} - */ - - - return Npc; -})(); - -module.exports = Npc; \ No newline at end of file diff --git a/server/Room.js b/server/Room.js index 1b519bf..83fd37e 100644 --- a/server/Room.js +++ b/server/Room.js @@ -2,17 +2,28 @@ var shortid = require("shortid"); var Battle = require("./Battle"); var Room = (function(){ - var Room = function(){ + var Room = function(scServer){ if(!(this instanceof Room)){ - return (new Room()); + return (new Room(scServer)); } /** * constructor here */ + var self = this; this._id = shortid.generate(); - this._room = []; + this._users = []; this._ready = {}; + this.socket = scServer.global; +/* + this._channel = this.socket.subscribe(this._id);*/ + + /*this._channel.watch(function(data) { + *//*self._users.forEach(function(user) { + + })*//* + });*/ + }; var r = Room.prototype; /** @@ -21,20 +32,21 @@ var Room = (function(){ * r.getProperty = function() {...} */ r.MAX_USER = 2; - r._room = null; + r._users = null; r._id = null; r._battle = null; r._ready = null; + r._channel = null; r.getID = function(){ return this._id; } r.join = function(user){ - if(this._room.length >= 2) return; - this._room.push(user); - user.setRoom(this); - user.joinRoom(this.getID()); + if(this._users.length >= 2) return; + this._users.push(user); + user.addRoom(this); + /*user.joinRoom(this.getID());*/ if(!this.isOpen()){ this.initBattle(); @@ -42,47 +54,60 @@ var Room = (function(){ } r.isOpen = function(){ - return !(this._room.length >= 2); + return !(this._users.length >= 2); } +/* r.send = function(event, data){ - io.to(this._id).emit(event, data); + */ +/*this.socket.publish(this._id + "|" + event, data); + this.socket.publish(this._id, { + event: event, + data: data + }); + var subs = this.socket.subscriptions(); + subs.forEach(function(sub) { + + });*//* + + this._channel.publish(event, data); } +*/ r.getPlayers = function(){ - return this._room; + return this._users; } r.initBattle = function(){ var self = this; var side = 0; - this._battle = Battle(this._id, this._room[0], this._room[1]); - this._room[0].send("init:battle", {side: "p1"}); - this._room[1].send("init:battle", {side: "p2"}); + this._battle = Battle(this._id, this._users[0], this._users[1], this.socket); + this._users[0].send("init:battle", {side: "p1"}); + this._users[1].send("init:battle", {side: "p2"}); } r.setReady = function(user, b){ b = typeof b == "undefined" ? true : b; this._ready[user.getID()] = b; - if(this.bothReady()) { + if(this.bothReady()){ this._battle.init(); } /* if(!this.checkIfReady()) return; - this._room[0].send("init:battle", {side: "p1"}); - this._room[1].send("init:battle", {side: "p2"}); + this._users[0].send("init:battle", {side: "p1"}); + this._users[1].send("init:battle", {side: "p2"}); if(!this.checkIfReady()) return; this._battle.init();*/ } - r.bothReady = function() { - return !!this._ready[this._room[0].getID()] && !!this._ready[this._room[1].getID()]; + r.bothReady = function(){ + return !!this._ready[this._users[0].getID()] && !!this._ready[this._users[1].getID()]; } /* r.checkIfReady = function(){ - for(var i = 0; i < this._room.length; i++) { - if(!this._ready[this._room[i].getID()]) return false; + for(var i = 0; i < this._users.length; i++) { + if(!this._ready[this._users[i].getID()]) return false; } return true; }*/ diff --git a/server/Socket.js b/server/Socket.js index bbdae9c..a1c7d35 100644 --- a/server/Socket.js +++ b/server/Socket.js @@ -6,9 +6,6 @@ var Battle = require("./Battle"); var Npc = require("./Npc"); var Room = require("./Room"); -/* -var Matchmaker = require("./Matchmaker"); -*/ var Socket = (function(){ var Socket = function(){ diff --git a/server/User.js b/server/User.js index 1436856..7ab70c1 100644 --- a/server/User.js +++ b/server/User.js @@ -1,22 +1,18 @@ -var Entity = require("./Entity"); - - var User = (function(){ var User = function(socket){ if(!(this instanceof User)){ return (new User(socket)); } - Entity.call(this); /** * constructor here */ this.socket = socket; + this._rooms = []; this._id = socket.id; this.generateName(); }; - User.prototype = Object.create(Entity.prototype); var r = User.prototype; /** * methods && properties here @@ -26,7 +22,7 @@ var User = (function(){ r._id = null; r._name = null; - r._room = null; + r._rooms = null; r.socket = null; r.getID = function(){ @@ -34,7 +30,11 @@ var User = (function(){ } r.joinRoom = function(roomid){ - this.socket.join(roomid); + var self = this; + /*this.socket.on(roomid, function(d) { + var event = d.event, data = d.data; + self.socket.on(event, data); + });*/ } r.send = function(event, data, room){ @@ -43,8 +43,12 @@ var User = (function(){ if(!room){ this.socket.emit(event, data); } - else { - this.socket.to(room).emit(event, data); + else {/* + this.socket.to(room).emit(event, data);*/ + this.socket.global.publish(room, { + event: event, + data: data + }) } } @@ -63,10 +67,10 @@ var User = (function(){ return this._name; } r.getRoom = function() { - return this._room; + return this._rooms[0]; } - r.setRoom = function(room) { - this._room = room; + r.addRoom = function(room) { + this._rooms.push(room); } r.disconnect = function() { diff --git a/server/_server.js b/server/_server.js new file mode 100644 index 0000000..d00d4a7 --- /dev/null +++ b/server/_server.js @@ -0,0 +1,2 @@ +var socket = require("./Socket")(); + diff --git a/server/server.js b/server/server.js index d00d4a7..e7ea4b7 100644 --- a/server/server.js +++ b/server/server.js @@ -1,2 +1,13 @@ -var socket = require("./Socket")(); +var argv = require('minimist')(process.argv.slice(2)); +var SocketCluster = require('socketcluster').SocketCluster; +var socketCluster = new SocketCluster({ + workers: Number(argv.w) || 1, + stores: Number(argv.s) || 1, + port: Number(argv.p) || 16918, + appName: argv.n || null, + workerController: __dirname + '/worker.js', + storeController: __dirname + '/store.js', + socketChannelLimit: 100, + rebootWorkerOnCrash: argv['auto-reboot'] != false +}); \ No newline at end of file diff --git a/server/store.js b/server/store.js new file mode 100644 index 0000000..92effd8 --- /dev/null +++ b/server/store.js @@ -0,0 +1,4 @@ + +module.exports.run = function (store) { + console.log(' >> Store PID:', process.pid); +}; diff --git a/server/worker.js b/server/worker.js new file mode 100644 index 0000000..177fb2e --- /dev/null +++ b/server/worker.js @@ -0,0 +1,78 @@ +var fs = require('fs'); +var express = require('express'); +var serveStatic = require('serve-static'); +var path = require('path'); + +var User = require("./User"); +var Connections = require("./Connections"); +var Battle = require("./Battle"); +var Room = require("./Room"); + +module.exports.run = function(worker){ + console.log(' >> Worker PID:', process.pid); + + var app = require('express')(); + + var httpServer = worker.httpServer; + var scServer = worker.scServer; + + app.use(serveStatic(path.resolve(__dirname, 'public'))); + + httpServer.on('request', app); + + var connections = Connections(); + var roomCollection = {}; + + + + scServer.on('connection', function(socket){ + var user = User(socket); + connections.add(user); + console.log("new user ", user.getName()); + + socket.on("request:name", function(data){ + if(data && data.name){ + user.setName(data.name); + } + socket.emit("response:name", {name: user.getName()}); + }) + + socket.on("request:gameLoaded", function(data){ + console.log(data); + roomCollection[data._roomID].setReady(user); + }) + + socket.on("request:createRoom", function(){ + var room = Room(worker.getSCServer()); + roomCollection[room.getID()] = room; + room.join(user); + console.log("room %s created by %s", room.getID(), user.getName()); + user.send("response:createRoom", room.getID()); + }) + + socket.on("request:joinRoom", function(){ + console.log("joinroom"); + var interval = setInterval(function(){ + for(var key in roomCollection) { + var room = roomCollection[key]; + if(!room.isOpen()) continue; + room.join(user); + clearInterval(interval); + console.log("user %s joined room %s", user.getName(), room.getID()); + user.send("response:joinRoom", room.getID()); + } + }, 1000); + }) + + socket.on("request:roomData", function(){ + var room = user.getRoom(); + var players = room.getPlayers(); + user.send("response:roomData", {players: players}); + }) + + socket.on('disconnect', function(){ + connections.remove(user); + user.disconnect(); + }); + }); +}; \ No newline at end of file