diff --git a/.gitignore b/.gitignore index 033836e..fe78449 100644 --- a/.gitignore +++ b/.gitignore @@ -41,4 +41,7 @@ entityflags.py /libbedrocktool.so /tex.png /packcache/* +/blobcache +/*-test +/actors*.txt changelog.txt diff --git a/dragonfly b/dragonfly index 2f796e1..6b4ec0d 160000 --- a/dragonfly +++ b/dragonfly @@ -1 +1 @@ -Subproject commit 2f796e1577d78a91506cd5ce92d6daac3a0328b4 +Subproject commit 6b4ec0d1ace167a3c2fb2ec96e8b1649c5c9a31d diff --git a/go.mod b/go.mod index 9f4edf1..59da657 100644 --- a/go.mod +++ b/go.mod @@ -4,9 +4,9 @@ go 1.22 require ( gioui.org v0.7.0 - gioui.org/shader v1.0.8 gioui.org/x v0.7.0 github.com/OneOfOne/xxhash v1.2.8 + github.com/cespare/xxhash/v2 v2.2.0 github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 github.com/dblezek/tga v0.0.0-20150626111426-80720cbc1017 github.com/denisbrodbeck/machineid v1.0.1 @@ -16,6 +16,7 @@ require ( github.com/fatih/color v1.17.0 github.com/flytam/filenamify v1.2.0 github.com/go-gl/mathgl v1.1.0 + github.com/go-jose/go-jose/v3 v3.0.3 github.com/google/uuid v1.6.0 github.com/gregwebs/go-recovery v0.3.2 github.com/klauspost/compress v1.17.9 @@ -42,6 +43,7 @@ require ( require ( aead.dev/minisign v0.3.0 // indirect gioui.org/cpu v0.0.0-20220412190645-f1e9e8c3b1f7 // indirect + gioui.org/shader v1.0.8 // indirect git.wow.st/gmp/jni v0.0.0-20210610011705-34026c7e22d0 // indirect github.com/brentp/intintmap v0.0.0-20190211203843-30dc0ade9af9 // indirect github.com/changkun/lockfree v0.0.1 // indirect @@ -49,7 +51,6 @@ require ( github.com/df-mc/worldupgrader v1.0.15 // indirect github.com/dlclark/regexp2 v1.11.0 // indirect github.com/ftrvxmtrx/tga v0.0.0-20150524081124-bd8e8d5be13a // indirect - github.com/go-jose/go-jose/v3 v3.0.3 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-sourcemap/sourcemap v2.1.4+incompatible // indirect github.com/go-text/typesetting v0.1.1 // indirect diff --git a/go.sum b/go.sum index 4be1425..671a254 100644 --- a/go.sum +++ b/go.sum @@ -20,6 +20,8 @@ github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8 github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= 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.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/changkun/lockfree v0.0.1 h1:5WefVJLglY4IHRqOQmh6Ao6wkJYaJkarshKU8VUtId4= github.com/changkun/lockfree v0.0.1/go.mod h1:3bKiaXn/iNzIPlSvSOMSVbRQUQtAp8qUAyBUtzU11s4= github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 h1:tuijfIjZyjZaHq9xDUh0tNitwXshJpbLkqMOJv4H3do= diff --git a/go.work.sum b/go.work.sum index d78d805..56fbef3 100644 --- a/go.work.sum +++ b/go.work.sum @@ -3,32 +3,100 @@ cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2Aawl cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= dmitri.shuralyov.com/gpu/mtl v0.0.0-20221208032759-85de2813cf6b/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= git.sr.ht/~jackmordaunt/go-toast v1.0.0/go.mod h1:aIuRX/HdBOz7yRS8rOVYQCwJQlFS7DbYBTpUV0SHeeg= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/andybalholm/stroke v0.0.0-20221221101821-bd29b49d73f0/go.mod h1:ccdDYaY5+gO+cbnQdFxEXqfy0RkoV25H3jLXUDNM3wg= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= +github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= +github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/esiqveland/notify v0.11.0/go.mod h1:63UbVSaeJwF0LVJARHFuPgUAoM7o1BEvCZyknsuonBc= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231223183121-56fa3ac82ce7/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= github.com/go-text/typesetting v0.0.0-20231201171600-344014252a3f h1:OgNBpSAZvbSDgW+tf1CSatkRIBQHqhi7kdorhGx4lsY= github.com/go-text/typesetting v0.0.0-20231201171600-344014252a3f/go.mod h1:xtHRnulqioPpQlqw/tZJZJcp8UJgnueuQVJ0o7nS/xY= github.com/go-text/typesetting-utils v0.0.0-20231121125213-61dadda55b86/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= +github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofiber/fiber/v2 v2.52.2/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/iris-contrib/httpexpect/v2 v2.12.1/go.mod h1:7+RB6W5oNClX7PTwJgJnsQP3ZuUUYB3u61KCqeSgZ88= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kamstrup/intmap v0.2.0/go.mod h1:z3uar6/7HP2QxJJoFTWAKsA5k7Uy1UJjAZoT3f62KEE= +github.com/kataras/blocks v0.0.7/go.mod h1:UJIU97CluDo0f+zEjbnbkeMRlvYORtmc1304EeyXf4I= +github.com/kataras/golog v0.1.8/go.mod h1:rGPAin4hYROfk1qT9wZP6VY2rsb4zzc37QpdPjdkqVw= +github.com/kataras/iris/v12 v12.2.0/go.mod h1:BLzBpEunc41GbE68OUaQlqX4jzi791mx5HU04uPb90Y= +github.com/kataras/pio v0.0.11/go.mod h1:38hH6SWH6m4DKSYmRhlrCJ5WItwWgCVrTNU62XZyUvI= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/labstack/echo/v4 v4.10.0/go.mod h1:S/T/5fy/GigaXnHTkh0ZGe4LpkkQysvRjFMSUTkDRNQ= +github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/microcosm-cc/bluemonday v1.0.23/go.mod h1:mN70sk7UkkF8TUr2IGBpNN0jAgStuPzlK76QuruE/z4= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= +github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/tdewolff/minify/v2 v2.12.4/go.mod h1:h+SRvSIX3kwgwTFOpSckvSxgax3uy8kZTSF1Ojrr3bk= +github.com/tdewolff/parse/v2 v2.6.4/go.mod h1:woz0cgbLwFdtbjJu8PIKxhW05KplTFQkOdX78o+Jgrs= +github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= +github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.52.0/go.mod h1:hf5C4QnVMkNXMspnsUlfM3WitlgYflyhHYoKol/szxQ= +github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= golang.org/x/exp v0.0.0-20231127185646-65229373498e/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= golang.org/x/exp/shiny v0.0.0-20231127185646-65229373498e/go.mod h1:UH99kUObWAZkDnWqppdQe5ZhPYESUw8I0zVV1uWBR+0= golang.org/x/image v0.3.0/go.mod h1:fXd9211C/0VTlYuAcOhW8dY/RtEJqODXOWBDpmYBf+A= @@ -52,6 +120,7 @@ golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNss golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= @@ -59,3 +128,6 @@ golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= diff --git a/gophertunnel b/gophertunnel index abbd278..80b0752 160000 --- a/gophertunnel +++ b/gophertunnel @@ -1 +1 @@ -Subproject commit abbd278a5534c600501db8c79bc1f833d0e7c228 +Subproject commit 80b0752a5cbc0df987a2ee37ab061c3ffe7f1a5e diff --git a/handlers/worlds/chunk.go b/handlers/worlds/chunk.go index 61fb5aa..1da00e2 100644 --- a/handlers/worlds/chunk.go +++ b/handlers/worlds/chunk.go @@ -2,20 +2,29 @@ package worlds import ( "bytes" + "encoding/binary" "errors" "time" "github.com/bedrock-tool/bedrocktool/handlers/worlds/worldstate" "github.com/bedrock-tool/bedrocktool/locale" + "github.com/cespare/xxhash/v2" "github.com/df-mc/dragonfly/server/block/cube" "github.com/df-mc/dragonfly/server/world" "github.com/df-mc/dragonfly/server/world/chunk" + "github.com/df-mc/goleveldb/leveldb" "github.com/sandertv/gophertunnel/minecraft/nbt" "github.com/sandertv/gophertunnel/minecraft/protocol" "github.com/sandertv/gophertunnel/minecraft/protocol/packet" ) -func (w *worldsHandler) processLevelChunk(pk *packet.LevelChunk, timeReceived time.Time) { +func (w *worldsHandler) blobKey(b uint64) []byte { + k := binary.LittleEndian.AppendUint64(nil, xxhash.Sum64String(w.serverState.Name)) + k = binary.LittleEndian.AppendUint64(k, b) + return k +} + +func (w *worldsHandler) processLevelChunk(pk *packet.LevelChunk, timeReceived time.Time) (err error) { if len(pk.RawPayload) == 0 { w.log.Info(locale.Loc("empty_chunk", nil)) return @@ -34,15 +43,59 @@ func (w *worldsHandler) processLevelChunk(pk *packet.LevelChunk, timeReceived ti //os.WriteFile("chunk.bin", pk.RawPayload, 0777) - ch, blockNBTs, err := chunk.NetworkDecode( - w.serverState.blocks, - pk.RawPayload, subChunkCount, - w.serverState.useOldBiomes, w.serverState.useHashedRids, w.currentWorld.Range(), - ) - if err != nil { - w.log.Error(err) - return + var ch *chunk.Chunk + var blockNBTs []map[string]any + + if pk.CacheEnabled { + w.blobLock.Lock() + defer w.blobLock.Unlock() + + var reply packet.ClientCacheBlobStatus + var blobs []protocol.CacheBlob + for _, h := range pk.BlobHashes { + blob, err := w.blobcache.Get(w.blobKey(h), nil) + if err != nil { + if errors.Is(err, leveldb.ErrNotFound) { + reply.MissHashes = append(reply.MissHashes, h) + continue + } + return err + } + //reply.HitHashes = append(reply.HitHashes, h) + blobs = append(blobs, protocol.CacheBlob{Hash: h, Payload: blob}) + } + err = w.processBlobs(blobs, false) + if err != nil { + return err + } + + err = w.session.Server.WritePacket(&reply) + if err != nil { + return err + } + ch = chunk.New(w.serverState.blocks, w.currentWorld.Range()) + + buf := bytes.NewBuffer(pk.RawPayload) + borderBlocks, _ := buf.ReadByte() + buf.Next(int(borderBlocks)) + + blockNBTs, err = chunk.DecodeBlockNBTs(buf) + if err != nil { + return err + } + } else { + ch, blockNBTs, err = chunk.NetworkDecode( + w.serverState.blocks, + pk.RawPayload, subChunkCount, + w.serverState.useOldBiomes, + w.serverState.useHashedRids, + w.currentWorld.Range(), + ) + if err != nil { + return err + } } + var chunkBlockNBT = make(map[cube.Pos]worldstate.DummyBlock) for _, blockNBT := range blockNBTs { x := int(blockNBT["x"].(int32)) @@ -66,38 +119,29 @@ func (w *worldsHandler) processLevelChunk(pk *packet.LevelChunk, timeReceived ti w.log.Error(err) } - max := w.currentWorld.Dimension().Range().Height() / 16 - switch pk.SubChunkCount { - case protocol.SubChunkRequestModeLimited: - max = int(pk.HighestSubChunk) - fallthrough - case protocol.SubChunkRequestModeLimitless: - var offsetTable []protocol.SubChunkOffset - r := w.currentWorld.Dimension().Range() - for y := int8(r.Min() / 16); y < int8(r.Max()/16)+1; y++ { - offsetTable = append(offsetTable, protocol.SubChunkOffset{0, y, 0}) - } - - dimId, _ := world.DimensionID(w.currentWorld.Dimension()) - _ = w.session.Server.WritePacket(&packet.SubChunkRequest{ - Dimension: int32(dimId), - Position: protocol.SubChunkPos{ - pk.Position.X(), 0, pk.Position.Z(), - }, - Offsets: offsetTable[:min(max+1, len(offsetTable))], - }) - default: - // legacy - //var empty = true - //for _, sub := range ch.Sub() { - // if !sub.Empty() { - // empty = false - // break - // } - //} - //if !empty { - // w.mapUI.SetChunk(pos, ch, w.currentWorld.IsPaused()) - //} + if !pk.CacheEnabled { + max := w.currentWorld.Dimension().Range().Height() / 16 + switch pk.SubChunkCount { + case protocol.SubChunkRequestModeLimited: + max = int(pk.HighestSubChunk) + fallthrough + case protocol.SubChunkRequestModeLimitless: + var offsetTable []protocol.SubChunkOffset + r := w.currentWorld.Dimension().Range() + for y := int8(r.Min() / 16); y < int8(r.Max()/16)+1; y++ { + offsetTable = append(offsetTable, protocol.SubChunkOffset{0, y, 0}) + } + + dimId, _ := world.DimensionID(w.currentWorld.Dimension()) + _ = w.session.Server.WritePacket(&packet.SubChunkRequest{ + Dimension: int32(dimId), + Position: protocol.SubChunkPos{ + pk.Position.X(), 0, pk.Position.Z(), + }, + Offsets: offsetTable[:min(max+1, len(offsetTable))], + }) + default: + } } w.session.SendPopup(locale.Locm("popup_chunk_count", locale.Strmap{ @@ -105,6 +149,68 @@ func (w *worldsHandler) processLevelChunk(pk *packet.LevelChunk, timeReceived ti "Entities": w.currentWorld.EntityCount(), "Name": w.currentWorld.Name, }, len(w.currentWorld.StoredChunks))) + + return nil +} + +func (w *worldsHandler) processBlobs(blobs []protocol.CacheBlob, put bool) (err error) { + // no lock! + var chunks = make(map[world.ChunkPos]*chunk.Chunk) + for _, blob := range blobs { + if put { + err = w.blobcache.Put(w.blobKey(blob.Hash), blob.Payload, nil) + if err != nil { + return err + } + } + wb := w.waitingBlobs[blob.Hash] + + if w.currentWorld.IgnoredChunks[wb.pos] { + continue + } + if _, ok := chunks[wb.pos]; ok { + continue + } + ch, ok, err := w.currentWorld.LoadChunk(wb.pos) + if err != nil { + return err + } + if !ok { + return errors.New("bug check: subchunk received before chunk") + } + chunks[wb.pos] = ch + } + + for _, blob := range blobs { + wb := w.waitingBlobs[blob.Hash] + ch, ok := chunks[wb.pos] + if !ok { + continue + } + + buf := bytes.NewBuffer(blob.Payload) + if wb.biome { + err = chunk.DecodeNetworkBiomes(ch, buf, w.serverState.useOldBiomes) + if err != nil { + return err + } + } else { + var index byte + ch.Sub()[index], err = chunk.DecodeSubChunk( + buf, + w.serverState.blocks, + w.currentWorld.Range(), + &index, + chunk.NetworkEncoding, + w.serverState.useHashedRids, + ) + if err != nil { + return err + } + } + } + + return nil } func (w *worldsHandler) processSubChunk(pk *packet.SubChunk) error { diff --git a/handlers/worlds/packets.go b/handlers/worlds/packets.go index d5d6ea1..9edd7ed 100644 --- a/handlers/worlds/packets.go +++ b/handlers/worlds/packets.go @@ -186,6 +186,12 @@ func (w *worldsHandler) packetCB(_pk packet.Packet, toServer bool, timeReceived if err := w.processSubChunk(pk); err != nil { w.log.WithField("packet", "SubChunk").Error(err) } + case *packet.ClientCacheMissResponse: + w.blobLock.Lock() + if err := w.processBlobs(pk.Blobs, true); err != nil { + w.log.WithField("packet", "SubChunk").Error(err) + } + w.blobLock.Unlock() case *packet.BlockActorData: p := pk.Position @@ -286,18 +292,18 @@ func (w *worldsHandler) packetCB(_pk packet.Packet, toServer bool, timeReceived w.serverState.behaviorPack.AddEntity(pk.EntityType, pk.Attributes, ent.Metadata, ent.Properties) } - case *packet.RemoveActor: - entity := w.currentWorld.GetEntityUniqueID(pk.EntityUniqueID) - if entity != nil { - /* - dist := entity.Position.Vec2().Sub(playerPos.Vec2()).Len() + /* + case *packet.RemoveActor: + entity := w.currentWorld.GetEntityUniqueID(pk.EntityUniqueID) + if entity != nil { + dist := entity.Position.Vec2().Sub(playerPos.Vec2()).Len() - fmt.Fprintf(distf, "%.5f\t%s\n", dist, entity.EntityType) + fmt.Fprintf(distf, "%.5f\t%s\n", dist, entity.EntityType) - _ = dist - println() - */ - } + _ = dist + println() + } + */ case *packet.SetActorData: if entity := w.getEntity(pk.EntityRuntimeID); entity != nil { diff --git a/handlers/worlds/world.go b/handlers/worlds/world.go index 837c64e..c050ebb 100644 --- a/handlers/worlds/world.go +++ b/handlers/worlds/world.go @@ -30,6 +30,7 @@ import ( "github.com/df-mc/dragonfly/server/block/cube" "github.com/df-mc/dragonfly/server/world" _ "github.com/df-mc/dragonfly/server/world/biome" + "github.com/df-mc/goleveldb/leveldb" "github.com/sandertv/gophertunnel/minecraft" "github.com/sandertv/gophertunnel/minecraft/protocol" "github.com/sandertv/gophertunnel/minecraft/protocol/packet" @@ -75,6 +76,11 @@ type serverState struct { Name string } +type waitBlob struct { + pos world.ChunkPos + biome bool +} + type worldsHandler struct { wg sync.WaitGroup ctx context.Context @@ -88,6 +94,10 @@ type worldsHandler struct { currentWorld *worldstate.World worldStateLock sync.Mutex + blobcache *leveldb.DB + waitingBlobs map[uint64]waitBlob + blobLock sync.Mutex + serverState serverState settings WorldSettings } @@ -117,7 +127,7 @@ func NewWorldsHandler(settings WorldSettings) *proxy.Handler { h := &proxy.Handler{ Name: "Worlds", - SessionStart: func(session *proxy.Session, serverName string) error { + SessionStart: func(session *proxy.Session, serverName string) (err error) { w.session = session w.currentWorld = nil w.serverState = serverState{ @@ -130,6 +140,12 @@ func NewWorldsHandler(settings WorldSettings) *proxy.Handler { entityProperties: make(map[string][]entity.EntityProperty), } + w.blobcache, err = leveldb.OpenFile("blobcache", nil) + if err != nil { + return err + } + w.waitingBlobs = make(map[uint64]waitBlob) + w.mapUI = NewMapUI(w) w.scripting = scripting.New() @@ -192,7 +208,6 @@ func NewWorldsHandler(settings WorldSettings) *proxy.Handler { w.serverState.Name = serverName // initialize a worldstate - var err error w.currentWorld, err = worldstate.New(w.serverState.dimensions, w.mapUI.SetChunk) if err != nil { return err @@ -260,6 +275,7 @@ func NewWorldsHandler(settings WorldSettings) *proxy.Handler { PacketCallback: w.packetCB, OnSessionEnd: func() { w.SaveAndReset(true, nil) + w.blobcache.Close() w.wg.Wait() }, OnProxyEnd: cancel, diff --git a/utils/proxy/packet_logger.go b/utils/proxy/packet_logger.go index 374b1ae..8980ec8 100644 --- a/utils/proxy/packet_logger.go +++ b/utils/proxy/packet_logger.go @@ -44,6 +44,7 @@ var mutedPackets = []uint32{ packet.IDPlaySound, packet.IDPlayerAction, packet.IDSetTitle, + packet.IDClientCacheMissResponse, } var dirS2C = color.GreenString("S") + "->" + color.CyanString("C") diff --git a/utils/proxy/session.go b/utils/proxy/session.go index 5da4f30..81dbcf5 100644 --- a/utils/proxy/session.go +++ b/utils/proxy/session.go @@ -30,6 +30,7 @@ type Session struct { Player Player rpHandler *rpHandler + loggedIn bool expectDisconnect bool dimensionData *packet.DimensionData clientConnecting chan struct{} @@ -331,6 +332,7 @@ func (s *Session) connectServer(ctx context.Context, connect *utils.ConnectInfo) d := minecraft.Dialer{ ErrorLog: log.Default(), PacketFunc: s.packetFunc, + //EnableClientCache: true, GetClientData: func() login.ClientData { if s.withClient { select { @@ -445,6 +447,7 @@ func (s *Session) connectClient(ctx context.Context, connect *utils.ConnectInfo) return err } accepted = true + logrus.Info("Client Connected") return nil } @@ -484,6 +487,14 @@ func (s *Session) proxyLoop(ctx context.Context, toServer bool) (err error) { var transfer *packet.Transfer switch _pk := pk.(type) { + case *packet.LevelChunk: + if _pk.CacheEnabled && !s.loggedIn { + s.Server.WritePacket(&packet.ClientCacheBlobStatus{ + MissHashes: _pk.BlobHashes, + }) + } + case *packet.SetLocalPlayerAsInitialised: + s.loggedIn = true case *packet.Transfer: transfer = _pk if s.Client != nil {