This repository has moved to https://codeberg.org/vanilla-technologies/minect to avoid GitHubs two factor authentication (2FA) requirement. We believe that Microsofts decision to force all code contributors to use 2FA is very problematic for the following reasons:
- 2FA significantly increases the risk of irreversible account loss. This is very different to 2FA for something like online banking where in the worst case you can contact your bank and verify your identity to regain access. With GitHub however, if you loose your phone and backup codes (both of which is possible), you will never gain access to your account again.
- The decision to require 2FA for every code contributor seems very needless. Yes software supply chain attacks are a thing, but not every code contributor on GitHub is responsible for widely used libraries. It's quite the opposite: most code contributors are not responsible for widely used libraries and their code is reviewed and merged by those that are. Also, the details of the 2FA requirement seem arbitrary. Why for example is email not accepted as a second factor or why can WebAuth only be a second second factor and not a primary second factor? Just to make it really hard to not use a phone for 2FA? It feels like a "trust us, we know what's good for you" attitude from Microsoft and it is scary to think what arbitrary decision could come next.
- Depending on how you use passwords the account security is not necessary improved that much by using 2FA, especially if it is forced onto people that don't want to use it. So why is there no opt out?
- Many other developers publicly stated that they are leaving GitHub because of this, so staying on GitHub would prevent any code contributions from these people. This makes finding good contributors even harder than before. By moving to https://codeberg.org everyone can continue to contribute to this project.
- Unfortunately Microsoft does not allow mail as a second factor and some companies do not allow you to bring your private phone to work or install proprietary software (such authenticators) for security reasons. This means 2FA can actually completely prevent you from logging into the website in some circumstances. This is really sad, because it can make it harder for professional developers at companies that use free and open source software to return something to the community.
- Not everyone owns/can afford a smartphone or dedicated authenticator hardware and Microsoft makes it very inconvenient to use 2FA without that by requiring you to install authenticator software on every development machine. This discourages code contributions from poor people.
2FA is a good technology, but it should be up to repository owners to decide whether it is appropriate for the project at hand. Requiring 2FA for all code contributions, even for code that is reviewed and merged by other people, is completely unnecessary and discourages contributions.
Minect (pronounced maɪnɛkt as in Minecraft connection) is a library that allows a Rust program to connect to a running Minecraft instance without requiring any Minecraft mods. The idea originated in the Java library Vanilla Injection.
Using Minect a Rust program can execute commands in Minecraft and listen for command output. This way a Rust program can control or be controlled by Minecraft.
The connection requires a building in Minecraft which continuously loads structure files that contain the commands generated by the Rust program. Listening for their output works by polling Minecraft's log file.
let identifier = "MyProgram";
let world_dir = "C:/Users/Herobrine/AppData/Roaming/.minecraft/saves/New World";
let mut connection = MinecraftConnection::builder(identifier, world_dir).build();
println!("If you are connecting for the first time please execute /reload in Minecraft.");
connection.connect().await?;
let events = connection.add_listener();
connection.execute_commands([
Command::new("scoreboard objectives add example dummy"),
Command::new("scoreboard players set Herobrine example 42"),
Command::new(query_scoreboard_command("Herobrine", "example")),
])?;
let output = events
.filter_map(|event| event.output.parse::<QueryScoreboardOutput>().ok())
.next()
.await
.expect("Minecraft connection was closed unexpectedly");
println!("{}'s score is {}", output.entity, output.score);
In order to set up the building in Minecraft, Minect provides the function MinecraftConnection::connect
. While blocked in this function, a player can execute /reload
in Minecraft to start an interactive installer.
By default connections operate at the maximum rate of 20 executions per second (1 execution per gametick). For slower computers this can be configured by increasing the score update_delay
in the scoreboard minect_config
. For example to update all connections once per second (once per 20 gameticks) execute the following command:
scoreboard players set update_delay minect_config 20
Minect supports operating multiple connection buildings in parallel, each with a unique identifier. A single connection building can be shared between any number of Rust programs, but it is limited to one execution every update_delay
gameticks. For optimal performance every Rust program can use a different connection identifier.
When executing commands that should log their output the following gamerules must be considered:
logAdminCommands
: This must betrue
for Minecraft to write the output of commands to the log file.commandBlockOutput
: This must betrue
for command blocks and command block minecarts to broadcast the output of their commands.sendCommandFeedback
: This should be set tofalse
to prevent the output to also be written to the chat which would likely annoy players.
To make things easy, Minect provides the function enable_logging_command()
to generate a command that sets these gamerules accordingly and reset_logging_command()
to reset them to their previous values. By default these two commands are automatically executed before/after all commands passed to execute_commands
. For full control, this can be disabled when building a MinecraftConnection
.
The output of commands in a datapack (in mcfunction files) is never logged, even if the above mentioned gamerules are set correctly. Minect provides two ways to work around this limitation: you can use the function logged_block_commands(command)
to spawn a command block or the function logged_cart_command(command)
to spawn a command block minecart, which will then execute the supplied command. The command is executed with a slight delay after the datapack function finishes.
let mut commands = Vec::new();
commands.push("say querying scoreboard ...".to_string());
commands.extend(logged_block_commands(query_scoreboard_command("@p", "my_scoreboard")));
let my_function = commands.join("\n");
// Generate datapack containing my_function ...
// Call my_function (could also be done in Minecraft)
connection.execute_commands(["function my_namespace:my_function"])?;
To remove a connection building in Minecraft a player can execute function minect:disconnect
to select a connection to remove.
To completely uninstall Minect in Minecraft a player can execute function minect:uninstall
to start an interactive uninstaller.
Alternatively function minect:uninstall_completely
will uninstall Minect unconditionally.
Uninstalling Minect in Minecraft will remove scoreboards, connections and disable the datapack. After doing so the following directories still need to be removed from the world directory manually:
- datapacks/minect
- generated/minect