diff --git a/go.mod b/go.mod index 3f8da3ce7..bcea2f8b6 100644 --- a/go.mod +++ b/go.mod @@ -7,12 +7,12 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 github.com/df-mc/atomic v1.10.0 github.com/df-mc/goleveldb v1.1.9 - github.com/df-mc/worldupgrader v1.0.11 + github.com/df-mc/worldupgrader v1.0.12 github.com/go-gl/mathgl v1.1.0 github.com/google/uuid v1.4.0 github.com/pelletier/go-toml v1.9.5 github.com/rogpeppe/go-internal v1.11.0 - github.com/sandertv/gophertunnel v1.34.1 + github.com/sandertv/gophertunnel v1.35.0 github.com/segmentio/fasthash v1.0.3 github.com/sirupsen/logrus v1.9.3 golang.org/x/exp v0.0.0-20230206171751-46f607a40771 diff --git a/go.sum b/go.sum index 023d3986f..25afe848a 100644 --- a/go.sum +++ b/go.sum @@ -9,8 +9,8 @@ github.com/df-mc/atomic v1.10.0 h1:0ZuxBKwR/hxcFGorKiHIp+hY7hgY+XBTzhCYD2NqSEg= github.com/df-mc/atomic v1.10.0/go.mod h1:Gw9rf+rPIbydMjA329Jn4yjd/O2c/qusw3iNp4tFGSc= github.com/df-mc/goleveldb v1.1.9 h1:ihdosZyy5jkQKrxucTQmN90jq/2lUwQnJZjIYIC/9YU= github.com/df-mc/goleveldb v1.1.9/go.mod h1:+NHCup03Sci5q84APIA21z3iPZCuk6m6ABtg4nANCSk= -github.com/df-mc/worldupgrader v1.0.11 h1:7dlebxDXY8QND3MnDPnty7qeAqtxJE8kVqvs6VDs1YI= -github.com/df-mc/worldupgrader v1.0.11/go.mod h1:tsSOLTRm9mpG7VHvYpAjjZrkRHWmSbKZAm9bOLNnlDk= +github.com/df-mc/worldupgrader v1.0.12 h1:Ry6XkcwclSMfRPdiwcfSFRWqTkVglu0u3oLd0X2CxZ4= +github.com/df-mc/worldupgrader v1.0.12/go.mod h1:tsSOLTRm9mpG7VHvYpAjjZrkRHWmSbKZAm9bOLNnlDk= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-gl/mathgl v1.1.0 h1:0lzZ+rntPX3/oGrDzYGdowSLC2ky8Osirvf5uAwfIEA= github.com/go-gl/mathgl v1.1.0/go.mod h1:yhpkQzEiH9yPyxDUGzkmgScbaBVlhC06qodikEM0ZwQ= @@ -50,8 +50,8 @@ github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDN github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/sandertv/go-raknet v1.12.0 h1:olUzZlIJyX/pgj/mrsLCZYjKLNDsYiWdvQ4NIm3z0DA= github.com/sandertv/go-raknet v1.12.0/go.mod h1:Gx+WgZBMQ0V2UoouGoJ8Wj6CDrMBQ4SB2F/ggpl5/+Y= -github.com/sandertv/gophertunnel v1.34.1 h1:gRU9KVT8GewlSPRCn3sQNw6RbTGyd02yyXZOXyIjz+o= -github.com/sandertv/gophertunnel v1.34.1/go.mod h1:4El8ZfEpUmOMIJhPt5SCc1PyLNiuQ2+grWczrBvSGVs= +github.com/sandertv/gophertunnel v1.35.0 h1:1QQ/FSvSBQ4nqYus7Br4ihDDoI6g+L4/4MYNpPrIDKs= +github.com/sandertv/gophertunnel v1.35.0/go.mod h1:4El8ZfEpUmOMIJhPt5SCc1PyLNiuQ2+grWczrBvSGVs= github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= diff --git a/server/block/decorated_pot.go b/server/block/decorated_pot.go index 4ed099d48..62f67e1a3 100644 --- a/server/block/decorated_pot.go +++ b/server/block/decorated_pot.go @@ -33,7 +33,7 @@ func (p DecoratedPot) BreakInfo() BreakInfo { // MaxCount ... func (DecoratedPot) MaxCount() int { - return 1 + return 64 } // EncodeItem ... diff --git a/server/block/ender_chest.go b/server/block/ender_chest.go index 1073b9a54..61e3c5559 100644 --- a/server/block/ender_chest.go +++ b/server/block/ender_chest.go @@ -95,7 +95,7 @@ func (c EnderChest) open(w *world.World, pos cube.Pos) { for _, v := range w.Viewers(pos.Vec3()) { v.ViewBlockAction(pos, OpenAction{}) } - w.PlaySound(pos.Vec3Centre(), sound.ChestOpen{}) + w.PlaySound(pos.Vec3Centre(), sound.EnderChestOpen{}) } // close closes the ender chest, displaying the animation and playing a sound. @@ -103,7 +103,7 @@ func (c EnderChest) close(w *world.World, pos cube.Pos) { for _, v := range w.Viewers(pos.Vec3()) { v.ViewBlockAction(pos, CloseAction{}) } - w.PlaySound(pos.Vec3Centre(), sound.ChestClose{}) + w.PlaySound(pos.Vec3Centre(), sound.EnderChestClose{}) } // EncodeNBT ... @@ -113,7 +113,7 @@ func (c EnderChest) EncodeNBT() map[string]interface{} { // DecodeNBT ... func (c EnderChest) DecodeNBT(map[string]interface{}) interface{} { - return NewEnderChest() + return c } // EncodeItem ... diff --git a/server/block/fire.go b/server/block/fire.go index 2f986d585..cbb570380 100644 --- a/server/block/fire.go +++ b/server/block/fire.go @@ -69,7 +69,7 @@ func (f Fire) burn(from, to cube.Pos, w *world.World, r *rand.Rand, chanceBound return } if t, ok := flammable.(TNT); ok { - t.Ignite(to, w) + t.Ignite(to, w, nil) return } w.SetBlock(to, nil, nil) diff --git a/server/block/tnt.go b/server/block/tnt.go index 32f11ee7d..4ae1bc4c5 100644 --- a/server/block/tnt.go +++ b/server/block/tnt.go @@ -14,13 +14,14 @@ import ( // TNT is an explosive block that can be primed to generate an explosion. type TNT struct { solid + igniter world.Entity } // Activate ... func (t TNT) Activate(pos cube.Pos, _ cube.Face, w *world.World, u item.User, ctx *item.UseContext) bool { held, _ := u.HeldItems() if _, ok := held.Enchantment(enchantment.FireAspect{}); ok { - t.Ignite(pos, w) + t.Ignite(pos, w, u) ctx.DamageItem(1) return true } @@ -28,14 +29,20 @@ func (t TNT) Activate(pos cube.Pos, _ cube.Face, w *world.World, u item.User, ct } // Ignite ... -func (t TNT) Ignite(pos cube.Pos, w *world.World) bool { - spawnTnt(pos, w, time.Second*4) +func (t TNT) Ignite(pos cube.Pos, w *world.World, igniter world.Entity) bool { + t.igniter = igniter + spawnTnt(pos, w, time.Second*4, t.igniter) return true } +// Igniter returns the entity that ignited the TNT. +func (t TNT) Igniter() world.Entity { + return t.igniter +} + // Explode ... func (t TNT) Explode(_ mgl64.Vec3, pos cube.Pos, w *world.World, _ ExplosionConfig) { - spawnTnt(pos, w, time.Second/2+time.Duration(rand.Intn(int(time.Second+time.Second/2)))) + spawnTnt(pos, w, time.Second/2+time.Duration(rand.Intn(int(time.Second+time.Second/2))), t.igniter) } // BreakInfo ... @@ -59,8 +66,8 @@ func (t TNT) EncodeBlock() (name string, properties map[string]interface{}) { } // spawnTnt creates a new TNT entity at the given position with the given fuse duration. -func spawnTnt(pos cube.Pos, w *world.World, fuse time.Duration) { +func spawnTnt(pos cube.Pos, w *world.World, fuse time.Duration, igniter world.Entity) { w.PlaySound(pos.Vec3Centre(), sound.TNT{}) w.SetBlock(pos, nil, nil) - w.AddEntity(w.EntityRegistry().Config().TNT(pos.Vec3Centre(), fuse)) + w.AddEntity(w.EntityRegistry().Config().TNT(pos.Vec3Centre(), fuse, igniter)) } diff --git a/server/entity/projectile.go b/server/entity/projectile.go index d9ecdd7dc..a6dfec91c 100644 --- a/server/entity/projectile.go +++ b/server/entity/projectile.go @@ -170,7 +170,7 @@ func (lt *ProjectileBehaviour) Tick(e *Ent) *Movement { case trace.BlockResult: bpos := r.BlockPosition() if t, ok := w.Block(bpos).(block.TNT); ok && e.OnFireDuration() > 0 { - t.Ignite(bpos, w) + t.Ignite(bpos, w, e) } if lt.conf.SurviveBlockCollision { lt.hitBlockSurviving(e, r, m) diff --git a/server/entity/register.go b/server/entity/register.go index a8353b978..1697fb152 100644 --- a/server/entity/register.go +++ b/server/entity/register.go @@ -39,8 +39,8 @@ var conf = world.EntityRegistryConfig{ FallingBlock: func(bl world.Block, pos mgl64.Vec3) world.Entity { return NewFallingBlock(bl, pos) }, - TNT: func(pos mgl64.Vec3, fuse time.Duration) world.Entity { - return NewTNT(pos, fuse) + TNT: func(pos mgl64.Vec3, fuse time.Duration, igniter world.Entity) world.Entity { + return NewTNT(pos, fuse, igniter) }, BottleOfEnchanting: func(pos, vel mgl64.Vec3, owner world.Entity) world.Entity { b := NewBottleOfEnchanting(pos, owner) diff --git a/server/entity/tnt.go b/server/entity/tnt.go index 4773ac2a1..d1e98208a 100644 --- a/server/entity/tnt.go +++ b/server/entity/tnt.go @@ -12,10 +12,10 @@ import ( ) // NewTNT creates a new primed TNT entity. -func NewTNT(pos mgl64.Vec3, fuse time.Duration) *Ent { +func NewTNT(pos mgl64.Vec3, fuse time.Duration, igniter world.Entity) *Ent { config := tntConf config.ExistenceDuration = fuse - ent := Config{Behaviour: config.New()}.New(TNTType{}, pos) + ent := Config{Behaviour: config.New()}.New(TNTType{igniter: igniter}, pos) angle := rand.Float64() * math.Pi * 2 ent.vel = mgl64.Vec3{-math.Sin(angle) * 0.02, 0.1, -math.Cos(angle) * 0.02} @@ -35,7 +35,11 @@ func explodeTNT(e *Ent) { } // TNTType is a world.EntityType implementation for TNT. -type TNTType struct{} +type TNTType struct { + igniter world.Entity +} + +func (t TNTType) Igniter() world.Entity { return t.igniter } func (TNTType) EncodeEntity() string { return "minecraft:tnt" } func (TNTType) NetworkOffset() float64 { return 0.49 } @@ -43,8 +47,8 @@ func (TNTType) BBox(world.Entity) cube.BBox { return cube.Box(-0.49, 0, -0.49, 0.49, 0.98, 0.49) } -func (TNTType) DecodeNBT(m map[string]any) world.Entity { - tnt := NewTNT(nbtconv.Vec3(m, "Pos"), nbtconv.TickDuration[uint8](m, "Fuse")) +func (t TNTType) DecodeNBT(m map[string]any) world.Entity { + tnt := NewTNT(nbtconv.Vec3(m, "Pos"), nbtconv.TickDuration[uint8](m, "Fuse"), t.igniter) tnt.vel = nbtconv.Vec3(m, "Motion") return tnt } diff --git a/server/internal/blockinternal/builder.go b/server/internal/blockinternal/builder.go index e320ab585..233c660c2 100644 --- a/server/internal/blockinternal/builder.go +++ b/server/internal/blockinternal/builder.go @@ -11,6 +11,7 @@ type ComponentBuilder struct { permutations map[string]map[string]any properties []map[string]any components map[string]any + blockID int32 identifier string menuCategory category.Category @@ -18,13 +19,14 @@ type ComponentBuilder struct { // NewComponentBuilder returns a new component builder with the provided block data, using the provided components map // as a base. -func NewComponentBuilder(identifier string, components map[string]any) *ComponentBuilder { +func NewComponentBuilder(identifier string, components map[string]any, blockID int32) *ComponentBuilder { if components == nil { components = map[string]any{} } return &ComponentBuilder{ permutations: make(map[string]map[string]any), components: components, + blockID: blockID, identifier: identifier, menuCategory: category.Construction(), @@ -79,6 +81,9 @@ func (builder *ComponentBuilder) Construct() map[string]any { "category": builder.menuCategory.String(), "group": builder.menuCategory.Group(), }, + "vanilla_block_data": map[string]any{ + "block_id": builder.blockID, + }, } if len(properties) > 0 { result["properties"] = properties diff --git a/server/internal/blockinternal/components.go b/server/internal/blockinternal/components.go index affec240e..c4ee35ccc 100644 --- a/server/internal/blockinternal/components.go +++ b/server/internal/blockinternal/components.go @@ -9,9 +9,9 @@ import ( ) // Components returns all the components for the custom block, including permutations and properties. -func Components(identifier string, b world.CustomBlock) map[string]any { +func Components(identifier string, b world.CustomBlock, blockID int32) map[string]any { components := componentsFromProperties(b.Properties()) - builder := NewComponentBuilder(identifier, components) + builder := NewComponentBuilder(identifier, components, blockID) if emitter, ok := b.(block.LightEmitter); ok { builder.AddComponent("minecraft:block_light_emission", map[string]any{ "emission": float32(emitter.LightEmissionLevel() / 15), diff --git a/server/internal/iteminternal/builder.go b/server/internal/iteminternal/builder.go index 7ae9a5719..bdc2e24e0 100644 --- a/server/internal/iteminternal/builder.go +++ b/server/internal/iteminternal/builder.go @@ -52,7 +52,9 @@ func (builder *ComponentBuilder) Construct() map[string]any { // not modify the builder's properties map directly otherwise Empty() will return false in future use of the builder. func (builder *ComponentBuilder) applyDefaultProperties(x map[string]any) { x["minecraft:icon"] = map[string]any{ - "texture": strings.Split(builder.identifier, ":")[1], + "textures": map[string]any{ + "default": strings.Split(builder.identifier, ":")[1], + }, } x["creative_group"] = builder.category.Group() x["creative_category"] = int32(builder.category.Uint8()) diff --git a/server/item/fire_charge.go b/server/item/fire_charge.go index ceffd7ace..7e1e0c70c 100644 --- a/server/item/fire_charge.go +++ b/server/item/fire_charge.go @@ -19,8 +19,8 @@ func (f FireCharge) EncodeItem() (name string, meta int16) { } // UseOnBlock ... -func (f FireCharge) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *world.World, _ User, ctx *UseContext) bool { - if l, ok := w.Block(pos).(ignitable); ok && l.Ignite(pos, w) { +func (f FireCharge) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *world.World, u User, ctx *UseContext) bool { + if l, ok := w.Block(pos).(ignitable); ok && l.Ignite(pos, w, u) { ctx.SubtractFromCount(1) w.PlaySound(pos.Vec3Centre(), sound.FireCharge{}) return true diff --git a/server/item/flint_and_steel.go b/server/item/flint_and_steel.go index 2e7c19bfd..9f600b97f 100644 --- a/server/item/flint_and_steel.go +++ b/server/item/flint_and_steel.go @@ -28,13 +28,13 @@ func (f FlintAndSteel) DurabilityInfo() DurabilityInfo { // ignitable represents a block that can be lit by a fire emitter, such as flint and steel. type ignitable interface { // Ignite is called when the block is lit by flint and steel. - Ignite(pos cube.Pos, w *world.World) bool + Ignite(pos cube.Pos, w *world.World, igniter world.Entity) bool } // UseOnBlock ... -func (f FlintAndSteel) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *world.World, _ User, ctx *UseContext) bool { +func (f FlintAndSteel) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *world.World, u User, ctx *UseContext) bool { ctx.DamageItem(1) - if l, ok := w.Block(pos).(ignitable); ok && l.Ignite(pos, w) { + if l, ok := w.Block(pos).(ignitable); ok && l.Ignite(pos, w, u) { return true } else if s := pos.Side(face); w.Block(s) == air() { w.PlaySound(s.Vec3Centre(), sound.Ignite{}) diff --git a/server/server.go b/server/server.go index e8bae1f35..8508305e8 100644 --- a/server/server.go +++ b/server/server.go @@ -297,7 +297,7 @@ func (srv *Server) makeBlockEntries() { name, _ := b.EncodeBlock() srv.customBlocks[i] = protocol.BlockEntry{ Name: name, - Properties: blockinternal.Components(name, b), + Properties: blockinternal.Components(name, b, 10000+int32(i)), } } } diff --git a/server/session/enchantment_texts.go b/server/session/enchantment_texts.go index 3d0b433a5..76bfef849 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", "deniel world", "didntpot", "eminarican", "endermanbugzjfc", "flonja", "hashim the arab", "hochbaum", "hyper flare mc", "im da real ani", "imlighty", "its zodia x", "ivan craft623", "javier leon9966", "just tal develops", "liatoast", "mmm545", "mohamed587100", "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", "da pig guy", "daft0175", "deniel world", "didntpot", "eminarican", "endermanbugzjfc", "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", "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/session/world.go b/server/session/world.go index 4624fb85d..1098b275f 100644 --- a/server/session/world.go +++ b/server/session/world.go @@ -662,6 +662,10 @@ func (s *Session) playSound(pos mgl64.Vec3, t world.Sound, disableRelative bool) pk.SoundType = packet.SoundEventChestClosed case sound.ChestOpen: pk.SoundType = packet.SoundEventChestOpen + case sound.EnderChestClose: + pk.SoundType = packet.SoundEventEnderChestClosed + case sound.EnderChestOpen: + pk.SoundType = packet.SoundEventEnderChestOpen case sound.BarrelClose: pk.SoundType = packet.SoundEventBarrelClose case sound.BarrelOpen: diff --git a/server/world/block_states.nbt b/server/world/block_states.nbt index 7867d4964..274cc2a2c 100644 Binary files a/server/world/block_states.nbt and b/server/world/block_states.nbt differ diff --git a/server/world/entity.go b/server/world/entity.go index 3bbf02cb5..0233388dc 100644 --- a/server/world/entity.go +++ b/server/world/entity.go @@ -101,7 +101,7 @@ type EntityRegistry struct { type EntityRegistryConfig struct { Item func(it any, pos, vel mgl64.Vec3) Entity FallingBlock func(bl Block, pos mgl64.Vec3) Entity - TNT func(pos mgl64.Vec3, fuse time.Duration) Entity + TNT func(pos mgl64.Vec3, fuse time.Duration, igniter Entity) Entity BottleOfEnchanting func(pos, vel mgl64.Vec3, owner Entity) Entity Arrow func(pos, vel mgl64.Vec3, rot cube.Rotation, damage float64, owner Entity, critical, disallowPickup, obtainArrowOnPickup bool, punchLevel int, tip any) Entity Egg func(pos, vel mgl64.Vec3, owner Entity) Entity diff --git a/server/world/sound/block.go b/server/world/sound/block.go index e735e3ec8..363d9d737 100644 --- a/server/world/sound/block.go +++ b/server/world/sound/block.go @@ -45,6 +45,12 @@ type ChestOpen struct{ sound } // ChestClose is played when a chest is closed. type ChestClose struct{ sound } +// EnderChestOpen is played when a ender chest is opened. +type EnderChestOpen struct{ sound } + +// EnderChestClose is played when a ender chest is closed. +type EnderChestClose struct{ sound } + // BarrelOpen is played when a barrel is opened. type BarrelOpen struct{ sound }