rpgsync 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rpgsync-0.1.0/CHANGELOG.md +29 -0
- rpgsync-0.1.0/LICENSE +21 -0
- rpgsync-0.1.0/PKG-INFO +288 -0
- rpgsync-0.1.0/README.md +257 -0
- rpgsync-0.1.0/pyproject.toml +95 -0
- rpgsync-0.1.0/pyproject.toml.orig +70 -0
- rpgsync-0.1.0/rpgsync/__init__.py +8 -0
- rpgsync-0.1.0/rpgsync/__main__.py +3 -0
- rpgsync-0.1.0/rpgsync/cli.py +1242 -0
- rpgsync-0.1.0/rpgsync/commands.py +920 -0
- rpgsync-0.1.0/rpgsync/compat.py +203 -0
- rpgsync-0.1.0/rpgsync/database.py +1025 -0
- rpgsync-0.1.0/rpgsync/db.py +1377 -0
- rpgsync-0.1.0/rpgsync/dbschema.py +1011 -0
- rpgsync-0.1.0/rpgsync/dsl.py +2616 -0
- rpgsync-0.1.0/rpgsync/dynparams.py +357 -0
- rpgsync-0.1.0/rpgsync/dynrpg.py +612 -0
- rpgsync-0.1.0/rpgsync/fmt.py +79 -0
- rpgsync-0.1.0/rpgsync/lcf.py +826 -0
- rpgsync-0.1.0/rpgsync/maniac.py +387 -0
- rpgsync-0.1.0/rpgsync/maptree.py +888 -0
- rpgsync-0.1.0/rpgsync/messages.py +113 -0
- rpgsync-0.1.0/rpgsync/named.py +1051 -0
- rpgsync-0.1.0/rpgsync/project.py +323 -0
- rpgsync-0.1.0/rpgsync/py.typed +0 -0
- rpgsync-0.1.0/rpgsync/pyexpr.py +1472 -0
- rpgsync-0.1.0/rpgsync/resources.py +455 -0
- rpgsync-0.1.0/rpgsync/scaffold.py +567 -0
- rpgsync-0.1.0/rpgsync/script.py +3532 -0
- rpgsync-0.1.0/rpgsync/scriptfiles.py +924 -0
- rpgsync-0.1.0/rpgsync/sync.py +1365 -0
- rpgsync-0.1.0/rpgsync/tables.py +114 -0
- rpgsync-0.1.0/rpgsync/venv.py +102 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Versions
|
|
4
|
+
|
|
5
|
+
rpgsync is released on [PyPI](https://pypi.org/project/rpgsync/) as `0.MINOR.PATCH`:
|
|
6
|
+
|
|
7
|
+
- **MINOR** goes up when the scripts change: `rpgsync pull` writes a game's scripts
|
|
8
|
+
differently (another layout, other names, another way to write a command), or scripts
|
|
9
|
+
written by it may not work with the previous minor version (a DSL name renamed or
|
|
10
|
+
removed).
|
|
11
|
+
- **PATCH** goes up for everything else: fixes and additions after which `rpgsync pull`
|
|
12
|
+
writes the same scripts.
|
|
13
|
+
|
|
14
|
+
A game's `Scripts/pyproject.toml` depends on the version that set it up,
|
|
15
|
+
`rpgsync~=0.MINOR.PATCH` (that version and its later patches), and its `Scripts/uv.lock`
|
|
16
|
+
pins the exact one. [Upgrading rpgsync](README.md#upgrading-rpgsync) moves a game to a
|
|
17
|
+
newer one; [Releasing](docs/development.md#releasing) makes a new one.
|
|
18
|
+
|
|
19
|
+
## Unreleased
|
|
20
|
+
|
|
21
|
+
## 0.1.0
|
|
22
|
+
|
|
23
|
+
First release on PyPI.
|
|
24
|
+
|
|
25
|
+
- A new game's scripts depend on `rpgsync~=0.1.0` from PyPI, pinned by their `uv.lock`,
|
|
26
|
+
instead of a link to this computer's rpgsync folder.
|
|
27
|
+
- A developer of rpgsync links their rpgsync folder as `Scripts/.rpgsync/rpgsync`:
|
|
28
|
+
rpgsync installs it, editable, in the scripts' environment, and leaves
|
|
29
|
+
`pyproject.toml` and `uv.lock` as they are.
|
rpgsync-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nicolas Oulianov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
rpgsync-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rpgsync
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A Python twin of your RPG Maker 2000/2003 game
|
|
5
|
+
Keywords: rpg-maker,rpg-maker-2000,rpg-maker-2003,easyrpg,gamedev,dsl
|
|
6
|
+
Author: Nicolas Oulianov
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
18
|
+
Classifier: Topic :: Games/Entertainment :: Role-Playing
|
|
19
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Dist: pydantic>=2.14.0
|
|
22
|
+
Requires-Dist: rich>=15.0.0
|
|
23
|
+
Requires-Dist: ruff>=0.16.10
|
|
24
|
+
Requires-Dist: typer>=0.27.3
|
|
25
|
+
Requires-Python: >=3.11
|
|
26
|
+
Project-URL: Homepage, https://github.com/oulianov/rpgsync
|
|
27
|
+
Project-URL: Repository, https://github.com/oulianov/rpgsync
|
|
28
|
+
Project-URL: Issues, https://github.com/oulianov/rpgsync/issues
|
|
29
|
+
Project-URL: Changelog, https://github.com/oulianov/rpgsync/blob/master/CHANGELOG.md
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# rpgsync
|
|
33
|
+
|
|
34
|
+
A Python twin of your RPG Maker 2000/2003 game.
|
|
35
|
+
|
|
36
|
+
**rpgsync** turns the events of your game into readable Python scripts, and keeps both sides in sync while you work.
|
|
37
|
+
|
|
38
|
+
- Edit events in your favourite editor, with autocompletion, type checking, search and git.
|
|
39
|
+
- Translate dialogs and database more easily
|
|
40
|
+
- Implement automated tests to verify game mechanics
|
|
41
|
+
- Improve your game using the modern developer's toolkit
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
## Code example
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
@event(10, "Jeremy", x=15, y=38)
|
|
48
|
+
class Jeremy(Event):
|
|
49
|
+
sprite = ("heroes1", 1) # the settings of every page
|
|
50
|
+
layer = "same"
|
|
51
|
+
|
|
52
|
+
def page_1(self):
|
|
53
|
+
"""Greetings (stored in the game as the page's first comment)"""
|
|
54
|
+
text(r"\n[3] : Bonjour, je suis \c[2]Jeremy\c[0].")
|
|
55
|
+
this.move(move_up * 3, face_player, frequency=8)
|
|
56
|
+
Ulysse.move(move_up * 2) # another event of this map, by name
|
|
57
|
+
if party.gold >= 100:
|
|
58
|
+
match show_choices("Payer", "Partir"):
|
|
59
|
+
case "Payer":
|
|
60
|
+
# Take gold (this is stored in the events!)
|
|
61
|
+
party.gold -= 100
|
|
62
|
+
items[3].count += 1
|
|
63
|
+
case "Partir":
|
|
64
|
+
return
|
|
65
|
+
else:
|
|
66
|
+
text("Reviens avec de l'or.")
|
|
67
|
+
variables[102] += 1
|
|
68
|
+
|
|
69
|
+
@page(when=variables[102] >= 1) # the active page: the last one whose condition holds
|
|
70
|
+
def page_2(self):
|
|
71
|
+
text("Merci encore !")
|
|
72
|
+
Ulysse.page_1() # runs Ulysse's page 1 (Call Event)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@event(11, "Ulysse", x=10, y=42)
|
|
76
|
+
class Ulysse(Event): # The other event!
|
|
77
|
+
sprite = ("heroes1", 0)
|
|
78
|
+
layer = "same"
|
|
79
|
+
|
|
80
|
+
def page_1(self):
|
|
81
|
+
pass
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Every command, option and value is typed and documented in
|
|
85
|
+
[`rpgsync/dsl.py`](https://github.com/oulianov/rpgsync/blob/master/rpgsync/dsl.py): your
|
|
86
|
+
editor shows the docs on hover and flags wrong values (a misspelled direction, a sprite
|
|
87
|
+
index above 7, ...). [Writing scripts](https://github.com/oulianov/rpgsync/blob/master/docs/scripts.md)
|
|
88
|
+
explains events and pages, variables by name, the database and the map tree.
|
|
89
|
+
|
|
90
|
+
## Demo
|
|
91
|
+
|
|
92
|
+
A Doom-like 3d game in RPGMaker using only pictures of vertical slices. The tedious, repetitive event code has been automatically generated.
|
|
93
|
+
|
|
94
|
+
https://github.com/user-attachments/assets/9246ff34-b226-4ebc-b8a3-e55b3adcc5d5
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
## Compatibility
|
|
98
|
+
|
|
99
|
+
rpgsync works with **RPG Maker 2000 and 2003** games, both in old versions (1.08) and
|
|
100
|
+
Steam version (1.12a). It was tested on EasyRPG's test suites and on complete games.
|
|
101
|
+
[Learn more.](https://github.com/oulianov/rpgsync/blob/master/Tested_Games.md)
|
|
102
|
+
|
|
103
|
+
**Supported Patches:** Everything! DynRPG, Maniac Patch, EasyRPG commands, Power Mode
|
|
104
|
+
2003, Ineluki Key Patch... Patches with unknown commands are kept as raw. Patches that
|
|
105
|
+
only change the engine don't matter for this module.
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
## Getting started
|
|
109
|
+
|
|
110
|
+
### 1. Install uv
|
|
111
|
+
|
|
112
|
+
rpgsync uses [uv](https://docs.astral.sh/uv/) to manage Python:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
(Windows: `powershell -c "irm https://astral.sh/uv/install.ps1 | iex"`)
|
|
119
|
+
|
|
120
|
+
### 2. Install rpgsync
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
uv tool install rpgsync
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
This puts the `rpgsync` command on your PATH.
|
|
127
|
+
|
|
128
|
+
### 3. Set up your game
|
|
129
|
+
|
|
130
|
+
Run rpgsync in your game folder (the one containing `RPG_RT.ldb`):
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
cd /path/to/MyGame
|
|
134
|
+
rpgsync
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The first time, it asks, then writes your maps, database and common events as Python
|
|
138
|
+
scripts in `Scripts/`, with tests and their own Python environment. It then keeps the
|
|
139
|
+
game and the scripts in sync until Ctrl+C.
|
|
140
|
+
|
|
141
|
+
Open the `Scripts` folder in your editor and select its `.venv` as the Python
|
|
142
|
+
interpreter. You're seeing your Python clone!
|
|
143
|
+
|
|
144
|
+
If the game is in git, commit `Scripts/` with it, `pyproject.toml` and `uv.lock`
|
|
145
|
+
included: they pin the rpgsync version of the game (see
|
|
146
|
+
[Sharing a game](#sharing-a-game)). Its `.gitignore` leaves out `.venv/` and rpgsync's
|
|
147
|
+
own files (`.rpgsync/`).
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
## Everyday use
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
rpgsync # keep the game and the scripts in sync, until Ctrl+C
|
|
154
|
+
rpgsync status # what is pending, on which side
|
|
155
|
+
rpgsync pull # game -> scripts
|
|
156
|
+
rpgsync push # scripts -> game
|
|
157
|
+
rpgsync check # compile and check the scripts (types too), write nothing
|
|
158
|
+
rpgsync clean # delete the backups of overwritten files
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
- A command works on the game of the current folder (the game's or `Scripts/`), or of
|
|
162
|
+
the folder given: `rpgsync status /path/to/MyGame`.
|
|
163
|
+
- `--map N` limits a command to one map. `check` also takes scripts and folders:
|
|
164
|
+
`rpgsync check Map0004.py database`.
|
|
165
|
+
- `pull --force` overwrites scripts that have unsynced edits; `push --force` writes
|
|
166
|
+
every script, not only those changed since the last sync.
|
|
167
|
+
- `rpgsync locate --map 4 --event 12` prints where the scripts write an event
|
|
168
|
+
(`FILE:LINE`).
|
|
169
|
+
- `rpgsync COMMAND --help` lists a command's options.
|
|
170
|
+
|
|
171
|
+
### With the EasyRPG Editor
|
|
172
|
+
|
|
173
|
+
> [!TIP]
|
|
174
|
+
> **The EasyRPG Editor is the recommended editor to use with rpgsync.** It stays open
|
|
175
|
+
> while rpgsync runs, and merges your Python edits with the changes you make in it.
|
|
176
|
+
|
|
177
|
+
In the [EasyRPG Editor](https://github.com/oulianov/Editor), turn on **rpgsync mode**
|
|
178
|
+
(Settings). The Editor reloads the changes made on disk and shows them as well as it
|
|
179
|
+
can, so it can stay open while `rpgsync` runs. When both sides change the same game,
|
|
180
|
+
it merges what each changed and only asks when the same entry changed on both sides.
|
|
181
|
+
|
|
182
|
+
### With the RPG Maker 2000/2003 editor
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
rpgsync pull # game -> scripts
|
|
186
|
+
# edit the Python files
|
|
187
|
+
rpgsync push # scripts -> game
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
then open the editor and keep editing there.
|
|
191
|
+
|
|
192
|
+
> [!WARNING]
|
|
193
|
+
> **Keep the RPG Maker editor closed while you edit the Python files.**
|
|
194
|
+
> The editor keeps its own copy of your game in memory and ignores your Python
|
|
195
|
+
> edits: its next save (a map, the database, or quitting) writes that copy back
|
|
196
|
+
> over them.
|
|
197
|
+
|
|
198
|
+
### Play-test with EasyRPG Player
|
|
199
|
+
|
|
200
|
+
[EasyRPG Player](https://easyrpg.org/player/) runs RPG Maker 2000/2003 games on
|
|
201
|
+
Windows, macOS, Linux and more, and is the quickest way to test your changes: start
|
|
202
|
+
the game, play, quit, edit, start again.
|
|
203
|
+
|
|
204
|
+
### Will this break my project?
|
|
205
|
+
|
|
206
|
+
rpgsync is built so that **it should not**. If anything, you can always go back.
|
|
207
|
+
|
|
208
|
+
- **Invalid scripts are never written.** A typo, a wrong value or a RPG Maker 2003
|
|
209
|
+
command in a 2000 game stops at the
|
|
210
|
+
[checks](https://github.com/oulianov/rpgsync/blob/master/docs/checks.md).
|
|
211
|
+
- **Every overwritten file is backed up** (game files and scripts) in
|
|
212
|
+
`Scripts/.rpgsync/history/`, the last 50 syncs. `rpgsync clean` deletes them once
|
|
213
|
+
you no longer need them.
|
|
214
|
+
- Only what you changed is written.
|
|
215
|
+
- If the same event changed on both sides, the editor's version is kept and your
|
|
216
|
+
script is saved next to it as `MapXXXX.conflict-<time>.py` (in one file, for a
|
|
217
|
+
script split in files).
|
|
218
|
+
|
|
219
|
+
Using git on the game folder and doing backups is still a good idea.
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
## Sharing a game
|
|
223
|
+
|
|
224
|
+
`Scripts/pyproject.toml` depends on the rpgsync release that set the game up
|
|
225
|
+
(`rpgsync~=0.1.0`), and `Scripts/uv.lock` pins its exact version. Whoever clones the
|
|
226
|
+
game runs that version, in `Scripts/`:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
uv sync # install the game's rpgsync, and the scripts' tools
|
|
230
|
+
uv run rpgsync # run it
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
A CI job does the same: `uv sync --locked`, then `uv run --locked rpgsync ...`.
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
## Upgrading rpgsync
|
|
237
|
+
|
|
238
|
+
The `rpgsync` command:
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
uv tool upgrade rpgsync
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
A game, in its `Scripts/` folder:
|
|
245
|
+
|
|
246
|
+
- **A fix release** (0.1.0 → 0.1.3) writes the same scripts:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
uv sync --upgrade-package rpgsync
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
then commit `uv.lock`.
|
|
253
|
+
- **A new minor version** (0.1.x → 0.2.0) writes the scripts differently. With
|
|
254
|
+
nothing pending (`rpgsync status`):
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
uv add "rpgsync~=0.2.0"
|
|
258
|
+
uv run rpgsync pull --force
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
then commit `pyproject.toml`, `uv.lock` and the rewritten scripts together.
|
|
262
|
+
|
|
263
|
+
[CHANGELOG.md](https://github.com/oulianov/rpgsync/blob/master/CHANGELOG.md) lists
|
|
264
|
+
what each version changes. An `rpgsync` command newer than a game's version would
|
|
265
|
+
rewrite its scripts in the newer format: on a game you don't upgrade yet, use
|
|
266
|
+
`uv run rpgsync` in its `Scripts/`.
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
## Learn more
|
|
270
|
+
|
|
271
|
+
- [Writing scripts](https://github.com/oulianov/rpgsync/blob/master/docs/scripts.md):
|
|
272
|
+
events and pages, variables and switches by name, the database, the map tree, big
|
|
273
|
+
scripts as folders
|
|
274
|
+
- [Checks and tests](https://github.com/oulianov/rpgsync/blob/master/docs/checks.md):
|
|
275
|
+
`rpgsync check`, the scripts' tests, resource files
|
|
276
|
+
- [DynRPG and DynParams](https://github.com/oulianov/rpgsync/blob/master/docs/dynrpg.md):
|
|
277
|
+
plugin calls, and a variable wherever RPG Maker takes a number
|
|
278
|
+
- [Patches](https://github.com/oulianov/rpgsync/blob/master/Patches.md): how each patch
|
|
279
|
+
shows in the scripts, and their settings
|
|
280
|
+
- [Tested games](https://github.com/oulianov/rpgsync/blob/master/Tested_Games.md)
|
|
281
|
+
- [Working on rpgsync](https://github.com/oulianov/rpgsync/blob/master/docs/development.md):
|
|
282
|
+
use your own rpgsync in a game, run its tests, release it
|
|
283
|
+
- [Changelog](https://github.com/oulianov/rpgsync/blob/master/CHANGELOG.md)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
## License
|
|
287
|
+
|
|
288
|
+
MIT, 2026: see [LICENSE](https://github.com/oulianov/rpgsync/blob/master/LICENSE). Source: https://github.com/oulianov/rpgsync
|
rpgsync-0.1.0/README.md
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
# rpgsync
|
|
2
|
+
|
|
3
|
+
A Python twin of your RPG Maker 2000/2003 game.
|
|
4
|
+
|
|
5
|
+
**rpgsync** turns the events of your game into readable Python scripts, and keeps both sides in sync while you work.
|
|
6
|
+
|
|
7
|
+
- Edit events in your favourite editor, with autocompletion, type checking, search and git.
|
|
8
|
+
- Translate dialogs and database more easily
|
|
9
|
+
- Implement automated tests to verify game mechanics
|
|
10
|
+
- Improve your game using the modern developer's toolkit
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## Code example
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
@event(10, "Jeremy", x=15, y=38)
|
|
17
|
+
class Jeremy(Event):
|
|
18
|
+
sprite = ("heroes1", 1) # the settings of every page
|
|
19
|
+
layer = "same"
|
|
20
|
+
|
|
21
|
+
def page_1(self):
|
|
22
|
+
"""Greetings (stored in the game as the page's first comment)"""
|
|
23
|
+
text(r"\n[3] : Bonjour, je suis \c[2]Jeremy\c[0].")
|
|
24
|
+
this.move(move_up * 3, face_player, frequency=8)
|
|
25
|
+
Ulysse.move(move_up * 2) # another event of this map, by name
|
|
26
|
+
if party.gold >= 100:
|
|
27
|
+
match show_choices("Payer", "Partir"):
|
|
28
|
+
case "Payer":
|
|
29
|
+
# Take gold (this is stored in the events!)
|
|
30
|
+
party.gold -= 100
|
|
31
|
+
items[3].count += 1
|
|
32
|
+
case "Partir":
|
|
33
|
+
return
|
|
34
|
+
else:
|
|
35
|
+
text("Reviens avec de l'or.")
|
|
36
|
+
variables[102] += 1
|
|
37
|
+
|
|
38
|
+
@page(when=variables[102] >= 1) # the active page: the last one whose condition holds
|
|
39
|
+
def page_2(self):
|
|
40
|
+
text("Merci encore !")
|
|
41
|
+
Ulysse.page_1() # runs Ulysse's page 1 (Call Event)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@event(11, "Ulysse", x=10, y=42)
|
|
45
|
+
class Ulysse(Event): # The other event!
|
|
46
|
+
sprite = ("heroes1", 0)
|
|
47
|
+
layer = "same"
|
|
48
|
+
|
|
49
|
+
def page_1(self):
|
|
50
|
+
pass
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Every command, option and value is typed and documented in
|
|
54
|
+
[`rpgsync/dsl.py`](https://github.com/oulianov/rpgsync/blob/master/rpgsync/dsl.py): your
|
|
55
|
+
editor shows the docs on hover and flags wrong values (a misspelled direction, a sprite
|
|
56
|
+
index above 7, ...). [Writing scripts](https://github.com/oulianov/rpgsync/blob/master/docs/scripts.md)
|
|
57
|
+
explains events and pages, variables by name, the database and the map tree.
|
|
58
|
+
|
|
59
|
+
## Demo
|
|
60
|
+
|
|
61
|
+
A Doom-like 3d game in RPGMaker using only pictures of vertical slices. The tedious, repetitive event code has been automatically generated.
|
|
62
|
+
|
|
63
|
+
https://github.com/user-attachments/assets/9246ff34-b226-4ebc-b8a3-e55b3adcc5d5
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
## Compatibility
|
|
67
|
+
|
|
68
|
+
rpgsync works with **RPG Maker 2000 and 2003** games, both in old versions (1.08) and
|
|
69
|
+
Steam version (1.12a). It was tested on EasyRPG's test suites and on complete games.
|
|
70
|
+
[Learn more.](https://github.com/oulianov/rpgsync/blob/master/Tested_Games.md)
|
|
71
|
+
|
|
72
|
+
**Supported Patches:** Everything! DynRPG, Maniac Patch, EasyRPG commands, Power Mode
|
|
73
|
+
2003, Ineluki Key Patch... Patches with unknown commands are kept as raw. Patches that
|
|
74
|
+
only change the engine don't matter for this module.
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
## Getting started
|
|
78
|
+
|
|
79
|
+
### 1. Install uv
|
|
80
|
+
|
|
81
|
+
rpgsync uses [uv](https://docs.astral.sh/uv/) to manage Python:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
(Windows: `powershell -c "irm https://astral.sh/uv/install.ps1 | iex"`)
|
|
88
|
+
|
|
89
|
+
### 2. Install rpgsync
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
uv tool install rpgsync
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
This puts the `rpgsync` command on your PATH.
|
|
96
|
+
|
|
97
|
+
### 3. Set up your game
|
|
98
|
+
|
|
99
|
+
Run rpgsync in your game folder (the one containing `RPG_RT.ldb`):
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
cd /path/to/MyGame
|
|
103
|
+
rpgsync
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The first time, it asks, then writes your maps, database and common events as Python
|
|
107
|
+
scripts in `Scripts/`, with tests and their own Python environment. It then keeps the
|
|
108
|
+
game and the scripts in sync until Ctrl+C.
|
|
109
|
+
|
|
110
|
+
Open the `Scripts` folder in your editor and select its `.venv` as the Python
|
|
111
|
+
interpreter. You're seeing your Python clone!
|
|
112
|
+
|
|
113
|
+
If the game is in git, commit `Scripts/` with it, `pyproject.toml` and `uv.lock`
|
|
114
|
+
included: they pin the rpgsync version of the game (see
|
|
115
|
+
[Sharing a game](#sharing-a-game)). Its `.gitignore` leaves out `.venv/` and rpgsync's
|
|
116
|
+
own files (`.rpgsync/`).
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
## Everyday use
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
rpgsync # keep the game and the scripts in sync, until Ctrl+C
|
|
123
|
+
rpgsync status # what is pending, on which side
|
|
124
|
+
rpgsync pull # game -> scripts
|
|
125
|
+
rpgsync push # scripts -> game
|
|
126
|
+
rpgsync check # compile and check the scripts (types too), write nothing
|
|
127
|
+
rpgsync clean # delete the backups of overwritten files
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
- A command works on the game of the current folder (the game's or `Scripts/`), or of
|
|
131
|
+
the folder given: `rpgsync status /path/to/MyGame`.
|
|
132
|
+
- `--map N` limits a command to one map. `check` also takes scripts and folders:
|
|
133
|
+
`rpgsync check Map0004.py database`.
|
|
134
|
+
- `pull --force` overwrites scripts that have unsynced edits; `push --force` writes
|
|
135
|
+
every script, not only those changed since the last sync.
|
|
136
|
+
- `rpgsync locate --map 4 --event 12` prints where the scripts write an event
|
|
137
|
+
(`FILE:LINE`).
|
|
138
|
+
- `rpgsync COMMAND --help` lists a command's options.
|
|
139
|
+
|
|
140
|
+
### With the EasyRPG Editor
|
|
141
|
+
|
|
142
|
+
> [!TIP]
|
|
143
|
+
> **The EasyRPG Editor is the recommended editor to use with rpgsync.** It stays open
|
|
144
|
+
> while rpgsync runs, and merges your Python edits with the changes you make in it.
|
|
145
|
+
|
|
146
|
+
In the [EasyRPG Editor](https://github.com/oulianov/Editor), turn on **rpgsync mode**
|
|
147
|
+
(Settings). The Editor reloads the changes made on disk and shows them as well as it
|
|
148
|
+
can, so it can stay open while `rpgsync` runs. When both sides change the same game,
|
|
149
|
+
it merges what each changed and only asks when the same entry changed on both sides.
|
|
150
|
+
|
|
151
|
+
### With the RPG Maker 2000/2003 editor
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
rpgsync pull # game -> scripts
|
|
155
|
+
# edit the Python files
|
|
156
|
+
rpgsync push # scripts -> game
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
then open the editor and keep editing there.
|
|
160
|
+
|
|
161
|
+
> [!WARNING]
|
|
162
|
+
> **Keep the RPG Maker editor closed while you edit the Python files.**
|
|
163
|
+
> The editor keeps its own copy of your game in memory and ignores your Python
|
|
164
|
+
> edits: its next save (a map, the database, or quitting) writes that copy back
|
|
165
|
+
> over them.
|
|
166
|
+
|
|
167
|
+
### Play-test with EasyRPG Player
|
|
168
|
+
|
|
169
|
+
[EasyRPG Player](https://easyrpg.org/player/) runs RPG Maker 2000/2003 games on
|
|
170
|
+
Windows, macOS, Linux and more, and is the quickest way to test your changes: start
|
|
171
|
+
the game, play, quit, edit, start again.
|
|
172
|
+
|
|
173
|
+
### Will this break my project?
|
|
174
|
+
|
|
175
|
+
rpgsync is built so that **it should not**. If anything, you can always go back.
|
|
176
|
+
|
|
177
|
+
- **Invalid scripts are never written.** A typo, a wrong value or a RPG Maker 2003
|
|
178
|
+
command in a 2000 game stops at the
|
|
179
|
+
[checks](https://github.com/oulianov/rpgsync/blob/master/docs/checks.md).
|
|
180
|
+
- **Every overwritten file is backed up** (game files and scripts) in
|
|
181
|
+
`Scripts/.rpgsync/history/`, the last 50 syncs. `rpgsync clean` deletes them once
|
|
182
|
+
you no longer need them.
|
|
183
|
+
- Only what you changed is written.
|
|
184
|
+
- If the same event changed on both sides, the editor's version is kept and your
|
|
185
|
+
script is saved next to it as `MapXXXX.conflict-<time>.py` (in one file, for a
|
|
186
|
+
script split in files).
|
|
187
|
+
|
|
188
|
+
Using git on the game folder and doing backups is still a good idea.
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
## Sharing a game
|
|
192
|
+
|
|
193
|
+
`Scripts/pyproject.toml` depends on the rpgsync release that set the game up
|
|
194
|
+
(`rpgsync~=0.1.0`), and `Scripts/uv.lock` pins its exact version. Whoever clones the
|
|
195
|
+
game runs that version, in `Scripts/`:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
uv sync # install the game's rpgsync, and the scripts' tools
|
|
199
|
+
uv run rpgsync # run it
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
A CI job does the same: `uv sync --locked`, then `uv run --locked rpgsync ...`.
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
## Upgrading rpgsync
|
|
206
|
+
|
|
207
|
+
The `rpgsync` command:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
uv tool upgrade rpgsync
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
A game, in its `Scripts/` folder:
|
|
214
|
+
|
|
215
|
+
- **A fix release** (0.1.0 → 0.1.3) writes the same scripts:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
uv sync --upgrade-package rpgsync
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
then commit `uv.lock`.
|
|
222
|
+
- **A new minor version** (0.1.x → 0.2.0) writes the scripts differently. With
|
|
223
|
+
nothing pending (`rpgsync status`):
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
uv add "rpgsync~=0.2.0"
|
|
227
|
+
uv run rpgsync pull --force
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
then commit `pyproject.toml`, `uv.lock` and the rewritten scripts together.
|
|
231
|
+
|
|
232
|
+
[CHANGELOG.md](https://github.com/oulianov/rpgsync/blob/master/CHANGELOG.md) lists
|
|
233
|
+
what each version changes. An `rpgsync` command newer than a game's version would
|
|
234
|
+
rewrite its scripts in the newer format: on a game you don't upgrade yet, use
|
|
235
|
+
`uv run rpgsync` in its `Scripts/`.
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
## Learn more
|
|
239
|
+
|
|
240
|
+
- [Writing scripts](https://github.com/oulianov/rpgsync/blob/master/docs/scripts.md):
|
|
241
|
+
events and pages, variables and switches by name, the database, the map tree, big
|
|
242
|
+
scripts as folders
|
|
243
|
+
- [Checks and tests](https://github.com/oulianov/rpgsync/blob/master/docs/checks.md):
|
|
244
|
+
`rpgsync check`, the scripts' tests, resource files
|
|
245
|
+
- [DynRPG and DynParams](https://github.com/oulianov/rpgsync/blob/master/docs/dynrpg.md):
|
|
246
|
+
plugin calls, and a variable wherever RPG Maker takes a number
|
|
247
|
+
- [Patches](https://github.com/oulianov/rpgsync/blob/master/Patches.md): how each patch
|
|
248
|
+
shows in the scripts, and their settings
|
|
249
|
+
- [Tested games](https://github.com/oulianov/rpgsync/blob/master/Tested_Games.md)
|
|
250
|
+
- [Working on rpgsync](https://github.com/oulianov/rpgsync/blob/master/docs/development.md):
|
|
251
|
+
use your own rpgsync in a game, run its tests, release it
|
|
252
|
+
- [Changelog](https://github.com/oulianov/rpgsync/blob/master/CHANGELOG.md)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
## License
|
|
256
|
+
|
|
257
|
+
MIT, 2026: see [LICENSE](https://github.com/oulianov/rpgsync/blob/master/LICENSE). Source: https://github.com/oulianov/rpgsync
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "rpgsync"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "A Python twin of your RPG Maker 2000/2003 game"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
keywords = [
|
|
8
|
+
"rpg-maker",
|
|
9
|
+
"rpg-maker-2000",
|
|
10
|
+
"rpg-maker-2003",
|
|
11
|
+
"easyrpg",
|
|
12
|
+
"gamedev",
|
|
13
|
+
"dsl",
|
|
14
|
+
]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
"Environment :: Console",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Programming Language :: Python :: 3.14",
|
|
25
|
+
"Programming Language :: Python :: 3.15",
|
|
26
|
+
"Topic :: Games/Entertainment :: Role-Playing",
|
|
27
|
+
"Topic :: Software Development :: Code Generators",
|
|
28
|
+
"Typing :: Typed",
|
|
29
|
+
]
|
|
30
|
+
requires-python = ">=3.11"
|
|
31
|
+
dependencies = [
|
|
32
|
+
"pydantic>=2.14.0",
|
|
33
|
+
"rich>=15.0.0",
|
|
34
|
+
"ruff>=0.16.10",
|
|
35
|
+
"typer>=0.27.3",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[[project.authors]]
|
|
39
|
+
name = "Nicolas Oulianov"
|
|
40
|
+
|
|
41
|
+
[project.urls]
|
|
42
|
+
Homepage = "https://github.com/oulianov/rpgsync"
|
|
43
|
+
Repository = "https://github.com/oulianov/rpgsync"
|
|
44
|
+
Issues = "https://github.com/oulianov/rpgsync/issues"
|
|
45
|
+
Changelog = "https://github.com/oulianov/rpgsync/blob/master/CHANGELOG.md"
|
|
46
|
+
|
|
47
|
+
[project.scripts]
|
|
48
|
+
rpgsync = "rpgsync.cli:main"
|
|
49
|
+
|
|
50
|
+
[build-system]
|
|
51
|
+
requires = ["uv_build>=0.9,<0.14"]
|
|
52
|
+
build-backend = "uv_build"
|
|
53
|
+
|
|
54
|
+
[tool.uv.build-backend]
|
|
55
|
+
module-root = ""
|
|
56
|
+
source-include = [
|
|
57
|
+
"LICENSE",
|
|
58
|
+
"CHANGELOG.md",
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
[tool.pytest.ini_options]
|
|
62
|
+
testpaths = ["tests"]
|
|
63
|
+
addopts = "-n auto"
|
|
64
|
+
|
|
65
|
+
[tool.ruff]
|
|
66
|
+
line-length = 120
|
|
67
|
+
extend-exclude = [
|
|
68
|
+
"rpgsync/dbschema.py",
|
|
69
|
+
"rpgsync/db.py",
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
[tool.ruff.lint]
|
|
73
|
+
select = [
|
|
74
|
+
"E",
|
|
75
|
+
"F",
|
|
76
|
+
"W",
|
|
77
|
+
"I",
|
|
78
|
+
"UP",
|
|
79
|
+
"B",
|
|
80
|
+
]
|
|
81
|
+
ignore = [
|
|
82
|
+
"E501",
|
|
83
|
+
"UP031",
|
|
84
|
+
"B008",
|
|
85
|
+
"B905",
|
|
86
|
+
"E741",
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
[dependency-groups]
|
|
90
|
+
dev = [
|
|
91
|
+
"pytest>=9.1.1",
|
|
92
|
+
"pytest-xdist>=3.8.0",
|
|
93
|
+
"ruff>=0.16.10",
|
|
94
|
+
"ty>=0.0.85",
|
|
95
|
+
]
|