diff --git a/commands/debug.go b/commands/debug.go index 3da5e51b..3aa6d773 100644 --- a/commands/debug.go +++ b/commands/debug.go @@ -6,7 +6,9 @@ import ( "github.com/zeppelinmc/zeppelin/protocol/text" "github.com/zeppelinmc/zeppelin/server" "github.com/zeppelinmc/zeppelin/server/command" - "github.com/zeppelinmc/zeppelin/server/session" + "github.com/zeppelinmc/zeppelin/server/player/state" + + //"github.com/zeppelinmc/zeppelin/server/session" "github.com/zeppelinmc/zeppelin/util" ) @@ -15,7 +17,7 @@ var debug = command.Command{ Aliases: []string{"f3"}, Namespace: "zeppelin", Callback: func(ccc command.CommandCallContext) { - s, ok := ccc.Executor.(session.Session) + s, ok := ccc.Executor.(interface{ Player() *state.PlayerEntity }) if !ok { ccc.Executor.SystemMessage(text.TextComponent{ Text: "This command should be used by a player.", @@ -50,23 +52,21 @@ var debug = command.Command{ } onBlock, _ := c.Block(xb&0x0f, yb-1, zb&0x0f) sky, _ := c.SkyLightLevel(xb&0x0f, yb, zb&0x0f) - block, _ := c.BlockLightLevel(xb&0x0f, yb, zb&0x0f) - - name, props := onBlock.Encode() ccc.Executor.SystemMessage(text.Unmarshalf( - ccc.Executor.Config().ChatFormatter.Rune(), - "XYZ: %.03f / %.05f / %.03f\nBlock: %d %d %d [%d %d %d]\nChunk: %d %d %d [%d %d in r.%d.%d.mca]\nStanding on: %s [%v]\nFacing: (%.01f / %.01f)\nClient Light: %d (%d sky, %d block)\n\nYou are using: %s", + '&', //ccc.Executor.Config().ChatFormatter.Rune(), + "XYZ: %.03f / %.05f / %.03f\nBlock: %d %d %d [%d %d %d]\nChunk: %d %d %d [%d %d in r.%d.%d.mca]\nStanding on: %s [%v]\nFacing: (%.01f / %.01f)\nClient Light: %d (%d sky, 0 block)\n\nYou are using: %s", x, y, z, xb, yb, zb, xb&0xf, yb&0xf, zb&0xf, chunkX, chunkY, chunkZ, chunkX&31, chunkZ&31, rx, rz, - name, props, + onBlock.Name, onBlock.Properties, util.NormalizeYaw(yaw), pitch, - sky+block, sky, block, - s.ClientName(), + sky, sky, + "idk", + //s.ClientName(), )) }, } diff --git a/commands/tick.go b/commands/tick.go index aa5ab741..58ac2816 100644 --- a/commands/tick.go +++ b/commands/tick.go @@ -1,7 +1,6 @@ package commands import ( - "fmt" "time" "github.com/zeppelinmc/zeppelin/protocol/text" @@ -19,12 +18,10 @@ var tick = command.Command{ switch command { case "info": freq := tickManager.Frequency() - ccc.Executor.SystemMessage(text.TextComponent{ - Text: fmt.Sprintf( - "Server Tickers: %d\nTicking Frequency: %.02ftps (expected ticks per second)", - num, 1/(float64(freq)/float64(time.Second)), - ), - }) + ccc.Executor.SystemMessage(text.Sprintf( + "Server Tickers: %d\nTicking Frequency: %.02ftps (expected ticks per second)", + num, 1/(float64(freq)/float64(time.Second)), + )) case "freeze": tickManager.Freeze() ccc.Executor.SystemMessage(text.Sprintf("Froze %d tickers", num)) diff --git a/commands/time.go b/commands/time.go index 6f7901b4..7ba34b5f 100644 --- a/commands/time.go +++ b/commands/time.go @@ -1,17 +1,13 @@ package commands import ( - "strconv" - - "github.com/zeppelinmc/zeppelin/protocol/text" - "github.com/zeppelinmc/zeppelin/server" "github.com/zeppelinmc/zeppelin/server/command" ) var timecmd = command.Command{ Node: command.NewLiteral("time" /*command.NewCommand("add", command.NewTimeArgument("time", 0)), command.NewCommand("set", command.NewTimeArgument("time", 0))*/), Callback: func(ccc command.CommandCallContext) { - command := ccc.Arguments.At(0) + /*command := ccc.Arguments.At(0) w := ccc.Server.(*server.Server).World switch command { @@ -25,6 +21,6 @@ var timecmd = command.Command{ a, _ := w.Time() ccc.Executor.UpdateTime(a, int64(time)) - } + }*/ }, } diff --git a/go.mod b/go.mod index eb96b5db..bc06166d 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,10 @@ require ( require github.com/oq-x/unsafe2 v0.0.0-20240901191313-2b7bec1d9e3b -require github.com/grailbio/base v0.0.11 // indirect +require ( + github.com/aimjel/mine-net v0.0.0-20241231185445-f0751c927ecb // indirect + github.com/grailbio/base v0.0.11 // indirect +) require ( github.com/4kills/go-zlib v1.2.0 diff --git a/go.sum b/go.sum index 9e03b162..9539d5a1 100644 --- a/go.sum +++ b/go.sum @@ -20,6 +20,10 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/StackExchange/wmi v0.0.0-20170410192909-ea383cf3ba6e/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/aimjel/mine-net v0.0.0-20241231184943-192b6fd6bfdc h1:Fl6/rTVRsK3yRvLIe59RgElHb/fpVVo8fOm1SYvAfS8= +github.com/aimjel/mine-net v0.0.0-20241231184943-192b6fd6bfdc/go.mod h1:2p/uMjMBAOvMK8NvNnTsXS7s00IYvbS3Ji3YM2ApzxA= +github.com/aimjel/mine-net v0.0.0-20241231185445-f0751c927ecb h1:DzjkzmO1C8qXdEUSWU0I4hHEi0tuaFNrKeLeRZ8ntZo= +github.com/aimjel/mine-net v0.0.0-20241231185445-f0751c927ecb/go.mod h1:2p/uMjMBAOvMK8NvNnTsXS7s00IYvbS3Ji3YM2ApzxA= github.com/aimjel/minecraft v0.0.0-20240907220502-e1fe5798908b h1:P5dA2C10r7BqzbhXqjjx07+LBV1tcsioFJrogWBOOBY= github.com/aimjel/minecraft v0.0.0-20240907220502-e1fe5798908b/go.mod h1:jb47g4nDw3J8JdA4WxQpDx25NoIZiyNCjFOtM1b3Urk= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= diff --git a/main.go b/main.go index 59505d05..a6157685 100644 --- a/main.go +++ b/main.go @@ -2,9 +2,8 @@ package main import ( _ "embed" - "fmt" + properties2 "github.com/zeppelinmc/zeppelin/properties" "math/rand" - "net/http" "os" "runtime" "runtime/debug" @@ -14,11 +13,9 @@ import ( "time" "github.com/zeppelinmc/zeppelin/commands" - "github.com/zeppelinmc/zeppelin/protocol/properties" "github.com/zeppelinmc/zeppelin/server" "github.com/zeppelinmc/zeppelin/server/command" "github.com/zeppelinmc/zeppelin/server/world" - "github.com/zeppelinmc/zeppelin/server/world/chunk/section" "github.com/zeppelinmc/zeppelin/util" "github.com/zeppelinmc/zeppelin/util/console" "github.com/zeppelinmc/zeppelin/util/log" @@ -29,9 +26,6 @@ var timeStart = time.Now() func main() { log.Infolnf("Zeppelin 1.21 Minecraft server with %s on platform %s-%s", runtime.Version(), runtime.GOOS, runtime.GOARCH) - if !loadStates() { - return - } max, ok := console.GetFlag("xmem") if ok { @@ -100,63 +94,22 @@ func main() { srv.Start(timeStart) } -func loadConfig() properties.ServerProperties { +func loadConfig() properties2.ServerProperties { file, err := os.ReadFile("server.properties") if err != nil { file, err := os.Create("server.properties") if err == nil { - properties.Marshal(file, properties.Default) + properties2.Marshal(file, properties2.Default) file.Close() } - return properties.Default + return properties2.Default } - var cfg properties.ServerProperties + var cfg properties2.ServerProperties - err = properties.Unmarshal(string(file), &cfg) + err = properties2.Unmarshal(string(file), &cfg) if err != nil { - cfg = properties.Default + cfg = properties2.Default } return cfg } - -func loadStates() (ok bool) { - os.Mkdir("resources", 0755) - f, err := os.OpenFile("./resources/blocks", os.O_CREATE|os.O_RDWR, 0755) - if err != nil { - log.ErrorlnClean("Error opening block states file: ", err) - return false - } - - if err := section.ImportStates(f); err == nil { - return true - } - - log.Info("Downloading block states file") - - res, err := http.Get(statesfilei) - if err != nil { - fmt.Println("... error") - log.ErrorlnClean("Error downloading block states file: ", err) - return false - } - if _, err := f.ReadFrom(res.Body); err != nil { - fmt.Println("... error") - log.ErrorlnClean("Error downloading block states file: ", err) - return false - } - - f.Seek(0, 0) - - fmt.Println("... done") - - if err := section.ImportStates(f); err != nil { - log.ErrorlnClean("An error occured while loading block states file: ", err) - - return false - } - - return true -} - -var statesfilei = "https://github.com/ZeppelinMC/resources/raw/main/blocks" diff --git a/protocol/properties/decode.go b/properties/decode.go similarity index 100% rename from protocol/properties/decode.go rename to properties/decode.go diff --git a/protocol/properties/encode.go b/properties/encode.go similarity index 100% rename from protocol/properties/encode.go rename to properties/encode.go diff --git a/protocol/properties/properties.go b/properties/properties.go similarity index 94% rename from protocol/properties/properties.go rename to properties/properties.go index 565e7229..72ebd311 100644 --- a/protocol/properties/properties.go +++ b/properties/properties.go @@ -28,7 +28,7 @@ type ServerProperties struct { EnforceSecureProfile bool `properties:"enforce-secure-profile"` EnforceWhitelist bool `properties:"enforce-whitelist"` - EntityBroadcastRangePrecentage int `properties:"entity-broadcast-range-precentage"` + EntityBroadcastRangePrecentage int `properties:"state-broadcast-range-precentage"` ForceGamemode bool `properties:"force-gamemode"` FunctionPermissionLevel int `properties:"function-permission-level"` Gamemode string `properties:"gamemode"` @@ -66,9 +66,7 @@ type ServerProperties struct { SimulationDistance int `properties:"simulation-distance"` - SpawnAnimals bool `properties:"spawn-animals"` SpawnMonsters bool `properties:"spawn-monsters"` - SpawnNPCs bool `properties:"spawn-npcs"` SpawnProtection int `properties:"spawn-protection"` ViewDistance int32 `properties:"view-distance"` @@ -102,9 +100,7 @@ var Default = ServerProperties{ RegionFileCompression: "deflate", ServerPort: 25565, SimulationDistance: 10, - SpawnAnimals: true, SpawnMonsters: true, - SpawnNPCs: true, SpawnProtection: 16, ViewDistance: 10, } diff --git a/readme.md b/readme.md index 840272d5..e03356cb 100644 --- a/readme.md +++ b/readme.md @@ -1,7 +1,7 @@ ![zeppelinbanner (1)](https://github.com/user-attachments/assets/21605ec4-1253-460e-84c3-d984df14f212) # Zeppelin -Highly optimized server implementation written in [Go](https://go.dev) for Minecraft 1.21.1 +Highly optimized server implementation written in [Go](https://go.dev) for Minecraft 1.21.3 [Discord Server](https://discord.gg/T8qEtDWPak) diff --git a/server/command/command.go b/server/command/command.go index b9c218ba..15daddbb 100644 --- a/server/command/command.go +++ b/server/command/command.go @@ -3,7 +3,6 @@ package command import ( "github.com/zeppelinmc/zeppelin/protocol/text" - "github.com/zeppelinmc/zeppelin/server/session" ) type Command struct { @@ -33,8 +32,8 @@ func (a Arguments) Fallback(i int, fb string) string { type CommandCallContext struct { Command Command - Executor session.DummySession Server any + Executor Caller Arguments Arguments } diff --git a/server/command/manager.go b/server/command/manager.go index c256718e..0dab7801 100644 --- a/server/command/manager.go +++ b/server/command/manager.go @@ -6,7 +6,6 @@ import ( "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" "github.com/zeppelinmc/zeppelin/protocol/text" - "github.com/zeppelinmc/zeppelin/server/session" ) type Manager struct { @@ -17,6 +16,10 @@ type Manager struct { graph *play.Commands } +type Caller interface { + SystemMessage(text.TextComponent) error +} + func NewManager(srv any, cmds ...Command) *Manager { return &Manager{commands: cmds, srv: srv} } @@ -28,7 +31,7 @@ func (mgr *Manager) Register(cmds ...Command) { mgr.graph = nil } -func (mgr *Manager) Call(command string, caller session.DummySession) { +func (mgr *Manager) Call(command string, caller Caller) { arguments := strings.Split(command, " ") if len(arguments) == 0 { caller.SystemMessage( diff --git a/server/console.go b/server/console.go deleted file mode 100644 index 894f2625..00000000 --- a/server/console.go +++ /dev/null @@ -1,127 +0,0 @@ -package server - -import ( - "errors" - - "github.com/google/uuid" - "github.com/zeppelinmc/zeppelin/protocol/net/metadata" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/protocol/properties" - "github.com/zeppelinmc/zeppelin/protocol/text" - "github.com/zeppelinmc/zeppelin/server/entity" - "github.com/zeppelinmc/zeppelin/server/session" - "github.com/zeppelinmc/zeppelin/server/world/block/pos" - "github.com/zeppelinmc/zeppelin/server/world/chunk" - "github.com/zeppelinmc/zeppelin/server/world/chunk/section" - "github.com/zeppelinmc/zeppelin/util/log" -) - -var errConsoleUnsupportedFunc = errors.New("unsupported function for console session") - -var _ session.DummySession = (*Console)(nil) - -// Console is an implementation of session that's the server -type Console struct { - Server *Server -} - -func (c *Console) Config() properties.ServerProperties { - return c.Server.cfg -} - -func (c *Console) DespawnEntities(...int32) error { - return errConsoleUnsupportedFunc -} - -func (c *Console) EntityAnimation(int32, byte) error { - return errConsoleUnsupportedFunc -} - -func (c *Console) EntityMetadata(int32, metadata.Metadata) error { - return errConsoleUnsupportedFunc -} - -func (c *Console) DisguisedChatMessage(msg text.TextComponent, session session.Session, chatType string) error { - switch chatType { - case "minecraft:chat": - log.Printlnf("%s <%s> %s", log.Time(), session.Username(), log.SprintText(msg)) - } - return nil -} - -func (c *Console) PlayerChatMessage(pk play.ChatMessage, session session.Session, chatType string, index int32, prev []play.PreviousMessage) error { - switch chatType { - case "minecraft:chat": - log.Printlnf("%s <%s> %s", log.Time(), session.Username(), pk.Message) - } - return nil -} - -func (c *Console) PlayerInfoRemove(uuids ...uuid.UUID) error { - return errConsoleUnsupportedFunc -} - -func (c *Console) PlayerInfoUpdate(pk *play.PlayerInfoUpdate) error { - return errConsoleUnsupportedFunc -} - -func (c *Console) SpawnEntity(entity.Entity) error { - return errConsoleUnsupportedFunc -} - -func (c *Console) SpawnPlayer(session.Session) error { - return errConsoleUnsupportedFunc -} - -func (c *Console) SystemMessage(msg text.TextComponent) error { - log.Printlnf("%s %s", log.Time(), log.SprintText(msg)) - return nil -} - -func (c *Console) UpdateEntityPosition(entity.Entity, *play.UpdateEntityPosition) error { - return errConsoleUnsupportedFunc -} - -func (c *Console) UpdateEntityPositionRotation(entity.Entity, *play.UpdateEntityPositionAndRotation) error { - return errConsoleUnsupportedFunc -} - -func (c *Console) UpdateEntityRotation(entity.Entity, *play.UpdateEntityRotation) error { - return errConsoleUnsupportedFunc -} - -func (c *Console) UpdateTime(int64, int64) error { - return errConsoleUnsupportedFunc -} - -func (c *Console) BlockAction(*play.BlockAction) error { - return errConsoleUnsupportedFunc -} - -func (c *Console) PlaySound(*play.SoundEffect) error { - return errConsoleUnsupportedFunc -} - -func (c *Console) PlayEntitySound(*play.EntitySoundEffect) error { - return errConsoleUnsupportedFunc -} - -func (c *Console) UpdateBlock(pos pos.BlockPosition, b section.Block) error { - return errConsoleUnsupportedFunc -} - -func (c *Console) UpdateBlockEntity(pos pos.BlockPosition, be chunk.BlockEntity) error { - return errConsoleUnsupportedFunc -} - -func (c *Console) DeleteMessage(id int32, sig [256]byte) error { - return errConsoleUnsupportedFunc -} - -func (c *Console) DamageEvent(attacker, attacked session.Session, damageType string) error { - return errConsoleUnsupportedFunc -} - -func (c *Console) Broadcast() *session.Broadcast { - return c.Server.World.Broadcast -} diff --git a/server/entity/entity.go b/server/entity/entity.go index f554f727..ec20215f 100644 --- a/server/entity/entity.go +++ b/server/entity/entity.go @@ -1,8 +1,14 @@ package entity import ( + "maps" + "math" + "slices" + "sync" "sync/atomic" + a "github.com/zeppelinmc/zeppelin/util/atomic" + "github.com/google/uuid" "github.com/zeppelinmc/zeppelin/protocol/net/metadata" ) @@ -13,37 +19,184 @@ func NewEntityId() int32 { return entityId.Add(1) } -// The interface all entities should implement -type Entity interface { - // The type of entity this is - Type() int32 - // The unique global identifier of this entity - UUID() uuid.UUID - // The unique identifier of this entity for this server - EntityId() int32 - // The position of this entity (x, y, z) - Position() (x, y, z float64) - // The rotation of this entity (yaw, pitch) - Rotation() (yaw, pitch float32) - // The metadata of this entity - Metadata() metadata.Metadata - // The attributes of this entity - Attributes() []Attribute - // The name of the dimension this entity is in - Dimension() string -} - -// The interface all living entities should implement -type LivingEntity interface { +func New(uuid uuid.UUID, typ int32, metadata metadata.Metadata, attributes []Attribute) *Entity { + return &Entity{ + uuid: uuid, + typ: typ, + metadata: metadata, + attributes: attributes, + } +} + +func NewLiving(e *Entity) LivingEntity { + return LivingEntity{Entity: *e} +} + +// base state +type Entity struct { + uuid uuid.UUID + typ int32 + + x, y, z atomic.Uint64 // the position of the state + vx, vy, vz atomic.Uint64 // the velocity of the state + yaw, pitch atomic.Uint32 // the rotation of the state + onGround atomic.Bool + + md_mu sync.RWMutex + metadata metadata.Metadata + + attr_mu sync.RWMutex + attributes []Attribute + + dimension a.AtomicValue[string] +} + +func (p *Entity) Attribute(id string) *Attribute { + p.attr_mu.Lock() + defer p.attr_mu.Unlock() + i := slices.IndexFunc(p.attributes, func(att Attribute) bool { return att.Id == id }) + if i == -1 { + attr, ok := DefaultAttributes[id] + if !ok { + return nil + } + a := Attribute{ + Id: id, + Base: attr, + } + p.attributes = append(p.attributes, a) + return &a + } + attr := &p.attributes[i] + return attr +} + +// returns a clone of the attributes of this state +func (p *Entity) Attributes() []Attribute { + p.attr_mu.RLock() + defer p.attr_mu.RUnlock() + return slices.Clone(p.attributes) +} + +func (p *Entity) SetAttribute(id string, base float64) { + p.attr_mu.Lock() + defer p.attr_mu.Unlock() + i := slices.IndexFunc(p.attributes, func(att Attribute) bool { return att.Id == id }) + if i == -1 { + return + } + p.attributes[i].Base = base +} + +// returns a clone of the metadata of this state +func (e *Entity) Metadata() metadata.Metadata { + e.md_mu.RLock() + defer e.md_mu.RUnlock() + return maps.Clone(e.metadata) +} + +func (p *Entity) SetMetadata(md metadata.Metadata) { + p.md_mu.Lock() + defer p.md_mu.Unlock() + p.metadata = md +} + +func (p *Entity) MetadataIndex(i byte) any { + p.md_mu.RLock() + defer p.md_mu.RUnlock() + return p.metadata[i] +} + +func (p *Entity) SetMetadataIndex(i byte, v any) { + p.md_mu.Lock() + defer p.md_mu.Unlock() + p.metadata[i] = v +} + +func (p *Entity) SetMetadataIndexes(md metadata.Metadata) { + p.md_mu.Lock() + defer p.md_mu.Unlock() + for index, value := range md { + p.metadata[index] = value + } +} + +func (e *Entity) Dimension() string { + return e.dimension.Get() +} + +func (e *Entity) SetDimension(v string) { + e.dimension.Set(v) +} + +func (e *Entity) SetMotion(x, y, z float64) { + e.vx.Store(math.Float64bits(x)) + e.vy.Store(math.Float64bits(y)) + e.vz.Store(math.Float64bits(z)) +} + +func (e *Entity) SetPosition(x, y, z float64) { + e.x.Store(math.Float64bits(x)) + e.y.Store(math.Float64bits(y)) + e.z.Store(math.Float64bits(z)) +} + +func (e *Entity) SetRotation(yaw, pitch float32) { + e.yaw.Store(math.Float32bits(yaw)) + e.pitch.Store(math.Float32bits(pitch)) +} + +func (e *Entity) SetOnGround(v bool) { + e.onGround.Store(v) +} + +func (e *Entity) Position() (x, y, z float64) { + return math.Float64frombits(e.x.Load()), math.Float64frombits(e.y.Load()), math.Float64frombits(e.z.Load()) +} + +func (e *Entity) Motion() (vx, vy, vz float64) { + return math.Float64frombits(e.vx.Load()), math.Float64frombits(e.vy.Load()), math.Float64frombits(e.vz.Load()) +} + +func (e *Entity) Rotation() (yaw, pitch float32) { + return math.Float32frombits(e.yaw.Load()), math.Float32frombits(e.pitch.Load()) +} + +func (e *Entity) OnGround() bool { + return e.onGround.Load() +} + +func (e *Entity) UUID() uuid.UUID { + return e.uuid +} + +func (e *Entity) Type() int32 { + return e.typ +} + +type LivingEntity struct { Entity - // the health of this entity - Health() float32 - // the food level of this entity - Food() int32 - // the food saturation level of this entity - FoodSaturation() float32 - // the food exhaustion level of this entity - FoodExhaustion() float32 + health, + food, + foodSaturation, foodExhaustion atomic.Uint32 +} + +func (l *LivingEntity) SetHealth(h float32) { + l.health.Store(math.Float32bits(h)) +} + +func (l *LivingEntity) SetFood(food int32, saturation, exhaustion float32) { + l.food.Store(uint32(food)) + l.foodSaturation.Store(math.Float32bits(saturation)) + l.foodExhaustion.Store(math.Float32bits(exhaustion)) +} + +func (l *LivingEntity) Health() float32 { + return math.Float32frombits(l.health.Load()) +} + +func (l *LivingEntity) Food() (food int32, saturation, exhaustion float32) { + return int32(l.food.Load()), math.Float32frombits(l.foodSaturation.Load()), math.Float32frombits(l.foodExhaustion.Load()) } type Attribute struct { diff --git a/server/entity/levelEntity.go b/server/entity/levelEntity.go index 14cbaa45..01e8df4b 100644 --- a/server/entity/levelEntity.go +++ b/server/entity/levelEntity.go @@ -31,5 +31,5 @@ type LevelEntity struct { TicksFrozen int32 `nbt:"TicksFrozen,omitempty"` UUID uuid.UUID - //TODO add entity subclasses + //TODO add state subclasses } diff --git a/server/player/atomic.go b/server/player/atomic.go deleted file mode 100644 index 0e665b00..00000000 --- a/server/player/atomic.go +++ /dev/null @@ -1,51 +0,0 @@ -package player - -import ( - "sync/atomic" - "unsafe" -) - -func u64f(i uint64) float64 { - return *(*float64)(unsafe.Pointer(&i)) -} -func f64u(f float64) uint64 { - return *(*uint64)(unsafe.Pointer(&f)) -} - -func u32f(i uint32) float32 { - return *(*float32)(unsafe.Pointer(&i)) -} -func f32u(f float32) uint32 { - return *(*uint32)(unsafe.Pointer(&f)) -} - -func atomicFloat64(f float64) atomic.Uint64 { - var v atomic.Uint64 - v.Store(f64u(f)) - - return v -} -func atomicFloat32(f float32) atomic.Uint32 { - return atomicUint32(f32u(f)) -} - -func atomicUint32(i uint32) atomic.Uint32 { - var v atomic.Uint32 - v.Store(i) - - return v -} - -func atomicInt32(i int32) atomic.Int32 { - var v atomic.Int32 - v.Store(i) - - return v -} - -func atomicBool(b bool) atomic.Bool { - var v atomic.Bool - v.Store(b) - - return v -} diff --git a/server/player/chunks.go b/server/player/chunks.go new file mode 100644 index 00000000..281c3370 --- /dev/null +++ b/server/player/chunks.go @@ -0,0 +1,59 @@ +package player + +import ( + "bytes" + "github.com/zeppelinmc/zeppelin/protocol/net/io/buffers" + "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" + "github.com/zeppelinmc/zeppelin/server/world/dimension" +) + +// Dimension returns the dimension struct this player is in +func (p *Player) Dimension() *dimension.Dimension { + return p.dimensionManager.Dimension(p.state.Dimension()) +} + +func (p *Player) sendSpawnChunks() error { + viewDistance := p.ViewDistance() + + x, _, z := p.state.Position() + chunkX, chunkZ := int32(x)>>4, int32(z)>>4 + + if err := p.WritePacket(&play.SetCenterChunk{ChunkX: chunkX, ChunkZ: chunkZ}); err != nil { + return err + } + + var chunks int32 + + if err := p.WritePacket(&play.ChunkBatchStart{}); err != nil { + return err + } + + buf := buffers.Buffers.Get().(*bytes.Buffer) + + for x := chunkX - viewDistance; x < chunkX+viewDistance; x++ { + for z := chunkZ - viewDistance; z < chunkZ+viewDistance; z++ { + buf.Reset() + c, err := p.Dimension().GetChunkBuf(x, z, buf) + if err != nil { + continue + } + buf.Reset() + + if err := p.WritePacket(c.EncodeBuf(p.registryIndexes["minecraft:worldgen/biome"], buf)); err != nil { + return err + } + chunks++ + } + } + buffers.Buffers.Put(buf) + + if err := p.WritePacket(&play.ChunkBatchFinished{ + BatchSize: chunks, + }); err != nil { + return err + } + + _, err := p.awaitPacket(play.PacketIdChunkBatchReceived) + + return err +} diff --git a/server/player/conn.go b/server/player/conn.go new file mode 100644 index 00000000..ef617ddd --- /dev/null +++ b/server/player/conn.go @@ -0,0 +1,112 @@ +package player + +import ( + "github.com/zeppelinmc/zeppelin/protocol/net/packet" + "github.com/zeppelinmc/zeppelin/protocol/net/packet/configuration" + "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" + "github.com/zeppelinmc/zeppelin/util/log" + "time" + "unsafe" +) + +// RegisteredHandlers maps all handler functions by their state[0] and id[1] +var RegisteredHandlers = make(map[[2]int32]func(packet packet.Decodeable) error) + +// awaitPacket waits for the packet with the id to be received +func (p *Player) awaitPacket(id int32) (packet.Decodeable, error) { + p.packetAwaited.Store(id) + c := make(chan packet.Decodeable) + p.packetAwaitedChan.Store(&c) + + pk := <-c + if pk, ok := pk.(packet.Error); ok { + return nil, pk.Error + } + + return pk, nil +} + +func interfaceAssert[T any](v any) T { + return *(*T)(unsafe.Add(unsafe.Pointer(&v), unsafe.Sizeof(0))) +} + +func (p *Player) keepAlive() error { + l := time.Now().UnixMilli() + p.cbLastKeepAlive.Store(l) + return p.WritePacket(&play.ClientboundKeepAlive{KeepAliveID: l}) +} + +// isConnectionDead checks if more than 15 seconds have passed since the client sent a keep alive packet +func (p *Player) isConnectionDead() bool { + lastKeepAliveByClient := p.sbLastKeepalive.Load() + return lastKeepAliveByClient != 0 && time.Now().UnixMilli()-lastKeepAliveByClient > (15*1000) +} + +func (p *Player) listenPackets() { + keepAliveTicker := time.NewTicker(time.Second * 20) + for { + select { + case <-keepAliveTicker.C: + if err := p.keepAlive(); err != nil { + p.killConnection(false, "lost connection") + return + } + default: + if p.isConnectionDead() { + //todo disconnect + p.killConnection(false, "timed out") + return + } + pk, s, err := p.ReadPacket() + + awaitId := p.packetAwaited.Load() + + if err != nil { + p.killConnection(false, "lost connection") + + if awaitId != -1 { + *p.packetAwaitedChan.Swap(nil) <- packet.Error{Error: err} + p.packetAwaited.Store(-1) + } + return + } + + if s { + // The packet was stopped mid-interception, and shouldn't be handled + continue + } + + state, id := p.State(), pk.ID() + + // This packet is awaited by another goroutine + if awaitId == id { + *p.packetAwaitedChan.Swap(nil) <- pk + p.packetAwaited.Store(-1) + } + + handler, ok := RegisteredHandlers[[2]int32{state, id}] + if !ok { + switch pk := pk.(type) { + case *configuration.ClientInformation, *play.ClientInformation: + p.ClientInformation.Store(interfaceAssert[*configuration.ClientInformation](pk)) + } + continue + } + + if err := handler(pk); err != nil { + p.killConnection(false, "packet handling error: "+err.Error()) + return + } + } + } +} + +// killConnection kills the player's connection +func (p *Player) killConnection(serverError bool, reason string) { + var logFunction = log.Infolnf + if serverError { + // if an error happened on the server's side, the log message will be an error + logFunction = log.Errorlnf + } + logFunction("%sPlayer %s disconnected: %s", log.FormatAddr(true /*TODO replace*/, p.RemoteAddr()), p.Username(), reason) +} diff --git a/server/player/list/playerlist.go b/server/player/list/playerlist.go deleted file mode 100644 index b891b632..00000000 --- a/server/player/list/playerlist.go +++ /dev/null @@ -1,15 +0,0 @@ -// Package list provides parsing of playerlist files (whitelist.json, ops.json etc) - -package list - -type WhitelistPlayer struct { - UUID string `json:"uuid"` - Name string `json:"name"` -} - -type OperatorPlayer struct { - UUID string `json:"uuid"` - Name string `json:"name"` - Level int32 `json:"level"` - BypassesPlayerLimit bool `json:"bypassesPlayerLimit"` -} diff --git a/server/player/manager.go b/server/player/manager.go deleted file mode 100644 index d8d60c8c..00000000 --- a/server/player/manager.go +++ /dev/null @@ -1,43 +0,0 @@ -package player - -import ( - "sync" - - "github.com/google/uuid" -) - -// the player cache is used when saving the world playerdata - -type PlayerManager struct { - m map[uuid.UUID]*Player - mu sync.RWMutex -} - -func (cache *PlayerManager) lookup(id uuid.UUID) (*Player, bool) { - cache.mu.RLock() - defer cache.mu.RUnlock() - p, ok := cache.m[id] - - return p, ok -} - -func (cache *PlayerManager) add(p *Player) { - cache.mu.Lock() - defer cache.mu.Unlock() - cache.m[p.UUID()] = p -} - -// saves all the players in the manager to the path specified in their data file -func (cache *PlayerManager) SaveAll() { - cache.mu.RLock() - defer cache.mu.RUnlock() - for _, player := range cache.m { - player.sync() - - player.data.Save() - } -} - -func NewPlayerManager() *PlayerManager { - return &PlayerManager{m: make(map[uuid.UUID]*Player)} -} diff --git a/server/player/player.go b/server/player/player.go index b8be5c1f..5eae13d5 100644 --- a/server/player/player.go +++ b/server/player/player.go @@ -1,359 +1,186 @@ package player import ( - "maps" - "slices" - "sync" - a "sync/atomic" - - "github.com/google/uuid" - "github.com/zeppelinmc/zeppelin/protocol/net/metadata" - "github.com/zeppelinmc/zeppelin/server/container" + "github.com/zeppelinmc/zeppelin/protocol/net" + "github.com/zeppelinmc/zeppelin/protocol/net/io/encoding" + "github.com/zeppelinmc/zeppelin/protocol/net/packet" + "github.com/zeppelinmc/zeppelin/protocol/net/packet/configuration" + "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" + "github.com/zeppelinmc/zeppelin/protocol/net/tags" "github.com/zeppelinmc/zeppelin/server/entity" - "github.com/zeppelinmc/zeppelin/server/registry" + "github.com/zeppelinmc/zeppelin/server/player/state" + "github.com/zeppelinmc/zeppelin/server/world/dimension" "github.com/zeppelinmc/zeppelin/server/world/level" - "github.com/zeppelinmc/zeppelin/util/atomic" + "slices" + "sync/atomic" + "unsafe" ) -var _ entity.LivingEntity = (*Player)(nil) - type Player struct { - entityId int32 - - data level.Player - x, y, z, - vx, vy, vz a.Uint64 - yaw, pitch a.Uint32 - onGround a.Bool - - food a.Int32 - health, - foodExhaustion, - foodSaturation a.Uint32 - - abilities atomic.AtomicValue[level.PlayerAbilities] - - dimension atomic.AtomicValue[string] - - gameMode a.Int32 - selectedItemSlot a.Int32 + *net.Conn - recipeBook atomic.AtomicValue[level.RecipeBook] - - md_mu sync.RWMutex - metadata metadata.Metadata - - inventory *container.Container - - att_mu sync.RWMutex - attributes []entity.Attribute -} - -// looks up a player in the cache or creates one if not found -func (mgr *PlayerManager) New(data level.Player) *Player { - if p, ok := mgr.lookup(data.UUID.UUID()); ok { - return p - } - - pl := &Player{ - entityId: entity.NewEntityId(), - metadata: metadata.Metadata{ - // Entity - metadata.BaseIndex: metadata.Byte(0), - metadata.AirTicksIndex: metadata.VarInt(300), - metadata.CustomNameIndex: metadata.OptionalTextComponent(nil), - metadata.IsCustomNameVisibleIndex: metadata.Boolean(false), - metadata.IsSilentIndex: metadata.Boolean(false), - metadata.HasNoGravityIndex: metadata.Boolean(false), - metadata.PoseIndex: metadata.Standing, - metadata.TicksFrozenInPowderedSnowIndex: metadata.VarInt(0), - // Living Entity extends Entity - metadata.LivingEntityHandstatesIndex: metadata.Byte(0), - metadata.LivingEntityHealthIndex: metadata.Float(data.Health), - //metadata.LivingEntityPotionEffectColorIndex: metadata.VarInt(0), - metadata.LivingEntityPotionEffectAmbientIndex: metadata.Boolean(false), - metadata.LivingEntityArrowCountIndex: metadata.VarInt(0), - metadata.LivingEntityBeeStingersCountIndex: metadata.VarInt(0), - metadata.LivingEntitySleepingBedPositionIndex: metadata.OptionalPosition(nil), - // Player extends Living Entity - metadata.PlayerAdditionalHeartsIndex: metadata.Float(0), - metadata.PlayerScoreIndex: metadata.VarInt(0), - metadata.PlayerDisplayedSkinPartsIndex: metadata.Byte(0), - metadata.PlayerMainHandIndex: metadata.Byte(1), - }, - - x: atomicFloat64(data.Pos[0]), - y: atomicFloat64(data.Pos[1]), - z: atomicFloat64(data.Pos[2]), - - vx: atomicFloat64(data.Motion[0]), - vy: atomicFloat64(data.Motion[1]), - vz: atomicFloat64(data.Motion[2]), - - yaw: atomicFloat32(data.Rotation[0]), - pitch: atomicFloat32(data.Rotation[1]), - - onGround: atomicBool(data.OnGround), - - dimension: atomic.Value(data.Dimension), - - gameMode: atomicInt32(int32(data.PlayerGameType)), - - recipeBook: atomic.Value(data.RecipeBook), - - selectedItemSlot: atomicInt32(data.SelectedItemSlot), - - health: atomicFloat32(data.Health), - food: atomicInt32(data.FoodLevel), - foodExhaustion: atomicFloat32(data.FoodExhaustionLevel), - foodSaturation: atomicFloat32(data.FoodSaturationLevel), - - abilities: atomic.Value(data.Abilities), - - inventory: &data.Inventory, - - attributes: data.Attributes, - - data: data, - } - mgr.add(pl) - - return pl -} - -func (p *Player) Type() int32 { - return registry.EntityType.Get("minecraft:player") -} - -func (p *Player) UUID() uuid.UUID { - return p.data.UUID.UUID() -} - -func (p *Player) Position() (x, y, z float64) { - return u64f(p.x.Load()), u64f(p.y.Load()), u64f(p.z.Load()) -} - -func (p *Player) Rotation() (yaw, pitch float32) { - return u32f(p.yaw.Load()), u32f(p.pitch.Load()) -} + playerList *PlayerList + // the player entity + state *state.PlayerEntity + // the entity id for this player + entityId int32 -func (p *Player) OnGround() bool { - return p.onGround.Load() -} + ClientInformation atomic.Pointer[configuration.ClientInformation] -func (p *Player) SetPosition(x, y, z float64) { - p.x.Store(f64u(x)) - p.y.Store(f64u(y)) - p.z.Store(f64u(z)) -} + dimensionManager *dimension.DimensionManager + worldLevel *level.Level -func (p *Player) SetRotation(yaw, pitch float32) { - p.yaw.Store(f32u(yaw)) - p.pitch.Store(f32u(pitch)) -} + // the time in milliseconds that the keep alive packet was sent to the server from the client + sbLastKeepalive atomic.Int64 + // the time in milliseconds that the keep alive packet was sent to the client from the server + cbLastKeepAlive atomic.Int64 -func (p *Player) SetOnGround(val bool) { - p.onGround.Store(val) -} + registryIndexes map[string][]string -func (p *Player) Motion() (x, y, z float64) { - return u64f(p.vx.Load()), u64f(p.vy.Load()), u64f(p.vz.Load()) + // the packet currently awaited + packetAwaited atomic.Int32 + packetAwaitedChan atomic.Pointer[chan packet.Decodeable] } -func (p *Player) SetMotion(x, y, z float64) { - p.vx.Store(f64u(x)) - p.vy.Store(f64u(y)) - p.vz.Store(f64u(z)) +func int32toAtomic(i int32) atomic.Int32 { + // int32 and atomic.Int32 are the same structure and size + return *(*atomic.Int32)(unsafe.Pointer(&i)) } -func (p *Player) EntityId() int32 { - return p.entityId -} +func (list *PlayerList) New(conn *net.Conn, en *state.PlayerEntity, dimensionManager *dimension.DimensionManager, worldLevel *level.Level) *Player { + p := &Player{ + entityId: entity.NewEntityId(), + state: en, -// returns a clone of the metadata of this player -func (p *Player) Metadata() metadata.Metadata { - p.md_mu.RLock() - defer p.md_mu.RUnlock() - return maps.Clone(p.metadata) -} + dimensionManager: dimensionManager, + worldLevel: worldLevel, -func (p *Player) SetMetadata(md metadata.Metadata) { - p.md_mu.Lock() - defer p.md_mu.Unlock() - p.metadata = md -} + registryIndexes: make(map[string][]string), -func (p *Player) MetadataIndex(i byte) any { - p.md_mu.RLock() - defer p.md_mu.RUnlock() - return p.metadata[i] -} + packetAwaited: int32toAtomic(-1), -func (p *Player) SetMetadataIndex(i byte, v any) { - p.md_mu.Lock() - defer p.md_mu.Unlock() - p.metadata[i] = v -} + playerList: list, -func (p *Player) SetMetadataIndexes(md metadata.Metadata) { - p.md_mu.Lock() - defer p.md_mu.Unlock() - for index, value := range md { - p.metadata[index] = value + Conn: conn, } -} - -func (p *Player) Dimension() string { - return p.dimension.Get() -} + p.ClientInformation.Store(&configuration.ClientInformation{}) -func (p *Player) SetDimension(dim string) { - p.dimension.Set(dim) + return p } -func (p *Player) Health() float32 { - return u32f(p.health.Load()) -} +/* +ViewDistance returns the view distance of the client, in chunks, or the server's render distance if the client's view distance is bigger or not set +*/ +func (p *Player) ViewDistance() int32 { + plVd := int32(p.ClientInformation.Load().ViewDistance) + /*if plVd == 0 || plVd > int32(session.config.ViewDistance) { + return int32(session.config.ViewDistance) + }*/ // todo add this back -func (p *Player) SetHealth(h float32) { - p.health.Store(f32u(h)) + return plVd } -func (p *Player) Food() int32 { - return p.food.Load() -} +// finishConfiguration finishes the configuration phase by sending the server brand, registries and tags +func (p *Player) finishConfiguration() error { + // begin packet reading in the background + go p.listenPackets() -func (p *Player) SetFood(f int32) { - p.food.Store(f) -} + // send the server brand (shows in F3) + if err := p.WritePacket(&configuration.ClientboundPluginMessage{ + Channel: "minecraft:brand", + Data: encoding.AppendString(nil, "Zeppelin"), + }); err != nil { + return err + } -func (p *Player) FoodSaturation() float32 { - return u32f(p.foodSaturation.Load()) -} + // send the registry packets + configuration.RegistryPacketsMutex.Lock() + for _, pk := range configuration.RegistryPackets { + if err := p.WritePacket(pk); err != nil { + return err + } + p.registryIndexes[pk.RegistryId] = slices.Clone(pk.Indexes) + } + configuration.RegistryPacketsMutex.Unlock() -func (p *Player) SetFoodSaturation(fs float32) { - p.foodSaturation.Store(f32u(fs)) -} + // finish the configuration phase + if err := p.WritePacket(configuration.FinishConfiguration{}); err != nil { + return err + } -func (p *Player) FoodExhaustion() float32 { - return u32f(p.foodExhaustion.Load()) -} + // wait for the client to acknowledge the finish configuration packet + if _, err := p.awaitPacket(configuration.PacketIdAcknowledgeFinishConfiguration); err != nil { + return err + } -func (p *Player) SetFoodExhaustion(fh float32) { - p.foodExhaustion.Store(f32u(fh)) -} + // switch to play state + p.SetState(net.PlayState) -func (p *Player) Abilities() level.PlayerAbilities { - return p.abilities.Get() + // send tags (blocks, fluids, etc) + return p.WritePacket(tags.Tags) } -func (p *Player) SetAbilities(abs level.PlayerAbilities) { - p.abilities.Set(abs) -} +// startGame finishes the initialization for the player and logs it into the world +func (p *Player) startGame() error { + if err := p.WritePacket(&play.Login{ + EntityID: p.entityId, + DimensionName: p.state.Dimension(), + GameMode: 1, + DimensionType: int32(slices.Index(p.registryIndexes["minecraft:dimension_type"], p.state.Dimension())), + }); err != nil { + return err + } -func (p *Player) GameMode() level.GameMode { - return level.GameMode(p.gameMode.Load()) -} + // todo add all other stuff + if err := p.WritePacket(&play.SetDefaultSpawnPosition{ + X: p.worldLevel.Data.SpawnX, + Y: p.worldLevel.Data.SpawnY, + Z: p.worldLevel.Data.SpawnZ, + Angle: p.worldLevel.Data.SpawnAngle, + }); err != nil { + return err + } -func (p *Player) SetGameMode(mode level.GameMode) { - p.gameMode.Store(int32(mode)) -} + x, y, z := p.state.Position() + yaw, pitch := p.state.Rotation() -func (p *Player) Attribute(id string) *entity.Attribute { - p.att_mu.Lock() - defer p.att_mu.Unlock() - i := slices.IndexFunc(p.attributes, func(att entity.Attribute) bool { return att.Id == id }) - if i == -1 { - attr, ok := entity.DefaultAttributes[id] - if !ok { - return nil - } - a := entity.Attribute{ - Id: id, - Base: attr, - } - p.attributes = append(p.attributes, a) - return &a + if err := p.SynchronizePosition(x, y, z, yaw, pitch); err != nil { + return err } - attr := &p.attributes[i] - return attr -} -// returns a clone of the attributes of this player -func (p *Player) Attributes() []entity.Attribute { - p.att_mu.RLock() - defer p.att_mu.RUnlock() - return slices.Clone(p.attributes) -} + if err := p.sendSpawnChunks(); err != nil { + return err + } -func (p *Player) SetAttribute(id string, base float64) { - p.att_mu.Lock() - defer p.att_mu.Unlock() - i := slices.IndexFunc(p.attributes, func(att entity.Attribute) bool { return att.Id == id }) - if i == -1 { - return + if err := p.SynchronizePosition(x, y, z, yaw, pitch); err != nil { + return err } - p.attributes[i].Base = base -} -func (p *Player) RecipeBook() level.RecipeBook { - return p.recipeBook.Get() -} + if err := p.WritePacket(&play.GameEvent{Event: play.GameEventStartWaitingChunks}); err != nil { + return err + } + p.playerList.AddPlayer(p) -func (p *Player) SetRecipeBook(book level.RecipeBook) { - p.recipeBook.Set(book) + return nil } -func (p *Player) Inventory() *container.Container { - return p.inventory -} +// SynchronizePosition teleports the player to the specified coordinates +func (p *Player) SynchronizePosition(x, y, z float64, yaw, pitch float32) error { + p.state.SetPosition(x, y, z) + p.state.SetRotation(yaw, pitch) -// if negative, returns 0 and if over 8, returns 8 -func (p *Player) SelectedItemSlot() int32 { - slot := p.selectedItemSlot.Load() - if slot < 0 { - slot = 0 - } - if slot > 8 { - slot = 8 + if err := p.WritePacket(&play.SynchronizePlayerPosition{X: x, Y: y, Z: z, Yaw: yaw, Pitch: pitch}); err != nil { + return err } - return slot -} + _, err := p.awaitPacket(play.PacketIdConfirmTeleportation) -// if negative, set to 0 and if over 8, set to 8 -func (p *Player) SetSelectedItemSlot(slot int32) { - if slot < 0 { - slot = 0 - } - if slot > 8 { - slot = 8 - } - p.selectedItemSlot.Store(slot) + return err } -func (p *Player) sync() { - x, y, z := p.Position() - yaw, pitch := p.Rotation() - vx, vy, vz := p.Motion() - - p.data.Abilities = p.abilities.Get() - p.data.Pos = [3]float64{x, y, z} - p.data.Rotation = [2]float32{yaw, pitch} - p.data.OnGround = p.onGround.Load() - p.data.Dimension = p.dimension.Get() - p.data.Inventory = *p.inventory - p.data.RecipeBook = p.recipeBook.Get() - - p.data.Motion = [3]float64{vx, vy, vz} - - p.att_mu.RLock() - p.data.Attributes = p.attributes - p.att_mu.RUnlock() - - p.data.Health = u32f(p.health.Load()) - p.data.FoodLevel = p.food.Load() - p.data.FoodExhaustionLevel = u32f(p.foodExhaustion.Load()) - p.data.FoodSaturationLevel = u32f(p.foodSaturation.Load()) - p.data.PlayerGameType = level.GameMode(p.gameMode.Load()) - p.data.SelectedItemSlot = p.selectedItemSlot.Load() +// Login logs the player into the game +func (p *Player) Login() error { + if err := p.finishConfiguration(); err != nil { + return err + } + return p.startGame() } diff --git a/server/player/playerlist.go b/server/player/playerlist.go new file mode 100644 index 00000000..7ee789a7 --- /dev/null +++ b/server/player/playerlist.go @@ -0,0 +1,66 @@ +package player + +import ( + "github.com/google/uuid" + "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" + "github.com/zeppelinmc/zeppelin/util/atomic" + "unsafe" +) + +func NewPlayerList(cap uintptr) PlayerList { + return PlayerList{ + playerList: atomic.Make(0, cap, atomic.Pointer), + } +} + +type PlayerList struct { + playerList atomic.Slice +} + +func (list *PlayerList) NumPlayers() int { + return int(list.playerList.Len()) +} + +func (list *PlayerList) Player(uuid uuid.UUID) *Player { + for i := uintptr(0); i < list.playerList.Len(); i++ { + player := list.playerAtIndex(i) + + if player.UUID() == uuid { + return player + } + } + return nil +} + +func (list *PlayerList) playerAtIndex(index uintptr) *Player { + return *(**Player)(list.playerList.Element(index)) +} + +func (list *PlayerList) AddPlayer(player *Player) { + list.addPlayerToSlice(player) + + update := &play.PlayerInfoUpdate{ + Actions: play.ActionAddPlayer | play.ActionUpdateListed, //todo: add the rest + Players: make(map[uuid.UUID]play.PlayerAction, list.NumPlayers()), + } + + for i := uintptr(0); i < list.playerList.Len(); i++ { + player := list.playerAtIndex(i) + + update.Players[player.UUID()] = play.PlayerAction{ + Name: player.Username(), + Listed: true, + Properties: player.Properties(), + } + } + + for i := uintptr(0); i < list.playerList.Len(); i++ { + player := list.playerAtIndex(i) + player.WritePacket(update) + } +} + +func (list *PlayerList) addPlayerToSlice(player *Player) { + pointerOfPlayer := unsafe.Pointer(player) + list.playerList.Append(unsafe.Pointer(&pointerOfPlayer)) +} diff --git a/server/registry/command_argument_type.go b/server/registry/command_argument_type.go index dd4d569c..a6066281 100644 --- a/server/registry/command_argument_type.go +++ b/server/registry/command_argument_type.go @@ -4,59 +4,59 @@ package registry var CommandArgumentType = Registry{ Default: "", Entries: map[string]int32{ - "minecraft:particle": 26, - "minecraft:nbt_path": 22, - "minecraft:gamemode": 41, - "minecraft:resource_or_tag": 43, - "minecraft:angle": 27, - "minecraft:float_range": 39, - "minecraft:template_mirror": 47, - "minecraft:nbt_compound_tag": 20, - "minecraft:scoreboard_slot": 29, - "minecraft:column_pos": 9, - "minecraft:entity_anchor": 37, - "minecraft:loot_modifier": 52, - "minecraft:function": 36, - "minecraft:resource": 45, - "brigadier:string": 5, - "minecraft:component": 17, - "minecraft:loot_predicate": 51, - "minecraft:objective": 23, - "brigadier:bool": 0, - "brigadier:double": 2, - "minecraft:block_predicate": 13, - "minecraft:entity": 6, - "minecraft:item_slots": 34, - "minecraft:objective_criteria": 24, - "brigadier:long": 4, - "minecraft:block_state": 12, - "minecraft:heightmap": 49, - "minecraft:template_rotation": 48, - "minecraft:uuid": 53, - "minecraft:block_pos": 8, - "minecraft:operation": 25, - "minecraft:int_range": 38, - "minecraft:rotation": 28, - "minecraft:swizzle": 31, - "minecraft:game_profile": 7, - "minecraft:nbt_tag": 21, - "minecraft:message": 19, - "minecraft:dimension": 40, - "minecraft:item_stack": 14, + "minecraft:particle": 26, + "minecraft:nbt_path": 22, + "minecraft:gamemode": 41, + "minecraft:resource_or_tag": 43, + "minecraft:angle": 27, + "minecraft:float_range": 39, + "minecraft:template_mirror": 47, + "minecraft:nbt_compound_tag": 20, + "minecraft:scoreboard_slot": 29, + "minecraft:column_pos": 9, + "minecraft:entity_anchor": 37, + "minecraft:loot_modifier": 52, + "minecraft:function": 36, + "minecraft:resource": 45, + "brigadier:string": 5, + "minecraft:component": 17, + "minecraft:loot_predicate": 51, + "minecraft:objective": 23, + "brigadier:bool": 0, + "brigadier:double": 2, + "minecraft:block_predicate": 13, + "minecraft:state": 6, + "minecraft:item_slots": 34, + "minecraft:objective_criteria": 24, + "brigadier:long": 4, + "minecraft:block_state": 12, + "minecraft:heightmap": 49, + "minecraft:template_rotation": 48, + "minecraft:uuid": 53, + "minecraft:block_pos": 8, + "minecraft:operation": 25, + "minecraft:int_range": 38, + "minecraft:rotation": 28, + "minecraft:swizzle": 31, + "minecraft:game_profile": 7, + "minecraft:nbt_tag": 21, + "minecraft:message": 19, + "minecraft:dimension": 40, + "minecraft:item_stack": 14, "minecraft:resource_or_tag_key": 44, - "brigadier:integer": 3, - "minecraft:item_predicate": 15, - "minecraft:style": 18, - "minecraft:time": 42, - "brigadier:float": 1, - "minecraft:item_slot": 33, - "minecraft:loot_table": 50, - "minecraft:team": 32, - "minecraft:color": 16, - "minecraft:resource_key": 46, - "minecraft:resource_location": 35, - "minecraft:score_holder": 30, - "minecraft:vec2": 11, - "minecraft:vec3": 10, + "brigadier:integer": 3, + "minecraft:item_predicate": 15, + "minecraft:style": 18, + "minecraft:time": 42, + "brigadier:float": 1, + "minecraft:item_slot": 33, + "minecraft:loot_table": 50, + "minecraft:team": 32, + "minecraft:color": 16, + "minecraft:resource_key": 46, + "minecraft:resource_location": 35, + "minecraft:score_holder": 30, + "minecraft:vec2": 11, + "minecraft:vec3": 10, }, -} \ No newline at end of file +} diff --git a/server/registry/position_source_type.go b/server/registry/position_source_type.go index a80b88af..45bcaaac 100644 --- a/server/registry/position_source_type.go +++ b/server/registry/position_source_type.go @@ -5,6 +5,6 @@ var PositionSourceType = Registry{ Default: "", Entries: map[string]int32{ "minecraft:block": 0, - "minecraft:entity": 1, + "minecraft:state": 1, }, -} \ No newline at end of file +} diff --git a/server/registry/sound_event.go b/server/registry/sound_event.go index d896462d..4a26c03a 100644 --- a/server/registry/sound_event.go +++ b/server/registry/sound_event.go @@ -4,1616 +4,1616 @@ package registry var SoundEvent = Registry{ Default: "", Entries: map[string]int32{ - "minecraft:block.scaffolding.step": 1194, - "minecraft:entity.fishing_bobber.throw": 518, - "minecraft:entity.llama.chest": 786, - "minecraft:entity.player.hurt_sweet_berry_bush": 1113, - "minecraft:entity.strider.ambient": 1302, - "minecraft:block.cherry_sapling.step": 279, - "minecraft:block.coral_block.place": 363, - "minecraft:entity.armadillo.roll": 60, - "minecraft:entity.breeze.deflect": 187, - "minecraft:entity.dolphin.attack": 413, - "minecraft:entity.parrot.imitate.endermite": 1037, - "minecraft:block.deepslate_tiles.step": 407, - "minecraft:block.packed_mud.place": 944, - "minecraft:entity.armadillo.unroll_finish": 63, - "minecraft:entity.firework_rocket.twinkle": 511, - "minecraft:entity.parrot.imitate.pillager": 1048, - "minecraft:entity.ravager.step": 1158, - "minecraft:item.armor.equip_gold": 71, - "minecraft:block.fungus.fall": 965, - "minecraft:block.hanging_roots.fall": 649, - "minecraft:block.nylium.place": 953, - "minecraft:entity.ender_eye.launch": 476, - "minecraft:entity.evoker.death": 494, - "minecraft:entity.sniffer.digging": 1326, - "minecraft:entity.warden.death": 1498, - "minecraft:block.amethyst_cluster.step": 40, - "minecraft:block.beehive.shear": 153, - "minecraft:block.sculk_sensor.step": 1214, - "minecraft:entity.fox.bite": 527, - "minecraft:entity.frog.death": 558, - "minecraft:entity.vindicator.ambient": 1474, - "minecraft:entity.witch.celebrate": 1533, - "minecraft:item.trident.return": 1386, - "minecraft:music.overworld.grove": 897, - "minecraft:block.azalea_leaves.step": 104, - "minecraft:block.note_block.harp": 992, - "minecraft:entity.goat.step": 627, - "minecraft:entity.sniffer.digging_stop": 1327, - "minecraft:entity.splash_potion.break": 1347, - "minecraft:entity.strider.hurt": 1306, - "minecraft:entity.wandering_trader.reappeared": 1491, - "minecraft:item.goat_horn.sound.3": 709, - "minecraft:block.cherry_wood.hit": 272, - "minecraft:block.cherry_wood_pressure_plate.click_on": 297, - "minecraft:block.composter.empty": 330, - "minecraft:block.copper.hit": 349, - "minecraft:block.polished_tuff.hit": 1412, - "minecraft:block.suspicious_sand.fall": 540, - "minecraft:entity.iron_golem.hurt": 751, - "minecraft:entity.piglin.retreat": 1084, - "minecraft:entity.wolf.death": 1553, - "minecraft:block.amethyst_cluster.fall": 37, - "minecraft:block.deepslate_tiles.break": 403, - "minecraft:block.enchantment_table.use": 465, - "minecraft:block.sculk_sensor.clicking": 1208, - "minecraft:block.sweet_berry_bush.pick_berries": 1376, - "minecraft:ui.toast.challenge_complete": 1433, - "minecraft:block.bamboo_wood_hanging_sign.place": 672, - "minecraft:block.glass.hit": 595, - "minecraft:block.scaffolding.place": 1193, - "minecraft:entity.firework_rocket.launch": 509, - "minecraft:entity.shulker.hurt": 1246, - "minecraft:entity.sniffer.idle": 1319, - "minecraft:entity.turtle.ambient_land": 1415, - "minecraft:ambient.underwater.loop.additions.rare": 27, - "minecraft:block.end_portal.spawn": 490, - "minecraft:entity.elder_guardian.hurt": 462, - "minecraft:entity.generic.drink": 574, - "minecraft:entity.goat.long_jump": 612, - "minecraft:entity.puffer_fish.blow_up": 1141, - "minecraft:entity.turtle.lay_egg": 1423, - "minecraft:entity.villager.death": 1456, - "minecraft:item.armor.equip_wolf": 76, - "minecraft:item.goat_horn.sound.1": 707, - "minecraft:music.overworld.sparse_jungle": 915, - "minecraft:block.bamboo.hit": 107, - "minecraft:block.frogspawn.break": 552, - "minecraft:block.sculk_sensor.clicking_stop": 1209, - "minecraft:block.wet_sponge.dries": 1525, - "minecraft:entity.drowned.swim": 453, - "minecraft:entity.hoglin.converted_to_zombified": 693, - "minecraft:entity.phantom.ambient": 1066, - "minecraft:entity.wandering_trader.trade": 1492, - "minecraft:entity.wolf.howl": 1555, - "minecraft:block.cave_vines.fall": 260, - "minecraft:block.cherry_wood_hanging_sign.place": 289, - "minecraft:entity.glow_squid.hurt": 606, - "minecraft:entity.item.pickup": 762, - "minecraft:music.nether.basalt_deltas": 893, - "minecraft:block.cherry_wood_door.open": 291, - "minecraft:block.suspicious_gravel.step": 542, - "minecraft:block.bamboo_wood_pressure_plate.click_on": 125, - "minecraft:block.ender_chest.close": 466, - "minecraft:block.lantern.place": 771, - "minecraft:block.stem.fall": 950, - "minecraft:block.tuff_bricks.step": 1409, - "minecraft:entity.zoglin.death": 1582, - "minecraft:block.netherite_block.step": 977, - "minecraft:block.sculk.step": 1201, - "minecraft:block.wart_block.fall": 975, - "minecraft:entity.skeleton_horse.death": 1259, - "minecraft:music.overworld.cherry_grove": 904, - "minecraft:block.chiseled_bookshelf.insert": 311, - "minecraft:block.hanging_roots.hit": 650, - "minecraft:entity.panda.sneeze": 1015, - "minecraft:entity.slime.death_small": 1311, - "minecraft:item.axe.scrape": 86, - "minecraft:music.nether.nether_wastes": 905, - "minecraft:block.metal.hit": 818, - "minecraft:block.pink_petals.break": 836, - "minecraft:entity.cow.death": 366, - "minecraft:entity.parrot.imitate.slime": 1053, - "minecraft:entity.zombie.step": 1601, - "minecraft:item.armor.equip_elytra": 69, - "minecraft:block.roots.break": 565, - "minecraft:block.vault.close_shutter": 1439, - "minecraft:entity.glow_item_frame.break": 600, - "minecraft:entity.horse.breathe": 717, - "minecraft:entity.leash_knot.break": 778, - "minecraft:entity.wither.hurt": 1541, - "minecraft:block.suspicious_gravel.hit": 544, - "minecraft:entity.arrow.hit_player": 83, - "minecraft:ambient.soul_sand_valley.mood": 19, - "minecraft:block.ancient_debris.break": 41, - "minecraft:block.candle.fall": 246, - "minecraft:block.decorated_pot.place": 391, - "minecraft:block.mangrove_roots.step": 813, - "minecraft:entity.firework_rocket.large_blast": 507, - "minecraft:entity.firework_rocket.shoot": 510, - "minecraft:entity.goat.screaming.death": 619, - "minecraft:entity.husk.death": 735, - "minecraft:entity.stray.ambient": 1370, - "minecraft:block.amethyst_block.step": 35, - "minecraft:block.anvil.break": 46, - "minecraft:block.snow.step": 1342, - "minecraft:entity.puffer_fish.death": 1142, - "minecraft:entity.ravager.attack": 1154, - "minecraft:entity.witch.drink": 1535, - "minecraft:block.copper_bulb.hit": 342, - "minecraft:block.mangrove_roots.fall": 810, - "minecraft:block.wet_grass.place": 1522, - "minecraft:entity.armor_stand.place": 81, - "minecraft:entity.lightning_bolt.thunder": 782, - "minecraft:item.bottle.empty": 183, - "minecraft:block.nether_gold_ore.break": 1161, - "minecraft:block.slime_block.place": 1277, - "minecraft:block.stone_pressure_plate.click_off": 1367, - "minecraft:entity.axolotl.idle_air": 91, - "minecraft:entity.hostile.swim": 732, - "minecraft:item.brush.brushing.gravel.complete": 204, - "minecraft:item.ominous_bottle.dispose": 1011, - "minecraft:block.chiseled_bookshelf.fall": 309, - "minecraft:block.pointed_dripstone.drip_water": 440, - "minecraft:entity.villager.hurt": 1457, - "minecraft:block.mud_bricks.place": 854, - "minecraft:block.trial_spawner.step": 674, - "minecraft:entity.parrot.imitate.phantom": 1045, - "minecraft:entity.squid.death": 1358, - "minecraft:block.bamboo_wood_door.open": 119, - "minecraft:block.bone_block.break": 174, - "minecraft:block.suspicious_sand.place": 538, - "minecraft:entity.mooshroom.eat": 827, - "minecraft:entity.sheep.hurt": 1228, - "minecraft:entity.zombie_horse.ambient": 1592, - "minecraft:block.note_block.flute": 990, - "minecraft:block.piston.extend": 1098, - "minecraft:block.polished_deepslate.place": 1129, - "minecraft:block.sniffer_egg.plop": 1329, - "minecraft:block.tuff.place": 1402, - "minecraft:block.tuff_bricks.fall": 1406, - "minecraft:entity.piglin.step": 1085, - "minecraft:entity.turtle.shamble_baby": 1425, - "minecraft:entity.villager.work_toolsmith": 1472, - "minecraft:item.armor.unequip_wolf": 77, - "minecraft:item.firecharge.use": 504, - "minecraft:music_disc.chirp": 875, - "minecraft:ambient.basalt_deltas.mood": 10, - "minecraft:block.calcite.step": 227, - "minecraft:block.chorus_flower.death": 317, - "minecraft:block.grindstone.use": 638, - "minecraft:entity.fox.spit": 534, - "minecraft:music_disc.mall": 877, - "minecraft:block.decorated_pot.shatter": 392, - "minecraft:entity.allay.death": 2, - "minecraft:entity.breeze.jump": 192, - "minecraft:entity.hoglin.ambient": 690, - "minecraft:entity.husk.hurt": 736, - "minecraft:entity.iron_golem.death": 750, - "minecraft:entity.skeleton_horse.ambient_water": 1262, - "minecraft:entity.warden.tendril_clicks": 1513, - "minecraft:block.candle.break": 244, - "minecraft:block.nether_ore.break": 1166, - "minecraft:block.packed_mud.step": 945, - "minecraft:block.polished_deepslate.fall": 1127, - "minecraft:entity.cod.ambient": 325, - "minecraft:entity.dolphin.jump": 417, - "minecraft:entity.evoker.ambient": 491, - "minecraft:entity.parrot.imitate.zombie": 1063, - "minecraft:entity.player.hurt": 1109, - "minecraft:entity.spider.hurt": 1345, - "minecraft:entity.wither.shoot": 1542, - "minecraft:block.coral_block.fall": 361, - "minecraft:block.deepslate_bricks.place": 396, - "minecraft:block.dripstone_block.fall": 432, - "minecraft:block.wet_grass.fall": 1520, - "minecraft:item.flintandsteel.use": 519, - "minecraft:block.wart_block.step": 972, - "minecraft:entity.breeze.hurt": 196, - "minecraft:entity.piglin_brute.angry": 1088, - "minecraft:entity.player.hurt_on_fire": 1112, - "minecraft:entity.zombie.break_wooden_door": 1588, - "minecraft:block.moss_carpet.place": 834, - "minecraft:block.note_block.cow_bell": 998, - "minecraft:entity.allay.ambient_without_item": 1, - "minecraft:entity.bat.takeoff": 139, - "minecraft:entity.phantom.flap": 1069, - "minecraft:entity.player.small_fall": 1115, - "minecraft:entity.turtle.hurt": 1421, - "minecraft:entity.warden.agitated": 1494, - "minecraft:block.amethyst_cluster.place": 39, - "minecraft:block.copper_bulb.fall": 343, - "minecraft:block.decorated_pot.hit": 387, - "minecraft:block.nether_wood_hanging_sign.break": 664, - "minecraft:block.note_block.imitate.ender_dragon": 1005, - "minecraft:block.smoker.smoke": 1316, - "minecraft:entity.cow.hurt": 367, - "minecraft:entity.rabbit.ambient": 1147, - "minecraft:item.crossbow.loading_end": 378, - "minecraft:block.anvil.fall": 48, - "minecraft:block.polished_tuff.break": 1410, - "minecraft:block.anvil.destroy": 47, - "minecraft:block.azalea.fall": 96, - "minecraft:block.fence_gate.close": 502, - "minecraft:block.stone_button.click_off": 1362, - "minecraft:block.trial_spawner.eject_item": 688, - "minecraft:block.vault.reject_rewarded_player": 1442, - "minecraft:entity.goat.horn_break": 616, - "minecraft:entity.ravager.celebrate": 1155, - "minecraft:block.hanging_roots.break": 648, - "minecraft:block.soul_sand.place": 1288, - "minecraft:block.trial_spawner.about_to_spawn_item": 679, - "minecraft:entity.glow_squid.squirt": 607, - "minecraft:block.bamboo_sapling.hit": 111, - "minecraft:block.metal.fall": 817, - "minecraft:block.nether_wood.break": 925, - "minecraft:entity.donkey.eat": 425, - "minecraft:entity.goat.screaming.long_jump": 622, - "minecraft:entity.polar_bear.warning": 1125, - "minecraft:block.cherry_sapling.fall": 276, - "minecraft:block.fire.ambient": 513, - "minecraft:block.froglight.step": 550, - "minecraft:block.muddy_mangrove_roots.break": 856, - "minecraft:block.pointed_dripstone.fall": 437, - "minecraft:entity.allay.ambient_with_item": 0, - "minecraft:entity.magma_cube.hurt": 804, - "minecraft:entity.parrot.imitate.guardian": 1040, - "minecraft:ambient.basalt_deltas.additions": 8, - "minecraft:ambient.basalt_deltas.loop": 9, - "minecraft:block.bone_block.fall": 175, - "minecraft:block.candle.place": 248, - "minecraft:block.note_block.snare": 995, - "minecraft:block.rooted_dirt.fall": 1177, - "minecraft:block.small_amethyst_bud.place": 1280, - "minecraft:block.wet_grass.step": 1523, - "minecraft:entity.villager.work_cleric": 1464, - "minecraft:entity.zoglin.attack": 1581, - "minecraft:music_disc.mellohi": 878, - "minecraft:block.ladder.break": 763, - "minecraft:block.small_dripleaf.break": 1281, - "minecraft:entity.creeper.hurt": 373, - "minecraft:entity.drowned.ambient_water": 446, - "minecraft:entity.llama.hurt": 789, - "minecraft:music.menu": 892, - "minecraft:block.cherry_wood.place": 273, - "minecraft:block.flowering_azalea.step": 524, - "minecraft:block.pink_petals.fall": 837, - "minecraft:block.polished_deepslate.hit": 1128, - "minecraft:entity.skeleton.death": 1257, - "minecraft:item.glow_ink_sac.use": 598, - "minecraft:block.bamboo_wood_hanging_sign.hit": 671, - "minecraft:block.big_dripleaf.break": 157, - "minecraft:block.lantern.fall": 769, - "minecraft:block.powder_snow.hit": 1136, - "minecraft:block.wooden_pressure_plate.click_off": 1567, - "minecraft:entity.bee.loop_aggressive": 146, - "minecraft:entity.llama.step": 791, - "minecraft:block.sculk_shrieker.break": 1215, - "minecraft:block.slime_block.hit": 1276, - "minecraft:block.wood.fall": 1570, - "minecraft:entity.parrot.imitate.vindicator": 1057, - "minecraft:entity.sniffer.step": 1317, - "minecraft:item.spyglass.stop_using": 1356, - "minecraft:block.copper_grate.place": 355, - "minecraft:block.gravel.break": 633, - "minecraft:block.nether_bricks.break": 918, - "minecraft:entity.fishing_bobber.splash": 517, - "minecraft:entity.parrot.imitate.ender_dragon": 1036, - "minecraft:entity.strider.step_lava": 1308, - "minecraft:block.amethyst_block.resonate": 34, - "minecraft:block.lodestone.step": 795, - "minecraft:block.note_block.bass": 987, - "minecraft:block.note_block.imitate.skeleton": 1003, - "minecraft:block.packed_mud.break": 941, - "minecraft:block.wooden_trapdoor.close": 1563, - "minecraft:entity.mooshroom.suspicious_milk": 829, - "minecraft:entity.player.hurt_freeze": 1111, - "minecraft:entity.shulker.teleport": 1250, - "minecraft:entity.turtle.shamble": 1424, - "minecraft:block.deepslate_tiles.place": 406, - "minecraft:block.gravel.place": 636, - "minecraft:block.mud_bricks.fall": 852, - "minecraft:block.sculk.fall": 1198, - "minecraft:entity.fox.sniff": 533, - "minecraft:item.elytra.flying": 464, - "minecraft:music.overworld.swamp": 900, - "minecraft:block.calcite.fall": 230, - "minecraft:block.coral_block.hit": 362, - "minecraft:block.note_block.basedrum": 986, - "minecraft:entity.bee.loop": 147, - "minecraft:entity.witch.death": 1534, - "minecraft:block.candle.step": 249, - "minecraft:block.shroomlight.step": 1234, - "minecraft:entity.dolphin.hurt": 416, - "minecraft:music_disc.wait": 882, - "minecraft:ui.cartography_table.take_result": 1430, - "minecraft:block.cave_vines.pick_berries": 264, - "minecraft:block.fungus.break": 961, - "minecraft:block.hanging_sign.waxed_interact_fail": 1514, - "minecraft:block.honey_block.slide": 702, - "minecraft:block.netherite_block.break": 976, - "minecraft:block.stem.hit": 949, - "minecraft:entity.item_frame.rotate_item": 760, - "minecraft:entity.mule.angry": 862, - "minecraft:entity.shulker.death": 1245, - "minecraft:entity.skeleton_horse.swim": 1261, - "minecraft:entity.wither_skeleton.ambient": 1543, - "minecraft:block.bamboo.fall": 106, - "minecraft:block.bamboo_wood_button.click_on": 123, - "minecraft:block.metal.step": 822, - "minecraft:block.shroomlight.place": 1235, - "minecraft:block.snow.fall": 1334, - "minecraft:block.spore_blossom.place": 1300, - "minecraft:entity.allay.item_taken": 5, - "minecraft:entity.slime.attack": 1269, - "minecraft:entity.strider.death": 1305, - "minecraft:entity.warden.angry": 1496, - "minecraft:entity.wolf.whine": 1560, - "minecraft:block.cherry_wood_button.click_off": 294, - "minecraft:block.heavy_core.break": 658, - "minecraft:block.wet_grass.hit": 1521, - "minecraft:entity.salmon.hurt": 1184, - "minecraft:entity.sniffer.searching": 1325, - "minecraft:entity.zombie_villager.hurt": 1606, - "minecraft:block.copper.place": 348, - "minecraft:block.trial_spawner.ambient_ominous": 685, - "minecraft:entity.fox.hurt": 530, - "minecraft:entity.generic.small_fall": 579, - "minecraft:entity.parrot.imitate.ravager": 1049, - "minecraft:entity.strider.eat": 1309, - "minecraft:entity.strider.step": 1307, - "minecraft:entity.zombie_horse.hurt": 1594, - "minecraft:music.overworld.lush_caves": 899, - "minecraft:block.copper.step": 347, - "minecraft:block.tuff_bricks.break": 1405, - "minecraft:entity.allay.item_given": 4, - "minecraft:entity.magma_cube.hurt_small": 805, - "minecraft:entity.shulker.ambient": 1239, - "minecraft:music_disc.pigstep": 879, - "minecraft:weather.rain.above": 1518, - "minecraft:block.barrel.close": 128, - "minecraft:block.basalt.break": 130, - "minecraft:block.nether_wood_trapdoor.close": 932, - "minecraft:block.sand.step": 1189, - "minecraft:block.slime_block.break": 1274, - "minecraft:entity.stray.hurt": 1372, - "minecraft:entity.zombie.attack_wooden_door": 1586, - "minecraft:block.cherry_wood_hanging_sign.fall": 287, - "minecraft:block.heavy_core.fall": 659, - "minecraft:block.snow.place": 1341, - "minecraft:entity.ender_dragon.shoot": 474, - "minecraft:block.frogspawn.fall": 553, - "minecraft:block.grass.hit": 630, - "minecraft:block.nether_sprouts.place": 958, - "minecraft:block.wooden_button.click_on": 1566, - "minecraft:entity.player.attack.nodamage": 1101, - "minecraft:entity.skeleton.shoot": 1267, - "minecraft:entity.warden.ambient": 1495, - "minecraft:item.crossbow.quick_charge_2": 382, - "minecraft:ui.stonecutter.take_result": 1431, - "minecraft:block.coral_block.break": 360, - "minecraft:block.scaffolding.fall": 1191, - "minecraft:block.wood.step": 1573, - "minecraft:entity.iron_golem.step": 753, - "minecraft:entity.minecart.inside.underwater": 823, - "minecraft:item.armor.equip_iron": 72, - "minecraft:block.conduit.ambient.short": 336, - "minecraft:block.deepslate.break": 398, - "minecraft:block.nether_ore.fall": 1167, - "minecraft:block.nylium.hit": 954, - "minecraft:block.trial_spawner.ominous_activate": 683, - "minecraft:entity.blaze.hurt": 165, - "minecraft:entity.breeze.idle_ground": 189, - "minecraft:entity.dolphin.ambient": 411, - "minecraft:entity.hostile.small_fall": 730, - "minecraft:item.bucket.fill": 216, - "minecraft:block.azalea.place": 98, - "minecraft:entity.camel.saddle": 237, - "minecraft:entity.frog.long_jump": 562, - "minecraft:block.anvil.use": 53, - "minecraft:block.mangrove_roots.place": 812, - "minecraft:block.medium_amethyst_bud.place": 815, - "minecraft:block.sculk_sensor.hit": 1212, - "minecraft:block.soul_soil.place": 1293, - "minecraft:block.suspicious_sand.hit": 539, - "minecraft:entity.dolphin.death": 414, - "minecraft:entity.player.attack.crit": 1099, - "minecraft:item.trident.riptide_3": 1389, - "minecraft:block.mud_bricks.hit": 853, - "minecraft:block.nether_gold_ore.step": 1165, - "minecraft:block.soul_sand.hit": 1289, - "minecraft:entity.hoglin.attack": 692, - "minecraft:entity.stray.step": 1373, - "minecraft:entity.wither.death": 1540, - "minecraft:item.armor.equip_chain": 67, - "minecraft:music.overworld.meadow": 903, - "minecraft:block.beehive.drip": 150, - "minecraft:block.cherry_sapling.place": 278, - "minecraft:block.chiseled_bookshelf.pickup": 314, - "minecraft:block.hanging_sign.fall": 655, - "minecraft:entity.ghast.shoot": 586, - "minecraft:entity.hoglin.retreat": 696, - "minecraft:entity.item_frame.break": 757, - "minecraft:entity.piglin.death": 1081, - "minecraft:entity.ravager.death": 1156, + "minecraft:block.scaffolding.step": 1194, + "minecraft:state.fishing_bobber.throw": 518, + "minecraft:state.llama.chest": 786, + "minecraft:state.player.hurt_sweet_berry_bush": 1113, + "minecraft:state.strider.ambient": 1302, + "minecraft:block.cherry_sapling.step": 279, + "minecraft:block.coral_block.place": 363, + "minecraft:state.armadillo.roll": 60, + "minecraft:state.breeze.deflect": 187, + "minecraft:state.dolphin.attack": 413, + "minecraft:state.parrot.imitate.endermite": 1037, + "minecraft:block.deepslate_tiles.step": 407, + "minecraft:block.packed_mud.place": 944, + "minecraft:state.armadillo.unroll_finish": 63, + "minecraft:state.firework_rocket.twinkle": 511, + "minecraft:state.parrot.imitate.pillager": 1048, + "minecraft:state.ravager.step": 1158, + "minecraft:item.armor.equip_gold": 71, + "minecraft:block.fungus.fall": 965, + "minecraft:block.hanging_roots.fall": 649, + "minecraft:block.nylium.place": 953, + "minecraft:state.ender_eye.launch": 476, + "minecraft:state.evoker.death": 494, + "minecraft:state.sniffer.digging": 1326, + "minecraft:state.warden.death": 1498, + "minecraft:block.amethyst_cluster.step": 40, + "minecraft:block.beehive.shear": 153, + "minecraft:block.sculk_sensor.step": 1214, + "minecraft:state.fox.bite": 527, + "minecraft:state.frog.death": 558, + "minecraft:state.vindicator.ambient": 1474, + "minecraft:state.witch.celebrate": 1533, + "minecraft:item.trident.return": 1386, + "minecraft:music.overworld.grove": 897, + "minecraft:block.azalea_leaves.step": 104, + "minecraft:block.note_block.harp": 992, + "minecraft:state.goat.step": 627, + "minecraft:state.sniffer.digging_stop": 1327, + "minecraft:state.splash_potion.break": 1347, + "minecraft:state.strider.hurt": 1306, + "minecraft:state.wandering_trader.reappeared": 1491, + "minecraft:item.goat_horn.sound.3": 709, + "minecraft:block.cherry_wood.hit": 272, + "minecraft:block.cherry_wood_pressure_plate.click_on": 297, + "minecraft:block.composter.empty": 330, + "minecraft:block.copper.hit": 349, + "minecraft:block.polished_tuff.hit": 1412, + "minecraft:block.suspicious_sand.fall": 540, + "minecraft:state.iron_golem.hurt": 751, + "minecraft:state.piglin.retreat": 1084, + "minecraft:state.wolf.death": 1553, + "minecraft:block.amethyst_cluster.fall": 37, + "minecraft:block.deepslate_tiles.break": 403, + "minecraft:block.enchantment_table.use": 465, + "minecraft:block.sculk_sensor.clicking": 1208, + "minecraft:block.sweet_berry_bush.pick_berries": 1376, + "minecraft:ui.toast.challenge_complete": 1433, + "minecraft:block.bamboo_wood_hanging_sign.place": 672, + "minecraft:block.glass.hit": 595, + "minecraft:block.scaffolding.place": 1193, + "minecraft:state.firework_rocket.launch": 509, + "minecraft:state.shulker.hurt": 1246, + "minecraft:state.sniffer.idle": 1319, + "minecraft:state.turtle.ambient_land": 1415, + "minecraft:ambient.underwater.loop.additions.rare": 27, + "minecraft:block.end_portal.spawn": 490, + "minecraft:state.elder_guardian.hurt": 462, + "minecraft:state.generic.drink": 574, + "minecraft:state.goat.long_jump": 612, + "minecraft:state.puffer_fish.blow_up": 1141, + "minecraft:state.turtle.lay_egg": 1423, + "minecraft:state.villager.death": 1456, + "minecraft:item.armor.equip_wolf": 76, + "minecraft:item.goat_horn.sound.1": 707, + "minecraft:music.overworld.sparse_jungle": 915, + "minecraft:block.bamboo.hit": 107, + "minecraft:block.frogspawn.break": 552, + "minecraft:block.sculk_sensor.clicking_stop": 1209, + "minecraft:block.wet_sponge.dries": 1525, + "minecraft:state.drowned.swim": 453, + "minecraft:state.hoglin.converted_to_zombified": 693, + "minecraft:state.phantom.ambient": 1066, + "minecraft:state.wandering_trader.trade": 1492, + "minecraft:state.wolf.howl": 1555, + "minecraft:block.cave_vines.fall": 260, + "minecraft:block.cherry_wood_hanging_sign.place": 289, + "minecraft:state.glow_squid.hurt": 606, + "minecraft:state.item.pickup": 762, + "minecraft:music.nether.basalt_deltas": 893, + "minecraft:block.cherry_wood_door.open": 291, + "minecraft:block.suspicious_gravel.step": 542, + "minecraft:block.bamboo_wood_pressure_plate.click_on": 125, + "minecraft:block.ender_chest.close": 466, + "minecraft:block.lantern.place": 771, + "minecraft:block.stem.fall": 950, + "minecraft:block.tuff_bricks.step": 1409, + "minecraft:state.zoglin.death": 1582, + "minecraft:block.netherite_block.step": 977, + "minecraft:block.sculk.step": 1201, + "minecraft:block.wart_block.fall": 975, + "minecraft:state.skeleton_horse.death": 1259, + "minecraft:music.overworld.cherry_grove": 904, + "minecraft:block.chiseled_bookshelf.insert": 311, + "minecraft:block.hanging_roots.hit": 650, + "minecraft:state.panda.sneeze": 1015, + "minecraft:state.slime.death_small": 1311, + "minecraft:item.axe.scrape": 86, + "minecraft:music.nether.nether_wastes": 905, + "minecraft:block.metal.hit": 818, + "minecraft:block.pink_petals.break": 836, + "minecraft:state.cow.death": 366, + "minecraft:state.parrot.imitate.slime": 1053, + "minecraft:state.zombie.step": 1601, + "minecraft:item.armor.equip_elytra": 69, + "minecraft:block.roots.break": 565, + "minecraft:block.vault.close_shutter": 1439, + "minecraft:state.glow_item_frame.break": 600, + "minecraft:state.horse.breathe": 717, + "minecraft:state.leash_knot.break": 778, + "minecraft:state.wither.hurt": 1541, + "minecraft:block.suspicious_gravel.hit": 544, + "minecraft:state.arrow.hit_player": 83, + "minecraft:ambient.soul_sand_valley.mood": 19, + "minecraft:block.ancient_debris.break": 41, + "minecraft:block.candle.fall": 246, + "minecraft:block.decorated_pot.place": 391, + "minecraft:block.mangrove_roots.step": 813, + "minecraft:state.firework_rocket.large_blast": 507, + "minecraft:state.firework_rocket.shoot": 510, + "minecraft:state.goat.screaming.death": 619, + "minecraft:state.husk.death": 735, + "minecraft:state.stray.ambient": 1370, + "minecraft:block.amethyst_block.step": 35, + "minecraft:block.anvil.break": 46, + "minecraft:block.snow.step": 1342, + "minecraft:state.puffer_fish.death": 1142, + "minecraft:state.ravager.attack": 1154, + "minecraft:state.witch.drink": 1535, + "minecraft:block.copper_bulb.hit": 342, + "minecraft:block.mangrove_roots.fall": 810, + "minecraft:block.wet_grass.place": 1522, + "minecraft:state.armor_stand.place": 81, + "minecraft:state.lightning_bolt.thunder": 782, + "minecraft:item.bottle.empty": 183, + "minecraft:block.nether_gold_ore.break": 1161, + "minecraft:block.slime_block.place": 1277, + "minecraft:block.stone_pressure_plate.click_off": 1367, + "minecraft:state.axolotl.idle_air": 91, + "minecraft:state.hostile.swim": 732, + "minecraft:item.brush.brushing.gravel.complete": 204, + "minecraft:item.ominous_bottle.dispose": 1011, + "minecraft:block.chiseled_bookshelf.fall": 309, + "minecraft:block.pointed_dripstone.drip_water": 440, + "minecraft:state.villager.hurt": 1457, + "minecraft:block.mud_bricks.place": 854, + "minecraft:block.trial_spawner.step": 674, + "minecraft:state.parrot.imitate.phantom": 1045, + "minecraft:state.squid.death": 1358, + "minecraft:block.bamboo_wood_door.open": 119, + "minecraft:block.bone_block.break": 174, + "minecraft:block.suspicious_sand.place": 538, + "minecraft:state.mooshroom.eat": 827, + "minecraft:state.sheep.hurt": 1228, + "minecraft:state.zombie_horse.ambient": 1592, + "minecraft:block.note_block.flute": 990, + "minecraft:block.piston.extend": 1098, + "minecraft:block.polished_deepslate.place": 1129, + "minecraft:block.sniffer_egg.plop": 1329, + "minecraft:block.tuff.place": 1402, + "minecraft:block.tuff_bricks.fall": 1406, + "minecraft:state.piglin.step": 1085, + "minecraft:state.turtle.shamble_baby": 1425, + "minecraft:state.villager.work_toolsmith": 1472, + "minecraft:item.armor.unequip_wolf": 77, + "minecraft:item.firecharge.use": 504, + "minecraft:music_disc.chirp": 875, + "minecraft:ambient.basalt_deltas.mood": 10, + "minecraft:block.calcite.step": 227, + "minecraft:block.chorus_flower.death": 317, + "minecraft:block.grindstone.use": 638, + "minecraft:state.fox.spit": 534, + "minecraft:music_disc.mall": 877, + "minecraft:block.decorated_pot.shatter": 392, + "minecraft:state.allay.death": 2, + "minecraft:state.breeze.jump": 192, + "minecraft:state.hoglin.ambient": 690, + "minecraft:state.husk.hurt": 736, + "minecraft:state.iron_golem.death": 750, + "minecraft:state.skeleton_horse.ambient_water": 1262, + "minecraft:state.warden.tendril_clicks": 1513, + "minecraft:block.candle.break": 244, + "minecraft:block.nether_ore.break": 1166, + "minecraft:block.packed_mud.step": 945, + "minecraft:block.polished_deepslate.fall": 1127, + "minecraft:state.cod.ambient": 325, + "minecraft:state.dolphin.jump": 417, + "minecraft:state.evoker.ambient": 491, + "minecraft:state.parrot.imitate.zombie": 1063, + "minecraft:state.player.hurt": 1109, + "minecraft:state.spider.hurt": 1345, + "minecraft:state.wither.shoot": 1542, + "minecraft:block.coral_block.fall": 361, + "minecraft:block.deepslate_bricks.place": 396, + "minecraft:block.dripstone_block.fall": 432, + "minecraft:block.wet_grass.fall": 1520, + "minecraft:item.flintandsteel.use": 519, + "minecraft:block.wart_block.step": 972, + "minecraft:state.breeze.hurt": 196, + "minecraft:state.piglin_brute.angry": 1088, + "minecraft:state.player.hurt_on_fire": 1112, + "minecraft:state.zombie.break_wooden_door": 1588, + "minecraft:block.moss_carpet.place": 834, + "minecraft:block.note_block.cow_bell": 998, + "minecraft:state.allay.ambient_without_item": 1, + "minecraft:state.bat.takeoff": 139, + "minecraft:state.phantom.flap": 1069, + "minecraft:state.player.small_fall": 1115, + "minecraft:state.turtle.hurt": 1421, + "minecraft:state.warden.agitated": 1494, + "minecraft:block.amethyst_cluster.place": 39, + "minecraft:block.copper_bulb.fall": 343, + "minecraft:block.decorated_pot.hit": 387, + "minecraft:block.nether_wood_hanging_sign.break": 664, + "minecraft:block.note_block.imitate.ender_dragon": 1005, + "minecraft:block.smoker.smoke": 1316, + "minecraft:state.cow.hurt": 367, + "minecraft:state.rabbit.ambient": 1147, + "minecraft:item.crossbow.loading_end": 378, + "minecraft:block.anvil.fall": 48, + "minecraft:block.polished_tuff.break": 1410, + "minecraft:block.anvil.destroy": 47, + "minecraft:block.azalea.fall": 96, + "minecraft:block.fence_gate.close": 502, + "minecraft:block.stone_button.click_off": 1362, + "minecraft:block.trial_spawner.eject_item": 688, + "minecraft:block.vault.reject_rewarded_player": 1442, + "minecraft:state.goat.horn_break": 616, + "minecraft:state.ravager.celebrate": 1155, + "minecraft:block.hanging_roots.break": 648, + "minecraft:block.soul_sand.place": 1288, + "minecraft:block.trial_spawner.about_to_spawn_item": 679, + "minecraft:state.glow_squid.squirt": 607, + "minecraft:block.bamboo_sapling.hit": 111, + "minecraft:block.metal.fall": 817, + "minecraft:block.nether_wood.break": 925, + "minecraft:state.donkey.eat": 425, + "minecraft:state.goat.screaming.long_jump": 622, + "minecraft:state.polar_bear.warning": 1125, + "minecraft:block.cherry_sapling.fall": 276, + "minecraft:block.fire.ambient": 513, + "minecraft:block.froglight.step": 550, + "minecraft:block.muddy_mangrove_roots.break": 856, + "minecraft:block.pointed_dripstone.fall": 437, + "minecraft:state.allay.ambient_with_item": 0, + "minecraft:state.magma_cube.hurt": 804, + "minecraft:state.parrot.imitate.guardian": 1040, + "minecraft:ambient.basalt_deltas.additions": 8, + "minecraft:ambient.basalt_deltas.loop": 9, + "minecraft:block.bone_block.fall": 175, + "minecraft:block.candle.place": 248, + "minecraft:block.note_block.snare": 995, + "minecraft:block.rooted_dirt.fall": 1177, + "minecraft:block.small_amethyst_bud.place": 1280, + "minecraft:block.wet_grass.step": 1523, + "minecraft:state.villager.work_cleric": 1464, + "minecraft:state.zoglin.attack": 1581, + "minecraft:music_disc.mellohi": 878, + "minecraft:block.ladder.break": 763, + "minecraft:block.small_dripleaf.break": 1281, + "minecraft:state.creeper.hurt": 373, + "minecraft:state.drowned.ambient_water": 446, + "minecraft:state.llama.hurt": 789, + "minecraft:music.menu": 892, + "minecraft:block.cherry_wood.place": 273, + "minecraft:block.flowering_azalea.step": 524, + "minecraft:block.pink_petals.fall": 837, + "minecraft:block.polished_deepslate.hit": 1128, + "minecraft:state.skeleton.death": 1257, + "minecraft:item.glow_ink_sac.use": 598, + "minecraft:block.bamboo_wood_hanging_sign.hit": 671, + "minecraft:block.big_dripleaf.break": 157, + "minecraft:block.lantern.fall": 769, + "minecraft:block.powder_snow.hit": 1136, + "minecraft:block.wooden_pressure_plate.click_off": 1567, + "minecraft:state.bee.loop_aggressive": 146, + "minecraft:state.llama.step": 791, + "minecraft:block.sculk_shrieker.break": 1215, + "minecraft:block.slime_block.hit": 1276, + "minecraft:block.wood.fall": 1570, + "minecraft:state.parrot.imitate.vindicator": 1057, + "minecraft:state.sniffer.step": 1317, + "minecraft:item.spyglass.stop_using": 1356, + "minecraft:block.copper_grate.place": 355, + "minecraft:block.gravel.break": 633, + "minecraft:block.nether_bricks.break": 918, + "minecraft:state.fishing_bobber.splash": 517, + "minecraft:state.parrot.imitate.ender_dragon": 1036, + "minecraft:state.strider.step_lava": 1308, + "minecraft:block.amethyst_block.resonate": 34, + "minecraft:block.lodestone.step": 795, + "minecraft:block.note_block.bass": 987, + "minecraft:block.note_block.imitate.skeleton": 1003, + "minecraft:block.packed_mud.break": 941, + "minecraft:block.wooden_trapdoor.close": 1563, + "minecraft:state.mooshroom.suspicious_milk": 829, + "minecraft:state.player.hurt_freeze": 1111, + "minecraft:state.shulker.teleport": 1250, + "minecraft:state.turtle.shamble": 1424, + "minecraft:block.deepslate_tiles.place": 406, + "minecraft:block.gravel.place": 636, + "minecraft:block.mud_bricks.fall": 852, + "minecraft:block.sculk.fall": 1198, + "minecraft:state.fox.sniff": 533, + "minecraft:item.elytra.flying": 464, + "minecraft:music.overworld.swamp": 900, + "minecraft:block.calcite.fall": 230, + "minecraft:block.coral_block.hit": 362, + "minecraft:block.note_block.basedrum": 986, + "minecraft:state.bee.loop": 147, + "minecraft:state.witch.death": 1534, + "minecraft:block.candle.step": 249, + "minecraft:block.shroomlight.step": 1234, + "minecraft:state.dolphin.hurt": 416, + "minecraft:music_disc.wait": 882, + "minecraft:ui.cartography_table.take_result": 1430, + "minecraft:block.cave_vines.pick_berries": 264, + "minecraft:block.fungus.break": 961, + "minecraft:block.hanging_sign.waxed_interact_fail": 1514, + "minecraft:block.honey_block.slide": 702, + "minecraft:block.netherite_block.break": 976, + "minecraft:block.stem.hit": 949, + "minecraft:state.item_frame.rotate_item": 760, + "minecraft:state.mule.angry": 862, + "minecraft:state.shulker.death": 1245, + "minecraft:state.skeleton_horse.swim": 1261, + "minecraft:state.wither_skeleton.ambient": 1543, + "minecraft:block.bamboo.fall": 106, + "minecraft:block.bamboo_wood_button.click_on": 123, + "minecraft:block.metal.step": 822, + "minecraft:block.shroomlight.place": 1235, + "minecraft:block.snow.fall": 1334, + "minecraft:block.spore_blossom.place": 1300, + "minecraft:state.allay.item_taken": 5, + "minecraft:state.slime.attack": 1269, + "minecraft:state.strider.death": 1305, + "minecraft:state.warden.angry": 1496, + "minecraft:state.wolf.whine": 1560, + "minecraft:block.cherry_wood_button.click_off": 294, + "minecraft:block.heavy_core.break": 658, + "minecraft:block.wet_grass.hit": 1521, + "minecraft:state.salmon.hurt": 1184, + "minecraft:state.sniffer.searching": 1325, + "minecraft:state.zombie_villager.hurt": 1606, + "minecraft:block.copper.place": 348, + "minecraft:block.trial_spawner.ambient_ominous": 685, + "minecraft:state.fox.hurt": 530, + "minecraft:state.generic.small_fall": 579, + "minecraft:state.parrot.imitate.ravager": 1049, + "minecraft:state.strider.eat": 1309, + "minecraft:state.strider.step": 1307, + "minecraft:state.zombie_horse.hurt": 1594, + "minecraft:music.overworld.lush_caves": 899, + "minecraft:block.copper.step": 347, + "minecraft:block.tuff_bricks.break": 1405, + "minecraft:state.allay.item_given": 4, + "minecraft:state.magma_cube.hurt_small": 805, + "minecraft:state.shulker.ambient": 1239, + "minecraft:music_disc.pigstep": 879, + "minecraft:weather.rain.above": 1518, + "minecraft:block.barrel.close": 128, + "minecraft:block.basalt.break": 130, + "minecraft:block.nether_wood_trapdoor.close": 932, + "minecraft:block.sand.step": 1189, + "minecraft:block.slime_block.break": 1274, + "minecraft:state.stray.hurt": 1372, + "minecraft:state.zombie.attack_wooden_door": 1586, + "minecraft:block.cherry_wood_hanging_sign.fall": 287, + "minecraft:block.heavy_core.fall": 659, + "minecraft:block.snow.place": 1341, + "minecraft:state.ender_dragon.shoot": 474, + "minecraft:block.frogspawn.fall": 553, + "minecraft:block.grass.hit": 630, + "minecraft:block.nether_sprouts.place": 958, + "minecraft:block.wooden_button.click_on": 1566, + "minecraft:state.player.attack.nodamage": 1101, + "minecraft:state.skeleton.shoot": 1267, + "minecraft:state.warden.ambient": 1495, + "minecraft:item.crossbow.quick_charge_2": 382, + "minecraft:ui.stonecutter.take_result": 1431, + "minecraft:block.coral_block.break": 360, + "minecraft:block.scaffolding.fall": 1191, + "minecraft:block.wood.step": 1573, + "minecraft:state.iron_golem.step": 753, + "minecraft:state.minecart.inside.underwater": 823, + "minecraft:item.armor.equip_iron": 72, + "minecraft:block.conduit.ambient.short": 336, + "minecraft:block.deepslate.break": 398, + "minecraft:block.nether_ore.fall": 1167, + "minecraft:block.nylium.hit": 954, + "minecraft:block.trial_spawner.ominous_activate": 683, + "minecraft:state.blaze.hurt": 165, + "minecraft:state.breeze.idle_ground": 189, + "minecraft:state.dolphin.ambient": 411, + "minecraft:state.hostile.small_fall": 730, + "minecraft:item.bucket.fill": 216, + "minecraft:block.azalea.place": 98, + "minecraft:state.camel.saddle": 237, + "minecraft:state.frog.long_jump": 562, + "minecraft:block.anvil.use": 53, + "minecraft:block.mangrove_roots.place": 812, + "minecraft:block.medium_amethyst_bud.place": 815, + "minecraft:block.sculk_sensor.hit": 1212, + "minecraft:block.soul_soil.place": 1293, + "minecraft:block.suspicious_sand.hit": 539, + "minecraft:state.dolphin.death": 414, + "minecraft:state.player.attack.crit": 1099, + "minecraft:item.trident.riptide_3": 1389, + "minecraft:block.mud_bricks.hit": 853, + "minecraft:block.nether_gold_ore.step": 1165, + "minecraft:block.soul_sand.hit": 1289, + "minecraft:state.hoglin.attack": 692, + "minecraft:state.stray.step": 1373, + "minecraft:state.wither.death": 1540, + "minecraft:item.armor.equip_chain": 67, + "minecraft:music.overworld.meadow": 903, + "minecraft:block.beehive.drip": 150, + "minecraft:block.cherry_sapling.place": 278, + "minecraft:block.chiseled_bookshelf.pickup": 314, + "minecraft:block.hanging_sign.fall": 655, + "minecraft:state.ghast.shoot": 586, + "minecraft:state.hoglin.retreat": 696, + "minecraft:state.item_frame.break": 757, + "minecraft:state.piglin.death": 1081, + "minecraft:state.ravager.death": 1156, "minecraft:block.pointed_dripstone.drip_water_into_cauldron": 442, - "minecraft:block.portal.travel": 1132, - "minecraft:block.shulker_box.close": 1240, - "minecraft:entity.hostile.hurt": 729, - "minecraft:entity.mule.jump": 867, - "minecraft:entity.parrot.imitate.illusioner": 1043, - "minecraft:entity.salmon.ambient": 1181, - "minecraft:entity.vex.death": 1452, - "minecraft:entity.donkey.death": 424, - "minecraft:entity.player.hurt_drown": 1110, - "minecraft:entity.puffer_fish.hurt": 1144, - "minecraft:entity.spider.step": 1346, - "minecraft:block.bubble_column.upwards_ambient": 206, - "minecraft:entity.ender_dragon.ambient": 468, - "minecraft:entity.enderman.teleport": 482, - "minecraft:entity.squid.squirt": 1360, - "minecraft:block.dripstone_block.break": 428, - "minecraft:block.tuff.step": 1401, - "minecraft:entity.iron_golem.attack": 748, - "minecraft:entity.villager.work_librarian": 1469, - "minecraft:block.bubble_column.whirlpool_ambient": 208, - "minecraft:block.sculk_shrieker.fall": 1216, - "minecraft:entity.drowned.death": 447, - "minecraft:entity.ravager.roar": 1160, - "minecraft:block.decorated_pot.step": 390, - "minecraft:entity.illusioner.ambient": 738, - "minecraft:entity.sniffer.sniffing": 1324, - "minecraft:item.bucket.empty": 210, - "minecraft:block.azalea_leaves.place": 103, - "minecraft:block.cherry_wood.step": 274, - "minecraft:block.nether_wood_trapdoor.open": 933, - "minecraft:block.nylium.fall": 955, - "minecraft:block.wooden_button.click_off": 1565, - "minecraft:entity.ender_dragon.flap": 471, - "minecraft:entity.glow_item_frame.place": 601, - "minecraft:entity.goat.eat": 610, - "minecraft:entity.wandering_trader.drink_potion": 1488, - "minecraft:item.goat_horn.sound.0": 706, - "minecraft:block.amethyst_block.chime": 30, - "minecraft:block.calcite.break": 226, - "minecraft:block.calcite.place": 228, - "minecraft:block.coral_block.step": 364, - "minecraft:block.nether_ore.place": 1169, - "minecraft:block.sponge.fall": 1350, - "minecraft:block.weeping_vines.fall": 970, - "minecraft:entity.axolotl.splash": 93, - "minecraft:entity.evoker.prepare_attack": 497, - "minecraft:entity.parrot.imitate.blaze": 1030, - "minecraft:block.bubble_column.upwards_inside": 207, - "minecraft:block.nether_wood_hanging_sign.fall": 665, - "minecraft:block.sponge.absorb": 1354, - "minecraft:block.stone.hit": 1365, - "minecraft:block.wood.hit": 1571, - "minecraft:item.bucket.fill_tadpole": 221, - "minecraft:item.crossbow.shoot": 384, - "minecraft:block.moss_carpet.break": 831, - "minecraft:block.note_block.imitate.piglin": 1007, - "minecraft:block.redstone_torch.burnout": 1171, - "minecraft:block.soul_sand.break": 1286, - "minecraft:entity.elder_guardian.death": 459, - "minecraft:entity.guardian.ambient": 640, - "minecraft:entity.hoglin.death": 694, - "minecraft:block.amethyst_block.break": 29, - "minecraft:block.lever.click": 780, - "minecraft:entity.armor_stand.hit": 80, - "minecraft:entity.axolotl.death": 89, - "minecraft:entity.hoglin.step": 697, - "minecraft:entity.player.attack.knockback": 1100, - "minecraft:entity.wolf.ambient": 1552, - "minecraft:entity.zombified_piglin.ambient": 1597, - "minecraft:block.nether_bricks.place": 920, - "minecraft:block.respawn_anchor.ambient": 1172, - "minecraft:block.respawn_anchor.set_spawn": 1175, - "minecraft:block.sculk_shrieker.place": 1218, - "minecraft:entity.horse.ambient": 714, - "minecraft:entity.snow_golem.shear": 1339, - "minecraft:block.sculk_catalyst.step": 1207, - "minecraft:block.trial_spawner.fall": 677, - "minecraft:block.wet_sponge.place": 1528, - "minecraft:entity.llama.swag": 792, - "minecraft:entity.mooshroom.milk": 828, - "minecraft:entity.slime.death": 1270, - "minecraft:entity.wolf.pant": 1557, - "minecraft:block.nether_sprouts.fall": 960, - "minecraft:entity.minecart.inside": 824, - "minecraft:block.chain.break": 265, - "minecraft:block.vault.fall": 1443, - "minecraft:entity.breeze.charge": 186, - "minecraft:entity.enderman.stare": 481, - "minecraft:entity.zoglin.angry": 1580, - "minecraft:block.azalea.hit": 97, - "minecraft:block.gilded_blackstone.fall": 589, - "minecraft:block.note_block.bell": 988, - "minecraft:block.vault.break": 1438, - "minecraft:entity.puffer_fish.blow_out": 1140, - "minecraft:entity.skeleton.converted_to_stray": 1256, - "minecraft:item.goat_horn.sound.4": 710, - "minecraft:block.cherry_wood_door.close": 290, - "minecraft:block.cherry_wood_fence_gate.open": 299, - "minecraft:block.cobweb.fall": 324, - "minecraft:block.copper_grate.break": 353, - "minecraft:block.lantern.hit": 770, - "minecraft:block.muddy_mangrove_roots.place": 859, - "minecraft:block.snow.break": 1333, - "minecraft:entity.evoker.prepare_summon": 498, - "minecraft:entity.parrot.ambient": 1025, - "minecraft:entity.wolf.shake": 1558, - "minecraft:block.crop.break": 375, - "minecraft:block.sculk_catalyst.fall": 1204, - "minecraft:block.trial_spawner.detect_player": 682, - "minecraft:entity.endermite.death": 484, - "minecraft:entity.generic.burn": 572, - "minecraft:entity.lightning_bolt.impact": 781, - "minecraft:music.nether.soul_sand_valley": 908, - "minecraft:entity.fox.screech": 531, - "minecraft:entity.parrot.imitate.zombie_villager": 1064, - "minecraft:entity.player.levelup": 1114, - "minecraft:entity.villager.work_armorer": 1461, - "minecraft:music.overworld.badlands": 913, - "minecraft:block.candle.hit": 247, - "minecraft:block.dispenser.dispense": 408, - "minecraft:block.nether_wood_fence_gate.open": 939, - "minecraft:entity.glow_item_frame.add_item": 599, - "minecraft:entity.warden.nearby_closest": 1507, - "minecraft:block.moss.break": 841, - "minecraft:entity.llama.angry": 785, - "minecraft:entity.zombie.attack_iron_door": 1587, - "minecraft:block.copper_trapdoor.open": 359, - "minecraft:block.soul_soil.hit": 1294, - "minecraft:block.sponge.step": 1353, - "minecraft:entity.ghast.death": 583, - "minecraft:entity.sheep.ambient": 1226, - "minecraft:entity.slime.jump": 1272, - "minecraft:entity.villager.ambient": 1454, - "minecraft:entity.wither.break_block": 1539, - "minecraft:block.rooted_dirt.break": 1176, - "minecraft:entity.illusioner.cast_spell": 739, - "minecraft:entity.skeleton.ambient": 1255, - "minecraft:entity.warden.dig": 1499, - "minecraft:entity.zoglin.ambient": 1579, - "minecraft:block.small_dripleaf.fall": 1282, - "minecraft:entity.enderman.scream": 480, - "minecraft:entity.frog.ambient": 557, - "minecraft:entity.skeleton_horse.ambient": 1258, - "minecraft:item.bucket.empty_axolotl": 211, - "minecraft:item.bucket.empty_powder_snow": 214, - "minecraft:block.lava.pop": 777, - "minecraft:block.sculk_shrieker.hit": 1217, - "minecraft:entity.chicken.death": 304, - "minecraft:entity.dolphin.ambient_water": 412, - "minecraft:entity.villager.celebrate": 1455, - "minecraft:ambient.crimson_forest.additions": 11, - "minecraft:block.deepslate.hit": 400, - "minecraft:block.gravel.fall": 634, - "minecraft:entity.evoker.celebrate": 493, - "minecraft:entity.horse.gallop": 720, - "minecraft:entity.parrot.imitate.stray": 1055, - "minecraft:entity.player.attack.sweep": 1103, - "minecraft:ambient.underwater.enter": 23, - "minecraft:block.cherry_sapling.break": 275, - "minecraft:block.weeping_vines.hit": 969, - "minecraft:entity.guardian.flop": 645, - "minecraft:block.gilded_blackstone.place": 591, - "minecraft:block.growing_plant.crop": 639, - "minecraft:block.lodestone.break": 794, - "minecraft:block.nether_ore.step": 1170, - "minecraft:entity.horse.step": 725, - "minecraft:entity.wandering_trader.disappeared": 1486, - "minecraft:block.bamboo_wood.step": 117, - "minecraft:block.basalt.step": 131, - "minecraft:block.nylium.step": 952, - "minecraft:block.tripwire.detach": 1395, - "minecraft:entity.axolotl.idle_water": 92, - "minecraft:block.anvil.place": 51, - "minecraft:block.moss_carpet.fall": 832, - "minecraft:entity.ender_dragon.hurt": 473, - "minecraft:entity.piglin.celebrate": 1080, - "minecraft:entity.villager.work_weaponsmith": 1473, - "minecraft:item.bucket.empty_fish": 212, - "minecraft:block.chain.fall": 266, - "minecraft:block.furnace.fire_crackle": 570, - "minecraft:entity.armor_stand.fall": 79, - "minecraft:entity.turtle.hurt_baby": 1422, - "minecraft:block.heavy_core.place": 661, - "minecraft:block.note_block.imitate.wither_skeleton": 1006, - "minecraft:block.powder_snow.fall": 1135, - "minecraft:block.soul_soil.break": 1291, - "minecraft:entity.generic.hurt": 578, - "minecraft:entity.ghast.hurt": 584, - "minecraft:entity.guardian.death": 643, - "minecraft:entity.illusioner.death": 740, - "minecraft:entity.piglin.hurt": 1083, - "minecraft:entity.squid.ambient": 1357, - "minecraft:item.bucket.fill_powder_snow": 220, - "minecraft:music.creative": 868, - "minecraft:block.large_amethyst_bud.place": 774, - "minecraft:block.moss.hit": 843, - "minecraft:block.pointed_dripstone.place": 435, - "minecraft:music.overworld.forest": 901, - "minecraft:block.bamboo_wood.fall": 114, - "minecraft:block.chiseled_bookshelf.step": 313, - "minecraft:block.note_block.xylophone": 996, - "minecraft:block.sculk_catalyst.break": 1203, - "minecraft:block.snow.hit": 1340, - "minecraft:block.vine.fall": 1479, - "minecraft:entity.blaze.burn": 163, - "minecraft:entity.iron_golem.repair": 752, - "minecraft:entity.item_frame.place": 758, - "minecraft:entity.vindicator.hurt": 1477, - "minecraft:block.sculk_sensor.break": 1210, - "minecraft:block.vault.eject_item": 1441, - "minecraft:entity.goat.hurt": 611, - "minecraft:entity.warden.nearby_closer": 1506, - "minecraft:event.mob_effect.trial_omen": 1609, - "minecraft:item.nether_wart.plant": 924, - "minecraft:item.trident.hit": 1384, - "minecraft:ambient.warped_forest.loop": 21, - "minecraft:block.sculk_vein.place": 1224, - "minecraft:block.sweet_berry_bush.place": 1375, - "minecraft:block.vault.hit": 1444, - "minecraft:entity.breeze.inhale": 188, - "minecraft:entity.polar_bear.ambient": 1120, - "minecraft:entity.wandering_trader.drink_milk": 1487, - "minecraft:block.amethyst_cluster.break": 36, - "minecraft:block.vine.break": 1478, - "minecraft:block.wood.place": 1572, - "minecraft:entity.tropical_fish.death": 1397, - "minecraft:music.dragon": 889, - "minecraft:block.cherry_wood_fence_gate.close": 298, - "minecraft:entity.bee.hurt": 145, - "minecraft:block.bamboo_wood.hit": 115, - "minecraft:block.decorated_pot.insert_fail": 389, - "minecraft:block.roots.place": 567, - "minecraft:entity.breeze.wind_burst": 198, - "minecraft:entity.rabbit.jump": 1151, - "minecraft:entity.shulker.close": 1244, - "minecraft:entity.shulker.shoot": 1249, - "minecraft:music.overworld.stony_peaks": 909, - "minecraft:block.crafter.fail": 371, - "minecraft:block.nether_sprouts.break": 956, - "minecraft:entity.armadillo.eat": 54, - "minecraft:entity.goat.ambient": 608, - "minecraft:item.honey_bottle.drink": 705, - "minecraft:block.ancient_debris.place": 43, - "minecraft:block.copper.break": 346, - "minecraft:entity.fox.death": 528, - "minecraft:entity.parrot.imitate.husk": 1042, - "minecraft:entity.silverfish.death": 1252, - "minecraft:entity.warden.attack_impact": 1497, - "minecraft:block.sculk_sensor.fall": 1211, - "minecraft:block.sponge.place": 1352, - "minecraft:entity.bat.loop": 138, - "minecraft:entity.bee.sting": 148, - "minecraft:entity.enderman.hurt": 479, - "minecraft:entity.skeleton_horse.jump_water": 1264, - "minecraft:entity.villager.work_butcher": 1462, - "minecraft:block.anvil.hit": 49, - "minecraft:block.big_dripleaf.tilt_up": 444, - "minecraft:block.bubble_column.whirlpool_inside": 209, - "minecraft:block.sculk_catalyst.bloom": 1202, - "minecraft:block.trial_spawner.hit": 676, - "minecraft:entity.pig.saddle": 1075, - "minecraft:item.bucket.fill_fish": 218, - "minecraft:music_disc.ward": 883, - "minecraft:block.beacon.activate": 140, - "minecraft:block.nether_bricks.fall": 922, - "minecraft:entity.hoglin.hurt": 695, - "minecraft:item.armor.equip_turtle": 75, - "minecraft:item.book.page_turn": 180, - "minecraft:block.copper_bulb.place": 341, - "minecraft:block.grass.break": 628, - "minecraft:block.grass.place": 631, - "minecraft:block.mangrove_roots.hit": 811, - "minecraft:entity.goat.screaming.hurt": 621, - "minecraft:music_disc.13": 872, - "minecraft:entity.parrot.imitate.bogged": 1031, - "minecraft:item.goat_horn.sound.7": 713, - "minecraft:music.overworld.jagged_peaks": 898, - "minecraft:block.iron_door.open": 747, - "minecraft:block.iron_trapdoor.close": 754, - "minecraft:block.nether_wood_button.click_off": 934, - "minecraft:entity.generic.splash": 580, - "minecraft:entity.tropical_fish.ambient": 1396, - "minecraft:item.goat_horn.sound.2": 708, - "minecraft:block.chest.open": 302, - "minecraft:block.flowering_azalea.fall": 521, - "minecraft:block.nether_wart.break": 923, - "minecraft:entity.bogged.hurt": 171, - "minecraft:entity.endermite.ambient": 483, - "minecraft:entity.player.attack.strong": 1102, - "minecraft:entity.wither.spawn": 1547, - "minecraft:music_disc.far": 876, - "minecraft:music_disc.otherside": 884, - "minecraft:block.copper_grate.step": 354, - "minecraft:block.glass.step": 597, - "minecraft:block.grass.step": 632, - "minecraft:block.metal.break": 816, - "minecraft:block.mud.step": 850, - "minecraft:block.soul_sand.fall": 1290, - "minecraft:item.shield.block": 1231, - "minecraft:ui.stonecutter.select_recipe": 1432, - "minecraft:block.decorated_pot.fall": 386, - "minecraft:block.rooted_dirt.hit": 1178, - "minecraft:entity.guardian.hurt": 646, - "minecraft:entity.splash_potion.throw": 1348, - "minecraft:block.bamboo_wood_hanging_sign.fall": 670, - "minecraft:block.bamboo_wood_trapdoor.open": 121, - "minecraft:block.copper_grate.hit": 356, - "minecraft:block.flowering_azalea.place": 523, - "minecraft:block.fungus.hit": 964, - "minecraft:block.nether_wood_door.close": 930, - "minecraft:block.packed_mud.hit": 943, - "minecraft:block.trial_spawner.spawn_mob": 678, - "minecraft:entity.camel.sit": 238, - "minecraft:entity.parrot.imitate.spider": 1054, - "minecraft:entity.piglin.converted_to_zombified": 1086, - "minecraft:entity.sniffer.scenting": 1323, - "minecraft:entity.snow_golem.hurt": 1337, - "minecraft:entity.stray.death": 1371, - "minecraft:entity.tnt.primed": 1382, - "minecraft:ambient.soul_sand_valley.loop": 18, - "minecraft:block.tripwire.click_on": 1394, - "minecraft:entity.breeze.idle_air": 190, - "minecraft:entity.skeleton_horse.step_water": 1265, - "minecraft:item.bottle.fill_dragonbreath": 185, - "minecraft:block.froglight.break": 546, - "minecraft:entity.panda.hurt": 1023, - "minecraft:block.cherry_wood_button.click_on": 295, - "minecraft:block.wooden_door.close": 1561, - "minecraft:entity.bogged.step": 173, - "minecraft:entity.frog.lay_spawn": 561, - "minecraft:entity.villager.work_mason": 1470, - "minecraft:intentionally_empty": 940, - "minecraft:item.book.put": 181, - "minecraft:block.brewing_stand.brew": 199, - "minecraft:block.deepslate_bricks.step": 397, - "minecraft:entity.axolotl.attack": 88, - "minecraft:entity.lingering_potion.throw": 783, - "minecraft:entity.strider.happy": 1303, - "minecraft:item.armor.equip_netherite": 74, - "minecraft:block.ancient_debris.fall": 45, - "minecraft:block.hanging_roots.step": 652, - "minecraft:block.iron_door.close": 746, - "minecraft:block.moss_carpet.hit": 833, - "minecraft:block.sand.hit": 1187, - "minecraft:entity.cat.stray_ambient": 251, - "minecraft:entity.egg.throw": 455, - "minecraft:entity.illusioner.prepare_blindness": 743, - "minecraft:entity.panda.death": 1017, - "minecraft:entity.panda.pre_sneeze": 1014, - "minecraft:item.goat_horn.sound.5": 711, - "minecraft:item.mace.smash_air": 800, - "minecraft:block.lodestone.hit": 797, - "minecraft:block.shroomlight.break": 1233, - "minecraft:block.vine.hit": 1480, - "minecraft:item.bundle.insert": 223, - "minecraft:block.shulker_box.open": 1241, - "minecraft:block.trial_spawner.ambient": 684, - "minecraft:block.wet_sponge.break": 1524, - "minecraft:entity.bat.hurt": 137, - "minecraft:entity.elder_guardian.curse": 458, - "minecraft:entity.panda.eat": 1018, - "minecraft:entity.wandering_trader.hurt": 1489, - "minecraft:block.bamboo_wood.break": 113, - "minecraft:block.cave_vines.break": 259, - "minecraft:entity.villager.work_fisherman": 1466, - "minecraft:entity.witch.throw": 1537, - "minecraft:music.nether.crimson_forest": 894, - "minecraft:block.amethyst_block.place": 33, - "minecraft:block.comparator.click": 329, - "minecraft:block.portal.trigger": 1133, - "minecraft:entity.camel.step_sand": 241, - "minecraft:entity.creeper.death": 372, - "minecraft:entity.firework_rocket.twinkle_far": 512, - "minecraft:entity.puffer_fish.flop": 1143, - "minecraft:entity.vex.ambient": 1450, - "minecraft:entity.wandering_trader.yes": 1493, - "minecraft:entity.warden.sniff": 1509, - "minecraft:item.bucket.empty_tadpole": 215, - "minecraft:item.bucket.fill_lava": 219, - "minecraft:block.netherrack.place": 983, - "minecraft:block.wet_sponge.step": 1529, - "minecraft:entity.generic.big_fall": 571, - "minecraft:item.honeycomb.wax_on": 704, - "minecraft:block.ladder.step": 767, - "minecraft:block.trial_spawner.spawn_item": 680, - "minecraft:block.tuff.break": 1400, - "minecraft:entity.leash_knot.place": 779, - "minecraft:entity.player.teleport": 1119, - "minecraft:entity.ravager.hurt": 1157, - "minecraft:item.goat_horn.sound.6": 712, - "minecraft:item.trident.riptide_1": 1387, - "minecraft:ambient.warped_forest.mood": 22, - "minecraft:block.nether_sprouts.step": 957, - "minecraft:block.nether_wood.fall": 926, - "minecraft:block.note_block.pling": 994, - "minecraft:block.vine.place": 1481, - "minecraft:entity.elder_guardian.hurt_land": 463, - "minecraft:entity.hostile.big_fall": 727, - "minecraft:entity.parrot.hurt": 1029, - "minecraft:item.wolf_armor.damage": 1550, - "minecraft:music.nether.warped_forest": 910, - "minecraft:block.amethyst_block.hit": 32, - "minecraft:block.bamboo.break": 105, - "minecraft:block.bamboo.place": 108, - "minecraft:block.dispenser.launch": 410, - "minecraft:block.small_dripleaf.step": 1285, - "minecraft:block.vault.ambient": 1437, - "minecraft:entity.horse.death": 718, - "minecraft:item.ink_sac.use": 745, - "minecraft:block.hanging_sign.place": 657, - "minecraft:block.note_block.imitate.zombie": 1002, - "minecraft:block.sculk.place": 1200, - "minecraft:entity.parrot.imitate.skeleton": 1052, - "minecraft:entity.pig.step": 1076, - "minecraft:entity.piglin_brute.step": 1091, - "minecraft:entity.slime.jump_small": 1313, - "minecraft:entity.zombie.infect": 1596, - "minecraft:block.beacon.deactivate": 142, - "minecraft:block.respawn_anchor.deplete": 1174, - "minecraft:block.stem.break": 946, - "minecraft:block.tripwire.click_off": 1393, - "minecraft:entity.bogged.ambient": 169, - "minecraft:entity.chicken.egg": 305, - "minecraft:entity.villager.work_shepherd": 1471, - "minecraft:block.note_block.bit": 1000, - "minecraft:block.note_block.imitate.creeper": 1004, - "minecraft:entity.firework_rocket.blast_far": 506, - "minecraft:entity.ghast.scream": 585, - "minecraft:entity.glow_squid.ambient": 604, - "minecraft:entity.husk.step": 737, - "minecraft:entity.salmon.death": 1182, - "minecraft:entity.silverfish.ambient": 1251, - "minecraft:entity.spider.ambient": 1343, - "minecraft:block.copper_trapdoor.close": 358, - "minecraft:entity.elder_guardian.ambient_land": 457, - "minecraft:entity.firework_rocket.large_blast_far": 508, - "minecraft:entity.parrot.imitate.breeze": 1032, - "minecraft:music_disc.11": 871, - "minecraft:music_disc.relic": 885, - "minecraft:ui.toast.in": 1434, - "minecraft:ambient.crimson_forest.mood": 13, - "minecraft:block.beehive.enter": 151, - "minecraft:entity.bogged.death": 170, - "minecraft:entity.minecart.riding": 825, - "minecraft:entity.piglin_brute.death": 1089, - "minecraft:block.stem.place": 948, - "minecraft:block.stone.place": 1366, - "minecraft:entity.cat.ambient": 250, - "minecraft:entity.parrot.fly": 1028, - "minecraft:item.shield.break": 1232, - "minecraft:music_disc.precipice": 888, - "minecraft:block.frogspawn.hatch": 554, - "minecraft:entity.camel.hurt": 236, - "minecraft:entity.skeleton_horse.gallop_water": 1263, - "minecraft:entity.sniffer.eat": 1318, - "minecraft:entity.warden.hurt": 1502, - "minecraft:block.moss.fall": 842, - "minecraft:block.netherite_block.fall": 980, - "minecraft:entity.chicken.step": 307, - "minecraft:entity.fox.sleep": 532, - "minecraft:item.crossbow.quick_charge_3": 383, - "minecraft:block.frogspawn.step": 551, - "minecraft:block.lantern.step": 772, - "minecraft:block.mangrove_roots.break": 809, - "minecraft:block.mud.hit": 848, - "minecraft:entity.cat.hiss": 254, - "minecraft:entity.ender_eye.death": 475, - "minecraft:entity.endermite.hurt": 485, - "minecraft:entity.goat.milk": 613, - "minecraft:block.bamboo_sapling.break": 110, - "minecraft:block.nether_ore.hit": 1168, - "minecraft:entity.elder_guardian.ambient": 456, - "minecraft:item.bottle.fill": 184, - "minecraft:entity.donkey.angry": 422, - "minecraft:entity.zombie.destroy_egg": 1591, - "minecraft:block.bone_block.place": 177, - "minecraft:block.nether_wood_pressure_plate.click_on": 937, - "minecraft:entity.warden.sonic_charge": 1511, - "minecraft:block.chorus_flower.grow": 318, - "minecraft:block.lodestone.place": 796, - "minecraft:block.nether_sprouts.hit": 959, - "minecraft:block.slime_block.step": 1278, - "minecraft:block.sponge.break": 1349, - "minecraft:entity.allay.item_thrown": 6, - "minecraft:entity.armadillo.step": 58, - "minecraft:entity.zombie_villager.ambient": 1602, - "minecraft:item.hoe.till": 689, - "minecraft:block.copper_bulb.break": 339, - "minecraft:entity.cat.purr": 257, - "minecraft:entity.cat.purreow": 258, - "minecraft:entity.slime.squish_small": 1314, - "minecraft:entity.strider.saddle": 1310, - "minecraft:entity.turtle.egg_hatch": 1420, - "minecraft:block.copper_door.open": 352, - "minecraft:block.wool.break": 1574, - "minecraft:entity.polar_bear.death": 1122, - "minecraft:block.bamboo_sapling.place": 112, - "minecraft:block.wooden_door.open": 1562, - "minecraft:entity.magma_cube.jump": 806, - "minecraft:entity.parrot.imitate.warden": 1058, - "minecraft:item.armor.equip_generic": 70, - "minecraft:item.mace.smash_ground_heavy": 802, - "minecraft:block.ancient_debris.step": 42, - "minecraft:block.big_dripleaf.step": 161, - "minecraft:block.cherry_wood_trapdoor.close": 292, - "minecraft:block.honey_block.place": 701, - "minecraft:block.metal.place": 819, - "minecraft:block.pink_petals.hit": 838, - "minecraft:entity.cow.step": 369, - "minecraft:entity.donkey.jump": 427, - "minecraft:entity.ender_dragon.growl": 472, - "minecraft:entity.fox.teleport": 535, - "minecraft:entity.parrot.imitate.silverfish": 1051, - "minecraft:ambient.crimson_forest.loop": 12, - "minecraft:block.muddy_mangrove_roots.fall": 857, - "minecraft:block.note_block.iron_xylophone": 997, - "minecraft:entity.breeze.shoot": 191, - "minecraft:entity.dragon_fireball.explode": 470, - "minecraft:entity.pig.ambient": 1072, - "minecraft:block.nether_gold_ore.place": 1164, - "minecraft:block.rooted_dirt.step": 1180, - "minecraft:block.sculk_vein.step": 1225, - "minecraft:entity.illusioner.prepare_mirror": 744, - "minecraft:item.bucket.empty_lava": 213, - "minecraft:item.crossbow.loading_start": 380, - "minecraft:item.totem.use": 1383, - "minecraft:block.dripstone_block.step": 429, - "minecraft:block.ender_chest.open": 467, - "minecraft:block.nether_bricks.hit": 921, - "minecraft:entity.parrot.imitate.wither": 1060, - "minecraft:block.iron_trapdoor.open": 755, - "minecraft:block.stone_pressure_plate.click_on": 1368, - "minecraft:entity.zombie_villager.death": 1605, - "minecraft:block.ancient_debris.hit": 44, - "minecraft:block.azalea.step": 99, - "minecraft:block.big_dripleaf.hit": 159, - "minecraft:block.bubble_column.bubble_pop": 205, - "minecraft:block.chain.place": 268, - "minecraft:block.chiseled_bookshelf.place": 316, - "minecraft:entity.cat.death": 252, - "minecraft:entity.glow_item_frame.remove_item": 602, - "minecraft:entity.painting.place": 1013, - "minecraft:item.trident.thunder": 1391, - "minecraft:block.glass.fall": 594, - "minecraft:block.nether_bricks.step": 919, - "minecraft:entity.polar_bear.hurt": 1123, - "minecraft:block.amethyst_cluster.hit": 38, - "minecraft:block.crafter.craft": 370, - "minecraft:block.shroomlight.fall": 1237, - "minecraft:entity.breeze.whirl": 197, - "minecraft:entity.iron_golem.damage": 749, - "minecraft:entity.piglin_brute.hurt": 1090, - "minecraft:entity.skeleton.step": 1268, - "minecraft:block.gravel.step": 637, - "minecraft:block.ladder.place": 766, - "minecraft:entity.armadillo.death": 59, - "minecraft:entity.wind_charge.throw": 1531, - "minecraft:music.overworld.dripstone_caves": 896, - "minecraft:block.sand.break": 1185, - "minecraft:entity.goat.ram_impact": 615, - "minecraft:entity.zombified_piglin.death": 1599, - "minecraft:block.amethyst_block.fall": 31, - "minecraft:block.bamboo_wood_hanging_sign.step": 668, - "minecraft:block.froglight.place": 549, - "minecraft:block.wooden_trapdoor.open": 1564, - "minecraft:entity.dolphin.play": 418, - "minecraft:entity.generic.explode": 576, - "minecraft:entity.turtle.egg_crack": 1419, - "minecraft:entity.wolf.step": 1559, - "minecraft:block.deepslate.step": 402, - "minecraft:block.metal_pressure_plate.click_off": 820, - "minecraft:entity.horse.armor": 716, - "minecraft:entity.magma_cube.squish": 807, - "minecraft:block.chest.close": 300, - "minecraft:block.small_dripleaf.place": 1284, - "minecraft:entity.llama.ambient": 784, - "minecraft:music_disc.5": 870, - "minecraft:block.large_amethyst_bud.break": 773, - "minecraft:entity.ender_pearl.throw": 487, - "minecraft:entity.horse.jump": 722, - "minecraft:entity.mule.death": 864, - "minecraft:music_disc.stal": 880, - "minecraft:block.big_dripleaf.fall": 158, - "minecraft:block.deepslate_tiles.fall": 404, - "minecraft:block.hanging_sign.step": 653, - "minecraft:block.nether_gold_ore.fall": 1162, - "minecraft:block.roots.hit": 568, - "minecraft:entity.horse.saddle": 724, - "minecraft:entity.hostile.splash": 731, - "minecraft:entity.ravager.ambient": 1153, - "minecraft:entity.warden.listening": 1503, - "minecraft:ambient.underwater.loop.additions": 26, - "minecraft:block.note_block.banjo": 1001, - "minecraft:block.wart_block.place": 973, - "minecraft:entity.armadillo.unroll_start": 65, - "minecraft:entity.axolotl.swim": 94, - "minecraft:entity.fox.aggro": 525, - "minecraft:entity.parrot.imitate.wither_skeleton": 1061, - "minecraft:entity.player.big_fall": 1105, - "minecraft:entity.zombie_villager.cure": 1604, - "minecraft:item.trident.throw": 1390, - "minecraft:block.bamboo_wood_button.click_off": 122, - "minecraft:block.frogspawn.hit": 555, - "minecraft:entity.breeze.land": 193, - "minecraft:entity.evoker.hurt": 496, - "minecraft:entity.mooshroom.convert": 826, - "minecraft:entity.wither_skeleton.death": 1544, - "minecraft:item.trident.hit_ground": 1385, - "minecraft:block.chest.locked": 301, - "minecraft:block.conduit.ambient": 335, - "minecraft:entity.goat.screaming.milk": 623, - "minecraft:entity.snow_golem.ambient": 1335, - "minecraft:entity.warden.heartbeat": 1501, - "minecraft:item.bundle.drop_contents": 222, - "minecraft:music.overworld.desert": 912, - "minecraft:block.bone_block.step": 178, - "minecraft:entity.bee.death": 144, - "minecraft:entity.camel.dash": 232, - "minecraft:entity.husk.ambient": 733, - "minecraft:entity.wither.ambient": 1538, - "minecraft:entity.drowned.hurt_water": 450, - "minecraft:entity.enderman.death": 478, - "minecraft:entity.piglin_brute.ambient": 1087, - "minecraft:block.campfire.crackle": 242, - "minecraft:block.chain.hit": 267, - "minecraft:block.stone.break": 1361, - "minecraft:entity.wandering_trader.no": 1490, - "minecraft:block.grass.fall": 629, - "minecraft:block.stone.fall": 1364, - "minecraft:block.trial_spawner.place": 675, - "minecraft:entity.elder_guardian.flop": 461, - "minecraft:music.under_water": 917, - "minecraft:block.froglight.fall": 547, - "minecraft:entity.camel.death": 234, - "minecraft:entity.dolphin.splash": 419, - "minecraft:entity.panda.bite": 1024, - "minecraft:entity.parrot.step": 1065, - "minecraft:entity.pillager.hurt": 1096, - "minecraft:entity.tadpole.flop": 1378, - "minecraft:entity.villager.yes": 1460, - "minecraft:ambient.underwater.exit": 24, - "minecraft:block.cherry_sapling.hit": 277, - "minecraft:block.tripwire.attach": 1392, - "minecraft:block.azalea_leaves.hit": 102, - "minecraft:block.fire.extinguish": 514, - "minecraft:block.honey_block.step": 703, - "minecraft:block.sand.fall": 1186, - "minecraft:entity.llama.eat": 788, - "minecraft:entity.parrot.imitate.drowned": 1034, - "minecraft:entity.zombie.ambient": 1585, - "minecraft:item.brush.brushing.gravel": 202, - "minecraft:block.cake.add_candle": 225, - "minecraft:block.composter.fill_success": 332, - "minecraft:block.conduit.deactivate": 338, - "minecraft:block.nether_gold_ore.hit": 1163, - "minecraft:block.nether_wood_fence_gate.close": 938, - "minecraft:block.netherite_block.place": 978, - "minecraft:block.packed_mud.fall": 942, - "minecraft:block.wood.break": 1569, - "minecraft:entity.cat.eat": 253, - "minecraft:entity.elder_guardian.death_land": 460, - "minecraft:entity.glow_item_frame.rotate_item": 603, - "minecraft:entity.slime.hurt": 1271, - "minecraft:block.candle.ambient": 243, - "minecraft:block.cherry_wood_trapdoor.open": 293, - "minecraft:block.spore_blossom.step": 1301, - "minecraft:block.suspicious_sand.break": 536, - "minecraft:entity.evoker.prepare_wololo": 499, - "minecraft:entity.shulker.open": 1248, - "minecraft:entity.villager.no": 1458, - "minecraft:block.bamboo_wood_trapdoor.close": 120, - "minecraft:block.big_dripleaf.place": 160, - "minecraft:block.cherry_leaves.place": 283, - "minecraft:block.hanging_sign.break": 654, - "minecraft:block.heavy_core.step": 662, - "minecraft:block.ladder.fall": 764, - "minecraft:block.nether_wood_pressure_plate.click_off": 936, - "minecraft:block.sculk_catalyst.place": 1206, - "minecraft:block.sniffer_egg.hatch": 1331, - "minecraft:entity.piglin.angry": 1079, - "minecraft:block.cherry_wood.break": 270, - "minecraft:block.note_block.hat": 993, - "minecraft:block.sculk_vein.break": 1221, - "minecraft:block.stone.step": 1369, - "minecraft:entity.camel.dash_ready": 233, - "minecraft:entity.magma_cube.death_small": 793, - "minecraft:entity.parrot.imitate.ghast": 1039, - "minecraft:entity.vex.hurt": 1453, - "minecraft:block.chiseled_bookshelf.pickup.enchanted": 315, - "minecraft:block.weeping_vines.step": 967, - "minecraft:entity.cod.flop": 327, - "minecraft:entity.phantom.death": 1068, - "minecraft:entity.wandering_trader.death": 1485, - "minecraft:block.bell.use": 155, - "minecraft:block.copper_bulb.turn_on": 344, - "minecraft:entity.cat.beg_for_food": 255, - "minecraft:block.big_dripleaf.tilt_down": 443, - "minecraft:block.cave_vines.hit": 261, - "minecraft:block.mud_bricks.step": 855, - "minecraft:block.sculk.hit": 1199, - "minecraft:block.wart_block.break": 971, - "minecraft:block.sculk_catalyst.hit": 1205, - "minecraft:block.suspicious_gravel.place": 543, - "minecraft:entity.donkey.ambient": 421, - "minecraft:entity.guardian.hurt_land": 647, - "minecraft:entity.panda.worried_ambient": 1022, - "minecraft:block.bamboo_wood_door.close": 118, - "minecraft:block.chiseled_bookshelf.break": 308, - "minecraft:entity.horse.step_wood": 726, - "minecraft:music_disc.creator_music_box": 887, - "minecraft:block.cobweb.break": 320, - "minecraft:block.lava.extinguish": 776, - "minecraft:entity.guardian.attack": 642, - "minecraft:block.gravel.hit": 635, - "minecraft:block.sculk_shrieker.shriek": 1219, - "minecraft:entity.camel.ambient": 231, - "minecraft:entity.evoker_fangs.attack": 495, - "minecraft:entity.player.swim": 1118, - "minecraft:entity.turtle.swim": 1426, - "minecraft:item.bone_meal.use": 179, - "minecraft:entity.armadillo.scute_drop": 62, - "minecraft:entity.cow.milk": 368, - "minecraft:entity.silverfish.step": 1254, - "minecraft:entity.snow_golem.death": 1336, - "minecraft:entity.breeze.slide": 194, - "minecraft:entity.camel.stand": 239, - "minecraft:entity.drowned.step": 452, - "minecraft:entity.frog.eat": 559, - "minecraft:entity.salmon.flop": 1183, - "minecraft:entity.villager.work_leatherworker": 1468, - "minecraft:entity.zoglin.hurt": 1583, - "minecraft:block.bamboo_wood_fence_gate.open": 127, - "minecraft:block.deepslate_bricks.fall": 394, - "minecraft:block.mud_bricks.break": 851, - "minecraft:block.muddy_mangrove_roots.step": 860, - "minecraft:block.soul_soil.fall": 1295, - "minecraft:entity.guardian.ambient_land": 641, - "minecraft:entity.piglin_brute.converted_to_zombified": 1092, - "minecraft:block.bamboo_wood_pressure_plate.click_off": 124, - "minecraft:block.calcite.hit": 229, - "minecraft:block.decorated_pot.insert": 388, - "minecraft:block.polished_tuff.step": 1414, - "minecraft:entity.drowned.hurt": 449, - "minecraft:entity.ghast.ambient": 582, - "minecraft:entity.parrot.imitate.piglin_brute": 1047, - "minecraft:item.brush.brushing.sand": 201, - "minecraft:block.beacon.ambient": 141, - "minecraft:block.sand.place": 1188, - "minecraft:entity.ravager.stunned": 1159, - "minecraft:block.nether_wood.place": 928, - "minecraft:entity.generic.extinguish_fire": 577, - "minecraft:entity.sheep.shear": 1229, - "minecraft:block.basalt.fall": 134, - "minecraft:block.cave_vines.place": 262, - "minecraft:block.nether_wood_door.open": 931, - "minecraft:entity.item_frame.add_item": 756, - "minecraft:entity.item_frame.remove_item": 759, - "minecraft:entity.sniffer.death": 1321, - "minecraft:entity.zombie_villager.converted": 1603, - "minecraft:item.mace.smash_ground": 801, - "minecraft:block.bamboo_wood_fence_gate.close": 126, - "minecraft:block.netherrack.fall": 985, - "minecraft:block.pointed_dripstone.land": 438, - "minecraft:block.sculk_sensor.place": 1213, - "minecraft:entity.zoglin.step": 1584, - "minecraft:item.dye.use": 454, - "minecraft:block.deepslate_bricks.break": 393, - "minecraft:block.fungus.step": 962, - "minecraft:block.lantern.break": 768, - "minecraft:block.note_block.guitar": 991, - "minecraft:block.tuff_bricks.hit": 1407, - "minecraft:entity.camel.step": 240, - "minecraft:entity.cow.ambient": 365, - "minecraft:entity.drowned.ambient": 445, - "minecraft:music.overworld.jungle": 914, - "minecraft:block.bamboo.step": 109, - "minecraft:block.polished_tuff.fall": 1411, - "minecraft:entity.generic.eat": 575, - "minecraft:entity.llama.spit": 790, - "minecraft:entity.mule.hurt": 866, - "minecraft:entity.parrot.imitate.evoker": 1038, - "minecraft:entity.zombie_horse.death": 1593, - "minecraft:block.bamboo_wood.place": 116, - "minecraft:block.nether_wood.hit": 927, - "minecraft:block.nether_wood_hanging_sign.step": 663, - "minecraft:block.netherrack.break": 981, - "minecraft:entity.allay.hurt": 3, - "minecraft:entity.parrot.imitate.hoglin": 1041, - "minecraft:block.soul_soil.step": 1292, - "minecraft:entity.enderman.ambient": 477, - "minecraft:entity.goat.screaming.ram_impact": 625, - "minecraft:entity.parrot.imitate.zoglin": 1062, - "minecraft:entity.spider.death": 1344, - "minecraft:entity.vindicator.death": 1476, - "minecraft:ambient.underwater.loop": 25, - "minecraft:block.slime_block.fall": 1275, - "minecraft:block.wool.place": 1577, - "minecraft:entity.blaze.death": 164, - "minecraft:entity.ghast.warn": 587, - "minecraft:entity.hoglin.angry": 691, - "minecraft:entity.wolf.growl": 1554, - "minecraft:particle.soul_escape": 1296, - "minecraft:block.vault.step": 1449, - "minecraft:entity.generic.death": 573, - "minecraft:entity.mule.chest": 863, - "minecraft:entity.frog.tongue": 564, - "minecraft:ui.loom.take_result": 1429, - "minecraft:block.lava.ambient": 775, - "minecraft:block.lily_pad.place": 1483, - "minecraft:block.mud.break": 846, - "minecraft:entity.armadillo.hurt": 55, - "minecraft:entity.bee.pollinate": 149, - "minecraft:entity.player.breath": 1106, - "minecraft:ambient.nether_wastes.loop": 15, - "minecraft:block.vault.place": 1448, - "minecraft:entity.sniffer.hurt": 1320, - "minecraft:entity.tadpole.death": 1377, - "minecraft:entity.witch.hurt": 1536, - "minecraft:event.mob_effect.raid_omen": 1610, - "minecraft:item.brush.brushing.sand.complete": 203, - "minecraft:block.cherry_wood.fall": 271, - "minecraft:block.cobweb.step": 321, - "minecraft:block.copper_door.close": 351, - "minecraft:block.tuff.fall": 1404, - "minecraft:entity.axolotl.hurt": 90, - "minecraft:entity.mooshroom.shear": 830, - "minecraft:item.bundle.remove_one": 224, - "minecraft:block.cherry_wood_hanging_sign.break": 286, - "minecraft:block.conduit.activate": 334, - "minecraft:entity.arrow.hit": 82, - "minecraft:entity.donkey.hurt": 426, - "minecraft:ambient.warped_forest.additions": 20, - "minecraft:entity.goat.screaming.ambient": 618, - "minecraft:entity.parrot.imitate.piglin": 1046, - "minecraft:block.weeping_vines.break": 966, - "minecraft:entity.fish.swim": 515, - "minecraft:entity.fishing_bobber.retrieve": 516, - "minecraft:entity.phantom.swoop": 1071, - "minecraft:block.stone_button.click_on": 1363, - "minecraft:block.trial_spawner.break": 673, - "minecraft:entity.boat.paddle_land": 167, - "minecraft:entity.goat.screaming.eat": 620, - "minecraft:entity.wandering_trader.ambient": 1484, - "minecraft:entity.zombified_piglin.hurt": 1600, - "minecraft:block.cherry_leaves.step": 284, - "minecraft:block.vault.activate": 1436, - "minecraft:entity.drowned.shoot": 451, - "minecraft:entity.tadpole.hurt": 1380, - "minecraft:block.bamboo_wood_hanging_sign.break": 669, - "minecraft:block.copper.fall": 350, - "minecraft:block.pointed_dripstone.drip_lava": 439, - "minecraft:block.tuff.hit": 1403, - "minecraft:entity.frog.step": 563, - "minecraft:entity.magma_cube.squish_small": 808, - "minecraft:block.cherry_leaves.break": 280, - "minecraft:block.moss.place": 844, - "minecraft:block.scaffolding.hit": 1192, - "minecraft:entity.boat.paddle_water": 168, - "minecraft:entity.mule.ambient": 861, - "minecraft:entity.parrot.imitate.shulker": 1050, - "minecraft:entity.piglin.jealous": 1082, - "minecraft:entity.villager.work_farmer": 1465, - "minecraft:item.axe.strip": 85, - "minecraft:block.end_portal_frame.fill": 489, - "minecraft:block.trial_spawner.spawn_item_begin": 681, - "minecraft:entity.armadillo.peek": 64, - "minecraft:block.cherry_wood_hanging_sign.step": 285, - "minecraft:block.frogspawn.place": 556, - "minecraft:block.glass.break": 593, - "minecraft:block.powder_snow.step": 1138, - "minecraft:block.wooden_pressure_plate.click_on": 1568, - "minecraft:entity.armor_stand.break": 78, - "minecraft:entity.donkey.chest": 423, - "minecraft:entity.illusioner.hurt": 741, - "minecraft:entity.llama.death": 787, - "minecraft:entity.shulker.hurt_closed": 1247, - "minecraft:block.trial_spawner.open_shutter": 686, - "minecraft:block.weeping_vines.place": 968, - "minecraft:entity.experience_bottle.throw": 500, - "minecraft:entity.rabbit.hurt": 1150, - "minecraft:entity.silverfish.hurt": 1253, - "minecraft:entity.warden.nearby_close": 1505, - "minecraft:block.portal.ambient": 1131, - "minecraft:block.suspicious_gravel.fall": 545, - "minecraft:block.sweet_berry_bush.break": 1374, - "minecraft:block.vault.open_shutter": 1447, - "minecraft:entity.chicken.hurt": 306, - "minecraft:entity.slime.hurt_small": 1312, - "minecraft:entity.zombified_piglin.angry": 1598, - "minecraft:weather.rain": 1517, - "minecraft:block.copper_bulb.turn_off": 345, - "minecraft:block.hanging_roots.place": 651, - "minecraft:block.moss.step": 845, - "minecraft:block.mud.fall": 847, - "minecraft:block.powder_snow.break": 1134, - "minecraft:block.sculk.break": 1197, - "minecraft:block.tuff_bricks.place": 1408, - "minecraft:entity.goat.death": 609, - "minecraft:entity.polar_bear.step": 1124, - "minecraft:item.armor.equip_leather": 73, - "minecraft:ui.button.click": 1427, - "minecraft:block.copper_bulb.step": 340, - "minecraft:block.gilded_blackstone.break": 588, - "minecraft:block.vault.insert_item_fail": 1446, - "minecraft:entity.sheep.step": 1230, - "minecraft:entity.tadpole.grow_up": 1379, - "minecraft:entity.wither_skeleton.step": 1546, - "minecraft:block.polished_tuff.place": 1413, - "minecraft:block.suspicious_sand.step": 537, - "minecraft:entity.player.burp": 1107, - "minecraft:entity.player.death": 1108, - "minecraft:entity.horse.eat": 719, - "minecraft:entity.horse.hurt": 721, - "minecraft:entity.polar_bear.ambient_baby": 1121, - "minecraft:entity.warden.listening_angry": 1504, - "minecraft:block.azalea_leaves.break": 100, - "minecraft:block.cherry_wood_pressure_plate.click_off": 296, - "minecraft:block.composter.fill": 331, - "minecraft:block.honey_block.hit": 700, - "minecraft:block.piston.contract": 1097, - "minecraft:entity.frog.hurt": 560, - "minecraft:block.flowering_azalea.hit": 522, - "minecraft:block.sign.waxed_interact_fail": 1515, - "minecraft:entity.wolf.hurt": 1556, - "minecraft:block.cherry_leaves.hit": 282, - "minecraft:block.deepslate_bricks.hit": 395, - "minecraft:block.sculk.charge": 1196, - "minecraft:ui.loom.select_pattern": 1428, - "minecraft:ambient.cave": 7, - "minecraft:block.rooted_dirt.place": 1179, - "minecraft:block.spore_blossom.break": 1297, - "minecraft:block.spore_blossom.fall": 1298, - "minecraft:block.deepslate_tiles.hit": 405, - "minecraft:block.sniffer_egg.crack": 1330, - "minecraft:entity.generic.swim": 581, - "minecraft:entity.squid.hurt": 1359, - "minecraft:entity.villager.trade": 1459, - "minecraft:entity.villager.work_cartographer": 1463, - "minecraft:block.cobweb.hit": 323, - "minecraft:block.conduit.attack.target": 337, - "minecraft:block.nether_wood_button.click_on": 935, - "minecraft:block.pointed_dripstone.drip_lava_into_cauldron": 441, - "minecraft:entity.slime.squish": 1273, - "minecraft:event.raid.horn": 1152, - "minecraft:item.trident.riptide_2": 1388, - "minecraft:block.netherite_block.hit": 979, - "minecraft:block.sculk_vein.hit": 1223, - "minecraft:block.wool.hit": 1576, - "minecraft:entity.snowball.throw": 1332, - "minecraft:block.medium_amethyst_bud.break": 814, - "minecraft:block.scaffolding.break": 1190, - "minecraft:entity.chicken.ambient": 303, - "minecraft:entity.cod.death": 326, - "minecraft:entity.parrot.imitate.vex": 1056, - "minecraft:entity.warden.emerge": 1500, - "minecraft:item.brush.brushing.generic": 200, - "minecraft:block.beacon.power_select": 143, - "minecraft:block.decorated_pot.break": 385, - "minecraft:block.netherrack.hit": 984, - "minecraft:block.note_block.didgeridoo": 999, - "minecraft:block.suspicious_gravel.break": 541, - "minecraft:entity.player.splash": 1116, - "minecraft:entity.turtle.egg_break": 1418, - "minecraft:entity.zombie_villager.step": 1607, - "minecraft:block.basalt.hit": 133, - "minecraft:block.muddy_mangrove_roots.hit": 858, - "minecraft:block.vault.deactivate": 1440, - "minecraft:enchant.thorns.hit": 1381, - "minecraft:entity.puffer_fish.ambient": 1139, - "minecraft:entity.rabbit.attack": 1148, - "minecraft:entity.tropical_fish.hurt": 1399, - "minecraft:block.fungus.place": 963, - "minecraft:block.metal_pressure_plate.click_on": 821, - "minecraft:entity.dolphin.swim": 420, - "minecraft:block.bell.resonate": 156, - "minecraft:block.cave_vines.step": 263, - "minecraft:block.lodestone.fall": 798, - "minecraft:block.wool.fall": 1575, - "minecraft:entity.ocelot.death": 1010, - "minecraft:entity.panda.cant_breed": 1020, - "minecraft:entity.skeleton.hurt": 1266, - "minecraft:item.armor.equip_diamond": 68, - "minecraft:block.chiseled_bookshelf.insert.enchanted": 312, - "minecraft:block.wet_sponge.fall": 1526, - "minecraft:entity.goat.screaming.prepare_ram": 624, - "minecraft:entity.skeleton_horse.hurt": 1260, - "minecraft:entity.snow_golem.shoot": 1338, - "minecraft:item.wolf_armor.repair": 1551, - "minecraft:music_disc.blocks": 873, - "minecraft:block.gilded_blackstone.step": 592, - "minecraft:block.glass.place": 596, - "minecraft:block.note_block.chime": 989, - "minecraft:entity.fox.eat": 529, - "minecraft:entity.mule.eat": 865, - "minecraft:item.wolf_armor.break": 1548, - "minecraft:ui.toast.out": 1435, - "minecraft:ambient.underwater.loop.additions.ultra_rare": 28, - "minecraft:block.anvil.land": 50, - "minecraft:block.nether_wood_hanging_sign.place": 667, - "minecraft:entity.parrot.eat": 1027, - "minecraft:entity.parrot.imitate.creeper": 1033, - "minecraft:entity.wither_skeleton.hurt": 1545, - "minecraft:item.crossbow.loading_middle": 379, - "minecraft:music_disc.cat": 874, - "minecraft:block.pointed_dripstone.hit": 436, - "minecraft:entity.blaze.shoot": 166, - "minecraft:entity.ocelot.hurt": 1008, - "minecraft:entity.rabbit.death": 1149, - "minecraft:entity.sniffer.drop_seed": 1322, - "minecraft:entity.witch.ambient": 1532, - "minecraft:event.mob_effect.bad_omen": 1608, - "minecraft:music_disc.strad": 881, - "minecraft:block.pointed_dripstone.step": 434, - "minecraft:entity.ender_dragon.death": 469, - "minecraft:entity.parrot.imitate.witch": 1059, - "minecraft:music.overworld.flower_forest": 911, - "minecraft:block.vine.step": 1482, - "minecraft:entity.player.attack.weak": 1104, - "minecraft:item.shovel.flatten": 1238, - "minecraft:ambient.nether_wastes.mood": 16, - "minecraft:block.basalt.place": 132, - "minecraft:block.beehive.work": 154, - "minecraft:block.dispenser.fail": 409, - "minecraft:block.mud.place": 849, - "minecraft:block.polished_deepslate.step": 1130, - "minecraft:block.sculk_shrieker.step": 1220, - "minecraft:entity.breeze.death": 195, - "minecraft:entity.creeper.primed": 374, - "minecraft:entity.drowned.death_water": 448, - "minecraft:entity.glow_squid.death": 605, - "minecraft:entity.painting.break": 1012, - "minecraft:entity.piglin.admiring_item": 1077, - "minecraft:entity.player.splash.high_speed": 1117, - "minecraft:entity.vex.charge": 1451, - "minecraft:music_disc.creator": 886, - "minecraft:block.shroomlight.hit": 1236, - "minecraft:block.trial_spawner.close_shutter": 687, - "minecraft:entity.sniffer.happy": 1328, - "minecraft:entity.strider.retreat": 1304, - "minecraft:block.cherry_leaves.fall": 281, - "minecraft:block.end_gateway.spawn": 488, - "minecraft:entity.armadillo.hurt_reduced": 56, - "minecraft:entity.bat.ambient": 135, - "minecraft:entity.endermite.step": 486, - "minecraft:entity.illusioner.mirror_move": 742, - "minecraft:block.copper_grate.fall": 357, - "minecraft:block.nether_wood.step": 929, - "minecraft:block.polished_deepslate.break": 1126, - "minecraft:entity.evoker.cast_spell": 492, - "minecraft:entity.sheep.death": 1227, - "minecraft:entity.zombie.hurt": 1595, - "minecraft:ambient.nether_wastes.additions": 14, - "minecraft:block.cherry_wood_hanging_sign.hit": 288, - "minecraft:block.soul_sand.step": 1287, - "minecraft:block.spore_blossom.hit": 1299, - "minecraft:block.wet_sponge.hit": 1527, - "minecraft:entity.fox.ambient": 526, - "minecraft:entity.phantom.hurt": 1070, - "minecraft:entity.pillager.ambient": 1093, - "minecraft:entity.zombie.converted_to_drowned": 1589, - "minecraft:item.crossbow.quick_charge_1": 381, - "minecraft:item.goat_horn.play": 617, - "minecraft:music.overworld.deep_dark": 895, - "minecraft:block.bone_block.hit": 176, - "minecraft:block.stem.step": 947, - "minecraft:entity.armadillo.brush": 66, - "minecraft:entity.cod.hurt": 328, - "minecraft:entity.pillager.death": 1095, - "minecraft:block.blastfurnace.fire_crackle": 182, - "minecraft:block.chain.step": 269, - "minecraft:block.pumpkin.carve": 1146, - "minecraft:block.roots.fall": 569, - "minecraft:entity.bogged.shear": 172, - "minecraft:entity.ocelot.ambient": 1009, - "minecraft:entity.panda.aggressive_ambient": 1021, - "minecraft:music.game": 891, - "minecraft:music.overworld.snowy_slopes": 907, - "minecraft:block.heavy_core.hit": 660, - "minecraft:block.ladder.hit": 765, - "minecraft:block.nether_wood_hanging_sign.hit": 666, - "minecraft:block.pink_petals.place": 839, - "minecraft:entity.goat.prepare_ram": 614, - "minecraft:entity.husk.converted_to_zombie": 734, - "minecraft:entity.parrot.imitate.elder_guardian": 1035, - "minecraft:entity.puffer_fish.sting": 1145, - "minecraft:entity.turtle.death": 1416, - "minecraft:entity.villager.work_fletcher": 1467, - "minecraft:entity.warden.roar": 1508, - "minecraft:entity.warden.sonic_boom": 1510, - "minecraft:entity.warden.step": 1512, - "minecraft:block.smithing_table.use": 1315, - "minecraft:entity.cat.hurt": 256, - "minecraft:entity.horse.angry": 715, - "minecraft:entity.pig.hurt": 1074, - "minecraft:block.beehive.exit": 152, - "minecraft:block.gilded_blackstone.hit": 590, - "minecraft:block.netherrack.step": 982, - "minecraft:block.pink_petals.step": 840, - "minecraft:entity.bat.death": 136, - "minecraft:entity.blaze.ambient": 162, - "minecraft:entity.camel.eat": 235, - "minecraft:entity.dolphin.eat": 415, - "minecraft:entity.turtle.death_baby": 1417, - "minecraft:music.overworld.old_growth_taiga": 902, - "minecraft:block.anvil.step": 52, - "minecraft:block.cobweb.place": 322, - "minecraft:block.composter.ready": 333, - "minecraft:block.roots.step": 566, - "minecraft:block.small_dripleaf.hit": 1283, - "minecraft:block.wet_grass.break": 1519, - "minecraft:entity.pillager.celebrate": 1094, - "minecraft:entity.zombie.death": 1590, - "minecraft:item.chorus_fruit.teleport": 319, - "minecraft:item.wolf_armor.crack": 1549, - "minecraft:ambient.soul_sand_valley.additions": 17, - "minecraft:block.hanging_sign.hit": 656, - "minecraft:block.small_amethyst_bud.break": 1279, - "minecraft:entity.armadillo.land": 61, - "minecraft:entity.hostile.death": 728, - "minecraft:entity.pig.death": 1073, - "minecraft:entity.vindicator.celebrate": 1475, - "minecraft:block.azalea_leaves.fall": 101, - "minecraft:block.powder_snow.place": 1137, - "minecraft:block.sculk_vein.fall": 1222, - "minecraft:entity.tropical_fish.flop": 1398, - "minecraft:item.axe.wax_off": 87, - "minecraft:item.crossbow.hit": 377, - "minecraft:block.honey_block.break": 698, - "minecraft:block.water.ambient": 1516, - "minecraft:entity.armadillo.ambient": 57, - "minecraft:entity.horse.land": 723, - "minecraft:entity.parrot.imitate.magma_cube": 1044, - "minecraft:entity.magma_cube.death": 803, - "minecraft:entity.shulker_bullet.hurt": 1243, - "minecraft:block.deepslate.place": 401, - "minecraft:block.fence_gate.open": 503, - "minecraft:block.flowering_azalea.break": 520, - "minecraft:block.froglight.hit": 548, - "minecraft:block.vault.insert_item": 1445, - "minecraft:music.end": 890, - "minecraft:block.dripstone_block.place": 430, - "minecraft:block.nylium.break": 951, - "minecraft:block.sculk.spread": 1195, - "minecraft:entity.firework_rocket.blast": 505, - "minecraft:entity.item.break": 761, - "minecraft:entity.phantom.bite": 1067, - "minecraft:block.deepslate.fall": 399, - "minecraft:block.respawn_anchor.charge": 1173, - "minecraft:entity.panda.ambient": 1016, - "minecraft:item.spyglass.use": 1355, - "minecraft:music.overworld.frozen_peaks": 906, - "minecraft:block.moss_carpet.step": 835, - "minecraft:block.pointed_dripstone.break": 433, - "minecraft:item.crop.plant": 376, - "minecraft:block.dripstone_block.hit": 431, - "minecraft:block.honey_block.fall": 699, - "minecraft:entity.arrow.shoot": 84, - "minecraft:entity.experience_orb.pickup": 501, - "minecraft:entity.goat.screaming.horn_break": 626, - "minecraft:block.candle.extinguish": 245, - "minecraft:block.wart_block.hit": 974, - "minecraft:entity.guardian.death_land": 644, - "minecraft:entity.panda.step": 1019, - "minecraft:entity.parrot.death": 1026, - "minecraft:entity.piglin.ambient": 1078, - "minecraft:entity.wind_charge.wind_burst": 1530, - "minecraft:item.bucket.fill_axolotl": 217, - "minecraft:item.lodestone_compass.lock": 799, - "minecraft:music.credits": 869, - "minecraft:music.overworld.bamboo_jungle": 916, - "minecraft:block.azalea.break": 95, - "minecraft:block.barrel.open": 129, - "minecraft:block.chiseled_bookshelf.hit": 310, - "minecraft:block.sponge.hit": 1351, - "minecraft:block.wool.step": 1578, - "minecraft:entity.shulker_bullet.hit": 1242, + "minecraft:block.portal.travel": 1132, + "minecraft:block.shulker_box.close": 1240, + "minecraft:state.hostile.hurt": 729, + "minecraft:state.mule.jump": 867, + "minecraft:state.parrot.imitate.illusioner": 1043, + "minecraft:state.salmon.ambient": 1181, + "minecraft:state.vex.death": 1452, + "minecraft:state.donkey.death": 424, + "minecraft:state.player.hurt_drown": 1110, + "minecraft:state.puffer_fish.hurt": 1144, + "minecraft:state.spider.step": 1346, + "minecraft:block.bubble_column.upwards_ambient": 206, + "minecraft:state.ender_dragon.ambient": 468, + "minecraft:state.enderman.teleport": 482, + "minecraft:state.squid.squirt": 1360, + "minecraft:block.dripstone_block.break": 428, + "minecraft:block.tuff.step": 1401, + "minecraft:state.iron_golem.attack": 748, + "minecraft:state.villager.work_librarian": 1469, + "minecraft:block.bubble_column.whirlpool_ambient": 208, + "minecraft:block.sculk_shrieker.fall": 1216, + "minecraft:state.drowned.death": 447, + "minecraft:state.ravager.roar": 1160, + "minecraft:block.decorated_pot.step": 390, + "minecraft:state.illusioner.ambient": 738, + "minecraft:state.sniffer.sniffing": 1324, + "minecraft:item.bucket.empty": 210, + "minecraft:block.azalea_leaves.place": 103, + "minecraft:block.cherry_wood.step": 274, + "minecraft:block.nether_wood_trapdoor.open": 933, + "minecraft:block.nylium.fall": 955, + "minecraft:block.wooden_button.click_off": 1565, + "minecraft:state.ender_dragon.flap": 471, + "minecraft:state.glow_item_frame.place": 601, + "minecraft:state.goat.eat": 610, + "minecraft:state.wandering_trader.drink_potion": 1488, + "minecraft:item.goat_horn.sound.0": 706, + "minecraft:block.amethyst_block.chime": 30, + "minecraft:block.calcite.break": 226, + "minecraft:block.calcite.place": 228, + "minecraft:block.coral_block.step": 364, + "minecraft:block.nether_ore.place": 1169, + "minecraft:block.sponge.fall": 1350, + "minecraft:block.weeping_vines.fall": 970, + "minecraft:state.axolotl.splash": 93, + "minecraft:state.evoker.prepare_attack": 497, + "minecraft:state.parrot.imitate.blaze": 1030, + "minecraft:block.bubble_column.upwards_inside": 207, + "minecraft:block.nether_wood_hanging_sign.fall": 665, + "minecraft:block.sponge.absorb": 1354, + "minecraft:block.stone.hit": 1365, + "minecraft:block.wood.hit": 1571, + "minecraft:item.bucket.fill_tadpole": 221, + "minecraft:item.crossbow.shoot": 384, + "minecraft:block.moss_carpet.break": 831, + "minecraft:block.note_block.imitate.piglin": 1007, + "minecraft:block.redstone_torch.burnout": 1171, + "minecraft:block.soul_sand.break": 1286, + "minecraft:state.elder_guardian.death": 459, + "minecraft:state.guardian.ambient": 640, + "minecraft:state.hoglin.death": 694, + "minecraft:block.amethyst_block.break": 29, + "minecraft:block.lever.click": 780, + "minecraft:state.armor_stand.hit": 80, + "minecraft:state.axolotl.death": 89, + "minecraft:state.hoglin.step": 697, + "minecraft:state.player.attack.knockback": 1100, + "minecraft:state.wolf.ambient": 1552, + "minecraft:state.zombified_piglin.ambient": 1597, + "minecraft:block.nether_bricks.place": 920, + "minecraft:block.respawn_anchor.ambient": 1172, + "minecraft:block.respawn_anchor.set_spawn": 1175, + "minecraft:block.sculk_shrieker.place": 1218, + "minecraft:state.horse.ambient": 714, + "minecraft:state.snow_golem.shear": 1339, + "minecraft:block.sculk_catalyst.step": 1207, + "minecraft:block.trial_spawner.fall": 677, + "minecraft:block.wet_sponge.place": 1528, + "minecraft:state.llama.swag": 792, + "minecraft:state.mooshroom.milk": 828, + "minecraft:state.slime.death": 1270, + "minecraft:state.wolf.pant": 1557, + "minecraft:block.nether_sprouts.fall": 960, + "minecraft:state.minecart.inside": 824, + "minecraft:block.chain.break": 265, + "minecraft:block.vault.fall": 1443, + "minecraft:state.breeze.charge": 186, + "minecraft:state.enderman.stare": 481, + "minecraft:state.zoglin.angry": 1580, + "minecraft:block.azalea.hit": 97, + "minecraft:block.gilded_blackstone.fall": 589, + "minecraft:block.note_block.bell": 988, + "minecraft:block.vault.break": 1438, + "minecraft:state.puffer_fish.blow_out": 1140, + "minecraft:state.skeleton.converted_to_stray": 1256, + "minecraft:item.goat_horn.sound.4": 710, + "minecraft:block.cherry_wood_door.close": 290, + "minecraft:block.cherry_wood_fence_gate.open": 299, + "minecraft:block.cobweb.fall": 324, + "minecraft:block.copper_grate.break": 353, + "minecraft:block.lantern.hit": 770, + "minecraft:block.muddy_mangrove_roots.place": 859, + "minecraft:block.snow.break": 1333, + "minecraft:state.evoker.prepare_summon": 498, + "minecraft:state.parrot.ambient": 1025, + "minecraft:state.wolf.shake": 1558, + "minecraft:block.crop.break": 375, + "minecraft:block.sculk_catalyst.fall": 1204, + "minecraft:block.trial_spawner.detect_player": 682, + "minecraft:state.endermite.death": 484, + "minecraft:state.generic.burn": 572, + "minecraft:state.lightning_bolt.impact": 781, + "minecraft:music.nether.soul_sand_valley": 908, + "minecraft:state.fox.screech": 531, + "minecraft:state.parrot.imitate.zombie_villager": 1064, + "minecraft:state.player.levelup": 1114, + "minecraft:state.villager.work_armorer": 1461, + "minecraft:music.overworld.badlands": 913, + "minecraft:block.candle.hit": 247, + "minecraft:block.dispenser.dispense": 408, + "minecraft:block.nether_wood_fence_gate.open": 939, + "minecraft:state.glow_item_frame.add_item": 599, + "minecraft:state.warden.nearby_closest": 1507, + "minecraft:block.moss.break": 841, + "minecraft:state.llama.angry": 785, + "minecraft:state.zombie.attack_iron_door": 1587, + "minecraft:block.copper_trapdoor.open": 359, + "minecraft:block.soul_soil.hit": 1294, + "minecraft:block.sponge.step": 1353, + "minecraft:state.ghast.death": 583, + "minecraft:state.sheep.ambient": 1226, + "minecraft:state.slime.jump": 1272, + "minecraft:state.villager.ambient": 1454, + "minecraft:state.wither.break_block": 1539, + "minecraft:block.rooted_dirt.break": 1176, + "minecraft:state.illusioner.cast_spell": 739, + "minecraft:state.skeleton.ambient": 1255, + "minecraft:state.warden.dig": 1499, + "minecraft:state.zoglin.ambient": 1579, + "minecraft:block.small_dripleaf.fall": 1282, + "minecraft:state.enderman.scream": 480, + "minecraft:state.frog.ambient": 557, + "minecraft:state.skeleton_horse.ambient": 1258, + "minecraft:item.bucket.empty_axolotl": 211, + "minecraft:item.bucket.empty_powder_snow": 214, + "minecraft:block.lava.pop": 777, + "minecraft:block.sculk_shrieker.hit": 1217, + "minecraft:state.chicken.death": 304, + "minecraft:state.dolphin.ambient_water": 412, + "minecraft:state.villager.celebrate": 1455, + "minecraft:ambient.crimson_forest.additions": 11, + "minecraft:block.deepslate.hit": 400, + "minecraft:block.gravel.fall": 634, + "minecraft:state.evoker.celebrate": 493, + "minecraft:state.horse.gallop": 720, + "minecraft:state.parrot.imitate.stray": 1055, + "minecraft:state.player.attack.sweep": 1103, + "minecraft:ambient.underwater.enter": 23, + "minecraft:block.cherry_sapling.break": 275, + "minecraft:block.weeping_vines.hit": 969, + "minecraft:state.guardian.flop": 645, + "minecraft:block.gilded_blackstone.place": 591, + "minecraft:block.growing_plant.crop": 639, + "minecraft:block.lodestone.break": 794, + "minecraft:block.nether_ore.step": 1170, + "minecraft:state.horse.step": 725, + "minecraft:state.wandering_trader.disappeared": 1486, + "minecraft:block.bamboo_wood.step": 117, + "minecraft:block.basalt.step": 131, + "minecraft:block.nylium.step": 952, + "minecraft:block.tripwire.detach": 1395, + "minecraft:state.axolotl.idle_water": 92, + "minecraft:block.anvil.place": 51, + "minecraft:block.moss_carpet.fall": 832, + "minecraft:state.ender_dragon.hurt": 473, + "minecraft:state.piglin.celebrate": 1080, + "minecraft:state.villager.work_weaponsmith": 1473, + "minecraft:item.bucket.empty_fish": 212, + "minecraft:block.chain.fall": 266, + "minecraft:block.furnace.fire_crackle": 570, + "minecraft:state.armor_stand.fall": 79, + "minecraft:state.turtle.hurt_baby": 1422, + "minecraft:block.heavy_core.place": 661, + "minecraft:block.note_block.imitate.wither_skeleton": 1006, + "minecraft:block.powder_snow.fall": 1135, + "minecraft:block.soul_soil.break": 1291, + "minecraft:state.generic.hurt": 578, + "minecraft:state.ghast.hurt": 584, + "minecraft:state.guardian.death": 643, + "minecraft:state.illusioner.death": 740, + "minecraft:state.piglin.hurt": 1083, + "minecraft:state.squid.ambient": 1357, + "minecraft:item.bucket.fill_powder_snow": 220, + "minecraft:music.creative": 868, + "minecraft:block.large_amethyst_bud.place": 774, + "minecraft:block.moss.hit": 843, + "minecraft:block.pointed_dripstone.place": 435, + "minecraft:music.overworld.forest": 901, + "minecraft:block.bamboo_wood.fall": 114, + "minecraft:block.chiseled_bookshelf.step": 313, + "minecraft:block.note_block.xylophone": 996, + "minecraft:block.sculk_catalyst.break": 1203, + "minecraft:block.snow.hit": 1340, + "minecraft:block.vine.fall": 1479, + "minecraft:state.blaze.burn": 163, + "minecraft:state.iron_golem.repair": 752, + "minecraft:state.item_frame.place": 758, + "minecraft:state.vindicator.hurt": 1477, + "minecraft:block.sculk_sensor.break": 1210, + "minecraft:block.vault.eject_item": 1441, + "minecraft:state.goat.hurt": 611, + "minecraft:state.warden.nearby_closer": 1506, + "minecraft:event.mob_effect.trial_omen": 1609, + "minecraft:item.nether_wart.plant": 924, + "minecraft:item.trident.hit": 1384, + "minecraft:ambient.warped_forest.loop": 21, + "minecraft:block.sculk_vein.place": 1224, + "minecraft:block.sweet_berry_bush.place": 1375, + "minecraft:block.vault.hit": 1444, + "minecraft:state.breeze.inhale": 188, + "minecraft:state.polar_bear.ambient": 1120, + "minecraft:state.wandering_trader.drink_milk": 1487, + "minecraft:block.amethyst_cluster.break": 36, + "minecraft:block.vine.break": 1478, + "minecraft:block.wood.place": 1572, + "minecraft:state.tropical_fish.death": 1397, + "minecraft:music.dragon": 889, + "minecraft:block.cherry_wood_fence_gate.close": 298, + "minecraft:state.bee.hurt": 145, + "minecraft:block.bamboo_wood.hit": 115, + "minecraft:block.decorated_pot.insert_fail": 389, + "minecraft:block.roots.place": 567, + "minecraft:state.breeze.wind_burst": 198, + "minecraft:state.rabbit.jump": 1151, + "minecraft:state.shulker.close": 1244, + "minecraft:state.shulker.shoot": 1249, + "minecraft:music.overworld.stony_peaks": 909, + "minecraft:block.crafter.fail": 371, + "minecraft:block.nether_sprouts.break": 956, + "minecraft:state.armadillo.eat": 54, + "minecraft:state.goat.ambient": 608, + "minecraft:item.honey_bottle.drink": 705, + "minecraft:block.ancient_debris.place": 43, + "minecraft:block.copper.break": 346, + "minecraft:state.fox.death": 528, + "minecraft:state.parrot.imitate.husk": 1042, + "minecraft:state.silverfish.death": 1252, + "minecraft:state.warden.attack_impact": 1497, + "minecraft:block.sculk_sensor.fall": 1211, + "minecraft:block.sponge.place": 1352, + "minecraft:state.bat.loop": 138, + "minecraft:state.bee.sting": 148, + "minecraft:state.enderman.hurt": 479, + "minecraft:state.skeleton_horse.jump_water": 1264, + "minecraft:state.villager.work_butcher": 1462, + "minecraft:block.anvil.hit": 49, + "minecraft:block.big_dripleaf.tilt_up": 444, + "minecraft:block.bubble_column.whirlpool_inside": 209, + "minecraft:block.sculk_catalyst.bloom": 1202, + "minecraft:block.trial_spawner.hit": 676, + "minecraft:state.pig.saddle": 1075, + "minecraft:item.bucket.fill_fish": 218, + "minecraft:music_disc.ward": 883, + "minecraft:block.beacon.activate": 140, + "minecraft:block.nether_bricks.fall": 922, + "minecraft:state.hoglin.hurt": 695, + "minecraft:item.armor.equip_turtle": 75, + "minecraft:item.book.page_turn": 180, + "minecraft:block.copper_bulb.place": 341, + "minecraft:block.grass.break": 628, + "minecraft:block.grass.place": 631, + "minecraft:block.mangrove_roots.hit": 811, + "minecraft:state.goat.screaming.hurt": 621, + "minecraft:music_disc.13": 872, + "minecraft:state.parrot.imitate.bogged": 1031, + "minecraft:item.goat_horn.sound.7": 713, + "minecraft:music.overworld.jagged_peaks": 898, + "minecraft:block.iron_door.open": 747, + "minecraft:block.iron_trapdoor.close": 754, + "minecraft:block.nether_wood_button.click_off": 934, + "minecraft:state.generic.splash": 580, + "minecraft:state.tropical_fish.ambient": 1396, + "minecraft:item.goat_horn.sound.2": 708, + "minecraft:block.chest.open": 302, + "minecraft:block.flowering_azalea.fall": 521, + "minecraft:block.nether_wart.break": 923, + "minecraft:state.bogged.hurt": 171, + "minecraft:state.endermite.ambient": 483, + "minecraft:state.player.attack.strong": 1102, + "minecraft:state.wither.spawn": 1547, + "minecraft:music_disc.far": 876, + "minecraft:music_disc.otherside": 884, + "minecraft:block.copper_grate.step": 354, + "minecraft:block.glass.step": 597, + "minecraft:block.grass.step": 632, + "minecraft:block.metal.break": 816, + "minecraft:block.mud.step": 850, + "minecraft:block.soul_sand.fall": 1290, + "minecraft:item.shield.block": 1231, + "minecraft:ui.stonecutter.select_recipe": 1432, + "minecraft:block.decorated_pot.fall": 386, + "minecraft:block.rooted_dirt.hit": 1178, + "minecraft:state.guardian.hurt": 646, + "minecraft:state.splash_potion.throw": 1348, + "minecraft:block.bamboo_wood_hanging_sign.fall": 670, + "minecraft:block.bamboo_wood_trapdoor.open": 121, + "minecraft:block.copper_grate.hit": 356, + "minecraft:block.flowering_azalea.place": 523, + "minecraft:block.fungus.hit": 964, + "minecraft:block.nether_wood_door.close": 930, + "minecraft:block.packed_mud.hit": 943, + "minecraft:block.trial_spawner.spawn_mob": 678, + "minecraft:state.camel.sit": 238, + "minecraft:state.parrot.imitate.spider": 1054, + "minecraft:state.piglin.converted_to_zombified": 1086, + "minecraft:state.sniffer.scenting": 1323, + "minecraft:state.snow_golem.hurt": 1337, + "minecraft:state.stray.death": 1371, + "minecraft:state.tnt.primed": 1382, + "minecraft:ambient.soul_sand_valley.loop": 18, + "minecraft:block.tripwire.click_on": 1394, + "minecraft:state.breeze.idle_air": 190, + "minecraft:state.skeleton_horse.step_water": 1265, + "minecraft:item.bottle.fill_dragonbreath": 185, + "minecraft:block.froglight.break": 546, + "minecraft:state.panda.hurt": 1023, + "minecraft:block.cherry_wood_button.click_on": 295, + "minecraft:block.wooden_door.close": 1561, + "minecraft:state.bogged.step": 173, + "minecraft:state.frog.lay_spawn": 561, + "minecraft:state.villager.work_mason": 1470, + "minecraft:intentionally_empty": 940, + "minecraft:item.book.put": 181, + "minecraft:block.brewing_stand.brew": 199, + "minecraft:block.deepslate_bricks.step": 397, + "minecraft:state.axolotl.attack": 88, + "minecraft:state.lingering_potion.throw": 783, + "minecraft:state.strider.happy": 1303, + "minecraft:item.armor.equip_netherite": 74, + "minecraft:block.ancient_debris.fall": 45, + "minecraft:block.hanging_roots.step": 652, + "minecraft:block.iron_door.close": 746, + "minecraft:block.moss_carpet.hit": 833, + "minecraft:block.sand.hit": 1187, + "minecraft:state.cat.stray_ambient": 251, + "minecraft:state.egg.throw": 455, + "minecraft:state.illusioner.prepare_blindness": 743, + "minecraft:state.panda.death": 1017, + "minecraft:state.panda.pre_sneeze": 1014, + "minecraft:item.goat_horn.sound.5": 711, + "minecraft:item.mace.smash_air": 800, + "minecraft:block.lodestone.hit": 797, + "minecraft:block.shroomlight.break": 1233, + "minecraft:block.vine.hit": 1480, + "minecraft:item.bundle.insert": 223, + "minecraft:block.shulker_box.open": 1241, + "minecraft:block.trial_spawner.ambient": 684, + "minecraft:block.wet_sponge.break": 1524, + "minecraft:state.bat.hurt": 137, + "minecraft:state.elder_guardian.curse": 458, + "minecraft:state.panda.eat": 1018, + "minecraft:state.wandering_trader.hurt": 1489, + "minecraft:block.bamboo_wood.break": 113, + "minecraft:block.cave_vines.break": 259, + "minecraft:state.villager.work_fisherman": 1466, + "minecraft:state.witch.throw": 1537, + "minecraft:music.nether.crimson_forest": 894, + "minecraft:block.amethyst_block.place": 33, + "minecraft:block.comparator.click": 329, + "minecraft:block.portal.trigger": 1133, + "minecraft:state.camel.step_sand": 241, + "minecraft:state.creeper.death": 372, + "minecraft:state.firework_rocket.twinkle_far": 512, + "minecraft:state.puffer_fish.flop": 1143, + "minecraft:state.vex.ambient": 1450, + "minecraft:state.wandering_trader.yes": 1493, + "minecraft:state.warden.sniff": 1509, + "minecraft:item.bucket.empty_tadpole": 215, + "minecraft:item.bucket.fill_lava": 219, + "minecraft:block.netherrack.place": 983, + "minecraft:block.wet_sponge.step": 1529, + "minecraft:state.generic.big_fall": 571, + "minecraft:item.honeycomb.wax_on": 704, + "minecraft:block.ladder.step": 767, + "minecraft:block.trial_spawner.spawn_item": 680, + "minecraft:block.tuff.break": 1400, + "minecraft:state.leash_knot.place": 779, + "minecraft:state.player.teleport": 1119, + "minecraft:state.ravager.hurt": 1157, + "minecraft:item.goat_horn.sound.6": 712, + "minecraft:item.trident.riptide_1": 1387, + "minecraft:ambient.warped_forest.mood": 22, + "minecraft:block.nether_sprouts.step": 957, + "minecraft:block.nether_wood.fall": 926, + "minecraft:block.note_block.pling": 994, + "minecraft:block.vine.place": 1481, + "minecraft:state.elder_guardian.hurt_land": 463, + "minecraft:state.hostile.big_fall": 727, + "minecraft:state.parrot.hurt": 1029, + "minecraft:item.wolf_armor.damage": 1550, + "minecraft:music.nether.warped_forest": 910, + "minecraft:block.amethyst_block.hit": 32, + "minecraft:block.bamboo.break": 105, + "minecraft:block.bamboo.place": 108, + "minecraft:block.dispenser.launch": 410, + "minecraft:block.small_dripleaf.step": 1285, + "minecraft:block.vault.ambient": 1437, + "minecraft:state.horse.death": 718, + "minecraft:item.ink_sac.use": 745, + "minecraft:block.hanging_sign.place": 657, + "minecraft:block.note_block.imitate.zombie": 1002, + "minecraft:block.sculk.place": 1200, + "minecraft:state.parrot.imitate.skeleton": 1052, + "minecraft:state.pig.step": 1076, + "minecraft:state.piglin_brute.step": 1091, + "minecraft:state.slime.jump_small": 1313, + "minecraft:state.zombie.infect": 1596, + "minecraft:block.beacon.deactivate": 142, + "minecraft:block.respawn_anchor.deplete": 1174, + "minecraft:block.stem.break": 946, + "minecraft:block.tripwire.click_off": 1393, + "minecraft:state.bogged.ambient": 169, + "minecraft:state.chicken.egg": 305, + "minecraft:state.villager.work_shepherd": 1471, + "minecraft:block.note_block.bit": 1000, + "minecraft:block.note_block.imitate.creeper": 1004, + "minecraft:state.firework_rocket.blast_far": 506, + "minecraft:state.ghast.scream": 585, + "minecraft:state.glow_squid.ambient": 604, + "minecraft:state.husk.step": 737, + "minecraft:state.salmon.death": 1182, + "minecraft:state.silverfish.ambient": 1251, + "minecraft:state.spider.ambient": 1343, + "minecraft:block.copper_trapdoor.close": 358, + "minecraft:state.elder_guardian.ambient_land": 457, + "minecraft:state.firework_rocket.large_blast_far": 508, + "minecraft:state.parrot.imitate.breeze": 1032, + "minecraft:music_disc.11": 871, + "minecraft:music_disc.relic": 885, + "minecraft:ui.toast.in": 1434, + "minecraft:ambient.crimson_forest.mood": 13, + "minecraft:block.beehive.enter": 151, + "minecraft:state.bogged.death": 170, + "minecraft:state.minecart.riding": 825, + "minecraft:state.piglin_brute.death": 1089, + "minecraft:block.stem.place": 948, + "minecraft:block.stone.place": 1366, + "minecraft:state.cat.ambient": 250, + "minecraft:state.parrot.fly": 1028, + "minecraft:item.shield.break": 1232, + "minecraft:music_disc.precipice": 888, + "minecraft:block.frogspawn.hatch": 554, + "minecraft:state.camel.hurt": 236, + "minecraft:state.skeleton_horse.gallop_water": 1263, + "minecraft:state.sniffer.eat": 1318, + "minecraft:state.warden.hurt": 1502, + "minecraft:block.moss.fall": 842, + "minecraft:block.netherite_block.fall": 980, + "minecraft:state.chicken.step": 307, + "minecraft:state.fox.sleep": 532, + "minecraft:item.crossbow.quick_charge_3": 383, + "minecraft:block.frogspawn.step": 551, + "minecraft:block.lantern.step": 772, + "minecraft:block.mangrove_roots.break": 809, + "minecraft:block.mud.hit": 848, + "minecraft:state.cat.hiss": 254, + "minecraft:state.ender_eye.death": 475, + "minecraft:state.endermite.hurt": 485, + "minecraft:state.goat.milk": 613, + "minecraft:block.bamboo_sapling.break": 110, + "minecraft:block.nether_ore.hit": 1168, + "minecraft:state.elder_guardian.ambient": 456, + "minecraft:item.bottle.fill": 184, + "minecraft:state.donkey.angry": 422, + "minecraft:state.zombie.destroy_egg": 1591, + "minecraft:block.bone_block.place": 177, + "minecraft:block.nether_wood_pressure_plate.click_on": 937, + "minecraft:state.warden.sonic_charge": 1511, + "minecraft:block.chorus_flower.grow": 318, + "minecraft:block.lodestone.place": 796, + "minecraft:block.nether_sprouts.hit": 959, + "minecraft:block.slime_block.step": 1278, + "minecraft:block.sponge.break": 1349, + "minecraft:state.allay.item_thrown": 6, + "minecraft:state.armadillo.step": 58, + "minecraft:state.zombie_villager.ambient": 1602, + "minecraft:item.hoe.till": 689, + "minecraft:block.copper_bulb.break": 339, + "minecraft:state.cat.purr": 257, + "minecraft:state.cat.purreow": 258, + "minecraft:state.slime.squish_small": 1314, + "minecraft:state.strider.saddle": 1310, + "minecraft:state.turtle.egg_hatch": 1420, + "minecraft:block.copper_door.open": 352, + "minecraft:block.wool.break": 1574, + "minecraft:state.polar_bear.death": 1122, + "minecraft:block.bamboo_sapling.place": 112, + "minecraft:block.wooden_door.open": 1562, + "minecraft:state.magma_cube.jump": 806, + "minecraft:state.parrot.imitate.warden": 1058, + "minecraft:item.armor.equip_generic": 70, + "minecraft:item.mace.smash_ground_heavy": 802, + "minecraft:block.ancient_debris.step": 42, + "minecraft:block.big_dripleaf.step": 161, + "minecraft:block.cherry_wood_trapdoor.close": 292, + "minecraft:block.honey_block.place": 701, + "minecraft:block.metal.place": 819, + "minecraft:block.pink_petals.hit": 838, + "minecraft:state.cow.step": 369, + "minecraft:state.donkey.jump": 427, + "minecraft:state.ender_dragon.growl": 472, + "minecraft:state.fox.teleport": 535, + "minecraft:state.parrot.imitate.silverfish": 1051, + "minecraft:ambient.crimson_forest.loop": 12, + "minecraft:block.muddy_mangrove_roots.fall": 857, + "minecraft:block.note_block.iron_xylophone": 997, + "minecraft:state.breeze.shoot": 191, + "minecraft:state.dragon_fireball.explode": 470, + "minecraft:state.pig.ambient": 1072, + "minecraft:block.nether_gold_ore.place": 1164, + "minecraft:block.rooted_dirt.step": 1180, + "minecraft:block.sculk_vein.step": 1225, + "minecraft:state.illusioner.prepare_mirror": 744, + "minecraft:item.bucket.empty_lava": 213, + "minecraft:item.crossbow.loading_start": 380, + "minecraft:item.totem.use": 1383, + "minecraft:block.dripstone_block.step": 429, + "minecraft:block.ender_chest.open": 467, + "minecraft:block.nether_bricks.hit": 921, + "minecraft:state.parrot.imitate.wither": 1060, + "minecraft:block.iron_trapdoor.open": 755, + "minecraft:block.stone_pressure_plate.click_on": 1368, + "minecraft:state.zombie_villager.death": 1605, + "minecraft:block.ancient_debris.hit": 44, + "minecraft:block.azalea.step": 99, + "minecraft:block.big_dripleaf.hit": 159, + "minecraft:block.bubble_column.bubble_pop": 205, + "minecraft:block.chain.place": 268, + "minecraft:block.chiseled_bookshelf.place": 316, + "minecraft:state.cat.death": 252, + "minecraft:state.glow_item_frame.remove_item": 602, + "minecraft:state.painting.place": 1013, + "minecraft:item.trident.thunder": 1391, + "minecraft:block.glass.fall": 594, + "minecraft:block.nether_bricks.step": 919, + "minecraft:state.polar_bear.hurt": 1123, + "minecraft:block.amethyst_cluster.hit": 38, + "minecraft:block.crafter.craft": 370, + "minecraft:block.shroomlight.fall": 1237, + "minecraft:state.breeze.whirl": 197, + "minecraft:state.iron_golem.damage": 749, + "minecraft:state.piglin_brute.hurt": 1090, + "minecraft:state.skeleton.step": 1268, + "minecraft:block.gravel.step": 637, + "minecraft:block.ladder.place": 766, + "minecraft:state.armadillo.death": 59, + "minecraft:state.wind_charge.throw": 1531, + "minecraft:music.overworld.dripstone_caves": 896, + "minecraft:block.sand.break": 1185, + "minecraft:state.goat.ram_impact": 615, + "minecraft:state.zombified_piglin.death": 1599, + "minecraft:block.amethyst_block.fall": 31, + "minecraft:block.bamboo_wood_hanging_sign.step": 668, + "minecraft:block.froglight.place": 549, + "minecraft:block.wooden_trapdoor.open": 1564, + "minecraft:state.dolphin.play": 418, + "minecraft:state.generic.explode": 576, + "minecraft:state.turtle.egg_crack": 1419, + "minecraft:state.wolf.step": 1559, + "minecraft:block.deepslate.step": 402, + "minecraft:block.metal_pressure_plate.click_off": 820, + "minecraft:state.horse.armor": 716, + "minecraft:state.magma_cube.squish": 807, + "minecraft:block.chest.close": 300, + "minecraft:block.small_dripleaf.place": 1284, + "minecraft:state.llama.ambient": 784, + "minecraft:music_disc.5": 870, + "minecraft:block.large_amethyst_bud.break": 773, + "minecraft:state.ender_pearl.throw": 487, + "minecraft:state.horse.jump": 722, + "minecraft:state.mule.death": 864, + "minecraft:music_disc.stal": 880, + "minecraft:block.big_dripleaf.fall": 158, + "minecraft:block.deepslate_tiles.fall": 404, + "minecraft:block.hanging_sign.step": 653, + "minecraft:block.nether_gold_ore.fall": 1162, + "minecraft:block.roots.hit": 568, + "minecraft:state.horse.saddle": 724, + "minecraft:state.hostile.splash": 731, + "minecraft:state.ravager.ambient": 1153, + "minecraft:state.warden.listening": 1503, + "minecraft:ambient.underwater.loop.additions": 26, + "minecraft:block.note_block.banjo": 1001, + "minecraft:block.wart_block.place": 973, + "minecraft:state.armadillo.unroll_start": 65, + "minecraft:state.axolotl.swim": 94, + "minecraft:state.fox.aggro": 525, + "minecraft:state.parrot.imitate.wither_skeleton": 1061, + "minecraft:state.player.big_fall": 1105, + "minecraft:state.zombie_villager.cure": 1604, + "minecraft:item.trident.throw": 1390, + "minecraft:block.bamboo_wood_button.click_off": 122, + "minecraft:block.frogspawn.hit": 555, + "minecraft:state.breeze.land": 193, + "minecraft:state.evoker.hurt": 496, + "minecraft:state.mooshroom.convert": 826, + "minecraft:state.wither_skeleton.death": 1544, + "minecraft:item.trident.hit_ground": 1385, + "minecraft:block.chest.locked": 301, + "minecraft:block.conduit.ambient": 335, + "minecraft:state.goat.screaming.milk": 623, + "minecraft:state.snow_golem.ambient": 1335, + "minecraft:state.warden.heartbeat": 1501, + "minecraft:item.bundle.drop_contents": 222, + "minecraft:music.overworld.desert": 912, + "minecraft:block.bone_block.step": 178, + "minecraft:state.bee.death": 144, + "minecraft:state.camel.dash": 232, + "minecraft:state.husk.ambient": 733, + "minecraft:state.wither.ambient": 1538, + "minecraft:state.drowned.hurt_water": 450, + "minecraft:state.enderman.death": 478, + "minecraft:state.piglin_brute.ambient": 1087, + "minecraft:block.campfire.crackle": 242, + "minecraft:block.chain.hit": 267, + "minecraft:block.stone.break": 1361, + "minecraft:state.wandering_trader.no": 1490, + "minecraft:block.grass.fall": 629, + "minecraft:block.stone.fall": 1364, + "minecraft:block.trial_spawner.place": 675, + "minecraft:state.elder_guardian.flop": 461, + "minecraft:music.under_water": 917, + "minecraft:block.froglight.fall": 547, + "minecraft:state.camel.death": 234, + "minecraft:state.dolphin.splash": 419, + "minecraft:state.panda.bite": 1024, + "minecraft:state.parrot.step": 1065, + "minecraft:state.pillager.hurt": 1096, + "minecraft:state.tadpole.flop": 1378, + "minecraft:state.villager.yes": 1460, + "minecraft:ambient.underwater.exit": 24, + "minecraft:block.cherry_sapling.hit": 277, + "minecraft:block.tripwire.attach": 1392, + "minecraft:block.azalea_leaves.hit": 102, + "minecraft:block.fire.extinguish": 514, + "minecraft:block.honey_block.step": 703, + "minecraft:block.sand.fall": 1186, + "minecraft:state.llama.eat": 788, + "minecraft:state.parrot.imitate.drowned": 1034, + "minecraft:state.zombie.ambient": 1585, + "minecraft:item.brush.brushing.gravel": 202, + "minecraft:block.cake.add_candle": 225, + "minecraft:block.composter.fill_success": 332, + "minecraft:block.conduit.deactivate": 338, + "minecraft:block.nether_gold_ore.hit": 1163, + "minecraft:block.nether_wood_fence_gate.close": 938, + "minecraft:block.netherite_block.place": 978, + "minecraft:block.packed_mud.fall": 942, + "minecraft:block.wood.break": 1569, + "minecraft:state.cat.eat": 253, + "minecraft:state.elder_guardian.death_land": 460, + "minecraft:state.glow_item_frame.rotate_item": 603, + "minecraft:state.slime.hurt": 1271, + "minecraft:block.candle.ambient": 243, + "minecraft:block.cherry_wood_trapdoor.open": 293, + "minecraft:block.spore_blossom.step": 1301, + "minecraft:block.suspicious_sand.break": 536, + "minecraft:state.evoker.prepare_wololo": 499, + "minecraft:state.shulker.open": 1248, + "minecraft:state.villager.no": 1458, + "minecraft:block.bamboo_wood_trapdoor.close": 120, + "minecraft:block.big_dripleaf.place": 160, + "minecraft:block.cherry_leaves.place": 283, + "minecraft:block.hanging_sign.break": 654, + "minecraft:block.heavy_core.step": 662, + "minecraft:block.ladder.fall": 764, + "minecraft:block.nether_wood_pressure_plate.click_off": 936, + "minecraft:block.sculk_catalyst.place": 1206, + "minecraft:block.sniffer_egg.hatch": 1331, + "minecraft:state.piglin.angry": 1079, + "minecraft:block.cherry_wood.break": 270, + "minecraft:block.note_block.hat": 993, + "minecraft:block.sculk_vein.break": 1221, + "minecraft:block.stone.step": 1369, + "minecraft:state.camel.dash_ready": 233, + "minecraft:state.magma_cube.death_small": 793, + "minecraft:state.parrot.imitate.ghast": 1039, + "minecraft:state.vex.hurt": 1453, + "minecraft:block.chiseled_bookshelf.pickup.enchanted": 315, + "minecraft:block.weeping_vines.step": 967, + "minecraft:state.cod.flop": 327, + "minecraft:state.phantom.death": 1068, + "minecraft:state.wandering_trader.death": 1485, + "minecraft:block.bell.use": 155, + "minecraft:block.copper_bulb.turn_on": 344, + "minecraft:state.cat.beg_for_food": 255, + "minecraft:block.big_dripleaf.tilt_down": 443, + "minecraft:block.cave_vines.hit": 261, + "minecraft:block.mud_bricks.step": 855, + "minecraft:block.sculk.hit": 1199, + "minecraft:block.wart_block.break": 971, + "minecraft:block.sculk_catalyst.hit": 1205, + "minecraft:block.suspicious_gravel.place": 543, + "minecraft:state.donkey.ambient": 421, + "minecraft:state.guardian.hurt_land": 647, + "minecraft:state.panda.worried_ambient": 1022, + "minecraft:block.bamboo_wood_door.close": 118, + "minecraft:block.chiseled_bookshelf.break": 308, + "minecraft:state.horse.step_wood": 726, + "minecraft:music_disc.creator_music_box": 887, + "minecraft:block.cobweb.break": 320, + "minecraft:block.lava.extinguish": 776, + "minecraft:state.guardian.attack": 642, + "minecraft:block.gravel.hit": 635, + "minecraft:block.sculk_shrieker.shriek": 1219, + "minecraft:state.camel.ambient": 231, + "minecraft:state.evoker_fangs.attack": 495, + "minecraft:state.player.swim": 1118, + "minecraft:state.turtle.swim": 1426, + "minecraft:item.bone_meal.use": 179, + "minecraft:state.armadillo.scute_drop": 62, + "minecraft:state.cow.milk": 368, + "minecraft:state.silverfish.step": 1254, + "minecraft:state.snow_golem.death": 1336, + "minecraft:state.breeze.slide": 194, + "minecraft:state.camel.stand": 239, + "minecraft:state.drowned.step": 452, + "minecraft:state.frog.eat": 559, + "minecraft:state.salmon.flop": 1183, + "minecraft:state.villager.work_leatherworker": 1468, + "minecraft:state.zoglin.hurt": 1583, + "minecraft:block.bamboo_wood_fence_gate.open": 127, + "minecraft:block.deepslate_bricks.fall": 394, + "minecraft:block.mud_bricks.break": 851, + "minecraft:block.muddy_mangrove_roots.step": 860, + "minecraft:block.soul_soil.fall": 1295, + "minecraft:state.guardian.ambient_land": 641, + "minecraft:state.piglin_brute.converted_to_zombified": 1092, + "minecraft:block.bamboo_wood_pressure_plate.click_off": 124, + "minecraft:block.calcite.hit": 229, + "minecraft:block.decorated_pot.insert": 388, + "minecraft:block.polished_tuff.step": 1414, + "minecraft:state.drowned.hurt": 449, + "minecraft:state.ghast.ambient": 582, + "minecraft:state.parrot.imitate.piglin_brute": 1047, + "minecraft:item.brush.brushing.sand": 201, + "minecraft:block.beacon.ambient": 141, + "minecraft:block.sand.place": 1188, + "minecraft:state.ravager.stunned": 1159, + "minecraft:block.nether_wood.place": 928, + "minecraft:state.generic.extinguish_fire": 577, + "minecraft:state.sheep.shear": 1229, + "minecraft:block.basalt.fall": 134, + "minecraft:block.cave_vines.place": 262, + "minecraft:block.nether_wood_door.open": 931, + "minecraft:state.item_frame.add_item": 756, + "minecraft:state.item_frame.remove_item": 759, + "minecraft:state.sniffer.death": 1321, + "minecraft:state.zombie_villager.converted": 1603, + "minecraft:item.mace.smash_ground": 801, + "minecraft:block.bamboo_wood_fence_gate.close": 126, + "minecraft:block.netherrack.fall": 985, + "minecraft:block.pointed_dripstone.land": 438, + "minecraft:block.sculk_sensor.place": 1213, + "minecraft:state.zoglin.step": 1584, + "minecraft:item.dye.use": 454, + "minecraft:block.deepslate_bricks.break": 393, + "minecraft:block.fungus.step": 962, + "minecraft:block.lantern.break": 768, + "minecraft:block.note_block.guitar": 991, + "minecraft:block.tuff_bricks.hit": 1407, + "minecraft:state.camel.step": 240, + "minecraft:state.cow.ambient": 365, + "minecraft:state.drowned.ambient": 445, + "minecraft:music.overworld.jungle": 914, + "minecraft:block.bamboo.step": 109, + "minecraft:block.polished_tuff.fall": 1411, + "minecraft:state.generic.eat": 575, + "minecraft:state.llama.spit": 790, + "minecraft:state.mule.hurt": 866, + "minecraft:state.parrot.imitate.evoker": 1038, + "minecraft:state.zombie_horse.death": 1593, + "minecraft:block.bamboo_wood.place": 116, + "minecraft:block.nether_wood.hit": 927, + "minecraft:block.nether_wood_hanging_sign.step": 663, + "minecraft:block.netherrack.break": 981, + "minecraft:state.allay.hurt": 3, + "minecraft:state.parrot.imitate.hoglin": 1041, + "minecraft:block.soul_soil.step": 1292, + "minecraft:state.enderman.ambient": 477, + "minecraft:state.goat.screaming.ram_impact": 625, + "minecraft:state.parrot.imitate.zoglin": 1062, + "minecraft:state.spider.death": 1344, + "minecraft:state.vindicator.death": 1476, + "minecraft:ambient.underwater.loop": 25, + "minecraft:block.slime_block.fall": 1275, + "minecraft:block.wool.place": 1577, + "minecraft:state.blaze.death": 164, + "minecraft:state.ghast.warn": 587, + "minecraft:state.hoglin.angry": 691, + "minecraft:state.wolf.growl": 1554, + "minecraft:particle.soul_escape": 1296, + "minecraft:block.vault.step": 1449, + "minecraft:state.generic.death": 573, + "minecraft:state.mule.chest": 863, + "minecraft:state.frog.tongue": 564, + "minecraft:ui.loom.take_result": 1429, + "minecraft:block.lava.ambient": 775, + "minecraft:block.lily_pad.place": 1483, + "minecraft:block.mud.break": 846, + "minecraft:state.armadillo.hurt": 55, + "minecraft:state.bee.pollinate": 149, + "minecraft:state.player.breath": 1106, + "minecraft:ambient.nether_wastes.loop": 15, + "minecraft:block.vault.place": 1448, + "minecraft:state.sniffer.hurt": 1320, + "minecraft:state.tadpole.death": 1377, + "minecraft:state.witch.hurt": 1536, + "minecraft:event.mob_effect.raid_omen": 1610, + "minecraft:item.brush.brushing.sand.complete": 203, + "minecraft:block.cherry_wood.fall": 271, + "minecraft:block.cobweb.step": 321, + "minecraft:block.copper_door.close": 351, + "minecraft:block.tuff.fall": 1404, + "minecraft:state.axolotl.hurt": 90, + "minecraft:state.mooshroom.shear": 830, + "minecraft:item.bundle.remove_one": 224, + "minecraft:block.cherry_wood_hanging_sign.break": 286, + "minecraft:block.conduit.activate": 334, + "minecraft:state.arrow.hit": 82, + "minecraft:state.donkey.hurt": 426, + "minecraft:ambient.warped_forest.additions": 20, + "minecraft:state.goat.screaming.ambient": 618, + "minecraft:state.parrot.imitate.piglin": 1046, + "minecraft:block.weeping_vines.break": 966, + "minecraft:state.fish.swim": 515, + "minecraft:state.fishing_bobber.retrieve": 516, + "minecraft:state.phantom.swoop": 1071, + "minecraft:block.stone_button.click_on": 1363, + "minecraft:block.trial_spawner.break": 673, + "minecraft:state.boat.paddle_land": 167, + "minecraft:state.goat.screaming.eat": 620, + "minecraft:state.wandering_trader.ambient": 1484, + "minecraft:state.zombified_piglin.hurt": 1600, + "minecraft:block.cherry_leaves.step": 284, + "minecraft:block.vault.activate": 1436, + "minecraft:state.drowned.shoot": 451, + "minecraft:state.tadpole.hurt": 1380, + "minecraft:block.bamboo_wood_hanging_sign.break": 669, + "minecraft:block.copper.fall": 350, + "minecraft:block.pointed_dripstone.drip_lava": 439, + "minecraft:block.tuff.hit": 1403, + "minecraft:state.frog.step": 563, + "minecraft:state.magma_cube.squish_small": 808, + "minecraft:block.cherry_leaves.break": 280, + "minecraft:block.moss.place": 844, + "minecraft:block.scaffolding.hit": 1192, + "minecraft:state.boat.paddle_water": 168, + "minecraft:state.mule.ambient": 861, + "minecraft:state.parrot.imitate.shulker": 1050, + "minecraft:state.piglin.jealous": 1082, + "minecraft:state.villager.work_farmer": 1465, + "minecraft:item.axe.strip": 85, + "minecraft:block.end_portal_frame.fill": 489, + "minecraft:block.trial_spawner.spawn_item_begin": 681, + "minecraft:state.armadillo.peek": 64, + "minecraft:block.cherry_wood_hanging_sign.step": 285, + "minecraft:block.frogspawn.place": 556, + "minecraft:block.glass.break": 593, + "minecraft:block.powder_snow.step": 1138, + "minecraft:block.wooden_pressure_plate.click_on": 1568, + "minecraft:state.armor_stand.break": 78, + "minecraft:state.donkey.chest": 423, + "minecraft:state.illusioner.hurt": 741, + "minecraft:state.llama.death": 787, + "minecraft:state.shulker.hurt_closed": 1247, + "minecraft:block.trial_spawner.open_shutter": 686, + "minecraft:block.weeping_vines.place": 968, + "minecraft:state.experience_bottle.throw": 500, + "minecraft:state.rabbit.hurt": 1150, + "minecraft:state.silverfish.hurt": 1253, + "minecraft:state.warden.nearby_close": 1505, + "minecraft:block.portal.ambient": 1131, + "minecraft:block.suspicious_gravel.fall": 545, + "minecraft:block.sweet_berry_bush.break": 1374, + "minecraft:block.vault.open_shutter": 1447, + "minecraft:state.chicken.hurt": 306, + "minecraft:state.slime.hurt_small": 1312, + "minecraft:state.zombified_piglin.angry": 1598, + "minecraft:weather.rain": 1517, + "minecraft:block.copper_bulb.turn_off": 345, + "minecraft:block.hanging_roots.place": 651, + "minecraft:block.moss.step": 845, + "minecraft:block.mud.fall": 847, + "minecraft:block.powder_snow.break": 1134, + "minecraft:block.sculk.break": 1197, + "minecraft:block.tuff_bricks.place": 1408, + "minecraft:state.goat.death": 609, + "minecraft:state.polar_bear.step": 1124, + "minecraft:item.armor.equip_leather": 73, + "minecraft:ui.button.click": 1427, + "minecraft:block.copper_bulb.step": 340, + "minecraft:block.gilded_blackstone.break": 588, + "minecraft:block.vault.insert_item_fail": 1446, + "minecraft:state.sheep.step": 1230, + "minecraft:state.tadpole.grow_up": 1379, + "minecraft:state.wither_skeleton.step": 1546, + "minecraft:block.polished_tuff.place": 1413, + "minecraft:block.suspicious_sand.step": 537, + "minecraft:state.player.burp": 1107, + "minecraft:state.player.death": 1108, + "minecraft:state.horse.eat": 719, + "minecraft:state.horse.hurt": 721, + "minecraft:state.polar_bear.ambient_baby": 1121, + "minecraft:state.warden.listening_angry": 1504, + "minecraft:block.azalea_leaves.break": 100, + "minecraft:block.cherry_wood_pressure_plate.click_off": 296, + "minecraft:block.composter.fill": 331, + "minecraft:block.honey_block.hit": 700, + "minecraft:block.piston.contract": 1097, + "minecraft:state.frog.hurt": 560, + "minecraft:block.flowering_azalea.hit": 522, + "minecraft:block.sign.waxed_interact_fail": 1515, + "minecraft:state.wolf.hurt": 1556, + "minecraft:block.cherry_leaves.hit": 282, + "minecraft:block.deepslate_bricks.hit": 395, + "minecraft:block.sculk.charge": 1196, + "minecraft:ui.loom.select_pattern": 1428, + "minecraft:ambient.cave": 7, + "minecraft:block.rooted_dirt.place": 1179, + "minecraft:block.spore_blossom.break": 1297, + "minecraft:block.spore_blossom.fall": 1298, + "minecraft:block.deepslate_tiles.hit": 405, + "minecraft:block.sniffer_egg.crack": 1330, + "minecraft:state.generic.swim": 581, + "minecraft:state.squid.hurt": 1359, + "minecraft:state.villager.trade": 1459, + "minecraft:state.villager.work_cartographer": 1463, + "minecraft:block.cobweb.hit": 323, + "minecraft:block.conduit.attack.target": 337, + "minecraft:block.nether_wood_button.click_on": 935, + "minecraft:block.pointed_dripstone.drip_lava_into_cauldron": 441, + "minecraft:state.slime.squish": 1273, + "minecraft:event.raid.horn": 1152, + "minecraft:item.trident.riptide_2": 1388, + "minecraft:block.netherite_block.hit": 979, + "minecraft:block.sculk_vein.hit": 1223, + "minecraft:block.wool.hit": 1576, + "minecraft:state.snowball.throw": 1332, + "minecraft:block.medium_amethyst_bud.break": 814, + "minecraft:block.scaffolding.break": 1190, + "minecraft:state.chicken.ambient": 303, + "minecraft:state.cod.death": 326, + "minecraft:state.parrot.imitate.vex": 1056, + "minecraft:state.warden.emerge": 1500, + "minecraft:item.brush.brushing.generic": 200, + "minecraft:block.beacon.power_select": 143, + "minecraft:block.decorated_pot.break": 385, + "minecraft:block.netherrack.hit": 984, + "minecraft:block.note_block.didgeridoo": 999, + "minecraft:block.suspicious_gravel.break": 541, + "minecraft:state.player.splash": 1116, + "minecraft:state.turtle.egg_break": 1418, + "minecraft:state.zombie_villager.step": 1607, + "minecraft:block.basalt.hit": 133, + "minecraft:block.muddy_mangrove_roots.hit": 858, + "minecraft:block.vault.deactivate": 1440, + "minecraft:enchant.thorns.hit": 1381, + "minecraft:state.puffer_fish.ambient": 1139, + "minecraft:state.rabbit.attack": 1148, + "minecraft:state.tropical_fish.hurt": 1399, + "minecraft:block.fungus.place": 963, + "minecraft:block.metal_pressure_plate.click_on": 821, + "minecraft:state.dolphin.swim": 420, + "minecraft:block.bell.resonate": 156, + "minecraft:block.cave_vines.step": 263, + "minecraft:block.lodestone.fall": 798, + "minecraft:block.wool.fall": 1575, + "minecraft:state.ocelot.death": 1010, + "minecraft:state.panda.cant_breed": 1020, + "minecraft:state.skeleton.hurt": 1266, + "minecraft:item.armor.equip_diamond": 68, + "minecraft:block.chiseled_bookshelf.insert.enchanted": 312, + "minecraft:block.wet_sponge.fall": 1526, + "minecraft:state.goat.screaming.prepare_ram": 624, + "minecraft:state.skeleton_horse.hurt": 1260, + "minecraft:state.snow_golem.shoot": 1338, + "minecraft:item.wolf_armor.repair": 1551, + "minecraft:music_disc.blocks": 873, + "minecraft:block.gilded_blackstone.step": 592, + "minecraft:block.glass.place": 596, + "minecraft:block.note_block.chime": 989, + "minecraft:state.fox.eat": 529, + "minecraft:state.mule.eat": 865, + "minecraft:item.wolf_armor.break": 1548, + "minecraft:ui.toast.out": 1435, + "minecraft:ambient.underwater.loop.additions.ultra_rare": 28, + "minecraft:block.anvil.land": 50, + "minecraft:block.nether_wood_hanging_sign.place": 667, + "minecraft:state.parrot.eat": 1027, + "minecraft:state.parrot.imitate.creeper": 1033, + "minecraft:state.wither_skeleton.hurt": 1545, + "minecraft:item.crossbow.loading_middle": 379, + "minecraft:music_disc.cat": 874, + "minecraft:block.pointed_dripstone.hit": 436, + "minecraft:state.blaze.shoot": 166, + "minecraft:state.ocelot.hurt": 1008, + "minecraft:state.rabbit.death": 1149, + "minecraft:state.sniffer.drop_seed": 1322, + "minecraft:state.witch.ambient": 1532, + "minecraft:event.mob_effect.bad_omen": 1608, + "minecraft:music_disc.strad": 881, + "minecraft:block.pointed_dripstone.step": 434, + "minecraft:state.ender_dragon.death": 469, + "minecraft:state.parrot.imitate.witch": 1059, + "minecraft:music.overworld.flower_forest": 911, + "minecraft:block.vine.step": 1482, + "minecraft:state.player.attack.weak": 1104, + "minecraft:item.shovel.flatten": 1238, + "minecraft:ambient.nether_wastes.mood": 16, + "minecraft:block.basalt.place": 132, + "minecraft:block.beehive.work": 154, + "minecraft:block.dispenser.fail": 409, + "minecraft:block.mud.place": 849, + "minecraft:block.polished_deepslate.step": 1130, + "minecraft:block.sculk_shrieker.step": 1220, + "minecraft:state.breeze.death": 195, + "minecraft:state.creeper.primed": 374, + "minecraft:state.drowned.death_water": 448, + "minecraft:state.glow_squid.death": 605, + "minecraft:state.painting.break": 1012, + "minecraft:state.piglin.admiring_item": 1077, + "minecraft:state.player.splash.high_speed": 1117, + "minecraft:state.vex.charge": 1451, + "minecraft:music_disc.creator": 886, + "minecraft:block.shroomlight.hit": 1236, + "minecraft:block.trial_spawner.close_shutter": 687, + "minecraft:state.sniffer.happy": 1328, + "minecraft:state.strider.retreat": 1304, + "minecraft:block.cherry_leaves.fall": 281, + "minecraft:block.end_gateway.spawn": 488, + "minecraft:state.armadillo.hurt_reduced": 56, + "minecraft:state.bat.ambient": 135, + "minecraft:state.endermite.step": 486, + "minecraft:state.illusioner.mirror_move": 742, + "minecraft:block.copper_grate.fall": 357, + "minecraft:block.nether_wood.step": 929, + "minecraft:block.polished_deepslate.break": 1126, + "minecraft:state.evoker.cast_spell": 492, + "minecraft:state.sheep.death": 1227, + "minecraft:state.zombie.hurt": 1595, + "minecraft:ambient.nether_wastes.additions": 14, + "minecraft:block.cherry_wood_hanging_sign.hit": 288, + "minecraft:block.soul_sand.step": 1287, + "minecraft:block.spore_blossom.hit": 1299, + "minecraft:block.wet_sponge.hit": 1527, + "minecraft:state.fox.ambient": 526, + "minecraft:state.phantom.hurt": 1070, + "minecraft:state.pillager.ambient": 1093, + "minecraft:state.zombie.converted_to_drowned": 1589, + "minecraft:item.crossbow.quick_charge_1": 381, + "minecraft:item.goat_horn.play": 617, + "minecraft:music.overworld.deep_dark": 895, + "minecraft:block.bone_block.hit": 176, + "minecraft:block.stem.step": 947, + "minecraft:state.armadillo.brush": 66, + "minecraft:state.cod.hurt": 328, + "minecraft:state.pillager.death": 1095, + "minecraft:block.blastfurnace.fire_crackle": 182, + "minecraft:block.chain.step": 269, + "minecraft:block.pumpkin.carve": 1146, + "minecraft:block.roots.fall": 569, + "minecraft:state.bogged.shear": 172, + "minecraft:state.ocelot.ambient": 1009, + "minecraft:state.panda.aggressive_ambient": 1021, + "minecraft:music.game": 891, + "minecraft:music.overworld.snowy_slopes": 907, + "minecraft:block.heavy_core.hit": 660, + "minecraft:block.ladder.hit": 765, + "minecraft:block.nether_wood_hanging_sign.hit": 666, + "minecraft:block.pink_petals.place": 839, + "minecraft:state.goat.prepare_ram": 614, + "minecraft:state.husk.converted_to_zombie": 734, + "minecraft:state.parrot.imitate.elder_guardian": 1035, + "minecraft:state.puffer_fish.sting": 1145, + "minecraft:state.turtle.death": 1416, + "minecraft:state.villager.work_fletcher": 1467, + "minecraft:state.warden.roar": 1508, + "minecraft:state.warden.sonic_boom": 1510, + "minecraft:state.warden.step": 1512, + "minecraft:block.smithing_table.use": 1315, + "minecraft:state.cat.hurt": 256, + "minecraft:state.horse.angry": 715, + "minecraft:state.pig.hurt": 1074, + "minecraft:block.beehive.exit": 152, + "minecraft:block.gilded_blackstone.hit": 590, + "minecraft:block.netherrack.step": 982, + "minecraft:block.pink_petals.step": 840, + "minecraft:state.bat.death": 136, + "minecraft:state.blaze.ambient": 162, + "minecraft:state.camel.eat": 235, + "minecraft:state.dolphin.eat": 415, + "minecraft:state.turtle.death_baby": 1417, + "minecraft:music.overworld.old_growth_taiga": 902, + "minecraft:block.anvil.step": 52, + "minecraft:block.cobweb.place": 322, + "minecraft:block.composter.ready": 333, + "minecraft:block.roots.step": 566, + "minecraft:block.small_dripleaf.hit": 1283, + "minecraft:block.wet_grass.break": 1519, + "minecraft:state.pillager.celebrate": 1094, + "minecraft:state.zombie.death": 1590, + "minecraft:item.chorus_fruit.teleport": 319, + "minecraft:item.wolf_armor.crack": 1549, + "minecraft:ambient.soul_sand_valley.additions": 17, + "minecraft:block.hanging_sign.hit": 656, + "minecraft:block.small_amethyst_bud.break": 1279, + "minecraft:state.armadillo.land": 61, + "minecraft:state.hostile.death": 728, + "minecraft:state.pig.death": 1073, + "minecraft:state.vindicator.celebrate": 1475, + "minecraft:block.azalea_leaves.fall": 101, + "minecraft:block.powder_snow.place": 1137, + "minecraft:block.sculk_vein.fall": 1222, + "minecraft:state.tropical_fish.flop": 1398, + "minecraft:item.axe.wax_off": 87, + "minecraft:item.crossbow.hit": 377, + "minecraft:block.honey_block.break": 698, + "minecraft:block.water.ambient": 1516, + "minecraft:state.armadillo.ambient": 57, + "minecraft:state.horse.land": 723, + "minecraft:state.parrot.imitate.magma_cube": 1044, + "minecraft:state.magma_cube.death": 803, + "minecraft:state.shulker_bullet.hurt": 1243, + "minecraft:block.deepslate.place": 401, + "minecraft:block.fence_gate.open": 503, + "minecraft:block.flowering_azalea.break": 520, + "minecraft:block.froglight.hit": 548, + "minecraft:block.vault.insert_item": 1445, + "minecraft:music.end": 890, + "minecraft:block.dripstone_block.place": 430, + "minecraft:block.nylium.break": 951, + "minecraft:block.sculk.spread": 1195, + "minecraft:state.firework_rocket.blast": 505, + "minecraft:state.item.break": 761, + "minecraft:state.phantom.bite": 1067, + "minecraft:block.deepslate.fall": 399, + "minecraft:block.respawn_anchor.charge": 1173, + "minecraft:state.panda.ambient": 1016, + "minecraft:item.spyglass.use": 1355, + "minecraft:music.overworld.frozen_peaks": 906, + "minecraft:block.moss_carpet.step": 835, + "minecraft:block.pointed_dripstone.break": 433, + "minecraft:item.crop.plant": 376, + "minecraft:block.dripstone_block.hit": 431, + "minecraft:block.honey_block.fall": 699, + "minecraft:state.arrow.shoot": 84, + "minecraft:state.experience_orb.pickup": 501, + "minecraft:state.goat.screaming.horn_break": 626, + "minecraft:block.candle.extinguish": 245, + "minecraft:block.wart_block.hit": 974, + "minecraft:state.guardian.death_land": 644, + "minecraft:state.panda.step": 1019, + "minecraft:state.parrot.death": 1026, + "minecraft:state.piglin.ambient": 1078, + "minecraft:state.wind_charge.wind_burst": 1530, + "minecraft:item.bucket.fill_axolotl": 217, + "minecraft:item.lodestone_compass.lock": 799, + "minecraft:music.credits": 869, + "minecraft:music.overworld.bamboo_jungle": 916, + "minecraft:block.azalea.break": 95, + "minecraft:block.barrel.open": 129, + "minecraft:block.chiseled_bookshelf.hit": 310, + "minecraft:block.sponge.hit": 1351, + "minecraft:block.wool.step": 1578, + "minecraft:state.shulker_bullet.hit": 1242, }, -} \ No newline at end of file +} diff --git a/server/server.go b/server/server.go index 98f9b3c7..8bf83d22 100644 --- a/server/server.go +++ b/server/server.go @@ -1,7 +1,11 @@ package server import ( + "bytes" "fmt" + "github.com/zeppelinmc/zeppelin/properties" + "github.com/zeppelinmc/zeppelin/server/player" + "image/png" "os" "runtime" "slices" @@ -9,14 +13,10 @@ import ( nnet "net" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/configuration" "github.com/zeppelinmc/zeppelin/protocol/net/packet/status" - "github.com/zeppelinmc/zeppelin/protocol/properties" "github.com/zeppelinmc/zeppelin/protocol/text" "github.com/zeppelinmc/zeppelin/server/command" - "github.com/zeppelinmc/zeppelin/server/player" - "github.com/zeppelinmc/zeppelin/server/session/std" - _ "github.com/zeppelinmc/zeppelin/server/session/std/handler" + "github.com/zeppelinmc/zeppelin/server/player/state" "github.com/zeppelinmc/zeppelin/server/tick" "github.com/zeppelinmc/zeppelin/server/world" @@ -47,15 +47,27 @@ func New(cfg properties.ServerProperties, world *world.World) (*Server, error) { listener, err := lcfg.New() server := &Server{ - listener: listener, - cfg: cfg, - World: world, - Players: player.NewPlayerManager(), - stopLoop: make(chan struct{}), + listener: listener, + cfg: cfg, + World: world, + Players: state.NewPlayerEntityManager(), + stopLoop: make(chan struct{}), + playerList: player.NewPlayerList(0), + } + server.icon, err = os.ReadFile("server-icon.png") + if err == nil { + img, err := png.Decode(bytes.NewReader(server.icon)) + if err != nil { + log.Warn("Server icon must be a 64x64 image in the PNG format") + } + b := img.Bounds() + if b.Dx() != 64 || b.Dy() != 64 { + log.Warn("Server icon must be a 64x64 image in the PNG format") + } } - server.icon, _ = os.ReadFile("server-icon.png") - server.Console = &Console{Server: server} - server.World.Broadcast.AddDummy(server.Console) + + //server.Console = &Console{Server: server} + //server.World.Broadcast.AddDummy(server.Console) server.listener.SetStatusProvider(server.provideStatus) if server.cfg.EnforceSecureProfile && !server.cfg.OnlineMode { @@ -70,7 +82,7 @@ func New(cfg properties.ServerProperties, world *world.World) (*Server, error) { } log.Infolnf("Network compression threshold is %d (%s)", cfg.NetworkCompressionThreshold, compstr) - server.createTicker() + //server.createTicker() return server, err } @@ -79,12 +91,13 @@ type Server struct { listener *net.Listener TickManager *tick.TickManager + playerList player.PlayerList + timeStart time.Time World *world.World - Console *Console - icon []byte + icon []byte CommandManager *command.Manager onConnectionIntercept func(conn *net.Conn, stop *bool) @@ -92,7 +105,7 @@ type Server struct { closed bool stopLoop chan struct{} - Players *player.PlayerManager + Players *state.PlayerEntityManager } func (srv *Server) setOnConnectionIntercept(i func(conn *net.Conn, stop *bool)) { @@ -104,21 +117,22 @@ func (srv *Server) Listener() *net.Listener { } func (srv *Server) provideStatus(*net.Conn) status.StatusResponseData { - count := srv.World.Broadcast.NumSession() + //count := srv.World.Broadcast.NumSession() + count := 0 max := srv.cfg.MaxPlayers if max == -1 { max = count + 1 } return status.StatusResponseData{ Version: status.StatusVersion{ - Name: "Zeppelin 1.21", + Name: "Zeppelin 1.21.3", Protocol: net.ProtocolVersion, }, Description: text.Unmarshal(srv.cfg.MOTD, srv.cfg.ChatFormatter.Rune()), Players: status.StatusPlayers{ Max: max, Online: count, - Sample: srv.World.Broadcast.Sample(), + //Sample: srv.World.Broadcast.Sample(), }, Favicon: srv.icon, EnforcesSecureChat: srv.cfg.EnforceSecureProfile, @@ -181,28 +195,27 @@ func (srv *Server) Start(ts time.Time) { func (srv *Server) handleNewConnection(conn *net.Conn) { log.Infolnf("%sPlayer attempting to connect: %s (%s)", log.FormatAddr(srv.cfg.LogIPs, conn.RemoteAddr()), conn.Username(), conn.UUID()) - if _, ok := srv.World.Broadcast.SessionByUsername(conn.Username()); ok { + /*if _, ok := srv.World.Broadcast.SessionByUsername(conn.Username()); ok { conn.WritePacket(&configuration.Disconnect{ Reason: text.TextComponent{Text: "You are already connected to the server from another session. Please disconnect then try again"}, }) return - } + }*/ playerData, err := srv.World.PlayerData(conn.UUID().String()) if err != nil { playerData = srv.World.NewPlayerData(conn.UUID()) } - player := srv.Players.New(playerData) - std.New(conn, player, srv.World, srv.World.Broadcast, srv.cfg, func() net.StatusProvider { - return srv.listener.StatusProvider() - }, srv.CommandManager, srv.TickManager).Configure() + state := srv.Players.New(playerData) + + go srv.playerList.New(conn, state, &srv.World.DimensionManager, &srv.World.Level).Login() } func (srv *Server) Stop() { log.InfolnClean("Stopping server") srv.closed = true srv.listener.Close() - srv.World.Broadcast.DisconnectAll(text.TextComponent{Text: "Server closed"}) + //srv.World.Broadcast.DisconnectAll(text.TextComponent{Text: "Server closed"}) log.InfolnClean("Saving player data") srv.Players.SaveAll() @@ -218,7 +231,7 @@ func (srv *Server) formatTimestart() string { } func (srv *Server) createTicker() { - srv.TickManager = tick.New(20, srv.World.Broadcast) + //srv.TickManager = tick.New(20, srv.World.Broadcast) srv.TickManager.AddNew(func() { srv.World.IncrementTime() }) diff --git a/server/session/broadcast.go b/server/session/broadcast.go deleted file mode 100644 index 0f81f5e7..00000000 --- a/server/session/broadcast.go +++ /dev/null @@ -1,689 +0,0 @@ -package session - -import ( - "fmt" - "math" - "strings" - "sync" - - "github.com/google/uuid" - "github.com/zeppelinmc/zeppelin/protocol/net" - "github.com/zeppelinmc/zeppelin/protocol/net/metadata" - "github.com/zeppelinmc/zeppelin/protocol/net/packet" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/status" - "github.com/zeppelinmc/zeppelin/protocol/properties" - "github.com/zeppelinmc/zeppelin/protocol/text" - "github.com/zeppelinmc/zeppelin/server/registry" - "github.com/zeppelinmc/zeppelin/server/world/block/pos" - "github.com/zeppelinmc/zeppelin/server/world/chunk" - "github.com/zeppelinmc/zeppelin/server/world/chunk/section" - "github.com/zeppelinmc/zeppelin/server/world/level/seed" - "github.com/zeppelinmc/zeppelin/util" - "github.com/zeppelinmc/zeppelin/util/log" -) - -type Broadcast struct { - sessions map[uuid.UUID]Session - // a dummy session is not included in the player list - dummies []DummySession - sessions_mu sync.RWMutex - - cfg properties.ServerProperties - - EventManager EventManager - - prev_msgs_mu sync.Mutex - previousMessages []play.PreviousMessage -} - -func NewBroadcast(cfg properties.ServerProperties, dummies ...DummySession) *Broadcast { - return &Broadcast{ - sessions: make(map[uuid.UUID]Session), - dummies: dummies, - cfg: cfg, - EventManager: Default, - } -} - -// adds a dummy session to the broadcast. A dummy session is not listed in the player list -func (b *Broadcast) AddDummy(session DummySession) { - b.sessions_mu.Lock() - defer b.sessions_mu.Unlock() - b.dummies = append(b.dummies, session) -} - -// Disconnects all the players on the broadcast -func (b *Broadcast) DisconnectAll(reason text.TextComponent) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - for _, ses := range b.sessions { - ses.Disconnect(reason) - } -} - -// Returns a session by uuid -func (b *Broadcast) Session(uuid uuid.UUID) (ses Session, ok bool) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - ses, ok = b.sessions[uuid] - - return -} - -// safely ranges over the broadcast's sessions -func (b *Broadcast) Range(iter func(uuid.UUID, Session) bool) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - for u, ses := range b.sessions { - res := iter(u, ses) - if !res { - break - } - } -} - -// Returns a session by uuid without locking the mutex -func (b *Broadcast) AsyncSession(uuid uuid.UUID) (ses Session, ok bool) { - ses, ok = b.sessions[uuid] - - return -} - -// Returns a session by username -func (b *Broadcast) SessionByUsername(username string) (ses Session, ok bool) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - - for _, session := range b.sessions { - if session.Username() == username { - return session, true - } - } - - return nil, false -} - -// Returns a session by entity id -func (b *Broadcast) SessionByEntityId(entityId int32) (ses Session, ok bool) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - - for _, session := range b.sessions { - if session.Player().EntityId() == entityId { - return session, true - } - } - - return nil, false -} - -// when a player's session data updates -func (b *Broadcast) PlayerInfoUpdateSession(session Session) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - - sesData, ok := session.SessionData() - - for _, ses := range b.sessions { - ses.PlayerInfoUpdate(&play.PlayerInfoUpdate{ - Actions: play.ActionInitializeChat, - Players: map[uuid.UUID]play.PlayerAction{ - session.UUID(): { - HasSignatureData: ok, - Session: sesData, - }, - }, - }) - } - for _, ses := range b.dummies { - ses.PlayerInfoUpdate(&play.PlayerInfoUpdate{ - Actions: play.ActionInitializeChat, - Players: map[uuid.UUID]play.PlayerAction{ - session.UUID(): { - HasSignatureData: ok, - Session: sesData, - }, - }, - }) - } -} - -// when a player's game mode updates -func (b *Broadcast) PlayerInfoUpdateGameMode(session Session) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - - gm := session.Player().GameMode() - - pk := &play.PlayerInfoUpdate{ - Actions: play.ActionUpdateGameMode, - Players: map[uuid.UUID]play.PlayerAction{ - session.UUID(): { - GameMode: int32(gm), - }, - }, - } - for _, ses := range b.sessions { - ses.PlayerInfoUpdate(pk) - } - for _, ses := range b.dummies { - ses.PlayerInfoUpdate(pk) - } -} - -// when a player's latency updates -func (b *Broadcast) PlayerInfoUpdateLatency(session Session) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - - l := session.Latency() - - pk := &play.PlayerInfoUpdate{ - Actions: play.ActionUpdateLatency, - Players: map[uuid.UUID]play.PlayerAction{ - session.UUID(): { - Ping: int32(l), - }, - }, - } - for _, ses := range b.sessions { - ses.PlayerInfoUpdate(pk) - } - for _, ses := range b.dummies { - ses.PlayerInfoUpdate(pk) - } -} - -func (b *Broadcast) RemoveUUIDs(disconnectionReason text.TextComponent, uuids ...uuid.UUID) { - b.sessions_mu.Lock() - defer b.sessions_mu.Unlock() - for _, uuid := range uuids { - session, ok := b.sessions[uuid] - if !ok { - continue - } - session.Disconnect(disconnectionReason) - delete(b.sessions, uuid) - } -} - -// when a player leaves the server -func (b *Broadcast) RemovePlayer(session Session) { - b.sessions_mu.Lock() - delete(b.sessions, session.UUID()) - - id := session.Player().EntityId() - - for _, ses := range b.sessions { - ses.PlayerInfoRemove(session.UUID()) - ses.DespawnEntities(id) - } - for _, ses := range b.dummies { - ses.PlayerInfoRemove(session.UUID()) - ses.DespawnEntities(id) - } - - b.sessions_mu.Unlock() - - b.EventManager.OnSessionRemove.Trigger(session) -} - -// when a new player joins the server -func (b *Broadcast) AddPlayer(session Session) { - b.sessions_mu.Lock() - - newListed, newGameMode, newLatency := session.Listed(), int32(session.Player().GameMode()), int32(session.Latency()) - - var toPlayerPk = &play.PlayerInfoUpdate{ - Actions: play.ActionAddPlayer | play.ActionUpdateListed | play.ActionInitializeChat | play.ActionUpdateGameMode | play.ActionUpdateLatency, - Players: map[uuid.UUID]play.PlayerAction{ - session.UUID(): { - Name: session.Username(), - Properties: session.Properties(), - GameMode: newGameMode, - Listed: newListed, - Ping: newLatency, - }, - }, - } - - for _, ses := range b.sessions { - ses.PlayerInfoUpdate(&play.PlayerInfoUpdate{ - Actions: play.ActionAddPlayer | play.ActionUpdateListed | play.ActionInitializeChat | play.ActionUpdateGameMode | play.ActionUpdateLatency, - Players: map[uuid.UUID]play.PlayerAction{ - session.UUID(): { - Name: session.Username(), - Properties: session.Properties(), - Listed: newListed, - GameMode: newGameMode, - Ping: newLatency, - }, - }, - }) - sesData, ok := ses.SessionData() - toPlayerPk.Players[ses.UUID()] = play.PlayerAction{ - Name: ses.Username(), - Properties: ses.Properties(), - Listed: ses.Listed(), - GameMode: int32(ses.Player().GameMode()), - HasSignatureData: ok, - Session: sesData, - Ping: int32(ses.Latency()), - } - } - for _, ses := range b.dummies { - ses.PlayerInfoUpdate(&play.PlayerInfoUpdate{ - Actions: play.ActionAddPlayer | play.ActionUpdateListed | play.ActionInitializeChat | play.ActionUpdateGameMode | play.ActionUpdateLatency, - Players: map[uuid.UUID]play.PlayerAction{ - session.UUID(): { - Name: session.Username(), - Properties: session.Properties(), - Listed: newListed, - GameMode: newGameMode, - Ping: newLatency, - }, - }, - }) - } - - session.PlayerInfoUpdate(toPlayerPk) - b.sessions[session.UUID()] = session - - b.sessions_mu.Unlock() - b.EventManager.OnSessionAdd.Trigger(session) -} - -func (b *Broadcast) SpawnPlayer(session Session) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - - x, y, z := session.Player().Position() - - log.Infolnf("%sPlayer %s (%s) joined with entity id %d (%f %f %f)", log.FormatAddr(b.cfg.LogIPs, session.Addr()), session.Username(), session.UUID(), session.Player().EntityId(), x, y, z) - - dim := session.Player().Dimension() - - for _, ses := range b.sessions { - if ses.UUID() == session.UUID() { - continue - } - if ses.Player().Dimension() != dim { - continue - } - - ses.SpawnPlayer(session) - session.SpawnPlayer(ses) - } - for _, ses := range b.dummies { - ses.SpawnPlayer(session) - } -} - -// broadcasts the position and rotation changes to the server. should be used before setting the properties on the player -func (b *Broadcast) BroadcastPlayerMovement(session Session, x, y, z float64, yaw, pitch float32) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - - var ( - oldX, oldY, oldZ = session.Player().Position() - oldYaw, oldPitch = session.Player().Rotation() - ) - - player := session.Player() - - dim := session.Player().Dimension() - - //fmt.Printf("%s new: %f %f %f, old: %f %f %f\n", session.Username(), x, y, z, oldX, oldY, oldZ) - - eid := session.Player().EntityId() - - var pk packet.Encodeable - switch { - // changes in both position and rotation - case (x != oldX || y != oldY || z != oldZ) && (yaw != oldYaw || pitch != oldPitch): - yaw, pitch := util.DegreesToAngle(yaw), util.DegreesToAngle(pitch) - pk = &play.UpdateEntityPositionAndRotation{ - EntityId: eid, - DeltaX: int16(x*4096 - oldX*4096), - DeltaY: int16(y*4096 - oldY*4096), - DeltaZ: int16(z*4096 - oldZ*4096), - Yaw: yaw, - Pitch: pitch, - } - case x != oldX || y != oldY || z != oldZ: - pk = &play.UpdateEntityPosition{ - EntityId: eid, - DeltaX: int16(x*4096 - oldX*4096), - DeltaY: int16(y*4096 - oldY*4096), - DeltaZ: int16(z*4096 - oldZ*4096), - } - case yaw != oldYaw || pitch != oldPitch: - yaw, pitch := util.DegreesToAngle(yaw), util.DegreesToAngle(pitch) - pk = &play.UpdateEntityRotation{ - EntityId: eid, - Yaw: yaw, - Pitch: pitch, - } - } - - for _, ses := range b.sessions { - if ses.UUID() == session.UUID() { - continue - } - if ses.Player().Dimension() != dim { - continue - } - switch p := pk.(type) { - case *play.UpdateEntityPosition: - ses.UpdateEntityPosition(player, p) - case *play.UpdateEntityPositionAndRotation: - ses.UpdateEntityPositionRotation(player, p) - case *play.UpdateEntityRotation: - ses.UpdateEntityRotation(player, p) - } - } - for _, ses := range b.dummies { - switch p := pk.(type) { - case *play.UpdateEntityPosition: - ses.UpdateEntityPosition(player, p) - case *play.UpdateEntityPositionAndRotation: - ses.UpdateEntityPositionRotation(player, p) - case *play.UpdateEntityRotation: - ses.UpdateEntityRotation(player, p) - } - } -} - -func (b *Broadcast) Animation(session Session, animation byte) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - id := session.Player().EntityId() - for _, ses := range b.sessions { - if ses.UUID() == session.UUID() { - continue - } - ses.EntityAnimation(id, animation) - } - for _, ses := range b.dummies { - ses.EntityAnimation(id, animation) - } -} - -func (b *Broadcast) EntityMetadata(session Session, md metadata.Metadata) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - id := session.Player().EntityId() - for _, ses := range b.sessions { - if ses.UUID() == session.UUID() { - continue - } - ses.EntityMetadata(id, md) - } - for _, ses := range b.dummies { - ses.EntityMetadata(id, md) - } -} - -func (b *Broadcast) UpdateTimeForAll(worldAge, dayTime int64) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - - for _, ses := range b.sessions { - ses.UpdateTime(worldAge, dayTime) - } - for _, ses := range b.dummies { - ses.UpdateTime(worldAge, dayTime) - } -} - -func (b *Broadcast) BlockAction(x, y, z int32, dimension string, actionId, actionParameter byte) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - - pk := &play.BlockAction{ - X: x, Y: y, Z: z, - ActionId: actionId, - ActionParameter: actionParameter, - } - - for _, ses := range b.sessions { - if ses.Player().Dimension() != dimension { - continue - } - ses.BlockAction(pk) - } - for _, ses := range b.dummies { - ses.BlockAction(pk) - } -} - -func (b *Broadcast) PlaySound(pk *play.SoundEffect, dimension string) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - - for _, ses := range b.sessions { - if ses.Player().Dimension() != dimension { - continue - } - ses.PlaySound(pk) - } - for _, ses := range b.dummies { - ses.PlaySound(pk) - } -} - -// this updates the block for everyone. It doesn't set the block in the world -func (b *Broadcast) UpdateBlock(blockPos pos.BlockPosition, block section.Block, dimension string, blockPlaceSound bool) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - - var sound *play.SoundEffect - if b, ok := block.(interface { - PlaceSound(pos pos.BlockPosition) *play.SoundEffect - } /*avoid import cycle*/); ok { - sound = b.PlaceSound(blockPos) - } else { - name, _ := block.Encode() - name = strings.TrimPrefix(name, "minecraft:") - id, ok := registry.SoundEvent.Lookup(fmt.Sprintf("minecraft:block.%s.place", name)) - if ok { - sound = &play.SoundEffect{ - SoundId: id, - SoundCategory: play.SoundCategoryBlock, - X: blockPos.X(), Y: blockPos.Y(), Z: blockPos.Z(), - Volume: 1, Pitch: 1, - Seed: int64(seed.Random()), - } - } - } - - for _, ses := range b.sessions { - if ses.Player().Dimension() != dimension { - continue - } - ses.UpdateBlock(blockPos, block) - if sound != nil { - ses.PlaySound(sound) - } - } - for _, ses := range b.dummies { - ses.UpdateBlock(blockPos, block) - if sound != nil { - ses.PlaySound(sound) - } - } -} - -// this updates the block entity for everyone. It doesn't set the block entity in the world -func (b *Broadcast) UpdateBlockEntity(pos pos.BlockPosition, blockEntity chunk.BlockEntity, dimension string) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - - for _, ses := range b.sessions { - if ses.Player().Dimension() != dimension { - continue - } - ses.UpdateBlockEntity(pos, blockEntity) - } - for _, ses := range b.dummies { - ses.UpdateBlockEntity(pos, blockEntity) - } -} - -func (b *Broadcast) DeleteMessage(id int32, sig [256]byte) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - for _, ses := range b.sessions { - ses.DeleteMessage(id, sig) - } - for _, ses := range b.dummies { - ses.DeleteMessage(id, sig) - } -} - -// returns the number of players in the broadcast -func (b *Broadcast) NumSession() int { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - return len(b.sessions) -} - -func Clamp(f, low, high float32) float32 { - if f < low { - return low - } - if f > high { - return high - } - return f -} - -func getAttackStrengthScale(p_36404 float32) float32 { - return Clamp((1+p_36404)/1, 0, 1) -} - -func (b *Broadcast) DamageEvent(attacker, attacked Session, dimension string, damageType string) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - - id := attacked.Player().EntityId() - sound := EntitySoundEffect( - "minecraft:entity.player.hurt", false, nil, play.SoundCategoryPlayer, id, 1, 1, - ) - - x1, _, z1 := attacked.Player().Position() - x2, _, z2 := attacker.Player().Position() - - vx, vy, vz := x1/2.0-x2, min(0.4, 1), z1/2.0-z2 - - for _, s := range b.sessions { - if dimension != s.Player().Dimension() { - continue - } - s.DamageEvent(attacker, attacked, damageType) - s.PlayEntitySound(sound) - s.(interface { - Conn() *net.Conn - }).Conn().WritePacket(&play.SetEntityVelocity{ - EntityId: id, - X: int16(vx * 8000), - Y: int16(vy * 8000), - Z: int16(vz * 8000), - }) - - } -} - -func YawToXZDelta(yaw float32) (float64, float64) { - yawd := float64(yaw) - radians := yawd * math.Pi / 180.0 - - x := -math.Sin(radians) - z := -math.Cos(radians) - - return x, z -} - -func sign(f float64) float64 { - if f < 0 { - return -1 - } - return 1 -} - -// returns the players to display in status sample -func (b *Broadcast) Sample() []status.StatusSample { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - samples := make([]status.StatusSample, len(b.sessions)) - - var i int - for _, s := range b.sessions { - if !s.ClientInformation().AllowServerListing { - continue - } - samples[i] = status.StatusSample{ - Name: s.Username(), - ID: s.UUID().String(), - } - i++ - } - - samples = samples[:i] - - return samples -} - -// creates a sound effect with the provided data. If custom is true, or name wasn't found in the sound registry, the packet will use a custom sound name. This function generates a random seed for this event using level.NewSeed() -func SoundEffect(name string, custom bool, fixedRange *float32, category int32, x, y, z int32, volume, pitch float32) *play.SoundEffect { - pk := &play.SoundEffect{ - SoundCategory: category, - X: x, Y: y, Z: z, - Volume: volume, - Pitch: pitch, - Seed: int64(seed.Random()), - } - if !custom { - soundId, ok := registry.SoundEvent.Lookup(name) - if ok { - pk.SoundId = soundId - return pk - } - } - - pk.SoundId = -1 - pk.SoundName = name - pk.FixedRange = fixedRange != nil - if fixedRange != nil { - pk.Range = *fixedRange - } - - return pk -} - -func EntitySoundEffect(name string, custom bool, fixedRange *float32, category int32, entityId int32, volume, pitch float32) *play.EntitySoundEffect { - pk := &play.EntitySoundEffect{ - SoundCategory: category, - EntityId: entityId, - Volume: volume, - Pitch: pitch, - Seed: int64(seed.Random()), - } - if !custom { - soundId, ok := registry.SoundEvent.Lookup(name) - if ok { - pk.SoundId = soundId - return pk - } - } - - pk.SoundId = -1 - pk.SoundName = name - pk.FixedRange = fixedRange != nil - if fixedRange != nil { - pk.Range = *fixedRange - } - - return pk -} diff --git a/server/session/chat.go b/server/session/chat.go deleted file mode 100644 index 5df2432a..00000000 --- a/server/session/chat.go +++ /dev/null @@ -1,80 +0,0 @@ -package session - -import ( - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/protocol/text" -) - -func (b *Broadcast) SecureChatMessage(session Session, pk play.ChatMessage, index int32) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - - b.prev_msgs_mu.Lock() - defer b.prev_msgs_mu.Unlock() - - for _, ses := range b.sessions { - ses.PlayerChatMessage(pk, session, "minecraft:chat", index, b.previousMessages) - } - - for _, ses := range b.dummies { - ses.PlayerChatMessage(pk, session, "minecraft:chat", index, b.previousMessages) - } - b.appendMessage() -} - -func (b *Broadcast) appendMessage() { - if len(b.previousMessages) != 20 { - b.previousMessages = append([]play.PreviousMessage{{MessageID: int32(len(b.previousMessages))}}, b.previousMessages...) - } -} - -func (b *Broadcast) DisguisedChatMessage(session Session, content text.TextComponent) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - - for _, ses := range b.sessions { - ses.DisguisedChatMessage(content, session, "minecraft:chat") - } - for _, ses := range b.dummies { - ses.DisguisedChatMessage(content, session, "minecraft:chat") - } -} - -func (b *Broadcast) SystemChatMessage(content text.TextComponent) { - b.sessions_mu.RLock() - defer b.sessions_mu.RUnlock() - - for _, ses := range b.sessions { - ses.SystemMessage(content) - } - for _, ses := range b.dummies { - ses.SystemMessage(content) - } -} - -func onChatMessage(ev ChatMessageEvent) bool { - cfg := ev.Sender.Config() - b := ev.Sender.Broadcast() - - if !cfg.EnableChat { - return true - } - if cfg.EnforceSecureProfile && ev.HasSignature { - b.SecureChatMessage(ev.Sender, ev.ChatMessage, ev.Index) - return true - } - if cfg.SystemChatFormat == "" { - comp := text.TextComponent{Text: ev.Message} - //if s.Config().Chat.Colors { - // comp = text.Unmarshal(cm.Message, s.Config().Chat.Formatter.Rune()) - //} - b.DisguisedChatMessage(ev.Sender, comp) - } - return true -} - -type ChatMessageEvent struct { - play.ChatMessage - Sender Session - Index int32 -} diff --git a/server/session/events.go b/server/session/events.go deleted file mode 100644 index ee051869..00000000 --- a/server/session/events.go +++ /dev/null @@ -1,78 +0,0 @@ -package session - -import ( - "github.com/zeppelinmc/zeppelin/protocol/text" -) - -// A handler function. Should return false to break the event -type Handler[T any] func(T) bool - -func NewEvent[T any](handlers ...Handler[T]) Event[T] { - return Event[T]{handlers} -} - -type Event[T any] struct { - handlers []Handler[T] -} - -// Append adds handlers for the event. They will be handled last -func (e Event[T]) Append(handlers ...Handler[T]) { - e.handlers = append(e.handlers, handlers...) -} - -// Prepend adds handlers for the event. They will be handled first -func (e Event[T]) Prepend(handlers ...Handler[T]) { - e.handlers = append(handlers, e.handlers...) -} - -// Override replaces all of the handlers of the event with the new handlers -func (e Event[T]) Override(handlers ...Handler[T]) { - e.handlers = e.handlers[:copy(e.handlers, handlers)] -} - -// Chan creates a new channel handler -func (e Event[T]) Chan() <-chan T { - c := make(chan T) - e.Append(func(t T) bool { - c <- t - return true - }) - - return c -} - -// Await creates a new channel handler and waits for the event to be triggered -func (e Event[T]) Await() { - <-e.Chan() -} - -func (e Event[T]) Trigger(v T) { - for _, handler := range e.handlers { - if !handler(v) { - break - } - } -} - -type EventManager struct { - OnSessionAdd Event[Session] - OnSessionRemove Event[Session] - OnChatMessage Event[ChatMessageEvent] -} - -// Default is the default event manager -var Default = EventManager{ - OnSessionAdd: NewEvent(onSessionAdd), - OnSessionRemove: NewEvent(onSessionRemove), - OnChatMessage: NewEvent(onChatMessage), -} - -func onSessionAdd(s Session) bool { - s.Broadcast().SystemChatMessage(text.Unmarshalf('&', "&e%s joined the game", s.Username())) - return true -} - -func onSessionRemove(s Session) bool { - s.Broadcast().SystemChatMessage(text.Unmarshalf('&', "&e%s left the game", s.Username())) - return true -} diff --git a/server/session/session.go b/server/session/session.go deleted file mode 100644 index b51d9e25..00000000 --- a/server/session/session.go +++ /dev/null @@ -1,185 +0,0 @@ -package session - -import ( - "net" - - "github.com/google/uuid" - "github.com/zeppelinmc/zeppelin/protocol/net/metadata" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/configuration" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/login" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/protocol/properties" - "github.com/zeppelinmc/zeppelin/server/entity" - "github.com/zeppelinmc/zeppelin/server/player" - - "github.com/zeppelinmc/zeppelin/protocol/text" - "github.com/zeppelinmc/zeppelin/server/world/block/pos" - "github.com/zeppelinmc/zeppelin/server/world/chunk" - "github.com/zeppelinmc/zeppelin/server/world/chunk/section" - "github.com/zeppelinmc/zeppelin/server/world/dimension/window" - "github.com/zeppelinmc/zeppelin/server/world/level" -) - -type Session interface { - // Username of the session - Username() string - // UUID of the session - UUID() uuid.UUID - // Properties (typically only textures) - Properties() []login.Property - - // The player this session holds - Player() *player.Player - // The client name this session reports in minecraft:brand (vanilla) - ClientName() string - // the client settings of this client - ClientInformation() configuration.ClientInformation - // The address of this connection - Addr() net.Addr - - // the broadcaster of the session - Broadcast() *Broadcast - - // the server properties used by this session - Config() properties.ServerProperties - - // Disconnects the session from the server - Disconnect(reason text.TextComponent) error - // sends a player chat message packet to the session - PlayerChatMessage(pk play.ChatMessage, sender Session, chatType string, index int32, prevMsgs []play.PreviousMessage) error - // sends a player info update packet to the session - PlayerInfoUpdate(pk *play.PlayerInfoUpdate) error - // sends a player info remove packet to the session - PlayerInfoRemove(uuids ...uuid.UUID) error - - // sends a disguised chat message - DisguisedChatMessage(content text.TextComponent, sender Session, chatType string) error - - UpdateEntityPosition(entity entity.Entity, pk *play.UpdateEntityPosition) error - UpdateEntityPositionRotation(entity entity.Entity, pk *play.UpdateEntityPositionAndRotation) error - UpdateEntityRotation(entity entity.Entity, pk *play.UpdateEntityRotation) error - - // whether the entity is spawned for this session or not - IsSpawned(entityId int32) bool - // despawns the entities for this session - DespawnEntities(entityIds ...int32) error - // spawns the entity for this session - SpawnEntity(entity.Entity) error - // spawns a player - SpawnPlayer(Session) error - - // whether this session should be listed in the playerlist - Listed() bool - - // returns the latency of the client in milliseconds - Latency() int64 - - // sends entity animation - EntityAnimation(entityId int32, animation byte) error - // sends entity metadata - EntityMetadata(entityId int32, md metadata.Metadata) error - - // teleports the player to specified location with specified rotation - SynchronizePosition(x, y, z float64, yaw, pitch float32) error - // sends a system (unsigned) chat message to the client - SystemMessage(msg text.TextComponent) error - - // Returns the session data for this session, and if it has any - SessionData() (data play.PlayerSession, ok bool) - - // updates the time for the client - UpdateTime(worldAge, dayTime int64) error - - // sets the gamemode for the client - SetGameMode(gm level.GameMode) error - - // sends a block action to the session - BlockAction(*play.BlockAction) error - - // opens the window for the client and bumps up the window viewer number - OpenWindow(w *window.Window) error - - // plays the sound for the client - PlaySound(*play.SoundEffect) error - - // plays the sound for the client - PlayEntitySound(*play.EntitySoundEffect) error - - // updates the block for the player - UpdateBlock(pos pos.BlockPosition, b section.Block) error - - // updates the block entity for the player - UpdateBlockEntity(pos pos.BlockPosition, be chunk.BlockEntity) error - - // send damage event to the client - DamageEvent(attacker, attacked Session, damageType string) error - - // deletes a signed message for the client - DeleteMessage(id int32, sig [256]byte) error - - SetTickState(tps float32, frozen bool) error - - // the textures of this client - Textures() (login.Textures, error) -} - -type DummySession interface { - // the broadcaster of the session - Broadcast() *Broadcast - - // the server properties used by this session - Config() properties.ServerProperties - - // sends a player chat message packet to the session - PlayerChatMessage(pk play.ChatMessage, sender Session, chatType string, index int32, prevMsgs []play.PreviousMessage) error - // sends a player info update packet to the session - PlayerInfoUpdate(pk *play.PlayerInfoUpdate) error - // sends a player info remove packet to the session - PlayerInfoRemove(uuids ...uuid.UUID) error - - // sends a disguised chat message - DisguisedChatMessage(content text.TextComponent, sender Session, chatType string) error - - UpdateEntityPosition(entity entity.Entity, pk *play.UpdateEntityPosition) error - UpdateEntityPositionRotation(entity entity.Entity, pk *play.UpdateEntityPositionAndRotation) error - UpdateEntityRotation(entity entity.Entity, pk *play.UpdateEntityRotation) error - - // spawns the entity for this session - SpawnEntity(entity.Entity) error - // spawns a player - SpawnPlayer(Session) error - - // sends entity animation - EntityAnimation(entityId int32, animation byte) error - // sends entity metadata - EntityMetadata(entityId int32, md metadata.Metadata) error - - // sends a system (unsigned) chat message to the client - SystemMessage(msg text.TextComponent) error - - // updates the time for the client - UpdateTime(worldAge, dayTime int64) error - - // sends a block action to the session - BlockAction(*play.BlockAction) error - - // plays the sound for the client - PlaySound(*play.SoundEffect) error - - // plays the sound for the client - PlayEntitySound(*play.EntitySoundEffect) error - - // updates the block for the player - UpdateBlock(pos pos.BlockPosition, b section.Block) error - - // updates the block entity for the player - UpdateBlockEntity(pos pos.BlockPosition, be chunk.BlockEntity) error - - // send damage event to the client - DamageEvent(attacker, attacked Session, damageType string) error - - // deletes a signed message for the client - DeleteMessage(id int32, sig [256]byte) error - - DespawnEntities(entityIds ...int32) error -} diff --git a/server/session/std/chat.go b/server/session/std/chat.go deleted file mode 100644 index e88c976f..00000000 --- a/server/session/std/chat.go +++ /dev/null @@ -1,46 +0,0 @@ -package std - -import ( - "slices" - - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/protocol/text" - "github.com/zeppelinmc/zeppelin/server/session" -) - -func (session *StandardSession) PlayerChatMessage( - pk play.ChatMessage, sender session.Session, chatType string, - index int32, prevMsgs []play.PreviousMessage, -) error { - chatTypeIndex := slices.Index(session.registryIndexes["minecraft:chat_type"], chatType) - - return session.conn.WritePacket(&play.PlayerChatMessage{ - Sender: sender.UUID(), - Index: index, - HasMessageSignature: pk.HasSignature, - MessageSignature: pk.Signature, - Message: pk.Message, - Timestamp: pk.Timestamp, - Salt: pk.Salt, - - PreviousMessages: prevMsgs, - - ChatType: int32(chatTypeIndex + 1), - SenderName: text.Unmarshal(sender.Username(), session.config.ChatFormatter.Rune()), - }) -} - -func (session *StandardSession) DisguisedChatMessage(content text.TextComponent, sender session.Session, chatType string) error { - chatTypeIndex := slices.Index(session.registryIndexes["minecraft:chat_type"], chatType) - - return session.conn.WritePacket(&play.DisguisedChatMessage{ - Message: content, - - ChatType: int32(chatTypeIndex + 1), - SenderName: text.Unmarshal(sender.Username(), session.config.ChatFormatter.Rune()), - }) -} - -func (session *StandardSession) SystemMessage(msg text.TextComponent) error { - return session.conn.WritePacket(&play.SystemChatMessage{Content: msg}) -} diff --git a/server/session/std/chunkLoadWorker.go b/server/session/std/chunkLoadWorker.go deleted file mode 100644 index 37b336ef..00000000 --- a/server/session/std/chunkLoadWorker.go +++ /dev/null @@ -1,120 +0,0 @@ -package std - -import ( - "bytes" - - "github.com/zeppelinmc/zeppelin/protocol/net/io/buffers" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/server/world/level/region" -) - -// ChunkLoadWorker loads and unloads chunks for the session -type ChunkLoadWorker struct { - s *StandardSession - requests chan [3]int32 //x,z,radius -} - -func NewChunkLoadWorker(s *StandardSession) *ChunkLoadWorker { - return &ChunkLoadWorker{s: s, requests: make(chan [3]int32)} -} - -func (c ChunkLoadWorker) SendChunksRadius(chunkX, chunkZ, radius int32) { - c.requests <- [3]int32{chunkX, chunkZ, radius} -} - -func (c ChunkLoadWorker) sendChunksRadius(chunkX, chunkZ, rad int32) error { - c.s.load_ch_mu.Lock() - defer c.s.load_ch_mu.Unlock() - - if rad == 0 { - rad = c.s.ViewDistance() - } - - var chunks int32 - - if err := c.s.WritePacket(&play.ChunkBatchStart{}); err != nil { - return err - } - - for x := chunkX - rad; x < chunkX+rad; x++ { - for z := chunkZ - rad; z < chunkZ+rad; z++ { - if _, ok := c.s.loadedChunks[region.ChunkHash(x, z)]; ok { - continue - } - c.s.loadedChunks[region.ChunkHash(x, z)] = struct{}{} - chunk, err := c.s.Dimension().GetChunk(x, z) - if err != nil { - continue - } - - if err := c.s.WritePacket(chunk.Encode(c.s.registryIndexes["minecraft:worldgen/biome"])); err != nil { - return err - } - chunks++ - } - } - - if err := c.s.WritePacket(&play.ChunkBatchFinished{ - BatchSize: chunks, - }); err != nil { - return err - } - c.s.awaitingChunkBatchAcknowledgement.Store(true) - - return nil -} - -func (c ChunkLoadWorker) start() { - go func() { - for req := range c.requests { - c.sendChunksRadius(req[0], req[1], req[2]) - } - }() -} - -func (session *StandardSession) sendSpawnChunks() error { - viewDistance := session.ViewDistance() - - x, _, z := session.player.Position() - chunkX, chunkZ := int32(x)>>4, int32(z)>>4 - - if err := session.WritePacket(&play.SetCenterChunk{ChunkX: chunkX, ChunkZ: chunkZ}); err != nil { - return err - } - - var chunks int32 - - if err := session.WritePacket(&play.ChunkBatchStart{}); err != nil { - return err - } - - buf := buffers.Buffers.Get().(*bytes.Buffer) - - for x := chunkX - viewDistance; x < chunkX+viewDistance; x++ { - for z := chunkZ - viewDistance; z < chunkZ+viewDistance; z++ { - buf.Reset() - c, err := session.Dimension().GetChunkBuf(x, z, buf) - if err != nil { - continue - } - buf.Reset() - - if err := session.WritePacket(c.EncodeBuf(session.registryIndexes["minecraft:worldgen/biome"], buf)); err != nil { - return err - } - chunks++ - } - } - buffers.Buffers.Put(buf) - - if err := session.WritePacket(&play.ChunkBatchFinished{ - BatchSize: chunks, - }); err != nil { - return err - } - - session.awaitingChunkBatchAcknowledgement.Store(true) - session.ChunkLoadWorker.start() - - return nil -} diff --git a/server/session/std/handler.go b/server/session/std/handler.go deleted file mode 100644 index 1ce3e9e5..00000000 --- a/server/session/std/handler.go +++ /dev/null @@ -1,114 +0,0 @@ -package std - -import ( - "time" - - "github.com/zeppelinmc/zeppelin/protocol/net" - "github.com/zeppelinmc/zeppelin/protocol/net/io/encoding" - "github.com/zeppelinmc/zeppelin/protocol/net/packet" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/configuration" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/protocol/text" - "github.com/zeppelinmc/zeppelin/util/log" -) - -var PacketReadInterceptor func(s *StandardSession, pk packet.Decodeable) bool -var PacketWriteInterceptor func(s *StandardSession, pk packet.Encodeable) bool - -type handler func(*StandardSession, packet.Decodeable) - -var handlers = make(map[[2]int32]handler) - -func RegisterHandler(state, id int32, handler handler) { - handlers[[2]int32{state, id}] = handler -} -func (session *StandardSession) inConfiguration() bool { - return session.conn.State() == net.ConfigurationState -} - -func (session *StandardSession) readIntercept(pk packet.Decodeable) (stop bool) { - if PacketReadInterceptor != nil { - return PacketReadInterceptor(session, pk) - } - - return -} - -// kills the session's ticker, and removes it from the server broadcast -func (session *StandardSession) kill(err bool, reason string) { - var logfn = log.Infolnf - if err { - logfn = log.Errorlnf - } - logfn("%sPlayer %s disconnected: %s", log.FormatAddr(session.config.LogIPs, session.Addr()), session.Username(), reason) - session.stopTick <- struct{}{} - session.broadcast.RemovePlayer(session) -} - -func (session *StandardSession) handlePackets() { - keepAlive := time.NewTicker(time.Second * 20) - for { - select { - case <-keepAlive.C: - l := time.Now().UnixMilli() - session.cbLastKeepAlive.Store(l) - session.conn.WritePacket(&play.ClientboundKeepAlive{KeepAliveID: l}) - default: - if lastKeepAlive := session.sbLastKeepalive.Load(); lastKeepAlive != 0 && time.Now().UnixMilli()-lastKeepAlive > (21*1000) { - session.Disconnect(text.TextComponent{Text: "Timed out"}) - session.kill(false, "timed out") - return - } - p, s, err := session.conn.ReadPacket() - if err != nil { - session.kill(false, "lost connection") - return - } - - if s || session.readIntercept(p) { - continue - } - - handler, ok := handlers[[2]int32{session.conn.State(), p.ID()}] - if !ok { - switch pk := p.(type) { - case *play.ChunkBatchReceived: - session.chunksPerTick.Store(int32(pk.ChunksPerTick)) - session.awaitingChunkBatchAcknowledgement.Store(false) - case *play.ServerboundKeepAlive: - session.sbLastKeepalive.Store(time.Now().UnixMilli()) - session.broadcast.PlayerInfoUpdateLatency(session) - case *play.PlayerSession: - session.hasSessionData.Store(true) - session.sessionData.Set(*pk) - - session.broadcast.PlayerInfoUpdateSession(session) - case *configuration.ServerboundPluginMessage: - if pk.Channel == "minecraft:brand" { - if err := session.updateBrand(pk.Data); err != nil { - session.kill(true, "malformed brand") - } - } - case *play.ServerboundPluginMessage: - if pk.Channel == "minecraft:brand" { - if err := session.updateBrand(pk.Data); err != nil { - session.kill(true, "malformed brand") - } - } - case *configuration.AcknowledgeFinishConfiguration: - session.conn.SetState(net.PlayState) - session.login() - default: - log.Printlnf("Unknown packet 0x%02x %T", p.ID(), p) - } - continue - } - handler(session, p) - } - } -} - -func (session *StandardSession) updateBrand(data []byte) (err error) { - session.clientName, err = encoding.String(data) - return -} diff --git a/server/session/std/handler/chatCommand.go b/server/session/std/handler/chatCommand.go deleted file mode 100644 index ab3c21e2..00000000 --- a/server/session/std/handler/chatCommand.go +++ /dev/null @@ -1,22 +0,0 @@ -package handler - -import ( - "github.com/zeppelinmc/zeppelin/protocol/net" - "github.com/zeppelinmc/zeppelin/protocol/net/packet" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/server/session/std" - "github.com/zeppelinmc/zeppelin/util/log" -) - -func init() { - std.RegisterHandler(net.PlayState, play.PacketIdChatCommand, handleChatCommand) - std.RegisterHandler(net.PlayState, play.PacketIdSignedChatCommand, handleChatCommand) -} - -func handleChatCommand(session *std.StandardSession, p packet.Decodeable) { - switch pk := p.(type) { - case *play.ChatCommand: - log.Infolnf("%sPlayer %s (%s) issued server command: /%s", log.FormatAddr(session.Config().LogIPs, session.Addr()), session.Username(), session.UUID(), pk.Command) - session.CommandManager().Call(pk.Command, session) - } -} diff --git a/server/session/std/handler/chatMessage.go b/server/session/std/handler/chatMessage.go deleted file mode 100644 index c11e2806..00000000 --- a/server/session/std/handler/chatMessage.go +++ /dev/null @@ -1,26 +0,0 @@ -package handler - -import ( - "github.com/zeppelinmc/zeppelin/protocol/net" - "github.com/zeppelinmc/zeppelin/protocol/net/packet" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/protocol/text" - "github.com/zeppelinmc/zeppelin/server/session" - "github.com/zeppelinmc/zeppelin/server/session/std" -) - -func init() { - std.RegisterHandler(net.PlayState, play.PacketIdChatMessage, handleChatMessage) -} - -func handleChatMessage(s *std.StandardSession, pk packet.Decodeable) { - if cm, ok := pk.(*play.ChatMessage); ok { - if len(cm.Message) > 256 { - s.Disconnect(text.TextComponent{Text: "Chat message over 256 characters is not allowed"}) - return - } - s.Broadcast().EventManager.OnChatMessage.Trigger(session.ChatMessageEvent{ - ChatMessage: *cm, Sender: s, Index: s.ChatIndex.Add(1) - 1, - }) - } -} diff --git a/server/session/std/handler/clickContainer.go b/server/session/std/handler/clickContainer.go deleted file mode 100644 index 3a807196..00000000 --- a/server/session/std/handler/clickContainer.go +++ /dev/null @@ -1,78 +0,0 @@ -package handler - -import ( - "fmt" - - "github.com/zeppelinmc/zeppelin/protocol/net" - "github.com/zeppelinmc/zeppelin/protocol/net/packet" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/server/container" - "github.com/zeppelinmc/zeppelin/server/session/std" - "github.com/zeppelinmc/zeppelin/server/world/level/item" - - slot0 "github.com/zeppelinmc/zeppelin/protocol/net/slot" -) - -func init() { - std.RegisterHandler(net.PlayState, play.PacketIdClickContainer, handleClickContainer) -} - -func handleClickContainer(s *std.StandardSession, pk packet.Decodeable) { - ccpk, ok := pk.(*play.ClickContainer) - if !ok { - return - } - - if s.WindowView.Load() != int32(ccpk.WindowId) { - return // messing with a container other than the one open - ignore - } - - if s.StateID.Load() != ccpk.State { - switch ccpk.WindowId { - case 0: // inventory - s.SendInventory() - default: - _, w, ok := s.Dimension().WindowManager.Get(int32(ccpk.WindowId)) - if !ok { - return // didnt find the window //////////// - } - s.SetContainerContent(*w) - } - return // synchronise container with the client - } - - var w *container.Container - - switch ccpk.WindowId { - case 0: - w = s.Player().Inventory() - default: - _, c, ok := s.Dimension().WindowManager.Get(int32(ccpk.WindowId)) - if !ok { - return - } - w = &c.Items - } - - switch ccpk.Mode { - case 0: - switch ccpk.Button { - case 0: // left click - if ccpk.Slot == -999 { - panic("unimplemented left-click-outside-inv") - } - - slot := item.DataSlotFrom(int32(ccpk.Slot)) - - fmt.Println(slot, ccpk.ChangedSlots, ccpk.CarriedItem) - - if !ccpk.CarriedItem.Is(slot0.Air) { - s.CarriedItem, _ = w.Slot(slot) - - w.SetAt(item.Air, slot) - } else { - w.Merge(slot, &s.CarriedItem) - } - } - } -} diff --git a/server/session/std/handler/clientInfo.go b/server/session/std/handler/clientInfo.go deleted file mode 100644 index 7f56eda2..00000000 --- a/server/session/std/handler/clientInfo.go +++ /dev/null @@ -1,36 +0,0 @@ -package handler - -import ( - "github.com/zeppelinmc/zeppelin/protocol/net" - "github.com/zeppelinmc/zeppelin/protocol/net/metadata" - "github.com/zeppelinmc/zeppelin/protocol/net/packet" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/configuration" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/server/session/std" -) - -func init() { - std.RegisterHandler(net.PlayState, play.PacketIdClientInformation, handleClientInfo) - std.RegisterHandler(net.ConfigurationState, configuration.PacketIdClientInformation, handleClientInfo) -} - -func handleClientInfo(s *std.StandardSession, p packet.Decodeable) { - var inf configuration.ClientInformation - switch pk := p.(type) { - case *configuration.ClientInformation: - inf = *pk - s.ClientInfo.Set(*pk) - case *play.ClientInformation: - inf = pk.ClientInformation - s.ClientInfo.Set(pk.ClientInformation) - default: - return - } - - new := metadata.Metadata{ - metadata.PlayerDisplayedSkinPartsIndex: metadata.Byte(inf.DisplayedSkinParts), - metadata.PlayerMainHandIndex: metadata.Byte(inf.MainHand), - } - s.Player().SetMetadataIndexes(new) - s.Broadcast().EntityMetadata(s, new) -} diff --git a/server/session/std/handler/closeContainer.go b/server/session/std/handler/closeContainer.go deleted file mode 100644 index fb8c0fd2..00000000 --- a/server/session/std/handler/closeContainer.go +++ /dev/null @@ -1,47 +0,0 @@ -package handler - -import ( - "github.com/zeppelinmc/zeppelin/protocol/net" - "github.com/zeppelinmc/zeppelin/protocol/net/packet" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/server/session" - "github.com/zeppelinmc/zeppelin/server/session/std" -) - -func init() { - std.RegisterHandler(net.PlayState, play.PacketIdCloseContainer, handleCloseContainer) -} - -func handleCloseContainer(s *std.StandardSession, p packet.Decodeable) { - pk, ok := p.(*play.CloseContainer) - if !ok { - return - } - if s.WindowView.Load() == int32(pk.WindowId) { - pos, w, ok := s.Dimension().WindowManager.Get(int32(pk.WindowId)) - s.WindowView.Store(0) - if !ok { - return - } - oldViewers := w.Viewers - w.Viewers-- - - x, y, z := pos[0], pos[1], pos[2] - - block, err := s.Dimension().Block(x, y, z) - if err != nil { - return - } - blockType, _ := block.Encode() - - if blockType == "minecraft:chest" { - s.Broadcast().BlockAction(x, y, z, s.Player().Dimension(), 1, w.Viewers) - if oldViewers > 0 && w.Viewers == 0 { - // chest was closed by all players - s.Broadcast().PlaySound(session.SoundEffect( - "minecraft:block.chest.close", false, nil, play.SoundCategoryBlock, x, y, z, 1, 1, - ), s.Dimension().Name()) - } - } - } -} diff --git a/server/session/std/handler/confirmTeleportation.go b/server/session/std/handler/confirmTeleportation.go deleted file mode 100644 index 3e418138..00000000 --- a/server/session/std/handler/confirmTeleportation.go +++ /dev/null @@ -1,16 +0,0 @@ -package handler - -import ( - "github.com/zeppelinmc/zeppelin/protocol/net" - "github.com/zeppelinmc/zeppelin/protocol/net/packet" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/server/session/std" -) - -func init() { - std.RegisterHandler(net.PlayState, play.PacketIdConfirmTeleportation, handleConfirmTeleportation) -} - -func handleConfirmTeleportation(session *std.StandardSession, p packet.Decodeable) { - session.AwaitingTeleportAcknowledgement.Store(false) -} diff --git a/server/session/std/handler/interact.go b/server/session/std/handler/interact.go deleted file mode 100644 index f7df2ce2..00000000 --- a/server/session/std/handler/interact.go +++ /dev/null @@ -1,47 +0,0 @@ -package handler - -import ( - "math" - - "github.com/zeppelinmc/zeppelin/protocol/net" - "github.com/zeppelinmc/zeppelin/protocol/net/packet" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/server/session/std" - "github.com/zeppelinmc/zeppelin/server/world/level" -) - -func init() { - std.RegisterHandler(net.PlayState, play.PacketIdInteract, handleInteract) -} - -func handleInteract(s *std.StandardSession, pk packet.Decodeable) { - interact, ok := pk.(*play.Interact) - if !ok { - return - } - - //TODO entity attack - attacked, ok := s.Broadcast().SessionByEntityId(interact.EntityId) - if !ok { - return - } - if attacked.Player().Dimension() != s.Player().Dimension() { - return - } - - x1, y1, z1 := s.Player().Position() - x2, y2, z2 := attacked.Player().Position() - - distance := math.Sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2)) - if distance > 4 { - return - } - - switch interact.Type { - case play.InteractTypeAttack: - if gm := attacked.Player().GameMode(); gm == level.GameModeCreative || gm == level.GameModeSpectator { - return - } - s.Broadcast().DamageEvent(s, attacked, s.Player().Dimension(), "minecraft:player_attack") - } -} diff --git a/server/session/std/handler/movement.go b/server/session/std/handler/movement.go deleted file mode 100644 index d7aa7cbb..00000000 --- a/server/session/std/handler/movement.go +++ /dev/null @@ -1,35 +0,0 @@ -package handler - -import ( - "github.com/zeppelinmc/zeppelin/protocol/net" - "github.com/zeppelinmc/zeppelin/protocol/net/packet" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/server/session/std" -) - -func init() { - std.RegisterHandler(net.PlayState, play.PacketIdSetPlayerPosition, handleMovement) - std.RegisterHandler(net.PlayState, play.PacketIdSetPlayerPositionAndRotation, handleMovement) - std.RegisterHandler(net.PlayState, play.PacketIdSetPlayerRotation, handleMovement) - std.RegisterHandler(net.PlayState, play.PacketIdSetPlayerOnGround, handleMovement) -} - -func handleMovement(s *std.StandardSession, p packet.Decodeable) { - if s.AwaitingTeleportAcknowledgement.Load() { - return - } - switch pk := p.(type) { - case *play.SetPlayerPosition: - s.Input.SetPosition(pk.X, pk.Y, pk.Z) - s.Input.SetOnGround(pk.OnGround) - case *play.SetPlayerPositionAndRotation: - s.Input.SetPosition(pk.X, pk.Y, pk.Z) - s.Input.SetRotation(pk.Yaw, pk.Pitch) - s.Input.SetOnGround(pk.OnGround) - case *play.SetPlayerRotation: - s.Input.SetRotation(pk.Yaw, pk.Pitch) - s.Input.SetOnGround(pk.OnGround) - case *play.SetPlayerOnGround: - s.Input.SetOnGround(pk.OnGround) - } -} diff --git a/server/session/std/handler/playerAbilities.go b/server/session/std/handler/playerAbilities.go deleted file mode 100644 index e03a3a63..00000000 --- a/server/session/std/handler/playerAbilities.go +++ /dev/null @@ -1,28 +0,0 @@ -package handler - -import ( - "github.com/zeppelinmc/zeppelin/protocol/net" - "github.com/zeppelinmc/zeppelin/protocol/net/packet" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/protocol/text" - "github.com/zeppelinmc/zeppelin/server/session/std" -) - -func init() { - std.RegisterHandler(net.PlayState, play.PacketIdPlayerAbilitiesServerbound, handlePlayerAbilities) -} - -func handlePlayerAbilities(s *std.StandardSession, pk packet.Decodeable) { - abs, ok := pk.(*play.PlayerAbilitiesServerbound) - if !ok { - return - } - flying := abs.Flags&play.PlayerAbsFlying != 0 - abilities := s.Player().Abilities() - if flying && !abilities.MayFly { - s.Disconnect(text.TextComponent{Text: "You are not allowed to fly"}) - return - } - abilities.Flying = flying - s.Player().SetAbilities(abilities) -} diff --git a/server/session/std/handler/playerCommand.go b/server/session/std/handler/playerCommand.go deleted file mode 100644 index 3e804211..00000000 --- a/server/session/std/handler/playerCommand.go +++ /dev/null @@ -1,53 +0,0 @@ -package handler - -import ( - "github.com/zeppelinmc/zeppelin/protocol/net" - "github.com/zeppelinmc/zeppelin/protocol/net/metadata" - "github.com/zeppelinmc/zeppelin/protocol/net/packet" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/server/session/std" -) - -func init() { - std.RegisterHandler(net.PlayState, play.PacketIdPlayerCommand, handlePlayerCommand) -} - -func handlePlayerCommand(session *std.StandardSession, pk packet.Decodeable) { - if command, ok := pk.(*play.PlayerCommand); ok { - var newmd metadata.Metadata - switch command.ActionId { - case play.ActionIdStartSneaking: - base := session.Player().MetadataIndex(metadata.BaseIndex).(metadata.Byte) - base |= metadata.IsCrouching - - newmd = metadata.Metadata{ - metadata.BaseIndex: base, - metadata.PoseIndex: metadata.Sneaking, - } - case play.ActionIdStopSneaking: - base := session.Player().MetadataIndex(metadata.BaseIndex).(metadata.Byte) - base &= ^metadata.IsCrouching - - newmd = metadata.Metadata{ - metadata.BaseIndex: base, - metadata.PoseIndex: metadata.Standing, - } - case play.ActionIdStartSprinting: - base := session.Player().MetadataIndex(metadata.BaseIndex).(metadata.Byte) - base |= metadata.IsSprinting - - newmd = metadata.Metadata{ - metadata.BaseIndex: base, - } - case play.ActionIdStopSprinting: - base := session.Player().MetadataIndex(metadata.BaseIndex).(metadata.Byte) - base &= ^metadata.IsSprinting - - newmd = metadata.Metadata{ - metadata.BaseIndex: base, - } - } - session.Player().SetMetadataIndexes(newmd) - session.Broadcast().EntityMetadata(session, newmd) - } -} diff --git a/server/session/std/handler/setCreativeModeSlot.go b/server/session/std/handler/setCreativeModeSlot.go deleted file mode 100644 index 812efeb6..00000000 --- a/server/session/std/handler/setCreativeModeSlot.go +++ /dev/null @@ -1,41 +0,0 @@ -package handler - -import ( - "github.com/zeppelinmc/zeppelin/protocol/net" - "github.com/zeppelinmc/zeppelin/protocol/net/packet" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/protocol/text" - "github.com/zeppelinmc/zeppelin/server/session/std" - "github.com/zeppelinmc/zeppelin/server/world/level" - "github.com/zeppelinmc/zeppelin/server/world/level/item" -) - -func init() { - std.RegisterHandler(net.PlayState, play.PacketIdSetCreativeModeSlot, handleSetCreativeSlot) -} - -func handleSetCreativeSlot(s *std.StandardSession, pk packet.Decodeable) { - scs, ok := pk.(*play.SetCreativeModeSlot) - if !ok { - return - } - // out of bounds - if scs.Slot < 0 || scs.Slot > 45 { - s.Disconnect(text.Unmarshalf(s.Config().ChatFormatter.Rune(), "Creative mode slot out of bounds (expected 0 8 { - session.Disconnect(text.TextComponent{Text: "Invalid slot"}) - } - session.Player().SetSelectedItemSlot(int32(pk.Slot)) - } -} diff --git a/server/session/std/handler/swingArm.go b/server/session/std/handler/swingArm.go deleted file mode 100644 index 85333cf4..00000000 --- a/server/session/std/handler/swingArm.go +++ /dev/null @@ -1,26 +0,0 @@ -package handler - -import ( - "github.com/zeppelinmc/zeppelin/protocol/net" - "github.com/zeppelinmc/zeppelin/protocol/net/packet" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/server/session/std" -) - -func init() { - std.RegisterHandler(net.PlayState, play.PacketIdSwingArm, handleSwingArm) -} - -func handleSwingArm(session *std.StandardSession, pk packet.Decodeable) { - swing, ok := pk.(*play.SwingArm) - if !ok { - return - } - - var id byte - if swing.Hand == 1 { - id = 3 - } - - session.Broadcast().Animation(session, id) -} diff --git a/server/session/std/handler/useItemOn.go b/server/session/std/handler/useItemOn.go deleted file mode 100644 index 0f3507bf..00000000 --- a/server/session/std/handler/useItemOn.go +++ /dev/null @@ -1,113 +0,0 @@ -package handler - -import ( - "fmt" - "math" - - "github.com/zeppelinmc/zeppelin/protocol/net" - "github.com/zeppelinmc/zeppelin/protocol/net/metadata" - "github.com/zeppelinmc/zeppelin/protocol/net/packet" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/server/session/std" - "github.com/zeppelinmc/zeppelin/server/world/block" - "github.com/zeppelinmc/zeppelin/server/world/block/pos" - "github.com/zeppelinmc/zeppelin/server/world/level/item" - "github.com/zeppelinmc/zeppelin/util" -) - -func init() { - std.RegisterHandler(net.PlayState, play.PacketIdUseItemOn, handleUseItemOn) -} - -func handleUseItemOn(s *std.StandardSession, pk packet.Decodeable) { - use, ok := pk.(*play.UseItemOn) - if !ok { - return - } - dimension := s.Dimension() - - x1, y1, z1 := s.Player().Position() - x2, y2, z2 := float64(use.BlockX), float64(use.BlockY), float64(use.BlockZ) - - distance := math.Sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2)) - if distance > 4 { - return - } - - currentBlockLook, err := dimension.Block(use.BlockX, use.BlockY, use.BlockZ) - if err != nil { - return - } - - usable, ok := currentBlockLook.(block.Usable) - if ok && s.Player().MetadataIndex(metadata.PoseIndex) != metadata.Sneaking { - usable.Use(s, *use, dimension) - return - } - - itemInHand, ok := s.Player().Inventory().Slot(item.DataSlot(s.Player().SelectedItemSlot())) - if !ok || itemInHand.Is(item.Air) { - return - } - if itemInHand.IsTag("beds") { - fmt.Println("is placing bed ") - } - blockSet, ok := itemInHand.Block() - if !ok { - return - } - - var blockX, blockY, blockZ = use.BlockX, use.BlockY, use.BlockZ - yaw, _ := s.Player().Rotation() - - var axis block.Axis - var facing block.Direction - - switch use.Face { - case play.FaceBottom: - blockY-- - axis, facing = "y", util.YawDirection(yaw) - case play.FaceTop: - blockY++ - axis, facing = "y", util.YawDirection(yaw) - case play.FaceNorth: - blockZ-- - axis, facing = "z", "north" - case play.FaceSouth: - blockZ++ - axis, facing = "z", "south" - case play.FaceWest: - blockX-- - axis, facing = "x", "west" - case play.FaceEast: - blockX++ - axis, facing = "x", "east" - } - - replaceable := block.Is(currentBlockLook, "minecraft:replaceable") - - if replaceable { - blockX, blockY, blockZ = use.BlockX, use.BlockY, use.BlockZ - } - - currentBlock, err := dimension.Block(blockX, blockY, blockZ) - if err == nil { - name, _ := currentBlock.Encode() - if name != "minecraft:air" { - return - } - } - - blockSet = blockSet.New(map[string]string{"axis": axis, "facing": facing}) - - s.WritePacket(&play.AcknowledgeBlockChange{SequenceId: use.Sequence}) - pos := pos.New(blockX, blockY, blockZ) - - dimension.SetBlock(pos, blockSet, true) - - blockEntityHaver, ok := blockSet.(block.BlockEntityHaver) - if !ok { - return - } - dimension.SetBlockEntity(pos, blockEntityHaver.BlockEntity(pos)) -} diff --git a/server/session/std/session.go b/server/session/std/session.go deleted file mode 100644 index 0ea19ea3..00000000 --- a/server/session/std/session.go +++ /dev/null @@ -1,649 +0,0 @@ -package std - -import ( - "encoding/base64" - "encoding/json" - "fmt" - nnet "net" - "slices" - "sync" - "sync/atomic" - - "github.com/google/uuid" - "github.com/zeppelinmc/zeppelin/protocol/net" - "github.com/zeppelinmc/zeppelin/protocol/net/io/encoding" - "github.com/zeppelinmc/zeppelin/protocol/net/metadata" - "github.com/zeppelinmc/zeppelin/protocol/net/packet" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/configuration" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/login" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/protocol/net/tags" - "github.com/zeppelinmc/zeppelin/protocol/properties" - "github.com/zeppelinmc/zeppelin/protocol/text" - "github.com/zeppelinmc/zeppelin/server/command" - "github.com/zeppelinmc/zeppelin/server/entity" - "github.com/zeppelinmc/zeppelin/server/player" - "github.com/zeppelinmc/zeppelin/server/registry" - "github.com/zeppelinmc/zeppelin/server/session" - "github.com/zeppelinmc/zeppelin/server/tick" - "github.com/zeppelinmc/zeppelin/server/world" - "github.com/zeppelinmc/zeppelin/server/world/block" - "github.com/zeppelinmc/zeppelin/server/world/block/pos" - "github.com/zeppelinmc/zeppelin/server/world/chunk" - "github.com/zeppelinmc/zeppelin/server/world/chunk/section" - "github.com/zeppelinmc/zeppelin/server/world/dimension" - "github.com/zeppelinmc/zeppelin/server/world/dimension/window" - "github.com/zeppelinmc/zeppelin/server/world/level" - "github.com/zeppelinmc/zeppelin/server/world/level/item" - "github.com/zeppelinmc/zeppelin/util" - a "github.com/zeppelinmc/zeppelin/util/atomic" -) - -var _ session.Session = (*StandardSession)(nil) - -// StandardSession is a session that uses *net.Conn -type StandardSession struct { - World *world.World - player *player.Player - broadcast *session.Broadcast - config properties.ServerProperties - - Input Input - ChunkLoadWorker *ChunkLoadWorker - - conn *net.Conn - - clientName string // constant - ClientInfo a.AtomicValue[configuration.ClientInformation] - - statusProviderProvider func() net.StatusProvider - - hasSessionData atomic.Bool - sessionData a.AtomicValue[play.PlayerSession] - - spawned_ents_mu sync.Mutex - spawnedEntities []int32 - - commandManager *command.Manager - - registryIndexes map[string][]string - - // the index that should be sent in player chat messages - ChatIndex atomic.Int32 - - inBundle atomic.Bool - - AwaitingTeleportAcknowledgement, - awaitingChunkBatchAcknowledgement atomic.Bool - - // the time in milliseconds that the keep alive packet was sent to the server from the client - sbLastKeepalive atomic.Int64 - // the time in milliseconds that the keep alive packet was sent to the client from the server - cbLastKeepAlive atomic.Int64 - - load_ch_mu sync.RWMutex - loadedChunks map[uint64]struct{} - - listed atomic.Bool - - tick *tick.TickManager - - stopTick chan struct{} - - // the window id the client is viewing currently, 0 if none (inventory) - WindowView atomic.Int32 - - // the window state id for this client - StateID atomic.Int32 - - CarriedItem item.Item - - chunksPerTick atomic.Int32 -} - -func (s *StandardSession) Latency() int64 { - return s.sbLastKeepalive.Load() - s.cbLastKeepAlive.Load() -} - -func New( - conn *net.Conn, - player *player.Player, - world *world.World, - broadcast *session.Broadcast, - config properties.ServerProperties, - statusProviderProvider func() net.StatusProvider, - commandManager *command.Manager, - tickManager *tick.TickManager, -) *StandardSession { - s := &StandardSession{ - conn: conn, - World: world, - player: player, - broadcast: broadcast, - config: config, - statusProviderProvider: statusProviderProvider, - commandManager: commandManager, - loadedChunks: make(map[uint64]struct{}), - - tick: tickManager, - stopTick: make(chan struct{}), - - registryIndexes: make(map[string][]string), - } - s.listed.Store(true) - s.ChunkLoadWorker = NewChunkLoadWorker(s) - - s.Input.SetPosition(s.player.Position()) - s.Input.SetRotation(s.player.Rotation()) - s.Input.SetOnGround(s.player.OnGround()) - - return s -} - -func (session *StandardSession) CommandManager() *command.Manager { - return session.commandManager -} - -func (session *StandardSession) WritePacket(pk packet.Encodeable) error { - if PacketWriteInterceptor != nil { - if PacketWriteInterceptor(session, pk) { - return nil - } - } - return session.conn.WritePacket(pk) -} - -func (session *StandardSession) ReadPacket() (pk packet.Decodeable, interceptStop bool, err error) { - return session.conn.ReadPacket() -} - -func (session *StandardSession) Listed() bool { - return session.listed.Load() -} - -func (session *StandardSession) SetListed(v bool) { - session.listed.Store(v) -} - -func (session *StandardSession) SynchronizePosition(x, y, z float64, yaw, pitch float32) error { - session.player.SetPosition(x, y, z) - session.player.SetRotation(yaw, pitch) - session.AwaitingTeleportAcknowledgement.Store(true) - return session.WritePacket(&play.SynchronizePlayerPosition{X: x, Y: y, Z: z, Yaw: yaw, Pitch: pitch}) -} - -func (session *StandardSession) UpdateEntityPosition(entity entity.Entity, pk *play.UpdateEntityPosition) error { - return session.WritePacket(pk) -} - -// additionally sends head rotation -func (session *StandardSession) UpdateEntityPositionRotation(entity entity.Entity, pk *play.UpdateEntityPositionAndRotation) error { - if err := session.WritePacket(pk); err != nil { - return err - } - return session.WritePacket(&play.SetHeadRotation{EntityId: pk.EntityId, HeadYaw: pk.Yaw}) -} - -// additionally sends head rotation -func (session *StandardSession) UpdateEntityRotation(entity entity.Entity, pk *play.UpdateEntityRotation) error { - if err := session.WritePacket(pk); err != nil { - return err - } - return session.WritePacket(&play.SetHeadRotation{EntityId: pk.EntityId, HeadYaw: pk.Yaw}) -} - -func (session *StandardSession) EntityAnimation(entityId int32, animation byte) error { - return session.WritePacket(&play.EntityAnimation{EntityId: entityId, Animation: animation}) -} - -func (session *StandardSession) EntityMetadata(entityId int32, md metadata.Metadata) error { - return session.WritePacket(&play.SetEntityMetadata{EntityId: entityId, Metadata: md}) -} - -func (session *StandardSession) Conn() *net.Conn { - return session.conn -} - -func (session *StandardSession) Config() properties.ServerProperties { - return session.config -} - -func (session *StandardSession) Broadcast() *session.Broadcast { - return session.broadcast -} - -func (session *StandardSession) Player() *player.Player { - return session.player -} - -func (session *StandardSession) Addr() nnet.Addr { - return session.conn.RemoteAddr() -} - -func (session *StandardSession) ClientName() string { - return session.clientName -} - -func (session *StandardSession) ClientInformation() configuration.ClientInformation { - return session.ClientInfo.Get() -} - -func (session *StandardSession) Username() string { - return session.conn.Username() -} - -func (session *StandardSession) UUID() uuid.UUID { - return session.conn.UUID() -} - -func (session *StandardSession) Properties() []login.Property { - return session.conn.Properties() -} - -func (session *StandardSession) SessionData() (play.PlayerSession, bool) { - return session.sessionData.Get(), session.hasSessionData.Load() -} - -func (session *StandardSession) PlayerInfoUpdate(pk *play.PlayerInfoUpdate) error { - return session.WritePacket(pk) -} - -func (session *StandardSession) PlayerInfoRemove(uuids ...uuid.UUID) error { - return session.WritePacket(&play.PlayerInfoRemove{UUIDs: uuids}) -} - -func (session *StandardSession) Disconnect(reason text.TextComponent) error { - if session.inConfiguration() { - session.WritePacket(&configuration.Disconnect{Reason: reason}) - } else { - session.WritePacket(&play.Disconnect{Reason: reason}) - } - return session.conn.Close() -} - -// finishes configuration -func (session *StandardSession) Configure() error { - go session.handlePackets() - if err := session.WritePacket(&configuration.ClientboundPluginMessage{ - Channel: "minecraft:brand", - Data: encoding.AppendString(nil, "Zeppelin"), - }); err != nil { - return err - } - configuration.RegistryPacketsMutex.Lock() - for _, packet := range configuration.RegistryPackets { - if err := session.WritePacket(packet); err != nil { - return err - } - session.registryIndexes[packet.RegistryId] = slices.Clone(packet.Indexes) - } - configuration.RegistryPacketsMutex.Unlock() - - if err := session.WritePacket(configuration.FinishConfiguration{}); err != nil { - return err - } - - if err := session.WritePacket(tags.Tags); err != nil { - return err - } - return nil -} - -func (session *StandardSession) login() error { - if err := session.WritePacket(&play.Login{ - EntityID: session.player.EntityId(), - Dimensions: []string{session.player.Dimension()}, - - Hardcore: session.World.Data.Hardcore, - - ViewDistance: int32(session.config.ViewDistance), - SimulationDistance: int32(session.config.SimulationDistance), - - HashedSeed: session.World.Data.WorldGenSettings.Seed.Hash(), - - EnableRespawnScreen: true, - DimensionType: int32(slices.Index(session.registryIndexes["minecraft:dimension_type"], session.Dimension().Type())), - DimensionName: session.player.Dimension(), - GameMode: byte(session.player.GameMode()), - - EnforcesSecureChat: session.config.EnforceSecureProfile, - }); err != nil { - return err - } - - if err := session.WritePacket(&play.ChangeDifficulty{ - Difficulty: session.World.Data.Difficulty, - Locked: session.World.Data.DifficultyLocked, - }); err != nil { - return err - } - - movementSpeed := session.player.Attribute("minecraft:generic.movement_speed") - if movementSpeed == nil { - movementSpeed = &entity.Attribute{ - Id: "minecraft:generic.movement_speed", - Base: 0.1, - } - session.player.SetAttribute("minecraft:generic.movement_speed", 0.1) - } - - if err := session.WritePacket( - session.player.Abilities().Encode(float32(movementSpeed.Base)), - ); err != nil { - return err - } - - if err := session.WritePacket(&play.SetHeldItemClientbound{Slot: int8(session.player.SelectedItemSlot())}); err != nil { - return err - } - - recipeBook := session.player.RecipeBook() - - if err := session.WritePacket(&play.UpdateRecipeBook{ - Action: play.UpdateRecipeBookActionInit, - CraftingRecipeBookOpen: recipeBook.IsGuiOpen, - CraftingRecipeBookFilterActive: recipeBook.IsFilteringCraftable, - - SmeltingRecipeBookOpen: recipeBook.IsFurnaceGuiOpen, - SmeltingRecipeBookFilterActive: recipeBook.IsFurnaceFilteringCraftable, - - BlastFurnaceRecipeBookOpen: recipeBook.IsBlastingFurnaceGuiOpen, - BlastFurnaceRecipeBookFilterActive: recipeBook.IsBlastingFurnaceFilteringCraftable, - - SmokerRecipeBookOpen: recipeBook.IsSmokerGuiOpen, - SmokerRecipeBookFilterActive: recipeBook.IsSmokerFilteringCraftable, - - Array1: recipeBook.ToBeDisplayed, - Array2: recipeBook.Recipes, - }); err != nil { - return err - } - - if err := session.WritePacket(session.commandManager.Encode()); err != nil { - return err - } - - status := session.statusProviderProvider()(session.conn) - if err := session.WritePacket(&play.ServerData{ - MOTD: status.Description, - Icon: status.Favicon, - }); err != nil { - return err - } - - session.broadcast.AddPlayer(session) - - if err := session.sendTime(); err != nil { - return err - } - - if err := session.WritePacket(&play.SetDefaultSpawnPosition{ - X: session.World.Data.SpawnX, - Y: session.World.Data.SpawnY, - Z: session.World.Data.SpawnZ, - Angle: session.World.Data.SpawnAngle, - }); err != nil { - return err - } - - if err := session.initializeTicker(); err != nil { - return err - } - - x, y, z := session.player.Position() - yaw, pitch := session.player.Rotation() - - if err := session.SynchronizePosition(x, y, z, yaw, pitch); err != nil { - return err - } - - if err := session.sendSpawnChunks(); err != nil { - return err - } - - if err := session.WritePacket(&play.GameEvent{Event: play.GameEventStartWaitingChunks}); err != nil { - return err - } - - if err := session.SynchronizePosition(x, y, z, yaw, pitch); err != nil { - return err - } - - if err := session.SendInventory(); err != nil { - return err - } - - session.broadcast.SpawnPlayer(session) - return nil -} - -func (session *StandardSession) SetTickState(tps float32, frozen bool) error { - return session.WritePacket(&play.SetTickingState{TickRate: tps, IsFrozen: frozen}) -} - -func (session *StandardSession) IsSpawned(entityId int32) bool { - session.spawned_ents_mu.Lock() - defer session.spawned_ents_mu.Unlock() - for _, e := range session.spawnedEntities { - if e == entityId { - return true - } - } - return false -} - -func (session *StandardSession) Dimension() *dimension.Dimension { - return session.World.Dimension(session.player.Dimension()) -} - -/* -The view distance of the client, in chunks - -Returns the server's render distance if the client's view distance is bigger or not set -*/ -func (session *StandardSession) ViewDistance() int32 { - plVd := int32(session.ClientInformation().ViewDistance) - if plVd == 0 || plVd > int32(session.config.ViewDistance) { - return int32(session.config.ViewDistance) - } - - return plVd -} - -func (session *StandardSession) DespawnEntities(entityIds ...int32) error { - session.spawned_ents_mu.Lock() - defer session.spawned_ents_mu.Unlock() - session.spawnedEntities = slices.DeleteFunc(session.spawnedEntities, func(entityId int32) bool { - for _, e := range entityIds { - if e == entityId { - return true - } - } - return false - }) - return session.WritePacket(&play.RemoveEntities{EntityIDs: entityIds}) -} - -func (session *StandardSession) bundleStart() error { - if session.inBundle.Load() { - return nil - } - session.inBundle.Store(true) - return session.WritePacket(&play.BundleDelimiter{}) -} - -func (session *StandardSession) bundleStop() error { - if !session.inBundle.Load() { - return nil - } - session.inBundle.Store(false) - return session.WritePacket(&play.BundleDelimiter{}) -} - -func (session *StandardSession) SpawnEntity(e entity.Entity) error { - if err := session.bundleStart(); err != nil { - return err - } - x, y, z := e.Position() - yaw, pitch := e.Rotation() - id := e.EntityId() - - if err := session.WritePacket(&play.SpawnEntity{ - EntityId: id, - EntityUUID: e.UUID(), - Type: e.Type(), - X: x, - Y: y, - Z: z, - Yaw: util.DegreesToAngle(yaw), - Pitch: util.DegreesToAngle(pitch), - HeadYaw: util.DegreesToAngle(yaw), - }); err != nil { - return err - } - - session.spawned_ents_mu.Lock() - defer session.spawned_ents_mu.Unlock() - session.spawnedEntities = append(session.spawnedEntities, id) - - if err := session.WritePacket(&play.SetEntityMetadata{ - EntityId: id, - Metadata: e.Metadata(), - }); err != nil { - return err - } - - if err := session.bundleStop(); err != nil { - return err - } - - return nil -} - -func (session *StandardSession) UpdateBlock(pos pos.BlockPosition, b block.Block) error { - state, ok := section.BlockStateId(b) - if !ok { - return fmt.Errorf("invalid block") - } - x, y, z := pos.X(), pos.Y(), pos.Z() - return session.WritePacket(&play.BlockUpdate{ - X: x, Y: y, Z: z, - BlockId: state, - }) -} - -func (session *StandardSession) UpdateBlockEntity(pos pos.BlockPosition, be chunk.BlockEntity) error { - id, ok := registry.BlockEntityType.Lookup(be.Id) - if !ok { - return fmt.Errorf("invalid block entity") - } - x, y, z := pos.X(), pos.Y(), pos.Z() - return session.WritePacket(&play.BlockEntityData{ - X: x, Y: y, Z: z, - Type: id, - Data: be, - }) -} - -func (session *StandardSession) SpawnPlayer(ses session.Session) error { - return session.SpawnEntity(ses.Player()) -} - -func (session *StandardSession) SetGameMode(gm level.GameMode) error { - session.player.SetGameMode(gm) - return session.WritePacket(&play.GameEvent{ - Event: play.GameEventChangeGamemode, - Value: float32(gm), - }) -} - -func (session *StandardSession) DamageEvent(attacker, attacked session.Session, damageType string) error { - causeType := slices.Index(session.registryIndexes["minecraft:damage_type"], damageType) - if causeType == -1 { - return fmt.Errorf("unknown damage type") - } - de := &play.DamageEvent{ - SourceTypeId: int32(causeType), - } - if attacker != nil { - id := attacker.Player().EntityId() - de.SourceCauseId = id - de.SourceDirectId = id - } - if err := session.WritePacket(de); err != nil { - return err - } - return session.WritePacket(&play.HurtAnimation{ - EntityId: attacked.Player().EntityId(), - }) -} - -func (session *StandardSession) UpdateTime(worldAge, dayTime int64) error { - return session.WritePacket(&play.UpdateTime{WorldAge: worldAge, TimeOfDay: dayTime}) -} - -func (session *StandardSession) DeleteMessage(id int32, sig [256]byte) error { - return session.WritePacket(&play.DeleteMessage{MessageId: id, Signature: sig}) -} - -func (session *StandardSession) SendInventory() error { - return session.WritePacket(&play.SetContainerContent{ - StateId: session.StateID.Add(1), - Slots: session.player.Inventory().EncodeResize(46), - }) -} - -func (session *StandardSession) SetContainerContent(container window.Window) error { - return session.WritePacket(&play.SetContainerContent{ - StateId: session.StateID.Add(1), - WindowID: byte(container.Id), - Slots: container.Items.Encode(), - }) -} - -func (session *StandardSession) OpenWindow(w *window.Window) error { - if curw := session.WindowView.Load(); curw != 0 { - return fmt.Errorf("window %d already open for client", curw) - } - session.WindowView.Store(w.Id) - - err := session.WritePacket(&play.OpenScreen{ - WindowId: w.Id, - WindowType: registry.Menu.Get(w.Type), - WindowTitle: w.Title, - }) - if err != nil { - return err - } - - w.Viewers++ - - return session.SetContainerContent(*w) -} - -func (session *StandardSession) Textures() (login.Textures, error) { - var textures login.Textures - properties := session.Properties() - if len(properties) == 0 { - return textures, fmt.Errorf("client has no textures") - } - property := properties[0].Value - data, err := base64.StdEncoding.DecodeString(property) - if err != nil { - return textures, err - } - err = json.Unmarshal(data, &textures) - return textures, err -} - -func (session *StandardSession) BlockAction(pk *play.BlockAction) error { - return session.WritePacket(pk) -} - -func (session *StandardSession) PlaySound(pk *play.SoundEffect) error { - return session.WritePacket(pk) -} - -func (session *StandardSession) PlayEntitySound(pk *play.EntitySoundEffect) error { - return session.WritePacket(pk) -} diff --git a/server/session/std/tick.go b/server/session/std/tick.go deleted file mode 100644 index 5f4f66a9..00000000 --- a/server/session/std/tick.go +++ /dev/null @@ -1,161 +0,0 @@ -package std - -import ( - "math" - "sync/atomic" - "time" - - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/protocol/text" - "github.com/zeppelinmc/zeppelin/util/log" -) - -func chunkPos(x, z float64) (cx, cz int32) { - return int32(math.Floor(x / 16)), int32(math.Floor(z / 16)) -} - -type Input struct { - x, y, z atomic.Uint64 - yaw, pitch atomic.Uint32 - onGround atomic.Bool -} - -func (i *Input) SetPosition(x, y, z float64) { - i.x.Store(math.Float64bits(x)) - i.y.Store(math.Float64bits(y)) - i.z.Store(math.Float64bits(z)) -} - -func (i *Input) SetRotation(yaw, pitch float32) { - i.yaw.Store(math.Float32bits(yaw)) - i.pitch.Store(math.Float32bits(pitch)) -} - -func (i *Input) SetOnGround(b bool) { - i.onGround.Store(b) -} - -func (i *Input) Position() (x, y, z float64) { - return math.Float64frombits(i.x.Load()), math.Float64frombits(i.y.Load()), math.Float64frombits(i.z.Load()) -} - -func (i *Input) Rotation() (yaw, pitch float32) { - return math.Float32frombits(i.yaw.Load()), math.Float32frombits(i.pitch.Load()) -} - -func (i *Input) OnGround() bool { - return i.onGround.Load() -} - -func (session *StandardSession) initializeTicker() error { - freq := session.tick.Frequency() - ticker := time.NewTicker(freq) - session.tick.Add(ticker) - if err := session.conn.WritePacket(&play.SetTickingState{TickRate: 1 / (float32(freq) / float32(time.Second)), IsFrozen: false}); err != nil { - return err - } - if err := session.conn.WritePacket(&play.StepTick{}); err != nil { - return err - } - go func() { - var tick uint - - for { - select { - case <-session.stopTick: - ticker.Stop() - session.tick.Remove(ticker) - return - case <-ticker.C: - if err := session.processInput(); err != nil { - log.Errorlnf("%sPlayer %s disconnected (tick error: failed to process input: %v) (on tick %d)", log.FormatAddr(session.config.LogIPs, session.Addr()), session.Username(), err, tick) - session.Disconnect(text.Sprint("Tick error")) - return - } - if tick%20 == 0 { - if err := session.sendTime(); err != nil { - log.Errorlnf("%sPlayer %s disconnected (tick error: failed to update time: %v) (on tick %d)", log.FormatAddr(session.config.LogIPs, session.Addr()), session.Username(), err, tick) - session.Disconnect(text.Sprint("Tick error")) - return - } - } - - tick++ - } - } - }() - - return nil -} - -func (session *StandardSession) sendTime() error { - w, d := session.World.Time() - return session.conn.WritePacket(&play.UpdateTime{WorldAge: w, TimeOfDay: d}) -} - -func (session *StandardSession) processInput() error { - x, y, z, yaw, pitch, onGround := session.input() - oldX, oldY, oldZ, oldYaw, oldPitch, oldOnGround := session.state() - - posC, rotC, onC := session.inputUpdated(x, y, z, yaw, pitch, onGround, oldX, oldY, oldZ, oldYaw, oldPitch, oldOnGround) - if !posC && !rotC && !onC { - return nil - } - - if posC { - oldChunkPosX, oldChunkPosZ := chunkPos(oldX, oldZ) - newChunkPosX, newChunkPosZ := chunkPos(x, z) - - if oldChunkPosX != newChunkPosX || oldChunkPosZ != newChunkPosZ { - if err := session.WritePacket(&play.SetCenterChunk{ChunkX: newChunkPosX, ChunkZ: newChunkPosZ}); err != nil { - return err - } - session.ChunkLoadWorker.SendChunksRadius(newChunkPosX, newChunkPosZ, 0) - } - - distance := math.Sqrt((x-oldX)*(x-oldX) + (y-oldY)*(y-oldY) + (z-oldZ)*(z-oldZ)) - - if distance > 100 { - if err := session.SynchronizePosition(oldX, oldY, oldZ, oldYaw, oldPitch); err != nil { - return err - } - log.Infolnf("%s moved too quickly! (%f %f %f)", session.Username(), x-oldX, y-oldY, z-oldZ) - return nil - } - defer session.player.SetPosition(x, y, z) - } - if rotC { - defer session.player.SetRotation(yaw, pitch) - } - if onC { - defer session.player.SetOnGround(onGround) - } - - session.broadcast.BroadcastPlayerMovement(session, x, y, z, yaw, pitch) - - return nil -} - -func (session *StandardSession) inputUpdated( - x, y, z float64, yaw, pitch float32, onGround bool, - oldX, oldY, oldZ float64, oldYaw, oldPitch float32, oldOnGround bool, -) (posChanged, rotChanged, onGroundChanged bool) { - - return x != oldX || y != oldY || z != oldZ, yaw != oldYaw || pitch != oldPitch, onGround != oldOnGround -} - -func (session *StandardSession) input() (x, y, z float64, yaw, pitch float32, onGround bool) { - x, y, z = session.Input.Position() - yaw, pitch = session.Input.Rotation() - onGround = session.Input.OnGround() - - return -} - -func (session *StandardSession) state() (oldX, oldY, oldZ float64, oldYaw, oldPitch float32, oldOnGround bool) { - oldX, oldY, oldZ = session.player.Position() - oldYaw, oldPitch = session.player.Rotation() - oldOnGround = session.player.OnGround() - - return -} diff --git a/server/tick/tick.go b/server/tick/tick.go index 1965d0c6..af69eb0e 100644 --- a/server/tick/tick.go +++ b/server/tick/tick.go @@ -5,15 +5,13 @@ import ( "sync" "sync/atomic" "time" - - "github.com/google/uuid" - "github.com/zeppelinmc/zeppelin/server/session" + //"github.com/zeppelinmc/zeppelin/server/session" ) // New creates a new tick manager with tps ticks per second -func New(tps int, b *session.Broadcast) *TickManager { +func New(tps int /*b *session.Broadcast*/) *TickManager { mgr := &TickManager{ - b: b, + //b: b, } mgr.d.Store(int64(time.Second / time.Duration(tps))) @@ -26,7 +24,7 @@ type TickManager struct { mu sync.RWMutex d atomic.Int64 - b *session.Broadcast + //b *session.Broadcast } func (mgr *TickManager) AddNew(f func()) { @@ -53,10 +51,10 @@ func (mgr *TickManager) SetFrequency(tps int) error { ticker.Reset(d) } - mgr.b.Range(func(u uuid.UUID, s session.Session) bool { + /*mgr.b.Range(func(u uuid.UUID, s session.Session) bool { s.SetTickState(float32(tps), false) return true - }) + })*/ return nil } @@ -65,10 +63,10 @@ func (mgr *TickManager) Freeze() { for _, ticker := range mgr.tickers { ticker.Stop() } - mgr.b.Range(func(u uuid.UUID, s session.Session) bool { + /*mgr.b.Range(func(u uuid.UUID, s session.Session) bool { s.SetTickState(0, true) return true - }) + })*/ } func (mgr *TickManager) Unfreeze() { @@ -76,11 +74,11 @@ func (mgr *TickManager) Unfreeze() { for _, ticker := range mgr.tickers { ticker.Reset(freq) } - tps := 1 / (float32(freq) / float32(time.Second)) - mgr.b.Range(func(u uuid.UUID, s session.Session) bool { + //tps := 1 / (float32(freq) / float32(time.Second)) + /*mgr.b.Range(func(u uuid.UUID, s session.Session) bool { s.SetTickState(tps, false) return true - }) + })*/ } func (mgr *TickManager) Add(ticker *time.Ticker) { diff --git a/server/world/block/0block.go b/server/world/block/0block.go index 9de5d6ee..0d2e58ee 100644 --- a/server/world/block/0block.go +++ b/server/world/block/0block.go @@ -7,7 +7,8 @@ import ( "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" "github.com/zeppelinmc/zeppelin/protocol/net/tags" "github.com/zeppelinmc/zeppelin/server/registry" - "github.com/zeppelinmc/zeppelin/server/session" + + //"github.com/zeppelinmc/zeppelin/server/session" "github.com/zeppelinmc/zeppelin/server/world/block/pos" "github.com/zeppelinmc/zeppelin/server/world/chunk" "github.com/zeppelinmc/zeppelin/server/world/chunk/section" @@ -43,10 +44,10 @@ func atoi(str string) int { // A usable block is a block which performs a certain action when left clicked type Usable interface { Block - Use(clicker session.Session, pk play.UseItemOn, dimension *dimension.Dimension) + Use(clicker any, pk play.UseItemOn, dimension *dimension.Dimension) } -// A block entity haver is one that also has a block entity +// A block state haver is one that also has a block state type BlockEntityHaver interface { Block BlockEntity(pos.BlockPosition) chunk.BlockEntity diff --git a/server/world/block/blockstates/dec.go b/server/world/block/blockstates/dec.go deleted file mode 100644 index 8320dfb3..00000000 --- a/server/world/block/blockstates/dec.go +++ /dev/null @@ -1,124 +0,0 @@ -// package blockstates provides parsing of the custom format for storing block states -package blockstates - -import ( - "encoding/binary" - "fmt" - "io" - "unsafe" -) - -type BlockLocation struct { - Offset, Size int32 -} - -type BlockState struct { - Id int32 - Properties map[string]string -} - -type Block []BlockState - -// ReadBlock reads the block states at the offset and size -func ReadBlock(f io.ReaderAt, loc BlockLocation) (Block, error) { - var blockStates Block - - limiter := io.NewSectionReader(f, int64(loc.Offset), int64(loc.Size)) - - var stateCount uint16 - if err := binary.Read(limiter, binary.BigEndian, &stateCount); err != nil { - return blockStates, err - } - - blockStates = make(Block, stateCount) - - var stringlen = make([]byte, 1) - - for i := range blockStates { - var ( - blockStateId int32 - propertyCount uint8 - ) - if err := binary.Read(limiter, binary.BigEndian, &blockStateId); err != nil { - return blockStates, err - } - if err := binary.Read(limiter, binary.BigEndian, &propertyCount); err != nil { - return blockStates, err - } - - blockStates[i].Id = blockStateId - blockStates[i].Properties = make(map[string]string, propertyCount) - - for j := 0; j < int(propertyCount); j++ { - propertyName, err := readString(limiter, stringlen) - if err != nil { - return blockStates, nil - } - propertyValue, err := readString(limiter, stringlen) - if err != nil { - return blockStates, nil - } - blockStates[i].Properties[propertyName] = propertyValue - } - } - - return blockStates, nil -} - -var magic = [...]byte{0x0F, 0x06, 0x60, 0xF0} - -// ReadHeader reads the header of the block states format. The header contains locations for each block -func ReadHeader(f io.Reader) (map[string]BlockLocation, error) { - var rmagic [4]byte - if _, err := f.Read(rmagic[:]); err != nil { - return nil, err - } - if rmagic != magic { - return nil, fmt.Errorf("invalid magic header") - } - - var locations_tmp [8]byte - - if _, err := f.Read(locations_tmp[:4]); err != nil { - return nil, err - } - - blockCount := int32(locations_tmp[0])<<24 | int32(locations_tmp[1])<<16 | int32(locations_tmp[2])<<8 | int32(locations_tmp[3]) - - var locations = make(map[string]BlockLocation, blockCount) - - var strlen = make([]byte, 1) - for i := 0; i < int(blockCount); i++ { - name, err := readString(f, strlen) - if err != nil { - return nil, err - } - - var location BlockLocation - - if _, err := f.Read(locations_tmp[:]); err != nil { - return nil, err - } - location.Offset = int32(locations_tmp[0])<<24 | int32(locations_tmp[1])<<16 | int32(locations_tmp[2])<<8 | int32(locations_tmp[3]) - location.Size = int32(locations_tmp[4])<<24 | int32(locations_tmp[5])<<16 | int32(locations_tmp[6])<<8 | int32(locations_tmp[7]) - - locations[name] = location - } - - return locations, nil -} - -// reads a string prepended by a byte length, l should be a byte slice with a length of one, so make([]byte, 1) will work. nil will also work -func readString(f io.Reader, l []byte) (string, error) { - if l == nil { - l = make([]byte, 1) - } - if _, err := f.Read(l); err != nil { - return "", err - } - var strdata = make([]byte, l[0]) - if _, err := f.Read(strdata); err != nil { - return "", err - } - return unsafe.String(unsafe.SliceData(strdata), len(strdata)), nil -} diff --git a/server/world/block/blockstates/doc.txt b/server/world/block/blockstates/doc.txt deleted file mode 100644 index d5ad9e9c..00000000 --- a/server/world/block/blockstates/doc.txt +++ /dev/null @@ -1,30 +0,0 @@ -blockstates format (v0): - -data types: - byte- 1 byte, unsigned - (u)int16- 2 bytes, big endian (u=unsigned) - (u)int32- 4 bytes, big endian (u=unsigned) - string- prepended by a length (1 byte) - -file: - magic header: - 4 bytes (0x0F, 0x06, 0x60, 0xF0) - location table: - 4 bytes | count:int32 - - for 0...count: - min 1 byte | blockName:string - 4 bytes | offset:int32 - 4 bytes | size:int32 - - block (at offset): - 2 bytes | count:uint16 - - for 0...count: - 4 bytes | blockStateId:int32 - 1 byte | propertyCount:byte - for 0...propertyCount: - min 1 byte | propertyName: string - min 1 byte | propertyValue: string - -Last edited by oq, 20th August 2024 \ No newline at end of file diff --git a/server/world/block/blockstates/enc.go b/server/world/block/blockstates/enc.go deleted file mode 100644 index 0f89339c..00000000 --- a/server/world/block/blockstates/enc.go +++ /dev/null @@ -1,108 +0,0 @@ -package blockstates - -import ( - "bytes" - "encoding/binary" - "io" - "os" - "unsafe" - - "github.com/zeppelinmc/zeppelin/util/log" -) - -func Encode(f *os.File, blocks map[string]Block) error { - if _, err := f.Write(magic[:]); err != nil { - return err - } - - var buf = new(bytes.Buffer) - - var locations = make(map[string]BlockLocation, len(blocks)) - - for name, block := range blocks { - var loc = BlockLocation{Offset: int32(buf.Len())} - - if err := binary.Write(buf, binary.BigEndian, uint16(len(block))); err != nil { - return err - } - - for _, state := range block { - if err := binary.Write(buf, binary.BigEndian, state.Id); err != nil { - return err - } - if err := buf.WriteByte(byte(len(state.Properties))); err != nil { - return err - } - for name, value := range state.Properties { - if err := writeString(buf, name); err != nil { - return err - } - if err := writeString(buf, value); err != nil { - return err - } - } - } - - loc.Size = int32(buf.Len()) - loc.Offset - - if name == "minecraft:stone" { - log.Println(loc.Offset, loc.Size, buf.Bytes()[loc.Offset:loc.Offset+loc.Size]) - } - - locations[name] = loc - } - - i32 := calcheaderlen(locations) - - for i, loc := range locations { - loc.Offset += i32 - locations[i] = loc - } - - _, err := writeLocations(f, locations) - if err != nil { - return err - } - - _, err = buf.WriteTo(f) - - return err -} - -func calcheaderlen(loc map[string]BlockLocation) int32 { - i := 8 - - for name := range loc { - i += 1 + len(name) + 8 - } - - return int32(i) -} - -func writeLocations(f io.Writer, locs map[string]BlockLocation) (i int, err error) { - if err := binary.Write(f, binary.BigEndian, int32(len(locs))); err != nil { - return i, err - } - i += 4 - for name, loc := range locs { - if err := writeString(f, name); err != nil { - return i, err - } - i += 1 + len(name) - if err := binary.Write(f, binary.BigEndian, loc); err != nil { - return i, err - } - i += 8 - } - - return i, nil -} - -func writeString(f io.Writer, str string) error { - if _, err := f.Write([]byte{byte(len(str))}); err != nil { - return err - } - _, err := f.Write(unsafe.Slice(unsafe.StringData(str), len(str))) - - return err -} diff --git a/server/world/block/chest.go b/server/world/block/chest.go index 9038f0b2..ef869334 100644 --- a/server/world/block/chest.go +++ b/server/world/block/chest.go @@ -3,13 +3,9 @@ package block import ( "strconv" - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/protocol/text" "github.com/zeppelinmc/zeppelin/server/container" - "github.com/zeppelinmc/zeppelin/server/session" "github.com/zeppelinmc/zeppelin/server/world/block/pos" "github.com/zeppelinmc/zeppelin/server/world/chunk" - "github.com/zeppelinmc/zeppelin/server/world/dimension" ) type Chest struct { @@ -45,34 +41,35 @@ func (g Chest) BlockEntity(pos pos.BlockPosition) chunk.BlockEntity { } } -func (g Chest) PlaceSound(pos pos.BlockPosition) *play.SoundEffect { - return session.SoundEffect("minecraft:block.wood.place", false, nil, play.SoundCategoryBlock, pos.X(), pos.Y(), pos.Z(), 1, 1) -} +/* + func (g Chest) PlaceSound(pos pos.BlockPosition) *play.SoundEffect { + return session.SoundEffect("minecraft:block.wood.place", false, nil, play.SoundCategoryBlock, pos.X(), pos.Y(), pos.Z(), 1, 1) + } -func (g Chest) Use(clicker session.Session, pk play.UseItemOn, dimension *dimension.Dimension) { - w, ok := dimension.WindowManager.At(pk.BlockX, pk.BlockY, pk.BlockZ) - if !ok { - entity, ok := dimension.BlockEntity(pk.BlockX, pk.BlockY, pk.BlockZ) + func (g Chest) Use(clicker session.Session, pk play.UseItemOn, dimension *dimension.Dimension) { + w, ok := dimension.WindowManager.At(pk.BlockX, pk.BlockY, pk.BlockZ) if !ok { - return + state, ok := dimension.BlockEntity(pk.BlockX, pk.BlockY, pk.BlockZ) + if !ok { + return + } + if state.Id != "minecraft:chest" { + return + } + w = dimension.WindowManager.New("minecraft:generic_9x3", state.Id, state.Items, text.Sprint("Chest")) + dimension.WindowManager.AddWindow([3]int32{pk.BlockX, pk.BlockY, pk.BlockZ}, w) } - if entity.Id != "minecraft:chest" { - return - } - w = dimension.WindowManager.New("minecraft:generic_9x3", entity.Id, entity.Items, text.Sprint("Chest")) - dimension.WindowManager.AddWindow([3]int32{pk.BlockX, pk.BlockY, pk.BlockZ}, w) - } - oldViewers := w.Viewers + oldViewers := w.Viewers - clicker.OpenWindow(w) - clicker.Broadcast().BlockAction(pk.BlockX, pk.BlockY, pk.BlockZ, dimension.Name(), 1, w.Viewers) + clicker.OpenWindow(w) + clicker.Broadcast().BlockAction(pk.BlockX, pk.BlockY, pk.BlockZ, dimension.Name(), 1, w.Viewers) - if oldViewers == 0 && w.Viewers > 0 { // chest was opened - clicker.Broadcast().PlaySound(session.SoundEffect( - "minecraft:block.chest.open", false, nil, play.SoundCategoryBlock, pk.BlockX, pk.BlockY, pk.BlockZ, 1, 1, - ), dimension.Name()) + if oldViewers == 0 && w.Viewers > 0 { // chest was opened + clicker.Broadcast().PlaySound(session.SoundEffect( + "minecraft:block.chest.open", false, nil, play.SoundCategoryBlock, pk.BlockX, pk.BlockY, pk.BlockZ, 1, 1, + ), dimension.Name()) + } } -} - +*/ var _ Block = (*Chest)(nil) diff --git a/server/world/block/grassBlock.go b/server/world/block/grassBlock.go index aa7ebff1..2fee88bf 100644 --- a/server/world/block/grassBlock.go +++ b/server/world/block/grassBlock.go @@ -2,10 +2,6 @@ package block import ( "strconv" - - "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/server/session" - "github.com/zeppelinmc/zeppelin/server/world/block/pos" ) type GrassBlock struct { @@ -22,6 +18,7 @@ func (g GrassBlock) New(props BlockProperties) Block { return GrassBlock{Snowy: props["snowy"] == "true"} } -func (g GrassBlock) PlaceSound(pos pos.BlockPosition) *play.SoundEffect { +/*func (g GrassBlock) PlaceSound(pos pos.BlockPosition) *play.SoundEffect { return session.SoundEffect("minecraft:block.grass.place", false, nil, play.SoundCategoryBlock, pos.X(), pos.Y(), pos.Z(), 1, 1) } +*/ diff --git a/server/world/chunk/chunk.go b/server/world/chunk/chunk.go index dd411d4d..3477e69f 100644 --- a/server/world/chunk/chunk.go +++ b/server/world/chunk/chunk.go @@ -3,6 +3,7 @@ package chunk import ( "fmt" + "unsafe" "github.com/zeppelinmc/zeppelin/server/container" "github.com/zeppelinmc/zeppelin/server/world/chunk/heightmaps" @@ -27,108 +28,100 @@ type BlockEntity struct { Items container.Container `nbt:"Items,omitempty"` } -type Chunk struct { +type Chunk struct /*{ //LastModified int64 X, Y, Z int32 Heightmaps heightmaps.Heightmaps Sections []*section.Section BlockEntities []BlockEntity +}*/{ + DataVersion int32 + Heightmaps heightmaps.Heightmaps + InhabitedTime int64 + LastUpdate int64 + Status string + BlockEntities []BlockEntity `nbt:"block_entities,omitempty"` + + Sections []section.Section `nbt:"sections"` + + X int32 `nbt:"xPos"` + Y int32 `nbt:"yPos"` + Z int32 `nbt:"zPos"` } func NewChunk(x, z int32) Chunk { - var airBlock = section.GetBlock("minecraft:air") c := Chunk{ Y: MinChunkY, X: x, Z: z, //LastModified: time.Now().UnixMilli(), - Sections: make([]*section.Section, 24), + Sections: make([]section.Section, 24), } for i := range c.Sections { - c.Sections[i] = section.New( - int8(i-MinChunkY), - []section.Block{airBlock}, - nil, - []string{"minecraft:plains"}, - nil, - fullLightBuffer, - nil, - ) + c.Sections[i] = section.Section{ + Y: int8(i - MinChunkY), + BlockStates: section.AnvilBlockStates{ + Palette: []section.AnvilBlock{{Name: "minecraft:air"}}, + }, + Biomes: section.AnvilBiomes{ + Palette: []string{"minecraft:plains"}, + }, + SkyLight: *(*[]int8)(unsafe.Pointer(&fullLightBuffer)), + } } return c } // X and Z should be relative to the chunk (aka x&0x0f, z&0x0f), but Y should be absolute. -func (c *Chunk) Block(x, y, z int32) (section.Block, error) { - secIndex := (y >> 4) - c.Y - if secIndex < 0 || secIndex >= int32(len(c.Sections)) { - return nil, fmt.Errorf("null section") +func (chunk *Chunk) Block(x, y, z int32) (section.AnvilBlock, error) { + secIndex := (y >> 4) - chunk.Y + if secIndex < 0 || secIndex >= int32(len(chunk.Sections)) { + return section.AnvilBlock{}, fmt.Errorf("null section") } - sec := c.Sections[secIndex] + sec := chunk.Sections[secIndex] return sec.Block(byte(x), byte(y)&0x0f, byte(z)), nil } // This function does not update the block for the players, so it should not be used. X and Z should be relative to the chunk (aka x&0x0f, z&0x0f), but Y should be absolute. -func (c *Chunk) SetBlock(x, y, z int32, b section.Block) (state int64, err error) { +func (chunk *Chunk) SetBlock(x, y, z int32, b section.AnvilBlock) (state int64, err error) { //c.LastModified = time.Now().UnixMilli() - secIndex := (y >> 4) - c.Y - if secIndex < 0 || secIndex >= int32(len(c.Sections)) { + secIndex := (y >> 4) - chunk.Y + if secIndex < 0 || secIndex >= int32(len(chunk.Sections)) { return 0, fmt.Errorf("null section") } - sec := c.Sections[secIndex] + sec := chunk.Sections[secIndex] return sec.SetBlock(byte(x), byte(y)&0x0f, byte(z), b), nil } // This function does not update the block for the players, so it should not be used. X and Z should be relative to the chunk (aka x&0x0f, z&0x0f), but Y should be absolute. -func (c *Chunk) SetSkylightLevel(x, y, z int32, value byte) error { +func (chunk *Chunk) SetSkylightLevel(x, y, z int32, value byte) error { //c.LastModified = time.Now().UnixMilli() - secIndex := (y >> 4) - c.Y - if secIndex < 0 || secIndex >= int32(len(c.Sections)) { + secIndex := (y >> 4) - chunk.Y + if secIndex < 0 || secIndex >= int32(len(chunk.Sections)) { return fmt.Errorf("null section") } - sec := c.Sections[secIndex] + sec := chunk.Sections[secIndex] return sec.SetSkylightLevel(int(x), int(y)&0x0f, int(z), value) } // X and Z should be relative to the chunk (aka x&0x0f, z&0x0f), but Y should be absolute. -func (c *Chunk) SkyLightLevel(x, y, z int32) (byte, error) { - secIndex := (y >> 4) - c.Y - if secIndex < 0 || secIndex >= int32(len(c.Sections)) { +func (chunk *Chunk) SkyLightLevel(x, y, z int32) (byte, error) { + secIndex := (y >> 4) - chunk.Y + if secIndex < 0 || secIndex >= int32(len(chunk.Sections)) { return 0, fmt.Errorf("null section") } - sec := c.Sections[secIndex] + sec := chunk.Sections[secIndex] return sec.SkyLightLevel(int(x), int(y)&0x0f, int(z)) } -// This function does not update the block for the players, so it should not be used. X and Z should be relative to the chunk (aka x&0x0f, z&0x0f), but Y should be absolute. -func (c *Chunk) SetBlockLightLevel(x, y, z int32, value byte) error { - //c.LastModified = time.Now().UnixMilli() - secIndex := (y >> 4) - c.Y - if secIndex < 0 || secIndex >= int32(len(c.Sections)) { - return fmt.Errorf("null section") - } - sec := c.Sections[secIndex] - return sec.SetBlocklightLevel(int(x), int(y)&0x0f, int(z), value) -} - -// X and Z should be relative to the chunk (aka x&0x0f, z&0x0f), but Y should be absolute. -func (c *Chunk) BlockLightLevel(x, y, z int32) (byte, error) { - secIndex := (y >> 4) - c.Y - if secIndex < 0 || secIndex >= int32(len(c.Sections)) { - return 0, fmt.Errorf("null section") - } - sec := c.Sections[secIndex] - return sec.BlockLightLevel(int(x), int(y)&0x0f, int(z)) -} - -// Returns the block entity at the position. All of the position values should be absolute (aka (chunkPos<<4)+pos) -func (c *Chunk) BlockEntity(x, y, z int32) (*BlockEntity, bool) { - for _, entity := range c.BlockEntities { +// Returns the block state at the position. All of the position values should be absolute (aka (chunkPos<<4)+pos) +func (chunk *Chunk) BlockEntity(x, y, z int32) (*BlockEntity, bool) { + for _, entity := range chunk.BlockEntities { if entity.X == x && entity.Y == y && entity.Z == z { return &entity, true } @@ -137,19 +130,19 @@ func (c *Chunk) BlockEntity(x, y, z int32) (*BlockEntity, bool) { } // This function does not update the block for the players, so it should not be used. All of the position values should be absolute (aka (chunkPos<<4)+pos -func (c *Chunk) SetBlockEntity(x, y, z int32, be BlockEntity) { +func (chunk *Chunk) SetBlockEntity(x, y, z int32, be BlockEntity) { //c.LastModified = time.Now().UnixMilli() var index int = -1 be.X, be.Y, be.Z = x, y, z - for i, entity := range c.BlockEntities { + for i, entity := range chunk.BlockEntities { if entity.X == x && entity.Y == y && entity.Z == z { index = i break } } if index == -1 { - c.BlockEntities = append(c.BlockEntities, be) + chunk.BlockEntities = append(chunk.BlockEntities, be) return } - c.BlockEntities[index] = be + chunk.BlockEntities[index] = be } diff --git a/server/world/chunk/encode.go b/server/world/chunk/encode.go index 1c1639bf..7007f524 100644 --- a/server/world/chunk/encode.go +++ b/server/world/chunk/encode.go @@ -8,7 +8,6 @@ import ( "github.com/zeppelinmc/zeppelin/protocol/net/io/buffers" "github.com/zeppelinmc/zeppelin/protocol/net/io/encoding" "github.com/zeppelinmc/zeppelin/protocol/net/packet/play" - "github.com/zeppelinmc/zeppelin/server/registry" "github.com/zeppelinmc/zeppelin/server/world/chunk/section" "github.com/zeppelinmc/zeppelin/util/log" ) @@ -42,7 +41,7 @@ func (chunk *Chunk) EncodeBuf(biomeIndexes []string, buf *bytes.Buffer) *play.Ch Heightmaps: *(*play.Heightmaps)(unsafe.Pointer(&chunk.Heightmaps)), - BlockEntities: make([]play.BlockEntity, len(chunk.BlockEntities)), + //BlockEntities: make([]play.BlockEntity, len(chunk.BlockEntities)), SkyLightMask: make(encoding.BitSet, 1), EmptySkyLightMask: make(encoding.BitSet, 1), @@ -61,7 +60,7 @@ func (chunk *Chunk) EncodeBuf(biomeIndexes []string, buf *bytes.Buffer) *play.Ch pk.EmptyBlockLightMask.Set(1) pk.BlockLightArrays[0] = emptyLightBuffer - for i, entity := range chunk.BlockEntities { + /*for i, entity := range chunk.BlockEntities { pk.BlockEntities[i] = play.BlockEntity{ X: entity.X, Y: entity.Y, @@ -69,14 +68,12 @@ func (chunk *Chunk) EncodeBuf(biomeIndexes []string, buf *bytes.Buffer) *play.Ch Type: registry.BlockEntityType.Get(entity.Id), Data: entity, } - } + }*/ for secI, sec := range chunk.Sections { var blockCount int16 = 1024 + blockBitsPerEntry, biomeBitsPerEntry := sec.BPE() //var airId = -1 - skyLight, blockLight := sec.Light() - blockBitsPerEntry, blockPalette, blockStates := sec.BlockStates() - biomeBitsPerEntry, biomePalette, biomeStates := sec.Biomes() /*for i, state := range blockPalette { name, _ := state.Encode() @@ -122,21 +119,21 @@ func (chunk *Chunk) EncodeBuf(biomeIndexes []string, buf *bytes.Buffer) *play.Ch switch { case blockBitsPerEntry == 0: - stateId, _ := section.BlockStateId(blockPalette[0]) + stateId, _ := section.BlockStateId(sec.BlockStates.Palette[0]) w.VarInt(stateId) case blockBitsPerEntry >= 4 && blockBitsPerEntry <= 8: - w.VarInt(int32(len(blockPalette))) - for _, e := range blockPalette { + w.VarInt(int32(len(sec.BlockStates.Palette))) + for _, e := range sec.BlockStates.Palette { stateId, _ := section.BlockStateId(e) w.VarInt(stateId) } case blockBitsPerEntry == 15: // no palette default: - log.Println("invalid block bits per entry", blockBitsPerEntry, (len(blockStates)*64)/4096) + log.Println("invalid block bits per entry", blockBitsPerEntry, (len(sec.BlockStates.Data)*64)/4096) } - w.VarInt(int32(len(blockStates))) - for _, long := range blockStates { + w.VarInt(int32(len(sec.BlockStates.Data))) + for _, long := range sec.BlockStates.Data { w.Long(long) } @@ -156,8 +153,8 @@ func (chunk *Chunk) EncodeBuf(biomeIndexes []string, buf *bytes.Buffer) *play.Ch w.VarInt(bstateId) case biomeBitsPerEntry >= 1 && biomeBitsPerEntry <= 3: - w.VarInt(int32(len(biomePalette))) - for _, e := range biomePalette { + w.VarInt(int32(len(sec.Biomes.Palette))) + for _, e := range sec.Biomes.Palette { _ = e /*stateId := int32(slices.Index(biomeIndexes, e)) if stateId == -1 { @@ -168,11 +165,11 @@ func (chunk *Chunk) EncodeBuf(biomeIndexes []string, buf *bytes.Buffer) *play.Ch } case biomeBitsPerEntry == 6: // no palette default: - log.Println("invalid biome bits per entry", pk.CX, pk.CZ, sec.Y(), biomeBitsPerEntry) + log.Println("invalid biome bits per entry", pk.CX, pk.CZ, sec.Y, biomeBitsPerEntry) } - w.VarInt(int32(len(biomeStates))) - for _, long := range biomeStates { + w.VarInt(int32(len(sec.Biomes.Data))) + for _, long := range sec.Biomes.Data { w.Long(long) } @@ -180,20 +177,20 @@ func (chunk *Chunk) EncodeBuf(biomeIndexes []string, buf *bytes.Buffer) *play.Ch // Lighting // - if skyLight != nil { + if sec.SkyLight != nil { pk.SkyLightMask.Set(secI + 1) - if allZero(skyLight) { + if allZero(sec.SkyLight) { pk.EmptySkyLightMask.Set(secI + 1) } - pk.SkyLightArrays = append(pk.SkyLightArrays, skyLight) + pk.SkyLightArrays = append(pk.SkyLightArrays, *(*[]byte)(unsafe.Pointer(&sec.SkyLight))) } - if blockLight != nil { + if sec.BlockLight != nil { pk.BlockLightMask.Set(secI + 1) - if allZero(blockLight) { + if allZero(sec.BlockLight) { pk.EmptyBlockLightMask.Set(secI + 1) } - pk.BlockLightArrays = append(pk.BlockLightArrays, blockLight) + pk.BlockLightArrays = append(pk.BlockLightArrays, *(*[]byte)(unsafe.Pointer(&sec.BlockLight))) } } /*pk.SkyLightArrays = append(pk.SkyLightArrays, emptyLightBuffer) @@ -213,7 +210,7 @@ func (chunk *Chunk) EncodeBuf(biomeIndexes []string, buf *bytes.Buffer) *play.Ch return pk } -func allZero(inp []byte) bool { +func allZero(inp []int8) bool { for _, i := range inp { if i != 0 { return false diff --git a/server/world/chunk/section/blockRegister.go b/server/world/chunk/section/blockRegister.go index 71156e60..3ab0c702 100644 --- a/server/world/chunk/section/blockRegister.go +++ b/server/world/chunk/section/blockRegister.go @@ -2,27 +2,26 @@ package section import ( _ "embed" - "io" - - "github.com/zeppelinmc/zeppelin/server/world/block/blockstates" + "github.com/aimjel/minecraft/nbt" "github.com/zeppelinmc/zeppelin/util" ) -var blocks = make(map[string]blockstates.Block) +type blockState struct { + Id int32 `json:"id"` + Properties map[string]string `json:"properties"` +} -type RReaderAt interface { - io.Reader - io.ReaderAt +type blockInfo struct { + States []blockState `json:"states"` } -var header map[string]blockstates.BlockLocation -var blockFile RReaderAt +var blocks = make(map[string]blockInfo) -func ImportStates(f RReaderAt) (err error) { - blockFile = f - header, err = blockstates.ReadHeader(blockFile) +//go:embed data/blocks.nbt +var blockData []byte - return +func init() { + nbt.Unmarshal(blockData, &blocks) } var registeredBlocks = make(map[string]Block) @@ -42,17 +41,11 @@ func GetBlock(name string) Block { } // returns the block state id for this block -func BlockStateId(b Block) (id int32, ok bool) { - name, props := b.Encode() - block, ok := blocks[name] - - if !ok { - block, _ = blockstates.ReadBlock(blockFile, header[name]) - blocks[name] = block - } +func BlockStateId(b AnvilBlock) (id int32, ok bool) { + block := blocks[b.Name] - for _, state := range block { - if util.MapEqual(props, state.Properties) { + for _, state := range block.States { + if util.MapEqual(b.Properties, state.Properties) { return state.Id, true } } diff --git a/server/world/chunk/section/section.go b/server/world/chunk/section/section.go index 9dbe436e..52603ae7 100644 --- a/server/world/chunk/section/section.go +++ b/server/world/chunk/section/section.go @@ -5,66 +5,44 @@ import ( "fmt" "math" "math/bits" + "reflect" ) /* credit to https://github.com/aimjel for these calculations */ -func New(y int8, blockPalette []Block, blockStates []int64, biomePalette []string, biomesData []int64, skylight, blocklight []byte) *Section { - s := &Section{ - y: y, - blockPalette: blockPalette, - blockStates: blockStates, - skyLight: skylight, - blockLight: blocklight, - blockBitsPerEntry: blockBitsPerEntry(len(blockPalette)), - biomeBitsPerEntry: biomeBitsPerEntry(len(biomePalette)), - - stateCache: make(map[Block]int64), - oldStates: make(map[[3]byte]int64), - } - s.biomes.Palette = biomePalette - s.biomes.Data = biomesData - return s +type AnvilBlock struct { + Properties map[string]string + Name string } -// Section is a 16x16x16 chunk -type Section struct { - blockLight, skyLight []byte - y int8 - - blockPalette []Block - blockStates []int64 - - biomes struct { - Data []int64 `nbt:"data"` - Palette []string `nbt:"palette"` - } `nbt:"biomes"` - - // stateCache caches states for blocks with no properties - stateCache map[Block]int64 - oldStates map[[3]byte]int64 - - blockBitsPerEntry int - biomeBitsPerEntry int +type AnvilBiomes struct { + Data []int64 `nbt:"data,omitempty"` + Palette []string `nbt:"palette"` } -// Returns the lighting data for the section -func (sec *Section) Light() (skyLight, blockLight []byte) { - return sec.skyLight, sec.blockLight +type AnvilBlockStates struct { + Data []int64 `nbt:"data,omitempty"` + Palette []AnvilBlock `nbt:"palette"` } -// Returns the block states data for this section -func (sec *Section) BlockStates() (bpe int, palette []Block, states []int64) { - return sec.blockBitsPerEntry, sec.blockPalette, sec.blockStates +// Section is a 16x16x16 chunk +type Section struct { + BlockLight []int8 `nbt:"BlockLight,omitempty"` + SkyLight []int8 `nbt:"SkyLight,omitempty"` + Y int8 + Biomes AnvilBiomes `nbt:"biomes"` + BlockStates AnvilBlockStates `nbt:"block_states"` + + blockBitsPerEntry, biomeBitsPerEntry int } -// Returns the biome data for this section -func (sec *Section) Biomes() (bpe int, palette []string, states []int64) { - return sec.biomeBitsPerEntry, sec.biomes.Palette, sec.biomes.Data +func (s *Section) Init() { + s.blockBitsPerEntry = blockBitsPerEntry(len(s.BlockStates.Palette)) + s.biomeBitsPerEntry = biomeBitsPerEntry(len(s.Biomes.Palette)) } -func (sec *Section) Y() int8 { - return sec.y +func (s *Section) BPE() (block, biome int) { + return s.blockBitsPerEntry, s.biomeBitsPerEntry } func (s *Section) offset(x, y, z int) (long, offset int) { @@ -76,144 +54,97 @@ func (s *Section) offset(x, y, z int) (long, offset int) { } // X, Y, Z should be relative to the chunk section (AKA x&0x0f, y&0x0f, z&0x0f) -func (sec *Section) Block(x, y, z byte) Block { - if len(sec.blockStates) == 0 { - return sec.blockPalette[0] +func (s *Section) Block(x, y, z byte) AnvilBlock { + if len(s.BlockStates.Data) == 0 { + return s.BlockStates.Palette[0] } - long, off := sec.offset(int(x), int(y), int(z)) - l := sec.blockStates[long] - index := (l >> off) & (1<> off) & (1<> off) & (1<> off) & (1< len(sec.skyLight) { - return 0, fmt.Errorf("light index exceeds light length") - } - - var mask uint8 = 0x0f - var shift uint8 = 0 - if math.Remainder(float64(index), 2) != 0 { - mask = 0xf0 - shift = 4 - } - - index /= 2 - - return (sec.skyLight[index] & mask) >> shift, nil -} - -func (sec *Section) SetSkylightLevel(x, y, z int, level byte) error { - if level > 0x0F { - return fmt.Errorf("light level must not exceed 4 bits (15)") - } - index := (y << 8) | (z << 4) | x - if index < 0 || int(index) > len(sec.skyLight) { - return fmt.Errorf("light index exceeds light length") - } - - var mask uint8 = 0x0f - if math.Remainder(float64(index), 2) != 0 { - mask = 0xf0 - level <<= 4 - } - - index /= 2 - - sec.skyLight[index] &= ^mask - sec.skyLight[index] |= level - - return nil +func (s *Section) add(b AnvilBlock) { + s.BlockStates.Palette = append(s.BlockStates.Palette, b) + s.blockBitsPerEntry = blockBitsPerEntry(len(s.BlockStates.Palette)) } -func (sec *Section) BlockLightLevel(x, y, z int) (byte, error) { +func (s *Section) SkyLightLevel(x, y, z int) (byte, error) { index := (y << 8) | (z << 4) | x - if index < 0 || int(index) > len(sec.blockLight) { + if index < 0 || int(index) > len(s.SkyLight) { return 0, fmt.Errorf("light index exceeds light length") } @@ -226,15 +157,15 @@ func (sec *Section) BlockLightLevel(x, y, z int) (byte, error) { index /= 2 - return (sec.blockLight[index] & mask) >> shift, nil + return (uint8(s.SkyLight[index]) & mask) >> shift, nil } -func (sec *Section) SetBlocklightLevel(x, y, z int, level byte) error { +func (s *Section) SetSkylightLevel(x, y, z int, level byte) error { if level > 0x0F { return fmt.Errorf("light level must not exceed 4 bits (15)") } index := (y << 8) | (z << 4) | x - if index < 0 || int(index) > len(sec.blockLight) { + if index < 0 || int(index) > len(s.SkyLight) { return fmt.Errorf("light index exceeds light length") } @@ -246,8 +177,8 @@ func (sec *Section) SetBlocklightLevel(x, y, z int, level byte) error { index /= 2 - sec.blockLight[index] &= ^mask - sec.blockLight[index] |= level + s.SkyLight[index] = s.SkyLight[index] & ^int8(mask) + s.SkyLight[index] |= int8(level) return nil } diff --git a/server/world/dimension/dimension.go b/server/world/dimension/dimension.go index 5f788a2e..ce60f468 100644 --- a/server/world/dimension/dimension.go +++ b/server/world/dimension/dimension.go @@ -6,7 +6,6 @@ import ( "os" "sync" - "github.com/zeppelinmc/zeppelin/server/session" "github.com/zeppelinmc/zeppelin/server/world/block/pos" "github.com/zeppelinmc/zeppelin/server/world/chunk" "github.com/zeppelinmc/zeppelin/server/world/chunk/section" @@ -16,7 +15,7 @@ import ( "github.com/zeppelinmc/zeppelin/util/log" ) -func New(regionPath, typ, name string, broadcast *session.Broadcast, chunkGenerator chunk.Generator, level level.Level) *Dimension { +func New(regionPath, typ, name string, chunkGenerator chunk.Generator, level level.Level) *Dimension { return &Dimension{ regions: make(map[uint64]*region.File), @@ -24,7 +23,6 @@ func New(regionPath, typ, name string, broadcast *session.Broadcast, chunkGenera typ: typ, name: name, generator: chunkGenerator, - broadcast: broadcast, WindowManager: window.NewManager(), Level: level, } @@ -35,8 +33,6 @@ type Dimension struct { regions map[uint64]*region.File Level level.Level - broadcast *session.Broadcast - generator chunk.Generator WindowManager *window.WindowManager @@ -46,29 +42,25 @@ type Dimension struct { regionPath string } -func (s *Dimension) SetBroadcast(b *session.Broadcast) { - s.broadcast = b -} - -func (s *Dimension) Type() string { - return s.typ +func (d *Dimension) Type() string { + return d.typ } -func (s *Dimension) Name() string { - return s.name +func (d *Dimension) Name() string { + return d.name } -func (s *Dimension) Save() { - s.syncWindows() +func (d *Dimension) Save() { + d.syncWindows() //s.saveAllRegions() - s.Level.Close() - log.Infoln("Saved dimension", s.name) + d.Level.Close() + log.Infoln("Saved dimension", d.name) } -func (s *Dimension) syncWindows() { - s.WindowManager.Range(func(i pos.BlockPosition, w *window.Window) { +func (d *Dimension) syncWindows() { + d.WindowManager.Range(func(i pos.BlockPosition, w *window.Window) { if w.ChunkEntityType != "" { - s.SetBlockEntity(i, chunk.BlockEntity{ + d.SetBlockEntity(i, chunk.BlockEntity{ X: i.X(), Y: i.Y(), Z: i.Z(), Id: w.ChunkEntityType, Items: w.Items, @@ -77,13 +69,13 @@ func (s *Dimension) syncWindows() { }) } -func (s *Dimension) saveAllRegions() { - s.reg_mu.Lock() - defer s.reg_mu.Unlock() - os.MkdirAll(s.regionPath, 0755) - for hash, reg := range s.regions { - rx, rz := s.regionUnhash(hash) - path := fmt.Sprintf("%s/r.%d.%d.mca", s.regionPath, rx, rz) +func (d *Dimension) saveAllRegions() { + d.reg_mu.Lock() + defer d.reg_mu.Unlock() + _ = os.MkdirAll(d.regionPath, 0755) + for hash, reg := range d.regions { + rx, rz := d.regionUnhash(hash) + path := fmt.Sprintf("%s/r.%d.%d.mca", d.regionPath, rx, rz) file, err := os.Create(path) if err != nil { continue @@ -97,30 +89,30 @@ func (s *Dimension) saveAllRegions() { } } -func (s *Dimension) LoadedChunks() int32 { - s.reg_mu.Lock() - defer s.reg_mu.Unlock() +func (d *Dimension) LoadedChunks() int32 { + d.reg_mu.Lock() + defer d.reg_mu.Unlock() var count int32 - for _, reg := range s.regions { + for _, reg := range d.regions { count += reg.LoadedChunks() } return count } -func (s *Dimension) Block(x, y, z int32) (section.Block, error) { +func (d *Dimension) Block(x, y, z int32) (section.AnvilBlock, error) { chunkX, chunkZ := x>>4, z>>4 - chunk, err := s.GetChunk(chunkX, chunkZ) + chunk, err := d.GetChunk(chunkX, chunkZ) if err != nil { - return nil, err + return section.AnvilBlock{}, err } return chunk.Block(x&0x0f, y, z&0x0f) } -func (s *Dimension) SetBlock(pos pos.BlockPosition, b section.Block, placeSound bool) (state int64, err error) { +func (d *Dimension) SetBlock(pos pos.BlockPosition, b section.AnvilBlock, placeSound bool) (state int64, err error) { chunkX, chunkZ := pos.ChunkX(), pos.ChunkZ() - chunk, err := s.GetChunk(chunkX, chunkZ) + chunk, err := d.GetChunk(chunkX, chunkZ) if err != nil { return 0, err } @@ -128,36 +120,36 @@ func (s *Dimension) SetBlock(pos pos.BlockPosition, b section.Block, placeSound if err != nil { return i, err } - s.broadcast.UpdateBlock(pos, b, s.name, placeSound) + //s.broadcast.UpdateBlock(pos, b, s.name, placeSound) return i, err } -func (s *Dimension) SetBlockEntity(pos pos.BlockPosition, be chunk.BlockEntity) error { +func (d *Dimension) SetBlockEntity(pos pos.BlockPosition, be chunk.BlockEntity) error { chunkX, chunkZ := pos.ChunkX(), pos.ChunkZ() - chunk, err := s.GetChunk(chunkX, chunkZ) + chunk, err := d.GetChunk(chunkX, chunkZ) if err != nil { return err } chunk.SetBlockEntity(pos.X(), pos.Y(), pos.Z(), be) - s.broadcast.UpdateBlockEntity(pos, be, s.name) + //s.broadcast.UpdateBlockEntity(pos, be, s.name) return nil } -func (s *Dimension) BlockEntity(x, y, z int32) (*chunk.BlockEntity, bool) { +func (d *Dimension) BlockEntity(x, y, z int32) (*chunk.BlockEntity, bool) { chunkX, chunkZ := x>>4, z>>4 - chunk, err := s.GetChunk(chunkX, chunkZ) + chunk, err := d.GetChunk(chunkX, chunkZ) if err != nil { return nil, false } return chunk.BlockEntity(x, y, z) } -func (s *Dimension) GetChunkBuf(x, z int32, buf *bytes.Buffer) (*chunk.Chunk, error) { - rx, rz := s.chunkPosToRegionPos(x, z) - region, err := s.getRegion(rx, rz) +func (d *Dimension) GetChunkBuf(x, z int32, buf *bytes.Buffer) (*chunk.Chunk, error) { + rx, rz := d.chunkPosToRegionPos(x, z) + region, err := d.getRegion(rx, rz) if err != nil { - if s.generator != nil { - region = s.newRegion(rx, rz) + if d.generator != nil { + region = d.newRegion(rx, rz) } else { return nil, err } @@ -166,12 +158,12 @@ func (s *Dimension) GetChunkBuf(x, z int32, buf *bytes.Buffer) (*chunk.Chunk, er return region.GetChunkBuf(x, z, buf) } -func (s *Dimension) GetChunk(x, z int32) (*chunk.Chunk, error) { - rx, rz := s.chunkPosToRegionPos(x, z) - region, err := s.getRegion(rx, rz) +func (d *Dimension) GetChunk(x, z int32) (*chunk.Chunk, error) { + rx, rz := d.chunkPosToRegionPos(x, z) + region, err := d.getRegion(rx, rz) if err != nil { - if s.generator != nil { - region = s.newRegion(rx, rz) + if d.generator != nil { + region = d.newRegion(rx, rz) } else { return nil, err } @@ -180,24 +172,24 @@ func (s *Dimension) GetChunk(x, z int32) (*chunk.Chunk, error) { return region.GetChunk(x, z) } -func (s *Dimension) newRegion(rx, rz int32) *region.File { - s.reg_mu.Lock() - defer s.reg_mu.Unlock() - hash := s.regionHash(rx, rz) - s.regions[hash] = new(region.File) - region.Empty(s.regions[hash], rx, rz, s.generator) +func (d *Dimension) newRegion(rx, rz int32) *region.File { + d.reg_mu.Lock() + defer d.reg_mu.Unlock() + hash := d.regionHash(rx, rz) + d.regions[hash] = new(region.File) + region.Empty(d.regions[hash], rx, rz, d.generator) - return s.regions[hash] + return d.regions[hash] } -func (s *Dimension) getRegion(rx, rz int32) (*region.File, error) { - s.reg_mu.Lock() - defer s.reg_mu.Unlock() - if r, ok := s.regions[s.regionHash(rx, rz)]; ok { +func (d *Dimension) getRegion(rx, rz int32) (*region.File, error) { + d.reg_mu.Lock() + defer d.reg_mu.Unlock() + if r, ok := d.regions[d.regionHash(rx, rz)]; ok { return r, nil } - reg, err := s.openRegion(rx, rz) + reg, err := d.openRegion(rx, rz) if err != nil { return nil, err } @@ -205,33 +197,33 @@ func (s *Dimension) getRegion(rx, rz int32) (*region.File, error) { return reg, err } -func (s *Dimension) regionHash(rx, rz int32) uint64 { +func (d *Dimension) regionHash(rx, rz int32) uint64 { return uint64(uint32(rx)) | uint64(uint32(rz))<<32 } -func (s *Dimension) regionUnhash(hash uint64) (rx, rz int32) { +func (d *Dimension) regionUnhash(hash uint64) (rx, rz int32) { urx := uint32(hash) urz := uint32(hash >> 32) return int32(urx), int32(urz) } -func (s *Dimension) chunkPosToRegionPos(x, z int32) (rx, rz int32) { +func (d *Dimension) chunkPosToRegionPos(x, z int32) (rx, rz int32) { return x >> 5, z >> 5 } -func (s *Dimension) openRegion(rx, rz int32) (*region.File, error) { - path := fmt.Sprintf("%s/r.%d.%d.mca", s.regionPath, rx, rz) +func (d *Dimension) openRegion(rx, rz int32) (*region.File, error) { + path := fmt.Sprintf("%s/r.%d.%d.mca", d.regionPath, rx, rz) file, err := os.Open(path) if err != nil { return nil, err } //defer file.Close() - hash := s.regionHash(rx, rz) + hash := d.regionHash(rx, rz) - s.regions[hash] = new(region.File) + d.regions[hash] = new(region.File) - err = region.Decode(file, s.regions[hash], rx, rz, s.generator) + err = region.Decode(file, d.regions[hash], rx, rz, d.generator) - return s.regions[hash], err + return d.regions[hash], err } diff --git a/server/world/level/entity.go b/server/world/level/entity.go index 6f89ccd7..6005606f 100644 --- a/server/world/level/entity.go +++ b/server/world/level/entity.go @@ -31,5 +31,5 @@ type Entity struct { TicksFrozen int32 `nbt:"TicksFrozen,omitempty"` UUID uuid.UUID - //TODO add entity subclasses + //TODO add state subclasses } diff --git a/server/world/level/item/item.go b/server/world/level/item/item.go index 3f49eb76..6d5182b3 100644 --- a/server/world/level/item/item.go +++ b/server/world/level/item/item.go @@ -84,7 +84,7 @@ type Item struct { DyedColor any `nbt:"minecraft:dyed_color"` EnchantmentGlintOverride bool `nbt:"minecraft:enchantment_glint_override"` Enchantments Enchantments `nbt:"minecraft:enchantments"` - EntityData entity.LevelEntity `nbt:"minecraft:entity_data"` + EntityData state.LevelEntity `nbt:"minecraft:entity_data"` FireResistant FireResistant `nbt:"minecraft:fire_resistant"` FireworkExplosion FireworkExplosion `nbt:"minecraft:firework_explosion"` Fireworks Fireworks `nbt:"minecraft:fireworks"` diff --git a/server/world/level/level.go b/server/world/level/level.go index edeb409c..9c223adf 100644 --- a/server/world/level/level.go +++ b/server/world/level/level.go @@ -7,13 +7,13 @@ package level import ( "compress/gzip" "errors" + "github.com/zeppelinmc/zeppelin/properties" "io" "os" "strconv" "time" "github.com/zeppelinmc/zeppelin/protocol/nbt" - "github.com/zeppelinmc/zeppelin/protocol/properties" "github.com/zeppelinmc/zeppelin/server/world/chunk" "github.com/zeppelinmc/zeppelin/server/world/level/seed" ) @@ -22,20 +22,20 @@ var ErrAlreadyClosed = errors.New("already closed") var SessionLock = []byte{0xE2, 0x98, 0x83} -// A game rule is a string containing an integer or a boolean +// GameRule is a string containing an integer or a boolean type GameRule string -// Returns the boolean inside of the game rule string +// Boolean returns the boolean inside of the game rule string func (rule GameRule) Boolean() (bool, error) { return strconv.ParseBool(string(rule)) } -// Returns the int inside of the game rule string +// Integer returns the int inside of the game rule string func (rule GameRule) Integer() (int, error) { return strconv.Atoi(string(rule)) } -// A date represented by the amount of milliseconds since January 1st, 1970 +// UnixMilliTimestamp is date represented by the amount of milliseconds since January 1st, 1970 type UnixMilliTimestamp int64 func (stamp UnixMilliTimestamp) Time() time.Time { @@ -133,6 +133,7 @@ type Level struct { closed bool } +// TODO fix EOF error // worldPath is the base path of the world func Open(worldPath string) (Level, error) { var level Level diff --git a/server/world/level/region/anvil.go b/server/world/level/region/anvil.go index a91a5227..0fb55af6 100644 --- a/server/world/level/region/anvil.go +++ b/server/world/level/region/anvil.go @@ -2,90 +2,4 @@ package region -import ( - "unsafe" - - "github.com/zeppelinmc/zeppelin/server/world/chunk" - "github.com/zeppelinmc/zeppelin/server/world/chunk/heightmaps" -) - const DataVersion = 3953 - -// chunkToAnvil turns the chunk into an anvilChunk -func chunkToAnvil(c *chunk.Chunk) anvilChunk { - anvil := anvilChunk{ - Status: "minecraft:full", - BlockEntities: c.BlockEntities, - Heightmaps: c.Heightmaps, - Sections: make([]anvilSection, len(c.Sections)), - - XPos: c.X, YPos: c.Y, ZPos: c.Z, - DataVersion: DataVersion, - } - - for i, sec := range c.Sections { - sky, block := sec.Light() - _, biomePalette, biomeStates := sec.Biomes() - _, blockPalette, blockStates := sec.BlockStates() - - anvil.Sections[i] = anvilSection{ - Y: sec.Y(), - SkyLight: *(*[]int8)(unsafe.Pointer(&sky)), BlockLight: *(*[]int8)(unsafe.Pointer(&block)), - Biomes: anvilBiomes{ - Data: biomeStates, - Palette: biomePalette, - }, - BlockStates: anvilBlockStates{ - Data: blockStates, - Palette: make([]anvilBlock, len(blockPalette)), - }, - } - - for bi, block := range blockPalette { - name, properties := block.Encode() - anvil.Sections[i].BlockStates.Palette[bi] = anvilBlock{ - Name: name, Properties: properties, - } - } - } - - return anvil -} - -type anvilBlock struct { - Properties map[string]string - Name string -} - -type anvilSection struct { - BlockLight []int8 `nbt:"BlockLight,omitempty"` - SkyLight []int8 `nbt:"SkyLight,omitempty"` - Y int8 - Biomes anvilBiomes `nbt:"biomes"` - BlockStates anvilBlockStates `nbt:"block_states"` -} - -type anvilBiomes struct { - Data []int64 `nbt:"data,omitempty"` - Palette []string `nbt:"palette"` -} - -type anvilBlockStates struct { - Data []int64 `nbt:"data,omitempty"` - Palette []anvilBlock `nbt:"palette"` -} - -type anvilChunk struct { - DataVersion int32 - Heightmaps heightmaps.Heightmaps - InhabitedTime int64 - LastUpdate int64 - Status string - BlockEntities []chunk.BlockEntity `nbt:"block_entities,omitempty"` - - Sections []anvilSection `nbt:"sections"` - - XPos int32 `nbt:"xPos"` - YPos int32 `nbt:"yPos"` - ZPos int32 `nbt:"zPos"` -} diff --git a/server/world/level/region/region_dec.go b/server/world/level/region/region_dec.go index e0b9fde1..68aa0984 100644 --- a/server/world/level/region/region_dec.go +++ b/server/world/level/region/region_dec.go @@ -6,14 +6,12 @@ import ( "fmt" "io" "sync" - "unsafe" "github.com/4kills/go-zlib" "github.com/aimjel/minecraft/nbt" "github.com/zeppelinmc/zeppelin/protocol/net/io/buffers" "github.com/zeppelinmc/zeppelin/protocol/net/io/compress" "github.com/zeppelinmc/zeppelin/server/world/chunk" - "github.com/zeppelinmc/zeppelin/server/world/chunk/section" ) type File struct { @@ -21,7 +19,8 @@ type File struct { generator chunk.Generator - reader io.ReaderAt + reader io.ReaderAt + locations []byte chunks map[uint64]*chunk.Chunk @@ -64,7 +63,7 @@ func (r *File) GetChunkBuf(x, z int32, chunkBuffer *bytes.Buffer) (*chunk.Chunk, return c, nil } - locationIndex := 4 * ((x & 31) + (z&31)*32) + locationIndex := 4 * ((x & 31) + (z&31)<<5) if int(locationIndex) >= len(r.locations) { if r.generator != nil { r.chunks[hash] = new(chunk.Chunk) @@ -120,52 +119,25 @@ func (r *File) GetChunkBuf(x, z int32, chunkBuffer *bytes.Buffer) (*chunk.Chunk, chunkBuffer.ReadFrom(reader) } - var anvil = new(anvilChunk) + var anvil = new(chunk.Chunk) if err := nbt.Unmarshal(chunkBuffer.Bytes(), anvil); err != nil { return nil, err } - r.chunks[hash] = &chunk.Chunk{ - X: anvil.XPos, - Y: anvil.YPos, - Z: anvil.ZPos, - Heightmaps: anvil.Heightmaps, - BlockEntities: anvil.BlockEntities, + for i := range anvil.Sections { + (&anvil.Sections[i]).Init() } - r.chunks[hash].Sections = make([]*section.Section, len(anvil.Sections)) - var emptySections int - for i, sec := range anvil.Sections { - var blocks = make([]section.Block, len(sec.BlockStates.Palette)) + r.chunks[hash] = anvil - if l := len(sec.BlockStates.Palette); l == 0 || (l == 1 && sec.BlockStates.Palette[0].Name == "minecraft:air") { - emptySections++ - } - for i, entry := range sec.BlockStates.Palette { - b := section.GetBlock(entry.Name) - if entry.Properties != nil { - b = b.New(entry.Properties) - } - blocks[i] = b - } - - r.chunks[hash].Sections[i] = section.New(sec.Y, - blocks, - sec.BlockStates.Data, - sec.Biomes.Palette, - sec.Biomes.Data, - *(*[]byte)(unsafe.Pointer(&sec.SkyLight)), - *(*[]byte)(unsafe.Pointer(&sec.BlockLight)), - ) - } /*if emptySections == len(r.chunks[hash].Sections) && r.generateEmpty && r.generator != nil { r.chunks[hash] = new(chunk.Chunk) r.generateChunkAt(x, z, r.chunks[hash], r.generator) return r.chunks[hash], nil }*/ - return r.chunks[hash], err + return anvil, err } func Empty(f *File, rx, rz int32, generator chunk.Generator) { diff --git a/server/world/level/region/region_enc.go b/server/world/level/region/region_enc.go index 97f72e69..785fcf38 100644 --- a/server/world/level/region/region_enc.go +++ b/server/world/level/region/region_enc.go @@ -57,7 +57,7 @@ func (f *File) Encode(w *os.File, compressionScheme byte) error { chunkBuffer.Reset() - if err := nbt.NewEncoder(chunkBuffer).Encode("", chunkToAnvil(chunk)); err != nil { + if err := nbt.NewEncoder(chunkBuffer).Encode("", chunk); err != nil { return err } diff --git a/server/world/level/uuid/uuid.go b/server/world/level/uuid/uuid.go index 97b46ac3..2a0a065d 100644 --- a/server/world/level/uuid/uuid.go +++ b/server/world/level/uuid/uuid.go @@ -13,7 +13,7 @@ func New(u uuid.UUID) UUID { } } -// A uuid saved in playerdata and entity files contains 4 integers of the 128 bit uuid ordered from most to least significant +// A uuid saved in playerdata and state files contains 4 integers of the 128 bit uuid ordered from most to least significant type UUID [4]int32 // Returns the UUID object of this data uuid diff --git a/server/world/terrain/terrain.go b/server/world/terrain/terrain.go index 1f08b3d0..ce845187 100644 --- a/server/world/terrain/terrain.go +++ b/server/world/terrain/terrain.go @@ -7,6 +7,7 @@ import ( "github.com/aquilax/go-perlin" "github.com/zeppelinmc/zeppelin/server/world/block" "github.com/zeppelinmc/zeppelin/server/world/chunk" + "github.com/zeppelinmc/zeppelin/server/world/chunk/section" ) type TerrainGenerator struct { @@ -106,8 +107,8 @@ func isCorner(x, z, minX, minZ, maxX, maxZ int32) bool { return (x == minX && z == minZ) || (x == maxX && z == maxZ) || (x == maxX && z == minZ) || (x == minZ && z == maxZ) } -var grassBlock = block.GrassBlock{} -var dirt = block.Dirt{} -var bedrock = block.Bedrock{} -var oakLog = block.OakLog{Axis: block.AxisY} -var oakLeaves = block.OakLeaves{Distance: 1} +var grassBlock = section.AnvilBlock{Name: "minecraft:grass_block"} //block.GrassBlock{} +var dirt = section.AnvilBlock{Name: "minecraft:dirt"} +var bedrock = section.AnvilBlock{Name: "minecraft:bedrock"} +var oakLog = section.AnvilBlock{Name: "minecraft:oak_log", Properties: map[string]string{"axis": block.AxisY}} +var oakLeaves = section.AnvilBlock{Name: "minecraft:leaves", Properties: map[string]string{"distance": "1"}} diff --git a/server/world/world.go b/server/world/world.go index 372ce0db..9fd0feb8 100644 --- a/server/world/world.go +++ b/server/world/world.go @@ -2,23 +2,21 @@ package world import ( "fmt" + "github.com/zeppelinmc/zeppelin/properties" "os" - "strings" "sync/atomic" - "github.com/zeppelinmc/zeppelin/protocol/properties" - "github.com/zeppelinmc/zeppelin/server/session" + //"github.com/zeppelinmc/zeppelin/server/session" "github.com/zeppelinmc/zeppelin/server/world/chunk" "github.com/zeppelinmc/zeppelin/server/world/dimension" "github.com/zeppelinmc/zeppelin/server/world/level" "github.com/zeppelinmc/zeppelin/server/world/terrain" - "github.com/zeppelinmc/zeppelin/util/log" ) type World struct { level.Level - dimensions map[string]*dimension.Dimension - Broadcast *session.Broadcast + dimension.DimensionManager + //Broadcast *session.Broadcast levelPrepared bool @@ -35,23 +33,24 @@ const version = 19133 func NewWorld(props properties.ServerProperties) (*World, error) { var err error w := &World{ - path: props.LevelName, - Broadcast: session.NewBroadcast(props), - props: props, + path: props.LevelName, + //Broadcast: session.NewBroadcast(props), + props: props, } owgen := terrain.NewTerrainGenerator(int64(w.Data.WorldGenSettings.Seed)) w.Level, err = level.Open(props.LevelName) if err != nil { - w.prepareLevel(owgen, props) + fmt.Println(err) + _ = w.prepareLevel(owgen, props) } if w.Level.Data.VersionInt > version { - return nil, fmt.Errorf("world is too old!") + return nil, fmt.Errorf("world is too old") } if w.Level.Data.VersionInt < version { - return nil, fmt.Errorf("world is too new!") + return nil, fmt.Errorf("world is too new") } if w.obtainLock() != nil { @@ -60,16 +59,17 @@ func NewWorld(props properties.ServerProperties) (*World, error) { w.worldAge.Store(w.Level.Data.Time) w.dayTime.Store(w.Level.Data.DayTime) - w.dimensions = map[string]*dimension.Dimension{ + w.DimensionManager = dimension.NewDimensionManager(map[string]*dimension.Dimension{ "minecraft:overworld": dimension.New( props.LevelName+"/region", "minecraft:overworld", "minecraft:overworld", - w.Broadcast, - owgen, + //w.Broadcast, + //owgen, + nil, w.Level, ), - } + }) w.Level.Refresh(w.props) @@ -77,17 +77,27 @@ func NewWorld(props properties.ServerProperties) (*World, error) { } // prepareLevel creates a new level.dat file and other world folders -func (w *World) prepareLevel(owgen chunk.Generator, props properties.ServerProperties) { +func (w *World) prepareLevel(owgen chunk.Generator, props properties.ServerProperties) error { w.Level = level.New(owgen, props, w.path) - os.MkdirAll(w.path+"/playerdata", 0755) + return anyerror( + os.MkdirAll(w.path+"/playerdata", 0755), + os.Mkdir(w.path+"/region", 0755), + os.Mkdir(w.path+"/poi", 0755), + os.Mkdir(w.path+"/entities", 0755), - os.Mkdir(w.path+"/region", 0755) - os.Mkdir(w.path+"/poi", 0755) - os.Mkdir(w.path+"/entities", 0755) + os.MkdirAll(w.path+"/DIM-1/region", 0755), + os.MkdirAll(w.path+"/DIM1/region", 0755), + ) +} - os.MkdirAll(w.path+"/DIM-1/region", 0755) - os.MkdirAll(w.path+"/DIM1/region", 0755) +func anyerror(err ...error) error { + for _, err := range err { + if err != nil { + return err + } + } + return nil } func (w *World) obtainLock() error { @@ -100,27 +110,6 @@ func (w *World) obtainLock() error { return nil } -// returns the dimension struct for the dimension name -func (w *World) Dimension(name string) *dimension.Dimension { - if !strings.Contains(name, ":") { - name = "minecraft:" + name - } - - return w.dimensions[name] -} - -func (w *World) Save() { - for _, dim := range w.dimensions { - dim.Save() - } - w.lock.Close() - log.Infoln("Closed world") -} - -func (w *World) RegisterDimension(name string, dim *dimension.Dimension) { - w.dimensions[name] = dim -} - // increments the day time and world age by one tick and returns the updated time func (w *World) IncrementTime() (worldAge, dayTime int64) { worldAge = w.worldAge.Add(1) @@ -144,13 +133,3 @@ func (w *World) DaytimeSet(v int64) { func (w *World) WorldAgeSet(v int64) { w.worldAge.Store(v) } - -func (w *World) LoadedChunks() int32 { - var count int32 - - for _, dim := range w.dimensions { - count += dim.LoadedChunks() - } - - return count -} diff --git a/util/atomic/slice.go b/util/atomic/slice.go new file mode 100644 index 00000000..f086f146 --- /dev/null +++ b/util/atomic/slice.go @@ -0,0 +1,117 @@ +package atomic + +import ( + "sync/atomic" + "unsafe" +) + +// Pointer is the size of pointers +var Pointer = unsafe.Sizeof(0) + +//go:linkname mallocgc runtime.mallocgc +func mallocgc(size uintptr, typ unsafe.Pointer, needzero bool) unsafe.Pointer + +func memcpy(dst, src unsafe.Pointer, n uintptr) { + dstS := unsafe.Slice((*byte)(dst), n) + srcS := unsafe.Slice((*byte)(src), n) + + copy(dstS, srcS) +} + +func Make(len, cap, sizeOfElement uintptr) Slice { + return Slice{ + ptr: uintptr(mallocgc(cap, nil, false)), + len: len, cap: cap, + + sizeOfElement: sizeOfElement, + } +} + +// Slice is an atomic slice with all read only fields. Entries cannot be removed. +type Slice struct { + ptr, len, cap uintptr + + //not atomic + sizeOfElement uintptr +} + +func (a *Slice) Len() uintptr { + return atomic.LoadUintptr(&a.len) +} + +func (a *Slice) Cap() uintptr { + return atomic.LoadUintptr(&a.cap) +} + +func (a *Slice) Pointer() unsafe.Pointer { + return unsafe.Pointer(atomic.LoadUintptr(&a.ptr)) +} + +// At returns the element at the specified index, while checking that the index is in bounds +func (a *Slice) At(index uintptr) unsafe.Pointer { + if a.Cap() < index { + panic("out of bounds") + } + if a.Len() < index { + atomic.StoreUintptr(&a.len, index+1) + } + return a.Element(index) +} + +// Element returns the element at the specified index, without checking that the index is in bounds +func (a *Slice) Element(index uintptr) unsafe.Pointer { + return unsafe.Add(a.Pointer(), index*a.sizeOfElement) +} + +// Grow grows the slice to capacity of cap +func (a *Slice) Grow(cap uintptr) { + newPtr := mallocgc(cap*a.sizeOfElement, nil, false) + length := a.Len() + + memcpy(newPtr, unsafe.Pointer(a.ptr), a.sizeOfElement*length) + + atomic.StoreUintptr(&a.cap, cap) + atomic.StoreUintptr(&a.ptr, uintptr(newPtr)) +} + +// TrimStart removes the first count elements from the slice +func (a *Slice) TrimStart(count uintptr) { + if count > a.Cap() { + panic("out of bounds") + } + + atomic.AddUintptr(&a.ptr, count*a.sizeOfElement) +} + +// TrimEnd removes the last count elements from the slice +func (a *Slice) TrimEnd(count uintptr) { + if count > a.Cap() { + panic("out of bounds") + } + + atomic.AddUintptr(&a.len, -count*a.sizeOfElement) +} + +// Append adds the elements from the specified pointers to the slice +func (a *Slice) Append(elements ...unsafe.Pointer) { + currentLength := a.Len() + currentCapacity := a.Cap() + + count := uintptr(len(elements)) + + // need to expand the slice + if newLength := currentLength + count; newLength > currentCapacity { + a.Grow(newLength) + a.Append(elements...) + return + } + + basePtr := unsafe.Add(a.Pointer(), currentLength*a.sizeOfElement) + + for _, element := range elements { + memcpy(basePtr, element, a.sizeOfElement) + basePtr = unsafe.Add(basePtr, a.sizeOfElement) + } + + atomic.AddUintptr(&a.len, count) +} diff --git a/util/console/console.go b/util/console/console.go index 72a5ea97..83b79198 100644 --- a/util/console/console.go +++ b/util/console/console.go @@ -8,9 +8,20 @@ import ( "strings" "unsafe" + "github.com/zeppelinmc/zeppelin/protocol/text" "github.com/zeppelinmc/zeppelin/server" + "github.com/zeppelinmc/zeppelin/util/log" ) +type console struct{} + +func (c console) SystemMessage(t text.TextComponent) error { + log.Chat(t) + return nil +} + +var Console console + func GetFlag(name string) (string, bool) { name = "--" + name + "=" for _, a := range os.Args { @@ -50,7 +61,7 @@ func StartConsole(srv *server.Server) { break } line = scanner.Text() - srv.CommandManager.Call(line, srv.Console) + srv.CommandManager.Call(line, Console) fmt.Print("\r> ") } } @@ -127,7 +138,7 @@ charl: continue } fmt.Println() - srv.CommandManager.Call(currentLine, srv.Console) + srv.CommandManager.Call(currentLine, Console) previousLines = append([]string{currentLine}, previousLines...) currentLine = "" currentLineIndex = 0 diff --git a/util/log/log.go b/util/log/log.go index 937dd79a..76c2f415 100644 --- a/util/log/log.go +++ b/util/log/log.go @@ -2,6 +2,7 @@ package log import ( "fmt" + "math" "net" "runtime" "runtime/debug" @@ -14,11 +15,12 @@ import ( "github.com/zeppelinmc/zeppelin/protocol/text" ) -var timeColor = color.New(color.FgBlack).SprintFunc() +var timeColor = color.New(color.FgHiBlack).SprintFunc() var stackColor = color.New(color.FgHiBlack).SprintFunc() var infoColor = color.New(color.FgHiBlue, color.Bold).SprintFunc() var errorColor = color.New(color.FgRed, color.Bold).SprintFunc() var warningColor = color.New(color.FgYellow, color.Bold).SprintFunc() +var chatColor = color.New(color.FgHiGreen, color.Bold).SprintFunc() var buildInfo, _ = debug.ReadBuildInfo() var mainModuleName = buildInfo.Main.Path[strings.LastIndex(buildInfo.Main.Path, "/")+1:] @@ -98,49 +100,39 @@ var stackBuf = sync.Pool{ }, } -func stackCallerModule() string { +func stackCallerModule(i int) string { buf := stackBuf.Get().([]byte) defer stackBuf.Put(buf) buf = buf[:runtime.Stack(buf, false)] str := unsafe.String(unsafe.SliceData(buf), len(buf)) - for _, line := range strings.Split(str, "\n")[1:] { - if len(line) == 0 { - continue - } - isPath := line[0] == '\t' - if isPath { - continue - } - - sp := strings.Split(line, "/") - if len(sp) == 0 { - continue - } - i := strings.Index(sp[len(sp)-1], ".") - if i != -1 { - sp[len(sp)-1] = sp[len(sp)-1][:i] - } + lines := strings.Split(str, "\n")[1:] - if i := strings.Index(sp[0], "."); i != -1 { - sp = sp[2:] - } + i = int(math.RoundToEven(float64(i))) + 1 + line := lines[i] - modName := sp[0] - pkgName := sp[len(sp)-1] + sp := strings.Split(line, "/") + if len(sp) == 0 { + return "" + } + i = strings.Index(sp[len(sp)-1], ".") + if i != -1 { + sp[len(sp)-1] = sp[len(sp)-1][:i] + } - if pkgName == "log" { - continue - } + if i := strings.Index(sp[0], "."); i != -1 { + sp = sp[2:] + } - if modName == "main" { - modName = mainModuleName - } + modName := sp[0] + pkgName := sp[len(sp)-1] - return modName + "::" + pkgName + if modName == "main" { + modName = mainModuleName } - return "" + + return modName + "::" + pkgName } /* @@ -214,99 +206,103 @@ func Printlnf(format string, v ...any) (i int, err error) { return i + i0, err } +func Chat(t text.TextComponent) { + Printlnf("%s %s %s: %s", timeColor(timeString()), chatColor("CHAT "), stackColor(stackCallerModule(5)), SprintText(t)) +} + // prints the contents prefixed by a carriage return + time, blue info text and suffixed with a newline and "> " func Infoln(v ...any) { - fmt.Printf("\r%s %s %s: ", timeColor(timeString()), infoColor("INFO "), stackColor(stackCallerModule())) + fmt.Printf("\r%s %s %s: ", timeColor(timeString()), infoColor("INFO "), stackColor(stackCallerModule(3))) fmt.Println(v...) fmt.Print("\r> ") } // prints the contents prefixed by a carriage return + blue info text and suffixed with a new line func InfolnClean(v ...any) { - fmt.Printf("\r%s %s %s: ", timeColor(timeString()), infoColor("INFO "), stackColor(stackCallerModule())) + fmt.Printf("\r%s %s %s: ", timeColor(timeString()), infoColor("INFO "), stackColor(stackCallerModule(3))) fmt.Print(v...) fmt.Println("\r") } // prints the contents formatted prefixed by a carriage return + blue info text and suffixed with a new line func InfolnfClean(format string, v ...any) { - fmt.Printf("\r%s %s %s: ", timeColor(timeString()), infoColor("INFO "), stackColor(stackCallerModule())) + fmt.Printf("\r%s %s %s: ", timeColor(timeString()), infoColor("INFO "), stackColor(stackCallerModule(3))) fmt.Printf(format, v...) fmt.Println("\r") } // prints the contents prefixed by a carriage return + blue info text func Info(v ...any) { - fmt.Printf("\r%s %s %s: ", timeColor(timeString()), infoColor("INFO "), stackColor(stackCallerModule())) + fmt.Printf("\r%s %s %s: ", timeColor(timeString()), infoColor("INFO "), stackColor(stackCallerModule(3))) fmt.Print(v...) } // prints the contents prefixed by a carriage return + blue info text func Infof(format string, v ...any) { - fmt.Printf("\r%s %s %s: %s", timeColor(timeString()), infoColor("INFO "), stackColor(stackCallerModule()), fmt.Sprintf(format, v...)) + fmt.Printf("\r%s %s %s: %s", timeColor(timeString()), infoColor("INFO "), stackColor(stackCallerModule(3)), fmt.Sprintf(format, v...)) } // prints the contents prefixed by a carriage return + blue info text and suffixed with a newline and "> " func Infolnf(format string, v ...any) { - fmt.Printf("\r%s %s %s: %s\n\r> ", timeColor(timeString()), infoColor("INFO "), stackColor(stackCallerModule()), fmt.Sprintf(format, v...)) + fmt.Printf("\r%s %s %s: %s\n\r> ", timeColor(timeString()), infoColor("INFO "), stackColor(stackCallerModule(3)), fmt.Sprintf(format, v...)) } // prints the contents prefixed by a carriage return + blue info text and suffixed with a newline and "> " func Errorln(v ...any) { - fmt.Printf("\r%s %s %s: ", timeColor(timeString()), errorColor("ERROR"), stackColor(stackCallerModule())) + fmt.Printf("\r%s %s %s: ", timeColor(timeString()), errorColor("ERROR"), stackColor(stackCallerModule(3))) fmt.Println(v...) fmt.Print("\r> ") } // prints the contents prefixed by a carriage return + blue info text and suffixed with a new line func ErrorlnClean(v ...any) { - fmt.Printf("\r%s %s %s: ", timeColor(timeString()), errorColor("ERROR"), stackColor(stackCallerModule())) + fmt.Printf("\r%s %s %s: ", timeColor(timeString()), errorColor("ERROR"), stackColor(stackCallerModule(3))) fmt.Print(v...) fmt.Println("\r") } // prints the contents prefixed by a carriage return + blue info text func Error(v ...any) { - fmt.Printf("\r%s %s %s: ", timeColor(timeString()), errorColor("ERROR"), stackColor(stackCallerModule())) + fmt.Printf("\r%s %s %s: ", timeColor(timeString()), errorColor("ERROR"), stackColor(stackCallerModule(3))) fmt.Print(v...) } // prints the contents prefixed by a carriage return + blue info text func Errorf(format string, v ...any) { - fmt.Printf("\r%s %s %s: %s", timeColor(timeString()), errorColor("ERROR"), stackColor(stackCallerModule()), fmt.Sprintf(format, v...)) + fmt.Printf("\r%s %s %s: %s", timeColor(timeString()), errorColor("ERROR"), stackColor(stackCallerModule(3)), fmt.Sprintf(format, v...)) } // prints the contents prefixed by a carriage return + blue info text and suffixed with a newline and "> " func Errorlnf(format string, v ...any) { - fmt.Printf("\r%s %s %s: %s\n\r> ", timeColor(timeString()), errorColor("ERROR"), stackColor(stackCallerModule()), fmt.Sprintf(format, v...)) + fmt.Printf("\r%s %s %s: %s\n\r> ", timeColor(timeString()), errorColor("ERROR"), stackColor(stackCallerModule(3)), fmt.Sprintf(format, v...)) } // prints the contents prefixed by a carriage return + blue info text and suffixed with a newline and "> " func Warnln(v ...any) { - fmt.Printf("\r%s %s %s: ", timeColor(timeString()), warningColor("WARN "), stackColor(stackCallerModule())) + fmt.Printf("\r%s %s %s: ", timeColor(timeString()), warningColor("WARN "), stackColor(stackCallerModule(3))) fmt.Println(v...) fmt.Print("\r> ") } // prints the contents prefixed by a carriage return + blue info text and suffixed with a new line func WarnlnClean(v ...any) { - fmt.Printf("\r%s %s %s: ", timeColor(timeString()), warningColor("WARN "), stackColor(stackCallerModule())) + fmt.Printf("\r%s %s %s: ", timeColor(timeString()), warningColor("WARN "), stackColor(stackCallerModule(3))) fmt.Print(v...) fmt.Println("\r") } // prints the contents prefixed by a carriage return + blue info text func Warn(v ...any) { - fmt.Printf("\r%s %s %s: ", timeColor(timeString()), warningColor("WARN "), stackColor(stackCallerModule())) + fmt.Printf("\r%s %s %s: ", timeColor(timeString()), warningColor("WARN "), stackColor(stackCallerModule(3))) fmt.Print(v...) } // prints the contents prefixed by a carriage return + blue info text func Warnf(format string, v ...any) { - fmt.Printf("\r%s %s %s: %s", timeColor(timeString()), warningColor("WARN "), stackColor(stackCallerModule()), fmt.Sprintf(format, v...)) + fmt.Printf("\r%s %s %s: %s", timeColor(timeString()), warningColor("WARN "), stackColor(stackCallerModule(3)), fmt.Sprintf(format, v...)) } // prints the contents prefixed by a carriage return + blue info text and suffixed with a newline and "> " func Warnlnf(format string, v ...any) { - fmt.Printf("\r%s %s %s: %s\n\r> ", timeColor(timeString()), warningColor("WARN "), stackColor(stackCallerModule()), fmt.Sprintf(format, v...)) + fmt.Printf("\r%s %s %s: %s\n\r> ", timeColor(timeString()), warningColor("WARN "), stackColor(stackCallerModule(3)), fmt.Sprintf(format, v...)) }