0

So I'm starting a Bukkit (Minecraft) server from a GUI.

ProcessBuilder builder = new ProcessBuilder();
builder.redirectErrorStream(true);
builder.command("java", "-jar", file.getAbsolutePath());

try {
    p = builder.start();
    input = new BufferedReader(new InputStreamReader(p.getInputStream()));
    output = new DataOutputStream(p.getOutputStream());
} catch (IOException e) {
    Logger.logError(e);
    return;
}

There are no errors, and the server itself starts correctly. The input stream works correctly too, as I get all the input as I should. Now, I have this method to send a command to the server.

public void send(String message) {
    try {
        output.writeUTF(message + "\n");
        output.flush();
    } catch (IOException e) {
        Logger.logError(e);
    }
}

For some reason though, it doesn't work. I'm not sure if I missed a step, or am looking over something, etc. Any help would be greatly appreciated!

Tips48
  • 745
  • 2
  • 11
  • 26
  • Are you sure `\n` is the right new line character on server side? Try this: `output.writeUTF(String.format("%1$1s%n",message));` Please note that `%n` at the end represents a platform independent new line character. For more details check [Java: How do I get a platform independent new line character?](http://stackoverflow.com/questions/207947/java-how-do-i-get-a-platform-independent-new-line-character) – dic19 Sep 03 '13 at 21:58
  • Yeah, I'm positive that \n is correct. – Tips48 Sep 04 '13 at 01:28

1 Answers1

1

I suspect the DataOutputStream is writing data in a non-conventional way towards the OutputStream, try using a PrintWriter object instead.

Consider this:

try {
    p = builder.start();
    input = new BufferedReader(new InputStreamReader(p.getInputStream()));
    output = new PrintWriter(p.getOutputStream());
} catch (IOException e) {
    Logger.logError(e);
    return;
}


The Send method:

public void send(String message) {
    output.println(message);
    output.flush();
}

P.S You no longer need the try-catch around the output.println() as PrintWriter's print and println methods don't throw IOException.

From bukkit's plugin perspective (read my comment if you have no clue what this is):

final JavaPlugin Inst = ... //This plugin's object

try(BufferedReader Reader = new BufferedReader(new InputStreamReader(System.in, Charset.forName("UTF-8")))){
    while((Line = Reader.readLine()) != null){
        final String L = Line;
        Bukkit.getScheduler().runTask(Inst, new Runnable(){
            @Override
            public void run() {
                 Bukkit.dispatchCommand(Bukkit.getConsoleSender(), L);
            }
        });
    }
}catch(IOException ex){
    //Handle this
}
initramfs
  • 8,275
  • 2
  • 36
  • 58
  • Nope, thanks though. I also tried removing my input parsing incase the thread was hanging or something similar. also didn't work – Tips48 Sep 05 '13 at 01:17
  • @Tips48 Err... Not to be rude but what does "nope" mean? Do you mean you cannot implement something like this? Or do you mean it doesn't work? Because I too have made a bukkit server GUI and have successfully communicated with it via PrintWriter. One thing you need to note about bukkit is that it doesn't read the outputstream directly, you need to make a little plugin (in bukkit) which reads the outputstream (System.in from bukkit's perspective) and send it to the command scheduler manually. – initramfs Sep 05 '13 at 10:13
  • @Tips48 I've updated my answer to include a sample of what the plugin code should look like. – initramfs Sep 05 '13 at 10:21
  • Hey thanks @CPU Terminator. The problem i'm running into is a weird one, and to be honest doesn't make sense. Basically, I want to support both Bukkit and Vanilla. I create the process as shown above, but the output stream doesn't affect the server. E.X. if I call stop, the server doesn't stop. things like say hi don't work either. Thanks for that plugin code, but I already had some :) The server is definitely being started because I can join/use plugins on it, etc. – Tips48 Sep 06 '13 at 16:02
  • @Tips48 I cannot say for vanilla... but for Bukkit... the input relies on the [Console](http://docs.oracle.com/javase/6/docs/api/java/io/Console.html) object which is only set when actually started from a console (command prompt, terminal). If you start a bukkit server via ProcessBuilder, from bukkit's perspective the Console object is null, therefore it will not accept any input at all. This does not mean however that the standard I/O streams cannot be used (stdin, stdout, System.in, System.out). – initramfs Sep 06 '13 at 18:44
  • @Tips48 Try it yourself... create a dummy program that reads input via a Console object, notice how launching it by ProcessBuilder will render it incapable of reading input. – initramfs Sep 06 '13 at 18:44
  • Hmm, thanks CPU Terminator. Any advice how to be able to send input then? Or do I *have* to use a plugin? – Tips48 Sep 07 '13 at 22:28
  • WOOT! Figured it out. Needed to turn off jline. Thanks for your help :) – Tips48 Sep 08 '13 at 02:27
  • @Tips48 Sorry I didn't see your comment in time... Glad you figured it out though. I knew Bukkit used a external library (which uses the Console object) for input processing but I forgot which one... – initramfs Sep 08 '13 at 07:36
  • Yep, just launch with -nojline – Tips48 Sep 08 '13 at 13:15