Release BuildBattle maps
This commit is contained in:
1 parent
2ac0de9905
commit
f05b4ee2c4
30 files changed
+477
No files matched your search
@@ -0,0 +1,72 @@
|
||||
# Libers97 / Green Leave Lobby Attribution Notice
|
||||
|
||||
Copyright © Libers97.
|
||||
|
||||
This project includes or is derived from **Green Leave Lobby**, a Minecraft map originally created by **Libers97**.
|
||||
|
||||
## Original Work
|
||||
|
||||
**Title:** Green Leave Lobby
|
||||
|
||||
**Creator:** Libers97
|
||||
|
||||
## Original Description
|
||||
|
||||
> Hey Guys,
|
||||
>
|
||||
> I am back with a new Map for YOU,
|
||||
> Yes its free to use whereever you want, but you must give me credit.
|
||||
>
|
||||
> It is a lobby, basicly out of clay, wood, leave and stone.
|
||||
> Build in 2 hours in a Void map.
|
||||
|
||||
## License
|
||||
|
||||
The original work was published under the **Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)** license.
|
||||
|
||||
This project redistributes or adapts the work in accordance with that license.
|
||||
|
||||
### License Summary
|
||||
|
||||
You are free to:
|
||||
|
||||
- **Share** — copy and redistribute the material in any medium or format.
|
||||
- **Adapt** — remix, transform, and build upon the material for any purpose, including commercial use.
|
||||
|
||||
Under the following terms:
|
||||
|
||||
- **Attribution** — You must give appropriate credit, provide a link to the license, and indicate if changes were made.
|
||||
- **ShareAlike** — If you remix, transform, or build upon the material, you must distribute your contributions under the same license.
|
||||
|
||||
No additional legal or technological restrictions may be applied that prevent others from exercising the rights granted by the license.
|
||||
|
||||
The complete legal text of the license is available at:
|
||||
|
||||
https://creativecommons.org/licenses/by-sa/3.0/legalcode
|
||||
|
||||
A human-readable summary is available at:
|
||||
|
||||
https://creativecommons.org/licenses/by-sa/3.0/
|
||||
|
||||
## Attribution
|
||||
|
||||
When redistributing this project or substantial portions of this work, include at least the following attribution:
|
||||
|
||||
> Green Leave Lobby by Libers97, licensed under CC BY-SA 3.0.
|
||||
|
||||
## Modifications
|
||||
|
||||
This project may package, convert, adapt, modify, or otherwise incorporate the original work for use in a Minecraft server, plugin, or related software project.
|
||||
|
||||
Unless explicitly stated otherwise, all such modifications are the responsibility of this project and not of Libers97.
|
||||
|
||||
## No Endorsement
|
||||
|
||||
Use of this work does not imply endorsement by Libers97.
|
||||
|
||||
## Source
|
||||
|
||||
Original publication:
|
||||
|
||||
- Planet Minecraft — Green Leave Lobby [Libers97] (Free)
|
||||
https://www.planetminecraft.com/project/green-leave-lobby-free-to-use-libers97/
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,53 @@
|
||||
#Single Player Commands - Settings
|
||||
#Sat Jul 14 11:22:55 CST 2012
|
||||
textcolorrandom=0123456789abcdef
|
||||
flymode=dynamic
|
||||
noclip=false
|
||||
infiniteitems=false
|
||||
falldamage=true
|
||||
creeperexplosion=true
|
||||
engine=JavaScript
|
||||
disablehunger=false
|
||||
previousz=0.0
|
||||
previousy=0.0
|
||||
mobdamage=true
|
||||
previousx=0.0
|
||||
weather=true
|
||||
textcolornormal=f
|
||||
limitstack=false
|
||||
criticalhit=false
|
||||
norepair=false
|
||||
instantkill=false
|
||||
lastrift=-1
|
||||
sizeheight=962
|
||||
monsterspawn=true
|
||||
output=true
|
||||
stepheight=0.5
|
||||
prevgravity=1.0
|
||||
disablecommands=false
|
||||
prevspeed=1.0
|
||||
sprinting=false
|
||||
waterdamage=true
|
||||
startup=
|
||||
toggledropgive=true
|
||||
lastcommand=fly
|
||||
instantgrow=false
|
||||
mobsfrozen=false
|
||||
sizewidth=1280
|
||||
textcolorerror=4
|
||||
fly=false
|
||||
gravity=1.0
|
||||
animalspawn=true
|
||||
speed=1.0
|
||||
harvestitems=true
|
||||
instant=false
|
||||
superpunch=-1.0
|
||||
timespeed=0
|
||||
watermovement=true
|
||||
damage=true
|
||||
reachdistance=50.0
|
||||
updateson=true
|
||||
laddermode=false
|
||||
keepitems=false
|
||||
instantplant=false
|
||||
firedamage=false
|
||||
@@ -0,0 +1 @@
|
||||
{"stat.useItem.18":760,"stat.useItem.35":771,"stat.useItem.17":1657,"stat.useItem.323":22,"stat.useItem.85":29,"achievement.openInventory":53,"stat.useItem.145":5,"stat.useItem.89":85,"stat.jump":783,"achievement.exploreAllBiomes":{"value":0,"progress":["Ocean","Plains","River"]},"stat.useItem.1":2025,"stat.damageTaken":1720,"stat.useItem.3":294,"stat.useItem.4":25,"stat.useItem.5":31,"stat.deaths":1,"stat.useItem.76":5,"stat.useItem.109":813,"stat.useItem.389":9,"stat.useItem.77":14,"stat.useItem.126":5,"stat.drop":12,"stat.useItem.159":1654,"stat.flyOneCm":1272565,"stat.useItem.134":209,"stat.useItem.98":499,"stat.useItem.139":698,"stat.useItem.331":72,"stat.useItem.49":2,"stat.useItem.46":64,"stat.walkOneCm":603593,"stat.useItem.351":22,"stat.useItem.44":1282,"stat.useItem.67":10,"stat.useItem.397":2,"stat.playOneMinute":242038}
|
||||
@@ -0,0 +1,24 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <https://unlicense.org>
|
||||
@@ -0,0 +1,110 @@
|
||||
# Plaza
|
||||
|
||||
An open source BuildBattle-OG arena map for Purpur 1.19.4: twelve build plots in a ring
|
||||
around a central plaza, floating in the void. Generated by `gen_plaza.py` (this folder's
|
||||
`tools/` copy) from the public-domain `Template_World`, so every block here is
|
||||
[Unlicense](LICENSE.md) / public domain.
|
||||
|
||||
## Layout
|
||||
|
||||
| Element | Position |
|
||||
|---|---|
|
||||
| Plot floors | y = 64, 31 x 31 oak logs, plot cuboid y 64..96 |
|
||||
| Plot frame | 1-block polished deepslate ring outside the cuboid, sea lantern corners |
|
||||
| Plaza | 41 x 41 smooth stone at y = 64, centre (0, 64, 0), barrier rail three high |
|
||||
| Start / spectator spot | `0.5, 65, 0.5` |
|
||||
| Plot pitch | 44 blocks between centres, 13 blocks of gap |
|
||||
|
||||
The plugin regenerates every plot floor from its cuboid's lowest layer using
|
||||
`Floor.Material` (`log` by default), so the oak floor is what a reset produces too. Frames and
|
||||
pedestals sit outside the cuboids and survive resets.
|
||||
|
||||
Plot cuboids (min corner, max corner):
|
||||
|
||||
| # | min | max |
|
||||
|---|---|---|
|
||||
| 0 | -81, 64, -81 | -51, 96, -51 |
|
||||
| 1 | -37, 64, -81 | -7, 96, -51 |
|
||||
| 2 | 7, 64, -81 | 37, 96, -51 |
|
||||
| 3 | 51, 64, -81 | 81, 96, -51 |
|
||||
| 4 | -81, 64, -37 | -51, 96, -7 |
|
||||
| 5 | 51, 64, -37 | 81, 96, -7 |
|
||||
| 6 | -81, 64, 7 | -51, 96, 37 |
|
||||
| 7 | 51, 64, 7 | 81, 96, 37 |
|
||||
| 8 | -81, 64, 51 | -51, 96, 81 |
|
||||
| 9 | -37, 64, 51 | -7, 96, 81 |
|
||||
| 10 | 7, 64, 51 | 37, 96, 81 |
|
||||
| 11 | 51, 64, 51 | 81, 96, 81 |
|
||||
|
||||
## Deploying
|
||||
|
||||
1. Copy this folder to the server root as `BB1-map` and `BB1_Hub` as `BB1-hub`, then register
|
||||
both with MyWorlds (`/mw load BB1-map`, `/mw load BB1-hub`). The live `worlds.yml` already
|
||||
lists both with the `Splegg-OG:void` chunk generator, so ungenerated chunks stay void.
|
||||
2. Merge `arenas.yml` below into `plugins/BuildBattle-OG/arenas.yml`, run `/bba reload`.
|
||||
3. Lobby and end locations point at the Green Leave Lobby spawn in `BB1-hub`; move them with
|
||||
`/bba setup edit BB1` if the hub changes.
|
||||
|
||||
```yaml
|
||||
instances:
|
||||
BB1:
|
||||
lobbylocation: BB1-hub,-2.5,64.0,1.5,0.0,0.0
|
||||
startlocation: BB1-map,0.5,65.0,0.5,0.0,0.0
|
||||
endlocation: BB1-hub,-2.5,64.0,1.5,0.0,0.0
|
||||
spectatorlocation: BB1-map,0.5,65.0,0.5,0.0,0.0
|
||||
minimumplayers: 2
|
||||
maximumplayers: 12
|
||||
plotmembersize: 1
|
||||
mapname: Plaza
|
||||
world: BB1-map
|
||||
gametype: classic
|
||||
isdone: true
|
||||
signs: {}
|
||||
plots:
|
||||
'0':
|
||||
'1': BB1-map,-81.0,64.0,-81.0,0.0,0.0
|
||||
'2': BB1-map,-51.0,96.0,-51.0,0.0,0.0
|
||||
'1':
|
||||
'1': BB1-map,-37.0,64.0,-81.0,0.0,0.0
|
||||
'2': BB1-map,-7.0,96.0,-51.0,0.0,0.0
|
||||
'2':
|
||||
'1': BB1-map,7.0,64.0,-81.0,0.0,0.0
|
||||
'2': BB1-map,37.0,96.0,-51.0,0.0,0.0
|
||||
'3':
|
||||
'1': BB1-map,51.0,64.0,-81.0,0.0,0.0
|
||||
'2': BB1-map,81.0,96.0,-51.0,0.0,0.0
|
||||
'4':
|
||||
'1': BB1-map,-81.0,64.0,-37.0,0.0,0.0
|
||||
'2': BB1-map,-51.0,96.0,-7.0,0.0,0.0
|
||||
'5':
|
||||
'1': BB1-map,51.0,64.0,-37.0,0.0,0.0
|
||||
'2': BB1-map,81.0,96.0,-7.0,0.0,0.0
|
||||
'6':
|
||||
'1': BB1-map,-81.0,64.0,7.0,0.0,0.0
|
||||
'2': BB1-map,-51.0,96.0,37.0,0.0,0.0
|
||||
'7':
|
||||
'1': BB1-map,51.0,64.0,7.0,0.0,0.0
|
||||
'2': BB1-map,81.0,96.0,37.0,0.0,0.0
|
||||
'8':
|
||||
'1': BB1-map,-81.0,64.0,51.0,0.0,0.0
|
||||
'2': BB1-map,-51.0,96.0,81.0,0.0,0.0
|
||||
'9':
|
||||
'1': BB1-map,-37.0,64.0,51.0,0.0,0.0
|
||||
'2': BB1-map,-7.0,96.0,81.0,0.0,0.0
|
||||
'10':
|
||||
'1': BB1-map,7.0,64.0,51.0,0.0,0.0
|
||||
'2': BB1-map,37.0,96.0,81.0,0.0,0.0
|
||||
'11':
|
||||
'1': BB1-map,51.0,64.0,51.0,0.0,0.0
|
||||
'2': BB1-map,81.0,96.0,81.0,0.0,0.0
|
||||
```
|
||||
|
||||
## Regenerating
|
||||
|
||||
```
|
||||
python3 -m venv venv && venv/bin/pip install nbtlib
|
||||
venv/bin/python tools/gen_plaza.py /path/to/output/Plaza
|
||||
```
|
||||
|
||||
Edit the constants at the top of the script (plot size, pitch, blocks) and rerun; the script
|
||||
rebuilds the region files from `Template_World` every time.
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"pack": {
|
||||
"description": "Data pack for resources provided by Bukkit plugins",
|
||||
"pack_format": 12
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,6 @@
|
||||
# This is a world configuration file for Paper.
|
||||
# This file may start empty but can be filled with settings to override ones in the config/paper-world-defaults.yml
|
||||
#
|
||||
# World: Ancient_Plateau (minecraft:overworld)
|
||||
|
||||
_version: 30
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,205 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate the Plaza BuildBattle map: 12 build plots in a ring around a central plaza.
|
||||
|
||||
Writes 1.19.4 (DataVersion 3337) Anvil region files. Heightmaps and light are left
|
||||
for the server to compute on first load.
|
||||
"""
|
||||
import io, math, os, shutil, sys, zlib, time
|
||||
import nbtlib
|
||||
from nbtlib import Compound, List, String, Int, Long, Byte, LongArray, ByteArray
|
||||
|
||||
SRC = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', 'Template_World')
|
||||
DST = sys.argv[1] if len(sys.argv) > 1 else os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'build', 'Plaza')
|
||||
DATA_VERSION = 3337
|
||||
BIOME = 'minecraft:the_void'
|
||||
|
||||
# ---- layout ---------------------------------------------------------------
|
||||
PLOT_HALF = 15 # 31x31 floor
|
||||
PLOT_FLOOR_Y = 64
|
||||
PLOT_TOP_Y = 96 # cuboid max Y (33 layers of air incl. floor layer)
|
||||
PITCH = 44 # distance between plot centres (31 + 13 gap)
|
||||
CENTRES = [-66, -22, 22, 66]
|
||||
PLOTS = [] # (cx, cz)
|
||||
for cz in CENTRES:
|
||||
for cx in CENTRES:
|
||||
if abs(cx) == 22 and abs(cz) == 22:
|
||||
continue # inner 2x2 left open for the plaza
|
||||
PLOTS.append((cx, cz))
|
||||
assert len(PLOTS) == 12
|
||||
PLAZA_HALF = 20 # 41x41
|
||||
SPAWN = (0.5, 65.0, 0.5)
|
||||
|
||||
FLOOR = 'minecraft:oak_log' # BuildBattle-OG Floor.Material default (log -> oak_log)
|
||||
FRAME = 'minecraft:polished_deepslate'
|
||||
CORNER = 'minecraft:sea_lantern'
|
||||
PED1 = 'minecraft:stone_bricks'
|
||||
PED2 = 'minecraft:deepslate_bricks'
|
||||
PED3 = 'minecraft:deepslate_tiles'
|
||||
PED4 = 'minecraft:deepslate'
|
||||
PLAZA_FLOOR = 'minecraft:smooth_stone'
|
||||
PLAZA_RING = 'minecraft:polished_deepslate'
|
||||
PLAZA_INLAY = 'minecraft:polished_andesite'
|
||||
PLAZA_CENTER = 'minecraft:sea_lantern'
|
||||
BARRIER = 'minecraft:barrier'
|
||||
|
||||
blocks = {} # (x, y, z) -> block id
|
||||
|
||||
def fill(x1, y1, z1, x2, y2, z2, block):
|
||||
for x in range(min(x1, x2), max(x1, x2) + 1):
|
||||
for y in range(min(y1, y2), max(y1, y2) + 1):
|
||||
for z in range(min(z1, z2), max(z1, z2) + 1):
|
||||
blocks[(x, y, z)] = block
|
||||
|
||||
def ring(cx, cz, half, y, block):
|
||||
fill(cx - half, y, cz - half, cx + half, y, cz - half, block)
|
||||
fill(cx - half, y, cz + half, cx + half, y, cz + half, block)
|
||||
fill(cx - half, y, cz - half, cx - half, y, cz + half, block)
|
||||
fill(cx + half, y, cz - half, cx + half, y, cz + half, block)
|
||||
|
||||
def pedestal(cx, cz, half, top_y):
|
||||
# tapered island under a platform whose outer edge is `half`
|
||||
layers = [(half, PED1), (half - 2, PED2), (half - 4, PED2), (half - 7, PED3),
|
||||
(half - 10, PED4), (half - 13, PED4), (half - 15, PED4)]
|
||||
y = top_y - 1
|
||||
for h, block in layers:
|
||||
if h < 1:
|
||||
break
|
||||
fill(cx - h, y, cz - h, cx + h, y, cz + h, block)
|
||||
y -= 1
|
||||
|
||||
def plot(cx, cz):
|
||||
fill(cx - PLOT_HALF, PLOT_FLOOR_Y, cz - PLOT_HALF, cx + PLOT_HALF, PLOT_FLOOR_Y, cz + PLOT_HALF, FLOOR)
|
||||
ring(cx, cz, PLOT_HALF + 1, PLOT_FLOOR_Y, FRAME)
|
||||
for dx in (-1, 1):
|
||||
for dz in (-1, 1):
|
||||
blocks[(cx + dx * (PLOT_HALF + 1), PLOT_FLOOR_Y, cz + dz * (PLOT_HALF + 1))] = CORNER
|
||||
pedestal(cx, cz, PLOT_HALF + 1, PLOT_FLOOR_Y)
|
||||
|
||||
def plaza():
|
||||
fill(-PLAZA_HALF, PLOT_FLOOR_Y, -PLAZA_HALF, PLAZA_HALF, PLOT_FLOOR_Y, PLAZA_HALF, PLAZA_FLOOR)
|
||||
ring(0, 0, PLAZA_HALF, PLOT_FLOOR_Y, PLAZA_RING)
|
||||
ring(0, 0, 12, PLOT_FLOOR_Y, PLAZA_INLAY)
|
||||
ring(0, 0, 6, PLOT_FLOOR_Y, PLAZA_INLAY)
|
||||
fill(-1, PLOT_FLOOR_Y, -1, 1, PLOT_FLOOR_Y, 1, PLAZA_RING)
|
||||
blocks[(0, PLOT_FLOOR_Y, 0)] = PLAZA_CENTER
|
||||
for dx in (-PLAZA_HALF, PLAZA_HALF):
|
||||
for dz in (-PLAZA_HALF, PLAZA_HALF):
|
||||
blocks[(dx, PLOT_FLOOR_Y, dz)] = CORNER
|
||||
# invisible rail so spectators and waiting players cannot walk off
|
||||
for y in range(PLOT_FLOOR_Y + 1, PLOT_FLOOR_Y + 4):
|
||||
ring(0, 0, PLAZA_HALF, y, BARRIER)
|
||||
pedestal(0, 0, PLAZA_HALF, PLOT_FLOOR_Y)
|
||||
|
||||
for cx, cz in PLOTS:
|
||||
plot(cx, cz)
|
||||
plaza()
|
||||
|
||||
# ---- chunk serialisation ---------------------------------------------------
|
||||
def pack(indices, bits):
|
||||
per_long = 64 // bits
|
||||
longs = []
|
||||
cur = 0; n = 0
|
||||
for i, v in enumerate(indices):
|
||||
cur |= v << (bits * n)
|
||||
n += 1
|
||||
if n == per_long:
|
||||
longs.append(cur); cur = 0; n = 0
|
||||
if n:
|
||||
longs.append(cur)
|
||||
return [l - (1 << 64) if l >= (1 << 63) else l for l in longs]
|
||||
|
||||
def section(cx, sy, cz):
|
||||
ids = ['minecraft:air']
|
||||
idx = {}
|
||||
data = []
|
||||
nonair = False
|
||||
for y in range(16):
|
||||
for z in range(16):
|
||||
for x in range(16):
|
||||
b = blocks.get((cx * 16 + x, sy * 16 + y, cz * 16 + z), 'minecraft:air')
|
||||
if b not in idx:
|
||||
idx[b] = len(ids) if b != 'minecraft:air' else 0
|
||||
if b != 'minecraft:air':
|
||||
ids.append(b)
|
||||
nonair = True
|
||||
data.append(idx[b])
|
||||
palette = List[Compound]([Compound({'Name': String(n)}) for n in ids])
|
||||
bs = Compound({'palette': palette})
|
||||
if nonair:
|
||||
bits = max(4, math.ceil(math.log2(len(ids))))
|
||||
bs['data'] = LongArray(pack(data, bits))
|
||||
return Compound({
|
||||
'Y': Byte(sy),
|
||||
'block_states': bs,
|
||||
'biomes': Compound({'palette': List[String]([String(BIOME)])}),
|
||||
})
|
||||
|
||||
def chunk(cx, cz):
|
||||
return Compound({
|
||||
'DataVersion': Int(DATA_VERSION),
|
||||
'xPos': Int(cx), 'yPos': Int(-4), 'zPos': Int(cz),
|
||||
'Status': String('full'),
|
||||
'LastUpdate': Long(0), 'InhabitedTime': Long(0),
|
||||
'isLightOn': Byte(0),
|
||||
'sections': List[Compound]([section(cx, sy, cz) for sy in range(-4, 20)]),
|
||||
'block_entities': List[Compound]([]),
|
||||
'block_ticks': List[Compound]([]),
|
||||
'fluid_ticks': List[Compound]([]),
|
||||
'PostProcessing': List[List]([List[Short]([]) for _ in range(24)]) if False else List[List[nbtlib.Short]]([List[nbtlib.Short]([]) for _ in range(24)]),
|
||||
'structures': Compound({'References': Compound({}), 'starts': Compound({})}),
|
||||
})
|
||||
|
||||
def chunk_bytes(cx, cz):
|
||||
buf = io.BytesIO()
|
||||
nbtlib.File(chunk(cx, cz), root_name='').write(buf)
|
||||
return zlib.compress(buf.getvalue())
|
||||
|
||||
def write_region(rx, rz, chunks, path):
|
||||
# chunks: {(cx,cz): bytes}
|
||||
header_loc = bytearray(4096); header_ts = bytearray(4096)
|
||||
body = bytearray()
|
||||
sector = 2
|
||||
ts = int(time.time())
|
||||
for (cx, cz), payload in chunks.items():
|
||||
i = (cx & 31) + (cz & 31) * 32
|
||||
rec = len(payload) + 1
|
||||
block = (rec).to_bytes(4, 'big') + b'\x02' + payload
|
||||
pad = (-len(block)) % 4096
|
||||
block += b'\x00' * pad
|
||||
count = len(block) // 4096
|
||||
header_loc[i*4:i*4+3] = sector.to_bytes(3, 'big'); header_loc[i*4+3] = count
|
||||
header_ts[i*4:i*4+4] = ts.to_bytes(4, 'big')
|
||||
body += block
|
||||
sector += count
|
||||
with open(path, 'wb') as f:
|
||||
f.write(header_loc); f.write(header_ts); f.write(body)
|
||||
|
||||
# ---- world assembly --------------------------------------------------------
|
||||
if os.path.exists(DST):
|
||||
shutil.rmtree(DST)
|
||||
os.makedirs(os.path.join(DST, 'region'))
|
||||
for name in ('LICENSE.md', 'paper-world.yml'):
|
||||
shutil.copy(os.path.join(SRC, name), DST)
|
||||
for d in ('data', 'datapacks'):
|
||||
if os.path.isdir(os.path.join(SRC, d)):
|
||||
shutil.copytree(os.path.join(SRC, d), os.path.join(DST, d))
|
||||
|
||||
lvl = nbtlib.load(os.path.join(SRC, 'level.dat'))
|
||||
lvl['Data']['LevelName'] = String('Plaza')
|
||||
lvl['Data']['SpawnX'] = Int(0); lvl['Data']['SpawnY'] = Int(65); lvl['Data']['SpawnZ'] = Int(0)
|
||||
lvl.save(os.path.join(DST, 'level.dat'))
|
||||
|
||||
xs = [p[0] for p in blocks]; zs = [p[2] for p in blocks]
|
||||
cmin_x, cmax_x = (min(xs) >> 4) - 1, (max(xs) >> 4) + 1
|
||||
cmin_z, cmax_z = (min(zs) >> 4) - 1, (max(zs) >> 4) + 1
|
||||
regions = {}
|
||||
for cx in range(cmin_x, cmax_x + 1):
|
||||
for cz in range(cmin_z, cmax_z + 1):
|
||||
regions.setdefault((cx >> 5, cz >> 5), {})[(cx, cz)] = chunk_bytes(cx, cz)
|
||||
for (rx, rz), chunks in regions.items():
|
||||
write_region(rx, rz, chunks, os.path.join(DST, 'region', f'r.{rx}.{rz}.mca'))
|
||||
|
||||
print(f'blocks={len(blocks)} chunks={sum(len(c) for c in regions.values())} regions={len(regions)} -> {DST}')
|
||||
print('PLOTS (min corner, max corner):')
|
||||
for i, (cx, cz) in enumerate(PLOTS):
|
||||
print(f" {i}: ({cx-PLOT_HALF},{PLOT_FLOOR_Y},{cz-PLOT_HALF}) ({cx+PLOT_HALF},{PLOT_TOP_Y},{cz+PLOT_HALF})")
|
||||
Reference in new issue
Block a user