Skip to content
This repository has been archived by the owner on Feb 19, 2021. It is now read-only.

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
torralbaa committed Mar 26, 2020
0 parents commit 87368eb
Show file tree
Hide file tree
Showing 10 changed files with 727 additions and 0 deletions.
339 changes: 339 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# MCPIL
Minecraft Pi Launcher

A simple launcher for Minecraft: Pi Edition.

## Getting started
### Prerequisites
To use MCPIL you need to have ``Python> = 3.8.x`` pre-installed and root privileges.

### Installation
To install MCPIL, download or clone the repository:
``` shell
git clone https://github.com/Alvarito050506/MCPIL.git
```
and then run the file ``install.py``. It will create a desktop file that you can access in the "Games" category.

## Features
+ Switch between Minecraft Pi and PE
+ Username change
+ Skin change
+ Mod load
+ Coming soon: join non-local server

## Licensing
All the code of this project is licensed under the [GNU General Public License version 2.0](https://github.com/Alvarito050506/MCPIL/blob/master/LICENSE) (GPL-2.0).

All the documentation of this project is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-sa/4.0/) (CC BY-SA 4.0) license.

![CC BY-SA 4.0](https://i.creativecommons.org/l/by-sa/4.0/88x31.png)
46 changes: 46 additions & 0 deletions install.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import subprocess
import sys
import os
import shutil
import fileinput

def main():
if "arm" not in os.uname()[4] and "aarch" not in os.uname()[4]:
sys.stdout.write("Error: Minecraft Pi Launcher must run on a Raspberry Pi.\n");
return 1;

if os.geteuid() != 0:
sys.stdout.write("Error: You need to have root privileges to run this installer.\n");

sys.stdout.write("Installing dependencies... ");
subprocess.call(["sudo", "apt-get", "install", "python3-tk", "wget", "bspatch", "-qq"]);
sys.stdout.write("OK.\n");

sys.stdout.write("Downloading Minecraft... ");
subprocess.call(["sudo", "apt-get", "install", "minecraft-pi", "-qq"]);
sys.stdout.write("OK.\n");

sys.stdout.write("Installing Minecraft... ");
subprocess.call(["bspatch", "/opt/minecraft-pi/minecraft-pi", "/opt/minecraft-pi/minecraft-pe", "install_files/minecraft-pe.bsdiff"]);
subprocess.call(["chmod", "a+x", "/opt/minecraft-pi/minecraft-pe"]);
sys.stdout.write("OK.\n");

sys.stdout.write("Configuring... ");

desktop_template = open("install_files/mcpil.desktop", "r");
desktop_file = open("/usr/share/applications/mcpil.desktop", "w");
desktop_file.write(desktop_template.read().replace("$(EXECUTABLE_PATH)", os.getcwd() + "/mcpil.py").replace("$(ICON_PATH)", os.getcwd() + "/install_files/icon.png"));
desktop_template.close();
desktop_file.close();

shutil.copy2("./install_files/minecraft-pe", "/usr/bin/minecraft-pe");
subprocess.call(["chmod", "a+x", "/usr/bin/minecraft-pe"]);
subprocess.call(["chmod", "a+x", "mcpil.py"]);
sys.stdout.write("OK.\n");
return 0;

if __name__ == '__main__':
sys.exit(main());
Binary file added install_files/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions install_files/mcpil.desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[Desktop Entry]
Name=MCPIL
Comment=Minecraft Pi Launcher
Exec=$(EXECUTABLE_PATH)
Icon=$(ICON_PATH)
Terminal=false
Type=Application
Categories=Application;Game;
StartupNotify=true
13 changes: 13 additions & 0 deletions install_files/minecraft-pe
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/sh

cd /opt/minecraft-pi || exit

if grep -q okay /proc/device-tree/soc/v3d@7ec00000/status \
/proc/device-tree/soc/firmwarekms@7e600000/status 2> /dev/null; then
export LD_PRELOAD=libbcm_host.so.1.0
export LD_LIBRARY_PATH=lib/mesa
else
export LD_LIBRARY_PATH=lib/brcm
fi

./minecraft-pe
Binary file added install_files/minecraft-pe.bsdiff
Binary file not shown.
229 changes: 229 additions & 0 deletions mcpil.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
import subprocess
import atexit
import signal
import webbrowser
from os import walk, remove, path, chdir, kill
from tkinter import *
from tkinter import ttk
from tkinter.filedialog import askopenfilename
from shutil import copy2

descriptions = ["Miecraft Pi Edition. v0.1.1. Default game mode: Creative.", "Minecraft Pocket Edition. v0.6.1. Default game mode: Survival."];
binaries = ["minecraft-pi", "minecraft-pe"];

def on_select_versions(event):
global current_selection;
description_text["text"] = descriptions[int(event.widget.curselection()[0])];
current_selection = int(event.widget.curselection()[0]);
return 0;

def launch():
subprocess.Popen([binaries[current_selection]]);
return 0;

def save_settings():
username = username_entry.get();
i = 0;

while len(username) < 7:
username = username + "\x00";

mcpi_file = open("/opt/minecraft-pi/minecraft-pi", "r+");
mcpi_file.seek(0xfa8ca);
while i < 7:
mcpi_file.write(username[i]);
i += 1;
i = 0;
mcpi_file.close();

mcpe_file = open("/opt/minecraft-pi/minecraft-pe", "r+");
mcpe_file.seek(0xfa8ca);
while i < 7:
mcpe_file.write(username[i]);
i += 1;
mcpe_file.close();
return 0;

def on_select_mods(event):
if mods.get(int(event.widget.curselection()[0])) is not None:
delete_button["state"] = NORMAL;
else:
delete_button["state"] = DISABLED;
return 0;

def install_mod():
mod_file = askopenfilename(filetypes=[("Python scripts", "*.py")]);
copy2(mod_file, "./mods/" + path.basename(mod_file));
update_mods();
delete_button["state"] = DISABLED;
return 0;

def delete_mod():
remove("./mods/" + mods.get(int(mods.curselection()[0])));
update_mods();
delete_button["state"] = DISABLED;
return 0;

def update_mods():
mod_files = [];
i = 0;

for (_, _, files) in walk("mods"):
mod_files.extend(files);

mods.delete(0, END);

while i < len(mod_files):
mods.insert(i, mod_files[i]);
i += 1;
return 0;

def start_mods():
global mods_process;
mods_process = subprocess.Popen(["python3", "mcpim.py"]);
return 0;

def kill_mods():
kill(mods_process.pid, signal.SIGTERM);
return 0;

def change_skin():
skin_file = askopenfilename(filetypes=[("Portable Network Graphics", "*.png")]);
copy2(skin_file, "/opt/minecraft-pi/data/images/mob/char.png");
return 0;

def web_open(event):
webbrowser.open(event.widget.cget("text"));
return 0;

def play_tab(parent):
global description_text;

tab = Frame(parent);

title = Label(tab, text="Minecraft Pi Launcher");
title.config(font=("", 24));
title.pack();

choose_text = Label(tab, text="Choose a Minecraft version to launch.");
choose_text.pack(pady=16);

versions_frame = Frame(tab);
versions = Listbox(versions_frame, selectmode=SINGLE, width=22);
versions.insert(0, " Minecraft Pi Edition ");
versions.insert(1, " Minecraft Pocket Edition ");
versions.bind('<<ListboxSelect>>', on_select_versions);
versions.pack(side=LEFT);

description_text = Label(versions_frame, text="", wraplength=256);
description_text.pack(pady=48);

versions_frame.pack(fill=BOTH, expand=True);

launch_frame = Frame(tab);
launch_button = Button(launch_frame, text="Launch!", command=launch);
launch_button.pack(side=RIGHT, anchor=S);
launch_frame.pack(fill=BOTH, expand=True);
return tab;

def settings_tab(parent):
global username_entry;
tab = Frame(parent);

title = Label(tab, text="Settings");
title.config(font=("", 24));
title.pack();

form_frame = Frame(tab);
username_text = Label(form_frame, text="Username (7 characters max):");
username_text.pack(side=LEFT, anchor=N, pady=16);

username_entry = Entry(form_frame, width=32);
username_entry.pack(side=RIGHT, anchor=N, pady=16);
form_frame.pack();

buttons_frame = Frame(tab);
skin_button = Button(buttons_frame, text="Change skin", command=change_skin);
skin_button.pack(side=LEFT, anchor=S);
save_button = Button(buttons_frame, text="Save", command=save_settings);
save_button.pack(side=RIGHT, anchor=S);
buttons_frame.pack(fill=BOTH, expand=True);
return tab;

def mods_tab(parent):
global delete_button;
global mods;
tab = Frame(parent);

title = Label(tab, text="Mods");
title.config(font=("", 24));
title.pack();

mods_frame = Frame(tab);
mods = Listbox(mods_frame, selectmode=SINGLE, width=22);
update_mods();
mods.bind('<<ListboxSelect>>', on_select_mods);
mods.pack(pady=16);
mods_frame.pack();

buttons_frame = Frame(tab);
start_button = Button(buttons_frame, text="Start mods", command=start_mods);
start_button.pack(side=RIGHT, anchor=S);
install_button = Button(buttons_frame, text="Install", command=install_mod);
install_button.pack(side=RIGHT, anchor=S);
delete_button = Button(buttons_frame, text="Delete", command=delete_mod, state=DISABLED);
delete_button.pack(side=RIGHT, anchor=S);
buttons_frame.pack(fill=BOTH, expand=True);
return tab;

def about_tab(parent):
tab = Frame(parent);

title = Label(tab, text="Minecraft Pi Launcher");
title.config(font=("", 24));
title.pack();

version = Label(tab, text="v0.1.0");
version.config(font=("", 10));
version.pack();

author = Label(tab, text="by @Alvarito050506");
author.config(font=("", 10));
author.pack();
author.bind("<Button-1>", web_open);

url = Label(tab, text="https://github.com/Alvarito050506/MCPIL", fg="blue", cursor="hand2");
url.config(font=("", 10));
url.pack();
author.bind("<Button-1>", web_open);
return tab;

def main(args):
global mods_process;
chdir(path.dirname(__file__));
window = Tk();
window.title("MCPI Laucher");
window.geometry("480x348");
window.resizable(False, False);
window.iconphoto(True, PhotoImage(file="install_files/icon.png"))

tabs = ttk.Notebook(window);
tabs.add(play_tab(tabs), text="Play");
tabs.add(settings_tab(tabs), text="Settings");
tabs.add(mods_tab(tabs), text="Mods");
tabs.add(about_tab(tabs), text="About");
tabs.pack(fill=BOTH, expand=True);

copy2("/opt/minecraft-pi/data/images/mob/char.png", "/opt/minecraft-pi/data/images/mob/char_original.png");
start_mods();
atexit.register(kill_mods);

window.mainloop();
return 0;

if __name__ == '__main__':
sys.exit(main(sys.argv));
40 changes: 40 additions & 0 deletions mcpim.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
import subprocess
import signal
import atexit
from os import walk, kill
from mcpi import *

def kill_mods():
i = 0;
while i < len(mods_processes):
kill(mods_processes[i].pid, signal.SIGTERM);
i += 1;
return 0;

def main():
global mods_processes;
mods_processes = [];
mod_files = [];
i = 0;
j = None;

while j is None:
try:
minecraft.Minecraft.create();
for (_, _, files) in walk("mods"):
mod_files.extend(files);
while i < len(mod_files):
subprocess.Popen(["python3", "mods/" + mod_files[i]]);
i += 1;
atexit.register(kill_mods);
j = 1;
except:
pass;
return 0;

if __name__ == '__main__':
sys.exit(main());
22 changes: 22 additions & 0 deletions mods/example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env python3

import sys
import time
from mcpi import *

mc = minecraft.Minecraft.create();

def main(args):
mc.setting("world_immutable", True);
mc.camera.setFollow();
mc.saveCheckpoint();
mc.postToChat("Welcome to Minecraft Pi.");
time.sleep(5);
mc.setting("world_immutable", False);
mc.setting("nametags_visible", True);
mc.player.setting("autojump", True);
mc.camera.setNormal();
return 0;

if __name__ == '__main__':
sys.exit(main(sys.argv));

0 comments on commit 87368eb

Please sign in to comment.