Skip to content

Commit

Permalink
Fix: Unsafe world accessor
Browse files Browse the repository at this point in the history
  • Loading branch information
Edouard127 committed Oct 7, 2023
1 parent 1c95318 commit bad6800
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 25 deletions.
2 changes: 0 additions & 2 deletions bot/provider/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,6 @@ func RunTransactions(c *Client, cancel context.CancelFunc) error {
// I don't have to code all the physic by myself
// thx minecrossoft 🙏
func Step(cl *Client, cancel context.CancelFunc) error {
cancel()
return nil
feetBlock, err := cl.Player.World.GetBlock(cl.Player.EntityPlayer.Position)
if err != nil {
return err
Expand Down
25 changes: 4 additions & 21 deletions bot/provider/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import (
"github.com/Edouard127/go-mc/data/grids"
"github.com/Edouard127/go-mc/level"
"github.com/Edouard127/go-mc/maths"
"github.com/Edouard127/go-mc/save"
"github.com/Edouard127/go-mc/save/region"
"time"
"unsafe"

Expand Down Expand Up @@ -359,24 +357,6 @@ func SetContainerSlot(c *Client, p pk.Packet, cancel context.CancelFunc) error {
return fmt.Errorf("failed to scan SetSlot: %w", err)
}

var chunk save.Chunk
for i := range c.Player.World.Columns {
r, err := region.Create(fmt.Sprintf("r.%d.%d.mca", i[0], i[1]))
if err != nil {
return err
}

err = level.ChunkToSave(c.Player.World.Columns[i], &chunk)
if err != nil {
return err
}
data, err := chunk.Data(2)
if err != nil {
return err
}
r.WriteSector(int(i[0]), int(i[1]), data)
}

c.Player.Manager.StateID = int32(stateId)

if containerId == -1 && slotId == -1 {
Expand Down Expand Up @@ -933,7 +913,7 @@ func SelectAdvancementTab(c *Client, p pk.Packet, cancel context.CancelFunc) err
return nil
}

func WorldBorder(c *Client, p pk.Packet, cancel context.CancelFunc) error {
func InitializeBorder(c *Client, p pk.Packet, cancel context.CancelFunc) error {
var (
action pk.Byte
radius pk.Double
Expand All @@ -950,6 +930,9 @@ func WorldBorder(c *Client, p pk.Packet, cancel context.CancelFunc) error {
return fmt.Errorf("unable to read WorldBorder packet: %w", err)
}

// When we receive this packet, we know that the client has fully loaded the world.
c.World.SafeToAccess = true

return nil
}

Expand Down
1 change: 1 addition & 0 deletions bot/provider/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func TestExampleClient_JoinServer_online(t *testing.T) {

/* Physic */
PacketHandler[Client]{ID: packetid.CPacketChunkData, Priority: 50, F: ChunkData},
PacketHandler[Client]{ID: packetid.CPacketInitializeBorder, Priority: 50, F: InitializeBorder},
PacketHandler[Client]{ID: packetid.CPacketUnloadChunk, Priority: 50, F: UnloadChunk},
PacketHandler[Client]{ID: packetid.CPacketExplosion, Priority: 50, F: Explosion},

Expand Down
30 changes: 28 additions & 2 deletions bot/world/chunks.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package world

import (
"context"
"fmt"
"github.com/Edouard127/go-mc/bot/core"
. "github.com/Edouard127/go-mc/level"
"github.com/Edouard127/go-mc/level/block"
"github.com/Edouard127/go-mc/maths"
"math"
"sync"
"time"
)

type World struct {
Columns map[ChunkPos]*Chunk
Entities map[int32]core.Entity
Columns map[ChunkPos]*Chunk
Entities map[int32]core.Entity
SafeToAccess bool

worldSync sync.Mutex
entityMutex sync.Mutex
Expand All @@ -25,9 +28,32 @@ func NewWorld() *World {
}
}

func (w *World) safeLock() {
if w.SafeToAccess {
return
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
defer cancel()
for {
if w.SafeToAccess {
return
}
select {
case <-ctx.Done():
panic("world not safe to access")
default:
time.Sleep(time.Millisecond * 10)
}
}
}

func (w *World) GetBlock(pos maths.Vec3d) (*block.Block, error) {
w.worldSync.Lock()
defer w.worldSync.Unlock()
w.safeLock() // As long as the world is empty, we can't get any blocks
if len(w.Columns) == 0 {
return block.Air, fmt.Errorf("no chunks loaded")
}
chunk, ok := w.Columns[ChunkPos{int32(pos.X) >> 4, int32(pos.Z) >> 4}]
if ok {
return chunk.GetBlock(pos)
Expand Down

0 comments on commit bad6800

Please sign in to comment.