Compare commits

..

12 Commits

Author SHA1 Message Date
BuckarooBanzay
27d12c20bc wal mode 2022-07-05 09:54:40 +02:00
BuckarooBanzay
6a62d14102 sqlite open mode adjustements 2022-03-23 08:39:45 +01:00
BuckarooBanzay
2abe4f567b world stats 2022-03-21 19:21:06 +01:00
BuckarooBanzay
dbd13415df coord display 2022-03-21 18:51:06 +01:00
BuckarooBanzay
bb4da68ef5 layer service 2022-03-21 18:47:54 +01:00
BuckarooBanzay
3735dbd242 persistent hash route 2022-03-20 19:44:17 +01:00
BuckarooBanzay
c701170a07 realtime layer stub 2022-03-20 19:35:57 +01:00
BuckarooBanzay
8e29829e96 map element setup 2022-03-20 10:54:53 +01:00
BuckarooBanzay
0fb4f8fed6 full screen map page 2022-03-20 10:19:15 +01:00
BuckarooBanzay
eaa8cb5fc0 fix indents 2022-03-19 17:48:22 +01:00
BuckarooBanzay
92ecab7c44 update go versions 2022-03-19 17:45:37 +01:00
BuckarooBanzay
9371e1efb7 vuejs stuff 2022-03-19 17:40:45 +01:00
269 changed files with 70647 additions and 2456 deletions

View File

@ -13,17 +13,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5.0.1
uses: actions/setup-go@v3.0.0
with:
go-version: "1.22"
go-version: 1.17
- name: Set up nodejs
uses: actions/setup-node@v4
uses: actions/setup-node@v3
with:
node-version: '17'
@ -31,7 +31,7 @@ jobs:
run: cd public && npm ci && npm run bundle
- name: Cache Go modules
uses: actions/cache@v4
uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
@ -42,12 +42,24 @@ jobs:
run: |
go test ./...
# only on tags
- name: Docker Login
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6
uses: goreleaser/goreleaser-action@v2
if: success() && startsWith(github.ref, 'refs/tags/')
with:
version: latest
args: release --clean
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push latest docker image
if: success() && github.ref == 'refs/heads/master'
run: |
CGO_ENABLED=0 go build .
docker build . -t minetestmapserver/mapserver:latest
docker push minetestmapserver/mapserver:latest

View File

@ -1,39 +0,0 @@
name: docker
on:
push:
branches:
- 'main'
tags:
- 'v*'
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/minetest-mapserver/mapserver
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View File

@ -5,17 +5,19 @@ on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5.0.1
- uses: actions/checkout@v3
- uses: actions/setup-go@v3.0.0
with:
go-version: '1.21'
go-version: '1.17'
- name: test
run: go test ./... -coverprofile=profile.cov
run: |
cd public && npm ci && cd ..
go test ./... -coverprofile=profile.cov
- uses: shogo82148/actions-goveralls@v1.9.0
- uses: shogo82148/actions-goveralls@v1.6.0
with:
path-to-profile: profile.cov

View File

@ -5,13 +5,13 @@ on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- name: Set up nodejs
uses: actions/setup-node@v4
uses: actions/setup-node@v3
with:
node-version: '17'

View File

@ -1,13 +1,24 @@
before:
hooks:
- go mod tidy
builds:
- env:
- CGO_ENABLED=0
goos:
- linux
- windows
goarch:
- amd64
- arm64
targets:
- linux_amd64
- windows_amd64
- darwin_arm64
- linux_arm_6
ldflags:
- -s -w -X mapserver/app.Version={{.Version}}
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
dockers:
- image_templates:
- "minetestmapserver/mapserver:{{ .Version }}"
- "minetestmapserver/mapserver:latest"
dockerfile: Dockerfile

View File

@ -1,18 +1,4 @@
FROM node:20.15.0 as bundle-builder
COPY public /public
WORKDIR /public
RUN npm ci && npm run bundle
FROM golang:1.22.4 as go-builder
COPY . /data
COPY --from=bundle-builder /public/js/bundle* /data/public/js/
WORKDIR /data
RUN CGO_ENABLED=0 go build .
FROM alpine:3.20.1
COPY --from=go-builder /data/mapserver /bin/mapserver
ENV MT_CONFIG_PATH "mapserver.json"
ENV MT_LOGLEVEL "INFO"
ENV MT_READONLY "false"
FROM scratch
COPY mapserver /bin/mapserver
EXPOSE 8080
ENTRYPOINT ["/bin/mapserver"]
ENTRYPOINT ["/bin/mapserver"]

View File

