00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 package com.realtime.crossfire.jxclient.main;
00023
00024 import com.realtime.crossfire.jxclient.account.CharacterModel;
00025 import com.realtime.crossfire.jxclient.commands.BindCommand;
00026 import com.realtime.crossfire.jxclient.commands.ClearCommand;
00027 import com.realtime.crossfire.jxclient.commands.CommandExecutorImpl;
00028 import com.realtime.crossfire.jxclient.commands.Commands;
00029 import com.realtime.crossfire.jxclient.commands.DebugMessagesCommand;
00030 import com.realtime.crossfire.jxclient.commands.ExecCommand;
00031 import com.realtime.crossfire.jxclient.commands.ScreenshotCommand;
00032 import com.realtime.crossfire.jxclient.commands.ScriptCommand;
00033 import com.realtime.crossfire.jxclient.commands.ScriptkillCommand;
00034 import com.realtime.crossfire.jxclient.commands.ScriptkillallCommand;
00035 import com.realtime.crossfire.jxclient.commands.ScriptsCommand;
00036 import com.realtime.crossfire.jxclient.commands.ScripttellCommand;
00037 import com.realtime.crossfire.jxclient.commands.SetCommand;
00038 import com.realtime.crossfire.jxclient.commands.UnbindCommand;
00039 import com.realtime.crossfire.jxclient.faces.AskfaceFaceQueue;
00040 import com.realtime.crossfire.jxclient.faces.DefaultFacesManager;
00041 import com.realtime.crossfire.jxclient.faces.FacesManager;
00042 import com.realtime.crossfire.jxclient.faces.FacesQueue;
00043 import com.realtime.crossfire.jxclient.faces.FileCache;
00044 import com.realtime.crossfire.jxclient.gui.commands.ScreenshotFiles;
00045 import com.realtime.crossfire.jxclient.gui.keybindings.KeyBindings;
00046 import com.realtime.crossfire.jxclient.gui.label.JXCWindowRenderer;
00047 import com.realtime.crossfire.jxclient.gui.label.MouseTracker;
00048 import com.realtime.crossfire.jxclient.gui.label.TooltipManagerImpl;
00049 import com.realtime.crossfire.jxclient.gui.textinput.CommandExecutor;
00050 import com.realtime.crossfire.jxclient.gui.textinput.GUICommandFactory;
00051 import com.realtime.crossfire.jxclient.guistate.GuiState;
00052 import com.realtime.crossfire.jxclient.items.FloorView;
00053 import com.realtime.crossfire.jxclient.items.InventoryComparator;
00054 import com.realtime.crossfire.jxclient.items.InventoryView;
00055 import com.realtime.crossfire.jxclient.items.QuestsView;
00056 import com.realtime.crossfire.jxclient.items.SpellsView;
00057 import com.realtime.crossfire.jxclient.map.MapUpdaterState;
00058 import com.realtime.crossfire.jxclient.mapupdater.CfMapUpdater;
00059 import com.realtime.crossfire.jxclient.metaserver.Metaserver;
00060 import com.realtime.crossfire.jxclient.metaserver.MetaserverModel;
00061 import com.realtime.crossfire.jxclient.metaserver.MetaserverProcessor;
00062 import com.realtime.crossfire.jxclient.queue.CommandQueue;
00063 import com.realtime.crossfire.jxclient.scripts.ScriptManager;
00064 import com.realtime.crossfire.jxclient.server.crossfire.CrossfireServerConnection;
00065 import com.realtime.crossfire.jxclient.server.crossfire.DefaultCrossfireServerConnection;
00066 import com.realtime.crossfire.jxclient.server.crossfire.Model;
00067 import com.realtime.crossfire.jxclient.settings.Filenames;
00068 import com.realtime.crossfire.jxclient.settings.Macros;
00069 import com.realtime.crossfire.jxclient.settings.Settings;
00070 import com.realtime.crossfire.jxclient.settings.options.OptionException;
00071 import com.realtime.crossfire.jxclient.settings.options.OptionManager;
00072 import com.realtime.crossfire.jxclient.settings.options.Pickup;
00073 import com.realtime.crossfire.jxclient.shortcuts.Shortcuts;
00074 import com.realtime.crossfire.jxclient.skin.io.JXCSkinLoader;
00075 import com.realtime.crossfire.jxclient.skin.skin.GuiFactory;
00076 import com.realtime.crossfire.jxclient.sound.MusicWatcher;
00077 import com.realtime.crossfire.jxclient.sound.SoundCheckBoxOption;
00078 import com.realtime.crossfire.jxclient.sound.SoundManager;
00079 import com.realtime.crossfire.jxclient.sound.SoundWatcher;
00080 import com.realtime.crossfire.jxclient.sound.StatsWatcher;
00081 import com.realtime.crossfire.jxclient.stats.ActiveSkillWatcher;
00082 import com.realtime.crossfire.jxclient.stats.PoisonWatcher;
00083 import com.realtime.crossfire.jxclient.util.DebugWriter;
00084 import com.realtime.crossfire.jxclient.window.GuiManager;
00085 import com.realtime.crossfire.jxclient.window.JXCConnection;
00086 import com.realtime.crossfire.jxclient.window.KeyHandler;
00087 import com.realtime.crossfire.jxclient.window.KeybindingsManager;
00088 import java.io.File;
00089 import java.io.FileOutputStream;
00090 import java.io.IOException;
00091 import java.io.OutputStreamWriter;
00092 import java.io.Writer;
00093 import java.lang.reflect.InvocationTargetException;
00094 import java.util.MissingResourceException;
00095 import java.util.ResourceBundle;
00096 import javax.swing.SwingUtilities;
00097 import org.jetbrains.annotations.NotNull;
00098 import org.jetbrains.annotations.Nullable;
00099
00109 public class JXClient {
00110
00115 public static void main(@NotNull final String[] args) {
00116 Thread.currentThread().setName("JXClient:Main");
00117 final String buildNumber = getBuildNumber();
00118 System.out.println("JXClient "+buildNumber+" - Crossfire Java Client");
00119 System.out.println("(C)2005 by Lauwenmark.");
00120 System.out.println("This software is placed under the GPL License");
00121 final Options options = new Options();
00122 options.parse(args);
00123
00124 new JXClient(options, buildNumber);
00125 }
00126
00131 @NotNull
00132 private static String getBuildNumber() {
00133 try {
00134 return ResourceBundle.getBundle("build").getString("build.number");
00135 } catch (final MissingResourceException ignored) {
00136 return "unknown";
00137 }
00138 }
00139
00146 private JXClient(@NotNull final Options options, @NotNull final String buildNumber) {
00147 try {
00148 final Writer debugProtocolOutputStreamWriter = openDebugStream(options.getDebugProtocolFilename());
00149 try {
00150 final Writer debugKeyboardOutputStreamWriter = openDebugStream(options.getDebugKeyboardFilename());
00151 try {
00152 final Writer debugScreenOutputStreamWriter = openDebugStream(options.getDebugScreenFilename());
00153 try {
00154 final Writer debugSoundOutputStreamWriter = openDebugStream(options.getDebugSoundFilename());
00155 try {
00156 final Settings settings = new Settings(Filenames.getSettingsFile());
00157 settings.remove("resolution");
00158 settings.remove("width");
00159 settings.remove("height");
00160 settings.remove("skin");
00161 final OptionManager optionManager = new OptionManager(settings);
00162 final MetaserverModel metaserverModel = new MetaserverModel();
00163 final CharacterModel characterModel = new CharacterModel();
00164 final Model model = new Model();
00165 final CrossfireServerConnection server = new DefaultCrossfireServerConnection(model, debugProtocolOutputStreamWriter == null ? null : new DebugWriter(debugProtocolOutputStreamWriter), "JXClient "+buildNumber);
00166 server.start();
00167 try {
00168 final AskfaceFaceQueue askfaceFaceQueue = new AskfaceFaceQueue(server);
00169 model.setAskfaceFaceQueue(askfaceFaceQueue);
00170 final FacesQueue facesQueue = new FacesQueue(askfaceFaceQueue, new FileCache(Filenames.getOriginalImageCacheDir()), new FileCache(Filenames.getScaledImageCacheDir()), new FileCache(Filenames.getMagicMapImageCacheDir()));
00171 final FacesManager facesManager = new DefaultFacesManager(model.getFaceCache(), facesQueue);
00172 model.setItemsManager(facesManager);
00173 final InventoryView inventoryView = new InventoryView(model.getItemSet(), new InventoryComparator());
00174 final FloorView floorView = new FloorView(model.getItemSet());
00175 final Metaserver metaserver = new Metaserver(Filenames.getMetaserverCacheFile(), metaserverModel);
00176 new MetaserverProcessor(metaserver, model.getGuiStateManager());
00177 final SoundManager soundManager = new SoundManager(model.getGuiStateManager(), debugSoundOutputStreamWriter == null ? null : new DebugWriter(debugSoundOutputStreamWriter));
00178 try {
00179 optionManager.addOption("sound_enabled", "Whether sound is enabled.", new SoundCheckBoxOption(soundManager));
00180 } catch (final OptionException ex) {
00181 throw new AssertionError(ex);
00182 }
00183
00184 final MouseTracker mouseTracker = new MouseTracker(options.isDebugGui());
00185 final JXCWindowRenderer windowRenderer = new JXCWindowRenderer(mouseTracker, server, debugScreenOutputStreamWriter);
00186 new MusicWatcher(server, soundManager);
00187 new SoundWatcher(server, soundManager);
00188 new StatsWatcher(model.getStats(), windowRenderer, server, soundManager);
00189 new PoisonWatcher(model.getStats(), server);
00190 new ActiveSkillWatcher(model.getStats(), server);
00191 final Macros macros = new Macros(server);
00192 final MapUpdaterState mapUpdaterState = new MapUpdaterState(facesManager, model.getGuiStateManager());
00193 new CfMapUpdater(mapUpdaterState, server, facesManager, model.getGuiStateManager());
00194 final SpellsView spellsView = new SpellsView(model.getSpellsManager(), facesManager);
00195 final QuestsView questsView = new QuestsView(model.getQuestsManager(), facesManager);
00196 final CommandQueue commandQueue = new CommandQueue(server, model.getGuiStateManager());
00197 final ScriptManager scriptManager = new ScriptManager(commandQueue, server, model.getStats(), floorView, model.getItemSet(), model.getSpellsManager(), mapUpdaterState, model.getSkillSet());
00198 final Shortcuts shortcuts = new Shortcuts(commandQueue, model.getSpellsManager());
00199
00200 final Exiter exiter = new Exiter();
00201 final JXCWindow[] window = new JXCWindow[1];
00202 SwingUtilities.invokeAndWait(new Runnable() {
00203
00204 @Override
00205 public void run() {
00206 final TooltipManagerImpl tooltipManager = new TooltipManagerImpl();
00207 final Pickup characterPickup;
00208 try {
00209 characterPickup = new Pickup(commandQueue, optionManager);
00210 } catch (final OptionException ex) {
00211 throw new AssertionError(ex);
00212 }
00213 final GuiManagerCommandCallback commandCallback = new GuiManagerCommandCallback(exiter, server);
00214 final ScreenshotFiles screenshotFiles = new ScreenshotFiles();
00215 final Commands commands = new Commands();
00216 final CommandExecutor commandExecutor = new CommandExecutorImpl(commandQueue, commands);
00217 final GUICommandFactory guiCommandFactory = new GUICommandFactory(commandCallback, commandExecutor, macros);
00218 commands.addCommand(new BindCommand(server, commandCallback, guiCommandFactory));
00219 commands.addCommand(new UnbindCommand(commandCallback, server));
00220 commands.addCommand(new ScreenshotCommand(windowRenderer, server, screenshotFiles));
00221 commands.addCommand(new ScriptCommand(scriptManager, server));
00222 commands.addCommand(new ScriptkillCommand(scriptManager, server));
00223 commands.addCommand(new ScriptkillallCommand(scriptManager, server));
00224 commands.addCommand(new ScriptsCommand(scriptManager, server));
00225 commands.addCommand(new ScripttellCommand(scriptManager, server));
00226 commands.addCommand(new ExecCommand(commandCallback, server));
00227 commands.addCommand(new SetCommand(server, optionManager));
00228 commands.addCommand(new ClearCommand(windowRenderer, server));
00229 commands.addCommand(new DebugMessagesCommand(server));
00230 final File keybindingsFile;
00231 try {
00232 keybindingsFile = Filenames.getKeybindingsFile(null, null);
00233 } catch (final IOException ex) {
00234 System.err.println("Cannot read keybindings file: "+ex.getMessage());
00235 exiter.terminate();
00236 return;
00237 }
00238 final KeybindingsManager keybindingsManager = new KeybindingsManager(keybindingsFile, guiCommandFactory);
00239 final JXCConnection connection = new JXCConnection(keybindingsManager, shortcuts, settings, characterPickup, server, model.getGuiStateManager());
00240 final GuiFactory guiFactory = new GuiFactory(guiCommandFactory);
00241 final GuiManager guiManager = new GuiManager(model.getGuiStateManager(), tooltipManager, settings, server, windowRenderer, guiFactory, keybindingsManager, connection);
00242 commandCallback.init(guiManager);
00243 final KeyBindings defaultKeyBindings = new KeyBindings(null, guiCommandFactory);
00244 final JXCSkinLoader jxcSkinLoader = new JXCSkinLoader(model.getItemSet(), inventoryView, floorView, spellsView, model.getSpellsManager(), facesManager, model.getStats(), mapUpdaterState, defaultKeyBindings, optionManager, model.getExperienceTable(), model.getSkillSet(), options.getTileSize(), keybindingsManager, model.getQuestsManager(), questsView);
00245 final SkinLoader skinLoader = new SkinLoader(commandCallback, metaserverModel, options.getResolution(), macros, windowRenderer, server, model.getGuiStateManager(), tooltipManager, commandQueue, jxcSkinLoader, commandExecutor, shortcuts, characterModel, model.getSmoothFaces(), guiCommandFactory);
00246 new FacesTracker(model.getGuiStateManager(), facesManager);
00247 new PlayerNameTracker(model.getGuiStateManager(), connection, model.getItemSet());
00248 new OutputCountTracker(model.getGuiStateManager(), server, commandQueue);
00249 final DefaultKeyHandler defaultKeyHandler = new DefaultKeyHandler(exiter, guiManager, server, model.getGuiStateManager());
00250 final KeyHandler keyHandler = new KeyHandler(debugKeyboardOutputStreamWriter, keybindingsManager, commandQueue, windowRenderer, defaultKeyHandler);
00251 window[0] = new JXCWindow(exiter, server, optionManager, model.getGuiStateManager(), windowRenderer, commandQueue, guiManager, keyHandler, characterModel, connection);
00252 window[0].init(options.getResolution(), options.getSkin(), options.isFullScreen(), skinLoader);
00253 keybindingsManager.loadKeybindings();
00254 final String serverInfo = options.getServer();
00255 if (serverInfo != null) {
00256 model.getGuiStateManager().connect(serverInfo);
00257 } else {
00258 model.getGuiStateManager().changeGUI(JXCWindow.DISABLE_START_GUI ? GuiState.METASERVER : GuiState.START);
00259 }
00260 }
00261
00262 });
00263 exiter.waitForTermination();
00264 SwingUtilities.invokeAndWait(new Runnable() {
00265
00266 @Override
00267 public void run() {
00268 window[0].term();
00269 soundManager.shutdown();
00270 }
00271
00272 });
00273 } finally {
00274 server.stop();
00275 }
00276 } finally {
00277 if (debugSoundOutputStreamWriter != null) {
00278 debugSoundOutputStreamWriter.close();
00279 }
00280 }
00281 } finally {
00282 if (debugScreenOutputStreamWriter != null) {
00283 debugScreenOutputStreamWriter.close();
00284 }
00285 }
00286 } finally {
00287 if (debugKeyboardOutputStreamWriter != null) {
00288 debugKeyboardOutputStreamWriter.close();
00289 }
00290 }
00291 } finally {
00292 if (debugProtocolOutputStreamWriter != null) {
00293 debugProtocolOutputStreamWriter.close();
00294 }
00295 }
00296 } catch (final IOException e) {
00297
00298 e.printStackTrace();
00299 System.exit(1);
00300 throw new AssertionError();
00301 } catch (final InterruptedException e) {
00302
00303 e.printStackTrace();
00304 System.exit(1);
00305 throw new AssertionError();
00306 } catch (final InvocationTargetException e) {
00307
00308 e.printStackTrace();
00309 System.exit(1);
00310 throw new AssertionError();
00311 }
00312
00313 System.exit(0);
00314 }
00315
00321 @Nullable
00322 private static Writer openDebugStream(@Nullable final String filename) {
00323 if (filename == null) {
00324 return null;
00325 }
00326
00327 Writer writer = null;
00328 try {
00329 final FileOutputStream outputStream = new FileOutputStream(filename);
00330 try {
00331 writer = new OutputStreamWriter(outputStream, "UTF-8");
00332 } finally {
00333 if (writer == null) {
00334 outputStream.close();
00335 }
00336 }
00337 } catch (final IOException ex) {
00338 System.err.println(filename+": cannot create output file: "+ex.getMessage());
00339 return null;
00340 }
00341 return writer;
00342 }
00343
00344 }