All Downloads are FREE. Search and download functionalities are using the official Maven repository.

simple.client.DefaultClient Maven / Gradle / Ivy

The newest version!
package simple.client;

import java.io.IOException;
import static java.lang.Thread.sleep;
import java.net.ConnectException;
import java.net.SocketException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import marauroa.client.BannedAddressException;
import marauroa.client.ClientFramework;
import marauroa.client.LoginFailedException;
import marauroa.client.TimeoutException;
import marauroa.client.net.IPerceptionListener;
import marauroa.client.net.PerceptionHandler;
import marauroa.common.game.AccountResult;
import marauroa.common.game.CharacterResult;
import marauroa.common.game.RPAction;
import marauroa.common.game.RPObject;
import marauroa.common.net.InvalidVersionException;
import marauroa.common.net.message.MessageS2CLoginNACK.Reasons;
import marauroa.common.net.message.MessageS2CPerception;
import marauroa.common.net.message.TransferContent;
import org.openide.util.Lookup;
import org.openide.util.lookup.ServiceProvider;
import simple.client.api.AddListener;
import simple.client.api.ClearListener;
import simple.client.api.DeleteListener;
import simple.client.api.ExceptionListener;
import simple.client.api.IWorldManager;
import simple.client.api.ModificationListener;
import simple.client.api.PerceptionListener;
import simple.client.api.SelfChangeListener;
import simple.client.api.SyncListener;
import simple.server.core.entity.clientobject.ClientObject;

/**
 *
 * @author Javier A. Ortiz Bultron 
 */
@ServiceProvider(service = ClientFrameworkProvider.class, position = 1)
public class DefaultClient implements ClientFrameworkProvider {

    private String port;
    private String gameName;
    private String version;
    private marauroa.client.ClientFramework clientManager;
    private PerceptionHandler handler;
    private static boolean showWorld = false, chat = false;
    private String character;
    private String host;
    private String username;
    private String password;
    private String email;
    private Map characters = new HashMap<>();
    private boolean createDefaultCharacter = false;
    private boolean connected = false;
    private boolean autocreation = true;

    private static final Logger LOG
            = Logger.getLogger(DefaultClient.class.getSimpleName());

    @Override
    public boolean isShowWorld() {
        return showWorld;
    }

    @Override
    public void setShowWorld(boolean aShowWorld) {
        showWorld = aShowWorld;
    }

    @Override
    public boolean isChat() {
        return chat;
    }

    @Override
    public void setChat(boolean aChat) {
        chat = aChat;
    }

