From 7c80f1e7c08b1ec08c768085af44d36586445e46 Mon Sep 17 00:00:00 2001 From: Tnze Date: Thu, 16 Jun 2022 15:46:30 +0800 Subject: [PATCH] delete ecs system --- examples/dazeReadCommand/daze.go | 158 ++++++++++++++++++++++++++++++ examples/frameworkServer/main.go | 10 -- server/client.go | 4 +- server/ecs/bitset.go | 96 ------------------ server/ecs/bitset_test.go | 28 ------ server/ecs/dispatcher.go | 44 --------- server/ecs/ecs_test.go | 34 ------- server/ecs/storage.go | 75 -------------- server/ecs/system.go | 70 ------------- server/ecs/system_test.go | 13 --- server/ecs/world.go | 90 ----------------- server/gameplay.go | 69 +------------ server/keepalive.go | 6 -- server/player/player.go | 124 ----------------------- server/player/playerinfo.go | 163 ------------------------------- server/player/pool.go | 37 ------- server/server.go | 4 +- server/world/Dimension.snbt | 17 ---- server/world/DimensionCodec.snbt | 1 - server/world/pool.go | 74 -------------- server/world/world.go | 63 ------------ 21 files changed, 166 insertions(+), 1014 deletions(-) create mode 100644 examples/dazeReadCommand/daze.go delete mode 100644 server/ecs/bitset.go delete mode 100644 server/ecs/bitset_test.go delete mode 100644 server/ecs/dispatcher.go delete mode 100644 server/ecs/ecs_test.go delete mode 100644 server/ecs/storage.go delete mode 100644 server/ecs/system.go delete mode 100644 server/ecs/system_test.go delete mode 100644 server/ecs/world.go delete mode 100644 server/player/player.go delete mode 100644 server/player/playerinfo.go delete mode 100644 server/player/pool.go delete mode 100644 server/world/Dimension.snbt delete mode 100644 server/world/DimensionCodec.snbt delete mode 100644 server/world/pool.go delete mode 100644 server/world/world.go diff --git a/examples/dazeReadCommand/daze.go b/examples/dazeReadCommand/daze.go new file mode 100644 index 0000000..787fb43 --- /dev/null +++ b/examples/dazeReadCommand/daze.go @@ -0,0 +1,158 @@ +// Daze could join an offline-mode server as client. +// Just standing there and do nothing. Automatically reborn after five seconds of death. +package main + +import ( + "flag" + "io" + "log" + "strconv" + + //"github.com/mattn/go-colorable" + + "github.com/Tnze/go-mc/bot" + "github.com/Tnze/go-mc/bot/basic" + "github.com/Tnze/go-mc/bot/screen" + _ "github.com/Tnze/go-mc/data/lang/zh-cn" + "github.com/Tnze/go-mc/data/packetid" + pk "github.com/Tnze/go-mc/net/packet" +) + +var address = flag.String("address", "127.0.0.1", "The server address") +var client *bot.Client +var player *basic.Player +var screenManager *screen.Manager + +func main() { + flag.Parse() + //log.SetOutput(colorable.NewColorableStdout()) + client = bot.NewClient() + client.Auth.Name = "Daze" + player = basic.NewPlayer(client, basic.DefaultSettings) + client.Events.AddListener(bot.PacketHandler{ + ID: packetid.ClientboundCommands, + Priority: 50, + F: onCommands, + }) + + //Login + err := client.JoinServer(*address) + if err != nil { + log.Fatal(err) + } + log.Println("Login success") + + //JoinGame + for { + if err = client.HandleGame(); err == nil { + panic("HandleGame never return nil") + } + log.Fatal(err) + } +} + +func onCommands(p pk.Packet) error { + var nodes []Node + var root pk.VarInt + err := p.Scan(pk.Array(&nodes), &root) + if err != nil { + return err + } + log.Printf("Root index: %d", root) + return nil +} + +type Node struct { +} + +func (n Node) ReadFrom(r io.Reader) (int64, error) { + var Flags pk.Byte + var Children []pk.VarInt + var Redirect pk.VarInt + var Name pk.String + var Parser pk.Identifier + var Properties = Prop{Type: &Parser} + var SuggestionsType pk.Identifier + m, err := pk.Tuple{ + &Flags, + pk.Array(&Children), + pk.Opt{ + Has: func() bool { return Flags&0x08 != 0 }, + Field: &Redirect, + }, + pk.Opt{ + Has: func() bool { return Flags&0x03 == 2 || Flags&0x03 == 1 }, + Field: &Name, + }, + pk.Opt{ + Has: func() bool { return Flags&0x03 == 2 }, + Field: pk.Tuple{&Parser, &Properties}, + }, + pk.Opt{ + Has: func() bool { return Flags&0x10 != 0 }, + Field: &SuggestionsType, + }, + }.ReadFrom(r) + if err != nil { + return m, err + } + var redirect string + if Flags&0x08 != 0 { + redirect = "Redirect: " + strconv.Itoa(int(Redirect)) + } + var parser string + if Flags&0x03 == 2 { + redirect = string("Parser: " + Parser) + } + log.Printf("Type: %2d\tName: %s\tChildren: %v\t%v\t%v", Flags&0x03, Name, Children, redirect, parser) + + return m, nil +} + +type Prop struct { + Type *pk.Identifier +} + +func (p Prop) ReadFrom(r io.Reader) (int64, error) { + var Flags pk.Byte + switch *p.Type { + case "brigadier:double": + var Min, Max pk.Double + return pk.Tuple{ + &Flags, + pk.Opt{Has: func() bool { return Flags&0x01 != 0 }, Field: &Min}, + pk.Opt{Has: func() bool { return Flags&0x02 != 0 }, Field: &Max}, + }.ReadFrom(r) + case "brigadier:float": + var Min, Max pk.Float + return pk.Tuple{ + &Flags, + pk.Opt{Has: func() bool { return Flags&0x01 != 0 }, Field: &Min}, + pk.Opt{Has: func() bool { return Flags&0x02 != 0 }, Field: &Max}, + }.ReadFrom(r) + case "brigadier:integer": + var Min, Max pk.Int + return pk.Tuple{ + &Flags, + pk.Opt{Has: func() bool { return Flags&0x01 != 0 }, Field: &Min}, + pk.Opt{Has: func() bool { return Flags&0x02 != 0 }, Field: &Max}, + }.ReadFrom(r) + case "brigadier:long": + var Min, Max pk.Long + return pk.Tuple{ + &Flags, + pk.Opt{Has: func() bool { return Flags&0x01 != 0 }, Field: &Min}, + pk.Opt{Has: func() bool { return Flags&0x02 != 0 }, Field: &Max}, + }.ReadFrom(r) + case "brigadier:string": + return new(pk.VarInt).ReadFrom(r) + case "minecraft:entity": + return new(pk.Byte).ReadFrom(r) + case "minecraft:score_holder": + return new(pk.Byte).ReadFrom(r) + case "minecraft:range": + return new(pk.Boolean).ReadFrom(r) + default: + return 0, nil + } +} diff --git a/examples/frameworkServer/main.go b/examples/frameworkServer/main.go index 3c5be61..de22c0b 100644 --- a/examples/frameworkServer/main.go +++ b/examples/frameworkServer/main.go @@ -4,8 +4,6 @@ import ( "context" _ "embed" "flag" - "github.com/Tnze/go-mc/server/ecs" - "github.com/Tnze/go-mc/server/world" "image" _ "image/png" "log" @@ -14,7 +12,6 @@ import ( "github.com/Tnze/go-mc/chat" "github.com/Tnze/go-mc/server" "github.com/Tnze/go-mc/server/command" - "github.com/Tnze/go-mc/server/player" ) var motd = chat.Message{Text: "A Minecraft Server ", Extra: []chat.Message{{Text: "Powered by go-mc", Color: "yellow"}}} @@ -57,13 +54,6 @@ func main() { keepAlive, commands, ) - ecs.Register[world.Dimension, *ecs.HashMapStorage[world.Dimension]](game.World) - dimList := world.NewDimensionManager(game) - dimList.Add(game.CreateEntity(world.NewDimension( - "minecraft:overworld", *regionPath, - )), "minecraft:overworld") - player.SpawnSystem(game, *playerdataPath) - player.PosAndRotSystem(game) go game.Run(context.Background()) s := server.Server{ diff --git a/server/client.go b/server/client.go index cd57d70..5ab67ea 100644 --- a/server/client.go +++ b/server/client.go @@ -9,13 +9,11 @@ import ( "github.com/Tnze/go-mc/net" pk "github.com/Tnze/go-mc/net/packet" - "github.com/Tnze/go-mc/server/ecs" ) type Client struct { *net.Conn - Protocol int32 - ecs.Index + Protocol int32 packetQueue *PacketQueue errChan chan error } diff --git a/server/ecs/bitset.go b/server/ecs/bitset.go deleted file mode 100644 index 8bf9371..0000000 --- a/server/ecs/bitset.go +++ /dev/null @@ -1,96 +0,0 @@ -package ecs - -import ( - "golang.org/x/exp/constraints" - "math/bits" - "unsafe" -) - -const uintsize = uint(unsafe.Sizeof(BitSet{}.values[0])) - -type BitSet struct { - // TODO: this is not a BitSet, I'm just testing - values []uint -} - -func (b *BitSet) Set(i Index) (old bool) { - index := uint(i) / uintsize - offset := uint(i) % uintsize - if index >= uint(len(b.values)) { - if index < uint(cap(b.values)) { - b.values = b.values[:index] - } else { - newValues := make([]uint, index+1) - copy(newValues, b.values) - b.values = newValues - } - } - v := &b.values[index] - mask := uint(1 << offset) - old = *v&mask != 0 - *v |= mask - return -} - -func (b *BitSet) Unset(i Index) (old bool) { - index := uint(i) / uintsize - offset := uint(i) % uintsize - if index < uint(len(b.values)) { - v := &b.values[index] - mask := uint(1 << offset) - old = *v&mask != 0 - *v &= ^mask - } - return -} - -func (b *BitSet) Contains(i Index) bool { - index := uint(i) / uintsize - offset := uint(i) % uintsize - return index < uint(len(b.values)) && b.values[index]&(1< b { - return a - } - return b -} - -func min[T constraints.Integer](a, b T) T { - if a < b { - return a - } - return b -} diff --git a/server/ecs/bitset_test.go b/server/ecs/bitset_test.go deleted file mode 100644 index ad82bbf..0000000 --- a/server/ecs/bitset_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package ecs - -import ( - "reflect" - "testing" -) - -func TestBitSet_And(t *testing.T) { - var set1, set2 BitSet - - set1.Set(1) - set1.Set(3) - set1.Set(40) - - set2.Set(2) - set2.Set(3) - set2.Set(9) - set2.Set(40) - - var results []Index - set1.And(&set2).Range(func(eid Index) { - results = append(results, eid) - }) - want := []Index{3, 40} - if !reflect.DeepEqual(results, want) { - t.Errorf("want %v, got: %v", want, results) - } -} diff --git a/server/ecs/dispatcher.go b/server/ecs/dispatcher.go deleted file mode 100644 index 3f0c2eb..0000000 --- a/server/ecs/dispatcher.go +++ /dev/null @@ -1,44 +0,0 @@ -package ecs - -import "sync" - -type Dispatcher struct { - waiters map[string][]*sync.WaitGroup - tasks []func(w *World, wg *sync.WaitGroup) -} - -func NewDispatcher() *Dispatcher { - return &Dispatcher{ - waiters: make(map[string][]*sync.WaitGroup), - tasks: nil, - } -} - -func (d *Dispatcher) Add(s System, name string, deps []string) { - var start sync.WaitGroup - start.Add(len(deps)) - for _, dep := range deps { - if wg, ok := d.waiters[dep]; ok { - d.waiters[dep] = append(wg, &start) - } else { - panic("Unknown deps: " + dep) - } - } - d.tasks = append(d.tasks, func(w *World, done *sync.WaitGroup) { - start.Wait() - defer done.Done() - s.Update(w) - for _, wg := range d.waiters[name] { - wg.Done() - } - }) -} - -func (d *Dispatcher) Run(w *World) { - var wg sync.WaitGroup - wg.Add(len(d.tasks)) - for _, f := range d.tasks { - go f(w, &wg) - } - wg.Wait() -} diff --git a/server/ecs/ecs_test.go b/server/ecs/ecs_test.go deleted file mode 100644 index b8374bb..0000000 --- a/server/ecs/ecs_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package ecs - -import "testing" - -func Test_common(t *testing.T) { - // W - w := NewWorld() - // C - type pos [2]int - type vel [2]int - Register[pos, *HashMapStorage[pos]](w) - Register[vel, *HashMapStorage[vel]](w) - // E - e1 := w.CreateEntity(pos{0, 0}) - w.CreateEntity(vel{1, 2}) - w.CreateEntity(pos{1, 2}, vel{2, 0}) - // S - s1 := FuncSystem(func(p *pos) { - t.Log("system 1", p) - }) - s2 := FuncSystem(func(p *pos, v *vel) { - t.Log("system 2", p, v) - }) - s3 := FuncSystem(func(p pos, v *vel) { - t.Log("system 2", p, v) - }) - // Run - s1.Update(w) - s2.Update(w) - s3.Update(w) - - w.DeleteEntity(e1) - s1.Update(w) -} diff --git a/server/ecs/storage.go b/server/ecs/storage.go deleted file mode 100644 index f99a766..0000000 --- a/server/ecs/storage.go +++ /dev/null @@ -1,75 +0,0 @@ -package ecs - -import ( - "reflect" - "strconv" - "unsafe" -) - -type Index uint32 - -type Storage[T any] interface { - Init() - GetValue(eid Index) *T - SetValue(eid Index, v T) - DelValue(eid Index) -} - -type HashMapStorage[T any] struct { - values map[Index]*T -} - -func (h *HashMapStorage[T]) Init() { h.values = make(map[Index]*T) } -func (h *HashMapStorage[T]) Len() int { return len(h.values) } -func (h *HashMapStorage[T]) GetValue(eid Index) *T { return h.values[eid] } -func (h *HashMapStorage[T]) SetValue(eid Index, v T) { h.values[eid] = &v } -func (h *HashMapStorage[T]) DelValue(eid Index) { delete(h.values, eid) } -func (h *HashMapStorage[T]) Range(f func(eid Index, value *T)) { - for i, v := range h.values { - f(i, v) - } -} - -type NullStorage[T any] struct{} - -func (NullStorage[T]) Init() { - var v T - if size := unsafe.Sizeof(v); size != 0 { - typeName := reflect.TypeOf(v).String() - typeSize := strconv.Itoa(int(size)) - panic("NullStorage can only be used with ZST, " + typeName + " has size of " + typeSize) - } -} -func (NullStorage[T]) GetValue(eid Index) *T { return nil } -func (NullStorage[T]) SetValue(eid Index, v T) {} -func (NullStorage[T]) DelValue(eid Index) {} - -type MaskedStorage[T any] struct { - BitSet - Storage[T] - Len int -} - -func (m *MaskedStorage[T]) Init() { - m.Storage.Init() -} -func (m *MaskedStorage[T]) GetValue(eid Index) *T { - if m.Contains(eid) { - return m.Storage.GetValue(eid) - } - return nil -} -func (m *MaskedStorage[T]) GetValueAny(eid Index) any { return m.GetValue(eid) } -func (m *MaskedStorage[T]) SetValue(eid Index, v T) { - if !m.BitSet.Set(eid) { - m.Len++ - } - m.Storage.SetValue(eid, v) -} -func (m *MaskedStorage[T]) SetAny(eid Index, v any) { m.SetValue(eid, v.(T)) } -func (m *MaskedStorage[T]) DelValue(eid Index) { - if m.BitSet.Unset(eid) { - m.Len-- - } - m.Storage.DelValue(eid) -} diff --git a/server/ecs/system.go b/server/ecs/system.go deleted file mode 100644 index bb6aab1..0000000 --- a/server/ecs/system.go +++ /dev/null @@ -1,70 +0,0 @@ -package ecs - -import ( - "reflect" -) - -type System interface { - Update(w *World) -} - -type funcsystem struct { - update func(w *World) -} - -func FuncSystem(F any) System { - type Storage interface { - GetValueAny(eid Index) any - And(*BitSet) *BitSet - Range(f func(eid Index)) - } - f := reflect.ValueOf(F) - in := f.Type().NumIn() - argTypes := make([]reflect.Type, in) - needCopy := make([]bool, in) - for i := 0; i < in; i++ { - if t := f.Type().In(i); t.Kind() == reflect.Pointer { - argTypes[i] = t.Elem() - } else { - argTypes[i] = t - needCopy[i] = true - } - } - return &funcsystem{ - update: func(w *World) { - storages := make([]reflect.Value, in) - for i := 0; i < in; i++ { - storages[i] = reflect.ValueOf(w.GetResourceRaw(argTypes[i])) - } - args := make([]reflect.Value, len(storages)) - if len(storages) > 0 { - set := reflect.Indirect(storages[0]).FieldByName("BitSet").Addr() - for _, v := range storages[1:] { - p := reflect.Indirect(v).FieldByName("BitSet").Addr() - set = set.MethodByName("And").Call([]reflect.Value{p})[0] - } - set.MethodByName("Range").Call([]reflect.Value{ - reflect.ValueOf(func(eid Index) { - for i := range args { - arg := storages[i].MethodByName("GetValue").Call([]reflect.Value{reflect.ValueOf(eid)})[0] - if arg.IsNil() { - args[i] = reflect.Zero(argTypes[i]) - } else if needCopy[i] { - args[i] = arg.Elem() - } else { - args[i] = arg - } - } - f.Call(args) - }), - }) - } else { - f.Call(args) - } - }, - } -} - -func (f *funcsystem) Update(w *World) { - f.update(w) -} diff --git a/server/ecs/system_test.go b/server/ecs/system_test.go deleted file mode 100644 index 5b60e00..0000000 --- a/server/ecs/system_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package ecs - -type PositionComponent struct { - X, Y int -} - -type MySystem1 struct { - *PositionComponent -} - -func (s *MySystem1) Update(w *World) { - -} diff --git a/server/ecs/world.go b/server/ecs/world.go deleted file mode 100644 index d2d37d3..0000000 --- a/server/ecs/world.go +++ /dev/null @@ -1,90 +0,0 @@ -package ecs - -import ( - "reflect" - "sync/atomic" -) - -type World struct { - resources map[reflect.Type]any - maxEID Index -} - -func NewWorld() *World { - return &World{resources: make(map[reflect.Type]any)} -} - -func SetResource[Res any](w *World, v Res) *Res { - w.resources[reflect.TypeOf(v)] = &v - return &v -} - -func (w *World) Remove(resource any) any { - t := reflect.ValueOf(resource).Type() - resource = w.resources[t] - delete(w.resources, t) - return resource -} - -func GetResource[Res any](w *World) *Res { - var res Res - t := reflect.TypeOf(res) - if v, ok := w.resources[t]; ok { - return v.(*Res) - } - panic("Resource " + t.Name() + " not found") -} - -func (w *World) GetResourceRaw(t reflect.Type) any { - v, _ := w.resources[t] - return v -} - -func GetComponent[T any](w *World) *MaskedStorage[T] { - var value T - t := reflect.ValueOf(value).Type() - if res, ok := w.resources[t]; ok { - return res.(*MaskedStorage[T]) - } - panic("Component " + t.Name() + " not found") -} - -// Register the component with the storage. -// -// Will be changed to func (w *World) Register[C Component]() after Go support it -func Register[T any, S Storage[T]](w *World) { - var value T - t := reflect.TypeOf(value) - if _, ok := w.resources[t]; ok { - panic("Component " + t.Name() + " already exist") - } - var storage S - var storageInt Storage[T] - storageType := reflect.TypeOf(storage) - if storageType.Kind() == reflect.Pointer { - storageInt = reflect.New(storageType.Elem()).Interface().(Storage[T]) - } else { - storageInt = storage - } - ms := MaskedStorage[T]{Storage: storageInt} - ms.Init() - w.resources[t] = &ms -} - -func (w *World) CreateEntity(components ...any) (i Index) { - type Storage interface{ SetAny(Index, any) } - eid := Index(atomic.AddUint32((*uint32)(&w.maxEID), 1)) - for _, c := range components { - w.resources[reflect.TypeOf(c)].(Storage).SetAny(eid, c) - } - return eid -} - -func (w *World) DeleteEntity(eid Index) { - type Storage interface{ Del(eid Index) } - for _, r := range w.resources { - if c, ok := r.(Storage); ok { - c.Del(eid) - } - } -} diff --git a/server/gameplay.go b/server/gameplay.go index f0543c1..0b114dc 100644 --- a/server/gameplay.go +++ b/server/gameplay.go @@ -9,8 +9,6 @@ import ( "github.com/google/uuid" "github.com/Tnze/go-mc/net" - pk "github.com/Tnze/go-mc/net/packet" - "github.com/Tnze/go-mc/server/ecs" ) type GamePlay interface { @@ -22,13 +20,15 @@ type GamePlay interface { } type Game struct { - *ecs.World - *ecs.Dispatcher WorldLocker sync.Mutex handlers map[int32][]*PacketHandler components []Component } +func (g *Game) AcceptPlayer(name string, id uuid.UUID, protocol int32, conn *net.Conn) { + conn.Close() +} + type PacketHandler struct { ID int32 F packetHandlerFunc @@ -45,16 +45,12 @@ type Component interface { func NewGame(components ...Component) *Game { g := &Game{ - World: ecs.NewWorld(), - Dispatcher: ecs.NewDispatcher(), handlers: make(map[int32][]*PacketHandler), components: components, } for _, c := range components { c.Init(g) } - ecs.Register[Client, *ecs.HashMapStorage[Client]](g.World) - ecs.Register[Player, *ecs.HashMapStorage[Player]](g.World) return g } @@ -71,65 +67,10 @@ func (g *Game) Run(ctx context.Context) { select { case <-ticker.C: g.WorldLocker.Lock() - g.Dispatcher.Run(g.World) + //g.Dispatcher.Run(g.World) g.WorldLocker.Unlock() case <-ctx.Done(): return } } } - -func (g *Game) AcceptPlayer(name string, id uuid.UUID, protocol int32, conn *net.Conn) { - g.WorldLocker.Lock() - eid := g.CreateEntity( - Client{ - Conn: conn, - Protocol: protocol, - packetQueue: NewPacketQueue(), - errChan: make(chan error, 1), - }, - Player{ - UUID: id, - Name: name, - }, - ) - c := ecs.GetComponent[Client](g.World).GetValue(eid) - p := ecs.GetComponent[Player](g.World).GetValue(eid) - g.WorldLocker.Unlock() - defer c.packetQueue.Close() - - go func() { - for { - packet, ok := c.packetQueue.Pull() - if !ok { - break - } - err := c.Conn.WritePacket(packet) - if err != nil { - c.PutErr(err) - break - } - } - }() - - var err error - for _, component := range g.components { - component.ClientJoin(c, p) - defer func(cmp Component) { cmp.ClientLeft(c, p, err) }(component) - } - - var packet pk.Packet - for { - if err = c.ReadPacket(&packet); err != nil { - return - } - for _, ph := range g.handlers[packet.ID] { - if err = ph.F(c, p, Packet758(packet)); err != nil { - return - } - if err = c.GetErr(); err != nil { - return - } - } - } -} diff --git a/server/keepalive.go b/server/keepalive.go index fa267bc..3401d6a 100644 --- a/server/keepalive.go +++ b/server/keepalive.go @@ -8,7 +8,6 @@ import ( "github.com/Tnze/go-mc/data/packetid" pk "github.com/Tnze/go-mc/net/packet" - "github.com/Tnze/go-mc/server/ecs" ) // keepAliveInterval represents the interval when the server sends keep alive @@ -58,11 +57,6 @@ func (k *KeepAlive) AddPlayerDelayUpdateHandler(f func(p *Client, delay time.Dur // Init implement Component for KeepAlive func (k *KeepAlive) Init(g *Game) { - ecs.Register[ClientDelay, *ecs.HashMapStorage[ClientDelay]](g.World) - k.AddPlayerDelayUpdateHandler(func(p *Client, delay time.Duration) { - c := ClientDelay{Delay: delay} - ecs.GetComponent[ClientDelay](g.World).SetValue(p.Index, c) - }) g.AddHandler(&PacketHandler{ ID: packetid.ServerboundKeepAlive, F: func(client *Client, player *Player, packet Packet758) error { diff --git a/server/player/player.go b/server/player/player.go deleted file mode 100644 index 066011e..0000000 --- a/server/player/player.go +++ /dev/null @@ -1,124 +0,0 @@ -package player - -import ( - "fmt" - "github.com/Tnze/go-mc/data/packetid" - pk "github.com/Tnze/go-mc/net/packet" - "github.com/Tnze/go-mc/server" - "github.com/Tnze/go-mc/server/ecs" - "github.com/Tnze/go-mc/server/world" -) - -type PlayerProfile struct { - Dim ecs.Index -} - -type playerSpawnSystem struct { - storage -} - -func (p playerSpawnSystem) Update(w *ecs.World) { - clients := ecs.GetComponent[server.Client](w) - players := ecs.GetComponent[server.Player](w) - pos, rot := ecs.GetComponent[server.Pos](w), ecs.GetComponent[server.Rot](w) - profiles := ecs.GetComponent[PlayerProfile](w) - dimensionRes := ecs.GetResource[world.DimensionList](w) - players.AndNot(profiles.BitSet).Range(func(eid ecs.Index) { - player := players.GetValue(eid) - client := clients.GetValue(eid) - profile, err := p.GetPlayer(player.UUID) - if err != nil { - client.PutErr(fmt.Errorf("read player data fail: %w", err)) - return - } - dim, ok := dimensionRes.Find(profile.Dimension) - if !ok { - panic("dimension " + profile.Dimension + " not found") - } - profiles.SetValue(eid, PlayerProfile{Dim: dim}) - pos.SetValue(eid, server.Pos{ - X: profile.Pos[0], - Y: profile.Pos[1], - Z: profile.Pos[2], - }) - rot.SetValue(eid, server.Rot{ - Yaw: profile.Rotation[0], - Pitch: profile.Rotation[1], - }) - client.WritePacket(server.Packet758(pk.Marshal( - packetid.ClientboundLogin, - pk.Int(eid), // Entity ID - pk.Boolean(false), // Is hardcore - pk.Byte(profile.PlayerGameType), // Gamemode - pk.Byte(-1), // Prev Gamemode - dimensionRes, - pk.NBT(dimensionRes.DimCodecSNBT), - pk.NBT(dimensionRes.DimSNBT), - pk.Identifier(profile.Dimension), // World Name - pk.Long(1234567), // Hashed seed - pk.VarInt(0), // Max Players (Ignored by client) - pk.VarInt(15), // View Distance - pk.VarInt(15), // Simulation Distance - pk.Boolean(false), // Reduced Debug Info - pk.Boolean(true), // Enable respawn screen - pk.Boolean(false), // Is Debug - pk.Boolean(true), // Is Flat - ))) - }) -} - -func SpawnSystem(g *server.Game, playerdataPath string) { - ecs.Register[PlayerProfile, *ecs.HashMapStorage[PlayerProfile]](g.World) - g.Dispatcher.Add( - playerSpawnSystem{storage: storage{playerdataPath}}, - "go-mc:player:SpawnSystem", - nil, - ) -} - -// PosAndRotSystem add a system to g.Dispatcher that -// receive player movement packets and update Pos and Rot component -// Require component Pos and Rot to be registered before. -func PosAndRotSystem(g *server.Game) { - type posUpdate struct { - ecs.Index - server.Pos - } - updateChan := make(chan posUpdate) - ecs.Register[server.Pos, *ecs.HashMapStorage[server.Pos]](g.World) - ecs.Register[server.Rot, *ecs.HashMapStorage[server.Rot]](g.World) - g.Dispatcher.Add(ecs.FuncSystem(func() { - posStorage := ecs.GetComponent[server.Pos](g.World) - for { - select { - case event := <-updateChan: - if v := posStorage.GetValue(event.Index); v != nil { - *v = event.Pos - } - default: - return - } - } - }), "go-mc:player:PosAndRotSystem", nil) - - g.AddHandler(&server.PacketHandler{ - ID: packetid.ServerboundMovePlayerPos, - F: func(client *server.Client, player *server.Player, packet server.Packet758) error { - var X, FeetY, Z pk.Double - var OnGround pk.Boolean - err := pk.Packet(packet).Scan(&X, &FeetY, &Z, &OnGround) - if err != nil { - return err - } - updateChan <- posUpdate{ - Index: client.Index, - Pos: server.Pos{ - X: float64(X), - Y: float64(FeetY), - Z: float64(Z), - }, - } - return nil - }, - }) -} diff --git a/server/player/playerinfo.go b/server/player/playerinfo.go deleted file mode 100644 index dbb145a..0000000 --- a/server/player/playerinfo.go +++ /dev/null @@ -1,163 +0,0 @@ -package player - -//import ( -// "context" -// "io" -// "time" -// -// "github.com/Tnze/go-mc/data/packetid" -// pk "github.com/Tnze/go-mc/net/packet" -// "github.com/Tnze/go-mc/server" -// "github.com/Tnze/go-mc/server/ecs" -//) -// -//type PlayerInfo struct { -// updateDelay chan playerDelayUpdate -// quit chan clientAndPlayer -//} -//type clientAndPlayer struct { -// *server.Client -// *server.Player -//} -// -//type playerInfoList struct { -// players ecs.MaskedStorage[server.Player] -// delays ecs.MaskedStorage[server.ClientDelay] -//} -// -//func (p playerInfoList) WriteTo(w io.Writer) (n int64, err error) { -// n, err = pk.VarInt(p.players.Len).WriteTo(w) -// if err != nil { -// return -// } -// var n1 int64 -// p.players.And(p.delays.BitSetLike).Range(func(eid ecs.Index) { -// p := playerDelayUpdate{ -// player: p.players.Get(eid), -// delay: p.delays.Get(eid).Delay, -// } -// n1, err = p.WriteTo(w) -// n += n1 -// if err != nil { -// return -// } -// }) -// return -//} -// -//type playerDelayUpdate struct { -// player *server.Player -// delay time.Duration -//} -// -//func (p playerDelayUpdate) WriteTo(w io.Writer) (n int64, err error) { -// return pk.Tuple{ -// pk.UUID(p.player.UUID), -// pk.VarInt(p.delay.Milliseconds()), -// }.WriteTo(w) -//} -// -//const ( -// actionAddPlayer = iota -// actionUpdateGamemode -// actionUpdateLatency -// actionUpdateDisplayName -// actionRemovePlayer -//) -// -//type DelaySource interface { -// AddPlayerDelayUpdateHandler(f func(c *server.Client, p *server.Player, delay time.Duration)) -//} -// -//func NewPlayerInfo(delaySource DelaySource) *PlayerInfo { -// updateChan := make(chan playerDelayUpdate) -// p := &PlayerInfo{ -// updateDelay: updateChan, -// quit: make(chan clientAndPlayer), -// } -// if delaySource != nil { -// delaySource.AddPlayerDelayUpdateHandler(func(client *server.Client, player *server.Player, delay time.Duration) { -// updateChan <- playerDelayUpdate{player: player, delay: delay} -// }) -// } -// return p -//} -// -//type playerInfoSystemJoin struct{} -// -//func (p playerInfoSystemJoin) Update(w *ecs.World) { -// clients := ecs.GetComponent[server.Client](w) -// players := ecs.GetComponent[server.Player](w) -// delays := ecs.GetComponent[server.ClientDelay](w) -//} -// -//func (p *PlayerInfo) Init(g *server.Game) { -// var delayBuffer []playerDelayUpdate -// clients := ecs.GetComponent[server.Client](g.World) -// players := ecs.GetComponent[server.Player](g.World) -// delays := ecs.GetComponent[server.ClientDelay](g.World) -// g.Dispatcher.Add(ecs.FuncSystem(func(client *server.Client, player *server.Player, delay server.ClientDelay) { -// info := server.ClientDelay{Delay: 0} -// pack := server.Packet758(pk.Marshal( -// packetid.ClientboundPlayerInfo, -// pk.VarInt(actionAddPlayer), -// pk.VarInt(1), -// -// pk.UUID(player.UUID), -// pk.String(player.Name), -// pk.Array([]pk.FieldEncoder{}), -// pk.VarInt(profile.Gamemode), -// pk.VarInt(0), -// pk.Boolean(false), -// )) -// delays.Set(client.Index, info) -// clients.Range(func(eid ecs.Index) { -// clients.Get(eid).WritePacket(pack) -// }) -// client.WritePacket(server.Packet758(pk.Marshal( -// packetid.ClientboundPlayerInfo, -// pk.VarInt(actionAddPlayer), -// playerInfoList{players: players, delays: delays}, -// ))) -// }), "PlayerInfoSystem:Join", nil) -// g.Dispatcher.Add(ecs.FuncSystem(func() { -// for { -// select { -// case cp := <-p.quit: -// pack := server.Packet758(pk.Marshal( -// packetid.ClientboundPlayerInfo, -// pk.VarInt(actionRemovePlayer), -// pk.VarInt(1), -// pk.UUID(cp.UUID), -// )) -// for _, p := range players.list { -// cp.WritePacket(pack) -// } -// case change := <-p.updateDelay: -// delayBuffer = append(delayBuffer, change) -// default: -// if len(delayBuffer) > 0 { -// pack := server.Packet758(pk.Marshal( -// packetid.ClientboundPlayerInfo, -// pk.VarInt(actionUpdateLatency), -// pk.Array(&delayBuffer), -// )) -// players.Range(func(eid ecs.Index) { -// players.Get(eid).(*server.Client).WritePacket(pack) -// }) -// delayBuffer = delayBuffer[:0] -// } -// return -// } -// } -// }), "PlayerInfoSystem", nil) -//} -// -//func (p *PlayerInfo) Run(context.Context) {} -//func (p *PlayerInfo) ClientJoin(client *server.Client, player *server.Player) {} -//func (p *PlayerInfo) ClientLeft(client *server.Client, player *server.Player) { -// p.quit <- clientAndPlayer{ -// Client: client, -// Player: player, -// } -//} diff --git a/server/player/pool.go b/server/player/pool.go deleted file mode 100644 index 76f40ed..0000000 --- a/server/player/pool.go +++ /dev/null @@ -1,37 +0,0 @@ -package player - -import ( - "compress/gzip" - "os" - "path/filepath" - - "github.com/google/uuid" - - "github.com/Tnze/go-mc/level" - "github.com/Tnze/go-mc/save" -) - -type storage struct { - playerdataDir string -} - -func (s *storage) GetPlayer(id uuid.UUID) (data save.PlayerData, err error) { - filename := id.String() + ".dat" - - f, err := os.Open(filepath.Join(s.playerdataDir, filename)) - if err != nil { - return save.PlayerData{}, err - } - defer f.Close() - - r, err := gzip.NewReader(f) - if err != nil { - return save.PlayerData{}, err - } - - return save.ReadPlayerData(r) -} - -func (s *storage) PutPlayer(pos level.ChunkPos, c *level.Chunk) (err error) { - return nil -} diff --git a/server/server.go b/server/server.go index 1162b83..4776f8e 100644 --- a/server/server.go +++ b/server/server.go @@ -30,8 +30,8 @@ import ( "github.com/Tnze/go-mc/net" ) -const ProtocolName = "1.18.2" -const ProtocolVersion = 758 +const ProtocolName = "1.19" +const ProtocolVersion = 759 type Server struct { ListPingHandler diff --git a/server/world/Dimension.snbt b/server/world/Dimension.snbt deleted file mode 100644 index 86fe858..0000000 --- a/server/world/Dimension.snbt +++ /dev/null @@ -1,17 +0,0 @@ -{ - piglin_safe:0B, - natural:1B, - ambient_light:0.0000000000F, - infiniburn:"#minecraft:infiniburn_overworld", - respawn_anchor_works:0B, - has_skylight:1B, - bed_works:1B, - effects:"minecraft:overworld", - has_raids:1B, - logical_height:384, - coordinate_scale:1.0000000000D, - min_y:-64, - has_ceiling:0B, - ultrawarm:0B, - height:384 -} \ No newline at end of file diff --git a/server/world/DimensionCodec.snbt b/server/world/DimensionCodec.snbt deleted file mode 100644 index 59e3b9a..0000000 --- a/server/world/DimensionCodec.snbt +++ /dev/null @@ -1 +0,0 @@ -{"minecraft:dimension_type":{type:"minecraft:dimension_type",value:[{name:"minecraft:overworld",id:0,element:{piglin_safe:0B,natural:1B,ambient_light:0.0000000000F,infiniburn:"#minecraft:infiniburn_overworld",respawn_anchor_works:0B,has_skylight:1B,bed_works:1B,effects:"minecraft:overworld",has_raids:1B,logical_height:384,coordinate_scale:1.0000000000D,min_y:-64,has_ceiling:0B,ultrawarm:0B,height:384}},{name:"minecraft:overworld_caves",id:1,element:{piglin_safe:0B,natural:1B,ambient_light:0.0000000000F,infiniburn:"#minecraft:infiniburn_overworld",respawn_anchor_works:0B,has_skylight:1B,bed_works:1B,effects:"minecraft:overworld",has_raids:1B,logical_height:384,coordinate_scale:1.0000000000D,min_y:-64,has_ceiling:1B,ultrawarm:0B,height:384}},{name:"minecraft:the_nether",id:2,element:{piglin_safe:1B,natural:0B,ambient_light:0.1000000015F,infiniburn:"#minecraft:infiniburn_nether",respawn_anchor_works:1B,has_skylight:0B,bed_works:0B,effects:"minecraft:the_nether",fixed_time:18000L,has_raids:0B,logical_height:128,coordinate_scale:8.0000000000D,min_y:0,has_ceiling:1B,ultrawarm:1B,height:256}},{name:"minecraft:the_end",id:3,element:{piglin_safe:0B,natural:0B,ambient_light:0.0000000000F,infiniburn:"#minecraft:infiniburn_end",respawn_anchor_works:0B,has_skylight:0B,bed_works:0B,effects:"minecraft:the_end",fixed_time:6000L,has_raids:1B,logical_height:256,coordinate_scale:1.0000000000D,min_y:0,has_ceiling:0B,ultrawarm:0B,height:256}}]},"minecraft:worldgen/biome":{type:"minecraft:worldgen/biome",value:[{name:"minecraft:the_void",id:0,element:{precipitation:none,effects:{sky_color:8103167,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.5000000000F,downfall:0.5000000000F,category:none}},{name:"minecraft:plains",id:1,element:{precipitation:rain,effects:{sky_color:7907327,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.8000000119F,downfall:0.4000000060F,category:plains}},{name:"minecraft:sunflower_plains",id:2,element:{precipitation:rain,effects:{sky_color:7907327,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.8000000119F,downfall:0.4000000060F,category:plains}},{name:"minecraft:snowy_plains",id:3,element:{precipitation:snow,effects:{sky_color:8364543,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.0000000000F,downfall:0.5000000000F,category:icy}},{name:"minecraft:ice_spikes",id:4,element:{precipitation:snow,effects:{sky_color:8364543,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.0000000000F,downfall:0.5000000000F,category:icy}},{name:"minecraft:desert",id:5,element:{precipitation:none,effects:{sky_color:7254527,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:2.0000000000F,downfall:0.0000000000F,category:desert}},{name:"minecraft:swamp",id:6,element:{precipitation:rain,effects:{grass_color_modifier:swamp,sky_color:7907327,foliage_color:6975545,water_fog_color:2302743,fog_color:12638463,water_color:6388580,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.8000000119F,downfall:0.8999999762F,category:swamp}},{name:"minecraft:forest",id:7,element:{precipitation:rain,effects:{sky_color:7972607,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.6999999881F,downfall:0.8000000119F,category:forest}},{name:"minecraft:flower_forest",id:8,element:{precipitation:rain,effects:{sky_color:7972607,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.6999999881F,downfall:0.8000000119F,category:forest}},{name:"minecraft:birch_forest",id:9,element:{precipitation:rain,effects:{sky_color:8037887,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.6000000238F,downfall:0.6000000238F,category:forest}},{name:"minecraft:dark_forest",id:10,element:{precipitation:rain,effects:{grass_color_modifier:dark_forest,sky_color:7972607,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.6999999881F,downfall:0.8000000119F,category:forest}},{name:"minecraft:old_growth_birch_forest",id:11,element:{precipitation:rain,effects:{sky_color:8037887,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.6000000238F,downfall:0.6000000238F,category:forest}},{name:"minecraft:old_growth_pine_taiga",id:12,element:{precipitation:rain,effects:{sky_color:8168447,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.3000000119F,downfall:0.8000000119F,category:taiga}},{name:"minecraft:old_growth_spruce_taiga",id:13,element:{precipitation:rain,effects:{sky_color:8233983,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.2500000000F,downfall:0.8000000119F,category:taiga}},{name:"minecraft:taiga",id:14,element:{precipitation:rain,effects:{sky_color:8233983,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.2500000000F,downfall:0.8000000119F,category:taiga}},{name:"minecraft:snowy_taiga",id:15,element:{precipitation:snow,effects:{sky_color:8625919,water_fog_color:329011,fog_color:12638463,water_color:4020182,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:-0.5000000000F,downfall:0.4000000060F,category:taiga}},{name:"minecraft:savanna",id:16,element:{precipitation:none,effects:{sky_color:7254527,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:2.0000000000F,downfall:0.0000000000F,category:savanna}},{name:"minecraft:savanna_plateau",id:17,element:{precipitation:none,effects:{sky_color:7254527,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:2.0000000000F,downfall:0.0000000000F,category:savanna}},{name:"minecraft:windswept_hills",id:18,element:{precipitation:rain,effects:{sky_color:8233727,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.2000000030F,downfall:0.3000000119F,category:extreme_hills}},{name:"minecraft:windswept_gravelly_hills",id:19,element:{precipitation:rain,effects:{sky_color:8233727,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.2000000030F,downfall:0.3000000119F,category:extreme_hills}},{name:"minecraft:windswept_forest",id:20,element:{precipitation:rain,effects:{sky_color:8233727,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.2000000030F,downfall:0.3000000119F,category:extreme_hills}},{name:"minecraft:windswept_savanna",id:21,element:{precipitation:none,effects:{sky_color:7254527,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:2.0000000000F,downfall:0.0000000000F,category:savanna}},{name:"minecraft:jungle",id:22,element:{precipitation:rain,effects:{sky_color:7842047,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.9499999881F,downfall:0.8999999762F,category:jungle}},{name:"minecraft:sparse_jungle",id:23,element:{precipitation:rain,effects:{sky_color:7842047,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.9499999881F,downfall:0.8000000119F,category:jungle}},{name:"minecraft:bamboo_jungle",id:24,element:{precipitation:rain,effects:{sky_color:7842047,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.9499999881F,downfall:0.8999999762F,category:jungle}},{name:"minecraft:badlands",id:25,element:{precipitation:none,effects:{sky_color:7254527,grass_color:9470285,foliage_color:10387789,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:2.0000000000F,downfall:0.0000000000F,category:mesa}},{name:"minecraft:eroded_badlands",id:26,element:{precipitation:none,effects:{sky_color:7254527,grass_color:9470285,foliage_color:10387789,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:2.0000000000F,downfall:0.0000000000F,category:mesa}},{name:"minecraft:wooded_badlands",id:27,element:{precipitation:none,effects:{sky_color:7254527,grass_color:9470285,foliage_color:10387789,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:2.0000000000F,downfall:0.0000000000F,category:mesa}},{name:"minecraft:meadow",id:28,element:{precipitation:rain,effects:{music:{replace_current_music:0B,max_delay:24000,sound:"minecraft:music.overworld.meadow",min_delay:12000},sky_color:8103167,water_fog_color:329011,fog_color:12638463,water_color:937679,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.5000000000F,downfall:0.8000000119F,category:mountain}},{name:"minecraft:grove",id:29,element:{precipitation:snow,effects:{music:{replace_current_music:0B,max_delay:24000,sound:"minecraft:music.overworld.grove",min_delay:12000},sky_color:8495359,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:-0.2000000030F,downfall:0.8000000119F,category:forest}},{name:"minecraft:snowy_slopes",id:30,element:{precipitation:snow,effects:{music:{replace_current_music:0B,max_delay:24000,sound:"minecraft:music.overworld.snowy_slopes",min_delay:12000},sky_color:8560639,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:-0.3000000119F,downfall:0.8999999762F,category:mountain}},{name:"minecraft:frozen_peaks",id:31,element:{precipitation:snow,effects:{music:{replace_current_music:0B,max_delay:24000,sound:"minecraft:music.overworld.frozen_peaks",min_delay:12000},sky_color:8756735,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:-0.6999999881F,downfall:0.8999999762F,category:mountain}},{name:"minecraft:jagged_peaks",id:32,element:{precipitation:snow,effects:{music:{replace_current_music:0B,max_delay:24000,sound:"minecraft:music.overworld.jagged_peaks",min_delay:12000},sky_color:8756735,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:-0.6999999881F,downfall:0.8999999762F,category:mountain}},{name:"minecraft:stony_peaks",id:33,element:{precipitation:rain,effects:{music:{replace_current_music:0B,max_delay:24000,sound:"minecraft:music.overworld.stony_peaks",min_delay:12000},sky_color:7776511,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:1.0000000000F,downfall:0.3000000119F,category:mountain}},{name:"minecraft:river",id:34,element:{precipitation:rain,effects:{sky_color:8103167,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.5000000000F,downfall:0.5000000000F,category:river}},{name:"minecraft:frozen_river",id:35,element:{precipitation:snow,effects:{sky_color:8364543,water_fog_color:329011,fog_color:12638463,water_color:3750089,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.0000000000F,downfall:0.5000000000F,category:river}},{name:"minecraft:beach",id:36,element:{precipitation:rain,effects:{sky_color:7907327,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.8000000119F,downfall:0.4000000060F,category:beach}},{name:"minecraft:snowy_beach",id:37,element:{precipitation:snow,effects:{sky_color:8364543,water_fog_color:329011,fog_color:12638463,water_color:4020182,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.0500000007F,downfall:0.3000000119F,category:beach}},{name:"minecraft:stony_shore",id:38,element:{precipitation:rain,effects:{sky_color:8233727,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.2000000030F,downfall:0.3000000119F,category:beach}},{name:"minecraft:warm_ocean",id:39,element:{precipitation:rain,effects:{sky_color:8103167,water_fog_color:270131,fog_color:12638463,water_color:4445678,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.5000000000F,downfall:0.5000000000F,category:ocean}},{name:"minecraft:lukewarm_ocean",id:40,element:{precipitation:rain,effects:{sky_color:8103167,water_fog_color:267827,fog_color:12638463,water_color:4566514,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.5000000000F,downfall:0.5000000000F,category:ocean}},{name:"minecraft:deep_lukewarm_ocean",id:41,element:{precipitation:rain,effects:{sky_color:8103167,water_fog_color:267827,fog_color:12638463,water_color:4566514,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.5000000000F,downfall:0.5000000000F,category:ocean}},{name:"minecraft:ocean",id:42,element:{precipitation:rain,effects:{sky_color:8103167,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.5000000000F,downfall:0.5000000000F,category:ocean}},{name:"minecraft:deep_ocean",id:43,element:{precipitation:rain,effects:{sky_color:8103167,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.5000000000F,downfall:0.5000000000F,category:ocean}},{name:"minecraft:cold_ocean",id:44,element:{precipitation:rain,effects:{sky_color:8103167,water_fog_color:329011,fog_color:12638463,water_color:4020182,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.5000000000F,downfall:0.5000000000F,category:ocean}},{name:"minecraft:deep_cold_ocean",id:45,element:{precipitation:rain,effects:{sky_color:8103167,water_fog_color:329011,fog_color:12638463,water_color:4020182,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.5000000000F,downfall:0.5000000000F,category:ocean}},{name:"minecraft:frozen_ocean",id:46,element:{precipitation:snow,effects:{sky_color:8364543,water_fog_color:329011,fog_color:12638463,water_color:3750089,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.0000000000F,downfall:0.5000000000F,category:ocean,temperature_modifier:frozen}},{name:"minecraft:deep_frozen_ocean",id:47,element:{precipitation:rain,effects:{sky_color:8103167,water_fog_color:329011,fog_color:12638463,water_color:3750089,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.5000000000F,downfall:0.5000000000F,category:ocean,temperature_modifier:frozen}},{name:"minecraft:mushroom_fields",id:48,element:{precipitation:rain,effects:{sky_color:7842047,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.8999999762F,downfall:1.0000000000F,category:mushroom}},{name:"minecraft:dripstone_caves",id:49,element:{precipitation:rain,effects:{music:{replace_current_music:0B,max_delay:24000,sound:"minecraft:music.overworld.dripstone_caves",min_delay:12000},sky_color:7907327,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.8000000119F,downfall:0.4000000060F,category:underground}},{name:"minecraft:lush_caves",id:50,element:{precipitation:rain,effects:{music:{replace_current_music:0B,max_delay:24000,sound:"minecraft:music.overworld.lush_caves",min_delay:12000},sky_color:8103167,water_fog_color:329011,fog_color:12638463,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.5000000000F,downfall:0.5000000000F,category:underground}},{name:"minecraft:nether_wastes",id:51,element:{precipitation:none,effects:{music:{replace_current_music:0B,max_delay:24000,sound:"minecraft:music.nether.nether_wastes",min_delay:12000},sky_color:7254527,ambient_sound:"minecraft:ambient.nether_wastes.loop",additions_sound:{sound:"minecraft:ambient.nether_wastes.additions",tick_chance:0.0111000000D},water_fog_color:329011,fog_color:3344392,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.nether_wastes.mood",block_search_extent:8}},temperature:2.0000000000F,downfall:0.0000000000F,category:nether}},{name:"minecraft:warped_forest",id:52,element:{precipitation:none,effects:{music:{replace_current_music:0B,max_delay:24000,sound:"minecraft:music.nether.warped_forest",min_delay:12000},sky_color:7254527,ambient_sound:"minecraft:ambient.warped_forest.loop",additions_sound:{sound:"minecraft:ambient.warped_forest.additions",tick_chance:0.0111000000D},particle:{probability:0.0142799998F,options:{type:"minecraft:warped_spore"}},water_fog_color:329011,fog_color:1705242,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.warped_forest.mood",block_search_extent:8}},temperature:2.0000000000F,downfall:0.0000000000F,category:nether}},{name:"minecraft:crimson_forest",id:53,element:{precipitation:none,effects:{music:{replace_current_music:0B,max_delay:24000,sound:"minecraft:music.nether.crimson_forest",min_delay:12000},sky_color:7254527,ambient_sound:"minecraft:ambient.crimson_forest.loop",additions_sound:{sound:"minecraft:ambient.crimson_forest.additions",tick_chance:0.0111000000D},particle:{probability:0.0250000004F,options:{type:"minecraft:crimson_spore"}},water_fog_color:329011,fog_color:3343107,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.crimson_forest.mood",block_search_extent:8}},temperature:2.0000000000F,downfall:0.0000000000F,category:nether}},{name:"minecraft:soul_sand_valley",id:54,element:{precipitation:none,effects:{music:{replace_current_music:0B,max_delay:24000,sound:"minecraft:music.nether.soul_sand_valley",min_delay:12000},sky_color:7254527,ambient_sound:"minecraft:ambient.soul_sand_valley.loop",additions_sound:{sound:"minecraft:ambient.soul_sand_valley.additions",tick_chance:0.0111000000D},particle:{probability:0.0062500001F,options:{type:"minecraft:ash"}},water_fog_color:329011,fog_color:1787717,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.soul_sand_valley.mood",block_search_extent:8}},temperature:2.0000000000F,downfall:0.0000000000F,category:nether}},{name:"minecraft:basalt_deltas",id:55,element:{precipitation:none,effects:{music:{replace_current_music:0B,max_delay:24000,sound:"minecraft:music.nether.basalt_deltas",min_delay:12000},sky_color:7254527,ambient_sound:"minecraft:ambient.basalt_deltas.loop",additions_sound:{sound:"minecraft:ambient.basalt_deltas.additions",tick_chance:0.0111000000D},particle:{probability:0.1180933341F,options:{type:"minecraft:white_ash"}},water_fog_color:329011,fog_color:6840176,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.basalt_deltas.mood",block_search_extent:8}},temperature:2.0000000000F,downfall:0.0000000000F,category:nether}},{name:"minecraft:the_end",id:56,element:{precipitation:none,effects:{sky_color:0,water_fog_color:329011,fog_color:10518688,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.5000000000F,downfall:0.5000000000F,category:the_end}},{name:"minecraft:end_highlands",id:57,element:{precipitation:none,effects:{sky_color:0,water_fog_color:329011,fog_color:10518688,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.5000000000F,downfall:0.5000000000F,category:the_end}},{name:"minecraft:end_midlands",id:58,element:{precipitation:none,effects:{sky_color:0,water_fog_color:329011,fog_color:10518688,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.5000000000F,downfall:0.5000000000F,category:the_end}},{name:"minecraft:small_end_islands",id:59,element:{precipitation:none,effects:{sky_color:0,water_fog_color:329011,fog_color:10518688,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.5000000000F,downfall:0.5000000000F,category:the_end}},{name:"minecraft:end_barrens",id:60,element:{precipitation:none,effects:{sky_color:0,water_fog_color:329011,fog_color:10518688,water_color:4159204,mood_sound:{tick_delay:6000,offset:2.0000000000D,sound:"minecraft:ambient.cave",block_search_extent:8}},temperature:0.5000000000F,downfall:0.5000000000F,category:the_end}}]}} \ No newline at end of file diff --git a/server/world/pool.go b/server/world/pool.go deleted file mode 100644 index 7ac3225..0000000 --- a/server/world/pool.go +++ /dev/null @@ -1,74 +0,0 @@ -package world - -import ( - "fmt" - "path/filepath" - - "github.com/Tnze/go-mc/level" - "github.com/Tnze/go-mc/save" - "github.com/Tnze/go-mc/save/region" -) - -// TODO: Cache regions and chunks -type storage struct { - regionDir string -} - -func (s *storage) GetChunk(pos level.ChunkPos) (lc *level.Chunk, err error) { - filename := fmt.Sprintf("r.%d.%d.mca", pos.X>>5, pos.Z>>5) - - var r *region.Region - r, err = region.Open(filepath.Join(s.regionDir, filename)) - if err != nil { - return nil, err - } - defer func() { - err2 := r.Close() - if err == nil && err2 != nil { - err = err2 - } - }() - - sector, err := r.ReadSector(region.In(pos.X, pos.Z)) - if err != nil { - return nil, err - } - - var sc save.Chunk - err = sc.Load(sector) - if err != nil { - return nil, err - } - - return level.ChunkFromSave(&sc) -} - -func (s *storage) PutChunk(pos level.ChunkPos, c *level.Chunk) (err error) { - var sc save.Chunk - err = level.ChunkToSave(c, &sc) - if err != nil { - return - } - - var data []byte - data, err = sc.Data(1) - if err != nil { - return - } - - filename := fmt.Sprintf("r.%d.%d.mca", pos.X>>5, pos.Z>>5) - var r *region.Region - r, err = region.Open(filepath.Join(s.regionDir, filename)) - if err != nil { - return err - } - defer func() { - err2 := r.Close() - if err == nil && err2 != nil { - err = err2 - } - }() - x, z := region.In(pos.X, pos.Z) - err = r.WriteSector(x, z, data) - return -} diff --git a/server/world/world.go b/server/world/world.go deleted file mode 100644 index fbd8240..0000000 --- a/server/world/world.go +++ /dev/null @@ -1,63 +0,0 @@ -package world - -import ( - _ "embed" - "io" - "unsafe" - - "github.com/Tnze/go-mc/nbt" - pk "github.com/Tnze/go-mc/net/packet" - "github.com/Tnze/go-mc/server" - "github.com/Tnze/go-mc/server/ecs" -) - -//go:embed DimensionCodec.snbt -var dimensionCodecSNBT nbt.StringifiedMessage - -//go:embed Dimension.snbt -var dimensionSNBT nbt.StringifiedMessage - -type Dimension struct { - storage - Name string -} - -func NewDimension(name, path string) Dimension { - return Dimension{ - Name: name, - storage: storage{regionDir: path}, - } -} - -type DimensionList struct { - Dims []ecs.Index - DimNames []string - DimCodecSNBT, DimSNBT nbt.StringifiedMessage -} - -func (d *DimensionList) WriteTo(w io.Writer) (n int64, err error) { - return pk.Array(*(*[]pk.Identifier)(unsafe.Pointer(&d.DimNames))).WriteTo(w) -} - -func (d *DimensionList) Find(dim string) (ecs.Index, bool) { - for i, v := range d.DimNames { - if v == dim { - return d.Dims[i], true - } - } - return 0, false -} - -func (d *DimensionList) Add(id ecs.Index, name string) { - d.Dims = append(d.Dims, id) - d.DimNames = append(d.DimNames, name) -} - -func NewDimensionManager(g *server.Game) *DimensionList { - return ecs.SetResource(g.World, DimensionList{ - Dims: nil, - DimNames: nil, - DimCodecSNBT: dimensionCodecSNBT, - DimSNBT: dimensionSNBT, - }) -}