P2PKit is a Bluetooth or WiFi Networking framework for hackathons! It is uses Apple's Multipeer Connectivity and works for all iOS, including Vision Pro, iPhone, and iPad.
You're the mallet with the star. When the white puck enters a hole, the last person to touch the white puck with their mallet scores a point!
https://github.com/p-sun/iOSMultiplayerTemplate/assets/9044578/53169d75-bbda-4401-a376-e77a6dae1371
https://github.com/p-sun/iOSMultiplayerTemplate/assets/9044578/5610f760-0c3c-4100-b1ca-cbcb417c72b0
P2PSynced is the easiest way to sync data across devices.
let syncedRoom = P2PSynced<GameRoom>(
name: "GameRoom",
initial: GameRoom(),
writeAccess: .hostOnly, // Optional param. Defaults to .everyone has write access. If using .hostOnly, set host with `P2PNetwork.makeMeHost()`.
reliable: true) // Optional param. Defaults to false. Reliable sending is slower but preserves order and doesn't drop messages.
// GET data
syncedRoom.onReceiveSync = { gameRoom in }
// SEND DATA
syncedRoom.value = GameRoom(...)
Use P2PSyncedObservable, a light wrapper around P2PSynced, with SwiftUI.
In this example, an Int value is sent between devices to sync a counter.
struct SyncedCounter: View {
@StateObject private var counter = P2PSyncedObservable(name: "SyncedCounter", initial: 1)
var body: some View {
Button("+ 1") {
counter.value = counter.value + 1 // SET VALUE
}
Text("Counter: \(counter.value)") // RECEIVE VALUE
}
}
Similarily, in the SyncedCircles example, the Codable object SendableCircle
, is synced across all devices.
@StateObject var blueCircle = P2PSyncedObservable(name: "blue", initial: SendableCircle(point: CGPoint(x: 300, y: -26)))
@StateObject var greenCircle = P2PSyncedObservable(name: "green", initial: SendableCircle(point: CGPoint(x: 260, y: -10)))
// RECEIVE
let sendableCircle = blueCircle.value
// SEND
blueCircle.value = SendableCircle(point: newPoint)
let malletDraggedEvents = P2PEventService<MalletDragEvent>("MalletDrag")
// RECEIVE
malletDraggedEvents.onReceive { eventInfo, malletDragEvent, json, sender in
// Handle malletDragEvent
}
// SEND
malletDraggedEvents.send(payload: MalletDragEvent(...), reliable: false)
Get myself and connected peers.
let myPeer: Peer = P2PNework.myPeer
let connectedPeers: [Peer] = P2PNework.connectedPeers
Observe peer updates with P2PNetworkPeerDelegate
. When connectedPeers update, the p2pNetwork(didUpdate peer: Peer)
handler will be called.
protocol P2PNetworkPeerDelegate: AnyObject {
func p2pNetwork(didUpdate peer: Peer)
func p2pNetwork(didUpdateHost host: Peer?)
}
P2PNework.addPeerDelegate(self)
P2PNework.removePeerDelegate(self)
(Optional) Reset the session.
P2PNework.resetSession("New Display Name") // Change display name.
P2PNework.resetSession(nil) // Keep current display name.
(Optional) Get and set the host for all connected devices. Not all games need a host.
let currentHost: Peer? = P2PNework.host
P2PNework.makeMeHost()
https://github.com/p-sun/iOSMultiplayerTemplate/assets/9044578/469ae3dc-5c19-4a4f-a74d-32ffdeb422a4
When the current device connects to a host, P2PSynced
and P2PSyncedObservable
will sync the latest data from the host.
https://github.com/p-sun/iOSMultiplayerTemplate/assets/9044578/9755a6d7-e04b-4dc9-b900-38b60b50c24e