Home Manager module for Ninjabrain-Bot w/ Stylix support
mcsr minecraft ninjabrain-bot
at trunk 477 lines 14 kB view raw
1{ self, inputs }: 2{ 3 config, 4 pkgs, 5 lib, 6 ... 7}: 8let 9 # values from https://javadoc.io/doc/com.1stleg/jnativehook/2.0.2/constant-values.html 10 MODIFIER_MASKS = { 11 ALT_L = 8; 12 ALT_R = 128; 13 CTRL_L = 2; 14 CTRL_R = 32; 15 META_L = 4; 16 META_R = 64; 17 SHIFT_L = 1; 18 SHIFT_R = 16; 19 }; 20 LOCATION_VALUES = { 21 UNKNOWN = 0; 22 STANDARD = 1; 23 RIGHT = 3; 24 NUMPAD = 4; 25 LEFT = 2; 26 }; 27 28 cfg = config.programs.ninjabrain-bot; 29 30 # filters null & expands hotkeys into two attributes 31 hotkeyExpandedSettings = 32 let 33 expandHotkey = name: value: { 34 # reference: https://github.com/Ninjabrain1/Ninjabrain-Bot/blob/34117a46d700610aab0237f73bd9418a09940e5f/src/main/java/ninjabrainbot/io/preferences/HotkeyPreference.java#L64 35 # equivalent to (key | location << 16) 36 "${name}_code" = builtins.bitOr value.key (LOCATION_VALUES.${value.location} * 65536); 37 "${name}_modifier" = value.modifiers; 38 }; 39 in 40 lib.concatMapAttrs ( 41 name: value: 42 if builtins.isNull value then 43 { } 44 else if (builtins.isAttrs value) && (value ? "key") then 45 expandHotkey name value 46 else 47 { ${name} = value; } 48 ) cfg.settings; 49 50 mkNinbLines = 51 settings: 52 let 53 valueString = 54 value: 55 if builtins.isBool value then (if value then "true" else "false") else builtins.toString value; 56 in 57 lib.concatLines ( 58 lib.mapAttrsToList (k: v: "<entry key=\"${k}\" value=\"${valueString v}\"/>") settings 59 ); 60 61 mkStylixTheme = 62 lib.pipe 63 (pkgs.runCommand "generate-ninb-theme" { } '' 64 cat ${config.lib.stylix.colors.outPath} | ${ 65 lib.getExe' self.packages.${pkgs.stdenv.hostPlatform.system}.serializer "serializer" 66 } > $out 67 '') 68 [ 69 builtins.readFile 70 lib.escapeXML 71 ]; 72 73 mkEnumOption = 74 enum: default: 75 let 76 big_enum = (builtins.length enum) > 2; 77 in 78 lib.mkOption { 79 inherit default; 80 description = '' 81 When translated to XML, this option is turned into an integer, 82 with `0` being "${builtins.head enum}",${ 83 lib.optionalString (!big_enum) " and" 84 } `1` being "${builtins.elemAt enum 1}"${lib.optionalString big_enum ", and so on"}. 85 ''; 86 type = lib.types.enum enum; 87 apply = value: lib.lists.findFirstIndex (x: x == value) 0 enum; 88 }; 89 90 mkHotkeyOption = 91 name: 92 lib.mkOption { 93 description = "Hotkey for ${name}"; 94 default = null; 95 type = lib.types.nullOr ( 96 lib.types.submodule { 97 options = { 98 modifiers = lib.mkOption { 99 type = lib.types.listOf ( 100 lib.types.enum [ 101 "ALT_L" 102 "ALT_R" 103 "CTRL_L" 104 "CTRL_R" 105 "META_L" 106 "META_R" 107 "SHIFT_L" 108 "SHIFT_R" 109 ] 110 ); 111 default = [ ]; 112 example = [ "CTRL_L" ]; 113 description = "List of modifier keys."; 114 # bitwise or of all the values summed together 115 apply = list: builtins.foldl' (acc: element: builtins.bitOr acc MODIFIER_MASKS.${element}) 0 list; 116 }; 117 location = lib.mkOption { 118 type = lib.types.enum [ 119 "STANDARD" 120 "RIGHT" 121 "NUMPAD" 122 "LEFT" 123 "UNKNOWN" 124 ]; 125 default = "UNKNOWN"; 126 description = '' 127 The location of the key. 128 129 If you want to refer to '0' on your numpad, you would set this value to NUMPAD. Most of the time, the default is what you want. 130 ''; 131 }; 132 key = lib.mkOption { 133 type = lib.types.int; 134 example = 19; 135 description = '' 136 Integer keycode. 137 138 These can be obtained by finding the key from the list of constants at https://javadoc.io/doc/com.1stleg/jnativehook/2.0.2/constant-values.html. 139 140 For example, the key "A" corresponds to the field "VC_A", which has the value 30, so you should set this value to 30. 141 142 The key "R" would correspond to "VC_R", F6 to "VC_F6", etc. 143 ''; 144 }; 145 }; 146 } 147 ); 148 }; 149in 150{ 151 options.programs.ninjabrain-bot = { 152 enable = lib.mkEnableOption "ninjabrain-bot"; 153 package = 154 lib.mkPackageOption inputs.mcsr-nixos.packages.${pkgs.stdenv.hostPlatform.system} "ninjabrain-bot" 155 { 156 extraDescription = "Default's to uku's ninjabrain-bot package. Setting to null will skip installing the package."; 157 nullable = true; 158 pkgsText = "mcsrPkgs"; 159 }; 160 161 stylix = lib.mkEnableOption "style ninjabrain-bot with stylix"; 162 163 force = lib.mkOption { 164 type = lib.types.bool; 165 description = "Ninjabrain-bot will wipe the symlink to the nix store in it's config file, so this option exists to always force and overwrite the file back into place."; 166 default = false; 167 }; 168 169 additional_custom_themes = lib.mkOption { 170 type = lib.types.listOf ( 171 lib.types.submodule { 172 options = { 173 name = lib.mkOption { 174 type = lib.types.strMatching "^[^.]*$"; 175 description = "Name of the theme. Must not contain a `.`"; 176 }; 177 value = lib.mkOption { 178 type = lib.types.strMatching "^[^.]*$"; 179 description = '' 180 Theme colours encoded string. Find by creating the theme in the GUI then copying it from the preferences file. 181 Must not contain a `.`. 182 ''; 183 }; 184 }; 185 } 186 ); 187 default = [ ]; 188 description = '' 189 List of custom themes. 190 Obtaining a theme string is quite hard and it's recommended you create one in the GUI first then copying it manually from the preferences file. 191 Ninjabrain-bot separates themes by a `.`. 192 ''; 193 }; 194 195 settings = lib.mkOption { 196 default = { }; 197 description = "Settings for ninjabrain-bot"; 198 type = lib.types.submodule { 199 options = { 200 theme = lib.mkOption { 201 type = lib.types.int; 202 description = '' 203 Theme index. 204 Positive values refer to the builtin themes that come with ninjabrain bot. 205 Negative values refer to custom themes, backwards. `-1` would refer to the first custom theme, `-2` the second, and so on. 206 ''; 207 default = if cfg.stylix then -1 else 1; 208 }; 209 210 custom_themes = lib.mkOption { 211 type = lib.types.str; 212 internal = true; 213 visible = false; 214 default = lib.join "." ( 215 (map (x: x.value) cfg.additional_custom_themes) ++ (lib.optional cfg.stylix mkStylixTheme) 216 ); 217 }; 218 219 custom_themes_names = lib.mkOption { 220 type = lib.types.str; 221 internal = true; 222 visible = false; 223 default = lib.join "." ( 224 (map (x: x.name) cfg.additional_custom_themes) ++ (lib.optional cfg.stylix "Stylix") 225 ); 226 }; 227 228 settings_version = lib.mkOption { 229 type = lib.types.ints.positive; 230 default = 3; 231 internal = true; 232 visible = false; 233 }; 234 235 window_x = lib.mkOption { 236 type = lib.types.int; 237 default = 100; 238 description = "Window X position"; 239 }; 240 241 window_y = lib.mkOption { 242 type = lib.types.int; 243 default = 100; 244 description = "Window Y position"; 245 }; 246 247 sensitivity_manual = lib.mkOption { 248 type = lib.types.numbers.between 0 1; 249 default = 0.4341732; 250 }; 251 252 sigma = lib.mkOption { 253 type = lib.types.numbers.between 0.001 1; 254 default = 0.1; 255 }; 256 257 sigma_alt = lib.mkOption { 258 type = lib.types.numbers.between 0.001 1; 259 default = 0.1; 260 }; 261 262 sigma_manual = lib.mkOption { 263 type = lib.types.numbers.between 0.001 1; 264 default = 0.03; 265 }; 266 267 sigma_boat = lib.mkOption { 268 type = lib.types.numbers.between 0.0001 1; 269 default = 0.001; 270 }; 271 272 resolution_height = lib.mkOption { 273 type = lib.types.numbers.between 1 16384; 274 default = 16384; 275 }; 276 277 boat_error = lib.mkOption { 278 type = lib.types.numbers.between 0 0.7; 279 default = 0.03; 280 }; 281 282 overlay_hide_delay = lib.mkOption { 283 type = lib.types.numbers.between 1 3600; 284 default = 30.0; 285 }; 286 287 sensitivity = lib.mkOption { 288 type = lib.types.numbers.between 0 1; 289 default = 0.012727597; 290 }; 291 292 custom_adjustment = lib.mkOption { 293 type = lib.types.numbers.between 0 1; 294 default = 0.01; 295 }; 296 297 crosshair_correction = lib.mkOption { 298 type = lib.types.numbers.between (-1) 1; 299 default = 0; 300 }; 301 302 check_for_updates = lib.mkOption { 303 type = lib.types.bool; 304 default = true; 305 }; 306 307 translucent = lib.mkOption { 308 type = lib.types.bool; 309 default = false; 310 }; 311 312 always_on_top = lib.mkOption { 313 type = lib.types.bool; 314 default = true; 315 }; 316 317 show_nether_coords = lib.mkOption { 318 type = lib.types.bool; 319 default = true; 320 }; 321 322 show_angle_updates = lib.mkOption { 323 type = lib.types.bool; 324 default = false; 325 }; 326 327 show_angle_errors = lib.mkOption { 328 type = lib.types.bool; 329 default = false; 330 }; 331 332 auto_reset = lib.mkOption { 333 type = lib.types.bool; 334 default = false; 335 description = "Automatically reset the calculator after some period of time."; 336 }; 337 338 auto_reset_on_instance_change = lib.mkOption { 339 type = lib.types.bool; 340 default = false; 341 }; 342 343 use_adv_statistics = lib.mkOption { 344 type = lib.types.bool; 345 default = true; 346 }; 347 348 alt_clipboard_reader = lib.mkOption { 349 type = lib.types.bool; 350 default = false; 351 description = "Whether or not to use the 'alternative clipboard reader'"; 352 }; 353 354 use_alt_std = lib.mkOption { 355 type = lib.types.bool; 356 default = false; 357 }; 358 359 color_negative_coords = lib.mkOption { 360 type = lib.types.bool; 361 default = false; 362 }; 363 364 use_precise_angle = lib.mkOption { 365 type = lib.types.bool; 366 default = false; 367 }; 368 369 use_obs_overlay = lib.mkOption { 370 type = lib.types.bool; 371 default = false; 372 }; 373 374 save_state = lib.mkOption { 375 type = lib.types.bool; 376 default = true; 377 }; 378 379 enable_http_server = lib.mkOption { 380 type = lib.types.bool; 381 default = false; 382 description = "Enable the HTTP API server"; 383 }; 384 385 overlay_auto_hide = lib.mkOption { 386 type = lib.types.bool; 387 default = false; 388 }; 389 390 overlay_lock_hide = lib.mkOption { 391 type = lib.types.bool; 392 default = false; 393 }; 394 395 all_advancements = lib.mkOption { 396 type = lib.types.bool; 397 default = false; 398 }; 399 400 one_dot_twenty_plus_aa = lib.mkOption { 401 type = lib.types.bool; 402 default = false; 403 }; 404 405 mismeasure_warning_enabled = lib.mkOption { 406 type = lib.types.bool; 407 default = false; 408 }; 409 410 direction_help_enabled = lib.mkOption { 411 type = lib.types.bool; 412 default = false; 413 }; 414 415 combined_offset_information_enabled = lib.mkOption { 416 type = lib.types.bool; 417 default = true; 418 }; 419 420 portal_linking_warning_enabled = lib.mkOption { 421 type = lib.types.bool; 422 default = true; 423 }; 424 425 language_v2 = lib.mkOption { 426 description = "Language code. Leave to default for the system language."; 427 type = lib.types.str; 428 default = ""; 429 }; 430 431 size = mkEnumOption [ "small" "medium" "large" ] "small"; 432 stronghold_display_type = mkEnumOption [ "fourfour" "eighteight" "chunk" ] "fourfour"; 433 view = mkEnumOption [ "basic" "detailed" ] "basic"; 434 mc_version = mkEnumOption [ "pre_119" "post_119" ] "pre_119"; 435 aa_toggle_type = mkEnumOption [ "automatic" "hotkey" ] "automatic"; 436 default_boat_type = mkEnumOption [ "gray" "blue" "green" ] "gray"; 437 angle_adjustment_type = mkEnumOption [ "subpixel" "tall" "custom" ] "subpixel"; 438 angle_adjustment_display_type = mkEnumOption [ "angle_change" "increments" ] "angle_change"; 439 440 hotkey_increment = mkHotkeyOption "increment"; 441 hotkey_decrement = mkHotkeyOption "decrement"; 442 hotkey_reset = mkHotkeyOption "reset"; 443 hotkey_undo = mkHotkeyOption "undo"; 444 hotkey_redo = mkHotkeyOption "redo"; 445 hotkey_minimize = mkHotkeyOption "minimize"; 446 hotkey_alt_std = mkHotkeyOption "alt_std"; 447 hotkey_lock = mkHotkeyOption "lock"; 448 hotkey_boat = mkHotkeyOption "boat"; 449 hotkey_mod_360 = mkHotkeyOption "mod_360"; 450 hotkey_toggle_aa_mode = mkHotkeyOption "toggle_aa_mode"; 451 }; 452 }; 453 }; 454 }; 455 456 config = lib.mkMerge [ 457 (lib.mkIf cfg.enable { 458 home.file.".java/.userPrefs/ninjabrainbot/prefs.xml" = { 459 inherit (cfg) force; 460 461 text = '' 462 <?xml version="1.0" encoding="UTF-8" standalone="no"?> 463 <!DOCTYPE map SYSTEM "http://java.sun.com/dtd/preferences.dtd"> 464 <map MAP_XML_VERSION="1.0"> 465 '' 466 + (mkNinbLines hotkeyExpandedSettings) 467 + '' 468 </map> 469 ''; 470 }; 471 }) 472 473 (lib.mkIf (!(builtins.isNull cfg.package)) { 474 home.packages = [ cfg.package ]; 475 }) 476 ]; 477}