Search in sources :

Example 1 with MinecraftServerConnection

use of com.microsoft.Malmo.Schemas.MinecraftServerConnection in project malmo by Microsoft.

the class ClientStateMachine method initialiseComms.

/**
     * Set up the mission poller.<br>
     * This is called during the initialisation episode, but also needs to be
     * available for other episodes in case the configuration changes, resulting
     * in changes to the ports.
     * 
     * @throws UnknownHostException
     */
protected void initialiseComms() throws UnknownHostException {
    // Start polling for missions:
    if (this.missionPoller != null) {
        this.missionPoller.stopServer();
    }
    this.missionPoller = new TCPInputPoller(AddressHelper.getMissionControlPortOverride(), AddressHelper.MIN_MISSION_CONTROL_PORT, AddressHelper.MAX_FREE_PORT) {

        @Override
        public void onError(String error, DataOutputStream dos) {
            System.out.println("SENDING ERROR: " + error);
            try {
                dos.writeInt(error.length());
                dos.writeBytes(error);
            } catch (IOException e) {
            }
        }

        private void reply(String reply, DataOutputStream dos) {
            System.out.println("REPLYING WITH: " + reply);
            try {
                dos.writeInt(reply.length());
                dos.writeBytes(reply);
            } catch (IOException e) {
                System.out.println("Failed to reply to message!");
            }
        }

        @Override
        public boolean onCommand(String command, String ipFrom, DataOutputStream dos) {
            System.out.println("Received from " + ipFrom + ":");
            System.out.println(command.substring(0, Math.min(command.length(), 1024)));
            boolean keepProcessing = false;
            // Possible commands:
            // 1: MALMO_REQUEST_CLIENT:<malmo version>:<reservation_length(ms)><experiment_id>
            // 2: MALMO_CANCEL_REQUEST
            // 3: MALMO_FIND_SERVER<experiment_id>
            // 4: MissionInit
            String reservePrefix = "MALMO_REQUEST_CLIENT:" + Loader.instance().activeModContainer().getVersion() + ":";
            String findServerPrefix = "MALMO_FIND_SERVER";
            String cancelRequestCommand = "MALMO_CANCEL_REQUEST";
            if (command.startsWith(reservePrefix)) {
                // Reservation request.
                // We either reply with MALMOOK, if we are free, or MALMOBUSY if not.
                IState currentState = getStableState();
                if (currentState != null && currentState.equals(ClientState.DORMANT) && !isReserved()) {
                    reserveClient(command.substring(reservePrefix.length()));
                    reply("MALMOOK", dos);
                } else {
                    // We're busy - we can't be reserved.
                    reply("MALMOBUSY", dos);
                }
            } else if (command.equals(cancelRequestCommand)) {
                // If we've been reserved, cancel the reservation.
                if (isReserved()) {
                    cancelReservation();
                    reply("MALMOOK", dos);
                } else {
                    // We weren't reserved in the first place - something is odd.
                    reply("MALMOERRORAttempt to cancel a reservation that was never made.", dos);
                }
            } else if (command.startsWith(findServerPrefix)) {
                // Request to find the server for the given experiment ID.
                String expID = command.substring(findServerPrefix.length());
                if (currentMissionInit() != null && currentMissionInit().getExperimentUID().equals(expID)) {
                    // Our Experiment IDs match, so we are running the same experiment.
                    // Return the port and server IP address to the caller:
                    MinecraftServerConnection msc = currentMissionInit().getMinecraftServerConnection();
                    if (msc == null)
                        // Mission might be starting up.
                        reply("MALMONOSERVERYET", dos);
                    else
                        reply("MALMOS" + msc.getAddress() + ":" + msc.getPort(), dos);
                } else {
                    // We don't have a MissionInit ourselves, or we're running a different experiment,
                    // so we can't help.
                    reply("MALMONOSERVER", dos);
                }
            } else {
                // See if we've been sent a MissionInit message:
                MissionInitResult missionInitResult = decodeMissionInit(command);
                if (missionInitResult.wasMissionInit && missionInitResult.missionInit == null) {
                    // Got sent a duff MissionInit xml - pass back the JAXB/SAXB errors.
                    reply("MALMOERROR" + missionInitResult.error, dos);
                } else if (missionInitResult.wasMissionInit && missionInitResult.missionInit != null) {
                    MissionInit missionInit = missionInitResult.missionInit;
                    // We've been sent a MissionInit message.
                    // First, check the version number:
                    String platformVersion = missionInit.getPlatformVersion();
                    String ourVersion = Loader.instance().activeModContainer().getVersion();
                    if (platformVersion == null || !platformVersion.equals(ourVersion)) {
                        reply("MALMOERRORVERSIONMISMATCH (Got " + platformVersion + ", expected " + ourVersion + " - check your path for old versions of MalmoPython/MalmoJava/Malmo.lib etc)", dos);
                    } else {
                        // MissionInit passed to us - this is a request to launch this mission. Can we?
                        IState currentState = getStableState();
                        if (currentState != null && currentState.equals(ClientState.DORMANT) && isAvailable(missionInit.getExperimentUID())) {
                            reply("MALMOOK", dos);
                            // State machine will now process this MissionInit and start the mission.
                            keepProcessing = true;
                        } else {
                            // We're busy - we can't run this mission.
                            reply("MALMOBUSY", dos);
                        }
                    }
                }
            }
            return keepProcessing;
        }
    };
    this.missionPoller.start();
    // Tell the address helper what the actual port is:
    AddressHelper.setMissionControlPort(ClientStateMachine.this.missionPoller.getPortBlocking());
    if (AddressHelper.getMissionControlPort() == -1) {
        // Failed to create a mission control port - nothing will work!
        System.out.println("**** NO MISSION CONTROL SOCKET CREATED - WAS THE PORT IN USE? (Check Mod GUI options) ****");
        ClientStateMachine.this.getScreenHelper().addFragment("ERROR: Could not open a Mission Control Port - check the Mod GUI options.", TextCategory.TXT_CLIENT_WARNING, MISSING_MCP_PORT_ERROR);
    } else {
        // Clear the error string, if there was one:
        ClientStateMachine.this.getScreenHelper().clearFragment(MISSING_MCP_PORT_ERROR);
    }
    // Display the port number:
    ClientStateMachine.this.getScreenHelper().clearFragment(INFO_MCP_PORT);
    if (AddressHelper.getMissionControlPort() != -1)
        ClientStateMachine.this.getScreenHelper().addFragment("MCP: " + AddressHelper.getMissionControlPort(), TextCategory.TXT_INFO, INFO_MCP_PORT);
}
Also used : IState(com.microsoft.Malmo.IState) DataOutputStream(java.io.DataOutputStream) MinecraftServerConnection(com.microsoft.Malmo.Schemas.MinecraftServerConnection) IOException(java.io.IOException) MissionInit(com.microsoft.Malmo.Schemas.MissionInit) TCPInputPoller(com.microsoft.Malmo.Utils.TCPInputPoller)

Aggregations

IState (com.microsoft.Malmo.IState)1 MinecraftServerConnection (com.microsoft.Malmo.Schemas.MinecraftServerConnection)1 MissionInit (com.microsoft.Malmo.Schemas.MissionInit)1 TCPInputPoller (com.microsoft.Malmo.Utils.TCPInputPoller)1 DataOutputStream (java.io.DataOutputStream)1 IOException (java.io.IOException)1