├── .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 | Lorem ipsum preview book 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 | --------------------------------------------------------------------------------