    public DefaultClient() {
        if (handler == null) {
            handler = new PerceptionHandler(new IPerceptionListener() {
                @Override
                public boolean onAdded(RPObject object) {
                    boolean result = false;
                    LOG.log(Level.FINE, "onAdded: {0}", object);
                    for (AddListener listener
                            : Lookup.getDefault().lookupAll(AddListener.class)) {
                        if (!listener.onAdded(object)) {
                            result = true;
                        }
                    }
                    return result;
                }

                @Override
                public boolean onClear() {
                    LOG.fine("onClear");
                    boolean result = false;
                    for (ClearListener listener
                            : Lookup.getDefault().lookupAll(ClearListener.class)) {
                        if (!listener.onClear()) {
                            result = true;
                        }
                    }
                    return result;
                }

                @Override
                public boolean onDeleted(RPObject object) {
                    LOG.log(Level.FINE, "onDeleted: {0}", object);
                    boolean result = false;
                    for (DeleteListener listener
                            : Lookup.getDefault().lookupAll(DeleteListener.class)) {
                        if (!listener.onDeleted(object)) {
                            result = true;
                        }
                    }
                    Lookup.getDefault().lookup(IWorldManager.class).getWorld()
                            .remove(object.getID());
                    return result;
                }

                @Override
                public void onException(Exception exception,
                        MessageS2CPerception perception) {
                    Lookup.getDefault().lookupAll(ExceptionListener.class).stream().forEach((listener) -> {
                        listener.onException(exception, perception);
                    });
                    LOG.log(Level.SEVERE, getPort(), exception);
                }

                @Override
                public boolean onModifiedAdded(RPObject object, RPObject changes) {
                    LOG.log(Level.FINE, "onModifiedAdded: {0}, {1}",
                            new Object[]{object, changes});
                    boolean result = false;
                    for (ModificationListener listener
                            : Lookup.getDefault().lookupAll(ModificationListener.class)) {
                        if (!listener.onModifiedAdded(object, changes)) {
                            result = true;
                        }
                    }
                    return result;
                }

                @Override
                public boolean onModifiedDeleted(RPObject object, RPObject changes) {
                    LOG.log(Level.FINE, "onModifiedDeleted: {0}, {1}",
                            new Object[]{object, changes});
                    boolean result = false;
                    for (ModificationListener listener
                            : Lookup.getDefault().lookupAll(ModificationListener.class)) {
                        if (!listener.onModifiedDeleted(object, changes)) {
                            result = true;
                        }
                    }
                    return result;
                }

                @Override
                public boolean onMyRPObject(RPObject added, RPObject deleted) {
                    boolean result = true;
                    RPObject.ID id = null;
                    if (added != null) {
                        id = added.getID();
                    }
                    if (deleted != null) {
                        id = deleted.getID();
                    }
                    if (id != null) {
                        RPObject object = Lookup.getDefault().lookup(IWorldManager.class).get(id);
                        if (object != null) {
                            object.applyDifferences(added, deleted);
                            Collection listeners
                                    = Lookup.getDefault().lookupAll(SelfChangeListener.class);
                            for (SelfChangeListener listener : listeners) {
                                if (!listener.onMyRPObject(added, deleted)) {
                                    result = false;
                                    break;
                                }
                            }
                        }
                    } else {
                        // Unchanged.
                        // Do nothing.
                    }
                    return result;
                }

                @Override
                public void onPerceptionBegin(byte type, int timestamp) {
                    Lookup.getDefault().lookupAll(PerceptionListener.class)
                            .stream().forEach((listener) -> {
                                listener.onPerceptionBegin(type, timestamp);
                            });
                }

                @Override
                public void onPerceptionEnd(byte type, int timestamp) {
                    Lookup.getDefault().lookupAll(PerceptionListener.class)
                            .stream().forEach((listener) -> {
                                listener.onPerceptionEnd(type, timestamp);
                            });
                }

                @Override
                public void onSynced() {
                    Lookup.getDefault().lookupAll(SyncListener.class).stream()
                            .forEach((listener) -> {
                                listener.onSynced();
                            });
                }

                @Override
                public void onUnsynced() {
                    Lookup.getDefault().lookupAll(SyncListener.class).stream()
                            .forEach((listener) -> {
                                listener.onUnsynced();
                            });
                }
            });
        }
        if (clientManager == null) {
            createClientManager(gameName != null ? gameName : "jWrestling",
                    version != null ? version : "1.0");
        }
    }

