[Red5] SharedObjects and rooms help plz

Denis Zgonjanin me.snap at gmail.com
Wed Aug 12 13:14:24 PDT 2009


Hi Malchom,

It seems like you're using nc.call() when you can instead be using so.send()
to send updates to the shared objects. Doing it this way means you need very
little server side code to handle updating the clients. For example, on the
client you can just do:

so.send("sharedObjectCallback", argument1, argument2...);

the server will then call all the other clients subscribed to that shared
object, calling the method sharedObjectCallback(argument1, argument2).

This can be done the way you were doing it using NetConnection.call(), but
it's just more work.

Also, you need to wait until NetConnection.connect() connects to the server
before you call SharedObject.getRemote(). You can do this by adding an event
listener on the nc object like so:

m_nc.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);

function onNetStatus(e:NetStatusEvent){
 so = SharedObject.getRemote();
}

On Wed, Aug 12, 2009 at 3:14 PM, Malchom <simward at yahoo.com> wrote:

> I am currently developing a a simple TicTacToe game running through red5.
> This first game I am making will lead to other games but I started with
> TicTacToe for it's simplicity so I could focus on understanding how Red5
> works.
>
> I've had this issue for 2 days now and it's driving me crazy... And I don't
> understand why it's not working...
>
> First of all, I use a simple structure. The app on the server handles all
> the games. Each game has it's scope/room. Each scope/room has a SharedObject
> created inside it's scope with a default name, this SO contains information
> related to the current game. All these game SOs have the same name, but they
> were created in a different scope/room in the roomStart(...) hook
>
> The client app (in Flash10/AS3) connects to the app, with a room parameter
> in the URI, the server app creates everything and waits until 2 players join
> the room to start the game.
>
> The issue is the following. The SOs seem to work on the server side, but my
> clients dont work... I can call server functions no problem from the
> clients. But when the server calls the clients through the SO, the clients
> don't do anything, I don't have server errors, and flash events are not
> being dispatched so I can't catch anything if there even is something
> wrong...
>
> I'm pretty sure there is something wrong with my SO logic, or that I dont
> know how to connect adequatly to the server SO... Please help me!!
>
> Note : notice how the client calls specify the scope/room to use in the
> server... Logically, this seems like it would work, but I'm sure i'm missing
> a huge detail and my logic is a bit sloppy... Sorry, i'm a PHP programmer,
> just started AS and Java...
>
>
>
> *Here is the client AS3 code :*
> package { import flash.display.*; import flash.events.*; import
> flash.net.NetConnection; import flash.net.Responder; import
> flash.net.SharedObject; import ScratchEvent; public class GameBoard extends
> MovieClip { private var m_nc:NetConnection; private var m_so:SharedObject;
> private var m_myScratch:String; private var m_ScratchList:Array; public
> function GameBoard():void { // Connect to the server m_nc = new
> NetConnection(); m_nc.addEventListener(<WBR>NetStatusEvent.NET_STATUS,
> NetStatusHandler); m_nc.connect("rtmp://<WBR>localhost/tictactoe/room1"); //
> Get the remote SharedObject for the game m_so =
> SharedObject.getRemote('room1/<WBR>ttt_game', m_nc.uri, false); m_so.client
> = this; m_so.connect(m_nc); // Prepare a game m_ScratchList = new Array(
> 'tr', 'tm', 'tl', 'mr', 'mm', 'ml', 'bl', 'bm', 'br'); GetMyScratch(); }
> private function ClearBoard():void { // Clear the game board } private
> function SendScratch(e:ScratchEvent) { if (MyTurn()) { m_nc.call('Scratch',
> new Responder(null, RespondFail), e.scratchName, "room1"); } } private
> function GetMyScratch() { m_nc.call( 'AssignScratch', new Responder(
> function(p_obj:String):void { m_myScratch = p_obj; m_myTurn = p_obj == 'X';
> }, RespondFail ), "room1" ); } public function DoScratch(p_type:String,
> p_name:String) { // Scratch the board } public function DoClearBoard() {
> ClearBoard(); } // Rest of my code for this class... } }
>
> *Here is the server side code :*
> package ar.TicTacToeGame; //JAVA import java.util.ArrayList; //Red 5 import
> org.red5.server.adapter.<WBR>ApplicationAdapter; import
> org.red5.server.api.IScope; import org.red5.server.api.IClient; import
> org.red5.server.api.so.<WBR>ISharedObject; import org.slf4j.Logger; import
> org.slf4j.LoggerFactory; public class Application extends ApplicationAdapter
> { protected static Logger log =
> LoggerFactory.getLogger(<WBR>Application.class); private IScope m_appScope;
> private String m_soName = "ttt_game"; private String m_version = "0.0.32";
> private Character GetTurn(IScope p_scope) { ISharedObject so =
> getSharedObject(p_scope, m_soName); return
> so.getAttribute("turn").<WBR>toString().charAt(0); } private Character
> GetTurn(String p_scope) { return GetTurn(m_appScope.getScope(p_<WBR>scope));
> } private int GetPlayerCount(IScope p_scope) { ISharedObject so =
> getSharedObject(p_scope, m_soName); return
> Integer.parseInt(so.<WBR>getAttribute("playerCount").<WBR>toString()); }
> private int GetPlayerCount(String p_scope) { return
> GetPlayerCount(m_appScope.<WBR>getScope(p_scope)); } private int
> GetScratchCount(IScope p_scope) { ISharedObject so =
> getSharedObject(p_scope, m_soName); return
> Integer.parseInt(so.<WBR>getAttribute("scratchCount").<WBR>toString()); }
> private int GetScratchCount(String p_scope) { return
> GetScratchCount(m_appScope.<WBR>getScope(p_scope)); } private Character
> GetBoardScratch(String p_name, IScope p_scope) { ISharedObject so =
> getSharedObject(p_scope, m_soName); return so.getAttribute(p_name +
> "Scratch").toString().charAt(<WBR>0); } private Character
> GetBoardScratch(String p_name, String p_scope) { return
> GetBoardScratch(p_name, m_appScope.getScope(p_scope)); } private void
> SetTurn(Character p_value, IScope p_scope) { ISharedObject so =
> getSharedObject(p_scope, m_soName); so.setAttribute("turn", p_value); }
> private void SetTurn(Character p_value, String p_scope) { SetTurn(p_value,
> m_appScope.getScope(p_scope)); } private void SetPlayerCount(int p_value,
> IScope p_scope) { ISharedObject so = getSharedObject(p_scope, m_soName);
> so.setAttribute("playerCount", p_value); } private void SetPlayerCount(int
> p_value, String p_scope) { SetPlayerCount(p_value,
> m_appScope.getScope(p_scope)); } private void SetScratchCount(int p_value,
> IScope p_scope) { ISharedObject so = getSharedObject(p_scope, m_soName);
> so.setAttribute("scratchCount"<WBR>, p_value); } private void
> SetScratchCount(int p_value, String p_scope) { SetScratchCount(p_value,
> m_appScope.getScope(p_scope)); } private void SetBoardScratch(Character
> p_scratch, String p_name, IScope p_scope) { ISharedObject so =
> getSharedObject(p_scope, m_soName); so.setAttribute(p_name+"<WBR>Scratch",
> p_scratch); } private void SetBoardScratch(Character p_scratch, String
> p_name, String p_scope) { SetBoardScratch(p_scratch, p_name,
> m_appScope.getScope(p_scope)); } public boolean appStart(IScope p_appScope)
> { <a href="http://log.info" target="_blank">log.info</a>(
> "ar.TicTacToeGame Start.("+p_appScope.getName()+<WBR>") Ver "+m_version);
> createSharedObject(p_appScope, "test", false); m_appScope = p_appScope;
> return super.appStart(p_appScope); } public boolean testing(String p_param)
> { ISharedObject so = getSharedObject(m_appScope, "test"); ArrayList params =
> new ArrayList(); params.add(p_param); so.sendMessage("DoTest", params);
> return true; } public boolean roomStart(IScope p_room) { if
> (!super.roomStart(p_room)) return false; createSharedObject(p_room,
> m_soName, false); SetTurn('X', p_room); SetPlayerCount(0, p_room); <a href="
> http://log.info" target="_blank">log.info</a>("Game created, name : " +
> p_room.getName()); return true; } public boolean roomJoin(IClient p_client,
> IScope p_room) { if (!super.roomJoin(p_client, p_room) ||
> GetPlayerCount(p_room) >= 2) return false; <a href="http://log.info"
> target="_blank">log.info</a>("New player, joined game name : " +
> p_room.getName()); SetPlayerCount(GetPlayerCount(<WBR>p_room)+1, p_room); if
> (GetPlayerCount(p_room) == 2) { PrepareBoard(p_room); } return true; }
> public void roomLeave(IClient p_client, IScope p_room) {
> SetPlayerCount(GetPlayerCount(<WBR>p_room)-1, p_room); <a href="
> http://log.info" target="_blank">log.info</a>("A player has left");
> super.roomLeave(p_client, p_room); } public void roomStop(IScope p_room) {
> <a href="http://log.info" target="_blank">log.info</a>("Both players have
> left, game "+p_room.getName()+" destroyed"); super.roomStop(p_room); }
> private void PrepareBoard(String p_scope) {
> PrepareBoard(m_appScope.<WBR>getScope(p_scope)); } private void
> PrepareBoard(IScope p_scope) { // Clear server board SetBoardScratch(' ',
> "tr", p_scope); SetBoardScratch(' ', "tm", p_scope); SetBoardScratch(' ',
> "tl", p_scope); SetBoardScratch(' ', "mr", p_scope); SetBoardScratch(' ',
> "mm", p_scope); SetBoardScratch(' ', "ml", p_scope); SetBoardScratch(' ',
> "br", p_scope); SetBoardScratch(' ', "bm", p_scope); SetBoardScratch(' ',
> "bl", p_scope); // Reset the scratch count SetScratchCount(0, p_scope); //
> Clear client boards DoRemote("DoClearBoard", new ArrayList(), p_scope); //
> Inform <a href="http://log.info" target="_blank">log.info</a>("Prepared a
> board"); } private boolean CheckIfDoneOrTie(String p_scope) { return
> CheckIfDoneOrTie(m_appScope.<WBR>getScope(p_scope)); } private boolean
> CheckIfDoneOrTie(IScope p_scope) { Boolean outcome = false; if
> (GetScratchCount(p_scope) > 4) { if (GetBoardScratch("tl", p_scope) ==
> GetBoardScratch("tm", p_scope) && GetBoardScratch("tm", p_scope) ==
> GetBoardScratch("tr", p_scope) && GetBoardScratch("tr", p_scope) != ' ') {
> <a href="http://log.info" target="_blank">log.info</a>("Player
> "+GetBoardScratch("tl", p_scope) +" has won..."); outcome = true; } else if
> (GetBoardScratch("ml", p_scope) == GetBoardScratch("mm", p_scope) &&
> GetBoardScratch("mm", p_scope) == GetBoardScratch("mr", p_scope) &&
> GetBoardScratch("mr", p_scope) != ' ') { <a href="http://log.info"
> target="_blank">log.info</a>("Player "+GetBoardScratch("ml", p_scope) +"
> has won..."); outcome = true; } else if (GetBoardScratch("bl", p_scope) ==
> GetBoardScratch("bm", p_scope) && GetBoardScratch("bm", p_scope) ==
> GetBoardScratch("br", p_scope) && GetBoardScratch("br", p_scope) != ' ') {
> <a href="http://log.info" target="_blank">log.info</a>("Player
> "+GetBoardScratch("bl", p_scope) +" has won..."); outcome = true; } else if
> (GetBoardScratch("tl", p_scope) == GetBoardScratch("ml", p_scope) &&
> GetBoardScratch("ml", p_scope) == GetBoardScratch("bl", p_scope) &&
> GetBoardScratch("bl", p_scope) != ' ') { <a href="http://log.info"
> target="_blank">log.info</a>("Player "+GetBoardScratch("tl", p_scope) +"
> has won..."); outcome = true; } else if (GetBoardScratch("tm", p_scope) ==
> GetBoardScratch("mm", p_scope) && GetBoardScratch("mm", p_scope) ==
> GetBoardScratch("bm", p_scope) && GetBoardScratch("bm", p_scope) != ' ') {
> <a href="http://log.info" target="_blank">log.info</a>("Player
> "+GetBoardScratch("tm", p_scope) +" has won..."); outcome = true; } else if
> (GetBoardScratch("tr", p_scope) == GetBoardScratch("mr", p_scope) &&
> GetBoardScratch("mr", p_scope) == GetBoardScratch("br", p_scope) &&
> GetBoardScratch("br", p_scope) != ' ') { <a href="http://log.info"
> target="_blank">log.info</a>("Player "+GetBoardScratch("tr", p_scope) +"
> has won..."); outcome = true; } else if (GetBoardScratch("tl", p_scope) ==
> GetBoardScratch("mm", p_scope) && GetBoardScratch("mm", p_scope) ==
> GetBoardScratch("br", p_scope) && GetBoardScratch("br", p_scope) != ' ') {
> <a href="http://log.info" target="_blank">log.info</a>("Player
> "+GetBoardScratch("tl", p_scope) +" has won..."); outcome = true; } else if
> (GetBoardScratch("tr", p_scope) == GetBoardScratch("mm", p_scope) &&
> GetBoardScratch("mm", p_scope) == GetBoardScratch("tl", p_scope) &&
> GetBoardScratch("tl", p_scope) != ' ') { <a href="http://log.info"
> target="_blank">log.info</a>("Player "+GetBoardScratch("tr", p_scope) +"
> has won..."); outcome = true; } else if (GetScratchCount(p_scope) >= 9) { <a
> href="http://log.info" target="_blank">log.info</a>("Tie game...");
> outcome = true; } else { outcome = false; } } return outcome; } private void
> RestartGame(String p_scope) {
> RestartGame(m_appScope.<WBR>getScope(p_scope)); } private void
> RestartGame(IScope p_scope) { <a href="http://log.info" target="_blank">
> log.info</a>("Restarting game"); PrepareBoard(p_scope); } public void
> Scratch(String p_name, String p_scope) { Scratch(p_name,
> m_appScope.getScope(p_scope)); } public void Scratch(String p_name, IScope
> p_scope) { // Update the clients ArrayList params = new ArrayList();
> params.add(GetTurn(p_scope).<WBR>toString()); params.add(p_name);
> DoRemote("DoScratch", params, p_scope); <a href="http://log.info"
> target="_blank">log.info</a>("Sent scratch "+GetTurn(p_scope)+" on
> "+p_name); // Game progression SetBoardScratch(GetTurn(p_<WBR>scope),
> p_name, p_scope); SetScratchCount(<WBR>GetScratchCount(p_scope)+1, p_scope);
> <a href="http://log.info" target="_blank">log.info</a>("Scratch count =
> "+GetScratchCount(p_scope)); // Change the turn if (GetTurn(p_scope) == 'X')
> { SetTurn('O', p_scope); } else { SetTurn('X', p_scope); } // Check if the
> game is over if (CheckIfDoneOrTie(p_scope)) { RestartGame(p_scope); } }
> public String AssignScratch(String p_scope) { return
> AssignScratch(m_appScope.<WBR>getScope(p_scope)); } public String
> AssignScratch(IScope p_scope) { if (GetPlayerCount(p_scope) == 1) { <a
> href="http://log.info" target="_blank">log.info</a>("Assigned scratch O");
> return "O"; } else { <a href="http://log.info" target="_blank">log.info</a>("Assigned
> scratch X"); return "X"; } } private void DoRemote(String p_name, ArrayList
> p_params, String p_scope) { DoRemote(p_name, p_params,
> m_appScope.getScope(p_scope)); } private void DoRemote(String p_name,
> ArrayList p_params, IScope p_scope) { ISharedObject so =
> getSharedObject(p_scope, m_soName); <a href="http://log.info"
> target="_blank">log.info</a>("DoRemote("+p_name+",
> "+p_params.toString()+", "+p_scope.getName()+")"); so.sendMessage(p_name,
> p_params); } }
>
> *web.xml*
>  TicTacToe AR globalScope default contextConfigLocation /WEB-INF/red5-*.xml
> locatorFactorySelector red5.xml parentContextKey default.context
> webAppRootKey /tictactoe
> org.springframework.web.<WBR>context.ContextLoaderListener Forbidden
> /streams/*
>
> *red5-web.xml*
>
>
> *red5-web.properties*
> webapp.contextPath=/tictactoe webapp.virtualHosts=*, localhost, 127.0.0.1
> ------------------------------
> View this message in context: SharedObjects and rooms help plz<http://www.nabble.com/SharedObjects-and-rooms-help-plz-tp24869286p24869286.html>
> Sent from the Red5 - English mailing list archive<http://www.nabble.com/Red5---English-f16329.html>at Nabble.com.
>
> _______________________________________________
> Red5 mailing list
> Red5 at osflash.org
> http://osflash.org/mailman/listinfo/red5_osflash.org
>
>


-- 
Denis Zgonjanin
Blindside Networks
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://osflash.org/pipermail/red5_osflash.org/attachments/20090812/66dfe185/attachment-0001.html>


More information about the Red5 mailing list