Package gwlpr.loginshard.controllers

Source Code of gwlpr.loginshard.controllers.MapDispatch

/**
* For copyright information see the LICENSE document.
*/

package gwlpr.loginshard.controllers;

import gwlpr.database.entities.Map;
import gwlpr.protocol.intershard.LSRequest_AcceptClient;
import gwlpr.protocol.loginserver.inbound.P041_CharacterPlayInfo;
import gwlpr.loginshard.models.ClientBean;
import gwlpr.loginshard.models.MapDispatchModel;
import gwlpr.loginshard.models.enums.ErrorCode;
import gwlpr.loginshard.views.MapDispatchView;
import gwlpr.loginshard.views.StreamTerminatorView;
import gwlpr.protocol.intershard.GSNotify_ClientConnected;
import gwlpr.protocol.intershard.GSNotify_WorldEmpty;
import gwlpr.protocol.intershard.GSReply_AcceptClient;
import gwlpr.protocol.intershard.utils.DistrictLanguage;
import gwlpr.protocol.intershard.utils.DistrictRegion;
import io.netty.channel.Channel;
import java.net.InetSocketAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import realityshard.container.events.Event;
import realityshard.container.gameapp.GameAppContext;
import realityshard.container.util.Handle;
import realityshard.container.util.HandleRegistry;


/**
* This dispatches our clients to the appropriate mapshards, based on the models
* decisions.
*
* @author miracle444, _rusty
*/
public class MapDispatch
{

    private static Logger LOGGER = LoggerFactory.getLogger(MapDispatch.class);

    private final GameAppContext context;
    private final MapDispatchModel model;
    private final HandleRegistry<ClientBean> clientHandleRegistry;


    /**
     * Constructor.
     *
     * @param       context
     * @param       clientHandleRegistry
     */
    public MapDispatch(Handle<GameAppContext> context, HandleRegistry<ClientBean> clientHandleRegistry)
    {
        this.context = context.get();
        model = new MapDispatchModel(context);
        this.clientHandleRegistry = clientHandleRegistry;
    }


    /**
     * Event handler.
     *
     * @param action
     */
    @Event.Handler
    public void onCharacterPlayInfo(P041_CharacterPlayInfo action)
    {
        LOGGER.debug("Got the character play info packet");

        // get the channel attachment for that channel
        Channel channel = action.getChannel();
        ClientBean client = ClientBean.get(channel);
        Handle<ClientBean> clientHandle = ClientBean.getHandle(channel);

        // failcheck
        if (client == null) { channel.close(); return; }

        // update the login count
        client.setLoginCount(action.getLoginCount());

        // TODO: check mapId before directly creating a mapshard for it!
        // TODO: check the following values!
        // we ignore the instance number because the server needs to chose that...
        int mapId = (int)action.getGameMapId();
        int instanceNum = (int)action.getInstanceNumber();
        DistrictRegion region = DistrictRegion.values()[(int)action.getRegion()];
        DistrictLanguage language = DistrictLanguage.values()[(int)action.getLanguage()];
       
        // TODO: enable outposts
        Handle<GameAppContext> mapShardHandle = model.getOrCreateExplorable(mapId);
            // let the model do the work...
            //Handle<GameAppContext> mapShardHandle = model.getOrCreate(mapId, region, language, instanceNum, true);

        // lets check if we were successfull with the game app creation
        if (mapShardHandle == null)
        {
            LOGGER.warn("Was unable to create a game app! Please check the log for other errors!");
            StreamTerminatorView.send(channel, ErrorCode.InternalServerError);
            return;
        }

        // inform the model that we'r waiting for a mapshard to accept a client
        model.clientWaitingFor(clientHandle, mapShardHandle);

        // dont forget to update the client bean (it now has a mapshard, yay :)
        client.setMapShardHandle(mapShardHandle);

        LOGGER.debug("Asking a map shard to accept a client.");

        mapShardHandle.get().trigger(
                new LSRequest_AcceptClient(
                    clientHandle.getUid(),
                    client.getAccount(),
                    client.getCharacter()));

        // we will notify the client when the mapshard replies.
    }


    /**
     * Event handler.
     * Triggered when the map shard accepts a client.
     *
     * @param event
     */
    @Event.Handler
    public void onAcceptClientReply(GSReply_AcceptClient event)
    {
        Handle<ClientBean> clientHandle = clientHandleRegistry.getHandle(event.getClientUid());

        // failcheck
        if (clientHandle == null) { return; }

        Handle<GameAppContext> mapShardHandle = clientHandle.get().getMapShardHandle();

        // failcheck
        if (mapShardHandle == null || !mapShardHandle.getUid().equals(event.getServerUid())) { return; }

        // this is called when the mapshard didnt accept the client
        model.clientGotAcceptedBy(clientHandle, mapShardHandle, event.isAccepted());

        // check if the session has been accepted
        if (!event.isAccepted())
        {
            LOGGER.warn("The map shard did not accept the session!");

            StreamTerminatorView.send(clientHandle.get().getChannel(), ErrorCode.InternalServerError);
        }

        // retrieve socket address for that game server
        InetSocketAddress address = context.getManager().localAddressFor(mapShardHandle);
        Map map = model.getBean(mapShardHandle).getMap();

        // failcheck
        if (address == null || map == null) { return; }

        LOGGER.debug("The map shard accepted the client.");

        MapDispatchView.referToGameServer(
                clientHandle.get().getChannel(),
                address,
                event.getServerUid(),
                event.getClientUid(),
                map.getGameID());
    }


    /**
     * Event handler.
     * Triggered when a map shard established the actual connection to the client
     *
     * @param event
     */
    @Event.Handler
    public void onNotifyClientConnected(GSNotify_ClientConnected event)
    {
        Handle<ClientBean> clientHandle = clientHandleRegistry.getHandle(event.getClientUid());

        // failcheck
        if (clientHandle == null) { return; }

        Handle<GameAppContext> mapShardHandle = clientHandle.get().getMapShardHandle();

        // failcheck
        if (mapShardHandle == null || !mapShardHandle.getUid().equals(event.getServerUid())) { return; }

        model.dispatchDone(clientHandle, mapShardHandle);
    }


    /**
     * Event handler.
     * Triggered when a map shard runs out of clients. We need to decide whether
     * it should terminate in that case.
     *
     * @param       event
     */
    @Event.Handler
    public void onEmptyMapShard(GSNotify_WorldEmpty event)
    {
        // default behaviour: do nothing

//        RemoteShardletContext mapShard = null;
//
//        // lets see if we got that map shard:
//        if (mapShards.containsKey(action.getMapId()))
//        {
//            mapShard = mapShards.get(action.getMapId());
//
//            mapShard.sendTriggerableAction(new ISC_ShutdownMapshardRequestAction());
//
//            mapShards.remove(action.getMapId());
//        }
    }
}
TOP

Related Classes of gwlpr.loginshard.controllers.MapDispatch

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.