    protected void createClientManager(String name, String gversion) {
        setGameName(name);
        setVersion(gversion);
        setClientManager(new ClientFramework("log4j.properties") {
            @Override
            protected String getGameName() {
                return DefaultClient.this.getGameName();
            }

            @Override
            protected String getVersionNumber() {
                return getVersion();
            }

            @Override
            protected void onPerception(MessageS2CPerception message) {
                try {
                    LOG.log(Level.FINE, "Received perception {0}",
                            message.getPerceptionTimestamp());
                    getPerceptionHandler().apply(message,
                            Lookup.getDefault().lookup(IWorldManager.class).getWorld());
                    int i = message.getPerceptionTimestamp();
                    if (isChat()) {
                        RPAction action = new RPAction();
                        if (i % 50 == 0) {
                            action.put("type", "chat");
                            action.put("text", "Hi!");
                            send(action);
                        } else if (i % 50 == 20) {
                            action.put("type", "chat");
                            action.put("text", "How are you?");
                            send(action);
                        }
                    }
                    if (isShowWorld()) {
                        LOG.log(Level.FINE, "");
                        int j = 0;
                        for (RPObject object
                                : Lookup.getDefault().lookup(IWorldManager.class)
                                .getWorld().values()) {
                            j++;
                            LOG.log(Level.FINE, "{0}. {1}",
                                    new Object[]{j, object});
                        }
                        LOG.log(Level.FINE, "");
                    }
                } catch (Exception e) {
                    LOG.log(Level.SEVERE, null, e);
                }
            }

            @Override
            protected List onTransferREQ(List items) {
                items.stream().forEach((item) -> {
                    item.ack = true;
                });
                return items;
            }

            @Override
            protected void onTransfer(List items) {
                LOG.log(Level.FINE, "Transfering ----");
                items.stream().forEach((item) -> {
                    LOG.log(Level.FINE, item.toString());
                });
            }

            @Override
            protected void onAvailableCharacters(String[] characters) {
                //See onAvailableCharacterDetails
            }

            @Override
            protected void onAvailableCharacterDetails(Map characters) {
                DefaultClient.this.characters = characters;
                // If there are no characters, create one with the specified name automatically
                if (characters.isEmpty() && isCreateDefaultCharacter()) {
                    LOG.log(Level.WARNING,
                            "The requested character is not available, trying "
                            + "to create character {0}", getCharacter());
                    final ClientObject template = new ClientObject();
                    try {
                        final CharacterResult result = createCharacter(getCharacter(),
                                template);
                        if (result.getResult().failed()) {
                            LOG.log(Level.WARNING, result.getResult().getText());
                        }
                    } catch (final BannedAddressException | TimeoutException | InvalidVersionException e) {
                        LOG.log(Level.SEVERE, null, e);
                    }
                    return;
                }
                // Autologin if a valid character was specified.
                if ((getCharacter() != null)
                        && (characters.keySet().contains(getCharacter()))
                        && isCreateDefaultCharacter()) {
                    try {
                        chooseCharacter(getCharacter());
                    } catch (final BannedAddressException | TimeoutException | InvalidVersionException e) {
                        LOG.log(Level.SEVERE, null, e);
                    }
                }
            }

            @Override
            protected void onServerInfo(String[] info) {
                LOG.log(Level.FINE, "Server info");
                for (String info_string : info) {
                    LOG.log(Level.FINE, info_string);
                }
            }

            @Override
            protected void onPreviousLogins(List previousLogins) {
                LOG.log(Level.FINE, "Previous logins");
                previousLogins.stream().forEach((info_string) -> {
                    LOG.log(Level.FINE, info_string);
                });
            }
        });
    }

    private void showLoginDialog() {
        LoginProvider lp = Lookup.getDefault().lookup(LoginProvider.class);
        if (lp != null) {
            lp.displayLoginDialog();
        }
    }

    @Override
    @SuppressWarnings("empty-statement")
    public void run() {
        try {
            if (!Lookup.getDefault().lookup(LoginProvider.class).isAuthenticated()) {
                showLoginDialog();
            }
            getClientManager().connect(getHost(), Integer.parseInt(getPort()));
            LOG.log(Level.FINE, "Logging as: {0} with pass: {1} "
                    + "version: ''{2}''", new Object[]{getUsername(),
                        password, getVersion()});
            setEmail("[email protected]");
            getClientManager().login(getUsername(), password);
            connected = true;
        } catch (ConnectException ex) {
            Lookup.getDefault().lookup(MessageProvider.class).displayWarning(
                    "Unable to connect",
                    "Unable to connect to the server: " + getHost());
            showLoginDialog();
        } catch (IOException ex) {
            LOG.log(Level.SEVERE, null, ex);
            throw new RuntimeException(ex);
        } catch (LoginFailedException e) {
            if (e.getReason().equals(Reasons.USERNAME_WRONG) && isAutoCreation()) {
                try {
                    if (getEmail() == null) {
                        //Prompt user to enter additional information
                        LoginProvider lp = Lookup.getDefault().lookup(LoginProvider.class);
                        if (lp != null) {
                            lp.getEmailFromUser();
                            while (getEmail().trim().isEmpty()) {
                                Thread.sleep(100);
                            }
                        }
                    }
                    if (getEmail() == null) {
                        LOG.severe("Unable to proceed without an email!");
                        throw new RuntimeException("Unable to proceed without an email!");
                    }
                    LOG.log(Level.WARNING,
                            "Creating account and logging in to continue....");
                    AccountResult result = getClientManager().createAccount(getUsername(),
                            password, getEmail());
                    switch (result.getResult()) {
                        case OK_CREATED:
                            getClientManager().login(getUsername(), password);
                            connected = true;
                            break;
                        case FAILED_CREATE_ON_MAIN_INSTEAD:
                            LOG.severe("Account creation is disabled on server!");
                            Lookup.getDefault().lookup(MessageProvider.class).displayError("ERROR",
                                    "Account creation is disabled on server!");
                            break;
                        default:
                            LOG.log(Level.SEVERE, "Unable to create account: {0}",
                                    result.getResult().getText());
                            Lookup.getDefault().lookup(MessageProvider.class).displayError("ERROR",
                                    "Unable to create account: " + result.getResult().getText());
                            break;
                    }
                } catch (LoginFailedException | TimeoutException | BannedAddressException ex) {
                    if (ex instanceof LoginFailedException) {
                        Lookup.getDefault().lookup(MessageProvider.class)
                                .displayWarning("Login Failed!",
                                        ex.getLocalizedMessage()
                                        + "\nMake sure you have verified "
                                        + "your account. Check your provided email.");
                        showLoginDialog();
                    }
                } catch (InvalidVersionException ex) {
                    Lookup.getDefault().lookup(MessageProvider.class)
                            .displayError("Invalid version!",
                                    "Invalid version: " + ex.getVersion()
                                    + " vs. protocol version: " + ex.getProtocolVersion());
                } catch (InterruptedException ex) {
                    Logger.getLogger(DefaultClient.class.getName()).log(Level.SEVERE, null, ex);
                }
            } else {
                Lookup.getDefault().lookup(MessageProvider.class)
                        .displayWarning("Login Failed!", e.getLocalizedMessage());
                showLoginDialog();
            }
        } catch (InvalidVersionException | TimeoutException | BannedAddressException ex) {
            System.exit(1);
        }
        while (isConnected()) {
            getClientManager().loop(0);
            try {
                sleep(100);
            } catch (InterruptedException e) {
                LOG.log(Level.SEVERE, null, e);
                connected = false;
            }
        }
    }

