diff --git a/server/block/banner.go b/server/block/banner.go index d9cebdf88..ad265fa2c 100644 --- a/server/block/banner.go +++ b/server/block/banner.go @@ -105,7 +105,7 @@ func (b Banner) EncodeNBT() map[string]any { func (b Banner) DecodeNBT(m map[string]any) any { b.Colour = invertColourID(int16(nbtconv.Int32(m, "Base"))) b.Illager = nbtconv.Int32(m, "Type") == 1 - if patterns := nbtconv.Slice[any](m, "Patterns"); patterns != nil { + if patterns := nbtconv.Slice(m, "Patterns"); patterns != nil { b.Patterns = make([]BannerPatternLayer, len(patterns)) for i, p := range b.Patterns { b.Patterns[i] = p.DecodeNBT(patterns[i].(map[string]any)).(BannerPatternLayer) diff --git a/server/block/barrel.go b/server/block/barrel.go index 3558ec1ff..749f9a1ec 100644 --- a/server/block/barrel.go +++ b/server/block/barrel.go @@ -144,7 +144,7 @@ func (b Barrel) DecodeNBT(data map[string]any) any { b = NewBarrel() b.Facing = facing b.CustomName = nbtconv.String(data, "CustomName") - nbtconv.InvFromNBT(b.inventory, nbtconv.Slice[any](data, "Items")) + nbtconv.InvFromNBT(b.inventory, nbtconv.Slice(data, "Items")) return b } diff --git a/server/block/blast_furnace.go b/server/block/blast_furnace.go index e194f74f2..46956479d 100644 --- a/server/block/blast_furnace.go +++ b/server/block/blast_furnace.go @@ -116,7 +116,7 @@ func (b BlastFurnace) DecodeNBT(data map[string]interface{}) interface{} { b.Lit = lit b.setExperience(xp) b.setDurations(remaining, maximum, cook) - nbtconv.InvFromNBT(b.Inventory(), nbtconv.Slice[any](data, "Items")) + nbtconv.InvFromNBT(b.Inventory(), nbtconv.Slice(data, "Items")) return b } diff --git a/server/block/chest.go b/server/block/chest.go index db723f75b..0dc5c07b6 100644 --- a/server/block/chest.go +++ b/server/block/chest.go @@ -155,7 +155,7 @@ func (c Chest) DecodeNBT(data map[string]any) any { c = NewChest() c.Facing = facing c.CustomName = nbtconv.String(data, "CustomName") - nbtconv.InvFromNBT(c.inventory, nbtconv.Slice[any](data, "Items")) + nbtconv.InvFromNBT(c.inventory, nbtconv.Slice(data, "Items")) return c } diff --git a/server/block/decorated_pot.go b/server/block/decorated_pot.go index ef126f3f3..d90484edc 100644 --- a/server/block/decorated_pot.go +++ b/server/block/decorated_pot.go @@ -65,7 +65,7 @@ func (p DecoratedPot) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w * // EncodeNBT ... func (p DecoratedPot) EncodeNBT() map[string]any { - var sherds []string + var sherds []any for _, decoration := range p.Decorations { if decoration == nil { sherds = append(sherds, "minecraft:brick") @@ -83,9 +83,9 @@ func (p DecoratedPot) EncodeNBT() map[string]any { // DecodeNBT ... func (p DecoratedPot) DecodeNBT(data map[string]any) any { p.Decorations = [4]PotDecoration{} - if sherds := nbtconv.Slice[string](data, "sherds"); sherds != nil { + if sherds := nbtconv.Slice(data, "sherds"); sherds != nil { for i, name := range sherds { - it, ok := world.ItemByName(name, 0) + it, ok := world.ItemByName(name.(string), 0) if !ok { panic(fmt.Errorf("unknown item %s", name)) } diff --git a/server/block/furnace.go b/server/block/furnace.go index 4c758bc64..f7e664e3d 100644 --- a/server/block/furnace.go +++ b/server/block/furnace.go @@ -115,7 +115,7 @@ func (f Furnace) DecodeNBT(data map[string]interface{}) interface{} { f.Lit = lit f.setExperience(xp) f.setDurations(remaining, maximum, cook) - nbtconv.InvFromNBT(f.Inventory(), nbtconv.Slice[any](data, "Items")) + nbtconv.InvFromNBT(f.Inventory(), nbtconv.Slice(data, "Items")) return f } diff --git a/server/block/skull.go b/server/block/skull.go index 3a9ccffd5..ce7771ee7 100644 --- a/server/block/skull.go +++ b/server/block/skull.go @@ -89,7 +89,7 @@ func (s Skull) EncodeItem() (name string, meta int16) { // DecodeNBT ... func (s Skull) DecodeNBT(data map[string]interface{}) interface{} { s.Type = SkullType{skull(nbtconv.Uint8(data, "SkullType"))} - s.Attach.o = cube.Orientation(nbtconv.Uint8(data, "Rot")) + s.Attach.o = cube.OrientationFromYaw(float64(nbtconv.Float32(data, "Rotation"))) if s.Attach.facing >= 0 { s.Attach.hanging = true } @@ -98,7 +98,7 @@ func (s Skull) DecodeNBT(data map[string]interface{}) interface{} { // EncodeNBT ... func (s Skull) EncodeNBT() map[string]interface{} { - return map[string]interface{}{"id": "Skull", "SkullType": s.Type.Uint8(), "Rot": byte(s.Attach.o)} + return map[string]interface{}{"id": "Skull", "SkullType": s.Type.Uint8(), "Rotation": float32(s.Attach.o.Yaw())} } // EncodeBlock ... diff --git a/server/block/smoker.go b/server/block/smoker.go index da94ea200..94c2f8e8d 100644 --- a/server/block/smoker.go +++ b/server/block/smoker.go @@ -116,7 +116,7 @@ func (s Smoker) DecodeNBT(data map[string]interface{}) interface{} { s.Lit = lit s.setExperience(xp) s.setDurations(remaining, maximum, cook) - nbtconv.InvFromNBT(s.Inventory(), nbtconv.Slice[any](data, "Items")) + nbtconv.InvFromNBT(s.Inventory(), nbtconv.Slice(data, "Items")) return s } diff --git a/server/internal/nbtconv/read.go b/server/internal/nbtconv/read.go index 3263dda0d..a935ebfed 100644 --- a/server/internal/nbtconv/read.go +++ b/server/internal/nbtconv/read.go @@ -80,9 +80,9 @@ func Float64(m map[string]any, k string) float64 { return v } -// Slice reads a []T value from a map at key k. -func Slice[T any](m map[string]any, k string) []T { - v, _ := m[k].([]T) +// Slice reads a []any value from a map at key k. +func Slice(m map[string]any, k string) []any { + v, _ := m[k].([]any) return v } @@ -242,7 +242,7 @@ func readArmourTrim(m map[string]any, s *item.Stack) { func readEnchantments(m map[string]any, s *item.Stack) { enchantments, ok := m["ench"].([]map[string]any) if !ok { - for _, e := range Slice[any](m, "ench") { + for _, e := range Slice(m, "ench") { if v, ok := e.(map[string]any); ok { enchantments = append(enchantments, v) } diff --git a/server/item/creative/creative.go b/server/item/creative/creative.go index 9d3507cab..e2e62ba60 100644 --- a/server/item/creative/creative.go +++ b/server/item/creative/creative.go @@ -80,7 +80,7 @@ func init() { st := item.NewStack(it, 1) if len(data.NBT) > 0 { var invalid bool - for _, e := range nbtconv.Slice[any](data.NBT, "ench") { + for _, e := range nbtconv.Slice(data.NBT, "ench") { if v, ok := e.(map[string]any); ok { t, ok := item.EnchantmentByID(int(nbtconv.Int16(v, "id"))) if !ok { diff --git a/server/player/handler.go b/server/player/handler.go index 5f13e4ba5..d2baa2320 100644 --- a/server/player/handler.go +++ b/server/player/handler.go @@ -106,7 +106,7 @@ type Handler interface { HandlePunchAir(ctx *event.Context) // HandleSignEdit handles the player editing a sign. It is called for every keystroke while editing a sign and // has both the old text passed and the text after the edit. This typically only has a change of one character. - HandleSignEdit(ctx *event.Context, frontSide bool, oldText, newText string) + HandleSignEdit(ctx *event.Context, pos cube.Pos, frontSide bool, oldText, newText string) // HandleLecternPageTurn handles the player turning a page in a lectern. ctx.Cancel() may be called to cancel the // page turn. The page number may be changed by assigning to *page. HandleLecternPageTurn(ctx *event.Context, pos cube.Pos, oldPage int, newPage *int) @@ -156,7 +156,7 @@ func (NopHandler) HandleStartBreak(*event.Context, cube.Pos) func (NopHandler) HandleBlockBreak(*event.Context, cube.Pos, *[]item.Stack, *int) {} func (NopHandler) HandleBlockPlace(*event.Context, cube.Pos, world.Block) {} func (NopHandler) HandleBlockPick(*event.Context, cube.Pos, world.Block) {} -func (NopHandler) HandleSignEdit(*event.Context, bool, string, string) {} +func (NopHandler) HandleSignEdit(*event.Context, cube.Pos, bool, string, string) {} func (NopHandler) HandleLecternPageTurn(*event.Context, cube.Pos, int, *int) {} func (NopHandler) HandleItemPickup(*event.Context, *item.Stack) {} func (NopHandler) HandleItemUse(*event.Context) {} diff --git a/server/player/player.go b/server/player/player.go index c306781fc..c6c114aec 100644 --- a/server/player/player.go +++ b/server/player/player.go @@ -2642,14 +2642,14 @@ func (p *Player) EditSign(pos cube.Pos, frontText, backText string) error { ctx := event.C() if frontText != sign.Front.Text { - if p.Handler().HandleSignEdit(ctx, true, sign.Front.Text, frontText); ctx.Cancelled() { + if p.Handler().HandleSignEdit(ctx, pos, true, sign.Front.Text, frontText); ctx.Cancelled() { p.resendBlock(pos, w) return nil } sign.Front.Text = frontText sign.Front.Owner = p.XUID() } else { - if p.Handler().HandleSignEdit(ctx, false, sign.Back.Text, backText); ctx.Cancelled() { + if p.Handler().HandleSignEdit(ctx, pos, false, sign.Back.Text, backText); ctx.Cancelled() { p.resendBlock(pos, w) return nil } diff --git a/server/session/enchantment_texts.go b/server/session/enchantment_texts.go index bca9a9ddc..7d46a17fb 100644 --- a/server/session/enchantment_texts.go +++ b/server/session/enchantment_texts.go @@ -4,4 +4,4 @@ package session // enchantNames are names translated to the 'Standard Galactic Alphabet' client-side. The names generally have no meaning // on the vanilla server implementation, so we can sneak some easter eggs in here without anyone noticing. -var enchantNames = []string{"abimek", "aericio", "aimjel", "alvin0319", "andreas hgk", "atm85", "blackjack200", "da pig guy", "daft0175", "dasciam", "deniel world", "didntpot", "eminarican", "endermanbugzjfc", "erkam246", "flonja", "hashim the arab", "hochbaum", "hyper flare mc", "im da real ani", "its zodia x", "ivan craft623", "javier leon9966", "just tal develops", "liatoast", "mmm545", "mohamed587100", "myma qc", "natuyasai natuo", "neutronic mc", "nonono697", "provsalt", "restart fu", "riccskn", "robertdudaa", "royal mcpe", "sallypemdas", "sandertv", "sculas", "sqmatheus", "ssaini123456", "t14 raptor", "tadhunt", "thunder33345", "tristanmorgan", "twisted asylum mc", "unickorn", "unknown ore", "uramnoil", "wqrro", "x natsuri", "x4caa", "xd-pro"} +var enchantNames = []string{"abimek", "aericio", "aimjel", "alvin0319", "andreas hgk", "atm85", "blackjack200", "cetfu", "da pig guy", "daft0175", "dasciam", "deniel world", "didntpot", "eminarican", "endermanbugzjfc", "erkam246", "flonja", "hashim the arab", "hochbaum", "hyper flare mc", "im da real ani", "its zodia x", "ivan craft623", "javier leon9966", "just tal develops", "liatoast", "mmm545", "mohamed587100", "myma qc", "natuyasai natuo", "neutronic mc", "nonono697", "provsalt", "restart fu", "riccskn", "robertdudaa", "royal mcpe", "sallypemdas", "sandertv", "sculas", "sqmatheus", "ssaini123456", "t14 raptor", "tadhunt", "thunder33345", "tristanmorgan", "twisted asylum mc", "unickorn", "unknown ore", "uramnoil", "wqrro", "x natsuri", "x4caa", "xd-pro"} diff --git a/server/world/block_state.go b/server/world/block_state.go index 4cb0a23d6..9b618773b 100644 --- a/server/world/block_state.go +++ b/server/world/block_state.go @@ -7,6 +7,7 @@ import ( "github.com/df-mc/dragonfly/server/world/chunk" "github.com/sandertv/gophertunnel/minecraft/nbt" "github.com/segmentio/fasthash/fnv1" + "maps" "math" "slices" "sort" @@ -82,7 +83,7 @@ func registerBlockState(s blockState, order bool) { blockProperties[s.Name] = s.Properties } rid := uint32(len(blocks)) - blocks = append(blocks, unknownBlock{s}) + blocks = append(blocks, unknownBlock{blockState: s}) if order { sort.SliceStable(blocks, func(i, j int) bool { nameOne, _ := blocks[i].EncodeBlock() @@ -121,6 +122,7 @@ func registerBlockState(s blockState, order bool) { // states that haven't yet been added. type unknownBlock struct { blockState + data map[string]any } // EncodeBlock ... @@ -138,6 +140,17 @@ func (b unknownBlock) Hash() uint64 { return math.MaxUint64 } +// EncodeNBT ... +func (b unknownBlock) EncodeNBT() map[string]any { + return b.data +} + +// DecodeNBT ... +func (b unknownBlock) DecodeNBT(data map[string]any) any { + b.data = maps.Clone(data) + return b +} + // blockState holds a combination of a name and properties, together with a version. type blockState struct { Name string `nbt:"name"` diff --git a/server/world/chunk/light.go b/server/world/chunk/light.go index 119b27419..f20e813f1 100644 --- a/server/world/chunk/light.go +++ b/server/world/chunk/light.go @@ -31,14 +31,17 @@ func anyLightBlocks(sub *SubChunk) bool { // chunk. In addition, any skylight above those nodes will be set to 15. func (a *lightArea) insertSkyLightNodes(queue *list.List) { a.iterHeightmap(func(x, z int, height, highestNeighbour, highestY, lowestY int) { - // If we hit a block like water or leaves (something that diffuses but does not block light), we - // need a node above this block regardless of the neighbours. pos := cube.Pos{x, height, z} - a.setLight(pos, SkyLight, 15) + if height <= a.r.Max() { + // Only set light if we're not at the top of the world. + a.setLight(pos, SkyLight, 15) - if pos[1] > lowestY { - if level := a.highest(pos.Sub(cube.Pos{0, 1}), FilteringBlocks); level != 15 && level != 0 { - queue.PushBack(node(pos, 15, SkyLight)) + if pos[1] > lowestY { + if level := a.highest(pos.Sub(cube.Pos{0, 1}), FilteringBlocks); level != 15 && level != 0 { + // If we hit a block like water or leaves (something that diffuses but does not block light), we + // need a node above this block regardless of the neighbours. + queue.PushBack(node(pos, 15, SkyLight)) + } } } for y := pos[1]; y < highestY; y++ {