@ -1,6 +1,8 @@
package app
import (
"mapserver/blockaccessor"
"mapserver/colormapping"
"mapserver/db"
"mapserver/eventbus"
"mapserver/mapblockaccessor"
@ -10,8 +12,6 @@ import (
"mapserver/settings"
"mapserver/tiledb"
"mapserver/tilerenderer"
"github.com/minetest-go/colormapping"
)
type App struct {
@ -25,6 +25,7 @@ type App struct {
Settings settings.Settings
MapBlockAccessor *mapblockaccessor.MapBlockAccessor
BlockAccessor *blockaccessor.BlockAccessor
Colormapping *colormapping.ColorMapping
Mapblockrenderer *mapblockrenderer.MapBlockRenderer
Tilerenderer *tilerenderer.TileRenderer

View File

@ -2,7 +2,8 @@ package app
import (
"encoding/json"
"mapserver/types"
"io/ioutil"
"mapserver/layer"
"os"
"runtime"
"sync"
@ -43,13 +44,14 @@ func ParseConfig(filename string) (*Config, error) {
SecretKey: RandStringRunes(16),
}
layers := []*types.Layer{
{
layers := []*layer.Layer{
&layer.Layer{
Id: 0,
Name: "Ground",
From: -1,
To: 10,
}, {
},
&layer.Layer{
Id: 1,
Name: "Sky",
From: 11,
@ -58,44 +60,41 @@ func ParseConfig(filename string) (*Config, error) {
}
mapobjs := MapObjectConfig{
Areas: true,
Bones: true,
Protector: true,
XPProtector: true,
PrivProtector: true,
TechnicQuarry: true,
TechnicSwitch: true,
TechnicAnchor: true,
TechnicReactor: true,
LuaController: true,
Digiterms: true,
Digilines: true,
Travelnet: true,
MapserverPlayer: true,
MapserverPOI: true,
MapserverLabel: true,
MapserverTrainline: true,
MapserverBorder: true,
TileServerLegacy: true,
Mission: true,
Jumpdrive: true,
Smartshop: true,
Fancyvend: true,
ATM: true,
Train: true,
TrainSignal: true,
Minecart: false,
Locator: false,
Signs: true,
MapserverAirutils: true,
UnifiefMoneyAreaForSale: true,
Phonograph: true,
Areas: true,
Bones: true,
Protector: true,
XPProtector: true,
PrivProtector: true,
TechnicQuarry: true,
TechnicSwitch: true,
TechnicAnchor: true,
TechnicReactor: true,
LuaController: true,
Digiterms: true,
Digilines: true,
Travelnet: true,
MapserverPlayer: true,
MapserverPOI: true,
MapserverLabel: true,
MapserverTrainline: true,
MapserverBorder: true,
TileServerLegacy: true,
Mission: true,
Jumpdrive: true,
Smartshop: true,
Fancyvend: true,
ATM: true,
Train: true,
TrainSignal: true,
Minecart: false,
Locator: false,
Signs: true,
}
mapblockaccessor := MapBlockAccessorConfig{
Expiretime: "10s",
Purgetime: "15s",
MaxItems: 50,
Expiretime: "15s",
Purgetime: "30s",
MaxItems: 500,
}
defaultoverlays := []string{
@ -104,11 +103,6 @@ func ParseConfig(filename string) (*Config, error) {
"mapserver_player",
}
skins := SkinsConfig{
EnableSkinsDB: false,
SkinsPath: "",
}
cfg := Config{
ConfigVersion: 1,
Port: 8080,
@ -121,22 +115,18 @@ func ParseConfig(filename string) (*Config, error) {
Webdev: false,
WebApi: &webapi,
Layers: layers,
RenderingFetchLimit: 500,
RenderingFetchLimit: 10000,
RenderingJobs: runtime.NumCPU(),
RenderingQueue: 10,
RenderingQueue: 100,
IncrementalRenderingTimer: "5s",
MapObjects: &mapobjs,
MapBlockAccessorCfg: &mapblockaccessor,
DefaultOverlays: defaultoverlays,
Skins: &skins,
WorldPath: "./",
DataPath: "./",
ColorsTxtPath: "./",
}
info, err := os.Stat(filename)
if info != nil && err == nil {
data, err := os.ReadFile(filename)
data, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}

View File

@ -1,6 +1,8 @@
package app
import (
"mapserver/blockaccessor"
"mapserver/colormapping"
"mapserver/db/postgres"
"mapserver/db/sqlite"
"mapserver/eventbus"
@ -16,10 +18,8 @@ import (
"mapserver/worldconfig"
"time"
"github.com/minetest-go/colormapping"
"io/ioutil"
"os"
"path/filepath"
"github.com/sirupsen/logrus"
@ -33,14 +33,14 @@ func Setup(p params.ParamsType, cfg *Config) *App {
a.WebEventbus = eventbus.New()
//Parse world config
a.Worldconfig = worldconfig.Parse(filepath.Join(a.Config.WorldPath, "world.mt"))
a.Worldconfig = worldconfig.Parse("world.mt")
logrus.WithFields(logrus.Fields{"version": Version}).Info("Starting mapserver")
var err error
switch a.Worldconfig[worldconfig.CONFIG_BACKEND] {
case worldconfig.BACKEND_SQLITE3:
map_path := filepath.Join(a.Config.WorldPath, "map.sqlite")
map_path := "map.sqlite"
// check if the database exists, otherwise abort (nothing to render/display)
_, err := os.Stat(map_path)
@ -88,19 +88,37 @@ func Setup(p params.ParamsType, cfg *Config) *App {
expireDuration, purgeDuration,
cfg.MapBlockAccessorCfg.MaxItems)
// block accessor
a.BlockAccessor = blockaccessor.New(a.MapBlockAccessor)
//color mapping
a.Colormapping = colormapping.NewColorMapping()
err = a.Colormapping.LoadDefaults()
if err != nil {
panic(err)
colorfiles := []string{
//https://daconcepts.com/vanessa/hobbies/minetest/colors.txt
"colors/vanessa.txt",
"colors/advtrains.txt",
"colors/scifi_nodes.txt",
"colors/mc2.txt",
"colors/mtg.txt",
"colors/miles.txt",
"colors/custom.txt",
"colors/nodecore.txt",
}
for _, colorfile := range colorfiles {
_, err := a.Colormapping.LoadVFSColors(colorfile)
if err != nil {
panic(err.Error() + " file:" + colorfile)
}
}
//load provided colors, if available
info, err := os.Stat(filepath.Join(a.Config.ColorsTxtPath, "colors.txt"))
info, err := os.Stat("colors.txt")
if info != nil && err == nil {
logrus.WithFields(logrus.Fields{"filename": "colors.txt"}).Info("Loading colors from filesystem")
data, err := os.ReadFile(filepath.Join(a.Config.ColorsTxtPath, "colors.txt"))
data, err := ioutil.ReadFile("colors.txt")
if err != nil {
panic(err)
}
@ -121,7 +139,7 @@ func Setup(p params.ParamsType, cfg *Config) *App {
if a.Worldconfig[worldconfig.CONFIG_PSQL_MAPSERVER] != "" {
a.Objectdb, err = postgresobjdb.New(a.Worldconfig[worldconfig.CONFIG_PSQL_MAPSERVER])
} else {
a.Objectdb, err = sqliteobjdb.New(filepath.Join(a.Config.DataPath, "mapserver.sqlite"))
a.Objectdb, err = sqliteobjdb.New("mapserver.sqlite")
}
if err != nil {
@ -136,7 +154,7 @@ func Setup(p params.ParamsType, cfg *Config) *App {
}
//create tiledb
a.TileDB, err = tiledb.New(filepath.Join(a.Config.DataPath, "mapserver.tiles"))
a.TileDB, err = tiledb.New("./mapserver.tiles")
if err != nil {
panic(err)

View File

@ -1,6 +1,8 @@
package app
import "mapserver/types"
import (
"mapserver/layer"
)
type Config struct {
ConfigVersion int `json:"configversion"`
@ -13,7 +15,7 @@ type Config struct {
EnableMediaRepository bool `json:"enablemediarepository"`
Webdev bool `json:"webdev"`
WebApi *WebApiConfig `json:"webapi"`
Layers []*types.Layer `json:"layers"`
Layers []*layer.Layer `json:"layers"`
RenderingFetchLimit int `json:"renderingfetchlimit"`
RenderingJobs int `json:"renderingjobs"`
RenderingQueue int `json:"renderingqueue"`
@ -21,10 +23,6 @@ type Config struct {
MapObjects *MapObjectConfig `json:"mapobjects"`
MapBlockAccessorCfg *MapBlockAccessorConfig `json:"mapblockaccessor"`
DefaultOverlays []string `json:"defaultoverlays"`
Skins *SkinsConfig `json:"skins"`
WorldPath string `json:"worldpath"`
DataPath string `json:"datapath"`
ColorsTxtPath string `json:"colorstxtpath"`
}
type MapBlockAccessorConfig struct {
@ -34,38 +32,35 @@ type MapBlockAccessorConfig struct {
}
type MapObjectConfig struct {
Areas bool `json:"areas"`
Bones bool `json:"bones"`
Protector bool `json:"protector"`
XPProtector bool `json:"xpprotector"`
PrivProtector bool `json:"privprotector"`
TechnicQuarry bool `json:"technic_quarry"`
TechnicSwitch bool `json:"technic_switch"`
TechnicAnchor bool `json:"technic_anchor"`
TechnicReactor bool `json:"technic_reactor"`
LuaController bool `json:"luacontroller"`
Digiterms bool `json:"digiterms"`
Digilines bool `json:"digilines"`
Travelnet bool `json:"travelnet"`
MapserverPlayer bool `json:"mapserver_player"`
MapserverPOI bool `json:"mapserver_poi"`
MapserverLabel bool `json:"mapserver_label"`
MapserverTrainline bool `json:"mapserver_trainline"`
MapserverBorder bool `json:"mapserver_border"`
TileServerLegacy bool `json:"tileserverlegacy"`
Mission bool `json:"mission"`
Jumpdrive bool `json:"jumpdrive"`
Smartshop bool `json:"smartshop"`
Fancyvend bool `json:"fancyvend"`
ATM bool `json:"atm"`
Train bool `json:"train"`
TrainSignal bool `json:"trainsignal"`
Minecart bool `json:"minecart"`
Locator bool `json:"locator"`
Signs bool `json:"signs"`
MapserverAirutils bool `json:"mapserver_airutils"`
Phonograph bool `json:"phonograph"`
UnifiefMoneyAreaForSale bool `json:"um_area_forsale"`
Areas bool `json:"areas"`
Bones bool `json:"bones"`
Protector bool `json:"protector"`
XPProtector bool `json:"xpprotector"`
PrivProtector bool `json:"privprotector"`
TechnicQuarry bool `json:"technic_quarry"`
TechnicSwitch bool `json:"technic_switch"`
TechnicAnchor bool `json:"technic_anchor"`
TechnicReactor bool `json:"technic_reactor"`
LuaController bool `json:"luacontroller"`
Digiterms bool `json:"digiterms"`
Digilines bool `json:"digilines"`
Travelnet bool `json:"travelnet"`
MapserverPlayer bool `json:"mapserver_player"`
MapserverPOI bool `json:"mapserver_poi"`
MapserverLabel bool `json:"mapserver_label"`
MapserverTrainline bool `json:"mapserver_trainline"`
MapserverBorder bool `json:"mapserver_border"`
TileServerLegacy bool `json:"tileserverlegacy"`
Mission bool `json:"mission"`
Jumpdrive bool `json:"jumpdrive"`
Smartshop bool `json:"smartshop"`
Fancyvend bool `json:"fancyvend"`
ATM bool `json:"atm"`
Train bool `json:"train"`
TrainSignal bool `json:"trainsignal"`
Minecart bool `json:"minecart"`
Locator bool `json:"locator"`
Signs bool `json:"signs"`
}
type WebApiConfig struct {
@ -75,8 +70,3 @@ type WebApiConfig struct {
//mod http bridge secret
SecretKey string `json:"secretkey"`
}
type SkinsConfig struct {
EnableSkinsDB bool `json:"enableskinsdb"`
SkinsPath string `json:"skinspath"`
}

57
areasparser/parser.go Normal file
View File

@ -0,0 +1,57 @@
package areasparser
import (
"bytes"
"encoding/json"
"io/ioutil"
)
type GenericPos struct {
X int `json:"x"`
Y int `json:"y"`
Z int `json:"z"`
}
type Area struct {
Owner string `json:"owner"`
Name string `json:"name"`
Parent int `json:"parent"`
Pos1 *GenericPos `json:"pos1"`
Pos2 *GenericPos `json:"pos2"`
}
func getInt(o interface{}) int {
v, _ := o.(float64)
return int(v)
}
func (pos *GenericPos) UnmarshalJSON(data []byte) error {
m := make(map[string]interface{})
err := json.Unmarshal(data, &m)
if err != nil {
return err
}
// float-like to int workaround
pos.X = getInt(m["x"])
pos.Y = getInt(m["y"])
pos.Z = getInt(m["z"])
return nil
}
func ParseFile(filename string) ([]*Area, error) {
content, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
return Parse(content)
}
func Parse(data []byte) ([]*Area, error) {
areas := make([]*Area, 0)
json.NewDecoder(bytes.NewReader(data)).Decode(&areas)
return areas, nil
}

View File

@ -0,0 +1,20 @@
package areasparser
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestParse(t *testing.T) {
a, err := ParseFile("testdata/areas.json")
assert.NoError(t, err)
assert.True(t, len(a) > 1)
area := a[0]
assert.Equal(t, "ilai_house", area.Name)
assert.Equal(t, "ilai", area.Owner)
assert.NotNil(t, area.Pos1)
assert.NotNil(t, area.Pos2)
assert.Equal(t, 4970, area.Pos1.X)
}

323
areasparser/testdata/areas.json vendored Normal file
View File

@ -0,0 +1,323 @@
[
{
"name": "ilai_house",
"owner": "ilai",
"pos1": {
"x": 4970.0,
"y": 8.0,
"z": 88.0
},
"pos2": {
"x": 4983.0,
"y": 16.0,
"z": 99.0
}
},
{
"name": "temple",
"owner": "Lukc",
"pos1": {
"x": -1911.0,
"y": 18.0,
"z": -221.0
},
"pos2": {
"x": -1718.0,
"y": 68.0,
"z": -50.0
}
},
{
"name": "temple",
"owner": "BuckarooBanzai",
"parent": 2.0,
"pos1": {
"x": -1911.0,
"y": 18.0,
"z": -221.0
},
"pos2": {
"x": -1718.0,
"y": 68.0,
"z": -50.0
}
},
{
"name": "Spaceshipyard",
"owner": "Lukc",
"pos1": {
"x": -1784.0,
"y": -49.0,
"z": -1174.0
},
"pos2": {
"x": -1688.0,
"y": 58.0,
"z": -1068.0
}
},
{
"name": "Arena",
"owner": "Lukc",
"pos1": {
"x": -1860.0,
"y": -369.0,
"z": -1162.0
},
"pos2": {
"x": -1751.0,
"y": -310.0,
"z": -1061.0
}
},
{
"name": "Spaceshipyard",
"owner": "T4im",
"parent": 4.0,
"pos1": {
"x": -1784.0,
"y": -49.0,
"z": -1174.0
},
"pos2": {
"x": -1688.0,
"y": 58.0,
"z": -1068.0
}
},
{
"name": "temple",
"owner": "T4im",
"parent": 2.0,
"pos1": {
"x": -1911.0,
"y": 18.0,
"z": -221.0
},
"pos2": {
"x": -1718.0,
"y": 68.0,
"z": -50.0
}
},
{
"name": "Spaceshipyard",
"owner": "BuckarooBanzai",
"parent": 4.0,
"pos1": {
"x": -1784.0,
"y": -49.0,
"z": -1174.0
},
"pos2": {
"x": -1688.0,
"y": 58.0,
"z": -1068.0
}
},
{
"name": "Arena",
"owner": "T4im",
"parent": 5.0,
"pos1": {
"x": -1860.0,
"y": -369.0,
"z": -1162.0
},
"pos2": {
"x": -1751.0,
"y": -310.0,
"z": -1061.0
}
},
{
"name": "Humboldt Research Station",
"owner": "T4im",
"pos1": {
"x": -624.0,
"y": -32.0,
"z": 48.0
},
"pos2": {
"x": -369.0,
"y": 127.0,
"z": 351.0
}
},
{
"name": "centrifuge cascade",
"owner": "pipo",
"pos1": {
"x": -2995.0,
"y": -40.0,
"z": -3003.0
},
"pos2": {
"x": -2958.0,
"y": -26.0,
"z": -2990.0
}
},
{
"name": "centrifuge cascade",
"owner": "barsik",
"parent": 11.0,
"pos1": {
"x": -2995.0,
"y": -40.0,
"z": -3003.0
},
"pos2": {
"x": -2958.0,
"y": -26.0,
"z": -2990.0
}
},
{
"name": "centrifuge cascade",
"owner": "BuckarooBanzai",
"parent": 11.0,
"pos1": {
"x": -2995.0,
"y": -40.0,
"z": -3003.0
},
"pos2": {
"x": -2958.0,
"y": -26.0,
"z": -2990.0
}
},
{
"name": "centrifuge cascade",
"owner": "T4im",
"parent": 11.0,
"pos1": {
"x": -2995.0,
"y": -40.0,
"z": -3003.0
},
"pos2": {
"x": -2958.0,
"y": -26.0,
"z": -2990.0
}
},
{
"name": "centrifuge cascade",
"owner": "Lukc",
"parent": 11.0,
"pos1": {
"x": -2995.0,
"y": -40.0,
"z": -3003.0
},
"pos2": {
"x": -2958.0,
"y": -26.0,
"z": -2990.0
}
},
{
"name": "Spaceshipyard",
"owner": "pipo",
"parent": 6.0,
"pos1": {
"x": -1784.0,
"y": -49.0,
"z": -1174.0
},
"pos2": {
"x": -1688.0,
"y": 58.0,
"z": -1068.0
}
},
{
"name": "Emerald extention",
"owner": "Emerald",
"pos1": {
"x": 5055.0,
"y": 8.0,
"z": 48.0
},
"pos2": {
"x": 5059.0,
"y": 10.0,
"z": 54.0
}
},
{
"name": "tower1",
"owner": "pipo",
"parent": 19.0,
"pos1": {
"x": -14.0,
"y": -126.0,
"z": 587.0
},
"pos2": {
"x": 17.0,
"y": 103.0,
"z": 617.0
}
},
{
"name": "tower1",
"owner": "barsik",
"pos1": {
"x": -14.0,
"y": -126.0,
"z": 587.0
},
"pos2": {
"x": 17.0,
"y": 103.0,
"z": 617.0
}
},
{
"name": "tower1",
"owner": "BuckarooBanzai",
"parent": 19.0,
"pos1": {
"x": -14.0,
"y": -126.0,
"z": 587.0
},
"pos2": {
"x": 17.0,
"y": 103.0,
"z": 617.0
}
},
{
"name": "tower1",
"owner": "T4im",
"parent": 19.0,
"pos1": {
"x": -14.0,
"y": -126.0,
"z": 587.0
},
"pos2": {
"x": 17.0,
"y": 103.0,
"z": 617.0
}
},
{
"name": "Arboretum",
"owner": "pipo",
"pos1": {
"x": -1734.0,
"y": 7.0,
"z": 697.0
},
"pos2": {
"x": -1604.0,
"y": 50.0,
"z": 784.0
}
}
]

View File

@ -0,0 +1,43 @@
package blockaccessor
import (
"mapserver/coords"
"mapserver/mapblockaccessor"
)
func New(mba *mapblockaccessor.MapBlockAccessor) *BlockAccessor {
return &BlockAccessor{mba: mba}
}
type BlockAccessor struct {
mba *mapblockaccessor.MapBlockAccessor
}
type Block struct {
Name string
//TODO: param1, param2
}
func (this *BlockAccessor) GetBlock(x, y, z int) (*Block, error) {
mbc := coords.NewMapBlockCoordsFromBlock(x, y, z)
mapblock, err := this.mba.GetMapBlock(mbc)
if err != nil {
return nil, err
}
if mapblock == nil {
return nil, nil
}
relx := x % 16
rely := y % 16
relz := z % 16
block := Block{
Name: mapblock.GetNodeName(relx, rely, relz),
}
return &block, nil
}

View File

@ -0,0 +1,59 @@
package blockaccessor
import (
"fmt"
"io/ioutil"
"mapserver/db/sqlite"
"mapserver/mapblockaccessor"
"mapserver/testutils"
"os"
"testing"
"time"
"github.com/sirupsen/logrus"
)
func TestSimpleAccess(t *testing.T) {
logrus.SetLevel(logrus.DebugLevel)
tmpfile, err := ioutil.TempFile("", "TestMigrate.*.sqlite")
if err != nil {
panic(err)
}
defer os.Remove(tmpfile.Name())
testutils.CreateTestDatabase(tmpfile.Name())
a, err := sqlite.New(tmpfile.Name())
if err != nil {
panic(err)
}
err = a.Migrate()
if err != nil {
panic(err)
}
mba := mapblockaccessor.NewMapBlockAccessor(a, 500*time.Millisecond, 1000*time.Millisecond, 1000)
if mba == nil {
t.Fatal("Mapblockaccessor is nil")
}
ba := New(mba)
if ba == nil {
t.Fatal("blockaccessor is nil")
}
block, err := ba.GetBlock(0, 2, 0)
if err != nil {
panic(err)
}
if block == nil {
t.Fatal("block is nil")
}
fmt.Println(block.Name)
}

View File

@ -0,0 +1,148 @@
package colormapping
import (
"bufio"
"bytes"
"errors"
"image/color"
"mapserver/public"
"strconv"
"strings"
"github.com/sirupsen/logrus"
)
type ColorMapping struct {
colors map[string]*color.RGBA
extendedpaletteblock map[string]bool
extendedpalette *Palette
}
func (m *ColorMapping) GetColor(name string, param2 int) *color.RGBA {
//TODO: list of node->palette
if m.extendedpaletteblock[name] {
// param2 coloring
return m.extendedpalette.GetColor(param2)
}
return m.colors[name]
}
func (m *ColorMapping) GetColors() map[string]*color.RGBA {
return m.colors
}
func (m *ColorMapping) LoadBytes(buffer []byte) (int, error) {
scanner := bufio.NewScanner(bytes.NewReader(buffer))
count := 0
line := 0
for scanner.Scan() {
line++
txt := strings.Trim(scanner.Text(), " ")
if len(txt) == 0 {
//empty
continue
}
if strings.HasPrefix(txt, "#") {
//comment
continue
}
parts := strings.Fields(txt)
if len(parts) < 4 {
return 0, errors.New("invalid line: #" + strconv.Itoa(line))
}
if len(parts) >= 4 {
r, err := strconv.ParseInt(parts[1], 10, 32)
if err != nil {
return 0, err
}
g, err := strconv.ParseInt(parts[2], 10, 32)
if err != nil {
return 0, err
}
b, err := strconv.ParseInt(parts[3], 10, 32)
if err != nil {
return 0, err
}
a := int64(255)
if len(parts) >= 5 {
//with alpha
//a, err = strconv.ParseInt(parts[4], 10, 32)
//if err != nil {
// return 0, err
//}
}
c := color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)}
m.colors[parts[0]] = &c
count++
}
}
return count, nil
}
func (m *ColorMapping) LoadVFSColors(filename string) (int, error) {
buffer, err := public.Files.ReadFile(filename)
if err != nil {
return 0, err
}
log.WithFields(logrus.Fields{"size": len(buffer),
"filename": filename,
}).Info("Loading colors")
return m.LoadBytes(buffer)
}
func NewColorMapping() *ColorMapping {
data, err := public.Files.ReadFile("pics/unifieddyes_palette_extended.png")
if err != nil {
panic(err)
}
extendedpalette, err := NewPalette(data)
if err != nil {
panic(err)
}
data, err = public.Files.ReadFile("extended_palette.txt")
if err != nil {
panic(err)
}
scanner := bufio.NewScanner(bytes.NewReader(data))
extendedpaletteblock := make(map[string]bool)
if err != nil {
panic(err)
}
for scanner.Scan() {
txt := strings.Trim(scanner.Text(), " ")
if len(txt) == 0 {
//empty
continue
}
extendedpaletteblock[txt] = true
}
return &ColorMapping{
colors: make(map[string]*color.RGBA),
extendedpaletteblock: extendedpaletteblock,
extendedpalette: extendedpalette,
}
}

View File

@ -0,0 +1,38 @@
package colormapping
import (
"testing"
)
func TestNewMapping(t *testing.T) {
m := NewColorMapping()
_, err := m.LoadVFSColors("colors/vanessa.txt")
if err != nil {
t.Fatal(err)
}
_, err = m.LoadVFSColors("colors/scifi_nodes.txt")
if err != nil {
t.Fatal(err)
}
c := m.GetColor("scifi_nodes:blacktile2", 0)
if c == nil {
panic("no color")
}
c = m.GetColor("default:river_water_flowing", 0)
if c == nil {
panic("no color")
}
c = m.GetColor("unifiedbricks:brickblock_multicolor_dark", 100)
if c == nil {
panic("no color")
}
//if c.A != 128 {
// panic("wrong alpha")
//}
}

11
colormapping/logger.go Normal file
View File

@ -0,0 +1,11 @@
package colormapping
import (
"github.com/sirupsen/logrus"
)
var log *logrus.Entry
func init() {
log = logrus.WithFields(logrus.Fields{"prefix": "colormapping"})
}

45
colormapping/palette.go Normal file
View File

@ -0,0 +1,45 @@
package colormapping
import (
"bytes"
"image/color"
"image/png"
)
type Palette struct {
colors map[int]*color.RGBA
}
func NewPalette(imagefile []byte) (*Palette, error) {
palette := &Palette{
colors: make(map[int]*color.RGBA),
}
reader := bytes.NewReader(imagefile)
img, err := png.Decode(reader)
if err != nil {
return nil, err
}
bounds := img.Bounds()
index := 0
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
for x := bounds.Min.X; x < bounds.Max.X; x++ {
c := img.At(x, y)
r, g, b, a := c.RGBA()
//fmt.Println("x ", x, " y ", y, " Index: ", index, " Color ", c)
palette.colors[index] = &color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)}
index++
}
}
return palette, nil
}
func (m *Palette) GetColor(param2 int) *color.RGBA {
return m.colors[param2]
}

View File

@ -0,0 +1,30 @@
package colormapping
import (
"fmt"
"io/ioutil"
"testing"
)
func TestNewPalette(t *testing.T) {
data, err := ioutil.ReadFile("./testdata/unifieddyes_palette_extended.png")
if err != nil {
t.Fatal(err)
}
palette, err := NewPalette(data)
if err != nil {
t.Fatal(err)
}
color := palette.GetColor(0)
if color == nil {
t.Fatal("color not found!")
}
fmt.Println(color)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

View File

@ -1,8 +1,6 @@
package coords
import "mapserver/types"
// https://bitbucket.org/s_l_teichmann/mtsatellite/src/e1bf980a2b278c570b3f44f9452c9c087558acb3/common/coords.go?at=default&fileviewer=file-view-default
//https://bitbucket.org/s_l_teichmann/mtsatellite/src/e1bf980a2b278c570b3f44f9452c9c087558acb3/common/coords.go?at=default&fileviewer=file-view-default
const (
numBitsPerComponent = 12
modulo = 1 << numBitsPerComponent
@ -13,7 +11,7 @@ const (
MinPlainCoord = -34351347711
)
func CoordToPlain(c *types.MapBlockCoords) int64 {
func CoordToPlain(c *MapBlockCoords) int64 {
return int64(c.Z)<<(2*numBitsPerComponent) +
int64(c.Y)<<numBitsPerComponent +
int64(c.X)
@ -35,8 +33,8 @@ func pythonModulo(i int16) int16 {
return modulo - -i&mask
}
func PlainToCoord(i int64) *types.MapBlockCoords {
c := types.MapBlockCoords{}
func PlainToCoord(i int64) *MapBlockCoords {
c := MapBlockCoords{}
c.X = unsignedToSigned(pythonModulo(int16(i)))
i = (i - int64(c.X)) >> numBitsPerComponent
c.Y = unsignedToSigned(pythonModulo(int16(i)))

View File

@ -1,7 +1,6 @@
package coords
import (
"mapserver/types"
"testing"
"github.com/sirupsen/logrus"
@ -14,7 +13,7 @@ func init() {
}
func TestMinCoord(t *testing.T) {
c := types.NewMapBlockCoords(types.MinCoord, types.MinCoord, types.MinCoord)
c := NewMapBlockCoords(MinCoord, MinCoord, MinCoord)
pc := CoordToPlain(c)
log.WithFields(logrus.Fields{"coords": c, "plain": pc, "plain-1": pc - 1}).Info("TestMinCoord")
@ -23,7 +22,7 @@ func TestMinCoord(t *testing.T) {
}
}
func testCoordConvert(t *testing.T, mb *types.MapBlockCoords) {
func testCoordConvert(t *testing.T, mb *MapBlockCoords) {
log.WithFields(logrus.Fields{"coords": mb}).Info("MapblockCoords")
p := CoordToPlain(mb)
@ -46,6 +45,6 @@ func testCoordConvert(t *testing.T, mb *types.MapBlockCoords) {
}
func TestZeroCoord(t *testing.T) {
testCoordConvert(t, types.NewMapBlockCoords(0, 0, 0))
func TestZeorCoord(t *testing.T) {
testCoordConvert(t, NewMapBlockCoords(0, 0, 0))
}

View File

@ -1,4 +1,4 @@
package types
package coords
import (
"math"

View File

@ -1,24 +1,23 @@
package coords
import (
"mapserver/types"
"testing"
)
func TestNewMapBlockCoordsFromBlock(t *testing.T) {
c := types.NewMapBlockCoordsFromBlock(1, 1, 1)
c := NewMapBlockCoordsFromBlock(1, 1, 1)
if c.X != 0 || c.Y != 0 || c.Z != 0 {
t.Fatal("mismatch", c)
}
c = types.NewMapBlockCoordsFromBlock(16, 1, 1)
c = NewMapBlockCoordsFromBlock(16, 1, 1)
if c.X != 1 || c.Y != 0 || c.Z != 0 {
t.Fatal("mismatch", c)
}
c = types.NewMapBlockCoordsFromBlock(16, 1, -1)
c = NewMapBlockCoordsFromBlock(16, 1, -1)
if c.X != 1 || c.Y != 0 || c.Z != -1 {
t.Fatal("mismatch", c)

View File

@ -1,7 +1,7 @@
package coords
import (
"mapserver/types"
"mapserver/layer"
"math"
)
@ -9,10 +9,10 @@ const (
MAX_ZOOM = 13
)
func GetTileCoordsFromMapBlock(mbc *types.MapBlockCoords, layers []*types.Layer) *TileCoords {
func GetTileCoordsFromMapBlock(mbc *MapBlockCoords, layers []*layer.Layer) *TileCoords {
tc := TileCoords{X: mbc.X, Y: (mbc.Z + 1) * -1, Zoom: MAX_ZOOM}
currentLayer := types.FindLayerByY(layers, mbc.Y)
currentLayer := layer.FindLayerByY(layers, mbc.Y)
if currentLayer == nil {
return nil
@ -23,7 +23,7 @@ func GetTileCoordsFromMapBlock(mbc *types.MapBlockCoords, layers []*types.Layer)
return &tc
}
func GetMapBlockRangeFromTile(tc *TileCoords, y int) *types.MapBlockRange {
func GetMapBlockRangeFromTile(tc *TileCoords, y int) *MapBlockRange {
scaleDiff := float64(MAX_ZOOM - tc.Zoom)
scale := int(math.Pow(2, scaleDiff))
@ -33,8 +33,8 @@ func GetMapBlockRangeFromTile(tc *TileCoords, y int) *types.MapBlockRange {
mapBlockX2 := mapBlockX1 + scale - 1
mapBlockZ2 := (mapBlockZ1 + ((scale - 1) * -1))
return &types.MapBlockRange{
Pos1: types.NewMapBlockCoords(mapBlockX1, y, mapBlockZ1),
Pos2: types.NewMapBlockCoords(mapBlockX2, y, mapBlockZ2),
return &MapBlockRange{
Pos1: NewMapBlockCoords(mapBlockX1, y, mapBlockZ1),
Pos2: NewMapBlockCoords(mapBlockX2, y, mapBlockZ2),
}
}

View File

@ -1,16 +1,15 @@
package coords
import (
"mapserver/types"
"testing"
"github.com/stretchr/testify/assert"
"mapserver/layer"
"testing"
)
func TestConvertMapblockToTile1(t *testing.T) {
mbc := types.NewMapBlockCoords(0, 0, 0)
layers := []*types.Layer{
{
mbc := NewMapBlockCoords(0, 0, 0)
layers := []*layer.Layer{
&layer.Layer{
Id: 0,
Name: "Base",
From: -16,
@ -48,9 +47,9 @@ func TestGetMapBlockRangeFromTile(t *testing.T) {
}
func TestConvertMapblockToTile2(t *testing.T) {
mbc := types.NewMapBlockCoords(1, 0, 1)
layers := []*types.Layer{
{
mbc := NewMapBlockCoords(1, 0, 1)
layers := []*layer.Layer{
&layer.Layer{
Id: 0,
Name: "Base",
From: -16,
@ -74,9 +73,9 @@ func TestConvertMapblockToTile2(t *testing.T) {
}
func TestConvertMapblockToTile3(t *testing.T) {
mbc := types.NewMapBlockCoords(-1, 0, -1)
layers := []*types.Layer{
{
mbc := NewMapBlockCoords(-1, 0, -1)
layers := []*layer.Layer{
&layer.Layer{
Id: 0,
Name: "Base",
From: -16,

View File

@ -1,12 +1,13 @@
package db
import (
"mapserver/coords"
"mapserver/layer"
"mapserver/settings"
"mapserver/types"
)
type Block struct {
Pos *types.MapBlockCoords
Pos *coords.MapBlockCoords
Data []byte
Mtime int64
}
@ -24,6 +25,6 @@ type DBAccessor interface {
GetTimestamp() (int64, error)
FindBlocksByMtime(gtmtime int64, limit int) ([]*Block, error)
FindNextInitialBlocks(s settings.Settings, layers []*types.Layer, limit int) (*InitialBlocksResult, error)
GetBlock(pos *types.MapBlockCoords) (*Block, error)
FindNextInitialBlocks(s settings.Settings, layers []*layer.Layer, limit int) (*InitialBlocksResult, error)
GetBlock(pos *coords.MapBlockCoords) (*Block, error)
}

View File

@ -3,8 +3,8 @@ package postgres
import (
"mapserver/coords"
"mapserver/db"
"mapserver/layer"
"mapserver/settings"
"mapserver/types"
"math"
"github.com/sirupsen/logrus"
@ -16,8 +16,8 @@ const (
SETTING_LAST_Y_BLOCK = "last_y_block"
)
func (a *PostgresAccessor) countBlocks(x1, y1, z1, x2, y2, z2 int) (int, error) {
rows, err := a.db.Query(getBlockCountByInitialTileQuery,
func (this *PostgresAccessor) countBlocks(x1, y1, z1, x2, y2, z2 int) (int, error) {
rows, err := this.db.Query(getBlockCountByInitialTileQuery,
x1, y1, z1, x2, y2, z2,
)
@ -27,7 +27,7 @@ func (a *PostgresAccessor) countBlocks(x1, y1, z1, x2, y2, z2 int) (int, error)
defer rows.Close()
if rows.Next() {
for rows.Next() {
var count int
err = rows.Scan(&count)
@ -53,7 +53,7 @@ func (a *PostgresAccessor) countBlocks(x1, y1, z1, x2, y2, z2 int) (int, error)
//Zoom 9:
//10 mapblocks height * 16 * 16 == 2560
func (a *PostgresAccessor) FindNextInitialBlocks(s settings.Settings, layers []*types.Layer, limit int) (*db.InitialBlocksResult, error) {
func (this *PostgresAccessor) FindNextInitialBlocks(s settings.Settings, layers []*layer.Layer, limit int) (*db.InitialBlocksResult, error) {
lastlayer := s.GetInt(SETTING_LAST_LAYER, 0)
lastxblock := s.GetInt(SETTING_LAST_X_BLOCK, -129)
@ -88,7 +88,7 @@ func (a *PostgresAccessor) FindNextInitialBlocks(s settings.Settings, layers []*
}
tc := coords.NewTileCoords(lastxblock, lastyblock, 9, lastlayer)
currentlayer := types.FindLayerById(layers, lastlayer)
currentlayer := layer.FindLayerById(layers, lastlayer)
tcr := coords.GetMapBlockRangeFromTile(tc, 0)
tcr.Pos1.Y = currentlayer.From
@ -111,7 +111,7 @@ func (a *PostgresAccessor) FindNextInitialBlocks(s settings.Settings, layers []*
if lastxblock <= -128 {
//first x entry, check z stride
stridecount := a.intQuery(`
stridecount := this.intQuery(`
select count(*) from blocks
where posz >= $1 and posz <= $2
and posy >= $3 and posy <= $4`,
@ -139,7 +139,7 @@ func (a *PostgresAccessor) FindNextInitialBlocks(s settings.Settings, layers []*
}
}
count, err := a.countBlocks(minX, minY, minZ, maxX, maxY, maxZ)
count, err := this.countBlocks(minX, minY, minZ, maxX, maxY, maxZ)
if err != nil {
return nil, err
@ -150,7 +150,7 @@ func (a *PostgresAccessor) FindNextInitialBlocks(s settings.Settings, layers []*
if count > 0 {
rows, err := a.db.Query(getBlocksByInitialTileQuery,
rows, err := this.db.Query(getBlocksByInitialTileQuery,
minX, minY, minZ, maxX, maxY, maxZ,
)

View File

@ -2,9 +2,9 @@ package postgres
import (
"database/sql"
"embed"
"mapserver/coords"
"mapserver/db"
"mapserver/types"
"mapserver/public"
"time"
_ "github.com/lib/pq"
@ -15,9 +15,6 @@ type PostgresAccessor struct {
db *sql.DB
}
//go:embed migrations/*.sql
var migrations embed.FS
func (db *PostgresAccessor) Migrate() error {
hasMtime := true
_, err := db.db.Query("select max(mtime) from blocks")
@ -29,7 +26,7 @@ func (db *PostgresAccessor) Migrate() error {
log.Info("Migrating database, this might take a while depending on the mapblock-count")
start := time.Now()
sql, err := migrations.ReadFile("migrations/postgres_mapdb_migrate.sql")
sql, err := public.Files.ReadFile("sql/postgres_mapdb_migrate.sql")
if err != nil {
return err
}
@ -47,14 +44,14 @@ func (db *PostgresAccessor) Migrate() error {
}
func convertRows(posx, posy, posz int, data []byte, mtime int64) *db.Block {
c := types.NewMapBlockCoords(posx, posy, posz)
c := coords.NewMapBlockCoords(posx, posy, posz)
return &db.Block{Pos: c, Data: data, Mtime: mtime}
}
func (a *PostgresAccessor) FindBlocksByMtime(gtmtime int64, limit int) ([]*db.Block, error) {
func (this *PostgresAccessor) FindBlocksByMtime(gtmtime int64, limit int) ([]*db.Block, error) {
blocks := make([]*db.Block, 0)
rows, err := a.db.Query(getBlocksByMtimeQuery, gtmtime, limit)
rows, err := this.db.Query(getBlocksByMtimeQuery, gtmtime, limit)
if err != nil {
return nil, err
}
@ -78,8 +75,8 @@ func (a *PostgresAccessor) FindBlocksByMtime(gtmtime int64, limit int) ([]*db.Bl
return blocks, nil
}
func (a *PostgresAccessor) CountBlocks(frommtime, tomtime int64) (int, error) {
rows, err := a.db.Query(countBlocksQuery, frommtime, tomtime)
func (this *PostgresAccessor) CountBlocks(frommtime, tomtime int64) (int, error) {
rows, err := this.db.Query(countBlocksQuery, frommtime, tomtime)
if err != nil {
panic(err)
}
@ -100,8 +97,8 @@ func (a *PostgresAccessor) CountBlocks(frommtime, tomtime int64) (int, error) {
return 0, nil
}
func (a *PostgresAccessor) GetTimestamp() (int64, error) {
rows, err := a.db.Query(getTimestampQuery)
func (db *PostgresAccessor) GetTimestamp() (int64, error) {
rows, err := db.db.Query(getTimestampQuery)
if err != nil {
return 0, err
}
@ -122,8 +119,8 @@ func (a *PostgresAccessor) GetTimestamp() (int64, error) {
return 0, nil
}
func (a *PostgresAccessor) GetBlock(pos *types.MapBlockCoords) (*db.Block, error) {
rows, err := a.db.Query(getBlockQuery, pos.X, pos.Y, pos.Z)
func (this *PostgresAccessor) GetBlock(pos *coords.MapBlockCoords) (*db.Block, error) {
rows, err := this.db.Query(getBlockQuery, pos.X, pos.Y, pos.Z)
if err != nil {
return nil, err
}

View File

@ -1,7 +1,7 @@
package postgres
func (a *PostgresAccessor) intQuery(q string, params ...interface{}) int {
rows, err := a.db.Query(q, params...)
func (this *PostgresAccessor) intQuery(q string, params ...interface{}) int {
rows, err := this.db.Query(q, params...)
if err != nil {
panic(err)
}

View File

@ -3,8 +3,10 @@ package sqlite
import (
"mapserver/coords"
"mapserver/db"
"mapserver/layer"
"mapserver/settings"
"mapserver/types"
_ "modernc.org/sqlite"
)
const (
@ -21,7 +23,7 @@ order by b.pos asc, b.mtime asc
limit ?
`
func (a *Sqlite3Accessor) FindNextInitialBlocks(s settings.Settings, layers []*types.Layer, limit int) (*db.InitialBlocksResult, error) {
func (this *Sqlite3Accessor) FindNextInitialBlocks(s settings.Settings, layers []*layer.Layer, limit int) (*db.InitialBlocksResult, error) {
result := &db.InitialBlocksResult{}
blocks := make([]*db.Block, 0)
@ -31,7 +33,7 @@ func (a *Sqlite3Accessor) FindNextInitialBlocks(s settings.Settings, layers []*t
totallegacycount := s.GetInt64(SETTING_TOTAL_LEGACY_COUNT, -1)
if totallegacycount == -1 {
//Query from db
totallegacycount, err := a.CountBlocks()
totallegacycount, err := this.CountBlocks()
if err != nil {
panic(err)
@ -40,7 +42,7 @@ func (a *Sqlite3Accessor) FindNextInitialBlocks(s settings.Settings, layers []*t
s.SetInt64(SETTING_TOTAL_LEGACY_COUNT, int64(totallegacycount))
}
rows, err := a.db.Query(getLastBlockQuery, lastpos, limit)
rows, err := this.db.Query(getLastBlockQuery, lastpos, limit)
if err != nil {
return nil, err
}
@ -70,7 +72,7 @@ func (a *Sqlite3Accessor) FindNextInitialBlocks(s settings.Settings, layers []*t
lastpos = pos
blockcoordy := mb.Pos.Y
currentlayer := types.FindLayerByY(layers, blockcoordy)
currentlayer := layer.FindLayerByY(layers, blockcoordy)
if currentlayer != nil {
blocks = append(blocks, mb)

View File

@ -2,11 +2,10 @@ package sqlite
import (
"database/sql"
"embed"
"errors"
"mapserver/coords"
"mapserver/db"
"mapserver/types"
"mapserver/public"
"time"
"github.com/sirupsen/logrus"
@ -23,13 +22,10 @@ type Sqlite3Accessor struct {
filename string
}
//go:embed migrations/*.sql
var migrations embed.FS
func (db *Sqlite3Accessor) Migrate() error {
//RW connection
rwdb, err := sql.Open("sqlite", db.filename+"?mode=rw")
rwdb, err := sql.Open("sqlite", "file:"+db.filename+"?mode=rw")
if err != nil {
return err
}
@ -48,7 +44,7 @@ func (db *Sqlite3Accessor) Migrate() error {
}).Info("Migrating database, this might take a while depending on the mapblock-count")
start := time.Now()
sql, err := migrations.ReadFile("migrations/sqlite_mapdb_migrate.sql")
sql, err := public.Files.ReadFile("sql/sqlite_mapdb_migrate.sql")
if err != nil {
return err
}
@ -141,7 +137,7 @@ func (db *Sqlite3Accessor) GetTimestamp() (int64, error) {
return 0, nil
}
func (db *Sqlite3Accessor) GetBlock(pos *types.MapBlockCoords) (*db.Block, error) {
func (db *Sqlite3Accessor) GetBlock(pos *coords.MapBlockCoords) (*db.Block, error) {
ppos := coords.CoordToPlain(pos)
rows, err := db.db.Query(getBlockQuery, ppos)
@ -169,37 +165,21 @@ func (db *Sqlite3Accessor) GetBlock(pos *types.MapBlockCoords) (*db.Block, error
}
func New(filename string) (*Sqlite3Accessor, error) {
db, err := sql.Open("sqlite", filename+"?mode=ro")
db, err := sql.Open("sqlite", "file:"+filename)
if err != nil {
return nil, err
}
// sqlite connection limit
db.SetMaxOpenConns(1)
err = EnableWAL(db)
_, err = db.Exec("pragma busy_timeout = 5000;")
if err != nil {
return nil, err
}
_, err = db.Exec("pragma journal_mode = wal;")
if err != nil {
return nil, errors.New("could not set db to wal-mode, please stop the minetest-server to allow this one-time fixup")
}
sq := &Sqlite3Accessor{db: db, filename: filename}
return sq, nil
}
func EnableWAL(db *sql.DB) error {
result := db.QueryRow("pragma journal_mode;")
var mode string
err := result.Scan(&mode)
if err != nil {
return err
}
if mode != "wal" {
_, err = db.Exec("pragma journal_mode = wal;")
if err != nil {
return errors.New("couldn't switch the db-journal to wal-mode, please stop the minetest-engine to allow doing this or do it manually: " + err.Error())
}
}
return nil
}

View File

@ -2,8 +2,8 @@ package sqlite
import (
"io/ioutil"
"mapserver/coords"
"mapserver/testutils"
"mapserver/types"
"os"
"testing"
@ -11,7 +11,7 @@ import (
)
func TestMigrateEmpty(t *testing.T) {
tmpfile, err := os.CreateTemp("", "TestMigrateEmpty.*.sqlite")
tmpfile, err := ioutil.TempFile("", "TestMigrateEmpty.*.sqlite")
if err != nil {
panic(err)
}
@ -64,7 +64,7 @@ func TestMigrateAndQuery(t *testing.T) {
panic(err)
}
block, err := a.GetBlock(types.NewMapBlockCoords(0, 0, 0))
block, err := a.GetBlock(coords.NewMapBlockCoords(0, 0, 0))
if err != nil {
panic(err)

View File

@ -59,26 +59,16 @@
"trainsignal": true,
"minecart": false,
"locator": false,
"signs": true,
"mapserver_airutils": true,
"phonograph": true,
"um_area_forsale": true
"signs": true
},
"mapblockaccessor": {
"expiretime": "15s",
"purgetime": "30s",
"maxitems": 0
"maxitems": 500
},
"defaultoverlays": [
"mapserver_poi",
"mapserver_label",
"mapserver_player"
],
"skins": {
"enableskinsdb": false,
"skinspath": ""
},
"worldpath": "./",
"datapath": "./",
"colorstxtpath": "./"
]
}

View File

@ -1,17 +0,0 @@
gameid = minetest
creative_mode = true
enable_damage = true
auth_backend = postgresql
pgsql_auth_connection = host=postgres user=postgres password=enter dbname=postgres
player_backend = postgresql
pgsql_player_connection = host=postgres port=5432 user=postgres password=enter dbname=postgres
backend = postgresql
pgsql_connection = host=postgres port=5432 user=postgres password=enter dbname=postgres
mod_storage_backend = postgresql
pgsql_mod_storage_connection = host=postgres user=postgres password=enter dbname=postgres
pgsql_mapserver_connection = host=postgres port=5432 user=postgres password=enter dbname=postgres

@ -1 +1 @@
Subproject commit 1ab5ddd6ba9ac205814f8cc2bb181a212d74ab82
Subproject commit ad4e151184bc4abb3087b8fd45377accc88c0114

BIN
doc/Overview.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

1
doc/Overview.xml Normal file
View File

@ -0,0 +1 @@
<mxfile modified="2019-02-07T21:27:44.686Z" host="www.draw.io" agent="Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:65.0) Gecko/20100101 Firefox/65.0" etag="tnhgfPkYZ02dah6ygGXB" version="10.1.9" type="device"><diagram name="Page-1" id="5f0bae14-7c28-e335-631c-24af17079c00">7Vpbc9soFP41ntl9SEcXS3Eec2na6bRJZ5Nu2qcdLGGZBgkv4Njur1+QQEICOZc6irMTPyTigED6zne+c8Aehaf5+gMFi/kXkkI8Crx0PQrPRkHgj4NY/JOWTWU5PIwqQ0ZRqgY1hiv0Cyqjp6xLlELWGsgJwRwt2saEFAVMeMsGKCWr9rAZwe1VFyCDluEqAdi23qCUz5XV97ym4yNE2VwtPYlUxxQktxkly0KtNwrCWfmpunOg51Lj2RykZGWYwvej8JQSwqurfH0KscRWw1bdd97TWz83hQV/yA3hkR95cDKezPxoMvaSA+WnO4CXCosvYMEgvYNUPTHfaJTEwy/kZULyBSnKFU8ARlkhbBjOZJMtQIKK7HPZOgtjYSrRgXJ9Tw7QAMiGmAgl6hqDKcQnNZynBBMqugqxkLyNU3ILtVGg7JWfukd7zReWGcLYGKn8Ieyk4OcgR1iS9G9IU1AAZVaM9APVdi005zlWK9ioK0cI1DhcGyblhQ+Q5JDTjRiieoOJYsSm0141/Btrls0N6sXKBhTls3rqxu3iQnnezQJ2sYnB9fdvny6P0OX8LvdvLvhBYDHh6l+MOOylQQo4YJxQ6Z/VXIy8Es6XHSshEi7ALHQcGPYC5kdtwOrYNACLh8QrdEWOMJwJWKaAOXBboRyDks4GNIwDqvkXlDwjFP0SHAR6RCIbqID0elPizimEO8I0aGMa2ZAGYwem/rOB6tt6lIPFO+Zmonhz3kXT1AklHqYgKJOWrUQgJZQuPJE4IpEQjlVHjtIU9zG7LWkPckQ/hXq9M+4QPnAohMM5wXP5ZtxD+MvpT5mTTeZ7f1wjLBK6fJYY5BKz6m+Zw/98BaERTqLdh4Za7S8BFygyDI3ljp62XNfZAAs6F4DDE0lRZvm8ftGn08CO0IHzRD85+715r84Nmjp8O5RyXXX9X7Vuu4P2TetiW+uEzHDI+CvQrjjat7R+aMNJ0l7BWFCSQMbul4tm93W55BgV8LdlJN4KbKdcGtu4+oOW7L5N01pH/skdCL92EdnunsN2DvX9FxaRieWdb2zLtnqZ4+OEExPcz3JT/JUwxBGRIE8J5yTv3y2b292ugzjpRA+pYua0PlN5sG/ukZ9Oth3Hth/CIcPkyPLDiTwycrli77S8WxiOHdvemsED7dHskwJR5WMpLCm6E5eZvPx0dXmhzWIZo8cxWHBwhjLdMaXdod0J9uNEosNz1xHOsGWlfSTRlJU/mVCQV5wP7vFFp4AMHTXPoNrv2yWPhT4s0mN5eC1hxIAxeRZq+gKuEf8uMXoXRKr5w+g6Wyv8ysZGNwrx+NVdh5Fu/zA7m/vK1qblBZhaJ+XWKScjS5rALS+v3l3IZga51jHXwbPtT8NfrlJK2yjEgKO79qNu2XJ/JajgBl38Nl3qlKWnqF5R3RUY5+ndieJOqT3pTFRhYE20q824b9cYH6+vv+5poFPCgapkDqJwR9VGJ/Lr0uKlIl9P/OjIL8uM7YLQxHYrtP1nCe2+74rMsH7MVv8ttB/HI/2d0jPwqE4sT8orwUvllfAtrwxFPleN/8TyxTc41jDOzbIdkkVvU97Y8vxssTceL53y3BLnDUW+o33nXui1KVP/1uCx3As7h831AcVQ3LO/S6kq4PMbOGUkuYWcWWTcj3J49PvVb9Td9zrO2nZU/Ypm8zulynvNj8HC9/8B</diagram></mxfile>

View File

@ -15,7 +15,7 @@ Ubuntu install: https://github.com/golang/go/wiki/Ubuntu
Generate the js bundle for the frontend:
```
cd public
cd public/js
rollup -c rollup.config.js
```

View File

@ -14,6 +14,8 @@ scifi_nodes:slope_vent 120 120 120
scifi_nodes:white2 240 240 240
```
Default colors, see: [colors.txt](../server/static/colors.txt)
## Configuration json
All config options reside in the `mapserver.json` file with the default values
@ -61,11 +63,7 @@ The mapserver will generate a fresh `mapserver.json` if there is none at startup
"expiretime": "10s",
"purgetime": "15s",
"maxitems": 5000
},
"skins": {
"enableskinsdb": true,
"skinspath": "/path/to/minetest/mods/skinsdb/textures"
}
}
}
```
@ -121,11 +119,3 @@ Enables the [Prometheus](./prometheus.md) metrics endpoint
#### mapblockaccessor.maxitems
Number of mapblocks to keep in memory, dial this down if you have memory issues
#### skins.enableskinsdb
Enables support for serving/displaying custom player skins provided by the SkinsDB mod.
#### skins.skinspath
The path to where SkinsDB textures are stored. This should be the SkinsDB textures directory.
Example: `/path/to/minetest/mods/skinsdb/textures`

View File

@ -1,37 +1,58 @@
# System overview
<img src="./Overview.png">
# Build dependencies
* docker
* docker-compose
* go >= 1.16
* nodejs >= v17.4.0
* npm >= 8.3.0
# Create the frontend bundle
```bash
docker-compose up mapserver_frontend
cd public
npm ci
npm run bundle
```
# Development setup (sqlite)
# Development setup
```bash
# start the engine in the first window/shell
docker-compose up minetest
# and the mapserver in another
docker-compose up mapserver
Working directory: `./server`
## Preparing the files and map
Copy your `map.sqlite` into the working directory if you want to test with
a sqlite map database
### world.mt
You need a `world.mt` too in order to make the connection to the database.
In the sqlite case:
```
gameid = minetest
backend = sqlite3
creative_mode = false
enable_damage = false
player_backend = files
```
# Development setup (postgres)
```bash
# start postgres in the background
docker-compose -f docker-compose.yml -f docker-compose.postgres.yml up -d postgres
# start the engine in the first window/shell
docker-compose -f docker-compose.yml -f docker-compose.postgres.yml up minetest
# and the mapserver in another
docker-compose -f docker-compose.yml -f docker-compose.postgres.yml up mapserver
For postgres:
```
gameid = minetest
backend = postgresql
creative_mode = true
enable_damage = true
player_backend = postgresql
pgsql_connection = host=localhost port=5432 user=postgres password=enter dbname=postgres
pgsql_player_connection = host=localhost port=5432 user=postgres password=enter dbname=postgres
```
Utilities:
```sh
# psql
docker-compose -f docker-compose.yml -f docker-compose.postgres.yml exec postgres psql -U postgres
```
## Running the server
* Create a `mapserver.json` with `go run . -createconfig`
* Change the value `webdev` in the `mapserver.json` to `true`
* Start the server with `go run .` or with debug output: `go run . -debug`
* The web files in `public/` can now be changed on the fly without restarting the server

View File

@ -14,10 +14,12 @@ For additional infos (lag,time,players => active mode) on the mapserver interfac
## Docker image
* Docker-hub: https://hub.docker.com/repository/docker/minetestmapserver/mapserver
Simple docker run example to run in the world-directory:
```
docker run --rm --it -p 8080:8080 -v $(pwd):/minetest -w /minetest ghcr.io/minetest-mapserver/mapserver
docker run --rm --it -p 8080:8080 -v $(pwd):/minetest -w /minetest minetestmapserver/mapserver
```
## Docker compose
@ -27,7 +29,7 @@ Examplary `docker-compose` config:
```yml
services:
mapserver:
image: ghcr.io/minetest-mapserver/mapserver
image: minetesttools/mapserver
restart: always
networks:
- default

View File

@ -72,11 +72,3 @@
* unifieddyes_palette_extended.png
* GPL 2.0
* Source: https://gitlab.com/VanessaE/unifieddyes
* phonograph_node_temp.png
* License: CC By-SA 4.0
* Source: [phonograph](https://github.com/C-C-Minetest-Server/phonograph/)
* um_area_forsale_sign_alpha.png
* By Gabriel Pérez-Cerezo; AGPL 3.0
* Modified from https://github.com/C-C-Minetest-Server/um_area_forsale/blob/main/textures/um_area_forsale_sign.png

View File

@ -8,7 +8,6 @@ you get more realtime-data from within your minetest-world:
* Current players with their positions
* Current time and max lag
* Planes using the [Airutils library](https://github.com/APercy/airutils) by APercy, if installed
You can use the `mapserver-mod` either passive or active:
* *Passive* Makes some additional markers available (POI, Labels, etc)

View File

@ -11,7 +11,7 @@ but it will be in the region of several gigabytes (5 to 10 GB for "older" server
## Memory
Memory depends on the amount of caching (see: [Configuration](./config.md))
Memory depedends on the amount of caching (see: [Configuration](./config.md))
Per default there will be around 500 mapblocks cached for quicker access.
This will be around 5 to 10 megabytes depending on the contents.

View File

@ -1,21 +0,0 @@
version: "3.6"
services:
postgres:
image: postgres:16.3
restart: always
environment:
POSTGRES_PASSWORD: enter
volumes:
- "pg_data:/var/lib/postgresql/data"
mapserver:
volumes:
- "./dev/world.postgres.mt:/data/world/world.mt"
minetest:
volumes:
- "./dev/world.postgres.mt:/root/.minetest/worlds/world/world.mt"
volumes:
pg_data: {}

View File

@ -2,23 +2,21 @@ version: "3.6"
services:
mapserver_frontend:
image: node:21.7.3-alpine
image: node:alpine3.13
volumes:
- "dev_home:/root"
- ".:/data"
working_dir: /data/public
command: ["npm", "ci"]
command: ["npm", "i"]
mapserver:
image: golang:1.22.4
image: golang:1.17.8
depends_on:
- minetest
- mapserver_frontend
volumes:
- "dev_home:/root"
- "world_data:/data/world"
- "go_dir:/go"
- "go_cache:/.cache"
- ".:/data"
- "./public:/data/world/public"
- "./dev/mapserver.json:/data/world/mapserver.json"
@ -28,7 +26,7 @@ services:
command: ["go", "run", ".."]
minetest:
image: registry.gitlab.com/minetest/minetest/server:5.7.0
image: registry.gitlab.com/minetest/minetest/server:5.5.0
user: root
volumes:
- "world_data:/root/.minetest/worlds/world"
@ -40,6 +38,4 @@ services:
volumes:
world_data: {}
dev_home: {}
go_dir: {}
go_cache: {}
dev_home: {}

55
go.mod
View File

@ -1,52 +1,15 @@
module mapserver
require (
github.com/golang-migrate/migrate/v4 v4.17.1
github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.3
github.com/lib/pq v1.10.9
github.com/minetest-go/areasparser v1.0.5
github.com/minetest-go/colormapping v1.0.5
github.com/minetest-go/mapparser v0.1.9
github.com/gorilla/websocket v1.5.0
github.com/lib/pq v1.10.2
github.com/minetest-go/mapparser v0.1.1
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/prometheus/client_golang v1.19.1
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.9.0
github.com/yuin/gopher-lua v1.1.1
modernc.org/sqlite v1.30.1
github.com/prometheus/client_golang v1.12.1
github.com/sirupsen/logrus v1.8.1
github.com/stretchr/testify v1.7.1
github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9
modernc.org/sqlite v1.14.8
)
require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/klauspost/compress v1.16.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v1.14.16 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.48.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
go.uber.org/atomic v1.7.0 // indirect
golang.org/x/net v0.23.0 // indirect
golang.org/x/sys v0.19.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
modernc.org/libc v1.52.1 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.8.0 // indirect
modernc.org/strutil v1.2.0 // indirect
modernc.org/token v1.1.0 // indirect
)
go 1.22
toolchain go1.22.4
go 1.16

785
go.sum
View File

@ -1,144 +1,671 @@
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
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/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
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=
github.com/dhui/dktest v0.4.1 h1:/w+IWuDXVymg3IrRJCHHOkMK10m9aNVMOyD0X12YVTg=
github.com/dhui/dktest v0.4.1/go.mod h1:DdOqcUpL7vgyP4GlF3X3w7HbSlz8cEQzwewPveYEQbA=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0=
github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-migrate/migrate/v4 v4.17.1 h1:4zQ6iqL6t6AiItphxJctQb3cFqWiSpMnX7wLTPnnYO4=
github.com/golang-migrate/migrate/v4 v4.17.1/go.mod h1:m8hinFyWBn0SA4QKHuKh175Pm9wjmxj3S2Mia7dbXzM=
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/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
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/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4=
github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/minetest-go/areasparser v1.0.5 h1:kyfb7mk4S7Gvx5N42uJK8ze3BAbfj8uyLsv2Tuy43MQ=
github.com/minetest-go/areasparser v1.0.5/go.mod h1:NvohBk60WBrAbfvgmJccCEblz9I/Ygba4k9V81rwoNc=
github.com/minetest-go/colormapping v1.0.5 h1:axZm0xbOz0RQEIFvZmbxr3kuvebYiG0AAADPr8/ZQfg=
github.com/minetest-go/colormapping v1.0.5/go.mod h1:6UVusIQTqfWbcru5HTktWwB2BCNHUE3W0VkkRBaMfcw=
github.com/minetest-go/mapparser v0.1.9 h1:mGjRwA2twJRyzSrYuJWvyNpEkO469K/Qun327v8rhwE=
github.com/minetest-go/mapparser v0.1.9/go.mod h1:zE+JdqiicINR+kzZ4gS6BBh+vLVPQSwkYiEkG0A1Cys=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw=
github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-sqlite3 v1.14.10 h1:MLn+5bFRlWMGoSRmJour3CL1w/qL96mvipqpwQW/Sfk=
github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/minetest-go/mapparser v0.1.1 h1:Ir7ChKX0lwnyr6Zg/Jd3ipQT1vPCAQYN6GWmQXK020Y=
github.com/minetest-go/mapparser v0.1.1/go.mod h1:Rjv12WQ3Tn9BsOr0ohFguGWFol3vIfgQcTUy5wCACgo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=
github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 h1:k/gmLsJDWwWqbLCur2yWnJzwQEKRcAHXo6seXGuSwWw=
github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/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-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 h1:M8tBwCtWD/cZV9DZpFYRUgaymAYAr+aIUTWzDaM3uPs=
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1 h1:7QnIQpGRHE5RnLKnESfDoxm2dTapTZua5a0kS0A+VXQ=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
modernc.org/cc/v4 v4.21.2 h1:dycHFB/jDc3IyacKipCNSDrjIC0Lm1hyoWOZTRR20Lk=
modernc.org/cc/v4 v4.21.2/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
modernc.org/ccgo/v4 v4.17.10 h1:6wrtRozgrhCxieCeJh85QsxkX/2FFrT9hdaWPlbn4Zo=
modernc.org/ccgo/v4 v4.17.10/go.mod h1:0NBHgsqTTpm9cA5z2ccErvGZmtntSM9qD2kFAs6pjXM=
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI=
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
modernc.org/libc v1.52.1 h1:uau0VoiT5hnR+SpoWekCKbLqm7v6dhRL3hI+NQhgN3M=
modernc.org/libc v1.52.1/go.mod h1:HR4nVzFDSDizP620zcMCgjb1/8xk2lg5p/8yjfGv1IQ=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
modernc.org/sqlite v1.30.1 h1:YFhPVfu2iIgUf9kuA1CR7iiHdcEEsI2i+yjRYHscyxk=
modernc.org/sqlite v1.30.1/go.mod h1:DUmsiWQDaAvU4abhc/N+djlom/L2o8f7gZ95RCvyoLU=
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
lukechampine.com/uint128 v1.1.1 h1:pnxCASz787iMf+02ssImqk6OLt+Z5QHMoZyUXR4z6JU=
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.34.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.4/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.5/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.7/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.8/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.10/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.15/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.20/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/cc/v3 v3.35.22 h1:BzShpwCAP7TWzFppM4k2t03RhXhgYqaibROWkrWq7lE=
modernc.org/cc/v3 v3.35.22/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60=
modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw=
modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI=
modernc.org/ccgo/v3 v3.11.1/go.mod h1:lWHxfsn13L3f7hgGsGlU28D9eUOf6y3ZYHKoPaKU0ag=
modernc.org/ccgo/v3 v3.11.3/go.mod h1:0oHunRBMBiXOKdaglfMlRPBALQqsfrCKXgw9okQ3GEw=
modernc.org/ccgo/v3 v3.12.4/go.mod h1:Bk+m6m2tsooJchP/Yk5ji56cClmN6R1cqc9o/YtbgBQ=
modernc.org/ccgo/v3 v3.12.6/go.mod h1:0Ji3ruvpFPpz+yu+1m0wk68pdr/LENABhTrDkMDWH6c=
modernc.org/ccgo/v3 v3.12.8/go.mod h1:Hq9keM4ZfjCDuDXxaHptpv9N24JhgBZmUG5q60iLgUo=
modernc.org/ccgo/v3 v3.12.11/go.mod h1:0jVcmyDwDKDGWbcrzQ+xwJjbhZruHtouiBEvDfoIsdg=
modernc.org/ccgo/v3 v3.12.14/go.mod h1:GhTu1k0YCpJSuWwtRAEHAol5W7g1/RRfS4/9hc9vF5I=
modernc.org/ccgo/v3 v3.12.18/go.mod h1:jvg/xVdWWmZACSgOiAhpWpwHWylbJaSzayCqNOJKIhs=
modernc.org/ccgo/v3 v3.12.20/go.mod h1:aKEdssiu7gVgSy/jjMastnv/q6wWGRbszbheXgWRHc8=
modernc.org/ccgo/v3 v3.12.21/go.mod h1:ydgg2tEprnyMn159ZO/N4pLBqpL7NOkJ88GT5zNU2dE=
modernc.org/ccgo/v3 v3.12.22/go.mod h1:nyDVFMmMWhMsgQw+5JH6B6o4MnZ+UQNw1pp52XYFPRk=
modernc.org/ccgo/v3 v3.12.25/go.mod h1:UaLyWI26TwyIT4+ZFNjkyTbsPsY3plAEB6E7L/vZV3w=
modernc.org/ccgo/v3 v3.12.29/go.mod h1:FXVjG7YLf9FetsS2OOYcwNhcdOLGt8S9bQ48+OP75cE=
modernc.org/ccgo/v3 v3.12.36/go.mod h1:uP3/Fiezp/Ga8onfvMLpREq+KUjUmYMxXPO8tETHtA8=
modernc.org/ccgo/v3 v3.12.38/go.mod h1:93O0G7baRST1vNj4wnZ49b1kLxt0xCW5Hsa2qRaZPqc=
modernc.org/ccgo/v3 v3.12.43/go.mod h1:k+DqGXd3o7W+inNujK15S5ZYuPoWYLpF5PYougCmthU=
modernc.org/ccgo/v3 v3.12.46/go.mod h1:UZe6EvMSqOxaJ4sznY7b23/k13R8XNlyWsO5bAmSgOE=
modernc.org/ccgo/v3 v3.12.47/go.mod h1:m8d6p0zNps187fhBwzY/ii6gxfjob1VxWb919Nk1HUk=
modernc.org/ccgo/v3 v3.12.50/go.mod h1:bu9YIwtg+HXQxBhsRDE+cJjQRuINuT9PUK4orOco/JI=
modernc.org/ccgo/v3 v3.12.51/go.mod h1:gaIIlx4YpmGO2bLye04/yeblmvWEmE4BBBls4aJXFiE=
modernc.org/ccgo/v3 v3.12.53/go.mod h1:8xWGGTFkdFEWBEsUmi+DBjwu/WLy3SSOrqEmKUjMeEg=
modernc.org/ccgo/v3 v3.12.54/go.mod h1:yANKFTm9llTFVX1FqNKHE0aMcQb1fuPJx6p8AcUx+74=
modernc.org/ccgo/v3 v3.12.55/go.mod h1:rsXiIyJi9psOwiBkplOaHye5L4MOOaCjHg1Fxkj7IeU=
modernc.org/ccgo/v3 v3.12.56/go.mod h1:ljeFks3faDseCkr60JMpeDb2GSO3TKAmrzm7q9YOcMU=
modernc.org/ccgo/v3 v3.12.57/go.mod h1:hNSF4DNVgBl8wYHpMvPqQWDQx8luqxDnNGCMM4NFNMc=
modernc.org/ccgo/v3 v3.12.60/go.mod h1:k/Nn0zdO1xHVWjPYVshDeWKqbRWIfif5dtsIOCUVMqM=
modernc.org/ccgo/v3 v3.12.66/go.mod h1:jUuxlCFZTUZLMV08s7B1ekHX5+LIAurKTTaugUr/EhQ=
modernc.org/ccgo/v3 v3.12.67/go.mod h1:Bll3KwKvGROizP2Xj17GEGOTrlvB1XcVaBrC90ORO84=
modernc.org/ccgo/v3 v3.12.73/go.mod h1:hngkB+nUUqzOf3iqsM48Gf1FZhY599qzVg1iX+BT3cQ=
modernc.org/ccgo/v3 v3.12.81/go.mod h1:p2A1duHoBBg1mFtYvnhAnQyI6vL0uw5PGYLSIgF6rYY=
modernc.org/ccgo/v3 v3.12.84/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w=
modernc.org/ccgo/v3 v3.12.86/go.mod h1:dN7S26DLTgVSni1PVA3KxxHTcykyDurf3OgUzNqTSrU=
modernc.org/ccgo/v3 v3.12.90/go.mod h1:obhSc3CdivCRpYZmrvO88TXlW0NvoSVvdh/ccRjJYko=
modernc.org/ccgo/v3 v3.12.92/go.mod h1:5yDdN7ti9KWPi5bRVWPl8UNhpEAtCjuEE7ayQnzzqHA=
modernc.org/ccgo/v3 v3.13.1/go.mod h1:aBYVOUfIlcSnrsRVU8VRS35y2DIfpgkmVkYZ0tpIXi4=
modernc.org/ccgo/v3 v3.14.0/go.mod h1:hBrkiBlUwvr5vV/ZH9YzXIp982jKE8Ek8tR1ytoAL6Q=
modernc.org/ccgo/v3 v3.15.1 h1:bagyhO7uFlYWedkh6mfIYf8LZGYnVGPYh2FqXisaOV4=
modernc.org/ccgo/v3 v3.15.1/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0=
modernc.org/ccgo/v3 v3.15.9/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0=
modernc.org/ccgo/v3 v3.15.10/go.mod h1:wQKxoFn0ynxMuCLfFD09c8XPUCc8obfchoVR9Cn0fI8=
modernc.org/ccgo/v3 v3.15.12/go.mod h1:VFePOWoCd8uDGRJpq/zfJ29D0EVzMSyID8LCMWYbX6I=
modernc.org/ccgo/v3 v3.15.13 h1:hqlCzNJTXLrhS70y1PqWckrF9x1btSQRC7JFuQcBg5c=
modernc.org/ccgo/v3 v3.15.13/go.mod h1:QHtvdpeODlXjdK3tsbpyK+7U9JV4PQsrPGIbtmc0KfY=
modernc.org/ccgo/v3 v3.15.14 h1:/Pcjoc5mPznDMH3CErDeX4mHLAAQyR5lzr3s2FpqDY0=
modernc.org/ccgo/v3 v3.15.14/go.mod h1:144Sz2iBCKogb9OKwsu7hQEub3EVgOlyI8wMUPGKUXQ=
modernc.org/ccorpus v1.11.1 h1:K0qPfpVG1MJh5BYazccnmhywH4zHuOgJXgbjzyp6dWA=
modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/ccorpus v1.11.4/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q=
modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg=
modernc.org/libc v1.11.2/go.mod h1:ioIyrl3ETkugDO3SGZ+6EOKvlP3zSOycUETe4XM4n8M=
modernc.org/libc v1.11.5/go.mod h1:k3HDCP95A6U111Q5TmG3nAyUcp3kR5YFZTeDS9v8vSU=
modernc.org/libc v1.11.6/go.mod h1:ddqmzR6p5i4jIGK1d/EiSw97LBcE3dK24QEwCFvgNgE=
modernc.org/libc v1.11.11/go.mod h1:lXEp9QOOk4qAYOtL3BmMve99S5Owz7Qyowzvg6LiZso=
modernc.org/libc v1.11.13/go.mod h1:ZYawJWlXIzXy2Pzghaf7YfM8OKacP3eZQI81PDLFdY8=
modernc.org/libc v1.11.16/go.mod h1:+DJquzYi+DMRUtWI1YNxrlQO6TcA5+dRRiq8HWBWRC8=
modernc.org/libc v1.11.19/go.mod h1:e0dgEame6mkydy19KKaVPBeEnyJB4LGNb0bBH1EtQ3I=
modernc.org/libc v1.11.24/go.mod h1:FOSzE0UwookyT1TtCJrRkvsOrX2k38HoInhw+cSCUGk=
modernc.org/libc v1.11.26/go.mod h1:SFjnYi9OSd2W7f4ct622o/PAYqk7KHv6GS8NZULIjKY=
modernc.org/libc v1.11.27/go.mod h1:zmWm6kcFXt/jpzeCgfvUNswM0qke8qVwxqZrnddlDiE=
modernc.org/libc v1.11.28/go.mod h1:Ii4V0fTFcbq3qrv3CNn+OGHAvzqMBvC7dBNyC4vHZlg=
modernc.org/libc v1.11.31/go.mod h1:FpBncUkEAtopRNJj8aRo29qUiyx5AvAlAxzlx9GNaVM=
modernc.org/libc v1.11.34/go.mod h1:+Tzc4hnb1iaX/SKAutJmfzES6awxfU1BPvrrJO0pYLg=
modernc.org/libc v1.11.37/go.mod h1:dCQebOwoO1046yTrfUE5nX1f3YpGZQKNcITUYWlrAWo=
modernc.org/libc v1.11.39/go.mod h1:mV8lJMo2S5A31uD0k1cMu7vrJbSA3J3waQJxpV4iqx8=
modernc.org/libc v1.11.42/go.mod h1:yzrLDU+sSjLE+D4bIhS7q1L5UwXDOw99PLSX0BlZvSQ=
modernc.org/libc v1.11.44/go.mod h1:KFq33jsma7F5WXiYelU8quMJasCCTnHK0mkri4yPHgA=
modernc.org/libc v1.11.45/go.mod h1:Y192orvfVQQYFzCNsn+Xt0Hxt4DiO4USpLNXBlXg/tM=
modernc.org/libc v1.11.47/go.mod h1:tPkE4PzCTW27E6AIKIR5IwHAQKCAtudEIeAV1/SiyBg=
modernc.org/libc v1.11.49/go.mod h1:9JrJuK5WTtoTWIFQ7QjX2Mb/bagYdZdscI3xrvHbXjE=
modernc.org/libc v1.11.51/go.mod h1:R9I8u9TS+meaWLdbfQhq2kFknTW0O3aw3kEMqDDxMaM=
modernc.org/libc v1.11.53/go.mod h1:5ip5vWYPAoMulkQ5XlSJTy12Sz5U6blOQiYasilVPsU=
modernc.org/libc v1.11.54/go.mod h1:S/FVnskbzVUrjfBqlGFIPA5m7UwB3n9fojHhCNfSsnw=
modernc.org/libc v1.11.55/go.mod h1:j2A5YBRm6HjNkoSs/fzZrSxCuwWqcMYTDPLNx0URn3M=
modernc.org/libc v1.11.56/go.mod h1:pakHkg5JdMLt2OgRadpPOTnyRXm/uzu+Yyg/LSLdi18=
modernc.org/libc v1.11.58/go.mod h1:ns94Rxv0OWyoQrDqMFfWwka2BcaF6/61CqJRK9LP7S8=
modernc.org/libc v1.11.71/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw=
modernc.org/libc v1.11.75/go.mod h1:dGRVugT6edz361wmD9gk6ax1AbDSe0x5vji0dGJiPT0=
modernc.org/libc v1.11.82/go.mod h1:NF+Ek1BOl2jeC7lw3a7Jj5PWyHPwWD4aq3wVKxqV1fI=
modernc.org/libc v1.11.86/go.mod h1:ePuYgoQLmvxdNT06RpGnaDKJmDNEkV7ZPKI2jnsvZoE=
modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY=
modernc.org/libc v1.11.88/go.mod h1:h3oIVe8dxmTcchcFuCcJ4nAWaoiwzKCdv82MM0oiIdQ=
modernc.org/libc v1.11.98/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c=
modernc.org/libc v1.11.101/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI=
modernc.org/libc v1.12.0/go.mod h1:2MH3DaF/gCU8i/UBiVE1VFRos4o523M7zipmwH8SIgQ=
modernc.org/libc v1.13.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk=
modernc.org/libc v1.13.2/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk=
modernc.org/libc v1.14.1 h1:rwx9uVJU/fEmsmV5ECGRwdAiXgUm6k6tsFA+L8kQb6E=
modernc.org/libc v1.14.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk=
modernc.org/libc v1.14.2/go.mod h1:MX1GBLnRLNdvmK9azU9LCxZ5lMyhrbEMK8rG3X/Fe34=
modernc.org/libc v1.14.3/go.mod h1:GPIvQVOVPizzlqyRX3l756/3ppsAgg1QgPxjr5Q4agQ=
modernc.org/libc v1.14.5 h1:DAHvwGoVRDZs5iJXnX9RJrgXSsorupCWmJ2ac964Owk=
modernc.org/libc v1.14.5/go.mod h1:2PJHINagVxO4QW/5OQdRrvMYo+bm5ClpUFfyXCYl9ak=
modernc.org/libc v1.14.6 h1:SSiZiE5199iYsGM9gtkDj90xqcXVwubWG8CtoYE+Mnk=
modernc.org/libc v1.14.6/go.mod h1:2PJHINagVxO4QW/5OQdRrvMYo+bm5ClpUFfyXCYl9ak=
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8=
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14=
modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM=
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sqlite v1.14.5 h1:bYrrjwH9Y7QUGk1MbchZDhRfmpGuEAs/D45sVjNbfvs=
modernc.org/sqlite v1.14.5/go.mod h1:YyX5Rx0WbXokitdWl2GJIDy4BrPxBP0PwwhpXOHCDLE=
modernc.org/sqlite v1.14.6 h1:Jt5P3k80EtDBWaq1beAxnWW+5MdHXbZITujnRS7+zWg=
modernc.org/sqlite v1.14.6/go.mod h1:yiCvMv3HblGmzENNIaNtFhfaNIwcla4u2JQEwJPzfEc=
modernc.org/sqlite v1.14.8 h1:2OOqfZAyU4x4qusilvHoRXXqsAgaZobi1o+mjQ5MUpw=
modernc.org/sqlite v1.14.8/go.mod h1:TFmXjym+/jR31fxc2B5eHnKMuJJGY7i1L/T5A0jzVww=
modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs=
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
modernc.org/tcl v1.10.0 h1:vux2MNFhSXYqD8Kq4Uc9RjWcgv2c7Atx3da3VpLPPEw=
modernc.org/tcl v1.10.0/go.mod h1:WzWapmP/7dHVhFoyPpEaNSVTL8xtewhouN/cqSJ5A2s=
modernc.org/tcl v1.11.0/go.mod h1:zsTUpbQ+NxQEjOjCUlImDLPv1sG8Ww0qp66ZvyOxCgw=
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.2.21/go.mod h1:uXrObx4pGqXWIMliC5MiKuwAyMrltzwpteOFUP1PWCc=
modernc.org/z v1.3.0 h1:4RWULo1Nvaq5ZBhbLe74u8p6tV4Mmm0ZrPBXYPm/xjM=
modernc.org/z v1.3.0/go.mod h1:+mvgLH814oDjtATDdT3rs84JnUIpkvAF5B8AVkNlE2g=
modernc.org/z v1.3.1/go.mod h1:0RBFPpdFNiKpjTza1WYaB4+6ySjS6dLBoo09OQZ4E3w=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

View File

@ -1,4 +1,4 @@
package types
package layer
type Layer struct {
Id int `json:"id"`

23
main.go
View File

@ -2,7 +2,6 @@ package main
import (
"fmt"
"os"
"mapserver/app"
"mapserver/mapobject"
"mapserver/params"
@ -14,19 +13,11 @@ import (
)
func main() {
//get Env or Default value
env := func(key string, defaultVal string) string {
val, ok := os.LookupEnv(key)
if !ok {
return defaultVal
}
return val
}
//Parse command line
p := params.Parse()
if p.Debug || env("MT_LOGLEVEL", "INFO") == "DEBUG" {
if p.Debug {
logrus.SetLevel(logrus.DebugLevel)
} else {
logrus.SetLevel(logrus.InfoLevel)
@ -48,17 +39,15 @@ func main() {
}
//parse Config
cfg, err := app.ParseConfig(env("MT_CONFIG_PATH", app.ConfigFile))
cfg, err := app.ParseConfig(app.ConfigFile)
if err != nil {
panic(err)
}
//write back config with all values
if env("MT_READONLY", "false") != "true" {
err = cfg.Save()
if err != nil {
panic(err)
}
err = cfg.Save()
if err != nil {
panic(err)
}
//exit after creating the config

View File

@ -1,6 +1,7 @@
package mapblockaccessor
import (
"mapserver/coords"
"mapserver/eventbus"
"mapserver/types"
"sync"
@ -13,61 +14,56 @@ import (
var lock = &sync.RWMutex{}
func (a *MapBlockAccessor) GetMapBlock(pos *types.MapBlockCoords) (*mapparser.MapBlock, error) {
cache_enabled := a.maxcount > 0
func (a *MapBlockAccessor) GetMapBlock(pos *coords.MapBlockCoords) (*mapparser.MapBlock, error) {
key := getKey(pos)
if cache_enabled {
//maintenance
cacheBlocks.Set(float64(a.blockcache.ItemCount()))
if a.blockcache.ItemCount() > a.maxcount {
//flush cache
fields := logrus.Fields{
"cached items": a.blockcache.ItemCount(),
"maxcount": a.maxcount,
}
logrus.WithFields(fields).Debug("Flushing cache")
a.blockcache.Flush()
//maintenance
cacheBlocks.Set(float64(a.blockcache.ItemCount()))
if a.blockcache.ItemCount() > a.maxcount {
//flush cache
fields := logrus.Fields{
"cached items": a.blockcache.ItemCount(),
"maxcount": a.maxcount,
}
logrus.WithFields(fields).Debug("Flushing cache")
//read section
lock.RLock()
a.blockcache.Flush()
}
cachedblock, found := a.blockcache.Get(key)
if found {
defer lock.RUnlock()
//read section
lock.RLock()
getCacheHitCount.Inc()
if cachedblock == nil {
return nil, nil
} else {
return cachedblock.(*mapparser.MapBlock), nil
}
cachedblock, found := a.blockcache.Get(key)
if found {
defer lock.RUnlock()
getCacheHitCount.Inc()
if cachedblock == nil {
return nil, nil
} else {
return cachedblock.(*mapparser.MapBlock), nil
}
}
//end read
lock.RUnlock()
//end read
lock.RUnlock()
timer := prometheus.NewTimer(dbGetDuration)
defer timer.ObserveDuration()
timer := prometheus.NewTimer(dbGetDuration)
defer timer.ObserveDuration()
//write section
lock.Lock()
defer lock.Unlock()
//write section
lock.Lock()
defer lock.Unlock()
//try read
cachedblock, found = a.blockcache.Get(key)
if found {
getCacheHitCount.Inc()
if cachedblock == nil {
return nil, nil
} else {
return cachedblock.(*mapparser.MapBlock), nil
}
//try read
cachedblock, found = a.blockcache.Get(key)
if found {
getCacheHitCount.Inc()
if cachedblock == nil {
return nil, nil
} else {
return cachedblock.(*mapparser.MapBlock), nil
}
}
block, err := a.accessor.GetBlock(pos)
@ -77,16 +73,12 @@ func (a *MapBlockAccessor) GetMapBlock(pos *types.MapBlockCoords) (*mapparser.Ma
if block == nil {
//no mapblock here
if cache_enabled {
cacheBlockCount.Inc()
a.blockcache.Set(key, nil, cache.DefaultExpiration)
}
cacheBlockCount.Inc()
a.blockcache.Set(key, nil, cache.DefaultExpiration)
return nil, nil
}
if cache_enabled {
getCacheMissCount.Inc()
}
getCacheMissCount.Inc()
mapblock, err := mapparser.Parse(block.Data)
if err != nil {
@ -95,10 +87,8 @@ func (a *MapBlockAccessor) GetMapBlock(pos *types.MapBlockCoords) (*mapparser.Ma
a.Eventbus.Emit(eventbus.MAPBLOCK_RENDERED, types.NewParsedMapblock(mapblock, pos))
if cache_enabled {
cacheBlockCount.Inc()
a.blockcache.Set(key, mapblock, cache.DefaultExpiration)
}
cacheBlockCount.Inc()
a.blockcache.Set(key, mapblock, cache.DefaultExpiration)
return mapblock, nil
}

View File

@ -2,6 +2,7 @@ package mapblockaccessor
import (
"mapserver/eventbus"
"mapserver/layer"
"mapserver/settings"
"mapserver/types"
@ -18,7 +19,7 @@ type FindNextLegacyBlocksResult struct {
LastMtime int64
}
func (a *MapBlockAccessor) FindNextLegacyBlocks(s settings.Settings, layers []*types.Layer, limit int) (*FindNextLegacyBlocksResult, error) {
func (a *MapBlockAccessor) FindNextLegacyBlocks(s settings.Settings, layers []*layer.Layer, limit int) (*FindNextLegacyBlocksResult, error) {
nextResult, err := a.accessor.FindNextInitialBlocks(s, layers, limit)

View File

@ -0,0 +1,11 @@
package mapblockaccessor
import (
"github.com/sirupsen/logrus"
)
var log *logrus.Entry
func init() {
log = logrus.WithFields(logrus.Fields{"prefix": "mapblockaccessor"})
}

View File

@ -2,9 +2,9 @@ package mapblockaccessor
import (
"fmt"
"mapserver/coords"
"mapserver/db"
"mapserver/eventbus"
"mapserver/types"
"time"
@ -18,7 +18,7 @@ type MapBlockAccessor struct {
maxcount int
}
func getKey(pos *types.MapBlockCoords) string {
func getKey(pos *coords.MapBlockCoords) string {
return fmt.Sprintf("Coord %d/%d/%d", pos.X, pos.Y, pos.Z)
}

View File

@ -2,9 +2,9 @@ package mapblockaccessor
import (
"io/ioutil"
"mapserver/coords"
"mapserver/db/sqlite"
"mapserver/testutils"
"mapserver/types"
"os"
"testing"
"time"
@ -33,7 +33,7 @@ func TestSimpleAccess(t *testing.T) {
}
cache := NewMapBlockAccessor(a, 500*time.Millisecond, 1000*time.Millisecond, 1000)
mb, err := cache.GetMapBlock(types.NewMapBlockCoords(0, 0, 0))
mb, err := cache.GetMapBlock(coords.NewMapBlockCoords(0, 0, 0))
if err != nil {
panic(err)

View File

@ -1,7 +1,9 @@
package mapblockaccessor
import (
"mapserver/coords"
"mapserver/eventbus"
"mapserver/layer"
"mapserver/types"
"github.com/minetest-go/mapparser"
@ -12,13 +14,13 @@ import (
type FindMapBlocksByMtimeResult struct {
HasMore bool
LastPos *types.MapBlockCoords
LastPos *coords.MapBlockCoords
LastMtime int64
List []*types.ParsedMapblock
UnfilteredCount int
}
func (a *MapBlockAccessor) FindMapBlocksByMtime(lastmtime int64, limit int, layerfilter []*types.Layer) (*FindMapBlocksByMtimeResult, error) {
func (a *MapBlockAccessor) FindMapBlocksByMtime(lastmtime int64, limit int, layerfilter []*layer.Layer) (*FindMapBlocksByMtimeResult, error) {
fields := logrus.Fields{
"lastmtime": lastmtime,
@ -39,7 +41,7 @@ func (a *MapBlockAccessor) FindMapBlocksByMtime(lastmtime int64, limit int, laye
result := FindMapBlocksByMtimeResult{}
mblist := make([]*types.ParsedMapblock, 0)
var newlastpos *types.MapBlockCoords
var newlastpos *coords.MapBlockCoords
result.HasMore = len(blocks) == limit
result.UnfilteredCount = len(blocks)
@ -49,7 +51,7 @@ func (a *MapBlockAccessor) FindMapBlocksByMtime(lastmtime int64, limit int, laye
result.LastMtime = block.Mtime
}
currentLayer := types.FindLayerByY(layerfilter, block.Pos.Y)
currentLayer := layer.FindLayerByY(layerfilter, block.Pos.Y)
if currentLayer == nil {
continue

View File

@ -1,13 +1,13 @@
package mapblockaccessor
import (
"mapserver/types"
"mapserver/coords"
"github.com/minetest-go/mapparser"
cache "github.com/patrickmn/go-cache"
)
func (a *MapBlockAccessor) Update(pos *types.MapBlockCoords, mb *mapparser.MapBlock) {
func (a *MapBlockAccessor) Update(pos *coords.MapBlockCoords, mb *mapparser.MapBlock) {
key := getKey(pos)
cacheBlockCount.Inc()
a.blockcache.Set(key, mb, cache.DefaultExpiration)

View File

@ -4,12 +4,11 @@ import (
"errors"
"image"
"image/color"
"mapserver/colormapping"
"mapserver/coords"
"mapserver/mapblockaccessor"
"mapserver/types"
"time"
"github.com/minetest-go/colormapping"
"github.com/prometheus/client_golang/prometheus"
"github.com/sirupsen/logrus"
)
@ -73,13 +72,13 @@ func addColorComponent(c *color.RGBA, value int) *color.RGBA {
}
}
func (r *MapBlockRenderer) Render(pos1, pos2 *types.MapBlockCoords) (*image.NRGBA, error) {
func (r *MapBlockRenderer) Render(pos1, pos2 *coords.MapBlockCoords) (*image.NRGBA, error) {
if pos1.X != pos2.X {
return nil, errors.New("x does not line up")
return nil, errors.New("X does not line up")
}
if pos1.Z != pos2.Z {
return nil, errors.New("z does not line up")
return nil, errors.New("Z does not line up")
}
renderedMapblocks.Inc()
@ -111,7 +110,7 @@ func (r *MapBlockRenderer) Render(pos1, pos2 *types.MapBlockCoords) (*image.NRGB
}
for mapBlockY := maxY; mapBlockY >= minY; mapBlockY-- {
currentPos := types.NewMapBlockCoords(pos1.X, mapBlockY, pos1.Z)
currentPos := coords.NewMapBlockCoords(pos1.X, mapBlockY, pos1.Z)
mb, err := r.accessor.GetMapBlock(currentPos)
if err != nil {
@ -142,9 +141,6 @@ func (r *MapBlockRenderer) Render(pos1, pos2 *types.MapBlockCoords) (*image.NRGB
continue
}
// clamp alpha channel to max
c.A = 255
if r.enableShadow {
var left, leftAbove, top, topAbove string
@ -157,7 +153,7 @@ func (r *MapBlockRenderer) Render(pos1, pos2 *types.MapBlockCoords) (*image.NRGB
} else {
//neighbouring mapblock
neighbourPos := types.NewMapBlockCoords(currentPos.X-1, currentPos.Y, currentPos.Z)
neighbourPos := coords.NewMapBlockCoords(currentPos.X-1, currentPos.Y, currentPos.Z)
neighbourMapblock, err := r.accessor.GetMapBlock(neighbourPos)
if neighbourMapblock != nil && err == nil {
@ -177,7 +173,7 @@ func (r *MapBlockRenderer) Render(pos1, pos2 *types.MapBlockCoords) (*image.NRGB
} else {
//neighbouring mapblock
neighbourPos := types.NewMapBlockCoords(currentPos.X, currentPos.Y, currentPos.Z+1)
neighbourPos := coords.NewMapBlockCoords(currentPos.X, currentPos.Y, currentPos.Z+1)
neighbourMapblock, err := r.accessor.GetMapBlock(neighbourPos)
if neighbourMapblock != nil && err == nil {

View File

@ -2,16 +2,15 @@ package mapblockrenderer
import (
"io/ioutil"
"mapserver/colormapping"
"mapserver/coords"
"mapserver/db/sqlite"
"mapserver/mapblockaccessor"
"mapserver/testutils"
"mapserver/types"
"os"
"testing"
"time"
"github.com/minetest-go/colormapping"
"github.com/sirupsen/logrus"
)
@ -42,7 +41,7 @@ func createRenderer(b *testing.B) (*MapBlockRenderer, callback) {
cache := mapblockaccessor.NewMapBlockAccessor(a, 500*time.Millisecond, 1000*time.Millisecond, 1000)
c := colormapping.NewColorMapping()
err = c.LoadDefaults()
_, err = c.LoadVFSColors("colors/vanessa.txt")
if err != nil {
b.Fatal(err)
}
@ -59,8 +58,8 @@ func BenchmarkRenderEmptySingle(b *testing.B) {
for n := 0; n < b.N; n++ {
pos1 := types.NewMapBlockCoords(10, 0, 10)
pos2 := types.NewMapBlockCoords(10, 0, 10)
pos1 := coords.NewMapBlockCoords(10, 0, 10)
pos2 := coords.NewMapBlockCoords(10, 0, 10)
_, err := r.Render(pos1, pos2)
@ -76,8 +75,8 @@ func BenchmarkRenderSingle(b *testing.B) {
for n := 0; n < b.N; n++ {
pos1 := types.NewMapBlockCoords(0, 0, 0)
pos2 := types.NewMapBlockCoords(0, 0, 0)
pos1 := coords.NewMapBlockCoords(0, 0, 0)
pos2 := coords.NewMapBlockCoords(0, 0, 0)
_, err := r.Render(pos1, pos2)
@ -93,8 +92,8 @@ func BenchmarkRenderStride(b *testing.B) {
for n := 0; n < b.N; n++ {
pos1 := types.NewMapBlockCoords(0, 10, 0)
pos2 := types.NewMapBlockCoords(0, -1, 0)
pos1 := coords.NewMapBlockCoords(0, 10, 0)
pos2 := coords.NewMapBlockCoords(0, -1, 0)
_, err := r.Render(pos1, pos2)
@ -110,8 +109,8 @@ func BenchmarkRenderBigStride(b *testing.B) {
for n := 0; n < b.N; n++ {
pos1 := types.NewMapBlockCoords(0, 1000, 0)
pos2 := types.NewMapBlockCoords(0, -1000, 0)
pos1 := coords.NewMapBlockCoords(0, 1000, 0)
pos2 := coords.NewMapBlockCoords(0, -1000, 0)
_, err := r.Render(pos1, pos2)

View File

@ -3,25 +3,24 @@ package mapblockrenderer
import (
"fmt"
"io/ioutil"
"mapserver/colormapping"
"mapserver/coords"
"mapserver/db/sqlite"
"mapserver/layer"
"mapserver/mapblockaccessor"
"mapserver/testutils"
"mapserver/types"
"os"
"testing"
"time"
"github.com/minetest-go/colormapping"
"github.com/sirupsen/logrus"
)
func TestSimpleRender(t *testing.T) {
logrus.SetLevel(logrus.InfoLevel)
layers := []*types.Layer{
{
layers := []*layer.Layer{
&layer.Layer{
Id: 0,
Name: "Base",
From: -16,
@ -48,7 +47,7 @@ func TestSimpleRender(t *testing.T) {
cache := mapblockaccessor.NewMapBlockAccessor(a, 500*time.Millisecond, 1000*time.Millisecond, 1000)
c := colormapping.NewColorMapping()
err = c.LoadDefaults()
_, err = c.LoadVFSColors("colors/vanessa.txt")
if err != nil {
t.Fatal(err)
}
@ -81,8 +80,8 @@ func TestSimpleRender(t *testing.T) {
for x := from; x < to; x++ {
for z := from; z < to; z++ {
pos1 := types.NewMapBlockCoords(x, 10, z)
pos2 := types.NewMapBlockCoords(x, -1, z)
pos1 := coords.NewMapBlockCoords(x, 10, z)
pos2 := coords.NewMapBlockCoords(x, -1, z)
jobs <- JobData{Pos1: pos1, Pos2: pos2}
}

View File

@ -3,12 +3,12 @@ package mapblockrenderer
import (
"bytes"
"image/png"
"mapserver/types"
"mapserver/coords"
"time"
)
type JobData struct {
Pos1, Pos2 *types.MapBlockCoords
Pos1, Pos2 *coords.MapBlockCoords
}
type JobResult struct {

View File

@ -1,28 +1,31 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
type ATM struct{}
func (this *ATM) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *ATM) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
nodename := block.GetNodeName(x, y, z)
o := mapobjectdb.NewMapObject(mbpos, x, y, z, "atm")
switch nodename {
case "atm:wtt", "um_wtt:wtt":
o.Attributes["type"] = "wiretransfer"
case "atm:atm2", "um_atm:atm_2":
o.Attributes["type"] = "atm2"
case "atm:atm3", "um_atm:atm_3":
o.Attributes["type"] = "atm3"
default:
o.Attributes["type"] = "atm"
if nodename == "atm:wtt" {
o.Attributes["type"] = "wiretransfer"
} else if nodename == "atm:atm2" {
o.Attributes["type"] = "atm2"
} else if nodename == "atm:atm3" {
o.Attributes["type"] = "atm3"
} else {
o.Attributes["type"] = "atm"
}
return o

View File

@ -1,8 +1,8 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"strconv"
"github.com/minetest-go/mapparser"
@ -10,7 +10,7 @@ import (
type BonesBlock struct{}
func (this *BonesBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *BonesBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
invMap := block.Metadata.GetInventoryMapAtPos(x, y, z)

View File

@ -1,15 +1,15 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
type BorderBlock struct{}
func (this *BorderBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *BorderBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
o := mapobjectdb.NewMapObject(mbpos, x, y, z, "border")

View File

@ -1,15 +1,15 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
type DigilineLcdBlock struct{}
func (this *DigilineLcdBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *DigilineLcdBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
o := mapobjectdb.NewMapObject(mbpos, x, y, z, "digilinelcd")

View File

@ -1,15 +1,15 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
type DigitermsBlock struct{}
func (this *DigitermsBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *DigitermsBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
o := mapobjectdb.NewMapObject(mbpos, x, y, z, "digiterm")

View File

@ -1,9 +1,9 @@
package mapobject
import (
"mapserver/coords"
"mapserver/luaparser"
"mapserver/mapobjectdb"
"mapserver/types"
"math"
"strconv"
@ -13,7 +13,7 @@ import (
type FancyVend struct{}
func (this *FancyVend) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *FancyVend) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
nodename := block.GetNodeName(x, y, z)
invMap := block.Metadata.GetInventoryMapAtPos(x, y, z)

View File

@ -1,15 +1,15 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
type JumpdriveBlock struct{}
func (this *JumpdriveBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *JumpdriveBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
o := mapobjectdb.NewMapObject(mbpos, x, y, z, "jumpdrive")

View File

@ -1,15 +1,15 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
type LabelBlock struct{}
func (this *LabelBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *LabelBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
o := mapobjectdb.NewMapObject(mbpos, x, y, z, "label")

View File

@ -12,11 +12,11 @@ import (
)
type MapObjectListener interface {
onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject
onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject
}
type MapMultiObjectListener interface {
onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) []*mapobjectdb.MapObject
onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) []*mapobjectdb.MapObject
}
type Listener struct {

View File

@ -1,15 +1,15 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
type Locator struct{}
func (this *Locator) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *Locator) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
nodename := block.GetNodeName(x, y, z)

View File

@ -1,15 +1,15 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
type LuaControllerBlock struct{}
func (this *LuaControllerBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *LuaControllerBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
//md := block.Metadata.GetMetadata(x, y, z)
nodename := block.GetNodeName(x, y, z)

View File

@ -1,15 +1,15 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
type MissionBlock struct{}
func (this *MissionBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *MissionBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
if md["hidden"] == "1" {

View File

@ -1,15 +1,15 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
type NuclearReactorBlock struct{}
func (this *NuclearReactorBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *NuclearReactorBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
o := mapobjectdb.NewMapObject(mbpos, x, y, z, "nuclearreactor")

View File

@ -1,24 +0,0 @@
package mapobject
import (
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
type Phonograph struct{}
func (this *Phonograph) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
if _, ok := md["song_title"]; !ok {
return nil
}
o := mapobjectdb.NewMapObject(mbpos, x, y, z, "phonograph")
o.Attributes["song_title"] = md["song_title"]
o.Attributes["song_artist"] = md["song_artist"]
return o
}

View File

@ -1,8 +1,8 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
@ -11,15 +11,13 @@ type PoiBlock struct {
Color string
}
func (this *PoiBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *PoiBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
o := mapobjectdb.NewMapObject(mbpos, x, y, z, "poi")
o.Attributes["name"] = md["name"]
o.Attributes["category"] = md["category"]
o.Attributes["addr"] = md["addr"]
o.Attributes["url"] = md["url"]
o.Attributes["image"] = md["image"]
o.Attributes["owner"] = md["owner"]
o.Attributes["icon"] = md["icon"]
o.Attributes["color"] = this.Color

View File

@ -1,15 +1,15 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
type PrivProtectorBlock struct{}
func (this *PrivProtectorBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *PrivProtectorBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
o := mapobjectdb.NewMapObject(mbpos, x, y, z, "privprotector")

View File

@ -1,15 +1,15 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
type ProtectorBlock struct{}
func (this *ProtectorBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *ProtectorBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
o := mapobjectdb.NewMapObject(mbpos, x, y, z, "protector")

View File

@ -1,15 +1,15 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
type QuarryBlock struct{}
func (this *QuarryBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *QuarryBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
if md["owner"] == "" {

View File

@ -164,18 +164,10 @@ func Setup(ctx *app.App) {
if ctx.Config.MapObjects.ATM {
atm := &ATM{}
// ATMs and WTT of gpcf's mod
l.AddMapObject("atm:atm", atm)
l.AddMapObject("atm:atm2", atm)
l.AddMapObject("atm:atm3", atm)
l.AddMapObject("atm:wtt", atm)
// ATMs and WTT of Unified Money
l.AddMapObject("um_atm:atm_1", atm)
l.AddMapObject("um_atm:atm_2", atm)
l.AddMapObject("um_atm:atm_3", atm)
l.AddMapObject("um_wtt:wtt", atm)
}
//locator
@ -192,15 +184,5 @@ func Setup(ctx *app.App) {
l.AddMapObject("default:sign_wall_steel", &SignBlock{Material: "steel"})
}
//Phonograph
if ctx.Config.MapObjects.Phonograph {
l.AddMapObject("phonograph:phonograph", &Phonograph{})
}
//For Sale Sign for Unified Money
if ctx.Config.MapObjects.UnifiefMoneyAreaForSale {
l.AddMapObject("um_area_forsale:for_sale_sign", &UnifiefMoneyAreaForSale{})
}
ctx.MapBlockAccessor.Eventbus.AddListener(&l)
}

View File

@ -1,8 +1,8 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
@ -11,7 +11,7 @@ type SignBlock struct {
Material string
}
func (this *SignBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *SignBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
o := mapobjectdb.NewMapObject(mbpos, x, y, z, "sign")

View File

@ -1,8 +1,8 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"math"
"strconv"
@ -11,7 +11,7 @@ import (
type SmartShopBlock struct{}
func (this *SmartShopBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) []*mapobjectdb.MapObject {
func (this *SmartShopBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) []*mapobjectdb.MapObject {
list := make([]*mapobjectdb.MapObject, 0)
md := block.Metadata.GetMetadata(x, y, z)

View File

@ -1,15 +1,15 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
type TechnicAnchorBlock struct{}
func (this *TechnicAnchorBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *TechnicAnchorBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
o := mapobjectdb.NewMapObject(mbpos, x, y, z, "technicanchor")

View File

@ -1,15 +1,15 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
type TechnicSwitchBlock struct{}
func (this *TechnicSwitchBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *TechnicSwitchBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
o := mapobjectdb.NewMapObject(mbpos, x, y, z, "technicswitch")

View File

@ -1,15 +1,15 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
type TrainBlock struct{}
func (this *TrainBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *TrainBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
o := mapobjectdb.NewMapObject(mbpos, x, y, z, "train")

View File

@ -1,8 +1,8 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"strings"
"github.com/minetest-go/mapparser"
@ -10,7 +10,7 @@ import (
type TravelnetBlock struct{}
func (tn *TravelnetBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (tn *TravelnetBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
// ignore (P) prefixed stations

View File

@ -1,26 +0,0 @@
package mapobject
import (
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
type UnifiefMoneyAreaForSale struct{}
func (this *UnifiefMoneyAreaForSale) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
if _, ok := md["id"]; !ok {
return nil
}
o := mapobjectdb.NewMapObject(mbpos, x, y, z, "um_area_forsale")
o.Attributes["owner"] = md["owner"]
o.Attributes["id"] = md["id"] // ", " seperated
o.Attributes["price"] = md["price"]
o.Attributes["description"] = md["description"]
return o
}

View File

@ -1,15 +1,15 @@
package mapobject
import (
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"github.com/minetest-go/mapparser"
)
type XPProtectorBlock struct{}
func (this *XPProtectorBlock) onMapObject(mbpos *types.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
func (this *XPProtectorBlock) onMapObject(mbpos *coords.MapBlockCoords, x, y, z int, block *mapparser.MapBlock) *mapobjectdb.MapObject {
md := block.Metadata.GetMetadata(x, y, z)
o := mapobjectdb.NewMapObject(mbpos, x, y, z, "xpprotector")

View File

@ -2,7 +2,6 @@ package mapobjectdb
import (
"mapserver/coords"
"mapserver/types"
"time"
"github.com/sirupsen/logrus"
@ -22,7 +21,7 @@ type Tile struct {
type MapObject struct {
//mapblock position
MBPos *types.MapBlockCoords `json:"mapblock"`
MBPos *coords.MapBlockCoords `json:"mapblock"`
//block position
X int `json:"x"`
@ -34,7 +33,7 @@ type MapObject struct {
Attributes map[string]string `json:"attributes"`
}
func NewMapObject(MBPos *types.MapBlockCoords, x int, y int, z int, _type string) *MapObject {
func NewMapObject(MBPos *coords.MapBlockCoords, x int, y int, z int, _type string) *MapObject {
fields := logrus.Fields{
"mbpos": MBPos,
@ -65,11 +64,11 @@ type SearchAttributeLike struct {
type SearchQuery struct {
//mapblock position
Pos1 *types.MapBlockCoords `json:"pos1"`
Pos2 *types.MapBlockCoords `json:"pos2"`
Type string `json:"type"`
AttributeLike *SearchAttributeLike `json:"attributelike"`
Limit *int `json:"limit"`
Pos1 *coords.MapBlockCoords `json:"pos1"`
Pos2 *coords.MapBlockCoords `json:"pos2"`
Type string `json:"type"`
AttributeLike *SearchAttributeLike `json:"attributelike"`
Limit *int `json:"limit"`
}
type DBAccessor interface {
@ -78,7 +77,7 @@ type DBAccessor interface {
//Generic map objects (poi, etc)
GetMapData(q *SearchQuery) ([]*MapObject, error)
RemoveMapData(pos *types.MapBlockCoords) error
RemoveMapData(pos *coords.MapBlockCoords) error
AddMapData(data *MapObject) error
//Settings

View File

@ -2,7 +2,7 @@ package mapobjectdb
import (
"fmt"
"mapserver/types"
"mapserver/coords"
"testing"
)
@ -10,7 +10,7 @@ func TestNewMapBlockCoords(t *testing.T) {
attrs := make(map[string]string)
attrs["X"] = "y"
pos := types.NewMapBlockCoords(1, 2, 3)
pos := coords.NewMapBlockCoords(1, 2, 3)
fmt.Println(pos)
obj := NewMapObject(pos, 10, 12, 14, "xy")

View File

@ -2,22 +2,21 @@ package postgres
import (
"database/sql"
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"unicode/utf8"
"github.com/google/uuid"
"github.com/sirupsen/logrus"
)
func (a *PostgresAccessor) GetMapData(q *mapobjectdb.SearchQuery) ([]*mapobjectdb.MapObject, error) {
func (db *PostgresAccessor) GetMapData(q *mapobjectdb.SearchQuery) ([]*mapobjectdb.MapObject, error) {
var rows *sql.Rows
var err error
if q.AttributeLike == nil {
//plain pos search
rows, err = a.db.Query(getMapDataPosQuery,
rows, err = db.db.Query(getMapDataPosQuery,
q.Type,
q.Pos1.X, q.Pos1.Y, q.Pos1.Z,
q.Pos2.X, q.Pos2.Y, q.Pos2.Z,
@ -26,7 +25,7 @@ func (a *PostgresAccessor) GetMapData(q *mapobjectdb.SearchQuery) ([]*mapobjectd
} else {
//attribute like search
rows, err = a.db.Query(getMapDataWithAttributeLikePosQuery,
rows, err = db.db.Query(getMapDataWithAttributeLikePosQuery,
q.Type,
q.Pos1.X, q.Pos1.Y, q.Pos1.Z,
q.Pos2.X, q.Pos2.Y, q.Pos2.Z,
@ -43,10 +42,10 @@ func (a *PostgresAccessor) GetMapData(q *mapobjectdb.SearchQuery) ([]*mapobjectd
result := make([]*mapobjectdb.MapObject, 0)
var currentObj *mapobjectdb.MapObject
var currentUID string
var currentId *int64
for rows.Next() {
var id string
var id int64
var Type string
var mtime int64
var x, y, z int
@ -62,8 +61,8 @@ func (a *PostgresAccessor) GetMapData(q *mapobjectdb.SearchQuery) ([]*mapobjectd
return nil, err
}
if currentUID == "" || currentUID != id {
pos := types.NewMapBlockCoords(posx, posy, posz)
if currentId == nil || *currentId != id {
pos := coords.NewMapBlockCoords(posx, posy, posz)
mo := &mapobjectdb.MapObject{
MBPos: pos,
Type: Type,
@ -75,7 +74,7 @@ func (a *PostgresAccessor) GetMapData(q *mapobjectdb.SearchQuery) ([]*mapobjectd
}
currentObj = mo
currentUID = id
currentId = &id
result = append(result, currentObj)
@ -87,12 +86,12 @@ func (a *PostgresAccessor) GetMapData(q *mapobjectdb.SearchQuery) ([]*mapobjectd
return result, nil
}
func (a *PostgresAccessor) RemoveMapData(pos *types.MapBlockCoords) error {
_, err := a.db.Exec(removeMapDataQuery, pos.X, pos.Y, pos.Z)
func (db *PostgresAccessor) RemoveMapData(pos *coords.MapBlockCoords) error {
_, err := db.db.Exec(removeMapDataQuery, pos.X, pos.Y, pos.Z)
return err
}
func (a *PostgresAccessor) AddMapData(data *mapobjectdb.MapObject) error {
func (db *PostgresAccessor) AddMapData(data *mapobjectdb.MapObject) error {
for k, v := range data.Attributes {
if !utf8.Valid([]byte(v)) {
@ -107,19 +106,22 @@ func (a *PostgresAccessor) AddMapData(data *mapobjectdb.MapObject) error {
}
}
uid := uuid.NewString()
_, err := a.db.Exec(addMapDataQuery,
uid,
res := db.db.QueryRow(addMapDataQuery,
data.X, data.Y, data.Z,
data.MBPos.X, data.MBPos.Y, data.MBPos.Z,
data.Type, data.Mtime)
lastInsertId := 0
err := res.Scan(&lastInsertId)
if err != nil {
return err
}
for k, v := range data.Attributes {
_, err := a.db.Exec(addMapDataAttributeQuery, uid, k, v)
//TODO: batch insert
_, err := db.db.Exec(addMapDataAttributeQuery, lastInsertId, k, v)
if err != nil {
return err
}

View File

@ -2,44 +2,33 @@ package postgres
import (
"database/sql"
"embed"
"mapserver/public"
"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database/postgres"
"github.com/golang-migrate/migrate/v4/source/iofs"
"github.com/sirupsen/logrus"
)
//go:embed migrations/*.sql
var migrations embed.FS
"time"
)
type PostgresAccessor struct {
db *sql.DB
}
func (a *PostgresAccessor) Migrate() error {
driver, err := postgres.WithInstance(a.db, &postgres.Config{})
func (db *PostgresAccessor) Migrate() error {
log.Info("Migrating database")
start := time.Now()
sql, err := public.Files.ReadFile("sql/postgres_mapobjectdb_migrate.sql")
if err != nil {
return err
}
d, err := iofs.New(migrations, "migrations")
_, err = db.db.Exec(string(sql))
if err != nil {
return err
}
m, err := migrate.NewWithInstance("iofs", d, "postgres", driver)
if err != nil {
return err
}
err = m.Up()
if err != nil && err != migrate.ErrNoChange {
return err
}
v, _, _ := m.Version()
logrus.WithFields(logrus.Fields{"version": v}).Info("DB Migrated")
t := time.Now()
elapsed := t.Sub(start)
log.WithFields(logrus.Fields{"elapsed": elapsed}).Info("Migration completed")
return nil
}

View File

@ -1,20 +0,0 @@
-- add objects.uid
alter table objects add uid uuid not null default gen_random_uuid();
create index objects_uid on objects(uid);
alter table objects add constraint objects_uid_unique UNIQUE (uid);
-- add object_attributes.object_uid and update references
alter table object_attributes add object_uid uuid;
update object_attributes set object_uid = (select uid from objects o where o.id = objectid);
alter table object_attributes alter column object_uid set not null;
alter table object_attributes
add constraint object_attributes_object_uid_fk
FOREIGN KEY (object_uid)
REFERENCES objects(uid)
on delete cascade;
create index object_attributes_object_uid on object_attributes(object_uid);
-- drop old id's
alter table object_attributes drop objectid;
alter table objects drop id;

View File

@ -1,32 +1,32 @@
package postgres
const getMapDataPosQuery = `
select o.uid, o.type, o.mtime,
select o.id, o.type, o.mtime,
o.x, o.y, o.z,
o.posx, o.posy, o.posz,
oa.key, oa.value
from objects o
left join object_attributes oa on o.uid = oa.object_uid
left join object_attributes oa on o.id = oa.objectid
where o.type = $1
and o.posx >= $2 and o.posy >= $3 and o.posz >= $4
and o.posx <= $5 and o.posy <= $6 and o.posz <= $7
order by o.uid
order by o.id
limit $8
`
const getMapDataWithAttributeLikePosQuery = `
select o.uid, o.type, o.mtime,
select o.id, o.type, o.mtime,
o.x, o.y, o.z,
o.posx, o.posy, o.posz,
oa.key, oa.value
from objects o
left join object_attributes oa on o.uid = oa.object_uid
where o.uid in (
select object_uid from object_attributes where key = $8 and value ilike $9
left join object_attributes oa on o.id = oa.objectid
where o.id in (
select objectid from object_attributes where key = $8 and value ilike $9
)
and o.type = $1
and o.posx >= $2 and o.posy >= $3 and o.posz >= $4
and o.posx <= $5 and o.posy <= $6 and o.posz <= $7
order by o.uid
order by o.id
limit $10
`
@ -36,13 +36,14 @@ delete from objects where posx = $1 and posy = $2 and posz = $3
const addMapDataQuery = `
insert into
objects(uid, x,y,z,posx,posy,posz,type,mtime)
values($1, $2, $3, $4, $5, $6, $7, $8, $9)
objects(x,y,z,posx,posy,posz,type,mtime)
values($1, $2, $3, $4, $5, $6, $7, $8)
returning id
`
const addMapDataAttributeQuery = `
insert into
object_attributes(object_uid, key, value)
object_attributes(objectid, key, value)
values($1, $2, $3)
`

View File

@ -2,11 +2,10 @@ package sqlite
import (
"database/sql"
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"unicode/utf8"
"github.com/google/uuid"
"github.com/sirupsen/logrus"
)
@ -43,17 +42,17 @@ func (db *Sqlite3Accessor) GetMapData(q *mapobjectdb.SearchQuery) ([]*mapobjectd
result := make([]*mapobjectdb.MapObject, 0)
var currentObj *mapobjectdb.MapObject
var currentUID string
var currentId *int64
for rows.Next() {
var uid string
var id int64
var Type string
var mtime int64
var x, y, z int
var posx, posy, posz int
var key, value string
err = rows.Scan(&uid, &Type, &mtime,
err = rows.Scan(&id, &Type, &mtime,
&x, &y, &z, &posx, &posy, &posz,
&key, &value,
)
@ -62,8 +61,8 @@ func (db *Sqlite3Accessor) GetMapData(q *mapobjectdb.SearchQuery) ([]*mapobjectd
return nil, err
}
if currentUID == "" || currentUID != uid {
pos := types.NewMapBlockCoords(posx, posy, posz)
if currentId == nil || *currentId != id {
pos := coords.NewMapBlockCoords(posx, posy, posz)
mo := &mapobjectdb.MapObject{
MBPos: pos,
Type: Type,
@ -75,9 +74,10 @@ func (db *Sqlite3Accessor) GetMapData(q *mapobjectdb.SearchQuery) ([]*mapobjectd
}
currentObj = mo
currentUID = uid
currentId = &id
result = append(result, currentObj)
}
currentObj.Attributes[key] = value
@ -86,13 +86,8 @@ func (db *Sqlite3Accessor) GetMapData(q *mapobjectdb.SearchQuery) ([]*mapobjectd
return result, nil
}
func (a *Sqlite3Accessor) RemoveMapData(pos *types.MapBlockCoords) error {
_, err := a.db.Exec(removeMapDataAttributesQuery, pos.X, pos.Y, pos.Z)
if err != nil {
return err
}
_, err = a.db.Exec(removeMapDataQuery, pos.X, pos.Y, pos.Z)
func (db *Sqlite3Accessor) RemoveMapData(pos *coords.MapBlockCoords) error {
_, err := db.db.Exec(removeMapDataQuery, pos.X, pos.Y, pos.Z)
return err
}
@ -111,9 +106,7 @@ func (db *Sqlite3Accessor) AddMapData(data *mapobjectdb.MapObject) error {
}
}
uid := uuid.NewString()
_, err := db.db.Exec(addMapDataQuery,
uid,
res, err := db.db.Exec(addMapDataQuery,
data.X, data.Y, data.Z,
data.MBPos.X, data.MBPos.Y, data.MBPos.Z,
data.Type, data.Mtime)
@ -122,8 +115,16 @@ func (db *Sqlite3Accessor) AddMapData(data *mapobjectdb.MapObject) error {
return err
}
id, err := res.LastInsertId()
if err != nil {
return err
}
for k, v := range data.Attributes {
_, err := db.db.Exec(addMapDataAttributeQuery, uid, k, v)
//TODO: batch insert
_, err := db.db.Exec(addMapDataAttributeQuery, id, k, v)
if err != nil {
return err
}

View File

@ -3,8 +3,8 @@ package sqlite
import (
"fmt"
"io/ioutil"
"mapserver/coords"
"mapserver/mapobjectdb"
"mapserver/types"
"os"
"testing"
)
@ -48,7 +48,7 @@ func TestMapObjects(t *testing.T) {
attrs := make(map[string]string)
attrs["X"] = "y"
pos := types.NewMapBlockCoords(0, 0, 0)
pos := coords.NewMapBlockCoords(0, 0, 0)
o := mapobjectdb.MapObject{
MBPos: pos,
@ -105,7 +105,7 @@ func TestMapObjectsQueryWithAttribute(t *testing.T) {
attrs := make(map[string]string)
attrs["X"] = "y"
pos := types.NewMapBlockCoords(0, 0, 0)
pos := coords.NewMapBlockCoords(0, 0, 0)
o := mapobjectdb.MapObject{
MBPos: pos,
@ -169,7 +169,7 @@ func TestMapObjectsQueryWithAttributeIgnoreCase(t *testing.T) {
attrs := make(map[string]string)
attrs["X"] = "ABC"
pos := types.NewMapBlockCoords(0, 0, 0)
pos := coords.NewMapBlockCoords(0, 0, 0)
o := mapobjectdb.MapObject{
MBPos: pos,

View File

@ -2,45 +2,47 @@ package sqlite
import (
"database/sql"
"embed"
"mapserver/public"
"time"
"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database/sqlite3"
"github.com/golang-migrate/migrate/v4/source/iofs"
"github.com/sirupsen/logrus"
_ "modernc.org/sqlite"
)
//go:embed migrations/*.sql
var migrations embed.FS
type Sqlite3Accessor struct {
db *sql.DB
db *sql.DB
filename string
}
func (a *Sqlite3Accessor) Migrate() error {
driver, err := sqlite3.WithInstance(a.db, &sqlite3.Config{})
func (db *Sqlite3Accessor) Migrate() error {
log.WithFields(logrus.Fields{"filename": db.filename}).Info("Migrating database")
start := time.Now()
sql, err := public.Files.ReadFile("sql/sqlite_mapobjectdb_migrate.sql")
if err != nil {
return err
}
d, err := iofs.New(migrations, "migrations")
_, err = db.db.Exec(string(sql))
if err != nil {
return err
}
m, err := migrate.NewWithInstance("iofs", d, "sqlite", driver)
if err != nil {
return err
}
err = m.Up()
if err != nil && err != migrate.ErrNoChange {
return err
}
v, _, _ := m.Version()
logrus.WithFields(logrus.Fields{"version": v}).Info("DB Migrated")
t := time.Now()
elapsed := t.Sub(start)
log.WithFields(logrus.Fields{"elapsed": elapsed}).Info("Migration completed")
return nil
}
func (db *Sqlite3Accessor) EnableSpeedSafetyTradeoff(enableSpeed bool) error {
if enableSpeed {
_, err := db.db.Exec("PRAGMA journal_mode = MEMORY; PRAGMA synchronous = OFF;")
return err
} else {
_, err := db.db.Exec("PRAGMA journal_mode = TRUNCATE; PRAGMA synchronous = ON;")
return err
}
}

View File

@ -1,37 +0,0 @@
-- recreate tables (can't add a referential constraint on an existing table)
create table objects_ng(
uid text primary key not null,
x int,
y int,
z int,
posx int,
posy int,
posz int,
type varchar,
mtime bigint
);
create table object_attributes_ng(
object_uid text not null,
key varchar not null,
value varchar not null,
FOREIGN KEY (object_uid) references objects_ng(uid) ON DELETE CASCADE
primary key(object_uid, key)
);
-- migrate data
insert into objects_ng(uid,x,y,z,posx,posy,posz,type,mtime)
select id,x,y,z,posx,posy,posz,type,mtime from objects;
insert into object_attributes_ng(object_uid, key, value)
select objectid, key, value from object_attributes;
-- remove old tables
drop table object_attributes;
drop table objects;
-- rename tables
alter table objects_ng rename to objects;
alter table object_attributes_ng rename to object_attributes;
-- journal mode, just in case
pragma journal_mode=wal;

Some files were not shown because too many files have changed in this diff Show More