├── .github
└── FUNDING.yml
├── text.txt
├── LICENSE
├── .gitignore
├── README.md
└── text2mcbook.py
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | ko_fi: Neocky
4 |
--------------------------------------------------------------------------------
/text.txt:
--------------------------------------------------------------------------------
1 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
2 | sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
3 | sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Neocky
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.
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | pip-wheel-metadata/
24 | share/python-wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .nox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | *.py,cover
51 | .hypothesis/
52 | .pytest_cache/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | target/
76 |
77 | # Jupyter Notebook
78 | .ipynb_checkpoints
79 |
80 | # IPython
81 | profile_default/
82 | ipython_config.py
83 |
84 | # pyenv
85 | .python-version
86 |
87 | # pipenv
88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
91 | # install all needed dependencies.
92 | #Pipfile.lock
93 |
94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95 | __pypackages__/
96 |
97 | # Celery stuff
98 | celerybeat-schedule
99 | celerybeat.pid
100 |
101 | # SageMath parsed files
102 | *.sage.py
103 |
104 | # Environments
105 | .env
106 | .venv
107 | env/
108 | venv/
109 | ENV/
110 | env.bak/
111 | venv.bak/
112 |
113 | # Spyder project settings
114 | .spyderproject
115 | .spyproject
116 |
117 | # Rope project settings
118 | .ropeproject
119 |
120 | # mkdocs documentation
121 | /site
122 |
123 | # mypy
124 | .mypy_cache/
125 | .dmypy.json
126 | dmypy.json
127 |
128 | # Pyre type checker
129 | .pyre/
130 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Text2McBook
9 |
10 |
11 | 📚 Convert any text file to a formatted text for minecraft books to use them as easily as possible ingame.
12 |
13 | ## Issues? Found a bug?
14 |
15 | [Create an issue.](https://github.com/Neocky/Text2McBook/issues/new/choose)
16 |
17 | ## About
18 |
19 | This script will convert text from a text file to a formatted minecraft book file. The file contains a native `/give` command which can be used ingame to get a `writable_book` with the text as content.
20 | It supports different book formats which can be chosen with the parameter [`-f FORMATNAME`](https://github.com/Neocky/Text2McBook#parmaters).
21 | I got inspiration from a post from [r/admincraft](https://www.reddit.com/r/admincraft/).
22 |
23 | ### Default
24 |
25 | The `default` format will create a `/give` command which can be easily copied into a command block ingame to get the writable book.
26 | It will also format the text in a way in which it can be easily copy and pasted in a book in the game.
27 |
28 | ### Denizen
29 |
30 | [Denizen](https://denizenscript.com/) is a scripting plugin for minecraft servers.
31 | The `denizen` format will format the text for the `text` property in [Book Script Containers](https://meta.denizenscript.com/Docs/Search/book#book%20script%20containers). It will replace new line symbols with `` and indents the line with 4 spaces to make it easily pasteable in the `text` properties of `book script containers`.
32 |
33 | ## Installation
34 |
35 | ### Python
36 |
37 | Python (minimum: Version 3.10.4) needs to be installed on your machine.
38 | Get it [here](https://www.python.org/downloads/).
39 |
40 | ### Clone the repository / Download the latest release
41 |
42 | Download the script:
43 | Clone the repository or get the latest release [here](https://github.com/Neocky/Text2McBook/releases).
44 |
45 | ## Usage
46 |
47 | Create/edit the text file in the same folder where the python script is with the name `text.txt` and add your book text in there.
48 | This is the text that you want to be converted to a minecraft book format.
49 | Run the script: `text2mcbook.py`.
50 | Now a `booktext.txt` file should be created.
51 | In there is a `/give` command which can be inputted into a command block to get the book. There is also the formatted text which you can easily copy & paste in a book in minecraft.
52 |
53 |
54 | ## Advanced Usage
55 |
56 | ### Parametrs
57 |
58 | This script supports the following parameters to change the usage for the script.
59 |
60 | #### Get help about all available parameters
61 |
62 | ```shell
63 | py text2mcbook.py -h
64 | ```
65 |
66 | #### Input file
67 |
68 | ```shell
69 | py text2mcbook.py INPUTFILENAME
70 | ```
71 |
72 | Default: `text.txt`
73 | Changes the input file.
74 |
75 | #### Output file
76 |
77 | ```shell
78 | py text2mcbook.py INPUTFILENAME OUTPUTFILENAME
79 | ```
80 |
81 | Default: `booktext.txt`
82 | Changes the output file.
83 |
84 | #### Book format
85 |
86 | ```shell
87 | py text2mcbook.py -f FORMAT
88 | py text2mcbook.py --format FORMAT
89 | ```
90 |
91 | Default: `default`
92 | Possible Values: `default`, `denizen`
93 | Changes the book format and the resulting formatting.
94 |
95 | #### Characters per line
96 |
97 | ```shell
98 | py text2mcbook.py -c NUMBEROFCHARACTERSPERLINE
99 | py text2mcbook.py --characterlimit NUMBEROFCHARACTERSPERLINE
100 | ```
101 |
102 | Default: `19`
103 | The number of characters one book line can have.
104 | Warning: Don't set it to high or you are risking the loss of words!
105 |
106 | ### Examples
107 |
108 | #### Example 1
109 | ```shell
110 | py text2mcbook.py book_to_convert.txt book_formatted.txt
111 | ```
112 |
113 | Changes the input file to `book_to_convert.txt` and outupts the formatted book text to `book_formatted.txt`.
114 |
115 | #### Example 2
116 |
117 | ```shell
118 | py text2mcbook.py -f denizen -c 20
119 | ```
120 |
121 | Outputs denizen formated text, which can be used in the `text` propert of [Book Script Containers](https://meta.denizenscript.com/Docs/Search/book#book%20script%20containers) in [Denizen](https://denizenscript.com/). Also changes the number of characters per line to 20.
122 |
--------------------------------------------------------------------------------
/text2mcbook.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import argparse
3 | import textwrap
4 |
5 |
6 | def main(input_filename, output_filename, format, characters_per_line) -> None:
7 | try:
8 | with open(input_filename, encoding="utf-8") as f:
9 | text = f.read()
10 |
11 | except FileNotFoundError as exception:
12 | print(f"Error: {type(exception).__name__}")
13 | print(f"Error message: {exception}")
14 | sys.exit()
15 |
16 | # print warning if characters per line is too high, which could risk in missing words
17 | if characters_per_line >= 21:
18 | print("Warning: Setting '--charactersperline // -c' too high could result in missing words in books!")
19 |
20 | # split lines every x character
21 | lines = textwrap.wrap(text, characters_per_line)
22 | book_pages = []
23 | current_book_page = ""
24 |
25 | for line in range(len(lines)):
26 | # every page consists of 14 lines
27 | line_count = line % 14
28 | if line_count == 0 and current_book_page:
29 | book_pages.append(current_book_page)
30 | current_book_page = ""
31 | # create placeholder for linebreaks which gets later replaced
32 | current_book_page += lines[line] + ""
33 | # print last book page
34 | if current_book_page:
35 | book_pages.append(current_book_page)
36 |
37 | # create output
38 | with open(output_filename, "w", encoding="utf-8") as book_text:
39 | book_text.write("Made with Text2McBook by Neocky | https://github.com/Neocky/Text2McBook/\n\n")
40 | book_text.write(f"Format: {str(format).lower()}\n")
41 | book_text.write(f"Characters per line: {characters_per_line}\n\n")
42 | match str(format).lower():
43 | # could add more formats here
44 | # Denizen | https://denizenscript.com/ | scripting plugin for minecraft servers
45 | case "denizen":
46 | book_text.write("\n")
47 | for current_book_page in book_pages:
48 | # replace new line character with which stands for a new line in a book script container in denizen
49 | # already indent line with 4 spaces to work easily with text property of book container: https://meta.denizenscript.com/Docs/Search/book#book%20script%20containers
50 | current_book_page = current_book_page.replace("", "")
51 | book_text.write(f" - {current_book_page}\n")
52 |
53 | # Default minecraft book format with give command
54 | case _:
55 | # add give command for the book
56 | # book pages could have less than 14 lines, because we just use a space " " instead of an actual line break symbol here
57 | mc_give_command_all_pages = str(book_pages).replace("", " ")
58 | mc_give_command = f"/give @p writable_book{{pages:{mc_give_command_all_pages}}} 1"
59 | book_text.write(f"Give command:\n{mc_give_command}\n\n")
60 |
61 | # output book in a copy friendly format
62 | for i, current_book_page in enumerate(book_pages, start=1):
63 | # replace new line placeholder with actual new line and output to file
64 | current_book_page = current_book_page.replace("", "\n")
65 | book_text.write(f"\n ### Page: {i} ###\n")
66 | book_text.write(f"{current_book_page}\n")
67 |
68 | # check if book could be unsupported
69 | if len(book_pages) > 100:
70 | print(f"Warning: Book has more than 100 pages ({len(book_pages)})! Using the GUI, a player can write a single book up to 100[Java Edition only] or 50[Bedrock Edition only] pages long!")
71 |
72 | print(f"Text2McBook convertion of '{input_filename}' with format '{str(format).lower()}' completed! Outputfile: {output_filename}")
73 |
74 |
75 | if __name__ == "__main__":
76 | parser = argparse.ArgumentParser(description="Arguments for Text2McBook",
77 | formatter_class=argparse.ArgumentDefaultsHelpFormatter)
78 | parser.add_argument("file", nargs="?", help="Filename of textfile which should be converted to minecraft book format", default="text.txt")
79 | parser.add_argument("outputfile", nargs="?", help="Filename of output textfile ", default="booktext.txt")
80 | parser.add_argument("-f", "--format", nargs="?", help="Book format [default, denizen]", default="default")
81 | parser.add_argument("-c", "--characterlimit", nargs="?", type=int, help="Characters per book line", default=19)
82 | args = parser.parse_args()
83 |
84 | main(input_filename=args.file, output_filename=args.outputfile, format=args.format, characters_per_line=args.characterlimit)
85 |
--------------------------------------------------------------------------------