29
29
import time
30
30
import glob
31
31
import json
32
- from os import walk , remove , path , chdir , kill , rename , uname , geteuid , getenv
32
+ import threading
33
+ from os import *
33
34
from tkinter import *
34
35
from tkinter import ttk
35
36
from tkinter import simpledialog
36
37
from tkinter .filedialog import askopenfilename
37
38
from shutil import copy2
39
+ from mcpicentral import *
40
+ from mcpip import *
41
+ from mcpim import *
38
42
39
43
descriptions = ["Miecraft Pi Edition. v0.1.1. Default game mode: Creative." , "Minecraft Pocket Edition. v0.6.1. Default game mode: Survival." ];
40
44
binaries = ["/usr/bin/minecraft-pi.sh" , "/usr/bin/minecraft-pe.sh" ];
41
45
home = getenv ("HOME" );
46
+ api_client = APIClient (None );
47
+ proxy = Proxy ();
48
+ mod_names = [];
42
49
43
50
def on_select_versions (event ):
44
51
global current_selection ;
45
52
try :
46
- description_text ["text" ] = descriptions [int (event .widget .curselection ()[0 ])];
47
53
current_selection = int (event .widget .curselection ()[0 ]);
54
+ description_text ["text" ] = descriptions [current_selection ];
48
55
except IndexError :
49
56
pass ;
50
57
return 0 ;
51
58
52
59
def launch ():
53
- global mcpi_pid ;
54
60
mcpi_process = subprocess .Popen ([binaries [current_selection ]]);
55
61
time .sleep (2 );
56
- mcpi_pid = mcpi_process .pid + 2 ;
57
62
start_mods ();
58
63
return 0 ;
59
64
@@ -95,27 +100,61 @@ def delete_mod():
95
100
return 0 ;
96
101
97
102
def update_mods ():
103
+ global mod_names ;
98
104
mod_files = [];
99
105
i = 0 ;
106
+ basename = path .basename ;
100
107
101
108
mod_files = glob .glob (f"{ home } /.mcpil/mods/*.mcpi" );
102
109
mods .delete (0 , END );
103
110
104
- while i < len (mod_files ):
105
- mods .insert (i , path .basename (mod_files [i ].replace (".mcpi" , "" )));
111
+ for mod in mod_files :
112
+ mod_path = basename (mod .replace (".mcpi" , "" ));
113
+ mods .insert (i , mod_path );
114
+ mod_names .append (mod_path );
106
115
i += 1 ;
107
116
return 0 ;
108
117
109
- def start_mods ():
110
- global mods_process ;
111
- mods_process = subprocess .Popen (["mcpim" ]);
118
+ def update_servers ():
119
+ i = 0 ;
120
+
121
+ for server in api_client .servers :
122
+ servers .insert (i , server );
123
+ i += 1 ;
112
124
return 0 ;
113
125
114
- def kill_mods ( ):
126
+ def on_select_servers ( event ):
115
127
try :
128
+ if servers .get (int (event .widget .curselection ()[0 ])) is not None :
129
+ enable_server_button ["state" ] = NORMAL ;
130
+ else :
131
+ enable_serverbutton ["state" ] = DISABLED ;
132
+ except IndexError :
133
+ pass ;
134
+ return 0 ;
135
+
136
+ def enable_central_server ():
137
+ server_name = api_client .servers [int (servers .curselection ()[0 ])];
138
+ server = api_client .get_server (server_name );
139
+ proxy .stop ();
140
+ proxy .set_option ("src_addr" , server ["ip" ]);
141
+ proxy .set_option ("src_port" , int (server ["port" ]));
142
+ proxy_thread = threading .Thread (target = proxy .run );
143
+ proxy_thread .start ();
144
+
145
+ #def start_mods():
146
+ # global mods_process;
147
+ # mods_process = subprocess.Popen(["mcpim"]).pid;
148
+ # return 0;
149
+
150
+ def bye ():
151
+ proxy .stop ();
152
+ window .destroy ();
153
+ """try:
116
154
kill(mods_process.pid, signal.SIGTERM);
117
155
except NameError:
118
- pass ;
156
+ pass;"""
157
+ kill (getpid (), signal .SIGTERM );
119
158
return 0 ;
120
159
121
160
def web_open (event ):
@@ -126,7 +165,7 @@ def save_world():
126
165
old_world_name = old_worldname_entry .get ();
127
166
new_world_name = new_worldname_entry .get ();
128
167
world_file = open (f"{ home } /.minecraft/games/com.mojang/minecraftWorlds/{ old_world_name } /level.dat" , "rb+" );
129
- new_world = world_file .read ().replace (bytes ([len (old_world_name )]) + bytes ([ 0 ]) + bytes (old_world_name .encode ()), bytes ([len (new_world_name )]) + bytes ([ 0 ]) + bytes (new_world_name .encode ()));
168
+ new_world = world_file .read ().replace (bytes ([len (old_world_name ), 0x00 ]). join ( bytes (old_world_name .encode ())) , bytes ([len (old_world_name ), 0x00 ]). join ( bytes (old_world_name .encode () )));
130
169
world_file .seek (0 );
131
170
world_file .write (new_world );
132
171
world_file .seek (0x16 );
@@ -141,17 +180,35 @@ def set_default_worldname(event):
141
180
return True ;
142
181
143
182
def add_server ():
144
- global proxy_process ;
145
183
server_addr = server_addr_entry .get ();
146
184
server_port = server_port_entry .get ();
147
- proxy_process = subprocess .Popen (["mcpip" , server_addr , server_port ]);
185
+ proxy .stop ();
186
+ proxy .set_option ("src_addr" , server_addr );
187
+ proxy .set_option ("src_port" , int (server_port ));
188
+ proxy_thread = threading .Thread (target = proxy .run );
189
+ proxy_thread .start ();
148
190
return 0 ;
149
191
150
- def kill_proxy ():
192
+ def init ():
193
+ global launch_thread ;
151
194
try :
152
- kill (proxy_process .pid , signal .SIGTERM );
153
- except NameError :
195
+ mkdir (f"{ home } /.mcpil/" );
196
+ except FileExistsError :
197
+ pass ;
198
+
199
+ try :
200
+ mkdir (f"{ home } /.mcpil/mods" );
201
+ except FileExistsError :
202
+ pass ;
203
+
204
+ launch_thread = threading .Thread (target = launch );
205
+
206
+ try :
207
+ api_client .servers = api_client .get_servers ()["servers" ];
208
+ except :
209
+ api_client .servers = [];
154
210
pass ;
211
+ update_servers ();
155
212
return 0 ;
156
213
157
214
def play_tab (parent ):
@@ -179,7 +236,7 @@ def play_tab(parent):
179
236
versions_frame .pack (fill = BOTH , expand = True );
180
237
181
238
launch_frame = Frame (tab );
182
- launch_button = Button (launch_frame , text = "Launch!" , command = launch );
239
+ launch_button = Button (launch_frame , text = "Launch!" , command = launch_thread . start );
183
240
launch_button .pack (side = RIGHT , anchor = S );
184
241
launch_frame .pack (fill = BOTH , expand = True );
185
242
return tab ;
@@ -306,14 +363,39 @@ def servers_tab(parent):
306
363
buttons_frame .pack (fill = BOTH , expand = True );
307
364
return tab ;
308
365
366
+ def central_tab (parent ):
367
+ global servers ;
368
+ global enable_server_button ;
369
+ tab = Frame (parent );
370
+
371
+ title = Label (tab , text = "MCPI Central" );
372
+ title .config (font = ("" , 24 ));
373
+ title .pack ();
374
+
375
+ public = Label (tab , text = "Public servers" );
376
+ public .config (font = ("" , 10 ));
377
+ public .pack ();
378
+
379
+ servers_frame = Frame (tab );
380
+ servers = Listbox (servers_frame , selectmode = SINGLE , width = 22 );
381
+ servers .bind ('<<ListboxSelect>>' , on_select_servers );
382
+ servers .pack (pady = 16 );
383
+ servers_frame .pack ();
384
+
385
+ buttons_frame = Frame (tab );
386
+ enable_server_button = Button (buttons_frame , text = "Enable server" , command = enable_central_server , state = DISABLED );
387
+ enable_server_button .pack (side = RIGHT , anchor = S );
388
+ buttons_frame .pack (fill = BOTH , expand = True );
389
+ return tab ;
390
+
309
391
def about_tab (parent ):
310
392
tab = Frame (parent );
311
393
312
394
title = Label (tab , text = "Minecraft Pi Launcher" );
313
395
title .config (font = ("" , 24 ));
314
396
title .pack ();
315
397
316
- version = Label (tab , text = "v0.5 .0" );
398
+ version = Label (tab , text = "v0.6 .0" );
317
399
version .config (font = ("" , 10 ));
318
400
version .pack ();
319
401
@@ -329,49 +411,40 @@ def about_tab(parent):
329
411
330
412
def main (args ):
331
413
if "arm" not in uname ()[4 ] and "aarch" not in uname ()[4 ]:
332
- sys .stdout .write ("Error: Minecraft Pi Launcher must run on a Raspberry Pi.\n " );
414
+ sys .stderr .write ("Error: Minecraft Pi Launcher must run on a Raspberry Pi.\n " );
333
415
return - 1 ;
334
416
335
417
global mods_process ;
336
-
337
- if __debug__ == True :
338
- print ("Debug!" );
339
-
340
- if not path .isdir (f"{ home } /.mcpil/" ):
341
- os .mkdir (f"{ home } /.mcpil/" );
342
- os .mkdir (f"{ home } /.mcpil/mods/" );
343
-
344
- if not path .isdir (f"{ home } /.mcpil/mods/" ):
345
- os .mkdir (f"{ home } /.mcpil/mods/" );
346
-
347
- if not path .exists (f"{ home } /.mcpil/username.txt" ):
348
- config_file = open (f"{ home } /.mcpil/username.txt" , "w" );
349
- config_file .seek (0 );
350
- config_file .write ("StevePi" );
351
- config_file .close ();
418
+ global window ;
352
419
353
420
window = Tk ();
354
421
window .title ("MCPI Laucher" );
355
422
window .geometry ("480x348" );
356
423
window .resizable (False , False );
357
424
window .iconphoto (True , PhotoImage (file = "/usr/share/icons/hicolor/48x48/apps/mcpil.png" ));
358
425
426
+ init_thread = threading .Thread (target = init );
427
+ init_thread .start ();
428
+
359
429
tabs = ttk .Notebook (window );
360
430
tabs .add (play_tab (tabs ), text = "Play" );
361
431
tabs .add (settings_tab (tabs ), text = "Settings" );
362
432
tabs .add (mods_tab (tabs ), text = "Mods" );
363
433
tabs .add (worlds_tab (tabs ), text = "Worlds" );
364
434
tabs .add (servers_tab (tabs ), text = "Servers" );
435
+ tabs .add (central_tab (tabs ), text = "Central" );
365
436
tabs .add (about_tab (tabs ), text = "About" );
366
437
tabs .pack (fill = BOTH , expand = True );
367
438
368
439
if len (args ) > 1 :
369
440
install_mod (args [1 ]);
370
441
371
- atexit .register (kill_mods );
372
- atexit .register (kill_proxy );
442
+ window .wm_protocol ("WM_DELETE_WINDOW" , bye );
373
443
374
- window .mainloop ();
444
+ try :
445
+ window .mainloop ();
446
+ except KeyboardInterrupt :
447
+ bye ();
375
448
return 0 ;
376
449
377
450
if __name__ == "__main__" :
0 commit comments