diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/spacewar-swift.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/spacewar-swift.xcscheme
deleted file mode 100644
index 5db4095..0000000
--- a/.swiftpm/xcode/xcshareddata/xcschemes/spacewar-swift.xcscheme
+++ /dev/null
@@ -1,108 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Package.resolved b/Package.resolved
index 18adcc0..e18ce03 100644
--- a/Package.resolved
+++ b/Package.resolved
@@ -5,8 +5,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/johnfairh/steamworks-swift",
"state" : {
- "branch" : "main",
- "revision" : "78fae74c61a7e91096b4beecb01a18e72b562a05"
+ "revision" : "d65d442139b042ce1172de95b915e9974c7d7fa7",
+ "version" : "0.3.0"
}
},
{
@@ -14,8 +14,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-log.git",
"state" : {
- "revision" : "6fe203dc33195667ce1759bf0182975e4653ba1c",
- "version" : "1.4.4"
+ "revision" : "32e8d724467f8fe623624570367e3d50c5638e46",
+ "version" : "1.5.2"
}
},
{
@@ -23,8 +23,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/johnfairh/TMLEngines",
"state" : {
- "revision" : "81646b99277ce42ee5acc34577965cc292c2f587",
- "version" : "1.2.4"
+ "revision" : "51a2ff3056ff60d3ebc6df1f3d8504d02b7c8ef3",
+ "version" : "1.3.0"
}
}
],
diff --git a/Package.swift b/Package.swift
index d5ae4a9..f972330 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,15 +1,15 @@
-// swift-tools-version: 5.7
+// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "spacewar-swift",
platforms: [
- .macOS("12.0"),
+ .macOS("13.0"),
],
dependencies: [
.package(url: "https://github.com/johnfairh/steamworks-swift",
- branch: "main"),
+ from: "0.3.0"),
.package(url: "https://github.com/johnfairh/TMLEngines",
from: "1.2.0")
],
@@ -27,7 +27,8 @@ let package = Package(
.process("Resources/steam_input_manifest.vdf"),
.process("Resources/xbox_controller.vdf"),
.process("Resources/ps5_controller.vdf")
- ]
+ ],
+ swiftSettings: [.interoperabilityMode(.Cxx)]
),
.systemLibrary(name: "CSpaceWar")
]
diff --git a/README.md b/README.md
index 4fc1a07..32c224e 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,7 @@
# spacewar-swift
Educational port of Steamworks demo to Swift for macOS with Metal backend.
+
+Needs Xcode 15 / Swift 5.9
+
+Needs Steam up and logged in; best run from CLI `swift run`.
diff --git a/Sources/CSpaceWar/cspacewar.h b/Sources/CSpaceWar/cspacewar.h
index 1040256..6c75125 100644
--- a/Sources/CSpaceWar/cspacewar.h
+++ b/Sources/CSpaceWar/cspacewar.h
@@ -1,5 +1,7 @@
#ifndef CSPACEWAR_H
+extern "C" {
+
#include
typedef short int16;
@@ -8,7 +10,7 @@ typedef int int32;
typedef unsigned int uint32;
typedef long long int64;
typedef unsigned long long uint64;
-typedef unsigned char bool;
+typedef unsigned char netbool;
typedef unsigned char uint8;
typedef uint32 netfloat; // network rep of single-prec floating-point
@@ -20,7 +22,7 @@ typedef uint32 netfloat; // network rep of single-prec floating-point
typedef struct {
uint32 messageType;
uint64 steamIDServer;
- bool isVACSecure;
+ netbool isVACSecure;
char serverName[128];
} MsgServerSendInfo_t;
@@ -60,8 +62,14 @@ typedef struct {
#define ARRAY_GETTER(TYPE,FIELD,FIELDTYPE) \
__attribute__((swift_name("getter:" #TYPE "." #FIELD "_ptr(self:)"))) \
+static inline const FIELDTYPE * _Nonnull TYPE ## _Get ## FIELD (const TYPE * _Nonnull t) { \
+ return &t->FIELD[0]; \
+}
+
+#define ARRAY_MUTABLE_GETTER(TYPE,FIELD,FIELDTYPE) \
+__attribute__((swift_name("getter:" #TYPE "." #FIELD "_ptr(self:)"))) \
static inline FIELDTYPE * _Nonnull TYPE ## _Get ## FIELD (const TYPE * _Nonnull t) { \
- return t->FIELD; \
+ return const_cast(&t->FIELD[0]); \
}
ARRAY_GETTER(MsgClientBeginAuthentication_t, token, uint8)
@@ -76,11 +84,11 @@ static inline void MsgClientBeginAuthentication_SetToken(MsgClientBeginAuthentic
typedef struct {
uint32 messageType;
uint32 tokenLen;
- char token[1024];
+ uint8 token[1024];
uint64 steamID;
} MsgP2PSendingTicket_t;
-ARRAY_GETTER(MsgP2PSendingTicket_t, token, uint8)
+ARRAY_MUTABLE_GETTER(MsgP2PSendingTicket_t, token, uint8)
typedef struct {
uint32 messageType;
@@ -89,13 +97,13 @@ typedef struct {
uint8 data[1024];
} MsgVoiceChatData_t;
-ARRAY_GETTER(MsgVoiceChatData_t, data, uint8)
+ARRAY_MUTABLE_GETTER(MsgVoiceChatData_t, data, uint8)
// MARK: Game, Server -> Client
typedef struct {
// Does the photon beam exist right now?
- bool isActive;
+ netbool isActive;
// The current rotation
netfloat currentRotation;
@@ -132,14 +140,14 @@ typedef struct {
netfloat yPosition;
// Is the ship exploding?
- bool exploding;
+ netbool exploding;
// Is the ship disabled?
- bool disabled;
+ netbool disabled;
// Are the thrusters to be drawn?
- bool forwardThrustersActive;
- bool reverseThrustersActive;
+ netbool forwardThrustersActive;
+ netbool reverseThrustersActive;
// Decoration for this ship
int32 shipDecoration;
@@ -173,7 +181,7 @@ typedef struct {
uint32 playerWhoWonGame;
// which player slots are in use
- bool playersActive[MAX_PLAYERS_PER_SERVER];
+ netbool playersActive[MAX_PLAYERS_PER_SERVER];
// what are the scores for each player?
uint32 playerScores[MAX_PLAYERS_PER_SERVER];
@@ -185,7 +193,7 @@ typedef struct {
uint64 playerSteamIDs[MAX_PLAYERS_PER_SERVER];
} ServerSpaceWarUpdateData_t;
-ARRAY_GETTER(ServerSpaceWarUpdateData_t, playersActive, bool)
+ARRAY_GETTER(ServerSpaceWarUpdateData_t, playersActive, netbool)
ARRAY_GETTER(ServerSpaceWarUpdateData_t, playerScores, uint32)
ARRAY_GETTER(ServerSpaceWarUpdateData_t, shipData, ServerShipUpdateData_t)
ARRAY_GETTER(ServerSpaceWarUpdateData_t, playerSteamIDs, uint64)
@@ -199,11 +207,11 @@ typedef struct {
typedef struct {
// Key's which are done
- bool firePressed;
- bool turnLeftPressed;
- bool turnRightPressed;
- bool forwardThrustersPressed;
- bool reverseThrustersPressed;
+ netbool firePressed;
+ netbool turnLeftPressed;
+ netbool turnRightPressed;
+ netbool forwardThrustersPressed;
+ netbool reverseThrustersPressed;
// Decoration for this ship
int32 shipDecoration;
@@ -240,4 +248,6 @@ typedef struct {
#pragma pack( pop )
+}
+
#endif
diff --git a/Sources/SpaceWar/Messages.swift b/Sources/SpaceWar/Messages.swift
index 580ef0c..4a98d62 100644
--- a/Sources/SpaceWar/Messages.swift
+++ b/Sources/SpaceWar/Messages.swift
@@ -138,13 +138,13 @@ extension Bool {
/// Fixed-size array tuple bullshit. holy fuck.
extension Array {
- static func four(_ p: UnsafeMutablePointer, map: (X) -> Element) -> Array{
- let bp = UnsafeMutableBufferPointer(start: p, count: 4)
+ static func four(_ p: UnsafePointer, map: (X) -> Element) -> Array{
+ let bp = UnsafeBufferPointer(start: p, count: 4)
return bp.map(map)
}
- static func seven(_ p: UnsafeMutablePointer, map: (X) -> Element) -> Array{
- let bp = UnsafeMutableBufferPointer(start: p, count: 7)
+ static func seven(_ p: UnsafePointer, map: (X) -> Element) -> Array{
+ let bp = UnsafeBufferPointer(start: p, count: 7)
return bp.map(map)
}
@@ -623,10 +623,10 @@ extension MsgP2PSendingTicket_t: ConstructableFrom {
if let buf = from.buffer {
precondition(buf.count <= 1024)
self.tokenLen = UInt32(buf.count).bigEndian
- self.token_ptr.assign(from: buf.baseAddress!, count: buf.count)
+ self.token_ptr.update(from: buf.baseAddress!, count: buf.count)
} else {
self.tokenLen = UInt32(from.token.count).bigEndian
- self.token_ptr.assign(from: from.token, count: from.token.count)
+ self.token_ptr.update(from: from.token, count: from.token.count)
}
}
}
@@ -665,11 +665,11 @@ extension MsgVoiceChatData_t: ConstructableFrom {
// got msg from a client, forwarding it...
precondition(buf.count <= 1024) /* ahem */
self.dataLength = UInt32(buf.count).bigEndian
- self.data_ptr.assign(from: buf.baseAddress!, count: buf.count)
+ self.data_ptr.update(from: buf.baseAddress!, count: buf.count)
} else {
// created msg here, converting from swift
self.dataLength = UInt32(from.data.count).bigEndian
- self.data_ptr.assign(from: from.data, count: from.data.count)
+ self.data_ptr.update(from: from.data, count: from.data.count)
}
}
}
diff --git a/Sources/SpaceWar/SpaceWarEntity.swift b/Sources/SpaceWar/SpaceWarEntity.swift
index f614a93..f38ac65 100644
--- a/Sources/SpaceWar/SpaceWarEntity.swift
+++ b/Sources/SpaceWar/SpaceWarEntity.swift
@@ -23,13 +23,15 @@ class SpaceWarEntity: VectorEntity {
// The suns gravity, compute that here, sun is always at the center of the screen [JF: !!!]
let posSun = engine.viewportSize / 2
- // let distanceToSun = min(simd_distance(posSun, pos), 1) // JF: guard div0...
- // let distancePower = pow(distanceToSun, 2) // gravity power falls off exponentially
- let distancePower = max(simd_distance_squared(posSun, pos), 1)
+ #if true // XXX CxxInterop
+ let distancePower = max(my_distance_squared(posSun, pos), 1)
+ #else
+ let distancePower = max(simd_distance_squared(posSun, pos), 1) // gravity power falls off exponentially; guard div0
+ #endif
let factor = min(100000.0 / distancePower, SpaceWarEntity.MIN_GRAVITY) // arbitrary value for power of gravity
- let direction = simd_normalize(pos - posSun)
+ let direction = my_normalize(pos - posSun) // XXX CxxInterop simd_normalize(pos - posSun)
// Set updated acceleration
acceleration -= factor * direction
@@ -38,3 +40,23 @@ class SpaceWarEntity: VectorEntity {
super.runFrame()
}
}
+
+// Swift C++ interop makes simd_vector_add() not link, which loads depends on ... baffling
+func my_distance_squared(_ a: SIMD2, _ b: SIMD2) -> Float {
+ let xs = pow(a.x - b.x, 2)
+ let ys = pow(a.y - b.y, 2)
+ return xs + ys
+}
+
+func my_distance(_ a: SIMD2, _ b: SIMD2) -> Float {
+ sqrt(my_distance_squared(a, b))
+}
+
+func my_length(_ v: SIMD2) -> Float {
+ sqrt(pow(v.x, 2) + pow(v.y, 2))
+}
+
+private func my_normalize(_ v: SIMD2) -> SIMD2 {
+ let len = my_length(v)
+ return [v.x / len, v.y / len]
+}
diff --git a/Sources/SpaceWar/VectorEntity.swift b/Sources/SpaceWar/VectorEntity.swift
index 3e4d56f..023436c 100644
--- a/Sources/SpaceWar/VectorEntity.swift
+++ b/Sources/SpaceWar/VectorEntity.swift
@@ -31,7 +31,7 @@ class VectorEntity {
/// The distance travelled since the last frame
var distanceTraveledLastFrame: Float {
- simd_distance(pos, posLastFrame)
+ my_distance(pos, posLastFrame) // XXX CxxInterop simd_distance(pos, posLastFrame)
}
/// Current velocity - normally computed from acceleration
@@ -100,7 +100,7 @@ class VectorEntity {
// Make sure velocity does not exceed maximum allowed - this scales it while
// keeping the aspect ratio consistent
- let linearVelocity = simd_length(velocity)
+ let linearVelocity = my_length(velocity) // XXX CxxInterop simd_length(velocity)
if linearVelocity > maximumVelocity {
let ratio = maximumVelocity / linearVelocity
velocity *= ratio
@@ -143,7 +143,8 @@ class VectorEntity {
return false
}
- return simd_distance(pos, target.pos) < collisionRadius + target.collisionRadius
+// return simd_distance(pos, target.pos) < collisionRadius + target.collisionRadius XXX CxxInterop
+ return my_distance(pos, target.pos) < collisionRadius + target.collisionRadius
}
}