From 893721eb9b67c874caa8f513ea404515a6dae7de Mon Sep 17 00:00:00 2001 From: Sandertv Date: Tue, 15 Oct 2024 11:48:54 +0200 Subject: [PATCH] server.go: Use log/slog instead of logrus for logging. --- go.mod | 32 +++++----- go.sum | 63 +++++++++---------- main.go | 13 ++-- server/conf.go | 27 +++----- server/listener.go | 11 ++-- server/server.go | 58 +++++++++-------- server/session/chunk.go | 4 +- server/session/handler_block_actor_data.go | 2 +- .../session/handler_inventory_transaction.go | 4 +- server/session/handler_item_stack_request.go | 2 +- server/session/handler_player_auth_input.go | 6 +- server/session/handler_request_ability.go | 2 +- server/session/player.go | 4 +- server/session/session.go | 21 +++---- server/world/chunk/a_test.go | 20 ++++++ server/world/conf.go | 17 ++--- server/world/mcdb/conf.go | 22 +++---- server/world/mcdb/db.go | 16 ++--- server/world/world.go | 28 ++++----- 19 files changed, 168 insertions(+), 184 deletions(-) create mode 100644 server/world/chunk/a_test.go diff --git a/go.mod b/go.mod index 21630389e..ed7cefbed 100644 --- a/go.mod +++ b/go.mod @@ -1,38 +1,36 @@ module github.com/df-mc/dragonfly -go 1.22 +go 1.22.0 toolchain go1.22.1 require ( github.com/brentp/intintmap v0.0.0-20190211203843-30dc0ade9af9 - github.com/cespare/xxhash/v2 v2.2.0 + github.com/cespare/xxhash/v2 v2.3.0 github.com/df-mc/goleveldb v1.1.9 github.com/df-mc/worldupgrader v1.0.17 github.com/go-gl/mathgl v1.1.0 github.com/google/uuid v1.6.0 github.com/pelletier/go-toml v1.9.5 - github.com/rogpeppe/go-internal v1.11.0 - github.com/sandertv/gophertunnel v1.41.0 + github.com/rogpeppe/go-internal v1.13.1 + github.com/sandertv/gophertunnel v1.41.1 github.com/segmentio/fasthash v1.0.3 - github.com/sirupsen/logrus v1.9.3 - golang.org/x/exp v0.0.0-20230206171751-46f607a40771 - golang.org/x/text v0.16.0 - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d + golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c + golang.org/x/text v0.19.0 + golang.org/x/tools v0.26.0 ) require ( github.com/go-jose/go-jose/v3 v3.0.3 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/compress v1.17.11 // indirect github.com/muhammadmuzzammil1998/jsonc v1.0.0 // indirect - github.com/sandertv/go-raknet v1.14.1 // indirect - golang.org/x/crypto v0.24.0 // indirect - golang.org/x/image v0.17.0 // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.26.0 // indirect - golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect + github.com/sandertv/go-raknet v1.14.2 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/image v0.21.0 // indirect + golang.org/x/mod v0.21.0 // indirect + golang.org/x/net v0.30.0 // indirect + golang.org/x/oauth2 v0.23.0 // indirect + golang.org/x/sync v0.8.0 // indirect gopkg.in/yaml.v2 v2.3.0 // indirect ) diff --git a/go.sum b/go.sum index 0c7cd3e9d..80c01b1f3 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ 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/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.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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= @@ -26,8 +26,8 @@ github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= 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.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/muhammadmuzzammil1998/jsonc v1.0.0 h1:8o5gBQn4ZA3NBA9DlTujCj2a4w0tqWrPVjDwhzkgTIs= github.com/muhammadmuzzammil1998/jsonc v1.0.0/go.mod h1:saF2fIVw4banK0H4+/EuqfFLpRnoy5S+ECwTOCcRcSU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -39,16 +39,14 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= 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.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/sandertv/go-raknet v1.14.1 h1:V2Gslo+0x4jfj+p0PM48mWxmMbYkxSlgeKy//y3ZrzI= -github.com/sandertv/go-raknet v1.14.1/go.mod h1:/yysjwfCXm2+2OY8mBazLzcxJ3irnylKCyG3FLgUPVU= -github.com/sandertv/gophertunnel v1.41.0 h1:PGqqALaatGqcZ+qWXOcR4+CHPhQohnm/ZrnHdhWRtNw= -github.com/sandertv/gophertunnel v1.41.0/go.mod h1:uSaX7RbVaCcxsGAx2vyZnkT0M6kZFGCdAqLn0+wuKyY= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/sandertv/go-raknet v1.14.2 h1:UZLyHn5yQU2Dq2GVq/LlxwAUikaq4q4AA1rl/Pf3AXQ= +github.com/sandertv/go-raknet v1.14.2/go.mod h1:/yysjwfCXm2+2OY8mBazLzcxJ3irnylKCyG3FLgUPVU= +github.com/sandertv/gophertunnel v1.41.1 h1:6JoDLzw9CGA3+KVSBUxnectmpaEdH2JwiShCM5dA+Cg= +github.com/sandertv/gophertunnel v1.41.1/go.mod h1:krvLSeRUNQ2iEYJNEgzrKtWO8W5ybZxN5lFfSCkHoNk= github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= @@ -57,45 +55,44 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= -golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg= -golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= golang.org/x/image v0.0.0-20190321063152-3fc05d484e9f/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.17.0 h1:nTRVVdajgB8zCMZVsViyzhnMKPwYeroEERRC64JuLco= -golang.org/x/image v0.17.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= +golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s= +golang.org/x/image v0.21.0/go.mod h1:vUbsLavqK/W303ZroQQVKQ+Af3Yl6Uz1Ppu5J/cLz78= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -107,14 +104,14 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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= diff --git a/main.go b/main.go index 89c129769..f06338b79 100644 --- a/main.go +++ b/main.go @@ -5,20 +5,15 @@ import ( "github.com/df-mc/dragonfly/server" "github.com/df-mc/dragonfly/server/player/chat" "github.com/pelletier/go-toml" - "github.com/sirupsen/logrus" + "log/slog" "os" ) func main() { - log := logrus.New() - log.Formatter = &logrus.TextFormatter{ForceColors: true} - log.Level = logrus.DebugLevel - chat.Global.Subscribe(chat.StdoutSubscriber{}) - - conf, err := readConfig(log) + conf, err := readConfig(slog.Default()) if err != nil { - log.Fatalln(err) + panic(err) } srv := conf.New() @@ -31,7 +26,7 @@ func main() { // readConfig reads the configuration from the config.toml file, or creates the // file if it does not yet exist. -func readConfig(log server.Logger) (server.Config, error) { +func readConfig(log *slog.Logger) (server.Config, error) { c := server.DefaultConfig() var zero server.Config if _, err := os.Stat("config.toml"); os.IsNotExist(err) { diff --git a/server/conf.go b/server/conf.go index e5e6ac415..c9385b8e3 100644 --- a/server/conf.go +++ b/server/conf.go @@ -14,7 +14,7 @@ import ( "github.com/df-mc/dragonfly/server/world/mcdb" "github.com/google/uuid" "github.com/sandertv/gophertunnel/minecraft/resource" - "github.com/sirupsen/logrus" + "log/slog" "os" "path/filepath" "slices" @@ -23,11 +23,10 @@ import ( // Config contains options for starting a Minecraft server. type Config struct { - // Log is the Logger to use for logging information. If the Logger is a - // logrus.Logger, additional fields may be added to it for individual worlds - // to provide additional context. If left empty, Log will be set to a logger - // created with logrus.New(). - Log Logger + // Log is the Logger to use for logging information. If nil, Log is set to + // slog.Default(). Errors reported by the underlying network are only logged + // if Log has at least debug level. + Log *slog.Logger // Listeners is a list of functions to create a Listener using a Config, one // for each Listener to be added to the Server. If left empty, no players // will be able to connect to the Server. @@ -99,25 +98,15 @@ type Config struct { Entities world.EntityRegistry } -// Logger is used to report information and errors from a dragonfly Server. Any -// Logger implementation may be used by passing it to the Log field in Config. -type Logger interface { - world.Logger - session.Logger - Infof(format string, v ...any) - Fatalf(format string, v ...any) - Warnf(format string, v ...any) -} - // New creates a Server using fields of conf. The Server's worlds are created // and connections from the Server's listeners may be accepted by calling // Server.Listen() and Server.Accept() afterwards. func (conf Config) New() *Server { if conf.Log == nil { - conf.Log = logrus.New() + conf.Log = slog.Default() } if len(conf.Listeners) == 0 { - conf.Log.Warnf("config: no listeners set, no connections will be accepted") + conf.Log.Warn("config: no listeners set, no connections will be accepted") } if conf.Name == "" { conf.Name = "Dragonfly Server" @@ -240,7 +229,7 @@ type UserConfig struct { // Config converts a UserConfig to a Config, so that it may be used for creating // a Server. An error is returned if creating data providers or loading // resources failed. -func (uc UserConfig) Config(log Logger) (Config, error) { +func (uc UserConfig) Config(log *slog.Logger) (Config, error) { var err error conf := Config{ Log: log, diff --git a/server/listener.go b/server/listener.go index 8d57a1583..a6fdef233 100644 --- a/server/listener.go +++ b/server/listener.go @@ -1,12 +1,12 @@ package server import ( + "context" "fmt" "github.com/df-mc/dragonfly/server/session" "github.com/sandertv/gophertunnel/minecraft" - "github.com/sirupsen/logrus" "io" - "log" + "log/slog" ) // Listener is a source for connections that may be listened on by a Server using Server.listen. Proxies can use this to @@ -31,15 +31,14 @@ func (uc UserConfig) listenerFunc(conf Config) (Listener, error) { Biomes: biomes(), TexturePacksRequired: conf.ResourcesRequired, } - if l, ok := conf.Log.(*logrus.Logger); ok { - cfg.ErrorLog = log.Default() - log.SetOutput(l.WithField("src", "gophertunnel").WriterLevel(logrus.DebugLevel)) + if conf.Log.Enabled(context.Background(), slog.LevelDebug) { + cfg.ErrorLog = conf.Log.With("net origin", "gophertunnel") } l, err := cfg.Listen("raknet", uc.Network.Address) if err != nil { return nil, fmt.Errorf("create minecraft listener: %w", err) } - conf.Log.Infof("Server running on %v.\n", l.Addr()) + conf.Log.Info("Server running.", "addr", l.Addr()) return listener{l}, nil } diff --git a/server/server.go b/server/server.go index 8c7f560d2..1801e27ad 100644 --- a/server/server.go +++ b/server/server.go @@ -24,12 +24,12 @@ import ( "github.com/sandertv/gophertunnel/minecraft/protocol/login" "github.com/sandertv/gophertunnel/minecraft/protocol/packet" "github.com/sandertv/gophertunnel/minecraft/text" - "github.com/sirupsen/logrus" "golang.org/x/exp/maps" "os" "os/exec" "os/signal" "runtime" + "runtime/debug" "strings" "sync" "sync/atomic" @@ -85,7 +85,18 @@ func (srv *Server) Listen() { panic("start server: already started") } - srv.conf.Log.Infof("Starting Dragonfly for Minecraft v%v...", protocol.CurrentVersion) + info, _ := debug.ReadBuildInfo() + if info == nil { + info = &debug.BuildInfo{GoVersion: "N/A", Settings: []debug.BuildSetting{{Key: "vcs.revision", Value: "N/A"}}} + } + revision := "" + for _, set := range info.Settings { + if set.Key == "vcs.revision" { + revision = set.Value + } + } + + srv.conf.Log.Info("Starting Dragonfly server...", "mc-version", protocol.CurrentVersion, "go-version", info.GoVersion, "commit", revision) srv.startListening() go srv.wait() } @@ -189,7 +200,7 @@ func (srv *Server) CloseOnProgramEnd() { go func() { <-c if err := srv.Close(); err != nil { - srv.conf.Log.Errorf("close server: %v", err) + srv.conf.Log.Error("close server: " + err.Error()) } }() } @@ -206,31 +217,31 @@ func (srv *Server) Close() error { // close stops the server, storing player and world data to disk when // necessary. func (srv *Server) close() { - srv.conf.Log.Infof("Server shutting down...") - defer srv.conf.Log.Infof("Server stopped.") + srv.conf.Log.Info("Server shutting down...") + defer srv.conf.Log.Info("Server stopped.") - srv.conf.Log.Debugf("Disconnecting players...") + srv.conf.Log.Debug("Disconnecting players...") for _, p := range srv.Players() { p.Disconnect(text.Colourf("%v", srv.conf.ShutdownMessage)) } srv.pwg.Wait() - srv.conf.Log.Debugf("Closing player provider...") + srv.conf.Log.Debug("Closing player provider...") if err := srv.conf.PlayerProvider.Close(); err != nil { - srv.conf.Log.Errorf("Error while closing player provider: %v", err) + srv.conf.Log.Error("Close player provider: " + err.Error()) } - srv.conf.Log.Debugf("Closing worlds...") + srv.conf.Log.Debug("Closing worlds...") for _, w := range []*world.World{srv.end, srv.nether, srv.world} { if err := w.Close(); err != nil { - srv.conf.Log.Errorf("Error closing %v: %v", w.Dimension(), err) + srv.conf.Log.Error(fmt.Sprintf("Close dimension %v: ", w.Dimension()) + err.Error()) } } - srv.conf.Log.Debugf("Closing listeners...") + srv.conf.Log.Debug("Closing listeners...") for _, l := range srv.listeners { if err := l.Close(); err != nil { - srv.conf.Log.Errorf("Error closing listener: %v", err) + srv.conf.Log.Error("Close listener: " + err.Error()) } } } @@ -280,7 +291,8 @@ func (srv *Server) startListening() { for _, lf := range srv.conf.Listeners { l, err := lf(srv.conf) if err != nil { - srv.conf.Log.Fatalf("create listener: %v", err) + srv.conf.Log.Error("create listener: " + err.Error()) + return } srv.listeners = append(srv.listeners, l) go srv.listen(l) @@ -347,7 +359,7 @@ func (srv *Server) finaliseConn(ctx context.Context, conn session.Conn, l Listen if err := conn.StartGameContext(ctx, data); err != nil { _ = l.Disconnect(conn, "Connection timeout.") - srv.conf.Log.Debugf("connection %v failed spawning: %v\n", conn.RemoteAddr(), err) + srv.conf.Log.Debug("spawn failed: "+err.Error(), "raddr", conn.RemoteAddr()) return } _ = conn.WritePacket(&packet.ItemComponent{Items: srv.customItems}) @@ -413,7 +425,7 @@ func (srv *Server) checkNetIsolation() { return } const loopbackExemptCmd = `CheckNetIsolation LoopbackExempt -a -n="Microsoft.MinecraftUWP_8wekyb3d8bbwe"` - srv.conf.Log.Infof("You are currently unable to join the server on this machine. Run %v in an admin PowerShell session to resolve.\n", loopbackExemptCmd) + srv.conf.Log.Info("You are currently unable to join the server on this machine. Run " + loopbackExemptCmd + " in an admin PowerShell session to resolve.") } // handleSessionClose handles the closing of a session. It removes the player @@ -430,7 +442,7 @@ func (srv *Server) handleSessionClose(c session.Controllable) { } if err := srv.conf.PlayerProvider.Save(p.UUID(), p.Data()); err != nil { - srv.conf.Log.Errorf("Error while saving data: %v", err) + srv.conf.Log.Error("Save player data: " + err.Error()) } srv.pwg.Done() } @@ -454,16 +466,8 @@ func (srv *Server) createPlayer(id uuid.UUID, conn session.Conn, data *player.Da // the program if the world could not be loaded. The layers passed are used to // create a generator.Flat that is used as generator for the world. func (srv *Server) createWorld(dim world.Dimension, nether, end **world.World) *world.World { - logger := srv.conf.Log - if v, ok := logger.(interface { - WithField(key string, field any) *logrus.Entry - }); ok { - // Add a dimension field to be able to distinguish between the different - // dimensions in the log. Dimensions implement fmt.Stringer so we can - // just fmt.Sprint them for a readable name. - logger = v.WithField("dimension", strings.ToLower(fmt.Sprint(dim))) - } - logger.Debugf("Loading world...") + logger := srv.conf.Log.With("dimension", strings.ToLower(fmt.Sprint(dim))) + logger.Debug("Loading dimension...") conf := world.Config{ Log: logger, @@ -483,7 +487,7 @@ func (srv *Server) createWorld(dim world.Dimension, nether, end **world.World) * }, } w := conf.New() - logger.Infof(`Opened world "%v".`, w.Name()) + logger.Info("Opened world.", "name", w.Name()) return w } diff --git a/server/session/chunk.go b/server/session/chunk.go index 93880512b..909d8740d 100644 --- a/server/session/chunk.go +++ b/server/session/chunk.go @@ -167,7 +167,7 @@ func (s *Session) sendBlobHashes(pos world.ChunkPos, c *chunk.Chunk, blockEntiti s.openChunkTransactions = append(s.openChunkTransactions, m) if l := len(s.blobs); l > 4096 { s.blobMu.Unlock() - s.log.Errorf("player %v has too many blobs pending %v: disconnecting", s.c.Name(), l) + s.log.Error("too many blobs pending: disconnecting", "n", l) _ = s.c.Close() return } @@ -243,7 +243,7 @@ func (s *Session) trackBlob(hash uint64, blob []byte) bool { s.blobMu.Lock() if l := len(s.blobs); l > 4096 { s.blobMu.Unlock() - s.log.Errorf("player %v has too many blobs pending %v: disconnecting", s.c.Name(), l) + s.log.Error("too many blobs pending: disconnecting", "n", l) _ = s.c.Close() return false } diff --git a/server/session/handler_block_actor_data.go b/server/session/handler_block_actor_data.go index e69e798e1..443ca36aa 100644 --- a/server/session/handler_block_actor_data.go +++ b/server/session/handler_block_actor_data.go @@ -35,7 +35,7 @@ func (b BlockActorDataHandler) Handle(p packet.Packet, s *Session) error { // handleSign handles the BlockActorData packet sent when editing a sign. func (b BlockActorDataHandler) handleSign(pk *packet.BlockActorData, pos cube.Pos, s *Session) error { if _, ok := s.c.World().Block(pos).(block.Sign); !ok { - s.log.Debugf("sign block actor data for position without sign %v", pos) + s.log.Debug("no sign at position of sign block actor data", "pos", pos.String()) return nil } diff --git a/server/session/handler_inventory_transaction.go b/server/session/handler_inventory_transaction.go index 308f0ff0b..715b68e73 100644 --- a/server/session/handler_inventory_transaction.go +++ b/server/session/handler_inventory_transaction.go @@ -22,7 +22,7 @@ func (h *InventoryTransactionHandler) Handle(p packet.Packet, s *Session) error // Always resend inventories with normal transactions. Most of the time we do not use these // transactions, so we're best off making sure the client and server stay in sync. if err := h.handleNormalTransaction(pk, s); err != nil { - s.log.Debugf("failed processing packet from %v (%v): InventoryTransaction: failed verifying actions in Normal transaction: %v\n", s.conn.RemoteAddr(), s.c.Name(), err) + s.log.Debug("process packet: InventoryTransaction: verify Normal transaction actions: " + err.Error()) return nil } return nil @@ -117,7 +117,7 @@ func (h *InventoryTransactionHandler) handleUseItemOnEntityTransaction(data *pro if !ok { // In some cases, for example when a falling block entity solidifies, latency may allow attacking an entity that // no longer exists server side. This is expected, so we shouldn't kick the player. - s.log.Debugf("invalid entity interaction: no entity found with runtime ID %v", data.TargetEntityRuntimeID) + s.log.Debug("invalid entity interaction: no entity with runtime ID", "ID", data.TargetEntityRuntimeID) return nil } if data.TargetEntityRuntimeID == selfEntityRuntimeID { diff --git a/server/session/handler_item_stack_request.go b/server/session/handler_item_stack_request.go index 177c561bf..a34908ae1 100644 --- a/server/session/handler_item_stack_request.go +++ b/server/session/handler_item_stack_request.go @@ -55,7 +55,7 @@ func (h *ItemStackRequestHandler) Handle(p packet.Packet, s *Session) error { if err := h.handleRequest(req, s); err != nil { // Item stacks being out of sync isn't uncommon, so don't error. Just debug the error and let the // revert do its work. - s.log.Debugf("failed processing packet from %v (%v): ItemStackRequest: error resolving item stack request: %v", s.conn.RemoteAddr(), s.c.Name(), err) + s.log.Debug("process packet: ItemStackRequest: resolve item stack request: " + err.Error()) } } return nil diff --git a/server/session/handler_player_auth_input.go b/server/session/handler_player_auth_input.go index bc81cb18f..bb8fa9d4e 100644 --- a/server/session/handler_player_auth_input.go +++ b/server/session/handler_player_auth_input.go @@ -35,7 +35,7 @@ func (h PlayerAuthInputHandler) handleMovement(pk *packet.PlayerAuthInput, s *Se // world), see #425. For this reason, we don't actually return an error if this happens, because this will // result in the player being kicked. Just log it and replace the NaN value with the one we have tracked // server-side. - s.log.Debugf("failed processing packet from %v (%v): %T: must not have nan/inf values, but got %v (%v, %v, %v). assuming server-side values\n", s.conn.RemoteAddr(), s.c.Name(), pk, pk.Position, pk.Pitch, pk.Yaw, pk.HeadYaw) + s.log.Debug("process packet: PlayerAuthInput: found nan/inf values. assuming server-side values", "pos", fmt.Sprint(pk.Position), "yaw", pk.Yaw, "head-yaw", pk.HeadYaw, "pitch", pk.Pitch) *v = float32(reference[i]) } } @@ -87,7 +87,7 @@ func (h PlayerAuthInputHandler) handleActions(pk *packet.PlayerAuthInput, s *Ses if err := sh.handleRequest(pk.ItemStackRequest, s); err != nil { // Item stacks being out of sync isn't uncommon, so don't error. Just debug the error and let the // revert do its work. - s.log.Debugf("failed processing packet from %v (%v): PlayerAuthInput: error resolving item stack request: %v", s.conn.RemoteAddr(), s.c.Name(), err) + s.log.Debug("process packet: PlayerAuthInput: resolve item stack request: " + err.Error()) } } return nil @@ -136,7 +136,7 @@ func (h PlayerAuthInputHandler) handleUseItemData(data protocol.UseItemTransacti held, _ := s.c.HeldItems() if !held.Equal(stackToItem(data.HeldItem.Stack)) { - s.log.Debugf("failed processing item interaction from %v (%v): PlayerAuthInput: actual held and client held item mismatch", s.conn.RemoteAddr(), s.c.Name()) + s.log.Debug("process packet: PlayerAuthInput: UseItemTransaction: mismatch between actual held item and client held item") return nil } pos := cube.Pos{int(data.BlockPosition[0]), int(data.BlockPosition[1]), int(data.BlockPosition[2])} diff --git a/server/session/handler_request_ability.go b/server/session/handler_request_ability.go index 098814cdd..244bd9998 100644 --- a/server/session/handler_request_ability.go +++ b/server/session/handler_request_ability.go @@ -12,7 +12,7 @@ func (a RequestAbilityHandler) Handle(p packet.Packet, s *Session) error { pk := p.(*packet.RequestAbility) if pk.Ability == packet.AbilityFlying { if !s.c.GameMode().AllowsFlying() { - s.log.Debugf("failed processing packet from %v (%v): RequestAbility: flying flag enabled while not being able to fly\n", s.conn.RemoteAddr(), s.c.Name()) + s.log.Debug("process packet: RequestAbility: flying flag enabled while unable to fly") s.sendAbilities() return nil } diff --git a/server/session/player.go b/server/session/player.go index 9073d0c4c..27f878c9b 100644 --- a/server/session/player.go +++ b/server/session/player.go @@ -380,7 +380,7 @@ func (s *Session) SendForm(f form.Form) { h.mu.Lock() if len(h.forms) > 10 { - s.log.Debugf("SendForm %v: more than 10 active forms: dropping an existing one.", s.c.Name()) + s.log.Debug("SendForm: more than 10 active forms: dropping an existing one") for k := range h.forms { delete(h.forms, k) break @@ -733,7 +733,7 @@ func (s *Session) UpdateHeldSlot(slot int, expected item.Stack) error { if !clientSideItem.Equal(actual) { // Only ever debug these as they are frequent and expected to happen whenever client and server get // out of sync. - s.log.Debugf("failed processing packet from %v (%v): failed changing held slot: client-side item must be identical to server-side item, but got differences: client: %v vs server: %v", s.conn.RemoteAddr(), s.c.Name(), clientSideItem, actual) + s.log.Debug("update held slot: client-side item must be identical to server-side item, but got differences", "client-held", clientSideItem.String(), "server-held", actual.String()) } for _, viewer := range s.c.World().Viewers(s.c.Position()) { viewer.ViewEntityItems(s.c) diff --git a/server/session/session.go b/server/session/session.go index 1106ec8f4..8937804fb 100644 --- a/server/session/session.go +++ b/server/session/session.go @@ -21,6 +21,7 @@ import ( "github.com/sandertv/gophertunnel/minecraft/protocol/packet" "github.com/sandertv/gophertunnel/minecraft/text" "io" + "log/slog" "net" "sync" "sync/atomic" @@ -30,7 +31,7 @@ import ( // Session handles incoming packets from connections and sends outgoing packets by providing a thin layer // of abstraction over direct packets. A Session basically 'controls' an entity. type Session struct { - log Logger + log *slog.Logger once, connOnce sync.Once c Controllable @@ -115,12 +116,6 @@ type Conn interface { StartGameContext(ctx context.Context, data minecraft.GameData) error } -// Logger is used to write debug messages to. These messages are sent whenever handling of a packet of a client fails. -type Logger interface { - Errorf(format string, a ...any) - Debugf(format string, a ...any) -} - // Nop represents a no-operation session. It does not do anything when sending a packet to it. var Nop = &Session{} @@ -140,7 +135,7 @@ var errSelfRuntimeID = errors.New("invalid entity runtime ID: runtime ID for sel // packets that it receives. // New takes the connection from which to accept packets. It will start handling these packets after a call to // Session.Spawn(). -func New(conn Conn, maxChunkRadius int, log Logger, joinMessage, quitMessage string) *Session { +func New(conn Conn, maxChunkRadius int, log *slog.Logger, joinMessage, quitMessage string) *Session { r := conn.ChunkRadius() if r > maxChunkRadius { r = maxChunkRadius @@ -160,7 +155,7 @@ func New(conn Conn, maxChunkRadius int, log Logger, joinMessage, quitMessage str chunkRadius: int32(r), maxChunkRadius: int32(maxChunkRadius), conn: conn, - log: log, + log: log.With("name", conn.IdentityData().DisplayName, "uuid", conn.IdentityData().Identity, "raddr", conn.RemoteAddr().String()), currentEntityRuntimeID: 1, heldSlot: new(atomic.Uint32), joinMessage: joinMessage, @@ -318,9 +313,9 @@ func (s *Session) handlePackets() { return } if err := s.handlePacket(pk); err != nil { - // An error occurred during the handling of a packet. Print the error and stop handling any more - // packets. - s.log.Debugf("failed processing packet from %v (%v): %v\n", s.conn.RemoteAddr(), s.c.Name(), err) + // An error occurred during the handling of a packet. + // Print the error and stop handling any more packets. + s.log.Debug("process packet: " + err.Error()) return } } @@ -437,7 +432,7 @@ func (s *Session) ChangingDimension() bool { func (s *Session) handlePacket(pk packet.Packet) error { handler, ok := s.handlers[pk.ID()] if !ok { - s.log.Debugf("unhandled packet %T%v from %v\n", pk, fmt.Sprintf("%+v", pk)[1:], s.conn.RemoteAddr()) + s.log.Debug("unhandled packet", "packet", fmt.Sprintf("%T", pk), "data", fmt.Sprintf("%+v", pk)[1:]) return nil } if handler == nil { diff --git a/server/world/chunk/a_test.go b/server/world/chunk/a_test.go new file mode 100644 index 000000000..65a870630 --- /dev/null +++ b/server/world/chunk/a_test.go @@ -0,0 +1,20 @@ +package chunk + +import ( + "bytes" + "fmt" + "github.com/df-mc/dragonfly/server/block/cube" + "os" + "testing" +) + +func TestA(t *testing.T) { + data, err := os.ReadFile("biomes.out") + if err != nil { + panic(err) + } + buf := bytes.NewBuffer(data) + c := New(0, cube.Range{-64, 319}) + err = decodeBiomes(buf, c, NetworkEncoding) + fmt.Println(err) +} diff --git a/server/world/conf.go b/server/world/conf.go index 87ae975be..633af3294 100644 --- a/server/world/conf.go +++ b/server/world/conf.go @@ -2,16 +2,16 @@ package world import ( "github.com/df-mc/dragonfly/server/block/cube" - "github.com/sirupsen/logrus" + "log/slog" "math/rand" "time" ) // Config may be used to create a new World. It holds a variety of fields that influence the World. type Config struct { - // Log is the Logger that will be used to log errors and debug messages to. If set to nil, a Logrus logger will be - // used. - Log Logger + // Log is the Logger that will be used to log errors and debug messages to. + // If set to nil, slog.Default() is set. + Log *slog.Logger // Dim is the Dimension of the World. If set to nil, the World will use Overworld as its dimension. The dimension // set here influences, among others, the sky colour, weather/time and liquid behaviour in that World. Dim Dimension @@ -40,18 +40,11 @@ type Config struct { Entities EntityRegistry } -// Logger is a logger implementation that may be passed to the Log field of Config. World will send errors and debug -// messages to this Logger when appropriate. -type Logger interface { - Errorf(format string, a ...any) - Debugf(format string, a ...any) -} - // New creates a new World using the Config conf. The World returned will start ticking as soon as a viewer is added // to it and is otherwise ready for use. func (conf Config) New() *World { if conf.Log == nil { - conf.Log = logrus.New() + conf.Log = slog.Default() } if conf.Dim == nil { conf.Dim = Overworld diff --git a/server/world/mcdb/conf.go b/server/world/mcdb/conf.go index e31321ac4..150dec705 100644 --- a/server/world/mcdb/conf.go +++ b/server/world/mcdb/conf.go @@ -7,23 +7,16 @@ import ( "github.com/df-mc/dragonfly/server/world/mcdb/leveldat" "github.com/df-mc/goleveldb/leveldb" "github.com/df-mc/goleveldb/leveldb/opt" - "github.com/sirupsen/logrus" + "log/slog" "os" "path/filepath" ) -// Logger is a logger implementation that may be passed to the Log field of Config. World will send errors and debug -// messages to this Logger when appropriate. -type Logger interface { - Errorf(format string, a ...any) - Debugf(format string, a ...any) -} - // Config holds the optional parameters of a DB. type Config struct { // Log is the Logger that will be used to log errors and debug messages to. - // If set to nil, a Logrus logger will be used. - Log Logger + // If set to nil, Log is set to slog.Default(). + Log *slog.Logger // Compression specifies the compression to use for compressing new data in // the database. Decompression of the database will happen based on IDs // found in the compressed blocks and is therefore uninfluenced by this @@ -49,8 +42,9 @@ type Config struct { // returned. func (conf Config) Open(dir string) (*DB, error) { if conf.Log == nil { - conf.Log = logrus.New() + conf.Log = slog.Default() } + conf.Log = conf.Log.With("provider", "mcdb") if conf.BlockSize == 0 { conf.BlockSize = 16 * opt.KiB } @@ -66,7 +60,7 @@ func (conf Config) Open(dir string) (*DB, error) { } else { ldat, err := leveldat.ReadFile(filepath.Join(dir, "level.dat")) if err != nil { - return nil, fmt.Errorf("open db: %w", err) + return nil, fmt.Errorf("open db: read level.dat: %w", err) } // TODO: Perform proper conversion here. Dragonfly stored 3 for a long @@ -77,7 +71,7 @@ func (conf Config) Open(dir string) (*DB, error) { return nil, fmt.Errorf("open db: level.dat version %v is unsupported", ver) } if err = ldat.Unmarshal(db.ldat); err != nil { - return nil, fmt.Errorf("open db: %w", err) + return nil, fmt.Errorf("open db: unmarshal level.dat: %w", err) } } db.set = db.ldat.Settings() @@ -87,7 +81,7 @@ func (conf Config) Open(dir string) (*DB, error) { ReadOnly: conf.ReadOnly, }) if err != nil { - return nil, fmt.Errorf("error opening leveldb database: %w", err) + return nil, fmt.Errorf("open db: leveldb: %w", err) } db.ldb = ldb return db, nil diff --git a/server/world/mcdb/db.go b/server/world/mcdb/db.go index 035a73eb1..d8f66ec6e 100644 --- a/server/world/mcdb/db.go +++ b/server/world/mcdb/db.go @@ -70,7 +70,7 @@ func (db *DB) LoadPlayerSpawnPosition(id uuid.UUID) (pos cube.Pos, exists bool, // loadPlayerData loads the data stored in a LevelDB database for a specific UUID. func (db *DB) loadPlayerData(id uuid.UUID) (serverData map[string]interface{}, key string, exists bool, err error) { data, err := db.ldb.Get([]byte("player_"+id.String()), nil) - if err == leveldb.ErrNotFound { + if errors.Is(err, leveldb.ErrNotFound) { return nil, "", false, nil } else if err != nil { return nil, "", true, fmt.Errorf("error reading player data for uuid %v: %w", id, err) @@ -153,7 +153,7 @@ func (db *DB) column(k dbKey) (*world.Column, error) { return nil, fmt.Errorf("read version: %w", err) } if ver != chunkVersion { - db.conf.Log.Debugf("column %v (%v): unsupported chunk version %v, trying to load anyway", k.pos, k.dim, ver) + db.conf.Log.Debug("column: unsupported chunk version, trying to load anyway", "X", k.pos[0], "Z", k.pos[1], "dimension", fmt.Sprint(k.dim), "ver", ver) } cdata.Biomes, err = db.biomes(k) if err != nil && !errors.Is(err, leveldb.ErrNotFound) { @@ -252,13 +252,13 @@ func (db *DB) entities(k dbKey) ([]world.Entity, error) { } id, ok := m["identifier"] if !ok { - db.conf.Log.Errorf("missing identifier field in %v", m) + db.conf.Log.Error("missing identifier field", "data", fmt.Sprint(m)) continue } name, _ := id.(string) t, ok := db.conf.Entities.Lookup(name) if !ok { - db.conf.Log.Errorf("entity %v was not registered (%v)", name, m) + db.conf.Log.Error("no entity with ID", "id", name, "data", fmt.Sprint(m)) continue } if s, ok := t.(world.SaveableEntityType); ok { @@ -292,12 +292,12 @@ func (db *DB) blockEntities(k dbKey, c *chunk.Chunk) (map[cube.Pos]world.Block, id := c.Block(uint8(pos[0]), int16(pos[1]), uint8(pos[2]), 0) b, ok := world.BlockByRuntimeID(id) if !ok { - db.conf.Log.Errorf("no block registered with runtime id %v", id) + db.conf.Log.Error("no block with runtime ID", "ID", id) continue } nbter, ok := b.(world.NBTer) if !ok { - db.conf.Log.Errorf("block %#v has nbt but does not implement world.nbter", b) + db.conf.Log.Error("block with nbt does not implement world.NBTer", "block", fmt.Sprintf("%#v", b)) continue } blockEntities[pos] = nbter.DecodeNBT(m).(world.Block) @@ -368,7 +368,7 @@ func (db *DB) storeEntities(batch *leveldb.Batch, k dbKey, entities []world.Enti x := t.EncodeNBT(e) x["identifier"] = t.EncodeEntity() if err := enc.Encode(x); err != nil { - db.conf.Log.Errorf("store entities: error encoding NBT: %w", err) + db.conf.Log.Error("store entities: encode NBT: " + err.Error()) } } batch.Put(k.Sum(keyEntities), buf.Bytes()) @@ -390,7 +390,7 @@ func (db *DB) storeBlockEntities(batch *leveldb.Batch, k dbKey, blockEntities ma data := n.EncodeNBT() data["x"], data["y"], data["z"] = int32(pos[0]), int32(pos[1]), int32(pos[2]) if err := enc.Encode(data); err != nil { - db.conf.Log.Errorf("store block entities: error encoding NBT: %w", err) + db.conf.Log.Error("store block entities: encode NBT: " + err.Error()) } } batch.Put(k.Sum(keyBlockEntities), buf.Bytes()) diff --git a/server/world/world.go b/server/world/world.go index 965be6b8f..fce62e3a7 100644 --- a/server/world/world.go +++ b/server/world/world.go @@ -155,7 +155,7 @@ func (w *World) Biome(pos cube.Pos) Biome { id := int(c.Biome(uint8(pos[0]), int16(pos[1]), uint8(pos[2]))) b, ok := BiomeByID(id) if !ok { - w.conf.Log.Errorf("could not find biome by ID %v", id) + w.conf.Log.Error("biome not found by ID", "ID", id) } return b } @@ -426,7 +426,7 @@ func (w *World) Liquid(pos cube.Pos) (Liquid, bool) { id := c.Block(x, y, z, 0) b, ok := BlockByRuntimeID(id) if !ok { - w.conf.Log.Errorf("failed getting liquid: cannot get block by runtime ID %v", id) + w.conf.Log.Error("Liquid: no block with runtime ID", "ID", id) return nil, false } if liq, ok := b.(Liquid); ok { @@ -436,7 +436,7 @@ func (w *World) Liquid(pos cube.Pos) (Liquid, bool) { b, ok = BlockByRuntimeID(id) if !ok { - w.conf.Log.Errorf("failed getting liquid: cannot get block by runtime ID %v", id) + w.conf.Log.Error("Liquid: no block with runtime ID", "ID", id) return nil, false } liq, ok := b.(Liquid) @@ -515,7 +515,7 @@ func (w *World) removeLiquidOnLayer(c *chunk.Chunk, x uint8, y int16, z, layer u b, ok := BlockByRuntimeID(id) if !ok { - w.conf.Log.Errorf("failed removing liquids: cannot get block by runtime ID %v", id) + w.conf.Log.Error("removeLiquidOnLayer: no block with runtime ID", "ID", id) return false, false } if _, ok := b.(Liquid); ok { @@ -537,7 +537,7 @@ func (w *World) additionalLiquid(pos cube.Pos) (Liquid, bool) { c.Unlock() b, ok := BlockByRuntimeID(id) if !ok { - w.conf.Log.Errorf("failed getting liquid: cannot get block by runtime ID %v", id) + w.conf.Log.Error("additionalLiquid: no block with runtime ID", "ID", id) return nil, false } liq, ok := b.(Liquid) @@ -853,7 +853,7 @@ func (w *World) PlayerSpawn(uuid uuid.UUID) cube.Pos { } pos, exist, err := w.conf.Provider.LoadPlayerSpawnPosition(uuid) if err != nil { - w.conf.Log.Errorf("failed to get player spawn: %v", err) + w.conf.Log.Error("load player spawn: " + err.Error()) return w.Spawn() } if !exist { @@ -869,7 +869,7 @@ func (w *World) SetPlayerSpawn(uuid uuid.UUID, pos cube.Pos) { return } if err := w.conf.Provider.SavePlayerSpawnPosition(uuid, pos); err != nil { - w.conf.Log.Errorf("failed to set player spawn: %v", err) + w.conf.Log.Error("set player spawn: " + err.Error()) } } @@ -1020,7 +1020,7 @@ func (w *World) PortalDestination(dim Dimension) *World { // Save saves the World to the provider. func (w *World) Save() { - w.conf.Log.Debugf("Saving chunks in memory to disk...") + w.conf.Log.Debug("Saving chunks in memory to disk...") w.chunkMu.Lock() toSave := maps.Clone(w.chunks) @@ -1049,7 +1049,7 @@ func (w *World) close() { close(w.closing) w.running.Wait() - w.conf.Log.Debugf("Saving chunks in memory to disk...") + w.conf.Log.Debug("Saving chunks in memory to disk...") w.chunkMu.Lock() w.lastChunk = nil @@ -1067,14 +1067,14 @@ func (w *World) close() { } if !w.conf.ReadOnly { - w.conf.Log.Debugf("Updating level.dat values...") + w.conf.Log.Debug("Updating level.dat values...") w.provider().SaveSettings(w.set) } - w.conf.Log.Debugf("Closing provider...") + w.conf.Log.Debug("Closing provider...") if err := w.provider().Close(); err != nil { - w.conf.Log.Errorf("error closing world provider: %v", err) + w.conf.Log.Error("close world provider: " + err.Error()) } } @@ -1207,7 +1207,7 @@ func (w *World) chunk(pos ChunkPos) *Column { chunk.LightArea([]*chunk.Chunk{c.Chunk}, int(pos[0]), int(pos[1])).Fill() if err != nil { w.chunkMu.Unlock() - w.conf.Log.Errorf("load chunk: failed loading %v: %v\n", pos, err) + w.conf.Log.Error("load chunk: "+err.Error(), "X", pos[0], "Z", pos[1]) return c } c.Unlock() @@ -1333,7 +1333,7 @@ func (w *World) saveChunk(pos ChunkPos, c *Column, closeEntities bool) { if !w.conf.ReadOnly && c.modified { c.Compact() if err := w.provider().StoreColumn(pos, w.conf.Dim, c); err != nil { - w.conf.Log.Errorf("save chunk: %v", err) + w.conf.Log.Error("save chunk: "+err.Error(), "X", pos[0], "Z", pos[1]) } } if closeEntities {