Add BlockEntity support

This commit is contained in:
Tnze
2022-12-18 18:28:08 +08:00
parent 27b1347e74
commit c1a6528a05
10 changed files with 712 additions and 153 deletions

View File

@ -21,3 +21,10 @@ func ToGoTypeName(name string) string {
}
return strings.Join(words, "")
}
func ToFuncReceiverName(name string) string {
if len(name) > 0 {
name = string(unicode.ToLower([]rune(name)[0]))
}
return name
}

View File

@ -2,9 +2,12 @@ package biome
import "math/bits"
var BitsPerBiome int
type Type int
var biomesNames = []string{
var (
BitsPerBiome int
BiomesIDs map[string]Type
BiomesNames = []string{
"the_void",
"plains",
"sunflower_plains",
@ -69,7 +72,12 @@ var biomesNames = []string{
"small_end_islands",
"end_barrens",
}
)
func init() {
BitsPerBiome = bits.Len(uint(len(biomesNames)))
BitsPerBiome = bits.Len(uint(len(BiomesNames)))
BiomesIDs = make(map[string]Type, len(BiomesNames))
for i, v := range BiomesNames {
BiomesIDs[v] = Type(i)
}
}

Binary file not shown.

View File

@ -0,0 +1,397 @@
// Code generated by generator/blockentities/main.go; DO NOT EDIT.
package block
var EntityList = [...]Entity{
FurnaceEntity{},
ChestEntity{},
TrappedChestEntity{},
EnderChestEntity{},
JukeboxEntity{},
DispenserEntity{},
DropperEntity{},
SignEntity{},
HangingSignEntity{},
MobSpawnerEntity{},
PistonEntity{},
BrewingStandEntity{},
EnchantingTableEntity{},
EndPortalEntity{},
BeaconEntity{},
SkullEntity{},
DaylightDetectorEntity{},
HopperEntity{},
ComparatorEntity{},
BannerEntity{},
StructureBlockEntity{},
EndGatewayEntity{},
CommandBlockEntity{},
ShulkerBoxEntity{},
BedEntity{},
ConduitEntity{},
BarrelEntity{},
SmokerEntity{},
BlastFurnaceEntity{},
LecternEntity{},
BellEntity{},
JigsawEntity{},
CampfireEntity{},
BeehiveEntity{},
SculkSensorEntity{},
SculkCatalystEntity{},
SculkShriekerEntity{},
ChiseledBookshelfEntity{},
}
func (FurnaceEntity) ID() string { return "minecraft:furnace" }
func (ChestEntity) ID() string { return "minecraft:chest" }
func (TrappedChestEntity) ID() string { return "minecraft:trapped_chest" }
func (EnderChestEntity) ID() string { return "minecraft:ender_chest" }
func (JukeboxEntity) ID() string { return "minecraft:jukebox" }
func (DispenserEntity) ID() string { return "minecraft:dispenser" }
func (DropperEntity) ID() string { return "minecraft:dropper" }
func (SignEntity) ID() string { return "minecraft:sign" }
func (HangingSignEntity) ID() string { return "minecraft:hanging_sign" }
func (MobSpawnerEntity) ID() string { return "minecraft:mob_spawner" }
func (PistonEntity) ID() string { return "minecraft:piston" }
func (BrewingStandEntity) ID() string { return "minecraft:brewing_stand" }
func (EnchantingTableEntity) ID() string { return "minecraft:enchanting_table" }
func (EndPortalEntity) ID() string { return "minecraft:end_portal" }
func (BeaconEntity) ID() string { return "minecraft:beacon" }
func (SkullEntity) ID() string { return "minecraft:skull" }
func (DaylightDetectorEntity) ID() string { return "minecraft:daylight_detector" }
func (HopperEntity) ID() string { return "minecraft:hopper" }
func (ComparatorEntity) ID() string { return "minecraft:comparator" }
func (BannerEntity) ID() string { return "minecraft:banner" }
func (StructureBlockEntity) ID() string { return "minecraft:structure_block" }
func (EndGatewayEntity) ID() string { return "minecraft:end_gateway" }
func (CommandBlockEntity) ID() string { return "minecraft:command_block" }
func (ShulkerBoxEntity) ID() string { return "minecraft:shulker_box" }
func (BedEntity) ID() string { return "minecraft:bed" }
func (ConduitEntity) ID() string { return "minecraft:conduit" }
func (BarrelEntity) ID() string { return "minecraft:barrel" }
func (SmokerEntity) ID() string { return "minecraft:smoker" }
func (BlastFurnaceEntity) ID() string { return "minecraft:blast_furnace" }
func (LecternEntity) ID() string { return "minecraft:lectern" }
func (BellEntity) ID() string { return "minecraft:bell" }
func (JigsawEntity) ID() string { return "minecraft:jigsaw" }
func (CampfireEntity) ID() string { return "minecraft:campfire" }
func (BeehiveEntity) ID() string { return "minecraft:beehive" }
func (SculkSensorEntity) ID() string { return "minecraft:sculk_sensor" }
func (SculkCatalystEntity) ID() string { return "minecraft:sculk_catalyst" }
func (SculkShriekerEntity) ID() string { return "minecraft:sculk_shrieker" }
func (ChiseledBookshelfEntity) ID() string { return "minecraft:chiseled_bookshelf" }
func (m FurnaceEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:furnace"
}
func (m ChestEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:chest"
}
func (m TrappedChestEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:trapped_chest"
}
func (m EnderChestEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:ender_chest"
}
func (m JukeboxEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:jukebox"
}
func (m DispenserEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:dispenser"
}
func (m DropperEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:dropper"
}
func (m SignEntity) IsValidBlock(block Block) bool {
switch block.ID() {
case "minecraft:oak_sign",
"minecraft:spruce_sign",
"minecraft:birch_sign",
"minecraft:acacia_sign",
"minecraft:jungle_sign",
"minecraft:dark_oak_sign",
"minecraft:oak_wall_sign",
"minecraft:spruce_wall_sign",
"minecraft:birch_wall_sign",
"minecraft:acacia_wall_sign",
"minecraft:jungle_wall_sign",
"minecraft:dark_oak_wall_sign",
"minecraft:crimson_sign",
"minecraft:crimson_wall_sign",
"minecraft:warped_sign",
"minecraft:warped_wall_sign",
"minecraft:mangrove_sign",
"minecraft:mangrove_wall_sign",
"minecraft:bamboo_sign",
"minecraft:bamboo_wall_sign":
return true
default:
return false
}
}
func (m HangingSignEntity) IsValidBlock(block Block) bool {
switch block.ID() {
case "minecraft:oak_hanging_sign",
"minecraft:spruce_hanging_sign",
"minecraft:birch_hanging_sign",
"minecraft:acacia_hanging_sign",
"minecraft:jungle_hanging_sign",
"minecraft:dark_oak_hanging_sign",
"minecraft:crimson_hanging_sign",
"minecraft:warped_hanging_sign",
"minecraft:mangrove_hanging_sign",
"minecraft:bamboo_hanging_sign",
"minecraft:oak_wall_hanging_sign",
"minecraft:spruce_wall_hanging_sign",
"minecraft:birch_wall_hanging_sign",
"minecraft:acacia_wall_hanging_sign",
"minecraft:jungle_wall_hanging_sign",
"minecraft:dark_oak_wall_hanging_sign",
"minecraft:crimson_wall_hanging_sign",
"minecraft:warped_wall_hanging_sign",
"minecraft:mangrove_wall_hanging_sign",
"minecraft:bamboo_wall_hanging_sign":
return true
default:
return false
}
}
func (m MobSpawnerEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:spawner"
}
func (m PistonEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:moving_piston"
}
func (m BrewingStandEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:brewing_stand"
}
func (m EnchantingTableEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:enchanting_table"
}
func (m EndPortalEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:end_portal"
}
func (m BeaconEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:beacon"
}
func (m SkullEntity) IsValidBlock(block Block) bool {
switch block.ID() {
case "minecraft:skeleton_skull",
"minecraft:skeleton_wall_skull",
"minecraft:creeper_head",
"minecraft:creeper_wall_head",
"minecraft:dragon_head",
"minecraft:dragon_wall_head",
"minecraft:zombie_head",
"minecraft:zombie_wall_head",
"minecraft:wither_skeleton_skull",
"minecraft:wither_skeleton_wall_skull",
"minecraft:player_head",
"minecraft:player_wall_head",
"minecraft:piglin_head",
"minecraft:piglin_wall_head":
return true
default:
return false
}
}
func (m DaylightDetectorEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:daylight_detector"
}
func (m HopperEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:hopper"
}
func (m ComparatorEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:comparator"
}
func (m BannerEntity) IsValidBlock(block Block) bool {
switch block.ID() {
case "minecraft:white_banner",
"minecraft:orange_banner",
"minecraft:magenta_banner",
"minecraft:light_blue_banner",
"minecraft:yellow_banner",
"minecraft:lime_banner",
"minecraft:pink_banner",
"minecraft:gray_banner",
"minecraft:light_gray_banner",
"minecraft:cyan_banner",
"minecraft:purple_banner",
"minecraft:blue_banner",
"minecraft:brown_banner",
"minecraft:green_banner",
"minecraft:red_banner",
"minecraft:black_banner",
"minecraft:white_wall_banner",
"minecraft:orange_wall_banner",
"minecraft:magenta_wall_banner",
"minecraft:light_blue_wall_banner",
"minecraft:yellow_wall_banner",
"minecraft:lime_wall_banner",
"minecraft:pink_wall_banner",
"minecraft:gray_wall_banner",
"minecraft:light_gray_wall_banner",
"minecraft:cyan_wall_banner",
"minecraft:purple_wall_banner",
"minecraft:blue_wall_banner",
"minecraft:brown_wall_banner",
"minecraft:green_wall_banner",
"minecraft:red_wall_banner",
"minecraft:black_wall_banner":
return true
default:
return false
}
}
func (m StructureBlockEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:structure_block"
}
func (m EndGatewayEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:end_gateway"
}
func (m CommandBlockEntity) IsValidBlock(block Block) bool {
switch block.ID() {
case "minecraft:command_block",
"minecraft:chain_command_block",
"minecraft:repeating_command_block":
return true
default:
return false
}
}
func (m ShulkerBoxEntity) IsValidBlock(block Block) bool {
switch block.ID() {
case "minecraft:shulker_box",
"minecraft:black_shulker_box",
"minecraft:blue_shulker_box",
"minecraft:brown_shulker_box",
"minecraft:cyan_shulker_box",
"minecraft:gray_shulker_box",
"minecraft:green_shulker_box",
"minecraft:light_blue_shulker_box",
"minecraft:light_gray_shulker_box",
"minecraft:lime_shulker_box",
"minecraft:magenta_shulker_box",
"minecraft:orange_shulker_box",
"minecraft:pink_shulker_box",
"minecraft:purple_shulker_box",
"minecraft:red_shulker_box",
"minecraft:white_shulker_box",
"minecraft:yellow_shulker_box":
return true
default:
return false
}
}
func (m BedEntity) IsValidBlock(block Block) bool {
switch block.ID() {
case "minecraft:red_bed",
"minecraft:black_bed",
"minecraft:blue_bed",
"minecraft:brown_bed",
"minecraft:cyan_bed",
"minecraft:gray_bed",
"minecraft:green_bed",
"minecraft:light_blue_bed",
"minecraft:light_gray_bed",
"minecraft:lime_bed",
"minecraft:magenta_bed",
"minecraft:orange_bed",
"minecraft:pink_bed",
"minecraft:purple_bed",
"minecraft:white_bed",
"minecraft:yellow_bed":
return true
default:
return false
}
}
func (m ConduitEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:conduit"
}
func (m BarrelEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:barrel"
}
func (m SmokerEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:smoker"
}
func (m BlastFurnaceEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:blast_furnace"
}
func (m LecternEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:lectern"
}
func (m BellEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:bell"
}
func (m JigsawEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:jigsaw"
}
func (m CampfireEntity) IsValidBlock(block Block) bool {
switch block.ID() {
case "minecraft:campfire",
"minecraft:soul_campfire":
return true
default:
return false
}
}
func (m BeehiveEntity) IsValidBlock(block Block) bool {
switch block.ID() {
case "minecraft:bee_nest",
"minecraft:beehive":
return true
default:
return false
}
}
func (m SculkSensorEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:sculk_sensor"
}
func (m SculkCatalystEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:sculk_catalyst"
}
func (m SculkShriekerEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:sculk_shrieker"
}
func (m ChiseledBookshelfEntity) IsValidBlock(block Block) bool {
return block.ID() == "minecraft:chiseled_bookshelf"
}

View File

@ -0,0 +1,59 @@
package block
//go:generate go run ./generator/blockentities/main.go
type Entity interface {
ID() string
IsValidBlock(block Block) bool
}
type (
FurnaceEntity struct{}
ChestEntity struct{}
TrappedChestEntity struct{}
EnderChestEntity struct{}
JukeboxEntity struct{}
DispenserEntity struct{}
DropperEntity struct{}
SignEntity struct{}
HangingSignEntity struct{}
MobSpawnerEntity struct{}
PistonEntity struct{}
BrewingStandEntity struct{}
EnchantingTableEntity struct{}
EndPortalEntity struct{}
BeaconEntity struct{}
SkullEntity struct{}
DaylightDetectorEntity struct{}
HopperEntity struct{}
ComparatorEntity struct{}
BannerEntity struct{}
StructureBlockEntity struct{}
EndGatewayEntity struct{}
CommandBlockEntity struct{}
ShulkerBoxEntity struct{}
BedEntity struct{}
ConduitEntity struct{}
BarrelEntity struct{}
SmokerEntity struct{}
BlastFurnaceEntity struct{}
LecternEntity struct{}
BellEntity struct{}
JigsawEntity struct{}
CampfireEntity struct{}
BeehiveEntity struct{}
SculkSensorEntity struct{}
SculkCatalystEntity struct{}
SculkShriekerEntity struct{}
ChiseledBookshelfEntity struct{}
)
type EntityType int32
var EntityTypes map[string]EntityType
func init() {
EntityTypes = make(map[string]EntityType, len(EntityList))
for i, v := range EntityList {
EntityTypes[v.ID()] = EntityType(i)
}
}

View File

@ -1,15 +1,15 @@
package tnze.github.com;
package pers.tnze.gomc.gen;
import com.google.common.collect.ImmutableMap;
import net.minecraft.SharedConstants;
import net.minecraft.core.DefaultedRegistry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.*;
import net.minecraft.server.Bootstrap;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.Property;
@ -18,9 +18,10 @@ import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPOutputStream;
public class Main {
public class GenBlocks {
public static void main(String[] args) throws Exception {
System.out.println("program start!");
@ -40,6 +41,12 @@ public class Main {
NbtIo.writeUnnamedTag(getBlockStates(), writer);
}
}
try (FileOutputStream f = new FileOutputStream("block_entities.nbt")) {
try (GZIPOutputStream g = new GZIPOutputStream(f)) {
DataOutput writer = new DataOutputStream(g);
NbtIo.writeUnnamedTag(genBlockEntities(), writer);
}
}
}
private static ListTag getBlocksWithMeta() throws Exception {
@ -84,4 +91,21 @@ public class Main {
}
return list;
}
private static ListTag genBlockEntities() {
ListTag list = new ListTag();
for (BlockEntityType blockEntity : BuiltInRegistries.BLOCK_ENTITY_TYPE) {
ListTag validBlocksList = new ListTag();
Set<Block> validBlocks = blockEntity.validBlocks;
for (Block validBlock : validBlocks){
validBlocksList.add(StringTag.valueOf(BuiltInRegistries.BLOCK.getKey(validBlock).toString()));
}
CompoundTag be = new CompoundTag();
be.putString("Name", BuiltInRegistries.BLOCK_ENTITY_TYPE.getKey(blockEntity).toString());
be.putString("ValidBlocks", BuiltInRegistries.BLOCK_ENTITY_TYPE.getKey(blockEntity).toString());
list.add(be);
}
return list;
}
}

View File

@ -0,0 +1,31 @@
// Code generated by {{Generator}}; DO NOT EDIT.
package block
{{/* type (
{{- range .}}
{{.Name | ToGoTypeName}}Entity struct {}
{{- end}}
) */}}
var EntityList = [...]Entity{
{{- range .}}
{{.Name | ToGoTypeName}}Entity{},
{{- end}}
}
{{- range .}}
func ({{.Name | ToGoTypeName}}Entity) ID() string { return {{.Name | printf "%q"}} }
{{- end}}
{{range .}}
func ({{.Name | ToFuncReceiverName}} {{.Name | ToGoTypeName}}Entity) IsValidBlock(block Block) bool {
{{if eq 1 (len .ValidBlocks)}}return block.ID() == {{index .ValidBlocks 0 | printf "%q"}}{{else}}switch block.ID() {
case {{index .ValidBlocks 0 | printf "%q"}}{{range slice .ValidBlocks 1}},
{{. | printf "%q"}}{{end}}:
return true
default:
return false
}{{end}}
}
{{end}}

View File

@ -0,0 +1,77 @@
package main
import (
"bytes"
"compress/gzip"
_ "embed"
"go/format"
"log"
"os"
"text/template"
"github.com/Tnze/go-mc/internal/generateutils"
"github.com/Tnze/go-mc/nbt"
)
//go:embed blockentities.go.tmpl
var tempSource string
var temp = template.Must(template.
New("block_template").
Funcs(template.FuncMap{
"UpperTheFirst": generateutils.UpperTheFirst,
"ToGoTypeName": generateutils.ToGoTypeName,
"ToFuncReceiverName": generateutils.ToFuncReceiverName,
"Generator": func() string { return "generator/blockentities/main.go" },
}).
Parse(tempSource),
)
type BlockEntity struct {
Name string
ValidBlocks []string
}
func main() {
var states []BlockEntity
readBlockEntities(&states)
// generate go source file
genSourceFile(states)
}
func readBlockEntities(states *[]BlockEntity) {
f, err := os.Open("block_entities.nbt")
if err != nil {
log.Panic(err)
}
defer f.Close()
r, err := gzip.NewReader(f)
if err != nil {
log.Panic(err)
}
// parse the nbt format
if _, err := nbt.NewDecoder(r).Decode(states); err != nil {
log.Panic(err)
}
}
func genSourceFile(states []BlockEntity) {
var source bytes.Buffer
if err := temp.Execute(&source, states); err != nil {
log.Panic(err)
}
formattedSource, err := format.Source(source.Bytes())
if err != nil {
panic(err)
}
err = os.WriteFile("blockentities.go", formattedSource, 0o666)
if err != nil {
panic(err)
}
log.Print("Generated blockentities.go")
}

View File

@ -2,11 +2,14 @@ package level
import (
"bytes"
"errors"
"fmt"
"io"
"math/bits"
"strconv"
"strings"
"github.com/Tnze/go-mc/level/biome"
"github.com/Tnze/go-mc/level/block"
"github.com/Tnze/go-mc/nbt"
pk "github.com/Tnze/go-mc/net/packet"
@ -62,81 +65,6 @@ func EmptyChunk(secs int) *Chunk {
}
}
var biomesIDs map[string]BiomesState
var biomesNames = []string{
"the_void",
"plains",
"sunflower_plains",
"snowy_plains",
"ice_spikes",
"desert",
"swamp",
"mangrove_swamp",
"forest",
"flower_forest",
"birch_forest",
"dark_forest",
"old_growth_birch_forest",
"old_growth_pine_taiga",
"old_growth_spruce_taiga",
"taiga",
"snowy_taiga",
"savanna",
"savanna_plateau",
"windswept_hills",
"windswept_gravelly_hills",
"windswept_forest",
"windswept_savanna",
"jungle",
"sparse_jungle",
"bamboo_jungle",
"badlands",
"eroded_badlands",
"wooded_badlands",
"meadow",
"grove",
"snowy_slopes",
"frozen_peaks",
"jagged_peaks",
"stony_peaks",
"river",
"frozen_river",
"beach",
"snowy_beach",
"stony_shore",
"warm_ocean",
"lukewarm_ocean",
"deep_lukewarm_ocean",
"ocean",
"deep_ocean",
"cold_ocean",
"deep_cold_ocean",
"frozen_ocean",
"deep_frozen_ocean",
"mushroom_fields",
"dripstone_caves",
"lush_caves",
"deep_dark",
"nether_wastes",
"warped_forest",
"crimson_forest",
"soul_sand_valley",
"basalt_deltas",
"the_end",
"end_highlands",
"end_midlands",
"small_end_islands",
"end_barrens",
}
func init() {
biomesIDs = make(map[string]BiomesState, len(biomesNames))
for i, v := range biomesNames {
biomesIDs[v] = BiomesState(i)
}
}
// ChunkFromSave convert save.Chunk to level.Chunk.
func ChunkFromSave(c *save.Chunk) (*Chunk, error) {
secs := len(c.Sections)
@ -159,6 +87,25 @@ func ChunkFromSave(c *save.Chunk) (*Chunk, error) {
sections[i].BlockLight = v.BlockLight
}
blockEntities := make([]BlockEntity, len(c.BlockEntities))
for i, v := range c.BlockEntities {
var tmp struct {
ID string `nbt:"id"`
X int32 `nbt:"x"`
Y int32 `nbt:"y"`
Z int32 `nbt:"z"`
}
if err := v.Unmarshal(&tmp); err != nil {
return nil, err
}
blockEntities[i].Data = v
if x, z := int(tmp.X-c.XPos<<4), int(tmp.Z-c.ZPos<<4); !blockEntities[i].PackXZ(x, z) {
return nil, errors.New("Packing a XZ(" + strconv.Itoa(x) + ", " + strconv.Itoa(z) + ") out of bound")
}
blockEntities[i].Y = int16(tmp.Y)
blockEntities[i].Type = block.EntityTypes[tmp.ID]
}
motionBlocking := c.Heightmaps.MotionBlocking
motionBlockingNoLeaves := c.Heightmaps.MotionBlockingNoLeaves
oceanFloor := c.Heightmaps.OceanFloor
@ -173,6 +120,7 @@ func ChunkFromSave(c *save.Chunk) (*Chunk, error) {
OceanFloor: NewBitStorage(bitsForHeight, 16*16, oceanFloor),
WorldSurface: NewBitStorage(bitsForHeight, 16*16, worldSurface),
},
BlockEntity: blockEntities,
Status: ChunkStatus(c.Status),
}, nil
}
@ -206,7 +154,7 @@ func readBiomesPalette(palette []string, data []uint64) (*PaletteContainer[Biome
biomesRawPalette := make([]BiomesState, len(palette))
var ok bool
for i, v := range palette {
biomesRawPalette[i], ok = biomesIDs[strings.TrimPrefix(v, "minecraft:")]
biomesRawPalette[i], ok = biome.BiomesIDs[strings.TrimPrefix(v, "minecraft:")]
if !ok {
return nil, fmt.Errorf("unknown biomes: %s", v)
}
@ -264,7 +212,7 @@ func writeBiomesPalette(paletteData *PaletteContainer[BiomesState]) (palette []s
rawPalette := paletteData.palette.export()
palette = make([]string, len(rawPalette))
for i, v := range rawPalette {
palette[i] = biomesNames[v]
palette[i] = biome.BiomesNames[v]
}
data = append(data, paletteData.data.Raw()...)
@ -367,7 +315,7 @@ type HeightMaps struct {
type BlockEntity struct {
XZ int8
Y int16
Type int32
Type block.EntityType
Data nbt.RawMessage
}
@ -375,6 +323,14 @@ func (b BlockEntity) UnpackXZ() (X, Z int) {
return int((uint8(b.XZ) >> 4) & 0xF), int(uint8(b.XZ) & 0xF)
}
func (b *BlockEntity) PackXZ(X, Z int) bool {
if X > 0xF || Z > 0xF || X < 0 || Z < 0 {
return false
}
b.XZ = int8(X<<4 | Z)
return true
}
func (b BlockEntity) WriteTo(w io.Writer) (n int64, err error) {
return pk.Tuple{
pk.Byte(b.XZ),

View File

@ -15,7 +15,7 @@ type State interface {
}
type (
BlocksState = block.StateID
BiomesState int
BiomesState = biome.Type
)
type PaletteContainer[T State] struct {