mirror of
https://github.com/ModOrganizer2/modorganizer-basic_games.git
synced 2026-07-27 14:07:29 -07:00
Implement full save display
This commit is contained in:
+137
-77
@@ -1,17 +1,17 @@
|
||||
from pathlib import Path
|
||||
import json
|
||||
import time
|
||||
from time import mktime
|
||||
import os
|
||||
from typing import List
|
||||
|
||||
from PyQt6.QtCore import QDateTime, Qt
|
||||
from PyQt6.QtGui import QPainter, QPixmap
|
||||
from PyQt6.QtCore import QDateTime, QDir, QLocale, Qt
|
||||
from PyQt6.QtGui import QFont
|
||||
|
||||
import mobase
|
||||
|
||||
from PyQt6.QtWidgets import QSizePolicy, QVBoxLayout, QFormLayout, QLabel, QStyle
|
||||
from ..basic_features.basic_save_game_info import (
|
||||
BasicGameSaveGame,
|
||||
BasicGameSaveGameInfo,
|
||||
BasicGameSaveGameInfoWidget,
|
||||
BasicGameSaveGameInfo
|
||||
)
|
||||
|
||||
from ..basic_game import BasicGame
|
||||
@@ -21,100 +21,153 @@ class BaSSaveGame(BasicGameSaveGame):
|
||||
def __init__(self, filepath):
|
||||
super().__init__(filepath)
|
||||
self._filepath = Path(filepath)
|
||||
save = open(self._filepath.joinpath("SaveGame.inf"), "rb")
|
||||
save = open(self._filepath, "rb")
|
||||
save_data = json.load(save)
|
||||
self.gameMode: str = save_data["gameModeId"]
|
||||
self.gender: str = "Male" if save_data["creatureId"] == "PlayerDefaultMale" else "Female"
|
||||
self.ethnicity: str = save_data["ethnicGroupId"]
|
||||
self._gameMode: str = save_data["gameModeId"]
|
||||
self._gender: str = "Male" if save_data["creatureId"] == "PlayerDefaultMale" else "Female"
|
||||
self._ethnicity: str = save_data["ethnicGroupId"]
|
||||
h, m, s = save_data["playTime"].split(":")
|
||||
self.elapsed: tuple[int, int, float] = (int(h), int(m), float(s))
|
||||
self.lastsave: time.struct_time = time.strptime(save_data["lastPlayTime"], "%Y-%m-%dT%H:%M:%S")
|
||||
self.tutorial: bool = True if save_data["Tutorial"] == "Done" else False
|
||||
self.swim: bool = save_data["tutorialFlags"]["hasLearnedToSwim"]
|
||||
self.money: float = save_data["money"]
|
||||
self._elapsed: tuple[int, int, float] = (int(h), int(m), float(s))
|
||||
self._created: float = os.path.getctime(filepath)
|
||||
self._modified: float = os.path.getmtime(filepath)
|
||||
save.close()
|
||||
|
||||
def getName(self) -> str:
|
||||
return f"{self.getPlayerSlug()} - {self._gameMode}"
|
||||
|
||||
def getCreationTime(self) -> QDateTime:
|
||||
return QDateTime.fromSecsSinceEpoch(int(mktime(self.lastsave)))
|
||||
return QDateTime.fromSecsSinceEpoch(int(self._created))
|
||||
|
||||
def getModifiedTime(self) -> QDateTime:
|
||||
return QDateTime.fromSecsSinceEpoch(int(self._modified))
|
||||
|
||||
def getPlayerSlug(self) -> str:
|
||||
return f"{self._gender} {self._ethnicity}"
|
||||
|
||||
def getElapsed(self) -> str:
|
||||
return f"{self.elapsed[0]} hours, {self.elapsed[1]} minutes, {int(self.elapsed[2])} seconds"
|
||||
return f"{self._elapsed[0]} hours, {self._elapsed[1]} minutes, {int(self._elapsed[2])} seconds"
|
||||
|
||||
def getCharacter(self) -> str:
|
||||
return f"{self.gender} {self.ethnicity}"
|
||||
|
||||
def getGameMode(self) -> str:
|
||||
return self.gameMode
|
||||
|
||||
def getTutorial(self) -> str:
|
||||
return "Complete" if self.tutorial else "Incomplete"
|
||||
|
||||
def getCanSwim(self) -> bool:
|
||||
return self.swim
|
||||
|
||||
def getMoney(self) -> str:
|
||||
return str(self.money)
|
||||
return self._gameMode
|
||||
|
||||
|
||||
def getPreview(save: Path) -> QPixmap:
|
||||
save = BaSSaveGame(save)
|
||||
lines = [
|
||||
[
|
||||
("Name : " + save.getCharacter(), Qt.AlignmentFlag.AlignLeft),
|
||||
("- Game Mode : " + save.getGameMode(), Qt.AlignmentFlag.AlignLeft),
|
||||
],
|
||||
[("Saved at : " + save.getCreationTime().toString(), Qt.AlignmentFlag.AlignLeft)],
|
||||
[("Elapsed time : " + save.getElapsed(), Qt.AlignmentFlag.AlignLeft)],
|
||||
[("Tutorial : " + save.getTutorial(), Qt.AlignmentFlag.AlignLeft)],
|
||||
[("Money : " + save.getMoney(), Qt.AlignmentFlag.AlignLeft)],
|
||||
]
|
||||
class BaSSaveGameInfoWidget(mobase.ISaveGameInfoWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.resize(400, 125)
|
||||
sizePolicy = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
|
||||
self.setSizePolicy(sizePolicy)
|
||||
self._verticalLayout = QVBoxLayout()
|
||||
self._verticalLayout.setObjectName("verticalLayout")
|
||||
self._formLayout = QFormLayout()
|
||||
self._formLayout.setObjectName("formLayout")
|
||||
self._formLayout.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
|
||||
|
||||
pixmap = QPixmap(320, 320)
|
||||
pixmap.fill()
|
||||
# rightBuffer = []
|
||||
self._label = QLabel()
|
||||
self._label.setObjectName("label")
|
||||
font = QFont()
|
||||
font.setItalic(True)
|
||||
self._label.setFont(font)
|
||||
self._label.setText("Character")
|
||||
|
||||
painter = QPainter()
|
||||
painter.begin(pixmap)
|
||||
fm = painter.fontMetrics()
|
||||
margin = 5
|
||||
height = 0
|
||||
width = 0
|
||||
ln = 0
|
||||
for line in lines:
|
||||
self._formLayout.setWidget(0, QFormLayout.ItemRole.LabelRole, self._label)
|
||||
|
||||
cHeight = 0
|
||||
cWidth = 0
|
||||
self._label_2 = QLabel()
|
||||
self._label_2.setObjectName("label_2")
|
||||
self._label_2.setFont(font)
|
||||
self._label_2.setText("Game Mode")
|
||||
|
||||
for (toPrint, align) in line:
|
||||
bRect = fm.boundingRect(toPrint)
|
||||
cHeight = bRect.height() * (ln + 1)
|
||||
bRect.moveTop(cHeight - bRect.height())
|
||||
if align != Qt.AlignmentFlag.AlignLeft:
|
||||
continue
|
||||
else:
|
||||
bRect.moveLeft(cWidth + margin)
|
||||
cWidth = cWidth + bRect.width()
|
||||
painter.drawText(bRect, align, toPrint)
|
||||
self._formLayout.setWidget(1, QFormLayout.ItemRole.LabelRole, self._label_2)
|
||||
|
||||
height = max(height, cHeight)
|
||||
width = max(width, cWidth + (2 * margin))
|
||||
ln = ln + 1
|
||||
# height = height + lh
|
||||
self._label_3 = QLabel()
|
||||
self._label_3.setObjectName("label_4")
|
||||
self._label_3.setFont(font)
|
||||
self._label_3.setText("Created At")
|
||||
|
||||
painter.end()
|
||||
self._formLayout.setWidget(2, QFormLayout.ItemRole.LabelRole, self._label_3)
|
||||
|
||||
return pixmap.copy(0, 0, width, height)
|
||||
self._label_4 = QLabel()
|
||||
self._label_4.setObjectName("label_4")
|
||||
self._label_4.setFont(font)
|
||||
self._label_4.setText("Last Saved")
|
||||
|
||||
self._formLayout.setWidget(3, QFormLayout.ItemRole.LabelRole, self._label_4)
|
||||
|
||||
self._label_5 = QLabel()
|
||||
self._label_5.setObjectName("label_3")
|
||||
self._label_5.setFont(font)
|
||||
self._label_5.setText("Session Duration")
|
||||
|
||||
self._formLayout.setWidget(4, QFormLayout.ItemRole.LabelRole, self._label_5)
|
||||
|
||||
font1 = QFont()
|
||||
font1.setBold(True)
|
||||
|
||||
self._characterLabel = QLabel()
|
||||
self._characterLabel.setObjectName("characterLabel")
|
||||
self._characterLabel.setFont(font1)
|
||||
self._characterLabel.setText("")
|
||||
|
||||
self._formLayout.setWidget(0, QFormLayout.ItemRole.FieldRole, self._characterLabel)
|
||||
|
||||
self._gameModeLabel = QLabel()
|
||||
self._gameModeLabel.setObjectName("gameModeLabel")
|
||||
self._gameModeLabel.setFont(font1)
|
||||
self._gameModeLabel.setText("")
|
||||
|
||||
self._formLayout.setWidget(1, QFormLayout.ItemRole.FieldRole, self._gameModeLabel)
|
||||
|
||||
self._dateLabel = QLabel()
|
||||
self._dateLabel.setObjectName("dateLabel")
|
||||
self._dateLabel.setFont(font1)
|
||||
self._dateLabel.setText("")
|
||||
|
||||
self._formLayout.setWidget(2, QFormLayout.ItemRole.FieldRole, self._dateLabel)
|
||||
|
||||
self._sessionLabel = QLabel()
|
||||
self._sessionLabel.setObjectName("sessionLabel")
|
||||
self._sessionLabel.setFont(font1)
|
||||
self._sessionLabel.setText("")
|
||||
|
||||
self._formLayout.setWidget(3, QFormLayout.ItemRole.FieldRole, self._sessionLabel)
|
||||
|
||||
self._elapsedTimeLabel = QLabel()
|
||||
self._elapsedTimeLabel.setObjectName("elapsedTimeLabel")
|
||||
self._elapsedTimeLabel.setFont(font1)
|
||||
self._elapsedTimeLabel.setText("")
|
||||
|
||||
self._formLayout.setWidget(4, QFormLayout.ItemRole.FieldRole, self._elapsedTimeLabel)
|
||||
|
||||
self._verticalLayout.addLayout(self._formLayout)
|
||||
|
||||
self.setLayout(self._verticalLayout)
|
||||
self.setWindowFlags(Qt.WindowType.ToolTip | Qt.WindowType.BypassGraphicsProxyWidget)
|
||||
self.setWindowOpacity(
|
||||
self.style().styleHint(QStyle.StyleHint.SH_ToolTipLabel_Opacity) / 255.0
|
||||
)
|
||||
|
||||
def setSave(self, save: BaSSaveGame):
|
||||
self._characterLabel.setText(save.getPlayerSlug())
|
||||
self._gameModeLabel.setText(save.getGameMode())
|
||||
t = save.getCreationTime().toLocalTime()
|
||||
self._dateLabel.setText(QLocale.system().toString(t.date(), QLocale.FormatType.ShortFormat)
|
||||
+ " " + QLocale.system().toString(t.time()))
|
||||
s = save.getModifiedTime().toLocalTime()
|
||||
self._sessionLabel.setText(QLocale.system().toString(s.date(), QLocale.FormatType.ShortFormat)
|
||||
+ " " + QLocale.system().toString(s.time()))
|
||||
self._elapsedTimeLabel.setText(save.getElapsed())
|
||||
self.resize(0, 125)
|
||||
|
||||
|
||||
class BaSSaveGameInfo(BasicGameSaveGameInfo):
|
||||
def getSaveGameWidget(self, parent=None):
|
||||
if self._get_preview is not None:
|
||||
return BasicGameSaveGameInfoWidget(parent, self._get_preview)
|
||||
return None
|
||||
return BaSSaveGameInfoWidget(parent)
|
||||
|
||||
|
||||
class BaSGame(BasicGame):
|
||||
|
||||
Name = "Blade & Sorcery Plugin"
|
||||
Author = "R3z Shark"
|
||||
Version = "0.1.0"
|
||||
@@ -122,7 +175,7 @@ class BaSGame(BasicGame):
|
||||
GameName = "Blade & Sorcery"
|
||||
GameShortName = "bladeandsorcery"
|
||||
GameBinary = "BladeAndSorcery.exe"
|
||||
GameDataPath = r"BladeAndSorcery_Data\StreamingAssets\Mods"
|
||||
GameDataPath = r"BladeAndSorcery_Data\\StreamingAssets\\Mods"
|
||||
GameDocumentsDirectory = "%DOCUMENTS%/My Games/BladeAndSorcery"
|
||||
GameSavesDirectory = "%GAME_DOCUMENTS%/Saves/Default"
|
||||
GameSaveExtension = "chr"
|
||||
@@ -134,5 +187,12 @@ class BaSGame(BasicGame):
|
||||
|
||||
def init(self, organizer: mobase.IOrganizer) -> bool:
|
||||
BasicGame.init(self, organizer)
|
||||
self._featureMap[mobase.SaveGameInfo] = BaSSaveGameInfo(get_preview=getPreview)
|
||||
self._featureMap[mobase.SaveGameInfo] = BaSSaveGameInfo()
|
||||
return True
|
||||
|
||||
def listSaves(self, folder: QDir) -> List[mobase.ISaveGame]:
|
||||
ext = self._mappings.savegameExtension.get()
|
||||
return [
|
||||
BaSSaveGame(path)
|
||||
for path in Path(folder.absolutePath()).glob(f"*.{ext}")
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user