import json from dusk.event import Event from PyQt5.QtWidgets import QFileDialog, QMessageBox from PyQt5.QtCore import QTimer import os from editortool.map.chunkdata import ChunkData MAP_DEFAULT_PATH = os.path.join(os.path.dirname(__file__), '../../../assets/map/') EDITOR_CONFIG_PATH = os.path.join(os.path.dirname(__file__), '.editor') MAP_WIDTH = 5 MAP_HEIGHT = 5 MAP_DEPTH = 3 MAP_CHUNK_COUNT = MAP_WIDTH * MAP_HEIGHT * MAP_DEPTH class MapData: def __init__(self): self.data = {} self.dataOriginal = {} self.onMapData = Event() self.mapFileName = None self.chunks = {} index = 0 for x in range(MAP_WIDTH): for y in range(MAP_HEIGHT): for z in range(MAP_DEPTH): self.chunks[index] = ChunkData(self, x, y, z) index += 1 QTimer.singleShot(16, self.loadLastFile) def loadLastFile(self): if os.path.exists(EDITOR_CONFIG_PATH): try: with open(EDITOR_CONFIG_PATH, 'r') as f: config = json.load(f) lastFile = config.get('lastFile') if lastFile and os.path.exists(lastFile): self.load(lastFile) except Exception: pass def updateEditorConfig(self): try: config = {'lastFile': self.getMapFilename() if self.getMapFilename() else ""} with open(EDITOR_CONFIG_PATH, 'w') as f: json.dump(config, f, indent=2) except Exception: pass def newFile(self): self.data = {} self.dataOriginal = {} self.mapFileName = None for chunk in self.chunks.values(): chunk.new() self.onMapData.invoke(self.data) self.updateEditorConfig() def save(self, fname=None): if not self.getMapFilename() and fname is None: filePath, _ = QFileDialog.getSaveFileName(None, "Save Map File", MAP_DEFAULT_PATH, "Map Files (*.json)") if not filePath: return self.mapFileName = filePath if fname: self.mapFileName = fname try: with open(self.getMapFilename(), 'w') as f: json.dump(self.data, f, indent=2) self.dataOriginal = json.loads(json.dumps(self.data)) # Deep copy for chunk in self.chunks.values(): chunk.save() self.updateEditorConfig() except Exception as e: QMessageBox.critical(None, "Save Error", f"Failed to save map file:\n{e}") def load(self, fileName): try: with open(fileName, 'r') as f: self.data = json.load(f) self.mapFileName = fileName self.dataOriginal = json.loads(json.dumps(self.data)) # Deep copy for chunk in self.chunks.values(): chunk.load() self.onMapData.invoke(self.data) self.updateEditorConfig() except Exception as e: QMessageBox.critical(None, "Load Error", f"Failed to load map file:\n{e}") def isMapFileDirty(self): return json.dumps(self.data, sort_keys=True) != json.dumps(self.dataOriginal, sort_keys=True) def isDirty(self): return self.isMapFileDirty() or self.anyChunksDirty() def getMapFilename(self): return self.mapFileName if self.mapFileName else None def getMapDirectory(self): fname = self.getMapFilename() if not fname or not fname.endswith('.json'): return None return fname[:-5] # Remove '.json' extension def anyChunksDirty(self): for chunk in self.chunks.values(): if chunk.isDirty(): return True return False