diff --git a/go.mod b/go.mod index aca46f7..0fed7f8 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/akmalfairuz/legacy-version -go 1.24.0 +go 1.25.1 require ( github.com/cespare/xxhash/v2 v2.3.0 @@ -13,27 +13,53 @@ require ( github.com/samber/lo v1.49.1 github.com/sandertv/gophertunnel v1.52.0 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/oauth2 v0.32.0 + golang.org/x/oauth2 v0.34.0 ) 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/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/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/oreans/virtualizersdk v0.0.0-20250127084511-5dd538199a75 // indirect - github.com/sandertv/go-raknet v1.14.3-0.20250305181847-6af3e95113d6 // indirect - golang.org/x/mod v0.28.0 // indirect - golang.org/x/net v0.46.0 // indirect - golang.org/x/text v0.30.0 // indirect + github.com/lumineproxy/log v0.0.0-20251025091855-37df1c504536 // indirect + github.com/lumineproxy/socks5udp v1.0.1-0.20251223034400-3f3b0cbbe69b // indirect + github.com/muhammadmuzzammil1998/jsonc v1.0.0 // indirect + github.com/pion/datachannel v1.5.10 // 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 => ../dragonfly - -replace github.com/sandertv/go-raknet => ../go-raknet +replace ( + github.com/df-mc/dragonfly => github.com/lumineproxy/dragonfly v0.0.0-20260101232342-710c0a1931ba + 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 + github.com/sandertv/gophertunnel => github.com/lumineproxy/gophertunnel v0.0.0-20260102091803-5fb43dd59e0c +) diff --git a/go.sum b/go.sum index ad2df31..fe9c03e 100644 --- a/go.sum +++ b/go.sum @@ -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/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/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/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/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/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/go.mod h1:pf9+b5J3LFP7iZ4XXaVzZrCle0Q/vNpB/vDe5+3ulRE= 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 v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= 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/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/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/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.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= 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/oreans/virtualizersdk v0.0.0-20250127084511-5dd538199a75 h1:FqCGgY+GycamCHOhK7GWfCmPZwZ3Z6yh+zdoAqK1y/8= -github.com/oreans/virtualizersdk v0.0.0-20250127084511-5dd538199a75/go.mod h1:C1b5DqEix6/MXYnbMRdqofk6GXepv9p5Xw0EIfqvixw= +github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE= +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/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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= 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.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0= -golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU= +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/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs= -golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= -golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= +golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= +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.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= -golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= -golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY= -golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= +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/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.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +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.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= -golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= +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/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= 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/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 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.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/chunk/decode.go b/internal/chunk/decode.go index 78d0ffa..483dfa0 100644 --- a/internal/chunk/decode.go +++ b/internal/chunk/decode.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" + "github.com/akmalfairuz/legacy-version/mapping" "github.com/df-mc/dragonfly/server/block/cube" ) @@ -11,7 +12,7 @@ import ( // returned is nil and the error non-nil. // The sub chunk count passed must be that found in the LevelChunk packet. // 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 ( c = New(air, r) err error @@ -21,7 +22,7 @@ func NetworkDecode(air uint32, buf *bytes.Buffer, count int, oldFormat bool, r c if oldFormat { 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 { return nil, err } @@ -45,7 +46,7 @@ func NetworkDecode(air uint32, buf *bytes.Buffer, count int, oldFormat bool, r c } else { var last *PalettedStorage 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 { 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 // 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() if err != nil { 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) case 1: // 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 { 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) 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 { 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 // 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() if err != nil { 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 } 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 } diff --git a/internal/chunk/encode.go b/internal/chunk/encode.go index 77b3ae4..95b762d 100644 --- a/internal/chunk/encode.go +++ b/internal/chunk/encode.go @@ -4,6 +4,7 @@ import ( "bytes" "sync" + "github.com/akmalfairuz/legacy-version/mapping" "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) 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 { biomes := make([]byte, 256) @@ -30,7 +31,7 @@ func NetworkEncode(air uint32, c *Chunk, oldFormat bool, pe PaletteEncoding) ([] } _, _ = buf.Write(biomes) } else { - _, _ = buf.Write(EncodeBiomes(c, NetworkEncoding)) + _, _ = buf.Write(EncodeBiomes(c, NetworkEncoding, block, useBlockHashes)) } 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 // 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) defer func() { buf.Reset() @@ -47,7 +48,7 @@ func EncodeSubChunk(s *SubChunk, e Encoding, pe PaletteEncoding, subChunkVer sub subChunkVer.EncodeHeader(buf, s, r, ind) for _, storage := range s.storages { - encodePalettedStorage(buf, storage, nil, e, pe) + encodePalettedStorage(buf, storage, nil, e, pe, block, useBlockHashes) } sub := make([]byte, buf.Len()) _, _ = 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 // 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) defer func() { buf.Reset() @@ -65,7 +66,7 @@ func EncodeBiomes(c *Chunk, e Encoding) []byte { var previous *PalettedStorage for _, b := range c.biomes { - encodePalettedStorage(buf, b, previous, e, BiomePaletteEncoding) + encodePalettedStorage(buf, b, previous, e, BiomePaletteEncoding, block, useBlockHashes) previous = b } 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 // 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) { _, _ = buf.Write([]byte{0x7f<<1 | e.Network()}) return @@ -89,5 +90,13 @@ func encodePalettedStorage(buf *bytes.Buffer, storage, previous *PalettedStorage } _, _ = 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) } diff --git a/legacyver/all.go b/legacyver/all.go index e3350c0..6cf2eaa 100644 --- a/legacyver/all.go +++ b/legacyver/all.go @@ -64,7 +64,7 @@ func lookupOrCreateBlockTranslator(protocolVersion, blockVersion int32, blockSta } // 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() translator, ok := blockTranslators[protocolVersion] 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 translator.DowngradeLevelChunk(pk) + return translator.DowngradeLevelChunk(pk, conn) } diff --git a/legacyver/block_translator.go b/legacyver/block_translator.go index a2fd857..cf65bd9 100644 --- a/legacyver/block_translator.go +++ b/legacyver/block_translator.go @@ -9,6 +9,7 @@ import ( "github.com/cespare/xxhash/v2" "github.com/df-mc/dragonfly/server/block/cube" "github.com/df-mc/dragonfly/server/world" + "github.com/hashicorp/go-version" "github.com/sandertv/gophertunnel/minecraft" "github.com/sandertv/gophertunnel/minecraft/nbt" "github.com/sandertv/gophertunnel/minecraft/protocol" @@ -24,6 +25,7 @@ var ( LatestNetworkPersistentEncoding = chunk.NewNetworkPersistentEncoding(blockMappingLatest, BlockVersionLatest) // LatestBlockPaletteEncoding is the paletteEncoding used for encoding a palette of block states encoded as NBT. LatestBlockPaletteEncoding = chunk.NewBlockPaletteEncoding(blockMappingLatest, BlockVersionLatest) + cavesAndCliffsVersion, _ = version.NewVersion("1.18.0") ) type BlockTranslator interface { @@ -32,17 +34,18 @@ type BlockTranslator interface { // UpgradeBlockPackets upgrades the input block packets to the latest block packets. UpgradeBlockPackets([]packet.Packet, *minecraft.Conn) (result []packet.Packet) // 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() mapping.Block } - type DefaultBlockTranslator struct { - mapping mapping.Block - latest mapping.Block - pse chunk.Encoding - pe chunk.PaletteEncoding - oldFormat bool + mapping mapping.Block + latest mapping.Block + pse chunk.Encoding + pe chunk.PaletteEncoding + oldFormat bool + dimensionDefinitions []protocol.DimensionDefinition + currentDimension int32 } 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 } -func (t *DefaultBlockTranslator) DowngradeLevelChunk(pk *packet.LevelChunk) error { +func (t *DefaultBlockTranslator) DowngradeLevelChunk(pk *packet.LevelChunk, conn *minecraft.Conn) error { count := int(pk.SubChunkCount) if count == protocol.SubChunkRequestModeLimitless || count == protocol.SubChunkRequestModeLimited { return nil @@ -62,13 +65,13 @@ func (t *DefaultBlockTranslator) DowngradeLevelChunk(pk *packet.LevelChunk) erro buf := bytes.NewBuffer(pk.RawPayload) writeBuf := bytes.NewBuffer(nil) 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 { 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 { return err } @@ -114,7 +117,7 @@ func (t *DefaultBlockTranslator) DowngradeBlockPackets(pks []packet.Packet, conn if !EnableChunkTranslation { break } - if err := t.DowngradeLevelChunk(pk); err != nil { + if err := t.DowngradeLevelChunk(pk, conn); err != nil { //fmt.Println(err) break } @@ -122,7 +125,7 @@ func (t *DefaultBlockTranslator) DowngradeBlockPackets(pks []packet.Packet, conn if !EnableChunkTranslation { break } - r := world.Overworld.Range() + r := t.getRange(conn) if t.oldFormat { r = cube.Range{0, 255} } @@ -133,13 +136,13 @@ func (t *DefaultBlockTranslator) DowngradeBlockPackets(pks []packet.Packet, conn writeBuf := bytes.NewBuffer(nil) if !pk.CacheEnabled && !conn.ClientCacheEnabled() { 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 { //fmt.Println(err) continue } 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) @@ -162,7 +165,7 @@ func (t *DefaultBlockTranslator) DowngradeBlockPackets(pks []packet.Packet, conn } } case *packet.ClientCacheMissResponse: - r := world.Overworld.Range() + r := t.getRange(conn) if t.oldFormat { r = cube.Range{0, 255} } @@ -170,14 +173,13 @@ func (t *DefaultBlockTranslator) DowngradeBlockPackets(pks []packet.Packet, conn for i, blob := range pk.Blobs { buf := bytes.NewBuffer(blob.Payload) 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 { // Has a possibility to be a biome, ignore then continue } t.DowngradeSubChunk(subChunk) - - blob.Payload = append(chunk.EncodeSubChunk(subChunk, chunk.NetworkEncoding, t.pe, chunk.SubChunkVersion9, r, int(ind)), buf.Bytes()...) + blob.Payload = append(chunk.EncodeSubChunk(subChunk, chunk.NetworkEncoding, t.pe, chunk.SubChunkVersion9, r, int(ind), t.mapping, false), buf.Bytes()...) blob.Hash = xxhash.Sum64(blob.Payload) pk.Blobs[i] = blob } @@ -280,13 +282,13 @@ func (t *DefaultBlockTranslator) DowngradeBlockRuntimeID(input uint32) uint32 { 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 { return input } start := 0 - r := world.Overworld.Range() + r := t.getRange(conn) if t.oldFormat { start = 4 r = cube.Range{0, 255} @@ -357,3 +359,29 @@ func (t *DefaultBlockTranslator) upgradeEntityMetadata(metadata map[uint32]any) } 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 +} diff --git a/legacyver/legacypacket/dimension_data.go b/legacyver/legacypacket/dimension_data.go new file mode 100644 index 0000000..ca1bfac --- /dev/null +++ b/legacyver/legacypacket/dimension_data.go @@ -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) +} diff --git a/legacyver/protocol.go b/legacyver/protocol.go index 46a2d8e..e777e1c 100644 --- a/legacyver/protocol.go +++ b/legacyver/protocol.go @@ -31,6 +31,8 @@ func init() { func convertPacketFunc(pid uint32, cur func() packet.Packet) func() packet.Packet { switch pid { + case packet.IDDimensionData: + return func() packet.Packet { return &legacypacket.DimensionData{} } case packet.IDCameraAimAssist: return func() packet.Packet { return &legacypacket.CameraAimAssist{} } 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 { + translator, ok := p.blockTranslator.(*DefaultBlockTranslator) + if !ok { + return pks + } for pkIndex, pk := range pks { switch pk := pk.(type) { + case *packet.DimensionData: + translator.dimensionDefinitions = pk.Definitions case *packet.ClientCacheStatus: // pk.Enabled = false // TODO: enable when chunk translation is not broken case *packet.SetActorMotion: @@ -414,6 +422,7 @@ func (p *Protocol) downgradePackets(pks []packet.Packet, conn *minecraft.Conn) [ DetachFromEntity: pk.DetachFromEntity, } case *packet.ChangeDimension: + translator.currentDimension = pk.Dimension pks[pkIndex] = &legacypacket.ChangeDimension{ Dimension: pk.Dimension, Position: pk.Position, @@ -519,6 +528,7 @@ func (p *Protocol) downgradePackets(pks []packet.Packet, conn *minecraft.Conn) [ ClearRecipes: pk.ClearRecipes, } case *packet.StartGame: + translator.currentDimension = pk.Dimension // Adjust game version pk.GameVersion = p.ver pk.BaseGameVersion = p.ver diff --git a/mapping/block.go b/mapping/block.go index 397d3ab..a4c78bc 100644 --- a/mapping/block.go +++ b/mapping/block.go @@ -21,6 +21,8 @@ type Block interface { DowngradeBlockActorData(map[string]any) // UpgradeBlockActorData upgrades the input sub chunk to the latest block actor. 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([]protocol.BlockEntry) 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. infoUpdateBlockRID uint32 + + networkhashToRids map[uint32]uint32 + ridsToNetworkhash map[uint32]uint32 } func NewBlockMapping(raw []byte) *DefaultBlockMapping { @@ -51,6 +56,8 @@ func NewBlockMapping(raw []byte) *DefaultBlockMapping { runtimeIDToState := make(map[uint32]blockupgrader.BlockState) var airRID *uint32 var infoUpdateBlockRID *uint32 + networkhashToRids := make(map[uint32]uint32) + ridsToNetworkhash := make(map[uint32]uint32) var s blockupgrader.BlockState for { @@ -67,8 +74,11 @@ func NewBlockMapping(raw []byte) *DefaultBlockMapping { infoUpdateBlockRID = &rid } - stateRuntimeIDs[internal.HashState(blockupgrader.Upgrade(s))] = rid + upgradedStates := blockupgrader.Upgrade(s) + stateRuntimeIDs[internal.HashState(upgradedStates)] = rid runtimeIDToState[rid] = s + networkhashToRids[networkBlockHash(upgradedStates.Name, upgradedStates.Properties)] = rid + ridsToNetworkhash[rid] = networkBlockHash(s.Name, s.Properties) } if airRID == nil { panic("couldn't find air") @@ -83,6 +93,8 @@ func NewBlockMapping(raw []byte) *DefaultBlockMapping { runtimeIDToState: runtimeIDToState, airRID: *airRID, 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) { if len(entries) == 0 { return diff --git a/mapping/network_block_hash.go b/mapping/network_block_hash.go new file mode 100644 index 0000000..3962a57 --- /dev/null +++ b/mapping/network_block_hash.go @@ -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] +}