2

Lately i have been trying to make communication between minecraft server (running with Java) and scratch (running with JavaScript). I have written the code in java already:

package me.yotam180;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;

import org.bukkit.Bukkit;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;


public class HttpProcessor {
     public MainClass plugin;
    public HttpProcessor (MainClass plug) throws IOException {
        plugin = plug;
        plugin.getLogger().info("CREATED HTTTP PROCESSOR");
        HttpServer server = HttpServer.create(new InetSocketAddress(9090), 0);
        server.createContext("/pollplayer", new PollPlayerHandler());
        server.createContext("/killplayer", new KillPlayerHandler());
        plugin.getLogger().info("STARTED HTTTP SERVER");
        server.setExecutor(null); // creates a default executor
        server.start();
    }

    static class PollPlayerHandler implements HttpHandler {

        @SuppressWarnings("deprecation")
        @Override
        public void handle(HttpExchange httpExchange) throws IOException {
            // TODO Auto-generated method stub
            Map <String,String>parms = HttpProcessor.queryToMap(httpExchange.getRequestURI().getQuery());
            StringBuilder response = new StringBuilder();
            response.append(Bukkit.getPlayer(parms.get("name")).getLocation().toString());
            HttpProcessor.writeResponse(httpExchange, response.toString());
        }
    }
    static class KillPlayerHandler implements HttpHandler {

        @SuppressWarnings("deprecation")
        @Override
        public void handle(HttpExchange httpExchange) throws IOException {
            // TODO Auto-generated method stub
            Map <String,String>parms = HttpProcessor.queryToMap(httpExchange.getRequestURI().getQuery());
            Bukkit.getPlayer(parms.get("name")).setHealth(0);
            HttpProcessor.writeResponse(httpExchange, "SUCCESS");
        }
    }

    public static void writeResponse(HttpExchange httpExchange, String response) throws IOException {
        httpExchange.sendResponseHeaders(200, response.length());
        OutputStream os = httpExchange.getResponseBody();
        os.write(response.getBytes());
        os.close();
      }

    public static Map<String, String> queryToMap(String query){
        Map<String, String> result = new HashMap<String, String>();
        for (String param : query.split("&")) {
            String pair[] = param.split("=");
            if (pair.length>1) {
                result.put(pair[0], pair[1]);
            }else{
                result.put(pair[0], "");
            }
        }
        return result;
      }

}

Now I have to make the scratch side HTTP Client. Every way i tried, It just didn't work. I try to open my browser, i write http://localhost:9090/pollplayer?name=yotam_salmon and it reports my player location beautifully. Now my problmem is the scratch JS.

Here it is:

new (function () {
    var ext = this;

    // Cleanup function when the extension is unloaded
    ext._shutdown = function () { };

    // Status reporting code
    // Use this to report missing hardware, plugin or unsupported browser
    ext._getStatus = function () {
        return { status: 2, msg: 'Ready' };
    };

    ext.get_Player = function (name, callback) {
        //in this function i need to call http://localhost:9090/pollplayer?name= + name, wait for the response and then callback it.
        //the response can't be "return response;", and it cannot be call backed from another function. If this function was called, it
        //has to report the location back as a string
    };

    // Block and block menu descriptions
    var descriptor = {
        blocks: [
            ['R', 'location of %s', 'get_Player', 'Player'],
        ]
    };

    // Register the extension
    ScratchExtensions.register('ScratchCraft', descriptor, ext);
})();

I cannot format my JS code differently, because Scratch works only with this format.(It is explained here: http://llk.github.io/scratch-extension-docs/). In the ext.get_Player function i have to go to the Java http server, request /pollplayer?name= + name, and callback it .

I would be happy to get a solution :) Thanks!

Yotam Salmon
  • 2,400
  • 22
  • 36
  • `sun.net` is deprecated. Use a proper HTTP connection, such as the dependency Apache HTTP Library. – Unihedron Mar 15 '15 at 06:05
  • I'm sure you know what you're doing, but the boilerplate code in http://llk.github.io/scratch-extension-docs/ looks different from yours; why is that? Have you tried the 'Reporter blocks that wait' code sample (which is _very_ similar to what you want), and did it work? Have you checked your web browser's javascript console for possible errors? Have you tried a [packet analyzer](http://en.wikipedia.org/wiki/Packet_analyzer) to verify the correct URL is sent to the Minecraft server? – Ruud Helderman Mar 15 '15 at 20:06
  • Firstly, Thanks a lot for the answer. The reporterblocks that wait is exactly what I want, but I can't get it to work. I tried the weather example, and it worked. After that, I changed the url in the $.ajax part to my java server and it stopped working. I think that I'm maybe providing the HTTP responses wrong. It's kind of my 1st time with real javascript, so I didn't know that there is a console... How do I open it ni Chrome? and no, I didn't use a packet analyzer, but I'll try. Tommorow in my time zone I will try making different ways of HTTP responses, but thank you. – Yotam Salmon Mar 15 '15 at 21:09
  • If the code sample breaks when changing to your own URL, then that suggests the fault is in the Java part. A packet analyzer shows the 'weather' URL returns an `Access-Control-Allow-Origin` response header, as proposed [here](http://stackoverflow.com/questions/17285895/ajax-call-not-working-when-trying-to-send-data-to-localhost8000-from-localhost). Your Java code should do the same, otherwise the web browser might reject your URL for being an (unsafe) cross-origin request. In Google Chrome, you will find the JavaScript console in the menu under 'More tools' (shortcut: Ctrl+Shift+J). – Ruud Helderman Mar 16 '15 at 12:41
  • I added the line httpExchange.getRequestHeaders().set("Access-Control-Allow-Origin", "*"); in the response handling, but now it doesn't show the eresponse even in the browser :( – Yotam Salmon Mar 16 '15 at 19:33
  • You have to set the _response_ header; setting the _request_ header in your handlers is wrong and possibly throws [IllegalStateException](http://docs.oracle.com/javaee/7/api/javax/ws/rs/core/HttpHeaders.html#getRequestHeaders%28%29); hence the response becoming invisible altogether. – Ruud Helderman Mar 17 '15 at 12:09
  • Yeah I understood and fixed it thank you very much! Is there in this website a +1 or "Like" or "I appriciate" button? I'm new here :) – Yotam Salmon Mar 17 '15 at 20:46
  • Thank _you_ for the fast feedback. Please post an [answer to your own question](http://stackoverflow.com/help/self-answer) explaining in detail what exactly needed to be done to fix the problem. I don't have a reproducible situation here, so I think it is best you do the honours. Feel free to re-use text from my comments if you like. Then accept your own answer, to let others know the solution actually worked out well for you. – Ruud Helderman Mar 18 '15 at 14:08

1 Answers1

8

The solution was very simple. I just had to add an header of "Allow-Access-Cross-Origin", and it was solved.

httpExchange.getResponseHeaders().set("Access-Control-Allow-Origin", "*");
httpExchange.getResponseHeaders().set("Content-Type", "text/plain");
Yotam Salmon
  • 2,400
  • 22
  • 36