Order of proxy use in Wine

If both $http_proxy and $HTTP_PROXY is set, then $http_proxy has precendence. If it’s unset, $HTTP_PROXY will be used. If both are unset, $https_proxy will NOT be read

wine rundll32.exe shell32.dll,Control_RunDLL inetcpl.cpl is set to a proxy server and enabled, it overrides those variables

Some programs will completely ignore both of the variables and only look at the registry. Sometimes one component will just ignore the registry too, so some parts might load and some might not.

For example, battle.net launcher IGNORES the proxy settings, but the game itself might respect them after launch.

Advertisement
Privacy Settings

Use your socks5 proxy as a VPN in NixOS

Just today, I had Steam refuse to update when I tried to start it. This is because it doesn’t like my socks5 proxy as $http_proxy so it fails with the error message “Steam needs to be online to update”

I have a remote server running the proxy software, but the local machine is also running it and gives me a socks5://127.0.0.1:1080 proxy on localhost

NixOS provides the tun2socks package which is this one: https://github.com/xjasonlyu/tun2socks but it currently doesn’t have any options, which I’ll have to fix later

I also installed dnscrypt-proxy2 and gave it some configuration:

  services.dnscrypt-proxy2.enable = true;
  services.dnscrypt-proxy2.settings = {
  sources.public-resolvers = {
      urls = [ "https://download.dnscrypt.info/resolvers-list/v2/public-resolvers.md" ];
      cache_file = "public-resolvers.md";
      minisign_key = "RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3";
      refresh_delay = 72;
    };
  };

https://dev.to/jadolg/tunneling-all-your-internet-connections-through-a-socks-proxy-4f5i

I adapted some of these steps for the software I am running

sudo ip tuntap add mode tun dev tun0
sudo ip addr add 198.18.0.1/15 dev tun0
sudo ip link set dev tun0 up

curl –socks5 socks5://localhost:10808 https://myip.wtf/json

sudo ip route del default
sudo ip route add default via 198.18.0.1 dev tun0 metric 1
sudo ip route add default via 192.168.2.9 dev wlp38s0 metric 10

sudo ip r a $outside_ip via 192.168.2.9
tun2socks -device tun0 -proxy socks5://127.0.0.1:1080 -interface wlp38s0

wlp38s0 is my wireless interface, 192.168.2.9 is my gateway, the $outside_ip is the part we find out by running curl and getting the outside facing IP

When tun2socks runs, it will bridge the socks connection, while I am getting dnscrypt to do my DNS for me because I didn’t want to query the original DNS servers of my provider

Awful defaults for Asian languages in Linux

it’s not obvious when you add a Korean keyboard that it’s a Latin keyboard. This sends you to shave another yak and decide whether you want to use ibus or whatever. This is not how it should work, the “Korean” keyboard should type hangeul, the “Chinese” keyboard should type hanzi. That’s what the user expects, not just typing English when you add a Chinese or Korean keyboard.

Tried out KDE on NixOS

Dolphin doesn’t know how to ask for sudo. The year is 2022, and I need to use the console to do anything. Sure, I could just change the ownership of the mount, but that required me to put in something like:

options = [ “uid=1000” “gid=100” “dmask=007” “fmask=117” ]

into my hardware config, and this is just something I had to google, it’s not something that just works when you click the damn mount

There’s also software called Okular that doesn’t view my files with Korean text in them, and produces some kind of garbage symbols instead of Korean text.

ibus doesn’t work out of the box, but at this point I don’t care enough to fix it, KDE is too buggy to actually run right now

Gnome + Firefox how to open magnet:// links

There are two issues that will prevent this from working:

  1. Firefox will just ignore magnet:// links and won’t do anything. Here you need to set network.protocol-handler.expose.magnet to false in about.config and open the magnet link again.
  2. Gnome kind of knows that qbittorrent or your default program is the default, but not really. You need to run gio mime x-scheme-handler/magnet org.qbittorrent.qBittorrent.desktop in terminal to make it set the qbittorent application as the default

I tested this with qbittorrent on NixOs, I got the name by running xdg-mime query default x-scheme-handler/magnet first

Source:

How to Change Default Torrent Client for Magnet Links in Ubuntu 20.04+


			

How to get StarCraft 1.18+ running on Wine

Install the latest Wine Staging

The current staging has patches in it to make running StarCraft possible. You can install the latest staging from:

https://wine-staging.com/installation.html

Run the installer inside of a new Wine prefix like $HOME/sc-prefix and install the game there. Do not start the game after the installer is done. Hit x to close the installer when it’s finished.

Before you run it, run wineconfig on your StarCraft prefix.

env WINEPREFIX="$HOME/sc-prefix" wine winecfg

