0

Here follows a very basic Java version of Mudlet, a MUD client using Apache TelnetClient (not ssh).

Largely as an exercise, Context has, so far, just the one strategy, the TargetStrategy, which returns a Deque<GameActions> dependent upon the GameData objects values.

The idea is to add more strategies, and, more importantly to select the strategy based upon game data. For example, pass the String target in data...

And then I get a bit lost. One thing I'm fairly sure on is that a Context without GameData is nonsensical. For example, it's impossible to select a creature to target without the creature's name!

The current flow, set the strategy, then set the data, is backwards. Does this require a StrategySelector type class which takes the game data as a parameter and returns a Context?

Context code:

package game;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.logging.Logger;
import model.GameAction;
import model.GameData;

public class Context {

    private static Logger log = Logger.getLogger(Context.class.getName());
    private Strategy strategy;
    private GameData gameData = null;

    private Context() {
    }

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public Deque<GameAction> executeStrategy() {
        log.info(strategy.toString());
        return this.strategy.execute(gameData);
    }

    public void setGameData(GameData gameData) {
        this.gameData = gameData;
    }
}

when new data is observed, then do...what? Controller code below:

package telnet;

import game.Context;
import game.TargetStrategy;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Deque;
import java.util.Observable;
import java.util.Observer;
import java.util.Properties;
import java.util.logging.Logger;
import org.apache.commons.net.telnet.TelnetClient;
import model.GameAction;
import model.GameData;
import model.TelnetEventProcessor;

public class TelnetConnection implements Observer {

    private static Logger log = Logger.getLogger(TelnetConnection.class.getName());
    private TelnetClient telnetClient = new TelnetClient();
    private InputOutput inputOutput = new InputOutput();
    private TelnetEventProcessor parser = new TelnetEventProcessor();
    private Context context;// = new LogicalContext();

    public TelnetConnection() {
        try {
            init();
        } catch (SocketException ex) {
        } catch (FileNotFoundException ex) {
        } catch (IOException ex) {
        }
    }

    private void init() throws SocketException, FileNotFoundException, IOException {
        Properties props = PropertiesReader.getProps();
        InetAddress host = InetAddress.getByName(props.getProperty("host"));
        int port = Integer.parseInt(props.getProperty("port"));
        telnetClient.connect(host, port);
        inputOutput.readWriteParse(telnetClient.getInputStream(), telnetClient.getOutputStream());
        inputOutput.addObserver(this);
        parser.addObserver(this);
    }

    private void sendAction(GameAction action) throws IOException {
        log.fine(action.toString());
        byte[] actionBytes = action.getAction().getBytes();
        OutputStream outputStream = telnetClient.getOutputStream();
        outputStream.write(actionBytes);
        outputStream.write(13);
        outputStream.write(10);
        outputStream.flush();
    }

    private void sendActions(Deque<GameAction> gameActions) {
        while (!gameActions.isEmpty()) {
            GameAction action = gameActions.remove();
            try {
                sendAction(action);
            } catch (IOException ex) {
            }
        }
    }

    @Override
    public void update(Observable o, Object arg) {
        GameData data = null;
        String line = null;
        Deque<GameAction> gameActions;
        if (o instanceof InputOutput) {
            if (arg instanceof String) {
                line = arg.toString();
                parser.parse(line);
            } else if (arg instanceof GameData) {
                data = (GameData) arg;
                context = new Context(new TargetStrategy());
                context.setGameData(data);  //data changes frequently!
                //strategy depends on data
                //put all this in another class?
                gameActions = context.executeStrategy();
                sendActions(gameActions);
            } else {
                log.info("not a i/o arg");
            }
        } else if (o instanceof TelnetEventProcessor) {
            if (arg instanceof GameData) {
                log.info("game data arg");
                data = (GameData) arg;
                gameActions = context.executeStrategy();
                sendActions(gameActions);
            } else {
                log.info("not a telnetevent arg");
            }
        }
    }

    public static void main(String[] args) {
        new TelnetConnection();
    }
}
Thufir
  • 8,216
  • 28
  • 125
  • 273

1 Answers1

0

I'm not very happy with this:

package game;

import model.GameData;

public class RulesForStrategy {

    private Context context = null;
    private GameData gameData = null;

    private RulesForStrategy() {
    }

    public RulesForStrategy(GameData gameData) {
        this.gameData = gameData;
    }

    public Context getContext() {
        context = new Context(new TargetStrategy());
        context.setGameData(gameData);
        return context;
    }
}

because it doesn't solve the fundamental problem, that a context without data shouldn't exist!

However, I guess it will work...?

Thufir
  • 8,216
  • 28
  • 125
  • 273