Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions _examples/stash/stash.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ func render() {
}

func beforeExit() {
peer := firefly.GetMe()
state := states[peer]
buf := binary.LittleEndian.AppendUint32(nil, state.clicks)
firefly.SaveStash(peer, buf)
for _, peer := range peers.Slice() {
state := states[peer]
buf := binary.LittleEndian.AppendUint32(nil, state.clicks)
firefly.SaveStash(peer, buf)
}
}
4 changes: 2 additions & 2 deletions firefly/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ func (p Buttons) Any() bool {
//
// The peer can be [Combined] or one of the [GetPeers].
func ReadPad(p Peer) (Pad, bool) {
raw := readPad(uint32(p))
raw := readPad(uint32(p.raw))
pressed := raw != 0xffff
if !pressed {
return Pad{}, false
Expand All @@ -280,7 +280,7 @@ func ReadPad(p Peer) (Pad, bool) {
//
// The peer can be [Combined] or one of the [GetPeers].
func ReadButtons(p Peer) Buttons {
raw := readButtons(uint32(p))
raw := readButtons(uint32(p.raw))
return Buttons{
S: hasBitSet(raw, 0),
E: hasBitSet(raw, 1),
Expand Down
13 changes: 10 additions & 3 deletions firefly/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,19 @@ func GetRandom() uint32 {
func GetName(p Peer) string {
buf := [16]byte{}
ptr := unsafe.Pointer(&buf)
length := getName(uint32(p), ptr)
length := getName(uint32(p.raw), ptr)
return unsafe.String(&buf[0], length)
}

func GetSettings(p Peer) Settings {
raw := getSettings(uint32(p))
// Get the peer's system settings.
//
// IMPORTANT: This is the only function that accepts as input not only [Peer]
// but also [Me], which might lead to a state drift if used incorrectly.
// See [the docs] for more info.
//
// [the docs]: https://docs.fireflyzero.com/dev/net/
func GetSettings(p AnyPeer) Settings {
raw := getSettings(uint32(p.peerID()))
code := uint16(raw>>8) | uint16(raw)
language := Language(code)
flags := raw >> 16
Expand Down
69 changes: 56 additions & 13 deletions firefly/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,61 @@ import (
"unsafe"
)

// A peer obtained either from [Peers] ([GetPeers]) or from [GetMe].
type AnyPeer interface {
peerID() uint8
}

// The peer representing the current device.
//
// Can be compared to [Peer] (using [Me.Eq]) or used to [GetSettings].
//
// **IMPORTANT:** Using this type may cause state drift between device in multiplayer.
// See [the docs] for more info.
//
// [the docs]: https://docs.fireflyzero.com/dev/net/
type Me struct {
raw uint8
}

// Check if the given [Peer] represents the current device.
func (me Me) Eq(peer Peer) bool {
return me.raw == peer.raw
}

// peerID implements [AnyPeer].
func (me Me) peerID() uint8 {
return me.raw
}

// The peer ID.
//
// Can be obtained by getting the list of [Peers] using [GetPeers]
// and then iterating over it.
type Peer uint8
type Peer struct {
raw uint8
}

// Check if the given peers represent the same device.
func (peer Peer) Eq(other Peer) bool {
return peer.raw == other.raw
}

// peerID implements [AnyPeer].
func (peer Peer) peerID() uint8 {
return peer.raw
}

// Peer value that can be passed to [ReadPad] and [ReadButtons]
// A combination of all connected peers.
//
// Can be passed in functions like [ReadPad] and [ReadButtons]
// to get the combined input of all peers.
//
// Useful for single-player games that want in multi-player to handle
// Useful for single-player games that want in multiplayer to handle
// inputs from all devices as one input.
const Combined Peer = 0xFF
var Combined = Peer{0xFF}

// The map of peers online.
// The list of peers online.
//
// Can be obtained using [GetPeers].
type Peers uint32
Expand All @@ -38,7 +79,8 @@ type Stash = []byte
// Get the slice of all peers that are online.
func (peers Peers) Slice() []Peer {
res := make([]Peer, 0, 32)
for peer := range Peer(32) {
for peerID := range uint8(32) {
peer := Peer{peerID}
if peers.Contains(peer) {
res = append(res, peer)
}
Expand All @@ -51,7 +93,8 @@ func (peers Peers) Slice() []Peer {
// Uses the iterators API introduced in Go 1.23.
func (peers Peers) Iter() iter.Seq[Peer] {
return func(yield func(Peer) bool) {
for peer := range Peer(32) {
for peerID := range uint8(32) {
peer := Peer{peerID}
if !peers.Contains(peer) {
continue
}
Expand All @@ -65,7 +108,7 @@ func (peers Peers) Iter() iter.Seq[Peer] {

// Check if the given [Peer] is online.
func (peers Peers) Contains(peer Peer) bool {
return peers>>peer&1 != 0
return peers>>peer.raw&1 != 0
}

// Get how many peers are online.
Expand All @@ -74,9 +117,9 @@ func (peers Peers) Len() int {
return bits.OnesCount32(uint32(peers))
}

// Get the [Peer] representing the local device.
func GetMe() Peer {
return Peer(getMe())
// Get the peer corresponding to the local device.
func GetMe() Me {
return Me{uint8(getMe())}
}

// Get the list of peers that are currently online.
Expand All @@ -98,7 +141,7 @@ func GetPeers() Peers {
// saved earlier.
func SaveStash(p Peer, b Stash) {
ptr := unsafe.Pointer(unsafe.SliceData(b))
saveStash(uint32(p), ptr, uint32(len(b)))
saveStash(uint32(p.raw), ptr, uint32(len(b)))
}

// Load [Stash] saved earlier (in this or previous run) by [SaveStash].
Expand All @@ -114,7 +157,7 @@ func LoadStash(p Peer, buf []byte) Stash {
buf = make([]byte, 80)
}
ptr := unsafe.Pointer(unsafe.SliceData(buf))
size := loadStash(uint32(p), ptr, uint32(len(buf)))
size := loadStash(uint32(p.raw), ptr, uint32(len(buf)))
if size == 0 {
return nil
}
Expand Down
4 changes: 2 additions & 2 deletions firefly/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func GetProgress(p Peer, b Badge) Progress {
// If the Peer is [Combined], the progress is added to every peer
// and the returned value is the lowest progress.
func AddProgress(p Peer, b Badge, v int16) Progress {
r := addProgress(uint32(p), uint32(b), int32(v))
r := addProgress(uint32(p.raw), uint32(b), int32(v))
return Progress{
Done: uint16(r >> 16),
Goal: uint16(r),
Expand All @@ -51,6 +51,6 @@ func GetScore(p Peer, b Board) int16 {
// If the Peer is [Combined], the score is added for every peer
// and the returned value is the lowest of their best scores.
func AddScore(p Peer, b Board, v int16) int16 {
s := addScore(uint32(p), uint32(b), int32(v))
s := addScore(uint32(p.raw), uint32(b), int32(v))
return int16(s)
}