    @Override
    public String getPort() {
        return port;
    }

    @Override
    public String getGameName() {
        return gameName;
    }

    @Override
    public String getVersion() {
        return version;
    }

    @Override
    public marauroa.client.ClientFramework getClientManager() {
        return clientManager;
    }

    @Override
    public void setClientManager(marauroa.client.ClientFramework clientManager) {
        if (this.clientManager != null) {
            LOG.warning("Trying to override ClientFramework!");
        }
        this.clientManager = clientManager;
    }

    @Override
    public PerceptionHandler getPerceptionHandler() {
        return handler;
    }

    @Override
    public void setPort(String port) {
        this.port = port;
    }

    @Override
    public void setGameName(String gameName) {
        this.gameName = gameName;
    }

    @Override
    public void setVersion(String version) {
        LOG.log(Level.FINE, "Version changed from: ''{0}'' to: ''{1}''",
                new Object[]{this.version, version});
        this.version = version;
    }

    @Override
    public void setPerceptionHandler(PerceptionHandler handler) {
        this.handler = handler;
    }

    @Override
    public String getCharacter() {
        return character;
    }

    @Override
    public void setCharacter(String character) {
        this.character = character;
    }

    @Override
    public String getHost() {
        return host;
    }

    @Override
    public void setHost(String host) {
        this.host = host;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public void connect(String host, String username, String password,
            String user_character, String port,
            String game_name, String version)
            throws SocketException {
        setHost(host);
        setUsername(username);
        setPassword(password);
        setCharacter(user_character);
        setPort(port);
        setVersion(version);
        setGameName(game_name);
    }

    @Override
    public Map getCharacters() {
        return characters;
    }

    @Override
    public boolean isCreateDefaultCharacter() {
        return createDefaultCharacter;
    }

    @Override
    public void setCreateDefaultCharacter(boolean createDefaultCharacter) {
        this.createDefaultCharacter = createDefaultCharacter;
    }

    /**
     * @return the connected
     */
    @Override
    public boolean isConnected() {
        return connected;
    }

    @Override
    public boolean chooseCharacter(String character) throws TimeoutException,
            InvalidVersionException, BannedAddressException {
        return getClientManager().chooseCharacter(character);
    }

    /**
     * @return the email
     */
    public String getEmail() {
        return email;
    }

    /**
     * @param email the email to set
     */
    @Override
    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public boolean isAutoCreation() {
        return autocreation;
    }

    @Override
    public void setAutoCreation(boolean autocreation) {
        this.autocreation = autocreation;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy