All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.threerings.parlor.client.ParlorDirector Maven / Gradle / Ivy

The newest version!
//
// $Id$
//
// Vilya library - tools for developing networked games
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
// http://code.google.com/p/vilya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

package com.threerings.parlor.client;

import java.util.List;

import com.google.common.collect.Lists;

import com.samskivert.util.HashIntMap;

import com.threerings.util.Name;

import com.threerings.presents.client.BasicDirector;
import com.threerings.presents.client.Client;
import com.threerings.presents.client.InvocationService;

import com.threerings.parlor.data.ParlorCodes;
import com.threerings.parlor.game.data.GameConfig;
import com.threerings.parlor.util.ParlorContext;

import static com.threerings.parlor.Log.log;

/**
 * The parlor director manages the client side of the game configuration and matchmaking
 * processes. It is also the entity that is listening for game start notifications which it then
 * dispatches the client entity that will actually create and display the user interface for the
 * game that started.
 */
public class ParlorDirector extends BasicDirector
    implements ParlorCodes, ParlorReceiver
{
    /**
     * Constructs a parlor director and provides it with the parlor context that it can use to
     * access the client services that it needs to provide its own services. Only one parlor
     * director should be active in the client at one time and it should be made available via the
     * parlor context.
     *
     * @param ctx the parlor context in use by the client.
     */
    public ParlorDirector (ParlorContext ctx)
    {
        super(ctx);
        _ctx = ctx;

        // register ourselves with the invocation director as a parlor notification receiver
        _ctx.getClient().getInvocationDirector().registerReceiver(new ParlorDecoder(this));
    }

    /**
     * Sets the invitation handler, which is the entity that will be notified when we receive
     * incoming invitation notifications and when invitations have been cancelled.
     *
     * @param handler our new invitation handler.
     */
    public void setInvitationHandler (InvitationHandler handler)
    {
        _handler = handler;
    }

    /**
     * Adds the specified observer to the list of entities that are notified when we receive a game
     * ready notification.
     */
    public void addGameReadyObserver (GameReadyObserver observer)
    {
        _grobs.add(observer);
    }

    /**
     * Removes the specified observer from the list of entities that are notified when we receive a
     * game ready notification.
     */
    public void removeGameReadyObserver (GameReadyObserver observer)
    {
        _grobs.remove(observer);
    }

    /**
     * Requests that the named user be invited to a game described by the supplied game config.
     *
     * @param invitee the user to invite.
     * @param config the configuration of the game to which the user is being invited.
     * @param observer the entity that will be notified if this invitation is accepted, refused or
     * countered.
     *
     * @return an invitation object that can be used to manage the outstanding invitation.
     */
    public Invitation invite (Name invitee, GameConfig config, InvitationResponseObserver observer)
    {
        // create the invitation record
        Invitation invite = new Invitation(_ctx, _pservice, invitee, config, observer);
        // submit the invitation request to the server
        _pservice.invite(invitee, config, invite);
        // and return the invitation to the caller
        return invite;
    }

    /**
     * Requests that the specified single player game be started.
     *
     * @param config the configuration of the single player game to be started.
     * @param listener a listener to be informed of failure if the game cannot be started.
     */
    public void startSolitaire (GameConfig config, InvocationService.ConfirmListener listener)
    {
        _pservice.startSolitaire(config, listener);
    }

    @Override
    public void clientDidLogoff (Client client)
    {
        super.clientDidLogoff(client);
        _pservice = null;
        _pendingInvites.clear();
    }

    // documentation inherited from interface
    public void gameIsReady (int gameOid)
    {
        log.info("Handling game ready [goid=" + gameOid + "].");

        // see what our observers have to say about it
        boolean handled = false;
        for (int ii = 0; ii < _grobs.size(); ii++) {
            GameReadyObserver grob = _grobs.get(ii);
            handled = grob.receivedGameReady(gameOid) || handled;
        }

        // if none of the observers took matters into their own hands, then we'll head on over to
        // the game room ourselves
        if (!handled) {
            _ctx.getLocationDirector().moveTo(gameOid);
        }
    }

    // documentation inherited from interface
    public void receivedInvite (int remoteId, Name inviter, GameConfig config)
    {
        // create an invitation record for this invitation
        Invitation invite = new Invitation(_ctx, _pservice, inviter, config, null);
        invite.inviteId = remoteId;

        // put it in the pending invitations table
        _pendingInvites.put(remoteId, invite);

        try {
            // notify the invitation handler of the incoming invitation
            _handler.invitationReceived(invite);

        } catch (Exception e) {
            log.warning("Invitation handler choked on invite notification " + invite + ".", e);
        }
    }

    // documentation inherited from interface
    public void receivedInviteResponse (int remoteId, int code, Object arg)
    {
        // look up the invitation record for this invitation
        Invitation invite = _pendingInvites.get(remoteId);
        if (invite == null) {
            log.warning("Have no record of invitation for which we received a response?! " +
                        "[remoteId=" + remoteId + ", code=" + code + ", arg=" + arg + "].");

        } else {
            invite.receivedResponse(code, arg);
        }
    }

    // documentation inherited from interface
    public void receivedInviteCancellation (int remoteId)
    {
        // TBD
    }

    @Override
    protected void registerServices (Client client)
    {
        client.addServiceGroup(PARLOR_GROUP);
    }

    @Override
    protected void fetchServices (Client client)
    {
        // get a handle on our parlor services
        _pservice = client.requireService(ParlorService.class);
    }

    /**
     * Register a new invitation in our pending invitations table. The invitation will call this
     * when it knows its invitation id.
     */
    protected void registerInvitation (Invitation invite)
    {
        _pendingInvites.put(invite.inviteId, invite);
    }

    /**
     * Called by an invitation when it knows it is no longer and can be cleared from the pending
     * invitations table.
     */
    protected void clearInvitation (Invitation invite)
    {
        _pendingInvites.remove(invite.inviteId);
    }

    /** An active parlor context. */
    protected ParlorContext _ctx;

    /** Provides access to parlor server side services. */
    protected ParlorService _pservice;

    /** The entity that has registered itself to handle incoming invitation notifications. */
    protected InvitationHandler _handler;

    /** A table of acknowledged (but not yet accepted or refused) invitation requests, keyed on
     * invitation id. */
    protected HashIntMap _pendingInvites = new HashIntMap();

    /** We notify the entities on this list when we get a game ready notification. */
    protected List _grobs = Lists.newArrayList();
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy