From 9ea24fd283a04c8356dd468bfd1795aef5efeb29 Mon Sep 17 00:00:00 2001 From: David Vierra Date: Thu, 23 Jun 2016 23:06:52 -1000 Subject: [PATCH] Implement add/remove tile entity in block inspector --- src/mcedit2/ui/inspector.ui | 9 +++- src/mcedit2/widgets/inspector/__init__.py | 53 ++++++++++++++++++++--- src/mceditlib/anvil/entities.py | 35 ++++++++++++--- src/mceditlib/worldeditor.py | 24 ++++++++++ 4 files changed, 108 insertions(+), 13 deletions(-) diff --git a/src/mcedit2/ui/inspector.ui b/src/mcedit2/ui/inspector.ui index b95ba79..f610cac 100644 --- a/src/mcedit2/ui/inspector.ui +++ b/src/mcedit2/ui/inspector.ui @@ -20,7 +20,7 @@ - 1 + 0 @@ -275,6 +275,13 @@ + + + + Add Tile Entity + + + diff --git a/src/mcedit2/widgets/inspector/__init__.py b/src/mcedit2/widgets/inspector/__init__.py index 141b6e8..8f923b0 100644 --- a/src/mcedit2/widgets/inspector/__init__.py +++ b/src/mcedit2/widgets/inspector/__init__.py @@ -89,6 +89,9 @@ class InspectorWidget(QtGui.QWidget, Ui_inspectorWidget): self.removeEntityButton.clicked.connect(self.removeEntity) + self.addTileEntityButton.clicked.connect(self.addTileEntity) + self.removeTileEntityButton.clicked.connect(self.removeTileEntity) + def _changed(self, value, idx): if self.blockPos is None: return @@ -149,13 +152,22 @@ class InspectorWidget(QtGui.QWidget, Ui_inspectorWidget): self.blockInternalNameLabel.setText(block.internalName) self.blockStateLabel.setText(str(block.blockState)) - if self.blockEditorWidget: - self.blockTabWidget.removeTab(0) - self.blockEditorWidget = None + blockBox = BoundingBox((x, y, z), (1, 1, 1)) + + self.selectionNode.selectionBox = blockBox + + self.updateTileEntity() + + def updateTileEntity(self): + pos = self.blockPos self.tileEntity = self.editorSession.currentDimension.getTileEntity(pos) log.info("Inspecting TileEntity %s at %s", self.tileEntity, pos) + if self.blockEditorWidget: + self.blockTabWidget.removeTab(0) + self.blockEditorWidget = None + if self.tileEntity is not None: editorClass = tileEntityEditorClasses.get(self.tileEntity.id) if editorClass is not None: @@ -179,20 +191,47 @@ class InspectorWidget(QtGui.QWidget, Ui_inspectorWidget): self.removeTileEntityButton.setEnabled(self.tileEntity is not None) - blockBox = BoundingBox((x, y, z), (1, 1, 1)) - - self.selectionNode.selectionBox = blockBox if self.tileEntity is not None: if self.tileEntity.id == "Control": try: commandObj = ParseCommand(self.tileEntity.Command) - visuals = CommandVisuals((x, y, z), commandObj) + visuals = CommandVisuals(pos, commandObj) self.commandBlockVisualsNode = visuals self.overlayNode.addChild(visuals) self.editorSession.updateView() except Exception as e: log.warn("Failed to parse command.", exc_info=1) + _tileEntityIDs = { + "minecraft:command_block": "Control", + "minecraft:standing_sign": "Sign", + "minecraft:wall_sign": "Sign", + "minecraft:chest": "Chest", + "minecraft:hopper": "Hopper", + "minecraft:dispenser": "Trap", + } + + def addTileEntity(self): + if self.tileEntity is not None: + return + block = self.editorSession.currentDimension.getBlock(*self.blockPos) + + tileEntityID = self._tileEntityIDs[block.internalName] + + ref = self.editorSession.worldEditor.TileEntityRef.create(tileEntityID) + ref.Position = self.blockPos + + with self.editorSession.beginSimpleCommand("Create TileEntity"): + self.editorSession.currentDimension.addTileEntity(ref) + + self.updateTileEntity() + + def removeTileEntity(self): + if self.tileEntity is not None: + with self.editorSession.beginSimpleCommand("Remove TileEntity"): + self.editorSession.currentDimension.removeTileEntity(self.tileEntity) + + self.updateTileEntity() def inspectEntity(self, entity): self.tileEntity = None diff --git a/src/mceditlib/anvil/entities.py b/src/mceditlib/anvil/entities.py index ca27576..54acbd4 100644 --- a/src/mceditlib/anvil/entities.py +++ b/src/mceditlib/anvil/entities.py @@ -172,7 +172,7 @@ class _PCEntityRef(object): cls = _entityClasses.get(entityID) if cls is None: log.info("No PC entity ref class found for %s", entityID) - return None + cls = PCEntityRefBase ref = cls.create() ref.id = entityID return ref @@ -214,6 +214,8 @@ class PCEntityRefBase(object): nbtattr.SetNBTDefaults(ref) return ref + entityID = NotImplemented + id = nbtattr.NBTAttr("id", 't') Position = nbtattr.NBTVectorAttr("Pos", 'd') Motion = nbtattr.NBTVectorAttr("Motion", 'd') @@ -415,10 +417,24 @@ _entityClasses = { } -def PCTileEntityRef(rootTag, chunk=None): - id = rootTag["id"].value - cls = _tileEntityClasses.get(id, PCTileEntityRefBase) - return cls(rootTag, chunk) + +class _PCTileEntityRef(object): + + def create(self, entityID): + cls = _tileEntityClasses.get(entityID) + if cls is None: + log.info("No PC tile entity ref class found for %s", entityID) + cls = PCTileEntityRefBase + ref = cls.create() + ref.id = entityID + return ref + + def __call__(self, rootTag, chunk=None): + id = rootTag["id"].value + cls = _tileEntityClasses.get(id, PCEntityRefBase) + return cls(rootTag, chunk) + +PCTileEntityRef = _PCTileEntityRef() class PCTileEntityRefBase(object): @@ -429,6 +445,15 @@ class PCTileEntityRefBase(object): def raw_tag(self): return self.rootTag + @classmethod + def create(cls): + rootTag = nbt.TAG_Compound() + ref = cls(rootTag) + nbtattr.SetNBTDefaults(ref) + return ref + + tileEntityID = NotImplemented + id = nbtattr.NBTAttr("id", 't') Position = nbtattr.KeyedVectorAttr('x', 'y', 'z', nbt.TAG_Int, 0) diff --git a/src/mceditlib/worldeditor.py b/src/mceditlib/worldeditor.py index dee68f3..e5002fe 100644 --- a/src/mceditlib/worldeditor.py +++ b/src/mceditlib/worldeditor.py @@ -254,6 +254,7 @@ class WorldEditor(object): def __repr__(self): return "WorldEditor(adapter=%r)" % self.adapter + # --- Summary Info --- @classmethod @@ -261,12 +262,24 @@ class WorldEditor(object): worldInfo = findAdapter(filename, readonly=True, getInfo=True) return worldInfo + # --- Forwarded from Adapter --- + + @property + def EntityRef(self): + return self.adapter.EntityRef + + @property + def TileEntityRef(self): + return self.adapter.TileEntityRef + + # --- Debug --- def setCacheLimit(self, size): self._chunkDataCache.setCacheLimit(size) # --- Undo/redo --- + def requireRevisions(self): self.adapter.requireRevisions() @@ -865,6 +878,17 @@ class WorldEditorDimension(object): chunk.addTileEntity(ref.copy()) + def removeEntity(self, ref): + if ref.chunk is None: + return + ref.chunk.removeEntity(ref) + + def removeTileEntity(self, ref): + if ref.chunk is None: + return + ref.chunk.removeTileEntity(ref) + + # --- Import/Export --- def copyBlocksIter(self, *a, **kw):