2022-04-15 11:34:38 +00:00
"""
Copyright ( C ) 2022 Alexey Pavlov
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU Affero General Public License for more details .
You should have received a copy of the GNU Affero General Public License
along with this program . If not , see < https : / / www . gnu . org / licenses / > .
"""
2022-04-08 11:59:20 +00:00
# MCPIEdit
# This is a different editor from revival's MCPIedit!
2022-04-08 20:07:50 +00:00
# This one is intended to work with Planet but it can work on its own
2022-04-08 11:59:20 +00:00
import sys
import os
import pathlib
from PyQt5 . QtCore import *
from PyQt5 . QtWidgets import *
from PyQt5 . QtGui import *
2022-04-14 11:52:20 +00:00
import nbt_utils as nbt
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
USER = os . getenv ( " USER " ) # Get the username, used for later
absolute_path = pathlib . Path ( __file__ ) . parent . absolute ( )
if str ( absolute_path ) . startswith ( " /usr/bin " ) :
absolute_path = " /usr/lib/planet-launcher/ "
sys . path . append ( absolute_path )
if os . path . exists ( " /usr/lib/planet-launcher/ " ) :
sys . path . append ( " /usr/lib/planet-launcher/ " )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
if not os . path . exists ( f " /home/ { USER } /.minecraft-pi/games/com.mojang/minecraftWorlds/ " ) :
os . makedirs ( f " /home/ { USER } /.minecraft-pi/games/com.mojang/minecraftWorlds/ " )
2022-04-08 20:07:50 +00:00
2022-04-14 01:16:27 +00:00
GAME_TYPES = { " Survival " : nbt . pynbt . TAG_Int ( 0 ) , " Creative " : nbt . pynbt . TAG_Int ( 1 ) }
2022-04-08 20:07:50 +00:00
GAME_INTREGERS = { " 0 " : " Survival " , " 1 " : " Creative " }
BOOLEAN_INTREGERS = { 0 : False , 1 : True }
BOOLEAN_INTREGERS_REVERSED = { False : 0 , True : 1 }
2022-04-14 01:16:27 +00:00
2022-04-10 00:12:53 +00:00
class AboutWindow ( QWidget ) :
def __init__ ( self ) :
super ( ) . __init__ ( )
2022-04-14 01:16:27 +00:00
2022-04-10 00:12:53 +00:00
layout = QVBoxLayout ( )
2022-04-14 01:16:27 +00:00
2022-04-10 00:12:53 +00:00
label = QLabel ( " About MCPIedit " )
label . setAlignment ( Qt . AlignHCenter )
font = label . font ( ) # Font used
font . setPointSize ( 15 ) # Set the font size
label . setFont ( font ) # Aplly the font onto the label
2022-04-14 01:16:27 +00:00
desc_label = QLabel (
" The default built-in NBT editor for Planet. \n \n MCPIedit makes use of Pi-NBT \n from the original MCPIedit project \n by TheBrokenRail, which is \n licensed under the MIT license. "
)
2022-04-10 00:12:53 +00:00
desc_label . setAlignment ( Qt . AlignHCenter )
2022-04-14 01:16:27 +00:00
2022-04-10 00:12:53 +00:00
layout . addWidget ( label )
layout . addWidget ( desc_label )
2022-04-14 01:16:27 +00:00
2022-04-10 00:12:53 +00:00
self . setLayout ( layout )
2022-04-08 11:59:20 +00:00
class FileSelectorTab ( QWidget ) :
2022-04-08 20:07:50 +00:00
def __init__ ( self ) :
2022-04-08 11:59:20 +00:00
super ( ) . __init__ ( )
2022-04-08 20:07:50 +00:00
2022-04-10 00:12:53 +00:00
layout = QVBoxLayout ( )
2022-04-14 01:16:27 +00:00
info_label = QLabel (
" NBT editors allow you to edit your world \n files to change game modes, time, \n and even the world name. Select an NBT \n file to edit using the button below. "
)
2022-04-10 00:12:53 +00:00
info_label . setAlignment ( Qt . AlignHCenter )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
self . load_button = QPushButton ( " Select NBT File " )
2022-04-14 01:16:27 +00:00
2022-04-10 00:12:53 +00:00
self . about_button = QPushButton ( " About " )
self . about_button . clicked . connect ( self . about_window )
2022-04-08 20:07:50 +00:00
2022-04-10 00:12:53 +00:00
layout . addWidget ( info_label )
layout . addWidget ( self . load_button )
layout . addWidget ( self . about_button )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
self . setLayout ( layout )
2022-04-14 01:16:27 +00:00
2022-04-10 00:12:53 +00:00
def about_window ( self ) :
self . window = AboutWindow ( )
self . window . show ( )
2022-04-08 11:59:20 +00:00
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
class EditorTab ( QWidget ) :
2022-04-08 20:07:50 +00:00
def __init__ ( self , filename ) :
2022-04-08 11:59:20 +00:00
super ( ) . __init__ ( )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
layout = QVBoxLayout ( )
2022-04-08 20:07:50 +00:00
self . nbt = nbt . load_nbt ( filename , True )
2022-04-08 11:59:20 +00:00
self . filename = filename
self . tabs = QTabWidget ( )
self . tabs . setTabPosition ( QTabWidget . West )
self . tabs . setMovable ( True )
2022-04-08 20:07:50 +00:00
2022-04-09 01:07:36 +00:00
self . tabs . addTab ( self . main_tab ( ) , " General " )
self . tabs . addTab ( self . world_tab ( ) , " World " )
2022-04-08 20:07:50 +00:00
2022-04-14 01:16:27 +00:00
self . name_edit . setText ( str ( self . nbt [ " LevelName " ] . value ) )
self . timestamp_box . setValue ( int ( self . nbt [ " LastPlayed " ] . value ) )
2022-04-14 11:52:20 +00:00
self . game_box . setCurrentText (
GAME_INTREGERS [ str ( int ( self . nbt [ " GameType " ] . value ) ) ]
)
2022-04-14 01:16:27 +00:00
self . seed_edit . setText ( str ( int ( self . nbt [ " RandomSeed " ] . value ) ) )
self . time_edit . setText ( str ( int ( self . nbt [ " Time " ] . value ) ) )
# self.mobs_toggle.setChecked(BOOLEAN_INTREGERS[int(self.nbt["SpawnMobs"])]) # REMOVED BECAUSE DOES NOT WORK
self . spawn_x_box . setValue ( int ( self . nbt [ " SpawnX " ] . value ) )
self . spawn_y_box . setValue ( int ( self . nbt [ " SpawnY " ] . value ) )
self . spawn_z_box . setValue ( int ( self . nbt [ " SpawnZ " ] . value ) )
self . player_spawn_x_box . setValue ( int ( self . nbt [ " Player " ] [ " SpawnX " ] . value ) )
self . player_spawn_y_box . setValue ( int ( self . nbt [ " Player " ] [ " SpawnY " ] . value ) )
self . player_spawn_z_box . setValue ( int ( self . nbt [ " Player " ] [ " SpawnZ " ] . value ) )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
layout . addWidget ( self . tabs )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
self . setLayout ( layout )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
def main_tab ( self ) :
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
widget = QWidget ( )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
layout = QGridLayout ( )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
self . name_label = QLabel ( " World name " )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
self . name_edit = QLineEdit ( )
self . name_edit . setPlaceholderText ( " OneChunk " )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
self . seed_label = QLabel ( " World Seed " )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
self . seed_edit = QLineEdit ( )
self . seed_edit . setPlaceholderText ( " -121542953 " )
self . seed_edit . setValidator ( QIntValidator ( ) )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
self . timestamp_label = QLabel ( " Last Played Timestamp " )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
self . timestamp_box = QSpinBox ( )
self . timestamp_box . setMaximum ( 2147483647 )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
self . game_label = QLabel ( " Game mode " )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
self . game_box = QComboBox ( )
2022-04-08 20:07:50 +00:00
self . game_box . addItems ( [ " Survival " , " Creative " ] )
2022-04-14 01:16:27 +00:00
# self.mobs_toggle = AnimatedToggle(
2022-04-09 01:07:36 +00:00
# checked_color="#59b8e0",
# pulse_checked_color="#92cee8"
2022-04-14 01:16:27 +00:00
# )
2022-04-09 01:07:36 +00:00
self . time_label = QLabel ( " Time (In Ticks) " )
2022-04-14 01:16:27 +00:00
2022-04-09 01:07:36 +00:00
self . time_edit = QLineEdit ( )
self . time_edit . setPlaceholderText ( " 1770 " )
self . time_edit . setValidator ( QIntValidator ( ) )
2022-04-14 01:16:27 +00:00
2022-04-10 00:42:41 +00:00
self . back_button = QPushButton ( " Back " )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
self . save_button = QPushButton ( " Save " )
self . save_button . clicked . connect ( self . save )
2022-04-08 20:07:50 +00:00
layout . addWidget ( self . name_label , 0 , 0 )
layout . addWidget ( self . name_edit , 0 , 1 )
layout . addWidget ( self . seed_label , 1 , 0 )
layout . addWidget ( self . seed_edit , 1 , 1 )
layout . addWidget ( self . timestamp_label , 2 , 0 )
layout . addWidget ( self . timestamp_box , 2 , 1 )
layout . addWidget ( self . game_label , 3 , 0 )
layout . addWidget ( self . game_box , 3 , 1 )
2022-04-14 01:16:27 +00:00
layout . addWidget ( self . time_label , 4 , 0 )
layout . addWidget ( self . time_edit , 4 , 1 )
2022-04-08 20:07:50 +00:00
2022-04-10 00:42:41 +00:00
layout . addWidget ( self . back_button , 5 , 0 )
2022-04-08 20:07:50 +00:00
layout . addWidget ( self . save_button , 5 , 1 )
2022-04-08 11:59:20 +00:00
widget . setLayout ( layout )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
return widget
2022-04-14 01:16:27 +00:00
2022-04-09 01:07:36 +00:00
def world_tab ( self ) :
2022-04-14 01:16:27 +00:00
2022-04-09 01:07:36 +00:00
layout = QGridLayout ( )
2022-04-14 01:16:27 +00:00
2022-04-09 01:37:19 +00:00
x_label = QLabel ( " Spawnpoint X " )
2022-04-14 01:16:27 +00:00
2022-04-09 01:37:19 +00:00
self . spawn_x_box = QSpinBox ( )
self . spawn_x_box . setMinimum ( - 128 )
self . spawn_x_box . setMaximum ( 128 )
2022-04-14 01:16:27 +00:00
2022-04-09 01:37:19 +00:00
y_label = QLabel ( " Spawnpoint Y " )
2022-04-14 01:16:27 +00:00
2022-04-09 01:37:19 +00:00
self . spawn_y_box = QSpinBox ( )
self . spawn_y_box . setMinimum ( - 64 )
self . spawn_y_box . setMaximum ( 64 )
z_label = QLabel ( " Spawnpoint Z " )
2022-04-14 01:16:27 +00:00
2022-04-09 01:37:19 +00:00
self . spawn_z_box = QSpinBox ( )
self . spawn_z_box . setMinimum ( - 128 )
self . spawn_z_box . setMaximum ( 128 )
2022-04-14 01:16:27 +00:00
2022-04-11 00:21:59 +00:00
player_x_label = QLabel ( " Player Spawnpoint X " )
2022-04-14 01:16:27 +00:00
2022-04-11 00:21:59 +00:00
self . player_spawn_x_box = QSpinBox ( )
self . player_spawn_x_box . setMinimum ( - 128 )
self . player_spawn_x_box . setMaximum ( 128 )
2022-04-14 01:16:27 +00:00
2022-04-11 00:21:59 +00:00
player_y_label = QLabel ( " Player Spawnpoint Y " )
2022-04-14 01:16:27 +00:00
2022-04-11 00:21:59 +00:00
self . player_spawn_y_box = QSpinBox ( )
self . player_spawn_y_box . setMinimum ( - 64 )
self . player_spawn_y_box . setMaximum ( 64 )
player_z_label = QLabel ( " Player Spawnpoint Z " )
2022-04-14 01:16:27 +00:00
2022-04-11 00:21:59 +00:00
self . player_spawn_z_box = QSpinBox ( )
self . player_spawn_z_box . setMinimum ( - 128 )
self . player_spawn_z_box . setMaximum ( 128 )
2022-04-14 01:16:27 +00:00
layout . addWidget ( x_label , 0 , 0 )
layout . addWidget ( y_label , 1 , 0 )
layout . addWidget ( z_label , 2 , 0 )
2022-04-09 01:37:19 +00:00
2022-04-14 01:16:27 +00:00
layout . addWidget ( player_x_label , 3 , 0 )
layout . addWidget ( player_y_label , 4 , 0 )
layout . addWidget ( player_z_label , 5 , 0 )
note_label = QLabel (
" Note: \n Player spawnpoints are very buggy! \n You might spawn in the wrong \n place or even outside the world! \n Do not use on valuable worlds. "
)
layout . addWidget ( self . spawn_x_box , 0 , 1 )
layout . addWidget ( self . spawn_y_box , 1 , 1 )
layout . addWidget ( self . spawn_z_box , 2 , 1 )
layout . addWidget ( self . player_spawn_x_box , 3 , 1 )
layout . addWidget ( self . player_spawn_y_box , 4 , 1 )
layout . addWidget ( self . player_spawn_z_box , 5 , 1 )
layout . addWidget ( note_label , 6 , 0 , 1 , 2 )
2022-04-09 01:37:19 +00:00
2022-04-09 01:07:36 +00:00
widget = QWidget ( )
widget . setLayout ( layout )
2022-04-14 01:16:27 +00:00
2022-04-11 00:21:59 +00:00
self . scroll = QScrollArea ( )
2022-04-14 01:16:27 +00:00
2022-04-11 00:21:59 +00:00
self . scroll . setVerticalScrollBarPolicy ( Qt . ScrollBarAlwaysOn )
self . scroll . setHorizontalScrollBarPolicy ( Qt . ScrollBarAlwaysOff )
self . scroll . setWidgetResizable ( True )
self . scroll . setWidget ( widget )
2022-04-14 01:16:27 +00:00
2022-04-11 00:21:59 +00:00
return self . scroll
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
def save ( self ) :
2022-04-14 01:16:27 +00:00
self . nbt [ " LevelName " ] = nbt . pynbt . TAG_String ( self . name_edit . text ( ) )
self . nbt [ " LastPlayed " ] = nbt . pynbt . TAG_Long ( self . timestamp_box . value ( ) )
2022-04-08 11:59:20 +00:00
self . nbt [ " GameType " ] = GAME_TYPES [ self . game_box . currentText ( ) ]
2022-04-14 01:16:27 +00:00
self . nbt [ " RandomSeed " ] = nbt . pynbt . TAG_Long ( int ( self . seed_edit . text ( ) ) )
self . nbt [ " Time " ] = nbt . pynbt . TAG_Long ( int ( self . time_edit . text ( ) ) )
self . nbt [ " SpawnX " ] = nbt . pynbt . TAG_Int ( self . spawn_x_box . value ( ) )
self . nbt [ " SpawnY " ] = nbt . pynbt . TAG_Int ( self . spawn_y_box . value ( ) )
self . nbt [ " SpawnZ " ] = nbt . pynbt . TAG_Int ( self . spawn_z_box . value ( ) )
2022-04-14 11:52:20 +00:00
self . nbt [ " Player " ] [ " SpawnX " ] = nbt . pynbt . TAG_Int (
self . player_spawn_x_box . value ( )
)
self . nbt [ " Player " ] [ " SpawnY " ] = nbt . pynbt . TAG_Int (
self . player_spawn_y_box . value ( )
)
self . nbt [ " Player " ] [ " SpawnZ " ] = nbt . pynbt . TAG_Int (
self . player_spawn_z_box . value ( )
)
2022-04-08 20:07:50 +00:00
nbt . save_nbt ( self . nbt , self . filename )
2022-04-08 11:59:20 +00:00
class NBTEditor ( QWidget ) :
def __init__ ( self ) :
super ( ) . __init__ ( )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
self . layout = QStackedLayout ( )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
selector = FileSelectorTab ( )
selector . load_button . clicked . connect ( self . load_nbt )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
self . layout . addWidget ( selector )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
self . setLayout ( self . layout )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
def load_nbt ( self ) :
print ( " Hellow, Cruel World! " )
2022-04-08 20:07:50 +00:00
fname = QFileDialog . getOpenFileName (
self ,
" Open NBT File " ,
f " /home/ { USER } /.minecraft-pi/games/com.mojang/minecraftWorlds/ " ,
" Minecraft Pi Level NBT (level.dat) " ,
)
2022-04-14 01:16:27 +00:00
if fname [ 0 ] == " " :
2022-04-10 00:12:53 +00:00
return
2022-04-14 01:16:27 +00:00
2022-04-10 00:42:41 +00:00
editor = EditorTab ( fname [ 0 ] )
editor . back_button . clicked . connect ( lambda : self . layout . setCurrentIndex ( 0 ) )
2022-04-08 20:07:50 +00:00
2022-04-14 01:16:27 +00:00
self . layout . insertWidget ( 1 , editor )
2022-04-08 11:59:20 +00:00
self . layout . setCurrentIndex ( 1 )
self . setLayout ( self . layout )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
if __name__ == " __main__ " :
app = QApplication ( sys . argv )
2022-04-08 20:07:50 +00:00
2022-04-08 11:59:20 +00:00
window = QMainWindow ( )
window . setCentralWidget ( NBTEditor ( ) )
window . setWindowTitle ( " MCPIEdit " )
2022-04-08 20:07:50 +00:00
window . setWindowIcon ( QIcon ( f " { absolute_path } /assets/mcpiedit.png " ) )
2022-04-08 11:59:20 +00:00
window . show ( )
app . exec ( )