Skip to content

Commit 3cbffd9

Browse files
authored
1.0 dev (#7)
* 1.0 dev wip * v1.0 - support for minecraft 1.20.6 and 1.21
1 parent 7a6a8f5 commit 3cbffd9

File tree

117 files changed

+3918
-3654
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

117 files changed

+3918
-3654
lines changed

README.md

Lines changed: 113 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,124 @@
1-
# Babel Book Loot v0.5
1+
# Babel Book Loot v1.0
22
## A customisable pre-written book loot datapack for Minecraft
33

44
Babel Book Loot adds over 100 pre-written books to various loot tables in Minecraft. The default library of books is a collection of public domain fairy tales. You can customise the library by adding your own text files.
55

6-
It was last updated for Minecraft 1.18.2, but it should work in a wide range of versions.
6+
It was last updated for Minecraft 1.21.
77

88
## Quick-start
9-
Run `babel.py`. It will generate babel.zip. Put that file in your Minecraft world's datapack directory.
109

11-
Run `babel.py -h` to see more options.
10+
Download [babel_0.6.zip]() and place it in your Minecraft world's datapack directory.
11+
12+
If you don't want zombies dropping books, download [babel_0.6_no_zombies.zip]() instead.
1213

1314
## How the datapack works in-game
15+
1416
Written books can be dropped by zombies if killed by a player, or fished up with a fishing rod. They can also be found in villages, stronghold libraries and woodland mansions in chests.
1517

16-
The generation of the book is determined randomly
18+
The generation of the book is determined randomly:
1719
- 69% Tattered Book
1820
- 30% Copy of a copy
1921
- 1% Copy of original
2022
- <1% Original
2123

2224
## Customising Books
25+
26+
Run `py babel.py` (or `babel.exe` in windows.) this will output `babel.zip`. Put that file in your Minecraft world's datapack directory. Run `babel.py -h` to see more options.
27+
2328
Any books in the `books` directory will be included. You can add and remove books as you wish.
2429

25-
To create your own books go to https://minecraft.tools/en/book.php Once you've finished copy the command and delete the text `/give @p written_book` from the start. Then save it in `books` as `<Your Title>.json`.
30+
Book can be in JSON or YAML formats. Here is a simple example:
31+
32+
**sample_book.yaml**
33+
```
34+
title: Sample Book
35+
author: Some Author
36+
pages:
37+
- This is page one.
38+
- This is page two.
39+
- This is page three.
40+
```
41+
42+
**sample_book.json:**
43+
```
44+
{
45+
"title": "Sample Book",
46+
"author": "Some Author",
47+
"pages": [
48+
"This is page one.",
49+
"This is page two.",
50+
"This is page three."
51+
]
52+
}
53+
```
54+
55+
Minecraft accepts strictly non-valid JSON, so babel tries to too. Babel does it's best to read the books, but if it's having issues your best bet is to ensure the file is valid JSON.
56+
57+
### Advanced Books
58+
59+
You can do more advanced stuff with books if you need it.
60+
61+
#### Colors, formatting, etc.
62+
63+
Your pages can be in [Raw JSON text format](https://minecraft.wiki/w/Raw_JSON_text_format) e.g.
64+
65+
```
66+
{
67+
"title": "Sample Book",
68+
"author": "Some Author",
69+
"pages": [
70+
[{"text":"Hello ","color":"dark_red"},{"text":"World","bold":true},{"text":"!"}],
71+
]
72+
}
73+
```
74+
75+
#### Optional parameters
76+
77+
Book files can contain the following optional parameters:
78+
- `weight` - The chance this book will be selected vs others in the table. Default is `1`, so a value of `2` would mean the book is twice as likely to be selected.
79+
- `lore` - Item lore text. Works like `pages`.
80+
- `custom_model_data` - Sets item's custom_model_data value to allow the book a unique texture via a resource pack.
81+
- `custom_data` - Sets item's custom data. Can be a string containing nbt tags, or the tags themselves.
82+
83+
An example using all optional parameters:
84+
85+
```
86+
{
87+
"title": "Another Sample Book",
88+
"author": "Some Author",
89+
"pages": [
90+
"Hello World!",
91+
],
92+
"weight": 2,
93+
"lore": [
94+
[{"text":"Lore line 1","color":"blue"}],
95+
"Lore line 2"
96+
],
97+
"custom_model_data": 42,
98+
"custom_data": {
99+
"foo": "bar",
100+
"number": 16
101+
}
102+
}
103+
```
26104

27105
### Submitting books
28106
If you've made some books and the text is in the public domain, please consider submitting them back here!
29107

30108
### Default library
31109
The default collection of books was sourced from Project Gutenberg. https://www.gutenberg.org/
32110

111+
### Updating books from v0.5
112+
If you already have books in the v0.5 format, you can update them by running `update_books.py`. The books directory must only contain v0.5 format books. The script will also overwrite the originals, so keep a backup.
113+
33114
## Advanced Customisation
34115
### Altering where books will be found
35116
You can disable various book drops using command line options. Use `babel.py -h` to see the complete list. An example where zombies do not drop books:
36117
```
37118
babel.py -d zombie
38119
````
39120
40-
You can add books to other loot tables using type `loot_table` and name `babel:books`.
121+
You can add books to other loot tables using type `minecraft:loot_table` and value `babel:books`.
41122
42123
### Dealing with datapack conflicts
43124
If any of your other datapacks modify loot tables used by babel, it might be possible to create a compatible pack. To do this, replace the loot tables in the `base_loot_tables` with the ones from the conflicting datapack. This isn't guaranteed to work, and won't if the tables are much different from expected.
@@ -48,21 +129,36 @@ If you just want to generate the loot table without the surrounding files, try:
48129
build_loottable.py > books.json
49130
```
50131
51-
### Advanced Customising Books
52-
If you build your own datapacks, you have probably noticed the format of books the `books` directory is JSON. Minecraft accepts strictly non-valid JSON, so babel tries to too. Babel does it's best to read the books, but if it's having issues your best bet is to ensure the file is valid JSON.
53-
54-
The JSON determines the NBT tags to be added to the Written Book item. See the [full specification](https://minecraft.fandom.com/wiki/Player.dat_format#Written_Books) for more information. You could even add other tags such as `CustomModelData`.
55-
56-
Bonus tip: Babel actually uses a YAML parser to read the books, so you can format your books as YAML if you wish.
132+
### Full argument list:
133+
```
134+
usage: babel.py [-h] [-v] [-d {fishing,village,mansion,stronghold,zombie}]
135+
[-i] [-!] [filename]
136+
137+
positional arguments:
138+
filename Optional output zip filename. (default: babel.zip)
139+
140+
optional arguments:
141+
-h, --help show this help message and exit
142+
-v, --version show program's version number and exit
143+
-d {fishing,village,mansion,stronghold,zombie}
144+
Disable adding books to the given loot tables. Can be
145+
repeated to disable more than one.
146+
-i, --indent Indent output JSON files.
147+
-!, --no-wait Don't wait for user input when finished. Triggered
148+
automatically by using any other argument. (Windows
149+
version only.)
150+
```
57151
58152
## Comments, suggestions or contributions?
59-
Please use the Issue Tracker on GitHub, or send me a tweet [@JiFish](https://twitter.com/intent/tweet?text=.@JiFish)
153+
Please use the Issue Tracker on GitHub, or send me a tweet [@JiFish](https://twitter.com/intent/tweet?text=.@JiFish) or Toot [@joe@social.jifish.co.uk](https://social.jifish.co.uk/@joe).
60154
61155
## Copyright & use in your own datapacks
62-
Assuming the books are your own work, loot tables outputted by babel belong to you. You can use them freely in your own datapack. A credit is apprecicated, but not required.
156+
Assuming the books are your own work, loot tables outputted by babel belong to you. You can use them freely in your own datapack. A credit is very appreciated, but not required.
63157
64-
Books in the `books` directory are in the public domain. The loot table created from them is also in the public domain.
158+
Books in the `books` directory are in the public domain. The `books.json` file created from them is also in the public domain.
65159
66160
The babel tool and datapack is copyright Joseph Fowler.
67161
68-
Disclaimer: Software provided is "as is", without a warranty, and should be used at your own risk.
162+
## Disclaimer
163+
164+
Software provided is "as is", without a warranty, and should be used at your own risk.

babel.py

Lines changed: 42 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,64 @@
1-
import zipfile
2-
import json
31
import argparse
42
import sys
3+
from build_datapack import *
54

65
isCompiled = getattr(sys, 'frozen', False)
76
isUsingDefaults = (len(sys.argv) < 2)
87
validLootTableList = ['fishing', 'village', 'mansion', 'stronghold', 'zombie']
9-
greeting = "Babel Book Loot Generator, v0.5%s" % (' (Windows)' if isCompiled else '')
8+
greeting = "Babel Book Loot Generator, v1.0%s" % (' (Windows)' if isCompiled else '')
109

11-
print("\n"+greeting)
12-
print("="*len(greeting)+"\n")
10+
def restricted_float(x):
11+
error = "%r not a value between 0.0 and 1.0"
12+
try:
13+
x = float(x)
14+
except ValueError:
15+
raise argparse.ArgumentTypeError(error % x)
16+
17+
if x < 0.0 or x > 1.0:
18+
raise argparse.ArgumentTypeError(error % x)
19+
return x
1320

1421
parser = argparse.ArgumentParser()
15-
parser.add_argument('filename', help='Optional output zip filename. Default: babel.zip', nargs='?', default='babel.zip')
16-
parser.add_argument('-d', dest="loottable", default=[], action='append', help='Disable adding books to one of the following loot tables: '+
17-
', '.join(validLootTableList)+'. Can be repeated to disable more than one.')
18-
parser.add_argument('-c', '--clean', help='Indent output JSON files.', action='store_true')
22+
parser.add_argument('filename', help='Optional output zip filename. (default: %(default)s)', nargs='?', default='babel.zip')
23+
parser.add_argument('-v', '--version', action='version', version=greeting)
24+
parser.add_argument('-d', dest="loottable", default=[], action='append', choices=validLootTableList,
25+
help='Disable adding books to the given loot tables. Can be repeated to disable more than one.')
26+
# parser.add_argument('--gen2', action='store', type=restricted_float, default=0.3, metavar="CHANCE",
27+
# help="Chance a book will be marked as a 'Copy of a copy', between 0.0 and 1.0. (default: %(default)s)")
28+
# parser.add_argument('--gen1', action='store', type=restricted_float, default=0.01, metavar="CHANCE",
29+
# help="Chance a book will be marked as a 'Copy of original', between 0.0 and 1.0. (default: %(default)s)")
30+
# parser.add_argument('--gen0', action='store', type=restricted_float, default=0.003, metavar="CHANCE",
31+
# help="Chance a book will be marked as an 'Original', between 0.0 and 1.0. (default: %(default)s)")
32+
#parser.add_argument('-l', '--loottable', action='store_true',
33+
# help="Don't build the datapack, instead just output the loot table. The default filename is books.json.")
34+
parser.add_argument('-i', '--indent', help='Indent output JSON files.', action='store_true')
1935
if isCompiled:
20-
parser.add_argument('-!', '--no-wait', help="Don't wait for user input at the end of the build. Triggered automatically by using any other argument.",
21-
action='store_true')
36+
parser.add_argument('-!', '--no-wait', action='store_true',
37+
help="Don't wait for user input when finished. Triggered automatically by using any other argument.")
2238
args = parser.parse_args()
2339

24-
if set(args.loottable).issubset(validLootTableList) == False:
25-
print("ERROR: Invalid input on -d argument\n")
26-
parser.print_help()
27-
exit(1)
28-
29-
if args.clean:
40+
if args.indent:
3041
indent = 4
3142
else:
3243
indent = None
3344

45+
print("\n"+greeting)
46+
print("="*len(greeting)+"\n")
47+
3448
if isUsingDefaults:
3549
print("Using default configuration, for more options try %s -h\n" % sys.argv[0])
3650

37-
print ("Importing Books... (This may take a while.)")
38-
from build_loottable import loottable
39-
print ("Found %d books." % len(loottable['pools'][0]['entries']))
51+
try:
52+
from build_loottable import loottable
53+
print ("Found %d books." % len(loottable['pools'][0]['entries']))
4054

41-
def addToLootTable(lootfilename, weight = 1, pool = 0):
42-
global indent
43-
with open('base_loot_tables/'+lootfilename, 'r') as lootfile:
44-
lootjson = json.loads(lootfile.read())
45-
lootjson['pools'][pool]['entries'].append({
46-
'type': 'loot_table',
47-
'weight': weight,
48-
"name": "babel:books"
49-
})
50-
return json.dumps(lootjson, indent=indent, ensure_ascii=False)
55+
print ("Building datapack...")
56+
buildDatapack(args.filename, args.loottable, loottable, indent=indent)
57+
print ("\nDatapack build complete! Copy %s to your world's datapack directory." % args.filename)
5158

52-
print ("Building datapack...")
53-
zf = zipfile.ZipFile(args.filename, mode='w')
54-
zf.writestr('pack.mcmeta', json.dumps({
55-
"pack": {
56-
"pack_format": 9,
57-
"description": "Add pre-written books to your vanilla world"
58-
}
59-
}, indent=indent, ensure_ascii=False))
60-
zf.writestr('data/babel/loot_tables/books.json', json.dumps(loottable, indent=indent, ensure_ascii=False))
61-
if 'stronghold' not in args.loottable:
62-
print ("Adding to Stronghold Library loot table.")
63-
zf.writestr('data/minecraft/loot_tables/chests/stronghold_library.json', addToLootTable('stronghold_library.json',15))
64-
if 'mansion' not in args.loottable:
65-
print ("Adding to Woodland Mansion loot table.")
66-
zf.writestr('data/minecraft/loot_tables/chests/woodland_mansion.json', addToLootTable('woodland_mansion.json',5))
67-
if 'village' not in args.loottable:
68-
print ("Adding to Village loot table.")
69-
zf.writestr('data/minecraft/loot_tables/chests/village/village_desert_house.json', addToLootTable('village_desert_house.json',3))
70-
zf.writestr('data/minecraft/loot_tables/chests/village/village_plains_house.json', addToLootTable('village_plains_house.json',3))
71-
zf.writestr('data/minecraft/loot_tables/chests/village/village_savanna_house.json', addToLootTable('village_savanna_house.json',3))
72-
zf.writestr('data/minecraft/loot_tables/chests/village/village_snowy_house.json', addToLootTable('village_snowy_house.json',3))
73-
zf.writestr('data/minecraft/loot_tables/chests/village/village_taiga_house.json', addToLootTable('village_taiga_house.json',3))
74-
if 'fishing' not in args.loottable:
75-
print ("Adding to Fishing Treasure loot table.")
76-
zf.writestr('data/minecraft/loot_tables/gameplay/fishing/treasure.json', addToLootTable('treasure.json',1))
77-
if 'zombie' not in args.loottable:
78-
print ("Adding to Zombie drop loot table.")
79-
zf.writestr('data/minecraft/loot_tables/entities/zombie.json', addToLootTable('zombie.json',1,1))
80-
zf.close()
81-
print ("\nDatapack build complete! Copy %s to your world's datapack directory." % args.filename)
59+
except Exception as e:
60+
print("\nError: "+str(e))
8261

83-
if isCompiled and isUsingDefaults:
84-
input("\nPress ENTER or close this window.")
62+
finally:
63+
if isCompiled and isUsingDefaults:
64+
input("\nPress ENTER or close this window.")

0 commit comments

Comments
 (0)