Add support for dimension ranges and network hashes

This commit is contained in:
Javier León
2026-01-03 05:33:35 -03:00
parent 2ad86d772f
commit 7a4d57fa6a
10 changed files with 372 additions and 82 deletions

56
go.mod
View File

@@ -1,6 +1,6 @@
module github.com/akmalfairuz/legacy-version module github.com/akmalfairuz/legacy-version
go 1.24.0 go 1.25.1
require ( require (
github.com/cespare/xxhash/v2 v2.3.0 github.com/cespare/xxhash/v2 v2.3.0
@@ -13,27 +13,53 @@ require (
github.com/samber/lo v1.49.1 github.com/samber/lo v1.49.1
github.com/sandertv/gophertunnel v1.52.0 github.com/sandertv/gophertunnel v1.52.0
github.com/segmentio/fasthash v1.0.3 github.com/segmentio/fasthash v1.0.3
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b golang.org/x/exp v0.0.0-20251209150349-8475f28825e9
golang.org/x/image v0.25.0 golang.org/x/image v0.25.0
golang.org/x/oauth2 v0.32.0 golang.org/x/oauth2 v0.34.0
) )
require ( require (
github.com/brentp/intintmap v0.0.0-20190211203843-30dc0ade9af9 // indirect github.com/df-mc/go-nethernet v0.0.0-20250326113854-da40ae9a1339 // indirect
github.com/df-mc/go-playfab v1.0.0 // indirect
github.com/df-mc/go-xsapi v1.0.1 // indirect
github.com/df-mc/goleveldb v1.1.9 // indirect github.com/df-mc/goleveldb v1.1.9 // indirect
github.com/df-mc/jsonc v1.0.5 // indirect github.com/getsentry/sentry-go v0.40.0 // indirect
github.com/go-jose/go-jose/v4 v4.1.3 // indirect github.com/go-jose/go-jose/v4 v4.1.3 // indirect
github.com/golang/snappy v1.0.0 // indirect github.com/golang/snappy v1.0.0 // indirect
github.com/hashicorp/go-version v1.8.0 // indirect
github.com/klauspost/compress v1.18.2 // indirect github.com/klauspost/compress v1.18.2 // indirect
github.com/oreans/virtualizersdk v0.0.0-20250127084511-5dd538199a75 // indirect github.com/lumineproxy/log v0.0.0-20251025091855-37df1c504536 // indirect
github.com/sandertv/go-raknet v1.14.3-0.20250305181847-6af3e95113d6 // indirect github.com/lumineproxy/socks5udp v1.0.1-0.20251223034400-3f3b0cbbe69b // indirect
golang.org/x/mod v0.28.0 // indirect github.com/muhammadmuzzammil1998/jsonc v1.0.0 // indirect
golang.org/x/net v0.46.0 // indirect github.com/pion/datachannel v1.5.10 // indirect
golang.org/x/text v0.30.0 // indirect github.com/pion/dtls/v3 v3.0.9 // indirect
github.com/pion/ice/v4 v4.1.0 // indirect
github.com/pion/interceptor v0.1.42 // indirect
github.com/pion/logging v0.2.4 // indirect
github.com/pion/mdns/v2 v2.1.0 // indirect
github.com/pion/randutil v0.1.0 // indirect
github.com/pion/rtcp v1.2.16 // indirect
github.com/pion/rtp v1.8.27 // indirect
github.com/pion/sctp v1.8.41 // indirect
github.com/pion/sdp/v3 v3.0.17 // indirect
github.com/pion/srtp/v3 v3.0.9 // indirect
github.com/pion/stun/v3 v3.0.2 // indirect
github.com/pion/transport/v3 v3.1.1 // indirect
github.com/pion/turn/v4 v4.1.3 // indirect
github.com/pion/webrtc/v4 v4.1.8 // indirect
github.com/sandertv/go-raknet v1.14.3-0.20250823121252-325aeea25d25 // indirect
github.com/wlynxg/anet v0.0.5 // indirect
github.com/zaataylor/cartesian v0.0.0-20221028053253-3b3244d82727 // indirect
golang.org/x/crypto v0.46.0 // indirect
golang.org/x/mod v0.31.0 // indirect
golang.org/x/net v0.48.0 // indirect
golang.org/x/sys v0.39.0 // indirect
golang.org/x/text v0.32.0 // indirect
) )
replace github.com/sandertv/gophertunnel => ../gophertunnel replace (
github.com/df-mc/dragonfly => github.com/lumineproxy/dragonfly v0.0.0-20260101232342-710c0a1931ba
replace github.com/df-mc/dragonfly => ../dragonfly github.com/df-mc/go-nethernet => github.com/lumineproxy/go-nethernet v0.0.0-20251201013730-45766a8ec674
github.com/sandertv/go-raknet => github.com/lumineproxy/go-raknet v0.0.0-20260102015805-b139417c724e
replace github.com/sandertv/go-raknet => ../go-raknet github.com/sandertv/gophertunnel => github.com/lumineproxy/gophertunnel v0.0.0-20260102091803-5fb43dd59e0c
)

121
go.sum
View File

@@ -1,16 +1,23 @@
github.com/brentp/intintmap v0.0.0-20190211203843-30dc0ade9af9 h1:/G0ghZwrhou0Wq21qc1vXXMm/t/aKWkALWwITptKbE0=
github.com/brentp/intintmap v0.0.0-20190211203843-30dc0ade9af9/go.mod h1:TOk10ahXejq9wkEaym3KPRNeuR/h5Jx+s8QRWIa2oTM=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/df-mc/go-nethernet v0.0.0-20250326113854-da40ae9a1339 h1:4xyCykphezCW8p7fHYcNwQmGnPeFGdJYQ2E2PCvKMX4=
github.com/df-mc/go-nethernet v0.0.0-20250326113854-da40ae9a1339/go.mod h1:ZZI4ySBVAdbRfdZzxgBPaWcnqKglsxArW1gQbPfOXow=
github.com/df-mc/go-playfab v1.0.0 h1:6gVukk3aQbJ934GJFdcZJHVIw9lhauK+KHOevbwJA10=
github.com/df-mc/go-playfab v1.0.0/go.mod h1:nGOlE+JFGOH5Z0iidEgJapHhndFi/oNk17RN9pKCF+k=
github.com/df-mc/go-xsapi v1.0.1 h1:H1SbxYr4rXOqZSB8MwiODbDUsHRihxbHf+YOljUWgXw=
github.com/df-mc/go-xsapi v1.0.1/go.mod h1:uKC/a/2/JOamgRDezvgVe7OmXdqERUfmCcIWAOp9hPA=
github.com/df-mc/goleveldb v1.1.9 h1:ihdosZyy5jkQKrxucTQmN90jq/2lUwQnJZjIYIC/9YU= github.com/df-mc/goleveldb v1.1.9 h1:ihdosZyy5jkQKrxucTQmN90jq/2lUwQnJZjIYIC/9YU=
github.com/df-mc/goleveldb v1.1.9/go.mod h1:+NHCup03Sci5q84APIA21z3iPZCuk6m6ABtg4nANCSk= github.com/df-mc/goleveldb v1.1.9/go.mod h1:+NHCup03Sci5q84APIA21z3iPZCuk6m6ABtg4nANCSk=
github.com/df-mc/jsonc v1.0.5 h1:O7oh07kbS5AYY+l2Fji6l4h0iHcdjKbxCtK5VlZlLMU=
github.com/df-mc/jsonc v1.0.5/go.mod h1:+Q++JuCE9IKiP8v7sWImdf/RjQX0nfXyfX6PdfTTmc4=
github.com/df-mc/worldupgrader v1.0.20 h1:wfJyG3bFeaM/HXy7TCiO4HKVw3Mf3N4gPFmgxMHsKnc= github.com/df-mc/worldupgrader v1.0.20 h1:wfJyG3bFeaM/HXy7TCiO4HKVw3Mf3N4gPFmgxMHsKnc=
github.com/df-mc/worldupgrader v1.0.20/go.mod h1:tsSOLTRm9mpG7VHvYpAjjZrkRHWmSbKZAm9bOLNnlDk= github.com/df-mc/worldupgrader v1.0.20/go.mod h1:tsSOLTRm9mpG7VHvYpAjjZrkRHWmSbKZAm9bOLNnlDk=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/getsentry/sentry-go v0.40.0 h1:VTJMN9zbTvqDqPwheRVLcp0qcUcM+8eFivvGocAaSbo=
github.com/getsentry/sentry-go v0.40.0/go.mod h1:eRXCoh3uvmjQLY6qu63BjUZnaBu5L5WhMV1RwYO8W5s=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-gl/mathgl v1.2.0 h1:v2eOj/y1B2afDxF6URV1qCYmo1KW08lAMtTbOn3KXCY= github.com/go-gl/mathgl v1.2.0 h1:v2eOj/y1B2afDxF6URV1qCYmo1KW08lAMtTbOn3KXCY=
github.com/go-gl/mathgl v1.2.0/go.mod h1:pf9+b5J3LFP7iZ4XXaVzZrCle0Q/vNpB/vDe5+3ulRE= github.com/go-gl/mathgl v1.2.0/go.mod h1:pf9+b5J3LFP7iZ4XXaVzZrCle0Q/vNpB/vDe5+3ulRE=
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
@@ -19,22 +26,77 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4=
github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk= github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/lumineproxy/dragonfly v0.0.0-20260101232342-710c0a1931ba h1:saRfjri3R2SzMetb+5sa7EfbES78o9FrWhZrMXug+V8=
github.com/lumineproxy/dragonfly v0.0.0-20260101232342-710c0a1931ba/go.mod h1:mFWLjkOBy/UUAib+Lm0FsHpiHYcOkMySEqFOOlNBLzU=
github.com/lumineproxy/go-nethernet v0.0.0-20251201013730-45766a8ec674 h1:6Uzsrg+L1FTLOL9Sm/ThxBRAKV2BRM5VZH5lXLSkStU=
github.com/lumineproxy/go-nethernet v0.0.0-20251201013730-45766a8ec674/go.mod h1:ZZI4ySBVAdbRfdZzxgBPaWcnqKglsxArW1gQbPfOXow=
github.com/lumineproxy/go-raknet v0.0.0-20260102015805-b139417c724e h1:uO5S7wycolefX7xzm4vZimRliCSH4CRf3G41CF+wbOo=
github.com/lumineproxy/go-raknet v0.0.0-20260102015805-b139417c724e/go.mod h1:/yysjwfCXm2+2OY8mBazLzcxJ3irnylKCyG3FLgUPVU=
github.com/lumineproxy/gophertunnel v0.0.0-20260102091803-5fb43dd59e0c h1:l3WLstSweS2ZfLVWyBhmy4n+MmTRfo4ILZAuooSxQwY=
github.com/lumineproxy/gophertunnel v0.0.0-20260102091803-5fb43dd59e0c/go.mod h1:ZXQCPXRX+7aQpoKDtO3o6ZuhVkYmqsyAN54wYEPcs0g=
github.com/lumineproxy/log v0.0.0-20251025091855-37df1c504536 h1:1mqrDZdK6M2DU/GUOjY7B3voKv6Cibtmk7WXa04jKK8=
github.com/lumineproxy/log v0.0.0-20251025091855-37df1c504536/go.mod h1:VssmIwiWR46X7VSG7eBxf3MdogWm/lBhFIvASBUZf/4=
github.com/lumineproxy/socks5udp v1.0.1-0.20251223034400-3f3b0cbbe69b h1:guv1csIbQPQh9PXhFzKv8j5bxSTqa5Rsu9EA6F+a2Rg=
github.com/lumineproxy/socks5udp v1.0.1-0.20251223034400-3f3b0cbbe69b/go.mod h1:964howIepX8VNeFpEXR4a4uqHHlUnlxdGCTW/XCeFok=
github.com/muhammadmuzzammil1998/jsonc v1.0.0 h1:8o5gBQn4ZA3NBA9DlTujCj2a4w0tqWrPVjDwhzkgTIs=
github.com/muhammadmuzzammil1998/jsonc v1.0.0/go.mod h1:saF2fIVw4banK0H4+/EuqfFLpRnoy5S+ECwTOCcRcSU=
github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/oreans/virtualizersdk v0.0.0-20250127084511-5dd538199a75 h1:FqCGgY+GycamCHOhK7GWfCmPZwZ3Z6yh+zdoAqK1y/8= github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE=
github.com/oreans/virtualizersdk v0.0.0-20250127084511-5dd538199a75/go.mod h1:C1b5DqEix6/MXYnbMRdqofk6GXepv9p5Xw0EIfqvixw= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o=
github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M=
github.com/pion/dtls/v3 v3.0.9 h1:4AijfFRm8mAjd1gfdlB1wzJF3fjjR/VPIpJgkEtvYmM=
github.com/pion/dtls/v3 v3.0.9/go.mod h1:abApPjgadS/ra1wvUzHLc3o2HvoxppAh+NZkyApL4Os=
github.com/pion/ice/v4 v4.1.0 h1:YlxIii2bTPWyC08/4hdmtYq4srbrY0T9xcTsTjldGqU=
github.com/pion/ice/v4 v4.1.0/go.mod h1:5gPbzYxqenvn05k7zKPIZFuSAufolygiy6P1U9HzvZ4=
github.com/pion/interceptor v0.1.42 h1:0/4tvNtruXflBxLfApMVoMubUMik57VZ+94U0J7cmkQ=
github.com/pion/interceptor v0.1.42/go.mod h1:g6XYTChs9XyolIQFhRHOOUS+bGVGLRfgTCUzH29EfVU=
github.com/pion/logging v0.2.4 h1:tTew+7cmQ+Mc1pTBLKH2puKsOvhm32dROumOZ655zB8=
github.com/pion/logging v0.2.4/go.mod h1:DffhXTKYdNZU+KtJ5pyQDjvOAh/GsNSyv1lbkFbe3so=
github.com/pion/mdns/v2 v2.1.0 h1:3IJ9+Xio6tWYjhN6WwuY142P/1jA0D5ERaIqawg/fOY=
github.com/pion/mdns/v2 v2.1.0/go.mod h1:pcez23GdynwcfRU1977qKU0mDxSeucttSHbCSfFOd9A=
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
github.com/pion/rtcp v1.2.16 h1:fk1B1dNW4hsI78XUCljZJlC4kZOPk67mNRuQ0fcEkSo=
github.com/pion/rtcp v1.2.16/go.mod h1:/as7VKfYbs5NIb4h6muQ35kQF/J0ZVNz2Z3xKoCBYOo=
github.com/pion/rtp v1.8.27 h1:kbWTdZr62RDlYjatVAW4qFwrAu9XcGnwMsofCfAHlOU=
github.com/pion/rtp v1.8.27/go.mod h1:rF5nS1GqbR7H/TCpKwylzeq6yDM+MM6k+On5EgeThEM=
github.com/pion/sctp v1.8.41 h1:20R4OHAno4Vky3/iE4xccInAScAa83X6nWUfyc65MIs=
github.com/pion/sctp v1.8.41/go.mod h1:2wO6HBycUH7iCssuGyc2e9+0giXVW0pyCv3ZuL8LiyY=
github.com/pion/sdp/v3 v3.0.17 h1:9SfLAW/fF1XC8yRqQ3iWGzxkySxup4k4V7yN8Fs8nuo=
github.com/pion/sdp/v3 v3.0.17/go.mod h1:9tyKzznud3qiweZcD86kS0ff1pGYB3VX+Bcsmkx6IXo=
github.com/pion/srtp/v3 v3.0.9 h1:lRGF4G61xxj+m/YluB3ZnBpiALSri2lTzba0kGZMrQY=
github.com/pion/srtp/v3 v3.0.9/go.mod h1:E+AuWd7Ug2Fp5u38MKnhduvpVkveXJX6J4Lq4rxUYt8=
github.com/pion/stun/v3 v3.0.2 h1:BJuGEN2oLrJisiNEJtUTJC4BGbzbfp37LizfqswblFU=
github.com/pion/stun/v3 v3.0.2/go.mod h1:JFJKfIWvt178MCF5H/YIgZ4VX3LYE77vca4b9HP60SA=
github.com/pion/transport/v3 v3.1.1 h1:Tr684+fnnKlhPceU+ICdrw6KKkTms+5qHMgw6bIkYOM=
github.com/pion/transport/v3 v3.1.1/go.mod h1:+c2eewC5WJQHiAA46fkMMzoYZSuGzA/7E2FPrOYHctQ=
github.com/pion/turn/v4 v4.1.3 h1:jVNW0iR05AS94ysEtvzsrk3gKs9Zqxf6HmnsLfRvlzA=
github.com/pion/turn/v4 v4.1.3/go.mod h1:TD/eiBUf5f5LwXbCJa35T7dPtTpCHRJ9oJWmyPLVT3A=
github.com/pion/webrtc/v4 v4.1.8 h1:ynkjfiURDQ1+8EcJsoa60yumHAmyeYjz08AaOuor+sk=
github.com/pion/webrtc/v4 v4.1.8/go.mod h1:KVaARG2RN0lZx0jc7AWTe38JpPv+1/KicOZ9jN52J/s=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
@@ -43,33 +105,40 @@ github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew=
github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o= github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM=
github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0= github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4= github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
github.com/zaataylor/cartesian v0.0.0-20221028053253-3b3244d82727 h1:eP/MDnwQtFR2hwUv84a5kD5bKgjx3wir69Nhy33Pl4I=
github.com/zaataylor/cartesian v0.0.0-20221028053253-3b3244d82727/go.mod h1:gEXybXQbaNi8PEDSaJ/a9AEG8tiqtnEaPtKFugCAjwU=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
golang.org/x/exp v0.0.0-20251209150349-8475f28825e9 h1:MDfG8Cvcqlt9XXrmEiD4epKn7VJHZO84hejP9Jmp0MM=
golang.org/x/exp v0.0.0-20251209150349-8475f28825e9/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU=
golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ= golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ=
golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs= golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs=
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY= golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/akmalfairuz/legacy-version/mapping"
"github.com/df-mc/dragonfly/server/block/cube" "github.com/df-mc/dragonfly/server/block/cube"
) )
@@ -11,7 +12,7 @@ import (
// returned is nil and the error non-nil. // returned is nil and the error non-nil.
// The sub chunk count passed must be that found in the LevelChunk packet. // The sub chunk count passed must be that found in the LevelChunk packet.
// noinspection GoUnusedExportedFunction // noinspection GoUnusedExportedFunction
func NetworkDecode(air uint32, buf *bytes.Buffer, count int, oldFormat bool, r cube.Range, pse Encoding, pe PaletteEncoding) (*Chunk, error) { func NetworkDecode(air uint32, buf *bytes.Buffer, count int, oldFormat bool, r cube.Range, pse Encoding, pe PaletteEncoding, block mapping.Block, useBlockHashes bool) (*Chunk, error) {
var ( var (
c = New(air, r) c = New(air, r)
err error err error
@@ -21,7 +22,7 @@ func NetworkDecode(air uint32, buf *bytes.Buffer, count int, oldFormat bool, r c
if oldFormat { if oldFormat {
index += 4 index += 4
} }
c.sub[index], err = DecodeSubChunk(air, r, buf, &index, NetworkEncoding, pse, pe) c.sub[index], err = DecodeSubChunk(air, r, buf, &index, NetworkEncoding, pse, pe, block, useBlockHashes)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -45,7 +46,7 @@ func NetworkDecode(air uint32, buf *bytes.Buffer, count int, oldFormat bool, r c
} else { } else {
var last *PalettedStorage var last *PalettedStorage
for i := 0; i < len(c.sub); i++ { for i := 0; i < len(c.sub); i++ {
b, err := decodePalettedStorage(buf, NetworkEncoding, pse, BiomePaletteEncoding) b, err := decodePalettedStorage(buf, NetworkEncoding, pse, BiomePaletteEncoding, block, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -68,7 +69,7 @@ func NetworkDecode(air uint32, buf *bytes.Buffer, count int, oldFormat bool, r c
// DecodeSubChunk decodes a SubChunk from a bytes.Buffer. The Encoding passed defines how the block storages of the // DecodeSubChunk decodes a SubChunk from a bytes.Buffer. The Encoding passed defines how the block storages of the
// SubChunk are decoded. // SubChunk are decoded.
func DecodeSubChunk(air uint32, r cube.Range, buf *bytes.Buffer, index *byte, e Encoding, pse Encoding, pe PaletteEncoding) (*SubChunk, error) { func DecodeSubChunk(air uint32, r cube.Range, buf *bytes.Buffer, index *byte, e Encoding, pse Encoding, pe PaletteEncoding, block mapping.Block, useBlockHashes bool) (*SubChunk, error) {
ver, err := buf.ReadByte() ver, err := buf.ReadByte()
if err != nil { if err != nil {
return nil, fmt.Errorf("error reading version: %w", err) return nil, fmt.Errorf("error reading version: %w", err)
@@ -79,7 +80,7 @@ func DecodeSubChunk(air uint32, r cube.Range, buf *bytes.Buffer, index *byte, e
return nil, fmt.Errorf("unknown sub chunk version %v: can't decode", ver) return nil, fmt.Errorf("unknown sub chunk version %v: can't decode", ver)
case 1: case 1:
// Version 1 only has one layer for each sub chunk, but uses the format with palettes. // Version 1 only has one layer for each sub chunk, but uses the format with palettes.
storage, err := decodePalettedStorage(buf, e, pse, pe) storage, err := decodePalettedStorage(buf, e, pse, pe, block, useBlockHashes)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -102,7 +103,7 @@ func DecodeSubChunk(air uint32, r cube.Range, buf *bytes.Buffer, index *byte, e
sub.storages = make([]*PalettedStorage, storageCount) sub.storages = make([]*PalettedStorage, storageCount)
for i := byte(0); i < storageCount; i++ { for i := byte(0); i < storageCount; i++ {
sub.storages[i], err = decodePalettedStorage(buf, e, pse, pe) sub.storages[i], err = decodePalettedStorage(buf, e, pse, pe, block, useBlockHashes)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -113,7 +114,7 @@ func DecodeSubChunk(air uint32, r cube.Range, buf *bytes.Buffer, index *byte, e
// decodePalettedStorage decodes a PalettedStorage from a bytes.Buffer. The Encoding passed is used to read either a // decodePalettedStorage decodes a PalettedStorage from a bytes.Buffer. The Encoding passed is used to read either a
// network or disk block storage. // network or disk block storage.
func decodePalettedStorage(buf *bytes.Buffer, e Encoding, pse Encoding, pe PaletteEncoding) (*PalettedStorage, error) { func decodePalettedStorage(buf *bytes.Buffer, e Encoding, pse Encoding, pe PaletteEncoding, block mapping.Block, useBlockHashes bool) (*PalettedStorage, error) {
blockSize, err := buf.ReadByte() blockSize, err := buf.ReadByte()
if err != nil { if err != nil {
return nil, fmt.Errorf("error reading block size: %w", err) return nil, fmt.Errorf("error reading block size: %w", err)
@@ -142,5 +143,15 @@ func decodePalettedStorage(buf *bytes.Buffer, e Encoding, pse Encoding, pe Palet
uint32s[i] = uint32(data[i*4]) | uint32(data[i*4+1])<<8 | uint32(data[i*4+2])<<16 | uint32(data[i*4+3])<<24 uint32s[i] = uint32(data[i*4]) | uint32(data[i*4+1])<<8 | uint32(data[i*4+2])<<16 | uint32(data[i*4+3])<<24
} }
p, err := e.DecodePalette(buf, paletteSize(blockSize), pe) p, err := e.DecodePalette(buf, paletteSize(blockSize), pe)
return newPalettedStorage(uint32s, p), err if err != nil {
return nil, err
}
if useBlockHashes {
for i, hash := range p.values {
if rid, ok := block.HashToRuntimeID(hash); ok {
p.values[i] = rid
}
}
}
return newPalettedStorage(uint32s, p), nil
} }

View File

@@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"sync" "sync"
"github.com/akmalfairuz/legacy-version/mapping"
"github.com/df-mc/dragonfly/server/block/cube" "github.com/df-mc/dragonfly/server/block/cube"
) )
@@ -14,10 +15,10 @@ var pool = sync.Pool{
}, },
} }
func NetworkEncode(air uint32, c *Chunk, oldFormat bool, pe PaletteEncoding) ([]byte, error) { func NetworkEncode(air uint32, c *Chunk, oldFormat bool, pe PaletteEncoding, block mapping.Block, useBlockHashes bool) ([]byte, error) {
buf := pool.Get().(*bytes.Buffer) buf := pool.Get().(*bytes.Buffer)
for i := 0; i < len(c.sub); i++ { for i := 0; i < len(c.sub); i++ {
_, _ = buf.Write(EncodeSubChunk(c.sub[i], NetworkEncoding, pe, SubChunkVersion8, c.r, i)) _, _ = buf.Write(EncodeSubChunk(c.sub[i], NetworkEncoding, pe, SubChunkVersion8, c.r, i, block, useBlockHashes))
} }
if oldFormat { if oldFormat {
biomes := make([]byte, 256) biomes := make([]byte, 256)
@@ -30,7 +31,7 @@ func NetworkEncode(air uint32, c *Chunk, oldFormat bool, pe PaletteEncoding) ([]
} }
_, _ = buf.Write(biomes) _, _ = buf.Write(biomes)
} else { } else {
_, _ = buf.Write(EncodeBiomes(c, NetworkEncoding)) _, _ = buf.Write(EncodeBiomes(c, NetworkEncoding, block, useBlockHashes))
} }
return buf.Bytes(), nil return buf.Bytes(), nil
@@ -38,7 +39,7 @@ func NetworkEncode(air uint32, c *Chunk, oldFormat bool, pe PaletteEncoding) ([]
// EncodeSubChunk encodes a sub-chunk from a chunk into bytes. An Encoding may be passed to encode either for network or // EncodeSubChunk encodes a sub-chunk from a chunk into bytes. An Encoding may be passed to encode either for network or
// disk purposed, the most notable difference being that the network encoding generally uses varints and no NBT. // disk purposed, the most notable difference being that the network encoding generally uses varints and no NBT.
func EncodeSubChunk(s *SubChunk, e Encoding, pe PaletteEncoding, subChunkVer subChunkVersion, r cube.Range, ind int) []byte { func EncodeSubChunk(s *SubChunk, e Encoding, pe PaletteEncoding, subChunkVer subChunkVersion, r cube.Range, ind int, block mapping.Block, useBlockHashes bool) []byte {
buf := pool.Get().(*bytes.Buffer) buf := pool.Get().(*bytes.Buffer)
defer func() { defer func() {
buf.Reset() buf.Reset()
@@ -47,7 +48,7 @@ func EncodeSubChunk(s *SubChunk, e Encoding, pe PaletteEncoding, subChunkVer sub
subChunkVer.EncodeHeader(buf, s, r, ind) subChunkVer.EncodeHeader(buf, s, r, ind)
for _, storage := range s.storages { for _, storage := range s.storages {
encodePalettedStorage(buf, storage, nil, e, pe) encodePalettedStorage(buf, storage, nil, e, pe, block, useBlockHashes)
} }
sub := make([]byte, buf.Len()) sub := make([]byte, buf.Len())
_, _ = buf.Read(sub) _, _ = buf.Read(sub)
@@ -56,7 +57,7 @@ func EncodeSubChunk(s *SubChunk, e Encoding, pe PaletteEncoding, subChunkVer sub
// EncodeBiomes encodes the biomes of a chunk into bytes. An Encoding may be passed to encode either for network or // EncodeBiomes encodes the biomes of a chunk into bytes. An Encoding may be passed to encode either for network or
// disk purposed, the most notable difference being that the network encoding generally uses varints and no NBT. // disk purposed, the most notable difference being that the network encoding generally uses varints and no NBT.
func EncodeBiomes(c *Chunk, e Encoding) []byte { func EncodeBiomes(c *Chunk, e Encoding, block mapping.Block, useBlockHashes bool) []byte {
buf := pool.Get().(*bytes.Buffer) buf := pool.Get().(*bytes.Buffer)
defer func() { defer func() {
buf.Reset() buf.Reset()
@@ -65,7 +66,7 @@ func EncodeBiomes(c *Chunk, e Encoding) []byte {
var previous *PalettedStorage var previous *PalettedStorage
for _, b := range c.biomes { for _, b := range c.biomes {
encodePalettedStorage(buf, b, previous, e, BiomePaletteEncoding) encodePalettedStorage(buf, b, previous, e, BiomePaletteEncoding, block, useBlockHashes)
previous = b previous = b
} }
biomes := make([]byte, buf.Len()) biomes := make([]byte, buf.Len())
@@ -75,7 +76,7 @@ func EncodeBiomes(c *Chunk, e Encoding) []byte {
// encodePalettedStorage encodes a PalettedStorage into a bytes.Buffer. The Encoding passed is used to write the Palette // encodePalettedStorage encodes a PalettedStorage into a bytes.Buffer. The Encoding passed is used to write the Palette
// of the PalettedStorage. // of the PalettedStorage.
func encodePalettedStorage(buf *bytes.Buffer, storage, previous *PalettedStorage, e Encoding, pe PaletteEncoding) { func encodePalettedStorage(buf *bytes.Buffer, storage, previous *PalettedStorage, e Encoding, pe PaletteEncoding, block mapping.Block, useBlockHashes bool) {
if storage.Equal(previous) { if storage.Equal(previous) {
_, _ = buf.Write([]byte{0x7f<<1 | e.Network()}) _, _ = buf.Write([]byte{0x7f<<1 | e.Network()})
return return
@@ -89,5 +90,13 @@ func encodePalettedStorage(buf *bytes.Buffer, storage, previous *PalettedStorage
} }
_, _ = buf.Write(b) _, _ = buf.Write(b)
e.EncodePalette(buf, storage.palette, pe) palette := storage.palette
if useBlockHashes {
for i, rid := range palette.values {
if hash, ok := block.RuntimeIDToHash(rid); ok {
palette.values[i] = hash
}
}
}
e.EncodePalette(buf, palette, pe)
} }

View File

@@ -64,7 +64,7 @@ func lookupOrCreateBlockTranslator(protocolVersion, blockVersion int32, blockSta
} }
// DowngradeLevelChunkPacket downgrades the given level chunk packet to the specified protocol version. // DowngradeLevelChunkPacket downgrades the given level chunk packet to the specified protocol version.
func DowngradeLevelChunkPacket(protocolVersion int32, pk *packet.LevelChunk) error { func DowngradeLevelChunkPacket(protocolVersion int32, pk *packet.LevelChunk, conn *minecraft.Conn) error {
blockTranslatorsMu.RLock() blockTranslatorsMu.RLock()
translator, ok := blockTranslators[protocolVersion] translator, ok := blockTranslators[protocolVersion]
blockTranslatorsMu.RUnlock() blockTranslatorsMu.RUnlock()
@@ -72,5 +72,5 @@ func DowngradeLevelChunkPacket(protocolVersion int32, pk *packet.LevelChunk) err
return fmt.Errorf("no block translator found for protocol version %d", protocolVersion) return fmt.Errorf("no block translator found for protocol version %d", protocolVersion)
} }
return translator.DowngradeLevelChunk(pk) return translator.DowngradeLevelChunk(pk, conn)
} }

View File

@@ -9,6 +9,7 @@ import (
"github.com/cespare/xxhash/v2" "github.com/cespare/xxhash/v2"
"github.com/df-mc/dragonfly/server/block/cube" "github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/world" "github.com/df-mc/dragonfly/server/world"
"github.com/hashicorp/go-version"
"github.com/sandertv/gophertunnel/minecraft" "github.com/sandertv/gophertunnel/minecraft"
"github.com/sandertv/gophertunnel/minecraft/nbt" "github.com/sandertv/gophertunnel/minecraft/nbt"
"github.com/sandertv/gophertunnel/minecraft/protocol" "github.com/sandertv/gophertunnel/minecraft/protocol"
@@ -24,6 +25,7 @@ var (
LatestNetworkPersistentEncoding = chunk.NewNetworkPersistentEncoding(blockMappingLatest, BlockVersionLatest) LatestNetworkPersistentEncoding = chunk.NewNetworkPersistentEncoding(blockMappingLatest, BlockVersionLatest)
// LatestBlockPaletteEncoding is the paletteEncoding used for encoding a palette of block states encoded as NBT. // LatestBlockPaletteEncoding is the paletteEncoding used for encoding a palette of block states encoded as NBT.
LatestBlockPaletteEncoding = chunk.NewBlockPaletteEncoding(blockMappingLatest, BlockVersionLatest) LatestBlockPaletteEncoding = chunk.NewBlockPaletteEncoding(blockMappingLatest, BlockVersionLatest)
cavesAndCliffsVersion, _ = version.NewVersion("1.18.0")
) )
type BlockTranslator interface { type BlockTranslator interface {
@@ -32,17 +34,18 @@ type BlockTranslator interface {
// UpgradeBlockPackets upgrades the input block packets to the latest block packets. // UpgradeBlockPackets upgrades the input block packets to the latest block packets.
UpgradeBlockPackets([]packet.Packet, *minecraft.Conn) (result []packet.Packet) UpgradeBlockPackets([]packet.Packet, *minecraft.Conn) (result []packet.Packet)
// DowngradeLevelChunk downgrades the given LevelChunk packet to a legacy format. // DowngradeLevelChunk downgrades the given LevelChunk packet to a legacy format.
DowngradeLevelChunk(*packet.LevelChunk) error DowngradeLevelChunk(*packet.LevelChunk, *minecraft.Conn) error
// BlockMapping returns the block mapping used by this translator. // BlockMapping returns the block mapping used by this translator.
BlockMapping() mapping.Block BlockMapping() mapping.Block
} }
type DefaultBlockTranslator struct { type DefaultBlockTranslator struct {
mapping mapping.Block mapping mapping.Block
latest mapping.Block latest mapping.Block
pse chunk.Encoding pse chunk.Encoding
pe chunk.PaletteEncoding pe chunk.PaletteEncoding
oldFormat bool oldFormat bool
dimensionDefinitions []protocol.DimensionDefinition
currentDimension int32
} }
func NewBlockTranslator(mapping mapping.Block, latestMapping mapping.Block, pse chunk.Encoding, pe chunk.PaletteEncoding, oldFormat bool) *DefaultBlockTranslator { func NewBlockTranslator(mapping mapping.Block, latestMapping mapping.Block, pse chunk.Encoding, pe chunk.PaletteEncoding, oldFormat bool) *DefaultBlockTranslator {
@@ -53,7 +56,7 @@ func (t *DefaultBlockTranslator) BlockMapping() mapping.Block {
return t.mapping return t.mapping
} }
func (t *DefaultBlockTranslator) DowngradeLevelChunk(pk *packet.LevelChunk) error { func (t *DefaultBlockTranslator) DowngradeLevelChunk(pk *packet.LevelChunk, conn *minecraft.Conn) error {
count := int(pk.SubChunkCount) count := int(pk.SubChunkCount)
if count == protocol.SubChunkRequestModeLimitless || count == protocol.SubChunkRequestModeLimited { if count == protocol.SubChunkRequestModeLimitless || count == protocol.SubChunkRequestModeLimited {
return nil return nil
@@ -62,13 +65,13 @@ func (t *DefaultBlockTranslator) DowngradeLevelChunk(pk *packet.LevelChunk) erro
buf := bytes.NewBuffer(pk.RawPayload) buf := bytes.NewBuffer(pk.RawPayload)
writeBuf := bytes.NewBuffer(nil) writeBuf := bytes.NewBuffer(nil)
if !pk.CacheEnabled { if !pk.CacheEnabled {
c, err := chunk.NetworkDecode(t.latest.Air(), buf, count, false, world.Overworld.Range(), LatestNetworkPersistentEncoding, LatestBlockPaletteEncoding) c, err := chunk.NetworkDecode(t.latest.Air(), buf, count, false, t.getRange(conn), LatestNetworkPersistentEncoding, LatestBlockPaletteEncoding, t.latest, conn.GameData().UseBlockNetworkIDHashes)
if err != nil { if err != nil {
return err return err
} }
c = t.DowngradeChunk(c) c = t.DowngradeChunk(c, conn)
payload, err := chunk.NetworkEncode(t.mapping.Air(), c, t.oldFormat, t.pe) payload, err := chunk.NetworkEncode(t.mapping.Air(), c, t.oldFormat, t.pe, t.mapping, false)
if err != nil { if err != nil {
return err return err
} }
@@ -114,7 +117,7 @@ func (t *DefaultBlockTranslator) DowngradeBlockPackets(pks []packet.Packet, conn
if !EnableChunkTranslation { if !EnableChunkTranslation {
break break
} }
if err := t.DowngradeLevelChunk(pk); err != nil { if err := t.DowngradeLevelChunk(pk, conn); err != nil {
//fmt.Println(err) //fmt.Println(err)
break break
} }
@@ -122,7 +125,7 @@ func (t *DefaultBlockTranslator) DowngradeBlockPackets(pks []packet.Packet, conn
if !EnableChunkTranslation { if !EnableChunkTranslation {
break break
} }
r := world.Overworld.Range() r := t.getRange(conn)
if t.oldFormat { if t.oldFormat {
r = cube.Range{0, 255} r = cube.Range{0, 255}
} }
@@ -133,13 +136,13 @@ func (t *DefaultBlockTranslator) DowngradeBlockPackets(pks []packet.Packet, conn
writeBuf := bytes.NewBuffer(nil) writeBuf := bytes.NewBuffer(nil)
if !pk.CacheEnabled && !conn.ClientCacheEnabled() { if !pk.CacheEnabled && !conn.ClientCacheEnabled() {
ind := byte(i) ind := byte(i)
subChunk, err := chunk.DecodeSubChunk(t.latest.Air(), r, buf, &ind, chunk.NetworkEncoding, LatestNetworkPersistentEncoding, LatestBlockPaletteEncoding) subChunk, err := chunk.DecodeSubChunk(t.latest.Air(), r, buf, &ind, chunk.NetworkEncoding, LatestNetworkPersistentEncoding, LatestBlockPaletteEncoding, t.latest, conn.GameData().UseBlockNetworkIDHashes)
if err != nil { if err != nil {
//fmt.Println(err) //fmt.Println(err)
continue continue
} }
t.DowngradeSubChunk(subChunk) t.DowngradeSubChunk(subChunk)
writeBuf.Write(chunk.EncodeSubChunk(subChunk, chunk.NetworkEncoding, t.pe, chunk.SubChunkVersion9, r, int(ind))) writeBuf.Write(chunk.EncodeSubChunk(subChunk, chunk.NetworkEncoding, t.pe, chunk.SubChunkVersion9, r, int(ind), t.mapping, false))
} }
enc := nbt.NewEncoderWithEncoding(writeBuf, nbt.NetworkLittleEndian) enc := nbt.NewEncoderWithEncoding(writeBuf, nbt.NetworkLittleEndian)
@@ -162,7 +165,7 @@ func (t *DefaultBlockTranslator) DowngradeBlockPackets(pks []packet.Packet, conn
} }
} }
case *packet.ClientCacheMissResponse: case *packet.ClientCacheMissResponse:
r := world.Overworld.Range() r := t.getRange(conn)
if t.oldFormat { if t.oldFormat {
r = cube.Range{0, 255} r = cube.Range{0, 255}
} }
@@ -170,14 +173,13 @@ func (t *DefaultBlockTranslator) DowngradeBlockPackets(pks []packet.Packet, conn
for i, blob := range pk.Blobs { for i, blob := range pk.Blobs {
buf := bytes.NewBuffer(blob.Payload) buf := bytes.NewBuffer(blob.Payload)
ind := byte(0) ind := byte(0)
subChunk, err := chunk.DecodeSubChunk(t.latest.Air(), r, buf, &ind, chunk.NetworkEncoding, LatestNetworkPersistentEncoding, LatestBlockPaletteEncoding) subChunk, err := chunk.DecodeSubChunk(t.latest.Air(), r, buf, &ind, chunk.NetworkEncoding, LatestNetworkPersistentEncoding, LatestBlockPaletteEncoding, t.latest, conn.GameData().UseBlockNetworkIDHashes)
if err != nil { if err != nil {
// Has a possibility to be a biome, ignore then // Has a possibility to be a biome, ignore then
continue continue
} }
t.DowngradeSubChunk(subChunk) t.DowngradeSubChunk(subChunk)
blob.Payload = append(chunk.EncodeSubChunk(subChunk, chunk.NetworkEncoding, t.pe, chunk.SubChunkVersion9, r, int(ind), t.mapping, false), buf.Bytes()...)
blob.Payload = append(chunk.EncodeSubChunk(subChunk, chunk.NetworkEncoding, t.pe, chunk.SubChunkVersion9, r, int(ind)), buf.Bytes()...)
blob.Hash = xxhash.Sum64(blob.Payload) blob.Hash = xxhash.Sum64(blob.Payload)
pk.Blobs[i] = blob pk.Blobs[i] = blob
} }
@@ -280,13 +282,13 @@ func (t *DefaultBlockTranslator) DowngradeBlockRuntimeID(input uint32) uint32 {
return runtimeID return runtimeID
} }
func (t *DefaultBlockTranslator) DowngradeChunk(input *chunk.Chunk) *chunk.Chunk { func (t *DefaultBlockTranslator) DowngradeChunk(input *chunk.Chunk, conn *minecraft.Conn) *chunk.Chunk {
if t.latest == t.mapping { if t.latest == t.mapping {
return input return input
} }
start := 0 start := 0
r := world.Overworld.Range() r := t.getRange(conn)
if t.oldFormat { if t.oldFormat {
start = 4 start = 4
r = cube.Range{0, 255} r = cube.Range{0, 255}
@@ -357,3 +359,29 @@ func (t *DefaultBlockTranslator) upgradeEntityMetadata(metadata map[uint32]any)
} }
return metadata return metadata
} }
func (t *DefaultBlockTranslator) getRange(conn *minecraft.Conn) (r cube.Range) {
var dimName string
switch t.currentDimension {
case 0:
dimName = "minecraft:overworld"
r = world.Overworld.Range()
v, err := version.NewVersion(conn.GameData().BaseGameVersion)
if err == nil && v.LessThan(cavesAndCliffsVersion) {
r = cube.Range{0, 255}
}
case 1:
dimName = "minecraft:nether"
r = world.Nether.Range()
case 2:
dimName = "minecraft:the_end"
r = world.End.Range()
}
for _, def := range t.dimensionDefinitions {
if def.Name == dimName {
r = cube.Range{int(def.Range[0]), int(def.Range[1])}
break
}
}
return
}

View File

@@ -0,0 +1,18 @@
package legacypacket
import (
"github.com/sandertv/gophertunnel/minecraft/protocol"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
)
type DimensionData struct {
Definitions []protocol.DimensionDefinition
}
func (*DimensionData) ID() uint32 {
return packet.IDDimensionData
}
func (pk *DimensionData) Marshal(io protocol.IO) {
protocol.Slice(io, &pk.Definitions)
}

View File

@@ -31,6 +31,8 @@ func init() {
func convertPacketFunc(pid uint32, cur func() packet.Packet) func() packet.Packet { func convertPacketFunc(pid uint32, cur func() packet.Packet) func() packet.Packet {
switch pid { switch pid {
case packet.IDDimensionData:
return func() packet.Packet { return &legacypacket.DimensionData{} }
case packet.IDCameraAimAssist: case packet.IDCameraAimAssist:
return func() packet.Packet { return &legacypacket.CameraAimAssist{} } return func() packet.Packet { return &legacypacket.CameraAimAssist{} }
case packet.IDCameraPresets: case packet.IDCameraPresets:
@@ -190,8 +192,14 @@ func (p *Protocol) ConvertFromLatest(pk packet.Packet, conn *minecraft.Conn) []p
} }
func (p *Protocol) downgradePackets(pks []packet.Packet, conn *minecraft.Conn) []packet.Packet { func (p *Protocol) downgradePackets(pks []packet.Packet, conn *minecraft.Conn) []packet.Packet {
translator, ok := p.blockTranslator.(*DefaultBlockTranslator)
if !ok {
return pks
}
for pkIndex, pk := range pks { for pkIndex, pk := range pks {
switch pk := pk.(type) { switch pk := pk.(type) {
case *packet.DimensionData:
translator.dimensionDefinitions = pk.Definitions
case *packet.ClientCacheStatus: case *packet.ClientCacheStatus:
// pk.Enabled = false // TODO: enable when chunk translation is not broken // pk.Enabled = false // TODO: enable when chunk translation is not broken
case *packet.SetActorMotion: case *packet.SetActorMotion:
@@ -414,6 +422,7 @@ func (p *Protocol) downgradePackets(pks []packet.Packet, conn *minecraft.Conn) [
DetachFromEntity: pk.DetachFromEntity, DetachFromEntity: pk.DetachFromEntity,
} }
case *packet.ChangeDimension: case *packet.ChangeDimension:
translator.currentDimension = pk.Dimension
pks[pkIndex] = &legacypacket.ChangeDimension{ pks[pkIndex] = &legacypacket.ChangeDimension{
Dimension: pk.Dimension, Dimension: pk.Dimension,
Position: pk.Position, Position: pk.Position,
@@ -519,6 +528,7 @@ func (p *Protocol) downgradePackets(pks []packet.Packet, conn *minecraft.Conn) [
ClearRecipes: pk.ClearRecipes, ClearRecipes: pk.ClearRecipes,
} }
case *packet.StartGame: case *packet.StartGame:
translator.currentDimension = pk.Dimension
// Adjust game version // Adjust game version
pk.GameVersion = p.ver pk.GameVersion = p.ver
pk.BaseGameVersion = p.ver pk.BaseGameVersion = p.ver

View File

@@ -21,6 +21,8 @@ type Block interface {
DowngradeBlockActorData(map[string]any) DowngradeBlockActorData(map[string]any)
// UpgradeBlockActorData upgrades the input sub chunk to the latest block actor. // UpgradeBlockActorData upgrades the input sub chunk to the latest block actor.
UpgradeBlockActorData(map[string]any) UpgradeBlockActorData(map[string]any)
HashToRuntimeID(hash uint32) (rid uint32, ok bool)
RuntimeIDToHash(rid uint32) (hash uint32, ok bool)
// Adjust adjusts the latest mappings to account for custom states. // Adjust adjusts the latest mappings to account for custom states.
Adjust([]protocol.BlockEntry) Adjust([]protocol.BlockEntry)
Air() uint32 Air() uint32
@@ -41,6 +43,9 @@ type DefaultBlockMapping struct {
// infoUpdateRID is the runtime ID of the info_update block in the latest version of the game. // infoUpdateRID is the runtime ID of the info_update block in the latest version of the game.
infoUpdateBlockRID uint32 infoUpdateBlockRID uint32
networkhashToRids map[uint32]uint32
ridsToNetworkhash map[uint32]uint32
} }
func NewBlockMapping(raw []byte) *DefaultBlockMapping { func NewBlockMapping(raw []byte) *DefaultBlockMapping {
@@ -51,6 +56,8 @@ func NewBlockMapping(raw []byte) *DefaultBlockMapping {
runtimeIDToState := make(map[uint32]blockupgrader.BlockState) runtimeIDToState := make(map[uint32]blockupgrader.BlockState)
var airRID *uint32 var airRID *uint32
var infoUpdateBlockRID *uint32 var infoUpdateBlockRID *uint32
networkhashToRids := make(map[uint32]uint32)
ridsToNetworkhash := make(map[uint32]uint32)
var s blockupgrader.BlockState var s blockupgrader.BlockState
for { for {
@@ -67,8 +74,11 @@ func NewBlockMapping(raw []byte) *DefaultBlockMapping {
infoUpdateBlockRID = &rid infoUpdateBlockRID = &rid
} }
stateRuntimeIDs[internal.HashState(blockupgrader.Upgrade(s))] = rid upgradedStates := blockupgrader.Upgrade(s)
stateRuntimeIDs[internal.HashState(upgradedStates)] = rid
runtimeIDToState[rid] = s runtimeIDToState[rid] = s
networkhashToRids[networkBlockHash(upgradedStates.Name, upgradedStates.Properties)] = rid
ridsToNetworkhash[rid] = networkBlockHash(s.Name, s.Properties)
} }
if airRID == nil { if airRID == nil {
panic("couldn't find air") panic("couldn't find air")
@@ -83,6 +93,8 @@ func NewBlockMapping(raw []byte) *DefaultBlockMapping {
runtimeIDToState: runtimeIDToState, runtimeIDToState: runtimeIDToState,
airRID: *airRID, airRID: *airRID,
infoUpdateBlockRID: *infoUpdateBlockRID, infoUpdateBlockRID: *infoUpdateBlockRID,
networkhashToRids: networkhashToRids,
ridsToNetworkhash: ridsToNetworkhash,
} }
} }
@@ -114,6 +126,16 @@ func (m *DefaultBlockMapping) UpgradeBlockActorData(actorData map[string]any) {
} }
} }
func (m *DefaultBlockMapping) RuntimeIDToHash(rid uint32) (uint32, bool) {
hash, found := m.ridsToNetworkhash[rid]
return hash, found
}
func (m *DefaultBlockMapping) HashToRuntimeID(hash uint32) (uint32, bool) {
rid, found := m.networkhashToRids[hash]
return rid, found
}
func (m *DefaultBlockMapping) Adjust(entries []protocol.BlockEntry) { func (m *DefaultBlockMapping) Adjust(entries []protocol.BlockEntry) {
if len(entries) == 0 { if len(entries) == 0 {
return return

View File

@@ -0,0 +1,97 @@
package mapping
import (
"encoding/binary"
"hash/fnv"
"sort"
"strings"
)
var bufNetworkhash []byte = make([]byte, 0xff)
func networkBlockHash(name string, properties map[string]any) uint32 {
if name == "minecraft:unknown" {
return 0xfffffffe // -2
}
keys := make([]string, 0, len(properties))
for k := range properties {
keys = append(keys, k)
}
sort.Strings(keys)
bufNetworkhash = bufNetworkhash[:0]
var data = bufNetworkhash
writeString := func(str string) {
data = binary.LittleEndian.AppendUint16(data, uint16(len(str)))
data = append(data, []byte(str)...)
}
data = append(data, 10) // compound
data = append(data, 0)
data = append(data, 0)
data = append(data, 8) // string
writeString("name")
writeString(name)
data = append(data, 10) // compound
writeString("states")
for _, k := range keys {
v := properties[k]
switch v := v.(type) {
case string:
data = append(data, 8) // string
writeString(k)
writeString(v)
case uint8:
data = append(data, 1) // tagByte
writeString(k)
data = append(data, byte(v))
case int8:
data = append(data, 1) // tagByte
writeString(k)
data = append(data, byte(v))
case bool:
b := 0
if v {
b = 1
}
data = append(data, 1) // tagByte
writeString(k)
data = append(data, byte(b))
case uint16:
data = append(data, 2) // tagInt16
writeString(k)
data = binary.LittleEndian.AppendUint16(data, uint16(v))
case int16:
data = append(data, 2) // tagInt16
writeString(k)
data = binary.LittleEndian.AppendUint16(data, uint16(v))
case uint32:
data = append(data, 3) // tagInt32
writeString(k)
data = binary.LittleEndian.AppendUint32(data, uint32(v))
case int32:
data = append(data, 3) // tagInt32
writeString(k)
data = binary.LittleEndian.AppendUint32(data, uint32(v))
default:
panic("unhandled nbt type")
}
}
data = append(data, 0) // end
data = append(data, 0) // end
h := fnv.New32a()
h.Write(data)
return h.Sum32()
}
func splitNamespace(identifier string) (ns, name string) {
ns_name := strings.Split(identifier, ":")
return ns_name[0], ns_name[len(ns_name)-1]
}