diff --git a/.gitignore b/.gitignore index 2b2ae770ee..d29c7c870b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ syntax: glob Mage.Client/*.dck Mage.Client/db Mage.Client/gamelogs +Mage.Client/gamelogsJson Mage.Client/*.log Mage.Client/plugins/images Mage.Client/plugins/plugin.data diff --git a/Mage.Client/src/main/java/mage/client/SessionHandler.java b/Mage.Client/src/main/java/mage/client/SessionHandler.java index 97a183c3ca..8524b125da 100644 --- a/Mage.Client/src/main/java/mage/client/SessionHandler.java +++ b/Mage.Client/src/main/java/mage/client/SessionHandler.java @@ -1,7 +1,9 @@ package mage.client; +import java.util.*; import mage.cards.decks.DeckCardLists; import mage.client.chat.LocalCommands; +import mage.client.dialog.PreferencesDialog; import mage.constants.ManaType; import mage.constants.PlayerAction; import mage.game.match.MatchOptions; @@ -14,8 +16,6 @@ import mage.remote.Session; import mage.remote.SessionImpl; import mage.view.*; -import java.util.*; - /** * Created by IGOUDT on 15-9-2016. */ @@ -26,8 +26,9 @@ public final class SessionHandler { public static void startSession(MageFrame mageFrame) { session = new SessionImpl(mageFrame); + session.setJsonLogActive("true".equals(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_LOG_AUTO_SAVE, "true"))); } - + public static void ping() { session.ping(); } @@ -322,7 +323,7 @@ public final class SessionHandler { } public static void updateDeck(UUID tableId, DeckCardLists deckCardLists) { - session.updateDeck(tableId, deckCardLists); + session.updateDeck(tableId, deckCardLists); } public static boolean emailAuthToken(Connection connection) { @@ -330,10 +331,10 @@ public final class SessionHandler { } public static boolean resetPassword(Connection connection) { - return session.resetPassword(connection); + return session.resetPassword(connection); } public static boolean register(Connection connection) { - return session.register(connection); + return session.register(connection); } } diff --git a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form index 1058a968e7..fc3c45de37 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form @@ -25,17 +25,18 @@ - - - + + + + + + + + + - - - - - @@ -94,10 +95,10 @@ - + - + @@ -121,9 +122,10 @@ - - - + + + + @@ -134,7 +136,10 @@ - + + + + @@ -143,7 +148,7 @@ - + @@ -153,13 +158,23 @@ - + + + + + + + + + + + @@ -221,7 +236,7 @@ - + @@ -252,7 +267,7 @@ - + @@ -289,7 +304,7 @@ - + @@ -4318,7 +4333,7 @@ - + @@ -5743,7 +5758,7 @@ - + @@ -6008,7 +6023,7 @@ - + diff --git a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java index 869694af4f..9412a25778 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java @@ -65,12 +65,11 @@ import javax.swing.filechooser.FileFilter; import mage.client.MageFrame; import mage.client.SessionHandler; import mage.client.components.KeyBindButton; +import static mage.client.constants.Constants.BATTLEFIELD_FEEDBACK_COLORIZING_MODE_ENABLE_BY_MULTICOLOR; import mage.client.util.Config; import mage.client.util.GUISizeHelper; import mage.client.util.ImageHelper; import mage.client.util.gui.BufferedImageBuilder; - -import static mage.client.constants.Constants.BATTLEFIELD_FEEDBACK_COLORIZING_MODE_ENABLE_BY_MULTICOLOR; import static mage.constants.Constants.DEFAULT_AVATAR_ID; import static mage.constants.Constants.MAX_AVATAR_ID; import static mage.constants.Constants.MIN_AVATAR_ID; @@ -79,6 +78,7 @@ import mage.players.net.UserGroup; import mage.players.net.UserSkipPrioritySteps; import mage.remote.Connection; import mage.remote.Connection.ProxyType; +import mage.remote.Session; import mage.view.UserRequestMessage; import org.apache.log4j.Logger; @@ -122,6 +122,7 @@ public class PreferencesDialog extends javax.swing.JDialog { public static final String KEY_GAME_LOG_AUTO_SAVE = "gameLogAutoSave"; public static final String KEY_DRAFT_LOG_AUTO_SAVE = "draftLogAutoSave"; + public static final String KEY_JSON_GAME_LOG_AUTO_SAVE = "gameLogJsonAutoSave"; public static final String KEY_CARD_IMAGES_USE_DEFAULT = "cardImagesUseDefault"; public static final String KEY_CARD_IMAGES_PATH = "cardImagesPath"; @@ -406,6 +407,7 @@ public class PreferencesDialog extends javax.swing.JDialog { main_gamelog = new javax.swing.JPanel(); cbGameLogAutoSave = new javax.swing.JCheckBox(); cbDraftLogAutoSave = new javax.swing.JCheckBox(); + cbGameJsonLogAutoSave = new javax.swing.JCheckBox(); main_card = new javax.swing.JPanel(); showCardName = new javax.swing.JCheckBox(); tooltipDelayLabel = new javax.swing.JLabel(); @@ -600,7 +602,7 @@ public class PreferencesDialog extends javax.swing.JDialog { main_gamelog.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Game log")); cbGameLogAutoSave.setSelected(true); - cbGameLogAutoSave.setText("Auto save game logs (to \"../Mage.Client/gamelogs/\" directory)"); + cbGameLogAutoSave.setText("Save game logs (to \"../Mage.Client/gamelogs/\" directory)"); cbGameLogAutoSave.setToolTipText("The logs of all your games will be saved to the mentioned folder if this option is switched on."); cbGameLogAutoSave.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -609,7 +611,7 @@ public class PreferencesDialog extends javax.swing.JDialog { }); cbDraftLogAutoSave.setSelected(true); - cbDraftLogAutoSave.setText("Auto save draft logs (to \"../Mage.Client/gamelogs/\" directory)"); + cbDraftLogAutoSave.setText("Save draft logs (to \"../Mage.Client/gamelogs/\" directory)"); cbDraftLogAutoSave.setToolTipText("The logs of all your games will be saved to the mentioned folder if this option is switched on."); cbDraftLogAutoSave.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -617,15 +619,25 @@ public class PreferencesDialog extends javax.swing.JDialog { } }); + cbGameJsonLogAutoSave.setSelected(true); + cbGameJsonLogAutoSave.setText("Save JSON game logs (to \"../Mage.Client/gamelogsJson/\" directory)"); + cbGameJsonLogAutoSave.setToolTipText("The JSON logs of all your games will be saved to the mentioned folder if this option is switched on."); + cbGameJsonLogAutoSave.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cbGameJsonLogAutoSaveActionPerformed(evt); + } + }); + org.jdesktop.layout.GroupLayout main_gamelogLayout = new org.jdesktop.layout.GroupLayout(main_gamelog); main_gamelog.setLayout(main_gamelogLayout); main_gamelogLayout.setHorizontalGroup( main_gamelogLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(main_gamelogLayout.createSequentialGroup() .addContainerGap() - .add(main_gamelogLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false) - .add(cbDraftLogAutoSave, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .add(cbGameLogAutoSave, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .add(main_gamelogLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(cbDraftLogAutoSave) + .add(cbGameJsonLogAutoSave) + .add(cbGameLogAutoSave, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 505, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); main_gamelogLayout.setVerticalGroup( @@ -633,7 +645,10 @@ public class PreferencesDialog extends javax.swing.JDialog { .add(main_gamelogLayout.createSequentialGroup() .add(cbGameLogAutoSave) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) - .add(cbDraftLogAutoSave)) + .add(cbDraftLogAutoSave) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(cbGameJsonLogAutoSave) + .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); main_card.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Card")); @@ -785,7 +800,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .add(cbShowStormCounter, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(cbAskMoveToGraveOrder, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(showAbilityPickerForced, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addContainerGap(255, Short.MAX_VALUE)) + .addContainerGap(177, Short.MAX_VALUE)) ); main_gameLayout.setVerticalGroup( main_gameLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) @@ -860,10 +875,10 @@ public class PreferencesDialog extends javax.swing.JDialog { .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(main_game, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) - .add(main_gamelog, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .add(main_gamelog, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 107, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(main_battlefield, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) - .addContainerGap(154, Short.MAX_VALUE)) + .addContainerGap(121, Short.MAX_VALUE)) ); main_card.getAccessibleContext().setAccessibleName("Game panel"); @@ -1582,7 +1597,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(cbNumberOfDownloadThreads, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 153, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))) .add(cbUseDefaultImageFolder)) - .add(0, 270, Short.MAX_VALUE))) + .add(0, 308, Short.MAX_VALUE))) .addContainerGap()) ); panelCardImagesLayout.setVerticalGroup( @@ -2387,7 +2402,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .add(connection_serversLayout.createSequentialGroup() .add(141, 141, 141) .add(jLabel17))) - .addContainerGap(198, Short.MAX_VALUE)) + .addContainerGap(201, Short.MAX_VALUE)) ); connection_serversLayout.setVerticalGroup( connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) @@ -2626,7 +2641,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .add(keyEndStep, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .add(keyToggleRecordMacro, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) - .add(controlsDescriptionLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 441, Short.MAX_VALUE))) + .add(controlsDescriptionLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 478, Short.MAX_VALUE))) .addContainerGap()) ); tabControlsLayout.setVerticalGroup( @@ -2708,16 +2723,16 @@ public class PreferencesDialog extends javax.swing.JDialog { getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup() - .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .add(saveButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 100, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) - .add(exitButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 100, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) - .add(6, 6, 6)) .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup() .addContainerGap() - .add(tabsPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addContainerGap()) + .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING) + .add(org.jdesktop.layout.GroupLayout.LEADING, tabsPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .add(layout.createSequentialGroup() + .add(0, 0, Short.MAX_VALUE) + .add(saveButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 100, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(exitButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 100, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))) + .add(6, 6, 6)) ); layout.setVerticalGroup( layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) @@ -2749,6 +2764,7 @@ public class PreferencesDialog extends javax.swing.JDialog { save(prefs, dialog.cbAskMoveToGraveOrder, KEY_GAME_ASK_MOVE_TO_GRAVE_ORDER, "true", "false", UPDATE_CACHE_POLICY); save(prefs, dialog.cbGameLogAutoSave, KEY_GAME_LOG_AUTO_SAVE, "true", "false", UPDATE_CACHE_POLICY); save(prefs, dialog.cbDraftLogAutoSave, KEY_DRAFT_LOG_AUTO_SAVE, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbGameJsonLogAutoSave, KEY_JSON_GAME_LOG_AUTO_SAVE, "true", "false", UPDATE_CACHE_POLICY); String paramName = KEY_BATTLEFIELD_FEEDBACK_COLORIZING_MODE; int paramValue = dialog.cbBattlefieldFeedbackColorizingMode.getSelectedIndex(); @@ -3194,9 +3210,16 @@ public class PreferencesDialog extends javax.swing.JDialog { }//GEN-LAST:event_showFullImagePathActionPerformed private void cbBattlefieldFeedbackColorizingModeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbBattlefieldFeedbackColorizingModeActionPerformed - + }//GEN-LAST:event_cbBattlefieldFeedbackColorizingModeActionPerformed + private void cbGameJsonLogAutoSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbGameJsonLogAutoSaveActionPerformed + Session session = SessionHandler.getSession(); + if (session != null) { + session.setJsonLogActive(cbGameJsonLogAutoSave.isSelected()); + } + }//GEN-LAST:event_cbGameJsonLogAutoSaveActionPerformed + private void showProxySettings() { Connection.ProxyType proxyType = (Connection.ProxyType) cbProxyType.getSelectedItem(); switch (proxyType) { @@ -3311,6 +3334,7 @@ public class PreferencesDialog extends javax.swing.JDialog { load(prefs, dialog.cbGameLogAutoSave, KEY_GAME_LOG_AUTO_SAVE, "true"); load(prefs, dialog.cbDraftLogAutoSave, KEY_DRAFT_LOG_AUTO_SAVE, "true"); + load(prefs, dialog.cbGameJsonLogAutoSave, KEY_JSON_GAME_LOG_AUTO_SAVE, "true", "false"); String feedbackParam = ""; try { @@ -3865,6 +3889,7 @@ public class PreferencesDialog extends javax.swing.JDialog { private javax.swing.JCheckBox cbEnableGameSounds; private javax.swing.JCheckBox cbEnableOtherSounds; private javax.swing.JCheckBox cbEnableSkipButtonsSounds; + private javax.swing.JCheckBox cbGameJsonLogAutoSave; private javax.swing.JCheckBox cbGameLogAutoSave; private javax.swing.JComboBox cbNumberOfDownloadThreads; private javax.swing.JCheckBox cbPassPriorityActivation; diff --git a/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java b/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java index 758758e7ae..8dc603a1f2 100644 --- a/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java +++ b/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java @@ -190,16 +190,15 @@ public class CallbackClientImpl implements CallbackClient { break; } case GAME_OVER: { - GamePanel panel = MageFrame.getGame(callback.getObjectId()); - if (panel != null) { - appendJsonEvent("GAME_OVER", callback.getObjectId(), callback.getData()); - ActionData actionData = appendJsonEvent("GAME_OVER", callback.getObjectId(), callback.getData()); - String logFileName = "game-" + actionData.gameId + ".json"; - - S3Uploader.upload(logFileName, actionData.gameId.toString()); - + Session session = SessionHandler.getSession(); + if (session.isJsonLogActive()) { + appendJsonEvent("GAME_OVER", callback.getObjectId(), callback.getData()); + ActionData actionData = appendJsonEvent("GAME_OVER", callback.getObjectId(), callback.getData()); + String logFileName = "game-" + actionData.gameId + ".json"; + S3Uploader.upload(logFileName, actionData.gameId.toString()); + } panel.endMessage((String) callback.getData(), callback.getMessageId()); } break; @@ -408,10 +407,13 @@ public class CallbackClientImpl implements CallbackClient { private ActionData appendJsonEvent(String name, UUID gameId, Object value) { Session session = SessionHandler.getSession(); - ActionData actionData = new ActionData(name, gameId); - actionData.value = value; - session.appendJsonLog(actionData); - return actionData; + if (session.isJsonLogActive()) { + ActionData actionData = new ActionData(name, gameId); + actionData.value = value; + session.appendJsonLog(actionData); + return actionData; + } + return null; } private void createChatStartMessage(ChatPanelBasic chatPanel) { diff --git a/Mage.Common/src/main/java/mage/remote/SessionImpl.java b/Mage.Common/src/main/java/mage/remote/SessionImpl.java index 318e628f38..6d766b7398 100644 --- a/Mage.Common/src/main/java/mage/remote/SessionImpl.java +++ b/Mage.Common/src/main/java/mage/remote/SessionImpl.java @@ -28,6 +28,7 @@ package mage.remote; import java.io.BufferedWriter; +import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; @@ -89,6 +90,7 @@ public class SessionImpl implements Session { private static boolean debugMode = false; private boolean canceled = false; + private boolean jsonLogActive = false; static { debugMode = System.getProperty("debug.mage") != null; @@ -892,12 +894,20 @@ public class SessionImpl implements Session { @Override public void appendJsonLog(ActionData actionData) { - actionData.sessionId = getSessionId(); - String logFileName = "game-" + actionData.gameId + ".json"; - try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(logFileName, true)))) { - out.println(actionData.toJson()); - } catch (IOException e) { - System.err.println(e); + if (isJsonLogActive()) { + String dir = "gamelogsJson"; + File saveDir = new File(dir); + //Existence check + if (!saveDir.exists()) { + saveDir.mkdirs(); + } + actionData.sessionId = getSessionId(); + String logFileName = dir + File.separator + "game-" + actionData.gameId + ".json"; + try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(logFileName, true)))) { + out.println(actionData.toJson()); + } catch (IOException e) { + logger.error("Cant write JSON game log file - " + logFileName, e); + } } } @@ -1308,7 +1318,7 @@ public class SessionImpl implements Session { if (isConnected()) { ActionData actionData = new ActionData("SEND_PLAYER_ACTION", gameId, getSessionId()); - actionData.value = data; + actionData.value = passPriorityAction + (data != null ? " " + data.toString() : ""); appendJsonLog(actionData); server.sendPlayerAction(passPriorityAction, gameId, sessionId, data); @@ -1634,6 +1644,16 @@ public class SessionImpl implements Session { } } + @Override + public boolean isJsonLogActive() { + return jsonLogActive; + } + + @Override + public void setJsonLogActive(boolean jsonLogActive) { + this.jsonLogActive = jsonLogActive; + } + } class MageAuthenticator extends Authenticator { diff --git a/Mage.Common/src/main/java/mage/remote/interfaces/ClientData.java b/Mage.Common/src/main/java/mage/remote/interfaces/ClientData.java index 741b69b1b5..b8b29df27d 100644 --- a/Mage.Common/src/main/java/mage/remote/interfaces/ClientData.java +++ b/Mage.Common/src/main/java/mage/remote/interfaces/ClientData.java @@ -37,4 +37,8 @@ public interface ClientData { String getUserName(); boolean updatePreferencesForServer(UserData userData); + + void setJsonLogActive(boolean active); + + boolean isJsonLogActive(); }