Download the installer from:

https://www.blizzard.com/en-us/download/confirmation?platform=windows&locale=enUS&version=LIVE&id=bnetdesk

Then run the installer

env WINEPREFIX="$HOME/sc-prefix" wine Battle.net-Setup.exe

Then make sure you have the correct dependencies. On Ubuntu I needed to run:

sudo dpkg --add-architecture i386

sudo apt-get update

sudo apt-get install libasound2:i386 libasound2-plugins:i386 libc6:i386 libncurses5:i386 libstdc++6:i386 libxtst6:i386 libldap-2.4-2:i386 libfreetype6:i386

I needed the package libgl1-mesa-glx on Ubuntu 16, but I don’t need that one anymore.
An Arch user reported he needed lib32-mpg123. You might possibly need other packages as well.

I did have to reboot after installing the dependencies and drivers, otherwise they wouldn’t work.

You can create a shortcut like:

env WINEPREFIX="$HOME/sc-prefix" wine StarCraft.exe

that runs inside the StarCraft folder. That way you can run using a shortcut instead of having to manually open a terminal every time.

If you don’t want the launcher to launch modify the shortcut to

env WINEPREFIX="$HOME/sc-prefix" wine StarCraft.exe -launch

Run the DXVK script

I had issues with performance on Nvidia, so to fix them I used DXVK
First you need to make sure you have 64 and 32 bit versions of Vulkan

sudo apt-get install libvulkan1 libvulkan1:i386

download https://github.com/doitsujin/dxvk/releases unzip the whole archive somewhere, open terminal in that folder and run

env WINEPREFIX="$HOME/sc-prefix" ./setup_dxvk.sh install

What this does is it replaces the .dll files in the prefix with the files from the folder and does a native override in winecfg

Issues

If you encounter issues with StarCraft, there are two entries in Wine DB for the latest versions:

SD Remastered

You can check each issue for workarounds. I list some of them here.

Blizzard launcher

If Blizzard launcher has buttons you can’t click or see, change the version of the launcher to Windows 2003. It’s the Battle.net.exe executable inside of Blizzard App folder (not inside the StarCraft folder itself). This will give you a message that your Windows version is not supported, so you can change it back if you don’t need it.

Difficulties logging in, 6:3 Error

If you can’t log in to the Battle.net app, on the log-in screen you will see styled boxes on top. Those do not work. Use the white boxes below them. You won’t be able to see what you’re typing, but you will be able to log in if you type into them and hit the Enter key. If you are logged in, you won’t get 6:3 Error.

Lag in ladder games

Make sure to forward port 6112 on UDP.

Ctrl+5 doesn’t work

Ctrl+5 is a shortcut in fcitx for Reload configuration in Global Config (check Advance Option). Not a StarCraft bug per se, but international users keep running into it.

Appendix: How to Install from source

Use https://github.com/wine-compholio/wine-patched so you don’t have to apply staging patches manually.

$ git clone https://github.com/wine-compholio/wine-patched

and then follow this guide to compile it
https://wiki.winehq.org/Building_Biarch_Wine_On_Ubuntu

Note that you don’t need to run the `clean` command on a freshly created folder.

After you finish building the 32 bit Wine you don’t need to install it system-wide, just make the shortcut point to the correct version of Wine.

How to fix Google play services has stopped problem

I recently flashed my tablet with a newer Android version that wasn’t available over the air. I kept getting an error “Google play services has stopped” every few seconds. I tried clearing cache and data, but it wouldn’t go away.

What actually did work for me is going to Settings -> Apps -> Show system apps -> Google play services and giving it all the permissions. Apparently it was freaking out because it was lacking some permission.

FizzBuzz in Rust

The FizzBuzz Test is sometimes given at interviews to filter out candidates who don’t program. The test is as follows:

Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.

If you wanted to show that you can program, you’d write something like

fn main () {
    for n in 1..101 {
        if n % 15 == 0 {
            println!("FizzBuzz");
        } else if n % 3 == 0 {
            println!("Fizz");
        } else if n % 5 == 0 {
            println!("Buzz");
        } else {
            println!("{}", n);
        }
    }
}

This would be sufficient to get to the actual part of the interview where the interviewer can assume you can write a for loop. I’ll admit that half of the time I mess up if I’m not paying attention. This time I forgot to write the % 15 case first so I had to go back and fix it.

But let’s say you had to write this at your job for some reason. This solution is fine, until your boss comes back and says “OK, do the same thing, but now can you make it write Bazz instead of Buzz?”

It would be tempting to just make the substitution in place. But you have new knowledge that requirements may change frequently, so you decide to refactor the program before you change it.

