Skyriis Posted May 9, 2022 Posted May 9, 2022 Hey Guys, I'm working on a mod which allows to store your settings (options.txt) in a cloud service but something seems to cause a weird problem. I'm getting this log message which doesn't really makes sense to me since i'm just copying the values from the options.txt when the Options#save has finished writing and load those values on startup before Options#load once. Has someone an idea what could cause that problem? Quote
Skyriis Posted May 9, 2022 Author Posted May 9, 2022 i've checkt the content of the options.txt before and after sync with the cloud and the only difference is the order of the lines. APIHelper class: Spoiler public static boolean sendSetting(String key, String value) { try { CloseableHttpResponse response = HTTP_CLIENT.execute(authorizedGet(String.format("store/%s/%s/%s", getUserId(), encode(key), encode(value)))); HttpEntity entity = response.getEntity(); JsonReader reader = new JsonReader(new StringReader(EntityUtils.toString(entity))); reader.setLenient(true); JsonObject resultObject = new JsonParser().parse(reader).getAsJsonObject(); String resultValue = getResultValue(resultObject); if (resultValue == null) return false; if (resultValue.startsWith("Login failed")) { if (SettingsLoadingHandler.getLoginKeyFile().delete()) { LogHelper.getLogger().info("Login Token is outdated. Requesting new a new one..."); } AuthenticationWindow window = new AuthenticationWindow(Minecraft.getInstance().getUser().getUuid()); window.show(); return sendSetting(key, value); } return resultValue.equals("Value saved"); } catch (Exception e) { LogHelper.getLogger().trace("Exception while trying to send the update to the cloud.", e); return false; } } public static List<String> loadSettings() { try (CloseableHttpResponse response = HTTP_CLIENT.execute(authorizedGet(String.format("store/%s", getUserId())))) { HttpEntity entity = response.getEntity(); JsonObject resultObject = new JsonParser().parse(EntityUtils.toString(entity)).getAsJsonObject(); String resultValue = getResultValue(resultObject.get("result").getAsJsonObject()); //Exit if no status has been sent if (resultValue == null) return Lists.newArrayList(); if (resultValue.startsWith("Login failed")) { if (SettingsLoadingHandler.getLoginKeyFile().delete()) { LogHelper.getLogger().info("Login Token is outdated. Requesting new a new one..."); } AuthenticationWindow window = new AuthenticationWindow(Minecraft.getInstance().getUser().getUuid()); window.show(); return loadSettings(); } if (!resultValue.equals("Success")) return Lists.newArrayList(); //Exit if no values has been sent if (!resultObject.has("entries")) return Lists.newArrayList(); JsonArray storedSettings = resultObject.get("entries").getAsJsonArray(); ArrayList<String> settings = new ArrayList<>(); storedSettings.forEach(jsonElement -> { if (!jsonElement.isJsonObject()) return; JsonObject jsonObject = jsonElement.getAsJsonObject(); if (!jsonObject.has("key") || !jsonObject.has("value")) return; String settingLine = String.format("%s:%s", jsonObject.get("key").getAsString(), jsonObject.get("value").getAsString()); settings.add(settingLine); }); LogHelper.getLogger().info("Loaded {} settings from Cloud.", settings.size()); return settings; } catch (IOException e) { LogHelper.getLogger().trace("Failed to load settings from Cloud.", e); return Lists.newArrayList(); } } private static String getUserId() { return Minecraft.getInstance().getUser().getUuid(); } @Nullable private static String getResultValue(JsonObject jsonObject) { if (!jsonObject.has("result")) return null; return jsonObject.get("result").getAsString(); } private static String encode(String value) throws UnsupportedEncodingException { return URLEncoder.encode(value, "UTF-8"); } Handler class: Spoiler public class SettingsLoadingHandler { private static boolean initialLoadCompleted = false; @Getter private static final File loginKeyFile = new File(System.getProperty("user.home")) .toPath() .resolve(".minecraft") .resolve("cloudsettings") .resolve("login.key") .toFile(); public static AtomicReference<String> apiToken = new AtomicReference<>(""); private static final ConcurrentHashMap<String, String> settingsMap = new ConcurrentHashMap<>(); private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor(); public static void checkForLoad(Options options) { if (initialLoadCompleted) return; final File optionsFile = ((OptionsAccessor) options).getOptionsFile(); LogHelper.getLogger().info("Requesting for authentication..."); AuthenticationWindow window = new AuthenticationWindow(Minecraft.getInstance().getUser().getUuid()); window.show(); if (apiToken.get().isEmpty()) { LogHelper.getLogger().warn("No API Token found. Canceling Synchronization!"); return; } //Load known configs ApiHelper.loadSettings() .forEach(settingLine -> settingsMap.put(getKeyFromOptionLine(settingLine), settingLine)); if (!optionsFile.exists()) { LogHelper.getLogger().info("No options file found. Trying to create a new one..."); //generate new config file try { Files.write(optionsFile.toPath(), settingsMap.values(), StandardCharsets.UTF_8); } catch (IOException e) { LogHelper.getLogger().trace("Exception while trying to create a new options.txt file.", e); return; } } else { LogHelper.getLogger().info("Options file found. Trying up update settings..."); //write patches into file try { //TODO skip blacklisted settings Files.write(optionsFile.toPath(), settingsMap.values(), StandardCharsets.UTF_8); } catch (IOException e) { LogHelper.getLogger().trace("Exception while updating options.txt file.", e); } } initialLoadCompleted = true; } public static void checkForUpdate(Options options) { if (!initialLoadCompleted) return; //check for update final File optionsFile = ((OptionsAccessor) options).getOptionsFile(); LogHelper.getLogger().info("Checking options.txt for updates..."); try (Stream<String> lines = Files.lines(optionsFile.toPath())) { AtomicInteger added = new AtomicInteger(0); AtomicInteger updated = new AtomicInteger(0); lines.forEach(settingsLine -> { String key = getKeyFromOptionLine(settingsLine); //TODO skip blacklisted settings if (settingsMap.containsKey(key)) { // check for change String value = settingsMap.get(key); if (!value.equals(settingsLine)) { //update updateOption(key, settingsLine); updated.incrementAndGet(); } } else { //Add new entry updateOption(key, settingsLine); added.incrementAndGet(); } }); LogHelper.getLogger().info("Added {} and updated {} options", added.get(), updated.get()); } catch (IOException e) { LogHelper.getLogger().trace("Exception while checking the options.txt file", e); } } private static String getKeyFromOptionLine(String line) { return line.substring(0, line.indexOf(':')); } private static void updateOption(String key, String value) { EXECUTOR.submit(() -> { settingsMap.put(key, value); if (ApiHelper.sendSetting(key, value)) { LogHelper.getLogger().info("Updated {} in Cloud.", key); } else { LogHelper.getLogger().info("Failed to update {} in Cloud.", key); } }); } } Quote
Skyriis Posted May 9, 2022 Author Posted May 9, 2022 Before: Spoiler version:2586 autoJump:true autoSuggestions:true chatColors:true chatLinks:true chatLinksPrompt:true enableVsync:true entityShadows:true forceUnicodeFont:false discrete_mouse_scroll:false invertYMouse:false realmsNotifications:false reducedDebugInfo:false snooperEnabled:false showSubtitles:false touchscreen:false fullscreen:false bobView:true toggleCrouch:false toggleSprint:false mouseSensitivity:0.5 fov:0.0 screenEffectScale:1.0 fovEffectScale:1.0 gamma:0.0 renderDistance:12 entityDistanceScaling:1.0 guiScale:0 particles:0 maxFps:120 difficulty:2 graphicsMode:1 ao:2 biomeBlendRadius:2 renderClouds:true resourcePacks:[] incompatibleResourcePacks:[] lastServer: lang:en_us chatVisibility:0 chatOpacity:1.0 chatLineSpacing:0.0 textBackgroundOpacity:0.5 backgroundForChatOnly:true hideServerAddress:false advancedItemTooltips:false pauseOnLostFocus:true overrideWidth:0 overrideHeight:0 heldItemTooltips:true chatHeightFocused:1.0 chatDelay: 0.0 chatHeightUnfocused:0.44366195797920227 chatScale:1.0 chatWidth:1.0 mipmapLevels:4 useNativeTransport:true mainHand:right attackIndicator:1 narrator:0 tutorialStep:movement mouseWheelSensitivity:1.0 rawMouseInput:true glDebugVerbosity:1 skipMultiplayerWarning:false hideMatchedNames:true joinedFirstServer:false syncChunkWrites:true key_key.attack:key.mouse.left key_key.use:key.mouse.right key_key.forward:key.keyboard.w key_key.left:key.keyboard.a key_key.back:key.keyboard.s key_key.right:key.keyboard.d key_key.jump:key.keyboard.space key_key.sneak:key.keyboard.left.shift key_key.sprint:key.keyboard.left.control key_key.drop:key.keyboard.q key_key.inventory:key.keyboard.e key_key.chat:key.keyboard.t key_key.playerlist:key.keyboard.tab key_key.pickItem:key.mouse.middle key_key.command:key.keyboard.slash key_key.socialInteractions:key.keyboard.p key_key.screenshot:key.keyboard.f2 key_key.togglePerspective:key.keyboard.f5 key_key.smoothCamera:key.keyboard.unknown key_key.fullscreen:key.keyboard.f11 key_key.spectatorOutlines:key.keyboard.unknown key_key.swapOffhand:key.keyboard.f key_key.saveToolbarActivator:key.keyboard.c key_key.loadToolbarActivator:key.keyboard.x key_key.advancements:key.keyboard.l key_key.hotbar.1:key.keyboard.1 key_key.hotbar.2:key.keyboard.2 key_key.hotbar.3:key.keyboard.3 key_key.hotbar.4:key.keyboard.4 key_key.hotbar.5:key.keyboard.5 key_key.hotbar.6:key.keyboard.6 key_key.hotbar.7:key.keyboard.7 key_key.hotbar.8:key.keyboard.8 key_key.hotbar.9:key.keyboard.9 soundCategory_master:1.0 soundCategory_music:1.0 soundCategory_record:1.0 soundCategory_weather:1.0 soundCategory_block:1.0 soundCategory_hostile:1.0 soundCategory_neutral:1.0 soundCategory_player:1.0 soundCategory_ambient:1.0 soundCategory_voice:1.0 modelPart_cape:true modelPart_jacket:true modelPart_left_sleeve:true modelPart_right_sleeve:true modelPart_left_pants_leg:true modelPart_right_pants_leg:true modelPart_hat:true After: Spoiler tutorialStep:tutorialStep:movement key_key.pickItem:key_key.pickItem:key.mouse.middle chatDelay:chatDelay:+0.0 chatLinksPrompt:chatLinksPrompt:true key_key.playerlist:key_key.playerlist:key.keyboard.tab textBackgroundOpacity:textBackgroundOpacity:0.5 useNativeTransport:useNativeTransport:true chatScale:chatScale:1.0 enableVsync:enableVsync:true modelPart_cape:modelPart_cape:true particles:particles:0 toggleSprint:toggleSprint:false mouseSensitivity:mouseSensitivity:0.5 key_key.advancements:key_key.advancements:key.keyboard.l advancedItemTooltips:advancedItemTooltips:false key_key.swapOffhand:key_key.swapOffhand:key.keyboard.f modelPart_hat:modelPart_hat:true touchscreen:touchscreen:false entityShadows:entityShadows:true incompatibleResourcePacks:incompatibleResourcePacks:[] version:version:2586 ao:ao:2 mipmapLevels:mipmapLevels:4 hideMatchedNames:hideMatchedNames:true key_key.hotbar.5:key_key.hotbar.5:key.keyboard.5 key_key.hotbar.6:key_key.hotbar.6:key.keyboard.6 key_key.hotbar.7:key_key.hotbar.7:key.keyboard.7 key_key.hotbar.8:key_key.hotbar.8:key.keyboard.8 fullscreen:fullscreen:false renderDistance:renderDistance:12 key_key.hotbar.1:key_key.hotbar.1:key.keyboard.1 key_key.hotbar.2:key_key.hotbar.2:key.keyboard.2 key_key.hotbar.3:key_key.hotbar.3:key.keyboard.3 discrete_mouse_scroll:discrete_mouse_scroll:false key_key.hotbar.4:key_key.hotbar.4:key.keyboard.4 modelPart_left_sleeve:modelPart_left_sleeve:true soundCategory_record:soundCategory_record:1.0 key_key.sprint:key_key.sprint:key.keyboard.left.control key_key.forward:key_key.forward:key.keyboard.w skipMultiplayerWarning:skipMultiplayerWarning:false key_key.drop:key_key.drop:key.keyboard.q key_key.back:key_key.back:key.keyboard.s soundCategory_music:soundCategory_music:1.0 toggleCrouch:toggleCrouch:false key_key.attack:key_key.attack:key.mouse.left soundCategory_master:soundCategory_master:1.0 key_key.use:key_key.use:key.mouse.right chatWidth:chatWidth:1.0 key_key.saveToolbarActivator:key_key.saveToolbarActivator:key.keyboard.c chatHeightUnfocused:chatHeightUnfocused:0.44366195797920227 realmsNotifications:realmsNotifications:false showSubtitles:showSubtitles:false key_key.smoothCamera:key_key.smoothCamera:key.keyboard.unknown backgroundForChatOnly:backgroundForChatOnly:true chatHeightFocused:chatHeightFocused:1.0 glDebugVerbosity:glDebugVerbosity:1 hideServerAddress:hideServerAddress:false modelPart_right_pants_leg:modelPart_right_pants_leg:true maxFps:maxFps:120 renderClouds:renderClouds:true guiScale:guiScale:0 forceUnicodeFont:forceUnicodeFont:false biomeBlendRadius:biomeBlendRadius:2 entityDistanceScaling:entityDistanceScaling:1.0 chatOpacity:chatOpacity:1.0 gamma:gamma:0.0 key_key.right:key_key.right:key.keyboard.d key_key.jump:key_key.jump:key.keyboard.space resourcePacks:resourcePacks:[] modelPart_left_pants_leg:modelPart_left_pants_leg:true chatLineSpacing:chatLineSpacing:0.0 chatColors:chatColors:true soundCategory_weather:soundCategory_weather:1.0 mouseWheelSensitivity:mouseWheelSensitivity:1.0 key_key.sneak:key_key.sneak:key.keyboard.left.shift modelPart_jacket:modelPart_jacket:true heldItemTooltips:heldItemTooltips:true key_key.spectatorOutlines:key_key.spectatorOutlines:key.keyboard.unknown screenEffectScale:screenEffectScale:1.0 autoSuggestions:autoSuggestions:true soundCategory_player:soundCategory_player:1.0 key_key.left:key_key.left:key.keyboard.a graphicsMode:graphicsMode:1 difficulty:difficulty:2 mainHand:mainHand:right lastServer:lastServer: overrideHeight:overrideHeight:0 chatLinks:chatLinks:true autoJump:autoJump:true soundCategory_block:soundCategory_block:1.0 invertYMouse:invertYMouse:false reducedDebugInfo:reducedDebugInfo:false modelPart_right_sleeve:modelPart_right_sleeve:true key_key.command:key_key.command:key.keyboard.slash key_key.screenshot:key_key.screenshot:key.keyboard.f2 fov:fov:0.0 key_key.hotbar.9:key_key.hotbar.9:key.keyboard.9 soundCategory_neutral:soundCategory_neutral:1.0 rawMouseInput:rawMouseInput:true attackIndicator:attackIndicator:1 snooperEnabled:snooperEnabled:false key_key.togglePerspective:key_key.togglePerspective:key.keyboard.f5 soundCategory_ambient:soundCategory_ambient:1.0 pauseOnLostFocus:pauseOnLostFocus:true lang:lang:en_us key_key.chat:key_key.chat:key.keyboard.t bobView:bobView:true soundCategory_hostile:soundCategory_hostile:1.0 fovEffectScale:fovEffectScale:1.0 overrideWidth:overrideWidth:0 syncChunkWrites:syncChunkWrites:true key_key.inventory:key_key.inventory:key.keyboard.e key_key.fullscreen:key_key.fullscreen:key.keyboard.f11 key_key.loadToolbarActivator:key_key.loadToolbarActivator:key.keyboard.x chatVisibility:chatVisibility:0 narrator:narrator:0 joinedFirstServer:joinedFirstServer:false soundCategory_voice:soundCategory_voice:1.0 key_key.socialInteractions:key_key.socialInteractions:key.keyboard.p Quote
Skyriis Posted May 9, 2022 Author Posted May 9, 2022 2 hours ago, diesieben07 said: The files are not the same. Oh lol, you're right. Well, thank you Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.