mirror of
https://github.com/nixietab/picodulce.git
synced 2025-04-10 10:28:56 +01:00
Compare commits
29 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c125f440f8 | ||
![]() |
1543b36eb5 | ||
![]() |
eb6b27ed23 | ||
![]() |
0702f918dd | ||
![]() |
5792bcb6eb | ||
![]() |
b6241e7aad | ||
![]() |
0ac8a1bf51 | ||
![]() |
60e532b604 | ||
![]() |
52b07aab71 | ||
![]() |
bb48b3e293 | ||
![]() |
f86bb54abe | ||
![]() |
35e1cd7d17 | ||
![]() |
c0ce394fda | ||
![]() |
1f739f25e8 | ||
![]() |
2d362843c2 | ||
![]() |
ae14820c4d | ||
![]() |
50b3f09ed1 | ||
![]() |
b9bf71334b | ||
![]() |
40bf8ea23e | ||
![]() |
89cf8218f8 | ||
![]() |
520a1b500f | ||
![]() |
b6a3218bf6 | ||
![]() |
c1c98aafae | ||
![]() |
34c36c5b88 | ||
![]() |
fc058913cd | ||
![]() |
523431a557 | ||
![]() |
72f7cbec9d | ||
![]() |
fbdba505c9 | ||
![]() |
479bc4486a |
61
.github/workflows/Build.yml
vendored
Normal file
61
.github/workflows/Build.yml
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
name: Version Change Action
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- version.json # Trigger on changes to version.json
|
||||
|
||||
jobs:
|
||||
run-on-version-change:
|
||||
runs-on: windows-latest # Use Windows 10 runner
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x' # Specify the Python version you need
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install pyqt5 requests pywin32 pyinstaller pillow # Install specific dependencies
|
||||
|
||||
- name: Create actions-temp folder
|
||||
run: |
|
||||
mkdir actions-temp # Create the folder called actions-temp
|
||||
|
||||
- name: Download picoBuild.py script
|
||||
run: |
|
||||
curl -L -o actions-temp/picoBuild.py https://raw.githubusercontent.com/nixietab/picodulce-build-script/refs/heads/main/picoBuild.py
|
||||
|
||||
- name: Run picoBuild.py script
|
||||
run: |
|
||||
python actions-temp/picoBuild.py
|
||||
|
||||
- name: Read version and name from version.json
|
||||
id: version
|
||||
run: |
|
||||
$VERSION = (jq -r '.version' version.json)
|
||||
$NAME = (jq -r '.name' version.json)
|
||||
echo "VERSION=$VERSION" >> $GITHUB_ENV # Store version in the environment variable
|
||||
echo "NAME=$NAME" >> $GITHUB_ENV # Store name in the environment variable
|
||||
|
||||
- name: Tag release
|
||||
run: |
|
||||
# Set Git user for the GitHub Actions runner
|
||||
git config user.name "github-actions"
|
||||
git config user.email "github-actions@github.com"
|
||||
|
||||
# Create the tag and push it to GitHub
|
||||
$VERSION_NAME = "${env:VERSION} ${env:NAME}"
|
||||
git tag -a "v${env:VERSION}" -m "Release $VERSION_NAME" # Tag the release with version number and name
|
||||
git push origin "v${env:VERSION}" # Push the tag to GitHub
|
||||
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
files: actions-temp/build/2hsu.exe # Specify the path to the file to upload
|
@ -38,7 +38,7 @@
|
||||
- **Offline and Online Support**: Whether you're connected to Microsoft or not, Picodulce ensures you can still enjoy your game by supporting both offline and online modes.
|
||||
- **Integrated Mod Manager**: Includes the [Marroc Mod Manager](https://github.com/nixietab/marroc), enabling users to effortlessly manage and customize their game with mods and texturepacks.
|
||||
- **Custom Theme Support**: Create and apply personalized themes with ease. A dedicated repository and guide are [available to help you get started.](https://github.com/nixietab/picodulce-themes)
|
||||
|
||||
-- **Instance Support**: Allows users to create and manage multiple game instances, each with its own configuration, mods, and settings
|
||||
# Installation
|
||||
If you are on windows you may be more interested in a [installer](https://github.com/nixietab/2hsu/releases/download/release/2hsu.exe)
|
||||
|
||||
|
249
picodulce.py
249
picodulce.py
@ -299,6 +299,7 @@ class PicomcVersionSelector(QWidget):
|
||||
"IsRCPenabled": False,
|
||||
"CheckUpdate": False,
|
||||
"LastPlayed": "",
|
||||
"Instance": "default",
|
||||
"Theme": "Dark.json",
|
||||
"ThemeBackground": True,
|
||||
"ThemeRepository": "https://raw.githubusercontent.com/nixietab/picodulce-themes/main/repo.json"
|
||||
@ -825,12 +826,18 @@ class PicomcVersionSelector(QWidget):
|
||||
try:
|
||||
# Set current_state to the selected instance
|
||||
self.current_state = selected_instance
|
||||
|
||||
# Read the config.json to get the "Instance" value
|
||||
with open('config.json', 'r') as config_file:
|
||||
config = json.load(config_file)
|
||||
instance_value = config.get("Instance", "default") # Default to "default" if not found
|
||||
|
||||
# Update lastplayed field in config.json on a separate thread
|
||||
update_thread = threading.Thread(target=self.update_last_played, args=(selected_instance,))
|
||||
update_thread.start()
|
||||
|
||||
# Run the game subprocess
|
||||
subprocess.run(['picomc', 'play', selected_instance], check=True)
|
||||
# Run the game subprocess with the instance_value from config.json
|
||||
subprocess.run(['picomc', 'instance', 'launch', '--version-override', selected_instance, instance_value], check=True)
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
error_message = f"Error playing {selected_instance}: {e}"
|
||||
@ -843,7 +850,7 @@ class PicomcVersionSelector(QWidget):
|
||||
finally:
|
||||
# Reset current_state to "menu" after the game closes
|
||||
self.current_state = "menu"
|
||||
|
||||
|
||||
def update_last_played(self, selected_instance):
|
||||
config_path = "config.json"
|
||||
self.config["LastPlayed"] = selected_instance
|
||||
@ -1235,9 +1242,11 @@ class ModLoaderAndVersionMenu(QDialog):
|
||||
# Create tabs
|
||||
install_mod_tab = QWidget()
|
||||
download_version_tab = QWidget()
|
||||
instances_tab = QWidget() # New tab for instances
|
||||
|
||||
tab_widget.addTab(download_version_tab, "Download Version")
|
||||
tab_widget.addTab(install_mod_tab, "Install Mod Loader")
|
||||
tab_widget.addTab(instances_tab, "Instances") # Add the new tab
|
||||
|
||||
# Add content to "Install Mod Loader" tab
|
||||
self.setup_install_mod_loader_tab(install_mod_tab)
|
||||
@ -1245,6 +1254,240 @@ class ModLoaderAndVersionMenu(QDialog):
|
||||
# Add content to "Download Version" tab
|
||||
self.setup_download_version_tab(download_version_tab)
|
||||
|
||||
# Add content to "Instances" tab
|
||||
self.setup_instances_tab(instances_tab)
|
||||
|
||||
def setup_instances_tab(self, instances_tab):
|
||||
layout = QVBoxLayout(instances_tab)
|
||||
|
||||
# Create title label
|
||||
title_label = QLabel('Current Instance:')
|
||||
title_label.setFont(QFont("Arial", 14))
|
||||
layout.addWidget(title_label)
|
||||
|
||||
# Create a label to display the current instance
|
||||
self.current_instance_label = QLabel('Loading...') # Placeholder text
|
||||
layout.addWidget(self.current_instance_label)
|
||||
|
||||
# Create a QListWidget to display the instances
|
||||
self.instances_list_widget = QListWidget()
|
||||
layout.addWidget(self.instances_list_widget)
|
||||
|
||||
# Create input field and button to create a new instance
|
||||
self.create_instance_input = QLineEdit()
|
||||
self.create_instance_input.setPlaceholderText("Enter instance name")
|
||||
layout.addWidget(self.create_instance_input)
|
||||
|
||||
create_instance_button = QPushButton("Create Instance")
|
||||
create_instance_button.clicked.connect(self.create_instance)
|
||||
layout.addWidget(create_instance_button)
|
||||
|
||||
# Create input field and button to rename an instance
|
||||
self.rename_instance_input = QLineEdit()
|
||||
self.rename_instance_input.setPlaceholderText("Enter new instance name")
|
||||
layout.addWidget(self.rename_instance_input)
|
||||
|
||||
rename_instance_button = QPushButton("Rename Instance")
|
||||
rename_instance_button.clicked.connect(self.rename_instance)
|
||||
layout.addWidget(rename_instance_button)
|
||||
|
||||
# Create button to delete an instance
|
||||
delete_instance_button = QPushButton("Delete Instance")
|
||||
delete_instance_button.clicked.connect(self.delete_instance)
|
||||
layout.addWidget(delete_instance_button)
|
||||
|
||||
# Fetch and display the current instances
|
||||
self.load_instances()
|
||||
|
||||
# Connect the item selection to the instance selection method
|
||||
self.instances_list_widget.itemClicked.connect(self.on_instance_selected)
|
||||
|
||||
# Update the label with the current instance from the config
|
||||
self.update_instance_label()
|
||||
|
||||
def create_instance(self):
|
||||
instance_name = self.create_instance_input.text().strip()
|
||||
|
||||
if instance_name:
|
||||
try:
|
||||
# Run the "picomc instance create" command
|
||||
process = subprocess.Popen(['picomc', 'instance', 'create', instance_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
output, error = process.communicate()
|
||||
|
||||
if process.returncode != 0:
|
||||
raise subprocess.CalledProcessError(process.returncode, process.args, error)
|
||||
|
||||
# Notify the user that the instance was created
|
||||
QMessageBox.information(self, "Instance Created", f"Instance '{instance_name}' has been created successfully.")
|
||||
|
||||
# Reload the instances list
|
||||
self.load_instances()
|
||||
|
||||
# Optionally select the newly created instance
|
||||
self.on_instance_selected(self.instances_list_widget.item(self.instances_list_widget.count() - 1))
|
||||
|
||||
except FileNotFoundError:
|
||||
logging.error("'picomc' command not found. Please make sure it's installed and in your PATH.")
|
||||
except subprocess.CalledProcessError as e:
|
||||
logging.error("Error creating instance: %s", e.stderr)
|
||||
QMessageBox.critical(self, "Error", f"Failed to create instance: {e.stderr}")
|
||||
else:
|
||||
QMessageBox.warning(self, "Invalid Input", "Please enter a valid instance name.")
|
||||
|
||||
def rename_instance(self):
|
||||
selected_item = self.instances_list_widget.currentItem()
|
||||
|
||||
if not selected_item:
|
||||
QMessageBox.warning(self, "No Selection", "Please select an instance to rename.")
|
||||
return
|
||||
|
||||
old_instance_name = selected_item.text()
|
||||
new_instance_name = self.rename_instance_input.text().strip()
|
||||
|
||||
if not new_instance_name:
|
||||
QMessageBox.warning(self, "Invalid Input", "Please enter a valid new instance name.")
|
||||
return
|
||||
|
||||
if old_instance_name == "default":
|
||||
QMessageBox.warning(self, "Cannot Rename Instance", "You cannot rename the 'default' instance.")
|
||||
return
|
||||
|
||||
try:
|
||||
# Run the "picomc instance rename" command
|
||||
process = subprocess.Popen(
|
||||
['picomc', 'instance', 'rename', old_instance_name, new_instance_name],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
|
||||
)
|
||||
output, error = process.communicate()
|
||||
|
||||
if process.returncode != 0:
|
||||
raise subprocess.CalledProcessError(process.returncode, process.args, error)
|
||||
|
||||
QMessageBox.information(self, "Instance Renamed", f"Instance '{old_instance_name}' has been renamed to '{new_instance_name}' successfully.")
|
||||
|
||||
# Reload the instances list
|
||||
self.load_instances()
|
||||
|
||||
# Optionally select the newly renamed instance
|
||||
matching_items = self.instances_list_widget.findItems(new_instance_name, Qt.MatchExactly)
|
||||
if matching_items:
|
||||
self.instances_list_widget.setCurrentItem(matching_items[0])
|
||||
|
||||
except FileNotFoundError:
|
||||
logging.error("'picomc' command not found. Please make sure it's installed and in your PATH.")
|
||||
except subprocess.CalledProcessError as e:
|
||||
logging.error("Error renaming instance: %s", e.stderr)
|
||||
QMessageBox.critical(self, "Error", f"Failed to rename instance: {e.stderr}")
|
||||
|
||||
|
||||
|
||||
|
||||
def delete_instance(self):
|
||||
# Get the selected instance name
|
||||
selected_instance = self.instances_list_widget.currentItem()
|
||||
|
||||
if selected_instance:
|
||||
instance_name = selected_instance.text()
|
||||
|
||||
# Prevent deletion of the "default" instance
|
||||
if instance_name == "default":
|
||||
QMessageBox.warning(self, "Cannot Delete Instance", "You cannot delete the 'default' instance.")
|
||||
return
|
||||
|
||||
confirm_delete = QMessageBox.question(
|
||||
self, "Confirm Deletion", f"Are you sure you want to delete the instance '{instance_name}'?",
|
||||
QMessageBox.Yes | QMessageBox.No, QMessageBox.No
|
||||
)
|
||||
|
||||
if confirm_delete == QMessageBox.Yes:
|
||||
try:
|
||||
# Run the "picomc instance delete" command
|
||||
process = subprocess.Popen(['picomc', 'instance', 'delete', instance_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
output, error = process.communicate()
|
||||
|
||||
if process.returncode != 0:
|
||||
raise subprocess.CalledProcessError(process.returncode, process.args, error)
|
||||
|
||||
# Notify the user that the instance was deleted
|
||||
QMessageBox.information(self, "Instance Deleted", f"Instance '{instance_name}' has been deleted successfully.")
|
||||
|
||||
# Reload the instances list
|
||||
self.load_instances()
|
||||
|
||||
except FileNotFoundError:
|
||||
logging.error("'picomc' command not found. Please make sure it's installed and in your PATH.")
|
||||
except subprocess.CalledProcessError as e:
|
||||
logging.error("Error deleting instance: %s", e.stderr)
|
||||
QMessageBox.critical(self, "Error", f"Failed to delete instance: {e.stderr}")
|
||||
else:
|
||||
QMessageBox.warning(self, "No Selection", "Please select an instance to delete.")
|
||||
|
||||
def load_instances(self):
|
||||
try:
|
||||
process = subprocess.Popen(['picomc', 'instance', 'list'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
output, error = process.communicate()
|
||||
if process.returncode != 0:
|
||||
raise subprocess.CalledProcessError(process.returncode, process.args, error)
|
||||
|
||||
# Parse the output and add each instance to the list widget
|
||||
instances = output.splitlines()
|
||||
self.instances_list_widget.clear() # Clear the previous list
|
||||
self.instances_list_widget.addItems(instances)
|
||||
|
||||
except FileNotFoundError:
|
||||
logging.error("'picomc' command not found. Please make sure it's installed and in your PATH.")
|
||||
except subprocess.CalledProcessError as e:
|
||||
logging.error("Error fetching instances: %s", e.stderr)
|
||||
|
||||
def on_instance_selected(self, item):
|
||||
# Get the selected instance name
|
||||
selected_instance = item.text()
|
||||
|
||||
# Path to the config.json file
|
||||
config_file = 'config.json'
|
||||
|
||||
# Check if the config file exists
|
||||
if os.path.exists(config_file):
|
||||
try:
|
||||
# Load the current config.json file
|
||||
with open(config_file, 'r') as file:
|
||||
config_data = json.load(file)
|
||||
|
||||
# Update the "Instance" value with the selected instance name
|
||||
config_data['Instance'] = selected_instance
|
||||
|
||||
# Save the updated config back to the file
|
||||
with open(config_file, 'w') as file:
|
||||
json.dump(config_data, file, indent=4)
|
||||
|
||||
logging.info(f"Config updated: Instance set to {selected_instance}")
|
||||
|
||||
# Update the label with the new instance
|
||||
self.update_instance_label()
|
||||
|
||||
except (json.JSONDecodeError, FileNotFoundError) as e:
|
||||
logging.error(f"Error reading config.json: {e}")
|
||||
else:
|
||||
logging.warning(f"{config_file} not found. Unable to update instance.")
|
||||
|
||||
def update_instance_label(self):
|
||||
config_file = 'config.json'
|
||||
|
||||
if os.path.exists(config_file):
|
||||
try:
|
||||
# Load the config file
|
||||
with open(config_file, 'r') as file:
|
||||
config_data = json.load(file)
|
||||
|
||||
# Get the current instance from the config and update the label
|
||||
current_instance = config_data.get('Instance', 'Not set')
|
||||
self.current_instance_label.setText(f'Current instance: {current_instance}')
|
||||
|
||||
except (json.JSONDecodeError, FileNotFoundError) as e:
|
||||
logging.error(f"Error reading config.json: {e}")
|
||||
else:
|
||||
self.current_instance_label.setText('Current instance: Not set')
|
||||
|
||||
def setup_install_mod_loader_tab(self, install_mod_tab):
|
||||
layout = QVBoxLayout(install_mod_tab)
|
||||
|
||||
|
15
version.json
15
version.json
@ -1,11 +1,12 @@
|
||||
{
|
||||
"version": "0.11.2",
|
||||
"version": "0.11.4",
|
||||
"name": "Lucky Bastard",
|
||||
"links": [
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/main/version.json",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/main/picodulce.py",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/main/requirements.txt",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/main/drums.gif",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/main/marroc.py",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/main/holiday.ico"
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/canary/version.json",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/canary/picodulce.py",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/canary/requirements.txt",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/canary/drums.gif",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/canary/marroc.py",
|
||||
"https://raw.githubusercontent.com/nixietab/picodulce/canary/holiday.ico"
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user