fn main() {
    let first = "Fizz";
    let second = "Buzz";

    for n in 1..101 {
        println!("{}", fizzbuzz(first, second, n));
    }
    
}

fn fizzbuzz(first: &str, second: &str, n: i32) -> String {
    if n % 3 == 0 {
        first.to_string()
    } else if n % 5 == 0 {
        second.to_string()
    } else if n % 15 == 0 {
        first.to_string() + second
    } else {
        n.to_string()
    }
}

You can now freely change the string that’s being concatenated, it doesn’t matter if it’s Buzz or Bazz. You can even write a nice test for it:

#[cfg(test)]
mod tests {
    use super::fizzbuzz;

    #[test]
    fn it_works() {
        assert!(fizzbuzz("Fizz", "Buzz", 3) == "Fizz".to_string());
        assert!(fizzbuzz("Fizz", "Buzz", 5) == "Buzz".to_string());
        assert!(fizzbuzz("Fizz", "Buzz", 15) == "FizzBuzz".to_string());
        assert!(fizzbuzz("Fizz", "Buzz", 4) == 4.to_string());
    }
}

But now our boss comes back and says “What I meant is that you’re supposed to do Fizz, Buzz, Bazz for 3, 5, 7”. Suddenly, our solution is bad. Before we had four cases where we duplicate some code in one of them. Now we have nine cases, and if our boss comes back to ask for more features, possibly sixteen. We try this solution:

fn main() {
    let first = "Fizz";
    let second = "Buzz";

    for n in 1..101 {
        println!("{}", fizzbuzz(&[(first, 3), (second, 5)], n));
    }
}

pub fn fizzbuzz(tuples: &[(&str, i32)], n: i32) -> String {
    let mut output = String::from("");
    
    for &tuple in tuples {
        let (s, factor) = tuple;
        
        if n % factor == 0 {
             output = output + s;
        }
    }
    
    if output == "" {
        n.to_string()
    } else {
        output
    }
}

It’s a clever hack, exploiting the fact that the empty string is an identity element in string concatenation. Unfortunately, it doesn’t pass our new test suite:

#[cfg(test)]
mod tests {
    use super::fizzbuzz;

    #[test]
    fn it_works() {
        assert!(fizzbuzz(&[("Fizz", 3), ("Buzz", 5)], 3) == "Fizz".to_string());
        assert!(fizzbuzz(&[("Fizz", 3), ("Buzz", 5)], 5) == "Buzz".to_string());
        assert!(fizzbuzz(&[("Fizz", 3), ("Buzz", 5)], 15) == "FizzBuzz".to_string());
        assert!(fizzbuzz(&[("Fizz", 3), ("Buzz", 5)], 4) == 4.to_string());
        assert!(fizzbuzz(&[("", 3), ("Buzz", 5)], 3) == "".to_string());
    }
}

Because we used arbitrary strings, our function doesn’t work for empty strings! I don’t know about you, but I feel uneasy writing a function that fails on some valid inputs. Even if we think (read: hope) that those inputs won’t be fed into our function, we can do better. Rust helpfully has the Option type to actually mark absence of something. We can mark the absence of a match as None, and the presence of a match as Some(String).

pub fn fizzbuzz(tuples: &[(&str, i32)], n: i32) -> String {
    let default = || n.to_string();
    accumulate(tuples, n).unwrap_or_else(default)
}

Now we’ll write the accumulate function. There is actually a library called itertools that has a function called fold1 that does a fold starting with None and returns Some if there are things to fold.

fn accumulate(tuples: &[(&str, i32)], n: i32) -> Option<String> {
    tuples.iter()
        .filter(|&x|n % x.1 == 0)
        .map(first)
        .cloned()
        .map(<&str>::into)
        .fold1(String::concat)
}

fn first<A, B>(&(ref first, _): &(A, B)) -> &A {
    first
}

The function first is not really necessary, but it feels clearer to me. We also have to unfortunately write a trait for things that can be concatenated.

pub trait Concatenable {
    fn concat(self, other: Self) -> Self;
}

impl Concatenable for String {
    fn concat(mut self, other: String) -> String {
        self.push_str(&*other);
        self
    }
}

But we’ll ignore that and hope Add is implemented on String + String in the future so we can easily call fold1 on it. But notice that our FizzBuzz program no longer has a single if statement or even a match. This is because the logic of excluding non-factors is inside the filter and the logic for writing the original number is in unwrap_or_else. The benefit of this is there is only one path through the program. The whole program is now in a declarative style.

The final result (with some dependencies inlined) is here: https://is.gd/QVal2B

I also wrote the same thing using Cow<'a, str> and each condition being a closure in my repository:

https://bitbucket.org/iopq/fizzbuzz-in-rust