Tuesday 7 February 2017

Chop the head off - making a headless Haven and Hearth client

Today I figured out I need to cut the head off Amber Haven and Hearth client. Main reason for it is that JOGL doesn't really like raspberry pi - there are lots of forum discussions about raspberry pi and JOGL, a couple suggested solutions, but unfortunately none of them really worked for me. So what we are going to try to do today is introduce a way to start Haven and Hearth client without visible window and lets hope it solves the problem.

Find the neck

First of all we need to identify places we need to modify in order to supress window creation. This should be a pretty simple process - we build our client on raspberry pi and run it:
This gives us two places in MainFrame.java where we crash, so lets move them under a condition, which would be a command line option, so we'll get something like:
        add(p);
        if (!Config.headless)
        	pack();
        setResizable(!Utils.getprefb("wndlock", false));
        p.requestFocus();
        seticon();
        if (!Config.headless)
        	setVisible(true);
        p.init();
        addWindowListener(new WindowAdapter() {

Obviously we need to add "headless" as a field in Config.java and modify Config.cmdline() to set that field.
public class Config {
...
	public static boolean headless = false;
...
    public static void cmdline(String[] args) {
        PosixArgs opt = PosixArgs.getopt(args, "hdPGp:U:r:A:u:C:l:");
...
                case 'l':
                	headless = true;
                	System.out.println("Running Headless - enjoy!");
                	break;
...
Ok, now we have an option lets compile and try to use it, we might want to modify run.bat at some point, but for now lets just run the client from command line manually.
java -Xms512m -Xmx1024m -jar hafen.jar -U http://game.havenandhearth.com/hres/ game.havenandhearth.com -l true
This unfortunately still doesn't give us a stable state:
So, we'll get this exception under condition as well, like this:
        public void run() {
            try {
                uglyjoglhack();
                if (state == null){
                	if(!Config.headless)
                          throw (new RuntimeException("State applier is still null after redraw"));
                	else
                	  System.out.println("State applier is still null after redraw");
                	
                }

Now we got our headless client running, but it is still pretty useless, since there is no we can interact with it.

I have no mouth and I have to scream

So, we need a way to tell client what we want from it without interacting with graphical interface, so lets create a console interface! Our console interface is going to be pretty simple - it will read a command from standard input and will pass it to root console:
package haven.automation;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import haven.HavenPanel;

public class ConsoleInterface implements Runnable {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String cmd = null;
		while(true){
			System.out.print("?> ");
			try {
				cmd = br.readLine();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("< "+cmd);
			try {
				HavenPanel.lui.root.ui.cons.run(cmd);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

}
We need to remember to start our ConsoleInterface thread, so something like this:
...
        this.g = new ThreadGroup(HackThread.tg(), "Haven client");
        this.mt = new HackThread(this.g, this, "Haven main thread");
        this.ct = new Thread(new ConsoleInterface(),"Haven Console Interface");
        this.ct.start();
...
Now lets try it out - we will be using our console interface together with graphical interface for demonstration purposes.

Ways to go

This enables us with a number of interesting further developments - next thing we should do is enable our ConsoleInterface to receive command output, and then extend it with additional commands to interact with objects and subjects.


No comments:

Post a Comment