aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Metin2

Metin2 Root Python: Customizing the UI Windows

The Metin2 client's interface is written entirely in Python, and if you want to shape those windows around your own server, the place to start is the metin2 root python files. You don't need to touch the engine to move the inventory, enlarge the chat window or add a new button — you just need to find the right .py file and make a sensible edit. In this article I'll walk you through how the root package works, how to open and edit the files, and how to test your changes in the client.

The root package and the UI architecture

The client assembles its interface from three separate parts, and without understanding that split you'll get lost in the pile of files:

  • root — The actual Python logic lives here. ui.py defines the UI framework (classes such as Window, Board, Button, TextLine), while files like uiInventory.py, uiCharacter.py, uiChat.py and interfaceModule.py control how each window behaves.
  • uiscript — This is where the layout of the windows is kept. Files like inventorywindow.py aren't HTML; they describe geometry as a Python dictionary: coordinates, width, height and child elements.
  • locale — Texts and language-dependent settings (locale_string.txt and some labels used in uiscript) live here.

So how a window looks is largely defined in uiscript, while how it behaves lives in root. For most visual tweaks, touching uiscript alone is enough.

Unpacking the files and setting up an editing environment

The client stores these files in encrypted packages: root.epk / root.eix and uiscript.epk / uiscript.eix. To edit them, you first have to unpack:

  • Use a tool like EterNexus to unpack and repack. When you open the .eix file you can extract the folder structure inside.
  • The files usually ship as compiled .pyc. If you don't have the source .py, you'll need a Python 2 decompiler (for example uncompyle2) to turn them back. Since the client is built on Python 2.2, modern Python 3 tools often won't work.
  • Many private servers configure the client to read from loose folders instead of packages for easier development. If that's available, you can edit the root and uiscript folders directly and skip the repacking step.

Any editor with syntax highlighting (VS Code, Notepad++) will do. Save the files in the encoding the client expects, and avoid mixing tabs and spaces in your indentation — Python is indentation-sensitive.

Changing a window's layout with uiscript

The most common task is moving or resizing a window. The uiscript/inventorywindow.py file has roughly this structure:

window = {
    "name" : "InventoryWindow",
    "x" : SCREEN_WIDTH - 176,
    "y" : SCREEN_HEIGHT - 37 - 565,
    "style" : ("movable", "float",),
    "width" : 176,
    "height" : 565,

    "children" : (
        {
            "name" : "board",
            "type" : "board",
            "x" : 0,
            "y" : 0,
            "width" : 176,
            "height" : 565,
            "children" : (
                # title, tabs, slots...
            ),
        },
    ),
}

To shift the window left, change the "x" value; to make it wider, change "width". Remember: if you grow the outer window's width, you must also adjust the inner board element's width to match, otherwise the background graphic overflows. The SCREEN_WIDTH and SCREEN_HEIGHT constants let you anchor the window to a screen corner; using them instead of fixed numbers keeps things correct across different resolutions.

Editing the logic inside root

When layout isn't enough, you change behaviour on the root side. For example, uiInventory.py loads the layout file like this:

import ui
import uiScriptLocale

class InventoryWindow(ui.ScriptWindow):
    def __LoadWindow(self):
        pyScrLoader = ui.PythonScriptLoader()
        pyScrLoader.LoadScriptFile(self, "uiscript/inventorywindow.py")

        self.wndItem = self.GetChild("ItemSlot")
        # ... references to elements

The name in the GetChild call must match the "name" field in the uiscript file exactly. If you've added a new button, you first define it in uiscript, then grab it on the root side with GetChild("NewButton") and bind it to a function via SetEvent. If the names don't match, the client returns None and usually crashes with a 'NoneType' object has no attribute ... error.

Touching ui.py is an advanced move: since every window shares this framework, a single mistake here affects the entire interface. Unless you genuinely need a new component type, leave ui.py as it is.

Repacking, caching and debugging

When you've finished editing, repack the files (or, in loose-folder mode, just save) and restart the client. A few practical notes:

  • The client may cache old packages; to be safe, update both the .epk and .eix files together.
  • If something doesn't work, the first place to look is the syserr.txt file in the client folder. Python exceptions, along with the offending line number, are written there.
  • Common errors: indentation mismatch (IndentationError), an unclosed bracket, or a missing comma in a uiscript dict. In Python dictionaries, don't forget the trailing comma after each element.

Common mistakes and tips

  • Back up the original. Before you start editing, copy the root and uiscript packages so rolling back takes seconds, not minutes.
  • Make one change at a time. Don't edit ten files and then test; hunting for the bug becomes torture.
  • Name consistency is everything. The "name" in uiscript and the GetChild in root must be written identically; even case matters.
  • Think about resolution. Use SCREEN_WIDTH/SCREEN_HEIGHT instead of fixed coordinates so the window stays in place on wide screens too.

Frequently Asked Questions

The root files come as .pyc — how do I get the source?

Many files are distributed as compiled .pyc. A Python 2 decompiler (such as uncompyle2) can turn them into readable .py. Some community releases already share clean source; if possible, work with the source directly rather than decompiling.

I only want to move a window — do I have to touch root?

No. Position, size and child layout are entirely on the uiscript side. As long as you're not changing button behaviour, binding events or adding new logic, you never have to open the root files.

My change doesn't show up in the client — why?

Usually either the package wasn't updated (refresh the .eix/.epk pair together) or there's a Python error. Check syserr.txt first; you'll often find the problem there with the exact line number.

Want to redesign the interface around your own server from the ground up? If you need help with Metin2 client customization, root editing or bespoke UI design, get in touch with me — let's bring your project to life together.

Bu kategorideki tüm yazılar →

Devamı için