fix data race

This commit is contained in:
Tnze
2022-05-27 10:37:10 +08:00
parent 5acdadabcc
commit 61f9625297
4 changed files with 24 additions and 4 deletions

View File

@ -18,7 +18,7 @@ import (
) )
var motd = chat.Message{Text: "A Minecraft Server ", Extra: []chat.Message{{Text: "Powered by go-mc", Color: "yellow"}}} var motd = chat.Message{Text: "A Minecraft Server ", Extra: []chat.Message{{Text: "Powered by go-mc", Color: "yellow"}}}
var addr = flag.String("Address", ":25565", "Listening address") var addr = flag.String("Address", "127.0.0.1:25565", "Listening address")
var iconPath = flag.String("ServerIcon", "./server-icon.png", "The path to server icon") var iconPath = flag.String("ServerIcon", "./server-icon.png", "The path to server icon")
var maxPlayer = flag.Int("MaxPlayer", 16384, "The maximum number of players") var maxPlayer = flag.Int("MaxPlayer", 16384, "The maximum number of players")
var regionPath = flag.String("Regions", "./save/testdata/region/", "The region files") var regionPath = flag.String("Regions", "./save/testdata/region/", "The region files")

View File

@ -3,6 +3,7 @@ package server
import ( import (
"context" "context"
_ "embed" _ "embed"
"sync"
"time" "time"
"github.com/google/uuid" "github.com/google/uuid"
@ -23,6 +24,7 @@ type GamePlay interface {
type Game struct { type Game struct {
*ecs.World *ecs.World
*ecs.Dispatcher *ecs.Dispatcher
WorldLocker sync.Mutex
handlers map[int32][]*PacketHandler handlers map[int32][]*PacketHandler
components []Component components []Component
} }
@ -68,7 +70,9 @@ func (g *Game) Run(ctx context.Context) {
for { for {
select { select {
case <-ticker.C: case <-ticker.C:
g.WorldLocker.Lock()
g.Dispatcher.Run(g.World) g.Dispatcher.Run(g.World)
g.WorldLocker.Unlock()
case <-ctx.Done(): case <-ctx.Done():
return return
} }
@ -76,6 +80,7 @@ func (g *Game) Run(ctx context.Context) {
} }
func (g *Game) AcceptPlayer(name string, id uuid.UUID, protocol int32, conn *net.Conn) { func (g *Game) AcceptPlayer(name string, id uuid.UUID, protocol int32, conn *net.Conn) {
g.WorldLocker.Lock()
eid := g.CreateEntity( eid := g.CreateEntity(
Client{ Client{
Conn: conn, Conn: conn,
@ -90,6 +95,7 @@ func (g *Game) AcceptPlayer(name string, id uuid.UUID, protocol int32, conn *net
) )
c := ecs.GetComponent[Client](g.World).GetValue(eid) c := ecs.GetComponent[Client](g.World).GetValue(eid)
p := ecs.GetComponent[Player](g.World).GetValue(eid) p := ecs.GetComponent[Player](g.World).GetValue(eid)
g.WorldLocker.Unlock()
defer c.packetQueue.Close() defer c.packetQueue.Close()
go func() { go func() {

View File

@ -20,6 +20,7 @@ type playerSpawnSystem struct {
func (p playerSpawnSystem) Update(w *ecs.World) { func (p playerSpawnSystem) Update(w *ecs.World) {
clients := ecs.GetComponent[server.Client](w) clients := ecs.GetComponent[server.Client](w)
players := ecs.GetComponent[server.Player](w) players := ecs.GetComponent[server.Player](w)
pos, rot := ecs.GetComponent[server.Pos](w), ecs.GetComponent[server.Rot](w)
profiles := ecs.GetComponent[PlayerProfile](w) profiles := ecs.GetComponent[PlayerProfile](w)
dimensionRes := ecs.GetResource[world.DimensionList](w) dimensionRes := ecs.GetResource[world.DimensionList](w)
players.AndNot(profiles.BitSetLike).Range(func(eid ecs.Index) { players.AndNot(profiles.BitSetLike).Range(func(eid ecs.Index) {
@ -35,6 +36,15 @@ func (p playerSpawnSystem) Update(w *ecs.World) {
panic("dimension " + profile.Dimension + " not found") panic("dimension " + profile.Dimension + " not found")
} }
profiles.SetValue(eid, PlayerProfile{Dim: dim}) 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( client.WritePacket(server.Packet758(pk.Marshal(
packetid.ClientboundLogin, packetid.ClientboundLogin,
pk.Int(eid), // Entity ID pk.Int(eid), // Entity ID
@ -59,7 +69,11 @@ func (p playerSpawnSystem) Update(w *ecs.World) {
func SpawnSystem(g *server.Game, playerdataPath string) { func SpawnSystem(g *server.Game, playerdataPath string) {
ecs.Register[PlayerProfile, *ecs.HashMapStorage[PlayerProfile]](g.World) ecs.Register[PlayerProfile, *ecs.HashMapStorage[PlayerProfile]](g.World)
g.Dispatcher.Add(playerSpawnSystem{storage: storage{playerdataPath}}, "go-mc:player:SpawnSystem", nil) g.Dispatcher.Add(
playerSpawnSystem{storage: storage{playerdataPath}},
"go-mc:player:SpawnSystem",
nil,
)
} }
// PosAndRotSystem add a system to g.Dispatcher that // PosAndRotSystem add a system to g.Dispatcher that